BIOS: UT for bios attribute tables with string type

In libpldmresponder_bios_test.cpp:
1. Modify some existing UTs to match new implemented types.
2. Add new class TestSingleTypeBIOSTable to test attribute value table
based on single type.

Tested:
/tmp/singleTypeBIOSTable.pnzuaS$ hexdump -C stringTable
00000000  0f 00 0c 00 73 74 72 5f  65 78 61 6d 70 6c 65 31  |....str_example1|
00000010  10 00 0c 00 73 74 72 5f  65 78 61 6d 70 6c 65 32  |....str_example2|
00000020  11 00 0c 00 73 74 72 5f  65 78 61 6d 70 6c 65 33  |....str_example3|
00000030  98 4c 55 cf                                       |.LU.|
00000034
/tmp/singleTypeBIOSTable.pnzuaS$ hexdump -C attributeTable
00000000  07 00 01 0f 00 01 01 00  64 00 03 00 61 62 63 08  |........d...abc.|
00000010  00 01 10 00 02 00 00 64  00 00 00 09 00 01 11 00  |.......d........|
00000020  00 01 00 64 00 02 00 65  66 00 00 00 fb e0 7d 7f  |...d...ef.....}.|
00000030
/tmp/singleTypeBIOSTable.pnzuaS$ hexdump -C attributeValueTable
00000000  09 00 01 02 00 65 66 00  6d 81 4a b6              |.....ef.m.J.|

Change-Id: I65316bcbd52c60d2671709632dd567aea0a52593
Signed-off-by: Carol Wang <wangkair@cn.ibm.com>
diff --git a/libpldmresponder/bios.cpp b/libpldmresponder/bios.cpp
index 6454052..8b37e35 100644
--- a/libpldmresponder/bios.cpp
+++ b/libpldmresponder/bios.cpp
@@ -761,13 +761,13 @@
     {bios_parser::bIOSEnumJson, bios_type_enum::constructAttrTable},
     {bios_parser::bIOSStrJson, bios_type_string::constructAttrTable}};
 
-using valueHandler = void (*)(const BIOSTable& BIOSAttributeTable,
+using valueHandler = std::function<void(const BIOSTable& BIOSAttributeTable,
 
-                              const BIOSTable& BIOSStringTable,
+                                        const BIOSTable& BIOSStringTable,
 
-                              Table& attributeTable);
+                                        Table& attributeTable)>;
 
-std::map<std::string, valueHandler> attrValueHandlers{
+std::map<BIOSJsonName, valueHandler> attrValueHandlers{
     {bios_parser::bIOSEnumJson, bios_type_enum::constructAttrValueTable},
     {bios_parser::bIOSStrJson, bios_type_string::constructAttrValueTable}};
 
diff --git a/test/libpldmresponder_bios_test.cpp b/test/libpldmresponder_bios_test.cpp
index d54ef2c..417c0ae 100644
--- a/test/libpldmresponder_bios_test.cpp
+++ b/test/libpldmresponder_bios_test.cpp
@@ -73,9 +73,8 @@
     ASSERT_EQ(strings == vec, true);
 }
 
-TEST(getAttrValue, allScenarios)
+TEST(getAttrValue, enumScenarios)
 {
-    using namespace bios_parser::bios_enum;
     // All the BIOS Strings in the BIOS JSON config files.
     AttrValuesMap valueMap{
         {"HMCManagedState", {false, {"On", "Off"}, {"On"}}},
@@ -84,18 +83,43 @@
         {"CodeUpdatePolicy",
          {false, {"Concurrent", "Disruptive"}, {"Concurrent"}}}};
 
-    auto rc = setupValueLookup("./bios_jsons");
+    auto rc = bios_parser::bios_enum::setupValueLookup("./bios_jsons");
     ASSERT_EQ(rc, 0);
 
-    auto values = getValues();
+    auto values = bios_parser::bios_enum::getValues();
     ASSERT_EQ(valueMap == values, true);
 
-    CurrentValues cv{"Concurrent"};
-    auto value = getAttrValue("CodeUpdatePolicy");
+    bios_parser::bios_enum::CurrentValues cv{"Concurrent"};
+    auto value = bios_parser::bios_enum::getAttrValue("CodeUpdatePolicy");
     ASSERT_EQ(value == cv, true);
 
     // Invalid attribute name
-    ASSERT_THROW(getAttrValue("CodeUpdatePolic"), std::out_of_range);
+    ASSERT_THROW(bios_parser::bios_enum::getAttrValue("CodeUpdatePolic"),
+                 std::out_of_range);
+}
+
+TEST(getAttrValue, stringScenarios)
+{
+    // All the BIOS Strings in the BIOS JSON config files.
+    bios_parser::bios_string::AttrValuesMap valueMap{
+        {"str_example1", {false, 1, 1, 100, 3, "abc"}},
+        {"str_example2", {false, 2, 0, 100, 0, ""}},
+        {"str_example3", {true, 0, 1, 100, 2, "ef"}}};
+
+    auto rc = bios_parser::bios_string::setupValueLookup("./bios_jsons");
+    EXPECT_EQ(rc, 0);
+
+    auto values = bios_parser::bios_string::getValues();
+    ASSERT_EQ(valueMap == values, true);
+
+    // Test the attribute without dbus
+    std::string cv = "ef";
+    auto value = bios_parser::bios_string::getAttrValue("str_example3");
+    EXPECT_EQ(value, cv);
+
+    // Invalid attribute name
+    ASSERT_THROW(bios_parser::bios_string::getAttrValue("str_example"),
+                 std::out_of_range);
 }
 
 namespace fs = std::filesystem;
