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 = std::vector<std::byte>(size - shortSize * 3, 130 std::byte{0}); 131 std::span shortDataSpan{shortData}; 132 std::span restOfDataSpan{restOfData}; 133 stdplus::fd::FdMock mock; 134 135 // test write zeros with short blocks 136 EXPECT_CALL(mock, write(_)) 137 .WillOnce(Return(shortDataSpan)) 138 .WillOnce(Return(shortDataSpan)) 139 .WillOnce(Return(restOfDataSpan)) 140 .WillOnce(Return(shortDataSpan)); 141 142 EXPECT_NO_THROW(pass.writeZero(size, mock)); 143 144 // test read zeros with short blocks 145 EXPECT_CALL(mock, read(_)) 146 .WillOnce(Return(shortDataSpan)) 147 .WillOnce(Return(shortDataSpan)) 148 .WillOnce(Return(restOfDataSpan)) 149 .WillOnce(Return(shortDataSpan)); 150 151 EXPECT_NO_THROW(pass.verifyZero(size, mock)); 152 } 153 154 TEST(Zeros, shortReadWriteFail) 155 { 156 std::string testFileName = "testfile_shortRead"; 157 158 uint64_t size = 4096; 159 size_t shortSize = 128; 160 Zero tryZero(testFileName); 161 auto shortData = std::vector<std::byte>(shortSize, std::byte{0}); 162 auto restOfData = std::vector<std::byte>(size - shortSize * 3, 163 std::byte{0}); 164 std::span shortDataSpan{shortData}; 165 std::span restOfDataSpan{restOfData}; 166 // open the file and write none zero to it 167 168 stdplus::fd::FdMock mock; 169 170 // test writes 171 EXPECT_CALL(mock, write(_)) 172 .WillOnce(Return(shortDataSpan)) 173 .WillOnce(Return(shortDataSpan)) 174 .WillOnce(Return(restOfDataSpan)) 175 .WillOnce(Return(restOfDataSpan)); // return too much data! 176 177 EXPECT_THROW(tryZero.writeZero(size, mock), InternalFailure); 178 179 // test reads 180 EXPECT_CALL(mock, read(_)) 181 .WillOnce(Return(shortDataSpan)) 182 .WillOnce(Return(shortDataSpan)) 183 .WillOnce(Return(restOfDataSpan)) 184 .WillOnce(Return(restOfDataSpan)); // return too much data! 185 186 EXPECT_THROW(tryZero.verifyZero(size, mock), InternalFailure); 187 } 188 189 TEST(Zeros, driveIsSmaller) 190 { 191 std::string testFileName = "testfile_driveIsSmaller"; 192 193 uint64_t size = 4096; 194 Zero tryZero(testFileName); 195 196 stdplus::fd::FdMock mocks; 197 testing::InSequence s; 198 199 // test writes 200 EXPECT_CALL(mocks, write(_)) 201 .Times(33) 202 .WillRepeatedly(Return(std::span<std::byte>{})) 203 .RetiresOnSaturation(); 204 EXPECT_THROW(tryZero.writeZero(size, mocks), InternalFailure); 205 // test reads 206 EXPECT_CALL(mocks, read(_)) 207 .Times(33) 208 .WillRepeatedly(Return(std::span<std::byte>{})) 209 .RetiresOnSaturation(); 210 EXPECT_THROW(tryZero.verifyZero(size, mocks), InternalFailure); 211 } 212 213 } // namespace estoraged_test 214