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