1 #include "estoraged_conf.hpp" 2 #include "zero.hpp" 3 4 #include <fcntl.h> 5 #include <unistd.h> 6 7 #include <stdplus/fd/create.hpp> 8 #include <stdplus/fd/gmock.hpp> 9 #include <stdplus/fd/managed.hpp> 10 #include <xyz/openbmc_project/Common/error.hpp> 11 12 #include <fstream> 13 #include <system_error> 14 15 #include <gmock/gmock-matchers.h> 16 #include <gmock/gmock.h> 17 #include <gtest/gtest.h> 18 19 namespace estoraged_test 20 { 21 22 using estoraged::Zero; 23 using sdbusplus::xyz::openbmc_project::Common::Error::InternalFailure; 24 using testing::_; 25 using testing::Return; 26 27 TEST(Zeros, zeroPass) 28 { 29 std::string testFileName = "testfile_pass"; 30 std::ofstream testFile; 31 32 testFile.open(testFileName, 33 std::ios::out | std::ios::binary | std::ios::trunc); 34 testFile.close(); 35 uint64_t size = 4096; 36 Zero pass(testFileName); 37 stdplus::fd::Fd&& write = 38 stdplus::fd::open(testFileName, stdplus::fd::OpenAccess::ReadWrite); 39 EXPECT_NO_THROW(pass.writeZero(size, write)); 40 stdplus::fd::Fd&& read = 41 stdplus::fd::open(testFileName, stdplus::fd::OpenAccess::ReadWrite); 42 EXPECT_NO_THROW(pass.verifyZero(size, read)); 43 } 44 45 /* This test that pattern writes the correct number of bytes even if 46 * size of the drive is not divisable by the block size 47 */ 48 TEST(Zeros, notDivisible) 49 { 50 std::string testFileName = "testfile_notDivisible"; 51 std::ofstream testFile; 52 53 testFile.open(testFileName, 54 std::ios::out | std::ios::binary | std::ios::trunc); 55 testFile.close(); 56 57 uint64_t size = 4097; 58 // 4097 is not divisible by the block size, and we expect no errors 59 60 stdplus::fd::Fd&& write = 61 stdplus::fd::open(testFileName, stdplus::fd::OpenAccess::ReadWrite); 62 Zero pass(testFileName); 63 EXPECT_NO_THROW(pass.writeZero(size, write)); 64 stdplus::fd::Fd&& read = 65 stdplus::fd::open(testFileName, stdplus::fd::OpenAccess::ReadWrite); 66 EXPECT_NO_THROW(pass.verifyZero(size, read)); 67 } 68 69 TEST(Zeros, notZeroStart) 70 { 71 std::string testFileName = "testfile_notZeroStart"; 72 std::ofstream testFile; 73 74 // open the file and write none zero to it 75 uint32_t dummyValue = 0x88776655; 76 testFile.open(testFileName, std::ios::binary | std::ios::out); 77 testFile.write((reinterpret_cast<const char*>(&dummyValue)), 78 sizeof(dummyValue)); 79 testFile.close(); 80 uint64_t size = 4096; 81 stdplus::fd::Fd&& readWrite = 82 stdplus::fd::open(testFileName, stdplus::fd::OpenAccess::ReadWrite); 83 84 Zero pass(testFileName); 85 EXPECT_NO_THROW(pass.writeZero(size - sizeof(dummyValue), readWrite)); 86 87 // force flush, needed for unit testing 88 std::ofstream file; 89 file.open(testFileName); 90 file.close(); 91 92 EXPECT_THROW(pass.verifyZero(size, readWrite), InternalFailure); 93 } 94 95 TEST(Zeros, notZeroEnd) 96 { 97 std::string testFileName = "testfile_notZeroEnd"; 98 std::ofstream testFile; 99 100 testFile.open(testFileName, 101 std::ios::out | std::ios::binary | std::ios::trunc); 102 testFile.close(); 103 104 uint64_t size = 4096; 105 Zero pass(testFileName); 106 uint32_t dummyValue = 88; 107 stdplus::fd::Fd&& write = 108 stdplus::fd::open(testFileName, stdplus::fd::OpenAccess::ReadWrite); 109 EXPECT_NO_THROW(pass.writeZero(size - sizeof(dummyValue), write)); 110 111 // open the file and write none zero to it 112 testFile.open(testFileName, std::ios::out); 113 testFile << dummyValue; 114 testFile.close(); 115 116 stdplus::fd::Fd&& read = 117 stdplus::fd::open(testFileName, stdplus::fd::OpenAccess::ReadWrite); 118 EXPECT_THROW(pass.verifyZero(size, read), InternalFailure); 119 } 120 121 TEST(Zeros, shortReadWritePass) 122 { 123 std::string testFileName = "testfile_shortRead"; 124 125 uint64_t size = 4096; 126 size_t shortSize = 128; 127 Zero pass(testFileName); 128 auto shortData = std::vector<std::byte>(shortSize, std::byte{0}); 129 auto restOfData = 130 std::vector<std::byte>(size - shortSize * 3, std::byte{0}); 131 stdplus::fd::FdMock mock; 132 133 // test write zeros with short blocks 134 EXPECT_CALL(mock, write(_)) 135 .WillOnce(Return(shortData)) 136 .WillOnce(Return(shortData)) 137 .WillOnce(Return(restOfData)) 138 .WillOnce(Return(shortData)); 139 140 EXPECT_NO_THROW(pass.writeZero(size, mock)); 141 142 // test read zeros with short blocks 143 EXPECT_CALL(mock, read(_)) 144 .WillOnce(Return(shortData)) 145 .WillOnce(Return(shortData)) 146 .WillOnce(Return(restOfData)) 147 .WillOnce(Return(shortData)); 148 149 EXPECT_NO_THROW(pass.verifyZero(size, mock)); 150 } 151 152 TEST(Zeros, shortReadWriteFail) 153 { 154 std::string testFileName = "testfile_shortRead"; 155 156 uint64_t size = 4096; 157 size_t shortSize = 128; 158 Zero tryZero(testFileName); 159 auto shortData = std::vector<std::byte>(shortSize, std::byte{0}); 160 auto restOfData = 161 std::vector<std::byte>(size - shortSize * 3, std::byte{0}); 162 // open the file and write none zero to it 163 164 stdplus::fd::FdMock mock; 165 166 // test writes 167 EXPECT_CALL(mock, write(_)) 168 .WillOnce(Return(shortData)) 169 .WillOnce(Return(shortData)) 170 .WillOnce(Return(restOfData)) 171 .WillOnce(Return(restOfData)); // return too much data! 172 173 EXPECT_THROW(tryZero.writeZero(size, mock), InternalFailure); 174 175 // test reads 176 EXPECT_CALL(mock, read(_)) 177 .WillOnce(Return(shortData)) 178 .WillOnce(Return(shortData)) 179 .WillOnce(Return(restOfData)) 180 .WillOnce(Return(restOfData)); // return too much data! 181 182 EXPECT_THROW(tryZero.verifyZero(size, mock), InternalFailure); 183 } 184 185 TEST(Zeros, driveIsSmaller) 186 { 187 std::string testFileName = "testfile_driveIsSmaller"; 188 189 uint64_t size = 4096; 190 Zero tryZero(testFileName); 191 192 stdplus::fd::FdMock mocks; 193 testing::InSequence s; 194 195 // test writes 196 EXPECT_CALL(mocks, write(_)) 197 .Times(33) 198 .WillRepeatedly(Return(std::vector<std::byte>{})) 199 .RetiresOnSaturation(); 200 EXPECT_THROW(tryZero.writeZero(size, mocks), InternalFailure); 201 // test reads 202 EXPECT_CALL(mocks, read(_)) 203 .Times(33) 204 .WillRepeatedly(Return(std::vector<std::byte>{})) 205 .RetiresOnSaturation(); 206 EXPECT_THROW(tryZero.verifyZero(size, mocks), InternalFailure); 207 } 208 209 } // namespace estoraged_test 210