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