libpldm: Migrate to subproject

Organize files in libpldm to make it a subproject

In the current state, libpldm is not readily consumable
as a subproject.This commit does all the necessary re-organisation
of the source code to make it work as a subproject.

There are no .c/.h files changes in this commit, only meson
changes and re-organising the code structure.

Signed-off-by: Manojkiran Eda <manojkiran.eda@gmail.com>
Change-Id: I20a71c0c972b1fd81fb359d604433618799102c6
diff --git a/tests/libpldm_fru_test.cpp b/tests/libpldm_fru_test.cpp
new file mode 100644
index 0000000..0419826
--- /dev/null
+++ b/tests/libpldm_fru_test.cpp
@@ -0,0 +1,887 @@
+#include <string.h>
+
+#include <array>
+#include <cstring>
+
+#include "libpldm/base.h"
+#include "libpldm/fru.h"
+
+#include <gtest/gtest.h>
+
+TEST(GetFruRecordTableMetadata, testGoodEncodeRequest)
+{
+    std::array<uint8_t, sizeof(pldm_msg_hdr)> requestMsg{};
+    auto requestPtr = reinterpret_cast<pldm_msg*>(requestMsg.data());
+    auto rc = encode_get_fru_record_table_metadata_req(
+        0, requestPtr, PLDM_GET_FRU_RECORD_TABLE_METADATA_REQ_BYTES);
+    ASSERT_EQ(rc, PLDM_SUCCESS);
+    ASSERT_EQ(requestPtr->hdr.request, PLDM_REQUEST);
+    ASSERT_EQ(requestPtr->hdr.instance_id, 0u);
+    ASSERT_EQ(requestPtr->hdr.type, PLDM_FRU);
+    ASSERT_EQ(requestPtr->hdr.command, PLDM_GET_FRU_RECORD_TABLE_METADATA);
+}
+
+TEST(GetFruRecordTableMetadata, testBadEncodeRequest)
+{
+    auto rc = encode_get_fru_record_table_metadata_req(0, NULL, 0);
+    ASSERT_EQ(rc, PLDM_ERROR_INVALID_DATA);
+    std::array<uint8_t, sizeof(pldm_msg_hdr)> requestMsg{};
+    auto requestPtr = reinterpret_cast<pldm_msg*>(requestMsg.data());
+    rc = encode_get_fru_record_table_metadata_req(0, requestPtr, 1);
+    ASSERT_EQ(rc, PLDM_ERROR_INVALID_LENGTH);
+}
+
+TEST(GetFruRecordTableMetadata, testGoodDecodeResponse)
+{
+
+    std::vector<uint8_t> responseMsg(
+        sizeof(pldm_msg_hdr) + PLDM_GET_FRU_RECORD_TABLE_METADATA_RESP_BYTES);
+    auto responsePtr = reinterpret_cast<pldm_msg*>(responseMsg.data());
+    size_t payload_length = responseMsg.size() - sizeof(pldm_msg_hdr);
+    auto response = reinterpret_cast<pldm_get_fru_record_table_metadata_resp*>(
+        responsePtr->payload);
+
+    responsePtr->hdr.request = PLDM_RESPONSE;
+    responsePtr->hdr.instance_id = 0;
+    responsePtr->hdr.type = PLDM_FRU;
+    responsePtr->hdr.command = PLDM_GET_FRU_RECORD_TABLE_METADATA;
+    response->completion_code = PLDM_SUCCESS;
+    response->fru_data_major_version = 0x12;
+    response->fru_data_minor_version = 0x21;
+    response->fru_table_maximum_size = htole32(0x1234ABCD);
+    response->fru_table_length = htole32(0x56781234);
+    response->total_record_set_identifiers = htole16(0x34EF);
+    response->total_table_records = htole16(0xEEEF);
+    response->checksum = htole32(0x6543FA71);
+
+    uint8_t completion_code = 0xFF;
+    uint8_t fru_data_major_version = 0x00;
+    uint8_t fru_data_minor_version = 0x00;
+    uint32_t fru_table_maximum_size = htole32(0x00000000);
+    uint32_t fru_table_length = htole32(0x00000000);
+    uint16_t total_record_set_identifiers = htole16(0x0000);
+    uint16_t total_table_records = htole16(0x0000);
+    uint32_t checksum = htole32(0x00000000);
+
+    auto rc = decode_get_fru_record_table_metadata_resp(
+        responsePtr, payload_length, &completion_code, &fru_data_major_version,
+        &fru_data_minor_version, &fru_table_maximum_size, &fru_table_length,
+        &total_record_set_identifiers, &total_table_records, &checksum);
+    ASSERT_EQ(rc, PLDM_SUCCESS);
+    ASSERT_EQ(completion_code, PLDM_SUCCESS);
+    ASSERT_EQ(fru_data_major_version, 0x12u);
+    ASSERT_EQ(fru_data_minor_version, 0x21u);
+    ASSERT_EQ(fru_table_maximum_size, 0x1234ABCDu);
+    ASSERT_EQ(fru_table_length, 0x56781234u);
+    ASSERT_EQ(total_record_set_identifiers, 0x34EFu);
+    ASSERT_EQ(total_table_records, 0xEEEFu);
+    ASSERT_EQ(checksum, 0x6543FA71u);
+
+    response->fru_data_major_version = 0x00;
+    response->fru_data_minor_version = 0x00;
+    response->fru_table_maximum_size = htole32(0x00000000);
+    response->fru_table_length = htole32(0x00000000);
+    response->total_record_set_identifiers = htole16(0x0000);
+    response->total_table_records = htole16(0x0000);
+    response->checksum = htole32(0x00000000);
+    fru_data_major_version = 0x00;
+    fru_data_minor_version = 0x00;
+    fru_table_maximum_size = htole32(0x00000000);
+    fru_table_length = htole32(0x00000000);
+    total_record_set_identifiers = htole16(0x0000);
+    total_table_records = htole16(0x0000);
+    checksum = htole32(0x00000000);
+    response->completion_code = PLDM_ERROR_INVALID_LENGTH;
+    rc = decode_get_fru_record_table_metadata_resp(
+        responsePtr, payload_length, &completion_code, &fru_data_major_version,
+        &fru_data_minor_version, &fru_table_maximum_size, &fru_table_length,
+        &total_record_set_identifiers, &total_table_records, &checksum);
+    ASSERT_EQ(rc, PLDM_SUCCESS);
+    ASSERT_EQ(responsePtr->hdr.request, PLDM_RESPONSE);
+    ASSERT_EQ(responsePtr->hdr.instance_id, 0u);
+    ASSERT_EQ(responsePtr->hdr.type, PLDM_FRU);
+    ASSERT_EQ(responsePtr->hdr.command, PLDM_GET_FRU_RECORD_TABLE_METADATA);
+    ASSERT_EQ(completion_code, PLDM_ERROR_INVALID_LENGTH);
+    ASSERT_EQ(fru_data_major_version, 0x00u);
+    ASSERT_EQ(fru_data_minor_version, 0x00u);
+    ASSERT_EQ(fru_table_maximum_size, 0x00000000u);
+    ASSERT_EQ(fru_table_length, 0x00000000u);
+    ASSERT_EQ(total_record_set_identifiers, 0x0000u);
+    ASSERT_EQ(total_table_records, 0x0000u);
+    ASSERT_EQ(checksum, 0x00000000u);
+}
+
+TEST(GetFruRecordTableMetadata, testBadDecodeResponse)
+{
+    std::vector<uint8_t> responseMsg(
+        sizeof(pldm_msg_hdr) + PLDM_GET_FRU_RECORD_TABLE_METADATA_RESP_BYTES);
+    auto responsePtr = reinterpret_cast<pldm_msg*>(responseMsg.data());
+    size_t payload_length = responseMsg.size() - sizeof(pldm_msg_hdr);
+    auto response = reinterpret_cast<pldm_get_fru_record_table_metadata_resp*>(
+        responsePtr->payload);
+
+    response->completion_code = PLDM_SUCCESS;
+    response->fru_data_major_version = 0x12;
+    response->fru_data_minor_version = 0x21;
+    response->fru_table_maximum_size = htole32(0x1234ABCD);
+    response->fru_table_length = htole32(0x56781234);
+    response->total_record_set_identifiers = htole16(0x34EF);
+    response->total_table_records = htole16(0xEEEF);
+    response->checksum = htole32(0x6543FA71);
+
+    uint8_t completion_code = 0xFF;
+    uint8_t fru_data_major_version = 0x00;
+    uint8_t fru_data_minor_version = 0x00;
+    uint32_t fru_table_maximum_size = htole32(0x00000000);
+    uint32_t fru_table_length = htole32(0x00000000);
+    uint16_t total_record_set_identifiers = htole16(0x0000);
+    uint16_t total_table_records = htole16(0x0000);
+    uint32_t checksum = htole32(0x00000000);
+
+    auto rc = decode_get_fru_record_table_metadata_resp(
+        responsePtr, PLDM_GET_FRU_RECORD_TABLE_METADATA_RESP_BYTES + 2,
+        &completion_code, &fru_data_major_version, &fru_data_minor_version,
+        &fru_table_maximum_size, &fru_table_length,
+        &total_record_set_identifiers, &total_table_records, &checksum);
+    ASSERT_EQ(rc, PLDM_ERROR_INVALID_LENGTH);
+
+    rc = decode_get_fru_record_table_metadata_resp(
+        responsePtr, payload_length, &completion_code, NULL,
+        &fru_data_minor_version, &fru_table_maximum_size, &fru_table_length,
+        &total_record_set_identifiers, &total_table_records, &checksum);
+    ASSERT_EQ(rc, PLDM_ERROR_INVALID_DATA);
+
+    rc = decode_get_fru_record_table_metadata_resp(
+        responsePtr, payload_length, &completion_code, &fru_data_major_version,
+        NULL, &fru_table_maximum_size, &fru_table_length,
+        &total_record_set_identifiers, &total_table_records, &checksum);
+    ASSERT_EQ(rc, PLDM_ERROR_INVALID_DATA);
+
+    rc = decode_get_fru_record_table_metadata_resp(
+        responsePtr, payload_length, &completion_code, &fru_data_major_version,
+        &fru_data_minor_version, NULL, &fru_table_length,
+        &total_record_set_identifiers, &total_table_records, &checksum);
+    ASSERT_EQ(rc, PLDM_ERROR_INVALID_DATA);
+
+    rc = decode_get_fru_record_table_metadata_resp(
+        responsePtr, payload_length, &completion_code, &fru_data_major_version,
+        &fru_data_minor_version, &fru_table_maximum_size, NULL,
+        &total_record_set_identifiers, &total_table_records, &checksum);
+    ASSERT_EQ(rc, PLDM_ERROR_INVALID_DATA);
+
+    rc = decode_get_fru_record_table_metadata_resp(
+        responsePtr, payload_length, &completion_code, &fru_data_major_version,
+        &fru_data_minor_version, &fru_table_maximum_size, &fru_table_length,
+        NULL, &total_table_records, &checksum);
+    ASSERT_EQ(rc, PLDM_ERROR_INVALID_DATA);
+
+    rc = decode_get_fru_record_table_metadata_resp(
+        responsePtr, payload_length, &completion_code, &fru_data_major_version,
+        &fru_data_minor_version, &fru_table_maximum_size, &fru_table_length,
+        &total_record_set_identifiers, NULL, &checksum);
+    ASSERT_EQ(rc, PLDM_ERROR_INVALID_DATA);
+
+    rc = decode_get_fru_record_table_metadata_resp(
+        responsePtr, payload_length, &completion_code, &fru_data_major_version,
+        &fru_data_minor_version, &fru_table_maximum_size, &fru_table_length,
+        &total_record_set_identifiers, &total_table_records, NULL);
+    ASSERT_EQ(rc, PLDM_ERROR_INVALID_DATA);
+}
+
+TEST(GetFruRecordTableMetadata, testGoodEncodeResponse)
+{
+
+    std::array<uint8_t, sizeof(pldm_msg_hdr) +
+                            PLDM_GET_FRU_RECORD_TABLE_METADATA_RESP_BYTES>
+        responseMsg{};
+    auto responsePtr = reinterpret_cast<pldm_msg*>(responseMsg.data());
+
+    responsePtr->hdr.request = PLDM_RESPONSE;
+    responsePtr->hdr.instance_id = 0;
+    responsePtr->hdr.type = PLDM_FRU;
+    responsePtr->hdr.command = PLDM_GET_FRU_RECORD_TABLE_METADATA;
+
+    uint8_t completion_code = PLDM_SUCCESS;
+    uint8_t fru_data_major_version = 0x12;
+    uint8_t fru_data_minor_version = 0x21;
+    uint32_t fru_table_maximum_size = htole32(0x1234ABCD);
+    uint32_t fru_table_length = htole32(0x56781234);
+    uint16_t total_record_set_identifiers = htole16(0x34EF);
+    uint16_t total_table_records = htole16(0xEEEF);
+    uint32_t checksum = htole32(0x6543FA71);
+
+    auto rc = encode_get_fru_record_table_metadata_resp(
+        0, completion_code, fru_data_major_version, fru_data_minor_version,
+        fru_table_maximum_size, fru_table_length, total_record_set_identifiers,
+        total_table_records, checksum, responsePtr);
+
+    auto response = reinterpret_cast<pldm_get_fru_record_table_metadata_resp*>(
+        responsePtr->payload);
+
+    ASSERT_EQ(rc, PLDM_SUCCESS);
+    ASSERT_EQ(responsePtr->hdr.request, PLDM_RESPONSE);
+    ASSERT_EQ(responsePtr->hdr.instance_id, 0u);
+    ASSERT_EQ(responsePtr->hdr.type, PLDM_FRU);
+    ASSERT_EQ(responsePtr->hdr.command, PLDM_GET_FRU_RECORD_TABLE_METADATA);
+    ASSERT_EQ(response->completion_code, PLDM_SUCCESS);
+    ASSERT_EQ(response->fru_data_major_version, 0x12u);
+    ASSERT_EQ(response->fru_data_minor_version, 0x21u);
+    ASSERT_EQ(response->fru_table_maximum_size, 0x1234ABCDu);
+    ASSERT_EQ(response->fru_table_length, 0x56781234u);
+    ASSERT_EQ(response->total_record_set_identifiers, 0x34EFu);
+    ASSERT_EQ(response->total_table_records, 0xEEEFu);
+    ASSERT_EQ(response->checksum, 0x6543FA71u);
+
+    response->fru_data_major_version = 0;
+    response->fru_data_major_version = 0x00;
+    response->fru_data_minor_version = 0x00;
+    response->fru_table_maximum_size = htole32(0x00000000);
+    response->fru_table_length = htole32(0x00000000);
+    response->total_record_set_identifiers = htole16(0x0000);
+    response->total_table_records = htole16(0x0000);
+    response->checksum = htole32(0x00000000);
+    completion_code = PLDM_ERROR_INVALID_DATA;
+    rc = encode_get_fru_record_table_metadata_resp(
+        0, completion_code, fru_data_major_version, fru_data_minor_version,
+        fru_table_maximum_size, fru_table_length, total_record_set_identifiers,
+        total_table_records, checksum, responsePtr);
+
+    ASSERT_EQ(rc, PLDM_SUCCESS);
+    ASSERT_EQ(responsePtr->hdr.request, PLDM_RESPONSE);
+    ASSERT_EQ(responsePtr->hdr.instance_id, 0u);
+    ASSERT_EQ(responsePtr->hdr.type, PLDM_FRU);
+    ASSERT_EQ(responsePtr->hdr.command, PLDM_GET_FRU_RECORD_TABLE_METADATA);
+    ASSERT_EQ(completion_code, PLDM_ERROR_INVALID_DATA);
+    ASSERT_EQ(response->fru_data_major_version, 0x00u);
+    ASSERT_EQ(response->fru_data_minor_version, 0x00u);
+    ASSERT_EQ(response->fru_table_maximum_size, 0x00000000u);
+    ASSERT_EQ(response->fru_table_length, 0x00000000u);
+    ASSERT_EQ(response->total_record_set_identifiers, 0x0000u);
+    ASSERT_EQ(response->total_table_records, 0x0000u);
+    ASSERT_EQ(response->checksum, 0x00000000u);
+}
+
+TEST(GetFruRecordTableMetadata, testBadEncodeResponse)
+{
+    std::array<uint8_t, sizeof(pldm_msg_hdr) +
+                            PLDM_GET_FRU_RECORD_TABLE_METADATA_RESP_BYTES>
+        responseMsg{};
+    auto responsePtr = reinterpret_cast<pldm_msg*>(responseMsg.data());
+
+    uint8_t completion_code = PLDM_SUCCESS;
+    uint8_t fru_data_major_version = 0x12;
+    uint8_t fru_data_minor_version = 0x21;
+    uint32_t fru_table_maximum_size = htole32(0x1234ABCD);
+    uint32_t fru_table_length = htole32(0x56781234);
+    uint16_t total_record_set_identifiers = htole16(0x34EF);
+    uint16_t total_table_records = htole16(0xEEEF);
+    uint32_t checksum = htole32(0x6543FA71);
+
+    auto rc = encode_get_fru_record_table_metadata_resp(
+        0, completion_code, fru_data_major_version, fru_data_minor_version,
+        fru_table_maximum_size, fru_table_length, total_record_set_identifiers,
+        total_table_records, checksum, NULL);
+
+    auto response = reinterpret_cast<pldm_get_fru_record_table_metadata_resp*>(
+        responsePtr->payload);
+
+    ASSERT_EQ(rc, PLDM_ERROR_INVALID_DATA);
+    ASSERT_EQ(completion_code, PLDM_SUCCESS);
+    ASSERT_EQ(response->fru_data_major_version, 0x00u);
+    ASSERT_EQ(response->fru_data_minor_version, 0x00u);
+    ASSERT_EQ(response->fru_table_maximum_size, 0x00000000u);
+    ASSERT_EQ(response->fru_table_length, 0x00000000u);
+    ASSERT_EQ(response->total_record_set_identifiers, 0x0000u);
+    ASSERT_EQ(response->total_table_records, 0x0000u);
+    ASSERT_EQ(response->checksum, 0x00000000u);
+}
+
+TEST(GetFruRecordTable, testGoodDecodeRequest)
+{
+    uint32_t data_transfer_handle = 31;
+    uint8_t transfer_operation_flag = PLDM_GET_FIRSTPART;
+    std::array<uint8_t,
+               PLDM_GET_FRU_RECORD_TABLE_REQ_BYTES + sizeof(pldm_msg_hdr)>
+        requestMsg{};
+    auto requestPtr = reinterpret_cast<pldm_msg*>(requestMsg.data());
+    size_t payload_length = requestMsg.size() - sizeof(pldm_msg_hdr);
+    auto request =
+        reinterpret_cast<pldm_get_fru_record_table_req*>(requestPtr->payload);
+
+    request->data_transfer_handle = htole32(data_transfer_handle);
+    request->transfer_operation_flag = transfer_operation_flag;
+
+    uint32_t ret_data_transfer_handle = 0;
+    uint8_t ret_transfer_operation_flag = 0;
+
+    // Invoke decode get FRU record table request api
+    auto rc = decode_get_fru_record_table_req(requestPtr, payload_length,
+                                              &ret_data_transfer_handle,
+                                              &ret_transfer_operation_flag);
+
+    ASSERT_EQ(rc, PLDM_SUCCESS);
+    ASSERT_EQ(data_transfer_handle, ret_data_transfer_handle);
+    ASSERT_EQ(transfer_operation_flag, ret_transfer_operation_flag);
+}
+
+TEST(GetFruRecordTable, testBadDecodeRequest)
+{
+    uint32_t data_transfer_handle = 0x0;
+    uint8_t transfer_operation_flag = PLDM_GET_FIRSTPART;
+
+    std::array<uint8_t,
+               sizeof(pldm_msg_hdr) + PLDM_GET_FRU_RECORD_TABLE_REQ_BYTES>
+        requestMsg{};
+    auto requestPtr = reinterpret_cast<pldm_msg*>(requestMsg.data());
+
+    // Payload message is missing
+    auto rc = decode_get_fru_record_table_req(NULL, 0, &data_transfer_handle,
+                                              &transfer_operation_flag);
+    ASSERT_EQ(rc, PLDM_ERROR_INVALID_DATA);
+
+    // Payload length is invalid
+    rc = decode_get_fru_record_table_req(requestPtr, 0, &data_transfer_handle,
+                                         &transfer_operation_flag);
+    ASSERT_EQ(rc, PLDM_ERROR_INVALID_LENGTH);
+}
+
+TEST(GetFruRecordTable, testGoodEncodeResponse)
+{
+    uint8_t completion_code = 0;
+    uint32_t next_data_transfer_handle = 32;
+    uint8_t transfer_flag = PLDM_START_AND_END;
+
+    std::vector<uint8_t> responseMsg(sizeof(pldm_msg_hdr) +
+                                     PLDM_GET_FRU_RECORD_TABLE_MIN_RESP_BYTES);
+
+    auto responsePtr = reinterpret_cast<pldm_msg*>(responseMsg.data());
+    auto response =
+        reinterpret_cast<pldm_get_fru_record_table_resp*>(responsePtr->payload);
+
+    // Invoke encode get FRU record table response api
+    auto rc = encode_get_fru_record_table_resp(0, completion_code,
+                                               next_data_transfer_handle,
+                                               transfer_flag, responsePtr);
+
+    ASSERT_EQ(rc, PLDM_SUCCESS);
+    ASSERT_EQ(responsePtr->hdr.request, PLDM_RESPONSE);
+    ASSERT_EQ(responsePtr->hdr.instance_id, 0u);
+    ASSERT_EQ(responsePtr->hdr.type, PLDM_FRU);
+    ASSERT_EQ(responsePtr->hdr.command, PLDM_GET_FRU_RECORD_TABLE);
+    ASSERT_EQ(response->completion_code, PLDM_SUCCESS);
+    ASSERT_EQ(le32toh(response->next_data_transfer_handle),
+              next_data_transfer_handle);
+    ASSERT_EQ(response->transfer_flag, transfer_flag);
+}
+
+TEST(GetFruRecordTable, testBadEncodeResponse)
+{
+    uint32_t next_data_transfer_handle = 32;
+    uint8_t transfer_flag = PLDM_START_AND_END;
+
+    std::vector<uint8_t> responseMsg(sizeof(pldm_msg_hdr) +
+                                     PLDM_GET_FRU_RECORD_TABLE_MIN_RESP_BYTES);
+
+    auto responsePtr = reinterpret_cast<pldm_msg*>(responseMsg.data());
+    auto rc = encode_get_fru_record_table_resp(
+        0, PLDM_ERROR, next_data_transfer_handle, transfer_flag, responsePtr);
+
+    ASSERT_EQ(rc, PLDM_SUCCESS);
+    ASSERT_EQ(responsePtr->hdr.request, PLDM_RESPONSE);
+    ASSERT_EQ(responsePtr->hdr.instance_id, 0u);
+    ASSERT_EQ(responsePtr->hdr.type, PLDM_FRU);
+    ASSERT_EQ(responsePtr->hdr.command, PLDM_GET_FRU_RECORD_TABLE);
+    ASSERT_EQ(responsePtr->payload[0], PLDM_ERROR);
+
+    rc = encode_get_fru_record_table_resp(
+        0, PLDM_SUCCESS, next_data_transfer_handle, transfer_flag, nullptr);
+
+    ASSERT_EQ(rc, PLDM_ERROR_INVALID_DATA);
+}
+
+TEST(GetFruRecordTable, testGoodEncodeRequest)
+
+{
+    std::array<uint8_t,
+               sizeof(pldm_msg_hdr) + PLDM_GET_FRU_RECORD_TABLE_REQ_BYTES>
+        requestMsg{};
+
+    auto requestPtr = reinterpret_cast<pldm_msg*>(requestMsg.data());
+    auto request =
+        reinterpret_cast<pldm_get_fru_record_table_req*>(requestPtr->payload);
+
+    // Random value for data transfer handle and transfer operation flag
+    uint32_t data_transfer_handle = 32;
+    uint8_t transfer_operation_flag = PLDM_GET_FIRSTPART;
+
+    // Invoke encode get FRU record table request api
+    auto rc = encode_get_fru_record_table_req(
+        0, data_transfer_handle, transfer_operation_flag, requestPtr,
+        requestMsg.size() - sizeof(pldm_msg_hdr));
+
+    ASSERT_EQ(rc, PLDM_SUCCESS);
+    ASSERT_EQ(requestPtr->hdr.request, PLDM_REQUEST);
+    ASSERT_EQ(requestPtr->hdr.instance_id, 0u);
+    ASSERT_EQ(requestPtr->hdr.type, PLDM_FRU);
+    ASSERT_EQ(requestPtr->hdr.command, PLDM_GET_FRU_RECORD_TABLE);
+    ASSERT_EQ(le32toh(data_transfer_handle), request->data_transfer_handle);
+    ASSERT_EQ(transfer_operation_flag, request->transfer_operation_flag);
+}
+
+TEST(GetFruRecordTable, testBadEncodeRequest)
+
+{
+    uint32_t data_transfer_handle = 0x0;
+    uint8_t transfer_operation_flag = PLDM_GET_FIRSTPART;
+
+    std::array<uint8_t,
+               sizeof(pldm_msg_hdr) + PLDM_GET_FRU_RECORD_TABLE_REQ_BYTES>
+        requestMsg{};
+    auto rc = encode_get_fru_record_table_req(
+        0, data_transfer_handle, transfer_operation_flag, NULL,
+        requestMsg.size() - sizeof(pldm_msg_hdr));
+
+    ASSERT_EQ(rc, PLDM_ERROR_INVALID_DATA);
+}
+
+TEST(GetFruRecordTable, testGoodDecodeResponse)
+{
+    uint8_t completion_code = PLDM_SUCCESS;
+    uint32_t next_data_transfer_handle = 0x16;
+    uint8_t transfer_flag = PLDM_START_AND_END;
+    std::vector<uint8_t> fru_record_table_data = {1, 2, 3, 4, 5, 6, 7, 8, 9};
+
+    std::vector<uint8_t> responseMsg(sizeof(pldm_msg_hdr) +
+                                     PLDM_GET_FRU_RECORD_TABLE_MIN_RESP_BYTES +
+                                     fru_record_table_data.size());
+
+    auto responsePtr = reinterpret_cast<pldm_msg*>(responseMsg.data());
+    size_t payload_length = responseMsg.size() - sizeof(pldm_msg_hdr);
+    auto response =
+        reinterpret_cast<pldm_get_fru_record_table_resp*>(responsePtr->payload);
+
+    response->completion_code = completion_code;
+    response->next_data_transfer_handle = htole32(next_data_transfer_handle);
+    response->transfer_flag = transfer_flag;
+    memcpy(response->fru_record_table_data, fru_record_table_data.data(),
+           fru_record_table_data.size());
+
+    uint8_t ret_completion_code = 0;
+    uint32_t ret_next_data_transfer_handle = 0;
+    uint8_t ret_transfer_flag = 0;
+    std::vector<uint8_t> ret_fru_record_table_data(9, 0);
+    size_t ret_fru_record_table_length = 0;
+
+    // Invoke decode get FRU record table response api
+    auto rc = decode_get_fru_record_table_resp(
+        responsePtr, payload_length, &ret_completion_code,
+        &ret_next_data_transfer_handle, &ret_transfer_flag,
+        ret_fru_record_table_data.data(), &ret_fru_record_table_length);
+    ASSERT_EQ(rc, PLDM_SUCCESS);
+    ASSERT_EQ(completion_code, ret_completion_code);
+    ASSERT_EQ(next_data_transfer_handle, ret_next_data_transfer_handle);
+    ASSERT_EQ(transfer_flag, ret_transfer_flag);
+    ASSERT_EQ(0, memcmp(fru_record_table_data.data(),
+                        ret_fru_record_table_data.data(),
+                        ret_fru_record_table_length));
+    ASSERT_EQ(fru_record_table_data.size(), ret_fru_record_table_length);
+}
+
+TEST(GetFruRecordTable, testBadDecodeResponse)
+{
+    uint8_t completion_code = 0;
+    uint32_t next_data_transfer_handle = 0;
+    uint8_t transfer_flag = PLDM_START_AND_END;
+    std::vector<uint8_t> fru_record_table_data(9, 0);
+    size_t fru_record_table_length = 0;
+
+    std::vector<uint8_t> responseMsg(sizeof(pldm_msg_hdr) +
+                                     PLDM_GET_FRU_RECORD_TABLE_MIN_RESP_BYTES +
+                                     fru_record_table_data.size());
+
+    auto responsePtr = reinterpret_cast<pldm_msg*>(responseMsg.data());
+
+    // Payload message is missing
+    auto rc = decode_get_fru_record_table_resp(
+        NULL, 0, &completion_code, &next_data_transfer_handle, &transfer_flag,
+        fru_record_table_data.data(), &fru_record_table_length);
+
+    ASSERT_EQ(rc, PLDM_ERROR_INVALID_DATA);
+
+    // Payload length is invalid
+    rc = decode_get_fru_record_table_resp(
+        responsePtr, 0, &completion_code, &next_data_transfer_handle,
+        &transfer_flag, fru_record_table_data.data(), &fru_record_table_length);
+
+    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);
+}
+
+TEST(SetFRURecordTable, testGoodEncodeResponse)
+{
+    uint8_t instanceId = 2;
+    uint8_t completionCode = PLDM_SUCCESS;
+    uint32_t nextDataTransferHandle = 32;
+
+    std::array<uint8_t,
+               sizeof(pldm_msg_hdr) + PLDM_SET_FRU_RECORD_TABLE_RESP_BYTES>
+        responseMsg{};
+    struct pldm_msg* response =
+        reinterpret_cast<struct pldm_msg*>(responseMsg.data());
+    auto rc = encode_set_fru_record_table_resp(
+        instanceId, completionCode, nextDataTransferHandle,
+        responseMsg.size() - sizeof(pldm_msg_hdr), response);
+    EXPECT_EQ(rc, PLDM_SUCCESS);
+
+    struct pldm_set_fru_record_table_resp* resp =
+        reinterpret_cast<struct pldm_set_fru_record_table_resp*>(
+            response->payload);
+    EXPECT_EQ(completionCode, resp->completion_code);
+    EXPECT_EQ(htole32(nextDataTransferHandle), resp->next_data_transfer_handle);
+}
+
+TEST(SetFRURecordTable, testBadEncodeResponse)
+{
+    uint8_t instanceId = 0;
+    uint8_t completionCode = PLDM_SUCCESS;
+    uint32_t nextDataTransferHandle = 1;
+
+    std::array<uint8_t,
+               sizeof(pldm_msg_hdr) + PLDM_SET_FRU_RECORD_TABLE_RESP_BYTES>
+        responseMsg{};
+    struct pldm_msg* response =
+        reinterpret_cast<struct pldm_msg*>(responseMsg.data());
+
+    auto rc = encode_set_fru_record_table_resp(
+        instanceId, completionCode, nextDataTransferHandle,
+        responseMsg.size() - sizeof(pldm_msg_hdr), NULL);
+    EXPECT_EQ(rc, PLDM_ERROR_INVALID_DATA);
+
+    rc = encode_set_fru_record_table_resp(
+        instanceId, completionCode, nextDataTransferHandle,
+        responseMsg.size() - sizeof(pldm_msg_hdr) - 1, response);
+    EXPECT_EQ(rc, PLDM_ERROR_INVALID_LENGTH);
+}
+
+TEST(SetFRURecordTable, testGoodDecodeRequest)
+{
+    uint32_t transferHandle = 1;
+    uint8_t transferFlag = PLDM_GET_FIRSTPART;
+    uint32_t tableData = 44;
+
+    std::array<uint8_t, sizeof(pldm_msg_hdr) +
+                            PLDM_SET_FRU_RECORD_TABLE_MIN_REQ_BYTES +
+                            sizeof(tableData)>
+        requestMsg{};
+    auto request = reinterpret_cast<struct pldm_msg*>(requestMsg.data());
+    struct pldm_set_fru_record_table_req* req =
+        reinterpret_cast<struct pldm_set_fru_record_table_req*>(
+            request->payload);
+    req->data_transfer_handle = htole32(transferHandle);
+    req->transfer_flag = transferFlag;
+    memcpy(req->fru_record_table_data, &tableData, sizeof(tableData));
+
+    uint32_t retTransferHandle;
+    uint8_t retTransferFlag;
+    struct variable_field table;
+
+    auto rc = decode_set_fru_record_table_req(
+        request, requestMsg.size() - sizeof(pldm_msg_hdr), &retTransferHandle,
+        &retTransferFlag, &table);
+
+    EXPECT_EQ(rc, PLDM_SUCCESS);
+    EXPECT_EQ(retTransferHandle, transferHandle);
+    EXPECT_EQ(retTransferFlag, transferFlag);
+    EXPECT_EQ(table.length, sizeof(tableData));
+    EXPECT_EQ(0, memcmp(table.ptr, &tableData, sizeof(tableData)));
+}
+
+TEST(SetFRURecordTable, testBadDecodeRequest)
+{
+    uint32_t transferHandle = 1;
+    uint8_t transferFlag = PLDM_GET_FIRSTPART;
+    uint32_t tableData = 44;
+
+    std::array<uint8_t, sizeof(pldm_msg_hdr) +
+                            PLDM_SET_FRU_RECORD_TABLE_MIN_REQ_BYTES +
+                            sizeof(tableData)>
+        requestMsg{};
+    auto request = reinterpret_cast<struct pldm_msg*>(requestMsg.data());
+    struct pldm_set_fru_record_table_req* req =
+        reinterpret_cast<struct pldm_set_fru_record_table_req*>(
+            request->payload);
+    req->data_transfer_handle = htole32(transferHandle);
+    req->transfer_flag = transferFlag;
+    memcpy(req->fru_record_table_data, &tableData, sizeof(tableData));
+
+    uint32_t retTransferHandle;
+    uint8_t retTransferFlag;
+
+    auto rc = decode_set_fru_record_table_req(
+        request, requestMsg.size() - sizeof(pldm_msg_hdr), &retTransferHandle,
+        &retTransferFlag, NULL);
+    EXPECT_EQ(rc, PLDM_ERROR_INVALID_DATA);
+
+    struct variable_field table;
+    rc = decode_set_fru_record_table_req(
+        request,
+        requestMsg.size() - sizeof(pldm_msg_hdr) - sizeof(tableData) - 1,
+        &retTransferHandle, &retTransferFlag, &table);
+    EXPECT_EQ(rc, PLDM_ERROR_INVALID_LENGTH);
+}