xref: /openbmc/estoraged/src/test/erase/zero_test.cpp (revision d6071fc25a9880e8b622792b1e48d83fb5010e5e)
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