@@ -385,3 +409,112 @@
     }
 
 } // end TEST
+
+class TestSingleTypeBIOSTable : public ::testing::Test
+{
+  public:
+    void SetUp() override
+    { // will be executed before each individual test defined
+        // in TestSingleTypeBIOSTable
+        char tmpdir[] = "/tmp/singleTypeBIOSTable.XXXXXX";
+        destBiosPath = fs::path(mkdtemp(tmpdir));
+    }
+
+    void TearDown() override
+    { // will be executed after each individual test
+        // defined in TestSingleTypeBIOSTable
+        fs::remove_all(destBiosPath);
+    }
+
+    void CopySingleJsonFile(std::string file)
+    {
+        fs::path srcDir("./bios_jsons");
+        fs::path srcBiosPath = srcDir / file;
+        std::filesystem::copy(srcBiosPath, destBiosPath);
+    }
+
+    fs::path destBiosPath;
+};
+
+TEST_F(TestSingleTypeBIOSTable, getBIOSAttributeValueTableBasedOnStringTypeTest)
+{
+    // Copy string json file to the destination
+    TestSingleTypeBIOSTable::CopySingleJsonFile(bios_parser::bIOSStrJson);
+    auto fpath = TestSingleTypeBIOSTable::destBiosPath.c_str();
+
+    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;
+
+    // Get string table with string json file only
+    req->transfer_handle = 9;
+    req->transfer_op_flag = PLDM_GET_FIRSTPART;
+    req->table_type = PLDM_BIOS_STRING_TABLE;
+
+    size_t requestPayloadLength = requestPayload.size() - sizeof(pldm_msg_hdr);
+    auto str_response =
+        internal::buildBIOSTables(request, requestPayloadLength, fpath, fpath);
+
+    // Get attribute table with string json file only
+    req->transfer_handle = 9;
+    req->transfer_op_flag = PLDM_GET_FIRSTPART;
+    req->table_type = PLDM_BIOS_ATTR_TABLE;
+
+    auto attr_response =
+        internal::buildBIOSTables(request, requestPayloadLength, fpath, fpath);
+
+    // Get attribute value table with string type
+    req->transfer_handle = 9;
+    req->transfer_op_flag = PLDM_GET_FIRSTPART;
+    req->table_type = PLDM_BIOS_ATTR_VAL_TABLE;
+
+    // Test attribute str_example3 here, which has no dbus
+    for (uint8_t times = 0; times < 2; times++)
+    { // first time first table second time existing table
+        auto response = internal::buildBIOSTables(request, requestPayloadLength,
+                                                  fpath, fpath);
+        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(struct pldm_get_bios_table_resp) - 1);
+        uint32_t traversed = 0;
+        uint8_t* tableData = reinterpret_cast<uint8_t*>(resp->table_data);
+
+        while (true)
+        {
+            struct pldm_bios_attr_val_table_entry* ptr =
+                reinterpret_cast<struct pldm_bios_attr_val_table_entry*>(
+                    tableData);
+            uint16_t attrHdl = ptr->attr_handle;
+            uint8_t attrType = ptr->attr_type;
+            EXPECT_EQ(PLDM_BIOS_STRING_READ_ONLY, attrType);
+            tableData += sizeof(attrHdl) + sizeof(attrType);
+            traversed += sizeof(attrHdl) + sizeof(attrType);
+            auto sizeDefaultStr = *(reinterpret_cast<uint16_t*>(tableData));
+            EXPECT_EQ(2, sizeDefaultStr);
+            tableData += sizeof(uint16_t);
+            traversed += sizeof(uint16_t);
+            EXPECT_EQ('e', *tableData);
+            EXPECT_EQ('f', *(tableData + 1));
+            tableData += sizeDefaultStr;
+            traversed += sizeDefaultStr;
+            break; // testing for first row
+            if ((attrValTableLen - traversed) < 8)
+            {
+                break;
+            }
+        }
+    }
+
+} // end TEST