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>
137f2ab643SJohn Edward Broadbent #include <system_error>
147f2ab643SJohn Edward Broadbent 
157f2ab643SJohn Edward Broadbent #include <gmock/gmock-matchers.h>
167f2ab643SJohn Edward Broadbent #include <gmock/gmock.h>
177f2ab643SJohn Edward Broadbent #include <gtest/gtest.h>
187f2ab643SJohn Edward Broadbent 
19d3bfa7bbSJohn Edward Broadbent namespace estoraged_test
20d3bfa7bbSJohn Edward Broadbent {
21d3bfa7bbSJohn Edward Broadbent 
22d3bfa7bbSJohn Edward Broadbent using estoraged::Pattern;
237f2ab643SJohn Edward Broadbent using sdbusplus::xyz::openbmc_project::Common::Error::InternalFailure;
24d6071fc2SJohn Edward Broadbent using testing::_;
25d6071fc2SJohn Edward Broadbent using testing::Invoke;
26d6071fc2SJohn Edward Broadbent using testing::Return;
277f2ab643SJohn Edward Broadbent 
287f2ab643SJohn Edward Broadbent TEST(pattern, patternPass)
297f2ab643SJohn Edward Broadbent {
3069786761SJohn Edward Broadbent     std::string testFileName = "patternPass";
317f2ab643SJohn Edward Broadbent     uint64_t size = 4096;
3269786761SJohn Edward Broadbent     std::ofstream testFile;
3369786761SJohn Edward Broadbent     testFile.open(testFileName,
3469786761SJohn Edward Broadbent                   std::ios::out | std::ios::binary | std::ios::trunc);
3569786761SJohn Edward Broadbent     testFile.close();
3669786761SJohn Edward Broadbent 
37d6071fc2SJohn Edward Broadbent     stdplus::fd::Fd&& writeFd =
38d6071fc2SJohn Edward Broadbent         stdplus::fd::open(testFileName, stdplus::fd::OpenAccess::WriteOnly);
39d6071fc2SJohn Edward Broadbent 
4069786761SJohn Edward Broadbent     Pattern pass(testFileName);
41d6071fc2SJohn Edward Broadbent     EXPECT_NO_THROW(pass.writePattern(size, writeFd));
42d6071fc2SJohn Edward Broadbent 
43d6071fc2SJohn Edward Broadbent     stdplus::fd::Fd&& readFd =
44d6071fc2SJohn Edward Broadbent         stdplus::fd::open(testFileName, stdplus::fd::OpenAccess::ReadOnly);
45d6071fc2SJohn Edward Broadbent 
46d6071fc2SJohn Edward Broadbent     EXPECT_NO_THROW(pass.verifyPattern(size, readFd));
477f2ab643SJohn Edward Broadbent }
487f2ab643SJohn Edward Broadbent 
497f2ab643SJohn Edward Broadbent /* This test that pattern writes the correct number of bytes even if
507f2ab643SJohn Edward Broadbent  * size of the drive is not divisable by the block size
517f2ab643SJohn Edward Broadbent  */
52d6071fc2SJohn Edward Broadbent 
5369786761SJohn Edward Broadbent TEST(pattern, patternNotDivisible)
547f2ab643SJohn Edward Broadbent {
5569786761SJohn Edward Broadbent     std::string testFileName = "notDivisible";
567f2ab643SJohn Edward Broadbent     uint64_t size = 4097;
577f2ab643SJohn Edward Broadbent     // 4097 is not divisible by the block size, and we expect no errors
5869786761SJohn Edward Broadbent     std::ofstream testFile;
5969786761SJohn Edward Broadbent     testFile.open(testFileName,
6069786761SJohn Edward Broadbent                   std::ios::out | std::ios::binary | std::ios::trunc);
6169786761SJohn Edward Broadbent     testFile.close();
6269786761SJohn Edward Broadbent 
63d6071fc2SJohn Edward Broadbent     stdplus::fd::Fd&& writeFd =
64d6071fc2SJohn Edward Broadbent         stdplus::fd::open(testFileName, stdplus::fd::OpenAccess::WriteOnly);
6569786761SJohn Edward Broadbent     Pattern pass(testFileName);
66d6071fc2SJohn Edward Broadbent     EXPECT_NO_THROW(pass.writePattern(size, writeFd));
67d6071fc2SJohn Edward Broadbent 
68d6071fc2SJohn Edward Broadbent     stdplus::fd::Fd&& readFd =
69d6071fc2SJohn Edward Broadbent         stdplus::fd::open(testFileName, stdplus::fd::OpenAccess::ReadOnly);
70d6071fc2SJohn Edward Broadbent     EXPECT_NO_THROW(pass.verifyPattern(size, readFd));
717f2ab643SJohn Edward Broadbent }
727f2ab643SJohn Edward Broadbent 
737f2ab643SJohn Edward Broadbent TEST(pattern, patternsDontMatch)
747f2ab643SJohn Edward Broadbent {
7569786761SJohn Edward Broadbent     std::string testFileName = "patternsDontMatch";
767f2ab643SJohn Edward Broadbent     uint64_t size = 4096;
7769786761SJohn Edward Broadbent     std::ofstream testFile;
7869786761SJohn Edward Broadbent 
7969786761SJohn Edward Broadbent     Pattern pass(testFileName);
8069786761SJohn Edward Broadbent 
817f2ab643SJohn Edward Broadbent     int dummyValue = 88;
8269786761SJohn Edward Broadbent     testFile.open(testFileName, std::ios::binary | std::ios::out);
8382897c35SEd Tanous     testFile.write((reinterpret_cast<const char*>(&dummyValue)),
8482897c35SEd Tanous                    sizeof(dummyValue));
8569786761SJohn Edward Broadbent     testFile.close();
8669786761SJohn Edward Broadbent 
87d6071fc2SJohn Edward Broadbent     stdplus::fd::Fd&& writeFd =
88d6071fc2SJohn Edward Broadbent         stdplus::fd::open(testFileName, stdplus::fd::OpenAccess::WriteOnly);
89d6071fc2SJohn Edward Broadbent 
90d6071fc2SJohn Edward Broadbent     EXPECT_NO_THROW(pass.writePattern(size - sizeof(dummyValue), writeFd));
91d6071fc2SJohn Edward Broadbent 
92d6071fc2SJohn Edward Broadbent     stdplus::fd::Fd&& readFd =
93d6071fc2SJohn Edward Broadbent         stdplus::fd::open(testFileName, stdplus::fd::OpenAccess::ReadOnly);
94d6071fc2SJohn Edward Broadbent 
95d6071fc2SJohn Edward Broadbent     EXPECT_THROW(pass.verifyPattern(size, readFd), InternalFailure);
96d6071fc2SJohn Edward Broadbent }
97d6071fc2SJohn Edward Broadbent 
98*34a75f05SJohn Edward Broadbent TEST(pattern, shortReadWritePass)
99*34a75f05SJohn Edward Broadbent {
100*34a75f05SJohn Edward Broadbent     std::string testFileName = "testfile_shortRead";
101d6071fc2SJohn Edward Broadbent     uint64_t size = 4096;
102d6071fc2SJohn Edward Broadbent     size_t shortSize = 128;
103d6071fc2SJohn Edward Broadbent     static auto shortData1 = std::vector<std::byte>(shortSize);
104d6071fc2SJohn Edward Broadbent     static auto shortData2 = std::vector<std::byte>(shortSize);
105d6071fc2SJohn Edward Broadbent     static auto restOfData = std::vector<std::byte>(size - shortSize * 2);
106d6071fc2SJohn Edward Broadbent     Pattern pass(testFileName);
107d6071fc2SJohn Edward Broadbent     stdplus::fd::FdMock mock;
108d6071fc2SJohn Edward Broadbent 
109d6071fc2SJohn Edward Broadbent     testing::Sequence s;
110d6071fc2SJohn Edward Broadbent 
111d6071fc2SJohn Edward Broadbent     // test write pattern with short blocks
112d6071fc2SJohn Edward Broadbent     EXPECT_CALL(mock, write(_))
113d6071fc2SJohn Edward Broadbent         .WillOnce(Invoke([](std::span<const std::byte> x) {
114d6071fc2SJohn Edward Broadbent             std::copy_n(x.begin(), shortData1.size(), shortData1.begin());
115d6071fc2SJohn Edward Broadbent             return shortData1;
116d6071fc2SJohn Edward Broadbent         }))
117d6071fc2SJohn Edward Broadbent         .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;
122d6071fc2SJohn Edward Broadbent         }))
123d6071fc2SJohn Edward Broadbent         .RetiresOnSaturation();
124d6071fc2SJohn Edward Broadbent     EXPECT_CALL(mock, write(_))
125d6071fc2SJohn Edward Broadbent         .WillOnce(Invoke([](std::span<const std::byte> x) {
126d6071fc2SJohn Edward Broadbent             std::copy_n(x.begin(), shortData2.size(), shortData2.begin());
127d6071fc2SJohn Edward Broadbent             return shortData2;
128d6071fc2SJohn Edward Broadbent         }))
129d6071fc2SJohn Edward Broadbent         .RetiresOnSaturation();
130d6071fc2SJohn Edward Broadbent 
131d6071fc2SJohn Edward Broadbent     // test read pattern
132d6071fc2SJohn Edward Broadbent     EXPECT_CALL(mock, read(_))
133d6071fc2SJohn Edward Broadbent         .WillOnce(Invoke([](nonstd::span<std::byte> x) {
134d6071fc2SJohn Edward Broadbent             std::copy_n(shortData1.begin(), shortData1.size(), x.data());
135d6071fc2SJohn Edward Broadbent             nonstd::span ret(shortData1);
136d6071fc2SJohn Edward Broadbent             return ret;
137d6071fc2SJohn Edward Broadbent         }))
138d6071fc2SJohn Edward Broadbent         .RetiresOnSaturation();
139d6071fc2SJohn Edward Broadbent 
140d6071fc2SJohn Edward Broadbent     EXPECT_CALL(mock, read(_))
141d6071fc2SJohn Edward Broadbent         .WillOnce(Invoke([](nonstd::span<std::byte> x) {
142d6071fc2SJohn Edward Broadbent             std::copy_n(restOfData.begin(), restOfData.size(), x.data());
143d6071fc2SJohn Edward Broadbent             nonstd::span ret(restOfData);
144d6071fc2SJohn Edward Broadbent             return ret;
145d6071fc2SJohn Edward Broadbent         }))
146d6071fc2SJohn Edward Broadbent         .RetiresOnSaturation();
147d6071fc2SJohn Edward Broadbent 
148d6071fc2SJohn Edward Broadbent     EXPECT_CALL(mock, read(_))
149d6071fc2SJohn Edward Broadbent         .WillOnce(Invoke([](nonstd::span<std::byte> x) {
150d6071fc2SJohn Edward Broadbent             std::copy_n(shortData2.begin(), shortData2.size(), x.data());
151d6071fc2SJohn Edward Broadbent             nonstd::span ret(shortData2);
152d6071fc2SJohn Edward Broadbent             return ret;
153d6071fc2SJohn Edward Broadbent         }))
154d6071fc2SJohn Edward Broadbent         .RetiresOnSaturation();
155d6071fc2SJohn Edward Broadbent 
156d6071fc2SJohn Edward Broadbent     EXPECT_NO_THROW(pass.writePattern(size, mock));
157d6071fc2SJohn Edward Broadbent     EXPECT_NO_THROW(pass.verifyPattern(size, mock));
158d6071fc2SJohn Edward Broadbent }
159d6071fc2SJohn Edward Broadbent 
160d6071fc2SJohn Edward Broadbent TEST(Zeros, shortReadWriteFail)
161d6071fc2SJohn Edward Broadbent {
162d6071fc2SJohn Edward Broadbent     std::string testFileName = "testfile_shortRead";
163d6071fc2SJohn Edward Broadbent 
164d6071fc2SJohn Edward Broadbent     uint64_t size = 4096;
165d6071fc2SJohn Edward Broadbent     size_t shortSize = 128;
166d6071fc2SJohn Edward Broadbent     Pattern tryPattern(testFileName);
167d6071fc2SJohn Edward Broadbent     auto shortData = std::vector<std::byte>(shortSize, std::byte{0});
168d6071fc2SJohn Edward Broadbent     auto restOfData =
169d6071fc2SJohn Edward Broadbent         std::vector<std::byte>(size - shortSize * 3, std::byte{0});
170d6071fc2SJohn Edward Broadbent     // open the file and write none to it
171d6071fc2SJohn Edward Broadbent 
172d6071fc2SJohn Edward Broadbent     stdplus::fd::FdMock mock;
173d6071fc2SJohn Edward Broadbent 
174d6071fc2SJohn Edward Broadbent     // test writes
175d6071fc2SJohn Edward Broadbent     EXPECT_CALL(mock, write(_))
176d6071fc2SJohn Edward Broadbent         .WillOnce(Return(shortData))
177d6071fc2SJohn Edward Broadbent         .WillOnce(Return(shortData))
178d6071fc2SJohn Edward Broadbent         .WillOnce(Return(restOfData))
179d6071fc2SJohn Edward Broadbent         .WillOnce(Return(restOfData)); // return too much data!
180d6071fc2SJohn Edward Broadbent 
181d6071fc2SJohn Edward Broadbent     EXPECT_THROW(tryPattern.writePattern(size, mock), InternalFailure);
182d6071fc2SJohn Edward Broadbent 
183d6071fc2SJohn Edward Broadbent     // test reads
184d6071fc2SJohn Edward Broadbent     EXPECT_CALL(mock, read(_))
185d6071fc2SJohn Edward Broadbent         .WillOnce(Return(shortData))
186d6071fc2SJohn Edward Broadbent         .WillOnce(Return(shortData))
187d6071fc2SJohn Edward Broadbent         .WillOnce(Return(restOfData))
188d6071fc2SJohn Edward Broadbent         .WillOnce(Return(restOfData)); // return too much data!
189d6071fc2SJohn Edward Broadbent 
190d6071fc2SJohn Edward Broadbent     EXPECT_THROW(tryPattern.verifyPattern(size, mock), InternalFailure);
191d6071fc2SJohn Edward Broadbent }
192d6071fc2SJohn Edward Broadbent 
193d6071fc2SJohn Edward Broadbent TEST(pattern, driveIsSmaller)
194d6071fc2SJohn Edward Broadbent {
195d6071fc2SJohn Edward Broadbent     std::string testFileName = "testfile_driveIsSmaller";
196d6071fc2SJohn Edward Broadbent 
197d6071fc2SJohn Edward Broadbent     uint64_t size = 4096;
198d6071fc2SJohn Edward Broadbent     Pattern tryPattern(testFileName);
199d6071fc2SJohn Edward Broadbent 
200d6071fc2SJohn Edward Broadbent     stdplus::fd::FdMock mocks;
201d6071fc2SJohn Edward Broadbent     testing::InSequence s;
202d6071fc2SJohn Edward Broadbent 
203d6071fc2SJohn Edward Broadbent     // test writes
204d6071fc2SJohn Edward Broadbent     EXPECT_CALL(mocks, write(_))
205d6071fc2SJohn Edward Broadbent         .Times(33)
206d6071fc2SJohn Edward Broadbent         .WillRepeatedly(Return(std::vector<std::byte>{}))
207d6071fc2SJohn Edward Broadbent         .RetiresOnSaturation();
208d6071fc2SJohn Edward Broadbent 
209d6071fc2SJohn Edward Broadbent     EXPECT_THROW(tryPattern.writePattern(size, mocks), InternalFailure);
210d6071fc2SJohn Edward Broadbent 
211d6071fc2SJohn Edward Broadbent     // test reads
212d6071fc2SJohn Edward Broadbent     EXPECT_CALL(mocks, read(_))
213d6071fc2SJohn Edward Broadbent         .Times(33)
214d6071fc2SJohn Edward Broadbent         .WillRepeatedly(Return(std::vector<std::byte>{}))
215d6071fc2SJohn Edward Broadbent         .RetiresOnSaturation();
216d6071fc2SJohn Edward Broadbent 
217d6071fc2SJohn Edward Broadbent     EXPECT_THROW(tryPattern.verifyPattern(size, mocks), InternalFailure);
2187f2ab643SJohn Edward Broadbent }
219d3bfa7bbSJohn Edward Broadbent 
220d3bfa7bbSJohn Edward Broadbent } // namespace estoraged_test
221