xref: /openbmc/libpldm/tests/dsp/firmware_update.cpp (revision 412fa270c3999a38a911e84088a6b7a8ccf59121)
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 */
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 = 0;
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 
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 
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 
2960 #ifdef LIBPLDM_API_TESTING
2961 TEST(RequestDownstreamDeviceUpdate, goodPathEncodeRequest)
2962 {
2963     constexpr uint8_t instanceId = 1;
2964 
2965     std::array<uint8_t, hdrSize + PLDM_DOWNSTREAM_DEVICE_UPDATE_REQUEST_BYTES>
2966         request{};
2967 
2968     auto requestMsg = new (request.data()) pldm_msg;
2969 
2970     constexpr struct pldm_request_downstream_device_update_req req_data = {
2971         .maximum_downstream_device_transfer_size = 512,
2972         .maximum_outstanding_transfer_requests = 2,
2973         .downstream_device_package_data_length = 0x1234,
2974     };
2975     size_t enc_payload_len = PLDM_DOWNSTREAM_DEVICE_UPDATE_REQUEST_BYTES;
2976 
2977     auto rc = encode_request_downstream_device_update_req(
2978         instanceId, &req_data, requestMsg, &enc_payload_len);
2979 
2980     EXPECT_EQ(rc, 0);
2981 
2982     std::array<uint8_t, hdrSize + PLDM_DOWNSTREAM_DEVICE_UPDATE_REQUEST_BYTES>
2983         outRequest{0x81, 0x05, 0x20, 0x00, 0x02, 0x00, 0x00, 0x02, 0x34, 0x12};
2984     EXPECT_EQ(request, outRequest);
2985 }
2986 #endif // LIBPLDM_API_TESTING
2987 
2988 #ifdef LIBPLDM_API_TESTING
2989 TEST(RequestDownstreamDeviceUpdate, errorPathEncodeRequest)
2990 {
2991     constexpr uint8_t instanceId = 1;
2992     size_t enc_payload_len = PLDM_DOWNSTREAM_DEVICE_UPDATE_REQUEST_BYTES;
2993 
2994     std::array<uint8_t, hdrSize + PLDM_DOWNSTREAM_DEVICE_UPDATE_REQUEST_BYTES>
2995         request{};
2996 
2997     struct pldm_request_downstream_device_update_req req_data = {
2998         .maximum_downstream_device_transfer_size = 512,
2999         .maximum_outstanding_transfer_requests = 2,
3000         .downstream_device_package_data_length = 0x1234,
3001     };
3002 
3003     auto requestMsg = new (request.data()) pldm_msg;
3004 
3005     auto rc = encode_request_downstream_device_update_req(
3006         instanceId, nullptr, requestMsg, &enc_payload_len);
3007     EXPECT_EQ(rc, -EINVAL);
3008     rc = encode_request_downstream_device_update_req(
3009         instanceId, &req_data, requestMsg, &enc_payload_len);
3010     EXPECT_EQ(rc, 0);
3011 
3012     rc = encode_request_downstream_device_update_req(instanceId, &req_data,
3013                                                      nullptr, &enc_payload_len);
3014     EXPECT_EQ(rc, -EINVAL);
3015     rc = encode_request_downstream_device_update_req(
3016         instanceId, &req_data, requestMsg, &enc_payload_len);
3017     EXPECT_EQ(rc, 0);
3018 
3019     rc = encode_request_downstream_device_update_req(instanceId, &req_data,
3020                                                      requestMsg, nullptr);
3021     EXPECT_EQ(rc, -EINVAL);
3022     rc = encode_request_downstream_device_update_req(
3023         instanceId, &req_data, requestMsg, &enc_payload_len);
3024     EXPECT_EQ(rc, 0);
3025 
3026     enc_payload_len =
3027         static_cast<size_t>(PLDM_DOWNSTREAM_DEVICE_UPDATE_REQUEST_BYTES) - 1;
3028     rc = encode_request_downstream_device_update_req(
3029         instanceId, &req_data, requestMsg, &enc_payload_len);
3030     EXPECT_EQ(rc, -EOVERFLOW);
3031     enc_payload_len =
3032         static_cast<size_t>(PLDM_DOWNSTREAM_DEVICE_UPDATE_REQUEST_BYTES);
3033     rc = encode_request_downstream_device_update_req(
3034         instanceId, &req_data, requestMsg, &enc_payload_len);
3035     EXPECT_EQ(rc, 0);
3036 
3037     req_data.maximum_downstream_device_transfer_size = 31;
3038     rc = encode_request_downstream_device_update_req(
3039         instanceId, &req_data, requestMsg, &enc_payload_len);
3040     EXPECT_EQ(rc, -EINVAL);
3041     req_data.maximum_downstream_device_transfer_size =
3042         PLDM_FWUP_BASELINE_TRANSFER_SIZE;
3043 
3044     req_data.maximum_outstanding_transfer_requests = 0;
3045     rc = encode_request_downstream_device_update_req(
3046         instanceId, &req_data, requestMsg, &enc_payload_len);
3047     EXPECT_EQ(rc, -EINVAL);
3048     req_data.maximum_outstanding_transfer_requests = 2;
3049     rc = encode_request_downstream_device_update_req(
3050         instanceId, &req_data, requestMsg, &enc_payload_len);
3051     EXPECT_EQ(rc, 0);
3052 }
3053 #endif // LIBPLDM_API_TESTING
3054 
3055 #ifdef LIBPLDM_API_TESTING
3056 TEST(RequestDownstreamDeviceUpdate, goodPathDecodeResponse)
3057 {
3058     /* Test a success completion code */
3059     constexpr uint16_t ddMetaDataLen = 1024;
3060     constexpr uint8_t ddWillSendPkgData = 1;
3061     constexpr uint16_t getPkgDataMaxTransferSize = 512;
3062     std::array<uint8_t, hdrSize + PLDM_DOWNSTREAM_DEVICE_UPDATE_RESPONSE_BYTES>
3063         requestUpdateResponse1{0x00, 0x00, 0x00, 0x00, 0x00,
3064                                0x04, 0x01, 0x00, 0x02};
3065 
3066     auto responseMsg1 = new (requestUpdateResponse1.data()) pldm_msg;
3067 
3068     struct pldm_request_downstream_device_update_resp resp_data1 = {
3069         .completion_code = 0,
3070         .downstream_device_meta_data_length = 0,
3071         .downstream_device_will_send_get_package_data = 0,
3072         .get_package_data_maximum_transfer_size = 0};
3073 
3074     auto rc = decode_request_downstream_device_update_resp(
3075         responseMsg1, PLDM_DOWNSTREAM_DEVICE_UPDATE_RESPONSE_BYTES,
3076         &resp_data1);
3077     EXPECT_EQ(rc, 0);
3078     EXPECT_EQ(resp_data1.completion_code, PLDM_SUCCESS);
3079     EXPECT_EQ(resp_data1.downstream_device_meta_data_length, ddMetaDataLen);
3080     EXPECT_EQ(resp_data1.downstream_device_will_send_get_package_data,
3081               ddWillSendPkgData);
3082     EXPECT_EQ(resp_data1.get_package_data_maximum_transfer_size,
3083               getPkgDataMaxTransferSize);
3084 
3085     /* Test a failure completion code */
3086     std::array<uint8_t, hdrSize + PLDM_DOWNSTREAM_DEVICE_UPDATE_RESPONSE_BYTES>
3087         requestUpdateResponse2{0x00, 0x00, 0x00, 0x81};
3088 
3089     auto responseMsg2 = new (requestUpdateResponse2.data()) pldm_msg;
3090 
3091     struct pldm_request_downstream_device_update_resp resp_data2 = {
3092         .completion_code = 0,
3093         .downstream_device_meta_data_length = 0,
3094         .downstream_device_will_send_get_package_data = 0,
3095         .get_package_data_maximum_transfer_size = 0};
3096 
3097     rc = decode_request_downstream_device_update_resp(
3098         responseMsg2, PLDM_DOWNSTREAM_DEVICE_UPDATE_RESPONSE_BYTES,
3099         &resp_data2);
3100     EXPECT_EQ(rc, 0);
3101     EXPECT_EQ(resp_data2.completion_code, PLDM_FWUP_ALREADY_IN_UPDATE_MODE);
3102 }
3103 #endif // LIBPLDM_API_TESTING
3104 
3105 #ifdef LIBPLDM_API_TESTING
3106 TEST(RequestDownstreamDeviceUpdate, errorPathDecodeResponse)
3107 {
3108     std::array<uint8_t, hdrSize + PLDM_DOWNSTREAM_DEVICE_UPDATE_RESPONSE_BYTES>
3109         requestUpdateResponse{0x00, 0x00, 0x00, 0x00, 0x00,
3110                               0x04, 0x01, 0x00, 0x02};
3111 
3112     auto responseMsg = new (requestUpdateResponse.data()) pldm_msg;
3113 
3114     struct pldm_request_downstream_device_update_resp resp_data = {
3115         .completion_code = 0,
3116         .downstream_device_meta_data_length = 0,
3117         .downstream_device_will_send_get_package_data = 0,
3118         .get_package_data_maximum_transfer_size = 0};
3119 
3120     auto rc = decode_request_downstream_device_update_resp(
3121         nullptr, PLDM_DOWNSTREAM_DEVICE_UPDATE_RESPONSE_BYTES, &resp_data);
3122     EXPECT_EQ(rc, -EINVAL);
3123 
3124     rc = decode_request_downstream_device_update_resp(
3125         responseMsg, PLDM_DOWNSTREAM_DEVICE_UPDATE_RESPONSE_BYTES, nullptr);
3126     EXPECT_EQ(rc, -EINVAL);
3127 
3128     rc = decode_request_downstream_device_update_resp(responseMsg, 0,
3129                                                       &resp_data);
3130     EXPECT_EQ(rc, -EOVERFLOW);
3131 }
3132 #endif // LIBPLDM_API_TESTING
3133 
3134 TEST(PassComponentTable, goodPathEncodeRequest)
3135 {
3136     constexpr uint8_t instanceId = 1;
3137     constexpr uint16_t compIdentifier = 400;
3138     constexpr uint8_t compClassificationIndex = 40;
3139     constexpr uint32_t compComparisonStamp = 0x12345678;
3140     constexpr std::string_view compVerStr = "0penBmcv1.1";
3141     constexpr uint8_t compVerStrLen = static_cast<uint8_t>(compVerStr.size());
3142     variable_field compVerStrInfo{};
3143     // NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast)
3144     compVerStrInfo.ptr = reinterpret_cast<const uint8_t*>(compVerStr.data());
3145     compVerStrInfo.length = compVerStrLen;
3146 
3147     std::array<uint8_t,
3148                hdrSize + sizeof(pldm_pass_component_table_req) + compVerStrLen>
3149         request{};
3150     // NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast)
3151     auto requestMsg = reinterpret_cast<pldm_msg*>(request.data());
3152 
3153     auto rc = encode_pass_component_table_req(
3154         instanceId, PLDM_START_AND_END, PLDM_COMP_FIRMWARE, compIdentifier,
3155         compClassificationIndex, compComparisonStamp, PLDM_STR_TYPE_ASCII,
3156         compVerStrLen, &compVerStrInfo, requestMsg,
3157         sizeof(pldm_pass_component_table_req) + compVerStrLen);
3158     EXPECT_EQ(rc, PLDM_SUCCESS);
3159 
3160     std::array<uint8_t,
3161                hdrSize + sizeof(pldm_pass_component_table_req) + compVerStrLen>
3162         outRequest{0x81, 0x05, 0x13, 0x05, 0x0a, 0x00, 0x90, 0x01, 0x28,
3163                    0x78, 0x56, 0x34, 0x12, 0x01, 0x0b, 0x30, 0x70, 0x65,
3164                    0x6e, 0x42, 0x6d, 0x63, 0x76, 0x31, 0x2e, 0x31};
3165     EXPECT_EQ(request, outRequest);
3166 
3167 #ifdef LIBPLDM_API_TESTING
3168     /* Check the roundtrip */
3169     struct pldm_pass_component_table_req_full req;
3170     PLDM_MSG_DEFINE_P(dec, outRequest.size());
3171     std::copy(outRequest.begin(), outRequest.end(), dec_buf);
3172     rc =
3173         decode_pass_component_table_req(dec, outRequest.size() - hdrSize, &req);
3174     ASSERT_EQ(rc, 0);
3175 
3176     EXPECT_EQ(req.transfer_flag, PLDM_START_AND_END);
3177     EXPECT_EQ(req.comp_classification, PLDM_COMP_FIRMWARE);
3178     EXPECT_EQ(req.comp_identifier, compIdentifier);
3179     EXPECT_EQ(req.comp_classification_index, compClassificationIndex);
3180     EXPECT_EQ(req.comp_comparison_stamp, compComparisonStamp);
3181     EXPECT_EQ(req.version.str_type, PLDM_STR_TYPE_ASCII);
3182     EXPECT_EQ(req.version.str_len, compVerStrLen);
3183     EXPECT_TRUE(std::equal(req.version.str_data,
3184                            req.version.str_data + req.version.str_len,
3185                            compVerStr.data()));
3186 #endif
3187 }
3188 
3189 TEST(PassComponentTable, errorPathEncodeRequest)
3190 {
3191     constexpr uint8_t instanceId = 1;
3192     constexpr uint16_t compIdentifier = 400;
3193     constexpr uint8_t compClassificationIndex = 40;
3194     constexpr uint32_t compComparisonStamp = 0x12345678;
3195     constexpr std::string_view compVerStr = "0penBmcv1.1";
3196     constexpr uint8_t compVerStrLen = static_cast<uint8_t>(compVerStr.size());
3197     variable_field compVerStrInfo{};
3198     // NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast)
3199     compVerStrInfo.ptr = reinterpret_cast<const uint8_t*>(compVerStr.data());
3200     compVerStrInfo.length = compVerStrLen;
3201 
3202     std::array<uint8_t,
3203                hdrSize + sizeof(pldm_pass_component_table_req) + compVerStrLen>
3204         request{};
3205     // NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast)
3206     auto requestMsg = reinterpret_cast<pldm_msg*>(request.data());
3207 
3208     auto rc = encode_pass_component_table_req(
3209         instanceId, PLDM_START_AND_END, PLDM_COMP_FIRMWARE, compIdentifier,
3210         compClassificationIndex, compComparisonStamp, PLDM_STR_TYPE_ASCII,
3211         compVerStrLen, nullptr, requestMsg,
3212         sizeof(pldm_pass_component_table_req) + compVerStrLen);
3213     EXPECT_EQ(rc, PLDM_ERROR_INVALID_DATA);
3214 
3215     compVerStrInfo.ptr = nullptr;
3216     rc = encode_pass_component_table_req(
3217         instanceId, PLDM_START_AND_END, PLDM_COMP_FIRMWARE, compIdentifier,
3218         compClassificationIndex, compComparisonStamp, PLDM_STR_TYPE_ASCII,
3219         compVerStrLen, &compVerStrInfo, requestMsg,
3220         sizeof(pldm_pass_component_table_req) + compVerStrLen);
3221     EXPECT_EQ(rc, PLDM_ERROR_INVALID_DATA);
3222     // NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast)
3223     compVerStrInfo.ptr = reinterpret_cast<const uint8_t*>(compVerStr.data());
3224 
3225     rc = encode_pass_component_table_req(
3226         instanceId, PLDM_START_AND_END, PLDM_COMP_FIRMWARE, compIdentifier,
3227         compClassificationIndex, compComparisonStamp, PLDM_STR_TYPE_ASCII,
3228         compVerStrLen, &compVerStrInfo, nullptr,
3229         sizeof(pldm_pass_component_table_req) + compVerStrLen);
3230     EXPECT_EQ(rc, PLDM_ERROR_INVALID_DATA);
3231 
3232     rc = encode_pass_component_table_req(
3233         instanceId, PLDM_START_AND_END, PLDM_COMP_FIRMWARE, compIdentifier,
3234         compClassificationIndex, compComparisonStamp, PLDM_STR_TYPE_ASCII,
3235         compVerStrLen, &compVerStrInfo, requestMsg,
3236         sizeof(pldm_pass_component_table_req));
3237     EXPECT_EQ(rc, PLDM_ERROR_INVALID_LENGTH);
3238 
3239     rc = encode_pass_component_table_req(
3240         instanceId, PLDM_START_AND_END, PLDM_COMP_FIRMWARE, compIdentifier,
3241         compClassificationIndex, compComparisonStamp, PLDM_STR_TYPE_ASCII, 0,
3242         &compVerStrInfo, requestMsg,
3243         sizeof(pldm_pass_component_table_req) + compVerStrLen);
3244     EXPECT_EQ(rc, PLDM_ERROR_INVALID_DATA);
3245 
3246     rc = encode_pass_component_table_req(
3247         instanceId, PLDM_START_AND_END, PLDM_COMP_FIRMWARE, compIdentifier,
3248         compClassificationIndex, compComparisonStamp, PLDM_STR_TYPE_ASCII,
3249         compVerStrLen - 1, &compVerStrInfo, requestMsg,
3250         sizeof(pldm_pass_component_table_req) + compVerStrLen);
3251     EXPECT_EQ(rc, PLDM_ERROR_INVALID_DATA);
3252 
3253     rc = encode_pass_component_table_req(
3254         instanceId, PLDM_START_AND_END + 1, PLDM_COMP_FIRMWARE, compIdentifier,
3255         compClassificationIndex, compComparisonStamp, PLDM_STR_TYPE_ASCII,
3256         compVerStrLen, &compVerStrInfo, requestMsg,
3257         sizeof(pldm_pass_component_table_req) + compVerStrLen);
3258     EXPECT_EQ(rc, PLDM_INVALID_TRANSFER_OPERATION_FLAG);
3259 
3260     rc = encode_pass_component_table_req(
3261         instanceId, PLDM_START_AND_END, PLDM_COMP_FIRMWARE, compIdentifier,
3262         compClassificationIndex, compComparisonStamp, PLDM_STR_TYPE_UNKNOWN,
3263         compVerStrLen, &compVerStrInfo, requestMsg,
3264         sizeof(pldm_pass_component_table_req) + compVerStrLen);
3265     EXPECT_EQ(rc, PLDM_ERROR_INVALID_DATA);
3266 }
3267 
3268 TEST(PassComponentTable, goodPathDecodeResponse)
3269 {
3270     constexpr std::array<uint8_t,
3271                          hdrSize + sizeof(pldm_pass_component_table_resp)>
3272         passCompTableResponse1{0x00, 0x00, 0x00, 0x00, 0x00, 0x01};
3273     auto responseMsg1 =
3274         // NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast)
3275         reinterpret_cast<const pldm_msg*>(passCompTableResponse1.data());
3276 
3277     uint8_t completionCode = 0;
3278     uint8_t compResp = 0;
3279     uint8_t compRespCode = 0;
3280 
3281     auto rc = decode_pass_component_table_resp(
3282         responseMsg1, sizeof(pldm_pass_component_table_resp), &completionCode,
3283         &compResp, &compRespCode);
3284 
3285     EXPECT_EQ(rc, PLDM_SUCCESS);
3286     EXPECT_EQ(completionCode, PLDM_SUCCESS);
3287     EXPECT_EQ(compResp, PLDM_CR_COMP_CAN_BE_UPDATED);
3288     EXPECT_EQ(compRespCode, PLDM_CRC_COMP_COMPARISON_STAMP_IDENTICAL);
3289 
3290     constexpr std::array<uint8_t,
3291                          hdrSize + sizeof(pldm_pass_component_table_resp)>
3292         passCompTableResponse2{0x00, 0x00, 0x00, 0x00, 0x00, 0xd0};
3293     auto responseMsg2 =
3294         // NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast)
3295         reinterpret_cast<const pldm_msg*>(passCompTableResponse2.data());
3296     rc = decode_pass_component_table_resp(
3297         responseMsg2, sizeof(pldm_pass_component_table_resp), &completionCode,
3298         &compResp, &compRespCode);
3299 
3300     EXPECT_EQ(rc, PLDM_SUCCESS);
3301     EXPECT_EQ(completionCode, PLDM_SUCCESS);
3302     EXPECT_EQ(compResp, PLDM_CR_COMP_CAN_BE_UPDATED);
3303     EXPECT_EQ(compRespCode, PLDM_CRC_VENDOR_COMP_RESP_CODE_RANGE_MIN);
3304 
3305     constexpr std::array<uint8_t,
3306                          hdrSize + sizeof(pldm_pass_component_table_resp)>
3307         passCompTableResponse3{0x00, 0x00, 0x00, 0x80};
3308     auto responseMsg3 =
3309         // NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast)
3310         reinterpret_cast<const pldm_msg*>(passCompTableResponse3.data());
3311 
3312     rc = decode_pass_component_table_resp(
3313         responseMsg3, sizeof(pldm_pass_component_table_resp), &completionCode,
3314         &compResp, &compRespCode);
3315 
3316     EXPECT_EQ(rc, PLDM_SUCCESS);
3317     EXPECT_EQ(completionCode, PLDM_FWUP_NOT_IN_UPDATE_MODE);
3318 }
3319 
3320 TEST(PassComponentTable, errorPathDecodeResponse)
3321 {
3322     constexpr std::array<uint8_t,
3323                          hdrSize + sizeof(pldm_pass_component_table_resp) - 1>
3324         passCompTableResponse1{0x00, 0x00, 0x00, 0x00, 0x00};
3325     auto responseMsg1 =
3326         // NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast)
3327         reinterpret_cast<const pldm_msg*>(passCompTableResponse1.data());
3328 
3329     uint8_t completionCode = 0;
3330     uint8_t compResp = 0;
3331     uint8_t compRespCode = 0;
3332 
3333     auto rc = decode_pass_component_table_resp(
3334         nullptr, sizeof(pldm_pass_component_table_resp) - 1, &completionCode,
3335         &compResp, &compRespCode);
3336     EXPECT_EQ(rc, PLDM_ERROR_INVALID_DATA);
3337 
3338     rc = decode_pass_component_table_resp(
3339         responseMsg1, sizeof(pldm_pass_component_table_resp) - 1, nullptr,
3340         &compResp, &compRespCode);
3341     EXPECT_EQ(rc, PLDM_ERROR_INVALID_DATA);
3342 
3343     rc = decode_pass_component_table_resp(
3344         responseMsg1, sizeof(pldm_pass_component_table_resp) - 1,
3345         &completionCode, nullptr, &compRespCode);
3346     EXPECT_EQ(rc, PLDM_ERROR_INVALID_DATA);
3347 
3348     rc = decode_pass_component_table_resp(
3349         responseMsg1, sizeof(pldm_pass_component_table_resp) - 1,
3350         &completionCode, &compResp, nullptr);
3351     EXPECT_EQ(rc, PLDM_ERROR_INVALID_DATA);
3352 
3353     rc = decode_pass_component_table_resp(responseMsg1, 0, &completionCode,
3354                                           &compResp, &compRespCode);
3355     EXPECT_EQ(rc, PLDM_ERROR_INVALID_DATA);
3356 
3357     rc = decode_pass_component_table_resp(
3358         responseMsg1, sizeof(pldm_pass_component_table_resp) - 1,
3359         &completionCode, &compResp, &compRespCode);
3360     EXPECT_EQ(rc, PLDM_ERROR_INVALID_LENGTH);
3361 
3362     constexpr std::array<uint8_t,
3363                          hdrSize + sizeof(pldm_pass_component_table_resp)>
3364         passCompTableResponse2{0x00, 0x00, 0x00, 0x00, 0x02, 0x00};
3365     auto responseMsg2 =
3366         // NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast)
3367         reinterpret_cast<const pldm_msg*>(passCompTableResponse2.data());
3368     rc = decode_pass_component_table_resp(
3369         responseMsg2, sizeof(pldm_pass_component_table_resp), &completionCode,
3370         &compResp, &compRespCode);
3371     EXPECT_EQ(rc, PLDM_ERROR_INVALID_DATA);
3372 
3373     constexpr std::array<uint8_t,
3374                          hdrSize + sizeof(pldm_pass_component_table_resp)>
3375         passCompTableResponse3{0x00, 0x00, 0x00, 0x00, 0x00, 0x0c};
3376     auto responseMsg3 =
3377         // NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast)
3378         reinterpret_cast<const pldm_msg*>(passCompTableResponse3.data());
3379     rc = decode_pass_component_table_resp(
3380         responseMsg3, sizeof(pldm_pass_component_table_resp), &completionCode,
3381         &compResp, &compRespCode);
3382     EXPECT_EQ(rc, PLDM_ERROR_INVALID_DATA);
3383 
3384     constexpr std::array<uint8_t,
3385                          hdrSize + sizeof(pldm_pass_component_table_resp)>
3386         passCompTableResponse4{0x00, 0x00, 0x00, 0x00, 0x00, 0xf0};
3387     auto responseMsg4 =
3388         // NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast)
3389         reinterpret_cast<const pldm_msg*>(passCompTableResponse4.data());
3390     rc = decode_pass_component_table_resp(
3391         responseMsg4, sizeof(pldm_pass_component_table_resp), &completionCode,
3392         &compResp, &compRespCode);
3393     EXPECT_EQ(rc, PLDM_ERROR_INVALID_DATA);
3394 }
3395 
3396 TEST(UpdateComponent, goodPathEncodeRequest)
3397 {
3398     constexpr uint8_t instanceId = 2;
3399     constexpr uint16_t compIdentifier = 500;
3400     constexpr uint8_t compClassificationIndex = 50;
3401     constexpr uint32_t compComparisonStamp = 0x89abcdef;
3402     constexpr uint32_t compImageSize = 4096;
3403     constexpr bitfield32_t updateOptionFlags{1};
3404     constexpr std::string_view compVerStr = "OpenBmcv2.2";
3405     constexpr uint8_t compVerStrLen = static_cast<uint8_t>(compVerStr.size());
3406     variable_field compVerStrInfo{};
3407     // NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast)
3408     compVerStrInfo.ptr = reinterpret_cast<const uint8_t*>(compVerStr.data());
3409     compVerStrInfo.length = compVerStrLen;
3410 
3411     std::array<uint8_t,
3412                hdrSize + sizeof(pldm_update_component_req) + compVerStrLen>
3413         request{};
3414     // NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast)
3415     auto requestMsg = reinterpret_cast<pldm_msg*>(request.data());
3416 
3417     auto rc = encode_update_component_req(
3418         instanceId, PLDM_COMP_FIRMWARE, compIdentifier, compClassificationIndex,
3419         compComparisonStamp, compImageSize, updateOptionFlags,
3420         PLDM_STR_TYPE_ASCII, compVerStrLen, &compVerStrInfo, requestMsg,
3421         sizeof(pldm_update_component_req) + compVerStrLen);
3422     EXPECT_EQ(rc, PLDM_SUCCESS);
3423 
3424     std::array<uint8_t,
3425                hdrSize + sizeof(pldm_update_component_req) + compVerStrLen>
3426         outRequest{0x82, 0x05, 0x14, 0x0a, 0x00, 0xf4, 0x01, 0x32, 0xef,
3427                    0xcd, 0xab, 0x89, 0x00, 0x10, 0x00, 0x00, 0x01, 0x00,
3428                    0x00, 0x00, 0x01, 0x0b, 0x4f, 0x70, 0x65, 0x6e, 0x42,
3429                    0x6d, 0x63, 0x76, 0x32, 0x2e, 0x32};
3430     EXPECT_EQ(request, outRequest);
3431 
3432 #ifdef LIBPLDM_API_TESTING
3433     /* Check the roundtrip */
3434     struct pldm_update_component_req_full req;
3435     PLDM_MSG_DEFINE_P(dec, outRequest.size());
3436     std::copy(outRequest.begin(), outRequest.end(), dec_buf);
3437     rc = decode_update_component_req(dec, outRequest.size() - hdrSize, &req);
3438     ASSERT_EQ(rc, 0);
3439 
3440     EXPECT_EQ(req.comp_classification, PLDM_COMP_FIRMWARE);
3441     EXPECT_EQ(req.comp_identifier, compIdentifier);
3442     EXPECT_EQ(req.comp_classification_index, compClassificationIndex);
3443     EXPECT_EQ(req.comp_comparison_stamp, compComparisonStamp);
3444     EXPECT_EQ(req.comp_image_size, compImageSize);
3445     EXPECT_EQ(req.update_option_flags.value, updateOptionFlags.value);
3446     EXPECT_EQ(req.version.str_type, PLDM_STR_TYPE_ASCII);
3447     EXPECT_EQ(req.version.str_len, compVerStrLen);
3448     EXPECT_TRUE(std::equal(req.version.str_data,
3449                            req.version.str_data + req.version.str_len,
3450                            compVerStr.data()));
3451 #endif
3452 }
3453 
3454 TEST(UpdateComponent, errorPathEncodeRequest)
3455 {
3456     constexpr uint8_t instanceId = 2;
3457     constexpr uint16_t compIdentifier = 500;
3458     constexpr uint8_t compClassificationIndex = 50;
3459     constexpr uint32_t compComparisonStamp = 0x89abcdef;
3460     constexpr uint32_t compImageSize = 4096;
3461     constexpr bitfield32_t updateOptionFlags{1};
3462     constexpr std::string_view compVerStr = "OpenBmcv2.2";
3463     constexpr uint8_t compVerStrLen = static_cast<uint8_t>(compVerStr.size());
3464     variable_field compVerStrInfo{};
3465     // NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast)
3466     compVerStrInfo.ptr = reinterpret_cast<const uint8_t*>(compVerStr.data());
3467     compVerStrInfo.length = compVerStrLen;
3468 
3469     std::array<uint8_t,
3470                hdrSize + sizeof(pldm_update_component_req) + compVerStrLen>
3471         request{};
3472     // NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast)
3473     auto requestMsg = reinterpret_cast<pldm_msg*>(request.data());
3474 
3475     auto rc = encode_update_component_req(
3476         instanceId, PLDM_COMP_FIRMWARE, compIdentifier, compClassificationIndex,
3477         compComparisonStamp, compImageSize, updateOptionFlags,
3478         PLDM_STR_TYPE_ASCII, compVerStrLen, nullptr, requestMsg,
3479         sizeof(pldm_update_component_req) + compVerStrLen);
3480     EXPECT_EQ(rc, PLDM_ERROR_INVALID_DATA);
3481 
3482     compVerStrInfo.ptr = nullptr;
3483     rc = encode_update_component_req(
3484         instanceId, PLDM_COMP_FIRMWARE, compIdentifier, compClassificationIndex,
3485         compComparisonStamp, compImageSize, updateOptionFlags,
3486         PLDM_STR_TYPE_ASCII, compVerStrLen, &compVerStrInfo, requestMsg,
3487         sizeof(pldm_update_component_req) + compVerStrLen);
3488     EXPECT_EQ(rc, PLDM_ERROR_INVALID_DATA);
3489     // NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast)
3490     compVerStrInfo.ptr = reinterpret_cast<const uint8_t*>(compVerStr.data());
3491 
3492     rc = encode_update_component_req(
3493         instanceId, PLDM_COMP_FIRMWARE, compIdentifier, compClassificationIndex,
3494         compComparisonStamp, compImageSize, updateOptionFlags,
3495         PLDM_STR_TYPE_ASCII, compVerStrLen, &compVerStrInfo, nullptr,
3496         sizeof(pldm_update_component_req) + compVerStrLen);
3497     EXPECT_EQ(rc, PLDM_ERROR_INVALID_DATA);
3498 
3499     rc = encode_update_component_req(
3500         instanceId, PLDM_COMP_FIRMWARE, compIdentifier, compClassificationIndex,
3501         compComparisonStamp, compImageSize, updateOptionFlags,
3502         PLDM_STR_TYPE_ASCII, compVerStrLen, &compVerStrInfo, requestMsg,
3503         sizeof(pldm_update_component_req));
3504     EXPECT_EQ(rc, PLDM_ERROR_INVALID_LENGTH);
3505 
3506     rc = encode_update_component_req(
3507         instanceId, PLDM_COMP_FIRMWARE, compIdentifier, compClassificationIndex,
3508         compComparisonStamp, 0, updateOptionFlags, PLDM_STR_TYPE_ASCII,
3509         compVerStrLen, &compVerStrInfo, requestMsg,
3510         sizeof(pldm_update_component_req) + compVerStrLen);
3511     EXPECT_EQ(rc, PLDM_ERROR_INVALID_DATA);
3512 
3513     rc = encode_update_component_req(
3514         instanceId, PLDM_COMP_FIRMWARE, compIdentifier, compClassificationIndex,
3515         compComparisonStamp, compImageSize, updateOptionFlags,
3516         PLDM_STR_TYPE_ASCII, 0, &compVerStrInfo, requestMsg,
3517         sizeof(pldm_update_component_req) + compVerStrLen);
3518     EXPECT_EQ(rc, PLDM_ERROR_INVALID_DATA);
3519 
3520     rc = encode_update_component_req(
3521         instanceId, PLDM_COMP_FIRMWARE, compIdentifier, compClassificationIndex,
3522         compComparisonStamp, compImageSize, updateOptionFlags,
3523         PLDM_STR_TYPE_ASCII, compVerStrLen - 1, &compVerStrInfo, requestMsg,
3524         sizeof(pldm_update_component_req) + compVerStrLen);
3525     EXPECT_EQ(rc, PLDM_ERROR_INVALID_DATA);
3526 
3527     rc = encode_update_component_req(
3528         instanceId, PLDM_COMP_FIRMWARE, compIdentifier, compClassificationIndex,
3529         compComparisonStamp, compImageSize, updateOptionFlags,
3530         PLDM_STR_TYPE_UNKNOWN, compVerStrLen, &compVerStrInfo, requestMsg,
3531         sizeof(pldm_update_component_req) + compVerStrLen);
3532     EXPECT_EQ(rc, PLDM_ERROR_INVALID_DATA);
3533 }
3534 
3535 TEST(UpdateComponent, goodPathDecodeResponse)
3536 {
3537     constexpr std::bitset<32> forceUpdateComp{1};
3538     constexpr uint16_t timeBeforeSendingReqFwData100s = 100;
3539     constexpr std::array<uint8_t, hdrSize + sizeof(pldm_update_component_resp)>
3540         updateComponentResponse1{0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3541                                  0x01, 0x00, 0x00, 0x00, 0x64, 0x00};
3542     auto responseMsg1 =
3543         // NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast)
3544         reinterpret_cast<const pldm_msg*>(updateComponentResponse1.data());
3545 
3546     uint8_t completionCode = 0;
3547     uint8_t compCompatibilityResp = 0;
3548     uint8_t compCompatibilityRespCode = 0;
3549     bitfield32_t updateOptionFlagsEnabled{};
3550     uint16_t timeBeforeReqFWData = 0;
3551 
3552     auto rc = decode_update_component_resp(
3553         responseMsg1, sizeof(pldm_update_component_resp), &completionCode,
3554         &compCompatibilityResp, &compCompatibilityRespCode,
3555         &updateOptionFlagsEnabled, &timeBeforeReqFWData);
3556 
3557     EXPECT_EQ(rc, PLDM_SUCCESS);
3558     EXPECT_EQ(completionCode, PLDM_SUCCESS);
3559     EXPECT_EQ(compCompatibilityResp, PLDM_CCR_COMP_CAN_BE_UPDATED);
3560     EXPECT_EQ(compCompatibilityRespCode, PLDM_CCRC_NO_RESPONSE_CODE);
3561     EXPECT_EQ(updateOptionFlagsEnabled.value, forceUpdateComp);
3562     EXPECT_EQ(timeBeforeReqFWData, timeBeforeSendingReqFwData100s);
3563 
3564     constexpr std::bitset<32> noFlags{};
3565     constexpr uint16_t timeBeforeSendingReqFwData0s = 0;
3566     constexpr std::array<uint8_t, hdrSize + sizeof(pldm_update_component_resp)>
3567         updateComponentResponse2{0x00, 0x00, 0x00, 0x00, 0x01, 0x09,
3568                                  0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
3569     auto responseMsg2 =
3570         // NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast)
3571         reinterpret_cast<const pldm_msg*>(updateComponentResponse2.data());
3572     rc = decode_update_component_resp(
3573         responseMsg2, sizeof(pldm_update_component_resp), &completionCode,
3574         &compCompatibilityResp, &compCompatibilityRespCode,
3575         &updateOptionFlagsEnabled, &timeBeforeReqFWData);
3576 
3577     EXPECT_EQ(rc, PLDM_SUCCESS);
3578     EXPECT_EQ(completionCode, PLDM_SUCCESS);
3579     EXPECT_EQ(compCompatibilityResp, PLDM_CCR_COMP_CANNOT_BE_UPDATED);
3580     EXPECT_EQ(compCompatibilityRespCode, PLDM_CCRC_COMP_INFO_NO_MATCH);
3581     EXPECT_EQ(updateOptionFlagsEnabled.value, noFlags);
3582     EXPECT_EQ(timeBeforeReqFWData, timeBeforeSendingReqFwData0s);
3583 
3584     constexpr std::array<uint8_t, hdrSize + sizeof(pldm_update_component_resp)>
3585         updateComponentResponse3{0x00, 0x00, 0x00, 0x80};
3586     auto responseMsg3 =
3587         // NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast)
3588         reinterpret_cast<const pldm_msg*>(updateComponentResponse3.data());
3589 
3590     rc = decode_update_component_resp(
3591         responseMsg3, sizeof(pldm_update_component_resp), &completionCode,
3592         &compCompatibilityResp, &compCompatibilityRespCode,
3593         &updateOptionFlagsEnabled, &timeBeforeReqFWData);
3594 
3595     EXPECT_EQ(rc, PLDM_SUCCESS);
3596     EXPECT_EQ(completionCode, PLDM_FWUP_NOT_IN_UPDATE_MODE);
3597 }
3598 
3599 TEST(UpdateComponent, errorPathDecodeResponse)
3600 {
3601     constexpr std::array<uint8_t,
3602                          hdrSize + sizeof(pldm_update_component_resp) - 1>
3603         updateComponentResponse1{0x00, 0x00, 0x00, 0x00, 0x01, 0x09,
3604                                  0x00, 0x00, 0x00, 0x00, 0x00};
3605     auto responseMsg1 =
3606         // NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast)
3607         reinterpret_cast<const pldm_msg*>(updateComponentResponse1.data());
3608 
3609     uint8_t completionCode = 0;
3610     uint8_t compCompatibilityResp = 0;
3611     uint8_t compCompatibilityRespCode = 0;
3612     bitfield32_t updateOptionFlagsEnabled{};
3613     uint16_t timeBeforeReqFWData = 0;
3614 
3615     auto rc = decode_update_component_resp(
3616         nullptr, sizeof(pldm_update_component_resp) - 1, &completionCode,
3617         &compCompatibilityResp, &compCompatibilityRespCode,
3618         &updateOptionFlagsEnabled, &timeBeforeReqFWData);
3619     EXPECT_EQ(rc, PLDM_ERROR_INVALID_DATA);
3620 
3621     rc = decode_update_component_resp(
3622         responseMsg1, sizeof(pldm_update_component_resp) - 1, nullptr,
3623         &compCompatibilityResp, &compCompatibilityRespCode,
3624         &updateOptionFlagsEnabled, &timeBeforeReqFWData);
3625     EXPECT_EQ(rc, PLDM_ERROR_INVALID_DATA);
3626 
3627     rc = decode_update_component_resp(
3628         responseMsg1, sizeof(pldm_update_component_resp) - 1, &completionCode,
3629         nullptr, &compCompatibilityRespCode, &updateOptionFlagsEnabled,
3630         &timeBeforeReqFWData);
3631     EXPECT_EQ(rc, PLDM_ERROR_INVALID_DATA);
3632 
3633     rc = decode_update_component_resp(
3634         responseMsg1, sizeof(pldm_update_component_resp) - 1, &completionCode,
3635         &compCompatibilityResp, nullptr, &updateOptionFlagsEnabled,
3636         &timeBeforeReqFWData);
3637     EXPECT_EQ(rc, PLDM_ERROR_INVALID_DATA);
3638 
3639     rc = decode_update_component_resp(
3640         responseMsg1, sizeof(pldm_update_component_resp) - 1, &completionCode,
3641         &compCompatibilityResp, &compCompatibilityRespCode, nullptr,
3642         &timeBeforeReqFWData);
3643     EXPECT_EQ(rc, PLDM_ERROR_INVALID_DATA);
3644 
3645     rc = decode_update_component_resp(
3646         responseMsg1, sizeof(pldm_update_component_resp) - 1, &completionCode,
3647         &compCompatibilityResp, &compCompatibilityRespCode,
3648         &updateOptionFlagsEnabled, nullptr);
3649     EXPECT_EQ(rc, PLDM_ERROR_INVALID_DATA);
3650 
3651     rc = decode_update_component_resp(
3652         responseMsg1, 0, &completionCode, &compCompatibilityResp,
3653         &compCompatibilityRespCode, &updateOptionFlagsEnabled,
3654         &timeBeforeReqFWData);
3655     EXPECT_EQ(rc, PLDM_ERROR_INVALID_DATA);
3656 
3657     rc = decode_update_component_resp(
3658         responseMsg1, sizeof(pldm_update_component_resp) - 1, &completionCode,
3659         &compCompatibilityResp, &compCompatibilityRespCode,
3660         &updateOptionFlagsEnabled, &timeBeforeReqFWData);
3661     EXPECT_EQ(rc, PLDM_ERROR_INVALID_LENGTH);
3662 
3663     constexpr std::array<uint8_t, hdrSize + sizeof(pldm_update_component_resp)>
3664         updateComponentResponse2{0x00, 0x00, 0x00, 0x00, 0x02, 0x00,
3665                                  0x01, 0x00, 0x00, 0x00, 0x64, 0x00};
3666     auto responseMsg2 =
3667         // NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast)
3668         reinterpret_cast<const pldm_msg*>(updateComponentResponse2.data());
3669     rc = decode_update_component_resp(
3670         responseMsg2, sizeof(pldm_update_component_resp), &completionCode,
3671         &compCompatibilityResp, &compCompatibilityRespCode,
3672         &updateOptionFlagsEnabled, &timeBeforeReqFWData);
3673     EXPECT_EQ(rc, PLDM_ERROR_INVALID_DATA);
3674 
3675     constexpr std::array<uint8_t, hdrSize + sizeof(pldm_update_component_resp)>
3676         updateComponentResponse3{0x00, 0x00, 0x00, 0x00, 0x00, 0x0c,
3677                                  0x01, 0x00, 0x00, 0x00, 0x64, 0x00};
3678     auto responseMsg3 =
3679         // NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast)
3680         reinterpret_cast<const pldm_msg*>(updateComponentResponse3.data());
3681     rc = decode_update_component_resp(
3682         responseMsg3, sizeof(pldm_update_component_resp), &completionCode,
3683         &compCompatibilityResp, &compCompatibilityRespCode,
3684         &updateOptionFlagsEnabled, &timeBeforeReqFWData);
3685     EXPECT_EQ(rc, PLDM_ERROR_INVALID_DATA);
3686 
3687     constexpr std::array<uint8_t, hdrSize + sizeof(pldm_update_component_resp)>
3688         updateComponentResponse4{0x00, 0x00, 0x00, 0x00, 0x00, 0xf0,
3689                                  0x01, 0x00, 0x00, 0x00, 0x64, 0x00};
3690     auto responseMsg4 =
3691         // NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast)
3692         reinterpret_cast<const pldm_msg*>(updateComponentResponse4.data());
3693     rc = decode_update_component_resp(
3694         responseMsg4, sizeof(pldm_update_component_resp), &completionCode,
3695         &compCompatibilityResp, &compCompatibilityRespCode,
3696         &updateOptionFlagsEnabled, &timeBeforeReqFWData);
3697     EXPECT_EQ(rc, PLDM_ERROR_INVALID_DATA);
3698 }
3699 
3700 TEST(RequestFirmwareData, goodPathDecodeRequest)
3701 {
3702     constexpr uint32_t offset = 300;
3703     constexpr uint32_t length = 255;
3704     constexpr std::array<uint8_t,
3705                          hdrSize + sizeof(pldm_request_firmware_data_req)>
3706         reqFWDataReq{0x00, 0x00, 0x00, 0x2c, 0x01, 0x00,
3707                      0x00, 0xff, 0x00, 0x00, 0x00};
3708     // NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast)
3709     auto requestMsg = reinterpret_cast<const pldm_msg*>(reqFWDataReq.data());
3710 
3711     uint32_t outOffset = 0;
3712     uint32_t outLength = 0;
3713     auto rc = decode_request_firmware_data_req(
3714         requestMsg, sizeof(pldm_request_firmware_data_req), &outOffset,
3715         &outLength);
3716 
3717     EXPECT_EQ(rc, PLDM_SUCCESS);
3718     EXPECT_EQ(outOffset, offset);
3719     EXPECT_EQ(outLength, length);
3720 }
3721 
3722 TEST(RequestFirmwareData, errorPathDecodeRequest)
3723 {
3724     constexpr std::array<uint8_t,
3725                          hdrSize + sizeof(pldm_request_firmware_data_req)>
3726         reqFWDataReq{0x00, 0x00, 0x00, 0x2c, 0x01, 0x00,
3727                      0x00, 0x1f, 0x00, 0x00, 0x00};
3728     // NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast)
3729     auto requestMsg = reinterpret_cast<const pldm_msg*>(reqFWDataReq.data());
3730 
3731     uint32_t outOffset = 0;
3732     uint32_t outLength = 0;
3733     auto rc = decode_request_firmware_data_req(
3734         nullptr, sizeof(pldm_request_firmware_data_req), &outOffset,
3735         &outLength);
3736     EXPECT_EQ(rc, PLDM_ERROR_INVALID_DATA);
3737 
3738     rc = decode_request_firmware_data_req(
3739         requestMsg, sizeof(pldm_request_firmware_data_req), nullptr,
3740         &outLength);
3741     EXPECT_EQ(rc, PLDM_ERROR_INVALID_DATA);
3742 
3743     rc = decode_request_firmware_data_req(
3744         requestMsg, sizeof(pldm_request_firmware_data_req), &outOffset,
3745         nullptr);
3746     EXPECT_EQ(rc, PLDM_ERROR_INVALID_DATA);
3747 
3748     rc = decode_request_firmware_data_req(
3749         requestMsg, sizeof(pldm_request_firmware_data_req) - 1, &outOffset,
3750         &outLength);
3751     EXPECT_EQ(rc, PLDM_ERROR_INVALID_LENGTH);
3752 
3753     rc = decode_request_firmware_data_req(
3754         requestMsg, sizeof(pldm_request_firmware_data_req), &outOffset,
3755         &outLength);
3756     EXPECT_EQ(rc, PLDM_FWUP_INVALID_TRANSFER_LENGTH);
3757 }
3758 
3759 TEST(RequestFirmwareData, goodPathEncodeResponse)
3760 {
3761     constexpr uint8_t instanceId = 3;
3762     constexpr uint8_t completionCode = PLDM_SUCCESS;
3763     constexpr std::array<uint8_t, hdrSize + sizeof(completionCode) +
3764                                       PLDM_FWUP_BASELINE_TRANSFER_SIZE>
3765         outReqFwDataResponse1{0x03, 0x05, 0x15, 0x00, 0x01, 0x02, 0x03, 0x04,
3766                               0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c,
3767                               0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13, 0x14,
3768                               0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c,
3769                               0x1d, 0x1e, 0x1f, 0x20};
3770     std::array<uint8_t, hdrSize + sizeof(completionCode) +
3771                             PLDM_FWUP_BASELINE_TRANSFER_SIZE>
3772         reqFwDataResponse1{0x00, 0x00, 0x00, 0x00, 0x01, 0x02, 0x03, 0x04,
3773                            0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c,
3774                            0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13, 0x14,
3775                            0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c,
3776                            0x1d, 0x1e, 0x1f, 0x20};
3777     // NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast)
3778     auto responseMsg1 = reinterpret_cast<pldm_msg*>(reqFwDataResponse1.data());
3779     auto rc = encode_request_firmware_data_resp(
3780         instanceId, completionCode, responseMsg1,
3781         sizeof(completionCode) + PLDM_FWUP_BASELINE_TRANSFER_SIZE);
3782     EXPECT_EQ(rc, PLDM_SUCCESS);
3783     EXPECT_EQ(reqFwDataResponse1, outReqFwDataResponse1);
3784 
3785     constexpr std::array<uint8_t, hdrSize + sizeof(completionCode)>
3786         outReqFwDataResponse2{0x03, 0x05, 0x15, 0x82};
3787     std::array<uint8_t, hdrSize + sizeof(completionCode)> reqFwDataResponse2{
3788         0x00, 0x00, 0x00, 0x00};
3789     // NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast)
3790     auto responseMsg2 = reinterpret_cast<pldm_msg*>(reqFwDataResponse2.data());
3791     rc = encode_request_firmware_data_resp(
3792         instanceId, PLDM_FWUP_DATA_OUT_OF_RANGE, responseMsg2,
3793         sizeof(completionCode));
3794     EXPECT_EQ(rc, PLDM_SUCCESS);
3795     EXPECT_EQ(reqFwDataResponse2, outReqFwDataResponse2);
3796 }
3797 
3798 TEST(RequestFirmwareData, errorPathEncodeResponse)
3799 {
3800     std::array<uint8_t, hdrSize> reqFwDataResponse{0x00, 0x00, 0x00};
3801     // NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast)
3802     auto responseMsg = reinterpret_cast<pldm_msg*>(reqFwDataResponse.data());
3803     auto rc = encode_request_firmware_data_resp(0, PLDM_SUCCESS, nullptr, 0);
3804     EXPECT_EQ(rc, PLDM_ERROR_INVALID_DATA);
3805 
3806     rc = encode_request_firmware_data_resp(0, PLDM_SUCCESS, responseMsg, 0);
3807     EXPECT_EQ(rc, PLDM_ERROR_INVALID_DATA);
3808 }
3809 
3810 TEST(TransferComplete, goodPathDecodeRequest)
3811 {
3812     constexpr uint8_t transferResult = PLDM_FWUP_TRANSFER_SUCCESS;
3813     constexpr std::array<uint8_t, hdrSize + sizeof(transferResult)>
3814         transferCompleteReq1{0x00, 0x00, 0x00, 0x00};
3815     auto requestMsg1 =
3816         // NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast)
3817         reinterpret_cast<const pldm_msg*>(transferCompleteReq1.data());
3818     uint8_t outTransferResult = 0;
3819 
3820     auto rc = decode_transfer_complete_req(requestMsg1, sizeof(transferResult),
3821                                            &outTransferResult);
3822     EXPECT_EQ(rc, PLDM_SUCCESS);
3823     EXPECT_EQ(outTransferResult, transferResult);
3824 
3825     constexpr std::array<uint8_t, hdrSize + sizeof(transferResult)>
3826         transferCompleteReq2{0x00, 0x00, 0x00, 0x02};
3827     auto requestMsg2 =
3828         // NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast)
3829         reinterpret_cast<const pldm_msg*>(transferCompleteReq2.data());
3830     rc = decode_transfer_complete_req(requestMsg2, sizeof(transferResult),
3831                                       &outTransferResult);
3832     EXPECT_EQ(rc, PLDM_SUCCESS);
3833     EXPECT_EQ(outTransferResult, PLDM_FWUP_TRANSFER_ERROR_IMAGE_CORRUPT);
3834 }
3835 
3836 TEST(TransferComplete, errorPathDecodeRequest)
3837 {
3838     constexpr std::array<uint8_t, hdrSize> transferCompleteReq{0x00, 0x00,
3839                                                                0x00};
3840     auto requestMsg =
3841         // NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast)
3842         reinterpret_cast<const pldm_msg*>(transferCompleteReq.data());
3843     uint8_t outTransferResult = 0;
3844 
3845     auto rc = decode_transfer_complete_req(nullptr, 0, &outTransferResult);
3846     EXPECT_EQ(rc, PLDM_ERROR_INVALID_DATA);
3847 
3848     rc = decode_transfer_complete_req(requestMsg, 0, nullptr);
3849     EXPECT_EQ(rc, PLDM_ERROR_INVALID_DATA);
3850 
3851     rc = decode_transfer_complete_req(requestMsg, 0, &outTransferResult);
3852     EXPECT_EQ(rc, PLDM_ERROR_INVALID_LENGTH);
3853 }
3854 
3855 TEST(TransferComplete, goodPathEncodeResponse)
3856 {
3857     constexpr uint8_t instanceId = 4;
3858     constexpr uint8_t completionCode = PLDM_SUCCESS;
3859     constexpr std::array<uint8_t, hdrSize + sizeof(completionCode)>
3860         outTransferCompleteResponse1{0x04, 0x05, 0x16, 0x00};
3861     std::array<uint8_t, hdrSize + sizeof(completionCode)>
3862         transferCompleteResponse1{0x00, 0x00, 0x00, 0x00};
3863     auto responseMsg1 =
3864         // NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast)
3865         reinterpret_cast<pldm_msg*>(transferCompleteResponse1.data());
3866     auto rc = encode_transfer_complete_resp(
3867         instanceId, completionCode, responseMsg1, sizeof(completionCode));
3868     EXPECT_EQ(rc, PLDM_SUCCESS);
3869     EXPECT_EQ(transferCompleteResponse1, outTransferCompleteResponse1);
3870 
3871     constexpr std::array<uint8_t, hdrSize + sizeof(completionCode)>
3872         outTransferCompleteResponse2{0x04, 0x05, 0x16, 0x88};
3873     std::array<uint8_t, hdrSize + sizeof(completionCode)>
3874         transferCompleteResponse2{0x00, 0x00, 0x00, 0x00};
3875     auto responseMsg2 =
3876         // NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast)
3877         reinterpret_cast<pldm_msg*>(transferCompleteResponse2.data());
3878     rc = encode_transfer_complete_resp(instanceId,
3879                                        PLDM_FWUP_COMMAND_NOT_EXPECTED,
3880                                        responseMsg2, sizeof(completionCode));
3881     EXPECT_EQ(rc, PLDM_SUCCESS);
3882     EXPECT_EQ(transferCompleteResponse2, outTransferCompleteResponse2);
3883 }
3884 
3885 TEST(TransferComplete, errorPathEncodeResponse)
3886 {
3887     std::array<uint8_t, hdrSize> transferCompleteResponse{0x00, 0x00, 0x00};
3888     auto responseMsg =
3889         // NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast)
3890         reinterpret_cast<pldm_msg*>(transferCompleteResponse.data());
3891     auto rc = encode_transfer_complete_resp(0, PLDM_SUCCESS, nullptr, 0);
3892     EXPECT_EQ(rc, PLDM_ERROR_INVALID_DATA);
3893 
3894     rc = encode_transfer_complete_resp(0, PLDM_SUCCESS, responseMsg, 0);
3895     EXPECT_EQ(rc, PLDM_ERROR_INVALID_LENGTH);
3896 }
3897 
3898 TEST(VerifyComplete, goodPathDecodeRequest)
3899 {
3900     constexpr uint8_t verifyResult = PLDM_FWUP_VERIFY_SUCCESS;
3901     constexpr std::array<uint8_t, hdrSize + sizeof(verifyResult)>
3902         verifyCompleteReq1{0x00, 0x00, 0x00, 0x00};
3903     auto requestMsg1 =
3904         // NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast)
3905         reinterpret_cast<const pldm_msg*>(verifyCompleteReq1.data());
3906     uint8_t outVerifyResult = 0;
3907 
3908     auto rc = decode_verify_complete_req(requestMsg1, sizeof(verifyResult),
3909                                          &outVerifyResult);
3910     EXPECT_EQ(rc, PLDM_SUCCESS);
3911     EXPECT_EQ(outVerifyResult, verifyResult);
3912 
3913     constexpr std::array<uint8_t, hdrSize + sizeof(verifyResult)>
3914         verifyCompleteReq2{0x00, 0x00, 0x00, 0x03};
3915     auto requestMsg2 =
3916         // NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast)
3917         reinterpret_cast<const pldm_msg*>(verifyCompleteReq2.data());
3918     rc = decode_verify_complete_req(requestMsg2, sizeof(verifyResult),
3919                                     &outVerifyResult);
3920     EXPECT_EQ(rc, PLDM_SUCCESS);
3921     EXPECT_EQ(outVerifyResult, PLDM_FWUP_VERIFY_FAILED_FD_SECURITY_CHECKS);
3922 }
3923 
3924 TEST(VerifyComplete, errorPathDecodeRequest)
3925 {
3926     constexpr std::array<uint8_t, hdrSize> verifyCompleteReq{0x00, 0x00, 0x00};
3927     auto requestMsg =
3928         // NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast)
3929         reinterpret_cast<const pldm_msg*>(verifyCompleteReq.data());
3930     uint8_t outVerifyResult = 0;
3931 
3932     auto rc = decode_verify_complete_req(nullptr, 0, &outVerifyResult);
3933     EXPECT_EQ(rc, PLDM_ERROR_INVALID_DATA);
3934 
3935     rc = decode_verify_complete_req(requestMsg, 0, nullptr);
3936     EXPECT_EQ(rc, PLDM_ERROR_INVALID_DATA);
3937 
3938     rc = decode_verify_complete_req(requestMsg, 0, &outVerifyResult);
3939     EXPECT_EQ(rc, PLDM_ERROR_INVALID_LENGTH);
3940 }
3941 
3942 TEST(VerifyComplete, goodPathEncodeResponse)
3943 {
3944     constexpr uint8_t instanceId = 5;
3945     constexpr uint8_t completionCode = PLDM_SUCCESS;
3946     constexpr std::array<uint8_t, hdrSize + sizeof(completionCode)>
3947         outVerifyCompleteResponse1{0x05, 0x05, 0x17, 0x00};
3948     std::array<uint8_t, hdrSize + sizeof(completionCode)>
3949         verifyCompleteResponse1{0x00, 0x00, 0x00, 0x00};
3950     auto responseMsg1 =
3951         // NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast)
3952         reinterpret_cast<pldm_msg*>(verifyCompleteResponse1.data());
3953     auto rc = encode_verify_complete_resp(instanceId, completionCode,
3954                                           responseMsg1, sizeof(completionCode));
3955     EXPECT_EQ(rc, PLDM_SUCCESS);
3956     EXPECT_EQ(verifyCompleteResponse1, outVerifyCompleteResponse1);
3957 
3958     constexpr std::array<uint8_t, hdrSize + sizeof(completionCode)>
3959         outVerifyCompleteResponse2{0x05, 0x05, 0x17, 0x88};
3960     std::array<uint8_t, hdrSize + sizeof(completionCode)>
3961         verifyCompleteResponse2{0x00, 0x00, 0x00, 0x00};
3962     auto responseMsg2 =
3963         // NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast)
3964         reinterpret_cast<pldm_msg*>(verifyCompleteResponse2.data());
3965     rc = encode_verify_complete_resp(instanceId, PLDM_FWUP_COMMAND_NOT_EXPECTED,
3966                                      responseMsg2, sizeof(completionCode));
3967     EXPECT_EQ(rc, PLDM_SUCCESS);
3968     EXPECT_EQ(verifyCompleteResponse2, outVerifyCompleteResponse2);
3969 }
3970 
3971 TEST(VerifyComplete, errorPathEncodeResponse)
3972 {
3973     std::array<uint8_t, hdrSize> verifyCompleteResponse{0x00, 0x00, 0x00};
3974     auto responseMsg =
3975         // NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast)
3976         reinterpret_cast<pldm_msg*>(verifyCompleteResponse.data());
3977     auto rc = encode_verify_complete_resp(0, PLDM_SUCCESS, nullptr, 0);
3978     EXPECT_EQ(rc, PLDM_ERROR_INVALID_DATA);
3979 
3980     rc = encode_verify_complete_resp(0, PLDM_SUCCESS, responseMsg, 0);
3981     EXPECT_EQ(rc, PLDM_ERROR_INVALID_LENGTH);
3982 }
3983 
3984 TEST(ApplyComplete, goodPathDecodeRequest)
3985 {
3986     constexpr uint8_t applyResult1 =
3987         PLDM_FWUP_APPLY_SUCCESS_WITH_ACTIVATION_METHOD;
3988     // DC power cycle [Bit position 4] & AC power cycle [Bit position 5]
3989     constexpr std::bitset<16> compActivationModification1{0x30};
3990     constexpr std::array<uint8_t, hdrSize + sizeof(pldm_apply_complete_req)>
3991         applyCompleteReq1{0x00, 0x00, 0x00, 0x01, 0x30, 0x00};
3992     auto requestMsg1 =
3993         // NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast)
3994         reinterpret_cast<const pldm_msg*>(applyCompleteReq1.data());
3995     uint8_t outApplyResult = 0;
3996     bitfield16_t outCompActivationModification{};
3997     auto rc = decode_apply_complete_req(
3998         requestMsg1, sizeof(pldm_apply_complete_req), &outApplyResult,
3999         &outCompActivationModification);
4000     EXPECT_EQ(rc, PLDM_SUCCESS);
4001     EXPECT_EQ(outApplyResult, applyResult1);
4002     EXPECT_EQ(outCompActivationModification.value, compActivationModification1);
4003 
4004     constexpr uint8_t applyResult2 = PLDM_FWUP_APPLY_SUCCESS;
4005     constexpr std::bitset<16> compActivationModification2{};
4006     constexpr std::array<uint8_t, hdrSize + sizeof(pldm_apply_complete_req)>
4007         applyCompleteReq2{0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
4008     auto requestMsg2 =
4009         // NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast)
4010         reinterpret_cast<const pldm_msg*>(applyCompleteReq2.data());
4011     rc = decode_apply_complete_req(requestMsg2, sizeof(pldm_apply_complete_req),
4012                                    &outApplyResult,
4013                                    &outCompActivationModification);
4014     EXPECT_EQ(rc, PLDM_SUCCESS);
4015     EXPECT_EQ(outApplyResult, applyResult2);
4016     EXPECT_EQ(outCompActivationModification.value, compActivationModification2);
4017 }
4018 
4019 TEST(ApplyComplete, errorPathDecodeRequest)
4020 {
4021     constexpr std::array<uint8_t, hdrSize> applyCompleteReq1{0x00, 0x00, 0x00};
4022     auto requestMsg1 =
4023         // NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast)
4024         reinterpret_cast<const pldm_msg*>(applyCompleteReq1.data());
4025     uint8_t outApplyResult = 0;
4026     bitfield16_t outCompActivationModification{};
4027 
4028     auto rc = decode_apply_complete_req(
4029         nullptr, sizeof(pldm_apply_complete_req), &outApplyResult,
4030         &outCompActivationModification);
4031     EXPECT_EQ(rc, PLDM_ERROR_INVALID_DATA);
4032 
4033     rc = decode_apply_complete_req(requestMsg1, sizeof(pldm_apply_complete_req),
4034                                    nullptr, &outCompActivationModification);
4035     EXPECT_EQ(rc, PLDM_ERROR_INVALID_DATA);
4036 
4037     rc = decode_apply_complete_req(requestMsg1, sizeof(pldm_apply_complete_req),
4038                                    &outApplyResult, nullptr);
4039     EXPECT_EQ(rc, PLDM_ERROR_INVALID_DATA);
4040 
4041     rc = decode_apply_complete_req(requestMsg1, 0, &outApplyResult,
4042                                    &outCompActivationModification);
4043     EXPECT_EQ(rc, PLDM_ERROR_INVALID_LENGTH);
4044 
4045     constexpr std::array<uint8_t, hdrSize + sizeof(pldm_apply_complete_req)>
4046         applyCompleteReq2{0x00, 0x00, 0x00, 0x00, 0x01, 0x00};
4047     auto requestMsg2 =
4048         // NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast)
4049         reinterpret_cast<const pldm_msg*>(applyCompleteReq2.data());
4050     rc = decode_apply_complete_req(requestMsg2, sizeof(pldm_apply_complete_req),
4051                                    &outApplyResult,
4052                                    &outCompActivationModification);
4053     EXPECT_EQ(rc, PLDM_ERROR_INVALID_DATA);
4054 }
4055 
4056 TEST(ApplyComplete, goodPathEncodeResponse)
4057 {
4058     constexpr uint8_t instanceId = 6;
4059     constexpr uint8_t completionCode = PLDM_SUCCESS;
4060     constexpr std::array<uint8_t, hdrSize + sizeof(completionCode)>
4061         outApplyCompleteResponse1{0x06, 0x05, 0x18, 0x00};
4062     std::array<uint8_t, hdrSize + sizeof(completionCode)>
4063         applyCompleteResponse1{0x00, 0x00, 0x00, 0x00};
4064     auto responseMsg1 =
4065         // NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast)
4066         reinterpret_cast<pldm_msg*>(applyCompleteResponse1.data());
4067     auto rc = encode_apply_complete_resp(instanceId, completionCode,
4068                                          responseMsg1, sizeof(completionCode));
4069     EXPECT_EQ(rc, PLDM_SUCCESS);
4070     EXPECT_EQ(applyCompleteResponse1, outApplyCompleteResponse1);
4071 
4072     constexpr std::array<uint8_t, hdrSize + sizeof(completionCode)>
4073         outApplyCompleteResponse2{0x06, 0x05, 0x18, 0x88};
4074     std::array<uint8_t, hdrSize + sizeof(completionCode)>
4075         applyCompleteResponse2{0x00, 0x00, 0x00, 0x00};
4076     auto responseMsg2 =
4077         // NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast)
4078         reinterpret_cast<pldm_msg*>(applyCompleteResponse2.data());
4079     rc = encode_apply_complete_resp(instanceId, PLDM_FWUP_COMMAND_NOT_EXPECTED,
4080                                     responseMsg2, sizeof(completionCode));
4081     EXPECT_EQ(rc, PLDM_SUCCESS);
4082     EXPECT_EQ(applyCompleteResponse2, outApplyCompleteResponse2);
4083 }
4084 
4085 TEST(ApplyComplete, errorPathEncodeResponse)
4086 {
4087     std::array<uint8_t, hdrSize> applyCompleteResponse{0x00, 0x00, 0x00};
4088     auto responseMsg =
4089         // NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast)
4090         reinterpret_cast<pldm_msg*>(applyCompleteResponse.data());
4091     auto rc = encode_apply_complete_resp(0, PLDM_SUCCESS, nullptr, 0);
4092     EXPECT_EQ(rc, PLDM_ERROR_INVALID_DATA);
4093 
4094     rc = encode_apply_complete_resp(0, PLDM_SUCCESS, responseMsg, 0);
4095     EXPECT_EQ(rc, PLDM_ERROR_INVALID_LENGTH);
4096 }
4097 
4098 TEST(ActivateFirmware, goodPathEncodeRequest)
4099 {
4100     constexpr uint8_t instanceId = 7;
4101 
4102     std::array<uint8_t, hdrSize + sizeof(pldm_activate_firmware_req)> request{};
4103     // NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast)
4104     auto requestMsg = reinterpret_cast<pldm_msg*>(request.data());
4105 
4106     auto rc = encode_activate_firmware_req(
4107         instanceId, PLDM_ACTIVATE_SELF_CONTAINED_COMPONENTS, requestMsg,
4108         sizeof(pldm_activate_firmware_req));
4109     EXPECT_EQ(rc, PLDM_SUCCESS);
4110 
4111     std::array<uint8_t, hdrSize + sizeof(pldm_activate_firmware_req)>
4112         outRequest{0x87, 0x05, 0x1a, 0x01};
4113     EXPECT_EQ(request, outRequest);
4114 }
4115 
4116 TEST(ActivateFirmware, errorPathEncodeRequest)
4117 {
4118     std::array<uint8_t, hdrSize + sizeof(pldm_activate_firmware_req)> request{};
4119     // NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast)
4120     auto requestMsg = reinterpret_cast<pldm_msg*>(request.data());
4121 
4122     auto rc = encode_activate_firmware_req(
4123         0, PLDM_ACTIVATE_SELF_CONTAINED_COMPONENTS, nullptr,
4124         sizeof(pldm_activate_firmware_req));
4125     EXPECT_EQ(rc, PLDM_ERROR_INVALID_DATA);
4126 
4127     rc = encode_activate_firmware_req(
4128         0, PLDM_ACTIVATE_SELF_CONTAINED_COMPONENTS, requestMsg, 0);
4129     EXPECT_EQ(rc, PLDM_ERROR_INVALID_LENGTH);
4130 
4131     rc = encode_activate_firmware_req(0, 2, requestMsg,
4132                                       sizeof(pldm_activate_firmware_req));
4133     EXPECT_EQ(rc, PLDM_ERROR_INVALID_DATA);
4134 }
4135 
4136 TEST(ActivateFirmware, goodPathDecodeResponse)
4137 {
4138     constexpr uint16_t estimatedTimeForActivation100s = 100;
4139     constexpr std::array<uint8_t, hdrSize + sizeof(pldm_activate_firmware_resp)>
4140         activateFirmwareResponse1{0x00, 0x00, 0x00, 0x00, 0x64, 0x00};
4141     auto responseMsg1 =
4142         // NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast)
4143         reinterpret_cast<const pldm_msg*>(activateFirmwareResponse1.data());
4144 
4145     uint8_t completionCode = 0;
4146     uint16_t estimatedTimeForActivation = 0;
4147 
4148     auto rc = decode_activate_firmware_resp(
4149         responseMsg1, sizeof(pldm_activate_firmware_resp), &completionCode,
4150         &estimatedTimeForActivation);
4151 
4152     EXPECT_EQ(rc, PLDM_SUCCESS);
4153     EXPECT_EQ(completionCode, PLDM_SUCCESS);
4154     EXPECT_EQ(estimatedTimeForActivation, estimatedTimeForActivation100s);
4155 
4156     constexpr std::array<uint8_t, hdrSize + sizeof(completionCode)>
4157         activateFirmwareResponse2{0x00, 0x00, 0x00, 0x85};
4158     auto responseMsg2 =
4159         // NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast)
4160         reinterpret_cast<const pldm_msg*>(activateFirmwareResponse2.data());
4161 
4162     rc = decode_activate_firmware_resp(responseMsg2, sizeof(completionCode),
4163                                        &completionCode,
4164                                        &estimatedTimeForActivation);
4165 
4166     EXPECT_EQ(rc, PLDM_SUCCESS);
4167     EXPECT_EQ(completionCode, PLDM_FWUP_INCOMPLETE_UPDATE);
4168 }
4169 
4170 TEST(ActivateFirmware, errorPathDecodeResponse)
4171 {
4172     constexpr std::array<uint8_t, hdrSize + sizeof(pldm_activate_firmware_resp)>
4173         activateFirmwareResponse{0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
4174     auto responseMsg =
4175         // NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast)
4176         reinterpret_cast<const pldm_msg*>(activateFirmwareResponse.data());
4177 
4178     uint8_t completionCode = 0;
4179     uint16_t estimatedTimeForActivation = 0;
4180 
4181     auto rc = decode_activate_firmware_resp(
4182         nullptr, sizeof(pldm_activate_firmware_resp), &completionCode,
4183         &estimatedTimeForActivation);
4184     EXPECT_EQ(rc, PLDM_ERROR_INVALID_DATA);
4185 
4186     rc = decode_activate_firmware_resp(responseMsg,
4187                                        sizeof(pldm_activate_firmware_resp),
4188                                        nullptr, &estimatedTimeForActivation);
4189     EXPECT_EQ(rc, PLDM_ERROR_INVALID_DATA);
4190 
4191     rc = decode_activate_firmware_resp(responseMsg,
4192                                        sizeof(pldm_activate_firmware_resp),
4193                                        &completionCode, nullptr);
4194     EXPECT_EQ(rc, PLDM_ERROR_INVALID_DATA);
4195 
4196     rc = decode_activate_firmware_resp(responseMsg, 0, &completionCode,
4197                                        &estimatedTimeForActivation);
4198     EXPECT_EQ(rc, PLDM_ERROR_INVALID_DATA);
4199 
4200     rc = decode_activate_firmware_resp(
4201         responseMsg, sizeof(pldm_activate_firmware_resp) - 1, &completionCode,
4202         &estimatedTimeForActivation);
4203     EXPECT_EQ(rc, PLDM_ERROR_INVALID_LENGTH);
4204 }
4205 
4206 TEST(GetStatus, goodPathEncodeRequest)
4207 {
4208     constexpr uint8_t instanceId = 8;
4209     std::array<uint8_t, hdrSize> request{};
4210     // NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast)
4211     auto requestMsg = reinterpret_cast<pldm_msg*>(request.data());
4212 
4213     auto rc = encode_get_status_req(instanceId, requestMsg,
4214                                     PLDM_GET_STATUS_REQ_BYTES);
4215     EXPECT_EQ(rc, PLDM_SUCCESS);
4216 
4217     constexpr std::array<uint8_t, hdrSize> outRequest{0x88, 0x05, 0x1b};
4218     EXPECT_EQ(request, outRequest);
4219 }
4220 
4221 TEST(GetStatus, errorPathEncodeRequest)
4222 {
4223     std::array<uint8_t, hdrSize + sizeof(uint8_t)> request{};
4224     // NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast)
4225     auto requestMsg = reinterpret_cast<pldm_msg*>(request.data());
4226 
4227     auto rc = encode_get_status_req(0, nullptr, PLDM_GET_STATUS_REQ_BYTES);
4228     EXPECT_EQ(rc, PLDM_ERROR_INVALID_DATA);
4229 
4230     rc = encode_get_status_req(0, requestMsg, PLDM_GET_STATUS_REQ_BYTES + 1);
4231     EXPECT_EQ(rc, PLDM_ERROR_INVALID_LENGTH);
4232 }
4233 
4234 TEST(GetStatus, goodPathDecodeResponse)
4235 {
4236     constexpr std::bitset<32> updateOptionFlagsEnabled1{0};
4237     constexpr std::array<uint8_t, hdrSize + sizeof(pldm_get_status_resp)>
4238         getStatusResponse1{0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x03,
4239                            0x09, 0x65, 0x05, 0x00, 0x00, 0x00, 0x00};
4240     auto responseMsg1 =
4241         // NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast)
4242         reinterpret_cast<const pldm_msg*>(getStatusResponse1.data());
4243 
4244     uint8_t completionCode = 0;
4245     uint8_t currentState = 0;
4246     uint8_t previousState = 0;
4247     uint8_t auxState = 0;
4248     uint8_t auxStateStatus = 0;
4249     uint8_t progressPercent = 0;
4250     uint8_t reasonCode = 0;
4251     bitfield32_t updateOptionFlagsEnabled{0};
4252 
4253     auto rc = decode_get_status_resp(
4254         responseMsg1, getStatusResponse1.size() - hdrSize, &completionCode,
4255         &currentState, &previousState, &auxState, &auxStateStatus,
4256         &progressPercent, &reasonCode, &updateOptionFlagsEnabled);
4257 
4258     EXPECT_EQ(rc, PLDM_SUCCESS);
4259     EXPECT_EQ(completionCode, PLDM_SUCCESS);
4260     EXPECT_EQ(currentState, PLDM_FD_STATE_IDLE);
4261     EXPECT_EQ(previousState, PLDM_FD_STATE_DOWNLOAD);
4262     EXPECT_EQ(auxState, PLDM_FD_IDLE_LEARN_COMPONENTS_READ_XFER);
4263     EXPECT_EQ(auxStateStatus, PLDM_FD_TIMEOUT);
4264     EXPECT_EQ(progressPercent, PLDM_FWUP_MAX_PROGRESS_PERCENT);
4265     EXPECT_EQ(reasonCode, PLDM_FD_TIMEOUT_DOWNLOAD);
4266     EXPECT_EQ(updateOptionFlagsEnabled.value, updateOptionFlagsEnabled1);
4267 
4268     // Bit position 0 - Force update of component – FD will perform a force
4269     // update of the component.
4270     constexpr std::bitset<32> updateOptionFlagsEnabled2{1};
4271     constexpr uint8_t progressPercent2 = 50;
4272     constexpr std::array<uint8_t, hdrSize + sizeof(pldm_get_status_resp)>
4273         getStatusResponse2{0x00, 0x00, 0x00, 0x00, 0x04, 0x03, 0x00,
4274                            0x70, 0x32, 0x05, 0x01, 0x00, 0x00, 0x00};
4275     auto responseMsg2 =
4276         // NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast)
4277         reinterpret_cast<const pldm_msg*>(getStatusResponse2.data());
4278 
4279     rc = decode_get_status_resp(
4280         responseMsg2, getStatusResponse2.size() - hdrSize, &completionCode,
4281         &currentState, &previousState, &auxState, &auxStateStatus,
4282         &progressPercent, &reasonCode, &updateOptionFlagsEnabled);
4283 
4284     EXPECT_EQ(rc, PLDM_SUCCESS);
4285     EXPECT_EQ(completionCode, PLDM_SUCCESS);
4286     EXPECT_EQ(currentState, PLDM_FD_STATE_VERIFY);
4287     EXPECT_EQ(previousState, PLDM_FD_STATE_DOWNLOAD);
4288     EXPECT_EQ(auxState, PLDM_FD_OPERATION_IN_PROGRESS);
4289     EXPECT_EQ(auxStateStatus, PLDM_FD_VENDOR_DEFINED_STATUS_CODE_START);
4290     EXPECT_EQ(progressPercent, progressPercent2);
4291     EXPECT_EQ(reasonCode, PLDM_FD_TIMEOUT_DOWNLOAD);
4292     EXPECT_EQ(updateOptionFlagsEnabled.value, updateOptionFlagsEnabled2);
4293 
4294 #ifdef LIBPLDM_API_TESTING
4295     /* Check the roundtrip */
4296     PLDM_MSG_DEFINE_P(enc, 1000);
4297     size_t enc_payload_len = 1000;
4298     const struct pldm_get_status_resp status_enc = {
4299         .completion_code = PLDM_SUCCESS,
4300         .current_state = currentState,
4301         .previous_state = previousState,
4302         .aux_state = auxState,
4303         .aux_state_status = auxStateStatus,
4304         .progress_percent = progressPercent,
4305         .reason_code = reasonCode,
4306         .update_option_flags_enabled = updateOptionFlagsEnabled,
4307     };
4308     rc = encode_get_status_resp(FIXED_INSTANCE_ID, &status_enc, enc,
4309                                 &enc_payload_len);
4310     EXPECT_EQ(rc, PLDM_SUCCESS);
4311     EXPECT_EQ(enc_payload_len + hdrSize, getStatusResponse2.size());
4312     EXPECT_TRUE(std::equal(getStatusResponse2.begin() + hdrSize,
4313                            getStatusResponse2.end(), enc_buf + hdrSize));
4314     check_response(enc, PLDM_GET_STATUS);
4315 #endif
4316 
4317     /* Check a not-ready completion code */
4318     constexpr std::array<uint8_t, hdrSize + sizeof(completionCode)>
4319         getStatusResponse3{0x00, 0x00, 0x00, 0x04};
4320     auto responseMsg3 =
4321         // NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast)
4322         reinterpret_cast<const pldm_msg*>(getStatusResponse3.data());
4323     rc = decode_get_status_resp(
4324         responseMsg3, getStatusResponse3.size() - hdrSize, &completionCode,
4325         &currentState, &previousState, &auxState, &auxStateStatus,
4326         &progressPercent, &reasonCode, &updateOptionFlagsEnabled);
4327     EXPECT_EQ(rc, PLDM_SUCCESS);
4328     EXPECT_EQ(completionCode, PLDM_ERROR_NOT_READY);
4329 }
4330 
4331 TEST(GetStatus, errorPathDecodeResponse)
4332 {
4333     uint8_t completionCode = 0;
4334     uint8_t currentState = 0;
4335     uint8_t previousState = 0;
4336     uint8_t auxState = 0;
4337     uint8_t auxStateStatus = 0;
4338     uint8_t progressPercent = 0;
4339     uint8_t reasonCode = 0;
4340     bitfield32_t updateOptionFlagsEnabled{0};
4341 
4342     constexpr std::array<uint8_t, hdrSize> getStatusResponse1{0x00, 0x00, 0x00};
4343     auto responseMsg1 =
4344         // NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast)
4345         reinterpret_cast<const pldm_msg*>(getStatusResponse1.data());
4346 
4347     auto rc = decode_get_status_resp(
4348         nullptr, getStatusResponse1.size() - hdrSize, &completionCode,
4349         &currentState, &previousState, &auxState, &auxStateStatus,
4350         &progressPercent, &reasonCode, &updateOptionFlagsEnabled);
4351     EXPECT_EQ(rc, PLDM_ERROR_INVALID_DATA);
4352 
4353     rc = decode_get_status_resp(
4354         responseMsg1, getStatusResponse1.size() - hdrSize, nullptr,
4355         &currentState, &previousState, &auxState, &auxStateStatus,
4356         &progressPercent, &reasonCode, &updateOptionFlagsEnabled);
4357     EXPECT_EQ(rc, PLDM_ERROR_INVALID_DATA);
4358 
4359     rc = decode_get_status_resp(
4360         responseMsg1, getStatusResponse1.size() - hdrSize, &completionCode,
4361         nullptr, &previousState, &auxState, &auxStateStatus, &progressPercent,
4362         &reasonCode, &updateOptionFlagsEnabled);
4363     EXPECT_EQ(rc, PLDM_ERROR_INVALID_DATA);
4364 
4365     rc = decode_get_status_resp(
4366         responseMsg1, getStatusResponse1.size() - hdrSize, &completionCode,
4367         &currentState, nullptr, &auxState, &auxStateStatus, &progressPercent,
4368         &reasonCode, &updateOptionFlagsEnabled);
4369     EXPECT_EQ(rc, PLDM_ERROR_INVALID_DATA);
4370 
4371     rc = decode_get_status_resp(
4372         responseMsg1, getStatusResponse1.size() - hdrSize, &completionCode,
4373         &currentState, &previousState, nullptr, &auxStateStatus,
4374         &progressPercent, &reasonCode, &updateOptionFlagsEnabled);
4375     EXPECT_EQ(rc, PLDM_ERROR_INVALID_DATA);
4376 
4377     rc = decode_get_status_resp(
4378         responseMsg1, getStatusResponse1.size() - hdrSize, &completionCode,
4379         &currentState, &previousState, &auxState, nullptr, &progressPercent,
4380         &reasonCode, &updateOptionFlagsEnabled);
4381     EXPECT_EQ(rc, PLDM_ERROR_INVALID_DATA);
4382 
4383     rc = decode_get_status_resp(
4384         responseMsg1, getStatusResponse1.size() - hdrSize, &completionCode,
4385         &currentState, &previousState, &auxState, &auxStateStatus, nullptr,
4386         &reasonCode, &updateOptionFlagsEnabled);
4387     EXPECT_EQ(rc, PLDM_ERROR_INVALID_DATA);
4388 
4389     rc = decode_get_status_resp(
4390         responseMsg1, getStatusResponse1.size() - hdrSize, &completionCode,
4391         &currentState, &previousState, &auxState, &auxStateStatus,
4392         &progressPercent, nullptr, &updateOptionFlagsEnabled);
4393     EXPECT_EQ(rc, PLDM_ERROR_INVALID_DATA);
4394 
4395     rc = decode_get_status_resp(
4396         responseMsg1, getStatusResponse1.size() - hdrSize, &completionCode,
4397         &currentState, &previousState, &auxState, &auxStateStatus,
4398         &progressPercent, &reasonCode, nullptr);
4399     EXPECT_EQ(rc, PLDM_ERROR_INVALID_DATA);
4400 
4401     rc = decode_get_status_resp(
4402         responseMsg1, getStatusResponse1.size() - hdrSize, &completionCode,
4403         &currentState, &previousState, &auxState, &auxStateStatus,
4404         &progressPercent, &reasonCode, &updateOptionFlagsEnabled);
4405     EXPECT_EQ(rc, PLDM_ERROR_INVALID_DATA);
4406 
4407     constexpr std::array<uint8_t, hdrSize + sizeof(pldm_get_status_resp) - 1>
4408         getStatusResponse2{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
4409                            0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
4410     auto responseMsg2 =
4411         // NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast)
4412         reinterpret_cast<const pldm_msg*>(getStatusResponse2.data());
4413     rc = decode_get_status_resp(
4414         responseMsg2, getStatusResponse2.size() - hdrSize, &completionCode,
4415         &currentState, &previousState, &auxState, &auxStateStatus,
4416         &progressPercent, &reasonCode, &updateOptionFlagsEnabled);
4417     EXPECT_EQ(rc, PLDM_ERROR_INVALID_LENGTH);
4418 
4419     constexpr std::array<uint8_t, hdrSize + sizeof(pldm_get_status_resp)>
4420         getStatusResponse3{0x00, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00,
4421                            0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
4422     auto responseMsg3 =
4423         // NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast)
4424         reinterpret_cast<const pldm_msg*>(getStatusResponse3.data());
4425     rc = decode_get_status_resp(
4426         responseMsg3, getStatusResponse3.size() - hdrSize, &completionCode,
4427         &currentState, &previousState, &auxState, &auxStateStatus,
4428         &progressPercent, &reasonCode, &updateOptionFlagsEnabled);
4429     EXPECT_EQ(rc, PLDM_ERROR_INVALID_DATA);
4430 
4431     constexpr std::array<uint8_t, hdrSize + sizeof(pldm_get_status_resp)>
4432         getStatusResponse4{0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x00,
4433                            0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
4434     auto responseMsg4 =
4435         // NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast)
4436         reinterpret_cast<const pldm_msg*>(getStatusResponse4.data());
4437     rc = decode_get_status_resp(
4438         responseMsg4, getStatusResponse4.size() - hdrSize, &completionCode,
4439         &currentState, &previousState, &auxState, &auxStateStatus,
4440         &progressPercent, &reasonCode, &updateOptionFlagsEnabled);
4441     EXPECT_EQ(rc, PLDM_ERROR_INVALID_DATA);
4442 
4443     constexpr std::array<uint8_t, hdrSize + sizeof(pldm_get_status_resp)>
4444         getStatusResponse5{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04,
4445                            0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
4446     auto responseMsg5 =
4447         // NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast)
4448         reinterpret_cast<const pldm_msg*>(getStatusResponse5.data());
4449     rc = decode_get_status_resp(
4450         responseMsg5, getStatusResponse5.size() - hdrSize, &completionCode,
4451         &currentState, &previousState, &auxState, &auxStateStatus,
4452         &progressPercent, &reasonCode, &updateOptionFlagsEnabled);
4453     EXPECT_EQ(rc, PLDM_ERROR_INVALID_DATA);
4454 
4455     constexpr std::array<uint8_t, hdrSize + sizeof(pldm_get_status_resp)>
4456         getStatusResponse6{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
4457                            0x0b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
4458     auto responseMsg6 =
4459         // NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast)
4460         reinterpret_cast<const pldm_msg*>(getStatusResponse6.data());
4461     rc = decode_get_status_resp(
4462         responseMsg6, getStatusResponse6.size() - hdrSize, &completionCode,
4463         &currentState, &previousState, &auxState, &auxStateStatus,
4464         &progressPercent, &reasonCode, &updateOptionFlagsEnabled);
4465     EXPECT_EQ(rc, PLDM_ERROR_INVALID_DATA);
4466 
4467     constexpr std::array<uint8_t, hdrSize + sizeof(pldm_get_status_resp)>
4468         getStatusResponse7{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
4469                            0x00, 0x66, 0x00, 0x00, 0x00, 0x00, 0x00};
4470     auto responseMsg7 =
4471         // NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast)
4472         reinterpret_cast<const pldm_msg*>(getStatusResponse7.data());
4473     rc = decode_get_status_resp(
4474         responseMsg7, getStatusResponse7.size() - hdrSize, &completionCode,
4475         &currentState, &previousState, &auxState, &auxStateStatus,
4476         &progressPercent, &reasonCode, &updateOptionFlagsEnabled);
4477     EXPECT_EQ(rc, PLDM_ERROR_INVALID_DATA);
4478 
4479     constexpr std::array<uint8_t, hdrSize + sizeof(pldm_get_status_resp)>
4480         getStatusResponse8{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
4481                            0x00, 0x00, 0xc7, 0x00, 0x00, 0x00, 0x00};
4482     auto responseMsg8 =
4483         // NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast)
4484         reinterpret_cast<const pldm_msg*>(getStatusResponse8.data());
4485     rc = decode_get_status_resp(
4486         responseMsg8, getStatusResponse8.size() - hdrSize, &completionCode,
4487         &currentState, &previousState, &auxState, &auxStateStatus,
4488         &progressPercent, &reasonCode, &updateOptionFlagsEnabled);
4489     EXPECT_EQ(rc, PLDM_ERROR_INVALID_DATA);
4490 
4491     // AuxState is not PLDM_FD_IDLE_LEARN_COMPONENTS_READ_XFER when the state is
4492     // IDLE
4493     constexpr std::array<uint8_t, hdrSize + sizeof(pldm_get_status_resp)>
4494         getStatusResponse9{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
4495                            0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
4496     auto responseMsg9 =
4497         // NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast)
4498         reinterpret_cast<const pldm_msg*>(getStatusResponse9.data());
4499     rc = decode_get_status_resp(
4500         responseMsg9, getStatusResponse9.size() - hdrSize, &completionCode,
4501         &currentState, &previousState, &auxState, &auxStateStatus,
4502         &progressPercent, &reasonCode, &updateOptionFlagsEnabled);
4503     EXPECT_EQ(rc, PLDM_ERROR_INVALID_DATA);
4504 }
4505 
4506 TEST(CancelUpdateComponent, goodPathEncodeRequest)
4507 {
4508     constexpr uint8_t instanceId = 9;
4509     std::array<uint8_t, hdrSize> request{};
4510     // NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast)
4511     auto requestMsg = reinterpret_cast<pldm_msg*>(request.data());
4512 
4513     auto rc = encode_cancel_update_component_req(
4514         instanceId, requestMsg, PLDM_CANCEL_UPDATE_COMPONENT_REQ_BYTES);
4515     EXPECT_EQ(rc, PLDM_SUCCESS);
4516 
4517     constexpr std::array<uint8_t, hdrSize> outRequest{0x89, 0x05, 0x1c};
4518     EXPECT_EQ(request, outRequest);
4519 }
4520 
4521 TEST(CancelUpdateComponent, errorPathEncodeRequest)
4522 {
4523     std::array<uint8_t, hdrSize + sizeof(uint8_t)> request{};
4524     // NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast)
4525     auto requestMsg = reinterpret_cast<pldm_msg*>(request.data());
4526 
4527     auto rc = encode_cancel_update_component_req(
4528         0, nullptr, PLDM_CANCEL_UPDATE_COMPONENT_REQ_BYTES);
4529     EXPECT_EQ(rc, PLDM_ERROR_INVALID_DATA);
4530 
4531     rc = encode_cancel_update_component_req(
4532         0, requestMsg, PLDM_CANCEL_UPDATE_COMPONENT_REQ_BYTES + 1);
4533     EXPECT_EQ(rc, PLDM_ERROR_INVALID_LENGTH);
4534 }
4535 
4536 TEST(CancelUpdateComponent, testGoodDecodeResponse)
4537 {
4538     uint8_t completionCode = 0;
4539     constexpr std::array<uint8_t, hdrSize + sizeof(completionCode)>
4540         cancelUpdateComponentResponse1{0x00, 0x00, 0x00, 0x00};
4541     // NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast)
4542     auto responseMsg1 = reinterpret_cast<const pldm_msg*>(
4543         cancelUpdateComponentResponse1.data());
4544     auto rc = decode_cancel_update_component_resp(
4545         responseMsg1, cancelUpdateComponentResponse1.size() - hdrSize,
4546         &completionCode);
4547     EXPECT_EQ(rc, PLDM_SUCCESS);
4548     EXPECT_EQ(completionCode, PLDM_SUCCESS);
4549 
4550     constexpr std::array<uint8_t, hdrSize + sizeof(completionCode)>
4551         cancelUpdateComponentResponse2{0x00, 0x00, 0x00, 0x86};
4552     // NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast)
4553     auto responseMsg2 = reinterpret_cast<const pldm_msg*>(
4554         cancelUpdateComponentResponse2.data());
4555     rc = decode_cancel_update_component_resp(
4556         responseMsg2, cancelUpdateComponentResponse2.size() - hdrSize,
4557         &completionCode);
4558     EXPECT_EQ(rc, PLDM_SUCCESS);
4559     EXPECT_EQ(completionCode, PLDM_FWUP_BUSY_IN_BACKGROUND);
4560 }
4561 
4562 TEST(CancelUpdateComponent, testBadDecodeResponse)
4563 {
4564     uint8_t completionCode = 0;
4565     constexpr std::array<uint8_t, hdrSize> cancelUpdateComponentResponse{
4566         0x00, 0x00, 0x00};
4567     auto responseMsg =
4568         // NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast)
4569         reinterpret_cast<const pldm_msg*>(cancelUpdateComponentResponse.data());
4570 
4571     auto rc = decode_cancel_update_component_resp(
4572         nullptr, cancelUpdateComponentResponse.size() - hdrSize,
4573         &completionCode);
4574     EXPECT_EQ(rc, PLDM_ERROR_INVALID_DATA);
4575 
4576     rc = decode_cancel_update_component_resp(
4577         responseMsg, cancelUpdateComponentResponse.size() - hdrSize, nullptr);
4578     EXPECT_EQ(rc, PLDM_ERROR_INVALID_DATA);
4579 
4580     rc = decode_cancel_update_component_resp(
4581         responseMsg, cancelUpdateComponentResponse.size() - hdrSize,
4582         &completionCode);
4583     EXPECT_EQ(rc, PLDM_ERROR_INVALID_LENGTH);
4584 }
4585 
4586 TEST(CancelUpdate, goodPathEncodeRequest)
4587 {
4588     constexpr uint8_t instanceId = 10;
4589     std::array<uint8_t, hdrSize> request{};
4590     // NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast)
4591     auto requestMsg = reinterpret_cast<pldm_msg*>(request.data());
4592 
4593     auto rc = encode_cancel_update_req(instanceId, requestMsg,
4594                                        PLDM_CANCEL_UPDATE_REQ_BYTES);
4595     EXPECT_EQ(rc, PLDM_SUCCESS);
4596 
4597     constexpr std::array<uint8_t, hdrSize> outRequest{0x8a, 0x05, 0x1d};
4598     EXPECT_EQ(request, outRequest);
4599 }
4600 
4601 TEST(CancelUpdate, errorPathEncodeRequest)
4602 {
4603     std::array<uint8_t, hdrSize + sizeof(uint8_t)> request{};
4604     // NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast)
4605     auto requestMsg = reinterpret_cast<pldm_msg*>(request.data());
4606 
4607     auto rc =
4608         encode_cancel_update_req(0, nullptr, PLDM_CANCEL_UPDATE_REQ_BYTES);
4609     EXPECT_EQ(rc, PLDM_ERROR_INVALID_DATA);
4610 
4611     rc = encode_cancel_update_req(0, requestMsg,
4612                                   PLDM_CANCEL_UPDATE_REQ_BYTES + 1);
4613     EXPECT_EQ(rc, PLDM_ERROR_INVALID_LENGTH);
4614 }
4615 
4616 TEST(CancelUpdate, goodPathDecodeResponse)
4617 {
4618     constexpr std::bitset<64> nonFunctioningComponentBitmap1{0};
4619     constexpr std::array<uint8_t, hdrSize + sizeof(pldm_cancel_update_resp)>
4620         cancelUpdateResponse1{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
4621                               0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
4622     auto responseMsg1 =
4623         // NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast)
4624         reinterpret_cast<const pldm_msg*>(cancelUpdateResponse1.data());
4625     uint8_t completionCode = 0;
4626     bool8_t nonFunctioningComponentIndication = 0;
4627     bitfield64_t nonFunctioningComponentBitmap{0};
4628     auto rc = decode_cancel_update_resp(
4629         responseMsg1, cancelUpdateResponse1.size() - hdrSize, &completionCode,
4630         &nonFunctioningComponentIndication, &nonFunctioningComponentBitmap);
4631     EXPECT_EQ(rc, PLDM_SUCCESS);
4632     EXPECT_EQ(completionCode, PLDM_SUCCESS);
4633     EXPECT_EQ(nonFunctioningComponentIndication,
4634               PLDM_FWUP_COMPONENTS_FUNCTIONING);
4635     EXPECT_EQ(nonFunctioningComponentBitmap.value,
4636               nonFunctioningComponentBitmap1);
4637 
4638     constexpr std::bitset<64> nonFunctioningComponentBitmap2{0x0101};
4639     constexpr std::array<uint8_t, hdrSize + sizeof(pldm_cancel_update_resp)>
4640         cancelUpdateResponse2{0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01,
4641                               0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
4642     auto responseMsg2 =
4643         // NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast)
4644         reinterpret_cast<const pldm_msg*>(cancelUpdateResponse2.data());
4645     rc = decode_cancel_update_resp(
4646         responseMsg2, cancelUpdateResponse2.size() - hdrSize, &completionCode,
4647         &nonFunctioningComponentIndication, &nonFunctioningComponentBitmap);
4648     EXPECT_EQ(rc, PLDM_SUCCESS);
4649     EXPECT_EQ(completionCode, PLDM_SUCCESS);
4650     EXPECT_EQ(nonFunctioningComponentIndication,
4651               PLDM_FWUP_COMPONENTS_NOT_FUNCTIONING);
4652     EXPECT_EQ(nonFunctioningComponentBitmap.value,
4653               nonFunctioningComponentBitmap2);
4654 
4655     constexpr std::array<uint8_t, hdrSize + sizeof(completionCode)>
4656         cancelUpdateResponse3{0x00, 0x00, 0x00, 0x86};
4657     auto responseMsg3 =
4658         // NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast)
4659         reinterpret_cast<const pldm_msg*>(cancelUpdateResponse3.data());
4660     rc = decode_cancel_update_resp(
4661         responseMsg3, cancelUpdateResponse3.size() - hdrSize, &completionCode,
4662         &nonFunctioningComponentIndication, &nonFunctioningComponentBitmap);
4663     EXPECT_EQ(rc, PLDM_SUCCESS);
4664     EXPECT_EQ(completionCode, PLDM_FWUP_BUSY_IN_BACKGROUND);
4665 }
4666 
4667 TEST(CancelUpdate, errorPathDecodeResponse)
4668 {
4669     constexpr std::array<uint8_t, hdrSize> cancelUpdateResponse1{0x00, 0x00,
4670                                                                  0x00};
4671     auto responseMsg1 =
4672         // NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast)
4673         reinterpret_cast<const pldm_msg*>(cancelUpdateResponse1.data());
4674     uint8_t completionCode = 0;
4675     bool8_t nonFunctioningComponentIndication = 0;
4676     bitfield64_t nonFunctioningComponentBitmap{0};
4677 
4678     auto rc = decode_cancel_update_resp(
4679         nullptr, cancelUpdateResponse1.size() - hdrSize, &completionCode,
4680         &nonFunctioningComponentIndication, &nonFunctioningComponentBitmap);
4681     EXPECT_EQ(rc, PLDM_ERROR_INVALID_DATA);
4682 
4683     rc = decode_cancel_update_resp(
4684         responseMsg1, cancelUpdateResponse1.size() - hdrSize, nullptr,
4685         &nonFunctioningComponentIndication, &nonFunctioningComponentBitmap);
4686     EXPECT_EQ(rc, PLDM_ERROR_INVALID_DATA);
4687 
4688     rc = decode_cancel_update_resp(
4689         responseMsg1, cancelUpdateResponse1.size() - hdrSize, &completionCode,
4690         nullptr, &nonFunctioningComponentBitmap);
4691     EXPECT_EQ(rc, PLDM_ERROR_INVALID_DATA);
4692 
4693     rc = decode_cancel_update_resp(
4694         responseMsg1, cancelUpdateResponse1.size() - hdrSize, &completionCode,
4695         &nonFunctioningComponentIndication, nullptr);
4696     EXPECT_EQ(rc, PLDM_ERROR_INVALID_DATA);
4697 
4698     rc = decode_cancel_update_resp(
4699         responseMsg1, cancelUpdateResponse1.size() - hdrSize, &completionCode,
4700         &nonFunctioningComponentIndication, &nonFunctioningComponentBitmap);
4701     EXPECT_EQ(rc, PLDM_ERROR_INVALID_DATA);
4702 
4703     constexpr std::array<uint8_t, hdrSize + sizeof(completionCode)>
4704         cancelUpdateResponse2{0x00, 0x00, 0x00, 0x00};
4705     auto responseMsg2 =
4706         // NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast)
4707         reinterpret_cast<const pldm_msg*>(cancelUpdateResponse2.data());
4708     rc = decode_cancel_update_resp(
4709         responseMsg2, cancelUpdateResponse2.size() - hdrSize, &completionCode,
4710         &nonFunctioningComponentIndication, &nonFunctioningComponentBitmap);
4711     EXPECT_EQ(rc, PLDM_ERROR_INVALID_LENGTH);
4712 
4713     constexpr std::array<uint8_t, hdrSize + sizeof(pldm_cancel_update_resp)>
4714         cancelUpdateResponse3{0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00,
4715                               0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
4716     auto responseMsg3 =
4717         // NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast)
4718         reinterpret_cast<const pldm_msg*>(cancelUpdateResponse3.data());
4719     rc = decode_cancel_update_resp(
4720         responseMsg3, cancelUpdateResponse3.size() - hdrSize, &completionCode,
4721         &nonFunctioningComponentIndication, &nonFunctioningComponentBitmap);
4722     EXPECT_EQ(rc, PLDM_ERROR_INVALID_DATA);
4723 }
4724