GetBIOSTable responder implementation

This commit implements the GetBIOSTable responder handler
for the BIOS Enumeration type.
One of the tables among String table, Attribute table and Attribute
Value Table are created/fetched and sent to PLDM requester as response to
the command.

Tested:
Following are the tables constructed from the sample json file present at
"test/bios_jsons/enum_attrs.json"
-bash-4.2$ hexdump -C /tmp/AllBiosTables/stringTable
00000000  00 00 07 00 41 6c 6c 6f  77 65 64 01 00 10 00 43  |....Allowed....C|
00000010  6f 64 65 55 70 64 61 74  65 50 6f 6c 69 63 79 02  |odeUpdatePolicy.|
00000020  00 0a 00 43 6f 6e 63 75  72 72 65 6e 74 03 00 0a  |...Concurrent...|
00000030  00 44 69 73 72 75 70 74  69 76 65 04 00 0a 00 46  |.Disruptive....F|
00000040  57 42 6f 6f 74 53 69 64  65 05 00 0f 00 48 4d 43  |WBootSide....HMC|
00000050  4d 61 6e 61 67 65 64 53  74 61 74 65 06 00 10 00  |ManagedState....|
00000060  49 6e 62 61 6e 64 43 6f  64 65 55 70 64 61 74 65  |InbandCodeUpdate|
00000070  07 00 0a 00 4e 6f 74 41  6c 6c 6f 77 65 64 08 00  |....NotAllowed..|
00000080  03 00 4f 66 66 09 00 02  00 4f 6e 0a 00 04 00 50  |..Off....On....P|
00000090  65 72 6d 0b 00 04 00 54  65 6d 70 00 37 90 c0 da  |erm....Temp.7...|
000000a0
-bash-4.2$ hexdump -C /tmp/AllBiosTables/attributeTable
00000000  00 00 00 01 00 02 02 00  03 00 01 00 01 00 00 04  |................|
00000010  00 02 0a 00 0b 00 01 00  02 00 00 05 00 02 08 00  |................|
00000020  09 00 01 01 03 00 00 06  00 02 00 00 07 00 01 00  |................|
00000030  3b 85 69 a7                                       |;.i.|
00000034
-bash-4.2$ hexdump -C /tmp/AllBiosTables/attributeValueTable
00000000  00 00 00 01 00 00 00 00  d9 f6 42 58              |..........BX|
0000000c

Change-Id: I06aebcc2c2deea66e867fb775afa76a1e5d18dca
Signed-off-by: Sampa Misra <sampmisr@in.ibm.com>
diff --git a/test/Makefile.am b/test/Makefile.am
index cc0d6c2..4b0acca 100644
--- a/test/Makefile.am
+++ b/test/Makefile.am
@@ -72,16 +72,21 @@
 libpldmresponder_bios_test_CXXFLAGS = $(test_cxxflags)
 libpldmresponder_bios_test_LDFLAGS = \
 	$(test_ldflags) \
-	$(SDBUSPLUS_LIBS)
+	$(SDBUSPLUS_LIBS) \
+	-lstdc++fs
 libpldmresponder_bios_test_LDADD = \
 	$(top_builddir)/pldmd-registration.o \
 	$(top_builddir)/libpldmresponder/libpldmresponder_la-bios.o \
-	$(top_builddir)/libpldmresponder/libpldmresponder_la-bios_parser.o \
 	$(top_builddir)/libpldmresponder/libpldmresponder_la-utils.o \
+	$(top_builddir)/libpldmresponder/libpldmresponder_la-bios_table.o \
 	$(top_builddir)/libpldm/libpldm_la-base.o  \
 	$(top_builddir)/libpldm/libpldm_la-bios.o \
+	$(top_builddir)/libpldmresponder/libpldmresponder_la-bios_parser.o \
 	$(CODE_COVERAGE_LIBS) \
