xref: /openbmc/estoraged/src/test/erase/zero_test.cpp (revision 8d5a3a07)
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     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 =
163         std::vector<std::byte>(size - shortSize * 3, 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