bios: Implement BIOSStringAttribute
Implement BIOSStringAttribute, most of the code is copied from
bios/bios_parser.cpp.
Implement SetAttrValueOnDbus and constructEntry for string attribute
Signed-off-by: John Wang <wangzqbj@inspur.com>
Change-Id: Ic7c6b35d32738d698d7649f97cb7843606b8a2ba
diff --git a/libpldmresponder/bios_string_attribute.cpp b/libpldmresponder/bios_string_attribute.cpp
new file mode 100644
index 0000000..1d9ec5d
--- /dev/null
+++ b/libpldmresponder/bios_string_attribute.cpp
@@ -0,0 +1,115 @@
+#include "bios_string_attribute.hpp"
+
+#include "utils.hpp"
+
+#include <iostream>
+#include <tuple>
+#include <variant>
+
+namespace pldm
+{
+namespace responder
+{
+namespace bios
+{
+
+BIOSStringAttribute::BIOSStringAttribute(const Json& entry,
+ DBusHandler* const dbusHandler) :
+ BIOSAttribute(entry, dbusHandler)
+{
+ std::string strTypeTmp = entry.at("string_type");
+ auto iter = strTypeMap.find(strTypeTmp);
+ if (iter == strTypeMap.end())
+ {
+ std::cerr << "Wrong string type, STRING_TYPE=" << strTypeTmp
+ << " ATTRIBUTE_NAME=" << name << "\n";
+ throw std::invalid_argument("Wrong string type");
+ }
+ stringInfo.stringType = static_cast<uint8_t>(iter->second);
+
+ stringInfo.minLength = entry.at("minimum_string_length");
+ stringInfo.maxLength = entry.at("maximum_string_length");
+ stringInfo.defLength = entry.at("default_string_length");
+ stringInfo.defString = entry.at("default_string");
+
+ pldm_bios_table_attr_entry_string_info info = {
+ 0,
+ readOnly,
+ stringInfo.stringType,
+ stringInfo.minLength,
+ stringInfo.maxLength,
+ stringInfo.defLength,
+ stringInfo.defString.data(),
+ };
+
+ const char* errmsg;
+ auto rc = pldm_bios_table_attr_entry_string_info_check(&info, &errmsg);
+ if (rc != PLDM_SUCCESS)
+ {
+ std::cerr << "Wrong field for string attribute, ATTRIBUTE_NAME=" << name
+ << " ERRMSG=" << errmsg
+ << " MINIMUM_STRING_LENGTH=" << stringInfo.minLength
+ << " MAXIMUM_STRING_LENGTH=" << stringInfo.maxLength
+ << " DEFAULT_STRING_LENGTH=" << stringInfo.defLength
+ << " DEFAULT_STRING=" << stringInfo.defString << "\n";
+ throw std::invalid_argument("Wrong field for string attribute");
+ }
+}
+
+void BIOSStringAttribute::setAttrValueOnDbus(
+ const pldm_bios_attr_val_table_entry* attrValueEntry,
+ const pldm_bios_attr_table_entry*, const BIOSStringTable&)
+{
+ if (readOnly)
+ {
+ return;
+ }
+
+ PropertyValue value =
+ table::attribute_value::decodeStringEntry(attrValueEntry);
+ dbusHandler->setDbusProperty(*dBusMap, value);
+}
+
+std::string BIOSStringAttribute::getAttrValue()
+{
+ if (readOnly)
+ {
+ return stringInfo.defString;
+ }
+ try
+ {
+ return dbusHandler->getDbusProperty<std::string>(
+ dBusMap->objectPath.c_str(), dBusMap->propertyName.c_str(),
+ dBusMap->interface.c_str());
+ }
+ catch (const std::exception& e)
+ {
+ std::cerr << "Get String Attribute Value Error: AttributeName = "
+ << name << std::endl;
+ return stringInfo.defString;
+ }
+}
+
+void BIOSStringAttribute::constructEntry(const BIOSStringTable& stringTable,
+ Table& attrTable,
+ Table& attrValueTable)
+{
+ pldm_bios_table_attr_entry_string_info info = {
+ stringTable.findHandle(name), readOnly,
+ stringInfo.stringType, stringInfo.minLength,
+ stringInfo.maxLength, stringInfo.defLength,
+ stringInfo.defString.data(),
+ };
+
+ auto attrTableEntry =
+ table::attribute::constructStringEntry(attrTable, &info);
+ auto [attrHandle, attrType, _] =
+ table::attribute::decodeHeader(attrTableEntry);
+ auto currStr = getAttrValue();
+ table::attribute_value::constructStringEntry(attrValueTable, attrHandle,
+ attrType, currStr);
+}
+
+} // namespace bios
+} // namespace responder
+} // namespace pldm
diff --git a/libpldmresponder/bios_string_attribute.hpp b/libpldmresponder/bios_string_attribute.hpp
new file mode 100644
index 0000000..48b0d2d
--- /dev/null
+++ b/libpldmresponder/bios_string_attribute.hpp
@@ -0,0 +1,83 @@
+#pragma once
+#include "bios_attribute.hpp"
+
+#include <string>
+
+class TestBIOSStringAttribute;
+
+namespace pldm
+{
+namespace responder
+{
+namespace bios
+{
+
+/** @class BIOSStringAttribute
+ * @brief Associate string entry(attr table and attribute value table) and dbus
+ * attribute
+ */
+class BIOSStringAttribute : public BIOSAttribute
+{
+ public:
+ friend class ::TestBIOSStringAttribute;
+
+ /** @brief BIOS string types */
+ enum class Encoding : uint8_t
+ {
+ UNKNOWN = 0x00,
+ ASCII = 0x01,
+ HEX = 0x02,
+ UTF_8 = 0x03,
+ UTF_16LE = 0x04,
+ UTF_16BE = 0x05,
+ VENDOR_SPECIFIC = 0xFF
+ };
+
+ /** brief Mapping of string to enum for string type */
+ inline static const std::map<std::string, Encoding> strTypeMap{
+ {"Unknown", Encoding::UNKNOWN},
+ {"ASCII", Encoding::ASCII},
+ {"Hex", Encoding::HEX},
+ {"UTF-8", Encoding::UTF_8},
+ {"UTF-16LE", Encoding::UTF_16LE},
+ {"UTF-16LE", Encoding::UTF_16LE},
+ {"Vendor Specific", Encoding::VENDOR_SPECIFIC}};
+
+ /** @brief Construct a bios string attribute
+ * @param[in] entry - Json Object
+ * @param[in] dbusHandler - Dbus Handler
+ */
+ BIOSStringAttribute(const Json& entry, DBusHandler* const dbusHandler);
+
+ /** @brief Set Attribute value On Dbus according to the attribute value
+ * entry
+ * @param[in] attrValueEntry - The attribute value entry
+ * @param[in] attrEntry - The attribute entry corresponding to the
+ * attribute value entry
+ * @param[in] stringTable - The string table
+ */
+ void
+ setAttrValueOnDbus(const pldm_bios_attr_val_table_entry* attrValueEntry,
+ const pldm_bios_attr_table_entry* attrEntry,
+ const BIOSStringTable& stringTable) override;
+
+ /** @brief Construct corresponding entries at the end of the attribute table
+ * and attribute value tables
+ * @param[in] stringTable - The string Table
+ * @param[in,out] attrTable - The attribute table
+ * @param[in,out] attrValueTable - The attribute value table
+ */
+ void constructEntry(const BIOSStringTable& stringTable, Table& attrTable,
+ Table& attrValueTable) override;
+
+ private:
+ /** @brief string field from json */
+ table::attribute::StringField stringInfo;
+
+ /** @brief Get attribute value on dbus */
+ std::string getAttrValue();
+};
+
+} // namespace bios
+} // namespace responder
+} // namespace pldm
diff --git a/libpldmresponder/bios_table.cpp b/libpldmresponder/bios_table.cpp
index 5fd6ece..e68884b 100644
--- a/libpldmresponder/bios_table.cpp
+++ b/libpldmresponder/bios_table.cpp
@@ -64,7 +64,7 @@
{
throw std::invalid_argument("Invalid String Handle");
}
- return decodeString(stringEntry);
+ return table::string::decodeString(stringEntry);
}
uint16_t BIOSStringTable::findHandle(const std::string& name) const
@@ -76,17 +76,21 @@
throw std::invalid_argument("Invalid String Name");
}
- return decodeHandle(stringEntry);
+ return table::string::decodeHandle(stringEntry);
}
-uint16_t
- BIOSStringTable::decodeHandle(const pldm_bios_string_table_entry* entry)
+namespace table
+{
+
+namespace string
+{
+
+uint16_t decodeHandle(const pldm_bios_string_table_entry* entry)
{
return pldm_bios_table_string_entry_decode_handle(entry);
}
-std::string
- BIOSStringTable::decodeString(const pldm_bios_string_table_entry* entry)
+std::string decodeString(const pldm_bios_string_table_entry* entry)
{
auto strLength = pldm_bios_table_string_entry_decode_string_length(entry);
std::vector<char> buffer(strLength + 1 /* sizeof '\0' */);
@@ -95,6 +99,91 @@
return std::string(buffer.data(), buffer.data() + strLength);
}
+} // namespace string
+
+namespace attribute
+{
+
+TableHeader decodeHeader(const pldm_bios_attr_table_entry* entry)
+{
+ auto attrHandle = pldm_bios_table_attr_entry_decode_attribute_handle(entry);
+ auto attrType = pldm_bios_table_attr_entry_decode_attribute_type(entry);
+ auto stringHandle = pldm_bios_table_attr_entry_decode_string_handle(entry);
+ return {attrHandle, attrType, stringHandle};
+}
+
+const pldm_bios_attr_table_entry*
+ constructStringEntry(Table& table,
+ pldm_bios_table_attr_entry_string_info* info)
+{
+ auto entryLength =
+ pldm_bios_table_attr_entry_string_encode_length(info->def_length);
+
+ auto tableSize = table.size();
+ table.resize(tableSize + entryLength, 0);
+ pldm_bios_table_attr_entry_string_encode(table.data() + tableSize,
+ entryLength, info);
+ return reinterpret_cast<pldm_bios_attr_table_entry*>(table.data() +
+ tableSize);
+}
+
+StringField decodeStringEntry(const pldm_bios_attr_table_entry* entry)
+{
+ auto strType = pldm_bios_table_attr_entry_string_decode_string_type(entry);
+ auto minLength = pldm_bios_table_attr_entry_string_decode_min_length(entry);
+ auto maxLength = pldm_bios_table_attr_entry_string_decode_max_length(entry);
+ auto defLength =
+ pldm_bios_table_attr_entry_string_decode_def_string_length(entry);
+
+ std::vector<char> buffer(defLength + 1);
+ pldm_bios_table_attr_entry_string_decode_def_string(entry, buffer.data(),
+ buffer.size());
+ return {strType, minLength, maxLength, defLength,
+ std::string(buffer.data(), buffer.data() + defLength)};
+}
+
+} // namespace attribute
+
+namespace attribute_value
+{
+
+TableHeader decodeHeader(const pldm_bios_attr_val_table_entry* entry)
+{
+ auto handle =
+ pldm_bios_table_attr_value_entry_decode_attribute_handle(entry);
+ auto type = pldm_bios_table_attr_value_entry_decode_attribute_type(entry);
+ return {handle, type};
+}
+
+std::string decodeStringEntry(const pldm_bios_attr_val_table_entry* entry)
+{
+ variable_field currentString{};
+ pldm_bios_table_attr_value_entry_string_decode_string(entry,
+ ¤tString);
+ return std::string(currentString.ptr,
+ currentString.ptr + currentString.length);
+}
+
+const pldm_bios_attr_val_table_entry*
+ constructStringEntry(Table& table, uint16_t attrHandle, uint8_t attrType,
+ const std::string& str)
+{
+ auto strLen = str.size();
+ auto entryLength =
+ pldm_bios_table_attr_value_entry_encode_string_length(strLen);
+ auto tableSize = table.size();
+ table.resize(tableSize + entryLength);
+ pldm_bios_table_attr_value_entry_encode_string(
+ table.data() + tableSize, entryLength, attrHandle, attrType, strLen,
+ str.c_str());
+ return reinterpret_cast<pldm_bios_attr_val_table_entry*>(table.data() +
+ tableSize);
+}
+
+} // namespace attribute_value
+
+} // namespace table
+
} // namespace bios
} // namespace responder
} // namespace pldm
diff --git a/libpldmresponder/bios_table.hpp b/libpldmresponder/bios_table.hpp
index 7b28d49..d1dc7c9 100644
--- a/libpldmresponder/bios_table.hpp
+++ b/libpldmresponder/bios_table.hpp
@@ -7,6 +7,7 @@
#include <vector>
#include "libpldm/bios.h"
+#include "libpldm/bios_table.h"
namespace pldm
{
@@ -129,22 +130,119 @@
*/
uint16_t findHandle(const std::string& name) const override;
- /** @brief Get the string handle for the entry
- * @param[in] entry - Pointer to a bios string table entry
- * @return Handle to identify a string in the bios string table
- */
- static uint16_t decodeHandle(const pldm_bios_string_table_entry* entry);
-
- /** @brief Get the string from the entry
- * @param[in] entry - Pointer to a bios string table entry
- * @return The String
- */
- static std::string decodeString(const pldm_bios_string_table_entry* entry);
-
private:
Table stringTable;
};
+namespace table
+{
+
+namespace string
+{
+
+/** @brief Get the string handle for the entry
+ * @param[in] entry - Pointer to a bios string table entry
+ * @return Handle to identify a string in the bios string table
+ */
+uint16_t decodeHandle(const pldm_bios_string_table_entry* entry);
+
+/** @brief Get the string from the entry
+ * @param[in] entry - Pointer to a bios string table entry
+ * @return The String
+ */
+std::string decodeString(const pldm_bios_string_table_entry* entry);
+
+} // namespace string
+
+namespace attribute
+{
+
+/** @struct TableHeader
+ * @brief Header of attribute table
+ */
+struct TableHeader
+{
+ uint16_t attrHandle;
+ uint8_t attrType;
+ uint16_t stringHandle;
+};
+
+/** @brief Decode header of attribute table entry
+ * @param[in] entry - Pointer to an attribute table entry
+ * @return Attribute table header
+ */
+TableHeader decodeHeader(const pldm_bios_attr_table_entry* entry);
+
+/** @struct StringField
+ * @brief String field of attribute table
+ */
+struct StringField
+{
+ uint8_t stringType;
+ uint16_t minLength;
+ uint16_t maxLength;
+ uint16_t defLength;
+ std::string defString;
+};
+
+/** @brief decode string entry of attribute table
+ * @param[in] entry - Pointer to an attribute table entry
+ * @return String field of the entry
+ */
+StringField decodeStringEntry(const pldm_bios_attr_table_entry* entry);
+
+/** @brief construct string entry of attribute table at the end of the given
+ * table
+ * @param[in,out] table - The given table
+ * @param[in] info - string info
+ * @return pointer to the constructed entry
+ */
+const pldm_bios_attr_table_entry*
+ constructStringEntry(Table& table,
+ pldm_bios_table_attr_entry_string_info* info);
+
+} // namespace attribute
+
+namespace attribute_value
+{
+
+/** @struct TableHeader
+ * @brief Header of attribute value table
+ */
+struct TableHeader
+{
+ uint16_t attrHandle;
+ uint8_t attrType;
+};
+
+/** @brief Decode header of attribute value table
+ * @param[in] entry - Pointer to an attribute value table entry
+ * @return Attribute value table header
+ */
+TableHeader decodeHeader(const pldm_bios_attr_val_table_entry* entry);
+
+/** @brief Decode string entry of attribute value table
+ * @param[in] entry - Pointer to an attribute value table entry
+ * @return The decoded string
+ */
+std::string decodeStringEntry(const pldm_bios_attr_val_table_entry* entry);
+
+/** @brief Construct string entry of attribute value table at the end of the
+ * given table
+ * @param[in] table - The given table
+ * @param[in] attrHandle - attribute handle
+ * @param[in] attrType - attribute type
+ * @param[in] str - The string
+ * @return Pointer to the constructed entry
+ */
+const pldm_bios_attr_val_table_entry*
+ constructStringEntry(Table& table, uint16_t attrHandle, uint8_t attrType,
+ const std::string& str);
+
+} // namespace attribute_value
+
+} // namespace table
+
} // namespace bios
} // namespace responder
} // namespace pldm
diff --git a/libpldmresponder/meson.build b/libpldmresponder/meson.build
index 2797f51..372cae0 100644
--- a/libpldmresponder/meson.build
+++ b/libpldmresponder/meson.build
@@ -11,6 +11,7 @@
'bios_table.cpp',
'bios_parser.cpp',
'bios_attribute.cpp',
+ 'bios_string_attribute.cpp',
'pdr_utils.cpp',
'pdr.cpp',
'platform.cpp',
diff --git a/test/libpldmresponder_bios_string_attribute_test.cpp b/test/libpldmresponder_bios_string_attribute_test.cpp
new file mode 100644
index 0000000..747e60f
--- /dev/null
+++ b/test/libpldmresponder_bios_string_attribute_test.cpp
@@ -0,0 +1,200 @@
+#include "libpldmresponder/bios_string_attribute.hpp"
+#include "mocked_bios.hpp"
+#include "mocked_utils.hpp"
+
+#include <memory>
+#include <nlohmann/json.hpp>
+
+#include <gmock/gmock.h>
+#include <gtest/gtest.h>
+
+using namespace pldm::responder::bios;
+using ::testing::_;
+using ::testing::ElementsAreArray;
+using ::testing::Return;
+using ::testing::StrEq;
+using ::testing::Throw;
+
+class TestBIOSStringAttribute : public ::testing::Test
+{
+ public:
+ const auto& getStringInfo(const BIOSStringAttribute& biosStringAttribute)
+ {
+ return biosStringAttribute.stringInfo;
+ }
+};
+
+TEST_F(TestBIOSStringAttribute, CtorTest)
+{
+ auto jsonStringReadOnly = R"( {
+ "attribute_name" : "str_example3",
+ "string_type" : "ASCII",
+ "minimum_string_length" : 1,
+ "maximum_string_length" : 100,
+ "default_string_length" : 2,
+ "default_string" : "ef"
+ })"_json;
+ BIOSStringAttribute stringReadOnly{jsonStringReadOnly, nullptr};
+ EXPECT_EQ(stringReadOnly.name, "str_example3");
+ EXPECT_TRUE(stringReadOnly.readOnly);
+
+ auto& stringInfo = getStringInfo(stringReadOnly);
+ EXPECT_EQ(stringInfo.stringType,
+ static_cast<uint8_t>(BIOSStringAttribute::Encoding::ASCII));
+ EXPECT_EQ(stringInfo.minLength, 1);
+ EXPECT_EQ(stringInfo.maxLength, 100);
+ EXPECT_EQ(stringInfo.defLength, 2);
+ EXPECT_EQ(stringInfo.defString, "ef");
+
+ auto jsonStringReadOnlyError = R"( {
+ "attribute_name" : "str_example3",
+ "string_type" : "ASCII",
+ "minimum_string_length" : 1,
+ "maximum_string_length" : 100,
+ "default_string" : "ef"
+ })"_json; // missing default_string_length
+
+ EXPECT_THROW((BIOSStringAttribute{jsonStringReadOnlyError, nullptr}),
+ Json::exception);
+
+ auto jsonStringReadWrite = R"({
+ "attribute_name" : "str_example1",
+ "string_type" : "ASCII",
+ "minimum_string_length" : 1,
+ "maximum_string_length" : 100,
+ "default_string_length" : 3,
+ "default_string" : "abc",
+ "dbus" : {
+ "object_path" : "/xyz/abc/def",
+ "interface" : "xyz.openbmc_project.str_example1.value",
+ "property_name" : "Str_example1",
+ "property_type" : "string"
+ }
+ })"_json;
+ BIOSStringAttribute stringReadWrite{jsonStringReadWrite, nullptr};
+
+ EXPECT_EQ(stringReadWrite.name, "str_example1");
+ EXPECT_TRUE(!stringReadWrite.readOnly);
+}
+
+TEST_F(TestBIOSStringAttribute, ConstructEntry)
+{
+ MockBIOSStringTable biosStringTable;
+ MockdBusHandler dbusHandler;
+
+ auto jsonStringReadOnly = R"({
+ "attribute_name" : "str_example1",
+ "string_type" : "ASCII",
+ "minimum_string_length" : 1,
+ "maximum_string_length" : 100,
+ "default_string_length" : 3,
+ "default_string" : "abc"
+ })"_json;
+
+ std::vector<uint8_t> expectedAttrEntry{
+ 0, 0, /* attr handle */
+ 0x81, /* attr type string read-only */
+ 5, 0, /* attr name handle */
+ 1, /* string type */
+ 1, 0, /* minimum length of the string in bytes */
+ 100, 0, /* maximum length of the string in bytes */
+ 3, 0, /* length of default string in length */
+ 'a', 'b', 'c' /* default string */
+ };
+
+ std::vector<uint8_t> expectedAttrValueEntry{
+ 0, 0, /* attr handle */
+ 0x81, /* attr type string read-only */
+ 3, 0, /* current string length */
+ 'a', 'b', 'c', /* defaut value string handle index */
+ };
+
+ ON_CALL(biosStringTable, findHandle(StrEq("str_example1")))
+ .WillByDefault(Return(5));
+ BIOSStringAttribute stringReadOnly{jsonStringReadOnly, nullptr};
+
+ checkConstructEntry(stringReadOnly, biosStringTable, expectedAttrEntry,
+ expectedAttrValueEntry);
+
+ auto jsonStringReadWrite = R"({
+ "attribute_name" : "str_example1",
+ "string_type" : "ASCII",
+ "minimum_string_length" : 1,
+ "maximum_string_length" : 100,
+ "default_string_length" : 3,
+ "default_string" : "abc",
+ "dbus" : {
+ "object_path" : "/xyz/abc/def",
+ "interface" : "xyz.openbmc_project.str_example1.value",
+ "property_name" : "Str_example1",
+ "property_type" : "string"
+ }
+ })"_json;
+ BIOSStringAttribute stringReadWrite{jsonStringReadWrite, &dbusHandler};
+
+ /* Set expected attr type to read-write */
+ expectedAttrEntry[2] = PLDM_BIOS_STRING;
+ expectedAttrValueEntry[2] = PLDM_BIOS_STRING;
+
+ EXPECT_CALL(
+ dbusHandler,
+ getDbusPropertyVariant(StrEq("/xyz/abc/def"), StrEq("Str_example1"),
+ StrEq("xyz.openbmc_project.str_example1.value")))
+ .WillOnce(Throw(std::exception()));
+
+ checkConstructEntry(stringReadWrite, biosStringTable, expectedAttrEntry,
+ expectedAttrValueEntry);
+
+ EXPECT_CALL(
+ dbusHandler,
+ getDbusPropertyVariant(StrEq("/xyz/abc/def"), StrEq("Str_example1"),
+ StrEq("xyz.openbmc_project.str_example1.value")))
+ .WillOnce(Return(PropertyValue(std::string("abcd"))));
+
+ expectedAttrValueEntry = {
+ 0, 0, /* attr handle */
+ 1, /* attr type string read-write */
+ 4, 0, /* current string length */
+ 'a', 'b', 'c', 'd', /* defaut value string handle index */
+ };
+
+ checkConstructEntry(stringReadWrite, biosStringTable, expectedAttrEntry,
+ expectedAttrValueEntry);
+}
+
+TEST_F(TestBIOSStringAttribute, setAttrValueOnDbus)
+{
+ auto jsonStringReadWrite = R"({
+ "attribute_name" : "str_example1",
+ "string_type" : "ASCII",
+ "minimum_string_length" : 1,
+ "maximum_string_length" : 100,
+ "default_string_length" : 3,
+ "default_string" : "abc",
+ "dbus" : {
+ "object_path" : "/xyz/abc/def",
+ "interface" : "xyz.openbmc_project.str_example1.value",
+ "property_name" : "Str_example1",
+ "property_type" : "string"
+ }
+ })"_json;
+
+ MockdBusHandler dbusHandler;
+ MockBIOSStringTable biosStringTable;
+
+ BIOSStringAttribute stringReadWrite{jsonStringReadWrite, &dbusHandler};
+ DBusMapping dbusMapping{"/xyz/abc/def",
+ "xyz.openbmc_project.str_example1.value",
+ "Str_example1", "string"};
+ std::vector<uint8_t> attrValueEntry{
+ 0, 0, /* attr handle */
+ 1, /* attr type string read-write */
+ 4, 0, /* current string length */
+ 'a', 'b', 'c', 'd', /* defaut value string handle index */
+ };
+ auto entry = reinterpret_cast<pldm_bios_attr_val_table_entry*>(
+ attrValueEntry.data());
+ PropertyValue value = std::string("abcd");
+ EXPECT_CALL(dbusHandler, setDbusProperty(dbusMapping, value)).Times(1);
+ stringReadWrite.setAttrValueOnDbus(entry, nullptr, biosStringTable);
+}
diff --git a/test/meson.build b/test/meson.build
index a7bd88f..827f9fc 100644
--- a/test/meson.build
+++ b/test/meson.build
@@ -20,6 +20,7 @@
'libpldmresponder_base_test',
'libpldmresponder_bios_test',
'libpldmresponder_bios_attribute_test',
+ 'libpldmresponder_bios_string_attribute_test',
'libpldmresponder_pdr_state_effecter_test',
'libpldmresponder_bios_table_test',
'libpldmresponder_platform_test',
diff --git a/test/mocked_bios.hpp b/test/mocked_bios.hpp
new file mode 100644
index 0000000..eb95c33
--- /dev/null
+++ b/test/mocked_bios.hpp
@@ -0,0 +1,57 @@
+#include "libpldmresponder/bios_table.hpp"
+
+#include <gmock/gmock.h>
+#include <gtest/gtest.h>
+
+using testing::ElementsAreArray;
+using namespace pldm::responder::bios;
+
+class MockBIOSStringTable : public BIOSStringTable
+{
+ public:
+ MockBIOSStringTable() : BIOSStringTable({})
+ {
+ }
+
+ MOCK_METHOD(uint16_t, findHandle, (const std::string&), (const override));
+};
+
+void checkHeader(const Table& attrEntry, const Table& attrValueEntry)
+{
+ auto attrHeader = table::attribute::decodeHeader(
+ reinterpret_cast<const pldm_bios_attr_table_entry*>(attrEntry.data()));
+ auto attrValueHeader = table::attribute_value::decodeHeader(
+ reinterpret_cast<const pldm_bios_attr_val_table_entry*>(
+ attrValueEntry.data()));
+
+ EXPECT_EQ(attrHeader.attrHandle, attrValueHeader.attrHandle);
+}
+
+void checkEntry(Table& entry, Table& expectedEntry)
+{
+ /** backup the attr handle */
+ auto attr0 = entry[0], eAttr0 = expectedEntry[0];
+ auto attr1 = entry[1], eAttr1 = expectedEntry[1];
+
+ /** attr handle is computed by libpldm, set it to 0 to test */
+ entry[0] = 0, expectedEntry[0] = 0;
+ entry[1] = 0, expectedEntry[1] = 0;
+
+ EXPECT_THAT(entry, ElementsAreArray(expectedEntry));
+
+ /** restore the attr handle */
+ entry[0] = attr0, expectedEntry[0] = eAttr0;
+ entry[1] = attr1, expectedEntry[1] = eAttr1;
+}
+
+void checkConstructEntry(BIOSAttribute& attribute, BIOSStringTable& stringTable,
+ Table& expectedAttrEntry,
+ Table& expectedAttrValueEntry)
+{
+ Table attrEntry, attrValueEntry;
+ attribute.constructEntry(stringTable, attrEntry, attrValueEntry);
+
+ checkHeader(attrEntry, attrValueEntry);
+ checkEntry(attrEntry, expectedAttrEntry);
+ checkEntry(attrValueEntry, expectedAttrValueEntry);
+}
\ No newline at end of file
diff --git a/test/mocked_utils.hpp b/test/mocked_utils.hpp
index 39ac8bb..0813830 100644
--- a/test/mocked_utils.hpp
+++ b/test/mocked_utils.hpp
@@ -1,5 +1,3 @@
-#pragma once
-
#include "utils.hpp"
#include <gmock/gmock.h>
@@ -32,4 +30,7 @@
public:
MOCK_METHOD(void, setDbusProperty,
(const DBusMapping&, const PropertyValue&), (const override));
+
+ MOCK_METHOD(PropertyValue, getDbusPropertyVariant,
+ (const char*, const char*, const char*), (const override));
};