libpldm: Add encode/decode APIs for GetFRURecordByOption
This commit implements the encode/decode APIs for
GetFRURecordByOption command which is defined in
DSP0257 v1.0.0 Table 12
Signed-off-by: John Wang <wangzqbj@inspur.com>
Change-Id: If3649ac5e9b8e32a7b64bb26d443396d42b8c827
diff --git a/libpldm/fru.c b/libpldm/fru.c
index 242fc28..64c1aba 100644
--- a/libpldm/fru.c
+++ b/libpldm/fru.c
@@ -1,4 +1,6 @@
+#include <assert.h>
#include <endian.h>
+#include <stdbool.h>
#include <string.h>
#include "fru.h"
@@ -199,6 +201,154 @@
return PLDM_SUCCESS;
}
+int encode_get_fru_record_by_option_req(
+ uint8_t instance_id, uint32_t data_transfer_handle,
+ uint16_t fru_table_handle, uint16_t record_set_identifier,
+ uint8_t record_type, uint8_t field_type, uint8_t transfer_op_flag,
+ struct pldm_msg *msg, size_t payload_length)
+{
+
+ if (msg == NULL) {
+ return PLDM_ERROR_INVALID_DATA;
+ }
+
+ if (payload_length !=
+ sizeof(struct pldm_get_fru_record_by_option_req)) {
+ return PLDM_ERROR_INVALID_LENGTH;
+ }
+
+ struct pldm_header_info header = {0};
+ header.instance = instance_id;
+ header.msg_type = PLDM_REQUEST;
+ header.pldm_type = PLDM_FRU;
+ header.command = PLDM_GET_FRU_RECORD_BY_OPTION;
+ int rc = pack_pldm_header(&header, &(msg->hdr));
+ if (rc != PLDM_SUCCESS) {
+ return rc;
+ }
+
+ struct pldm_get_fru_record_by_option_req *req =
+ (struct pldm_get_fru_record_by_option_req *)msg->payload;
+
+ req->data_transfer_handle = htole32(data_transfer_handle);
+ req->fru_table_handle = htole16(fru_table_handle);
+ req->record_set_identifier = htole16(record_set_identifier);
+ req->record_type = record_type;
+ req->field_type = field_type;
+ req->transfer_op_flag = transfer_op_flag;
+
+ return PLDM_SUCCESS;
+}
+
+int decode_get_fru_record_by_option_req(
+ const struct pldm_msg *msg, size_t payload_length,
+ uint32_t *data_transfer_handle, uint16_t *fru_table_handle,
+ uint16_t *record_set_identifier, uint8_t *record_type, uint8_t *field_type,
+ uint8_t *transfer_op_flag)
+{
+ if (msg == NULL || data_transfer_handle == NULL ||
+ fru_table_handle == NULL || record_set_identifier == NULL ||
+ record_type == NULL || field_type == NULL ||
+ transfer_op_flag == NULL) {
+ return PLDM_ERROR_INVALID_DATA;
+ }
+
+ if (payload_length !=
+ sizeof(struct pldm_get_fru_record_by_option_req)) {
+ return PLDM_ERROR_INVALID_LENGTH;
+ }
+
+ struct pldm_get_fru_record_by_option_req *req =
+ (struct pldm_get_fru_record_by_option_req *)msg->payload;
+
+ *data_transfer_handle = le32toh(req->data_transfer_handle);
+ *fru_table_handle = le16toh(req->fru_table_handle);
+ *record_set_identifier = le16toh(req->record_set_identifier);
+ *record_type = req->record_type;
+ *field_type = req->field_type;
+ *transfer_op_flag = req->transfer_op_flag;
+ return PLDM_SUCCESS;
+}
+
+int encode_get_fru_record_by_option_resp(uint8_t instance_id,
+ uint8_t completion_code,
+ uint32_t next_data_transfer_handle,
+ uint8_t transfer_flag,
+ const void *fru_structure_data,
+ size_t data_size, struct pldm_msg *msg,
+ size_t payload_length)
+{
+ if (msg == NULL || fru_structure_data == NULL) {
+ return PLDM_ERROR_INVALID_DATA;
+ }
+
+ if (payload_length < PLDM_GET_FRU_RECORD_BY_OPTION_MIN_RESP_BYTES) {
+ return PLDM_ERROR_INVALID_LENGTH;
+ }
+
+ struct pldm_header_info header = {0};
+ header.instance = instance_id;
+ header.msg_type = PLDM_RESPONSE;
+ header.pldm_type = PLDM_FRU;
+ header.command = PLDM_GET_FRU_RECORD_BY_OPTION;
+ int rc = pack_pldm_header(&header, &(msg->hdr));
+ if (rc != PLDM_SUCCESS) {
+ return rc;
+ }
+
+ struct pldm_get_fru_record_by_option_resp *resp =
+ (struct pldm_get_fru_record_by_option_resp *)msg->payload;
+
+ resp->completion_code = completion_code;
+ resp->next_data_transfer_handle = htole32(next_data_transfer_handle);
+ resp->transfer_flag = transfer_flag;
+
+ if (completion_code != PLDM_SUCCESS) {
+ return PLDM_SUCCESS;
+ }
+
+ if (payload_length !=
+ PLDM_GET_FRU_RECORD_BY_OPTION_MIN_RESP_BYTES + data_size) {
+ return PLDM_ERROR_INVALID_LENGTH;
+ }
+
+ memcpy(resp->fru_structure_data, fru_structure_data, data_size);
+
+ return PLDM_SUCCESS;
+}
+
+int decode_get_fru_record_by_option_resp(
+ const struct pldm_msg *msg, size_t payload_length, uint8_t *completion_code,
+ uint32_t *next_transfer_handle, uint8_t *transfer_flag,
+ struct variable_field *fru_structure_data)
+{
+ if (msg == NULL || completion_code == NULL ||
+ next_transfer_handle == NULL || transfer_flag == NULL ||
+ fru_structure_data == NULL) {
+ return PLDM_ERROR_INVALID_DATA;
+ }
+
+ *completion_code = msg->payload[0];
+ if (PLDM_SUCCESS != *completion_code) {
+ return PLDM_SUCCESS;
+ }
+
+ if (payload_length < PLDM_GET_FRU_RECORD_BY_OPTION_MIN_RESP_BYTES) {
+ return PLDM_ERROR_INVALID_LENGTH;
+ }
+
+ struct pldm_get_fru_record_by_option_resp *resp =
+ (struct pldm_get_fru_record_by_option_resp *)msg->payload;
+
+ *next_transfer_handle = le32toh(resp->next_data_transfer_handle);
+ *transfer_flag = resp->transfer_flag;
+ fru_structure_data->ptr = resp->fru_structure_data;
+ fru_structure_data->length =
+ payload_length - PLDM_GET_FRU_RECORD_BY_OPTION_MIN_RESP_BYTES;
+
+ return PLDM_SUCCESS;
+}
+
int encode_get_fru_record_table_req(uint8_t instance_id,
uint32_t data_transfer_handle,
uint8_t transfer_operation_flag,
diff --git a/libpldm/fru.h b/libpldm/fru.h
index 4a8205e..3ec9e43 100644
--- a/libpldm/fru.h
+++ b/libpldm/fru.h
@@ -10,11 +10,13 @@
#include <stdint.h>
#include "base.h"
+#include "utils.h"
#define PLDM_GET_FRU_RECORD_TABLE_METADATA_REQ_BYTES 0
#define PLDM_GET_FRU_RECORD_TABLE_METADATA_RESP_BYTES 19
#define PLDM_GET_FRU_RECORD_TABLE_REQ_BYTES 5
#define PLDM_GET_FRU_RECORD_TABLE_MIN_RESP_BYTES 6
+#define PLDM_GET_FRU_RECORD_BY_OPTION_MIN_RESP_BYTES 6
#define FRU_TABLE_CHECKSUM_SIZE 4
@@ -104,6 +106,22 @@
uint8_t fru_record_table_data[1];
} __attribute__((packed));
+struct pldm_get_fru_record_by_option_req {
+ uint32_t data_transfer_handle;
+ uint16_t fru_table_handle;
+ uint16_t record_set_identifier;
+ uint8_t record_type;
+ uint8_t field_type;
+ uint8_t transfer_op_flag;
+} __attribute__((packed));
+
+struct pldm_get_fru_record_by_option_resp {
+ uint8_t completion_code;
+ uint32_t next_data_transfer_handle;
+ uint8_t transfer_flag;
+ uint8_t fru_structure_data[1];
+} __attribute__((packed));
+
/** @struct pldm_fru_record_tlv
*
* Structure representing each FRU field entry (type, length, value)
@@ -235,6 +253,53 @@
uint32_t next_data_transfer_handle,
uint8_t transfer_flag,
struct pldm_msg *msg);
+
+/* GetFRURecordByOption */
+
+/** @brief Decode GetFRURecordByOption request data
+ *
+ * @param[in] msg - PLDM request message payload
+ * @param[in] payload_length - Length of request payload
+ * @param[out] data_transfer_handle - A handle, used to identify a FRU Record
+ * Table data transfer
+ * @param[out] fru_table_handle - A handle, used to identify a FRU DATA
+ * records
+ * @param[out] record_set_identifier - FRU record set identifier
+ * @param[out] record_type - FRU record type
+ * @param[out] field_type - FRU field type
+ * @param[out] transfer_op_flag - A flag that indicates whether this is
+ * the start of the transfer
+ * @return pldm_completion_codes
+ */
+int decode_get_fru_record_by_option_req(
+ const struct pldm_msg *msg, size_t payload_length,
+ uint32_t *data_transfer_handle, uint16_t *fru_table_handle,
+ uint16_t *record_set_identifier, uint8_t *record_type, uint8_t *field_type,
+ uint8_t *transfer_op_flag);
+
+/** @brief Encode GetFRURecordByOption response data
+ *
+ * @param[in] instance_id - Message's instance id
+ * @param[in] completion_code - PLDM completion code
+ * @param[in] next_data_transfer_handle - A handle that is used to identify the
+ * next portion of the transfer
+ * @param[in] transfer_flag - The transfer flag that indicates what part of the
+ * transfer this response represents
+ * @param[in] fru_structure_data - FRU Structure Data
+ * @param[in] data_size - Size of FRU Structrue Data
+ * @param[in,out] msg - Message will be written to this
+ * @return pldm_completion_codes
+ * @note Caller is responsible for memory alloc and dealloc of param 'msg',
+ * and for appending the FRU table to the msg.
+ */
+int encode_get_fru_record_by_option_resp(uint8_t instance_id,
+ uint8_t completion_code,
+ uint32_t next_data_transfer_handle,
+ uint8_t transfer_flag,
+ const void *fru_structure_data,
+ size_t data_size, struct pldm_msg *msg,
+ size_t payload_length);
+
/* Requester */
/* GetFruRecordTable */
@@ -300,6 +365,48 @@
uint8_t num_frus, uint8_t encoding, uint8_t *tlvs,
size_t tlvs_size);
+/* GetFRURecordByOption */
+
+/** @brief Create a PLDM request message for GetFRURecordByOption
+ *
+ * @param[in] instance_id - Message's instance id
+ * @param[in] data_transfer_handle - A handle, used to identify a FRU Record
+ * Table data transfer
+ * @param[in] fru_table_handle - A handle, used to identify a FRU DATA records
+ * @param[in] record_set_identifier - FRU record set identifier
+ * @param[in] record_type - FRU record type
+ * @param[in] field_type - FRU field type
+ * @param[in] transfer_op_flag - A flag that indicates whether this is
+ * the start of the transfer
+ * @param[in,out] msg - Message will be written to this
+ * @param[in] payload_length - Length of request message payload
+ * @return pldm_completion_codes
+ * @note Caller is responsible for memory alloc and dealloc of param
+ * 'msg.payload'
+ */
+int encode_get_fru_record_by_option_req(
+ uint8_t instance_id, uint32_t data_transfer_handle,
+ uint16_t fru_table_handle, uint16_t record_set_identifier,
+ uint8_t record_type, uint8_t field_type, uint8_t transfer_op_flag,
+ struct pldm_msg *msg, size_t payload_length);
+
+/** @brief Decode GetFRURecordByOption response data
+ *
+ * @param[in] msg - Response message
+ * @param[in] payload_length - Length of response message payload
+ * @param[out] completion_code - Pointer to response msg's PLDM completion code
+ * @param[out] next_data_transfer_handle - A handle used to identify the next
+ * portion of the transfer
+ * @param[out] transfer_flag - The transfer flag that indicates what part of
+ * the transfer this response represents
+ * @param[out] fru_structure_data - FRU Structure Data
+ * @return pldm_completion_codes
+ */
+int decode_get_fru_record_by_option_resp(
+ const struct pldm_msg *msg, size_t payload_length, uint8_t *completion_code,
+ uint32_t *next_transfer_handle, uint8_t *transfer_flag,
+ struct variable_field *fru_structure_data);
+
#ifdef __cplusplus
}
#endif
diff --git a/libpldm/tests/libpldm_fru_test.cpp b/libpldm/tests/libpldm_fru_test.cpp
index d79df4b..68d68a6 100644
--- a/libpldm/tests/libpldm_fru_test.cpp
+++ b/libpldm/tests/libpldm_fru_test.cpp
@@ -1,6 +1,7 @@
#include <string.h>
#include <array>
+#include <cstring>
#include "libpldm/base.h"
#include "libpldm/fru.h"
@@ -514,3 +515,260 @@
ASSERT_EQ(rc, PLDM_ERROR_INVALID_LENGTH);
}
+
+TEST(GetFRURecordByOption, testGoodEncodeRequest)
+{
+ uint8_t instanceId = 2;
+ uint32_t dataTransferHandle = 3;
+ uint16_t fruTableHandle = 4;
+ uint16_t recordSetIdentifier = 5;
+ uint8_t recordType = 6;
+ uint8_t fieldType = 7;
+ uint8_t transferOpFlag = 0;
+
+ constexpr auto payLoadLength = sizeof(pldm_get_fru_record_by_option_req);
+
+ std::array<uint8_t, sizeof(pldm_msg_hdr) + payLoadLength> request;
+ auto reqMsg = reinterpret_cast<pldm_msg*>(request.data());
+
+ auto rc = encode_get_fru_record_by_option_req(
+ instanceId, dataTransferHandle, fruTableHandle, recordSetIdentifier,
+ recordType, fieldType, transferOpFlag, reqMsg, payLoadLength);
+
+ EXPECT_EQ(rc, PLDM_SUCCESS);
+ EXPECT_EQ(instanceId, reqMsg->hdr.instance_id);
+
+ auto payLoadMsg =
+ reinterpret_cast<pldm_get_fru_record_by_option_req*>(reqMsg->payload);
+
+ EXPECT_EQ(le32toh(payLoadMsg->data_transfer_handle), dataTransferHandle);
+ EXPECT_EQ(le16toh(payLoadMsg->fru_table_handle), fruTableHandle);
+ EXPECT_EQ(le16toh(payLoadMsg->record_set_identifier), recordSetIdentifier);
+ EXPECT_EQ(payLoadMsg->record_type, recordType);
+ EXPECT_EQ(payLoadMsg->field_type, fieldType);
+ EXPECT_EQ(payLoadMsg->transfer_op_flag, transferOpFlag);
+}
+
+TEST(GetFRURecordByOption, testBadEncodeRequest)
+{
+
+ constexpr auto payLoadLength = sizeof(pldm_get_fru_record_by_option_req);
+
+ auto rc = encode_get_fru_record_by_option_req(1, 2, 3, 4, 5, 6, 0, nullptr,
+ payLoadLength);
+
+ EXPECT_EQ(rc, PLDM_ERROR_INVALID_DATA);
+ std::array<uint8_t, sizeof(pldm_msg_hdr) + payLoadLength> request;
+ auto reqMsg = reinterpret_cast<pldm_msg*>(request.data());
+
+ rc = encode_get_fru_record_by_option_req(1, 2, 3, 4, 5, 6, 0, reqMsg,
+ payLoadLength - 1);
+
+ EXPECT_EQ(rc, PLDM_ERROR_INVALID_LENGTH);
+}
+
+TEST(GetFRURecordByOption, testGoodDecodeRequest)
+{
+ uint8_t instanceId = 2;
+ uint32_t dataTransferHandle = 3;
+ uint16_t fruTableHandle = 4;
+ uint16_t recordSetIdentifier = 5;
+ uint8_t recordType = 6;
+ uint8_t fieldType = 7;
+ uint8_t transferOpFlag = 0;
+
+ constexpr auto payLoadLength = sizeof(pldm_get_fru_record_by_option_req);
+
+ std::array<uint8_t, sizeof(pldm_msg_hdr) + payLoadLength> request;
+ auto reqMsg = reinterpret_cast<pldm_msg*>(request.data());
+
+ auto rc = encode_get_fru_record_by_option_req(
+ instanceId, dataTransferHandle, fruTableHandle, recordSetIdentifier,
+ recordType, fieldType, transferOpFlag, reqMsg, payLoadLength);
+
+ EXPECT_EQ(rc, PLDM_SUCCESS);
+
+ uint32_t retDataTransferHandle{};
+ uint16_t retFruTableHandle{};
+ uint16_t retRecordSetIdentifier{};
+ uint8_t retRecordType{};
+ uint8_t retFieldType{};
+ uint8_t retTransferOpFlag{};
+
+ rc = decode_get_fru_record_by_option_req(
+ reqMsg, payLoadLength, &retDataTransferHandle, &retFruTableHandle,
+ &retRecordSetIdentifier, &retRecordType, &retFieldType,
+ &retTransferOpFlag);
+
+ EXPECT_EQ(rc, PLDM_SUCCESS);
+ EXPECT_EQ(retDataTransferHandle, dataTransferHandle);
+ EXPECT_EQ(retFruTableHandle, fruTableHandle);
+ EXPECT_EQ(retRecordSetIdentifier, recordSetIdentifier);
+ EXPECT_EQ(retRecordType, recordType);
+ EXPECT_EQ(retFieldType, fieldType);
+ EXPECT_EQ(retTransferOpFlag, transferOpFlag);
+}
+
+TEST(GetFRURecordByOption, testBadDecodeRequest)
+{
+ constexpr auto payLoadLength = sizeof(pldm_get_fru_record_by_option_req);
+ std::array<uint8_t, sizeof(pldm_msg_hdr) + payLoadLength> request;
+ auto reqMsg = reinterpret_cast<pldm_msg*>(request.data());
+
+ uint32_t retDataTransferHandle{};
+ uint16_t retFruTableHandle{};
+ uint16_t retRecordSetIdentifier{};
+ uint8_t retRecordType{};
+ uint8_t retFieldType{};
+ uint8_t retTransferOpFlag{};
+
+ auto rc = decode_get_fru_record_by_option_req(
+ reqMsg, payLoadLength - 1, &retDataTransferHandle, &retFruTableHandle,
+ &retRecordSetIdentifier, &retRecordType, &retFieldType,
+ &retTransferOpFlag);
+
+ EXPECT_EQ(rc, PLDM_ERROR_INVALID_LENGTH);
+
+ rc = decode_get_fru_record_by_option_req(
+ reqMsg, payLoadLength - 1, nullptr, &retFruTableHandle,
+ &retRecordSetIdentifier, &retRecordType, &retFieldType,
+ &retTransferOpFlag);
+
+ EXPECT_EQ(rc, PLDM_ERROR_INVALID_DATA);
+}
+
+TEST(GetFruRecordByOption, testGoodEncodeResponse)
+{
+ uint8_t completionCode = PLDM_SUCCESS;
+ uint8_t instanceId = 2;
+ uint32_t dataTransferHandle = 3;
+ uint8_t transferFlag = 5;
+
+ std::array<uint8_t, 5> fruData = {1, 2, 3, 4, 5};
+ constexpr auto payLoadLength =
+ sizeof(pldm_get_fru_record_by_option_resp) - 1 + fruData.size();
+
+ std::array<uint8_t, sizeof(pldm_msg_hdr) + payLoadLength> response;
+ auto respMsg = reinterpret_cast<pldm_msg*>(response.data());
+
+ auto rc = encode_get_fru_record_by_option_resp(
+ instanceId, completionCode, dataTransferHandle, transferFlag,
+ fruData.data(), fruData.size(), respMsg, payLoadLength);
+
+ auto payLoadMsg =
+ reinterpret_cast<pldm_get_fru_record_by_option_resp*>(respMsg->payload);
+
+ EXPECT_EQ(rc, PLDM_SUCCESS);
+ EXPECT_EQ(payLoadMsg->completion_code, completionCode);
+ EXPECT_EQ(payLoadMsg->next_data_transfer_handle,
+ htole32(dataTransferHandle));
+ EXPECT_EQ(payLoadMsg->transfer_flag, transferFlag);
+
+ EXPECT_EQ(std::memcmp(payLoadMsg->fru_structure_data, fruData.data(),
+ fruData.size()),
+ 0);
+}
+
+TEST(GetFruRecordByOption, testBadEncodeResponse)
+{
+ uint8_t completionCode = PLDM_SUCCESS;
+ uint8_t instanceId = 2;
+ uint32_t dataTransferHandle = 3;
+ uint8_t transferFlag = 5;
+
+ std::array<uint8_t, 5> fruData = {1, 2, 3, 4, 5};
+ constexpr auto payLoadLength =
+ sizeof(pldm_get_fru_record_by_option_resp) - 1 + fruData.size();
+
+ std::array<uint8_t, sizeof(pldm_msg_hdr) + payLoadLength> response;
+ auto respMsg = reinterpret_cast<pldm_msg*>(response.data());
+
+ auto rc = encode_get_fru_record_by_option_resp(
+ instanceId, completionCode, dataTransferHandle, transferFlag, nullptr,
+ fruData.size(), respMsg, payLoadLength);
+
+ EXPECT_EQ(rc, PLDM_ERROR_INVALID_DATA);
+
+ rc = encode_get_fru_record_by_option_resp(
+ instanceId, completionCode, dataTransferHandle, transferFlag,
+ fruData.data(), fruData.size(), respMsg, payLoadLength - 1);
+
+ EXPECT_EQ(rc, PLDM_ERROR_INVALID_LENGTH);
+}
+
+TEST(GetFruRecordByOption, testGoodDecodeResponse)
+{
+ uint8_t completionCode = PLDM_SUCCESS;
+ uint8_t instanceId = 2;
+ uint32_t dataTransferHandle = 3;
+ uint8_t transferFlag = 5;
+
+ std::array<uint8_t, 5> fruData = {1, 2, 3, 4, 5};
+ constexpr auto payLoadLength =
+ sizeof(pldm_get_fru_record_by_option_resp) - 1 + fruData.size();
+
+ std::array<uint8_t, sizeof(pldm_msg_hdr) + payLoadLength> response;
+ auto respMsg = reinterpret_cast<pldm_msg*>(response.data());
+
+ auto rc = encode_get_fru_record_by_option_resp(
+ instanceId, completionCode, dataTransferHandle, transferFlag,
+ fruData.data(), fruData.size(), respMsg, payLoadLength);
+
+ EXPECT_EQ(rc, PLDM_SUCCESS);
+
+ uint8_t retCompletionCode;
+ uint32_t retDataTransferHandle;
+ uint8_t retTransferFlag;
+ variable_field retFruData;
+
+ rc = decode_get_fru_record_by_option_resp(
+ respMsg, payLoadLength, &retCompletionCode, &retDataTransferHandle,
+ &retTransferFlag, &retFruData);
+
+ EXPECT_EQ(rc, PLDM_SUCCESS);
+ EXPECT_EQ(retCompletionCode, completionCode);
+ EXPECT_EQ(retDataTransferHandle, dataTransferHandle);
+ EXPECT_EQ(retTransferFlag, transferFlag);
+ EXPECT_EQ(retFruData.length, fruData.size());
+ EXPECT_EQ(std::memcmp(fruData.data(), retFruData.ptr, fruData.size()), 0);
+}
+
+TEST(GetFruRecordByOption, testBadDecodeResponse)
+{
+
+ uint8_t completionCode = PLDM_SUCCESS;
+ uint8_t instanceId = 2;
+ uint32_t dataTransferHandle = 3;
+ uint8_t transferFlag = 5;
+
+ std::array<uint8_t, 5> fruData = {1, 2, 3, 4, 5};
+ constexpr auto payLoadLength =
+ sizeof(pldm_get_fru_record_by_option_resp) - 1 + fruData.size();
+
+ std::array<uint8_t, sizeof(pldm_msg_hdr) + payLoadLength> response;
+ auto respMsg = reinterpret_cast<pldm_msg*>(response.data());
+
+ auto rc = encode_get_fru_record_by_option_resp(
+ instanceId, completionCode, dataTransferHandle, transferFlag,
+ fruData.data(), fruData.size(), respMsg, payLoadLength);
+
+ EXPECT_EQ(rc, PLDM_SUCCESS);
+
+ uint8_t retCompletionCode;
+ uint32_t retDataTransferHandle;
+ uint8_t retTransferFlag;
+ variable_field retFruData;
+
+ rc = decode_get_fru_record_by_option_resp(respMsg, payLoadLength, nullptr,
+ &retDataTransferHandle,
+ &retTransferFlag, &retFruData);
+
+ EXPECT_EQ(rc, PLDM_ERROR_INVALID_DATA);
+
+ rc = decode_get_fru_record_by_option_resp(
+ respMsg, PLDM_GET_FRU_RECORD_BY_OPTION_MIN_RESP_BYTES - 1,
+ &retCompletionCode, &retDataTransferHandle, &retTransferFlag,
+ &retFruData);
+
+ EXPECT_EQ(rc, PLDM_ERROR_INVALID_LENGTH);
+}