-	$(SDBUSPLUS_LIBS)
+	$(PHOSPHOR_LOGGING_LIBS) \
+	$(PHOSPHOR_DBUS_INTERFACES_LIBS) \
+	$(SDBUSPLUS_LIBS) \
+	-lstdc++fs
 libpldmresponder_bios_test_SOURCES = \
 	libpldmresponder_bios_test.cpp
 
@@ -112,7 +117,7 @@
 libpldmoemresponder_fileio_test_CXXFLAGS = $(test_cxxflags)
 libpldmoemresponder_fileio_test_LDFLAGS = $(test_ldflags)
 libpldmoemresponder_fileio_test_LDADD = \
-        $(top_builddir)/pldmd-registration.o \
+	$(top_builddir)/pldmd-registration.o \
 	$(top_builddir)/libpldm/libpldm_la-base.o \
 	$(top_builddir)/oem/ibm/libpldm/libpldm_la-file_io.o \
 	$(top_builddir)/oem/ibm/libpldmresponder/libpldmresponder_la-file_io.o\
@@ -136,17 +141,20 @@
 libpldmresponder_bios_table_test_CPPFLAGS = $(test_cppflags)
 libpldmresponder_bios_table_test_CXXFLAGS = $(test_cxxflags)
 libpldmresponder_bios_table_test_LDFLAGS = \
-        $(test_ldflags) \
-        $(SDBUSPLUS_LIBS)
+	$(test_ldflags) \
+	$(SDBUSPLUS_LIBS)
 libpldmresponder_bios_table_test_LDADD = \
-        $(top_builddir)/libpldmresponder/libpldmresponder_la-bios.o \
-        $(top_builddir)/libpldmresponder/libpldmresponder_la-bios_table.o \
-        $(top_builddir)/libpldmresponder/libpldmresponder_la-utils.o \
-        $(top_builddir)/libpldm/libpldm_la-base.o  \
-        $(top_builddir)/libpldm/libpldm_la-bios.o \
+	$(top_builddir)/libpldmresponder/libpldmresponder_la-bios.o \
+	$(top_builddir)/libpldmresponder/libpldmresponder_la-bios_table.o \
+	$(top_builddir)/libpldmresponder/libpldmresponder_la-utils.o \
+	$(top_builddir)/libpldm/libpldm_la-base.o  \
+	$(top_builddir)/libpldm/libpldm_la-bios.o \
+	$(top_builddir)/libpldmresponder/libpldmresponder_la-bios_parser.o \
 	$(top_builddir)/pldmd-registration.o \
-        $(CODE_COVERAGE_LIBS) \
-        $(SDBUSPLUS_LIBS) \
+	$(CODE_COVERAGE_LIBS) \
+	$(SDBUSPLUS_LIBS) \
+	$(PHOSPHOR_LOGGING_LIBS) \
+	$(PHOSPHOR_DBUS_INTERFACES_LIBS) \
 	-lstdc++fs
 libpldmresponder_bios_table_test_SOURCES = \
         libpldmresponder_bios_table_test.cpp
diff --git a/test/libpldm_bios_test.cpp b/test/libpldm_bios_test.cpp
index 495a0d2..aff5d6d 100644
--- a/test/libpldm_bios_test.cpp
+++ b/test/libpldm_bios_test.cpp
@@ -112,3 +112,97 @@
     ASSERT_EQ(month, retMonth);
     ASSERT_EQ(year, retYear);
 }
