xref: /openbmc/libpldm/tests/dsp/base.cpp (revision d0ba43af)
1 #include <libpldm/base.h>
2 #include <libpldm/pldm_types.h>
3 
4 #include <array>
5 #include <cstdint>
6 #include <cstring>
7 #include <vector>
8 
9 #include <gmock/gmock.h>
10 #include <gtest/gtest.h>
11 
12 using testing::ElementsAreArray;
13 
14 constexpr auto hdrSize = sizeof(pldm_msg_hdr);
15 
TEST(PackPLDMMessage,BadPathTest)16 TEST(PackPLDMMessage, BadPathTest)
17 {
18     struct pldm_header_info hdr;
19     struct pldm_header_info* hdr_ptr = NULL;
20     pldm_msg_hdr msg{};
21 
22     // PLDM header information pointer is NULL
23     auto rc = pack_pldm_header(hdr_ptr, &msg);
24     EXPECT_EQ(rc, PLDM_ERROR_INVALID_DATA);
25 
26     // PLDM message pointer is NULL
27     rc = pack_pldm_header(&hdr, nullptr);
28     EXPECT_EQ(rc, PLDM_ERROR_INVALID_DATA);
29 
30     // PLDM header information pointer and PLDM message pointer is NULL
31     rc = pack_pldm_header(hdr_ptr, nullptr);
32     EXPECT_EQ(rc, PLDM_ERROR_INVALID_DATA);
33 
34     // RESERVED message type
35     hdr.msg_type = PLDM_RESERVED;
36     rc = pack_pldm_header(&hdr, &msg);
37     EXPECT_EQ(rc, PLDM_ERROR_INVALID_DATA);
38 
39     // Instance ID out of range
40     hdr.msg_type = PLDM_REQUEST;
41     hdr.instance = 32;
42     rc = pack_pldm_header(&hdr, &msg);
43     EXPECT_EQ(rc, PLDM_ERROR_INVALID_DATA);
44 
45     // PLDM type out of range
46     hdr.msg_type = PLDM_REQUEST;
47     hdr.instance = 31;
48     hdr.pldm_type = 64;
49     rc = pack_pldm_header(&hdr, &msg);
50     EXPECT_EQ(rc, PLDM_ERROR_INVALID_PLDM_TYPE);
51 }
52 
TEST(PackPLDMMessage,RequestMessageGoodPath)53 TEST(PackPLDMMessage, RequestMessageGoodPath)
54 {
55     struct pldm_header_info hdr;
56     pldm_msg_hdr msg{};
57 
58     // Message type is REQUEST and lower range of the field values
59     hdr.msg_type = PLDM_REQUEST;
60     hdr.instance = 0;
61     hdr.pldm_type = 0;
62     hdr.command = 0;
63 
64     auto rc = pack_pldm_header(&hdr, &msg);
65     EXPECT_EQ(rc, PLDM_SUCCESS);
66     EXPECT_EQ(msg.request, 1);
67     EXPECT_EQ(msg.datagram, 0);
68     EXPECT_EQ(msg.instance_id, 0);
69     EXPECT_EQ(msg.type, 0);
70     EXPECT_EQ(msg.command, 0);
71 
72     // Message type is REQUEST and upper range of the field values
73     hdr.instance = 31;
74     hdr.pldm_type = 63;
75     hdr.command = 255;
76 
77     rc = pack_pldm_header(&hdr, &msg);
78     EXPECT_EQ(rc, PLDM_SUCCESS);
79     EXPECT_EQ(msg.request, 1);
80     EXPECT_EQ(msg.datagram, 0);
81     EXPECT_EQ(msg.instance_id, 31);
82     EXPECT_EQ(msg.type, 63);
83     EXPECT_EQ(msg.command, 255);
84 
85     // Message type is PLDM_ASYNC_REQUEST_NOTIFY
86     hdr.msg_type = PLDM_ASYNC_REQUEST_NOTIFY;
87 
88     rc = pack_pldm_header(&hdr, &msg);
89     EXPECT_EQ(rc, PLDM_SUCCESS);
90     EXPECT_EQ(msg.request, 1);
91     EXPECT_EQ(msg.datagram, 1);
92     EXPECT_EQ(msg.instance_id, 31);
93     EXPECT_EQ(msg.type, 63);
94     EXPECT_EQ(msg.command, 255);
95 }
96 
TEST(PackPLDMMessage,ResponseMessageGoodPath)97 TEST(PackPLDMMessage, ResponseMessageGoodPath)
98 {
99     struct pldm_header_info hdr;
100     pldm_msg_hdr msg{};
101 
102     // Message type is PLDM_RESPONSE and lower range of the field values
103     hdr.msg_type = PLDM_RESPONSE;
104     hdr.instance = 0;
105     hdr.pldm_type = 0;
106     hdr.command = 0;
107 
108     auto rc = pack_pldm_header(&hdr, &msg);
109     EXPECT_EQ(rc, PLDM_SUCCESS);
110     EXPECT_EQ(msg.request, 0);
111     EXPECT_EQ(msg.datagram, 0);
112     EXPECT_EQ(msg.instance_id, 0);
113     EXPECT_EQ(msg.type, 0);
114     EXPECT_EQ(msg.command, 0);
115 
116     // Message type is PLDM_RESPONSE and upper range of the field values
117     hdr.instance = 31;
118     hdr.pldm_type = 63;
119     hdr.command = 255;
120 
121     rc = pack_pldm_header(&hdr, &msg);
122     EXPECT_EQ(rc, PLDM_SUCCESS);
123     EXPECT_EQ(msg.request, 0);
124     EXPECT_EQ(msg.datagram, 0);
125     EXPECT_EQ(msg.instance_id, 31);
126     EXPECT_EQ(msg.type, 63);
127     EXPECT_EQ(msg.command, 255);
128 }
129 
TEST(UnpackPLDMMessage,BadPathTest)130 TEST(UnpackPLDMMessage, BadPathTest)
131 {
132     struct pldm_header_info hdr;
133 
134     // PLDM message pointer is NULL
135     auto rc = unpack_pldm_header(nullptr, &hdr);
136     EXPECT_EQ(rc, PLDM_ERROR_INVALID_DATA);
137 }
138 
TEST(UnpackPLDMMessage,RequestMessageGoodPath)139 TEST(UnpackPLDMMessage, RequestMessageGoodPath)
140 {
141     struct pldm_header_info hdr;
142     pldm_msg_hdr msg{};
143 
144     // Unpack PLDM request message and lower range of field values
145     msg.request = 1;
146     auto rc = unpack_pldm_header(&msg, &hdr);
147     EXPECT_EQ(rc, PLDM_SUCCESS);
148     EXPECT_EQ(hdr.msg_type, PLDM_REQUEST);
149     EXPECT_EQ(hdr.instance, 0);
150     EXPECT_EQ(hdr.pldm_type, 0);
151     EXPECT_EQ(hdr.command, 0);
152 
153     // Unpack PLDM async request message and lower range of field values
154     msg.datagram = 1;
155     rc = unpack_pldm_header(&msg, &hdr);
156     EXPECT_EQ(rc, PLDM_SUCCESS);
157     EXPECT_EQ(hdr.msg_type, PLDM_ASYNC_REQUEST_NOTIFY);
158 
159     // Unpack PLDM request message and upper range of field values
160     msg.datagram = 0;
161     msg.instance_id = 31;
162     msg.type = 63;
163     msg.command = 255;
164     rc = unpack_pldm_header(&msg, &hdr);
165     EXPECT_EQ(rc, PLDM_SUCCESS);
166     EXPECT_EQ(hdr.msg_type, PLDM_REQUEST);
167     EXPECT_EQ(hdr.instance, 31);
168     EXPECT_EQ(hdr.pldm_type, 63);
169     EXPECT_EQ(hdr.command, 255);
170 }
171 
TEST(UnpackPLDMMessage,ResponseMessageGoodPath)172 TEST(UnpackPLDMMessage, ResponseMessageGoodPath)
173 {
174     struct pldm_header_info hdr;
175     pldm_msg_hdr msg{};
176 
177     // Unpack PLDM response message and lower range of field values
178     auto rc = unpack_pldm_header(&msg, &hdr);
179     EXPECT_EQ(rc, PLDM_SUCCESS);
180     EXPECT_EQ(hdr.msg_type, PLDM_RESPONSE);
181     EXPECT_EQ(hdr.instance, 0);
182     EXPECT_EQ(hdr.pldm_type, 0);
183     EXPECT_EQ(hdr.command, 0);
184 
185     // Unpack PLDM response message and upper range of field values
186     msg.instance_id = 31;
187     msg.type = 63;
188     msg.command = 255;
189     rc = unpack_pldm_header(&msg, &hdr);
190     EXPECT_EQ(rc, PLDM_SUCCESS);
191     EXPECT_EQ(hdr.msg_type, PLDM_RESPONSE);
192     EXPECT_EQ(hdr.instance, 31);
193     EXPECT_EQ(hdr.pldm_type, 63);
194     EXPECT_EQ(hdr.command, 255);
195 }
196 
TEST(GetPLDMCommands,testEncodeRequest)197 TEST(GetPLDMCommands, testEncodeRequest)
198 {
199     uint8_t pldmType = 0x05;
200     ver32_t version{0xff, 0xff, 0xff, 0xff};
201     std::array<uint8_t, sizeof(pldm_msg_hdr) + PLDM_GET_COMMANDS_REQ_BYTES>
202         requestMsg{};
203     // NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast)
204     auto request = reinterpret_cast<pldm_msg*>(requestMsg.data());
205 
206     auto rc = encode_get_commands_req(0, pldmType, version, request);
207     EXPECT_EQ(rc, PLDM_SUCCESS);
208     EXPECT_EQ(0, memcmp(request->payload, &pldmType, sizeof(pldmType)));
209     EXPECT_EQ(0, memcmp(request->payload + sizeof(pldmType), &version,
210                         sizeof(version)));
211 }
212 
TEST(GetPLDMCommands,testDecodeRequest)213 TEST(GetPLDMCommands, testDecodeRequest)
214 {
215     uint8_t pldmType = 0x05;
216     ver32_t version{0xff, 0xff, 0xff, 0xff};
217     uint8_t pldmTypeOut{};
218     ver32_t versionOut{0xff, 0xff, 0xff, 0xff};
219     std::array<uint8_t, hdrSize + PLDM_GET_COMMANDS_REQ_BYTES> requestMsg{};
220 
221     memcpy(requestMsg.data() + hdrSize, &pldmType, sizeof(pldmType));
222     memcpy(requestMsg.data() + sizeof(pldmType) + hdrSize, &version,
223            sizeof(version));
224 
225     // NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast)
226     auto request = reinterpret_cast<pldm_msg*>(requestMsg.data());
227     auto rc = decode_get_commands_req(request, requestMsg.size() - hdrSize,
228                                       &pldmTypeOut, &versionOut);
229 
230     EXPECT_EQ(rc, PLDM_SUCCESS);
231     EXPECT_EQ(pldmTypeOut, pldmType);
232     EXPECT_EQ(0, memcmp(&versionOut, &version, sizeof(version)));
233 }
234 
TEST(GetPLDMCommands,testEncodeResponse)235 TEST(GetPLDMCommands, testEncodeResponse)
236 {
237     uint8_t completionCode = 0;
238     std::array<uint8_t, sizeof(pldm_msg_hdr) + PLDM_GET_COMMANDS_RESP_BYTES>
239         responseMsg{};
240     // NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast)
241     auto response = reinterpret_cast<pldm_msg*>(responseMsg.data());
242     std::array<bitfield8_t, PLDM_MAX_CMDS_PER_TYPE / 8> commands{};
243     commands[0].byte = 1;
244     commands[1].byte = 2;
245     commands[2].byte = 3;
246 
247     auto rc =
248         encode_get_commands_resp(0, PLDM_SUCCESS, commands.data(), response);
249     EXPECT_EQ(rc, PLDM_SUCCESS);
250     uint8_t* payload_ptr = response->payload;
251     EXPECT_EQ(completionCode, payload_ptr[0]);
252     EXPECT_EQ(1, payload_ptr[sizeof(completionCode)]);
253     EXPECT_EQ(2,
254               payload_ptr[sizeof(completionCode) + sizeof(commands[0].byte)]);
255     EXPECT_EQ(3, payload_ptr[sizeof(completionCode) + sizeof(commands[0].byte) +
256                              sizeof(commands[1].byte)]);
257 }
258 
TEST(GetPLDMTypes,testEncodeResponse)259 TEST(GetPLDMTypes, testEncodeResponse)
260 {
261     uint8_t completionCode = 0;
262     std::array<uint8_t, sizeof(pldm_msg_hdr) + PLDM_GET_TYPES_RESP_BYTES>
263         responseMsg{};
264     // NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast)
265     auto response = reinterpret_cast<pldm_msg*>(responseMsg.data());
266     std::array<bitfield8_t, PLDM_MAX_TYPES / 8> types{};
267     types[0].byte = 1;
268     types[1].byte = 2;
269     types[2].byte = 3;
270 
271     auto rc = encode_get_types_resp(0, PLDM_SUCCESS, types.data(), response);
272     EXPECT_EQ(rc, PLDM_SUCCESS);
273     uint8_t* payload_ptr = response->payload;
274     EXPECT_EQ(completionCode, payload_ptr[0]);
275     EXPECT_EQ(1, payload_ptr[sizeof(completionCode)]);
276     EXPECT_EQ(2, payload_ptr[sizeof(completionCode) + sizeof(types[0].byte)]);
277     EXPECT_EQ(3, payload_ptr[sizeof(completionCode) + sizeof(types[0].byte) +
278                              sizeof(types[1].byte)]);
279 }
280 
TEST(GetPLDMTypes,testGoodDecodeResponse)281 TEST(GetPLDMTypes, testGoodDecodeResponse)
282 {
283     std::array<uint8_t, hdrSize + PLDM_GET_TYPES_RESP_BYTES> responseMsg{};
284     responseMsg[1 + hdrSize] = 1;
285     responseMsg[2 + hdrSize] = 2;
286     responseMsg[3 + hdrSize] = 3;
287     std::array<bitfield8_t, PLDM_MAX_TYPES / 8> outTypes{};
288 
289     uint8_t completion_code;
290     responseMsg[hdrSize] = PLDM_SUCCESS;
291 
292     // NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast)
293     auto response = reinterpret_cast<pldm_msg*>(responseMsg.data());
294 
295     auto rc = decode_get_types_resp(response, responseMsg.size() - hdrSize,
296                                     &completion_code, outTypes.data());
297 
298     EXPECT_EQ(rc, PLDM_SUCCESS);
299     EXPECT_EQ(completion_code, PLDM_SUCCESS);
300     EXPECT_EQ(responseMsg[1 + hdrSize], outTypes[0].byte);
301     EXPECT_EQ(responseMsg[2 + hdrSize], outTypes[1].byte);
302     EXPECT_EQ(responseMsg[3 + hdrSize], outTypes[2].byte);
303 }
304 
TEST(GetPLDMTypes,testBadDecodeResponse)305 TEST(GetPLDMTypes, testBadDecodeResponse)
306 {
307     std::array<uint8_t, hdrSize + PLDM_GET_TYPES_RESP_BYTES> responseMsg{};
308     responseMsg[1 + hdrSize] = 1;
309     responseMsg[2 + hdrSize] = 2;
310     responseMsg[3 + hdrSize] = 3;
311     std::array<bitfield8_t, PLDM_MAX_TYPES / 8> outTypes{};
312 
313     uint8_t retcompletion_code = 0;
314     responseMsg[hdrSize] = PLDM_SUCCESS;
315 
316     // NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast)
317     auto response = reinterpret_cast<pldm_msg*>(responseMsg.data());
318 
319     auto rc = decode_get_types_resp(response, responseMsg.size() - hdrSize - 1,
320                                     &retcompletion_code, outTypes.data());
321 
322     EXPECT_EQ(rc, PLDM_ERROR_INVALID_LENGTH);
323 }
324 
TEST(GetPLDMCommands,testGoodDecodeResponse)325 TEST(GetPLDMCommands, testGoodDecodeResponse)
326 {
327     std::array<uint8_t, hdrSize + PLDM_GET_COMMANDS_RESP_BYTES> responseMsg{};
328     responseMsg[1 + hdrSize] = 1;
329     responseMsg[2 + hdrSize] = 2;
330     responseMsg[3 + hdrSize] = 3;
331     std::array<bitfield8_t, PLDM_MAX_CMDS_PER_TYPE / 8> outTypes{};
332 
333     uint8_t completion_code;
334     responseMsg[hdrSize] = PLDM_SUCCESS;
335 
336     // NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast)
337     auto response = reinterpret_cast<pldm_msg*>(responseMsg.data());
338 
339     auto rc = decode_get_commands_resp(response, responseMsg.size() - hdrSize,
340                                        &completion_code, outTypes.data());
341 
342     EXPECT_EQ(rc, PLDM_SUCCESS);
343     EXPECT_EQ(completion_code, PLDM_SUCCESS);
344     EXPECT_EQ(responseMsg[1 + hdrSize], outTypes[0].byte);
345     EXPECT_EQ(responseMsg[2 + hdrSize], outTypes[1].byte);
346     EXPECT_EQ(responseMsg[3 + hdrSize], outTypes[2].byte);
347 }
348 
TEST(GetPLDMCommands,testBadDecodeResponse)349 TEST(GetPLDMCommands, testBadDecodeResponse)
350 {
351     std::array<uint8_t, hdrSize + PLDM_GET_COMMANDS_RESP_BYTES> responseMsg{};
352     responseMsg[1 + hdrSize] = 1;
353     responseMsg[2 + hdrSize] = 2;
354     responseMsg[3 + hdrSize] = 3;
355     std::array<bitfield8_t, PLDM_MAX_CMDS_PER_TYPE / 8> outTypes{};
356 
357     uint8_t retcompletion_code = 0;
358     responseMsg[hdrSize] = PLDM_SUCCESS;
359 
360     // NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast)
361     auto response = reinterpret_cast<pldm_msg*>(responseMsg.data());
362 
363     auto rc =
364         decode_get_commands_resp(response, responseMsg.size() - hdrSize - 1,
365                                  &retcompletion_code, outTypes.data());
366 
367     EXPECT_EQ(rc, PLDM_ERROR_INVALID_LENGTH);
368 }
369 
TEST(GetPLDMVersion,testGoodEncodeRequest)370 TEST(GetPLDMVersion, testGoodEncodeRequest)
371 {
372     std::array<uint8_t, sizeof(pldm_msg_hdr) + PLDM_GET_VERSION_REQ_BYTES>
373         requestMsg{};
374     // NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast)
375     auto request = reinterpret_cast<pldm_msg*>(requestMsg.data());
376     uint8_t pldmType = 0x03;
377     uint32_t transferHandle = 0x0;
378     uint8_t opFlag = 0x01;
379 
380     auto rc =
381         encode_get_version_req(0, transferHandle, opFlag, pldmType, request);
382     EXPECT_EQ(rc, PLDM_SUCCESS);
383     EXPECT_EQ(
384         0, memcmp(request->payload, &transferHandle, sizeof(transferHandle)));
385     EXPECT_EQ(0, memcmp(request->payload + sizeof(transferHandle), &opFlag,
386                         sizeof(opFlag)));
387     EXPECT_EQ(0,
388               memcmp(request->payload + sizeof(transferHandle) + sizeof(opFlag),
389                      &pldmType, sizeof(pldmType)));
390 }
391 
TEST(GetPLDMVersion,testBadEncodeRequest)392 TEST(GetPLDMVersion, testBadEncodeRequest)
393 {
394     uint8_t pldmType = 0x03;
395     uint32_t transferHandle = 0x0;
396     uint8_t opFlag = 0x01;
397 
398     auto rc =
399         encode_get_version_req(0, transferHandle, opFlag, pldmType, nullptr);
400 
401     EXPECT_EQ(rc, PLDM_ERROR_INVALID_DATA);
402 }
403 
TEST(GetPLDMVersion,testEncodeResponse)404 TEST(GetPLDMVersion, testEncodeResponse)
405 {
406     uint8_t completionCode = 0;
407     uint32_t transferHandle = 0;
408     uint8_t flag = PLDM_START_AND_END;
409     std::array<uint8_t, sizeof(pldm_msg_hdr) + PLDM_GET_VERSION_RESP_BYTES>
410         responseMsg{};
411     // NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast)
412     auto response = reinterpret_cast<pldm_msg*>(responseMsg.data());
413     ver32_t version = {0xff, 0xff, 0xff, 0xff};
414 
415     auto rc = encode_get_version_resp(0, PLDM_SUCCESS, 0, PLDM_START_AND_END,
416                                       &version, sizeof(ver32_t), response);
417 
418     EXPECT_EQ(rc, PLDM_SUCCESS);
419     EXPECT_EQ(completionCode, response->payload[0]);
420     EXPECT_EQ(0, memcmp(response->payload + sizeof(response->payload[0]),
421                         &transferHandle, sizeof(transferHandle)));
422     EXPECT_EQ(0, memcmp(response->payload + sizeof(response->payload[0]) +
423                             sizeof(transferHandle),
424                         &flag, sizeof(flag)));
425     EXPECT_EQ(0, memcmp(response->payload + sizeof(response->payload[0]) +
426                             sizeof(transferHandle) + sizeof(flag),
427                         &version, sizeof(version)));
428 }
429 
TEST(GetPLDMVersion,testDecodeRequest)430 TEST(GetPLDMVersion, testDecodeRequest)
431 {
432     std::array<uint8_t, hdrSize + PLDM_GET_VERSION_REQ_BYTES> requestMsg{};
433     uint32_t transferHandle = 0x0;
434     uint32_t retTransferHandle = 0x0;
435     uint8_t flag = PLDM_GET_FIRSTPART;
436     uint8_t retFlag = PLDM_GET_FIRSTPART;
437     uint8_t pldmType = PLDM_BASE;
438     uint8_t retType = PLDM_BASE;
439 
440     memcpy(requestMsg.data() + hdrSize, &transferHandle,
441            sizeof(transferHandle));
442     memcpy(requestMsg.data() + sizeof(transferHandle) + hdrSize, &flag,
443            sizeof(flag));
444     memcpy(requestMsg.data() + sizeof(transferHandle) + sizeof(flag) + hdrSize,
445            &pldmType, sizeof(pldmType));
446 
447     // NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast)
448     auto request = reinterpret_cast<pldm_msg*>(requestMsg.data());
449 
450     auto rc = decode_get_version_req(request, requestMsg.size() - hdrSize,
451                                      &retTransferHandle, &retFlag, &retType);
452 
453     EXPECT_EQ(rc, PLDM_SUCCESS);
454     EXPECT_EQ(transferHandle, retTransferHandle);
455     EXPECT_EQ(flag, retFlag);
456     EXPECT_EQ(pldmType, retType);
457 }
458 
TEST(GetPLDMVersion,testDecodeResponse)459 TEST(GetPLDMVersion, testDecodeResponse)
460 {
461     std::array<uint8_t, sizeof(pldm_msg_hdr) + PLDM_GET_VERSION_RESP_BYTES>
462         responseMsg{};
463     uint32_t transferHandle = 0x0;
464     uint32_t retTransferHandle = 0x0;
465     uint8_t flag = PLDM_START_AND_END;
466     uint8_t retFlag = PLDM_START_AND_END;
467     uint8_t completionCode = 0;
468     ver32_t version = {0xff, 0xff, 0xff, 0xff};
469     ver32_t versionOut;
470     uint8_t completion_code;
471 
472     memcpy(responseMsg.data() + sizeof(completionCode) + hdrSize,
473            &transferHandle, sizeof(transferHandle));
474     memcpy(responseMsg.data() + sizeof(completionCode) +
475                sizeof(transferHandle) + hdrSize,
476            &flag, sizeof(flag));
477     memcpy(responseMsg.data() + sizeof(completionCode) +
478                sizeof(transferHandle) + sizeof(flag) + hdrSize,
479            &version, sizeof(version));
480 
481     // NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast)
482     auto response = reinterpret_cast<pldm_msg*>(responseMsg.data());
483 
484     auto rc = decode_get_version_resp(response, responseMsg.size() - hdrSize,
485                                       &completion_code, &retTransferHandle,
486                                       &retFlag, &versionOut);
487     EXPECT_EQ(rc, PLDM_SUCCESS);
488     EXPECT_EQ(transferHandle, retTransferHandle);
489     EXPECT_EQ(flag, retFlag);
490 
491     EXPECT_EQ(versionOut.major, version.major);
492     EXPECT_EQ(versionOut.minor, version.minor);
493     EXPECT_EQ(versionOut.update, version.update);
494     EXPECT_EQ(versionOut.alpha, version.alpha);
495 }
496 
TEST(GetTID,testEncodeRequest)497 TEST(GetTID, testEncodeRequest)
498 {
499     pldm_msg request{};
500 
501     auto rc = encode_get_tid_req(0, &request);
502     ASSERT_EQ(rc, PLDM_SUCCESS);
503 }
504 
TEST(GetTID,testEncodeResponse)505 TEST(GetTID, testEncodeResponse)
506 {
507     uint8_t completionCode = 0;
508     std::array<uint8_t, sizeof(pldm_msg_hdr) + PLDM_GET_TID_RESP_BYTES>
509         responseMsg{};
510     // NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast)
511     auto response = reinterpret_cast<pldm_msg*>(responseMsg.data());
512     uint8_t tid = 1;
513 
514     auto rc = encode_get_tid_resp(0, PLDM_SUCCESS, tid, response);
515     EXPECT_EQ(rc, PLDM_SUCCESS);
516     uint8_t* payload = response->payload;
517     EXPECT_EQ(completionCode, payload[0]);
518     EXPECT_EQ(1, payload[sizeof(completionCode)]);
519 }
520 
TEST(GetTID,testDecodeResponse)521 TEST(GetTID, testDecodeResponse)
522 {
523     std::array<uint8_t, hdrSize + PLDM_GET_TID_RESP_BYTES> responseMsg{};
524     responseMsg[1 + hdrSize] = 1;
525 
526     uint8_t tid;
527     uint8_t completion_code;
528     responseMsg[hdrSize] = PLDM_SUCCESS;
529 
530     // NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast)
531     auto response = reinterpret_cast<pldm_msg*>(responseMsg.data());
532 
533     auto rc = decode_get_tid_resp(response, responseMsg.size() - hdrSize,
534                                   &completion_code, &tid);
535 
536     EXPECT_EQ(rc, PLDM_SUCCESS);
537     EXPECT_EQ(completion_code, PLDM_SUCCESS);
538     EXPECT_EQ(tid, 1);
539 }
540 
TEST(MultipartReceive,testDecodeRequestPass)541 TEST(MultipartReceive, testDecodeRequestPass)
542 {
543     constexpr uint8_t kPldmType = PLDM_BASE;
544     constexpr uint8_t kFlag = PLDM_XFER_FIRST_PART;
545     constexpr uint32_t kTransferCtx = 0x01;
546     constexpr uint32_t kTransferHandle = 0x10;
547     constexpr uint32_t kSectionOffset = 0x0;
548     constexpr uint32_t kSectionLength = 0x10;
549     uint8_t pldm_type = 0x0;
550     uint8_t flag = PLDM_GET_FIRSTPART;
551     uint32_t transfer_ctx;
552     uint32_t transfer_handle;
553     uint32_t section_offset;
554     uint32_t section_length;
555 
556     // Header values don't matter for this test.
557     pldm_msg_hdr hdr{};
558     // Assign values to the packet struct and memcpy to ensure correct byte
559     // ordering.
560     pldm_multipart_receive_req req_pkt = {
561         .pldm_type = kPldmType,
562         .transfer_opflag = kFlag,
563         .transfer_ctx = kTransferCtx,
564         .transfer_handle = kTransferHandle,
565         .section_offset = kSectionOffset,
566         .section_length = kSectionLength,
567     };
568     std::vector<uint8_t> req(sizeof(hdr) + PLDM_MULTIPART_RECEIVE_REQ_BYTES);
569     std::memcpy(req.data(), &hdr, sizeof(hdr));
570     std::memcpy(req.data() + sizeof(hdr), &req_pkt, sizeof(req_pkt));
571 
572     // NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast)
573     pldm_msg* pldm_request = reinterpret_cast<pldm_msg*>(req.data());
574     int rc = decode_multipart_receive_req(
575         pldm_request, req.size() - hdrSize, &pldm_type, &flag, &transfer_ctx,
576         &transfer_handle, &section_offset, &section_length);
577 
578     EXPECT_EQ(rc, PLDM_SUCCESS);
579     EXPECT_EQ(pldm_type, kPldmType);
580     EXPECT_EQ(flag, kFlag);
581     EXPECT_EQ(transfer_ctx, kTransferCtx);
582     EXPECT_EQ(transfer_handle, kTransferHandle);
583     EXPECT_EQ(section_offset, kSectionOffset);
584     EXPECT_EQ(section_length, kSectionLength);
585 }
586 
TEST(MultipartReceive,testDecodeRequestFailNullData)587 TEST(MultipartReceive, testDecodeRequestFailNullData)
588 {
589     EXPECT_EQ(decode_multipart_receive_req(NULL, 0, NULL, NULL, NULL, NULL,
590                                            NULL, NULL),
591               PLDM_ERROR_INVALID_DATA);
592 }
593 
TEST(MultipartReceive,testDecodeRequestFailBadLength)594 TEST(MultipartReceive, testDecodeRequestFailBadLength)
595 {
596     constexpr uint8_t kPldmType = PLDM_BASE;
597     constexpr uint8_t kFlag = PLDM_XFER_FIRST_PART;
598     uint8_t pldm_type;
599     uint8_t flag;
600     uint32_t transfer_ctx;
601     uint32_t transfer_handle;
602     uint32_t section_offset;
603     uint32_t section_length;
604 
605     // Header values don't matter for this test.
606     pldm_msg_hdr hdr{};
607     // Assign values to the packet struct and memcpy to ensure correct byte
608     // ordering.
609     pldm_multipart_receive_req req_pkt{};
610     req_pkt.pldm_type = kPldmType;
611     req_pkt.transfer_opflag = kFlag;
612 
613     std::vector<uint8_t> req(sizeof(hdr) + PLDM_MULTIPART_RECEIVE_REQ_BYTES);
614     std::memcpy(req.data(), &hdr, sizeof(hdr));
615     std::memcpy(req.data() + sizeof(hdr), &req_pkt, sizeof(req_pkt));
616 
617     // NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast)
618     pldm_msg* pldm_request = reinterpret_cast<pldm_msg*>(req.data());
619     EXPECT_EQ(decode_multipart_receive_req(
620                   pldm_request, (req.size() - hdrSize) + 1, &pldm_type, &flag,
621                   &transfer_ctx, &transfer_handle, &section_offset,
622                   &section_length),
623               PLDM_ERROR_INVALID_LENGTH);
624 }
625 
TEST(MultipartReceive,testDecodeRequestFailBadPldmType)626 TEST(MultipartReceive, testDecodeRequestFailBadPldmType)
627 {
628     constexpr uint8_t kPldmType = 0xff;
629     constexpr uint8_t kFlag = PLDM_XFER_FIRST_PART;
630     uint8_t pldm_type;
631     uint8_t flag;
632     uint32_t transfer_ctx;
633     uint32_t transfer_handle;
634     uint32_t section_offset;
635     uint32_t section_length;
636 
637     // Header values don't matter for this test.
638     pldm_msg_hdr hdr{};
639     // Assign values to the packet struct and memcpy to ensure correct byte
640     // ordering.
641     pldm_multipart_receive_req req_pkt{};
642     req_pkt.pldm_type = kPldmType;
643     req_pkt.transfer_opflag = kFlag;
644 
645     std::vector<uint8_t> req(sizeof(hdr) + PLDM_MULTIPART_RECEIVE_REQ_BYTES);
646     std::memcpy(req.data(), &hdr, sizeof(hdr));
647     std::memcpy(req.data() + sizeof(hdr), &req_pkt, sizeof(req_pkt));
648 
649     // NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast)
650     pldm_msg* pldm_request = reinterpret_cast<pldm_msg*>(req.data());
651     EXPECT_EQ(decode_multipart_receive_req(pldm_request, req.size() - hdrSize,
652                                            &pldm_type, &flag, &transfer_ctx,
653                                            &transfer_handle, &section_offset,
654                                            &section_length),
655               PLDM_ERROR_INVALID_PLDM_TYPE);
656 }
657 
TEST(MultipartReceive,testDecodeRequestFailBadTransferFlag)658 TEST(MultipartReceive, testDecodeRequestFailBadTransferFlag)
659 {
660     constexpr uint8_t kPldmType = PLDM_BASE;
661     constexpr uint8_t kFlag = PLDM_XFER_CURRENT_PART + 0x10;
662     uint8_t pldm_type;
663     uint8_t flag;
664     uint32_t transfer_ctx;
665     uint32_t transfer_handle;
666     uint32_t section_offset;
667     uint32_t section_length;
668 
669     // Header values don't matter for this test.
670     pldm_msg_hdr hdr{};
671     // Assign values to the packet struct and memcpy to ensure correct byte
672     // ordering.
673     pldm_multipart_receive_req req_pkt{};
674     req_pkt.pldm_type = kPldmType;
675     req_pkt.transfer_opflag = kFlag;
676 
677     std::vector<uint8_t> req(sizeof(hdr) + PLDM_MULTIPART_RECEIVE_REQ_BYTES);
678     std::memcpy(req.data(), &hdr, sizeof(hdr));
679     std::memcpy(req.data() + sizeof(hdr), &req_pkt, sizeof(req_pkt));
680 
681     // NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast)
682     pldm_msg* pldm_request = reinterpret_cast<pldm_msg*>(req.data());
683     EXPECT_EQ(decode_multipart_receive_req(pldm_request, req.size() - hdrSize,
684                                            &pldm_type, &flag, &transfer_ctx,
685                                            &transfer_handle, &section_offset,
686                                            &section_length),
687               PLDM_INVALID_TRANSFER_OPERATION_FLAG);
688 }
689 
TEST(MultipartReceive,testDecodeRequestFailBadOffset)690 TEST(MultipartReceive, testDecodeRequestFailBadOffset)
691 {
692     constexpr uint8_t kPldmType = PLDM_BASE;
693     constexpr uint8_t kFlag = PLDM_XFER_NEXT_PART;
694     constexpr uint32_t kTransferHandle = 0x01;
695     constexpr uint32_t kSectionOffset = 0x0;
696     uint8_t pldm_type;
697     uint8_t flag;
698     uint32_t transfer_ctx;
699     uint32_t transfer_handle;
700     uint32_t section_offset;
701     uint32_t section_length;
702 
703     // Header values don't matter for this test.
704     pldm_msg_hdr hdr{};
705     // Assign values to the packet struct and memcpy to ensure correct byte
706     // ordering.
707     pldm_multipart_receive_req req_pkt{};
708     req_pkt.pldm_type = kPldmType;
709     req_pkt.transfer_opflag = kFlag;
710     req_pkt.transfer_handle = kTransferHandle;
711     req_pkt.section_offset = kSectionOffset;
712 
713     std::vector<uint8_t> req(sizeof(hdr) + PLDM_MULTIPART_RECEIVE_REQ_BYTES);
714     std::memcpy(req.data(), &hdr, sizeof(hdr));
715     std::memcpy(req.data() + sizeof(hdr), &req_pkt, sizeof(req_pkt));
716 
717     // NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast)
718     pldm_msg* pldm_request = reinterpret_cast<pldm_msg*>(req.data());
719     EXPECT_EQ(decode_multipart_receive_req(pldm_request, req.size() - hdrSize,
720                                            &pldm_type, &flag, &transfer_ctx,
721                                            &transfer_handle, &section_offset,
722                                            &section_length),
723               PLDM_ERROR_INVALID_DATA);
724 }
725 
TEST(MultipartReceive,testDecodeRequestFailBadHandle)726 TEST(MultipartReceive, testDecodeRequestFailBadHandle)
727 {
728     constexpr uint8_t kPldmType = PLDM_BASE;
729     constexpr uint8_t kFlag = PLDM_XFER_NEXT_PART;
730     constexpr uint32_t kSectionOffset = 0x100;
731     constexpr uint32_t kTransferHandle = 0x0;
732     uint8_t pldm_type;
733     uint8_t flag;
734     uint32_t transfer_ctx;
735     uint32_t transfer_handle;
736     uint32_t section_offset;
737     uint32_t section_length;
738 
739     // Header values don't matter for this test.
740     pldm_msg_hdr hdr{};
741     // Assign values to the packet struct and memcpy to ensure correct byte
742     // ordering.
743     pldm_multipart_receive_req req_pkt{};
744     req_pkt.pldm_type = kPldmType;
745     req_pkt.transfer_opflag = kFlag;
746     req_pkt.transfer_handle = kTransferHandle;
747     req_pkt.section_offset = kSectionOffset;
748 
749     std::vector<uint8_t> req(sizeof(hdr) + PLDM_MULTIPART_RECEIVE_REQ_BYTES);
750     std::memcpy(req.data(), &hdr, sizeof(hdr));
751     std::memcpy(req.data() + sizeof(hdr), &req_pkt, sizeof(req_pkt));
752 
753     // NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast)
754     pldm_msg* pldm_request = reinterpret_cast<pldm_msg*>(req.data());
755     EXPECT_EQ(decode_multipart_receive_req(pldm_request, req.size() - hdrSize,
756                                            &pldm_type, &flag, &transfer_ctx,
757                                            &transfer_handle, &section_offset,
758                                            &section_length),
759               PLDM_ERROR_INVALID_DATA);
760 }
761 
TEST(CcOnlyResponse,testEncode)762 TEST(CcOnlyResponse, testEncode)
763 {
764     struct pldm_msg responseMsg;
765 
766     auto rc =
767         encode_cc_only_resp(0 /*instance id*/, 1 /*pldm type*/, 2 /*command*/,
768                             3 /*completion code*/, &responseMsg);
769     EXPECT_EQ(rc, PLDM_SUCCESS);
770 
771     // NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast)
772     auto p = reinterpret_cast<uint8_t*>(&responseMsg);
773     EXPECT_THAT(std::vector<uint8_t>(p, p + sizeof(responseMsg)),
774                 ElementsAreArray({0, 1, 2, 3}));
775 
776     rc = encode_cc_only_resp(PLDM_INSTANCE_MAX + 1, 1, 2, 3, &responseMsg);
777     EXPECT_EQ(rc, PLDM_ERROR_INVALID_DATA);
778 
779     rc = encode_cc_only_resp(0, 1, 2, 3, nullptr);
780     EXPECT_EQ(rc, PLDM_ERROR_INVALID_DATA);
781 }
782 
TEST(SetTID,testGoodEncodeRequest)783 TEST(SetTID, testGoodEncodeRequest)
784 {
785     uint8_t instanceId = 0;
786     uint8_t tid = 0x01;
787     std::array<uint8_t, sizeof(pldm_msg_hdr) + sizeof(tid)> requestMsg{};
788     // NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast)
789     auto request = reinterpret_cast<pldm_msg*>(requestMsg.data());
790 
791     auto rc = encode_set_tid_req(instanceId, tid, request);
792     ASSERT_EQ(rc, PLDM_SUCCESS);
793 
794     EXPECT_EQ(request->hdr.command, PLDM_SET_TID);
795     EXPECT_EQ(request->hdr.type, PLDM_BASE);
796     EXPECT_EQ(request->hdr.request, 1);
797     EXPECT_EQ(request->hdr.datagram, 0);
798     EXPECT_EQ(request->hdr.instance_id, instanceId);
799     EXPECT_EQ(0, memcmp(request->payload, &tid, sizeof(tid)));
800 }
801 
TEST(SetTID,testBadEncodeRequest)802 TEST(SetTID, testBadEncodeRequest)
803 {
804     uint8_t tid = 0x01;
805     std::array<uint8_t, sizeof(pldm_msg_hdr) + sizeof(tid)> requestMsg{};
806     // NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast)
807     auto request = reinterpret_cast<pldm_msg*>(requestMsg.data());
808 
809     auto rc = encode_set_tid_req(0, tid, nullptr);
810     EXPECT_EQ(rc, PLDM_ERROR_INVALID_DATA);
811 
812     rc = encode_set_tid_req(0, 0, request);
813     EXPECT_EQ(rc, PLDM_ERROR_INVALID_DATA);
814 
815     rc = encode_set_tid_req(0, 0xff, request);
816     EXPECT_EQ(rc, PLDM_ERROR_INVALID_DATA);
817 }
818 
819 #ifdef LIBPLDM_API_TESTING
TEST(PldmMsgHdr,correlateSuccess)820 TEST(PldmMsgHdr, correlateSuccess)
821 {
822     static const struct pldm_msg_hdr req = {
823         .instance_id = 0,
824         .reserved = 0,
825         .datagram = 0,
826         .request = 1,
827         .type = 0,
828         .header_ver = 1,
829         .command = 0x01,
830     };
831     static const struct pldm_msg_hdr resp = {
832         .instance_id = 0,
833         .reserved = 0,
834         .datagram = 0,
835         .request = 0,
836         .type = 0,
837         .header_ver = 1,
838         .command = 0x01,
839     };
840 
841     ASSERT_EQ(pldm_msg_hdr_correlate_response(&req, &resp), true);
842 }
843 #endif
844 
845 #ifdef LIBPLDM_API_TESTING
TEST(PldmMsgHdr,correlateFailInstanceID)846 TEST(PldmMsgHdr, correlateFailInstanceID)
847 {
848     static const struct pldm_msg_hdr req = {
849         .instance_id = 0,
850         .reserved = 0,
851         .datagram = 0,
852         .request = 1,
853         .type = 0,
854         .header_ver = 1,
855         .command = 0x01,
856     };
857     static const struct pldm_msg_hdr resp = {
858         .instance_id = 1,
859         .reserved = 0,
860         .datagram = 0,
861         .request = 0,
862         .type = 0,
863         .header_ver = 1,
864         .command = 0x01,
865     };
866 
867     ASSERT_EQ(pldm_msg_hdr_correlate_response(&req, &resp), false);
868 }
869 #endif
870 
871 #ifdef LIBPLDM_API_TESTING
TEST(PldmMsgHdr,correlateFailRequest)872 TEST(PldmMsgHdr, correlateFailRequest)
873 {
874     static const struct pldm_msg_hdr req = {
875         .instance_id = 0,
876         .reserved = 0,
877         .datagram = 0,
878         .request = 1,
879         .type = 0,
880         .header_ver = 1,
881         .command = 0x01,
882     };
883     static const struct pldm_msg_hdr resp = {
884         .instance_id = 0,
885         .reserved = 0,
886         .datagram = 0,
887         .request = 1,
888         .type = 0,
889         .header_ver = 1,
890         .command = 0x01,
891     };
892 
893     ASSERT_EQ(pldm_msg_hdr_correlate_response(&req, &resp), false);
894 }
895 #endif
896 
897 #ifdef LIBPLDM_API_TESTING
TEST(PldmMsgHdr,correlateFailType)898 TEST(PldmMsgHdr, correlateFailType)
899 {
900     static const struct pldm_msg_hdr req = {
901         .instance_id = 0,
902         .reserved = 0,
903         .datagram = 0,
904         .request = 1,
905         .type = 0,
906         .header_ver = 1,
907         .command = 0x01,
908     };
909     static const struct pldm_msg_hdr resp = {
910         .instance_id = 0,
911         .reserved = 0,
912         .datagram = 0,
913         .request = 0,
914         .type = 1,
915         .header_ver = 1,
916         .command = 0x01,
917     };
918 
919     ASSERT_EQ(pldm_msg_hdr_correlate_response(&req, &resp), false);
920 }
921 #endif
922 
923 #ifdef LIBPLDM_API_TESTING
TEST(PldmMsgHdr,correlateFailCommand)924 TEST(PldmMsgHdr, correlateFailCommand)
925 {
926     static const struct pldm_msg_hdr req = {
927         .instance_id = 0,
928         .reserved = 0,
929         .datagram = 0,
930         .request = 1,
931         .type = 0,
932         .header_ver = 1,
933         .command = 0x01,
934     };
935     static const struct pldm_msg_hdr resp = {
936         .instance_id = 0,
937         .reserved = 0,
938         .datagram = 0,
939         .request = 0,
940         .type = 0,
941         .header_ver = 1,
942         .command = 0x02,
943     };
944 
945     ASSERT_EQ(pldm_msg_hdr_correlate_response(&req, &resp), false);
946 }
947 #endif
948 
949 #ifdef LIBPLDM_API_TESTING
TEST(PldmMsgHdr,correlateFailRequestIsResponse)950 TEST(PldmMsgHdr, correlateFailRequestIsResponse)
951 {
952     static const struct pldm_msg_hdr req = {
953         .instance_id = 0,
954         .reserved = 0,
955         .datagram = 0,
956         .request = 0,
957         .type = 0,
958         .header_ver = 1,
959         .command = 0x01,
960     };
961     static const struct pldm_msg_hdr resp = {
962         .instance_id = 0,
963         .reserved = 0,
964         .datagram = 0,
965         .request = 0,
966         .type = 0,
967         .header_ver = 1,
968         .command = 0x02,
969     };
970 
971     ASSERT_EQ(pldm_msg_hdr_correlate_response(&req, &resp), false);
972 }
973 #endif
974