xref: /openbmc/libpldm/tests/dsp/fru.cpp (revision 615344fc)
1 #include <endian.h>
2 #include <libpldm/base.h>
3 #include <libpldm/fru.h>
4 #include <libpldm/utils.h>
5 
6 #include <array>
7 #include <cstdint>
8 #include <cstring>
9 #include <vector>
10 
11 #include <gtest/gtest.h>
12 
13 TEST(GetFruRecordTableMetadata, testGoodEncodeRequest)
14 {
15     std::array<uint8_t, sizeof(pldm_msg_hdr)> requestMsg{};
16     auto requestPtr = reinterpret_cast<pldm_msg*>(requestMsg.data());
17     auto rc = encode_get_fru_record_table_metadata_req(
18         0, requestPtr, PLDM_GET_FRU_RECORD_TABLE_METADATA_REQ_BYTES);
19     ASSERT_EQ(rc, PLDM_SUCCESS);
20     ASSERT_EQ(requestPtr->hdr.request, PLDM_REQUEST);
21     ASSERT_EQ(requestPtr->hdr.instance_id, 0u);
22     ASSERT_EQ(requestPtr->hdr.type, PLDM_FRU);
23     ASSERT_EQ(requestPtr->hdr.command, PLDM_GET_FRU_RECORD_TABLE_METADATA);
24 }
25 
26 TEST(GetFruRecordTableMetadata, testBadEncodeRequest)
27 {
28     auto rc = encode_get_fru_record_table_metadata_req(0, NULL, 0);
29     ASSERT_EQ(rc, PLDM_ERROR_INVALID_DATA);
30     std::array<uint8_t, sizeof(pldm_msg_hdr)> requestMsg{};
31     auto requestPtr = reinterpret_cast<pldm_msg*>(requestMsg.data());
32     rc = encode_get_fru_record_table_metadata_req(0, requestPtr, 1);
33     ASSERT_EQ(rc, PLDM_ERROR_INVALID_LENGTH);
34 }
35 
36 TEST(GetFruRecordTableMetadata, testGoodDecodeResponse)
37 {
38 
39     std::vector<uint8_t> responseMsg(
40         sizeof(pldm_msg_hdr) + PLDM_GET_FRU_RECORD_TABLE_METADATA_RESP_BYTES);
41     auto responsePtr = reinterpret_cast<pldm_msg*>(responseMsg.data());
42     size_t payload_length = responseMsg.size() - sizeof(pldm_msg_hdr);
43     auto response = reinterpret_cast<pldm_get_fru_record_table_metadata_resp*>(
44         responsePtr->payload);
45 
46     responsePtr->hdr.request = PLDM_RESPONSE;
47     responsePtr->hdr.instance_id = 0;
48     responsePtr->hdr.type = PLDM_FRU;
49     responsePtr->hdr.command = PLDM_GET_FRU_RECORD_TABLE_METADATA;
50     response->completion_code = PLDM_SUCCESS;
51     response->fru_data_major_version = 0x12;
52     response->fru_data_minor_version = 0x21;
53     response->fru_table_maximum_size = htole32(0x1234abcd);
54     response->fru_table_length = htole32(0x56781234);
55     response->total_record_set_identifiers = htole16(0x34ef);
56     response->total_table_records = htole16(0xeeef);
57     response->checksum = htole32(0x6543fa71);
58 
59     uint8_t completion_code = 0xff;
60     uint8_t fru_data_major_version = 0x00;
61     uint8_t fru_data_minor_version = 0x00;
62     uint32_t fru_table_maximum_size = htole32(0x00000000);
63     uint32_t fru_table_length = htole32(0x00000000);
64     uint16_t total_record_set_identifiers = htole16(0x0000);
65     uint16_t total_table_records = htole16(0x0000);
66     uint32_t checksum = htole32(0x00000000);
67 
68     auto rc = decode_get_fru_record_table_metadata_resp(
69         responsePtr, payload_length, &completion_code, &fru_data_major_version,
70         &fru_data_minor_version, &fru_table_maximum_size, &fru_table_length,
71         &total_record_set_identifiers, &total_table_records, &checksum);
72     ASSERT_EQ(rc, PLDM_SUCCESS);
73     ASSERT_EQ(completion_code, PLDM_SUCCESS);
74     ASSERT_EQ(fru_data_major_version, 0x12u);
75     ASSERT_EQ(fru_data_minor_version, 0x21u);
76     ASSERT_EQ(fru_table_maximum_size, 0x1234abcdu);
77     ASSERT_EQ(fru_table_length, 0x56781234u);
78     ASSERT_EQ(total_record_set_identifiers, 0x34efu);
79     ASSERT_EQ(total_table_records, 0xeeefu);
80     ASSERT_EQ(checksum, 0x6543fa71u);
81 
82     response->fru_data_major_version = 0x00;
83     response->fru_data_minor_version = 0x00;
84     response->fru_table_maximum_size = htole32(0x00000000);
85     response->fru_table_length = htole32(0x00000000);
86     response->total_record_set_identifiers = htole16(0x0000);
87     response->total_table_records = htole16(0x0000);
88     response->checksum = htole32(0x00000000);
89     fru_data_major_version = 0x00;
90     fru_data_minor_version = 0x00;
91     fru_table_maximum_size = htole32(0x00000000);
92     fru_table_length = htole32(0x00000000);
93     total_record_set_identifiers = htole16(0x0000);
94     total_table_records = htole16(0x0000);
95     checksum = htole32(0x00000000);
96     response->completion_code = PLDM_ERROR_INVALID_LENGTH;
97     rc = decode_get_fru_record_table_metadata_resp(
98         responsePtr, payload_length, &completion_code, &fru_data_major_version,
99         &fru_data_minor_version, &fru_table_maximum_size, &fru_table_length,
100         &total_record_set_identifiers, &total_table_records, &checksum);
101     ASSERT_EQ(rc, PLDM_SUCCESS);
102     ASSERT_EQ(responsePtr->hdr.request, PLDM_RESPONSE);
103     ASSERT_EQ(responsePtr->hdr.instance_id, 0u);
104     ASSERT_EQ(responsePtr->hdr.type, PLDM_FRU);
105     ASSERT_EQ(responsePtr->hdr.command, PLDM_GET_FRU_RECORD_TABLE_METADATA);
106     ASSERT_EQ(completion_code, PLDM_ERROR_INVALID_LENGTH);
107     ASSERT_EQ(fru_data_major_version, 0x00u);
108     ASSERT_EQ(fru_data_minor_version, 0x00u);
109     ASSERT_EQ(fru_table_maximum_size, 0x00000000u);
110     ASSERT_EQ(fru_table_length, 0x00000000u);
111     ASSERT_EQ(total_record_set_identifiers, 0x0000u);
112     ASSERT_EQ(total_table_records, 0x0000u);
113     ASSERT_EQ(checksum, 0x00000000u);
114 }
115 
116 TEST(GetFruRecordTableMetadata, testBadDecodeResponse)
117 {
118     std::vector<uint8_t> responseMsg(
119         sizeof(pldm_msg_hdr) + PLDM_GET_FRU_RECORD_TABLE_METADATA_RESP_BYTES);
120     auto responsePtr = reinterpret_cast<pldm_msg*>(responseMsg.data());
121     size_t payload_length = responseMsg.size() - sizeof(pldm_msg_hdr);
122     auto response = reinterpret_cast<pldm_get_fru_record_table_metadata_resp*>(
123         responsePtr->payload);
124 
125     response->completion_code = PLDM_SUCCESS;
126     response->fru_data_major_version = 0x12;
127     response->fru_data_minor_version = 0x21;
128     response->fru_table_maximum_size = htole32(0x1234abcd);
129     response->fru_table_length = htole32(0x56781234);
130     response->total_record_set_identifiers = htole16(0x34ef);
131     response->total_table_records = htole16(0xeeef);
132     response->checksum = htole32(0x6543fa71);
133 
134     uint8_t completion_code = 0xff;
135     uint8_t fru_data_major_version = 0x00;
136     uint8_t fru_data_minor_version = 0x00;
137     uint32_t fru_table_maximum_size = htole32(0x00000000);
138     uint32_t fru_table_length = htole32(0x00000000);
139     uint16_t total_record_set_identifiers = htole16(0x0000);
140     uint16_t total_table_records = htole16(0x0000);
141     uint32_t checksum = htole32(0x00000000);
142 
143     auto rc = decode_get_fru_record_table_metadata_resp(
144         responsePtr, PLDM_GET_FRU_RECORD_TABLE_METADATA_RESP_BYTES + 2,
145         &completion_code, &fru_data_major_version, &fru_data_minor_version,
146         &fru_table_maximum_size, &fru_table_length,
147         &total_record_set_identifiers, &total_table_records, &checksum);
148     ASSERT_EQ(rc, PLDM_ERROR_INVALID_LENGTH);
149 
150     rc = decode_get_fru_record_table_metadata_resp(
151         responsePtr, payload_length, &completion_code, NULL,
152         &fru_data_minor_version, &fru_table_maximum_size, &fru_table_length,
153         &total_record_set_identifiers, &total_table_records, &checksum);
154     ASSERT_EQ(rc, PLDM_ERROR_INVALID_DATA);
155 
156     rc = decode_get_fru_record_table_metadata_resp(
157         responsePtr, payload_length, &completion_code, &fru_data_major_version,
158         NULL, &fru_table_maximum_size, &fru_table_length,
159         &total_record_set_identifiers, &total_table_records, &checksum);
160     ASSERT_EQ(rc, PLDM_ERROR_INVALID_DATA);
161 
162     rc = decode_get_fru_record_table_metadata_resp(
163         responsePtr, payload_length, &completion_code, &fru_data_major_version,
164         &fru_data_minor_version, NULL, &fru_table_length,
165         &total_record_set_identifiers, &total_table_records, &checksum);
166     ASSERT_EQ(rc, PLDM_ERROR_INVALID_DATA);
167 
168     rc = decode_get_fru_record_table_metadata_resp(
169         responsePtr, payload_length, &completion_code, &fru_data_major_version,
170         &fru_data_minor_version, &fru_table_maximum_size, NULL,
171         &total_record_set_identifiers, &total_table_records, &checksum);
172     ASSERT_EQ(rc, PLDM_ERROR_INVALID_DATA);
173 
174     rc = decode_get_fru_record_table_metadata_resp(
175         responsePtr, payload_length, &completion_code, &fru_data_major_version,
176         &fru_data_minor_version, &fru_table_maximum_size, &fru_table_length,
177         NULL, &total_table_records, &checksum);
178     ASSERT_EQ(rc, PLDM_ERROR_INVALID_DATA);
179 
180     rc = decode_get_fru_record_table_metadata_resp(
181         responsePtr, payload_length, &completion_code, &fru_data_major_version,
182         &fru_data_minor_version, &fru_table_maximum_size, &fru_table_length,
183         &total_record_set_identifiers, NULL, &checksum);
184     ASSERT_EQ(rc, PLDM_ERROR_INVALID_DATA);
185 
186     rc = decode_get_fru_record_table_metadata_resp(
187         responsePtr, payload_length, &completion_code, &fru_data_major_version,
188         &fru_data_minor_version, &fru_table_maximum_size, &fru_table_length,
189         &total_record_set_identifiers, &total_table_records, NULL);
190     ASSERT_EQ(rc, PLDM_ERROR_INVALID_DATA);
191 }
192 
193 TEST(GetFruRecordTableMetadata, testGoodEncodeResponse)
194 {
195 
196     std::array<uint8_t, sizeof(pldm_msg_hdr) +
197                             PLDM_GET_FRU_RECORD_TABLE_METADATA_RESP_BYTES>
198         responseMsg{};
199     auto responsePtr = reinterpret_cast<pldm_msg*>(responseMsg.data());
200 
201     responsePtr->hdr.request = PLDM_RESPONSE;
202     responsePtr->hdr.instance_id = 0;
203     responsePtr->hdr.type = PLDM_FRU;
204     responsePtr->hdr.command = PLDM_GET_FRU_RECORD_TABLE_METADATA;
205 
206     uint8_t completion_code = PLDM_SUCCESS;
207     uint8_t fru_data_major_version = 0x12;
208     uint8_t fru_data_minor_version = 0x21;
209     uint32_t fru_table_maximum_size = htole32(0x1234abcd);
210     uint32_t fru_table_length = htole32(0x56781234);
211     uint16_t total_record_set_identifiers = htole16(0x34ef);
212     uint16_t total_table_records = htole16(0xeeef);
213     uint32_t checksum = htole32(0x6543fa71);
214 
215     auto rc = encode_get_fru_record_table_metadata_resp(
216         0, completion_code, fru_data_major_version, fru_data_minor_version,
217         fru_table_maximum_size, fru_table_length, total_record_set_identifiers,
218         total_table_records, checksum, responsePtr);
219 
220     auto response = reinterpret_cast<pldm_get_fru_record_table_metadata_resp*>(
221         responsePtr->payload);
222 
223     ASSERT_EQ(rc, PLDM_SUCCESS);
224     ASSERT_EQ(responsePtr->hdr.request, PLDM_RESPONSE);
225     ASSERT_EQ(responsePtr->hdr.instance_id, 0u);
226     ASSERT_EQ(responsePtr->hdr.type, PLDM_FRU);
227     ASSERT_EQ(responsePtr->hdr.command, PLDM_GET_FRU_RECORD_TABLE_METADATA);
228     ASSERT_EQ(response->completion_code, PLDM_SUCCESS);
229     ASSERT_EQ(response->fru_data_major_version, 0x12u);
230     ASSERT_EQ(response->fru_data_minor_version, 0x21u);
231     ASSERT_EQ(response->fru_table_maximum_size, 0x1234abcdu);
232     ASSERT_EQ(response->fru_table_length, 0x56781234u);
233     ASSERT_EQ(response->total_record_set_identifiers, 0x34efu);
234     ASSERT_EQ(response->total_table_records, 0xeeefu);
235     ASSERT_EQ(response->checksum, 0x6543fa71u);
236 
237     response->fru_data_major_version = 0;
238     response->fru_data_major_version = 0x00;
239     response->fru_data_minor_version = 0x00;
240     response->fru_table_maximum_size = htole32(0x00000000);
241     response->fru_table_length = htole32(0x00000000);
242     response->total_record_set_identifiers = htole16(0x0000);
243     response->total_table_records = htole16(0x0000);
244     response->checksum = htole32(0x00000000);
245     completion_code = PLDM_ERROR_INVALID_DATA;
246     rc = encode_get_fru_record_table_metadata_resp(
247         0, completion_code, fru_data_major_version, fru_data_minor_version,
248         fru_table_maximum_size, fru_table_length, total_record_set_identifiers,
249         total_table_records, checksum, responsePtr);
250 
251     ASSERT_EQ(rc, PLDM_SUCCESS);
252     ASSERT_EQ(responsePtr->hdr.request, PLDM_RESPONSE);
253     ASSERT_EQ(responsePtr->hdr.instance_id, 0u);
254     ASSERT_EQ(responsePtr->hdr.type, PLDM_FRU);
255     ASSERT_EQ(responsePtr->hdr.command, PLDM_GET_FRU_RECORD_TABLE_METADATA);
256     ASSERT_EQ(completion_code, PLDM_ERROR_INVALID_DATA);
257     ASSERT_EQ(response->fru_data_major_version, 0x00u);
258     ASSERT_EQ(response->fru_data_minor_version, 0x00u);
259     ASSERT_EQ(response->fru_table_maximum_size, 0x00000000u);
260     ASSERT_EQ(response->fru_table_length, 0x00000000u);
261     ASSERT_EQ(response->total_record_set_identifiers, 0x0000u);
262     ASSERT_EQ(response->total_table_records, 0x0000u);
263     ASSERT_EQ(response->checksum, 0x00000000u);
264 }
265 
266 TEST(GetFruRecordTableMetadata, testBadEncodeResponse)
267 {
268     std::array<uint8_t, sizeof(pldm_msg_hdr) +
269                             PLDM_GET_FRU_RECORD_TABLE_METADATA_RESP_BYTES>
270         responseMsg{};
271     auto responsePtr = reinterpret_cast<pldm_msg*>(responseMsg.data());
272 
273     uint8_t completion_code = PLDM_SUCCESS;
274     uint8_t fru_data_major_version = 0x12;
275     uint8_t fru_data_minor_version = 0x21;
276     uint32_t fru_table_maximum_size = htole32(0x1234abcd);
277     uint32_t fru_table_length = htole32(0x56781234);
278     uint16_t total_record_set_identifiers = htole16(0x34ef);
279     uint16_t total_table_records = htole16(0xeeef);
280     uint32_t checksum = htole32(0x6543fa71);
281 
282     auto rc = encode_get_fru_record_table_metadata_resp(
283         0, completion_code, fru_data_major_version, fru_data_minor_version,
284         fru_table_maximum_size, fru_table_length, total_record_set_identifiers,
285         total_table_records, checksum, NULL);
286 
287     auto response = reinterpret_cast<pldm_get_fru_record_table_metadata_resp*>(
288         responsePtr->payload);
289 
290     ASSERT_EQ(rc, PLDM_ERROR_INVALID_DATA);
291     ASSERT_EQ(completion_code, PLDM_SUCCESS);
292     ASSERT_EQ(response->fru_data_major_version, 0x00u);
293     ASSERT_EQ(response->fru_data_minor_version, 0x00u);
294     ASSERT_EQ(response->fru_table_maximum_size, 0x00000000u);
295     ASSERT_EQ(response->fru_table_length, 0x00000000u);
296     ASSERT_EQ(response->total_record_set_identifiers, 0x0000u);
297     ASSERT_EQ(response->total_table_records, 0x0000u);
298     ASSERT_EQ(response->checksum, 0x00000000u);
299 }
300 
301 TEST(GetFruRecordTable, testGoodDecodeRequest)
302 {
303     uint32_t data_transfer_handle = 31;
304     uint8_t transfer_operation_flag = PLDM_GET_FIRSTPART;
305     std::array<uint8_t,
306                PLDM_GET_FRU_RECORD_TABLE_REQ_BYTES + sizeof(pldm_msg_hdr)>
307         requestMsg{};
308     auto requestPtr = reinterpret_cast<pldm_msg*>(requestMsg.data());
309     size_t payload_length = requestMsg.size() - sizeof(pldm_msg_hdr);
310     auto request =
311         reinterpret_cast<pldm_get_fru_record_table_req*>(requestPtr->payload);
312 
313     request->data_transfer_handle = htole32(data_transfer_handle);
314     request->transfer_operation_flag = transfer_operation_flag;
315 
316     uint32_t ret_data_transfer_handle = 0;
317     uint8_t ret_transfer_operation_flag = 0;
318 
319     // Invoke decode get FRU record table request api
320     auto rc = decode_get_fru_record_table_req(requestPtr, payload_length,
321                                               &ret_data_transfer_handle,
322                                               &ret_transfer_operation_flag);
323 
324     ASSERT_EQ(rc, PLDM_SUCCESS);
325     ASSERT_EQ(data_transfer_handle, ret_data_transfer_handle);
326     ASSERT_EQ(transfer_operation_flag, ret_transfer_operation_flag);
327 }
328 
329 TEST(GetFruRecordTable, testBadDecodeRequest)
330 {
331     uint32_t data_transfer_handle = 0x0;
332     uint8_t transfer_operation_flag = PLDM_GET_FIRSTPART;
333 
334     std::array<uint8_t,
335                sizeof(pldm_msg_hdr) + PLDM_GET_FRU_RECORD_TABLE_REQ_BYTES>
336         requestMsg{};
337     auto requestPtr = reinterpret_cast<pldm_msg*>(requestMsg.data());
338 
339     // Payload message is missing
340     auto rc = decode_get_fru_record_table_req(NULL, 0, &data_transfer_handle,
341                                               &transfer_operation_flag);
342     ASSERT_EQ(rc, PLDM_ERROR_INVALID_DATA);
343 
344     // Payload length is invalid
345     rc = decode_get_fru_record_table_req(requestPtr, 0, &data_transfer_handle,
346                                          &transfer_operation_flag);
347     ASSERT_EQ(rc, PLDM_ERROR_INVALID_LENGTH);
348 }
349 
350 TEST(GetFruRecordTable, testGoodEncodeResponse)
351 {
352     uint8_t completion_code = 0;
353     uint32_t next_data_transfer_handle = 32;
354     uint8_t transfer_flag = PLDM_START_AND_END;
355 
356     std::vector<uint8_t> responseMsg(sizeof(pldm_msg_hdr) +
357                                      PLDM_GET_FRU_RECORD_TABLE_MIN_RESP_BYTES);
358 
359     auto responsePtr = reinterpret_cast<pldm_msg*>(responseMsg.data());
360     auto response =
361         reinterpret_cast<pldm_get_fru_record_table_resp*>(responsePtr->payload);
362 
363     // Invoke encode get FRU record table response api
364     auto rc = encode_get_fru_record_table_resp(0, completion_code,
365                                                next_data_transfer_handle,
366                                                transfer_flag, responsePtr);
367 
368     ASSERT_EQ(rc, PLDM_SUCCESS);
369     ASSERT_EQ(responsePtr->hdr.request, PLDM_RESPONSE);
370     ASSERT_EQ(responsePtr->hdr.instance_id, 0u);
371     ASSERT_EQ(responsePtr->hdr.type, PLDM_FRU);
372     ASSERT_EQ(responsePtr->hdr.command, PLDM_GET_FRU_RECORD_TABLE);
373     ASSERT_EQ(response->completion_code, PLDM_SUCCESS);
374     ASSERT_EQ(le32toh(response->next_data_transfer_handle),
375               next_data_transfer_handle);
376     ASSERT_EQ(response->transfer_flag, transfer_flag);
377 }
378 
379 TEST(GetFruRecordTable, testBadEncodeResponse)
380 {
381     uint32_t next_data_transfer_handle = 32;
382     uint8_t transfer_flag = PLDM_START_AND_END;
383 
384     std::vector<uint8_t> responseMsg(sizeof(pldm_msg_hdr) +
385                                      PLDM_GET_FRU_RECORD_TABLE_MIN_RESP_BYTES);
386 
387     auto responsePtr = reinterpret_cast<pldm_msg*>(responseMsg.data());
388     auto rc = encode_get_fru_record_table_resp(
389         0, PLDM_ERROR, next_data_transfer_handle, transfer_flag, responsePtr);
390 
391     ASSERT_EQ(rc, PLDM_SUCCESS);
392     ASSERT_EQ(responsePtr->hdr.request, PLDM_RESPONSE);
393     ASSERT_EQ(responsePtr->hdr.instance_id, 0u);
394     ASSERT_EQ(responsePtr->hdr.type, PLDM_FRU);
395     ASSERT_EQ(responsePtr->hdr.command, PLDM_GET_FRU_RECORD_TABLE);
396     ASSERT_EQ(responsePtr->payload[0], PLDM_ERROR);
397 
398     rc = encode_get_fru_record_table_resp(
399         0, PLDM_SUCCESS, next_data_transfer_handle, transfer_flag, nullptr);
400 
401     ASSERT_EQ(rc, PLDM_ERROR_INVALID_DATA);
402 }
403 
404 TEST(GetFruRecordTable, testGoodEncodeRequest)
405 
406 {
407     std::array<uint8_t,
408                sizeof(pldm_msg_hdr) + PLDM_GET_FRU_RECORD_TABLE_REQ_BYTES>
409         requestMsg{};
410 
411     auto requestPtr = reinterpret_cast<pldm_msg*>(requestMsg.data());
412     auto request =
413         reinterpret_cast<pldm_get_fru_record_table_req*>(requestPtr->payload);
414 
415     // Random value for data transfer handle and transfer operation flag
416     uint32_t data_transfer_handle = 32;
417     uint8_t transfer_operation_flag = PLDM_GET_FIRSTPART;
418 
419     // Invoke encode get FRU record table request api
420     auto rc = encode_get_fru_record_table_req(
421         0, data_transfer_handle, transfer_operation_flag, requestPtr,
422         requestMsg.size() - sizeof(pldm_msg_hdr));
423 
424     ASSERT_EQ(rc, PLDM_SUCCESS);
425     ASSERT_EQ(requestPtr->hdr.request, PLDM_REQUEST);
426     ASSERT_EQ(requestPtr->hdr.instance_id, 0u);
427     ASSERT_EQ(requestPtr->hdr.type, PLDM_FRU);
428     ASSERT_EQ(requestPtr->hdr.command, PLDM_GET_FRU_RECORD_TABLE);
429     ASSERT_EQ(le32toh(data_transfer_handle), request->data_transfer_handle);
430     ASSERT_EQ(transfer_operation_flag, request->transfer_operation_flag);
431 }
432 
433 TEST(GetFruRecordTable, testBadEncodeRequest)
434 
435 {
436     uint32_t data_transfer_handle = 0x0;
437     uint8_t transfer_operation_flag = PLDM_GET_FIRSTPART;
438 
439     std::array<uint8_t,
440                sizeof(pldm_msg_hdr) + PLDM_GET_FRU_RECORD_TABLE_REQ_BYTES>
441         requestMsg{};
442     auto rc = encode_get_fru_record_table_req(
443         0, data_transfer_handle, transfer_operation_flag, NULL,
444         requestMsg.size() - sizeof(pldm_msg_hdr));
445 
446     ASSERT_EQ(rc, PLDM_ERROR_INVALID_DATA);
447 }
448 
449 TEST(GetFruRecordTable, testGoodDecodeResponse)
450 {
451     uint8_t completion_code = PLDM_SUCCESS;
452     uint32_t next_data_transfer_handle = 0x16;
453     uint8_t transfer_flag = PLDM_START_AND_END;
454     std::vector<uint8_t> fru_record_table_data = {1, 2, 3, 4, 5, 6, 7, 8, 9};
455 
456     std::vector<uint8_t> responseMsg(sizeof(pldm_msg_hdr) +
457                                      PLDM_GET_FRU_RECORD_TABLE_MIN_RESP_BYTES +
458                                      fru_record_table_data.size());
459 
460     auto responsePtr = reinterpret_cast<pldm_msg*>(responseMsg.data());
461     size_t payload_length = responseMsg.size() - sizeof(pldm_msg_hdr);
462     auto response =
463         reinterpret_cast<pldm_get_fru_record_table_resp*>(responsePtr->payload);
464 
465     response->completion_code = completion_code;
466     response->next_data_transfer_handle = htole32(next_data_transfer_handle);
467     response->transfer_flag = transfer_flag;
468     memcpy(response->fru_record_table_data, fru_record_table_data.data(),
469            fru_record_table_data.size());
470 
471     uint8_t ret_completion_code = 0;
472     uint32_t ret_next_data_transfer_handle = 0;
473     uint8_t ret_transfer_flag = 0;
474     std::vector<uint8_t> ret_fru_record_table_data(9, 0);
475     size_t ret_fru_record_table_length = 0;
476 
477     // Invoke decode get FRU record table response api
478     auto rc = decode_get_fru_record_table_resp(
479         responsePtr, payload_length, &ret_completion_code,
480         &ret_next_data_transfer_handle, &ret_transfer_flag,
481         ret_fru_record_table_data.data(), &ret_fru_record_table_length);
482     ASSERT_EQ(rc, PLDM_SUCCESS);
483     ASSERT_EQ(completion_code, ret_completion_code);
484     ASSERT_EQ(next_data_transfer_handle, ret_next_data_transfer_handle);
485     ASSERT_EQ(transfer_flag, ret_transfer_flag);
486     ASSERT_EQ(0, memcmp(fru_record_table_data.data(),
487                         ret_fru_record_table_data.data(),
488                         ret_fru_record_table_length));
489     ASSERT_EQ(fru_record_table_data.size(), ret_fru_record_table_length);
490 }
491 
492 TEST(GetFruRecordTable, testBadDecodeResponse)
493 {
494     uint8_t completion_code = 0;
495     uint32_t next_data_transfer_handle = 0;
496     uint8_t transfer_flag = PLDM_START_AND_END;
497     std::vector<uint8_t> fru_record_table_data(9, 0);
498     size_t fru_record_table_length = 0;
499 
500     std::vector<uint8_t> responseMsg(sizeof(pldm_msg_hdr) +
501                                      PLDM_GET_FRU_RECORD_TABLE_MIN_RESP_BYTES +
502                                      fru_record_table_data.size());
503 
504     auto responsePtr = reinterpret_cast<pldm_msg*>(responseMsg.data());
505 
506     // Payload message is missing
507     auto rc = decode_get_fru_record_table_resp(
508         NULL, 0, &completion_code, &next_data_transfer_handle, &transfer_flag,
509         fru_record_table_data.data(), &fru_record_table_length);
510 
511     ASSERT_EQ(rc, PLDM_ERROR_INVALID_DATA);
512 
513     // Payload length is invalid
514     rc = decode_get_fru_record_table_resp(
515         responsePtr, 0, &completion_code, &next_data_transfer_handle,
516         &transfer_flag, fru_record_table_data.data(), &fru_record_table_length);
517 
518     ASSERT_EQ(rc, PLDM_ERROR_INVALID_LENGTH);
519 }
520 
521 TEST(GetFRURecordByOption, testGoodEncodeRequest)
522 {
523     uint8_t instanceId = 2;
524     uint32_t dataTransferHandle = 3;
525     uint16_t fruTableHandle = 4;
526     uint16_t recordSetIdentifier = 5;
527     uint8_t recordType = 6;
528     uint8_t fieldType = 7;
529     uint8_t transferOpFlag = 0;
530 
531     constexpr auto payLoadLength = sizeof(pldm_get_fru_record_by_option_req);
532 
533     std::array<uint8_t, sizeof(pldm_msg_hdr) + payLoadLength> request;
534     auto reqMsg = reinterpret_cast<pldm_msg*>(request.data());
535 
536     auto rc = encode_get_fru_record_by_option_req(
537         instanceId, dataTransferHandle, fruTableHandle, recordSetIdentifier,
538         recordType, fieldType, transferOpFlag, reqMsg, payLoadLength);
539 
540     EXPECT_EQ(rc, PLDM_SUCCESS);
541     EXPECT_EQ(instanceId, reqMsg->hdr.instance_id);
542 
543     auto payLoadMsg =
544         reinterpret_cast<pldm_get_fru_record_by_option_req*>(reqMsg->payload);
545 
546     EXPECT_EQ(le32toh(payLoadMsg->data_transfer_handle), dataTransferHandle);
547     EXPECT_EQ(le16toh(payLoadMsg->fru_table_handle), fruTableHandle);
548     EXPECT_EQ(le16toh(payLoadMsg->record_set_identifier), recordSetIdentifier);
549     EXPECT_EQ(payLoadMsg->record_type, recordType);
550     EXPECT_EQ(payLoadMsg->field_type, fieldType);
551     EXPECT_EQ(payLoadMsg->transfer_op_flag, transferOpFlag);
552 }
553 
554 TEST(GetFRURecordByOption, testBadEncodeRequest)
555 {
556 
557     constexpr auto payLoadLength = sizeof(pldm_get_fru_record_by_option_req);
558 
559     auto rc = encode_get_fru_record_by_option_req(1, 2, 3, 4, 5, 6, 0, nullptr,
560                                                   payLoadLength);
561 
562     EXPECT_EQ(rc, PLDM_ERROR_INVALID_DATA);
563     std::array<uint8_t, sizeof(pldm_msg_hdr) + payLoadLength> request;
564     auto reqMsg = reinterpret_cast<pldm_msg*>(request.data());
565 
566     rc = encode_get_fru_record_by_option_req(1, 2, 3, 4, 5, 6, 0, reqMsg,
567                                              payLoadLength - 1);
568 
569     EXPECT_EQ(rc, PLDM_ERROR_INVALID_LENGTH);
570 }
571 
572 TEST(GetFRURecordByOption, testGoodDecodeRequest)
573 {
574     uint8_t instanceId = 2;
575     uint32_t dataTransferHandle = 3;
576     uint16_t fruTableHandle = 4;
577     uint16_t recordSetIdentifier = 5;
578     uint8_t recordType = 6;
579     uint8_t fieldType = 7;
580     uint8_t transferOpFlag = 0;
581 
582     constexpr auto payLoadLength = sizeof(pldm_get_fru_record_by_option_req);
583 
584     std::array<uint8_t, sizeof(pldm_msg_hdr) + payLoadLength> request;
585     auto reqMsg = reinterpret_cast<pldm_msg*>(request.data());
586 
587     auto rc = encode_get_fru_record_by_option_req(
588         instanceId, dataTransferHandle, fruTableHandle, recordSetIdentifier,
589         recordType, fieldType, transferOpFlag, reqMsg, payLoadLength);
590 
591     EXPECT_EQ(rc, PLDM_SUCCESS);
592 
593     uint32_t retDataTransferHandle{};
594     uint16_t retFruTableHandle{};
595     uint16_t retRecordSetIdentifier{};
596     uint8_t retRecordType{};
597     uint8_t retFieldType{};
598     uint8_t retTransferOpFlag{};
599 
600     rc = decode_get_fru_record_by_option_req(
601         reqMsg, payLoadLength, &retDataTransferHandle, &retFruTableHandle,
602         &retRecordSetIdentifier, &retRecordType, &retFieldType,
603         &retTransferOpFlag);
604 
605     EXPECT_EQ(rc, PLDM_SUCCESS);
606     EXPECT_EQ(retDataTransferHandle, dataTransferHandle);
607     EXPECT_EQ(retFruTableHandle, fruTableHandle);
608     EXPECT_EQ(retRecordSetIdentifier, recordSetIdentifier);
609     EXPECT_EQ(retRecordType, recordType);
610     EXPECT_EQ(retFieldType, fieldType);
611     EXPECT_EQ(retTransferOpFlag, transferOpFlag);
612 }
613 
614 TEST(GetFRURecordByOption, testBadDecodeRequest)
615 {
616     constexpr auto payLoadLength = sizeof(pldm_get_fru_record_by_option_req);
617     std::array<uint8_t, sizeof(pldm_msg_hdr) + payLoadLength> request{};
618     auto reqMsg = reinterpret_cast<pldm_msg*>(request.data());
619 
620     uint32_t retDataTransferHandle{};
621     uint16_t retFruTableHandle{};
622     uint16_t retRecordSetIdentifier{};
623     uint8_t retRecordType{};
624     uint8_t retFieldType{};
625     uint8_t retTransferOpFlag{};
626 
627     auto rc = decode_get_fru_record_by_option_req(
628         reqMsg, payLoadLength - 1, &retDataTransferHandle, &retFruTableHandle,
629         &retRecordSetIdentifier, &retRecordType, &retFieldType,
630         &retTransferOpFlag);
631 
632     EXPECT_EQ(rc, PLDM_ERROR_INVALID_LENGTH);
633 
634     rc = decode_get_fru_record_by_option_req(
635         reqMsg, payLoadLength - 1, nullptr, &retFruTableHandle,
636         &retRecordSetIdentifier, &retRecordType, &retFieldType,
637         &retTransferOpFlag);
638 
639     EXPECT_EQ(rc, PLDM_ERROR_INVALID_DATA);
640 }
641 
642 TEST(GetFruRecordByOption, testGoodEncodeResponse)
643 {
644     uint8_t completionCode = PLDM_SUCCESS;
645     uint8_t instanceId = 2;
646     uint32_t dataTransferHandle = 3;
647     uint8_t transferFlag = 5;
648 
649     std::array<uint8_t, 5> fruData = {1, 2, 3, 4, 5};
650     constexpr auto payLoadLength =
651         sizeof(pldm_get_fru_record_by_option_resp) - 1 + fruData.size();
652 
653     std::array<uint8_t, sizeof(pldm_msg_hdr) + payLoadLength> response;
654     auto respMsg = reinterpret_cast<pldm_msg*>(response.data());
655 
656     auto rc = encode_get_fru_record_by_option_resp(
657         instanceId, completionCode, dataTransferHandle, transferFlag,
658         fruData.data(), fruData.size(), respMsg, payLoadLength);
659 
660     auto payLoadMsg =
661         reinterpret_cast<pldm_get_fru_record_by_option_resp*>(respMsg->payload);
662 
663     EXPECT_EQ(rc, PLDM_SUCCESS);
664     EXPECT_EQ(payLoadMsg->completion_code, completionCode);
665     EXPECT_EQ(payLoadMsg->next_data_transfer_handle,
666               htole32(dataTransferHandle));
667     EXPECT_EQ(payLoadMsg->transfer_flag, transferFlag);
668 
669     EXPECT_EQ(std::memcmp(payLoadMsg->fru_structure_data, fruData.data(),
670                           fruData.size()),
671               0);
672 }
673 
674 TEST(GetFruRecordByOption, testBadEncodeResponse)
675 {
676     uint8_t completionCode = PLDM_SUCCESS;
677     uint8_t instanceId = 2;
678     uint32_t dataTransferHandle = 3;
679     uint8_t transferFlag = 5;
680 
681     std::array<uint8_t, 5> fruData = {1, 2, 3, 4, 5};
682     constexpr auto payLoadLength =
683         sizeof(pldm_get_fru_record_by_option_resp) - 1 + fruData.size();
684 
685     std::array<uint8_t, sizeof(pldm_msg_hdr) + payLoadLength> response;
686     auto respMsg = reinterpret_cast<pldm_msg*>(response.data());
687 
688     auto rc = encode_get_fru_record_by_option_resp(
689         instanceId, completionCode, dataTransferHandle, transferFlag, nullptr,
690         fruData.size(), respMsg, payLoadLength);
691 
692     EXPECT_EQ(rc, PLDM_ERROR_INVALID_DATA);
693 
694     rc = encode_get_fru_record_by_option_resp(
695         instanceId, completionCode, dataTransferHandle, transferFlag,
696         fruData.data(), fruData.size(), respMsg, payLoadLength - 1);
697 
698     EXPECT_EQ(rc, PLDM_ERROR_INVALID_LENGTH);
699 }
700 
701 TEST(GetFruRecordByOption, testGoodDecodeResponse)
702 {
703     uint8_t completionCode = PLDM_SUCCESS;
704     uint8_t instanceId = 2;
705     uint32_t dataTransferHandle = 3;
706     uint8_t transferFlag = 5;
707 
708     std::array<uint8_t, 5> fruData = {1, 2, 3, 4, 5};
709     constexpr auto payLoadLength =
710         sizeof(pldm_get_fru_record_by_option_resp) - 1 + fruData.size();
711 
712     std::array<uint8_t, sizeof(pldm_msg_hdr) + payLoadLength> response;
713     auto respMsg = reinterpret_cast<pldm_msg*>(response.data());
714 
715     auto rc = encode_get_fru_record_by_option_resp(
716         instanceId, completionCode, dataTransferHandle, transferFlag,
717         fruData.data(), fruData.size(), respMsg, payLoadLength);
718 
719     EXPECT_EQ(rc, PLDM_SUCCESS);
720 
721     uint8_t retCompletionCode;
722     uint32_t retDataTransferHandle;
723     uint8_t retTransferFlag;
724     variable_field retFruData;
725 
726     rc = decode_get_fru_record_by_option_resp(
727         respMsg, payLoadLength, &retCompletionCode, &retDataTransferHandle,
728         &retTransferFlag, &retFruData);
729 
730     EXPECT_EQ(rc, PLDM_SUCCESS);
731     EXPECT_EQ(retCompletionCode, completionCode);
732     EXPECT_EQ(retDataTransferHandle, dataTransferHandle);
733     EXPECT_EQ(retTransferFlag, transferFlag);
734     EXPECT_EQ(retFruData.length, fruData.size());
735     EXPECT_EQ(std::memcmp(fruData.data(), retFruData.ptr, fruData.size()), 0);
736 }
737 
738 TEST(GetFruRecordByOption, testBadDecodeResponse)
739 {
740 
741     uint8_t completionCode = PLDM_SUCCESS;
742     uint8_t instanceId = 2;
743     uint32_t dataTransferHandle = 3;
744     uint8_t transferFlag = 5;
745 
746     std::array<uint8_t, 5> fruData = {1, 2, 3, 4, 5};
747     constexpr auto payLoadLength =
748         sizeof(pldm_get_fru_record_by_option_resp) - 1 + fruData.size();
749 
750     std::array<uint8_t, sizeof(pldm_msg_hdr) + payLoadLength> response;
751     auto respMsg = reinterpret_cast<pldm_msg*>(response.data());
752 
753     auto rc = encode_get_fru_record_by_option_resp(
754         instanceId, completionCode, dataTransferHandle, transferFlag,
755         fruData.data(), fruData.size(), respMsg, payLoadLength);
756 
757     EXPECT_EQ(rc, PLDM_SUCCESS);
758 
759     uint8_t retCompletionCode;
760     uint32_t retDataTransferHandle;
761     uint8_t retTransferFlag;
762     variable_field retFruData;
763 
764     rc = decode_get_fru_record_by_option_resp(respMsg, payLoadLength, nullptr,
765                                               &retDataTransferHandle,
766                                               &retTransferFlag, &retFruData);
767 
768     EXPECT_EQ(rc, PLDM_ERROR_INVALID_DATA);
769 
770     rc = decode_get_fru_record_by_option_resp(
771         respMsg, PLDM_GET_FRU_RECORD_BY_OPTION_MIN_RESP_BYTES - 1,
772         &retCompletionCode, &retDataTransferHandle, &retTransferFlag,
773         &retFruData);
774 
775     EXPECT_EQ(rc, PLDM_ERROR_INVALID_LENGTH);
776 }
777 
778 TEST(SetFRURecordTable, testGoodEncodeResponse)
779 {
780     uint8_t instanceId = 2;
781     uint8_t completionCode = PLDM_SUCCESS;
782     uint32_t nextDataTransferHandle = 32;
783 
784     std::array<uint8_t,
785                sizeof(pldm_msg_hdr) + PLDM_SET_FRU_RECORD_TABLE_RESP_BYTES>
786         responseMsg{};
787     struct pldm_msg* response =
788         reinterpret_cast<struct pldm_msg*>(responseMsg.data());
789     auto rc = encode_set_fru_record_table_resp(
790         instanceId, completionCode, nextDataTransferHandle,
791         responseMsg.size() - sizeof(pldm_msg_hdr), response);
792     EXPECT_EQ(rc, PLDM_SUCCESS);
793 
794     struct pldm_set_fru_record_table_resp* resp =
795         reinterpret_cast<struct pldm_set_fru_record_table_resp*>(
796             response->payload);
797     EXPECT_EQ(completionCode, resp->completion_code);
798     EXPECT_EQ(htole32(nextDataTransferHandle), resp->next_data_transfer_handle);
799 }
800 
801 TEST(SetFRURecordTable, testBadEncodeResponse)
802 {
803     uint8_t instanceId = 0;
804     uint8_t completionCode = PLDM_SUCCESS;
805     uint32_t nextDataTransferHandle = 1;
806 
807     std::array<uint8_t,
808                sizeof(pldm_msg_hdr) + PLDM_SET_FRU_RECORD_TABLE_RESP_BYTES>
809         responseMsg{};
810     struct pldm_msg* response =
811         reinterpret_cast<struct pldm_msg*>(responseMsg.data());
812 
813     auto rc = encode_set_fru_record_table_resp(
814         instanceId, completionCode, nextDataTransferHandle,
815         responseMsg.size() - sizeof(pldm_msg_hdr), NULL);
816     EXPECT_EQ(rc, PLDM_ERROR_INVALID_DATA);
817 
818     rc = encode_set_fru_record_table_resp(
819         instanceId, completionCode, nextDataTransferHandle,
820         responseMsg.size() - sizeof(pldm_msg_hdr) - 1, response);
821     EXPECT_EQ(rc, PLDM_ERROR_INVALID_LENGTH);
822 }
823 
824 TEST(SetFRURecordTable, testGoodDecodeRequest)
825 {
826     uint32_t transferHandle = 1;
827     uint8_t transferFlag = PLDM_GET_FIRSTPART;
828     uint32_t tableData = 44;
829 
830     std::array<uint8_t, sizeof(pldm_msg_hdr) +
831                             PLDM_SET_FRU_RECORD_TABLE_MIN_REQ_BYTES +
832                             sizeof(tableData)>
833         requestMsg{};
834     auto request = reinterpret_cast<struct pldm_msg*>(requestMsg.data());
835     struct pldm_set_fru_record_table_req* req =
836         reinterpret_cast<struct pldm_set_fru_record_table_req*>(
837             request->payload);
838     req->data_transfer_handle = htole32(transferHandle);
839     req->transfer_flag = transferFlag;
840     memcpy(req->fru_record_table_data, &tableData, sizeof(tableData));
841 
842     uint32_t retTransferHandle;
843     uint8_t retTransferFlag;
844     struct variable_field table;
845 
846     auto rc = decode_set_fru_record_table_req(
847         request, requestMsg.size() - sizeof(pldm_msg_hdr), &retTransferHandle,
848         &retTransferFlag, &table);
849 
850     EXPECT_EQ(rc, PLDM_SUCCESS);
851     EXPECT_EQ(retTransferHandle, transferHandle);
852     EXPECT_EQ(retTransferFlag, transferFlag);
853     EXPECT_EQ(table.length, sizeof(tableData));
854     EXPECT_EQ(0, memcmp(table.ptr, &tableData, sizeof(tableData)));
855 }
856 
857 TEST(SetFRURecordTable, testBadDecodeRequest)
858 {
859     uint32_t transferHandle = 1;
860     uint8_t transferFlag = PLDM_GET_FIRSTPART;
861     uint32_t tableData = 44;
862 
863     std::array<uint8_t, sizeof(pldm_msg_hdr) +
864                             PLDM_SET_FRU_RECORD_TABLE_MIN_REQ_BYTES +
865                             sizeof(tableData)>
866         requestMsg{};
867     auto request = reinterpret_cast<struct pldm_msg*>(requestMsg.data());
868     struct pldm_set_fru_record_table_req* req =
869         reinterpret_cast<struct pldm_set_fru_record_table_req*>(
870             request->payload);
871     req->data_transfer_handle = htole32(transferHandle);
872     req->transfer_flag = transferFlag;
873     memcpy(req->fru_record_table_data, &tableData, sizeof(tableData));
874 
875     uint32_t retTransferHandle;
876     uint8_t retTransferFlag;
877 
878     auto rc = decode_set_fru_record_table_req(
879         request, requestMsg.size() - sizeof(pldm_msg_hdr), &retTransferHandle,
880         &retTransferFlag, NULL);
881     EXPECT_EQ(rc, PLDM_ERROR_INVALID_DATA);
882 
883     struct variable_field table;
884     rc = decode_set_fru_record_table_req(
885         request,
886         requestMsg.size() - sizeof(pldm_msg_hdr) - sizeof(tableData) - 1,
887         &retTransferHandle, &retTransferFlag, &table);
888     EXPECT_EQ(rc, PLDM_ERROR_INVALID_LENGTH);
889 }
890