+
+TEST(GetBIOSTable, testGoodEncodeResponse)
+{
+    std::array<uint8_t,
+               sizeof(pldm_msg_hdr) + PLDM_GET_BIOS_TABLE_MIN_RESP_BYTES + 4>
+        responseMsg{};
+    auto response = reinterpret_cast<pldm_msg*>(responseMsg.data());
+
+    uint8_t completionCode = PLDM_SUCCESS;
+    uint32_t nextTransferHandle = 32;
+    uint8_t transferFlag = PLDM_START_AND_END;
+    std::array<uint8_t, 4> tableData{1, 2, 3, 4};
+
+    auto rc = encode_get_bios_table_resp(
+        0, PLDM_SUCCESS, nextTransferHandle, transferFlag, tableData.data(),
+        sizeof(pldm_msg_hdr) + PLDM_GET_BIOS_TABLE_MIN_RESP_BYTES + 4,
+        response);
+    ASSERT_EQ(rc, PLDM_SUCCESS);
+
+    struct pldm_get_bios_table_resp* resp =
+        reinterpret_cast<struct pldm_get_bios_table_resp*>(response->payload);
+
+    ASSERT_EQ(completionCode, resp->completion_code);
+    ASSERT_EQ(nextTransferHandle, resp->next_transfer_handle);
+    ASSERT_EQ(transferFlag, resp->transfer_flag);
+    ASSERT_EQ(0, memcmp(tableData.data(), resp->table_data, tableData.size()));
+}
+
+TEST(GetBIOSTable, testBadEncodeResponse)
+{
+    uint32_t nextTransferHandle = 32;
+    uint8_t transferFlag = PLDM_START_AND_END;
+    std::array<uint8_t, 4> tableData{1, 2, 3, 4};
+
+    auto rc = encode_get_bios_table_resp(
+        0, PLDM_SUCCESS, nextTransferHandle, transferFlag, tableData.data(),
+        sizeof(pldm_msg_hdr) + PLDM_GET_BIOS_TABLE_MIN_RESP_BYTES + 4, nullptr);
+    ASSERT_EQ(rc, PLDM_ERROR_INVALID_DATA);
+}
+
+TEST(GetBIOSTable, testGoodDecodeRequest)
+{
+    const auto hdr_size = sizeof(pldm_msg_hdr);
+    std::array<uint8_t, hdr_size + PLDM_GET_BIOS_TABLE_REQ_BYTES> requestMsg{};
+    uint32_t transferHandle = 31;
+    uint8_t transferOpFlag = PLDM_GET_FIRSTPART;
+    uint8_t tableType = PLDM_BIOS_ATTR_TABLE;
+    uint32_t retTransferHandle = 0;
+    uint8_t retTransferOpFlag = 0;
+    uint8_t retTableType = 0;
+
+    auto req = reinterpret_cast<pldm_msg*>(requestMsg.data());
+    struct pldm_get_bios_table_req* request =
+        reinterpret_cast<struct pldm_get_bios_table_req*>(req->payload);
+
+    request->transfer_handle = transferHandle;
+    request->transfer_op_flag = transferOpFlag;
+    request->table_type = tableType;
+
+    auto rc = decode_get_bios_table_req(req, requestMsg.size() - hdr_size,
+                                        &retTransferHandle, &retTransferOpFlag,
+                                        &retTableType);
+
+    ASSERT_EQ(rc, PLDM_SUCCESS);
+    ASSERT_EQ(transferHandle, retTransferHandle);
+    ASSERT_EQ(transferOpFlag, retTransferOpFlag);
+    ASSERT_EQ(tableType, retTableType);
+}
+
+TEST(GetBIOSTable, testBadDecodeRequest)
+{
+    const auto hdr_size = sizeof(pldm_msg_hdr);
+    std::array<uint8_t, hdr_size + PLDM_GET_BIOS_TABLE_REQ_BYTES> requestMsg{};
+    uint32_t transferHandle = 31;
+    uint8_t transferOpFlag = PLDM_GET_FIRSTPART;
+    uint8_t tableType = PLDM_BIOS_ATTR_TABLE;
+    uint32_t retTransferHandle = 0;
+    uint8_t retTransferOpFlag = 0;
+    uint8_t retTableType = 0;
+
+    auto req = reinterpret_cast<pldm_msg*>(requestMsg.data());
+    struct pldm_get_bios_table_req* request =
+        reinterpret_cast<struct pldm_get_bios_table_req*>(req->payload);
+
+    request->transfer_handle = transferHandle;
+    request->transfer_op_flag = transferOpFlag;
+    request->table_type = tableType;
+
+    auto rc = decode_get_bios_table_req(req, requestMsg.size() - hdr_size - 3,
+                                        &retTransferHandle, &retTransferOpFlag,
+                                        &retTableType);
+
+    ASSERT_EQ(rc, PLDM_ERROR_INVALID_LENGTH);
+}
diff --git a/test/libpldmresponder_bios_test.cpp b/test/libpldmresponder_bios_test.cpp
index 6e404de..b5b207b 100644
--- a/test/libpldmresponder_bios_test.cpp
+++ b/test/libpldmresponder_bios_test.cpp
@@ -1,18 +1,24 @@
 #include "libpldmresponder/bios.hpp"
 #include "libpldmresponder/bios_parser.hpp"
