1 
2 #include "libpldmresponder/file_io.hpp"
3 #include "libpldmresponder/file_io_by_type.hpp"
4 #include "libpldmresponder/file_io_type_cert.hpp"
5 #include "libpldmresponder/file_io_type_dump.hpp"
6 #include "libpldmresponder/file_io_type_lid.hpp"
7 #include "libpldmresponder/file_io_type_pcie.hpp"
8 #include "libpldmresponder/file_io_type_pel.hpp"
9 #include "libpldmresponder/file_table.hpp"
10 #include "xyz/openbmc_project/Common/error.hpp"
11 
12 #include <libpldm/base.h>
13 #include <libpldm/oem/ibm/file_io.h>
14 
15 #include <nlohmann/json.hpp>
16 
17 #include <filesystem>
18 #include <fstream>
19 
20 #include <gmock/gmock-matchers.h>
21 #include <gmock/gmock.h>
22 #include <gtest/gtest.h>
23 
24 namespace fs = std::filesystem;
25 using Json = nlohmann::json;
26 using namespace pldm::filetable;
27 using namespace pldm::responder;
28 
29 class TestFileTable : public testing::Test
30 {
31   public:
SetUp()32     void SetUp() override
33     {
34         // Create a temporary directory to hold the config file and files to
35         // populate the file table.
36         char tmppldm[] = "/tmp/pldm_fileio_table.XXXXXX";
37         dir = fs::path(mkdtemp(tmppldm));
38 
39         // Copy the sample image files to the directory
40         fs::copy("./files", dir);
41 
42         imageFile = dir / "NVRAM-IMAGE";
43         auto jsonObjects = Json::array();
44         auto obj = Json::object();
45         obj["path"] = imageFile.c_str();
46         obj["file_traits"] = 1;
47 
48         jsonObjects.push_back(obj);
49         obj.clear();
50         cksumFile = dir / "NVRAM-IMAGE-CKSUM";
51         obj["path"] = cksumFile.c_str();
52         obj["file_traits"] = 4;
53         jsonObjects.push_back(obj);
54 
55         fileTableConfig = dir / "configFile.json";
56         std::ofstream file(fileTableConfig.c_str());
57         file << std::setw(4) << jsonObjects << std::endl;
58     }
59 
TearDown()60     void TearDown() override
61     {
62         fs::remove_all(dir);
63     }
64 
65     fs::path dir;
66     fs::path imageFile;
67     fs::path cksumFile;
68     fs::path fileTableConfig;
69 
70     // <4 bytes - File handle - 0 (0x00 0x00 0x00 0x00)>,
71     // <2 bytes - Filename length - 11 (0x0b 0x00>
72     // <11 bytes - Filename - ASCII for NVRAM-IMAGE>
73     // <4 bytes - File size - 1024 (0x00 0x04 0x00 0x00)>
74     // <4 bytes - File traits - 1 (0x01 0x00 0x00 0x00)>
75     // <4 bytes - File handle - 1 (0x01 0x00 0x00 0x00)>,
76     // <2 bytes - Filename length - 17 (0x11 0x00>
77     // <17 bytes - Filename - ASCII for NVRAM-IMAGE-CKSUM>
78     // <4 bytes - File size - 16 (0x0f 0x00 0x00 0x00)>
79     // <4 bytes - File traits - 4 (0x04 0x00 0x00 0x00)>
80     // No pad bytes added since the length for both the file entries in the
81     // table is 56, which is a multiple of 4.
82     // <4 bytes - Checksum - 2088303182(0x4e 0xfa 0x78 0x7c)>
83     Table attrTable = {
84         0x00, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x4e, 0x56, 0x52, 0x41, 0x4d, 0x2d,
85         0x49, 0x4d, 0x41, 0x47, 0x45, 0x00, 0x04, 0x00, 0x00, 0x01, 0x00, 0x00,
86         0x00, 0x01, 0x00, 0x00, 0x00, 0x11, 0x00, 0x4e, 0x56, 0x52, 0x41, 0x4d,
87         0x2d, 0x49, 0x4d, 0x41, 0x47, 0x45, 0x2d, 0x43, 0x4b, 0x53, 0x55, 0x4d,
88         0x10, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x4e, 0xfa, 0x78, 0x7c};
89 };
90 
91 namespace pldm
92 {
93 
94 namespace responder
95 {
96 
97 namespace dma
98 {
99 
100 class MockDMA
101 {
102   public:
103     MOCK_METHOD5(transferDataHost, int(int fd, uint32_t offset, uint32_t length,
104                                        uint64_t address, bool upstream));
105 };
106 
107 } // namespace dma
108 } // namespace responder
109 } // namespace pldm
110 using namespace pldm::responder;
111 using ::testing::_;
112 using ::testing::Return;
113 
TEST(TransferDataHost,GoodPath)114 TEST(TransferDataHost, GoodPath)
115 {
116     using namespace pldm::responder::dma;
117 
118     MockDMA dmaObj;
119     char tmpfile[] = "/tmp/pldm_fileio_table.XXXXXX";
120     int fd = mkstemp(tmpfile);
121     close(fd);
122     fs::path path(tmpfile);
123 
124     // Minimum length of 16 and expect transferDataHost to be called once
125     // returns the default value of 0 (the return type of transferDataHost is
126     // int, the default value for int is 0)
127     uint32_t length = minSize;
128     EXPECT_CALL(dmaObj, transferDataHost(_, 0, length, 0, true)).Times(1);
129     auto response = transferAll<MockDMA>(&dmaObj, PLDM_READ_FILE_INTO_MEMORY,
130                                          path, 0, length, 0, true, 0);
131     auto responsePtr = reinterpret_cast<pldm_msg*>(response.data());
132     ASSERT_EQ(responsePtr->payload[0], PLDM_SUCCESS);
133     ASSERT_EQ(0, memcmp(responsePtr->payload + sizeof(responsePtr->payload[0]),
134                         &length, sizeof(length)));
135 
136     // maxsize of DMA
137     length = maxSize;
138     EXPECT_CALL(dmaObj, transferDataHost(_, 0, length, 0, true)).Times(1);
139     response = transferAll<MockDMA>(&dmaObj, PLDM_READ_FILE_INTO_MEMORY, path,
140                                     0, length, 0, true, 0);
141     responsePtr = reinterpret_cast<pldm_msg*>(response.data());
142     ASSERT_EQ(responsePtr->payload[0], PLDM_SUCCESS);
143     ASSERT_EQ(0, memcmp(responsePtr->payload + sizeof(responsePtr->payload[0]),
144                         &length, sizeof(length)));
145 
146     // length greater than maxsize of DMA
147     length = maxSize + minSize;
148     EXPECT_CALL(dmaObj, transferDataHost(_, 0, maxSize, 0, true)).Times(1);
149     EXPECT_CALL(dmaObj, transferDataHost(_, maxSize, minSize, maxSize, true))
150         .Times(1);
151     response = transferAll<MockDMA>(&dmaObj, PLDM_READ_FILE_INTO_MEMORY, path,
152                                     0, length, 0, true, 0);
153     responsePtr = reinterpret_cast<pldm_msg*>(response.data());
154     ASSERT_EQ(responsePtr->payload[0], PLDM_SUCCESS);
155     ASSERT_EQ(0, memcmp(responsePtr->payload + sizeof(responsePtr->payload[0]),
156                         &length, sizeof(length)));
157 
158     // length greater than 2*maxsize of DMA
159     length = 3 * maxSize;
160     EXPECT_CALL(dmaObj, transferDataHost(_, _, _, _, true)).Times(3);
161     response = transferAll<MockDMA>(&dmaObj, PLDM_READ_FILE_INTO_MEMORY, path,
162                                     0, length, 0, true, 0);
163     responsePtr = reinterpret_cast<pldm_msg*>(response.data());
164     ASSERT_EQ(responsePtr->payload[0], PLDM_SUCCESS);
165     ASSERT_EQ(0, memcmp(responsePtr->payload + sizeof(responsePtr->payload[0]),
166                         &length, sizeof(length)));
167 
168     // check for downstream(copy data from host to BMC) parameter
169     length = minSize;
170     EXPECT_CALL(dmaObj, transferDataHost(_, 0, length, 0, false)).Times(1);
171     response = transferAll<MockDMA>(&dmaObj, PLDM_READ_FILE_INTO_MEMORY, path,
172                                     0, length, 0, false, 0);
173     responsePtr = reinterpret_cast<pldm_msg*>(response.data());
174     ASSERT_EQ(responsePtr->payload[0], PLDM_SUCCESS);
175     ASSERT_EQ(0, memcmp(responsePtr->payload + sizeof(responsePtr->payload[0]),
176                         &length, sizeof(length)));
177 }
178 
TEST(TransferDataHost,BadPath)179 TEST(TransferDataHost, BadPath)
180 {
181     using namespace pldm::responder::dma;
182 
183     MockDMA dmaObj;
184     char tmpfile[] = "/tmp/pldm_fileio_table.XXXXXX";
185     int fd = mkstemp(tmpfile);
186     close(fd);
187     fs::path path(tmpfile);
188 
189     // Minimum length of 16 and transferDataHost returning a negative errno
190     uint32_t length = minSize;
191     EXPECT_CALL(dmaObj, transferDataHost(_, _, _, _, _)).WillOnce(Return(-1));
192     auto response = transferAll<MockDMA>(&dmaObj, PLDM_READ_FILE_INTO_MEMORY,
193                                          path, 0, length, 0, true, 0);
194     auto responsePtr = reinterpret_cast<pldm_msg*>(response.data());
195     ASSERT_EQ(responsePtr->payload[0], PLDM_ERROR);
196 
197     // length greater than maxsize of DMA and transferDataHost returning a
198     // negative errno
199     length = maxSize + minSize;
200     EXPECT_CALL(dmaObj, transferDataHost(_, _, _, _, _)).WillOnce(Return(-1));
201     response = transferAll<MockDMA>(&dmaObj, PLDM_READ_FILE_INTO_MEMORY, path,
202                                     0, length, 0, true, 0);
203     responsePtr = reinterpret_cast<pldm_msg*>(response.data());
204     ASSERT_EQ(responsePtr->payload[0], PLDM_ERROR);
205 }
206 
TEST(ReadFileIntoMemory,BadPath)207 TEST(ReadFileIntoMemory, BadPath)
208 {
209     uint32_t fileHandle = 0;
210     uint32_t offset = 0;
211     uint32_t length = 10;
212     uint64_t address = 0;
213     uint8_t host_eid = 0;
214     int hostSocketFd = 0;
215 
216     std::array<uint8_t, sizeof(pldm_msg_hdr) + PLDM_RW_FILE_MEM_REQ_BYTES>
217         requestMsg{};
218     auto request = reinterpret_cast<pldm_msg*>(requestMsg.data());
219     memcpy(request->payload, &fileHandle, sizeof(fileHandle));
220     memcpy(request->payload + sizeof(fileHandle), &offset, sizeof(offset));
221     memcpy(request->payload + sizeof(fileHandle) + sizeof(offset), &length,
222            sizeof(length));
223     memcpy(request->payload + sizeof(fileHandle) + sizeof(offset) +
224                sizeof(length),
225            &address, sizeof(address));
226 
227     // Pass invalid payload length
228     std::unique_ptr<oem_platform::Handler> oemPlatformHandler{};
229     oem_ibm::Handler handler(oemPlatformHandler.get(), hostSocketFd, host_eid,
230                              nullptr, nullptr);
231     auto response = handler.readFileIntoMemory(request, 0);
232     auto responsePtr = reinterpret_cast<pldm_msg*>(response.data());
233     ASSERT_EQ(responsePtr->payload[0], PLDM_ERROR_INVALID_LENGTH);
234 }
235 
TEST_F(TestFileTable,ReadFileInvalidFileHandle)236 TEST_F(TestFileTable, ReadFileInvalidFileHandle)
237 {
238     // Invalid file handle in the file table
239     uint32_t fileHandle = 2;
240     uint32_t offset = 0;
241     uint32_t length = 0;
242     uint64_t address = 0;
243     uint8_t host_eid = 0;
244     int hostSocketFd = 0;
245 
246     std::array<uint8_t, sizeof(pldm_msg_hdr) + PLDM_RW_FILE_MEM_REQ_BYTES>
247         requestMsg{};
248     auto request = reinterpret_cast<pldm_msg*>(requestMsg.data());
249     size_t requestPayloadLength = requestMsg.size() - sizeof(pldm_msg_hdr);
250     memcpy(request->payload, &fileHandle, sizeof(fileHandle));
251     memcpy(request->payload + sizeof(fileHandle), &offset, sizeof(offset));
252     memcpy(request->payload + sizeof(fileHandle) + sizeof(offset), &length,
253            sizeof(length));
254     memcpy(request->payload + sizeof(fileHandle) + sizeof(offset) +
255                sizeof(length),
256            &address, sizeof(address));
257 
258     using namespace pldm::filetable;
259     // Initialise the file table with 2 valid file handles 0 & 1.
260     auto& table = buildFileTable(fileTableConfig.c_str());
261 
262     std::unique_ptr<oem_platform::Handler> oemPlatformHandler{};
263     oem_ibm::Handler handler(oemPlatformHandler.get(), hostSocketFd, host_eid,
264                              nullptr, nullptr);
265     auto response = handler.readFileIntoMemory(request, requestPayloadLength);
266     auto responsePtr = reinterpret_cast<pldm_msg*>(response.data());
267     ASSERT_EQ(responsePtr->payload[0], PLDM_INVALID_FILE_HANDLE);
268     // Clear the file table contents.
269     table.clear();
270 }
271 
TEST_F(TestFileTable,ReadFileInvalidOffset)272 TEST_F(TestFileTable, ReadFileInvalidOffset)
273 {
274     uint32_t fileHandle = 0;
275     // The file size is 1024, so the offset is invalid
276     uint32_t offset = 1024;
277     uint32_t length = 0;
278     uint64_t address = 0;
279     uint8_t host_eid = 0;
280     int hostSocketFd = 0;
281 
282     std::array<uint8_t, sizeof(pldm_msg_hdr) + PLDM_RW_FILE_MEM_REQ_BYTES>
283         requestMsg{};
284     auto request = reinterpret_cast<pldm_msg*>(requestMsg.data());
285     size_t requestPayloadLength = requestMsg.size() - sizeof(pldm_msg_hdr);
286     memcpy(request->payload, &fileHandle, sizeof(fileHandle));
287     memcpy(request->payload + sizeof(fileHandle), &offset, sizeof(offset));
288     memcpy(request->payload + sizeof(fileHandle) + sizeof(offset), &length,
289            sizeof(length));
290     memcpy(request->payload + sizeof(fileHandle) + sizeof(offset) +
291                sizeof(length),
292            &address, sizeof(address));
293 
294     using namespace pldm::filetable;
295     auto& table = buildFileTable(fileTableConfig.c_str());
296 
297     std::unique_ptr<oem_platform::Handler> oemPlatformHandler{};
298     oem_ibm::Handler handler(oemPlatformHandler.get(), hostSocketFd, host_eid,
299                              nullptr, nullptr);
300     auto response = handler.readFileIntoMemory(request, requestPayloadLength);
301     auto responsePtr = reinterpret_cast<pldm_msg*>(response.data());
302     ASSERT_EQ(responsePtr->payload[0], PLDM_DATA_OUT_OF_RANGE);
303     // Clear the file table contents.
304     table.clear();
305 }
306 
TEST_F(TestFileTable,ReadFileInvalidLength)307 TEST_F(TestFileTable, ReadFileInvalidLength)
308 {
309     uint32_t fileHandle = 0;
310     uint32_t offset = 100;
311     // Length should be a multiple of dma min size(16)
312     uint32_t length = 10;
313     uint64_t address = 0;
314     uint8_t host_eid = 0;
315     int hostSocketFd = 0;
316 
317     std::array<uint8_t, sizeof(pldm_msg_hdr) + PLDM_RW_FILE_MEM_REQ_BYTES>
318         requestMsg{};
319     auto request = reinterpret_cast<pldm_msg*>(requestMsg.data());
320     size_t requestPayloadLength = requestMsg.size() - sizeof(pldm_msg_hdr);
321     memcpy(request->payload, &fileHandle, sizeof(fileHandle));
322     memcpy(request->payload + sizeof(fileHandle), &offset, sizeof(offset));
323     memcpy(request->payload + sizeof(fileHandle) + sizeof(offset), &length,
324            sizeof(length));
325     memcpy(request->payload + sizeof(fileHandle) + sizeof(offset) +
326                sizeof(length),
327            &address, sizeof(address));
328 
329     using namespace pldm::filetable;
330     auto& table = buildFileTable(fileTableConfig.c_str());
331 
332     std::unique_ptr<oem_platform::Handler> oemPlatformHandler{};
333     oem_ibm::Handler handler(oemPlatformHandler.get(), hostSocketFd, host_eid,
334                              nullptr, nullptr);
335     auto response = handler.readFileIntoMemory(request, requestPayloadLength);
336     auto responsePtr = reinterpret_cast<pldm_msg*>(response.data());
337     ASSERT_EQ(responsePtr->payload[0], PLDM_ERROR_INVALID_LENGTH);
338     // Clear the file table contents.
339     table.clear();
340 }
341 
TEST_F(TestFileTable,ReadFileInvalidEffectiveLength)342 TEST_F(TestFileTable, ReadFileInvalidEffectiveLength)
343 {
344     uint32_t fileHandle = 0;
345     // valid offset
346     uint32_t offset = 100;
347     // length + offset exceeds the size, so effective length is
348     // filesize(1024) - offset(100). The effective length is not a multiple of
349     // DMA min size(16)
350     uint32_t length = 1024;
351     uint64_t address = 0;
352     uint8_t host_eid = 0;
353     int hostSocketFd = 0;
354 
355     std::array<uint8_t, sizeof(pldm_msg_hdr) + PLDM_RW_FILE_MEM_REQ_BYTES>
356         requestMsg{};
357     auto request = reinterpret_cast<pldm_msg*>(requestMsg.data());
358     size_t requestPayloadLength = requestMsg.size() - sizeof(pldm_msg_hdr);
359     memcpy(request->payload, &fileHandle, sizeof(fileHandle));
360     memcpy(request->payload + sizeof(fileHandle), &offset, sizeof(offset));
361     memcpy(request->payload + sizeof(fileHandle) + sizeof(offset), &length,
362            sizeof(length));
363     memcpy(request->payload + sizeof(fileHandle) + sizeof(offset) +
364                sizeof(length),
365            &address, sizeof(address));
366 
367     using namespace pldm::filetable;
368     auto& table = buildFileTable(fileTableConfig.c_str());
369 
370     std::unique_ptr<oem_platform::Handler> oemPlatformHandler{};
371     oem_ibm::Handler handler(oemPlatformHandler.get(), hostSocketFd, host_eid,
372                              nullptr, nullptr);
373     auto response = handler.readFileIntoMemory(request, requestPayloadLength);
374     auto responsePtr = reinterpret_cast<pldm_msg*>(response.data());
375     ASSERT_EQ(responsePtr->payload[0], PLDM_ERROR_INVALID_LENGTH);
376     // Clear the file table contents.
377     table.clear();
378 }
379 
TEST(WriteFileFromMemory,BadPath)380 TEST(WriteFileFromMemory, BadPath)
381 {
382     uint32_t fileHandle = 0;
383     uint32_t offset = 0;
384     uint32_t length = 10;
385     uint64_t address = 0;
386     uint8_t host_eid = 0;
387     int hostSocketFd = 0;
388 
389     std::array<uint8_t, sizeof(pldm_msg_hdr) + PLDM_RW_FILE_MEM_REQ_BYTES>
390         requestMsg{};
391     auto request = reinterpret_cast<pldm_msg*>(requestMsg.data());
392     size_t requestPayloadLength = requestMsg.size() - sizeof(pldm_msg_hdr);
393     memcpy(request->payload, &fileHandle, sizeof(fileHandle));
394     memcpy(request->payload + sizeof(fileHandle), &offset, sizeof(offset));
395     memcpy(request->payload + sizeof(fileHandle) + sizeof(offset), &length,
396            sizeof(length));
397     memcpy(request->payload + sizeof(fileHandle) + sizeof(offset) +
398                sizeof(length),
399            &address, sizeof(address));
400 
401     // Pass invalid payload length
402     std::unique_ptr<oem_platform::Handler> oemPlatformHandler{};
403     oem_ibm::Handler handler(oemPlatformHandler.get(), hostSocketFd, host_eid,
404                              nullptr, nullptr);
405     auto response = handler.writeFileFromMemory(request, 0);
406     auto responsePtr = reinterpret_cast<pldm_msg*>(response.data());
407     ASSERT_EQ(responsePtr->payload[0], PLDM_ERROR_INVALID_LENGTH);
408 
409     // The length field is not a multiple of DMA minsize
410     response = handler.writeFileFromMemory(request, requestPayloadLength);
411     responsePtr = reinterpret_cast<pldm_msg*>(response.data());
412     ASSERT_EQ(responsePtr->payload[0], PLDM_ERROR_INVALID_LENGTH);
413 }
414 
TEST_F(TestFileTable,WriteFileInvalidFileHandle)415 TEST_F(TestFileTable, WriteFileInvalidFileHandle)
416 {
417     // Invalid file handle in the file table
418     uint32_t fileHandle = 2;
419     uint32_t offset = 0;
420     uint32_t length = 16;
421     uint64_t address = 0;
422     uint8_t host_eid = 0;
423     int hostSocketFd = 0;
424 
425     std::array<uint8_t, sizeof(pldm_msg_hdr) + PLDM_RW_FILE_MEM_REQ_BYTES>
426         requestMsg{};
427     auto request = reinterpret_cast<pldm_msg*>(requestMsg.data());
428     size_t requestPayloadLength = requestMsg.size() - sizeof(pldm_msg_hdr);
429     memcpy(request->payload, &fileHandle, sizeof(fileHandle));
430     memcpy(request->payload + sizeof(fileHandle), &offset, sizeof(offset));
431     memcpy(request->payload + sizeof(fileHandle) + sizeof(offset), &length,
432            sizeof(length));
433     memcpy(request->payload + sizeof(fileHandle) + sizeof(offset) +
434                sizeof(length),
435            &address, sizeof(address));
436 
437     using namespace pldm::filetable;
438     // Initialise the file table with 2 valid file handles 0 & 1.
439     auto& table = buildFileTable(fileTableConfig.c_str());
440 
441     std::unique_ptr<oem_platform::Handler> oemPlatformHandler{};
442     oem_ibm::Handler handler(oemPlatformHandler.get(), hostSocketFd, host_eid,
443                              nullptr, nullptr);
444     auto response = handler.writeFileFromMemory(request, requestPayloadLength);
445     auto responsePtr = reinterpret_cast<pldm_msg*>(response.data());
446     ASSERT_EQ(responsePtr->payload[0], PLDM_INVALID_FILE_HANDLE);
447     // Clear the file table contents.
448     table.clear();
449 }
450 
TEST_F(TestFileTable,WriteFileInvalidOffset)451 TEST_F(TestFileTable, WriteFileInvalidOffset)
452 {
453     uint32_t fileHandle = 0;
454     // The file size is 1024, so the offset is invalid
455     uint32_t offset = 1024;
456     uint32_t length = 16;
457     uint64_t address = 0;
458     uint8_t host_eid = 0;
459     int hostSocketFd = 0;
460 
461     std::array<uint8_t, sizeof(pldm_msg_hdr) + PLDM_RW_FILE_MEM_REQ_BYTES>
462         requestMsg{};
463     auto request = reinterpret_cast<pldm_msg*>(requestMsg.data());
464     size_t requestPayloadLength = requestMsg.size() - sizeof(pldm_msg_hdr);
465     memcpy(request->payload, &fileHandle, sizeof(fileHandle));
466     memcpy(request->payload + sizeof(fileHandle), &offset, sizeof(offset));
467     memcpy(request->payload + sizeof(fileHandle) + sizeof(offset), &length,
468            sizeof(length));
469     memcpy(request->payload + sizeof(fileHandle) + sizeof(offset) +
470                sizeof(length),
471            &address, sizeof(address));
472 
473     using namespace pldm::filetable;
474     // Initialise the file table with 2 valid file handles 0 & 1.
475     auto& table = buildFileTable(TestFileTable::fileTableConfig.c_str());
476 
477     std::unique_ptr<oem_platform::Handler> oemPlatformHandler{};
478     oem_ibm::Handler handler(oemPlatformHandler.get(), hostSocketFd, host_eid,
479                              nullptr, nullptr);
480     auto response = handler.writeFileFromMemory(request, requestPayloadLength);
481     auto responsePtr = reinterpret_cast<pldm_msg*>(response.data());
482     ASSERT_EQ(responsePtr->payload[0], PLDM_DATA_OUT_OF_RANGE);
483     // Clear the file table contents.
484     table.clear();
485 }
486 
TEST(FileTable,ConfigNotExist)487 TEST(FileTable, ConfigNotExist)
488 {
489     FileTable tableObj("");
490     EXPECT_EQ(tableObj.isEmpty(), true);
491 }
492 
TEST_F(TestFileTable,ValidateFileEntry)493 TEST_F(TestFileTable, ValidateFileEntry)
494 {
495     FileTable tableObj(fileTableConfig.c_str());
496 
497     // Test file handle 0, the file size is 1K bytes.
498     auto value = tableObj.at(0);
499     ASSERT_EQ(value.handle, 0);
500     ASSERT_EQ(strcmp(value.fsPath.c_str(), imageFile.c_str()), 0);
501     ASSERT_EQ(static_cast<uint32_t>(fs::file_size(value.fsPath)), 1024);
502     ASSERT_EQ(value.traits.value, 1);
503     ASSERT_EQ(true, fs::exists(value.fsPath));
504 
505     // Test file handle 1, the file size is 16 bytes
506     auto value1 = tableObj.at(1);
507     ASSERT_EQ(value1.handle, 1);
508     ASSERT_EQ(strcmp(value1.fsPath.c_str(), cksumFile.c_str()), 0);
509     ASSERT_EQ(static_cast<uint32_t>(fs::file_size(value1.fsPath)), 16);
510     ASSERT_EQ(value1.traits.value, 4);
511     ASSERT_EQ(true, fs::exists(value1.fsPath));
512 
513     // Test invalid file handle
514     ASSERT_THROW(tableObj.at(2), std::out_of_range);
515 }
516 
TEST_F(TestFileTable,ValidateFileTable)517 TEST_F(TestFileTable, ValidateFileTable)
518 {
519     FileTable tableObj(fileTableConfig.c_str());
520 
521     // Validate file attribute table
522     auto table = tableObj();
523     ASSERT_EQ(true,
524               std::equal(attrTable.begin(), attrTable.end(), table.begin()));
525 }
526 
TEST_F(TestFileTable,GetFileTableCommand)527 TEST_F(TestFileTable, GetFileTableCommand)
528 {
529     // Initialise the file table with a valid handle of 0 & 1
530     auto& table = buildFileTable(fileTableConfig.c_str());
531 
532     uint32_t transferHandle = 0;
533     uint8_t opFlag = 0;
534     uint8_t type = PLDM_FILE_ATTRIBUTE_TABLE;
535     uint32_t nextTransferHandle = 0;
536     uint8_t transferFlag = PLDM_START_AND_END;
537     uint8_t host_eid = 0;
538     int hostSocketFd = 0;
539 
540     std::array<uint8_t, sizeof(pldm_msg_hdr) + PLDM_GET_FILE_TABLE_REQ_BYTES>
541         requestMsg{};
542     auto requestMsgPtr = reinterpret_cast<pldm_msg*>(requestMsg.data());
543     size_t requestPayloadLength = requestMsg.size() - sizeof(pldm_msg_hdr);
544     auto request = reinterpret_cast<pldm_get_file_table_req*>(
545         requestMsg.data() + sizeof(pldm_msg_hdr));
546     request->transfer_handle = transferHandle;
547     request->operation_flag = opFlag;
548     request->table_type = type;
549 
550     std::unique_ptr<oem_platform::Handler> oemPlatformHandler{};
551     oem_ibm::Handler handler(oemPlatformHandler.get(), hostSocketFd, host_eid,
552                              nullptr, nullptr);
553     auto response = handler.getFileTable(requestMsgPtr, requestPayloadLength);
554     auto responsePtr = reinterpret_cast<pldm_msg*>(response.data());
555     ASSERT_EQ(responsePtr->payload[0], PLDM_SUCCESS);
556     size_t offsetSize = sizeof(responsePtr->payload[0]);
557     ASSERT_EQ(0, memcmp(responsePtr->payload + offsetSize, &nextTransferHandle,
558                         sizeof(nextTransferHandle)));
559     offsetSize += sizeof(nextTransferHandle);
560     ASSERT_EQ(0, memcmp(responsePtr->payload + offsetSize, &transferFlag,
561                         sizeof(transferFlag)));
562     offsetSize += sizeof(transferFlag);
563     ASSERT_EQ(0, memcmp(responsePtr->payload + offsetSize, attrTable.data(),
564                         attrTable.size()));
565     table.clear();
566 }
567 
TEST_F(TestFileTable,GetFileTableCommandReqLengthMismatch)568 TEST_F(TestFileTable, GetFileTableCommandReqLengthMismatch)
569 {
570     uint8_t host_eid = 0;
571     int hostSocketFd = 0;
572     std::array<uint8_t, sizeof(pldm_msg_hdr) + PLDM_GET_FILE_TABLE_REQ_BYTES>
573         requestMsg{};
574     auto request = reinterpret_cast<pldm_msg*>(requestMsg.data());
575 
576     // Pass invalid command payload length
577     std::unique_ptr<oem_platform::Handler> oemPlatformHandler{};
578     oem_ibm::Handler handler(oemPlatformHandler.get(), hostSocketFd, host_eid,
579                              nullptr, nullptr);
580     auto response = handler.getFileTable(request, 0);
581     auto responsePtr = reinterpret_cast<pldm_msg*>(response.data());
582     ASSERT_EQ(responsePtr->payload[0], PLDM_ERROR_INVALID_LENGTH);
583 }
584 
TEST_F(TestFileTable,GetFileTableCommandOEMAttrTable)585 TEST_F(TestFileTable, GetFileTableCommandOEMAttrTable)
586 {
587     uint32_t transferHandle = 0;
588     uint8_t opFlag = 0;
589     uint8_t type = PLDM_OEM_FILE_ATTRIBUTE_TABLE;
590     uint8_t host_eid = 0;
591     int hostSocketFd = 0;
592 
593     std::array<uint8_t, sizeof(pldm_msg_hdr) + PLDM_GET_FILE_TABLE_REQ_BYTES>
594         requestMsg{};
595     auto requestMsgPtr = reinterpret_cast<pldm_msg*>(requestMsg.data());
596     size_t requestPayloadLength = requestMsg.size() - sizeof(pldm_msg_hdr);
597     auto request = reinterpret_cast<pldm_get_file_table_req*>(
598         requestMsg.data() + sizeof(pldm_msg_hdr));
599     request->transfer_handle = transferHandle;
600     request->operation_flag = opFlag;
601     request->table_type = type;
602 
603     std::unique_ptr<oem_platform::Handler> oemPlatformHandler{};
604     oem_ibm::Handler handler(oemPlatformHandler.get(), hostSocketFd, host_eid,
605                              nullptr, nullptr);
606     auto response = handler.getFileTable(requestMsgPtr, requestPayloadLength);
607     auto responsePtr = reinterpret_cast<pldm_msg*>(response.data());
608     ASSERT_EQ(responsePtr->payload[0], PLDM_INVALID_FILE_TABLE_TYPE);
609 }
610 
TEST_F(TestFileTable,ReadFileBadPath)611 TEST_F(TestFileTable, ReadFileBadPath)
612 {
613     uint32_t fileHandle = 1;
614     uint32_t offset = 0;
615     uint32_t length = 0x4;
616     uint8_t host_eid = 0;
617     int hostSocketFd = 0;
618 
619     std::array<uint8_t, sizeof(pldm_msg_hdr) + PLDM_READ_FILE_REQ_BYTES>
620         requestMsg{};
621     auto requestMsgPtr = reinterpret_cast<pldm_msg*>(requestMsg.data());
622     auto payload_length = requestMsg.size() - sizeof(pldm_msg_hdr);
623     auto request = reinterpret_cast<pldm_read_file_req*>(requestMsg.data() +
624                                                          sizeof(pldm_msg_hdr));
625 
626     request->file_handle = fileHandle;
627     request->offset = offset;
628     request->length = length;
629 
630     using namespace pldm::filetable;
631     // Initialise the file table with 2 valid file handles 0 & 1.
632     auto& table = buildFileTable(fileTableConfig.c_str());
633 
634     // Invalid payload length
635     std::unique_ptr<oem_platform::Handler> oemPlatformHandler{};
636     oem_ibm::Handler handler(oemPlatformHandler.get(), hostSocketFd, host_eid,
637                              nullptr, nullptr);
638     auto response = handler.readFile(requestMsgPtr, 0);
639     auto responsePtr = reinterpret_cast<pldm_msg*>(response.data());
640     ASSERT_EQ(responsePtr->payload[0], PLDM_ERROR_INVALID_LENGTH);
641 
642     // Data out of range. File size is 1024, offset = 1024 is invalid.
643     request->offset = 1024;
644 
645     response = handler.readFile(requestMsgPtr, payload_length);
646     responsePtr = reinterpret_cast<pldm_msg*>(response.data());
647     ASSERT_EQ(responsePtr->payload[0], PLDM_DATA_OUT_OF_RANGE);
648 
649     // Invalid file handle
650     request->file_handle = 2;
651 
652     response = handler.readFile(requestMsgPtr, payload_length);
653     responsePtr = reinterpret_cast<pldm_msg*>(response.data());
654     ASSERT_EQ(responsePtr->payload[0], PLDM_INVALID_FILE_HANDLE);
655 
656     table.clear();
657 }
658 
TEST_F(TestFileTable,ReadFileGoodPath)659 TEST_F(TestFileTable, ReadFileGoodPath)
660 {
661     uint32_t fileHandle = 0;
662     uint32_t offset = 0;
663     uint32_t length = 0x4;
664     uint8_t host_eid = 0;
665     int hostSocketFd = 0;
666 
667     std::array<uint8_t, sizeof(pldm_msg_hdr) + PLDM_READ_FILE_REQ_BYTES>
668         requestMsg{};
669     auto requestMsgPtr = reinterpret_cast<pldm_msg*>(requestMsg.data());
670     auto payload_length = requestMsg.size() - sizeof(pldm_msg_hdr);
671     auto request = reinterpret_cast<pldm_read_file_req*>(requestMsg.data() +
672                                                          sizeof(pldm_msg_hdr));
673 
674     request->file_handle = fileHandle;
675     request->offset = offset;
676     request->length = length;
677 
678     using namespace pldm::filetable;
679     // Initialise the file table with 2 valid file handles 0 & 1.
680     auto& table = buildFileTable(fileTableConfig.c_str());
681     FileEntry value{};
682     value = table.at(fileHandle);
683 
684     std::ifstream stream(value.fsPath, std::ios::in | std::ios::binary);
685     stream.seekg(offset);
686     std::vector<char> buffer(length);
687     stream.read(buffer.data(), length);
688 
689     std::unique_ptr<oem_platform::Handler> oemPlatformHandler{};
690     oem_ibm::Handler handler(oemPlatformHandler.get(), hostSocketFd, host_eid,
691                              nullptr, nullptr);
692     auto responseMsg = handler.readFile(requestMsgPtr, payload_length);
693     auto response = reinterpret_cast<pldm_read_file_resp*>(
694         responseMsg.data() + sizeof(pldm_msg_hdr));
695     ASSERT_EQ(response->completion_code, PLDM_SUCCESS);
696     ASSERT_EQ(response->length, length);
697     ASSERT_EQ(0, memcmp(response->file_data, buffer.data(), length));
698 
699     // Test condition offset + length > fileSize;
700     size_t fileSize = 1024;
701     request->offset = 1023;
702     request->length = 10;
703 
704     stream.seekg(request->offset);
705     buffer.resize(fileSize - request->offset);
706     stream.read(buffer.data(), (fileSize - request->offset));
707 
708     responseMsg = handler.readFile(requestMsgPtr, payload_length);
709     response = reinterpret_cast<pldm_read_file_resp*>(responseMsg.data() +
710                                                       sizeof(pldm_msg_hdr));
711     ASSERT_EQ(response->completion_code, PLDM_SUCCESS);
712     ASSERT_EQ(response->length, (fileSize - request->offset));
713     ASSERT_EQ(0, memcmp(response->file_data, buffer.data(),
714                         (fileSize - request->offset)));
715 
716     table.clear();
717 }
718 
TEST_F(TestFileTable,WriteFileBadPath)719 TEST_F(TestFileTable, WriteFileBadPath)
720 {
721     uint32_t fileHandle = 0;
722     uint32_t offset = 0;
723     uint32_t length = 0x10;
724     uint8_t host_eid = 0;
725     int hostSocketFd = 0;
726 
727     std::vector<uint8_t> requestMsg(sizeof(pldm_msg_hdr) +
728                                     PLDM_WRITE_FILE_REQ_BYTES + length);
729     auto requestMsgPtr = reinterpret_cast<pldm_msg*>(requestMsg.data());
730     auto payload_length = requestMsg.size() - sizeof(pldm_msg_hdr);
731     auto request = reinterpret_cast<pldm_write_file_req*>(requestMsg.data() +
732                                                           sizeof(pldm_msg_hdr));
733 
734     using namespace pldm::filetable;
735     // Initialise the file table with 2 valid file handles 0 & 1.
736     auto& table = buildFileTable(fileTableConfig.c_str());
737 
738     request->file_handle = fileHandle;
739     request->offset = offset;
740     request->length = length;
741 
742     // Invalid payload length
743     std::unique_ptr<oem_platform::Handler> oemPlatformHandler{};
744     oem_ibm::Handler handler(oemPlatformHandler.get(), hostSocketFd, host_eid,
745                              nullptr, nullptr);
746     auto response = handler.writeFile(requestMsgPtr, 0);
747     auto responsePtr = reinterpret_cast<pldm_msg*>(response.data());
748     ASSERT_EQ(responsePtr->payload[0], PLDM_ERROR_INVALID_LENGTH);
749 
750     // Data out of range. File size is 1024, offset = 1024 is invalid.
751     request->offset = 1024;
752 
753     response = handler.writeFile(requestMsgPtr, payload_length);
754     responsePtr = reinterpret_cast<pldm_msg*>(response.data());
755     ASSERT_EQ(responsePtr->payload[0], PLDM_DATA_OUT_OF_RANGE);
756 
757     // Invalid file handle
758     request->file_handle = 2;
759 
760     response = handler.writeFile(requestMsgPtr, payload_length);
761     responsePtr = reinterpret_cast<pldm_msg*>(response.data());
762     ASSERT_EQ(responsePtr->payload[0], PLDM_INVALID_FILE_HANDLE);
763 
764     table.clear();
765 }
766 
TEST_F(TestFileTable,WriteFileGoodPath)767 TEST_F(TestFileTable, WriteFileGoodPath)
768 {
769     uint32_t fileHandle = 1;
770     uint32_t offset = 0;
771     std::array<uint8_t, 4> fileData = {0x41, 0x42, 0x43, 0x44};
772     uint32_t length = fileData.size();
773     uint8_t host_eid = 0;
774     int hostSocketFd = 0;
775 
776     std::vector<uint8_t> requestMsg(sizeof(pldm_msg_hdr) +
777                                     PLDM_WRITE_FILE_REQ_BYTES + length);
778     auto requestMsgPtr = reinterpret_cast<pldm_msg*>(requestMsg.data());
779     auto payload_length = requestMsg.size() - sizeof(pldm_msg_hdr);
780     auto request = reinterpret_cast<pldm_write_file_req*>(requestMsg.data() +
781                                                           sizeof(pldm_msg_hdr));
782 
783     using namespace pldm::filetable;
784     // Initialise the file table with 2 valid file handles 0 & 1.
785     auto& table = buildFileTable(fileTableConfig.c_str());
786     FileEntry value{};
787     value = table.at(fileHandle);
788 
789     request->file_handle = fileHandle;
790     request->offset = offset;
791     request->length = length;
792     memcpy(request->file_data, fileData.data(), fileData.size());
793 
794     std::unique_ptr<oem_platform::Handler> oemPlatformHandler{};
795     oem_ibm::Handler handler(oemPlatformHandler.get(), hostSocketFd, host_eid,
796                              nullptr, nullptr);
797     auto responseMsg = handler.writeFile(requestMsgPtr, payload_length);
798     auto response = reinterpret_cast<pldm_read_file_resp*>(
799         responseMsg.data() + sizeof(pldm_msg_hdr));
800 
801     std::ifstream stream(value.fsPath, std::ios::in | std::ios::binary);
802     stream.seekg(offset);
803     std::vector<char> buffer(length);
804     stream.read(buffer.data(), length);
805 
806     ASSERT_EQ(response->completion_code, PLDM_SUCCESS);
807     ASSERT_EQ(response->length, length);
808     ASSERT_EQ(0, memcmp(fileData.data(), buffer.data(), length));
809 
810     table.clear();
811 }
812 
TEST(writeFileByTypeFromMemory,testBadPath)813 TEST(writeFileByTypeFromMemory, testBadPath)
814 {
815     uint8_t host_eid = 0;
816     int hostSocketFd = 0;
817 
818     const auto hdr_size = sizeof(pldm_msg_hdr);
819     std::array<uint8_t, hdr_size + PLDM_RW_FILE_BY_TYPE_MEM_REQ_BYTES>
820         requestMsg{};
821     auto req = reinterpret_cast<pldm_msg*>(requestMsg.data());
822     size_t requestPayloadLength = requestMsg.size() - hdr_size;
823     struct pldm_read_write_file_by_type_memory_req* request =
824         reinterpret_cast<struct pldm_read_write_file_by_type_memory_req*>(
825             req->payload);
826     request->file_type = PLDM_FILE_TYPE_PEL;
827     request->file_handle = 0xFFFFFFFF;
828     request->offset = 0;
829     request->length = 17;
830     request->address = 0;
831 
832     std::unique_ptr<oem_platform::Handler> oemPlatformHandler{};
833     oem_ibm::Handler handler(oemPlatformHandler.get(), hostSocketFd, host_eid,
834                              nullptr, nullptr);
835     auto response = handler.writeFileByTypeFromMemory(req, 0);
836     auto responsePtr = reinterpret_cast<pldm_msg*>(response.data());
837 
838     struct pldm_read_write_file_by_type_memory_resp* resp =
839         reinterpret_cast<struct pldm_read_write_file_by_type_memory_resp*>(
840             responsePtr->payload);
841     ASSERT_EQ(PLDM_ERROR_INVALID_LENGTH, resp->completion_code);
842 
843     response = handler.writeFileByTypeFromMemory(req, requestPayloadLength);
844     responsePtr = reinterpret_cast<pldm_msg*>(response.data());
845 
846     resp = reinterpret_cast<struct pldm_read_write_file_by_type_memory_resp*>(
847         responsePtr->payload);
848     ASSERT_EQ(PLDM_ERROR_INVALID_LENGTH, resp->completion_code);
849 }
850 
TEST(getHandlerByType,allPaths)851 TEST(getHandlerByType, allPaths)
852 {
853     uint32_t fileHandle{};
854     auto handler = getHandlerByType(PLDM_FILE_TYPE_PEL, fileHandle);
855     auto pelType = dynamic_cast<PelHandler*>(handler.get());
856     ASSERT_TRUE(pelType != nullptr);
857 
858     handler = getHandlerByType(PLDM_FILE_TYPE_LID_PERM, fileHandle);
859     auto lidType = dynamic_cast<LidHandler*>(handler.get());
860     ASSERT_TRUE(lidType != nullptr);
861     pelType = dynamic_cast<PelHandler*>(handler.get());
862     ASSERT_TRUE(pelType == nullptr);
863     handler = getHandlerByType(PLDM_FILE_TYPE_LID_TEMP, fileHandle);
864     lidType = dynamic_cast<LidHandler*>(handler.get());
865     ASSERT_TRUE(lidType != nullptr);
866 
867     handler = getHandlerByType(PLDM_FILE_TYPE_DUMP, fileHandle);
868     auto dumpType = dynamic_cast<DumpHandler*>(handler.get());
869     ASSERT_TRUE(dumpType != nullptr);
870 
871     handler = getHandlerByType(PLDM_FILE_TYPE_RESOURCE_DUMP_PARMS, fileHandle);
872     dumpType = dynamic_cast<DumpHandler*>(handler.get());
873     ASSERT_TRUE(dumpType != nullptr);
874 
875     handler = getHandlerByType(PLDM_FILE_TYPE_RESOURCE_DUMP, fileHandle);
876     dumpType = dynamic_cast<DumpHandler*>(handler.get());
877     ASSERT_TRUE(dumpType != nullptr);
878 
879     handler = getHandlerByType(PLDM_FILE_TYPE_CERT_SIGNING_REQUEST, fileHandle);
880     auto certType = dynamic_cast<CertHandler*>(handler.get());
881     ASSERT_TRUE(certType != nullptr);
882 
883     handler = getHandlerByType(PLDM_FILE_TYPE_SIGNED_CERT, fileHandle);
884     certType = dynamic_cast<CertHandler*>(handler.get());
885     ASSERT_TRUE(certType != nullptr);
886 
887     handler = getHandlerByType(PLDM_FILE_TYPE_PCIE_TOPOLOGY, fileHandle);
888     auto pcieTopologyType = dynamic_cast<PCIeInfoHandler*>(handler.get());
889     ASSERT_TRUE(pcieTopologyType != nullptr);
890 
891     handler = getHandlerByType(PLDM_FILE_TYPE_CABLE_INFO, fileHandle);
892     auto cableInfoType = dynamic_cast<PCIeInfoHandler*>(handler.get());
893     ASSERT_TRUE(cableInfoType != nullptr);
894 
895     handler = getHandlerByType(PLDM_FILE_TYPE_ROOT_CERT, fileHandle);
896     certType = dynamic_cast<CertHandler*>(handler.get());
897     ASSERT_TRUE(certType != nullptr);
898 
899     using namespace sdbusplus::xyz::openbmc_project::Common::Error;
900     ASSERT_THROW(getHandlerByType(0xFFFF, fileHandle), InternalFailure);
901 }
902 
TEST(readFileByTypeIntoMemory,testBadPath)903 TEST(readFileByTypeIntoMemory, testBadPath)
904 {
905     uint8_t host_eid = 0;
906     int hostSocketFd = 0;
907     const auto hdr_size = sizeof(pldm_msg_hdr);
908     std::array<uint8_t, hdr_size + PLDM_RW_FILE_BY_TYPE_MEM_REQ_BYTES>
909         requestMsg{};
910     auto req = reinterpret_cast<pldm_msg*>(requestMsg.data());
911     struct pldm_read_write_file_by_type_memory_req* request =
912         reinterpret_cast<struct pldm_read_write_file_by_type_memory_req*>(
913             req->payload);
914     request->file_type = 0xFFFF;
915     request->file_handle = 0;
916     request->offset = 0;
917     request->length = 17;
918     request->address = 0;
919 
920     std::unique_ptr<oem_platform::Handler> oemPlatformHandler{};
921     oem_ibm::Handler handler(oemPlatformHandler.get(), hostSocketFd, host_eid,
922                              nullptr, nullptr);
923     auto response = handler.readFileByTypeIntoMemory(req, 0);
924     auto responsePtr = reinterpret_cast<pldm_msg*>(response.data());
925     struct pldm_read_write_file_by_type_memory_resp* resp =
926         reinterpret_cast<struct pldm_read_write_file_by_type_memory_resp*>(
927             responsePtr->payload);
928     ASSERT_EQ(PLDM_ERROR_INVALID_LENGTH, resp->completion_code);
929 
930     response = handler.readFileByTypeIntoMemory(
931         req, PLDM_RW_FILE_BY_TYPE_MEM_REQ_BYTES);
932     responsePtr = reinterpret_cast<pldm_msg*>(response.data());
933     resp = reinterpret_cast<struct pldm_read_write_file_by_type_memory_resp*>(
934         responsePtr->payload);
935     ASSERT_EQ(PLDM_ERROR_INVALID_LENGTH, resp->completion_code);
936 
937     request->length = 16;
938     response = handler.readFileByTypeIntoMemory(
939         req, PLDM_RW_FILE_BY_TYPE_MEM_REQ_BYTES);
940     responsePtr = reinterpret_cast<pldm_msg*>(response.data());
941     resp = reinterpret_cast<struct pldm_read_write_file_by_type_memory_resp*>(
942         responsePtr->payload);
943     ASSERT_EQ(PLDM_INVALID_FILE_TYPE, resp->completion_code);
944 }
945 
TEST(readFileByType,testBadPath)946 TEST(readFileByType, testBadPath)
947 {
948     uint8_t host_eid = 0;
949     int hostSocketFd = 0;
950     const auto hdr_size = sizeof(pldm_msg_hdr);
951     std::array<uint8_t, hdr_size + PLDM_RW_FILE_BY_TYPE_REQ_BYTES> requestMsg{};
952     auto payloadLength = requestMsg.size() - hdr_size;
953     auto req = reinterpret_cast<pldm_msg*>(requestMsg.data());
954     struct pldm_read_write_file_by_type_req* request =
955         reinterpret_cast<struct pldm_read_write_file_by_type_req*>(
956             req->payload);
957     request->file_type = 0xFFFF;
958     request->file_handle = 0;
959     request->offset = 0;
960     request->length = 13;
961 
962     std::unique_ptr<oem_platform::Handler> oemPlatformHandler{};
963     oem_ibm::Handler handler(oemPlatformHandler.get(), hostSocketFd, host_eid,
964                              nullptr, nullptr);
965     auto response = handler.readFileByType(req, 0);
966     auto responsePtr = reinterpret_cast<pldm_msg*>(response.data());
967     struct pldm_read_write_file_by_type_resp* resp =
968         reinterpret_cast<struct pldm_read_write_file_by_type_resp*>(
969             responsePtr->payload);
970     ASSERT_EQ(PLDM_ERROR_INVALID_LENGTH, resp->completion_code);
971 
972     response = handler.readFileByType(req, payloadLength);
973     responsePtr = reinterpret_cast<pldm_msg*>(response.data());
974     resp = reinterpret_cast<struct pldm_read_write_file_by_type_resp*>(
975         responsePtr->payload);
976     ASSERT_EQ(PLDM_INVALID_FILE_TYPE, resp->completion_code);
977 }
978 
TEST(readFileByType,testReadFile)979 TEST(readFileByType, testReadFile)
980 {
981     LidHandler handler(0, true);
982     Response response;
983     uint32_t length{};
984 
985     auto rc = handler.readFile({}, 0, length, response);
986     ASSERT_EQ(PLDM_INVALID_FILE_HANDLE, rc);
987 
988     char tmplt[] = "/tmp/lid.XXXXXX";
989     auto fd = mkstemp(tmplt);
990     std::vector<uint8_t> in = {100, 10, 56, 78, 34, 56, 79, 235, 111};
991     rc = write(fd, in.data(), in.size());
992     ASSERT_NE(rc, PLDM_ERROR);
993     close(fd);
994     length = in.size() + 1000;
995     rc = handler.readFile(tmplt, 0, length, response);
996     ASSERT_EQ(rc, PLDM_SUCCESS);
997     ASSERT_EQ(length, in.size());
998     ASSERT_EQ(response.size(), in.size());
999     ASSERT_EQ(std::equal(in.begin(), in.end(), response.begin()), true);
1000 }
1001