blob: 3ebf96a08ec2d38a489ff16f4aa2b67a2e1be7d3 [file] [log] [blame]
Jinu Joy Thomas7f57f442019-06-13 20:38:49 +05301#include "libpldmresponder/file_io.hpp"
Tom Joseph0c6d22c2019-06-26 09:58:41 +05302#include "libpldmresponder/file_table.hpp"
3
4#include <filesystem>
5#include <fstream>
6#include <nlohmann/json.hpp>
Jinu Joy Thomas7f57f442019-06-13 20:38:49 +05307
8#include "libpldm/base.h"
9#include "libpldm/file_io.h"
10
11#include <gmock/gmock-matchers.h>
12#include <gmock/gmock.h>
13#include <gtest/gtest.h>
Tom Joseph0c6d22c2019-06-26 09:58:41 +053014
Tom Joseph0c6d22c2019-06-26 09:58:41 +053015namespace fs = std::filesystem;
16using Json = nlohmann::json;
17using namespace pldm::filetable;
18
19class TestFileTable : public testing::Test
20{
21 public:
22 void SetUp() override
23 {
24 // Create a temporary directory to hold the config file and files to
25 // populate the file table.
26 char tmppldm[] = "/tmp/pldm_fileio_table.XXXXXX";
27 dir = fs::path(mkdtemp(tmppldm));
28
29 // Copy the sample image files to the directory
30 fs::copy("./files", dir);
31
32 imageFile = dir / "NVRAM-IMAGE";
33 auto jsonObjects = Json::array();
34 auto obj = Json::object();
35 obj["path"] = imageFile.c_str();
36 obj["file_traits"] = 1;
37
38 jsonObjects.push_back(obj);
39 obj.clear();
40 cksumFile = dir / "NVRAM-IMAGE-CKSUM";
41 obj["path"] = cksumFile.c_str();
42 obj["file_traits"] = 4;
43 jsonObjects.push_back(obj);
44
45 fileTableConfig = dir / "configFile.json";
46 std::ofstream file(fileTableConfig.c_str());
47 file << std::setw(4) << jsonObjects << std::endl;
48 }
49
50 void TearDown() override
51 {
52 fs::remove_all(dir);
53 }
54
55 fs::path dir;
56 fs::path imageFile;
57 fs::path cksumFile;
58 fs::path fileTableConfig;
59
60 // <4 bytes - File handle - 0 (0x00 0x00 0x00 0x00)>,
61 // <2 bytes - Filename length - 11 (0x0b 0x00>
62 // <11 bytes - Filename - ASCII for NVRAM-IMAGE>
63 // <4 bytes - File size - 1024 (0x00 0x04 0x00 0x00)>
64 // <4 bytes - File traits - 1 (0x01 0x00 0x00 0x00)>
65 // <4 bytes - File handle - 1 (0x01 0x00 0x00 0x00)>,
66 // <2 bytes - Filename length - 17 (0x11 0x00>
67 // <17 bytes - Filename - ASCII for NVRAM-IMAGE-CKSUM>
68 // <4 bytes - File size - 16 (0x0f 0x00 0x00 0x00)>
69 // <4 bytes - File traits - 4 (0x04 0x00 0x00 0x00)>
70 // No pad bytes added since the length for both the file entries in the
71 // table is 56, which is a multiple of 4.
72 // <4 bytes - Checksum - 2088303182(0x4e 0xfa 0x78 0x7c)>
73 Table attrTable = {
74 0x00, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x4e, 0x56, 0x52, 0x41, 0x4d, 0x2d,
75 0x49, 0x4d, 0x41, 0x47, 0x45, 0x00, 0x04, 0x00, 0x00, 0x01, 0x00, 0x00,
76 0x00, 0x01, 0x00, 0x00, 0x00, 0x11, 0x00, 0x4e, 0x56, 0x52, 0x41, 0x4d,
77 0x2d, 0x49, 0x4d, 0x41, 0x47, 0x45, 0x2d, 0x43, 0x4b, 0x53, 0x55, 0x4d,
78 0x10, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x4e, 0xfa, 0x78, 0x7c};
79};
80
Jinu Joy Thomas7f57f442019-06-13 20:38:49 +053081namespace pldm
82{
83
84namespace responder
85{
86
87namespace dma
88{
89
90class MockDMA
91{
92 public:
93 MOCK_METHOD5(transferDataHost,
94 int(const fs::path& file, uint32_t offset, uint32_t length,
95 uint64_t address, bool upstream));
96};
97
98} // namespace dma
99} // namespace responder
100} // namespace pldm
101using namespace pldm::responder;
102using ::testing::_;
103using ::testing::Return;
104
105TEST(TransferDataHost, GoodPath)
106{
107 using namespace pldm::responder::dma;
108
109 MockDMA dmaObj;
110 fs::path path("");
111
112 // Minimum length of 16 and expect transferDataHost to be called once
113 // returns the default value of 0 (the return type of transferDataHost is
114 // int, the default value for int is 0)
115 uint32_t length = minSize;
116 EXPECT_CALL(dmaObj, transferDataHost(path, 0, length, 0, true)).Times(1);
117 auto response = transferAll<MockDMA>(&dmaObj, PLDM_READ_FILE_INTO_MEMORY,
Jinu Joy Thomas33705fd2019-07-02 16:03:05 +0530118 path, 0, length, 0, true, 0);
Jinu Joy Thomas7f57f442019-06-13 20:38:49 +0530119 auto responsePtr = reinterpret_cast<pldm_msg*>(response.data());
120 ASSERT_EQ(responsePtr->payload[0], PLDM_SUCCESS);
121 ASSERT_EQ(0, memcmp(responsePtr->payload + sizeof(responsePtr->payload[0]),
122 &length, sizeof(length)));
123
124 // maxsize of DMA
125 length = maxSize;
126 EXPECT_CALL(dmaObj, transferDataHost(path, 0, length, 0, true)).Times(1);
127 response = transferAll<MockDMA>(&dmaObj, PLDM_READ_FILE_INTO_MEMORY, path,
Jinu Joy Thomas33705fd2019-07-02 16:03:05 +0530128 0, length, 0, true, 0);
Jinu Joy Thomas7f57f442019-06-13 20:38:49 +0530129 responsePtr = reinterpret_cast<pldm_msg*>(response.data());
130 ASSERT_EQ(responsePtr->payload[0], PLDM_SUCCESS);
131 ASSERT_EQ(0, memcmp(responsePtr->payload + sizeof(responsePtr->payload[0]),
132 &length, sizeof(length)));
133
134 // length greater than maxsize of DMA
135 length = maxSize + minSize;
136 EXPECT_CALL(dmaObj, transferDataHost(path, 0, maxSize, 0, true)).Times(1);
137 EXPECT_CALL(dmaObj, transferDataHost(path, maxSize, minSize, maxSize, true))
138 .Times(1);
139 response = transferAll<MockDMA>(&dmaObj, PLDM_READ_FILE_INTO_MEMORY, path,
Jinu Joy Thomas33705fd2019-07-02 16:03:05 +0530140 0, length, 0, true, 0);
Jinu Joy Thomas7f57f442019-06-13 20:38:49 +0530141 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 2*maxsize of DMA
147 length = 3 * maxSize;
148 EXPECT_CALL(dmaObj, transferDataHost(_, _, _, _, true)).Times(3);
149 response = transferAll<MockDMA>(&dmaObj, PLDM_READ_FILE_INTO_MEMORY, path,
Jinu Joy Thomas33705fd2019-07-02 16:03:05 +0530150 0, length, 0, true, 0);
Jinu Joy Thomas7f57f442019-06-13 20:38:49 +0530151 responsePtr = reinterpret_cast<pldm_msg*>(response.data());
152 ASSERT_EQ(responsePtr->payload[0], PLDM_SUCCESS);
153 ASSERT_EQ(0, memcmp(responsePtr->payload + sizeof(responsePtr->payload[0]),
154 &length, sizeof(length)));
155
156 // check for downstream(copy data from host to BMC) parameter
157 length = minSize;
158 EXPECT_CALL(dmaObj, transferDataHost(path, 0, length, 0, false)).Times(1);
159 response = transferAll<MockDMA>(&dmaObj, PLDM_READ_FILE_INTO_MEMORY, path,
Jinu Joy Thomas33705fd2019-07-02 16:03:05 +0530160 0, length, 0, false, 0);
Jinu Joy Thomas7f57f442019-06-13 20:38:49 +0530161 responsePtr = reinterpret_cast<pldm_msg*>(response.data());
162 ASSERT_EQ(responsePtr->payload[0], PLDM_SUCCESS);
163 ASSERT_EQ(0, memcmp(responsePtr->payload + sizeof(responsePtr->payload[0]),
164 &length, sizeof(length)));
165}
166
167TEST(TransferDataHost, BadPath)
168{
169 using namespace pldm::responder::dma;
170
171 MockDMA dmaObj;
172 fs::path path("");
173
174 // Minimum length of 16 and transferDataHost returning a negative errno
175 uint32_t length = minSize;
176 EXPECT_CALL(dmaObj, transferDataHost(_, _, _, _, _)).WillOnce(Return(-1));
177 auto response = transferAll<MockDMA>(&dmaObj, PLDM_READ_FILE_INTO_MEMORY,
Jinu Joy Thomas33705fd2019-07-02 16:03:05 +0530178 path, 0, length, 0, true, 0);
Jinu Joy Thomas7f57f442019-06-13 20:38:49 +0530179 auto responsePtr = reinterpret_cast<pldm_msg*>(response.data());
180 ASSERT_EQ(responsePtr->payload[0], PLDM_ERROR);
181
182 // length greater than maxsize of DMA and transferDataHost returning a
183 // negative errno
184 length = maxSize + minSize;
185 EXPECT_CALL(dmaObj, transferDataHost(_, _, _, _, _)).WillOnce(Return(-1));
186 response = transferAll<MockDMA>(&dmaObj, PLDM_READ_FILE_INTO_MEMORY, path,
Jinu Joy Thomas33705fd2019-07-02 16:03:05 +0530187 0, length, 0, true, 0);
Jinu Joy Thomas7f57f442019-06-13 20:38:49 +0530188 responsePtr = reinterpret_cast<pldm_msg*>(response.data());
189 ASSERT_EQ(responsePtr->payload[0], PLDM_ERROR);
190}
191
192TEST(ReadFileIntoMemory, BadPath)
193{
194 uint32_t fileHandle = 0;
195 uint32_t offset = 0;
196 uint32_t length = 10;
197 uint64_t address = 0;
198
Jinu Joy Thomasf666db12019-05-29 05:22:31 -0500199 std::array<uint8_t, sizeof(pldm_msg_hdr) + PLDM_RW_FILE_MEM_REQ_BYTES>
200 requestMsg{};
201 auto request = reinterpret_cast<pldm_msg*>(requestMsg.data());
202 memcpy(request->payload, &fileHandle, sizeof(fileHandle));
203 memcpy(request->payload + sizeof(fileHandle), &offset, sizeof(offset));
204 memcpy(request->payload + sizeof(fileHandle) + sizeof(offset), &length,
Jinu Joy Thomas7f57f442019-06-13 20:38:49 +0530205 sizeof(length));
Jinu Joy Thomasf666db12019-05-29 05:22:31 -0500206 memcpy(request->payload + sizeof(fileHandle) + sizeof(offset) +
Jinu Joy Thomas7f57f442019-06-13 20:38:49 +0530207 sizeof(length),
208 &address, sizeof(address));
209
210 // Pass invalid payload length
Jinu Joy Thomasf666db12019-05-29 05:22:31 -0500211 auto response = readFileIntoMemory(request, 0);
Jinu Joy Thomas7f57f442019-06-13 20:38:49 +0530212 auto responsePtr = reinterpret_cast<pldm_msg*>(response.data());
213 ASSERT_EQ(responsePtr->payload[0], PLDM_ERROR_INVALID_LENGTH);
214}
215
Tom Joseph0c6d22c2019-06-26 09:58:41 +0530216TEST_F(TestFileTable, ReadFileInvalidFileHandle)
217{
218 // Invalid file handle in the file table
219 uint32_t fileHandle = 2;
220 uint32_t offset = 0;
221 uint32_t length = 0;
222 uint64_t address = 0;
223
224 std::array<uint8_t, sizeof(pldm_msg_hdr) + PLDM_RW_FILE_MEM_REQ_BYTES>
225 requestMsg{};
226 auto request = reinterpret_cast<pldm_msg*>(requestMsg.data());
227 size_t requestPayloadLength = requestMsg.size() - sizeof(pldm_msg_hdr);
228 memcpy(request->payload, &fileHandle, sizeof(fileHandle));
229 memcpy(request->payload + sizeof(fileHandle), &offset, sizeof(offset));
230 memcpy(request->payload + sizeof(fileHandle) + sizeof(offset), &length,
231 sizeof(length));
232 memcpy(request->payload + sizeof(fileHandle) + sizeof(offset) +
233 sizeof(length),
234 &address, sizeof(address));
235
236 using namespace pldm::filetable;
237 // Initialise the file table with 2 valid file handles 0 & 1.
238 auto& table = buildFileTable(fileTableConfig.c_str());
239
240 auto response = readFileIntoMemory(request, requestPayloadLength);
241 auto responsePtr = reinterpret_cast<pldm_msg*>(response.data());
242 ASSERT_EQ(responsePtr->payload[0], PLDM_INVALID_FILE_HANDLE);
243 // Clear the file table contents.
244 table.clear();
245}
246
247TEST_F(TestFileTable, ReadFileInvalidOffset)
248{
249 uint32_t fileHandle = 0;
250 // The file size is 1024, so the offset is invalid
251 uint32_t offset = 1024;
252 uint32_t length = 0;
253 uint64_t address = 0;
254
255 std::array<uint8_t, sizeof(pldm_msg_hdr) + PLDM_RW_FILE_MEM_REQ_BYTES>
256 requestMsg{};
257 auto request = reinterpret_cast<pldm_msg*>(requestMsg.data());
258 size_t requestPayloadLength = requestMsg.size() - sizeof(pldm_msg_hdr);
259 memcpy(request->payload, &fileHandle, sizeof(fileHandle));
260 memcpy(request->payload + sizeof(fileHandle), &offset, sizeof(offset));
261 memcpy(request->payload + sizeof(fileHandle) + sizeof(offset), &length,
262 sizeof(length));
263 memcpy(request->payload + sizeof(fileHandle) + sizeof(offset) +
264 sizeof(length),
265 &address, sizeof(address));
266
267 using namespace pldm::filetable;
268 auto& table = buildFileTable(fileTableConfig.c_str());
269
270 auto response = readFileIntoMemory(request, requestPayloadLength);
271 auto responsePtr = reinterpret_cast<pldm_msg*>(response.data());
272 ASSERT_EQ(responsePtr->payload[0], PLDM_DATA_OUT_OF_RANGE);
273 // Clear the file table contents.
274 table.clear();
275}
276
277TEST_F(TestFileTable, ReadFileInvalidLength)
278{
279 uint32_t fileHandle = 0;
280 uint32_t offset = 100;
281 // Length should be a multiple of dma min size(16)
282 uint32_t length = 10;
283 uint64_t address = 0;
284
285 std::array<uint8_t, sizeof(pldm_msg_hdr) + PLDM_RW_FILE_MEM_REQ_BYTES>
286 requestMsg{};
287 auto request = reinterpret_cast<pldm_msg*>(requestMsg.data());
288 size_t requestPayloadLength = requestMsg.size() - sizeof(pldm_msg_hdr);
289 memcpy(request->payload, &fileHandle, sizeof(fileHandle));
290 memcpy(request->payload + sizeof(fileHandle), &offset, sizeof(offset));
291 memcpy(request->payload + sizeof(fileHandle) + sizeof(offset), &length,
292 sizeof(length));
293 memcpy(request->payload + sizeof(fileHandle) + sizeof(offset) +
294 sizeof(length),
295 &address, sizeof(address));
296
297 using namespace pldm::filetable;
298 auto& table = buildFileTable(fileTableConfig.c_str());
299
300 auto response = readFileIntoMemory(request, requestPayloadLength);
301 auto responsePtr = reinterpret_cast<pldm_msg*>(response.data());
302 ASSERT_EQ(responsePtr->payload[0], PLDM_INVALID_READ_LENGTH);
303 // Clear the file table contents.
304 table.clear();
305}
306
307TEST_F(TestFileTable, ReadFileInvalidEffectiveLength)
308{
309 uint32_t fileHandle = 0;
310 // valid offset
311 uint32_t offset = 100;
312 // length + offset exceeds the size, so effective length is
313 // filesize(1024) - offset(100). The effective length is not a multiple of
314 // DMA min size(16)
315 uint32_t length = 1024;
316 uint64_t address = 0;
317
318 std::array<uint8_t, sizeof(pldm_msg_hdr) + PLDM_RW_FILE_MEM_REQ_BYTES>
319 requestMsg{};
320 auto request = reinterpret_cast<pldm_msg*>(requestMsg.data());
321 size_t requestPayloadLength = requestMsg.size() - sizeof(pldm_msg_hdr);
322 memcpy(request->payload, &fileHandle, sizeof(fileHandle));
323 memcpy(request->payload + sizeof(fileHandle), &offset, sizeof(offset));
324 memcpy(request->payload + sizeof(fileHandle) + sizeof(offset), &length,
325 sizeof(length));
326 memcpy(request->payload + sizeof(fileHandle) + sizeof(offset) +
327 sizeof(length),
328 &address, sizeof(address));
329
330 using namespace pldm::filetable;
331 auto& table = buildFileTable(fileTableConfig.c_str());
332
333 auto response = readFileIntoMemory(request, requestPayloadLength);
334 auto responsePtr = reinterpret_cast<pldm_msg*>(response.data());
335 ASSERT_EQ(responsePtr->payload[0], PLDM_INVALID_READ_LENGTH);
336 // Clear the file table contents.
337 table.clear();
338}
339
Jinu Joy Thomas7f57f442019-06-13 20:38:49 +0530340TEST(WriteFileFromMemory, BadPath)
341{
342 uint32_t fileHandle = 0;
343 uint32_t offset = 0;
344 uint32_t length = 10;
345 uint64_t address = 0;
346
Jinu Joy Thomasf666db12019-05-29 05:22:31 -0500347 std::array<uint8_t, sizeof(pldm_msg_hdr) + PLDM_RW_FILE_MEM_REQ_BYTES>
348 requestMsg{};
349 auto request = reinterpret_cast<pldm_msg*>(requestMsg.data());
350 size_t requestPayloadLength = requestMsg.size() - sizeof(pldm_msg_hdr);
351 memcpy(request->payload, &fileHandle, sizeof(fileHandle));
352 memcpy(request->payload + sizeof(fileHandle), &offset, sizeof(offset));
353 memcpy(request->payload + sizeof(fileHandle) + sizeof(offset), &length,
Jinu Joy Thomas7f57f442019-06-13 20:38:49 +0530354 sizeof(length));
Jinu Joy Thomasf666db12019-05-29 05:22:31 -0500355 memcpy(request->payload + sizeof(fileHandle) + sizeof(offset) +
Jinu Joy Thomas7f57f442019-06-13 20:38:49 +0530356 sizeof(length),
357 &address, sizeof(address));
358
359 // Pass invalid payload length
Jinu Joy Thomasf666db12019-05-29 05:22:31 -0500360 auto response = writeFileFromMemory(request, 0);
Jinu Joy Thomas7f57f442019-06-13 20:38:49 +0530361 auto responsePtr = reinterpret_cast<pldm_msg*>(response.data());
362 ASSERT_EQ(responsePtr->payload[0], PLDM_ERROR_INVALID_LENGTH);
363
364 // The length field is not a multiple of DMA minsize
Jinu Joy Thomasf666db12019-05-29 05:22:31 -0500365 response = writeFileFromMemory(request, requestPayloadLength);
Jinu Joy Thomas7f57f442019-06-13 20:38:49 +0530366 responsePtr = reinterpret_cast<pldm_msg*>(response.data());
367 ASSERT_EQ(responsePtr->payload[0], PLDM_INVALID_WRITE_LENGTH);
368}
Tom Joseph0c6d22c2019-06-26 09:58:41 +0530369
370TEST_F(TestFileTable, WriteFileInvalidFileHandle)
371{
372 // Invalid file handle in the file table
373 uint32_t fileHandle = 2;
374 uint32_t offset = 0;
375 uint32_t length = 16;
376 uint64_t address = 0;
377
378 std::array<uint8_t, sizeof(pldm_msg_hdr) + PLDM_RW_FILE_MEM_REQ_BYTES>
379 requestMsg{};
380 auto request = reinterpret_cast<pldm_msg*>(requestMsg.data());
381 size_t requestPayloadLength = requestMsg.size() - sizeof(pldm_msg_hdr);
382 memcpy(request->payload, &fileHandle, sizeof(fileHandle));
383 memcpy(request->payload + sizeof(fileHandle), &offset, sizeof(offset));
384 memcpy(request->payload + sizeof(fileHandle) + sizeof(offset), &length,
385 sizeof(length));
386 memcpy(request->payload + sizeof(fileHandle) + sizeof(offset) +
387 sizeof(length),
388 &address, sizeof(address));
389
390 using namespace pldm::filetable;
391 // Initialise the file table with 2 valid file handles 0 & 1.
392 auto& table = buildFileTable(fileTableConfig.c_str());
393
394 auto response = writeFileFromMemory(request, requestPayloadLength);
395 auto responsePtr = reinterpret_cast<pldm_msg*>(response.data());
396 ASSERT_EQ(responsePtr->payload[0], PLDM_INVALID_FILE_HANDLE);
397 // Clear the file table contents.
398 table.clear();
399}
400
401TEST_F(TestFileTable, WriteFileInvalidOffset)
402{
403 uint32_t fileHandle = 0;
404 // The file size is 1024, so the offset is invalid
405 uint32_t offset = 1024;
406 uint32_t length = 16;
407 uint64_t address = 0;
408
409 std::array<uint8_t, sizeof(pldm_msg_hdr) + PLDM_RW_FILE_MEM_REQ_BYTES>
410 requestMsg{};
411 auto request = reinterpret_cast<pldm_msg*>(requestMsg.data());
412 size_t requestPayloadLength = requestMsg.size() - sizeof(pldm_msg_hdr);
413 memcpy(request->payload, &fileHandle, sizeof(fileHandle));
414 memcpy(request->payload + sizeof(fileHandle), &offset, sizeof(offset));
415 memcpy(request->payload + sizeof(fileHandle) + sizeof(offset), &length,
416 sizeof(length));
417 memcpy(request->payload + sizeof(fileHandle) + sizeof(offset) +
418 sizeof(length),
419 &address, sizeof(address));
420
421 using namespace pldm::filetable;
422 // Initialise the file table with 2 valid file handles 0 & 1.
423 auto& table = buildFileTable(TestFileTable::fileTableConfig.c_str());
424
425 auto response = writeFileFromMemory(request, requestPayloadLength);
426 auto responsePtr = reinterpret_cast<pldm_msg*>(response.data());
427 ASSERT_EQ(responsePtr->payload[0], PLDM_DATA_OUT_OF_RANGE);
428 // Clear the file table contents.
429 table.clear();
430}
431
432TEST(FileTable, ConfigNotExist)
433{
Tom Joseph0c6d22c2019-06-26 09:58:41 +0530434 FileTable tableObj("");
John Wang881cde12019-10-24 15:08:48 +0800435 EXPECT_EQ(tableObj.isEmpty(), true);
Tom Joseph0c6d22c2019-06-26 09:58:41 +0530436}
437
438TEST_F(TestFileTable, ValidateFileEntry)
439{
440 FileTable tableObj(fileTableConfig.c_str());
441
442 // Test file handle 0, the file size is 1K bytes.
443 auto value = tableObj.at(0);
444 ASSERT_EQ(value.handle, 0);
445 ASSERT_EQ(strcmp(value.fsPath.c_str(), imageFile.c_str()), 0);
446 ASSERT_EQ(static_cast<uint32_t>(fs::file_size(value.fsPath)), 1024);
447 ASSERT_EQ(value.traits.value, 1);
448 ASSERT_EQ(true, fs::exists(value.fsPath));
449
450 // Test file handle 1, the file size is 16 bytes
451 auto value1 = tableObj.at(1);
452 ASSERT_EQ(value1.handle, 1);
453 ASSERT_EQ(strcmp(value1.fsPath.c_str(), cksumFile.c_str()), 0);
454 ASSERT_EQ(static_cast<uint32_t>(fs::file_size(value1.fsPath)), 16);
455 ASSERT_EQ(value1.traits.value, 4);
456 ASSERT_EQ(true, fs::exists(value1.fsPath));
457
458 // Test invalid file handle
459 ASSERT_THROW(tableObj.at(2), std::out_of_range);
460}
461
462TEST_F(TestFileTable, ValidateFileTable)
463{
464 FileTable tableObj(fileTableConfig.c_str());
465
466 // Validate file attribute table
467 auto table = tableObj();
468 ASSERT_EQ(true,
469 std::equal(attrTable.begin(), attrTable.end(), table.begin()));
470}
471
472TEST_F(TestFileTable, GetFileTableCommand)
473{
474 // Initialise the file table with a valid handle of 0 & 1
475 auto& table = buildFileTable(fileTableConfig.c_str());
476
477 uint32_t transferHandle = 0;
478 uint8_t opFlag = 0;
479 uint8_t type = PLDM_FILE_ATTRIBUTE_TABLE;
480 uint32_t nextTransferHandle = 0;
481 uint8_t transferFlag = PLDM_START_AND_END;
482
483 std::array<uint8_t, sizeof(pldm_msg_hdr) + PLDM_GET_FILE_TABLE_REQ_BYTES>
484 requestMsg{};
485 auto requestMsgPtr = reinterpret_cast<pldm_msg*>(requestMsg.data());
486 size_t requestPayloadLength = requestMsg.size() - sizeof(pldm_msg_hdr);
487 auto request = reinterpret_cast<pldm_get_file_table_req*>(
488 requestMsg.data() + sizeof(pldm_msg_hdr));
489 request->transfer_handle = transferHandle;
490 request->operation_flag = opFlag;
491 request->table_type = type;
492
493 auto response = getFileTable(requestMsgPtr, requestPayloadLength);
494 auto responsePtr = reinterpret_cast<pldm_msg*>(response.data());
495 ASSERT_EQ(responsePtr->payload[0], PLDM_SUCCESS);
496 size_t offsetSize = sizeof(responsePtr->payload[0]);
497 ASSERT_EQ(0, memcmp(responsePtr->payload + offsetSize, &nextTransferHandle,
498 sizeof(nextTransferHandle)));
499 offsetSize += sizeof(nextTransferHandle);
500 ASSERT_EQ(0, memcmp(responsePtr->payload + offsetSize, &transferFlag,
501 sizeof(transferFlag)));
502 offsetSize += sizeof(transferFlag);
503 ASSERT_EQ(0, memcmp(responsePtr->payload + offsetSize, attrTable.data(),
504 attrTable.size()));
505 table.clear();
506}
507
508TEST_F(TestFileTable, GetFileTableCommandReqLengthMismatch)
509{
510 std::array<uint8_t, sizeof(pldm_msg_hdr) + PLDM_GET_FILE_TABLE_REQ_BYTES>
511 requestMsg{};
512 auto request = reinterpret_cast<pldm_msg*>(requestMsg.data());
513
514 // Pass invalid command payload length
515 auto response = getFileTable(request, 0);
516 auto responsePtr = reinterpret_cast<pldm_msg*>(response.data());
517 ASSERT_EQ(responsePtr->payload[0], PLDM_ERROR_INVALID_LENGTH);
518}
519
520TEST_F(TestFileTable, GetFileTableCommandOEMAttrTable)
521{
522 uint32_t transferHandle = 0;
523 uint8_t opFlag = 0;
524 uint8_t type = PLDM_OEM_FILE_ATTRIBUTE_TABLE;
525
526 std::array<uint8_t, sizeof(pldm_msg_hdr) + PLDM_GET_FILE_TABLE_REQ_BYTES>
527 requestMsg{};
528 auto requestMsgPtr = reinterpret_cast<pldm_msg*>(requestMsg.data());
529 size_t requestPayloadLength = requestMsg.size() - sizeof(pldm_msg_hdr);
530 auto request = reinterpret_cast<pldm_get_file_table_req*>(
531 requestMsg.data() + sizeof(pldm_msg_hdr));
532 request->transfer_handle = transferHandle;
533 request->operation_flag = opFlag;
534 request->table_type = type;
535
536 auto response = getFileTable(requestMsgPtr, requestPayloadLength);
537 auto responsePtr = reinterpret_cast<pldm_msg*>(response.data());
538 ASSERT_EQ(responsePtr->payload[0], PLDM_INVALID_FILE_TABLE_TYPE);
539}
vkaverap5b914c32019-06-30 22:23:54 -0500540
541TEST_F(TestFileTable, ReadFileBadPath)
542{
543 uint32_t fileHandle = 1;
544 uint32_t offset = 0;
545 uint32_t length = 0x4;
546
547 std::array<uint8_t, sizeof(pldm_msg_hdr) + PLDM_READ_FILE_REQ_BYTES>
548 requestMsg{};
549 auto requestMsgPtr = reinterpret_cast<pldm_msg*>(requestMsg.data());
550 auto payload_length = requestMsg.size() - sizeof(pldm_msg_hdr);
551 auto request = reinterpret_cast<pldm_read_file_req*>(requestMsg.data() +
552 sizeof(pldm_msg_hdr));
553
554 request->file_handle = fileHandle;
555 request->offset = offset;
556 request->length = length;
557
558 using namespace pldm::filetable;
559 // Initialise the file table with 2 valid file handles 0 & 1.
560 auto& table = buildFileTable(fileTableConfig.c_str());
561
562 // Invalid payload length
563 auto response = readFile(requestMsgPtr, 0);
564 auto responsePtr = reinterpret_cast<pldm_msg*>(response.data());
565 ASSERT_EQ(responsePtr->payload[0], PLDM_ERROR_INVALID_LENGTH);
566
567 // Data out of range. File size is 1024, offset = 1024 is invalid.
568 request->offset = 1024;
569
570 response = readFile(requestMsgPtr, payload_length);
571 responsePtr = reinterpret_cast<pldm_msg*>(response.data());
572 ASSERT_EQ(responsePtr->payload[0], PLDM_DATA_OUT_OF_RANGE);
573
574 // Invalid file handle
575 request->file_handle = 2;
576
577 response = readFile(requestMsgPtr, payload_length);
578 responsePtr = reinterpret_cast<pldm_msg*>(response.data());
579 ASSERT_EQ(responsePtr->payload[0], PLDM_INVALID_FILE_HANDLE);
580
581 table.clear();
582}
583
584TEST_F(TestFileTable, ReadFileGoodPath)
585{
586 uint32_t fileHandle = 0;
587 uint32_t offset = 0;
588 uint32_t length = 0x4;
589
590 std::array<uint8_t, sizeof(pldm_msg_hdr) + PLDM_READ_FILE_REQ_BYTES>
591 requestMsg{};
592 auto requestMsgPtr = reinterpret_cast<pldm_msg*>(requestMsg.data());
593 auto payload_length = requestMsg.size() - sizeof(pldm_msg_hdr);
594 auto request = reinterpret_cast<pldm_read_file_req*>(requestMsg.data() +
595 sizeof(pldm_msg_hdr));
596
597 request->file_handle = fileHandle;
598 request->offset = offset;
599 request->length = length;
600
601 using namespace pldm::filetable;
602 // Initialise the file table with 2 valid file handles 0 & 1.
603 auto& table = buildFileTable(fileTableConfig.c_str());
604 FileEntry value{};
605 value = table.at(fileHandle);
606
607 std::ifstream stream(value.fsPath, std::ios::in | std::ios::binary);
608 stream.seekg(offset);
609 std::vector<char> buffer(length);
610 stream.read(buffer.data(), length);
611
612 auto responseMsg = readFile(requestMsgPtr, payload_length);
613 auto response = reinterpret_cast<pldm_read_file_resp*>(
614 responseMsg.data() + sizeof(pldm_msg_hdr));
615 ASSERT_EQ(response->completion_code, PLDM_SUCCESS);
616 ASSERT_EQ(response->length, length);
617 ASSERT_EQ(0, memcmp(response->file_data, buffer.data(), length));
618
619 // Test condition offset + length > fileSize;
620 size_t fileSize = 1024;
621 request->offset = 1023;
622 request->length = 10;
623
624 stream.seekg(request->offset);
625 buffer.resize(fileSize - request->offset);
626 stream.read(buffer.data(), (fileSize - request->offset));
627
628 responseMsg = readFile(requestMsgPtr, payload_length);
629 response = reinterpret_cast<pldm_read_file_resp*>(responseMsg.data() +
630 sizeof(pldm_msg_hdr));
631 ASSERT_EQ(response->completion_code, PLDM_SUCCESS);
632 ASSERT_EQ(response->length, (fileSize - request->offset));
633 ASSERT_EQ(0, memcmp(response->file_data, buffer.data(),
634 (fileSize - request->offset)));
635
636 table.clear();
637}
638
639TEST_F(TestFileTable, WriteFileBadPath)
640{
641 uint32_t fileHandle = 0;
642 uint32_t offset = 0;
643 uint32_t length = 0x10;
644
645 std::vector<uint8_t> requestMsg(sizeof(pldm_msg_hdr) +
646 PLDM_WRITE_FILE_REQ_BYTES + length);
647 auto requestMsgPtr = reinterpret_cast<pldm_msg*>(requestMsg.data());
648 auto payload_length = requestMsg.size() - sizeof(pldm_msg_hdr);
649 auto request = reinterpret_cast<pldm_write_file_req*>(requestMsg.data() +
650 sizeof(pldm_msg_hdr));
651
652 using namespace pldm::filetable;
653 // Initialise the file table with 2 valid file handles 0 & 1.
654 auto& table = buildFileTable(fileTableConfig.c_str());
655
656 request->file_handle = fileHandle;
657 request->offset = offset;
658 request->length = length;
659
660 // Invalid payload length
661 auto response = writeFile(requestMsgPtr, 0);
662 auto responsePtr = reinterpret_cast<pldm_msg*>(response.data());
663 ASSERT_EQ(responsePtr->payload[0], PLDM_ERROR_INVALID_LENGTH);
664
665 // Data out of range. File size is 1024, offset = 1024 is invalid.
666 request->offset = 1024;
667
668 response = writeFile(requestMsgPtr, payload_length);
669 responsePtr = reinterpret_cast<pldm_msg*>(response.data());
670 ASSERT_EQ(responsePtr->payload[0], PLDM_DATA_OUT_OF_RANGE);
671
672 // Invalid file handle
673 request->file_handle = 2;
674
675 response = writeFile(requestMsgPtr, payload_length);
676 responsePtr = reinterpret_cast<pldm_msg*>(response.data());
677 ASSERT_EQ(responsePtr->payload[0], PLDM_INVALID_FILE_HANDLE);
678
679 table.clear();
680}
681
682TEST_F(TestFileTable, WriteFileGoodPath)
683{
684 uint32_t fileHandle = 1;
685 uint32_t offset = 0;
686 std::array<uint8_t, 4> fileData = {0x41, 0x42, 0x43, 0x44};
687 uint32_t length = fileData.size();
688
689 std::vector<uint8_t> requestMsg(sizeof(pldm_msg_hdr) +
690 PLDM_WRITE_FILE_REQ_BYTES + length);
691 auto requestMsgPtr = reinterpret_cast<pldm_msg*>(requestMsg.data());
692 auto payload_length = requestMsg.size() - sizeof(pldm_msg_hdr);
693 auto request = reinterpret_cast<pldm_write_file_req*>(requestMsg.data() +
694 sizeof(pldm_msg_hdr));
695
696 using namespace pldm::filetable;
697 // Initialise the file table with 2 valid file handles 0 & 1.
698 auto& table = buildFileTable(fileTableConfig.c_str());
699 FileEntry value{};
700 value = table.at(fileHandle);
701
702 request->file_handle = fileHandle;
703 request->offset = offset;
704 request->length = length;
705 memcpy(request->file_data, fileData.data(), fileData.size());
706
707 auto responseMsg = writeFile(requestMsgPtr, payload_length);
708 auto response = reinterpret_cast<pldm_read_file_resp*>(
709 responseMsg.data() + sizeof(pldm_msg_hdr));
710
711 std::ifstream stream(value.fsPath, std::ios::in | std::ios::binary);
712 stream.seekg(offset);
713 std::vector<char> buffer(length);
714 stream.read(buffer.data(), length);
715
716 ASSERT_EQ(response->completion_code, PLDM_SUCCESS);
717 ASSERT_EQ(response->length, length);
718 ASSERT_EQ(0, memcmp(fileData.data(), buffer.data(), length));
719
720 table.clear();
721}