+#include "libpldmresponder/bios_table.hpp"
 
 #include <string.h>
 
 #include <array>
 #include <ctime>
+#include <filesystem>
 
 #include "libpldm/base.h"
 #include "libpldm/bios.h"
 
 #include <gtest/gtest.h>
 
+using namespace pldm;
 using namespace pldm::responder;
+using namespace pldm::responder::bios;
 using namespace pldm::responder::utils;
+using namespace bios_parser;
+using namespace bios_parser::bios_enum;
 
 TEST(epochToBCDTime, testTime)
 {
@@ -67,15 +73,6 @@
 TEST(getAttrValue, allScenarios)
 {
     using namespace bios_parser::bios_enum;
-
-    // Invalid directory
-    auto rc = setupValueLookup("./bios_json");
-    ASSERT_EQ(rc, -1);
-
-    // Initializes the lookup data structures
-    rc = setupValueLookup("./bios_jsons");
-    ASSERT_EQ(rc, 0);
-
     // All the BIOS Strings in the BIOS JSON config files.
     AttrValuesMap valueMap{
         {"HMCManagedState", {false, {"On", "Off"}, {"On"}}},
@@ -84,6 +81,9 @@
         {"CodeUpdatePolicy",
          {false, {"Concurrent", "Disruptive"}, {"Concurrent"}}}};
 
+    auto rc = setupValueLookup("./bios_jsons");
+    ASSERT_EQ(rc, 0);
+
     auto values = getValues();
     ASSERT_EQ(valueMap == values, true);
 
@@ -94,3 +94,291 @@
     // Invalid attribute name
     ASSERT_THROW(getAttrValue("CodeUpdatePolic"), std::out_of_range);
 }
+
+namespace fs = std::filesystem;
+class TestAllBIOSTables : public ::testing::Test
+{
+  public:
+    static void SetUpTestCase() // will execute once at the begining of all
+                                // TestAllBIOSTables objects
+    {
+        char tmpdir[] = "/tmp/allBiosTables.XXXXXX";
+        biosPath = fs::path(mkdtemp(tmpdir));
+    }
+
+    static void TearDownTestCase() // will be executed once at th eend of all
+                                   // TestAllBIOSTables objects
+    {
+        fs::remove_all(biosPath);
+    }
+
+    static fs::path biosPath;
+};
+
+fs::path TestAllBIOSTables::biosPath;
+
+TEST_F(TestAllBIOSTables, GetBIOSTableTestBadRequest)
+{
+    std::array<uint8_t, sizeof(pldm_msg_hdr) + PLDM_GET_BIOS_TABLE_REQ_BYTES>
+        requestPayload{};
+    auto request = reinterpret_cast<pldm_msg*>(requestPayload.data());
+    struct pldm_get_bios_table_req* req =
+        (struct pldm_get_bios_table_req*)request->payload;
+    req->transfer_handle = 9;
+    req->transfer_op_flag = PLDM_GET_FIRSTPART;
+    req->table_type = 0xFF;
+
+    size_t requestPayloadLength = requestPayload.size() - sizeof(pldm_msg_hdr);
+
+    auto response = internal::buildBIOSTables(request, requestPayloadLength,
+                                              "./bios_jsons", biosPath.c_str());
+    auto responsePtr = reinterpret_cast<pldm_msg*>(response.data());
+
+    struct pldm_get_bios_table_resp* resp =
+        reinterpret_cast<struct pldm_get_bios_table_resp*>(
+            responsePtr->payload);
+
+    ASSERT_EQ(PLDM_INVALID_BIOS_TABLE_TYPE, resp->completion_code);
+}
+
+TEST_F(TestAllBIOSTables, buildBIOSTablesTestBadRequest)
+{
+    std::array<uint8_t, sizeof(pldm_msg_hdr) + PLDM_GET_BIOS_TABLE_REQ_BYTES>
+        requestPayload{};
+    auto request = reinterpret_cast<pldm_msg*>(requestPayload.data());
+    struct pldm_get_bios_table_req* req =
+        (struct pldm_get_bios_table_req*)request->payload;
+    req->transfer_handle = 9;
+    req->transfer_op_flag = PLDM_GET_FIRSTPART;
+    req->table_type = PLDM_BIOS_ATTR_VAL_TABLE;
+
+    size_t requestPayloadLength = requestPayload.size() - sizeof(pldm_msg_hdr);
+
+    auto response = internal::buildBIOSTables(request, requestPayloadLength,
+                                              "./bios_jsons", biosPath.c_str());
+    auto responsePtr = reinterpret_cast<pldm_msg*>(response.data());
+    struct pldm_get_bios_table_resp* resp =
+        reinterpret_cast<struct pldm_get_bios_table_resp*>(
+            responsePtr->payload);
+    ASSERT_EQ(PLDM_BIOS_TABLE_UNAVAILABLE, resp->completion_code);
+
+    req->table_type = PLDM_BIOS_ATTR_TABLE;
+    response = internal::buildBIOSTables(request, requestPayloadLength,
+                                         "./bios_jsons", biosPath.c_str());
+    responsePtr = reinterpret_cast<pldm_msg*>(response.data());
+    resp = reinterpret_cast<struct pldm_get_bios_table_resp*>(
+        responsePtr->payload);
+    ASSERT_EQ(PLDM_BIOS_TABLE_UNAVAILABLE, resp->completion_code);
+}
+
+TEST_F(TestAllBIOSTables, GetBIOSStringTableTestGoodRequest)
+{
+    std::array<uint8_t, sizeof(pldm_msg_hdr) + PLDM_GET_BIOS_TABLE_REQ_BYTES>
+        requestPayload{};
+    auto request = reinterpret_cast<pldm_msg*>(requestPayload.data());
+    struct pldm_get_bios_table_req* req =
+        (struct pldm_get_bios_table_req*)request->payload;
+    req->transfer_handle = 9;
+    req->transfer_op_flag = PLDM_GET_FIRSTPART;
+    req->table_type = PLDM_BIOS_STRING_TABLE;
+
+    Strings biosStrings = getStrings("./bios_jsons");
+    std::sort(biosStrings.begin(), biosStrings.end());
+    biosStrings.erase(std::unique(biosStrings.begin(), biosStrings.end()),
+                      biosStrings.end());
+
+    size_t requestPayloadLength = requestPayload.size() - sizeof(pldm_msg_hdr);
+    uint8_t times = 0;
+    while (times < 2)
+    { // first time fresh table second time existing table
+        auto response = internal::buildBIOSTables(
+            request, requestPayloadLength, "./bios_jsons", biosPath.c_str());
+        auto responsePtr = reinterpret_cast<pldm_msg*>(response.data());
+
+        struct pldm_get_bios_table_resp* resp =
+            reinterpret_cast<struct pldm_get_bios_table_resp*>(
+                responsePtr->payload);
+
+        ASSERT_EQ(0, resp->completion_code);
+        ASSERT_EQ(0, resp->next_transfer_handle);
+        ASSERT_EQ(PLDM_START_AND_END, resp->transfer_flag);
+
+        uint16_t strLen = 0;
+        uint8_t* tableData = reinterpret_cast<uint8_t*>(resp->table_data);
+
+        for (auto elem : biosStrings)
+        {
+            struct pldm_bios_string_table_entry* ptr =
+                reinterpret_cast<struct pldm_bios_string_table_entry*>(
+                    tableData);
+            strLen = ptr->string_length;
+            ASSERT_EQ(strLen, elem.size());
+            ASSERT_EQ(0, memcmp(elem.c_str(), ptr->name, strLen));
+            tableData += (sizeof(pldm_bios_string_table_entry) - 1) + strLen;
+
+        } // end for
+        times++;
+    }
+}
+
+TEST_F(TestAllBIOSTables, getBIOSAttributeTableTestGoodRequest)
+{
+    std::array<uint8_t, sizeof(pldm_msg_hdr) + PLDM_GET_BIOS_TABLE_REQ_BYTES>
+        requestPayload{};
+    auto request = reinterpret_cast<pldm_msg*>(requestPayload.data());
+    struct pldm_get_bios_table_req* req =
+        (struct pldm_get_bios_table_req*)request->payload;
+    req->transfer_handle = 9;
+    req->transfer_op_flag = PLDM_GET_FIRSTPART;
+    req->table_type = PLDM_BIOS_ATTR_TABLE;
+
+    size_t requestPayloadLength = requestPayload.size() - sizeof(pldm_msg_hdr);
+
+    uint8_t times = 0;
+    while (times < 2)
+    { // first time fresh table second time existing table
+        auto response = internal::buildBIOSTables(
+            request, requestPayloadLength, "./bios_jsons", biosPath.c_str());
+        auto responsePtr = reinterpret_cast<pldm_msg*>(response.data());
+
+        struct pldm_get_bios_table_resp* resp =
+            reinterpret_cast<struct pldm_get_bios_table_resp*>(
+                responsePtr->payload);
+
+        ASSERT_EQ(0, resp->completion_code);
+        ASSERT_EQ(0, resp->next_transfer_handle);
+        ASSERT_EQ(PLDM_START_AND_END, resp->transfer_flag);
+
+        uint32_t attrTableLen =
+            response.size() - sizeof(pldm_msg_hdr) -
+            (sizeof(resp->completion_code) +
+             sizeof(resp->next_transfer_handle) + sizeof(resp->transfer_flag));
+        uint32_t traversed = 0;
+        uint16_t attrHdl = 0;
+        uint16_t stringHdl = 0;
+        uint8_t attrType = 0;
+        uint8_t numPosVals = 0;
+        uint8_t numDefVals = 0;
+        uint8_t defIndex = 0;
+
+        uint8_t* tableData = reinterpret_cast<uint8_t*>(resp->table_data);
+        while (1)
+        {
+            struct pldm_bios_attr_table_entry* ptr =
+                reinterpret_cast<struct pldm_bios_attr_table_entry*>(tableData);
+            attrHdl = ptr->attr_handle;
+            attrType = ptr->attr_type;
+            EXPECT_EQ(0, attrHdl);
+            EXPECT_EQ(PLDM_BIOS_ENUMERATION, attrType);
+            stringHdl = ptr->string_handle;
+            EXPECT_EQ(stringHdl, 1);
+            tableData += sizeof(attrHdl) + sizeof(attrType) + sizeof(stringHdl);
+            numPosVals = *tableData;
+            EXPECT_EQ(numPosVals, 2);
+            traversed += sizeof(attrHdl) + sizeof(attrType) + sizeof(stringHdl);
+            traversed += sizeof(numPosVals);
+            PossibleValuesByHandle possiVals;
+            tableData++;
+            uint16_t* temp = reinterpret_cast<uint16_t*>(tableData);
+            uint32_t i = 0;
+            while (i < numPosVals)
+            {
+                uint16_t val = *temp;
+                possiVals.push_back(val);
+                temp++;
+                i++;
+            }
+            EXPECT_EQ(possiVals.size(), 2);
+            tableData += numPosVals * sizeof(stringHdl);
+            traversed += numPosVals * sizeof(stringHdl);
+            numDefVals = *tableData;
+            EXPECT_EQ(numDefVals, 1);
+            tableData += numDefVals * sizeof(defIndex);
+            traversed += numDefVals + sizeof(numDefVals);
+
+            break; // test for first row only
+
+            if ((attrTableLen - traversed) < 8)
+            {
+                // reached pad
+                break;
+            }
+
+        } // end while
+        times++;
+    }
+
+} // end TEST
+
+TEST_F(TestAllBIOSTables, getBIOSAttributeValueTableTestGoodRequest)
+{
+    std::array<uint8_t, sizeof(pldm_msg_hdr) + PLDM_GET_BIOS_TABLE_REQ_BYTES>
+        requestPayload{};
+    auto request = reinterpret_cast<pldm_msg*>(requestPayload.data());
+    struct pldm_get_bios_table_req* req =
+        (struct pldm_get_bios_table_req*)request->payload;
+    req->transfer_handle = 9;
+    req->transfer_op_flag = PLDM_GET_FIRSTPART;
+    req->table_type = PLDM_BIOS_ATTR_VAL_TABLE;
+
+    std::string attrName("CodeUpdatePolicy");
+    CurrentValues currVals = getAttrValue(attrName);
+
+    size_t requestPayloadLength = requestPayload.size() - sizeof(pldm_msg_hdr);
+
+    uint8_t times = 0;
+    while (times < 2)
+    { // first time frest table second time existing table
+        auto response = internal::buildBIOSTables(
+            request, requestPayloadLength, "./bios_jsons", biosPath.c_str());
+        auto responsePtr = reinterpret_cast<pldm_msg*>(response.data());
+
+        struct pldm_get_bios_table_resp* resp =
+            reinterpret_cast<struct pldm_get_bios_table_resp*>(
+                responsePtr->payload);
+
+        ASSERT_EQ(0, resp->completion_code);
+        ASSERT_EQ(0, resp->next_transfer_handle);
+        ASSERT_EQ(PLDM_START_AND_END, resp->transfer_flag);
+
+        uint32_t attrValTableLen =
+            response.size() - sizeof(pldm_msg_hdr) -
+            (sizeof(resp->completion_code) +
+             sizeof(resp->next_transfer_handle) + sizeof(resp->transfer_flag));
+        uint32_t traversed = 0;
+        uint8_t* tableData = reinterpret_cast<uint8_t*>(resp->table_data);
+
+        uint16_t attrHdl;
+        uint8_t attrType;
+        uint8_t numCurrVals;
+        uint8_t currValStrIndex;
+
+        while (1)
+        {
+            struct pldm_bios_attr_val_table_entry* ptr =
+                reinterpret_cast<struct pldm_bios_attr_val_table_entry*>(
+                    tableData);
+            attrHdl = ptr->attr_handle;
+            attrType = ptr->attr_type;
+            EXPECT_EQ(0, attrHdl);
+            EXPECT_EQ(PLDM_BIOS_ENUMERATION, attrType);
+            tableData += sizeof(attrHdl) + sizeof(attrType);
+            traversed += sizeof(attrHdl) + sizeof(attrType);
+            numCurrVals = *tableData;
+            EXPECT_EQ(1, numCurrVals);
+            tableData += sizeof(numCurrVals);
+            traversed += sizeof(numCurrVals);
+            currValStrIndex = *tableData;
+            EXPECT_EQ(0, currValStrIndex);
+            tableData += numCurrVals;
+            traversed += numCurrVals;
+            break; // testing for first row
+            if ((attrValTableLen - traversed) < 8)
+            {
+                break;
+            }
+        }
+        times++;
+    }
+
+} // end TEST