xref: /openbmc/libpldm/tests/dsp/firmware_update.cpp (revision 92c323690dc201338e82acab65980deb0052da51)
1 #include <endian.h>
2 #include <libpldm/base.h>
3 #include <libpldm/firmware_update.h>
4 #include <libpldm/pldm_types.h>
5 #include <libpldm/utils.h>
6 
7 #include <algorithm>
8 #include <array>
9 #include <bitset>
10 #include <cstddef>
11 #include <cstdint>
12 #include <cstring>
13 #include <span>
14 #include <string>
15 #include <string_view>
16 #include <vector>
17 
18 #include "msgbuf.h"
19 
20 #include <gmock/gmock.h>
21 #include <gtest/gtest.h>
22 
23 using testing::ElementsAreArray;
24 
25 constexpr auto hdrSize = sizeof(pldm_msg_hdr);
26 
27 #ifdef LIBPLDM_API_TESTING
28 
29 static const uint8_t FIXED_INSTANCE_ID = 31;
30 
31 /* data is a pointer to pldm message response header */
check_response(const void * data,uint8_t command)32 static void check_response(const void* data, uint8_t command)
33 {
34     auto enc = static_cast<const pldm_msg*>(data);
35     EXPECT_EQ(enc->hdr.request, PLDM_RESPONSE);
36     EXPECT_EQ(enc->hdr.type, PLDM_FWUP);
37     EXPECT_EQ(enc->hdr.command, command);
38     EXPECT_EQ(enc->hdr.reserved, 0);
39     EXPECT_EQ(enc->hdr.datagram, 0);
40     EXPECT_EQ(enc->hdr.header_ver, 0);
41     EXPECT_EQ(enc->hdr.instance_id, FIXED_INSTANCE_ID);
42 }
43 #endif
44 
45 static constexpr std::array<uint8_t, PLDM_FWUP_UUID_LENGTH>
46     PLDM_FWUP_PACKAGE_HEADER_IDENTIFIER_V1_0{0xf0, 0x18, 0x87, 0x8c, 0xcb, 0x7d,
47                                              0x49, 0x43, 0x98, 0x00, 0xa0, 0x2f,
48                                              0x05, 0x9a, 0xca, 0x02};
49 
50 static constexpr uint8_t PLDM_FWUP_PACKAGE_HEADER_FORMAT_REVISION_V1_0 = 0x01;
51 
TEST(DecodePackageHeaderInfo,goodPath)52 TEST(DecodePackageHeaderInfo, goodPath)
53 {
54     // Random PackageHeaderSize
55     constexpr uint16_t pkgHeaderSize = 303;
56     // PackageReleaseDateTime - "25/12/2021 00:00:00"
57     std::array<uint8_t, PLDM_TIMESTAMP104_SIZE> package_release_date_time{
58         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
59         0x00, 0x19, 0x0c, 0xe5, 0x07, 0x00};
60     constexpr uint16_t componentBitmapBitLength = 8;
61     // PackageVersionString
62     constexpr std::string_view packageVersionStr{"OpenBMCv1.0"};
63     constexpr size_t packageHeaderSize =
64         sizeof(pldm_package_header_information) + packageVersionStr.size();
65 
66     constexpr std::array<uint8_t, packageHeaderSize> packagerHeaderInfo{
67         0xf0, 0x18, 0x87, 0x8c, 0xcb, 0x7d, 0x49, 0x43, 0x98, 0x00, 0xa0, 0x2f,
68         0x05, 0x9a, 0xca, 0x02, 0x01, 0x2f, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
69         0x00, 0x00, 0x00, 0x19, 0x0c, 0xe5, 0x07, 0x00, 0x08, 0x00, 0x01, 0x0b,
70         0x4f, 0x70, 0x65, 0x6e, 0x42, 0x4d, 0x43, 0x76, 0x31, 0x2e, 0x30};
71     pldm_package_header_information pkgHeader{};
72     variable_field packageVersion{};
73 
74     auto rc = decode_pldm_package_header_info(packagerHeaderInfo.data(),
75                                               packagerHeaderInfo.size(),
76                                               &pkgHeader, &packageVersion);
77 
78     EXPECT_EQ(rc, PLDM_SUCCESS);
79     EXPECT_EQ(true,
80               std::equal(pkgHeader.uuid, pkgHeader.uuid + PLDM_FWUP_UUID_LENGTH,
81                          PLDM_FWUP_PACKAGE_HEADER_IDENTIFIER_V1_0.begin(),
82                          PLDM_FWUP_PACKAGE_HEADER_IDENTIFIER_V1_0.end()));
83     EXPECT_EQ(pkgHeader.package_header_format_version,
84               PLDM_FWUP_PACKAGE_HEADER_FORMAT_REVISION_V1_0);
85     EXPECT_EQ(pkgHeader.package_header_size, pkgHeaderSize);
86     EXPECT_EQ(true, std::equal(pkgHeader.package_release_date_time,
87                                pkgHeader.package_release_date_time +
88                                    PLDM_TIMESTAMP104_SIZE,
89                                package_release_date_time.begin(),
90                                package_release_date_time.end()));
91     EXPECT_EQ(pkgHeader.component_bitmap_bit_length, componentBitmapBitLength);
92     EXPECT_EQ(pkgHeader.package_version_string_type, PLDM_STR_TYPE_ASCII);
93     EXPECT_EQ(pkgHeader.package_version_string_length,
94               packageVersionStr.size());
95     std::string packageVersionString(
96         // NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast)
97         reinterpret_cast<const char*>(packageVersion.ptr),
98         packageVersion.length);
99     EXPECT_EQ(packageVersionString, packageVersionStr);
100 }
101 
TEST(DecodePackageHeaderInfo,invalidArguments)102 TEST(DecodePackageHeaderInfo, invalidArguments)
103 {
104     constexpr std::string_view packageVersionStr{"OpenBMCv1.0"};
105     constexpr size_t packageHeaderSize =
106         sizeof(pldm_package_header_information) + packageVersionStr.size();
107 
108     constexpr std::array<uint8_t, packageHeaderSize> packagerHeaderInfo{
109         0xf0, 0x18, 0x87, 0x8c, 0xcb, 0x7d, 0x49, 0x43, 0x98, 0x00, 0xa0, 0x2f,
110         0x05, 0x9a, 0xca, 0x02, 0x01, 0x2f, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
111         0x00, 0x00, 0x00, 0x19, 0x0c, 0xe5, 0x07, 0x00, 0x08, 0x00, 0x01, 0x0b,
112         0x4f, 0x70, 0x65, 0x6e, 0x42, 0x4d, 0x43, 0x76, 0x31, 0x2e, 0x30};
113 
114     pldm_package_header_information packageHeader{};
115     variable_field packageVersion{};
116     int rc = 0;
117 
118     rc = decode_pldm_package_header_info(nullptr, packagerHeaderInfo.size(),
119                                          &packageHeader, &packageVersion);
120     EXPECT_EQ(rc, PLDM_ERROR_INVALID_DATA);
121 
122     rc = decode_pldm_package_header_info(packagerHeaderInfo.data(),
123                                          packagerHeaderInfo.size(), nullptr,
124                                          &packageVersion);
125     EXPECT_EQ(rc, PLDM_ERROR_INVALID_DATA);
126 
127     rc = decode_pldm_package_header_info(packagerHeaderInfo.data(),
128                                          packagerHeaderInfo.size(),
129                                          &packageHeader, nullptr);
130     EXPECT_EQ(rc, PLDM_ERROR_INVALID_DATA);
131 }
132 
TEST(DecodePackageHeaderInfo,invalidPackageLengths)133 TEST(DecodePackageHeaderInfo, invalidPackageLengths)
134 {
135     constexpr std::string_view packageVersionStr{"OpenBMCv1.0"};
136     constexpr size_t packageHeaderSize =
137         sizeof(pldm_package_header_information) + packageVersionStr.size();
138 
139     constexpr std::array<uint8_t, packageHeaderSize> packagerHeaderInfo{
140         0xf0, 0x18, 0x87, 0x8c, 0xcb, 0x7d, 0x49, 0x43, 0x98, 0x00, 0xa0, 0x2f,
141         0x05, 0x9a, 0xca, 0x02, 0x01, 0x2f, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
142         0x00, 0x00, 0x00, 0x19, 0x0c, 0xe5, 0x07, 0x00, 0x08, 0x00, 0x01, 0x0b,
143         0x4f, 0x70, 0x65, 0x6e, 0x42, 0x4d, 0x43, 0x76, 0x31, 0x2e, 0x30};
144 
145     pldm_package_header_information packageHeader{};
146     variable_field packageVersion{};
147     int rc = 0;
148 
149     rc = decode_pldm_package_header_info(
150         packagerHeaderInfo.data(), sizeof(pldm_package_header_information) - 1,
151         &packageHeader, &packageVersion);
152     EXPECT_EQ(rc, PLDM_ERROR_INVALID_LENGTH);
153 }
154 
TEST(DecodePackageHeaderInfo,invalidPackageVersionStringType)155 TEST(DecodePackageHeaderInfo, invalidPackageVersionStringType)
156 {
157     constexpr std::string_view packageVersionStr{"OpenBMCv1.0"};
158     constexpr size_t packageHeaderSize =
159         sizeof(pldm_package_header_information) + packageVersionStr.size();
160 
161     constexpr std::array<uint8_t, packageHeaderSize> invalidPackagerHeaderInfo{
162         0xf0, 0x18, 0x87, 0x8c, 0xcb, 0x7d, 0x49, 0x43, 0x98, 0x00, 0xa0, 0x2f,
163         0x05, 0x9a, 0xca, 0x02, 0x02, 0x2f, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
164         0x00, 0x00, 0x00, 0x19, 0x0c, 0xe5, 0x07, 0x00, 0x08, 0x00, 0x06, 0x0b,
165         0x4f, 0x70, 0x65, 0x6e, 0x42, 0x4d, 0x43, 0x76, 0x31, 0x2e, 0x30};
166 
167     pldm_package_header_information packageHeader{};
168     variable_field packageVersion{};
169     int rc = 0;
170 
171     rc = decode_pldm_package_header_info(invalidPackagerHeaderInfo.data(),
172                                          invalidPackagerHeaderInfo.size(),
173                                          &packageHeader, &packageVersion);
174     EXPECT_EQ(rc, PLDM_ERROR_INVALID_DATA);
175 }
176 
TEST(DecodePackageHeaderInfo,invalidPackageVersionStringLength)177 TEST(DecodePackageHeaderInfo, invalidPackageVersionStringLength)
178 {
179     constexpr std::string_view packageVersionStr{"OpenBMCv1.0"};
180     constexpr size_t packageHeaderSize =
181         sizeof(pldm_package_header_information) + packageVersionStr.size();
182 
183     constexpr std::array<uint8_t, packageHeaderSize> invalidPackagerHeaderInfo{
184         0xf0, 0x18, 0x87, 0x8c, 0xcb, 0x7d, 0x49, 0x43, 0x98, 0x00, 0xa0, 0x2f,
185         0x05, 0x9a, 0xca, 0x02, 0x02, 0x2f, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
186         0x00, 0x00, 0x00, 0x19, 0x0c, 0xe5, 0x07, 0x00, 0x08, 0x00, 0x01, 0x00,
187         0x4f, 0x70, 0x65, 0x6e, 0x42, 0x4d, 0x43, 0x76, 0x31, 0x2e, 0x30};
188 
189     pldm_package_header_information packageHeader{};
190     variable_field packageVersion{};
191     int rc = 0;
192 
193     rc = decode_pldm_package_header_info(invalidPackagerHeaderInfo.data(),
194                                          invalidPackagerHeaderInfo.size(),
195                                          &packageHeader, &packageVersion);
196     EXPECT_EQ(rc, PLDM_ERROR_INVALID_DATA);
197 }
198 
TEST(DecodePackageHeaderInfo,corruptPackageVersionStringLength)199 TEST(DecodePackageHeaderInfo, corruptPackageVersionStringLength)
200 {
201     constexpr std::string_view packageVersionStr{"OpenBMCv1.0"};
202     constexpr size_t packageHeaderSize =
203         sizeof(pldm_package_header_information) + packageVersionStr.size();
204 
205     constexpr std::array<uint8_t, packageHeaderSize - 1>
206         invalidPackagerHeaderInfo{
207             0xf0, 0x18, 0x87, 0x8c, 0xcb, 0x7d, 0x49, 0x43, 0x98, 0x00,
208             0xa0, 0x2f, 0x05, 0x9a, 0xca, 0x02, 0x02, 0x2f, 0x01, 0x00,
209             0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x19, 0x0c, 0xe5,
210             0x07, 0x00, 0x08, 0x00, 0x01, 0x0b, 0x4f, 0x70, 0x65, 0x6e,
211             0x42, 0x4d, 0x43, 0x76, 0x31, 0x2e};
212 
213     pldm_package_header_information packageHeader{};
214     variable_field packageVersion{};
215     int rc = 0;
216 
217     rc = decode_pldm_package_header_info(invalidPackagerHeaderInfo.data(),
218                                          invalidPackagerHeaderInfo.size(),
219                                          &packageHeader, &packageVersion);
220     EXPECT_EQ(rc, PLDM_ERROR_INVALID_LENGTH);
221 }
222 
TEST(DecodePackageHeaderInfo,invalidComponentBitmapBitLength)223 TEST(DecodePackageHeaderInfo, invalidComponentBitmapBitLength)
224 {
225     constexpr std::string_view packageVersionStr{"OpenBMCv1.0"};
226     constexpr size_t packageHeaderSize =
227         sizeof(pldm_package_header_information) + packageVersionStr.size();
228 
229     constexpr std::array<uint8_t, packageHeaderSize> invalidPackagerHeaderInfo{
230         0xf0, 0x18, 0x87, 0x8c, 0xcb, 0x7d, 0x49, 0x43, 0x98, 0x00, 0xa0, 0x2f,
231         0x05, 0x9a, 0xca, 0x02, 0x02, 0x2f, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
232         0x00, 0x00, 0x00, 0x19, 0x0c, 0xe5, 0x07, 0x00, 0x09, 0x00, 0x01, 0x0b,
233         0x4f, 0x70, 0x65, 0x6e, 0x42, 0x4d, 0x43, 0x76, 0x31, 0x2e, 0x30};
234 
235     pldm_package_header_information packageHeader{};
236     variable_field packageVersion{};
237     int rc = 0;
238 
239     rc = decode_pldm_package_header_info(invalidPackagerHeaderInfo.data(),
240                                          invalidPackagerHeaderInfo.size(),
241                                          &packageHeader, &packageVersion);
242     EXPECT_EQ(rc, PLDM_ERROR_INVALID_DATA);
243 }
244 
TEST(DecodeFirmwareDeviceIdRecord,goodPath)245 TEST(DecodeFirmwareDeviceIdRecord, goodPath)
246 {
247     constexpr uint8_t descriptorCount = 1;
248     // Continue component updates after failure
249     constexpr std::bitset<32> deviceUpdateFlag{1};
250     constexpr uint16_t componentBitmapBitLength = 16;
251     // Applicable Components - 1,2,5,8,9
252     std::vector<std::bitset<8>> applicableComponentsBitfield{0x93, 0x01};
253     // ComponentImageSetVersionString
254     constexpr std::string_view imageSetVersionStr{"VersionString1"};
255     // Initial descriptor - UUID
256     constexpr std::array<uint8_t, PLDM_FWUP_UUID_LENGTH> uuid{
257         0x12, 0x44, 0xd2, 0x64, 0x8d, 0x7d, 0x47, 0x18,
258         0xa0, 0x30, 0xfc, 0x8a, 0x56, 0x58, 0x7d, 0x5b};
259     constexpr uint16_t fwDevicePkgDataLen = 2;
260     // FirmwareDevicePackageData
261     constexpr std::array<uint8_t, fwDevicePkgDataLen> fwDevicePkgData{0xab,
262                                                                       0xcd};
263     // Size of the firmware device ID record
264     constexpr uint16_t recordLen =
265         sizeof(pldm_firmware_device_id_record) +
266         (componentBitmapBitLength / PLDM_FWUP_COMPONENT_BITMAP_MULTIPLE) +
267         imageSetVersionStr.size() + sizeof(pldm_descriptor_tlv) - 1 +
268         uuid.size() + fwDevicePkgData.size();
269     // Firmware device ID record
270     constexpr std::array<uint8_t, recordLen> record{
271         0x31, 0x00, 0x01, 0x01, 0x00, 0x00, 0x00, 0x01, 0x0e, 0x02,
272         0x00, 0x93, 0x01, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e,
273         0x53, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x31, 0x02, 0x00, 0x10,
274         0x00, 0x12, 0x44, 0xd2, 0x64, 0x8d, 0x7d, 0x47, 0x18, 0xa0,
275         0x30, 0xfc, 0x8a, 0x56, 0x58, 0x7d, 0x5b, 0xab, 0xcd};
276 
277     pldm_firmware_device_id_record deviceIdRecHeader{};
278     variable_field applicableComponents{};
279     variable_field outCompImageSetVersionStr{};
280     variable_field recordDescriptors{};
281     variable_field outFwDevicePkgData{};
282 
283     auto rc = decode_firmware_device_id_record(
284         record.data(), record.size(), componentBitmapBitLength,
285         &deviceIdRecHeader, &applicableComponents, &outCompImageSetVersionStr,
286         &recordDescriptors, &outFwDevicePkgData);
287 
288     EXPECT_EQ(rc, PLDM_SUCCESS);
289     EXPECT_EQ(deviceIdRecHeader.record_length, recordLen);
290     EXPECT_EQ(deviceIdRecHeader.descriptor_count, descriptorCount);
291     EXPECT_EQ(deviceIdRecHeader.device_update_option_flags.value,
292               deviceUpdateFlag);
293     EXPECT_EQ(deviceIdRecHeader.comp_image_set_version_string_type,
294               PLDM_STR_TYPE_ASCII);
295     EXPECT_EQ(deviceIdRecHeader.comp_image_set_version_string_length,
296               imageSetVersionStr.size());
297     EXPECT_EQ(deviceIdRecHeader.fw_device_pkg_data_length, fwDevicePkgDataLen);
298 
299     EXPECT_EQ(applicableComponents.length, applicableComponentsBitfield.size());
300     EXPECT_EQ(true,
301               std::equal(applicableComponents.ptr,
302                          applicableComponents.ptr + applicableComponents.length,
303                          applicableComponentsBitfield.begin(),
304                          applicableComponentsBitfield.end()));
305 
306     EXPECT_EQ(outCompImageSetVersionStr.length, imageSetVersionStr.size());
307     std::string compImageSetVersionStr(
308         // NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast)
309         reinterpret_cast<const char*>(outCompImageSetVersionStr.ptr),
310         outCompImageSetVersionStr.length);
311     EXPECT_EQ(compImageSetVersionStr, imageSetVersionStr);
312 
313     uint16_t descriptorType = 0;
314     uint16_t descriptorLen = 0;
315     variable_field descriptorData{};
316     // DescriptorCount is 1, so decode_descriptor_type_length_value called once
317     rc = decode_descriptor_type_length_value(recordDescriptors.ptr,
318                                              recordDescriptors.length,
319                                              &descriptorType, &descriptorData);
320     EXPECT_EQ(rc, PLDM_SUCCESS);
321     EXPECT_EQ(recordDescriptors.length, sizeof(descriptorType) +
322                                             sizeof(descriptorLen) +
323                                             descriptorData.length);
324     EXPECT_EQ(descriptorType, PLDM_FWUP_UUID);
325     EXPECT_EQ(descriptorData.length, PLDM_FWUP_UUID_LENGTH);
326     EXPECT_EQ(true, std::equal(descriptorData.ptr,
327                                descriptorData.ptr + descriptorData.length,
328                                uuid.begin(), uuid.end()));
329 
330     EXPECT_EQ(outFwDevicePkgData.length, fwDevicePkgData.size());
331     EXPECT_EQ(true,
332               std::equal(outFwDevicePkgData.ptr,
333                          outFwDevicePkgData.ptr + outFwDevicePkgData.length,
334                          fwDevicePkgData.begin(), fwDevicePkgData.end()));
335 }
336 
TEST(DecodeFirmwareDeviceIdRecord,goodPathNofwDevicePkgData)337 TEST(DecodeFirmwareDeviceIdRecord, goodPathNofwDevicePkgData)
338 {
339     constexpr uint8_t descriptorCount = 1;
340     // Continue component updates after failure
341     constexpr std::bitset<32> deviceUpdateFlag{1};
342     constexpr uint16_t componentBitmapBitLength = 8;
343     // Applicable Components - 1,2
344     std::vector<std::bitset<8>> applicableComponentsBitfield{0x03};
345     // ComponentImageSetVersionString
346     constexpr std::string_view imageSetVersionStr{"VersionString1"};
347     // Initial descriptor - UUID
348     constexpr std::array<uint8_t, PLDM_FWUP_UUID_LENGTH> uuid{
349         0x12, 0x44, 0xd2, 0x64, 0x8d, 0x7d, 0x47, 0x18,
350         0xa0, 0x30, 0xfc, 0x8a, 0x56, 0x58, 0x7d, 0x5b};
351     constexpr uint16_t fwDevicePkgDataLen = 0;
352 
353     // Size of the firmware device ID record
354     constexpr uint16_t recordLen =
355         sizeof(pldm_firmware_device_id_record) +
356         (componentBitmapBitLength / PLDM_FWUP_COMPONENT_BITMAP_MULTIPLE) +
357         imageSetVersionStr.size() +
358         sizeof(pldm_descriptor_tlv().descriptor_type) +
359         sizeof(pldm_descriptor_tlv().descriptor_length) + uuid.size() +
360         fwDevicePkgDataLen;
361     // Firmware device ID record
362     constexpr std::array<uint8_t, recordLen> record{
363         0x2e, 0x00, 0x01, 0x01, 0x00, 0x00, 0x00, 0x01, 0x0e, 0x00, 0x00, 0x03,
364         0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x53, 0x74, 0x72, 0x69, 0x6e,
365         0x67, 0x31, 0x02, 0x00, 0x10, 0x00, 0x12, 0x44, 0xd2, 0x64, 0x8d, 0x7d,
366         0x47, 0x18, 0xa0, 0x30, 0xfc, 0x8a, 0x56, 0x58, 0x7d, 0x5b};
367 
368     pldm_firmware_device_id_record deviceIdRecHeader{};
369     variable_field applicableComponents{};
370     variable_field outCompImageSetVersionStr{};
371     variable_field recordDescriptors{};
372     variable_field outFwDevicePkgData{};
373 
374     auto rc = decode_firmware_device_id_record(
375         record.data(), record.size(), componentBitmapBitLength,
376         &deviceIdRecHeader, &applicableComponents, &outCompImageSetVersionStr,
377         &recordDescriptors, &outFwDevicePkgData);
378 
379     EXPECT_EQ(rc, PLDM_SUCCESS);
380     EXPECT_EQ(deviceIdRecHeader.record_length, recordLen);
381     EXPECT_EQ(deviceIdRecHeader.descriptor_count, descriptorCount);
382     EXPECT_EQ(deviceIdRecHeader.device_update_option_flags.value,
383               deviceUpdateFlag);
384     EXPECT_EQ(deviceIdRecHeader.comp_image_set_version_string_type,
385               PLDM_STR_TYPE_ASCII);
386     EXPECT_EQ(deviceIdRecHeader.comp_image_set_version_string_length,
387               imageSetVersionStr.size());
388     EXPECT_EQ(deviceIdRecHeader.fw_device_pkg_data_length, 0);
389 
390     EXPECT_EQ(applicableComponents.length, applicableComponentsBitfield.size());
391     EXPECT_EQ(true,
392               std::equal(applicableComponents.ptr,
393                          applicableComponents.ptr + applicableComponents.length,
394                          applicableComponentsBitfield.begin(),
395                          applicableComponentsBitfield.end()));
396 
397     EXPECT_EQ(outCompImageSetVersionStr.length, imageSetVersionStr.size());
398     std::string compImageSetVersionStr(
399         // NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast)
400         reinterpret_cast<const char*>(outCompImageSetVersionStr.ptr),
401         outCompImageSetVersionStr.length);
402     EXPECT_EQ(compImageSetVersionStr, imageSetVersionStr);
403 
404     uint16_t descriptorType = 0;
405     uint16_t descriptorLen = 0;
406     variable_field descriptorData{};
407     // DescriptorCount is 1, so decode_descriptor_type_length_value called once
408     rc = decode_descriptor_type_length_value(recordDescriptors.ptr,
409                                              recordDescriptors.length,
410                                              &descriptorType, &descriptorData);
411     EXPECT_EQ(rc, PLDM_SUCCESS);
412     EXPECT_EQ(recordDescriptors.length, sizeof(descriptorType) +
413                                             sizeof(descriptorLen) +
414                                             descriptorData.length);
415     EXPECT_EQ(descriptorType, PLDM_FWUP_UUID);
416     EXPECT_EQ(descriptorData.length, PLDM_FWUP_UUID_LENGTH);
417     EXPECT_EQ(true, std::equal(descriptorData.ptr,
418                                descriptorData.ptr + descriptorData.length,
419                                uuid.begin(), uuid.end()));
420 
421     EXPECT_EQ(outFwDevicePkgData.ptr, nullptr);
422     EXPECT_EQ(outFwDevicePkgData.length, 0);
423 }
424 
TEST(DecodeFirmwareDeviceIdRecord,ErrorPaths)425 TEST(DecodeFirmwareDeviceIdRecord, ErrorPaths)
426 {
427     // Invalid ComponentImageSetVersionStringType
428     constexpr std::array<uint8_t, 11> rec{0x0b, 0x00, 0x01, 0x01, 0x00, 0x00,
429                                           0x00, 0x06, 0x0e, 0x00, 0x00};
430     constexpr uint16_t componentBitmapBitLength = 8;
431 
432     pldm_firmware_device_id_record deviceIdRecHeader{};
433     variable_field outCompImageSetVersionStr{};
434     variable_field applicableComponents{};
435     variable_field outFwDevicePkgData{};
436     variable_field recordDescriptors{};
437     int rc = 0;
438 
439     rc = decode_firmware_device_id_record(
440         nullptr, rec.size(), componentBitmapBitLength, &deviceIdRecHeader,
441         &applicableComponents, &outCompImageSetVersionStr, &recordDescriptors,
442         &outFwDevicePkgData);
443     EXPECT_EQ(rc, PLDM_ERROR_INVALID_DATA);
444 
445     rc = decode_firmware_device_id_record(
446         rec.data(), rec.size(), componentBitmapBitLength, nullptr,
447         &applicableComponents, &outCompImageSetVersionStr, &recordDescriptors,
448         &outFwDevicePkgData);
449     EXPECT_EQ(rc, PLDM_ERROR_INVALID_DATA);
450 
451     rc = decode_firmware_device_id_record(
452         rec.data(), rec.size(), componentBitmapBitLength, &deviceIdRecHeader,
453         nullptr, &outCompImageSetVersionStr, &recordDescriptors,
454         &outFwDevicePkgData);
455     EXPECT_EQ(rc, PLDM_ERROR_INVALID_DATA);
456 
457     rc = decode_firmware_device_id_record(
458         rec.data(), rec.size(), componentBitmapBitLength, &deviceIdRecHeader,
459         &applicableComponents, nullptr, &recordDescriptors,
460         &outFwDevicePkgData);
461     EXPECT_EQ(rc, PLDM_ERROR_INVALID_DATA);
462 
463     rc = decode_firmware_device_id_record(
464         rec.data(), rec.size(), componentBitmapBitLength, &deviceIdRecHeader,
465         &applicableComponents, &outCompImageSetVersionStr, nullptr,
466         &outFwDevicePkgData);
467     EXPECT_EQ(rc, PLDM_ERROR_INVALID_DATA);
468 
469     rc = decode_firmware_device_id_record(
470         rec.data(), rec.size(), componentBitmapBitLength, &deviceIdRecHeader,
471         &applicableComponents, &outCompImageSetVersionStr, &recordDescriptors,
472         nullptr);
473     EXPECT_EQ(rc, PLDM_ERROR_INVALID_DATA);
474 
475     rc = decode_firmware_device_id_record(
476         rec.data(), rec.size() - 1, componentBitmapBitLength,
477         &deviceIdRecHeader, &applicableComponents, &outCompImageSetVersionStr,
478         &recordDescriptors, &outFwDevicePkgData);
479     EXPECT_EQ(rc, PLDM_ERROR_INVALID_LENGTH);
480 
481     rc = decode_firmware_device_id_record(
482         rec.data(), rec.size(), componentBitmapBitLength + 1,
483         &deviceIdRecHeader, &applicableComponents, &outCompImageSetVersionStr,
484         &recordDescriptors, &outFwDevicePkgData);
485     EXPECT_EQ(rc, PLDM_ERROR_INVALID_DATA);
486 
487     rc = decode_firmware_device_id_record(
488         rec.data(), rec.size(), componentBitmapBitLength, &deviceIdRecHeader,
489         &applicableComponents, &outCompImageSetVersionStr, &recordDescriptors,
490         &outFwDevicePkgData);
491     EXPECT_EQ(rc, PLDM_ERROR_INVALID_DATA);
492 }
493 
TEST(DecodeFirmwareDeviceIdRecord,invalidComponentImageSetVersionStringLength)494 TEST(DecodeFirmwareDeviceIdRecord, invalidComponentImageSetVersionStringLength)
495 {
496     constexpr std::array<uint8_t, 11> rec{0x0b, 0x00, 0x01, 0x01, 0x00, 0x00,
497                                           0x00, 0x01, 0x00, 0x00, 0x00};
498     constexpr uint16_t componentBitmapBitLength = 8;
499 
500     int rc = 0;
501     pldm_firmware_device_id_record deviceIdRecHeader{};
502     variable_field applicableComponents{};
503     variable_field outCompImageSetVersionStr{};
504     variable_field recordDescriptors{};
505     variable_field outFwDevicePkgData{};
506 
507     rc = decode_firmware_device_id_record(
508         rec.data(), rec.size(), componentBitmapBitLength, &deviceIdRecHeader,
509         &applicableComponents, &outCompImageSetVersionStr, &recordDescriptors,
510         &outFwDevicePkgData);
511     EXPECT_EQ(rc, PLDM_ERROR_INVALID_DATA);
512 }
513 
TEST(DecodeFirmwareDeviceIdRecord,shortBuffer)514 TEST(DecodeFirmwareDeviceIdRecord, shortBuffer)
515 {
516     constexpr std::array<uint8_t, 11> rec{0x2e, 0x00, 0x01, 0x01, 0x00, 0x00,
517                                           0x00, 0x01, 0x0e, 0x00, 0x00};
518     constexpr uint16_t componentBitmapBitLength = 8;
519 
520     pldm_firmware_device_id_record deviceIdRecHeader{};
521     variable_field outCompImageSetVersionStr{};
522     variable_field applicableComponents{};
523     variable_field outFwDevicePkgData{};
524     variable_field recordDescriptors{};
525     int rc = 0;
526 
527     rc = decode_firmware_device_id_record(
528         rec.data(), rec.size(), componentBitmapBitLength, &deviceIdRecHeader,
529         &applicableComponents, &outCompImageSetVersionStr, &recordDescriptors,
530         &outFwDevicePkgData);
531     EXPECT_EQ(rc, PLDM_ERROR_INVALID_LENGTH);
532 }
533 
TEST(DecodeFirmwareDeviceIdRecord,recordLengthMismatch)534 TEST(DecodeFirmwareDeviceIdRecord, recordLengthMismatch)
535 {
536     constexpr std::array<uint8_t, 11> rec{0x15, 0x00, 0x01, 0x01, 0x00, 0x00,
537                                           0x00, 0x01, 0x0e, 0x02, 0x00};
538     constexpr uint16_t componentBitmapBitLength = 8;
539 
540     pldm_firmware_device_id_record deviceIdRecHeader{};
541     variable_field outCompImageSetVersionStr{};
542     variable_field applicableComponents{};
543     variable_field outFwDevicePkgData{};
544     variable_field recordDescriptors{};
545     int rc = 0;
546 
547     rc = decode_firmware_device_id_record(
548         rec.data(), rec.size(), componentBitmapBitLength, &deviceIdRecHeader,
549         &applicableComponents, &outCompImageSetVersionStr, &recordDescriptors,
550         &outFwDevicePkgData);
551     EXPECT_EQ(rc, PLDM_ERROR_INVALID_LENGTH);
552 }
553 
TEST(DecodeFirmwareDeviceIdRecord,invalidFirmwareDevicePackageDataLength)554 TEST(DecodeFirmwareDeviceIdRecord, invalidFirmwareDevicePackageDataLength)
555 {
556     constexpr std::array<uint8_t, 49> rec{
557         0x31, 0x00, 0x01, 0x01, 0x00, 0x00, 0x00, 0x01, 0x0e,
558         // FirmwareDevicePackageDataLength = 0xffff
559         0xff, 0xff,
560         //
561         0x93, 0x01, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x53, 0x74, 0x72,
562         0x69, 0x6e, 0x67, 0x31, 0x02, 0x00, 0x10, 0x00, 0x12, 0x44, 0xd2, 0x64,
563         0x8d, 0x7d, 0x47, 0x18, 0xa0, 0x30, 0xfc, 0x8a, 0x56, 0x58, 0x7d, 0x5b,
564         0xab, 0xcd};
565     constexpr uint16_t componentBitmapBitLength = 8;
566 
567     pldm_firmware_device_id_record deviceIdRecHeader{};
568     variable_field outCompImageSetVersionStr{};
569     variable_field applicableComponents{};
570     variable_field outFwDevicePkgData{};
571     variable_field recordDescriptors{};
572     int rc = 0;
573 
574     rc = decode_firmware_device_id_record(
575         rec.data(), rec.size(), componentBitmapBitLength, &deviceIdRecHeader,
576         &applicableComponents, &outCompImageSetVersionStr, &recordDescriptors,
577         &outFwDevicePkgData);
578     EXPECT_EQ(rc, PLDM_ERROR_INVALID_LENGTH);
579 }
580 
TEST(DecodeDescriptors,goodPath3Descriptors)581 TEST(DecodeDescriptors, goodPath3Descriptors)
582 {
583     // In the descriptor data there are 3 descriptor entries
584     // 1) IANA enterprise ID
585     constexpr std::array<uint8_t, PLDM_FWUP_IANA_ENTERPRISE_ID_LENGTH> iana{
586         0x0a, 0x0b, 0x0c, 0xd};
587     // 2) UUID
588     constexpr std::array<uint8_t, PLDM_FWUP_UUID_LENGTH> uuid{
589         0x12, 0x44, 0xd2, 0x64, 0x8d, 0x7d, 0x47, 0x18,
590         0xa0, 0x30, 0xfc, 0x8a, 0x56, 0x58, 0x7d, 0x5b};
591     // 3) Vendor Defined
592     constexpr std::string_view vendorTitle{"OpenBMC"};
593     constexpr size_t vendorDescriptorLen = 2;
594     constexpr std::array<uint8_t, vendorDescriptorLen> vendorDescriptorData{
595         0x01, 0x02};
596 
597     constexpr size_t vendorDefinedDescriptorLen =
598         sizeof(pldm_vendor_defined_descriptor_title_data()
599                    .vendor_defined_descriptor_title_str_type) +
600         sizeof(pldm_vendor_defined_descriptor_title_data()
601                    .vendor_defined_descriptor_title_str_len) +
602         vendorTitle.size() + vendorDescriptorData.size();
603 
604     constexpr size_t descriptorsLength =
605         3 * (sizeof(pldm_descriptor_tlv().descriptor_type) +
606              sizeof(pldm_descriptor_tlv().descriptor_length)) +
607         iana.size() + uuid.size() + vendorDefinedDescriptorLen;
608 
609     constexpr std::array<uint8_t, descriptorsLength> descriptors{
610         0x01, 0x00, 0x04, 0x00, 0x0a, 0x0b, 0x0c, 0x0d, 0x02, 0x00, 0x10,
611         0x00, 0x12, 0x44, 0xd2, 0x64, 0x8d, 0x7d, 0x47, 0x18, 0xa0, 0x30,
612         0xfc, 0x8a, 0x56, 0x58, 0x7d, 0x5b, 0xff, 0xff, 0x0b, 0x00, 0x01,
613         0x07, 0x4f, 0x70, 0x65, 0x6e, 0x42, 0x4d, 0x43, 0x01, 0x02};
614 
615     size_t descriptorCount = 1;
616     size_t descriptorsRemainingLength = descriptorsLength;
617     int rc = 0;
618 
619     while (descriptorsRemainingLength && (descriptorCount <= 3))
620     {
621         uint16_t descriptorType = 0;
622         uint16_t descriptorLen = 0;
623         variable_field descriptorData{};
624 
625         rc = decode_descriptor_type_length_value(
626             descriptors.data() + descriptorsLength - descriptorsRemainingLength,
627             descriptorsRemainingLength, &descriptorType, &descriptorData);
628         EXPECT_EQ(rc, PLDM_SUCCESS);
629 
630         if (descriptorCount == 1)
631         {
632             EXPECT_EQ(descriptorType, PLDM_FWUP_IANA_ENTERPRISE_ID);
633             EXPECT_EQ(descriptorData.length,
634                       PLDM_FWUP_IANA_ENTERPRISE_ID_LENGTH);
635             EXPECT_EQ(true,
636                       std::equal(descriptorData.ptr,
637                                  descriptorData.ptr + descriptorData.length,
638                                  iana.begin(), iana.end()));
639         }
640         else if (descriptorCount == 2)
641         {
642             EXPECT_EQ(descriptorType, PLDM_FWUP_UUID);
643             EXPECT_EQ(descriptorData.length, PLDM_FWUP_UUID_LENGTH);
644             EXPECT_EQ(true,
645                       std::equal(descriptorData.ptr,
646                                  descriptorData.ptr + descriptorData.length,
647                                  uuid.begin(), uuid.end()));
648         }
649         else if (descriptorCount == 3)
650         {
651             EXPECT_EQ(descriptorType, PLDM_FWUP_VENDOR_DEFINED);
652             EXPECT_EQ(descriptorData.length, vendorDefinedDescriptorLen);
653 
654             uint8_t descriptorTitleStrType = 0;
655             variable_field descriptorTitleStr{};
656             variable_field vendorDefinedDescriptorData{};
657 
658             rc = decode_vendor_defined_descriptor_value(
659                 descriptorData.ptr, descriptorData.length,
660                 &descriptorTitleStrType, &descriptorTitleStr,
661                 &vendorDefinedDescriptorData);
662             EXPECT_EQ(rc, PLDM_SUCCESS);
663 
664             EXPECT_EQ(descriptorTitleStrType, PLDM_STR_TYPE_ASCII);
665             EXPECT_EQ(descriptorTitleStr.length, vendorTitle.size());
666             std::string vendorTitleStr(
667                 // NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast)
668                 reinterpret_cast<const char*>(descriptorTitleStr.ptr),
669                 descriptorTitleStr.length);
670             EXPECT_EQ(vendorTitleStr, vendorTitle);
671 
672             EXPECT_EQ(vendorDefinedDescriptorData.length,
673                       vendorDescriptorData.size());
674             EXPECT_EQ(true, std::equal(vendorDefinedDescriptorData.ptr,
675                                        vendorDefinedDescriptorData.ptr +
676                                            vendorDefinedDescriptorData.length,
677                                        vendorDescriptorData.begin(),
678                                        vendorDescriptorData.end()));
679         }
680 
681         descriptorsRemainingLength -= sizeof(descriptorType) +
682                                       sizeof(descriptorLen) +
683                                       descriptorData.length;
684         descriptorCount++;
685     }
686 }
687 
TEST(DecodeDescriptors,errorPathDecodeDescriptorTLV)688 TEST(DecodeDescriptors, errorPathDecodeDescriptorTLV)
689 {
690     int rc = 0;
691     // IANA Enterprise ID descriptor length incorrect
692     constexpr std::array<uint8_t, 7> invalidIANADescriptor1{
693         0x01, 0x00, 0x03, 0x00, 0x0a, 0x0b, 0x0c};
694     uint16_t descriptorType = 0;
695     variable_field descriptorData{};
696 
697     rc = decode_descriptor_type_length_value(nullptr,
698                                              invalidIANADescriptor1.size(),
699                                              &descriptorType, &descriptorData);
700     EXPECT_EQ(rc, PLDM_ERROR_INVALID_DATA);
701 
702     rc = decode_descriptor_type_length_value(invalidIANADescriptor1.data(),
703                                              invalidIANADescriptor1.size(),
704                                              nullptr, &descriptorData);
705     EXPECT_EQ(rc, PLDM_ERROR_INVALID_DATA);
706 
707     rc = decode_descriptor_type_length_value(invalidIANADescriptor1.data(),
708                                              invalidIANADescriptor1.size(),
709                                              &descriptorType, nullptr);
710     EXPECT_EQ(rc, PLDM_ERROR_INVALID_DATA);
711 
712     rc = decode_descriptor_type_length_value(
713         invalidIANADescriptor1.data(), PLDM_FWUP_DEVICE_DESCRIPTOR_MIN_LEN - 1,
714         &descriptorType, &descriptorData);
715     EXPECT_EQ(rc, PLDM_ERROR_INVALID_LENGTH);
716 
717     rc = decode_descriptor_type_length_value(invalidIANADescriptor1.data(),
718                                              invalidIANADescriptor1.size(),
719                                              &descriptorType, &descriptorData);
720     EXPECT_EQ(rc, PLDM_ERROR_INVALID_DATA);
721 
722     // IANA Enterprise ID descriptor data less than length
723     std::array<uint8_t, 7> invalidIANADescriptor2{0x01, 0x00, 0x04, 0x00,
724                                                   0x0a, 0x0b, 0x0c};
725     rc = decode_descriptor_type_length_value(invalidIANADescriptor2.data(),
726                                              invalidIANADescriptor2.size(),
727                                              &descriptorType, &descriptorData);
728     EXPECT_EQ(rc, PLDM_ERROR_INVALID_LENGTH);
729 }
730 
TEST(DecodeDescriptors,errorPathVendorDefinedDescriptor)731 TEST(DecodeDescriptors, errorPathVendorDefinedDescriptor)
732 {
733     int rc = 0;
734     // VendorDefinedDescriptorTitleStringType is invalid
735     constexpr std::array<uint8_t, 9> invalidVendorDescriptor1{
736         0x06, 0x07, 0x4f, 0x70, 0x65, 0x6e, 0x42, 0x4d, 0x43};
737     uint8_t descriptorStringType = 0;
738     variable_field descriptorTitleStr{};
739     variable_field vendorDefinedDescriptorData{};
740 
741     rc = decode_vendor_defined_descriptor_value(
742         nullptr, invalidVendorDescriptor1.size(), &descriptorStringType,
743         &descriptorTitleStr, &vendorDefinedDescriptorData);
744     EXPECT_EQ(rc, PLDM_ERROR_INVALID_DATA);
745 
746     rc = decode_vendor_defined_descriptor_value(
747         invalidVendorDescriptor1.data(), invalidVendorDescriptor1.size(),
748         &descriptorStringType, &descriptorTitleStr,
749         &vendorDefinedDescriptorData);
750     EXPECT_EQ(rc, PLDM_ERROR_INVALID_DATA);
751 
752     rc = decode_vendor_defined_descriptor_value(
753         invalidVendorDescriptor1.data(), invalidVendorDescriptor1.size(),
754         nullptr, &descriptorTitleStr, &vendorDefinedDescriptorData);
755     EXPECT_EQ(rc, PLDM_ERROR_INVALID_DATA);
756 
757     rc = decode_vendor_defined_descriptor_value(
758         invalidVendorDescriptor1.data(), invalidVendorDescriptor1.size(),
759         &descriptorStringType, nullptr, &vendorDefinedDescriptorData);
760     EXPECT_EQ(rc, PLDM_ERROR_INVALID_DATA);
761 
762     rc = decode_vendor_defined_descriptor_value(
763         invalidVendorDescriptor1.data(), invalidVendorDescriptor1.size(),
764         &descriptorStringType, &descriptorTitleStr, nullptr);
765     EXPECT_EQ(rc, PLDM_ERROR_INVALID_DATA);
766 
767     rc = decode_vendor_defined_descriptor_value(
768         invalidVendorDescriptor1.data(),
769         sizeof(pldm_vendor_defined_descriptor_title_data) - 1,
770         &descriptorStringType, &descriptorTitleStr,
771         &vendorDefinedDescriptorData);
772     EXPECT_EQ(rc, PLDM_ERROR_INVALID_LENGTH);
773 
774     rc = decode_vendor_defined_descriptor_value(
775         invalidVendorDescriptor1.data(), invalidVendorDescriptor1.size(),
776         &descriptorStringType, &descriptorTitleStr,
777         &vendorDefinedDescriptorData);
778     EXPECT_EQ(rc, PLDM_ERROR_INVALID_DATA);
779 
780     // VendorDefinedDescriptorTitleStringLength is 0
781     std::array<uint8_t, 9> invalidVendorDescriptor2{
782         0x01, 0x00, 0x4f, 0x70, 0x65, 0x6e, 0x42, 0x4d, 0x43};
783     rc = decode_vendor_defined_descriptor_value(
784         invalidVendorDescriptor2.data(), invalidVendorDescriptor2.size(),
785         &descriptorStringType, &descriptorTitleStr,
786         &vendorDefinedDescriptorData);
787     EXPECT_EQ(rc, PLDM_ERROR_INVALID_DATA);
788 
789     // VendorDefinedDescriptorData not present in the data
790     std::array<uint8_t, 9> invalidVendorDescriptor3{
791         0x01, 0x07, 0x4f, 0x70, 0x65, 0x6e, 0x42, 0x4d, 0x43};
792     rc = decode_vendor_defined_descriptor_value(
793         invalidVendorDescriptor3.data(), invalidVendorDescriptor3.size(),
794         &descriptorStringType, &descriptorTitleStr,
795         &vendorDefinedDescriptorData);
796     EXPECT_EQ(rc, PLDM_ERROR_INVALID_LENGTH);
797 }
798 
TEST(DecodeComponentImageInfo,goodPath)799 TEST(DecodeComponentImageInfo, goodPath)
800 {
801     // Firmware
802     constexpr uint16_t compClassification = 16;
803     constexpr uint16_t compIdentifier = 300;
804     constexpr uint32_t compComparisonStamp = 0xffffffff;
805     // Force update
806     constexpr std::bitset<16> compOptions{1};
807     // System reboot[Bit position 3] & Medium-specific reset[Bit position 2]
808     constexpr std::bitset<16> reqCompActivationMethod{0x0c};
809     // Random ComponentLocationOffset
810     constexpr uint32_t compLocOffset = 357;
811     // Random ComponentSize
812     constexpr uint32_t compSize = 27;
813     // ComponentVersionString
814     constexpr std::string_view compVersionStr{"VersionString1"};
815     constexpr size_t compImageInfoSize =
816         sizeof(pldm_component_image_information) + compVersionStr.size();
817 
818     constexpr std::array<uint8_t, compImageInfoSize> compImageInfo{
819         0x10, 0x00, 0x2c, 0x01, 0xff, 0xff, 0xff, 0xff, 0x01, 0x00, 0x0c, 0x00,
820         0x65, 0x01, 0x00, 0x00, 0x1b, 0x00, 0x00, 0x00, 0x01, 0x0e, 0x56, 0x65,
821         0x72, 0x73, 0x69, 0x6f, 0x6e, 0x53, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x31};
822     pldm_component_image_information outCompImageInfo{};
823     variable_field outCompVersionStr{};
824 
825     auto rc =
826         decode_pldm_comp_image_info(compImageInfo.data(), compImageInfo.size(),
827                                     &outCompImageInfo, &outCompVersionStr);
828 
829     EXPECT_EQ(rc, PLDM_SUCCESS);
830     EXPECT_EQ(outCompImageInfo.comp_classification, compClassification);
831     EXPECT_EQ(outCompImageInfo.comp_identifier, compIdentifier);
832     EXPECT_EQ(outCompImageInfo.comp_comparison_stamp, compComparisonStamp);
833     EXPECT_EQ(outCompImageInfo.comp_options.value, compOptions);
834     EXPECT_EQ(outCompImageInfo.requested_comp_activation_method.value,
835               reqCompActivationMethod);
836     EXPECT_EQ(outCompImageInfo.comp_location_offset, compLocOffset);
837     EXPECT_EQ(outCompImageInfo.comp_size, compSize);
838     EXPECT_EQ(outCompImageInfo.comp_version_string_type, PLDM_STR_TYPE_ASCII);
839     EXPECT_EQ(outCompImageInfo.comp_version_string_length,
840               compVersionStr.size());
841 
842     EXPECT_EQ(outCompVersionStr.length,
843               outCompImageInfo.comp_version_string_length);
844     std::string componentVersionString(
845         // NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast)
846         reinterpret_cast<const char*>(outCompVersionStr.ptr),
847         outCompVersionStr.length);
848     EXPECT_EQ(componentVersionString, compVersionStr);
849 }
850 
TEST(DecodeComponentImageInfo,errorPaths)851 TEST(DecodeComponentImageInfo, errorPaths)
852 {
853     int rc = 0;
854     // ComponentVersionString
855     constexpr std::string_view compVersionStr{"VersionString1"};
856     constexpr size_t compImageInfoSize =
857         sizeof(pldm_component_image_information) + compVersionStr.size();
858     // Invalid ComponentVersionStringType - 0x06
859     constexpr std::array<uint8_t, compImageInfoSize> invalidCompImageInfo1{
860         0x10, 0x00, 0x2c, 0x01, 0xff, 0xff, 0xff, 0xff, 0x01, 0x00, 0x0c, 0x00,
861         0x65, 0x01, 0x00, 0x00, 0x1b, 0x00, 0x00, 0x00, 0x06, 0x0e, 0x56, 0x65,
862         0x72, 0x73, 0x69, 0x6f, 0x6e, 0x53, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x31};
863     pldm_component_image_information outCompImageInfo{};
864     variable_field outCompVersionStr{};
865 
866     rc = decode_pldm_comp_image_info(nullptr, invalidCompImageInfo1.size(),
867                                      &outCompImageInfo, &outCompVersionStr);
868     EXPECT_EQ(rc, PLDM_ERROR_INVALID_DATA);
869 
870     rc = decode_pldm_comp_image_info(invalidCompImageInfo1.data(),
871                                      invalidCompImageInfo1.size(), nullptr,
872                                      &outCompVersionStr);
873     EXPECT_EQ(rc, PLDM_ERROR_INVALID_DATA);
874 
875     rc = decode_pldm_comp_image_info(invalidCompImageInfo1.data(),
876                                      invalidCompImageInfo1.size(),
877                                      &outCompImageInfo, nullptr);
878     EXPECT_EQ(rc, PLDM_ERROR_INVALID_DATA);
879 
880     rc = decode_pldm_comp_image_info(invalidCompImageInfo1.data(),
881                                      sizeof(pldm_component_image_information) -
882                                          1,
883                                      &outCompImageInfo, &outCompVersionStr);
884     EXPECT_EQ(rc, PLDM_ERROR_INVALID_LENGTH);
885 
886     rc = decode_pldm_comp_image_info(invalidCompImageInfo1.data(),
887                                      invalidCompImageInfo1.size(),
888                                      &outCompImageInfo, &outCompVersionStr);
889     EXPECT_EQ(rc, PLDM_ERROR_INVALID_DATA);
890 
891     // Invalid ComponentVersionStringLength - 0x00
892     constexpr std::array<uint8_t, compImageInfoSize> invalidCompImageInfo2{
893         0x10, 0x00, 0x2c, 0x01, 0xff, 0xff, 0xff, 0xff, 0x01, 0x00, 0x0c, 0x00,
894         0x65, 0x01, 0x00, 0x00, 0x1b, 0x00, 0x00, 0x00, 0x01, 0x00, 0x56, 0x65,
895         0x72, 0x73, 0x69, 0x6f, 0x6e, 0x53, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x31};
896     rc = decode_pldm_comp_image_info(invalidCompImageInfo2.data(),
897                                      invalidCompImageInfo2.size(),
898                                      &outCompImageInfo, &outCompVersionStr);
899     EXPECT_EQ(rc, PLDM_ERROR_INVALID_DATA);
900 
901     // Use Component Comparison Stamp is not set, but ComponentComparisonStamp
902     // is not 0xffffffff
903     constexpr std::array<uint8_t, compImageInfoSize> invalidCompImageInfo3{
904         0x10, 0x00, 0x2c, 0x01, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x0c, 0x00,
905         0x65, 0x01, 0x00, 0x00, 0x1b, 0x00, 0x00, 0x00, 0x01, 0x0e, 0x56, 0x65,
906         0x72, 0x73, 0x69, 0x6f, 0x6e, 0x53, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x31};
907 
908     rc = decode_pldm_comp_image_info(invalidCompImageInfo3.data(),
909                                      invalidCompImageInfo3.size() - 1,
910                                      &outCompImageInfo, &outCompVersionStr);
911     EXPECT_EQ(rc, PLDM_ERROR_INVALID_LENGTH);
912 
913     rc = decode_pldm_comp_image_info(invalidCompImageInfo3.data(),
914                                      invalidCompImageInfo3.size(),
915                                      &outCompImageInfo, &outCompVersionStr);
916     EXPECT_EQ(rc, PLDM_ERROR_INVALID_DATA);
917 
918     // Invalid ComponentLocationOffset - 0
919     constexpr std::array<uint8_t, compImageInfoSize> invalidCompImageInfo4{
920         0x10, 0x00, 0x2c, 0x01, 0xff, 0xff, 0xff, 0xff, 0x01, 0x00, 0x0c, 0x00,
921         0x00, 0x00, 0x00, 0x00, 0x1b, 0x00, 0x00, 0x00, 0x01, 0x0e, 0x56, 0x65,
922         0x72, 0x73, 0x69, 0x6f, 0x6e, 0x53, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x31};
923     rc = decode_pldm_comp_image_info(invalidCompImageInfo4.data(),
924                                      invalidCompImageInfo4.size(),
925                                      &outCompImageInfo, &outCompVersionStr);
926     EXPECT_EQ(rc, PLDM_ERROR_INVALID_DATA);
927 
928     // Invalid ComponentSize - 0
929     constexpr std::array<uint8_t, compImageInfoSize> invalidCompImageInfo5{
930         0x10, 0x00, 0x2c, 0x01, 0xff, 0xff, 0xff, 0xff, 0x01, 0x00, 0x0c, 0x00,
931         0x65, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x0e, 0x56, 0x65,
932         0x72, 0x73, 0x69, 0x6f, 0x6e, 0x53, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x31};
933     rc = decode_pldm_comp_image_info(invalidCompImageInfo5.data(),
934                                      invalidCompImageInfo5.size(),
935                                      &outCompImageInfo, &outCompVersionStr);
936     EXPECT_EQ(rc, PLDM_ERROR_INVALID_DATA);
937 }
938 
TEST(QueryDeviceIdentifiers,goodPathEncodeRequest)939 TEST(QueryDeviceIdentifiers, goodPathEncodeRequest)
940 {
941     std::array<uint8_t, sizeof(pldm_msg_hdr)> requestMsg{};
942     // NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast)
943     auto requestPtr = reinterpret_cast<pldm_msg*>(requestMsg.data());
944 
945     uint8_t instanceId = 0x01;
946 
947     auto rc = encode_query_device_identifiers_req(
948         instanceId, PLDM_QUERY_DEVICE_IDENTIFIERS_REQ_BYTES, requestPtr);
949     EXPECT_EQ(rc, PLDM_SUCCESS);
950     EXPECT_EQ(requestPtr->hdr.request, PLDM_REQUEST);
951     EXPECT_EQ(requestPtr->hdr.instance_id, instanceId);
952     EXPECT_EQ(requestPtr->hdr.type, PLDM_FWUP);
953     EXPECT_EQ(requestPtr->hdr.command, PLDM_QUERY_DEVICE_IDENTIFIERS);
954 }
955 
TEST(QueryDeviceIdentifiers,goodPathDecodeResponse)956 TEST(QueryDeviceIdentifiers, goodPathDecodeResponse)
957 {
958     // descriptorDataLen is not fixed here taking it as 6
959     constexpr uint8_t descriptorDataLen = 6;
960     std::array<uint8_t, hdrSize +
961                             sizeof(struct pldm_query_device_identifiers_resp) +
962                             descriptorDataLen>
963         responseMsg{};
964     // NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast)
965     auto inResp = reinterpret_cast<struct pldm_query_device_identifiers_resp*>(
966         responseMsg.data() + hdrSize);
967 
968     inResp->completion_code = PLDM_SUCCESS;
969     inResp->device_identifiers_len = htole32(descriptorDataLen);
970     inResp->descriptor_count = 1;
971 
972     // filling descriptor data
973     std::fill_n(responseMsg.data() + hdrSize +
974                     sizeof(struct pldm_query_device_identifiers_resp),
975                 descriptorDataLen, 0xff);
976 
977     // NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast)
978     auto response = reinterpret_cast<pldm_msg*>(responseMsg.data());
979     uint8_t completionCode = PLDM_SUCCESS;
980     uint32_t deviceIdentifiersLen = 0;
981     uint8_t descriptorCount = 0;
982     uint8_t* outDescriptorData = nullptr;
983 
984     auto rc = decode_query_device_identifiers_resp(
985         response, responseMsg.size() - hdrSize, &completionCode,
986         &deviceIdentifiersLen, &descriptorCount, &outDescriptorData);
987 
988     EXPECT_EQ(rc, PLDM_SUCCESS);
989     EXPECT_EQ(completionCode, PLDM_SUCCESS);
990     EXPECT_EQ(deviceIdentifiersLen, inResp->device_identifiers_len);
991     EXPECT_EQ(descriptorCount, inResp->descriptor_count);
992     EXPECT_EQ(true,
993               std::equal(outDescriptorData,
994                          outDescriptorData + deviceIdentifiersLen,
995                          responseMsg.begin() + hdrSize +
996                              sizeof(struct pldm_query_device_identifiers_resp),
997                          responseMsg.end()));
998 }
999 
1000 #ifdef LIBPLDM_API_TESTING
TEST(QueryDeviceIdentifiers,goodPathEncodeResponse)1001 TEST(QueryDeviceIdentifiers, goodPathEncodeResponse)
1002 {
1003     int rc;
1004     PLDM_MSG_DEFINE_P(enc, 1000);
1005     size_t enc_payload_len = 1000;
1006     pldm_descriptor check_desc[] = {
1007         {
1008             .descriptor_type = PLDM_FWUP_IANA_ENTERPRISE_ID,
1009             .descriptor_length = 4,
1010             .descriptor_data = "a123",
1011         },
1012         {
1013             .descriptor_type = PLDM_FWUP_VENDOR_DEFINED,
1014             .descriptor_length = 3,
1015             .descriptor_data = "987",
1016         },
1017     };
1018     rc = encode_query_device_identifiers_resp(FIXED_INSTANCE_ID, 2, check_desc,
1019                                               enc, &enc_payload_len);
1020     EXPECT_EQ(rc, 0);
1021     EXPECT_THAT(std::span<uint8_t>(enc_buf + hdrSize, enc_payload_len),
1022                 ElementsAreArray<uint8_t>({
1023                     // completion code
1024                     0x00,
1025                     // device identifiers length = 15
1026                     0x0f,
1027                     0x00,
1028                     0x00,
1029                     0x00,
1030                     // descriptor count
1031                     0x02,
1032                     // desc 0
1033                     0x01,
1034                     0x00,
1035                     0x04,
1036                     0x00,
1037                     0x61,
1038                     0x31,
1039                     0x32,
1040                     0x33,
1041                     // desc 1
1042                     0xff,
1043                     0xff,
1044                     0x03,
1045                     0x00,
1046                     0x39,
1047                     0x38,
1048                     0x37,
1049                 }));
1050 
1051     check_response(enc, PLDM_QUERY_DEVICE_IDENTIFIERS);
1052 }
1053 #endif
1054 
TEST(GetFirmwareParameters,goodPathEncodeRequest)1055 TEST(GetFirmwareParameters, goodPathEncodeRequest)
1056 {
1057     std::array<uint8_t, sizeof(pldm_msg_hdr)> requestMsg{};
1058     // NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast)
1059     auto requestPtr = reinterpret_cast<pldm_msg*>(requestMsg.data());
1060     uint8_t instanceId = 0x01;
1061 
1062     auto rc = encode_get_firmware_parameters_req(
1063         instanceId, PLDM_GET_FIRMWARE_PARAMETERS_REQ_BYTES, requestPtr);
1064     EXPECT_EQ(rc, PLDM_SUCCESS);
1065     EXPECT_EQ(requestPtr->hdr.request, PLDM_REQUEST);
1066     EXPECT_EQ(requestPtr->hdr.instance_id, instanceId);
1067     EXPECT_EQ(requestPtr->hdr.type, PLDM_FWUP);
1068     EXPECT_EQ(requestPtr->hdr.command, PLDM_GET_FIRMWARE_PARAMETERS);
1069 }
1070 
TEST(GetFirmwareParameters,decodeResponse)1071 TEST(GetFirmwareParameters, decodeResponse)
1072 {
1073     // CapabilitiesDuringUpdate of the firmware device
1074     // Firmware device downgrade restrictions [Bit position 8] &
1075     // Firmware Device Partial Updates [Bit position 3]
1076     constexpr std::bitset<32> fdCapabilities{0x00000104};
1077     constexpr uint16_t compCount = 1;
1078     constexpr std::string_view activeCompImageSetVersion{"VersionString1"};
1079     constexpr std::string_view pendingCompImageSetVersion{"VersionString2"};
1080 
1081     // constexpr uint16_t compClassification = 16;
1082     // constexpr uint16_t compIdentifier = 300;
1083     // constexpr uint8_t compClassificationIndex = 20;
1084     // constexpr uint32_t activeCompComparisonStamp = 0xabcdefab;
1085     // constexpr std::array<uint8_t, 8> activeComponentReleaseData = {
1086     //     0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08};
1087     // constexpr uint32_t pendingCompComparisonStamp = 0x12345678;
1088     // constexpr std::array<uint8_t, 8> pendingComponentReleaseData = {
1089     //     0x08, 0x07, 0x06, 0x05, 0x04, 0x03, 0x02, 0x01};
1090     constexpr std::string_view activeCompVersion{"VersionString3"};
1091     constexpr std::string_view pendingCompVersion{"VersionString4"};
1092 
1093     constexpr size_t compParamTableSize =
1094         sizeof(pldm_component_parameter_entry) + activeCompVersion.size() +
1095         pendingCompVersion.size();
1096 
1097     constexpr std::array<uint8_t, compParamTableSize> compParamTable{
1098         0x10, 0x00, 0x2c, 0x01, 0x14, 0xab, 0xef, 0xcd, 0xab, 0x01, 0x0e, 0x01,
1099         0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x78, 0x56, 0x34, 0x12, 0x01,
1100         0x0e, 0x08, 0x07, 0x06, 0x05, 0x04, 0x03, 0x02, 0x01, 0x12, 0x00, 0x02,
1101         0x00, 0x00, 0x00, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x53, 0x74,
1102         0x72, 0x69, 0x6e, 0x67, 0x33, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e,
1103         0x53, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x34};
1104 
1105     constexpr size_t getFwParamsPayloadLen =
1106         sizeof(pldm_get_firmware_parameters_resp) +
1107         activeCompImageSetVersion.size() + pendingCompImageSetVersion.size() +
1108         compParamTableSize;
1109 
1110     constexpr std::array<uint8_t, hdrSize + getFwParamsPayloadLen>
1111         getFwParamsResponse{
1112             0x00, 0x00, 0x00, 0x00, 0x04, 0x01, 0x00, 0x00, 0x01, 0x00, 0x01,
1113             0x0e, 0x01, 0x0e, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x53,
1114             0x74, 0x72, 0x69, 0x6e, 0x67, 0x31, 0x56, 0x65, 0x72, 0x73, 0x69,
1115             0x6f, 0x6e, 0x53, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x32, 0x10, 0x00,
1116             0x2c, 0x01, 0x14, 0xab, 0xef, 0xcd, 0xab, 0x01, 0x0e, 0x01, 0x02,
1117             0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x78, 0x56, 0x34, 0x12, 0x01,
1118             0x0e, 0x08, 0x07, 0x06, 0x05, 0x04, 0x03, 0x02, 0x01, 0x12, 0x00,
1119             0x02, 0x00, 0x00, 0x00, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e,
1120             0x53, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x33, 0x56, 0x65, 0x72, 0x73,
1121             0x69, 0x6f, 0x6e, 0x53, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x34};
1122 
1123     auto responseMsg =
1124         // NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast)
1125         reinterpret_cast<const pldm_msg*>(getFwParamsResponse.data());
1126     pldm_get_firmware_parameters_resp outResp{};
1127     variable_field outActiveCompImageSetVersion{};
1128     variable_field outPendingCompImageSetVersion{};
1129     variable_field outCompParameterTable{};
1130 
1131     auto rc = decode_get_firmware_parameters_resp(
1132         responseMsg, getFwParamsPayloadLen, &outResp,
1133         &outActiveCompImageSetVersion, &outPendingCompImageSetVersion,
1134         &outCompParameterTable);
1135 
1136     EXPECT_EQ(rc, PLDM_SUCCESS);
1137     EXPECT_EQ(outResp.completion_code, PLDM_SUCCESS);
1138     EXPECT_EQ(outResp.capabilities_during_update.value, fdCapabilities);
1139     EXPECT_EQ(outResp.comp_count, compCount);
1140     EXPECT_EQ(outResp.active_comp_image_set_ver_str_type, PLDM_STR_TYPE_ASCII);
1141     EXPECT_EQ(outResp.active_comp_image_set_ver_str_len,
1142               activeCompImageSetVersion.size());
1143     EXPECT_EQ(outResp.pending_comp_image_set_ver_str_type, PLDM_STR_TYPE_ASCII);
1144     EXPECT_EQ(outResp.pending_comp_image_set_ver_str_len,
1145               pendingCompImageSetVersion.size());
1146     std::string activeCompImageSetVersionStr(
1147         // NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast)
1148         reinterpret_cast<const char*>(outActiveCompImageSetVersion.ptr),
1149         outActiveCompImageSetVersion.length);
1150     EXPECT_EQ(activeCompImageSetVersionStr, activeCompImageSetVersion);
1151     std::string pendingCompImageSetVersionStr(
1152         // NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast)
1153         reinterpret_cast<const char*>(outPendingCompImageSetVersion.ptr),
1154         outPendingCompImageSetVersion.length);
1155     EXPECT_EQ(pendingCompImageSetVersionStr, pendingCompImageSetVersion);
1156     EXPECT_EQ(outCompParameterTable.length, compParamTableSize);
1157     EXPECT_EQ(true, std::equal(outCompParameterTable.ptr,
1158                                outCompParameterTable.ptr +
1159                                    outCompParameterTable.length,
1160                                compParamTable.begin(), compParamTable.end()));
1161 }
1162 
TEST(GetFirmwareParameters,decodeResponseZeroCompCount)1163 TEST(GetFirmwareParameters, decodeResponseZeroCompCount)
1164 {
1165     // CapabilitiesDuringUpdate of the firmware device
1166     // FD Host Functionality during Firmware Update [Bit position 2] &
1167     // Component Update Failure Retry Capability [Bit position 1]
1168     constexpr std::bitset<32> fdCapabilities{0x06};
1169     constexpr uint16_t compCount = 0;
1170     constexpr std::string_view activeCompImageSetVersion{"VersionString1"};
1171     constexpr std::string_view pendingCompImageSetVersion{"VersionString2"};
1172 
1173     constexpr size_t getFwParamsPayloadLen =
1174         sizeof(pldm_get_firmware_parameters_resp) +
1175         activeCompImageSetVersion.size() + pendingCompImageSetVersion.size();
1176 
1177     constexpr std::array<uint8_t, hdrSize + getFwParamsPayloadLen>
1178         getFwParamsResponse{
1179             0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
1180             0x0e, 0x01, 0x0e, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x53,
1181             0x74, 0x72, 0x69, 0x6e, 0x67, 0x31, 0x56, 0x65, 0x72, 0x73, 0x69,
1182             0x6f, 0x6e, 0x53, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x32};
1183 
1184     auto responseMsg =
1185         // NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast)
1186         reinterpret_cast<const pldm_msg*>(getFwParamsResponse.data());
1187     pldm_get_firmware_parameters_resp outResp{};
1188     variable_field outActiveCompImageSetVersion{};
1189     variable_field outPendingCompImageSetVersion{};
1190     variable_field outCompParameterTable{};
1191 
1192     auto rc = decode_get_firmware_parameters_resp(
1193         responseMsg, getFwParamsPayloadLen, &outResp,
1194         &outActiveCompImageSetVersion, &outPendingCompImageSetVersion,
1195         &outCompParameterTable);
1196 
1197     EXPECT_EQ(rc, PLDM_SUCCESS);
1198     EXPECT_EQ(outResp.completion_code, PLDM_SUCCESS);
1199     EXPECT_EQ(outResp.capabilities_during_update.value, fdCapabilities);
1200     EXPECT_EQ(outResp.comp_count, compCount);
1201     EXPECT_EQ(outResp.active_comp_image_set_ver_str_type, PLDM_STR_TYPE_ASCII);
1202     EXPECT_EQ(outResp.active_comp_image_set_ver_str_len,
1203               activeCompImageSetVersion.size());
1204     EXPECT_EQ(outResp.pending_comp_image_set_ver_str_type, PLDM_STR_TYPE_ASCII);
1205     EXPECT_EQ(outResp.pending_comp_image_set_ver_str_len,
1206               pendingCompImageSetVersion.size());
1207     std::string activeCompImageSetVersionStr(
1208         // NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast)
1209         reinterpret_cast<const char*>(outActiveCompImageSetVersion.ptr),
1210         outActiveCompImageSetVersion.length);
1211     EXPECT_EQ(activeCompImageSetVersionStr, activeCompImageSetVersion);
1212     std::string pendingCompImageSetVersionStr(
1213         // NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast)
1214         reinterpret_cast<const char*>(outPendingCompImageSetVersion.ptr),
1215         outPendingCompImageSetVersion.length);
1216     EXPECT_EQ(pendingCompImageSetVersionStr, pendingCompImageSetVersion);
1217     EXPECT_EQ(outCompParameterTable.ptr, nullptr);
1218     EXPECT_EQ(outCompParameterTable.length, 0);
1219 }
1220 
TEST(GetFirmwareParameters,decodeResponseNoPendingCompImageVersionStrZeroCompCount)1221 TEST(GetFirmwareParameters,
1222      decodeResponseNoPendingCompImageVersionStrZeroCompCount)
1223 {
1224     // CapabilitiesDuringUpdate of the firmware device
1225     // FD Host Functionality during Firmware Update [Bit position 2] &
1226     // Component Update Failure Retry Capability [Bit position 1]
1227     constexpr std::bitset<32> fdCapabilities{0x06};
1228     constexpr uint16_t compCount = 0;
1229     constexpr std::string_view activeCompImageSetVersion{"VersionString"};
1230 
1231     constexpr size_t getFwParamsPayloadLen =
1232         sizeof(pldm_get_firmware_parameters_resp) +
1233         activeCompImageSetVersion.size();
1234 
1235     constexpr std::array<uint8_t, hdrSize + getFwParamsPayloadLen>
1236         getFwParamsResponse{0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00,
1237                             0x00, 0x00, 0x00, 0x01, 0x0d, 0x00, 0x00,
1238                             0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e,
1239                             0x53, 0x74, 0x72, 0x69, 0x6e, 0x67};
1240 
1241     auto responseMsg =
1242         // NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast)
1243         reinterpret_cast<const pldm_msg*>(getFwParamsResponse.data());
1244     pldm_get_firmware_parameters_resp outResp{};
1245     variable_field outActiveCompImageSetVersion{};
1246     variable_field outPendingCompImageSetVersion{};
1247     variable_field outCompParameterTable{};
1248 
1249     auto rc = decode_get_firmware_parameters_resp(
1250         responseMsg, getFwParamsPayloadLen, &outResp,
1251         &outActiveCompImageSetVersion, &outPendingCompImageSetVersion,
1252         &outCompParameterTable);
1253 
1254     EXPECT_EQ(rc, PLDM_SUCCESS);
1255     EXPECT_EQ(outResp.completion_code, PLDM_SUCCESS);
1256     EXPECT_EQ(outResp.capabilities_during_update.value, fdCapabilities);
1257     EXPECT_EQ(outResp.comp_count, compCount);
1258     EXPECT_EQ(outResp.active_comp_image_set_ver_str_type, PLDM_STR_TYPE_ASCII);
1259     EXPECT_EQ(outResp.active_comp_image_set_ver_str_len,
1260               activeCompImageSetVersion.size());
1261     EXPECT_EQ(outResp.pending_comp_image_set_ver_str_type,
1262               PLDM_STR_TYPE_UNKNOWN);
1263     EXPECT_EQ(outResp.pending_comp_image_set_ver_str_len, 0);
1264     std::string activeCompImageSetVersionStr(
1265         // NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast)
1266         reinterpret_cast<const char*>(outActiveCompImageSetVersion.ptr),
1267         outActiveCompImageSetVersion.length);
1268     EXPECT_EQ(activeCompImageSetVersionStr, activeCompImageSetVersion);
1269     EXPECT_EQ(outPendingCompImageSetVersion.ptr, nullptr);
1270     EXPECT_EQ(outPendingCompImageSetVersion.length, 0);
1271     EXPECT_EQ(outCompParameterTable.ptr, nullptr);
1272     EXPECT_EQ(outCompParameterTable.length, 0);
1273 }
1274 
TEST(GetFirmwareParameters,decodeResponseErrorCompletionCode)1275 TEST(GetFirmwareParameters, decodeResponseErrorCompletionCode)
1276 {
1277     constexpr std::array<uint8_t, hdrSize + sizeof(uint8_t)>
1278         getFwParamsResponse{0x00, 0x00, 0x00, 0x01};
1279 
1280     auto responseMsg =
1281         // NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast)
1282         reinterpret_cast<const pldm_msg*>(getFwParamsResponse.data());
1283     pldm_get_firmware_parameters_resp outResp{};
1284     variable_field outActiveCompImageSetVersion{};
1285     variable_field outPendingCompImageSetVersion{};
1286     variable_field outCompParameterTable{};
1287 
1288     auto rc = decode_get_firmware_parameters_resp(
1289         responseMsg, getFwParamsResponse.size(), &outResp,
1290         &outActiveCompImageSetVersion, &outPendingCompImageSetVersion,
1291         &outCompParameterTable);
1292 
1293     EXPECT_EQ(rc, PLDM_SUCCESS);
1294     EXPECT_EQ(outResp.completion_code, PLDM_ERROR);
1295 }
1296 
TEST(GetFirmwareParameters,errorPathdecodeResponse)1297 TEST(GetFirmwareParameters, errorPathdecodeResponse)
1298 {
1299     int rc = 0;
1300     // Invalid ActiveComponentImageSetVersionStringType
1301     constexpr std::array<uint8_t, 14> invalidGetFwParamsResponse1{
1302         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1303         0x00, 0x00, 0x00, 0x06, 0x0e, 0x00, 0x00};
1304 
1305     auto responseMsg =
1306         // NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast)
1307         reinterpret_cast<const pldm_msg*>(invalidGetFwParamsResponse1.data());
1308     pldm_get_firmware_parameters_resp outResp{};
1309     variable_field outActiveCompImageSetVersion{};
1310     variable_field outPendingCompImageSetVersion{};
1311     variable_field outCompParameterTable{};
1312 
1313     rc = decode_get_firmware_parameters_resp(
1314         nullptr, invalidGetFwParamsResponse1.size() - hdrSize, &outResp,
1315         &outActiveCompImageSetVersion, &outPendingCompImageSetVersion,
1316         &outCompParameterTable);
1317     EXPECT_EQ(rc, PLDM_ERROR_INVALID_DATA);
1318 
1319     rc = decode_get_firmware_parameters_resp(
1320         responseMsg, invalidGetFwParamsResponse1.size() - hdrSize, nullptr,
1321         &outActiveCompImageSetVersion, &outPendingCompImageSetVersion,
1322         &outCompParameterTable);
1323     EXPECT_EQ(rc, PLDM_ERROR_INVALID_DATA);
1324 
1325     rc = decode_get_firmware_parameters_resp(
1326         responseMsg, invalidGetFwParamsResponse1.size() - hdrSize, &outResp,
1327         nullptr, &outPendingCompImageSetVersion, &outCompParameterTable);
1328     EXPECT_EQ(rc, PLDM_ERROR_INVALID_DATA);
1329 
1330     rc = decode_get_firmware_parameters_resp(
1331         responseMsg, invalidGetFwParamsResponse1.size() - hdrSize, &outResp,
1332         &outActiveCompImageSetVersion, nullptr, &outCompParameterTable);
1333     EXPECT_EQ(rc, PLDM_ERROR_INVALID_DATA);
1334 
1335     rc = decode_get_firmware_parameters_resp(
1336         responseMsg, invalidGetFwParamsResponse1.size() - hdrSize, &outResp,
1337         &outActiveCompImageSetVersion, &outPendingCompImageSetVersion, nullptr);
1338     EXPECT_EQ(rc, PLDM_ERROR_INVALID_DATA);
1339 
1340     rc = decode_get_firmware_parameters_resp(
1341         responseMsg, 0, &outResp, &outActiveCompImageSetVersion,
1342         &outPendingCompImageSetVersion, &outCompParameterTable);
1343     EXPECT_EQ(rc, PLDM_ERROR_INVALID_DATA);
1344 
1345     rc = decode_get_firmware_parameters_resp(
1346         responseMsg, invalidGetFwParamsResponse1.size() - 1 - hdrSize, &outResp,
1347         &outActiveCompImageSetVersion, &outPendingCompImageSetVersion,
1348         &outCompParameterTable);
1349     EXPECT_EQ(rc, PLDM_ERROR_INVALID_LENGTH);
1350 
1351     rc = decode_get_firmware_parameters_resp(
1352         responseMsg, invalidGetFwParamsResponse1.size() - hdrSize, &outResp,
1353         &outActiveCompImageSetVersion, &outPendingCompImageSetVersion,
1354         &outCompParameterTable);
1355     EXPECT_EQ(rc, PLDM_ERROR_INVALID_DATA);
1356 
1357     // Invalid ActiveComponentImageSetVersionStringLength
1358     constexpr std::array<uint8_t, 14> invalidGetFwParamsResponse2{
1359         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1360         0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00};
1361     responseMsg =
1362         // NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast)
1363         reinterpret_cast<const pldm_msg*>(invalidGetFwParamsResponse2.data());
1364     rc = decode_get_firmware_parameters_resp(
1365         responseMsg, invalidGetFwParamsResponse2.size() - hdrSize, &outResp,
1366         &outActiveCompImageSetVersion, &outPendingCompImageSetVersion,
1367         &outCompParameterTable);
1368     EXPECT_EQ(rc, PLDM_ERROR_INVALID_DATA);
1369 
1370     // Invalid PendingComponentImageSetVersionStringType &
1371     // PendingComponentImageSetVersionStringLength
1372     constexpr std::array<uint8_t, 14> invalidGetFwParamsResponse3{
1373         0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00,
1374         0x00, 0x00, 0x00, 0x01, 0x0e, 0x01, 0x00};
1375     responseMsg =
1376         // NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast)
1377         reinterpret_cast<const pldm_msg*>(invalidGetFwParamsResponse3.data());
1378     rc = decode_get_firmware_parameters_resp(
1379         responseMsg, invalidGetFwParamsResponse3.size() - hdrSize, &outResp,
1380         &outActiveCompImageSetVersion, &outPendingCompImageSetVersion,
1381         &outCompParameterTable);
1382     EXPECT_EQ(rc, PLDM_ERROR_INVALID_DATA);
1383 
1384     // Invalid PendingComponentImageSetVersionStringType &
1385     // PendingComponentImageSetVersionStringLength
1386     constexpr std::array<uint8_t, 14> invalidGetFwParamsResponse4{
1387         0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00,
1388         0x00, 0x00, 0x00, 0x01, 0x0e, 0x06, 0x0e};
1389     responseMsg =
1390         // NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast)
1391         reinterpret_cast<const pldm_msg*>(invalidGetFwParamsResponse4.data());
1392     rc = decode_get_firmware_parameters_resp(
1393         responseMsg, invalidGetFwParamsResponse4.size() - hdrSize, &outResp,
1394         &outActiveCompImageSetVersion, &outPendingCompImageSetVersion,
1395         &outCompParameterTable);
1396     EXPECT_EQ(rc, PLDM_ERROR_INVALID_DATA);
1397 
1398     // Total payload length less than expected
1399     constexpr std::array<uint8_t, 14> invalidGetFwParamsResponse5{
1400         0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00,
1401         0x00, 0x00, 0x00, 0x01, 0x0e, 0x01, 0x0e};
1402     responseMsg =
1403         // NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast)
1404         reinterpret_cast<const pldm_msg*>(invalidGetFwParamsResponse5.data());
1405     rc = decode_get_firmware_parameters_resp(
1406         responseMsg, invalidGetFwParamsResponse5.size() - hdrSize, &outResp,
1407         &outActiveCompImageSetVersion, &outPendingCompImageSetVersion,
1408         &outCompParameterTable);
1409     EXPECT_EQ(rc, PLDM_ERROR_INVALID_LENGTH);
1410 }
1411 
TEST(GetFirmwareParameters,goodPathDecodeComponentParameterEntry)1412 TEST(GetFirmwareParameters, goodPathDecodeComponentParameterEntry)
1413 {
1414     // Random value for component classification
1415     constexpr uint16_t compClassification = 0x0a0b;
1416     // Random value for component classification
1417     constexpr uint16_t compIdentifier = 0x0c0d;
1418     constexpr uint16_t compClassificationIndex = 0xf;
1419     // Random value for component classification
1420     constexpr uint32_t timestamp = 0x12345678;
1421     // Random value for component activation methods
1422     constexpr uint16_t compActivationMethods = 0xbbdd;
1423     // Random value for capabilities during update
1424     constexpr uint32_t capabilitiesDuringUpdate = 0xbadbeefe;
1425 
1426     // ActiveCompImageSetVerStrLen is not fixed here taking it as 8
1427     constexpr uint8_t activeCompVerStrLen = 8;
1428     // PendingCompImageSetVerStrLen is not fixed here taking it as 8
1429     constexpr uint8_t pendingCompVerStrLen = 8;
1430     constexpr size_t entryLength =
1431         sizeof(struct pldm_component_parameter_entry) + activeCompVerStrLen +
1432         pendingCompVerStrLen;
1433     std::array<uint8_t, entryLength> entry{};
1434 
1435     auto inEntry =
1436         // NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast)
1437         reinterpret_cast<struct pldm_component_parameter_entry*>(entry.data());
1438 
1439     inEntry->comp_classification = htole16(compClassification);
1440     inEntry->comp_identifier = htole16(compIdentifier);
1441     inEntry->comp_classification_index = compClassificationIndex;
1442     inEntry->active_comp_comparison_stamp = htole32(timestamp);
1443     inEntry->active_comp_ver_str_type = 1;
1444     inEntry->active_comp_ver_str_len = activeCompVerStrLen;
1445     std::fill_n(inEntry->active_comp_release_date,
1446                 sizeof(inEntry->active_comp_release_date), 0xff);
1447     inEntry->pending_comp_comparison_stamp = htole32(timestamp);
1448     inEntry->pending_comp_ver_str_type = 1;
1449     inEntry->pending_comp_ver_str_len = pendingCompVerStrLen;
1450     std::fill_n(inEntry->pending_comp_release_date,
1451                 sizeof(inEntry->pending_comp_release_date), 0xff);
1452     inEntry->comp_activation_methods.value = htole16(compActivationMethods);
1453     inEntry->capabilities_during_update.value =
1454         htole32(capabilitiesDuringUpdate);
1455     constexpr auto activeCompVerStrPos =
1456         sizeof(struct pldm_component_parameter_entry);
1457     std::fill_n(entry.data() + activeCompVerStrPos, activeCompVerStrLen, 0xaa);
1458     constexpr auto pendingCompVerStrPos =
1459         activeCompVerStrPos + activeCompVerStrLen;
1460     std::fill_n(entry.data() + pendingCompVerStrPos, pendingCompVerStrLen,
1461                 0xbb);
1462 
1463     struct pldm_component_parameter_entry outEntry;
1464     struct variable_field outActiveCompVerStr;
1465     struct variable_field outPendingCompVerStr;
1466 
1467     auto rc = decode_get_firmware_parameters_resp_comp_entry(
1468         entry.data(), entryLength, &outEntry, &outActiveCompVerStr,
1469         &outPendingCompVerStr);
1470 
1471     EXPECT_EQ(rc, PLDM_SUCCESS);
1472 
1473     EXPECT_EQ(outEntry.comp_classification, compClassification);
1474     EXPECT_EQ(outEntry.comp_identifier, compIdentifier);
1475     EXPECT_EQ(inEntry->comp_classification_index,
1476               outEntry.comp_classification_index);
1477     EXPECT_EQ(outEntry.active_comp_comparison_stamp, timestamp);
1478     EXPECT_EQ(inEntry->active_comp_ver_str_type,
1479               outEntry.active_comp_ver_str_type);
1480     EXPECT_EQ(inEntry->active_comp_ver_str_len,
1481               outEntry.active_comp_ver_str_len);
1482     EXPECT_EQ(0, memcmp(inEntry->active_comp_release_date,
1483                         outEntry.active_comp_release_date,
1484                         sizeof(inEntry->active_comp_release_date)));
1485     EXPECT_EQ(outEntry.pending_comp_comparison_stamp, timestamp);
1486     EXPECT_EQ(inEntry->pending_comp_ver_str_type,
1487               outEntry.pending_comp_ver_str_type);
1488     EXPECT_EQ(inEntry->pending_comp_ver_str_len,
1489               outEntry.pending_comp_ver_str_len);
1490     EXPECT_EQ(0, memcmp(inEntry->pending_comp_release_date,
1491                         outEntry.pending_comp_release_date,
1492                         sizeof(inEntry->pending_comp_release_date)));
1493     EXPECT_EQ(outEntry.comp_activation_methods.value, compActivationMethods);
1494     EXPECT_EQ(outEntry.capabilities_during_update.value,
1495               capabilitiesDuringUpdate);
1496 
1497     EXPECT_EQ(0, memcmp(outActiveCompVerStr.ptr,
1498                         entry.data() + activeCompVerStrPos,
1499                         outActiveCompVerStr.length));
1500     EXPECT_EQ(0, memcmp(outPendingCompVerStr.ptr,
1501                         entry.data() + pendingCompVerStrPos,
1502                         outPendingCompVerStr.length));
1503 
1504 #ifdef LIBPLDM_API_TESTING
1505     /* Check the roundtrip matches */
1506     std::vector<uint8_t> enc_data(1000);
1507     size_t enc_payload_len = enc_data.size();
1508     struct pldm_component_parameter_entry_full entryFull = {
1509         .comp_classification = compClassification,
1510         .comp_identifier = compIdentifier,
1511         .comp_classification_index = compClassificationIndex,
1512         .active_ver =
1513             {
1514                 .comparison_stamp = 0x12345678,
1515                 .str = {.str_type = PLDM_STR_TYPE_ASCII,
1516                         .str_len = activeCompVerStrLen,
1517                         .str_data = {}},
1518                 .date = {},
1519             },
1520         .pending_ver =
1521             {
1522                 .comparison_stamp = 0x12345678,
1523                 .str = {.str_type = PLDM_STR_TYPE_ASCII,
1524                         .str_len = pendingCompVerStrLen,
1525                         .str_data = {}},
1526                 .date = {},
1527             },
1528         .comp_activation_methods = inEntry->comp_activation_methods,
1529         .capabilities_during_update = inEntry->capabilities_during_update,
1530     };
1531     // Fill strings
1532     std::fill_n(entryFull.active_ver.str.str_data, activeCompVerStrLen, 0xaa);
1533     std::fill_n(entryFull.pending_ver.str.str_data, pendingCompVerStrLen, 0xbb);
1534     std::fill_n(entryFull.active_ver.date, PLDM_FWUP_COMPONENT_RELEASE_DATA_LEN,
1535                 0xff);
1536     std::fill_n(entryFull.pending_ver.date,
1537                 PLDM_FWUP_COMPONENT_RELEASE_DATA_LEN, 0xff);
1538 
1539     rc = encode_get_firmware_parameters_resp_comp_entry(
1540         &entryFull, enc_data.data(), &enc_payload_len);
1541     EXPECT_EQ(rc, PLDM_SUCCESS);
1542     EXPECT_EQ(enc_payload_len, entryLength);
1543     EXPECT_TRUE(std::equal(entry.begin(), entry.end(), enc_data.begin()));
1544 #endif
1545 }
1546 
TEST(QueryDownstreamDevices,goodPathEncodeRequest)1547 TEST(QueryDownstreamDevices, goodPathEncodeRequest)
1548 {
1549     constexpr uint8_t instanceId = 1;
1550     std::array<uint8_t, sizeof(pldm_msg_hdr)> requestMsg{};
1551     // NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast)
1552     auto requestPtr = reinterpret_cast<pldm_msg*>(requestMsg.data());
1553 
1554     auto rc = encode_query_downstream_devices_req(instanceId, requestPtr);
1555 
1556     EXPECT_EQ(rc, 0);
1557     EXPECT_EQ(requestPtr->hdr.request, PLDM_REQUEST);
1558     EXPECT_EQ(requestPtr->hdr.instance_id, instanceId);
1559     EXPECT_EQ(requestPtr->hdr.type, PLDM_FWUP);
1560     EXPECT_EQ(requestPtr->hdr.command, PLDM_QUERY_DOWNSTREAM_DEVICES);
1561 }
1562 
TEST(QueryDownstreamDevices,encodeRequestInvalidData)1563 TEST(QueryDownstreamDevices, encodeRequestInvalidData)
1564 {
1565     constexpr uint8_t instanceId = 1;
1566 
1567     auto rc = encode_query_downstream_devices_req(instanceId, nullptr);
1568 
1569     EXPECT_EQ(rc, -EINVAL);
1570 }
1571 
TEST(QueryDownstreamDevices,goodPathDecodeResponse)1572 TEST(QueryDownstreamDevices, goodPathDecodeResponse)
1573 {
1574     uint8_t completion_code_resp = PLDM_SUCCESS;
1575     uint8_t downstream_device_update_supported_resp =
1576         PLDM_FWUP_DOWNSTREAM_DEVICE_UPDATE_SUPPORTED;
1577     uint16_t number_of_downstream_devices_resp = 1;
1578     uint16_t max_number_of_downstream_devices_resp = 1;
1579     /** Capabilities of updating downstream devices
1580      * FDP supports downstream devices dynamically attached [Bit position 0] &
1581      * FDP supports downstream devices dynamically removed [Bit position 1]
1582      */
1583     bitfield32_t capabilities_resp = {.value = 0x0002};
1584     int rc;
1585 
1586     std::array<uint8_t, hdrSize + PLDM_QUERY_DOWNSTREAM_DEVICES_RESP_BYTES>
1587         responseMsg{};
1588 
1589     PLDM_MSGBUF_DEFINE_P(buf);
1590     rc = pldm_msgbuf_init_errno(buf, 0, responseMsg.data() + hdrSize,
1591                                 responseMsg.size() - hdrSize);
1592     EXPECT_EQ(rc, 0);
1593 
1594     pldm_msgbuf_insert_uint8(buf, completion_code_resp);
1595     pldm_msgbuf_insert_uint8(buf, downstream_device_update_supported_resp);
1596     pldm_msgbuf_insert_uint16(buf, number_of_downstream_devices_resp);
1597     pldm_msgbuf_insert_uint16(buf, max_number_of_downstream_devices_resp);
1598     pldm_msgbuf_insert_uint32(buf, capabilities_resp.value);
1599     ASSERT_EQ(pldm_msgbuf_complete_consumed(buf), 0);
1600 
1601     // NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast)
1602     auto response = reinterpret_cast<pldm_msg*>(responseMsg.data());
1603     struct pldm_query_downstream_devices_resp resp_data;
1604 
1605     rc = decode_query_downstream_devices_resp(
1606         response, responseMsg.size() - hdrSize, &resp_data);
1607 
1608     EXPECT_EQ(rc, 0);
1609     EXPECT_EQ(resp_data.completion_code, completion_code_resp);
1610     EXPECT_EQ(resp_data.downstream_device_update_supported,
1611               downstream_device_update_supported_resp);
1612     EXPECT_EQ(resp_data.number_of_downstream_devices,
1613               number_of_downstream_devices_resp);
1614     EXPECT_EQ(resp_data.max_number_of_downstream_devices,
1615               max_number_of_downstream_devices_resp);
1616     EXPECT_EQ(resp_data.capabilities.value, capabilities_resp.value);
1617 }
1618 
TEST(QueryDownstreamDevices,decodeRequestUndefinedValue)1619 TEST(QueryDownstreamDevices, decodeRequestUndefinedValue)
1620 {
1621     uint8_t completion_code_resp = PLDM_SUCCESS;
1622     uint8_t downstream_device_update_supported_resp = 0xe; /*Undefined value*/
1623     uint16_t number_of_downstream_devices_resp = 1;
1624     uint16_t max_number_of_downstream_devices_resp = 1;
1625     /** Capabilities of updating downstream devices
1626      * FDP supports downstream devices dynamically attached [Bit position 0] &
1627      * FDP supports downstream devices dynamically removed [Bit position 1]
1628      */
1629     bitfield32_t capabilities_resp = {.value = 0x0002};
1630     int rc;
1631 
1632     std::array<uint8_t, hdrSize + PLDM_QUERY_DOWNSTREAM_DEVICES_RESP_BYTES>
1633         responseMsg{};
1634 
1635     PLDM_MSGBUF_DEFINE_P(buf);
1636     rc = pldm_msgbuf_init_errno(buf, 0, responseMsg.data() + hdrSize,
1637                                 responseMsg.size() - hdrSize);
1638     ASSERT_EQ(rc, 0);
1639     pldm_msgbuf_insert_uint8(buf, completion_code_resp);
1640     pldm_msgbuf_insert_uint8(buf, downstream_device_update_supported_resp);
1641     pldm_msgbuf_insert_uint16(buf, number_of_downstream_devices_resp);
1642     pldm_msgbuf_insert_uint16(buf, max_number_of_downstream_devices_resp);
1643     pldm_msgbuf_insert_uint32(buf, capabilities_resp.value);
1644     ASSERT_EQ(pldm_msgbuf_complete_consumed(buf), 0);
1645 
1646     // NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast)
1647     auto response = reinterpret_cast<pldm_msg*>(responseMsg.data());
1648     struct pldm_query_downstream_devices_resp resp_data;
1649 
1650     rc = decode_query_downstream_devices_resp(
1651         response, responseMsg.size() - hdrSize, &resp_data);
1652 
1653     ASSERT_EQ(rc, -EINVAL);
1654 }
1655 
TEST(QueryDownstreamDevices,decodeRequestErrorBufSize)1656 TEST(QueryDownstreamDevices, decodeRequestErrorBufSize)
1657 {
1658     uint8_t completion_code_resp = PLDM_SUCCESS;
1659     uint8_t downstream_device_update_supported_resp =
1660         PLDM_FWUP_DOWNSTREAM_DEVICE_UPDATE_SUPPORTED;
1661     uint16_t number_of_downstream_devices_resp = 1;
1662     uint16_t max_number_of_downstream_devices_resp = 1;
1663     /** Capabilities of updating downstream devices
1664      * FDP supports downstream devices dynamically attached [Bit position 0] &
1665      * FDP supports downstream devices dynamically removed [Bit position 1]
1666      */
1667     bitfield32_t capabilities_resp = {.value = 0x0002};
1668     int rc;
1669 
1670     std::array<uint8_t, hdrSize + PLDM_QUERY_DOWNSTREAM_DEVICES_RESP_BYTES -
1671                             2 /* Inject error length*/>
1672         responseMsg{};
1673 
1674     PLDM_MSGBUF_DEFINE_P(buf);
1675     rc = pldm_msgbuf_init_errno(buf, 0, responseMsg.data() + hdrSize,
1676                                 responseMsg.size() - hdrSize);
1677     ASSERT_EQ(rc, 0);
1678 
1679     pldm_msgbuf_insert_uint8(buf, completion_code_resp);
1680     pldm_msgbuf_insert_uint8(buf, downstream_device_update_supported_resp);
1681     pldm_msgbuf_insert_uint16(buf, number_of_downstream_devices_resp);
1682     pldm_msgbuf_insert_uint16(buf, max_number_of_downstream_devices_resp);
1683     // Inject error value
1684     pldm_msgbuf_insert_uint16(buf, (uint16_t)capabilities_resp.value);
1685     ASSERT_EQ(pldm_msgbuf_complete_consumed(buf), 0);
1686 
1687     // NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast)
1688     auto response = reinterpret_cast<pldm_msg*>(responseMsg.data());
1689     struct pldm_query_downstream_devices_resp resp_data;
1690 
1691     rc = decode_query_downstream_devices_resp(
1692         response, responseMsg.size() - hdrSize, &resp_data);
1693 
1694     EXPECT_EQ(rc, -EBADMSG);
1695 }
1696 
TEST(QueryDownstreamIdentifiers,goodPathEncodeRequest)1697 TEST(QueryDownstreamIdentifiers, goodPathEncodeRequest)
1698 {
1699     constexpr uint8_t instanceId = 1;
1700     constexpr size_t payloadLen = PLDM_QUERY_DOWNSTREAM_IDENTIFIERS_REQ_BYTES;
1701     PLDM_MSG_DEFINE_P(request, payloadLen);
1702     constexpr pldm_query_downstream_identifiers_req params_req{
1703         0xFFFFFFFF, PLDM_GET_FIRSTPART};
1704 
1705     auto rc = encode_query_downstream_identifiers_req(instanceId, &params_req,
1706                                                       request, payloadLen);
1707     ASSERT_EQ(rc, 0);
1708     EXPECT_THAT(std::span<uint8_t>(request_buf, sizeof(request_buf)),
1709                 ElementsAreArray<uint8_t>(
1710                     {0x81, 0x05, 0x04, 0xFF, 0xFF, 0xFF, 0xFF, 0x01}));
1711 }
1712 
TEST(QueryDownstreamIdentifiers,encodeRequestInvalidErrorPaths)1713 TEST(QueryDownstreamIdentifiers, encodeRequestInvalidErrorPaths)
1714 {
1715     constexpr uint8_t instanceId = 1;
1716     constexpr pldm_query_downstream_identifiers_req params_req{
1717         0xFFFFFFFF, PLDM_GET_FIRSTPART};
1718     constexpr pldm_query_downstream_identifiers_req params_req_invalid{
1719         0xFFFFFFFF, PLDM_ACKNOWLEDGEMENT_ONLY};
1720     constexpr size_t payload_length =
1721         PLDM_QUERY_DOWNSTREAM_IDENTIFIERS_REQ_BYTES;
1722     std::array<uint8_t, hdrSize + payload_length> requestMsg{};
1723     // NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast)
1724     auto requestPtr = reinterpret_cast<pldm_msg*>(requestMsg.data());
1725 
1726     auto rc = encode_query_downstream_identifiers_req(instanceId, &params_req,
1727                                                       nullptr, payload_length);
1728     EXPECT_EQ(rc, -EINVAL);
1729 
1730     rc = encode_query_downstream_identifiers_req(
1731         instanceId, &params_req, requestPtr, payload_length - 1);
1732     EXPECT_EQ(rc, -EOVERFLOW);
1733 
1734     rc = encode_query_downstream_identifiers_req(
1735         instanceId, &params_req_invalid, requestPtr, payload_length);
1736     EXPECT_EQ(rc, -EINVAL);
1737 }
1738 
TEST(QueryDownstreamIdentifiers,decodeResponseNoDevices)1739 TEST(QueryDownstreamIdentifiers, decodeResponseNoDevices)
1740 {
1741     constexpr uint8_t completion_code_resp = PLDM_SUCCESS;
1742     constexpr uint32_t next_data_transfer_handle_resp = 0x0;
1743     constexpr uint8_t transfer_flag_resp = PLDM_START_AND_END;
1744     constexpr uint32_t downstream_devices_length_resp = 0;
1745     constexpr uint16_t number_of_downstream_devices_resp = 0;
1746 
1747     PLDM_MSG_DEFINE_P(response, PLDM_QUERY_DOWNSTREAM_IDENTIFIERS_RESP_MIN_LEN);
1748     struct pldm_query_downstream_identifiers_resp resp_data = {};
1749     struct pldm_downstream_device_iter devs;
1750     PLDM_MSGBUF_DEFINE_P(buf);
1751     int rc = 0;
1752 
1753     rc = pldm_msgbuf_init_errno(buf, 0, response->payload,
1754                                 PLDM_QUERY_DOWNSTREAM_IDENTIFIERS_RESP_MIN_LEN);
1755     ASSERT_EQ(rc, 0);
1756 
1757     pldm_msgbuf_insert_uint8(buf, completion_code_resp);
1758     pldm_msgbuf_insert_uint32(buf, next_data_transfer_handle_resp);
1759     pldm_msgbuf_insert_uint8(buf, transfer_flag_resp);
1760     pldm_msgbuf_insert_uint32(buf, downstream_devices_length_resp);
1761     pldm_msgbuf_insert_uint16(buf, number_of_downstream_devices_resp);
1762 
1763     ASSERT_EQ(pldm_msgbuf_complete_consumed(buf), 0);
1764 
1765     rc = decode_query_downstream_identifiers_resp(
1766         response, PLDM_QUERY_DOWNSTREAM_IDENTIFIERS_RESP_MIN_LEN, &resp_data,
1767         &devs);
1768 
1769     ASSERT_EQ(rc, 0);
1770     EXPECT_EQ(resp_data.completion_code, completion_code_resp);
1771     EXPECT_EQ(resp_data.next_data_transfer_handle,
1772               next_data_transfer_handle_resp);
1773     EXPECT_EQ(resp_data.transfer_flag, transfer_flag_resp);
1774     EXPECT_EQ(resp_data.downstream_devices_length,
1775               downstream_devices_length_resp);
1776     EXPECT_EQ(resp_data.number_of_downstream_devices,
1777               number_of_downstream_devices_resp);
1778 }
1779 
TEST(QueryDownstreamIdentifiers,decodeResponseNoDevicesBadCount)1780 TEST(QueryDownstreamIdentifiers, decodeResponseNoDevicesBadCount)
1781 {
1782     constexpr uint8_t completion_code_resp = PLDM_SUCCESS;
1783     constexpr uint32_t next_data_transfer_handle_resp = 0x0;
1784     constexpr uint8_t transfer_flag_resp = PLDM_START_AND_END;
1785     constexpr uint32_t downstream_devices_length_resp = 0;
1786     constexpr uint16_t number_of_downstream_devices_resp = 1;
1787 
1788     PLDM_MSG_DEFINE_P(response, PLDM_QUERY_DOWNSTREAM_IDENTIFIERS_RESP_MIN_LEN);
1789     struct pldm_query_downstream_identifiers_resp resp = {};
1790     struct pldm_downstream_device_iter devs;
1791     struct pldm_downstream_device dev;
1792     PLDM_MSGBUF_DEFINE_P(buf);
1793     int rc = 0;
1794 
1795     rc = pldm_msgbuf_init_errno(buf, 0, response->payload,
1796                                 PLDM_QUERY_DOWNSTREAM_IDENTIFIERS_RESP_MIN_LEN);
1797     ASSERT_EQ(rc, 0);
1798 
1799     pldm_msgbuf_insert_uint8(buf, completion_code_resp);
1800     pldm_msgbuf_insert_uint32(buf, next_data_transfer_handle_resp);
1801     pldm_msgbuf_insert_uint8(buf, transfer_flag_resp);
1802     pldm_msgbuf_insert_uint32(buf, downstream_devices_length_resp);
1803     pldm_msgbuf_insert_uint16(buf, number_of_downstream_devices_resp);
1804 
1805     ASSERT_EQ(pldm_msgbuf_complete_consumed(buf), 0);
1806 
1807     rc = decode_query_downstream_identifiers_resp(
1808         response, PLDM_QUERY_DOWNSTREAM_IDENTIFIERS_RESP_MIN_LEN, &resp, &devs);
1809     ASSERT_EQ(rc, 0);
1810 
1811     foreach_pldm_downstream_device(devs, dev, rc)
1812     {
1813         FAIL();
1814     }
1815     ASSERT_NE(rc, 0);
1816 }
1817 
TEST(QueryDownstreamIdentifiers,decodeResponseOneDeviceOneDescriptor)1818 TEST(QueryDownstreamIdentifiers, decodeResponseOneDeviceOneDescriptor)
1819 {
1820     constexpr uint32_t downstreamDevicesLen = 11;
1821     constexpr uint8_t completion_code_resp = PLDM_SUCCESS;
1822     constexpr uint32_t next_data_transfer_handle_resp = 0x0;
1823     constexpr uint8_t transfer_flag_resp = PLDM_START_AND_END;
1824     const uint32_t downstream_devices_length_resp =
1825         htole32(downstreamDevicesLen);
1826     constexpr uint16_t number_of_downstream_devices_resp = 1;
1827     constexpr size_t payloadLen =
1828         PLDM_QUERY_DOWNSTREAM_IDENTIFIERS_RESP_MIN_LEN + downstreamDevicesLen;
1829 
1830     struct pldm_query_downstream_identifiers_resp resp_data = {};
1831     PLDM_MSG_DEFINE_P(response, payloadLen);
1832     struct pldm_downstream_device_iter devs;
1833     struct pldm_downstream_device dev;
1834     PLDM_MSGBUF_DEFINE_P(buf);
1835     int rc = 0;
1836 
1837     rc = pldm_msgbuf_init_errno(buf, 0, response->payload, payloadLen);
1838     ASSERT_EQ(rc, 0);
1839 
1840     pldm_msgbuf_insert_uint8(buf, completion_code_resp);
1841     pldm_msgbuf_insert_uint32(buf, next_data_transfer_handle_resp);
1842     pldm_msgbuf_insert_uint8(buf, transfer_flag_resp);
1843     pldm_msgbuf_insert_uint32(buf, downstream_devices_length_resp);
1844     pldm_msgbuf_insert_uint16(buf, number_of_downstream_devices_resp);
1845 
1846     /* Downstream device */
1847     pldm_msgbuf_insert_uint16(buf, 1);
1848     pldm_msgbuf_insert_uint8(buf, 1);
1849 
1850     /* Device descriptor */
1851     pldm_msgbuf_insert_uint16(buf, 1);
1852     pldm_msgbuf_insert_uint16(buf, 4);
1853     pldm_msgbuf_insert_uint32(buf, 412);
1854 
1855     ASSERT_EQ(pldm_msgbuf_complete_consumed(buf), 0);
1856 
1857     rc = decode_query_downstream_identifiers_resp(response, payloadLen,
1858                                                   &resp_data, &devs);
1859 
1860     ASSERT_EQ(rc, 0);
1861     EXPECT_EQ(resp_data.completion_code, completion_code_resp);
1862     EXPECT_EQ(resp_data.next_data_transfer_handle,
1863               next_data_transfer_handle_resp);
1864     EXPECT_EQ(resp_data.transfer_flag, transfer_flag_resp);
1865     EXPECT_EQ(resp_data.downstream_devices_length,
1866               downstream_devices_length_resp);
1867     EXPECT_EQ(resp_data.number_of_downstream_devices,
1868               number_of_downstream_devices_resp);
1869 
1870     foreach_pldm_downstream_device(devs, dev, rc)
1871     {
1872         struct pldm_descriptor desc;
1873 
1874         EXPECT_EQ(dev.downstream_device_index, 1);
1875         EXPECT_EQ(dev.downstream_descriptor_count, 1);
1876 
1877         foreach_pldm_downstream_device_descriptor(devs, dev, desc, rc)
1878         {
1879             static const uint32_t dmtf = htole32(412);
1880             EXPECT_EQ(desc.descriptor_type, 1);
1881             EXPECT_EQ(desc.descriptor_length, 4);
1882             EXPECT_EQ(memcmp(desc.descriptor_data, &dmtf, sizeof(dmtf)), 0);
1883         }
1884         ASSERT_EQ(rc, 0);
1885     }
1886     ASSERT_EQ(rc, 0);
1887 }
1888 
1889 constexpr const uint16_t descriptor_id_type_iana_pen = 0x1;
1890 constexpr const uint16_t descriptor_id_len_iana_pen = 0x4;
1891 const uint32_t iana_pen_openbmc = htole16(49871u);
1892 const uint32_t iana_pen_dmtf = htole16(412u);
1893 
TEST(QueryDownstreamIdentifiers,decodeResponseTwoDevicesOneDescriptorEach)1894 TEST(QueryDownstreamIdentifiers, decodeResponseTwoDevicesOneDescriptorEach)
1895 {
1896     constexpr const std::array<pldm_downstream_device, 2> expected_devices = {{
1897         {0, 1},
1898         {1, 1},
1899     }};
1900 
1901     constexpr const std::array<pldm_descriptor, 2> expected_descriptors = {{
1902         {descriptor_id_type_iana_pen, descriptor_id_len_iana_pen,
1903          &iana_pen_dmtf},
1904         {descriptor_id_type_iana_pen, descriptor_id_len_iana_pen,
1905          &iana_pen_openbmc},
1906     }};
1907 
1908     constexpr uint32_t downstream_devices_len = 22;
1909     constexpr uint8_t completion_code_resp = PLDM_SUCCESS;
1910     constexpr uint32_t next_data_transfer_handle_resp = 0x0;
1911     constexpr uint8_t transfer_flag_resp = PLDM_START_AND_END;
1912     const uint32_t downstream_devices_length_resp =
1913         htole32(downstream_devices_len);
1914     constexpr uint16_t number_of_downstream_devices_resp = 2;
1915     constexpr size_t payloadLen =
1916         PLDM_QUERY_DOWNSTREAM_IDENTIFIERS_RESP_MIN_LEN + downstream_devices_len;
1917 
1918     struct pldm_query_downstream_identifiers_resp resp_data{};
1919     PLDM_MSG_DEFINE_P(response, payloadLen);
1920     struct pldm_downstream_device_iter devs;
1921     struct pldm_downstream_device dev;
1922     PLDM_MSGBUF_DEFINE_P(buf);
1923     int rc = 0;
1924 
1925     rc = pldm_msgbuf_init_errno(buf, 0, response->payload, payloadLen);
1926     ASSERT_EQ(rc, 0);
1927 
1928     pldm_msgbuf_insert_uint8(buf, completion_code_resp);
1929     pldm_msgbuf_insert_uint32(buf, next_data_transfer_handle_resp);
1930     pldm_msgbuf_insert_uint8(buf, transfer_flag_resp);
1931     pldm_msgbuf_insert_uint32(buf, downstream_devices_length_resp);
1932     pldm_msgbuf_insert_uint16(buf, number_of_downstream_devices_resp);
1933 
1934     /* Downstream device */
1935     pldm_msgbuf_insert_uint16(buf, 0);
1936     pldm_msgbuf_insert_uint8(buf, 1);
1937 
1938     /* Device descriptor */
1939     pldm_msgbuf_insert_uint16(buf, descriptor_id_type_iana_pen);
1940     pldm_msgbuf_insert_uint16(buf, descriptor_id_len_iana_pen);
1941     pldm_msgbuf_insert_uint32(buf, iana_pen_dmtf);
1942 
1943     /* Downstream device */
1944     pldm_msgbuf_insert_uint16(buf, 1);
1945     pldm_msgbuf_insert_uint8(buf, 1);
1946 
1947     /* Device descriptor */
1948     pldm_msgbuf_insert_uint16(buf, descriptor_id_type_iana_pen);
1949     pldm_msgbuf_insert_uint16(buf, descriptor_id_len_iana_pen);
1950     pldm_msgbuf_insert_uint32(buf, iana_pen_openbmc);
1951 
1952     ASSERT_EQ(pldm_msgbuf_complete_consumed(buf), 0);
1953 
1954     rc = decode_query_downstream_identifiers_resp(response, payloadLen,
1955                                                   &resp_data, &devs);
1956 
1957     ASSERT_EQ(rc, 0);
1958     EXPECT_EQ(resp_data.number_of_downstream_devices,
1959               number_of_downstream_devices_resp);
1960 
1961     size_t devIndex = 0;
1962     size_t descIndex = 0;
1963     foreach_pldm_downstream_device(devs, dev, rc)
1964     {
1965         struct pldm_descriptor desc;
1966 
1967         ASSERT_LT(devIndex, expected_devices.size());
1968 
1969         const struct pldm_downstream_device* expectedDev =
1970             &expected_devices[devIndex];
1971 
1972         EXPECT_EQ(dev.downstream_device_index,
1973                   expectedDev->downstream_device_index);
1974         EXPECT_EQ(dev.downstream_descriptor_count,
1975                   expectedDev->downstream_descriptor_count);
1976 
1977         foreach_pldm_downstream_device_descriptor(devs, dev, desc, rc)
1978         {
1979             ASSERT_LT(descIndex, expected_descriptors.size());
1980 
1981             const struct pldm_descriptor* expectedDesc =
1982                 &expected_descriptors[descIndex];
1983 
1984             EXPECT_EQ(desc.descriptor_type, expectedDesc->descriptor_type);
1985             ASSERT_EQ(desc.descriptor_length, expectedDesc->descriptor_length);
1986             EXPECT_EQ(memcmp(desc.descriptor_data,
1987                              expectedDesc->descriptor_data,
1988                              expectedDesc->descriptor_length),
1989                       0);
1990 
1991             descIndex++;
1992         }
1993         ASSERT_EQ(rc, 0);
1994         EXPECT_EQ(descIndex, 1 * devIndex + 1);
1995 
1996         devIndex++;
1997     }
1998     ASSERT_EQ(rc, 0);
1999     EXPECT_EQ(devIndex, 2);
2000 }
2001 
TEST(QueryDownstreamIdentifiers,decodeResponseTwoDevicesTwoOneDescriptors)2002 TEST(QueryDownstreamIdentifiers, decodeResponseTwoDevicesTwoOneDescriptors)
2003 {
2004     constexpr const std::array<pldm_downstream_device, 2> expected_devices = {{
2005         {0, 2},
2006         {1, 1},
2007     }};
2008 
2009     constexpr const std::array<pldm_descriptor, 3> expected_descriptors = {{
2010         {descriptor_id_type_iana_pen, descriptor_id_len_iana_pen,
2011          &iana_pen_dmtf},
2012         {descriptor_id_type_iana_pen, descriptor_id_len_iana_pen,
2013          &iana_pen_openbmc},
2014         {descriptor_id_type_iana_pen, descriptor_id_len_iana_pen,
2015          &iana_pen_dmtf},
2016     }};
2017 
2018     constexpr uint32_t downstream_devices_len = 30;
2019     constexpr uint8_t completion_code_resp = PLDM_SUCCESS;
2020     constexpr uint32_t next_data_transfer_handle_resp = 0x0;
2021     constexpr uint8_t transfer_flag_resp = PLDM_START_AND_END;
2022     const uint32_t downstream_devices_length_resp =
2023         htole32(downstream_devices_len);
2024     constexpr uint16_t number_of_downstream_devices_resp = 2;
2025     constexpr size_t payloadLen =
2026         PLDM_QUERY_DOWNSTREAM_IDENTIFIERS_RESP_MIN_LEN + downstream_devices_len;
2027 
2028     struct pldm_query_downstream_identifiers_resp resp_data{};
2029     PLDM_MSG_DEFINE_P(response, payloadLen);
2030     struct pldm_downstream_device_iter devs;
2031     struct pldm_downstream_device dev;
2032     PLDM_MSGBUF_DEFINE_P(buf);
2033     int rc = 0;
2034 
2035     rc = pldm_msgbuf_init_errno(buf, 0, response->payload, payloadLen);
2036     ASSERT_EQ(rc, 0);
2037 
2038     pldm_msgbuf_insert_uint8(buf, completion_code_resp);
2039     pldm_msgbuf_insert_uint32(buf, next_data_transfer_handle_resp);
2040     pldm_msgbuf_insert_uint8(buf, transfer_flag_resp);
2041     pldm_msgbuf_insert_uint32(buf, downstream_devices_length_resp);
2042     pldm_msgbuf_insert_uint16(buf, number_of_downstream_devices_resp);
2043 
2044     /* Downstream device */
2045     pldm_msgbuf_insert_uint16(buf, 0);
2046     pldm_msgbuf_insert_uint8(buf, 2);
2047 
2048     /* Device descriptor */
2049     pldm_msgbuf_insert_uint16(buf, descriptor_id_type_iana_pen);
2050     pldm_msgbuf_insert_uint16(buf, descriptor_id_len_iana_pen);
2051     pldm_msgbuf_insert_uint32(buf, iana_pen_dmtf);
2052 
2053     /* Device descriptor */
2054     pldm_msgbuf_insert_uint16(buf, descriptor_id_type_iana_pen);
2055     pldm_msgbuf_insert_uint16(buf, descriptor_id_len_iana_pen);
2056     pldm_msgbuf_insert_uint32(buf, iana_pen_openbmc);
2057 
2058     /* Downstream device */
2059     pldm_msgbuf_insert_uint16(buf, 1);
2060     pldm_msgbuf_insert_uint8(buf, 1);
2061 
2062     /* Device descriptor */
2063     pldm_msgbuf_insert_uint16(buf, descriptor_id_type_iana_pen);
2064     pldm_msgbuf_insert_uint16(buf, descriptor_id_len_iana_pen);
2065     pldm_msgbuf_insert_uint32(buf, iana_pen_dmtf);
2066 
2067     ASSERT_EQ(pldm_msgbuf_complete_consumed(buf), 0);
2068 
2069     rc = decode_query_downstream_identifiers_resp(response, payloadLen,
2070                                                   &resp_data, &devs);
2071 
2072     ASSERT_EQ(rc, 0);
2073     EXPECT_EQ(resp_data.number_of_downstream_devices,
2074               number_of_downstream_devices_resp);
2075 
2076     size_t devIndex = 0;
2077     size_t descIndex = 0;
2078     foreach_pldm_downstream_device(devs, dev, rc)
2079     {
2080         struct pldm_descriptor desc;
2081 
2082         ASSERT_LT(devIndex, expected_devices.size());
2083 
2084         const struct pldm_downstream_device* expectedDev =
2085             &expected_devices[devIndex];
2086 
2087         EXPECT_EQ(dev.downstream_device_index,
2088                   expectedDev->downstream_device_index);
2089         EXPECT_EQ(dev.downstream_descriptor_count,
2090                   expectedDev->downstream_descriptor_count);
2091 
2092         foreach_pldm_downstream_device_descriptor(devs, dev, desc, rc)
2093         {
2094             ASSERT_LT(descIndex, expected_descriptors.size());
2095 
2096             const struct pldm_descriptor* expectedDesc =
2097                 &expected_descriptors[descIndex];
2098 
2099             EXPECT_EQ(desc.descriptor_type, expectedDesc->descriptor_type);
2100             ASSERT_EQ(desc.descriptor_length, expectedDesc->descriptor_length);
2101             EXPECT_EQ(memcmp(desc.descriptor_data,
2102                              expectedDesc->descriptor_data,
2103                              expectedDesc->descriptor_length),
2104                       0);
2105 
2106             descIndex++;
2107         }
2108         ASSERT_EQ(rc, 0);
2109 
2110         devIndex++;
2111     }
2112     ASSERT_EQ(rc, 0);
2113     EXPECT_EQ(devIndex, 2);
2114     EXPECT_EQ(descIndex, 3);
2115 }
2116 
TEST(QueryDownstreamIdentifiers,decodeResponseTwoDevicesOneTwoDescriptors)2117 TEST(QueryDownstreamIdentifiers, decodeResponseTwoDevicesOneTwoDescriptors)
2118 {
2119     constexpr const std::array<pldm_downstream_device, 2> expected_devices = {{
2120         {0, 1},
2121         {1, 2},
2122     }};
2123 
2124     constexpr const std::array<pldm_descriptor, 3> expected_descriptors = {{
2125         {descriptor_id_type_iana_pen, descriptor_id_len_iana_pen,
2126          &iana_pen_dmtf},
2127         {descriptor_id_type_iana_pen, descriptor_id_len_iana_pen,
2128          &iana_pen_openbmc},
2129         {descriptor_id_type_iana_pen, descriptor_id_len_iana_pen,
2130          &iana_pen_dmtf},
2131     }};
2132 
2133     constexpr uint32_t downstream_devices_len = 30;
2134     constexpr uint8_t completion_code_resp = PLDM_SUCCESS;
2135     constexpr uint32_t next_data_transfer_handle_resp = 0x0;
2136     constexpr uint8_t transfer_flag_resp = PLDM_START_AND_END;
2137     const uint32_t downstream_devices_length_resp =
2138         htole32(downstream_devices_len);
2139     constexpr uint16_t number_of_downstream_devices_resp = 2;
2140     constexpr size_t payloadLen =
2141         PLDM_QUERY_DOWNSTREAM_IDENTIFIERS_RESP_MIN_LEN + downstream_devices_len;
2142 
2143     struct pldm_query_downstream_identifiers_resp resp_data{};
2144     PLDM_MSG_DEFINE_P(response, payloadLen);
2145     struct pldm_downstream_device_iter devs;
2146     struct pldm_downstream_device dev;
2147     PLDM_MSGBUF_DEFINE_P(buf);
2148     int rc = 0;
2149 
2150     rc = pldm_msgbuf_init_errno(buf, 0, response->payload, payloadLen);
2151     ASSERT_EQ(rc, 0);
2152 
2153     pldm_msgbuf_insert_uint8(buf, completion_code_resp);
2154     pldm_msgbuf_insert_uint32(buf, next_data_transfer_handle_resp);
2155     pldm_msgbuf_insert_uint8(buf, transfer_flag_resp);
2156     pldm_msgbuf_insert_uint32(buf, downstream_devices_length_resp);
2157     pldm_msgbuf_insert_uint16(buf, number_of_downstream_devices_resp);
2158 
2159     /* Downstream device */
2160     pldm_msgbuf_insert_uint16(buf, 0);
2161     pldm_msgbuf_insert_uint8(buf, 1);
2162 
2163     /* Device descriptor */
2164     pldm_msgbuf_insert_uint16(buf, descriptor_id_type_iana_pen);
2165     pldm_msgbuf_insert_uint16(buf, descriptor_id_len_iana_pen);
2166     pldm_msgbuf_insert_uint32(buf, iana_pen_dmtf);
2167 
2168     /* Downstream device */
2169     pldm_msgbuf_insert_uint16(buf, 1);
2170     pldm_msgbuf_insert_uint8(buf, 2);
2171 
2172     /* Device descriptor */
2173     pldm_msgbuf_insert_uint16(buf, descriptor_id_type_iana_pen);
2174     pldm_msgbuf_insert_uint16(buf, descriptor_id_len_iana_pen);
2175     pldm_msgbuf_insert_uint32(buf, iana_pen_openbmc);
2176 
2177     /* Device descriptor */
2178     pldm_msgbuf_insert_uint16(buf, descriptor_id_type_iana_pen);
2179     pldm_msgbuf_insert_uint16(buf, descriptor_id_len_iana_pen);
2180     pldm_msgbuf_insert_uint32(buf, iana_pen_dmtf);
2181 
2182     ASSERT_EQ(pldm_msgbuf_complete_consumed(buf), 0);
2183 
2184     rc = decode_query_downstream_identifiers_resp(response, payloadLen,
2185                                                   &resp_data, &devs);
2186 
2187     ASSERT_EQ(rc, 0);
2188     EXPECT_EQ(resp_data.number_of_downstream_devices,
2189               number_of_downstream_devices_resp);
2190 
2191     size_t devIndex = 0;
2192     size_t descIndex = 0;
2193     foreach_pldm_downstream_device(devs, dev, rc)
2194     {
2195         struct pldm_descriptor desc;
2196 
2197         ASSERT_LT(devIndex, expected_devices.size());
2198 
2199         const struct pldm_downstream_device* expectedDev =
2200             &expected_devices[devIndex];
2201 
2202         EXPECT_EQ(dev.downstream_device_index,
2203                   expectedDev->downstream_device_index);
2204         EXPECT_EQ(dev.downstream_descriptor_count,
2205                   expectedDev->downstream_descriptor_count);
2206 
2207         foreach_pldm_downstream_device_descriptor(devs, dev, desc, rc)
2208         {
2209             ASSERT_LT(descIndex, expected_descriptors.size());
2210 
2211             const struct pldm_descriptor* expectedDesc =
2212                 &expected_descriptors[descIndex];
2213 
2214             EXPECT_EQ(desc.descriptor_type, expectedDesc->descriptor_type);
2215             ASSERT_EQ(desc.descriptor_length, expectedDesc->descriptor_length);
2216             EXPECT_EQ(memcmp(desc.descriptor_data,
2217                              expectedDesc->descriptor_data,
2218                              expectedDesc->descriptor_length),
2219                       0);
2220 
2221             descIndex++;
2222         }
2223         ASSERT_EQ(rc, 0);
2224 
2225         devIndex++;
2226     }
2227     ASSERT_EQ(rc, 0);
2228     EXPECT_EQ(devIndex, 2);
2229     EXPECT_EQ(descIndex, 3);
2230 }
2231 
TEST(QueryDownstreamIdentifiers,decodeRequestErrorPaths)2232 TEST(QueryDownstreamIdentifiers, decodeRequestErrorPaths)
2233 {
2234     constexpr size_t payloadLen = sizeof(uint8_t);
2235 
2236     struct pldm_query_downstream_identifiers_resp resp_data = {};
2237     struct pldm_downstream_device_iter devs;
2238     PLDM_MSG_DEFINE_P(response, payloadLen);
2239 
2240     // Test nullptr
2241     auto rc = decode_query_downstream_identifiers_resp(nullptr, payloadLen,
2242                                                        nullptr, &devs);
2243     EXPECT_EQ(rc, -EINVAL);
2244 
2245     // Test not PLDM_SUCCESS completion code
2246     response->payload[0] = PLDM_ERROR_UNSUPPORTED_PLDM_CMD;
2247     rc = decode_query_downstream_identifiers_resp(response, payloadLen,
2248                                                   &resp_data, &devs);
2249     EXPECT_EQ(rc, 0);
2250     EXPECT_EQ(resp_data.completion_code, PLDM_ERROR_UNSUPPORTED_PLDM_CMD);
2251 
2252     // Test payload length less than minimum length
2253     response->payload[0] = PLDM_SUCCESS;
2254     rc = decode_query_downstream_identifiers_resp(response, payloadLen,
2255                                                   &resp_data, &devs);
2256 
2257     EXPECT_EQ(rc, -EBADMSG);
2258 }
2259 
TEST(QueryDownstreamIdentifiers,decodeRequestErrorDownstreamDevicesSize)2260 TEST(QueryDownstreamIdentifiers, decodeRequestErrorDownstreamDevicesSize)
2261 {
2262     // Len is not fixed here taking it as 9, contains 1 downstream device with
2263     // 1 descriptor
2264     constexpr uint32_t actualDownstreamDevicesLen = 9;
2265     constexpr uint8_t complition_code_resp = PLDM_SUCCESS;
2266     constexpr uint32_t next_data_transfer_handle_resp = 0x0;
2267     constexpr uint8_t transfer_flag_resp = PLDM_START_AND_END;
2268     constexpr uint16_t number_of_downstream_devices_resp = 1;
2269     constexpr size_t payloadLen =
2270         PLDM_QUERY_DOWNSTREAM_IDENTIFIERS_RESP_MIN_LEN +
2271         actualDownstreamDevicesLen;
2272 
2273     const uint32_t downstream_devices_length_resp =
2274         htole32(actualDownstreamDevicesLen + 1 /* inject error length*/);
2275 
2276     struct pldm_query_downstream_identifiers_resp resp_data = {};
2277     struct pldm_downstream_device_iter devs;
2278     PLDM_MSG_DEFINE_P(response, payloadLen);
2279     PLDM_MSGBUF_DEFINE_P(buf);
2280     void* devicesStart = NULL;
2281     size_t devicesLen;
2282     int rc = 0;
2283 
2284     rc = pldm_msgbuf_init_errno(buf, 0, response->payload, payloadLen);
2285     ASSERT_EQ(rc, 0);
2286 
2287     pldm_msgbuf_insert_uint8(buf, complition_code_resp);
2288     pldm_msgbuf_insert_uint32(buf, next_data_transfer_handle_resp);
2289     pldm_msgbuf_insert_uint8(buf, transfer_flag_resp);
2290     pldm_msgbuf_insert_uint32(buf, downstream_devices_length_resp);
2291     pldm_msgbuf_insert_uint16(buf, number_of_downstream_devices_resp);
2292     pldm_msgbuf_span_remaining(buf, &devicesStart, &devicesLen);
2293 
2294     ASSERT_EQ(0, pldm_msgbuf_complete(buf));
2295 
2296     /** Filling descriptor data, the correctness of the downstream devices data
2297      *  is not checked in this test case so filling with 0xff
2298      */
2299     std::fill_n(static_cast<uint8_t*>(devicesStart), actualDownstreamDevicesLen,
2300                 0xff);
2301 
2302     EXPECT_NE(decode_query_downstream_identifiers_resp(response, payloadLen,
2303                                                        &resp_data, &devs),
2304               0);
2305 }
2306 
TEST(QueryDownstreamIdentifiers,decodeRequestErrorBufSize)2307 TEST(QueryDownstreamIdentifiers, decodeRequestErrorBufSize)
2308 {
2309     constexpr uint32_t actualDownstreamDevicesLen = 0;
2310     constexpr uint16_t number_of_downstream_devices_resp = 1;
2311     constexpr uint8_t complition_code_resp = PLDM_SUCCESS;
2312     constexpr uint32_t next_data_transfer_handle_resp = 0x0;
2313     constexpr uint8_t transfer_flag_resp = PLDM_START_AND_END;
2314     constexpr size_t payloadLen =
2315         PLDM_QUERY_DOWNSTREAM_IDENTIFIERS_RESP_MIN_LEN - 1;
2316 
2317     const uint32_t downstream_devices_length_resp =
2318         htole32(actualDownstreamDevicesLen);
2319 
2320     struct pldm_query_downstream_identifiers_resp resp_data = {};
2321     struct pldm_downstream_device_iter devs;
2322     PLDM_MSG_DEFINE_P(response, payloadLen);
2323     PLDM_MSGBUF_DEFINE_P(buf);
2324     int rc = 0;
2325 
2326     rc = pldm_msgbuf_init_errno(buf, 0, response->payload, payloadLen);
2327     ASSERT_EQ(rc, 0);
2328 
2329     pldm_msgbuf_insert_uint8(buf, complition_code_resp);
2330     pldm_msgbuf_insert_uint32(buf, next_data_transfer_handle_resp);
2331     pldm_msgbuf_insert_uint8(buf, transfer_flag_resp);
2332     pldm_msgbuf_insert_uint32(buf, downstream_devices_length_resp);
2333     // Inject error buffer size
2334     pldm_msgbuf_insert_uint8(buf, (uint8_t)number_of_downstream_devices_resp);
2335     ASSERT_EQ(pldm_msgbuf_complete_consumed(buf), 0);
2336 
2337     rc = decode_query_downstream_identifiers_resp(response, payloadLen,
2338                                                   &resp_data, &devs);
2339 
2340     EXPECT_EQ(rc, -EBADMSG);
2341 }
2342 
TEST(GetDownstreamFirmwareParameters,goodPathEncodeRequest)2343 TEST(GetDownstreamFirmwareParameters, goodPathEncodeRequest)
2344 {
2345     constexpr uint8_t instanceId = 1;
2346     constexpr pldm_get_downstream_firmware_parameters_req params_req{
2347         0x0, PLDM_GET_FIRSTPART};
2348     constexpr size_t payload_length =
2349         PLDM_GET_DOWNSTREAM_FIRMWARE_PARAMETERS_REQ_BYTES;
2350     std::array<uint8_t, sizeof(pldm_msg_hdr) + payload_length> requestMsg{};
2351     // NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast)
2352     auto requestPtr = reinterpret_cast<pldm_msg*>(requestMsg.data());
2353 
2354     auto rc = encode_get_downstream_firmware_parameters_req(
2355         instanceId, &params_req, requestPtr, payload_length);
2356     EXPECT_EQ(rc, 0);
2357 
2358     std::array<uint8_t,
2359                hdrSize + PLDM_GET_DOWNSTREAM_FIRMWARE_PARAMETERS_REQ_BYTES>
2360         expectedReq{0x81, 0x05, 0x05, 0x00, 0x00, 0x00, 0x00, 0x01};
2361     EXPECT_EQ(requestMsg, expectedReq);
2362 }
2363 
TEST(GetDownstreamFirmwareParameters,encodeRequestInvalidTransferOperationFlag)2364 TEST(GetDownstreamFirmwareParameters, encodeRequestInvalidTransferOperationFlag)
2365 {
2366     constexpr uint8_t instanceId = 1;
2367     // Setup invalid transfer operation flag
2368     constexpr pldm_get_downstream_firmware_parameters_req params_req{
2369         0x0, PLDM_ACKNOWLEDGEMENT_ONLY};
2370     constexpr size_t payload_length =
2371         PLDM_GET_DOWNSTREAM_FIRMWARE_PARAMETERS_REQ_BYTES;
2372     std::array<uint8_t, sizeof(pldm_msg_hdr) + payload_length> requestMsg{};
2373     // NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast)
2374     auto requestPtr = reinterpret_cast<pldm_msg*>(requestMsg.data());
2375 
2376     auto rc = encode_get_downstream_firmware_parameters_req(
2377         instanceId, &params_req, requestPtr, payload_length);
2378     EXPECT_EQ(rc, -EBADMSG);
2379 }
2380 
TEST(GetDownstreamFirmwareParameters,encodeRequestErrorBufSize)2381 TEST(GetDownstreamFirmwareParameters, encodeRequestErrorBufSize)
2382 {
2383     constexpr uint8_t instanceId = 1;
2384     // Setup invalid transfer operation flag
2385     constexpr pldm_get_downstream_firmware_parameters_req params_req{
2386         0x0, PLDM_GET_FIRSTPART};
2387     constexpr size_t payload_length =
2388         PLDM_GET_DOWNSTREAM_FIRMWARE_PARAMETERS_REQ_BYTES -
2389         1 /* inject erro length*/;
2390 
2391     std::array<uint8_t, sizeof(pldm_msg_hdr) + payload_length> requestMsg{};
2392     // NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast)
2393     auto requestPtr = reinterpret_cast<pldm_msg*>(requestMsg.data());
2394 
2395     auto rc = encode_get_downstream_firmware_parameters_req(
2396         instanceId, &params_req, requestPtr, payload_length);
2397     EXPECT_EQ(rc, -EOVERFLOW);
2398 }
2399 
TEST(GetDownstreamFirmwareParameters,goodPathDecodeResponseOneEntry)2400 TEST(GetDownstreamFirmwareParameters, goodPathDecodeResponseOneEntry)
2401 {
2402     constexpr uint16_t downstreamDeviceCount = 1;
2403     constexpr uint8_t activeComponentVersionStringLength = 8;
2404     constexpr uint8_t pendingComponentVersionStringLength = 8;
2405     constexpr size_t downstreamDeviceParamTableLen =
2406         PLDM_DOWNSTREAM_DEVICE_PARAMETERS_ENTRY_MIN_LEN +
2407         activeComponentVersionStringLength +
2408         pendingComponentVersionStringLength;
2409     constexpr uint8_t completion_code_resp = PLDM_SUCCESS;
2410     constexpr uint32_t next_data_transfer_handle_resp = 0x0;
2411     constexpr uint8_t transfer_flag_resp = PLDM_START_AND_END;
2412     constexpr bitfield32_t fdp_capabilities_during_update = {.value = 0x0002};
2413     constexpr size_t payload_len =
2414         PLDM_GET_DOWNSTREAM_FIRMWARE_PARAMETERS_RESP_MIN_LEN +
2415         downstreamDeviceParamTableLen;
2416 
2417     PLDM_MSG_DEFINE_P(response, payload_len);
2418     PLDM_MSGBUF_DEFINE_P(buf);
2419     int rc = 0;
2420 
2421     rc = pldm_msgbuf_init_errno(buf, 0, response->payload, payload_len);
2422     ASSERT_EQ(rc, 0);
2423 
2424     // Table 24
2425     pldm_msgbuf_insert_uint8(buf, completion_code_resp);
2426     pldm_msgbuf_insert_uint32(buf, next_data_transfer_handle_resp);
2427     pldm_msgbuf_insert_uint8(buf, transfer_flag_resp);
2428 
2429     // Table 25
2430     pldm_msgbuf_insert_uint32(buf, fdp_capabilities_during_update.value);
2431     pldm_msgbuf_insert_uint16(buf, downstreamDeviceCount);
2432 
2433     // Table 26
2434     pldm_msgbuf_insert_uint16(buf, 0);
2435 
2436     // - Active metadata
2437     pldm_msgbuf_insert_uint32(buf, 0);
2438     pldm_msgbuf_insert_uint8(buf, 1);
2439     pldm_msgbuf_insert_uint8(buf, activeComponentVersionStringLength);
2440     rc = pldm__msgbuf_insert_array_void(buf, 8, "20241206", 8);
2441     ASSERT_EQ(rc, 0);
2442 
2443     // - Pending metadata
2444     pldm_msgbuf_insert_uint32(buf, 0);
2445     pldm_msgbuf_insert_uint8(buf, 1);
2446     pldm_msgbuf_insert_uint8(buf, pendingComponentVersionStringLength);
2447     rc = pldm__msgbuf_insert_array_void(buf, 8, "20241206", 8);
2448     ASSERT_EQ(rc, 0);
2449 
2450     // - Methods and capabilities
2451     pldm_msgbuf_insert_uint16(buf, 1);
2452     pldm_msgbuf_insert_uint32(buf, 0);
2453 
2454     // - Version strings
2455     rc = pldm__msgbuf_insert_array_void(buf, activeComponentVersionStringLength,
2456                                         "abcdefgh", 8);
2457     ASSERT_EQ(rc, 0);
2458     rc = pldm__msgbuf_insert_array_void(
2459         buf, pendingComponentVersionStringLength, "zyxwvuts", 8);
2460     ASSERT_EQ(rc, 0);
2461 
2462     rc = pldm_msgbuf_complete_consumed(buf);
2463     ASSERT_EQ(rc, 0);
2464 
2465     struct pldm_get_downstream_firmware_parameters_resp resp_data = {};
2466     struct pldm_downstream_device_parameters_iter iter = {};
2467 
2468     rc = decode_get_downstream_firmware_parameters_resp(response, payload_len,
2469                                                         &resp_data, &iter);
2470 
2471     ASSERT_EQ(rc, 0);
2472     EXPECT_EQ(resp_data.completion_code, completion_code_resp);
2473     EXPECT_EQ(resp_data.next_data_transfer_handle,
2474               next_data_transfer_handle_resp);
2475     EXPECT_EQ(resp_data.transfer_flag, transfer_flag_resp);
2476     EXPECT_EQ(resp_data.downstream_device_count, downstreamDeviceCount);
2477 
2478     struct pldm_downstream_device_parameters_entry entry;
2479     size_t entries = 0;
2480     foreach_pldm_downstream_device_parameters_entry(iter, entry, rc)
2481     {
2482         EXPECT_EQ(entry.downstream_device_index, 0);
2483         EXPECT_EQ(entry.active_comp_comparison_stamp, 0);
2484         EXPECT_EQ(entry.active_comp_ver_str_type, 1);
2485         EXPECT_EQ(entry.active_comp_ver_str_len,
2486                   activeComponentVersionStringLength);
2487         EXPECT_STREQ("20241206", entry.active_comp_release_date);
2488         EXPECT_EQ(entry.pending_comp_comparison_stamp, 0);
2489         EXPECT_EQ(entry.pending_comp_ver_str_type, 1);
2490         EXPECT_EQ(entry.pending_comp_ver_str_len,
2491                   pendingComponentVersionStringLength);
2492         EXPECT_STREQ("20241206", entry.pending_comp_release_date);
2493         EXPECT_EQ(entry.comp_activation_methods.value, 1);
2494         EXPECT_EQ(entry.capabilities_during_update.value, 0);
2495         EXPECT_FALSE(memcmp("abcdefgh", entry.active_comp_ver_str,
2496                             entry.active_comp_ver_str_len));
2497         EXPECT_FALSE(memcmp("zyxwvuts", entry.pending_comp_ver_str,
2498                             entry.pending_comp_ver_str_len));
2499         entries++;
2500     }
2501     EXPECT_EQ(rc, 0);
2502     EXPECT_EQ(entries, 1);
2503 }
2504 
TEST(GetDownstreamFirmwareParameters,goodPathDecodeResponseTwoEntries)2505 TEST(GetDownstreamFirmwareParameters, goodPathDecodeResponseTwoEntries)
2506 {
2507     /** Count is not fixed here taking it as 1, and the downstream device's
2508      *  version strings length are set to 8
2509      */
2510     constexpr uint16_t downstreamDeviceCount = 2;
2511     constexpr uint8_t activeComponentVersionStringLength = 8;
2512     constexpr uint8_t pendingComponentVersionStringLength = 9;
2513     constexpr size_t downstreamDeviceParamTableLen =
2514         static_cast<size_t>(downstreamDeviceCount *
2515                             (PLDM_DOWNSTREAM_DEVICE_PARAMETERS_ENTRY_MIN_LEN +
2516                              activeComponentVersionStringLength +
2517                              pendingComponentVersionStringLength));
2518     constexpr uint8_t completion_code_resp = PLDM_SUCCESS;
2519     constexpr uint32_t next_data_transfer_handle_resp = 0x0;
2520     constexpr uint8_t transfer_flag_resp = PLDM_START_AND_END;
2521     constexpr bitfield32_t fdp_capabilities_during_update = {.value = 0x0002};
2522     constexpr size_t payload_len =
2523         PLDM_GET_DOWNSTREAM_FIRMWARE_PARAMETERS_RESP_MIN_LEN +
2524         downstreamDeviceParamTableLen;
2525 
2526     PLDM_MSG_DEFINE_P(response, payload_len);
2527     PLDM_MSGBUF_DEFINE_P(buf);
2528     int rc = 0;
2529 
2530     rc = pldm_msgbuf_init_errno(buf, 0, response->payload, payload_len);
2531     ASSERT_EQ(rc, 0);
2532 
2533     // Table 24
2534     pldm_msgbuf_insert_uint8(buf, completion_code_resp);
2535     pldm_msgbuf_insert_uint32(buf, next_data_transfer_handle_resp);
2536     pldm_msgbuf_insert_uint8(buf, transfer_flag_resp);
2537 
2538     // Table 25
2539     pldm_msgbuf_insert_uint32(buf, fdp_capabilities_during_update.value);
2540     pldm_msgbuf_insert_uint16(buf, downstreamDeviceCount);
2541 
2542     constexpr const std::array<pldm_downstream_device_parameters_entry, 2>
2543         table = {{{
2544                       0,
2545                       0,
2546                       1,
2547                       8,
2548                       "20241206",
2549                       0,
2550                       1,
2551                       9,
2552                       "20241209",
2553                       {1},
2554                       {0},
2555                       "active_0",
2556                       "pending_0",
2557                   },
2558                   {
2559                       1,
2560                       0,
2561                       1,
2562                       8,
2563                       "20241209",
2564                       0,
2565                       1,
2566                       9,
2567                       "20241206",
2568                       {1},
2569                       {0},
2570                       "active_1",
2571                       "pending_1",
2572                   }}};
2573     for (const auto& e : table)
2574     {
2575         // Table 26
2576         pldm_msgbuf_insert_uint16(buf, e.downstream_device_index);
2577 
2578         // - Active metadata
2579         pldm_msgbuf_insert_uint32(buf, e.active_comp_comparison_stamp);
2580         pldm_msgbuf_insert_uint8(buf, e.active_comp_ver_str_type);
2581         pldm_msgbuf_insert_uint8(buf, e.active_comp_ver_str_len);
2582         rc = pldm__msgbuf_insert_array_void(buf, 8, &e.active_comp_release_date,
2583                                             sizeof(e.active_comp_release_date));
2584         ASSERT_EQ(rc, 0);
2585 
2586         // - Pending metadata
2587         pldm_msgbuf_insert_uint32(buf, e.pending_comp_comparison_stamp);
2588         pldm_msgbuf_insert_uint8(buf, e.pending_comp_ver_str_type);
2589         pldm_msgbuf_insert_uint8(buf, e.pending_comp_ver_str_len);
2590         rc =
2591             pldm__msgbuf_insert_array_void(buf, 8, e.pending_comp_release_date,
2592                                            sizeof(e.pending_comp_release_date));
2593         ASSERT_EQ(rc, 0);
2594 
2595         // - Methods and capabilities
2596         pldm_msgbuf_insert_uint16(buf, e.comp_activation_methods.value);
2597         pldm_msgbuf_insert_uint32(buf, e.capabilities_during_update.value);
2598 
2599         // - Version strings
2600         rc = pldm__msgbuf_insert_array_void(buf, e.active_comp_ver_str_len,
2601                                             e.active_comp_ver_str,
2602                                             e.active_comp_ver_str_len);
2603         ASSERT_EQ(rc, 0);
2604         rc = pldm__msgbuf_insert_array_void(buf, e.pending_comp_ver_str_len,
2605                                             e.pending_comp_ver_str,
2606                                             e.pending_comp_ver_str_len);
2607         ASSERT_EQ(rc, 0);
2608     }
2609 
2610     rc = pldm_msgbuf_complete_consumed(buf);
2611     ASSERT_EQ(rc, 0);
2612 
2613     struct pldm_get_downstream_firmware_parameters_resp resp_data = {};
2614     struct pldm_downstream_device_parameters_iter iter = {};
2615 
2616     rc = decode_get_downstream_firmware_parameters_resp(response, payload_len,
2617                                                         &resp_data, &iter);
2618 
2619     ASSERT_EQ(rc, 0);
2620     EXPECT_EQ(resp_data.completion_code, completion_code_resp);
2621     EXPECT_EQ(resp_data.next_data_transfer_handle,
2622               next_data_transfer_handle_resp);
2623     EXPECT_EQ(resp_data.transfer_flag, transfer_flag_resp);
2624     EXPECT_EQ(resp_data.downstream_device_count, downstreamDeviceCount);
2625 
2626     struct pldm_downstream_device_parameters_entry entry;
2627     size_t entryIndex = 0;
2628     foreach_pldm_downstream_device_parameters_entry(iter, entry, rc)
2629     {
2630         ASSERT_LE(entryIndex, table.size());
2631 
2632         EXPECT_EQ(table[entryIndex].downstream_device_index,
2633                   entry.downstream_device_index);
2634         EXPECT_EQ(table[entryIndex].active_comp_comparison_stamp,
2635                   entry.active_comp_comparison_stamp);
2636         EXPECT_EQ(table[entryIndex].active_comp_ver_str_type,
2637                   entry.active_comp_ver_str_type);
2638         EXPECT_EQ(table[entryIndex].active_comp_ver_str_len,
2639                   entry.active_comp_ver_str_len);
2640         EXPECT_STREQ(&table[entryIndex].active_comp_release_date[0],
2641                      &entry.active_comp_release_date[0]);
2642         EXPECT_EQ(table[entryIndex].pending_comp_comparison_stamp,
2643                   entry.pending_comp_comparison_stamp);
2644         EXPECT_EQ(table[entryIndex].pending_comp_ver_str_type,
2645                   entry.pending_comp_ver_str_type);
2646         EXPECT_EQ(table[entryIndex].pending_comp_ver_str_len,
2647                   entry.pending_comp_ver_str_len);
2648         EXPECT_STREQ(&table[entryIndex].pending_comp_release_date[0],
2649                      &entry.pending_comp_release_date[0]);
2650         EXPECT_EQ(table[entryIndex].comp_activation_methods.value,
2651                   entry.comp_activation_methods.value);
2652         EXPECT_EQ(table[entryIndex].capabilities_during_update.value,
2653                   entry.capabilities_during_update.value);
2654         EXPECT_FALSE(memcmp(table[entryIndex].active_comp_ver_str,
2655                             entry.active_comp_ver_str,
2656                             table[entryIndex].active_comp_ver_str_len));
2657         EXPECT_FALSE(memcmp(table[entryIndex].pending_comp_ver_str,
2658                             entry.pending_comp_ver_str,
2659                             table[entryIndex].pending_comp_ver_str_len));
2660         entryIndex++;
2661     }
2662     EXPECT_EQ(rc, 0);
2663     EXPECT_EQ(entryIndex, table.size());
2664 }
2665 
TEST(GetDownstreamFirmwareParameters,decodeResponseInvalidLength)2666 TEST(GetDownstreamFirmwareParameters, decodeResponseInvalidLength)
2667 {
2668     /** Count is not fixed here taking it as 1, and the downstream device's
2669      *  version strings length are set to 8
2670      */
2671     constexpr uint16_t downstreamDeviceCount = 1;
2672     constexpr uint8_t activeComponentVersionStringLength = 8;
2673     constexpr uint8_t pendingComponentVersionStringLength = 8;
2674     constexpr size_t downstreamDeviceParamTableLen =
2675         PLDM_DOWNSTREAM_DEVICE_PARAMETERS_ENTRY_MIN_LEN +
2676         activeComponentVersionStringLength +
2677         pendingComponentVersionStringLength;
2678     constexpr uint8_t complition_code_resp = PLDM_SUCCESS;
2679     constexpr uint32_t next_data_transfer_handle_resp = 0x0;
2680     constexpr uint8_t transfer_flag_resp = PLDM_START_AND_END;
2681     constexpr bitfield32_t fdp_capabilities_during_update = {.value = 0x0002};
2682 
2683     std::array<uint8_t,
2684                hdrSize + PLDM_GET_DOWNSTREAM_FIRMWARE_PARAMETERS_RESP_MIN_LEN +
2685                    downstreamDeviceParamTableLen - 1 /* inject error length*/>
2686         responseMsg{};
2687 
2688     int rc = 0;
2689 
2690     PLDM_MSGBUF_DEFINE_P(buf);
2691     rc = pldm_msgbuf_init_errno(buf, 0, responseMsg.data() + hdrSize,
2692                                 responseMsg.size() - hdrSize);
2693     ASSERT_EQ(rc, 0);
2694 
2695     pldm_msgbuf_insert_uint8(buf, complition_code_resp);
2696     pldm_msgbuf_insert_uint32(buf, next_data_transfer_handle_resp);
2697     pldm_msgbuf_insert_uint8(buf, transfer_flag_resp);
2698     pldm_msgbuf_insert_uint32(buf, fdp_capabilities_during_update.value);
2699     pldm_msgbuf_insert_uint16(buf, downstreamDeviceCount);
2700     ASSERT_EQ(pldm_msgbuf_complete(buf), 0);
2701 
2702     /** Filling paramter table, the correctness of the downstream devices data
2703      *  is not checked in this test case so filling with 0xff
2704      */
2705     std::fill_n(responseMsg.data() + hdrSize +
2706                     PLDM_GET_DOWNSTREAM_FIRMWARE_PARAMETERS_RESP_MIN_LEN,
2707                 downstreamDeviceParamTableLen - 1 /* inject error length*/,
2708                 0xff);
2709 
2710     // NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast)
2711     auto response = reinterpret_cast<pldm_msg*>(responseMsg.data());
2712     struct pldm_get_downstream_firmware_parameters_resp resp_data = {};
2713     struct pldm_downstream_device_parameters_iter iter;
2714 
2715     rc = decode_get_downstream_firmware_parameters_resp(
2716         response, responseMsg.size() - hdrSize, &resp_data, &iter);
2717     EXPECT_EQ(rc, 0);
2718 
2719     struct pldm_downstream_device_parameters_entry entry;
2720     foreach_pldm_downstream_device_parameters_entry(iter, entry, rc)
2721     {
2722         FAIL();
2723     }
2724     EXPECT_EQ(rc, -EOVERFLOW);
2725 }
2726 
TEST(RequestUpdate,goodPathEncodeRequest)2727 TEST(RequestUpdate, goodPathEncodeRequest)
2728 {
2729     constexpr uint8_t instanceId = 1;
2730     constexpr uint32_t maxTransferSize = 512;
2731     constexpr uint16_t numOfComp = 3;
2732     constexpr uint8_t maxOutstandingTransferReq = 2;
2733     constexpr uint16_t pkgDataLen = 0x1234;
2734     constexpr std::string_view compImgSetVerStr = "0penBmcv1.0";
2735     constexpr uint8_t compImgSetVerStrLen =
2736         static_cast<uint8_t>(compImgSetVerStr.size());
2737     variable_field compImgSetVerStrInfo{};
2738     compImgSetVerStrInfo.ptr =
2739         // NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast)
2740         reinterpret_cast<const uint8_t*>(compImgSetVerStr.data());
2741     compImgSetVerStrInfo.length = compImgSetVerStrLen;
2742 
2743     std::array<uint8_t, hdrSize + sizeof(struct pldm_request_update_req) +
2744                             compImgSetVerStrLen>
2745         request{};
2746     // NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast)
2747     auto requestMsg = reinterpret_cast<pldm_msg*>(request.data());
2748 
2749     auto rc = encode_request_update_req(
2750         instanceId, maxTransferSize, numOfComp, maxOutstandingTransferReq,
2751         pkgDataLen, PLDM_STR_TYPE_ASCII, compImgSetVerStrLen,
2752         &compImgSetVerStrInfo, requestMsg,
2753         sizeof(struct pldm_request_update_req) + compImgSetVerStrLen);
2754     EXPECT_EQ(rc, PLDM_SUCCESS);
2755 
2756     std::array<uint8_t, hdrSize + sizeof(struct pldm_request_update_req) +
2757                             compImgSetVerStrLen>
2758         outRequest{0x81, 0x05, 0x10, 0x00, 0x02, 0x00, 0x00, 0x03, 0x00,
2759                    0x02, 0x34, 0x12, 0x01, 0x0b, 0x30, 0x70, 0x65, 0x6e,
2760                    0x42, 0x6d, 0x63, 0x76, 0x31, 0x2e, 0x30};
2761     EXPECT_EQ(request, outRequest);
2762 }
2763 
TEST(RequestUpdate,errorPathEncodeRequest)2764 TEST(RequestUpdate, errorPathEncodeRequest)
2765 {
2766     constexpr uint8_t instanceId = 1;
2767     uint32_t maxTransferSize = 512;
2768     constexpr uint16_t numOfComp = 3;
2769     uint8_t maxOutstandingTransferReq = 2;
2770     constexpr uint16_t pkgDataLen = 0x1234;
2771     constexpr std::string_view compImgSetVerStr = "0penBmcv1.0";
2772     uint8_t compImgSetVerStrLen = static_cast<uint8_t>(compImgSetVerStr.size());
2773     variable_field compImgSetVerStrInfo{};
2774     compImgSetVerStrInfo.ptr =
2775         // NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast)
2776         reinterpret_cast<const uint8_t*>(compImgSetVerStr.data());
2777     compImgSetVerStrInfo.length = compImgSetVerStrLen;
2778 
2779     std::array<uint8_t, hdrSize + sizeof(struct pldm_request_update_req) +
2780                             compImgSetVerStr.size()>
2781         request{};
2782     // NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast)
2783     auto requestMsg = reinterpret_cast<pldm_msg*>(request.data());
2784 
2785     auto rc = encode_request_update_req(
2786         instanceId, maxTransferSize, numOfComp, maxOutstandingTransferReq,
2787         pkgDataLen, PLDM_STR_TYPE_ASCII, compImgSetVerStrLen, nullptr,
2788         requestMsg,
2789         sizeof(struct pldm_request_update_req) + compImgSetVerStrLen);
2790     EXPECT_EQ(rc, PLDM_ERROR_INVALID_DATA);
2791 
2792     compImgSetVerStrInfo.ptr = nullptr;
2793     rc = encode_request_update_req(
2794         instanceId, maxTransferSize, numOfComp, maxOutstandingTransferReq,
2795         pkgDataLen, PLDM_STR_TYPE_ASCII, compImgSetVerStrLen,
2796         &compImgSetVerStrInfo, requestMsg,
2797         sizeof(struct pldm_request_update_req) + compImgSetVerStrLen);
2798     EXPECT_EQ(rc, PLDM_ERROR_INVALID_DATA);
2799     compImgSetVerStrInfo.ptr =
2800         // NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast)
2801         reinterpret_cast<const uint8_t*>(compImgSetVerStr.data());
2802 
2803     rc = encode_request_update_req(
2804         instanceId, maxTransferSize, numOfComp, maxOutstandingTransferReq,
2805         pkgDataLen, PLDM_STR_TYPE_ASCII, compImgSetVerStrLen,
2806         &compImgSetVerStrInfo, nullptr,
2807         sizeof(struct pldm_request_update_req) + compImgSetVerStrLen);
2808     EXPECT_EQ(rc, PLDM_ERROR_INVALID_DATA);
2809 
2810     rc = encode_request_update_req(instanceId, maxTransferSize, numOfComp,
2811                                    maxOutstandingTransferReq, pkgDataLen,
2812                                    PLDM_STR_TYPE_ASCII, compImgSetVerStrLen,
2813                                    &compImgSetVerStrInfo, requestMsg, 0);
2814     EXPECT_EQ(rc, PLDM_ERROR_INVALID_LENGTH);
2815 
2816     compImgSetVerStrLen = 0;
2817     rc = encode_request_update_req(
2818         instanceId, maxTransferSize, numOfComp, maxOutstandingTransferReq,
2819         pkgDataLen, PLDM_STR_TYPE_ASCII, 0, &compImgSetVerStrInfo, nullptr,
2820         sizeof(struct pldm_request_update_req) + compImgSetVerStrLen);
2821     EXPECT_EQ(rc, PLDM_ERROR_INVALID_DATA);
2822     compImgSetVerStrLen = static_cast<uint8_t>(compImgSetVerStr.size());
2823 
2824     compImgSetVerStrInfo.length = 0xffff;
2825     rc = encode_request_update_req(
2826         instanceId, maxTransferSize, numOfComp, maxOutstandingTransferReq,
2827         pkgDataLen, PLDM_STR_TYPE_ASCII, compImgSetVerStrLen,
2828         &compImgSetVerStrInfo, nullptr,
2829         sizeof(struct pldm_request_update_req) + compImgSetVerStrLen);
2830     EXPECT_EQ(rc, PLDM_ERROR_INVALID_DATA);
2831     compImgSetVerStrInfo.length = compImgSetVerStrLen;
2832 
2833     maxTransferSize = PLDM_FWUP_BASELINE_TRANSFER_SIZE - 1;
2834     rc = encode_request_update_req(
2835         instanceId, maxTransferSize, numOfComp, maxOutstandingTransferReq,
2836         pkgDataLen, PLDM_STR_TYPE_ASCII, compImgSetVerStrLen,
2837         &compImgSetVerStrInfo, nullptr,
2838         sizeof(struct pldm_request_update_req) + compImgSetVerStrLen);
2839     EXPECT_EQ(rc, PLDM_ERROR_INVALID_DATA);
2840     maxTransferSize = PLDM_FWUP_BASELINE_TRANSFER_SIZE;
2841 
2842     maxOutstandingTransferReq = PLDM_FWUP_MIN_OUTSTANDING_REQ - 1;
2843     rc = encode_request_update_req(
2844         instanceId, maxTransferSize, numOfComp, maxOutstandingTransferReq,
2845         pkgDataLen, PLDM_STR_TYPE_ASCII, compImgSetVerStrLen,
2846         &compImgSetVerStrInfo, nullptr,
2847         sizeof(struct pldm_request_update_req) + compImgSetVerStrLen);
2848     EXPECT_EQ(rc, PLDM_ERROR_INVALID_DATA);
2849     maxOutstandingTransferReq = PLDM_FWUP_MIN_OUTSTANDING_REQ;
2850 
2851     rc = encode_request_update_req(
2852         instanceId, maxTransferSize, numOfComp, maxOutstandingTransferReq,
2853         pkgDataLen, PLDM_STR_TYPE_UNKNOWN, compImgSetVerStrLen,
2854         &compImgSetVerStrInfo, nullptr,
2855         sizeof(struct pldm_request_update_req) + compImgSetVerStrLen);
2856     EXPECT_EQ(rc, PLDM_ERROR_INVALID_DATA);
2857 }
2858 
TEST(RequestUpdate,goodPathDecodeResponse)2859 TEST(RequestUpdate, goodPathDecodeResponse)
2860 {
2861     /* Test a success completion code */
2862     constexpr uint16_t fdMetaDataLen = 1024;
2863     constexpr uint8_t fdWillSendPkgData = 1;
2864     constexpr std::array<uint8_t, hdrSize + sizeof(pldm_request_update_resp)>
2865         requestUpdateResponse1{0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x01};
2866 
2867     auto responseMsg1 =
2868         // NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast)
2869         reinterpret_cast<const pldm_msg*>(requestUpdateResponse1.data());
2870     uint8_t outCompletionCode = 0;
2871     uint16_t outFdMetaDataLen = 0;
2872     uint8_t outFdWillSendPkgData = 0;
2873 
2874     auto rc = decode_request_update_resp(
2875         responseMsg1, requestUpdateResponse1.size() - hdrSize,
2876         &outCompletionCode, &outFdMetaDataLen, &outFdWillSendPkgData);
2877     EXPECT_EQ(rc, PLDM_SUCCESS);
2878     EXPECT_EQ(outCompletionCode, PLDM_SUCCESS);
2879     EXPECT_EQ(outFdMetaDataLen, fdMetaDataLen);
2880     EXPECT_EQ(outFdWillSendPkgData, fdWillSendPkgData);
2881 
2882 #ifdef LIBPLDM_API_TESTING
2883     /* Check the success roundtrip matches */
2884     PLDM_MSG_DEFINE_P(enc, 1000);
2885     size_t enc_payload_len = 1000;
2886     const struct pldm_request_update_resp resp_data = {
2887         .completion_code = PLDM_SUCCESS,
2888         .fd_meta_data_len = outFdMetaDataLen,
2889         .fd_will_send_pkg_data = outFdWillSendPkgData,
2890     };
2891     rc = encode_request_update_resp(FIXED_INSTANCE_ID, &resp_data, enc,
2892                                     &enc_payload_len);
2893     EXPECT_EQ(rc, PLDM_SUCCESS);
2894     EXPECT_EQ(enc_payload_len + hdrSize, requestUpdateResponse1.size());
2895     EXPECT_TRUE(std::equal(requestUpdateResponse1.begin() + hdrSize,
2896                            requestUpdateResponse1.end(), enc_buf + hdrSize));
2897     check_response(enc, PLDM_REQUEST_UPDATE);
2898 #endif
2899 
2900     /* Test a failure completion code */
2901     outCompletionCode = 0;
2902     outFdMetaDataLen = 0;
2903     outFdWillSendPkgData = 0;
2904 
2905     constexpr std::array<uint8_t, hdrSize + sizeof(outCompletionCode)>
2906         requestUpdateResponse2{0x00, 0x00, 0x00, 0x81};
2907     auto responseMsg2 =
2908         // NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast)
2909         reinterpret_cast<const pldm_msg*>(requestUpdateResponse2.data());
2910     rc = decode_request_update_resp(
2911         responseMsg2, requestUpdateResponse2.size() - hdrSize,
2912         &outCompletionCode, &outFdMetaDataLen, &outFdWillSendPkgData);
2913     EXPECT_EQ(rc, PLDM_SUCCESS);
2914     EXPECT_EQ(outCompletionCode, PLDM_FWUP_ALREADY_IN_UPDATE_MODE);
2915 }
2916 
TEST(RequestUpdate,errorPathDecodeResponse)2917 TEST(RequestUpdate, errorPathDecodeResponse)
2918 {
2919     constexpr std::array<uint8_t,
2920                          hdrSize + sizeof(pldm_request_update_resp) - 1>
2921         requestUpdateResponse{0x00, 0x00, 0x00, 0x00, 0x00, 0x04};
2922 
2923     auto responseMsg =
2924         // NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast)
2925         reinterpret_cast<const pldm_msg*>(requestUpdateResponse.data());
2926     uint8_t outCompletionCode = 0;
2927     uint16_t outFdMetaDataLen = 0;
2928     uint8_t outFdWillSendPkgData = 0;
2929 
2930     auto rc = decode_request_update_resp(
2931         nullptr, requestUpdateResponse.size() - hdrSize, &outCompletionCode,
2932         &outFdMetaDataLen, &outFdWillSendPkgData);
2933     EXPECT_EQ(rc, PLDM_ERROR_INVALID_DATA);
2934 
2935     rc = decode_request_update_resp(
2936         responseMsg, requestUpdateResponse.size() - hdrSize, nullptr,
2937         &outFdMetaDataLen, &outFdWillSendPkgData);
2938     EXPECT_EQ(rc, PLDM_ERROR_INVALID_DATA);
2939 
2940     rc = decode_request_update_resp(
2941         responseMsg, requestUpdateResponse.size() - hdrSize, &outCompletionCode,
2942         nullptr, &outFdWillSendPkgData);
2943     EXPECT_EQ(rc, PLDM_ERROR_INVALID_DATA);
2944 
2945     rc = decode_request_update_resp(
2946         responseMsg, requestUpdateResponse.size() - hdrSize, &outCompletionCode,
2947         &outFdMetaDataLen, nullptr);
2948     EXPECT_EQ(rc, PLDM_ERROR_INVALID_DATA);
2949 
2950     rc = decode_request_update_resp(responseMsg, 0, &outCompletionCode,
2951                                     &outFdMetaDataLen, &outFdWillSendPkgData);
2952     EXPECT_EQ(rc, PLDM_ERROR_INVALID_DATA);
2953 
2954     rc = decode_request_update_resp(
2955         responseMsg, requestUpdateResponse.size() - hdrSize, &outCompletionCode,
2956         &outFdMetaDataLen, &outFdWillSendPkgData);
2957     EXPECT_EQ(rc, PLDM_ERROR_INVALID_LENGTH);
2958 }
2959 
TEST(PassComponentTable,goodPathEncodeRequest)2960 TEST(PassComponentTable, goodPathEncodeRequest)
2961 {
2962     constexpr uint8_t instanceId = 1;
2963     constexpr uint16_t compIdentifier = 400;
2964     constexpr uint8_t compClassificationIndex = 40;
2965     constexpr uint32_t compComparisonStamp = 0x12345678;
2966     constexpr std::string_view compVerStr = "0penBmcv1.1";
2967     constexpr uint8_t compVerStrLen = static_cast<uint8_t>(compVerStr.size());
2968     variable_field compVerStrInfo{};
2969     // NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast)
2970     compVerStrInfo.ptr = reinterpret_cast<const uint8_t*>(compVerStr.data());
2971     compVerStrInfo.length = compVerStrLen;
2972 
2973     std::array<uint8_t,
2974                hdrSize + sizeof(pldm_pass_component_table_req) + compVerStrLen>
2975         request{};
2976     // NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast)
2977     auto requestMsg = reinterpret_cast<pldm_msg*>(request.data());
2978 
2979     auto rc = encode_pass_component_table_req(
2980         instanceId, PLDM_START_AND_END, PLDM_COMP_FIRMWARE, compIdentifier,
2981         compClassificationIndex, compComparisonStamp, PLDM_STR_TYPE_ASCII,
2982         compVerStrLen, &compVerStrInfo, requestMsg,
2983         sizeof(pldm_pass_component_table_req) + compVerStrLen);
2984     EXPECT_EQ(rc, PLDM_SUCCESS);
2985 
2986     std::array<uint8_t,
2987                hdrSize + sizeof(pldm_pass_component_table_req) + compVerStrLen>
2988         outRequest{0x81, 0x05, 0x13, 0x05, 0x0a, 0x00, 0x90, 0x01, 0x28,
2989                    0x78, 0x56, 0x34, 0x12, 0x01, 0x0b, 0x30, 0x70, 0x65,
2990                    0x6e, 0x42, 0x6d, 0x63, 0x76, 0x31, 0x2e, 0x31};
2991     EXPECT_EQ(request, outRequest);
2992 
2993 #ifdef LIBPLDM_API_TESTING
2994     /* Check the roundtrip */
2995     struct pldm_pass_component_table_req_full req;
2996     PLDM_MSG_DEFINE_P(dec, outRequest.size());
2997     std::copy(outRequest.begin(), outRequest.end(), dec_buf);
2998     rc =
2999         decode_pass_component_table_req(dec, outRequest.size() - hdrSize, &req);
3000     ASSERT_EQ(rc, 0);
3001 
3002     EXPECT_EQ(req.transfer_flag, PLDM_START_AND_END);
3003     EXPECT_EQ(req.comp_classification, PLDM_COMP_FIRMWARE);
3004     EXPECT_EQ(req.comp_identifier, compIdentifier);
3005     EXPECT_EQ(req.comp_classification_index, compClassificationIndex);
3006     EXPECT_EQ(req.comp_comparison_stamp, compComparisonStamp);
3007     EXPECT_EQ(req.version.str_type, PLDM_STR_TYPE_ASCII);
3008     EXPECT_EQ(req.version.str_len, compVerStrLen);
3009     EXPECT_TRUE(std::equal(req.version.str_data,
3010                            req.version.str_data + req.version.str_len,
3011                            compVerStr.data()));
3012 #endif
3013 }
3014 
TEST(PassComponentTable,errorPathEncodeRequest)3015 TEST(PassComponentTable, errorPathEncodeRequest)
3016 {
3017     constexpr uint8_t instanceId = 1;
3018     constexpr uint16_t compIdentifier = 400;
3019     constexpr uint8_t compClassificationIndex = 40;
3020     constexpr uint32_t compComparisonStamp = 0x12345678;
3021     constexpr std::string_view compVerStr = "0penBmcv1.1";
3022     constexpr uint8_t compVerStrLen = static_cast<uint8_t>(compVerStr.size());
3023     variable_field compVerStrInfo{};
3024     // NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast)
3025     compVerStrInfo.ptr = reinterpret_cast<const uint8_t*>(compVerStr.data());
3026     compVerStrInfo.length = compVerStrLen;
3027 
3028     std::array<uint8_t,
3029                hdrSize + sizeof(pldm_pass_component_table_req) + compVerStrLen>
3030         request{};
3031     // NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast)
3032     auto requestMsg = reinterpret_cast<pldm_msg*>(request.data());
3033 
3034     auto rc = encode_pass_component_table_req(
3035         instanceId, PLDM_START_AND_END, PLDM_COMP_FIRMWARE, compIdentifier,
3036         compClassificationIndex, compComparisonStamp, PLDM_STR_TYPE_ASCII,
3037         compVerStrLen, nullptr, requestMsg,
3038         sizeof(pldm_pass_component_table_req) + compVerStrLen);
3039     EXPECT_EQ(rc, PLDM_ERROR_INVALID_DATA);
3040 
3041     compVerStrInfo.ptr = nullptr;
3042     rc = encode_pass_component_table_req(
3043         instanceId, PLDM_START_AND_END, PLDM_COMP_FIRMWARE, compIdentifier,
3044         compClassificationIndex, compComparisonStamp, PLDM_STR_TYPE_ASCII,
3045         compVerStrLen, &compVerStrInfo, requestMsg,
3046         sizeof(pldm_pass_component_table_req) + compVerStrLen);
3047     EXPECT_EQ(rc, PLDM_ERROR_INVALID_DATA);
3048     // NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast)
3049     compVerStrInfo.ptr = reinterpret_cast<const uint8_t*>(compVerStr.data());
3050 
3051     rc = encode_pass_component_table_req(
3052         instanceId, PLDM_START_AND_END, PLDM_COMP_FIRMWARE, compIdentifier,
3053         compClassificationIndex, compComparisonStamp, PLDM_STR_TYPE_ASCII,
3054         compVerStrLen, &compVerStrInfo, nullptr,
3055         sizeof(pldm_pass_component_table_req) + compVerStrLen);
3056     EXPECT_EQ(rc, PLDM_ERROR_INVALID_DATA);
3057 
3058     rc = encode_pass_component_table_req(
3059         instanceId, PLDM_START_AND_END, PLDM_COMP_FIRMWARE, compIdentifier,
3060         compClassificationIndex, compComparisonStamp, PLDM_STR_TYPE_ASCII,
3061         compVerStrLen, &compVerStrInfo, requestMsg,
3062         sizeof(pldm_pass_component_table_req));
3063     EXPECT_EQ(rc, PLDM_ERROR_INVALID_LENGTH);
3064 
3065     rc = encode_pass_component_table_req(
3066         instanceId, PLDM_START_AND_END, PLDM_COMP_FIRMWARE, compIdentifier,
3067         compClassificationIndex, compComparisonStamp, PLDM_STR_TYPE_ASCII, 0,
3068         &compVerStrInfo, requestMsg,
3069         sizeof(pldm_pass_component_table_req) + compVerStrLen);
3070     EXPECT_EQ(rc, PLDM_ERROR_INVALID_DATA);
3071 
3072     rc = encode_pass_component_table_req(
3073         instanceId, PLDM_START_AND_END, PLDM_COMP_FIRMWARE, compIdentifier,
3074         compClassificationIndex, compComparisonStamp, PLDM_STR_TYPE_ASCII,
3075         compVerStrLen - 1, &compVerStrInfo, requestMsg,
3076         sizeof(pldm_pass_component_table_req) + compVerStrLen);
3077     EXPECT_EQ(rc, PLDM_ERROR_INVALID_DATA);
3078 
3079     rc = encode_pass_component_table_req(
3080         instanceId, PLDM_START_AND_END + 1, PLDM_COMP_FIRMWARE, compIdentifier,
3081         compClassificationIndex, compComparisonStamp, PLDM_STR_TYPE_ASCII,
3082         compVerStrLen, &compVerStrInfo, requestMsg,
3083         sizeof(pldm_pass_component_table_req) + compVerStrLen);
3084     EXPECT_EQ(rc, PLDM_INVALID_TRANSFER_OPERATION_FLAG);
3085 
3086     rc = encode_pass_component_table_req(
3087         instanceId, PLDM_START_AND_END, PLDM_COMP_FIRMWARE, compIdentifier,
3088         compClassificationIndex, compComparisonStamp, PLDM_STR_TYPE_UNKNOWN,
3089         compVerStrLen, &compVerStrInfo, requestMsg,
3090         sizeof(pldm_pass_component_table_req) + compVerStrLen);
3091     EXPECT_EQ(rc, PLDM_ERROR_INVALID_DATA);
3092 }
3093 
TEST(PassComponentTable,goodPathDecodeResponse)3094 TEST(PassComponentTable, goodPathDecodeResponse)
3095 {
3096     constexpr std::array<uint8_t,
3097                          hdrSize + sizeof(pldm_pass_component_table_resp)>
3098         passCompTableResponse1{0x00, 0x00, 0x00, 0x00, 0x00, 0x01};
3099     auto responseMsg1 =
3100         // NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast)
3101         reinterpret_cast<const pldm_msg*>(passCompTableResponse1.data());
3102 
3103     uint8_t completionCode = 0;
3104     uint8_t compResp = 0;
3105     uint8_t compRespCode = 0;
3106 
3107     auto rc = decode_pass_component_table_resp(
3108         responseMsg1, sizeof(pldm_pass_component_table_resp), &completionCode,
3109         &compResp, &compRespCode);
3110 
3111     EXPECT_EQ(rc, PLDM_SUCCESS);
3112     EXPECT_EQ(completionCode, PLDM_SUCCESS);
3113     EXPECT_EQ(compResp, PLDM_CR_COMP_CAN_BE_UPDATED);
3114     EXPECT_EQ(compRespCode, PLDM_CRC_COMP_COMPARISON_STAMP_IDENTICAL);
3115 
3116     constexpr std::array<uint8_t,
3117                          hdrSize + sizeof(pldm_pass_component_table_resp)>
3118         passCompTableResponse2{0x00, 0x00, 0x00, 0x00, 0x00, 0xd0};
3119     auto responseMsg2 =
3120         // NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast)
3121         reinterpret_cast<const pldm_msg*>(passCompTableResponse2.data());
3122     rc = decode_pass_component_table_resp(
3123         responseMsg2, sizeof(pldm_pass_component_table_resp), &completionCode,
3124         &compResp, &compRespCode);
3125 
3126     EXPECT_EQ(rc, PLDM_SUCCESS);
3127     EXPECT_EQ(completionCode, PLDM_SUCCESS);
3128     EXPECT_EQ(compResp, PLDM_CR_COMP_CAN_BE_UPDATED);
3129     EXPECT_EQ(compRespCode, PLDM_CRC_VENDOR_COMP_RESP_CODE_RANGE_MIN);
3130 
3131     constexpr std::array<uint8_t,
3132                          hdrSize + sizeof(pldm_pass_component_table_resp)>
3133         passCompTableResponse3{0x00, 0x00, 0x00, 0x80};
3134     auto responseMsg3 =
3135         // NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast)
3136         reinterpret_cast<const pldm_msg*>(passCompTableResponse3.data());
3137 
3138     rc = decode_pass_component_table_resp(
3139         responseMsg3, sizeof(pldm_pass_component_table_resp), &completionCode,
3140         &compResp, &compRespCode);
3141 
3142     EXPECT_EQ(rc, PLDM_SUCCESS);
3143     EXPECT_EQ(completionCode, PLDM_FWUP_NOT_IN_UPDATE_MODE);
3144 }
3145 
TEST(PassComponentTable,errorPathDecodeResponse)3146 TEST(PassComponentTable, errorPathDecodeResponse)
3147 {
3148     constexpr std::array<uint8_t,
3149                          hdrSize + sizeof(pldm_pass_component_table_resp) - 1>
3150         passCompTableResponse1{0x00, 0x00, 0x00, 0x00, 0x00};
3151     auto responseMsg1 =
3152         // NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast)
3153         reinterpret_cast<const pldm_msg*>(passCompTableResponse1.data());
3154 
3155     uint8_t completionCode = 0;
3156     uint8_t compResp = 0;
3157     uint8_t compRespCode = 0;
3158 
3159     auto rc = decode_pass_component_table_resp(
3160         nullptr, sizeof(pldm_pass_component_table_resp) - 1, &completionCode,
3161         &compResp, &compRespCode);
3162     EXPECT_EQ(rc, PLDM_ERROR_INVALID_DATA);
3163 
3164     rc = decode_pass_component_table_resp(
3165         responseMsg1, sizeof(pldm_pass_component_table_resp) - 1, nullptr,
3166         &compResp, &compRespCode);
3167     EXPECT_EQ(rc, PLDM_ERROR_INVALID_DATA);
3168 
3169     rc = decode_pass_component_table_resp(
3170         responseMsg1, sizeof(pldm_pass_component_table_resp) - 1,
3171         &completionCode, nullptr, &compRespCode);
3172     EXPECT_EQ(rc, PLDM_ERROR_INVALID_DATA);
3173 
3174     rc = decode_pass_component_table_resp(
3175         responseMsg1, sizeof(pldm_pass_component_table_resp) - 1,
3176         &completionCode, &compResp, nullptr);
3177     EXPECT_EQ(rc, PLDM_ERROR_INVALID_DATA);
3178 
3179     rc = decode_pass_component_table_resp(responseMsg1, 0, &completionCode,
3180                                           &compResp, &compRespCode);
3181     EXPECT_EQ(rc, PLDM_ERROR_INVALID_DATA);
3182 
3183     rc = decode_pass_component_table_resp(
3184         responseMsg1, sizeof(pldm_pass_component_table_resp) - 1,
3185         &completionCode, &compResp, &compRespCode);
3186     EXPECT_EQ(rc, PLDM_ERROR_INVALID_LENGTH);
3187 
3188     constexpr std::array<uint8_t,
3189                          hdrSize + sizeof(pldm_pass_component_table_resp)>
3190         passCompTableResponse2{0x00, 0x00, 0x00, 0x00, 0x02, 0x00};
3191     auto responseMsg2 =
3192         // NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast)
3193         reinterpret_cast<const pldm_msg*>(passCompTableResponse2.data());
3194     rc = decode_pass_component_table_resp(
3195         responseMsg2, sizeof(pldm_pass_component_table_resp), &completionCode,
3196         &compResp, &compRespCode);
3197     EXPECT_EQ(rc, PLDM_ERROR_INVALID_DATA);
3198 
3199     constexpr std::array<uint8_t,
3200                          hdrSize + sizeof(pldm_pass_component_table_resp)>
3201         passCompTableResponse3{0x00, 0x00, 0x00, 0x00, 0x00, 0x0c};
3202     auto responseMsg3 =
3203         // NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast)
3204         reinterpret_cast<const pldm_msg*>(passCompTableResponse3.data());
3205     rc = decode_pass_component_table_resp(
3206         responseMsg3, sizeof(pldm_pass_component_table_resp), &completionCode,
3207         &compResp, &compRespCode);
3208     EXPECT_EQ(rc, PLDM_ERROR_INVALID_DATA);
3209 
3210     constexpr std::array<uint8_t,
3211                          hdrSize + sizeof(pldm_pass_component_table_resp)>
3212         passCompTableResponse4{0x00, 0x00, 0x00, 0x00, 0x00, 0xf0};
3213     auto responseMsg4 =
3214         // NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast)
3215         reinterpret_cast<const pldm_msg*>(passCompTableResponse4.data());
3216     rc = decode_pass_component_table_resp(
3217         responseMsg4, sizeof(pldm_pass_component_table_resp), &completionCode,
3218         &compResp, &compRespCode);
3219     EXPECT_EQ(rc, PLDM_ERROR_INVALID_DATA);
3220 }
3221 
TEST(UpdateComponent,goodPathEncodeRequest)3222 TEST(UpdateComponent, goodPathEncodeRequest)
3223 {
3224     constexpr uint8_t instanceId = 2;
3225     constexpr uint16_t compIdentifier = 500;
3226     constexpr uint8_t compClassificationIndex = 50;
3227     constexpr uint32_t compComparisonStamp = 0x89abcdef;
3228     constexpr uint32_t compImageSize = 4096;
3229     constexpr bitfield32_t updateOptionFlags{1};
3230     constexpr std::string_view compVerStr = "OpenBmcv2.2";
3231     constexpr uint8_t compVerStrLen = static_cast<uint8_t>(compVerStr.size());
3232     variable_field compVerStrInfo{};
3233     // NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast)
3234     compVerStrInfo.ptr = reinterpret_cast<const uint8_t*>(compVerStr.data());
3235     compVerStrInfo.length = compVerStrLen;
3236 
3237     std::array<uint8_t,
3238                hdrSize + sizeof(pldm_update_component_req) + compVerStrLen>
3239         request{};
3240     // NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast)
3241     auto requestMsg = reinterpret_cast<pldm_msg*>(request.data());
3242 
3243     auto rc = encode_update_component_req(
3244         instanceId, PLDM_COMP_FIRMWARE, compIdentifier, compClassificationIndex,
3245         compComparisonStamp, compImageSize, updateOptionFlags,
3246         PLDM_STR_TYPE_ASCII, compVerStrLen, &compVerStrInfo, requestMsg,
3247         sizeof(pldm_update_component_req) + compVerStrLen);
3248     EXPECT_EQ(rc, PLDM_SUCCESS);
3249 
3250     std::array<uint8_t,
3251                hdrSize + sizeof(pldm_update_component_req) + compVerStrLen>
3252         outRequest{0x82, 0x05, 0x14, 0x0a, 0x00, 0xf4, 0x01, 0x32, 0xef,
3253                    0xcd, 0xab, 0x89, 0x00, 0x10, 0x00, 0x00, 0x01, 0x00,
3254                    0x00, 0x00, 0x01, 0x0b, 0x4f, 0x70, 0x65, 0x6e, 0x42,
3255                    0x6d, 0x63, 0x76, 0x32, 0x2e, 0x32};
3256     EXPECT_EQ(request, outRequest);
3257 
3258 #ifdef LIBPLDM_API_TESTING
3259     /* Check the roundtrip */
3260     struct pldm_update_component_req_full req;
3261     PLDM_MSG_DEFINE_P(dec, outRequest.size());
3262     std::copy(outRequest.begin(), outRequest.end(), dec_buf);
3263     rc = decode_update_component_req(dec, outRequest.size() - hdrSize, &req);
3264     ASSERT_EQ(rc, 0);
3265 
3266     EXPECT_EQ(req.comp_classification, PLDM_COMP_FIRMWARE);
3267     EXPECT_EQ(req.comp_identifier, compIdentifier);
3268     EXPECT_EQ(req.comp_classification_index, compClassificationIndex);
3269     EXPECT_EQ(req.comp_comparison_stamp, compComparisonStamp);
3270     EXPECT_EQ(req.comp_image_size, compImageSize);
3271     EXPECT_EQ(req.update_option_flags.value, updateOptionFlags.value);
3272     EXPECT_EQ(req.version.str_type, PLDM_STR_TYPE_ASCII);
3273     EXPECT_EQ(req.version.str_len, compVerStrLen);
3274     EXPECT_TRUE(std::equal(req.version.str_data,
3275                            req.version.str_data + req.version.str_len,
3276                            compVerStr.data()));
3277 #endif
3278 }
3279 
TEST(UpdateComponent,errorPathEncodeRequest)3280 TEST(UpdateComponent, errorPathEncodeRequest)
3281 {
3282     constexpr uint8_t instanceId = 2;
3283     constexpr uint16_t compIdentifier = 500;
3284     constexpr uint8_t compClassificationIndex = 50;
3285     constexpr uint32_t compComparisonStamp = 0x89abcdef;
3286     constexpr uint32_t compImageSize = 4096;
3287     constexpr bitfield32_t updateOptionFlags{1};
3288     constexpr std::string_view compVerStr = "OpenBmcv2.2";
3289     constexpr uint8_t compVerStrLen = static_cast<uint8_t>(compVerStr.size());
3290     variable_field compVerStrInfo{};
3291     // NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast)
3292     compVerStrInfo.ptr = reinterpret_cast<const uint8_t*>(compVerStr.data());
3293     compVerStrInfo.length = compVerStrLen;
3294 
3295     std::array<uint8_t,
3296                hdrSize + sizeof(pldm_update_component_req) + compVerStrLen>
3297         request{};
3298     // NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast)
3299     auto requestMsg = reinterpret_cast<pldm_msg*>(request.data());
3300 
3301     auto rc = encode_update_component_req(
3302         instanceId, PLDM_COMP_FIRMWARE, compIdentifier, compClassificationIndex,
3303         compComparisonStamp, compImageSize, updateOptionFlags,
3304         PLDM_STR_TYPE_ASCII, compVerStrLen, nullptr, requestMsg,
3305         sizeof(pldm_update_component_req) + compVerStrLen);
3306     EXPECT_EQ(rc, PLDM_ERROR_INVALID_DATA);
3307 
3308     compVerStrInfo.ptr = nullptr;
3309     rc = encode_update_component_req(
3310         instanceId, PLDM_COMP_FIRMWARE, compIdentifier, compClassificationIndex,
3311         compComparisonStamp, compImageSize, updateOptionFlags,
3312         PLDM_STR_TYPE_ASCII, compVerStrLen, &compVerStrInfo, requestMsg,
3313         sizeof(pldm_update_component_req) + compVerStrLen);
3314     EXPECT_EQ(rc, PLDM_ERROR_INVALID_DATA);
3315     // NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast)
3316     compVerStrInfo.ptr = reinterpret_cast<const uint8_t*>(compVerStr.data());
3317 
3318     rc = encode_update_component_req(
3319         instanceId, PLDM_COMP_FIRMWARE, compIdentifier, compClassificationIndex,
3320         compComparisonStamp, compImageSize, updateOptionFlags,
3321         PLDM_STR_TYPE_ASCII, compVerStrLen, &compVerStrInfo, nullptr,
3322         sizeof(pldm_update_component_req) + compVerStrLen);
3323     EXPECT_EQ(rc, PLDM_ERROR_INVALID_DATA);
3324 
3325     rc = encode_update_component_req(
3326         instanceId, PLDM_COMP_FIRMWARE, compIdentifier, compClassificationIndex,
3327         compComparisonStamp, compImageSize, updateOptionFlags,
3328         PLDM_STR_TYPE_ASCII, compVerStrLen, &compVerStrInfo, requestMsg,
3329         sizeof(pldm_update_component_req));
3330     EXPECT_EQ(rc, PLDM_ERROR_INVALID_LENGTH);
3331 
3332     rc = encode_update_component_req(
3333         instanceId, PLDM_COMP_FIRMWARE, compIdentifier, compClassificationIndex,
3334         compComparisonStamp, 0, updateOptionFlags, PLDM_STR_TYPE_ASCII,
3335         compVerStrLen, &compVerStrInfo, requestMsg,
3336         sizeof(pldm_update_component_req) + compVerStrLen);
3337     EXPECT_EQ(rc, PLDM_ERROR_INVALID_DATA);
3338 
3339     rc = encode_update_component_req(
3340         instanceId, PLDM_COMP_FIRMWARE, compIdentifier, compClassificationIndex,
3341         compComparisonStamp, compImageSize, updateOptionFlags,
3342         PLDM_STR_TYPE_ASCII, 0, &compVerStrInfo, requestMsg,
3343         sizeof(pldm_update_component_req) + compVerStrLen);
3344     EXPECT_EQ(rc, PLDM_ERROR_INVALID_DATA);
3345 
3346     rc = encode_update_component_req(
3347         instanceId, PLDM_COMP_FIRMWARE, compIdentifier, compClassificationIndex,
3348         compComparisonStamp, compImageSize, updateOptionFlags,
3349         PLDM_STR_TYPE_ASCII, compVerStrLen - 1, &compVerStrInfo, requestMsg,
3350         sizeof(pldm_update_component_req) + compVerStrLen);
3351     EXPECT_EQ(rc, PLDM_ERROR_INVALID_DATA);
3352 
3353     rc = encode_update_component_req(
3354         instanceId, PLDM_COMP_FIRMWARE, compIdentifier, compClassificationIndex,
3355         compComparisonStamp, compImageSize, updateOptionFlags,
3356         PLDM_STR_TYPE_UNKNOWN, compVerStrLen, &compVerStrInfo, requestMsg,
3357         sizeof(pldm_update_component_req) + compVerStrLen);
3358     EXPECT_EQ(rc, PLDM_ERROR_INVALID_DATA);
3359 }
3360 
TEST(UpdateComponent,goodPathDecodeResponse)3361 TEST(UpdateComponent, goodPathDecodeResponse)
3362 {
3363     constexpr std::bitset<32> forceUpdateComp{1};
3364     constexpr uint16_t timeBeforeSendingReqFwData100s = 100;
3365     constexpr std::array<uint8_t, hdrSize + sizeof(pldm_update_component_resp)>
3366         updateComponentResponse1{0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3367                                  0x01, 0x00, 0x00, 0x00, 0x64, 0x00};
3368     auto responseMsg1 =
3369         // NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast)
3370         reinterpret_cast<const pldm_msg*>(updateComponentResponse1.data());
3371 
3372     uint8_t completionCode = 0;
3373     uint8_t compCompatibilityResp = 0;
3374     uint8_t compCompatibilityRespCode = 0;
3375     bitfield32_t updateOptionFlagsEnabled{};
3376     uint16_t timeBeforeReqFWData = 0;
3377 
3378     auto rc = decode_update_component_resp(
3379         responseMsg1, sizeof(pldm_update_component_resp), &completionCode,
3380         &compCompatibilityResp, &compCompatibilityRespCode,
3381         &updateOptionFlagsEnabled, &timeBeforeReqFWData);
3382 
3383     EXPECT_EQ(rc, PLDM_SUCCESS);
3384     EXPECT_EQ(completionCode, PLDM_SUCCESS);
3385     EXPECT_EQ(compCompatibilityResp, PLDM_CCR_COMP_CAN_BE_UPDATED);
3386     EXPECT_EQ(compCompatibilityRespCode, PLDM_CCRC_NO_RESPONSE_CODE);
3387     EXPECT_EQ(updateOptionFlagsEnabled.value, forceUpdateComp);
3388     EXPECT_EQ(timeBeforeReqFWData, timeBeforeSendingReqFwData100s);
3389 
3390     constexpr std::bitset<32> noFlags{};
3391     constexpr uint16_t timeBeforeSendingReqFwData0s = 0;
3392     constexpr std::array<uint8_t, hdrSize + sizeof(pldm_update_component_resp)>
3393         updateComponentResponse2{0x00, 0x00, 0x00, 0x00, 0x01, 0x09,
3394                                  0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
3395     auto responseMsg2 =
3396         // NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast)
3397         reinterpret_cast<const pldm_msg*>(updateComponentResponse2.data());
3398     rc = decode_update_component_resp(
3399         responseMsg2, sizeof(pldm_update_component_resp), &completionCode,
3400         &compCompatibilityResp, &compCompatibilityRespCode,
3401         &updateOptionFlagsEnabled, &timeBeforeReqFWData);
3402 
3403     EXPECT_EQ(rc, PLDM_SUCCESS);
3404     EXPECT_EQ(completionCode, PLDM_SUCCESS);
3405     EXPECT_EQ(compCompatibilityResp, PLDM_CCR_COMP_CANNOT_BE_UPDATED);
3406     EXPECT_EQ(compCompatibilityRespCode, PLDM_CCRC_COMP_INFO_NO_MATCH);
3407     EXPECT_EQ(updateOptionFlagsEnabled.value, noFlags);
3408     EXPECT_EQ(timeBeforeReqFWData, timeBeforeSendingReqFwData0s);
3409 
3410     constexpr std::array<uint8_t, hdrSize + sizeof(pldm_update_component_resp)>
3411         updateComponentResponse3{0x00, 0x00, 0x00, 0x80};
3412     auto responseMsg3 =
3413         // NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast)
3414         reinterpret_cast<const pldm_msg*>(updateComponentResponse3.data());
3415 
3416     rc = decode_update_component_resp(
3417         responseMsg3, sizeof(pldm_update_component_resp), &completionCode,
3418         &compCompatibilityResp, &compCompatibilityRespCode,
3419         &updateOptionFlagsEnabled, &timeBeforeReqFWData);
3420 
3421     EXPECT_EQ(rc, PLDM_SUCCESS);
3422     EXPECT_EQ(completionCode, PLDM_FWUP_NOT_IN_UPDATE_MODE);
3423 }
3424 
TEST(UpdateComponent,errorPathDecodeResponse)3425 TEST(UpdateComponent, errorPathDecodeResponse)
3426 {
3427     constexpr std::array<uint8_t,
3428                          hdrSize + sizeof(pldm_update_component_resp) - 1>
3429         updateComponentResponse1{0x00, 0x00, 0x00, 0x00, 0x01, 0x09,
3430                                  0x00, 0x00, 0x00, 0x00, 0x00};
3431     auto responseMsg1 =
3432         // NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast)
3433         reinterpret_cast<const pldm_msg*>(updateComponentResponse1.data());
3434 
3435     uint8_t completionCode = 0;
3436     uint8_t compCompatibilityResp = 0;
3437     uint8_t compCompatibilityRespCode = 0;
3438     bitfield32_t updateOptionFlagsEnabled{};
3439     uint16_t timeBeforeReqFWData = 0;
3440 
3441     auto rc = decode_update_component_resp(
3442         nullptr, sizeof(pldm_update_component_resp) - 1, &completionCode,
3443         &compCompatibilityResp, &compCompatibilityRespCode,
3444         &updateOptionFlagsEnabled, &timeBeforeReqFWData);
3445     EXPECT_EQ(rc, PLDM_ERROR_INVALID_DATA);
3446 
3447     rc = decode_update_component_resp(
3448         responseMsg1, sizeof(pldm_update_component_resp) - 1, nullptr,
3449         &compCompatibilityResp, &compCompatibilityRespCode,
3450         &updateOptionFlagsEnabled, &timeBeforeReqFWData);
3451     EXPECT_EQ(rc, PLDM_ERROR_INVALID_DATA);
3452 
3453     rc = decode_update_component_resp(
3454         responseMsg1, sizeof(pldm_update_component_resp) - 1, &completionCode,
3455         nullptr, &compCompatibilityRespCode, &updateOptionFlagsEnabled,
3456         &timeBeforeReqFWData);
3457     EXPECT_EQ(rc, PLDM_ERROR_INVALID_DATA);
3458 
3459     rc = decode_update_component_resp(
3460         responseMsg1, sizeof(pldm_update_component_resp) - 1, &completionCode,
3461         &compCompatibilityResp, nullptr, &updateOptionFlagsEnabled,
3462         &timeBeforeReqFWData);
3463     EXPECT_EQ(rc, PLDM_ERROR_INVALID_DATA);
3464 
3465     rc = decode_update_component_resp(
3466         responseMsg1, sizeof(pldm_update_component_resp) - 1, &completionCode,
3467         &compCompatibilityResp, &compCompatibilityRespCode, nullptr,
3468         &timeBeforeReqFWData);
3469     EXPECT_EQ(rc, PLDM_ERROR_INVALID_DATA);
3470 
3471     rc = decode_update_component_resp(
3472         responseMsg1, sizeof(pldm_update_component_resp) - 1, &completionCode,
3473         &compCompatibilityResp, &compCompatibilityRespCode,
3474         &updateOptionFlagsEnabled, nullptr);
3475     EXPECT_EQ(rc, PLDM_ERROR_INVALID_DATA);
3476 
3477     rc = decode_update_component_resp(
3478         responseMsg1, 0, &completionCode, &compCompatibilityResp,
3479         &compCompatibilityRespCode, &updateOptionFlagsEnabled,
3480         &timeBeforeReqFWData);
3481     EXPECT_EQ(rc, PLDM_ERROR_INVALID_DATA);
3482 
3483     rc = decode_update_component_resp(
3484         responseMsg1, sizeof(pldm_update_component_resp) - 1, &completionCode,
3485         &compCompatibilityResp, &compCompatibilityRespCode,
3486         &updateOptionFlagsEnabled, &timeBeforeReqFWData);
3487     EXPECT_EQ(rc, PLDM_ERROR_INVALID_LENGTH);
3488 
3489     constexpr std::array<uint8_t, hdrSize + sizeof(pldm_update_component_resp)>
3490         updateComponentResponse2{0x00, 0x00, 0x00, 0x00, 0x02, 0x00,
3491                                  0x01, 0x00, 0x00, 0x00, 0x64, 0x00};
3492     auto responseMsg2 =
3493         // NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast)
3494         reinterpret_cast<const pldm_msg*>(updateComponentResponse2.data());
3495     rc = decode_update_component_resp(
3496         responseMsg2, sizeof(pldm_update_component_resp), &completionCode,
3497         &compCompatibilityResp, &compCompatibilityRespCode,
3498         &updateOptionFlagsEnabled, &timeBeforeReqFWData);
3499     EXPECT_EQ(rc, PLDM_ERROR_INVALID_DATA);
3500 
3501     constexpr std::array<uint8_t, hdrSize + sizeof(pldm_update_component_resp)>
3502         updateComponentResponse3{0x00, 0x00, 0x00, 0x00, 0x00, 0x0c,
3503                                  0x01, 0x00, 0x00, 0x00, 0x64, 0x00};
3504     auto responseMsg3 =
3505         // NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast)
3506         reinterpret_cast<const pldm_msg*>(updateComponentResponse3.data());
3507     rc = decode_update_component_resp(
3508         responseMsg3, sizeof(pldm_update_component_resp), &completionCode,
3509         &compCompatibilityResp, &compCompatibilityRespCode,
3510         &updateOptionFlagsEnabled, &timeBeforeReqFWData);
3511     EXPECT_EQ(rc, PLDM_ERROR_INVALID_DATA);
3512 
3513     constexpr std::array<uint8_t, hdrSize + sizeof(pldm_update_component_resp)>
3514         updateComponentResponse4{0x00, 0x00, 0x00, 0x00, 0x00, 0xf0,
3515                                  0x01, 0x00, 0x00, 0x00, 0x64, 0x00};
3516     auto responseMsg4 =
3517         // NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast)
3518         reinterpret_cast<const pldm_msg*>(updateComponentResponse4.data());
3519     rc = decode_update_component_resp(
3520         responseMsg4, sizeof(pldm_update_component_resp), &completionCode,
3521         &compCompatibilityResp, &compCompatibilityRespCode,
3522         &updateOptionFlagsEnabled, &timeBeforeReqFWData);
3523     EXPECT_EQ(rc, PLDM_ERROR_INVALID_DATA);
3524 }
3525 
TEST(RequestFirmwareData,goodPathDecodeRequest)3526 TEST(RequestFirmwareData, goodPathDecodeRequest)
3527 {
3528     constexpr uint32_t offset = 300;
3529     constexpr uint32_t length = 255;
3530     constexpr std::array<uint8_t,
3531                          hdrSize + sizeof(pldm_request_firmware_data_req)>
3532         reqFWDataReq{0x00, 0x00, 0x00, 0x2c, 0x01, 0x00,
3533                      0x00, 0xff, 0x00, 0x00, 0x00};
3534     // NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast)
3535     auto requestMsg = reinterpret_cast<const pldm_msg*>(reqFWDataReq.data());
3536 
3537     uint32_t outOffset = 0;
3538     uint32_t outLength = 0;
3539     auto rc = decode_request_firmware_data_req(
3540         requestMsg, sizeof(pldm_request_firmware_data_req), &outOffset,
3541         &outLength);
3542 
3543     EXPECT_EQ(rc, PLDM_SUCCESS);
3544     EXPECT_EQ(outOffset, offset);
3545     EXPECT_EQ(outLength, length);
3546 }
3547 
TEST(RequestFirmwareData,errorPathDecodeRequest)3548 TEST(RequestFirmwareData, errorPathDecodeRequest)
3549 {
3550     constexpr std::array<uint8_t,
3551                          hdrSize + sizeof(pldm_request_firmware_data_req)>
3552         reqFWDataReq{0x00, 0x00, 0x00, 0x2c, 0x01, 0x00,
3553                      0x00, 0x1f, 0x00, 0x00, 0x00};
3554     // NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast)
3555     auto requestMsg = reinterpret_cast<const pldm_msg*>(reqFWDataReq.data());
3556 
3557     uint32_t outOffset = 0;
3558     uint32_t outLength = 0;
3559     auto rc = decode_request_firmware_data_req(
3560         nullptr, sizeof(pldm_request_firmware_data_req), &outOffset,
3561         &outLength);
3562     EXPECT_EQ(rc, PLDM_ERROR_INVALID_DATA);
3563 
3564     rc = decode_request_firmware_data_req(
3565         requestMsg, sizeof(pldm_request_firmware_data_req), nullptr,
3566         &outLength);
3567     EXPECT_EQ(rc, PLDM_ERROR_INVALID_DATA);
3568 
3569     rc = decode_request_firmware_data_req(
3570         requestMsg, sizeof(pldm_request_firmware_data_req), &outOffset,
3571         nullptr);
3572     EXPECT_EQ(rc, PLDM_ERROR_INVALID_DATA);
3573 
3574     rc = decode_request_firmware_data_req(
3575         requestMsg, sizeof(pldm_request_firmware_data_req) - 1, &outOffset,
3576         &outLength);
3577     EXPECT_EQ(rc, PLDM_ERROR_INVALID_LENGTH);
3578 
3579     rc = decode_request_firmware_data_req(
3580         requestMsg, sizeof(pldm_request_firmware_data_req), &outOffset,
3581         &outLength);
3582     EXPECT_EQ(rc, PLDM_FWUP_INVALID_TRANSFER_LENGTH);
3583 }
3584 
TEST(RequestFirmwareData,goodPathEncodeResponse)3585 TEST(RequestFirmwareData, goodPathEncodeResponse)
3586 {
3587     constexpr uint8_t instanceId = 3;
3588     constexpr uint8_t completionCode = PLDM_SUCCESS;
3589     constexpr std::array<uint8_t, hdrSize + sizeof(completionCode) +
3590                                       PLDM_FWUP_BASELINE_TRANSFER_SIZE>
3591         outReqFwDataResponse1{0x03, 0x05, 0x15, 0x00, 0x01, 0x02, 0x03, 0x04,
3592                               0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c,
3593                               0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13, 0x14,
3594                               0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c,
3595                               0x1d, 0x1e, 0x1f, 0x20};
3596     std::array<uint8_t, hdrSize + sizeof(completionCode) +
3597                             PLDM_FWUP_BASELINE_TRANSFER_SIZE>
3598         reqFwDataResponse1{0x00, 0x00, 0x00, 0x00, 0x01, 0x02, 0x03, 0x04,
3599                            0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c,
3600                            0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13, 0x14,
3601                            0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c,
3602                            0x1d, 0x1e, 0x1f, 0x20};
3603     // NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast)
3604     auto responseMsg1 = reinterpret_cast<pldm_msg*>(reqFwDataResponse1.data());
3605     auto rc = encode_request_firmware_data_resp(
3606         instanceId, completionCode, responseMsg1,
3607         sizeof(completionCode) + PLDM_FWUP_BASELINE_TRANSFER_SIZE);
3608     EXPECT_EQ(rc, PLDM_SUCCESS);
3609     EXPECT_EQ(reqFwDataResponse1, outReqFwDataResponse1);
3610 
3611     constexpr std::array<uint8_t, hdrSize + sizeof(completionCode)>
3612         outReqFwDataResponse2{0x03, 0x05, 0x15, 0x82};
3613     std::array<uint8_t, hdrSize + sizeof(completionCode)> reqFwDataResponse2{
3614         0x00, 0x00, 0x00, 0x00};
3615     // NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast)
3616     auto responseMsg2 = reinterpret_cast<pldm_msg*>(reqFwDataResponse2.data());
3617     rc = encode_request_firmware_data_resp(
3618         instanceId, PLDM_FWUP_DATA_OUT_OF_RANGE, responseMsg2,
3619         sizeof(completionCode));
3620     EXPECT_EQ(rc, PLDM_SUCCESS);
3621     EXPECT_EQ(reqFwDataResponse2, outReqFwDataResponse2);
3622 }
3623 
TEST(RequestFirmwareData,errorPathEncodeResponse)3624 TEST(RequestFirmwareData, errorPathEncodeResponse)
3625 {
3626     std::array<uint8_t, hdrSize> reqFwDataResponse{0x00, 0x00, 0x00};
3627     // NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast)
3628     auto responseMsg = reinterpret_cast<pldm_msg*>(reqFwDataResponse.data());
3629     auto rc = encode_request_firmware_data_resp(0, PLDM_SUCCESS, nullptr, 0);
3630     EXPECT_EQ(rc, PLDM_ERROR_INVALID_DATA);
3631 
3632     rc = encode_request_firmware_data_resp(0, PLDM_SUCCESS, responseMsg, 0);
3633     EXPECT_EQ(rc, PLDM_ERROR_INVALID_DATA);
3634 }
3635 
TEST(TransferComplete,goodPathDecodeRequest)3636 TEST(TransferComplete, goodPathDecodeRequest)
3637 {
3638     constexpr uint8_t transferResult = PLDM_FWUP_TRANSFER_SUCCESS;
3639     constexpr std::array<uint8_t, hdrSize + sizeof(transferResult)>
3640         transferCompleteReq1{0x00, 0x00, 0x00, 0x00};
3641     auto requestMsg1 =
3642         // NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast)
3643         reinterpret_cast<const pldm_msg*>(transferCompleteReq1.data());
3644     uint8_t outTransferResult = 0;
3645 
3646     auto rc = decode_transfer_complete_req(requestMsg1, sizeof(transferResult),
3647                                            &outTransferResult);
3648     EXPECT_EQ(rc, PLDM_SUCCESS);
3649     EXPECT_EQ(outTransferResult, transferResult);
3650 
3651     constexpr std::array<uint8_t, hdrSize + sizeof(transferResult)>
3652         transferCompleteReq2{0x00, 0x00, 0x00, 0x02};
3653     auto requestMsg2 =
3654         // NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast)
3655         reinterpret_cast<const pldm_msg*>(transferCompleteReq2.data());
3656     rc = decode_transfer_complete_req(requestMsg2, sizeof(transferResult),
3657                                       &outTransferResult);
3658     EXPECT_EQ(rc, PLDM_SUCCESS);
3659     EXPECT_EQ(outTransferResult, PLDM_FWUP_TRANSFER_ERROR_IMAGE_CORRUPT);
3660 }
3661 
TEST(TransferComplete,errorPathDecodeRequest)3662 TEST(TransferComplete, errorPathDecodeRequest)
3663 {
3664     constexpr std::array<uint8_t, hdrSize> transferCompleteReq{0x00, 0x00,
3665                                                                0x00};
3666     auto requestMsg =
3667         // NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast)
3668         reinterpret_cast<const pldm_msg*>(transferCompleteReq.data());
3669     uint8_t outTransferResult = 0;
3670 
3671     auto rc = decode_transfer_complete_req(nullptr, 0, &outTransferResult);
3672     EXPECT_EQ(rc, PLDM_ERROR_INVALID_DATA);
3673 
3674     rc = decode_transfer_complete_req(requestMsg, 0, nullptr);
3675     EXPECT_EQ(rc, PLDM_ERROR_INVALID_DATA);
3676 
3677     rc = decode_transfer_complete_req(requestMsg, 0, &outTransferResult);
3678     EXPECT_EQ(rc, PLDM_ERROR_INVALID_LENGTH);
3679 }
3680 
TEST(TransferComplete,goodPathEncodeResponse)3681 TEST(TransferComplete, goodPathEncodeResponse)
3682 {
3683     constexpr uint8_t instanceId = 4;
3684     constexpr uint8_t completionCode = PLDM_SUCCESS;
3685     constexpr std::array<uint8_t, hdrSize + sizeof(completionCode)>
3686         outTransferCompleteResponse1{0x04, 0x05, 0x16, 0x00};
3687     std::array<uint8_t, hdrSize + sizeof(completionCode)>
3688         transferCompleteResponse1{0x00, 0x00, 0x00, 0x00};
3689     auto responseMsg1 =
3690         // NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast)
3691         reinterpret_cast<pldm_msg*>(transferCompleteResponse1.data());
3692     auto rc = encode_transfer_complete_resp(
3693         instanceId, completionCode, responseMsg1, sizeof(completionCode));
3694     EXPECT_EQ(rc, PLDM_SUCCESS);
3695     EXPECT_EQ(transferCompleteResponse1, outTransferCompleteResponse1);
3696 
3697     constexpr std::array<uint8_t, hdrSize + sizeof(completionCode)>
3698         outTransferCompleteResponse2{0x04, 0x05, 0x16, 0x88};
3699     std::array<uint8_t, hdrSize + sizeof(completionCode)>
3700         transferCompleteResponse2{0x00, 0x00, 0x00, 0x00};
3701     auto responseMsg2 =
3702         // NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast)
3703         reinterpret_cast<pldm_msg*>(transferCompleteResponse2.data());
3704     rc = encode_transfer_complete_resp(instanceId,
3705                                        PLDM_FWUP_COMMAND_NOT_EXPECTED,
3706                                        responseMsg2, sizeof(completionCode));
3707     EXPECT_EQ(rc, PLDM_SUCCESS);
3708     EXPECT_EQ(transferCompleteResponse2, outTransferCompleteResponse2);
3709 }
3710 
TEST(TransferComplete,errorPathEncodeResponse)3711 TEST(TransferComplete, errorPathEncodeResponse)
3712 {
3713     std::array<uint8_t, hdrSize> transferCompleteResponse{0x00, 0x00, 0x00};
3714     auto responseMsg =
3715         // NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast)
3716         reinterpret_cast<pldm_msg*>(transferCompleteResponse.data());
3717     auto rc = encode_transfer_complete_resp(0, PLDM_SUCCESS, nullptr, 0);
3718     EXPECT_EQ(rc, PLDM_ERROR_INVALID_DATA);
3719 
3720     rc = encode_transfer_complete_resp(0, PLDM_SUCCESS, responseMsg, 0);
3721     EXPECT_EQ(rc, PLDM_ERROR_INVALID_LENGTH);
3722 }
3723 
TEST(VerifyComplete,goodPathDecodeRequest)3724 TEST(VerifyComplete, goodPathDecodeRequest)
3725 {
3726     constexpr uint8_t verifyResult = PLDM_FWUP_VERIFY_SUCCESS;
3727     constexpr std::array<uint8_t, hdrSize + sizeof(verifyResult)>
3728         verifyCompleteReq1{0x00, 0x00, 0x00, 0x00};
3729     auto requestMsg1 =
3730         // NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast)
3731         reinterpret_cast<const pldm_msg*>(verifyCompleteReq1.data());
3732     uint8_t outVerifyResult = 0;
3733 
3734     auto rc = decode_verify_complete_req(requestMsg1, sizeof(verifyResult),
3735                                          &outVerifyResult);
3736     EXPECT_EQ(rc, PLDM_SUCCESS);
3737     EXPECT_EQ(outVerifyResult, verifyResult);
3738 
3739     constexpr std::array<uint8_t, hdrSize + sizeof(verifyResult)>
3740         verifyCompleteReq2{0x00, 0x00, 0x00, 0x03};
3741     auto requestMsg2 =
3742         // NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast)
3743         reinterpret_cast<const pldm_msg*>(verifyCompleteReq2.data());
3744     rc = decode_verify_complete_req(requestMsg2, sizeof(verifyResult),
3745                                     &outVerifyResult);
3746     EXPECT_EQ(rc, PLDM_SUCCESS);
3747     EXPECT_EQ(outVerifyResult, PLDM_FWUP_VERIFY_FAILED_FD_SECURITY_CHECKS);
3748 }
3749 
TEST(VerifyComplete,errorPathDecodeRequest)3750 TEST(VerifyComplete, errorPathDecodeRequest)
3751 {
3752     constexpr std::array<uint8_t, hdrSize> verifyCompleteReq{0x00, 0x00, 0x00};
3753     auto requestMsg =
3754         // NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast)
3755         reinterpret_cast<const pldm_msg*>(verifyCompleteReq.data());
3756     uint8_t outVerifyResult = 0;
3757 
3758     auto rc = decode_verify_complete_req(nullptr, 0, &outVerifyResult);
3759     EXPECT_EQ(rc, PLDM_ERROR_INVALID_DATA);
3760 
3761     rc = decode_verify_complete_req(requestMsg, 0, nullptr);
3762     EXPECT_EQ(rc, PLDM_ERROR_INVALID_DATA);
3763 
3764     rc = decode_verify_complete_req(requestMsg, 0, &outVerifyResult);
3765     EXPECT_EQ(rc, PLDM_ERROR_INVALID_LENGTH);
3766 }
3767 
TEST(VerifyComplete,goodPathEncodeResponse)3768 TEST(VerifyComplete, goodPathEncodeResponse)
3769 {
3770     constexpr uint8_t instanceId = 5;
3771     constexpr uint8_t completionCode = PLDM_SUCCESS;
3772     constexpr std::array<uint8_t, hdrSize + sizeof(completionCode)>
3773         outVerifyCompleteResponse1{0x05, 0x05, 0x17, 0x00};
3774     std::array<uint8_t, hdrSize + sizeof(completionCode)>
3775         verifyCompleteResponse1{0x00, 0x00, 0x00, 0x00};
3776     auto responseMsg1 =
3777         // NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast)
3778         reinterpret_cast<pldm_msg*>(verifyCompleteResponse1.data());
3779     auto rc = encode_verify_complete_resp(instanceId, completionCode,
3780                                           responseMsg1, sizeof(completionCode));
3781     EXPECT_EQ(rc, PLDM_SUCCESS);
3782     EXPECT_EQ(verifyCompleteResponse1, outVerifyCompleteResponse1);
3783 
3784     constexpr std::array<uint8_t, hdrSize + sizeof(completionCode)>
3785         outVerifyCompleteResponse2{0x05, 0x05, 0x17, 0x88};
3786     std::array<uint8_t, hdrSize + sizeof(completionCode)>
3787         verifyCompleteResponse2{0x00, 0x00, 0x00, 0x00};
3788     auto responseMsg2 =
3789         // NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast)
3790         reinterpret_cast<pldm_msg*>(verifyCompleteResponse2.data());
3791     rc = encode_verify_complete_resp(instanceId, PLDM_FWUP_COMMAND_NOT_EXPECTED,
3792                                      responseMsg2, sizeof(completionCode));
3793     EXPECT_EQ(rc, PLDM_SUCCESS);
3794     EXPECT_EQ(verifyCompleteResponse2, outVerifyCompleteResponse2);
3795 }
3796 
TEST(VerifyComplete,errorPathEncodeResponse)3797 TEST(VerifyComplete, errorPathEncodeResponse)
3798 {
3799     std::array<uint8_t, hdrSize> verifyCompleteResponse{0x00, 0x00, 0x00};
3800     auto responseMsg =
3801         // NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast)
3802         reinterpret_cast<pldm_msg*>(verifyCompleteResponse.data());
3803     auto rc = encode_verify_complete_resp(0, PLDM_SUCCESS, nullptr, 0);
3804     EXPECT_EQ(rc, PLDM_ERROR_INVALID_DATA);
3805 
3806     rc = encode_verify_complete_resp(0, PLDM_SUCCESS, responseMsg, 0);
3807     EXPECT_EQ(rc, PLDM_ERROR_INVALID_LENGTH);
3808 }
3809 
TEST(ApplyComplete,goodPathDecodeRequest)3810 TEST(ApplyComplete, goodPathDecodeRequest)
3811 {
3812     constexpr uint8_t applyResult1 =
3813         PLDM_FWUP_APPLY_SUCCESS_WITH_ACTIVATION_METHOD;
3814     // DC power cycle [Bit position 4] & AC power cycle [Bit position 5]
3815     constexpr std::bitset<16> compActivationModification1{0x30};
3816     constexpr std::array<uint8_t, hdrSize + sizeof(pldm_apply_complete_req)>
3817         applyCompleteReq1{0x00, 0x00, 0x00, 0x01, 0x30, 0x00};
3818     auto requestMsg1 =
3819         // NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast)
3820         reinterpret_cast<const pldm_msg*>(applyCompleteReq1.data());
3821     uint8_t outApplyResult = 0;
3822     bitfield16_t outCompActivationModification{};
3823     auto rc = decode_apply_complete_req(
3824         requestMsg1, sizeof(pldm_apply_complete_req), &outApplyResult,
3825         &outCompActivationModification);
3826     EXPECT_EQ(rc, PLDM_SUCCESS);
3827     EXPECT_EQ(outApplyResult, applyResult1);
3828     EXPECT_EQ(outCompActivationModification.value, compActivationModification1);
3829 
3830     constexpr uint8_t applyResult2 = PLDM_FWUP_APPLY_SUCCESS;
3831     constexpr std::bitset<16> compActivationModification2{};
3832     constexpr std::array<uint8_t, hdrSize + sizeof(pldm_apply_complete_req)>
3833         applyCompleteReq2{0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
3834     auto requestMsg2 =
3835         // NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast)
3836         reinterpret_cast<const pldm_msg*>(applyCompleteReq2.data());
3837     rc = decode_apply_complete_req(requestMsg2, sizeof(pldm_apply_complete_req),
3838                                    &outApplyResult,
3839                                    &outCompActivationModification);
3840     EXPECT_EQ(rc, PLDM_SUCCESS);
3841     EXPECT_EQ(outApplyResult, applyResult2);
3842     EXPECT_EQ(outCompActivationModification.value, compActivationModification2);
3843 }
3844 
TEST(ApplyComplete,errorPathDecodeRequest)3845 TEST(ApplyComplete, errorPathDecodeRequest)
3846 {
3847     constexpr std::array<uint8_t, hdrSize> applyCompleteReq1{0x00, 0x00, 0x00};
3848     auto requestMsg1 =
3849         // NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast)
3850         reinterpret_cast<const pldm_msg*>(applyCompleteReq1.data());
3851     uint8_t outApplyResult = 0;
3852     bitfield16_t outCompActivationModification{};
3853 
3854     auto rc = decode_apply_complete_req(
3855         nullptr, sizeof(pldm_apply_complete_req), &outApplyResult,
3856         &outCompActivationModification);
3857     EXPECT_EQ(rc, PLDM_ERROR_INVALID_DATA);
3858 
3859     rc = decode_apply_complete_req(requestMsg1, sizeof(pldm_apply_complete_req),
3860                                    nullptr, &outCompActivationModification);
3861     EXPECT_EQ(rc, PLDM_ERROR_INVALID_DATA);
3862 
3863     rc = decode_apply_complete_req(requestMsg1, sizeof(pldm_apply_complete_req),
3864                                    &outApplyResult, nullptr);
3865     EXPECT_EQ(rc, PLDM_ERROR_INVALID_DATA);
3866 
3867     rc = decode_apply_complete_req(requestMsg1, 0, &outApplyResult,
3868                                    &outCompActivationModification);
3869     EXPECT_EQ(rc, PLDM_ERROR_INVALID_LENGTH);
3870 
3871     constexpr std::array<uint8_t, hdrSize + sizeof(pldm_apply_complete_req)>
3872         applyCompleteReq2{0x00, 0x00, 0x00, 0x00, 0x01, 0x00};
3873     auto requestMsg2 =
3874         // NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast)
3875         reinterpret_cast<const pldm_msg*>(applyCompleteReq2.data());
3876     rc = decode_apply_complete_req(requestMsg2, sizeof(pldm_apply_complete_req),
3877                                    &outApplyResult,
3878                                    &outCompActivationModification);
3879     EXPECT_EQ(rc, PLDM_ERROR_INVALID_DATA);
3880 }
3881 
TEST(ApplyComplete,goodPathEncodeResponse)3882 TEST(ApplyComplete, goodPathEncodeResponse)
3883 {
3884     constexpr uint8_t instanceId = 6;
3885     constexpr uint8_t completionCode = PLDM_SUCCESS;
3886     constexpr std::array<uint8_t, hdrSize + sizeof(completionCode)>
3887         outApplyCompleteResponse1{0x06, 0x05, 0x18, 0x00};
3888     std::array<uint8_t, hdrSize + sizeof(completionCode)>
3889         applyCompleteResponse1{0x00, 0x00, 0x00, 0x00};
3890     auto responseMsg1 =
3891         // NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast)
3892         reinterpret_cast<pldm_msg*>(applyCompleteResponse1.data());
3893     auto rc = encode_apply_complete_resp(instanceId, completionCode,
3894                                          responseMsg1, sizeof(completionCode));
3895     EXPECT_EQ(rc, PLDM_SUCCESS);
3896     EXPECT_EQ(applyCompleteResponse1, outApplyCompleteResponse1);
3897 
3898     constexpr std::array<uint8_t, hdrSize + sizeof(completionCode)>
3899         outApplyCompleteResponse2{0x06, 0x05, 0x18, 0x88};
3900     std::array<uint8_t, hdrSize + sizeof(completionCode)>
3901         applyCompleteResponse2{0x00, 0x00, 0x00, 0x00};
3902     auto responseMsg2 =
3903         // NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast)
3904         reinterpret_cast<pldm_msg*>(applyCompleteResponse2.data());
3905     rc = encode_apply_complete_resp(instanceId, PLDM_FWUP_COMMAND_NOT_EXPECTED,
3906                                     responseMsg2, sizeof(completionCode));
3907     EXPECT_EQ(rc, PLDM_SUCCESS);
3908     EXPECT_EQ(applyCompleteResponse2, outApplyCompleteResponse2);
3909 }
3910 
TEST(ApplyComplete,errorPathEncodeResponse)3911 TEST(ApplyComplete, errorPathEncodeResponse)
3912 {
3913     std::array<uint8_t, hdrSize> applyCompleteResponse{0x00, 0x00, 0x00};
3914     auto responseMsg =
3915         // NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast)
3916         reinterpret_cast<pldm_msg*>(applyCompleteResponse.data());
3917     auto rc = encode_apply_complete_resp(0, PLDM_SUCCESS, nullptr, 0);
3918     EXPECT_EQ(rc, PLDM_ERROR_INVALID_DATA);
3919 
3920     rc = encode_apply_complete_resp(0, PLDM_SUCCESS, responseMsg, 0);
3921     EXPECT_EQ(rc, PLDM_ERROR_INVALID_LENGTH);
3922 }
3923 
TEST(ActivateFirmware,goodPathEncodeRequest)3924 TEST(ActivateFirmware, goodPathEncodeRequest)
3925 {
3926     constexpr uint8_t instanceId = 7;
3927 
3928     std::array<uint8_t, hdrSize + sizeof(pldm_activate_firmware_req)> request{};
3929     // NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast)
3930     auto requestMsg = reinterpret_cast<pldm_msg*>(request.data());
3931 
3932     auto rc = encode_activate_firmware_req(
3933         instanceId, PLDM_ACTIVATE_SELF_CONTAINED_COMPONENTS, requestMsg,
3934         sizeof(pldm_activate_firmware_req));
3935     EXPECT_EQ(rc, PLDM_SUCCESS);
3936 
3937     std::array<uint8_t, hdrSize + sizeof(pldm_activate_firmware_req)>
3938         outRequest{0x87, 0x05, 0x1a, 0x01};
3939     EXPECT_EQ(request, outRequest);
3940 }
3941 
TEST(ActivateFirmware,errorPathEncodeRequest)3942 TEST(ActivateFirmware, errorPathEncodeRequest)
3943 {
3944     std::array<uint8_t, hdrSize + sizeof(pldm_activate_firmware_req)> request{};
3945     // NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast)
3946     auto requestMsg = reinterpret_cast<pldm_msg*>(request.data());
3947 
3948     auto rc = encode_activate_firmware_req(
3949         0, PLDM_ACTIVATE_SELF_CONTAINED_COMPONENTS, nullptr,
3950         sizeof(pldm_activate_firmware_req));
3951     EXPECT_EQ(rc, PLDM_ERROR_INVALID_DATA);
3952 
3953     rc = encode_activate_firmware_req(
3954         0, PLDM_ACTIVATE_SELF_CONTAINED_COMPONENTS, requestMsg, 0);
3955     EXPECT_EQ(rc, PLDM_ERROR_INVALID_LENGTH);
3956 
3957     rc = encode_activate_firmware_req(0, 2, requestMsg,
3958                                       sizeof(pldm_activate_firmware_req));
3959     EXPECT_EQ(rc, PLDM_ERROR_INVALID_DATA);
3960 }
3961 
TEST(ActivateFirmware,goodPathDecodeResponse)3962 TEST(ActivateFirmware, goodPathDecodeResponse)
3963 {
3964     constexpr uint16_t estimatedTimeForActivation100s = 100;
3965     constexpr std::array<uint8_t, hdrSize + sizeof(pldm_activate_firmware_resp)>
3966         activateFirmwareResponse1{0x00, 0x00, 0x00, 0x00, 0x64, 0x00};
3967     auto responseMsg1 =
3968         // NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast)
3969         reinterpret_cast<const pldm_msg*>(activateFirmwareResponse1.data());
3970 
3971     uint8_t completionCode = 0;
3972     uint16_t estimatedTimeForActivation = 0;
3973 
3974     auto rc = decode_activate_firmware_resp(
3975         responseMsg1, sizeof(pldm_activate_firmware_resp), &completionCode,
3976         &estimatedTimeForActivation);
3977 
3978     EXPECT_EQ(rc, PLDM_SUCCESS);
3979     EXPECT_EQ(completionCode, PLDM_SUCCESS);
3980     EXPECT_EQ(estimatedTimeForActivation, estimatedTimeForActivation100s);
3981 
3982     constexpr std::array<uint8_t, hdrSize + sizeof(completionCode)>
3983         activateFirmwareResponse2{0x00, 0x00, 0x00, 0x85};
3984     auto responseMsg2 =
3985         // NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast)
3986         reinterpret_cast<const pldm_msg*>(activateFirmwareResponse2.data());
3987 
3988     rc = decode_activate_firmware_resp(responseMsg2, sizeof(completionCode),
3989                                        &completionCode,
3990                                        &estimatedTimeForActivation);
3991 
3992     EXPECT_EQ(rc, PLDM_SUCCESS);
3993     EXPECT_EQ(completionCode, PLDM_FWUP_INCOMPLETE_UPDATE);
3994 }
3995 
TEST(ActivateFirmware,errorPathDecodeResponse)3996 TEST(ActivateFirmware, errorPathDecodeResponse)
3997 {
3998     constexpr std::array<uint8_t, hdrSize + sizeof(pldm_activate_firmware_resp)>
3999         activateFirmwareResponse{0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
4000     auto responseMsg =
4001         // NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast)
4002         reinterpret_cast<const pldm_msg*>(activateFirmwareResponse.data());
4003 
4004     uint8_t completionCode = 0;
4005     uint16_t estimatedTimeForActivation = 0;
4006 
4007     auto rc = decode_activate_firmware_resp(
4008         nullptr, sizeof(pldm_activate_firmware_resp), &completionCode,
4009         &estimatedTimeForActivation);
4010     EXPECT_EQ(rc, PLDM_ERROR_INVALID_DATA);
4011 
4012     rc = decode_activate_firmware_resp(responseMsg,
4013                                        sizeof(pldm_activate_firmware_resp),
4014                                        nullptr, &estimatedTimeForActivation);
4015     EXPECT_EQ(rc, PLDM_ERROR_INVALID_DATA);
4016 
4017     rc = decode_activate_firmware_resp(responseMsg,
4018                                        sizeof(pldm_activate_firmware_resp),
4019                                        &completionCode, nullptr);
4020     EXPECT_EQ(rc, PLDM_ERROR_INVALID_DATA);
4021 
4022     rc = decode_activate_firmware_resp(responseMsg, 0, &completionCode,
4023                                        &estimatedTimeForActivation);
4024     EXPECT_EQ(rc, PLDM_ERROR_INVALID_DATA);
4025 
4026     rc = decode_activate_firmware_resp(
4027         responseMsg, sizeof(pldm_activate_firmware_resp) - 1, &completionCode,
4028         &estimatedTimeForActivation);
4029     EXPECT_EQ(rc, PLDM_ERROR_INVALID_LENGTH);
4030 }
4031 
TEST(GetStatus,goodPathEncodeRequest)4032 TEST(GetStatus, goodPathEncodeRequest)
4033 {
4034     constexpr uint8_t instanceId = 8;
4035     std::array<uint8_t, hdrSize> request{};
4036     // NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast)
4037     auto requestMsg = reinterpret_cast<pldm_msg*>(request.data());
4038 
4039     auto rc = encode_get_status_req(instanceId, requestMsg,
4040                                     PLDM_GET_STATUS_REQ_BYTES);
4041     EXPECT_EQ(rc, PLDM_SUCCESS);
4042 
4043     constexpr std::array<uint8_t, hdrSize> outRequest{0x88, 0x05, 0x1b};
4044     EXPECT_EQ(request, outRequest);
4045 }
4046 
TEST(GetStatus,errorPathEncodeRequest)4047 TEST(GetStatus, errorPathEncodeRequest)
4048 {
4049     std::array<uint8_t, hdrSize + sizeof(uint8_t)> request{};
4050     // NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast)
4051     auto requestMsg = reinterpret_cast<pldm_msg*>(request.data());
4052 
4053     auto rc = encode_get_status_req(0, nullptr, PLDM_GET_STATUS_REQ_BYTES);
4054     EXPECT_EQ(rc, PLDM_ERROR_INVALID_DATA);
4055 
4056     rc = encode_get_status_req(0, requestMsg, PLDM_GET_STATUS_REQ_BYTES + 1);
4057     EXPECT_EQ(rc, PLDM_ERROR_INVALID_LENGTH);
4058 }
4059 
TEST(GetStatus,goodPathDecodeResponse)4060 TEST(GetStatus, goodPathDecodeResponse)
4061 {
4062     constexpr std::bitset<32> updateOptionFlagsEnabled1{0};
4063     constexpr std::array<uint8_t, hdrSize + sizeof(pldm_get_status_resp)>
4064         getStatusResponse1{0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x03,
4065                            0x09, 0x65, 0x05, 0x00, 0x00, 0x00, 0x00};
4066     auto responseMsg1 =
4067         // NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast)
4068         reinterpret_cast<const pldm_msg*>(getStatusResponse1.data());
4069 
4070     uint8_t completionCode = 0;
4071     uint8_t currentState = 0;
4072     uint8_t previousState = 0;
4073     uint8_t auxState = 0;
4074     uint8_t auxStateStatus = 0;
4075     uint8_t progressPercent = 0;
4076     uint8_t reasonCode = 0;
4077     bitfield32_t updateOptionFlagsEnabled{0};
4078 
4079     auto rc = decode_get_status_resp(
4080         responseMsg1, getStatusResponse1.size() - hdrSize, &completionCode,
4081         &currentState, &previousState, &auxState, &auxStateStatus,
4082         &progressPercent, &reasonCode, &updateOptionFlagsEnabled);
4083 
4084     EXPECT_EQ(rc, PLDM_SUCCESS);
4085     EXPECT_EQ(completionCode, PLDM_SUCCESS);
4086     EXPECT_EQ(currentState, PLDM_FD_STATE_IDLE);
4087     EXPECT_EQ(previousState, PLDM_FD_STATE_DOWNLOAD);
4088     EXPECT_EQ(auxState, PLDM_FD_IDLE_LEARN_COMPONENTS_READ_XFER);
4089     EXPECT_EQ(auxStateStatus, PLDM_FD_TIMEOUT);
4090     EXPECT_EQ(progressPercent, PLDM_FWUP_MAX_PROGRESS_PERCENT);
4091     EXPECT_EQ(reasonCode, PLDM_FD_TIMEOUT_DOWNLOAD);
4092     EXPECT_EQ(updateOptionFlagsEnabled.value, updateOptionFlagsEnabled1);
4093 
4094     // Bit position 0 - Force update of component – FD will perform a force
4095     // update of the component.
4096     constexpr std::bitset<32> updateOptionFlagsEnabled2{1};
4097     constexpr uint8_t progressPercent2 = 50;
4098     constexpr std::array<uint8_t, hdrSize + sizeof(pldm_get_status_resp)>
4099         getStatusResponse2{0x00, 0x00, 0x00, 0x00, 0x04, 0x03, 0x00,
4100                            0x70, 0x32, 0x05, 0x01, 0x00, 0x00, 0x00};
4101     auto responseMsg2 =
4102         // NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast)
4103         reinterpret_cast<const pldm_msg*>(getStatusResponse2.data());
4104 
4105     rc = decode_get_status_resp(
4106         responseMsg2, getStatusResponse2.size() - hdrSize, &completionCode,
4107         &currentState, &previousState, &auxState, &auxStateStatus,
4108         &progressPercent, &reasonCode, &updateOptionFlagsEnabled);
4109 
4110     EXPECT_EQ(rc, PLDM_SUCCESS);
4111     EXPECT_EQ(completionCode, PLDM_SUCCESS);
4112     EXPECT_EQ(currentState, PLDM_FD_STATE_VERIFY);
4113     EXPECT_EQ(previousState, PLDM_FD_STATE_DOWNLOAD);
4114     EXPECT_EQ(auxState, PLDM_FD_OPERATION_IN_PROGRESS);
4115     EXPECT_EQ(auxStateStatus, PLDM_FD_VENDOR_DEFINED_STATUS_CODE_START);
4116     EXPECT_EQ(progressPercent, progressPercent2);
4117     EXPECT_EQ(reasonCode, PLDM_FD_TIMEOUT_DOWNLOAD);
4118     EXPECT_EQ(updateOptionFlagsEnabled.value, updateOptionFlagsEnabled2);
4119 
4120 #ifdef LIBPLDM_API_TESTING
4121     /* Check the roundtrip */
4122     PLDM_MSG_DEFINE_P(enc, 1000);
4123     size_t enc_payload_len = 1000;
4124     const struct pldm_get_status_resp status_enc = {
4125         .completion_code = PLDM_SUCCESS,
4126         .current_state = currentState,
4127         .previous_state = previousState,
4128         .aux_state = auxState,
4129         .aux_state_status = auxStateStatus,
4130         .progress_percent = progressPercent,
4131         .reason_code = reasonCode,
4132         .update_option_flags_enabled = updateOptionFlagsEnabled,
4133     };
4134     rc = encode_get_status_resp(FIXED_INSTANCE_ID, &status_enc, enc,
4135                                 &enc_payload_len);
4136     EXPECT_EQ(rc, PLDM_SUCCESS);
4137     EXPECT_EQ(enc_payload_len + hdrSize, getStatusResponse2.size());
4138     EXPECT_TRUE(std::equal(getStatusResponse2.begin() + hdrSize,
4139                            getStatusResponse2.end(), enc_buf + hdrSize));
4140     check_response(enc, PLDM_GET_STATUS);
4141 #endif
4142 
4143     /* Check a not-ready completion code */
4144     constexpr std::array<uint8_t, hdrSize + sizeof(completionCode)>
4145         getStatusResponse3{0x00, 0x00, 0x00, 0x04};
4146     auto responseMsg3 =
4147         // NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast)
4148         reinterpret_cast<const pldm_msg*>(getStatusResponse3.data());
4149     rc = decode_get_status_resp(
4150         responseMsg3, getStatusResponse3.size() - hdrSize, &completionCode,
4151         &currentState, &previousState, &auxState, &auxStateStatus,
4152         &progressPercent, &reasonCode, &updateOptionFlagsEnabled);
4153     EXPECT_EQ(rc, PLDM_SUCCESS);
4154     EXPECT_EQ(completionCode, PLDM_ERROR_NOT_READY);
4155 }
4156 
TEST(GetStatus,errorPathDecodeResponse)4157 TEST(GetStatus, errorPathDecodeResponse)
4158 {
4159     uint8_t completionCode = 0;
4160     uint8_t currentState = 0;
4161     uint8_t previousState = 0;
4162     uint8_t auxState = 0;
4163     uint8_t auxStateStatus = 0;
4164     uint8_t progressPercent = 0;
4165     uint8_t reasonCode = 0;
4166     bitfield32_t updateOptionFlagsEnabled{0};
4167 
4168     constexpr std::array<uint8_t, hdrSize> getStatusResponse1{0x00, 0x00, 0x00};
4169     auto responseMsg1 =
4170         // NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast)
4171         reinterpret_cast<const pldm_msg*>(getStatusResponse1.data());
4172 
4173     auto rc = decode_get_status_resp(
4174         nullptr, getStatusResponse1.size() - hdrSize, &completionCode,
4175         &currentState, &previousState, &auxState, &auxStateStatus,
4176         &progressPercent, &reasonCode, &updateOptionFlagsEnabled);
4177     EXPECT_EQ(rc, PLDM_ERROR_INVALID_DATA);
4178 
4179     rc = decode_get_status_resp(
4180         responseMsg1, getStatusResponse1.size() - hdrSize, nullptr,
4181         &currentState, &previousState, &auxState, &auxStateStatus,
4182         &progressPercent, &reasonCode, &updateOptionFlagsEnabled);
4183     EXPECT_EQ(rc, PLDM_ERROR_INVALID_DATA);
4184 
4185     rc = decode_get_status_resp(
4186         responseMsg1, getStatusResponse1.size() - hdrSize, &completionCode,
4187         nullptr, &previousState, &auxState, &auxStateStatus, &progressPercent,
4188         &reasonCode, &updateOptionFlagsEnabled);
4189     EXPECT_EQ(rc, PLDM_ERROR_INVALID_DATA);
4190 
4191     rc = decode_get_status_resp(
4192         responseMsg1, getStatusResponse1.size() - hdrSize, &completionCode,
4193         &currentState, nullptr, &auxState, &auxStateStatus, &progressPercent,
4194         &reasonCode, &updateOptionFlagsEnabled);
4195     EXPECT_EQ(rc, PLDM_ERROR_INVALID_DATA);
4196 
4197     rc = decode_get_status_resp(
4198         responseMsg1, getStatusResponse1.size() - hdrSize, &completionCode,
4199         &currentState, &previousState, nullptr, &auxStateStatus,
4200         &progressPercent, &reasonCode, &updateOptionFlagsEnabled);
4201     EXPECT_EQ(rc, PLDM_ERROR_INVALID_DATA);
4202 
4203     rc = decode_get_status_resp(
4204         responseMsg1, getStatusResponse1.size() - hdrSize, &completionCode,
4205         &currentState, &previousState, &auxState, nullptr, &progressPercent,
4206         &reasonCode, &updateOptionFlagsEnabled);
4207     EXPECT_EQ(rc, PLDM_ERROR_INVALID_DATA);
4208 
4209     rc = decode_get_status_resp(
4210         responseMsg1, getStatusResponse1.size() - hdrSize, &completionCode,
4211         &currentState, &previousState, &auxState, &auxStateStatus, nullptr,
4212         &reasonCode, &updateOptionFlagsEnabled);
4213     EXPECT_EQ(rc, PLDM_ERROR_INVALID_DATA);
4214 
4215     rc = decode_get_status_resp(
4216         responseMsg1, getStatusResponse1.size() - hdrSize, &completionCode,
4217         &currentState, &previousState, &auxState, &auxStateStatus,
4218         &progressPercent, nullptr, &updateOptionFlagsEnabled);
4219     EXPECT_EQ(rc, PLDM_ERROR_INVALID_DATA);
4220 
4221     rc = decode_get_status_resp(
4222         responseMsg1, getStatusResponse1.size() - hdrSize, &completionCode,
4223         &currentState, &previousState, &auxState, &auxStateStatus,
4224         &progressPercent, &reasonCode, nullptr);
4225     EXPECT_EQ(rc, PLDM_ERROR_INVALID_DATA);
4226 
4227     rc = decode_get_status_resp(
4228         responseMsg1, getStatusResponse1.size() - hdrSize, &completionCode,
4229         &currentState, &previousState, &auxState, &auxStateStatus,
4230         &progressPercent, &reasonCode, &updateOptionFlagsEnabled);
4231     EXPECT_EQ(rc, PLDM_ERROR_INVALID_DATA);
4232 
4233     constexpr std::array<uint8_t, hdrSize + sizeof(pldm_get_status_resp) - 1>
4234         getStatusResponse2{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
4235                            0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
4236     auto responseMsg2 =
4237         // NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast)
4238         reinterpret_cast<const pldm_msg*>(getStatusResponse2.data());
4239     rc = decode_get_status_resp(
4240         responseMsg2, getStatusResponse2.size() - hdrSize, &completionCode,
4241         &currentState, &previousState, &auxState, &auxStateStatus,
4242         &progressPercent, &reasonCode, &updateOptionFlagsEnabled);
4243     EXPECT_EQ(rc, PLDM_ERROR_INVALID_LENGTH);
4244 
4245     constexpr std::array<uint8_t, hdrSize + sizeof(pldm_get_status_resp)>
4246         getStatusResponse3{0x00, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00,
4247                            0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
4248     auto responseMsg3 =
4249         // NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast)
4250         reinterpret_cast<const pldm_msg*>(getStatusResponse3.data());
4251     rc = decode_get_status_resp(
4252         responseMsg3, getStatusResponse3.size() - hdrSize, &completionCode,
4253         &currentState, &previousState, &auxState, &auxStateStatus,
4254         &progressPercent, &reasonCode, &updateOptionFlagsEnabled);
4255     EXPECT_EQ(rc, PLDM_ERROR_INVALID_DATA);
4256 
4257     constexpr std::array<uint8_t, hdrSize + sizeof(pldm_get_status_resp)>
4258         getStatusResponse4{0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x00,
4259                            0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
4260     auto responseMsg4 =
4261         // NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast)
4262         reinterpret_cast<const pldm_msg*>(getStatusResponse4.data());
4263     rc = decode_get_status_resp(
4264         responseMsg4, getStatusResponse4.size() - hdrSize, &completionCode,
4265         &currentState, &previousState, &auxState, &auxStateStatus,
4266         &progressPercent, &reasonCode, &updateOptionFlagsEnabled);
4267     EXPECT_EQ(rc, PLDM_ERROR_INVALID_DATA);
4268 
4269     constexpr std::array<uint8_t, hdrSize + sizeof(pldm_get_status_resp)>
4270         getStatusResponse5{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04,
4271                            0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
4272     auto responseMsg5 =
4273         // NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast)
4274         reinterpret_cast<const pldm_msg*>(getStatusResponse5.data());
4275     rc = decode_get_status_resp(
4276         responseMsg5, getStatusResponse5.size() - hdrSize, &completionCode,
4277         &currentState, &previousState, &auxState, &auxStateStatus,
4278         &progressPercent, &reasonCode, &updateOptionFlagsEnabled);
4279     EXPECT_EQ(rc, PLDM_ERROR_INVALID_DATA);
4280 
4281     constexpr std::array<uint8_t, hdrSize + sizeof(pldm_get_status_resp)>
4282         getStatusResponse6{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
4283                            0x0b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
4284     auto responseMsg6 =
4285         // NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast)
4286         reinterpret_cast<const pldm_msg*>(getStatusResponse6.data());
4287     rc = decode_get_status_resp(
4288         responseMsg6, getStatusResponse6.size() - hdrSize, &completionCode,
4289         &currentState, &previousState, &auxState, &auxStateStatus,
4290         &progressPercent, &reasonCode, &updateOptionFlagsEnabled);
4291     EXPECT_EQ(rc, PLDM_ERROR_INVALID_DATA);
4292 
4293     constexpr std::array<uint8_t, hdrSize + sizeof(pldm_get_status_resp)>
4294         getStatusResponse7{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
4295                            0x00, 0x66, 0x00, 0x00, 0x00, 0x00, 0x00};
4296     auto responseMsg7 =
4297         // NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast)
4298         reinterpret_cast<const pldm_msg*>(getStatusResponse7.data());
4299     rc = decode_get_status_resp(
4300         responseMsg7, getStatusResponse7.size() - hdrSize, &completionCode,
4301         &currentState, &previousState, &auxState, &auxStateStatus,
4302         &progressPercent, &reasonCode, &updateOptionFlagsEnabled);
4303     EXPECT_EQ(rc, PLDM_ERROR_INVALID_DATA);
4304 
4305     constexpr std::array<uint8_t, hdrSize + sizeof(pldm_get_status_resp)>
4306         getStatusResponse8{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
4307                            0x00, 0x00, 0xc7, 0x00, 0x00, 0x00, 0x00};
4308     auto responseMsg8 =
4309         // NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast)
4310         reinterpret_cast<const pldm_msg*>(getStatusResponse8.data());
4311     rc = decode_get_status_resp(
4312         responseMsg8, getStatusResponse8.size() - hdrSize, &completionCode,
4313         &currentState, &previousState, &auxState, &auxStateStatus,
4314         &progressPercent, &reasonCode, &updateOptionFlagsEnabled);
4315     EXPECT_EQ(rc, PLDM_ERROR_INVALID_DATA);
4316 
4317     // AuxState is not PLDM_FD_IDLE_LEARN_COMPONENTS_READ_XFER when the state is
4318     // IDLE
4319     constexpr std::array<uint8_t, hdrSize + sizeof(pldm_get_status_resp)>
4320         getStatusResponse9{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
4321                            0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
4322     auto responseMsg9 =
4323         // NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast)
4324         reinterpret_cast<const pldm_msg*>(getStatusResponse9.data());
4325     rc = decode_get_status_resp(
4326         responseMsg9, getStatusResponse9.size() - hdrSize, &completionCode,
4327         &currentState, &previousState, &auxState, &auxStateStatus,
4328         &progressPercent, &reasonCode, &updateOptionFlagsEnabled);
4329     EXPECT_EQ(rc, PLDM_ERROR_INVALID_DATA);
4330 }
4331 
TEST(CancelUpdateComponent,goodPathEncodeRequest)4332 TEST(CancelUpdateComponent, goodPathEncodeRequest)
4333 {
4334     constexpr uint8_t instanceId = 9;
4335     std::array<uint8_t, hdrSize> request{};
4336     // NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast)
4337     auto requestMsg = reinterpret_cast<pldm_msg*>(request.data());
4338 
4339     auto rc = encode_cancel_update_component_req(
4340         instanceId, requestMsg, PLDM_CANCEL_UPDATE_COMPONENT_REQ_BYTES);
4341     EXPECT_EQ(rc, PLDM_SUCCESS);
4342 
4343     constexpr std::array<uint8_t, hdrSize> outRequest{0x89, 0x05, 0x1c};
4344     EXPECT_EQ(request, outRequest);
4345 }
4346 
TEST(CancelUpdateComponent,errorPathEncodeRequest)4347 TEST(CancelUpdateComponent, errorPathEncodeRequest)
4348 {
4349     std::array<uint8_t, hdrSize + sizeof(uint8_t)> request{};
4350     // NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast)
4351     auto requestMsg = reinterpret_cast<pldm_msg*>(request.data());
4352 
4353     auto rc = encode_cancel_update_component_req(
4354         0, nullptr, PLDM_CANCEL_UPDATE_COMPONENT_REQ_BYTES);
4355     EXPECT_EQ(rc, PLDM_ERROR_INVALID_DATA);
4356 
4357     rc = encode_cancel_update_component_req(
4358         0, requestMsg, PLDM_CANCEL_UPDATE_COMPONENT_REQ_BYTES + 1);
4359     EXPECT_EQ(rc, PLDM_ERROR_INVALID_LENGTH);
4360 }
4361 
TEST(CancelUpdateComponent,testGoodDecodeResponse)4362 TEST(CancelUpdateComponent, testGoodDecodeResponse)
4363 {
4364     uint8_t completionCode = 0;
4365     constexpr std::array<uint8_t, hdrSize + sizeof(completionCode)>
4366         cancelUpdateComponentResponse1{0x00, 0x00, 0x00, 0x00};
4367     // NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast)
4368     auto responseMsg1 = reinterpret_cast<const pldm_msg*>(
4369         cancelUpdateComponentResponse1.data());
4370     auto rc = decode_cancel_update_component_resp(
4371         responseMsg1, cancelUpdateComponentResponse1.size() - hdrSize,
4372         &completionCode);
4373     EXPECT_EQ(rc, PLDM_SUCCESS);
4374     EXPECT_EQ(completionCode, PLDM_SUCCESS);
4375 
4376     constexpr std::array<uint8_t, hdrSize + sizeof(completionCode)>
4377         cancelUpdateComponentResponse2{0x00, 0x00, 0x00, 0x86};
4378     // NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast)
4379     auto responseMsg2 = reinterpret_cast<const pldm_msg*>(
4380         cancelUpdateComponentResponse2.data());
4381     rc = decode_cancel_update_component_resp(
4382         responseMsg2, cancelUpdateComponentResponse2.size() - hdrSize,
4383         &completionCode);
4384     EXPECT_EQ(rc, PLDM_SUCCESS);
4385     EXPECT_EQ(completionCode, PLDM_FWUP_BUSY_IN_BACKGROUND);
4386 }
4387 
TEST(CancelUpdateComponent,testBadDecodeResponse)4388 TEST(CancelUpdateComponent, testBadDecodeResponse)
4389 {
4390     uint8_t completionCode = 0;
4391     constexpr std::array<uint8_t, hdrSize> cancelUpdateComponentResponse{
4392         0x00, 0x00, 0x00};
4393     auto responseMsg =
4394         // NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast)
4395         reinterpret_cast<const pldm_msg*>(cancelUpdateComponentResponse.data());
4396 
4397     auto rc = decode_cancel_update_component_resp(
4398         nullptr, cancelUpdateComponentResponse.size() - hdrSize,
4399         &completionCode);
4400     EXPECT_EQ(rc, PLDM_ERROR_INVALID_DATA);
4401 
4402     rc = decode_cancel_update_component_resp(
4403         responseMsg, cancelUpdateComponentResponse.size() - hdrSize, nullptr);
4404     EXPECT_EQ(rc, PLDM_ERROR_INVALID_DATA);
4405 
4406     rc = decode_cancel_update_component_resp(
4407         responseMsg, cancelUpdateComponentResponse.size() - hdrSize,
4408         &completionCode);
4409     EXPECT_EQ(rc, PLDM_ERROR_INVALID_LENGTH);
4410 }
4411 
TEST(CancelUpdate,goodPathEncodeRequest)4412 TEST(CancelUpdate, goodPathEncodeRequest)
4413 {
4414     constexpr uint8_t instanceId = 10;
4415     std::array<uint8_t, hdrSize> request{};
4416     // NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast)
4417     auto requestMsg = reinterpret_cast<pldm_msg*>(request.data());
4418 
4419     auto rc = encode_cancel_update_req(instanceId, requestMsg,
4420                                        PLDM_CANCEL_UPDATE_REQ_BYTES);
4421     EXPECT_EQ(rc, PLDM_SUCCESS);
4422 
4423     constexpr std::array<uint8_t, hdrSize> outRequest{0x8a, 0x05, 0x1d};
4424     EXPECT_EQ(request, outRequest);
4425 }
4426 
TEST(CancelUpdate,errorPathEncodeRequest)4427 TEST(CancelUpdate, errorPathEncodeRequest)
4428 {
4429     std::array<uint8_t, hdrSize + sizeof(uint8_t)> request{};
4430     // NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast)
4431     auto requestMsg = reinterpret_cast<pldm_msg*>(request.data());
4432 
4433     auto rc =
4434         encode_cancel_update_req(0, nullptr, PLDM_CANCEL_UPDATE_REQ_BYTES);
4435     EXPECT_EQ(rc, PLDM_ERROR_INVALID_DATA);
4436 
4437     rc = encode_cancel_update_req(0, requestMsg,
4438                                   PLDM_CANCEL_UPDATE_REQ_BYTES + 1);
4439     EXPECT_EQ(rc, PLDM_ERROR_INVALID_LENGTH);
4440 }
4441 
TEST(CancelUpdate,goodPathDecodeResponse)4442 TEST(CancelUpdate, goodPathDecodeResponse)
4443 {
4444     constexpr std::bitset<64> nonFunctioningComponentBitmap1{0};
4445     constexpr std::array<uint8_t, hdrSize + sizeof(pldm_cancel_update_resp)>
4446         cancelUpdateResponse1{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
4447                               0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
4448     auto responseMsg1 =
4449         // NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast)
4450         reinterpret_cast<const pldm_msg*>(cancelUpdateResponse1.data());
4451     uint8_t completionCode = 0;
4452     bool8_t nonFunctioningComponentIndication = 0;
4453     bitfield64_t nonFunctioningComponentBitmap{0};
4454     auto rc = decode_cancel_update_resp(
4455         responseMsg1, cancelUpdateResponse1.size() - hdrSize, &completionCode,
4456         &nonFunctioningComponentIndication, &nonFunctioningComponentBitmap);
4457     EXPECT_EQ(rc, PLDM_SUCCESS);
4458     EXPECT_EQ(completionCode, PLDM_SUCCESS);
4459     EXPECT_EQ(nonFunctioningComponentIndication,
4460               PLDM_FWUP_COMPONENTS_FUNCTIONING);
4461     EXPECT_EQ(nonFunctioningComponentBitmap.value,
4462               nonFunctioningComponentBitmap1);
4463 
4464     constexpr std::bitset<64> nonFunctioningComponentBitmap2{0x0101};
4465     constexpr std::array<uint8_t, hdrSize + sizeof(pldm_cancel_update_resp)>
4466         cancelUpdateResponse2{0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01,
4467                               0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
4468     auto responseMsg2 =
4469         // NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast)
4470         reinterpret_cast<const pldm_msg*>(cancelUpdateResponse2.data());
4471     rc = decode_cancel_update_resp(
4472         responseMsg2, cancelUpdateResponse2.size() - hdrSize, &completionCode,
4473         &nonFunctioningComponentIndication, &nonFunctioningComponentBitmap);
4474     EXPECT_EQ(rc, PLDM_SUCCESS);
4475     EXPECT_EQ(completionCode, PLDM_SUCCESS);
4476     EXPECT_EQ(nonFunctioningComponentIndication,
4477               PLDM_FWUP_COMPONENTS_NOT_FUNCTIONING);
4478     EXPECT_EQ(nonFunctioningComponentBitmap.value,
4479               nonFunctioningComponentBitmap2);
4480 
4481     constexpr std::array<uint8_t, hdrSize + sizeof(completionCode)>
4482         cancelUpdateResponse3{0x00, 0x00, 0x00, 0x86};
4483     auto responseMsg3 =
4484         // NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast)
4485         reinterpret_cast<const pldm_msg*>(cancelUpdateResponse3.data());
4486     rc = decode_cancel_update_resp(
4487         responseMsg3, cancelUpdateResponse3.size() - hdrSize, &completionCode,
4488         &nonFunctioningComponentIndication, &nonFunctioningComponentBitmap);
4489     EXPECT_EQ(rc, PLDM_SUCCESS);
4490     EXPECT_EQ(completionCode, PLDM_FWUP_BUSY_IN_BACKGROUND);
4491 }
4492 
TEST(CancelUpdate,errorPathDecodeResponse)4493 TEST(CancelUpdate, errorPathDecodeResponse)
4494 {
4495     constexpr std::array<uint8_t, hdrSize> cancelUpdateResponse1{0x00, 0x00,
4496                                                                  0x00};
4497     auto responseMsg1 =
4498         // NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast)
4499         reinterpret_cast<const pldm_msg*>(cancelUpdateResponse1.data());
4500     uint8_t completionCode = 0;
4501     bool8_t nonFunctioningComponentIndication = 0;
4502     bitfield64_t nonFunctioningComponentBitmap{0};
4503 
4504     auto rc = decode_cancel_update_resp(
4505         nullptr, cancelUpdateResponse1.size() - hdrSize, &completionCode,
4506         &nonFunctioningComponentIndication, &nonFunctioningComponentBitmap);
4507     EXPECT_EQ(rc, PLDM_ERROR_INVALID_DATA);
4508 
4509     rc = decode_cancel_update_resp(
4510         responseMsg1, cancelUpdateResponse1.size() - hdrSize, nullptr,
4511         &nonFunctioningComponentIndication, &nonFunctioningComponentBitmap);
4512     EXPECT_EQ(rc, PLDM_ERROR_INVALID_DATA);
4513 
4514     rc = decode_cancel_update_resp(
4515         responseMsg1, cancelUpdateResponse1.size() - hdrSize, &completionCode,
4516         nullptr, &nonFunctioningComponentBitmap);
4517     EXPECT_EQ(rc, PLDM_ERROR_INVALID_DATA);
4518 
4519     rc = decode_cancel_update_resp(
4520         responseMsg1, cancelUpdateResponse1.size() - hdrSize, &completionCode,
4521         &nonFunctioningComponentIndication, nullptr);
4522     EXPECT_EQ(rc, PLDM_ERROR_INVALID_DATA);
4523 
4524     rc = decode_cancel_update_resp(
4525         responseMsg1, cancelUpdateResponse1.size() - hdrSize, &completionCode,
4526         &nonFunctioningComponentIndication, &nonFunctioningComponentBitmap);
4527     EXPECT_EQ(rc, PLDM_ERROR_INVALID_DATA);
4528 
4529     constexpr std::array<uint8_t, hdrSize + sizeof(completionCode)>
4530         cancelUpdateResponse2{0x00, 0x00, 0x00, 0x00};
4531     auto responseMsg2 =
4532         // NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast)
4533         reinterpret_cast<const pldm_msg*>(cancelUpdateResponse2.data());
4534     rc = decode_cancel_update_resp(
4535         responseMsg2, cancelUpdateResponse2.size() - hdrSize, &completionCode,
4536         &nonFunctioningComponentIndication, &nonFunctioningComponentBitmap);
4537     EXPECT_EQ(rc, PLDM_ERROR_INVALID_LENGTH);
4538 
4539     constexpr std::array<uint8_t, hdrSize + sizeof(pldm_cancel_update_resp)>
4540         cancelUpdateResponse3{0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00,
4541                               0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
4542     auto responseMsg3 =
4543         // NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast)
4544         reinterpret_cast<const pldm_msg*>(cancelUpdateResponse3.data());
4545     rc = decode_cancel_update_resp(
4546         responseMsg3, cancelUpdateResponse3.size() - hdrSize, &completionCode,
4547         &nonFunctioningComponentIndication, &nonFunctioningComponentBitmap);
4548     EXPECT_EQ(rc, PLDM_ERROR_INVALID_DATA);
4549 }
4550