17f2ab643SJohn Edward Broadbent #include "estoraged_conf.hpp"
27f2ab643SJohn Edward Broadbent #include "pattern.hpp"
37f2ab643SJohn Edward Broadbent 
47f2ab643SJohn Edward Broadbent #include <fcntl.h>
57f2ab643SJohn Edward Broadbent #include <unistd.h>
67f2ab643SJohn Edward Broadbent 
77f2ab643SJohn Edward Broadbent #include <stdplus/fd/create.hpp>
8d6071fc2SJohn Edward Broadbent #include <stdplus/fd/gmock.hpp>
97f2ab643SJohn Edward Broadbent #include <stdplus/fd/managed.hpp>
107f2ab643SJohn Edward Broadbent #include <xyz/openbmc_project/Common/error.hpp>
117f2ab643SJohn Edward Broadbent 
1269786761SJohn Edward Broadbent #include <fstream>
134906f4efSJohn Edward Broadbent #include <span>
147f2ab643SJohn Edward Broadbent #include <system_error>
157f2ab643SJohn Edward Broadbent 
167f2ab643SJohn Edward Broadbent #include <gmock/gmock-matchers.h>
177f2ab643SJohn Edward Broadbent #include <gmock/gmock.h>
187f2ab643SJohn Edward Broadbent #include <gtest/gtest.h>
197f2ab643SJohn Edward Broadbent 
20d3bfa7bbSJohn Edward Broadbent namespace estoraged_test
21d3bfa7bbSJohn Edward Broadbent {
22d3bfa7bbSJohn Edward Broadbent 
23d3bfa7bbSJohn Edward Broadbent using estoraged::Pattern;
247f2ab643SJohn Edward Broadbent using sdbusplus::xyz::openbmc_project::Common::Error::InternalFailure;
25d6071fc2SJohn Edward Broadbent using testing::_;
26d6071fc2SJohn Edward Broadbent using testing::Invoke;
27d6071fc2SJohn Edward Broadbent using testing::Return;
287f2ab643SJohn Edward Broadbent 
TEST(pattern,patternPass)297f2ab643SJohn Edward Broadbent TEST(pattern, patternPass)
307f2ab643SJohn Edward Broadbent {
3169786761SJohn Edward Broadbent     std::string testFileName = "patternPass";
327f2ab643SJohn Edward Broadbent     uint64_t size = 4096;
3369786761SJohn Edward Broadbent     std::ofstream testFile;
3469786761SJohn Edward Broadbent     testFile.open(testFileName,
3569786761SJohn Edward Broadbent                   std::ios::out | std::ios::binary | std::ios::trunc);
3669786761SJohn Edward Broadbent     testFile.close();
3769786761SJohn Edward Broadbent 
38d6071fc2SJohn Edward Broadbent     stdplus::fd::Fd&& writeFd =
39d6071fc2SJohn Edward Broadbent         stdplus::fd::open(testFileName, stdplus::fd::OpenAccess::WriteOnly);
40d6071fc2SJohn Edward Broadbent 
4169786761SJohn Edward Broadbent     Pattern pass(testFileName);
42d6071fc2SJohn Edward Broadbent     EXPECT_NO_THROW(pass.writePattern(size, writeFd));
43d6071fc2SJohn Edward Broadbent 
44d6071fc2SJohn Edward Broadbent     stdplus::fd::Fd&& readFd =
45d6071fc2SJohn Edward Broadbent         stdplus::fd::open(testFileName, stdplus::fd::OpenAccess::ReadOnly);
46d6071fc2SJohn Edward Broadbent 
47d6071fc2SJohn Edward Broadbent     EXPECT_NO_THROW(pass.verifyPattern(size, readFd));
487f2ab643SJohn Edward Broadbent }
497f2ab643SJohn Edward Broadbent 
507f2ab643SJohn Edward Broadbent /* This test that pattern writes the correct number of bytes even if
51*d4554f2aSManojkiran Eda  * size of the drive is not divisible by the block size
527f2ab643SJohn Edward Broadbent  */
53d6071fc2SJohn Edward Broadbent 
TEST(pattern,patternNotDivisible)5469786761SJohn Edward Broadbent TEST(pattern, patternNotDivisible)
557f2ab643SJohn Edward Broadbent {
5669786761SJohn Edward Broadbent     std::string testFileName = "notDivisible";
577f2ab643SJohn Edward Broadbent     uint64_t size = 4097;
587f2ab643SJohn Edward Broadbent     // 4097 is not divisible by the block size, and we expect no errors
5969786761SJohn Edward Broadbent     std::ofstream testFile;
6069786761SJohn Edward Broadbent     testFile.open(testFileName,
6169786761SJohn Edward Broadbent                   std::ios::out | std::ios::binary | std::ios::trunc);
6269786761SJohn Edward Broadbent     testFile.close();
6369786761SJohn Edward Broadbent 
64d6071fc2SJohn Edward Broadbent     stdplus::fd::Fd&& writeFd =
65d6071fc2SJohn Edward Broadbent         stdplus::fd::open(testFileName, stdplus::fd::OpenAccess::WriteOnly);
6669786761SJohn Edward Broadbent     Pattern pass(testFileName);
67d6071fc2SJohn Edward Broadbent     EXPECT_NO_THROW(pass.writePattern(size, writeFd));
68d6071fc2SJohn Edward Broadbent 
69d6071fc2SJohn Edward Broadbent     stdplus::fd::Fd&& readFd =
70d6071fc2SJohn Edward Broadbent         stdplus::fd::open(testFileName, stdplus::fd::OpenAccess::ReadOnly);
71d6071fc2SJohn Edward Broadbent     EXPECT_NO_THROW(pass.verifyPattern(size, readFd));
727f2ab643SJohn Edward Broadbent }
737f2ab643SJohn Edward Broadbent 
TEST(pattern,patternsDontMatch)747f2ab643SJohn Edward Broadbent TEST(pattern, patternsDontMatch)
757f2ab643SJohn Edward Broadbent {
7669786761SJohn Edward Broadbent     std::string testFileName = "patternsDontMatch";
777f2ab643SJohn Edward Broadbent     uint64_t size = 4096;
7869786761SJohn Edward Broadbent     std::ofstream testFile;
7969786761SJohn Edward Broadbent 
8069786761SJohn Edward Broadbent     Pattern pass(testFileName);
8169786761SJohn Edward Broadbent 
827f2ab643SJohn Edward Broadbent     int dummyValue = 88;
8369786761SJohn Edward Broadbent     testFile.open(testFileName, std::ios::binary | std::ios::out);
8482897c35SEd Tanous     testFile.write((reinterpret_cast<const char*>(&dummyValue)),
8582897c35SEd Tanous                    sizeof(dummyValue));
8669786761SJohn Edward Broadbent     testFile.close();
8769786761SJohn Edward Broadbent 
88d6071fc2SJohn Edward Broadbent     stdplus::fd::Fd&& writeFd =
89d6071fc2SJohn Edward Broadbent         stdplus::fd::open(testFileName, stdplus::fd::OpenAccess::WriteOnly);
90d6071fc2SJohn Edward Broadbent 
91d6071fc2SJohn Edward Broadbent     EXPECT_NO_THROW(pass.writePattern(size - sizeof(dummyValue), writeFd));
92d6071fc2SJohn Edward Broadbent 
93d6071fc2SJohn Edward Broadbent     stdplus::fd::Fd&& readFd =
94d6071fc2SJohn Edward Broadbent         stdplus::fd::open(testFileName, stdplus::fd::OpenAccess::ReadOnly);
95d6071fc2SJohn Edward Broadbent 
96d6071fc2SJohn Edward Broadbent     EXPECT_THROW(pass.verifyPattern(size, readFd), InternalFailure);
97d6071fc2SJohn Edward Broadbent }
98d6071fc2SJohn Edward Broadbent 
TEST(pattern,shortReadWritePass)9934a75f05SJohn Edward Broadbent TEST(pattern, shortReadWritePass)
10034a75f05SJohn Edward Broadbent {
10134a75f05SJohn Edward Broadbent     std::string testFileName = "testfile_shortRead";
102d6071fc2SJohn Edward Broadbent     uint64_t size = 4096;
103d6071fc2SJohn Edward Broadbent     size_t shortSize = 128;
104d6071fc2SJohn Edward Broadbent     static auto shortData1 = std::vector<std::byte>(shortSize);
105d6071fc2SJohn Edward Broadbent     static auto shortData2 = std::vector<std::byte>(shortSize);
106d6071fc2SJohn Edward Broadbent     static auto restOfData = std::vector<std::byte>(size - shortSize * 2);
107d6071fc2SJohn Edward Broadbent     Pattern pass(testFileName);
108d6071fc2SJohn Edward Broadbent     stdplus::fd::FdMock mock;
109d6071fc2SJohn Edward Broadbent 
110d6071fc2SJohn Edward Broadbent     testing::Sequence s;
111d6071fc2SJohn Edward Broadbent 
112d6071fc2SJohn Edward Broadbent     // test write pattern with short blocks
113d6071fc2SJohn Edward Broadbent     EXPECT_CALL(mock, write(_))
114d6071fc2SJohn Edward Broadbent         .WillOnce(Invoke([](std::span<const std::byte> x) {
115d6071fc2SJohn Edward Broadbent         std::copy_n(x.begin(), shortData1.size(), shortData1.begin());
116d6071fc2SJohn Edward Broadbent         return shortData1;
117ff1b64f0SPatrick Williams     })).RetiresOnSaturation();
118d6071fc2SJohn Edward Broadbent     EXPECT_CALL(mock, write(_))
119d6071fc2SJohn Edward Broadbent         .WillOnce(Invoke([](std::span<const std::byte> x) {
120d6071fc2SJohn Edward Broadbent         std::copy_n(x.begin(), restOfData.size(), restOfData.begin());
121d6071fc2SJohn Edward Broadbent         return restOfData;
122ff1b64f0SPatrick Williams     })).RetiresOnSaturation();
123d6071fc2SJohn Edward Broadbent     EXPECT_CALL(mock, write(_))
124d6071fc2SJohn Edward Broadbent         .WillOnce(Invoke([](std::span<const std::byte> x) {
125d6071fc2SJohn Edward Broadbent         std::copy_n(x.begin(), shortData2.size(), shortData2.begin());
126d6071fc2SJohn Edward Broadbent         return shortData2;
127ff1b64f0SPatrick Williams     })).RetiresOnSaturation();
128d6071fc2SJohn Edward Broadbent 
129d6071fc2SJohn Edward Broadbent     // test read pattern
130d6071fc2SJohn Edward Broadbent     EXPECT_CALL(mock, read(_))
1314906f4efSJohn Edward Broadbent         .WillOnce(Invoke([](std::span<std::byte> x) {
132d6071fc2SJohn Edward Broadbent         std::copy_n(shortData1.begin(), shortData1.size(), x.data());
1334906f4efSJohn Edward Broadbent         std::span ret(shortData1);
134d6071fc2SJohn Edward Broadbent         return ret;
135ff1b64f0SPatrick Williams     })).RetiresOnSaturation();
136d6071fc2SJohn Edward Broadbent 
137d6071fc2SJohn Edward Broadbent     EXPECT_CALL(mock, read(_))
1384906f4efSJohn Edward Broadbent         .WillOnce(Invoke([](std::span<std::byte> x) {
139d6071fc2SJohn Edward Broadbent         std::copy_n(restOfData.begin(), restOfData.size(), x.data());
1404906f4efSJohn Edward Broadbent         std::span ret(restOfData);
141d6071fc2SJohn Edward Broadbent         return ret;
142ff1b64f0SPatrick Williams     })).RetiresOnSaturation();
143d6071fc2SJohn Edward Broadbent 
144d6071fc2SJohn Edward Broadbent     EXPECT_CALL(mock, read(_))
1454906f4efSJohn Edward Broadbent         .WillOnce(Invoke([](std::span<std::byte> x) {
146d6071fc2SJohn Edward Broadbent         std::copy_n(shortData2.begin(), shortData2.size(), x.data());
1474906f4efSJohn Edward Broadbent         std::span ret(shortData2);
148d6071fc2SJohn Edward Broadbent         return ret;
149ff1b64f0SPatrick Williams     })).RetiresOnSaturation();
150d6071fc2SJohn Edward Broadbent 
151d6071fc2SJohn Edward Broadbent     EXPECT_NO_THROW(pass.writePattern(size, mock));
152d6071fc2SJohn Edward Broadbent     EXPECT_NO_THROW(pass.verifyPattern(size, mock));
153d6071fc2SJohn Edward Broadbent }
154d6071fc2SJohn Edward Broadbent 
TEST(Zeros,shortReadWriteFail)155d6071fc2SJohn Edward Broadbent TEST(Zeros, shortReadWriteFail)
156d6071fc2SJohn Edward Broadbent {
157d6071fc2SJohn Edward Broadbent     std::string testFileName = "testfile_shortRead";
158d6071fc2SJohn Edward Broadbent 
159d6071fc2SJohn Edward Broadbent     uint64_t size = 4096;
160d6071fc2SJohn Edward Broadbent     size_t shortSize = 128;
161d6071fc2SJohn Edward Broadbent     Pattern tryPattern(testFileName);
162d6071fc2SJohn Edward Broadbent     auto shortData = std::vector<std::byte>(shortSize, std::byte{0});
16304c28fadSPatrick Williams     auto restOfData = std::vector<std::byte>(size - shortSize * 3,
16404c28fadSPatrick Williams                                              std::byte{0});
165be47c8feSJohn Wedig     std::span shortDataSpan{shortData};
166be47c8feSJohn Wedig     std::span restOfDataSpan{restOfData};
167d6071fc2SJohn Edward Broadbent     // open the file and write none to it
168d6071fc2SJohn Edward Broadbent 
169d6071fc2SJohn Edward Broadbent     stdplus::fd::FdMock mock;
170d6071fc2SJohn Edward Broadbent 
171d6071fc2SJohn Edward Broadbent     // test writes
172d6071fc2SJohn Edward Broadbent     EXPECT_CALL(mock, write(_))
173be47c8feSJohn Wedig         .WillOnce(Return(shortDataSpan))
174be47c8feSJohn Wedig         .WillOnce(Return(shortDataSpan))
175be47c8feSJohn Wedig         .WillOnce(Return(restOfDataSpan))
176be47c8feSJohn Wedig         .WillOnce(Return(restOfDataSpan)); // return too much data!
177d6071fc2SJohn Edward Broadbent 
178d6071fc2SJohn Edward Broadbent     EXPECT_THROW(tryPattern.writePattern(size, mock), InternalFailure);
179d6071fc2SJohn Edward Broadbent 
180d6071fc2SJohn Edward Broadbent     // test reads
181d6071fc2SJohn Edward Broadbent     EXPECT_CALL(mock, read(_))
182be47c8feSJohn Wedig         .WillOnce(Return(shortDataSpan))
183be47c8feSJohn Wedig         .WillOnce(Return(shortDataSpan))
184be47c8feSJohn Wedig         .WillOnce(Return(restOfDataSpan))
185be47c8feSJohn Wedig         .WillOnce(Return(restOfDataSpan)); // return too much data!
186d6071fc2SJohn Edward Broadbent 
187d6071fc2SJohn Edward Broadbent     EXPECT_THROW(tryPattern.verifyPattern(size, mock), InternalFailure);
188d6071fc2SJohn Edward Broadbent }
189d6071fc2SJohn Edward Broadbent 
TEST(pattern,driveIsSmaller)190d6071fc2SJohn Edward Broadbent TEST(pattern, driveIsSmaller)
191d6071fc2SJohn Edward Broadbent {
192d6071fc2SJohn Edward Broadbent     std::string testFileName = "testfile_driveIsSmaller";
193d6071fc2SJohn Edward Broadbent 
194d6071fc2SJohn Edward Broadbent     uint64_t size = 4096;
195d6071fc2SJohn Edward Broadbent     Pattern tryPattern(testFileName);
196d6071fc2SJohn Edward Broadbent 
197d6071fc2SJohn Edward Broadbent     stdplus::fd::FdMock mocks;
198d6071fc2SJohn Edward Broadbent     testing::InSequence s;
199d6071fc2SJohn Edward Broadbent 
200d6071fc2SJohn Edward Broadbent     // test writes
201d6071fc2SJohn Edward Broadbent     EXPECT_CALL(mocks, write(_))
202d6071fc2SJohn Edward Broadbent         .Times(33)
203be47c8feSJohn Wedig         .WillRepeatedly(Return(std::span<std::byte>{}))
204d6071fc2SJohn Edward Broadbent         .RetiresOnSaturation();
205d6071fc2SJohn Edward Broadbent 
206d6071fc2SJohn Edward Broadbent     EXPECT_THROW(tryPattern.writePattern(size, mocks), InternalFailure);
207d6071fc2SJohn Edward Broadbent 
208d6071fc2SJohn Edward Broadbent     // test reads
209d6071fc2SJohn Edward Broadbent     EXPECT_CALL(mocks, read(_))
210d6071fc2SJohn Edward Broadbent         .Times(33)
211be47c8feSJohn Wedig         .WillRepeatedly(Return(std::span<std::byte>{}))
212d6071fc2SJohn Edward Broadbent         .RetiresOnSaturation();
213d6071fc2SJohn Edward Broadbent 
214d6071fc2SJohn Edward Broadbent     EXPECT_THROW(tryPattern.verifyPattern(size, mocks), InternalFailure);
2157f2ab643SJohn Edward Broadbent }
216d3bfa7bbSJohn Edward Broadbent 
217d3bfa7bbSJohn Edward Broadbent } // namespace estoraged_test
218