tests: Organize the test code to make it modular

The unit test code for libpldmresponder, host-bmc and common is
in a shared test directory. This patch separates the test code
to the respective directory.

Tested: Ran the unit test and tests passed.

Signed-off-by: Tom Joseph <rushtotom@gmail.com>
Change-Id: I31d53681fa6c0d8bc6eb7c4e3341aaff4bc341ee
diff --git a/libpldmresponder/meson.build b/libpldmresponder/meson.build
index 7e52c3d..8436e14 100644
--- a/libpldmresponder/meson.build
+++ b/libpldmresponder/meson.build
@@ -52,3 +52,7 @@
 
 libpldmresponder = declare_dependency(
   link_with: libpldmresponder)
+
+if get_option('tests').enabled()
+  subdir('test')
+endif
diff --git a/libpldmresponder/test/bios_jsons/enum_attrs.json b/libpldmresponder/test/bios_jsons/enum_attrs.json
new file mode 100644
index 0000000..bee666f
--- /dev/null
+++ b/libpldmresponder/test/bios_jsons/enum_attrs.json
@@ -0,0 +1,60 @@
+{
+   "entries":[
+      {
+         "attribute_name" : "HMCManagedState",
+         "possible_values" : [ "On", "Off" ],
+         "default_values" : [ "On" ],
+         "readOnly" : false,
+         "helpText" : "HMCManagedState HelpText",
+         "displayName" : "HMCManagedState DisplayName",
+         "dbus":
+            {
+               "object_path" : "/xyz/abc/def",
+               "interface" : "xyz.openbmc_project.HMCManaged.State",
+               "property_name" : "State",
+               "property_type" : "string",
+               "property_values" : ["xyz.openbmc_project.State.On", "xyz.openbmc_project.State.Off"]
+            }
+      },
+      {
+         "attribute_name" : "FWBootSide",
+         "possible_values" : [ "Perm", "Temp" ],
+         "default_values" : [ "Perm" ],
+         "readOnly" : false,
+         "helpText" : "FWBootSide HelpText",
+         "displayName" : "FWBootSide DisplayName",
+         "dbus":
+            {
+               "object_path" : "/xyz/abc/def",
+               "interface" : "xyz.openbmc.FWBoot.Side",
+               "property_name" : "Side",
+               "property_type" : "bool",
+               "property_values" : [true, false]
+            }
+      },
+      {
+         "attribute_name" : "InbandCodeUpdate",
+         "possible_values" : [ "Allowed", "NotAllowed" ],
+         "default_values" : [ "Allowed" ],
+         "readOnly" : false,
+         "helpText" : "InbandCodeUpdate HelpText",
+         "displayName" : "InbandCodeUpdate DisplayName",
+         "dbus":
+            {
+               "object_path" : "/xyz/abc/def",
+               "interface" : "xyz.openbmc.InBandCodeUpdate",
+               "property_name" : "Policy",
+               "property_type" : "uint8_t",
+               "property_values" : [0, 1]
+            }
+      },
+      {
+         "attribute_name" : "CodeUpdatePolicy",
+         "possible_values" : [ "Concurrent", "Disruptive" ],
+         "default_values" : [ "Concurrent" ],
+         "readOnly" : true,
+         "helpText" : "CodeUpdatePolicy HelpText",
+         "displayName" : "CodeUpdatePolicy DisplayName"
+      }
+    ]
+}
diff --git a/libpldmresponder/test/bios_jsons/integer_attrs.json b/libpldmresponder/test/bios_jsons/integer_attrs.json
new file mode 100644
index 0000000..e6833aa
--- /dev/null
+++ b/libpldmresponder/test/bios_jsons/integer_attrs.json
@@ -0,0 +1,40 @@
+{
+   "entries":[
+      {
+         "attribute_name" : "VDD_AVSBUS_RAIL",
+         "lower_bound" : 0,
+         "upper_bound" : 15,
+         "scalar_increment" : 1,
+         "default_value" : 0,
+         "readOnly" : false,
+         "helpText" : "VDD_AVSBUS_RAIL HelpText",
+         "displayName" : "VDD_AVSBUS_RAIL DisplayName",
+         "dbus":{
+            "object_path" : "/xyz/openbmc_project/avsbus",
+            "interface" : "xyz.openbmc.AvsBus.Manager",
+            "property_type" : "uint8_t",
+            "property_name" : "Rail"
+         }
+      },
+      {
+         "attribute_name" : "SBE_IMAGE_MINIMUM_VALID_ECS",
+         "lower_bound" : 1,
+         "upper_bound" : 15,
+         "scalar_increment" : 1,
+         "default_value" : 2,
+         "readOnly" : true,
+         "helpText" : "SBE_IMAGE_MINIMUM_VALID_ECS HelpText",
+         "displayName" : "SBE_IMAGE_MINIMUM_VALID_ECS DisplayName"
+      },
+      {
+         "attribute_name" : "INTEGER_INVALID_CASE",
+         "lower_bound" : 1,
+         "upper_bound" : 15,
+         "scalar_increment" : 2,
+         "default_value" : 3,
+         "readOnly" : true,
+         "helpText" : "INTEGER_INVALID_CASE HelpText",
+         "displayName" : "INTEGER_INVALID_CASE DisplayName"
+      }
+   ]
+}
diff --git a/libpldmresponder/test/bios_jsons/string_attrs.json b/libpldmresponder/test/bios_jsons/string_attrs.json
new file mode 100644
index 0000000..09e0e4c
--- /dev/null
+++ b/libpldmresponder/test/bios_jsons/string_attrs.json
@@ -0,0 +1,49 @@
+{
+    "entries" : [
+        {
+            "attribute_name" : "str_example1",
+            "string_type" : "ASCII",
+            "minimum_string_length" : 1,
+            "maximum_string_length" : 100,
+            "default_string_length" : 3,
+            "default_string" : "abc",
+            "readOnly" : false,
+            "helpText" : "str_example1 HelpText",
+            "displayName" : "str_example1 DisplayName",
+            "dbus" : {
+                "object_path" : "/xyz/abc/def",
+                "interface" : "xyz.openbmc_project.str_example1.value",
+                "property_name" : "Str_example1",
+                "property_type" : "string"
+            }
+        },
+        {
+            "attribute_name" : "str_example2",
+            "string_type" : "Hex",
+            "minimum_string_length" : 0,
+            "maximum_string_length" : 100,
+            "default_string_length" : 0,
+            "default_string" : "",
+            "readOnly" : false,
+            "helpText" : "str_example2 HelpText",
+            "displayName" : "str_example2 DisplayName",
+            "dbus" : {
+                "object_path" : "/xyz/abc/def",
+                "interface" : "xyz.openbmc_project.str_example2.value",
+                "property_name" : "Str_example2",
+                "property_type" : "string"
+            }
+        },
+        {
+            "attribute_name" : "str_example3",
+            "string_type" : "Unknown",
+            "minimum_string_length" : 1,
+            "maximum_string_length" : 100,
+            "default_string_length" : 2,
+            "default_string" : "ef",
+            "readOnly" : true,
+            "helpText" : "str_example3 HelpText",
+            "displayName" : "str_example3 DisplayName"
+        }
+    ]
+}
diff --git a/libpldmresponder/test/event_jsons/good/event_state_sensor.json b/libpldmresponder/test/event_jsons/good/event_state_sensor.json
new file mode 100644
index 0000000..f10a319
--- /dev/null
+++ b/libpldmresponder/test/event_jsons/good/event_state_sensor.json
@@ -0,0 +1,66 @@
+{

+    "entries": [

+        {

+            "containerID": 1,

+            "entityType": 64,

+            "entityInstance": 1,

+            "sensorOffset": 0,

+            "event_states": [

+                0,

+                1,

+                2

+            ],

+            "dbus": {

+                "object_path": "/xyz/abc/def",

+                "interface": "xyz.openbmc_project.example1.value",

+                "property_name": "value1",

+                "property_type": "string",

+                "property_values": [

+                    "xyz.openbmc_project.State.Normal",

+                    "xyz.openbmc_project.State.Critical",

+                    "xyz.openbmc_project.State.Fatal"

+                ]

+            }

+        },

+        {

+            "containerID": 1,

+            "entityType": 64,

+            "entityInstance": 1,

+            "sensorOffset": 1,

+            "event_states": [

+                2,

+                3

+            ],

+            "dbus": {

+                "object_path": "/xyz/abc/def",

+                "interface": "xyz.openbmc_project.example2.value",

+                "property_name": "value2",

+                "property_type": "uint8_t",

+                "property_values": [

+                    9,

+                    10

+                ]

+            }

+        },

+        {

+            "containerID": 2,

+            "entityType": 67,

+            "entityInstance": 2,

+            "sensorOffset": 0,

+            "event_states": [

+                0,

+                1

+            ],

+            "dbus": {

+                "object_path": "/xyz/abc/ghi",

+                "interface": "xyz.openbmc_project.example3.value",

+                "property_name": "value3",

+                "property_type": "bool",

+                "property_values": [

+                    false,

+                    true

+                ]

+            }

+        }

+    ]

+}

diff --git a/libpldmresponder/test/files/NVRAM-IMAGE b/libpldmresponder/test/files/NVRAM-IMAGE
new file mode 100644
index 0000000..06d7405
--- /dev/null
+++ b/libpldmresponder/test/files/NVRAM-IMAGE
Binary files differ
diff --git a/libpldmresponder/test/files/NVRAM-IMAGE-CKSUM b/libpldmresponder/test/files/NVRAM-IMAGE-CKSUM
new file mode 100644
index 0000000..01d633b
--- /dev/null
+++ b/libpldmresponder/test/files/NVRAM-IMAGE-CKSUM
Binary files differ
diff --git a/libpldmresponder/test/fru_jsons/good/Board_General.json b/libpldmresponder/test/fru_jsons/good/Board_General.json
new file mode 100644
index 0000000..d4efdab
--- /dev/null
+++ b/libpldmresponder/test/fru_jsons/good/Board_General.json
@@ -0,0 +1,29 @@
+{
+   "record_details":
+   {
+        "fru_record_type" : 1,
+        "fru_encoding_type": 1,
+        "dbus_interface_name": "xyz.openbmc_project.Inventory.Item.Board"
+   },
+   "fru_fields":[
+      {
+         "fru_field_type" : 3,
+         "dbus":
+            {
+               "interface" : "xyz.openbmc_project.Inventory.Decorator.Asset",
+               "property_name" : "PartNumber",
+               "property_type" : "string"
+            }
+      },
+      {
+         "fru_field_type" : 4,
+         "dbus":
+            {
+               "interface" : "xyz.openbmc_project.Inventory.Decorator.Asset",
+               "property_name" : "SerialNumber",
+               "property_type" : "string"
+            }
+      }
+    ]
+}
+
diff --git a/libpldmresponder/test/fru_jsons/good/Board_VINI.json b/libpldmresponder/test/fru_jsons/good/Board_VINI.json
new file mode 100644
index 0000000..1ef87ef
--- /dev/null
+++ b/libpldmresponder/test/fru_jsons/good/Board_VINI.json
@@ -0,0 +1,30 @@
+{
+   "record_details":
+   {
+        "fru_record_type" : 254,
+        "fru_encoding_type": 1,
+        "dbus_interface_name": "xyz.openbmc_project.Inventory.Item.Board"
+   },
+   "fru_fields":[
+      {
+         "fru_field_type" : 2,
+         "dbus":
+            {
+               "interface" : "com.ibm.ipzvpd.VINI",
+               "property_name" : "RT",
+               "property_type" : "string"
+            }
+      },
+      {
+         "fru_field_type" : 3,
+         "dbus":
+            {
+               "interface" : "com.ibm.ipzvpd.VINI",
+               "property_name" : "B3",
+               "property_type" : "bytearray"
+            }
+      }
+
+    ]
+}
+
diff --git a/libpldmresponder/test/fru_jsons/good/Cpu_General.json b/libpldmresponder/test/fru_jsons/good/Cpu_General.json
new file mode 100644
index 0000000..01a378a
--- /dev/null
+++ b/libpldmresponder/test/fru_jsons/good/Cpu_General.json
@@ -0,0 +1,28 @@
+{
+   "record_details":
+   {
+        "fru_record_type" : 1,
+        "fru_encoding_type": 1,
+        "dbus_interface_name": "xyz.openbmc_project.Inventory.Item.Cpu"
+   },
+   "fru_fields":[
+      {
+         "fru_field_type" : 3,
+         "dbus":
+            {
+               "interface" : "xyz.openbmc_project.Inventory.Decorator.Asset",
+               "property_name" : "PartNumber",
+               "property_type" : "string"
+            }
+      },
+      {
+         "fru_field_type" : 4,
+         "dbus":
+            {
+               "interface" : "xyz.openbmc_project.Inventory.Decorator.Asset",
+               "property_name" : "SerialNumber",
+               "property_type" : "string"
+            }
+      }
+    ]
+}
diff --git a/libpldmresponder/test/fru_jsons/good/FRU_Master.json b/libpldmresponder/test/fru_jsons/good/FRU_Master.json
new file mode 100644
index 0000000..fa2c405
--- /dev/null
+++ b/libpldmresponder/test/fru_jsons/good/FRU_Master.json
@@ -0,0 +1,14 @@
+{
+    "service":"xyz.openbmc_project.Inventory.Manager",
+    "root_path":"/xyz/openbmc_project/inventory/system/",
+    "entities":[
+        {
+            "interface" : "xyz.openbmc_project.Inventory.Item.Board",
+            "entity_type" : 64
+        },
+        {
+            "interface" : "xyz.openbmc_project.Inventory.Item.Cpu",
+            "entity_type" : 135
+        }
+    ]
+}
diff --git a/libpldmresponder/test/libpldmresponder_base_test.cpp b/libpldmresponder/test/libpldmresponder_base_test.cpp
new file mode 100644
index 0000000..ac6e681
--- /dev/null
+++ b/libpldmresponder/test/libpldmresponder_base_test.cpp
@@ -0,0 +1,140 @@
+#include "libpldm/base.h"
+
+#include "libpldmresponder/base.hpp"
+
+#include <string.h>
+
+#include <array>
+
+#include <gtest/gtest.h>
+
+using namespace pldm::responder;
+
+TEST(GetPLDMTypes, testGoodRequest)
+{
+    std::array<uint8_t, sizeof(pldm_msg_hdr)> requestPayload{};
+    auto request = reinterpret_cast<pldm_msg*>(requestPayload.data());
+    // payload length will be 0 in this case
+    size_t requestPayloadLength = 0;
+    base::Handler handler;
+    auto response = handler.getPLDMTypes(request, requestPayloadLength);
+    // Need to support OEM type.
+    auto responsePtr = reinterpret_cast<pldm_msg*>(response.data());
+    uint8_t* payload_ptr = responsePtr->payload;
+    ASSERT_EQ(payload_ptr[0], 0);
+    ASSERT_EQ(payload_ptr[1], 29); // 0b11101 see DSP0240 table11
+    ASSERT_EQ(payload_ptr[2], 0);
+}
+
+TEST(GetPLDMCommands, testGoodRequest)
+{
+    // Need to support OEM type commands.
+    std::array<uint8_t, sizeof(pldm_msg_hdr) + PLDM_GET_COMMANDS_REQ_BYTES>
+        requestPayload{};
+    auto request = reinterpret_cast<pldm_msg*>(requestPayload.data());
+    size_t requestPayloadLength = requestPayload.size() - sizeof(pldm_msg_hdr);
+    base::Handler handler;
+    auto response = handler.getPLDMCommands(request, requestPayloadLength);
+    auto responsePtr = reinterpret_cast<pldm_msg*>(response.data());
+    uint8_t* payload_ptr = responsePtr->payload;
+    ASSERT_EQ(payload_ptr[0], 0);
+    ASSERT_EQ(payload_ptr[1], 60); // 60 = 0b111100
+    ASSERT_EQ(payload_ptr[2], 0);
+}
+
+TEST(GetPLDMCommands, testBadRequest)
+{
+    std::array<uint8_t, sizeof(pldm_msg_hdr) + PLDM_GET_COMMANDS_REQ_BYTES>
+        requestPayload{};
+    auto request = reinterpret_cast<pldm_msg*>(requestPayload.data());
+
+    request->payload[0] = 0xFF;
+    size_t requestPayloadLength = requestPayload.size() - sizeof(pldm_msg_hdr);
+    base::Handler handler;
+    auto response = handler.getPLDMCommands(request, requestPayloadLength);
+    auto responsePtr = reinterpret_cast<pldm_msg*>(response.data());
+    uint8_t* payload_ptr = responsePtr->payload;
+    ASSERT_EQ(payload_ptr[0], PLDM_ERROR_INVALID_PLDM_TYPE);
+}
+TEST(GetPLDMVersion, testGoodRequest)
+{
+    std::array<uint8_t, sizeof(pldm_msg_hdr) + PLDM_GET_VERSION_REQ_BYTES>
+        requestPayload{};
+    auto request = reinterpret_cast<pldm_msg*>(requestPayload.data());
+    size_t requestPayloadLength = requestPayload.size() - sizeof(pldm_msg_hdr);
+
+    uint8_t pldmType = PLDM_BASE;
+    uint32_t transferHandle = 0x0;
+    uint8_t flag = PLDM_GET_FIRSTPART;
+    uint8_t retFlag = PLDM_START_AND_END;
+    ver32_t version = {0xF1, 0xF0, 0xF0, 0x00};
+
+    auto rc =
+        encode_get_version_req(0, transferHandle, flag, pldmType, request);
+
+    ASSERT_EQ(0, rc);
+
+    base::Handler handler;
+    auto response = handler.getPLDMVersion(request, requestPayloadLength);
+    auto responsePtr = reinterpret_cast<pldm_msg*>(response.data());
+
+    ASSERT_EQ(responsePtr->payload[0], 0);
+    ASSERT_EQ(0, memcmp(responsePtr->payload + sizeof(responsePtr->payload[0]),
+                        &transferHandle, sizeof(transferHandle)));
+    ASSERT_EQ(0, memcmp(responsePtr->payload + sizeof(responsePtr->payload[0]) +
+                            sizeof(transferHandle),
+                        &retFlag, sizeof(flag)));
+    ASSERT_EQ(0, memcmp(responsePtr->payload + sizeof(responsePtr->payload[0]) +
+                            sizeof(transferHandle) + sizeof(flag),
+                        &version, sizeof(version)));
+}
+TEST(GetPLDMVersion, testBadRequest)
+{
+    std::array<uint8_t, sizeof(pldm_msg_hdr) + PLDM_GET_VERSION_REQ_BYTES>
+        requestPayload{};
+    auto request = reinterpret_cast<pldm_msg*>(requestPayload.data());
+    size_t requestPayloadLength = requestPayload.size() - sizeof(pldm_msg_hdr);
+
+    uint8_t pldmType = 7;
+    uint32_t transferHandle = 0x0;
+    uint8_t flag = PLDM_GET_FIRSTPART;
+
+    auto rc =
+        encode_get_version_req(0, transferHandle, flag, pldmType, request);
+
+    ASSERT_EQ(0, rc);
+
+    base::Handler handler;
+    auto response = handler.getPLDMVersion(request, requestPayloadLength - 1);
+    auto responsePtr = reinterpret_cast<pldm_msg*>(response.data());
+
+    ASSERT_EQ(responsePtr->payload[0], PLDM_ERROR_INVALID_LENGTH);
+
+    request = reinterpret_cast<pldm_msg*>(requestPayload.data());
+    requestPayloadLength = requestPayload.size() - sizeof(pldm_msg_hdr);
+
+    rc = encode_get_version_req(0, transferHandle, flag, pldmType, request);
+
+    ASSERT_EQ(0, rc);
+
+    response = handler.getPLDMVersion(request, requestPayloadLength);
+    responsePtr = reinterpret_cast<pldm_msg*>(response.data());
+
+    ASSERT_EQ(responsePtr->payload[0], PLDM_ERROR_INVALID_PLDM_TYPE);
+}
+
+TEST(GetTID, testGoodRequest)
+{
+    std::array<uint8_t, sizeof(pldm_msg_hdr)> requestPayload{};
+    auto request = reinterpret_cast<pldm_msg*>(requestPayload.data());
+    size_t requestPayloadLength = 0;
+
+    base::Handler handler;
+    auto response = handler.getTID(request, requestPayloadLength);
+
+    auto responsePtr = reinterpret_cast<pldm_msg*>(response.data());
+    uint8_t* payload = responsePtr->payload;
+
+    ASSERT_EQ(payload[0], 0);
+    ASSERT_EQ(payload[1], 1);
+}
diff --git a/libpldmresponder/test/libpldmresponder_bios_attribute_test.cpp b/libpldmresponder/test/libpldmresponder_bios_attribute_test.cpp
new file mode 100644
index 0000000..f7b9d50
--- /dev/null
+++ b/libpldmresponder/test/libpldmresponder_bios_attribute_test.cpp
@@ -0,0 +1,99 @@
+#include "libpldmresponder/bios_attribute.hpp"
+
+#include <nlohmann/json.hpp>
+
+#include <gtest/gtest.h>
+
+using namespace pldm::responder::bios;
+
+class TestAttribute : public BIOSAttribute
+{
+  public:
+    TestAttribute(const Json& entry, DBusHandler* const dbusHandler) :
+        BIOSAttribute(entry, dbusHandler)
+    {}
+
+    void setAttrValueOnDbus(const pldm_bios_attr_val_table_entry*,
+                            const pldm_bios_attr_table_entry*,
+                            const BIOSStringTable&) override
+    {}
+
+    void constructEntry(
+        const BIOSStringTable&, Table&, Table&,
+        std::optional<std::variant<int64_t, std::string>>) override
+    {}
+
+    const std::optional<DBusMapping>& getDbusMap()
+    {
+        return dBusMap;
+    }
+
+    int updateAttrVal(Table& /*newValue*/, uint16_t /*attrHdl*/,
+                      uint8_t /*attrType*/,
+                      const PropertyValue& /*newPropVal*/) override
+    {
+        return PLDM_SUCCESS;
+    }
+
+    void generateAttributeEntry(
+        const std::variant<int64_t, std::string>& /*attributevalue*/,
+        Table& /*attrValueEntry*/)
+    {}
+};
+
+TEST(BIOSAttribute, CtorTest)
+{
+    auto jsonReadOnly = R"({
+      "attribute_name" : "ReadOnly",
+      "readOnly" : true,
+      "helpText" : "HelpText",
+      "displayName" : "DisplayName"
+    })"_json;
+
+    TestAttribute readOnly{jsonReadOnly, nullptr};
+    EXPECT_EQ(readOnly.name, "ReadOnly");
+    EXPECT_EQ(readOnly.readOnly, true);
+
+    auto jsonReadOnlyError = R"({
+      "attribute_nam":"ReadOnly"
+    })"_json;
+    using Json = nlohmann::json;
+
+    EXPECT_THROW((TestAttribute{jsonReadOnlyError, nullptr}), Json::exception);
+
+    auto jsonReadWrite = R"({
+      "attribute_name":"ReadWrite",
+      "readOnly" : false,
+      "helpText" : "HelpText",
+      "displayName" : "DisplayName",
+      "dbus":
+           {
+               "object_path" : "/xyz/abc/def",
+               "interface" : "xyz.openbmc.FWBoot.Side",
+               "property_name" : "Side",
+               "property_type" : "bool"
+           }
+    })"_json;
+
+    TestAttribute readWrite{jsonReadWrite, nullptr};
+    EXPECT_EQ(readWrite.name, "ReadWrite");
+    EXPECT_EQ(readWrite.readOnly, false);
+    auto dbusMap = readWrite.getDbusMap();
+    EXPECT_NE(dbusMap, std::nullopt);
+    EXPECT_EQ(dbusMap->objectPath, "/xyz/abc/def");
+    EXPECT_EQ(dbusMap->interface, "xyz.openbmc.FWBoot.Side");
+    EXPECT_EQ(dbusMap->propertyName, "Side");
+    EXPECT_EQ(dbusMap->propertyType, "bool");
+
+    auto jsonReadWriteError = R"({
+      "attribute_name":"ReadWrite",
+      "dbus":
+           {
+               "object_path" : "/xyz/abc/def",
+               "interface" : "xyz.openbmc.FWBoot.Side",
+               "property_name" : "Side"
+           }
+    })"_json; // missing property_type.
+
+    EXPECT_THROW((TestAttribute{jsonReadWriteError, nullptr}), Json::exception);
+}
diff --git a/libpldmresponder/test/libpldmresponder_bios_config_test.cpp b/libpldmresponder/test/libpldmresponder_bios_config_test.cpp
new file mode 100644
index 0000000..25300ca
--- /dev/null
+++ b/libpldmresponder/test/libpldmresponder_bios_config_test.cpp
@@ -0,0 +1,318 @@
+#include "common/bios_utils.hpp"
+#include "common/test/mocked_utils.hpp"
+#include "libpldmresponder/bios_config.hpp"
+#include "libpldmresponder/bios_string_attribute.hpp"
+#include "mocked_bios.hpp"
+
+#include <nlohmann/json.hpp>
+
+#include <fstream>
+#include <memory>
+
+#include <gmock/gmock.h>
+#include <gtest/gtest.h>
+
+using namespace pldm::bios::utils;
+
+using ::testing::_;
+using ::testing::ElementsAreArray;
+using ::testing::Throw;
+
+class TestBIOSConfig : public ::testing::Test
+{
+  public:
+    static void SetUpTestCase() // will execute once at the begining of all
+                                // TestBIOSConfig objects
+    {
+        char tmpdir[] = "/tmp/BIOSTables.XXXXXX";
+        tableDir = fs::path(mkdtemp(tmpdir));
+
+        std::vector<fs::path> paths = {
+            "./bios_jsons/string_attrs.json",
+            "./bios_jsons/integer_attrs.json",
+            "./bios_jsons/enum_attrs.json",
+        };
+
+        for (auto& path : paths)
+        {
+            std::ifstream file;
+            file.open(path);
+            auto j = Json::parse(file);
+            jsons.emplace_back(j);
+        }
+    }
+
+    std::optional<Json> findJsonEntry(const std::string& name)
+    {
+        for (auto& json : jsons)
+        {
+            auto entries = json.at("entries");
+            for (auto& entry : entries)
+            {
+                auto n = entry.at("attribute_name").get<std::string>();
+                if (n == name)
+                {
+                    return entry;
+                }
+            }
+        }
+        return std::nullopt;
+    }
+
+    static void TearDownTestCase() // will be executed once at th end of all
+                                   // TestBIOSConfig objects
+    {
+        fs::remove_all(tableDir);
+    }
+
+    static fs::path tableDir;
+    static std::vector<Json> jsons;
+};
+
+fs::path TestBIOSConfig::tableDir;
+std::vector<Json> TestBIOSConfig::jsons;
+
+TEST_F(TestBIOSConfig, buildTablesTest)
+{
+    MockdBusHandler dbusHandler;
+
+    ON_CALL(dbusHandler, getDbusPropertyVariant(_, _, _))
+        .WillByDefault(Throw(std::exception()));
+
+    BIOSConfig biosConfig("./bios_jsons", tableDir.c_str(), &dbusHandler, 0, 0,
+                          nullptr);
+    biosConfig.buildTables();
+
+    auto stringTable = biosConfig.getBIOSTable(PLDM_BIOS_STRING_TABLE);
+    auto attrTable = biosConfig.getBIOSTable(PLDM_BIOS_ATTR_TABLE);
+    auto attrValueTable = biosConfig.getBIOSTable(PLDM_BIOS_ATTR_VAL_TABLE);
+
+    EXPECT_TRUE(stringTable);
+    EXPECT_TRUE(attrTable);
+    EXPECT_TRUE(attrValueTable);
+
+    std::set<std::string> expectedStrings = {"HMCManagedState",
+                                             "On",
+                                             "Off",
+                                             "FWBootSide",
+                                             "Perm",
+                                             "Temp",
+                                             "InbandCodeUpdate",
+                                             "Allowed",
+                                             "NotAllowed",
+                                             "CodeUpdatePolicy",
+                                             "Concurrent",
+                                             "Disruptive",
+                                             "VDD_AVSBUS_RAIL",
+                                             "SBE_IMAGE_MINIMUM_VALID_ECS",
+                                             "INTEGER_INVALID_CASE",
+                                             "str_example1",
+                                             "str_example2",
+                                             "str_example3"};
+    std::set<std::string> strings;
+    for (auto entry : BIOSTableIter<PLDM_BIOS_STRING_TABLE>(
+             stringTable->data(), stringTable->size()))
+    {
+        auto str = table::string::decodeString(entry);
+        strings.emplace(str);
+    }
+
+    EXPECT_EQ(strings, expectedStrings);
+
+    BIOSStringTable biosStringTable(*stringTable);
+
+    for (auto entry : BIOSTableIter<PLDM_BIOS_ATTR_TABLE>(attrTable->data(),
+                                                          attrTable->size()))
+    {
+        auto header = table::attribute::decodeHeader(entry);
+        auto attrName = biosStringTable.findString(header.stringHandle);
+        auto jsonEntry = findJsonEntry(attrName);
+        EXPECT_TRUE(jsonEntry);
+        switch (header.attrType)
+        {
+            case PLDM_BIOS_STRING:
+            case PLDM_BIOS_STRING_READ_ONLY:
+            {
+                auto stringField = table::attribute::decodeStringEntry(entry);
+                auto stringType = BIOSStringAttribute::strTypeMap.at(
+                    jsonEntry->at("string_type").get<std::string>());
+                EXPECT_EQ(stringField.stringType,
+                          static_cast<uint8_t>(stringType));
+
+                EXPECT_EQ(
+                    stringField.minLength,
+                    jsonEntry->at("minimum_string_length").get<uint16_t>());
+                EXPECT_EQ(
+                    stringField.maxLength,
+                    jsonEntry->at("maximum_string_length").get<uint16_t>());
+                EXPECT_EQ(
+                    stringField.defLength,
+                    jsonEntry->at("default_string_length").get<uint16_t>());
+                EXPECT_EQ(stringField.defString,
+                          jsonEntry->at("default_string").get<std::string>());
+                break;
+            }
+            case PLDM_BIOS_INTEGER:
+            case PLDM_BIOS_INTEGER_READ_ONLY:
+            {
+                auto integerField = table::attribute::decodeIntegerEntry(entry);
+                EXPECT_EQ(integerField.lowerBound,
+                          jsonEntry->at("lower_bound").get<uint64_t>());
+                EXPECT_EQ(integerField.upperBound,
+                          jsonEntry->at("upper_bound").get<uint64_t>());
+                EXPECT_EQ(integerField.scalarIncrement,
+                          jsonEntry->at("scalar_increment").get<uint32_t>());
+                EXPECT_EQ(integerField.defaultValue,
+                          jsonEntry->at("default_value").get<uint64_t>());
+                break;
+            }
+            case PLDM_BIOS_ENUMERATION:
+            case PLDM_BIOS_ENUMERATION_READ_ONLY:
+            {
+                auto [pvHdls, defInds] =
+                    table::attribute::decodeEnumEntry(entry);
+                auto possibleValues = jsonEntry->at("possible_values")
+                                          .get<std::vector<std::string>>();
+                std::vector<std::string> strings;
+                for (auto pv : pvHdls)
+                {
+                    auto s = biosStringTable.findString(pv);
+                    strings.emplace_back(s);
+                }
+                EXPECT_EQ(strings, possibleValues);
+                EXPECT_EQ(defInds.size(), 1);
+
+                auto defValue = biosStringTable.findString(pvHdls[defInds[0]]);
+                auto defaultValues = jsonEntry->at("default_values")
+                                         .get<std::vector<std::string>>();
+                EXPECT_EQ(defValue, defaultValues[0]);
+
+                break;
+            }
+            default:
+                EXPECT_TRUE(false);
+                break;
+        }
+    }
+
+    for (auto entry : BIOSTableIter<PLDM_BIOS_ATTR_VAL_TABLE>(
+             attrValueTable->data(), attrValueTable->size()))
+    {
+        auto header = table::attribute_value::decodeHeader(entry);
+        auto attrEntry =
+            table::attribute::findByHandle(*attrTable, header.attrHandle);
+        auto attrHeader = table::attribute::decodeHeader(attrEntry);
+        auto attrName = biosStringTable.findString(attrHeader.stringHandle);
+        auto jsonEntry = findJsonEntry(attrName);
+        EXPECT_TRUE(jsonEntry);
+        switch (header.attrType)
+        {
+            case PLDM_BIOS_STRING:
+            case PLDM_BIOS_STRING_READ_ONLY:
+            {
+                auto value = table::attribute_value::decodeStringEntry(entry);
+                auto defValue =
+                    jsonEntry->at("default_string").get<std::string>();
+                EXPECT_EQ(value, defValue);
+                break;
+            }
+            case PLDM_BIOS_INTEGER:
+            case PLDM_BIOS_INTEGER_READ_ONLY:
+            {
+                auto value = table::attribute_value::decodeIntegerEntry(entry);
+                auto defValue = jsonEntry->at("default_value").get<uint64_t>();
+                EXPECT_EQ(value, defValue);
+                break;
+            }
+            case PLDM_BIOS_ENUMERATION:
+            case PLDM_BIOS_ENUMERATION_READ_ONLY:
+            {
+                auto indices = table::attribute_value::decodeEnumEntry(entry);
+                EXPECT_EQ(indices.size(), 1);
+                auto possibleValues = jsonEntry->at("possible_values")
+                                          .get<std::vector<std::string>>();
+
+                auto defValues = jsonEntry->at("default_values")
+                                     .get<std::vector<std::string>>();
+                EXPECT_EQ(possibleValues[indices[0]], defValues[0]);
+                break;
+            }
+            default:
+                EXPECT_TRUE(false);
+                break;
+        }
+    }
+}
+
+TEST_F(TestBIOSConfig, setAttrValue)
+{
+    MockdBusHandler dbusHandler;
+
+    BIOSConfig biosConfig("./bios_jsons", tableDir.c_str(), &dbusHandler, 0, 0,
+                          nullptr);
+    biosConfig.removeTables();
+    biosConfig.buildTables();
+
+    auto stringTable = biosConfig.getBIOSTable(PLDM_BIOS_STRING_TABLE);
+    auto attrTable = biosConfig.getBIOSTable(PLDM_BIOS_ATTR_TABLE);
+
+    BIOSStringTable biosStringTable(*stringTable);
+    BIOSTableIter<PLDM_BIOS_ATTR_TABLE> attrTableIter(attrTable->data(),
+                                                      attrTable->size());
+    auto stringHandle = biosStringTable.findHandle("str_example1");
+    uint16_t attrHandle{};
+
+    for (auto entry : BIOSTableIter<PLDM_BIOS_ATTR_TABLE>(attrTable->data(),
+                                                          attrTable->size()))
+    {
+        auto header = table::attribute::decodeHeader(entry);
+        if (header.stringHandle == stringHandle)
+        {
+            attrHandle = header.attrHandle;
+            break;
+        }
+    }
+
+    EXPECT_NE(attrHandle, 0);
+
+    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 */
+    };
+
+    attrValueEntry[0] = attrHandle & 0xff;
+    attrValueEntry[1] = (attrHandle >> 8) & 0xff;
+
+    DBusMapping dbusMapping{"/xyz/abc/def",
+                            "xyz.openbmc_project.str_example1.value",
+                            "Str_example1", "string"};
+    PropertyValue value = std::string("abcd");
+    EXPECT_CALL(dbusHandler, setDbusProperty(dbusMapping, value)).Times(1);
+
+    auto rc =
+        biosConfig.setAttrValue(attrValueEntry.data(), attrValueEntry.size());
+    EXPECT_EQ(rc, PLDM_SUCCESS);
+
+    auto attrValueTable = biosConfig.getBIOSTable(PLDM_BIOS_ATTR_VAL_TABLE);
+    auto findEntry =
+        [&attrValueTable](
+            uint16_t handle) -> const pldm_bios_attr_val_table_entry* {
+        for (auto entry : BIOSTableIter<PLDM_BIOS_ATTR_VAL_TABLE>(
+                 attrValueTable->data(), attrValueTable->size()))
+        {
+            auto [attrHandle, _] = table::attribute_value::decodeHeader(entry);
+            if (attrHandle == handle)
+                return entry;
+        }
+        return nullptr;
+    };
+
+    auto entry = findEntry(attrHandle);
+    EXPECT_NE(entry, nullptr);
+
+    auto p = reinterpret_cast<const uint8_t*>(entry);
+    EXPECT_THAT(std::vector<uint8_t>(p, p + attrValueEntry.size()),
+                ElementsAreArray(attrValueEntry));
+}
diff --git a/libpldmresponder/test/libpldmresponder_bios_enum_attribute_test.cpp b/libpldmresponder/test/libpldmresponder_bios_enum_attribute_test.cpp
new file mode 100644
index 0000000..08d960d
--- /dev/null
+++ b/libpldmresponder/test/libpldmresponder_bios_enum_attribute_test.cpp
@@ -0,0 +1,231 @@
+#include "common/test/mocked_utils.hpp"
+#include "libpldmresponder/bios_enum_attribute.hpp"
+#include "mocked_bios.hpp"
+
+#include <nlohmann/json.hpp>
+
+#include <memory>
+
+#include <gmock/gmock.h>
+#include <gtest/gtest.h>
+
+using ::testing::_;
+using ::testing::ElementsAreArray;
+using ::testing::Return;
+using ::testing::StrEq;
+using ::testing::Throw;
+
+class TestBIOSEnumAttribute : public ::testing::Test
+{
+  public:
+    const auto& getPossibleValues(const BIOSEnumAttribute& attribute)
+    {
+        return attribute.possibleValues;
+    }
+
+    const auto& getDefaultValue(const BIOSEnumAttribute& attribute)
+    {
+        return attribute.defaultValue;
+    }
+};
+
+TEST_F(TestBIOSEnumAttribute, CtorTest)
+{
+    auto jsonEnumReadOnly = R"({
+         "attribute_name" : "CodeUpdatePolicy",
+         "possible_values" : [ "Concurrent", "Disruptive" ],
+         "default_values" : [ "Concurrent" ],
+         "readOnly" : true,
+         "helpText" : "HelpText",
+         "displayName" : "DisplayName"
+      })"_json;
+
+    BIOSEnumAttribute enumReadOnly{jsonEnumReadOnly, nullptr};
+    EXPECT_EQ(enumReadOnly.name, "CodeUpdatePolicy");
+    EXPECT_TRUE(enumReadOnly.readOnly);
+    EXPECT_THAT(getPossibleValues(enumReadOnly),
+                ElementsAreArray({"Concurrent", "Disruptive"}));
+    EXPECT_EQ(getDefaultValue(enumReadOnly), "Concurrent");
+
+    auto jsonEnumReadOnlyError = R"({
+         "attribute_name" : "CodeUpdatePolicy",
+         "possible_value" : [ "Concurrent", "Disruptive" ],
+         "default_values" : [ "Concurrent" ],
+         "readOnly" : true,
+         "helpText" : "HelpText",
+         "displayName" : "DisplayName"
+      })"_json; // possible_value -> possible_values
+    EXPECT_THROW((BIOSEnumAttribute{jsonEnumReadOnlyError, nullptr}),
+                 Json::exception);
+
+    auto jsonEnumReadWrite = R"({
+         "attribute_name" : "FWBootSide",
+         "possible_values" : [ "Perm", "Temp" ],
+         "default_values" : [ "Perm" ],
+         "readOnly" : false,
+         "helpText" : "HelpText",
+         "displayName" : "DisplayName",
+         "dbus":
+            {
+               "object_path" : "/xyz/abc/def",
+               "interface" : "xyz.openbmc.FWBoot.Side",
+               "property_name" : "Side",
+               "property_type" : "bool",
+               "property_values" : [true, false]
+            }
+      })"_json;
+
+    BIOSEnumAttribute enumReadWrite{jsonEnumReadWrite, nullptr};
+    EXPECT_EQ(enumReadWrite.name, "FWBootSide");
+    EXPECT_TRUE(!enumReadWrite.readOnly);
+}
+
+TEST_F(TestBIOSEnumAttribute, ConstructEntry)
+{
+    MockBIOSStringTable biosStringTable;
+    MockdBusHandler dbusHandler;
+
+    auto jsonEnumReadOnly = R"({
+         "attribute_name" : "CodeUpdatePolicy",
+         "possible_values" : [ "Concurrent", "Disruptive" ],
+         "default_values" : [ "Disruptive" ],
+         "readOnly" : true,
+         "helpText" : "HelpText",
+         "displayName" : "DisplayName"
+      })"_json;
+
+    std::vector<uint8_t> expectedAttrEntry{
+        0,    0, /* attr handle */
+        0x80,    /* attr type enum read-only*/
+        4,    0, /* attr name handle */
+        2,       /* number of possible value */
+        2,    0, /* possible value handle */
+        3,    0, /* possible value handle */
+        1,       /* number of default value */
+        1        /* defaut value string handle index */
+    };
+
+    std::vector<uint8_t> expectedAttrValueEntry{
+        0, 0, /* attr handle */
+        0x80, /* attr type enum read-only*/
+        1,    /* number of current value */
+        1     /* current value string handle index */
+    };
+
+    BIOSEnumAttribute enumReadOnly{jsonEnumReadOnly, nullptr};
+
+    ON_CALL(biosStringTable, findHandle(StrEq("Concurrent")))
+        .WillByDefault(Return(2));
+    ON_CALL(biosStringTable, findHandle(StrEq("Disruptive")))
+        .WillByDefault(Return(3));
+    ON_CALL(biosStringTable, findHandle(StrEq("CodeUpdatePolicy")))
+        .WillByDefault(Return(4));
+
+    checkConstructEntry(enumReadOnly, biosStringTable, expectedAttrEntry,
+                        expectedAttrValueEntry);
+
+    auto jsonEnumReadWrite = R"({
+         "attribute_name" : "CodeUpdatePolicy",
+         "possible_values" : [ "Concurrent", "Disruptive" ],
+         "default_values" : [ "Disruptive" ],
+         "readOnly" : false,
+         "helpText" : "HelpText",
+         "displayName" : "DisplayName",
+         "dbus":
+            {
+               "object_path" : "/xyz/abc/def",
+               "interface" : "xyz.openbmc.abc.def",
+               "property_name" : "Policy",
+               "property_type" : "bool",
+               "property_values" : [true, false]
+          }
+      })"_json;
+
+    BIOSEnumAttribute enumReadWrite{jsonEnumReadWrite, &dbusHandler};
+
+    EXPECT_CALL(dbusHandler,
+                getDbusPropertyVariant(StrEq("/xyz/abc/def"), StrEq("Policy"),
+                                       StrEq("xyz.openbmc.abc.def")))
+        .WillOnce(Throw(std::exception()));
+
+    /* Set expected attr type to read-write */
+    expectedAttrEntry[2] = PLDM_BIOS_ENUMERATION;
+    expectedAttrValueEntry[2] = PLDM_BIOS_ENUMERATION;
+
+    checkConstructEntry(enumReadWrite, biosStringTable, expectedAttrEntry,
+                        expectedAttrValueEntry);
+
+    EXPECT_CALL(dbusHandler,
+                getDbusPropertyVariant(StrEq("/xyz/abc/def"), StrEq("Policy"),
+                                       StrEq("xyz.openbmc.abc.def")))
+        .WillOnce(Return(PropertyValue(true)));
+
+    expectedAttrValueEntry = {
+        0, 0, /* attr handle */
+        0,    /* attr type enum read-write*/
+        1,    /* number of current value */
+        0     /* current value string handle index */
+    };
+
+    checkConstructEntry(enumReadWrite, biosStringTable, expectedAttrEntry,
+                        expectedAttrValueEntry);
+}
+
+TEST_F(TestBIOSEnumAttribute, setAttrValueOnDbus)
+{
+    MockBIOSStringTable biosStringTable;
+    MockdBusHandler dbusHandler;
+
+    auto jsonEnumReadWrite = R"({
+         "attribute_name" : "CodeUpdatePolicy",
+         "possible_values" : [ "Concurrent", "Disruptive" ],
+         "default_values" : [ "Disruptive" ],
+         "readOnly" : false,
+         "helpText" : "HelpText",
+         "displayName" : "DisplayName",
+         "dbus":
+            {
+               "object_path" : "/xyz/abc/def",
+               "interface" : "xyz.openbmc.abc.def",
+               "property_name" : "Policy",
+               "property_type" : "bool",
+               "property_values" : [true, false]
+          }
+      })"_json;
+    DBusMapping dbusMapping{"/xyz/abc/def", "xyz.openbmc.abc.def", "Policy",
+                            "bool"};
+
+    BIOSEnumAttribute enumReadWrite{jsonEnumReadWrite, &dbusHandler};
+
+    std::vector<uint8_t> attrEntry{
+        0, 0, /* attr handle */
+        0,    /* attr type enum read-only*/
+        4, 0, /* attr name handle */
+        2,    /* number of possible value */
+        2, 0, /* possible value handle */
+        3, 0, /* possible value handle */
+        1,    /* number of default value */
+        1     /* defaut value string handle index */
+    };
+
+    ON_CALL(biosStringTable, findString(2))
+        .WillByDefault(Return(std::string("Concurrent")));
+    ON_CALL(biosStringTable, findString(3))
+        .WillByDefault(Return(std::string("Disruptive")));
+
+    std::vector<uint8_t> attrValueEntry{
+        0, 0, /* attr handle */
+        0,    /* attr type enum read-only*/
+        1,    /* number of current value */
+        0     /* current value string handle index */
+    };
+
+    EXPECT_CALL(dbusHandler,
+                setDbusProperty(dbusMapping, PropertyValue{bool(true)}))
+        .Times(1);
+    enumReadWrite.setAttrValueOnDbus(
+        reinterpret_cast<pldm_bios_attr_val_table_entry*>(
+            attrValueEntry.data()),
+        reinterpret_cast<pldm_bios_attr_table_entry*>(attrEntry.data()),
+        biosStringTable);
+}
diff --git a/libpldmresponder/test/libpldmresponder_bios_integer_attribute_test.cpp b/libpldmresponder/test/libpldmresponder_bios_integer_attribute_test.cpp
new file mode 100644
index 0000000..fe1d6a8
--- /dev/null
+++ b/libpldmresponder/test/libpldmresponder_bios_integer_attribute_test.cpp
@@ -0,0 +1,206 @@
+#include "common/test/mocked_utils.hpp"
+#include "libpldmresponder/bios_integer_attribute.hpp"
+#include "mocked_bios.hpp"
+
+#include <nlohmann/json.hpp>
+
+#include <memory>
+
+#include <gmock/gmock.h>
+#include <gtest/gtest.h>
+
+using ::testing::_;
+using ::testing::ElementsAreArray;
+using ::testing::Return;
+using ::testing::StrEq;
+using ::testing::Throw;
+
+class TestBIOSIntegerAttribute : public ::testing::Test
+{
+  public:
+    const auto& getIntegerInfo(const BIOSIntegerAttribute& attribute)
+    {
+        return attribute.integerInfo;
+    }
+};
+
+TEST_F(TestBIOSIntegerAttribute, CtorTest)
+{
+    auto jsonIntegerReadOnly = R"({
+         "attribute_name" : "SBE_IMAGE_MINIMUM_VALID_ECS",
+         "lower_bound" : 1,
+         "upper_bound" : 15,
+         "scalar_increment" : 1,
+         "default_value" : 2,
+         "readOnly" : true,
+         "helpText" : "HelpText",
+         "displayName" : "DisplayName"
+      })"_json;
+
+    BIOSIntegerAttribute integerReadOnly{jsonIntegerReadOnly, nullptr};
+    EXPECT_EQ(integerReadOnly.name, "SBE_IMAGE_MINIMUM_VALID_ECS");
+    EXPECT_TRUE(integerReadOnly.readOnly);
+    auto& integerInfo = getIntegerInfo(integerReadOnly);
+    EXPECT_EQ(integerInfo.lowerBound, 1);
+    EXPECT_EQ(integerInfo.upperBound, 15);
+    EXPECT_EQ(integerInfo.scalarIncrement, 1);
+    EXPECT_EQ(integerInfo.defaultValue, 2);
+
+    auto jsonIntegerReadOnlyError = R"({
+         "attribute_name" : "SBE_IMAGE_MINIMUM_VALID_ECS",
+         "lower_bound" : 1,
+         "upper_bound" : 15,
+         "scalar_increment" : 1,
+         "default_valu" : 2,
+         "readOnly" : true,
+         "helpText" : "HelpText",
+         "displayName" : "DisplayName"
+      })"_json; // default_valu -> default_value
+    EXPECT_THROW((BIOSIntegerAttribute{jsonIntegerReadOnlyError, nullptr}),
+                 Json::exception);
+
+    auto jsonIntegerReadWrite = R"({
+         "attribute_name" : "VDD_AVSBUS_RAIL",
+         "lower_bound" : 0,
+         "upper_bound" : 15,
+         "scalar_increment" : 1,
+         "default_value" : 0,
+         "readOnly" : false,
+         "helpText" : "HelpText",
+         "displayName" : "DisplayName",
+         "dbus":{
+            "object_path" : "/xyz/openbmc_project/avsbus",
+            "interface" : "xyz.openbmc.AvsBus.Manager",
+            "property_type" : "uint8_t",
+            "property_name" : "Rail"
+         }
+      })"_json;
+
+    BIOSIntegerAttribute integerReadWrite{jsonIntegerReadWrite, nullptr};
+    EXPECT_EQ(integerReadWrite.name, "VDD_AVSBUS_RAIL");
+    EXPECT_TRUE(!integerReadWrite.readOnly);
+}
+
+TEST_F(TestBIOSIntegerAttribute, ConstructEntry)
+{
+    MockBIOSStringTable biosStringTable;
+    MockdBusHandler dbusHandler;
+
+    auto jsonIntegerReadOnly = R"({
+         "attribute_name" : "VDD_AVSBUS_RAIL",
+         "lower_bound" : 1,
+         "upper_bound" : 15,
+         "scalar_increment" : 1,
+         "default_value" : 2,
+         "readOnly" : true,
+         "helpText" : "HelpText",
+         "displayName" : "DisplayName"
+      })"_json;
+
+    std::vector<uint8_t> expectedAttrEntry{
+        0,    0,                   /* attr handle */
+        0x83,                      /* attr type integer read-only*/
+        5,    0,                   /* attr name handle */
+        1,    0, 0, 0, 0, 0, 0, 0, /* lower bound */
+        15,   0, 0, 0, 0, 0, 0, 0, /* upper bound */
+        1,    0, 0, 0,             /* scalar increment */
+        2,    0, 0, 0, 0, 0, 0, 0, /* defaut value */
+    };
+    std::vector<uint8_t> expectedAttrValueEntry{
+        0,    0,                   /* attr handle */
+        0x83,                      /* attr type integer read-only*/
+        2,    0, 0, 0, 0, 0, 0, 0, /* current value */
+    };
+
+    BIOSIntegerAttribute integerReadOnly{jsonIntegerReadOnly, nullptr};
+
+    ON_CALL(biosStringTable, findHandle(StrEq("VDD_AVSBUS_RAIL")))
+        .WillByDefault(Return(5));
+
+    checkConstructEntry(integerReadOnly, biosStringTable, expectedAttrEntry,
+                        expectedAttrValueEntry);
+
+    auto jsonIntegerReadWrite = R"({
+         "attribute_name" : "VDD_AVSBUS_RAIL",
+         "lower_bound" : 1,
+         "upper_bound" : 15,
+         "scalar_increment" : 1,
+         "default_value" : 2,
+         "readOnly" : false,
+         "helpText" : "HelpText",
+         "displayName" : "DisplayName",
+         "dbus":{
+            "object_path" : "/xyz/openbmc_project/avsbus",
+            "interface" : "xyz.openbmc.AvsBus.Manager",
+            "property_type" : "uint8_t",
+            "property_name" : "Rail"
+         }
+      })"_json;
+    BIOSIntegerAttribute integerReadWrite{jsonIntegerReadWrite, &dbusHandler};
+
+    EXPECT_CALL(dbusHandler,
+                getDbusPropertyVariant(StrEq("/xyz/openbmc_project/avsbus"),
+                                       StrEq("Rail"),
+                                       StrEq("xyz.openbmc.AvsBus.Manager")))
+        .WillOnce(Throw(std::exception()));
+
+    /* Set expected attr type to read-write */
+    expectedAttrEntry[2] = PLDM_BIOS_INTEGER;
+    expectedAttrValueEntry[2] = PLDM_BIOS_INTEGER;
+
+    checkConstructEntry(integerReadWrite, biosStringTable, expectedAttrEntry,
+                        expectedAttrValueEntry);
+
+    EXPECT_CALL(dbusHandler,
+                getDbusPropertyVariant(StrEq("/xyz/openbmc_project/avsbus"),
+                                       StrEq("Rail"),
+                                       StrEq("xyz.openbmc.AvsBus.Manager")))
+        .WillOnce(Return(PropertyValue(uint8_t(7))));
+
+    expectedAttrValueEntry = {
+        0, 0,                   /* attr handle */
+        3,                      /* attr type integer read-write*/
+        7, 0, 0, 0, 0, 0, 0, 0, /* current value */
+    };
+
+    checkConstructEntry(integerReadWrite, biosStringTable, expectedAttrEntry,
+                        expectedAttrValueEntry);
+}
+
+TEST_F(TestBIOSIntegerAttribute, setAttrValueOnDbus)
+{
+    MockdBusHandler dbusHandler;
+    MockBIOSStringTable biosStringTable;
+
+    auto jsonIntegerReadWrite = R"({
+         "attribute_name" : "VDD_AVSBUS_RAIL",
+         "lower_bound" : 1,
+         "upper_bound" : 15,
+         "scalar_increment" : 1,
+         "default_value" : 2,
+         "readOnly" : false,
+         "helpText" : "HelpText",
+         "displayName" : "DisplayName",
+         "dbus":{
+            "object_path" : "/xyz/openbmc_project/avsbus",
+            "interface" : "xyz.openbmc.AvsBus.Manager",
+            "property_type" : "uint8_t",
+            "property_name" : "Rail"
+         }
+      })"_json;
+    BIOSIntegerAttribute integerReadWrite{jsonIntegerReadWrite, &dbusHandler};
+    DBusMapping dbusMapping{"/xyz/openbmc_project/avsbus",
+                            "xyz.openbmc.AvsBus.Manager", "Rail", "uint8_t"};
+    std::vector<uint8_t> attrValueEntry = {
+        0, 0,                   /* attr handle */
+        3,                      /* attr type integer read-write*/
+        7, 0, 0, 0, 0, 0, 0, 0, /* current value */
+    };
+
+    auto entry = reinterpret_cast<pldm_bios_attr_val_table_entry*>(
+        attrValueEntry.data());
+    EXPECT_CALL(dbusHandler,
+                setDbusProperty(dbusMapping, PropertyValue{uint8_t(7)}))
+        .Times(1);
+    integerReadWrite.setAttrValueOnDbus(entry, nullptr, biosStringTable);
+}
diff --git a/libpldmresponder/test/libpldmresponder_bios_string_attribute_test.cpp b/libpldmresponder/test/libpldmresponder_bios_string_attribute_test.cpp
new file mode 100644
index 0000000..d1c1703
--- /dev/null
+++ b/libpldmresponder/test/libpldmresponder_bios_string_attribute_test.cpp
@@ -0,0 +1,218 @@
+#include "common/test/mocked_utils.hpp"
+#include "libpldmresponder/bios_string_attribute.hpp"
+#include "mocked_bios.hpp"
+
+#include <nlohmann/json.hpp>
+
+#include <memory>
+
+#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",
+            "readOnly" : true,
+            "helpText" : "HelpText",
+            "displayName" : "DisplayName"
+        })"_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",
+            "helpText" : "HelpText",
+            "displayName" : "DisplayName"
+        })"_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",
+            "readOnly" : false,
+            "helpText" : "HelpText",
+            "displayName" : "DisplayName",
+            "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",
+            "readOnly" : true,
+            "helpText" : "HelpText",
+            "displayName" : "DisplayName"
+        })"_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",
+            "readOnly" : false,
+            "helpText" : "HelpText",
+            "displayName" : "DisplayName",
+            "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",
+            "readOnly" : false,
+            "helpText" : "HelpText",
+            "displayName" : "DisplayName",
+            "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/libpldmresponder/test/libpldmresponder_bios_table_test.cpp b/libpldmresponder/test/libpldmresponder_bios_table_test.cpp
new file mode 100644
index 0000000..47764ee
--- /dev/null
+++ b/libpldmresponder/test/libpldmresponder_bios_table_test.cpp
@@ -0,0 +1,61 @@
+#include "libpldmresponder/bios_table.hpp"
+
+#include <stdlib.h>
+
+#include <algorithm>
+#include <vector>
+
+#include <gtest/gtest.h>
+
+using namespace pldm::responder::bios;
+
+class TestBIOSTable : public testing::Test
+{
+  public:
+    void SetUp() override
+    {
+        char tmpdir[] = "/tmp/pldm_bios_table.XXXXXX";
+        dir = fs::path(mkdtemp(tmpdir));
+    }
+
+    void TearDown() override
+    {
+        fs::remove_all(dir);
+    }
+
+    fs::path dir;
+};
+
+TEST_F(TestBIOSTable, testStoreLoad)
+{
+    std::vector<uint8_t> table{10, 34, 56, 100, 44, 55, 69, 21, 48, 2, 7, 82};
+    fs::path file(dir / "t1");
+    BIOSTable t(file.string().c_str());
+    std::vector<uint8_t> out{};
+
+    ASSERT_THROW(t.load(out), fs::filesystem_error);
+
+    ASSERT_EQ(true, t.isEmpty());
+
+    t.store(table);
+    t.load(out);
+    ASSERT_EQ(true, std::equal(table.begin(), table.end(), out.begin()));
+}
+
+TEST_F(TestBIOSTable, testLoadOntoExisting)
+{
+    std::vector<uint8_t> table{10, 34, 56, 100, 44, 55, 69, 21, 48, 2, 7, 82};
+    fs::path file(dir / "t1");
+    BIOSTable t(file.string().c_str());
+    std::vector<uint8_t> out{99, 99};
+
+    ASSERT_THROW(t.load(out), fs::filesystem_error);
+
+    ASSERT_EQ(true, t.isEmpty());
+
+    t.store(table);
+    t.load(out);
+    ASSERT_EQ(true, std::equal(table.begin(), table.end(), out.begin() + 2));
+    ASSERT_EQ(out[0], 99);
+    ASSERT_EQ(out[1], 99);
+}
diff --git a/libpldmresponder/test/libpldmresponder_bios_test.cpp b/libpldmresponder/test/libpldmresponder_bios_test.cpp
new file mode 100644
index 0000000..9683d49
--- /dev/null
+++ b/libpldmresponder/test/libpldmresponder_bios_test.cpp
@@ -0,0 +1,66 @@
+#include "libpldm/base.h"
+#include "libpldm/bios.h"
+
+#include "libpldmresponder/bios.hpp"
+#include "libpldmresponder/bios_table.hpp"
+
+#include <string.h>
+
+#include <array>
+#include <cstring>
+#include <ctime>
+#include <filesystem>
+
+#include <gtest/gtest.h>
+
+using namespace pldm;
+using namespace pldm::responder;
+using namespace pldm::responder::bios;
+using namespace pldm::responder::utils;
+
+TEST(epochToBCDTime, testTime)
+{
+    struct tm time
+    {};
+    time.tm_year = 119;
+    time.tm_mon = 3;
+    time.tm_mday = 13;
+    time.tm_hour = 5;
+    time.tm_min = 18;
+    time.tm_sec = 13;
+    time.tm_isdst = -1;
+
+    time_t epochTime = mktime(&time);
+    uint8_t seconds = 0;
+    uint8_t minutes = 0;
+    uint8_t hours = 0;
+    uint8_t day = 0;
+    uint8_t month = 0;
+    uint16_t year = 0;
+
+    epochToBCDTime(epochTime, seconds, minutes, hours, day, month, year);
+
+    ASSERT_EQ(0x13, seconds);
+    ASSERT_EQ(0x18, minutes);
+    ASSERT_EQ(0x5, hours);
+    ASSERT_EQ(0x13, day);
+    ASSERT_EQ(0x4, month);
+    ASSERT_EQ(0x2019, year);
+}
+
+TEST(timeToEpoch, testTime0)
+{
+    std::time_t ret = 1555132693;
+
+    uint8_t sec = 13;
+    uint8_t min = 18;
+    uint8_t hours = 5;
+    uint8_t day = 13;
+    uint8_t month = 4;
+    uint16_t year = 2019;
+
+    std::time_t timeSec = 0;
+    timeSec = timeToEpoch(sec, min, hours, day, month, year);
+
+    EXPECT_EQ(ret, timeSec);
+}
\ No newline at end of file
diff --git a/libpldmresponder/test/libpldmresponder_fru_test.cpp b/libpldmresponder/test/libpldmresponder_fru_test.cpp
new file mode 100644
index 0000000..7b1b470
--- /dev/null
+++ b/libpldmresponder/test/libpldmresponder_fru_test.cpp
@@ -0,0 +1,64 @@
+#include "libpldmresponder/fru_parser.hpp"
+
+#include <gtest/gtest.h>
+TEST(FruParser, allScenarios)
+{
+    using namespace pldm::responder::fru_parser;
+
+    FruParser parser{"./fru_jsons/good"};
+
+    // Get an item with a single PLDM FRU record
+    FruRecordInfos cpu{
+        {1,
+         1,
+         {{"xyz.openbmc_project.Inventory.Decorator.Asset", "Model", "string",
+           2},
+          {"xyz.openbmc_project.Inventory.Decorator.Asset", "PartNumber",
+           "string", 3},
+          {"xyz.openbmc_project.Inventory.Decorator.Asset", "SerialNumber",
+           "string", 4},
+          {"xyz.openbmc_project.Inventory.Decorator.Asset", "Manufacturer",
+           "string", 5},
+          {"xyz.openbmc_project.Inventory.Item", "PrettyName", "string", 8},
+          {"xyz.openbmc_project.Inventory.Decorator.AssetTag", "AssetTag",
+           "string", 11},
+          {"xyz.openbmc_project.Inventory.Decorator.Revision", "Version",
+           "string", 10}}},
+        {1,
+         1,
+         {{"xyz.openbmc_project.Inventory.Decorator.Asset", "PartNumber",
+           "string", 3},
+          {"xyz.openbmc_project.Inventory.Decorator.Asset", "SerialNumber",
+           "string", 4}}}};
+    auto cpuInfos =
+        parser.getRecordInfo("xyz.openbmc_project.Inventory.Item.Cpu");
+    ASSERT_EQ(cpuInfos.size(), 2);
+    ASSERT_EQ(cpu == cpuInfos, true);
+
+    // Get an item type with 3 PLDM FRU records
+    auto boardInfos =
+        parser.getRecordInfo("xyz.openbmc_project.Inventory.Item.Board");
+    ASSERT_EQ(boardInfos.size(), 3);
+
+    // D-Bus lookup info for FRU information
+    DBusLookupInfo lookupInfo{
+        "xyz.openbmc_project.Inventory.Manager",
+        "/xyz/openbmc_project/inventory",
+        {"xyz.openbmc_project.Inventory.Item.Chassis",
+         "xyz.openbmc_project.Inventory.Item.Board",
+         "xyz.openbmc_project.Inventory.Item.Board.Motherboard",
+         "xyz.openbmc_project.Inventory.Item.Panel",
+         "xyz.openbmc_project.Inventory.Item.PowerSupply",
+         "xyz.openbmc_project.Inventory.Item.Vrm",
+         "xyz.openbmc_project.Inventory.Item.Cpu",
+         "xyz.openbmc_project.Inventory.Item.Bmc",
+         "xyz.openbmc_project.Inventory.Item.Dimm",
+         "xyz.openbmc_project.Inventory.Item.Tpm",
+         "xyz.openbmc_project.Inventory.Item.System"}};
+    auto dbusInfo = parser.inventoryLookup();
+    ASSERT_EQ(dbusInfo == lookupInfo, true);
+
+    ASSERT_THROW(
+        parser.getRecordInfo("xyz.openbmc_project.Inventory.Item.DIMM"),
+        std::exception);
+}
diff --git a/libpldmresponder/test/libpldmresponder_pdr_effecter_test.cpp b/libpldmresponder/test/libpldmresponder_pdr_effecter_test.cpp
new file mode 100644
index 0000000..4f3df87
--- /dev/null
+++ b/libpldmresponder/test/libpldmresponder_pdr_effecter_test.cpp
@@ -0,0 +1,215 @@
+#include "libpldm/platform.h"
+
+#include "common/test/mocked_utils.hpp"
+#include "libpldmresponder/pdr_utils.hpp"
+#include "libpldmresponder/platform.hpp"
+
+#include <sdbusplus/test/sdbus_mock.hpp>
+#include <sdeventplus/event.hpp>
+
+#include <gtest/gtest.h>
+
+using namespace pldm::responder;
+using namespace pldm::responder::platform;
+using namespace pldm::responder::pdr;
+using namespace pldm::responder::pdr_utils;
+
+using ::testing::_;
+using ::testing::Return;
+using ::testing::StrEq;
+
+TEST(GeneratePDRByStateEffecter, testGoodJson)
+{
+    MockdBusHandler mockedUtils;
+    EXPECT_CALL(mockedUtils, getService(StrEq("/foo/bar"), _))
+        .Times(5)
+        .WillRepeatedly(Return("foo.bar"));
+
+    auto inPDRRepo = pldm_pdr_init();
+    auto outPDRRepo = pldm_pdr_init();
+    Repo outRepo(outPDRRepo);
+    auto event = sdeventplus::Event::get_default();
+    Handler handler(&mockedUtils, "./pdr_jsons/state_effecter/good", inPDRRepo,
+                    nullptr, nullptr, nullptr, nullptr, event);
+    Repo inRepo(inPDRRepo);
+    getRepoByType(inRepo, outRepo, PLDM_STATE_EFFECTER_PDR);
+
+    // 2 entries
+    ASSERT_EQ(outRepo.getRecordCount(), 2);
+
+    // Check first PDR
+    pdr_utils::PdrEntry e;
+    auto record2 = pdr::getRecordByHandle(outRepo, 2, e);
+    ASSERT_NE(record2, nullptr);
+    pldm_state_effecter_pdr* pdr =
+        reinterpret_cast<pldm_state_effecter_pdr*>(e.data);
+
+    ASSERT_EQ(pdr->hdr.record_handle, 2);
+    ASSERT_EQ(pdr->hdr.version, 1);
+    ASSERT_EQ(pdr->hdr.type, PLDM_STATE_EFFECTER_PDR);
+    ASSERT_EQ(pdr->hdr.record_change_num, 0);
+    ASSERT_EQ(pdr->hdr.length, 23);
+
+    ASSERT_EQ(pdr->terminus_handle, BmcPldmTerminusHandle);
+    ASSERT_EQ(pdr->effecter_id, 1);
+    ASSERT_EQ(pdr->entity_type, 33);
+    ASSERT_EQ(pdr->entity_instance, 0);
+    ASSERT_EQ(pdr->container_id, 0);
+    ASSERT_EQ(pdr->effecter_semantic_id, 0);
+    ASSERT_EQ(pdr->effecter_init, PLDM_NO_INIT);
+    ASSERT_EQ(pdr->has_description_pdr, false);
+    ASSERT_EQ(pdr->composite_effecter_count, 2);
+    state_effecter_possible_states* states =
+        reinterpret_cast<state_effecter_possible_states*>(pdr->possible_states);
+    ASSERT_EQ(states->state_set_id, 196);
+    ASSERT_EQ(states->possible_states_size, 1);
+    bitfield8_t bf1{};
+    bf1.byte = 2;
+    ASSERT_EQ(states->states[0].byte, bf1.byte);
+
+    const auto& [dbusMappings1, dbusValMaps1] =
+        handler.getDbusObjMaps(pdr->effecter_id);
+    ASSERT_EQ(dbusMappings1[0].objectPath, "/foo/bar");
+
+    // Check second PDR
+    auto record3 = pdr::getRecordByHandle(outRepo, 3, e);
+    ASSERT_NE(record3, nullptr);
+    pdr = reinterpret_cast<pldm_state_effecter_pdr*>(e.data);
+
+    ASSERT_EQ(pdr->hdr.record_handle, 3);
+    ASSERT_EQ(pdr->hdr.version, 1);
+    ASSERT_EQ(pdr->hdr.type, PLDM_STATE_EFFECTER_PDR);
+    ASSERT_EQ(pdr->hdr.record_change_num, 0);
+    ASSERT_EQ(pdr->hdr.length, 24);
+
+    ASSERT_EQ(pdr->terminus_handle, BmcPldmTerminusHandle);
+    ASSERT_EQ(pdr->effecter_id, 2);
+    ASSERT_EQ(pdr->entity_type, 100);
+    ASSERT_EQ(pdr->entity_instance, 0);
+    ASSERT_EQ(pdr->container_id, 0);
+    ASSERT_EQ(pdr->effecter_semantic_id, 0);
+    ASSERT_EQ(pdr->effecter_init, PLDM_NO_INIT);
+    ASSERT_EQ(pdr->has_description_pdr, false);
+    ASSERT_EQ(pdr->composite_effecter_count, 2);
+    states =
+        reinterpret_cast<state_effecter_possible_states*>(pdr->possible_states);
+    ASSERT_EQ(states->state_set_id, 197);
+    ASSERT_EQ(states->possible_states_size, 1);
+    bf1.byte = 2;
+    ASSERT_EQ(states->states[0].byte, bf1.byte);
+    states = reinterpret_cast<state_effecter_possible_states*>(
+        pdr->possible_states + sizeof(state_effecter_possible_states));
+    ASSERT_EQ(states->state_set_id, 198);
+    ASSERT_EQ(states->possible_states_size, 2);
+    bitfield8_t bf2[2];
+    bf2[0].byte = 38;
+    bf2[1].byte = 128;
+    ASSERT_EQ(states->states[0].byte, bf2[0].byte);
+    ASSERT_EQ(states->states[1].byte, bf2[1].byte);
+
+    const auto& [dbusMappings2, dbusValMaps2] =
+        handler.getDbusObjMaps(pdr->effecter_id);
+    ASSERT_EQ(dbusMappings2[0].objectPath, "/foo/bar");
+    ASSERT_EQ(dbusMappings2[1].objectPath, "/foo/bar");
+
+    ASSERT_THROW(handler.getDbusObjMaps(0xDEAD), std::exception);
+
+    pldm_pdr_destroy(inPDRRepo);
+    pldm_pdr_destroy(outPDRRepo);
+}
+
+TEST(GeneratePDRByNumericEffecter, testGoodJson)
+{
+    MockdBusHandler mockedUtils;
+    EXPECT_CALL(mockedUtils, getService(StrEq("/foo/bar"), _))
+        .Times(5)
+        .WillRepeatedly(Return("foo.bar"));
+
+    auto inPDRRepo = pldm_pdr_init();
+    auto outPDRRepo = pldm_pdr_init();
+    Repo outRepo(outPDRRepo);
+    auto event = sdeventplus::Event::get_default();
+    Handler handler(&mockedUtils, "./pdr_jsons/state_effecter/good", inPDRRepo,
+                    nullptr, nullptr, nullptr, nullptr, event);
+    Repo inRepo(inPDRRepo);
+    getRepoByType(inRepo, outRepo, PLDM_NUMERIC_EFFECTER_PDR);
+
+    // 1 entries
+    ASSERT_EQ(outRepo.getRecordCount(), 1);
+
+    // Check first PDR
+    pdr_utils::PdrEntry e;
+    auto record = pdr::getRecordByHandle(outRepo, 4, e);
+    ASSERT_NE(record, nullptr);
+
+    pldm_numeric_effecter_value_pdr* pdr =
+        reinterpret_cast<pldm_numeric_effecter_value_pdr*>(e.data);
+    EXPECT_EQ(pdr->hdr.record_handle, 4);
+    EXPECT_EQ(pdr->hdr.version, 1);
+    EXPECT_EQ(pdr->hdr.type, PLDM_NUMERIC_EFFECTER_PDR);
+    EXPECT_EQ(pdr->hdr.record_change_num, 0);
+    EXPECT_EQ(pdr->hdr.length,
+              sizeof(pldm_numeric_effecter_value_pdr) - sizeof(pldm_pdr_hdr));
+
+    EXPECT_EQ(pdr->effecter_id, 3);
+    EXPECT_EQ(pdr->effecter_data_size, 4);
+
+    const auto& [dbusMappings, dbusValMaps] =
+        handler.getDbusObjMaps(pdr->effecter_id);
+    EXPECT_EQ(dbusMappings[0].objectPath, "/foo/bar");
+    EXPECT_EQ(dbusMappings[0].interface, "xyz.openbmc_project.Foo.Bar");
+    EXPECT_EQ(dbusMappings[0].propertyName, "propertyName");
+    EXPECT_EQ(dbusMappings[0].propertyType, "uint64_t");
+
+    pldm_pdr_destroy(inPDRRepo);
+    pldm_pdr_destroy(outPDRRepo);
+}
+
+TEST(GeneratePDR, testMalformedJson)
+{
+    MockdBusHandler mockedUtils;
+    EXPECT_CALL(mockedUtils, getService(StrEq("/foo/bar"), _))
+        .Times(5)
+        .WillRepeatedly(Return("foo.bar"));
+
+    auto inPDRRepo = pldm_pdr_init();
+    auto outPDRRepo = pldm_pdr_init();
+    Repo outRepo(outPDRRepo);
+    auto event = sdeventplus::Event::get_default();
+    Handler handler(&mockedUtils, "./pdr_jsons/state_effecter/good", inPDRRepo,
+                    nullptr, nullptr, nullptr, nullptr, event);
+    Repo inRepo(inPDRRepo);
+    getRepoByType(inRepo, outRepo, PLDM_STATE_EFFECTER_PDR);
+
+    ASSERT_EQ(outRepo.getRecordCount(), 2);
+    ASSERT_THROW(pdr_utils::readJson("./pdr_jsons/state_effecter/malformed"),
+                 std::exception);
+
+    pldm_pdr_destroy(inPDRRepo);
+    pldm_pdr_destroy(outPDRRepo);
+}
+
+TEST(findStateEffecterId, goodJson)
+{
+    MockdBusHandler mockedUtils;
+    EXPECT_CALL(mockedUtils, getService(StrEq("/foo/bar"), _))
+        .Times(5)
+        .WillRepeatedly(Return("foo.bar"));
+
+    auto inPDRRepo = pldm_pdr_init();
+    auto event = sdeventplus::Event::get_default();
+    Handler handler(&mockedUtils, "./pdr_jsons/state_effecter/good", inPDRRepo,
+                    nullptr, nullptr, nullptr, nullptr, event);
+    uint16_t entityType = 33;
+    uint16_t entityInstance = 0;
+    uint16_t containerId = 0;
+    uint16_t stateSetId = 196;
+    auto effecterId = findStateEffecterId(inPDRRepo, entityType, entityInstance,
+                                          containerId, stateSetId, true);
+    ASSERT_EQ(effecterId, 1);
+    stateSetId = 300;
+    effecterId = findStateEffecterId(inPDRRepo, entityType, entityInstance,
+                                     containerId, stateSetId, true);
+    ASSERT_EQ(effecterId, PLDM_INVALID_EFFECTER_ID);
+    pldm_pdr_destroy(inPDRRepo);
+}
diff --git a/libpldmresponder/test/libpldmresponder_pdr_sensor_test.cpp b/libpldmresponder/test/libpldmresponder_pdr_sensor_test.cpp
new file mode 100644
index 0000000..f95df0c
--- /dev/null
+++ b/libpldmresponder/test/libpldmresponder_pdr_sensor_test.cpp
@@ -0,0 +1,100 @@
+#include "libpldm/platform.h"
+
+#include "common/test/mocked_utils.hpp"
+#include "libpldmresponder/pdr_utils.hpp"
+#include "libpldmresponder/platform.hpp"
+
+#include <sdbusplus/test/sdbus_mock.hpp>
+#include <sdeventplus/event.hpp>
+
+#include <gtest/gtest.h>
+
+using namespace pldm::responder;
+using namespace pldm::responder::platform;
+using namespace pldm::responder::pdr;
+using namespace pldm::responder::pdr_utils;
+
+using ::testing::_;
+using ::testing::Return;
+using ::testing::StrEq;
+
+TEST(GeneratePDRByStateSensor, testGoodJson)
+{
+    std::array<uint8_t, sizeof(pldm_msg_hdr) + PLDM_GET_PDR_REQ_BYTES>
+        requestPayload{};
+    auto req = reinterpret_cast<pldm_msg*>(requestPayload.data());
+    size_t requestPayloadLength = requestPayload.size() - sizeof(pldm_msg_hdr);
+
+    MockdBusHandler mockedUtils;
+    EXPECT_CALL(mockedUtils, getService(StrEq("/foo/bar"), _))
+        .Times(1)
+        .WillRepeatedly(Return("foo.bar"));
+
+    auto inPDRRepo = pldm_pdr_init();
+    auto outPDRRepo = pldm_pdr_init();
+    Repo outRepo(outPDRRepo);
+    auto event = sdeventplus::Event::get_default();
+    Handler handler(&mockedUtils, "./pdr_jsons/state_sensor/good", inPDRRepo,
+                    nullptr, nullptr, nullptr, nullptr, event);
+    handler.getPDR(req, requestPayloadLength);
+    Repo inRepo(inPDRRepo);
+    getRepoByType(inRepo, outRepo, PLDM_STATE_SENSOR_PDR);
+
+    // 1 entries
+    ASSERT_EQ(outRepo.getRecordCount(), 1);
+
+    // Check first PDR
+    pdr_utils::PdrEntry e;
+    auto record = pdr::getRecordByHandle(outRepo, 2, e);
+    ASSERT_NE(record, nullptr);
+
+    pldm_state_sensor_pdr* pdr =
+        reinterpret_cast<pldm_state_sensor_pdr*>(e.data);
+    EXPECT_EQ(pdr->hdr.record_handle, 2);
+    EXPECT_EQ(pdr->hdr.version, 1);
+    EXPECT_EQ(pdr->hdr.type, PLDM_STATE_SENSOR_PDR);
+    EXPECT_EQ(pdr->hdr.record_change_num, 0);
+    EXPECT_EQ(pdr->hdr.length, 17);
+
+    EXPECT_EQ(pdr->sensor_id, 1);
+
+    const auto& [dbusMappings, dbusValMaps] =
+        handler.getDbusObjMaps(pdr->sensor_id, TypeId::PLDM_SENSOR_ID);
+    ASSERT_EQ(dbusMappings[0].objectPath, "/foo/bar");
+    ASSERT_EQ(dbusMappings[0].interface, "xyz.openbmc_project.Foo.Bar");
+    ASSERT_EQ(dbusMappings[0].propertyName, "propertyName");
+    ASSERT_EQ(dbusMappings[0].propertyType, "string");
+
+    pldm_pdr_destroy(inPDRRepo);
+    pldm_pdr_destroy(outPDRRepo);
+}
+
+TEST(GeneratePDR, testMalformedJson)
+{
+    std::array<uint8_t, sizeof(pldm_msg_hdr) + PLDM_GET_PDR_REQ_BYTES>
+        requestPayload{};
+    auto req = reinterpret_cast<pldm_msg*>(requestPayload.data());
+    size_t requestPayloadLength = requestPayload.size() - sizeof(pldm_msg_hdr);
+
+    MockdBusHandler mockedUtils;
+    EXPECT_CALL(mockedUtils, getService(StrEq("/foo/bar"), _))
+        .Times(1)
+        .WillRepeatedly(Return("foo.bar"));
+
+    auto inPDRRepo = pldm_pdr_init();
+    auto outPDRRepo = pldm_pdr_init();
+    Repo outRepo(outPDRRepo);
+    auto event = sdeventplus::Event::get_default();
+    Handler handler(&mockedUtils, "./pdr_jsons/state_sensor/good", inPDRRepo,
+                    nullptr, nullptr, nullptr, nullptr, event);
+    handler.getPDR(req, requestPayloadLength);
+    Repo inRepo(inPDRRepo);
+    getRepoByType(inRepo, outRepo, PLDM_STATE_SENSOR_PDR);
+
+    ASSERT_EQ(outRepo.getRecordCount(), 1);
+    ASSERT_THROW(pdr_utils::readJson("./pdr_jsons/state_sensor/malformed"),
+                 std::exception);
+
+    pldm_pdr_destroy(inPDRRepo);
+    pldm_pdr_destroy(outPDRRepo);
+}
diff --git a/libpldmresponder/test/libpldmresponder_platform_test.cpp b/libpldmresponder/test/libpldmresponder_platform_test.cpp
new file mode 100644
index 0000000..b8fe603
--- /dev/null
+++ b/libpldmresponder/test/libpldmresponder_platform_test.cpp
@@ -0,0 +1,664 @@
+#include "common/test/mocked_utils.hpp"
+#include "common/utils.hpp"
+#include "libpldmresponder/event_parser.hpp"
+#include "libpldmresponder/pdr.hpp"
+#include "libpldmresponder/pdr_utils.hpp"
+#include "libpldmresponder/platform.hpp"
+#include "libpldmresponder/platform_numeric_effecter.hpp"
+#include "libpldmresponder/platform_state_effecter.hpp"
+#include "libpldmresponder/platform_state_sensor.hpp"
+
+#include <sdbusplus/test/sdbus_mock.hpp>
+#include <sdeventplus/event.hpp>
+
+#include <iostream>
+
+using namespace pldm::utils;
+using namespace pldm::responder;
+using namespace pldm::responder::platform;
+using namespace pldm::responder::pdr;
+using namespace pldm::responder::pdr_utils;
+
+using ::testing::_;
+using ::testing::Return;
+using ::testing::StrEq;
+
+TEST(getPDR, testGoodPath)
+{
+    std::array<uint8_t, sizeof(pldm_msg_hdr) + PLDM_GET_PDR_REQ_BYTES>
+        requestPayload{};
+    auto req = reinterpret_cast<pldm_msg*>(requestPayload.data());
+    size_t requestPayloadLength = requestPayload.size() - sizeof(pldm_msg_hdr);
+
+    struct pldm_get_pdr_req* request =
+        reinterpret_cast<struct pldm_get_pdr_req*>(req->payload);
+    request->request_count = 100;
+
+    MockdBusHandler mockedUtils;
+    EXPECT_CALL(mockedUtils, getService(StrEq("/foo/bar"), _))
+        .Times(5)
+        .WillRepeatedly(Return("foo.bar"));
+
+    auto pdrRepo = pldm_pdr_init();
+    auto event = sdeventplus::Event::get_default();
+    Handler handler(&mockedUtils, "./pdr_jsons/state_effecter/good", pdrRepo,
+                    nullptr, nullptr, nullptr, nullptr, event);
+    Repo repo(pdrRepo);
+    ASSERT_EQ(repo.empty(), false);
+    auto response = handler.getPDR(req, requestPayloadLength);
+    auto responsePtr = reinterpret_cast<pldm_msg*>(response.data());
+
+    struct pldm_get_pdr_resp* resp =
+        reinterpret_cast<struct pldm_get_pdr_resp*>(responsePtr->payload);
+    ASSERT_EQ(PLDM_SUCCESS, resp->completion_code);
+    ASSERT_EQ(2, resp->next_record_handle);
+    ASSERT_EQ(true, resp->response_count != 0);
+
+    pldm_pdr_hdr* hdr = reinterpret_cast<pldm_pdr_hdr*>(resp->record_data);
+    ASSERT_EQ(hdr->record_handle, 1);
+    ASSERT_EQ(hdr->version, 1);
+
+    pldm_pdr_destroy(pdrRepo);
+}
+
+TEST(getPDR, testShortRead)
+{
+    std::array<uint8_t, sizeof(pldm_msg_hdr) + PLDM_GET_PDR_REQ_BYTES>
+        requestPayload{};
+    auto req = reinterpret_cast<pldm_msg*>(requestPayload.data());
+    size_t requestPayloadLength = requestPayload.size() - sizeof(pldm_msg_hdr);
+
+    struct pldm_get_pdr_req* request =
+        reinterpret_cast<struct pldm_get_pdr_req*>(req->payload);
+    request->request_count = 1;
+
+    MockdBusHandler mockedUtils;
+    EXPECT_CALL(mockedUtils, getService(StrEq("/foo/bar"), _))
+        .Times(5)
+        .WillRepeatedly(Return("foo.bar"));
+
+    auto pdrRepo = pldm_pdr_init();
+    auto event = sdeventplus::Event::get_default();
+    Handler handler(&mockedUtils, "./pdr_jsons/state_effecter/good", pdrRepo,
+                    nullptr, nullptr, nullptr, nullptr, event);
+    Repo repo(pdrRepo);
+    ASSERT_EQ(repo.empty(), false);
+    auto response = handler.getPDR(req, requestPayloadLength);
+    auto responsePtr = reinterpret_cast<pldm_msg*>(response.data());
+    struct pldm_get_pdr_resp* resp =
+        reinterpret_cast<struct pldm_get_pdr_resp*>(responsePtr->payload);
+    ASSERT_EQ(PLDM_SUCCESS, resp->completion_code);
+    ASSERT_EQ(1, resp->response_count);
+    pldm_pdr_destroy(pdrRepo);
+}
+
+TEST(getPDR, testBadRecordHandle)
+{
+    std::array<uint8_t, sizeof(pldm_msg_hdr) + PLDM_GET_PDR_REQ_BYTES>
+        requestPayload{};
+    auto req = reinterpret_cast<pldm_msg*>(requestPayload.data());
+    size_t requestPayloadLength = requestPayload.size() - sizeof(pldm_msg_hdr);
+
+    struct pldm_get_pdr_req* request =
+        reinterpret_cast<struct pldm_get_pdr_req*>(req->payload);
+    request->record_handle = 100000;
+    request->request_count = 1;
+
+    MockdBusHandler mockedUtils;
+    EXPECT_CALL(mockedUtils, getService(StrEq("/foo/bar"), _))
+        .Times(5)
+        .WillRepeatedly(Return("foo.bar"));
+
+    auto pdrRepo = pldm_pdr_init();
+    auto event = sdeventplus::Event::get_default();
+    Handler handler(&mockedUtils, "./pdr_jsons/state_effecter/good", pdrRepo,
+                    nullptr, nullptr, nullptr, nullptr, event);
+    Repo repo(pdrRepo);
+    ASSERT_EQ(repo.empty(), false);
+    auto response = handler.getPDR(req, requestPayloadLength);
+    auto responsePtr = reinterpret_cast<pldm_msg*>(response.data());
+
+    ASSERT_EQ(responsePtr->payload[0], PLDM_PLATFORM_INVALID_RECORD_HANDLE);
+
+    pldm_pdr_destroy(pdrRepo);
+}
+
+TEST(getPDR, testNoNextRecord)
+{
+    std::array<uint8_t, sizeof(pldm_msg_hdr) + PLDM_GET_PDR_REQ_BYTES>
+        requestPayload{};
+    auto req = reinterpret_cast<pldm_msg*>(requestPayload.data());
+    size_t requestPayloadLength = requestPayload.size() - sizeof(pldm_msg_hdr);
+
+    struct pldm_get_pdr_req* request =
+        reinterpret_cast<struct pldm_get_pdr_req*>(req->payload);
+    request->record_handle = 1;
+
+    MockdBusHandler mockedUtils;
+    EXPECT_CALL(mockedUtils, getService(StrEq("/foo/bar"), _))
+        .Times(5)
+        .WillRepeatedly(Return("foo.bar"));
+
+    auto pdrRepo = pldm_pdr_init();
+    auto event = sdeventplus::Event::get_default();
+    Handler handler(&mockedUtils, "./pdr_jsons/state_effecter/good", pdrRepo,
+                    nullptr, nullptr, nullptr, nullptr, event);
+    Repo repo(pdrRepo);
+    ASSERT_EQ(repo.empty(), false);
+    auto response = handler.getPDR(req, requestPayloadLength);
+    auto responsePtr = reinterpret_cast<pldm_msg*>(response.data());
+    struct pldm_get_pdr_resp* resp =
+        reinterpret_cast<struct pldm_get_pdr_resp*>(responsePtr->payload);
+    ASSERT_EQ(PLDM_SUCCESS, resp->completion_code);
+    ASSERT_EQ(2, resp->next_record_handle);
+
+    pldm_pdr_destroy(pdrRepo);
+}
+
+TEST(getPDR, testFindPDR)
+{
+    std::array<uint8_t, sizeof(pldm_msg_hdr) + PLDM_GET_PDR_REQ_BYTES>
+        requestPayload{};
+    auto req = reinterpret_cast<pldm_msg*>(requestPayload.data());
+    size_t requestPayloadLength = requestPayload.size() - sizeof(pldm_msg_hdr);
+
+    struct pldm_get_pdr_req* request =
+        reinterpret_cast<struct pldm_get_pdr_req*>(req->payload);
+    request->request_count = 100;
+
+    MockdBusHandler mockedUtils;
+    EXPECT_CALL(mockedUtils, getService(StrEq("/foo/bar"), _))
+        .Times(5)
+        .WillRepeatedly(Return("foo.bar"));
+
+    auto pdrRepo = pldm_pdr_init();
+    auto event = sdeventplus::Event::get_default();
+    Handler handler(&mockedUtils, "./pdr_jsons/state_effecter/good", pdrRepo,
+                    nullptr, nullptr, nullptr, nullptr, event);
+    Repo repo(pdrRepo);
+    ASSERT_EQ(repo.empty(), false);
+    auto response = handler.getPDR(req, requestPayloadLength);
+
+    // Let's try to find a PDR of type stateEffecter (= 11) and entity type =
+    // 100
+    bool found = false;
+    uint32_t handle = 0; // start asking for PDRs from recordHandle 0
+    while (!found)
+    {
+        request->record_handle = handle;
+        auto response = handler.getPDR(req, requestPayloadLength);
+        auto responsePtr = reinterpret_cast<pldm_msg*>(response.data());
+        struct pldm_get_pdr_resp* resp =
+            reinterpret_cast<struct pldm_get_pdr_resp*>(responsePtr->payload);
+        ASSERT_EQ(PLDM_SUCCESS, resp->completion_code);
+
+        handle = resp->next_record_handle; // point to the next pdr in case
+                                           // current is not what we want
+
+        pldm_pdr_hdr* hdr = reinterpret_cast<pldm_pdr_hdr*>(resp->record_data);
+        std::cerr << "PDR next record handle " << handle << "\n";
+        std::cerr << "PDR type " << hdr->type << "\n";
+        if (hdr->type == PLDM_STATE_EFFECTER_PDR)
+        {
+            pldm_state_effecter_pdr* pdr =
+                reinterpret_cast<pldm_state_effecter_pdr*>(resp->record_data);
+            std::cerr << "PDR entity type " << pdr->entity_type << "\n";
+            if (pdr->entity_type == 100)
+            {
+                found = true;
+                // Rest of the PDR can be accessed as need be
+                break;
+            }
+        }
+        if (!resp->next_record_handle) // no more records
+        {
+            break;
+        }
+    }
+    ASSERT_EQ(found, true);
+
+    pldm_pdr_destroy(pdrRepo);
+}
+
+TEST(setStateEffecterStatesHandler, testGoodRequest)
+{
+    std::array<uint8_t, sizeof(pldm_msg_hdr) + PLDM_GET_PDR_REQ_BYTES>
+        requestPayload{};
+    auto req = reinterpret_cast<pldm_msg*>(requestPayload.data());
+    size_t requestPayloadLength = requestPayload.size() - sizeof(pldm_msg_hdr);
+
+    MockdBusHandler mockedUtils;
+    EXPECT_CALL(mockedUtils, getService(StrEq("/foo/bar"), _))
+        .Times(5)
+        .WillRepeatedly(Return("foo.bar"));
+
+    auto inPDRRepo = pldm_pdr_init();
+    auto outPDRRepo = pldm_pdr_init();
+    Repo outRepo(outPDRRepo);
+    auto event = sdeventplus::Event::get_default();
+    Handler handler(&mockedUtils, "./pdr_jsons/state_effecter/good", inPDRRepo,
+                    nullptr, nullptr, nullptr, nullptr, event);
+    handler.getPDR(req, requestPayloadLength);
+    Repo inRepo(inPDRRepo);
+    getRepoByType(inRepo, outRepo, PLDM_STATE_EFFECTER_PDR);
+    pdr_utils::PdrEntry e;
+    auto record1 = pdr::getRecordByHandle(outRepo, 2, e);
+    ASSERT_NE(record1, nullptr);
+    pldm_state_effecter_pdr* pdr =
+        reinterpret_cast<pldm_state_effecter_pdr*>(e.data);
+    EXPECT_EQ(pdr->hdr.type, PLDM_STATE_EFFECTER_PDR);
+
+    std::vector<set_effecter_state_field> stateField;
+    stateField.push_back({PLDM_REQUEST_SET, 1});
+    stateField.push_back({PLDM_REQUEST_SET, 1});
+    std::string value = "xyz.openbmc_project.Foo.Bar.V1";
+    PropertyValue propertyValue = value;
+
+    DBusMapping dbusMapping{"/foo/bar", "xyz.openbmc_project.Foo.Bar",
+                            "propertyName", "string"};
+
+    EXPECT_CALL(mockedUtils, setDbusProperty(dbusMapping, propertyValue))
+        .Times(2);
+    auto rc = platform_state_effecter::setStateEffecterStatesHandler<
+        MockdBusHandler, Handler>(mockedUtils, handler, 0x1, stateField);
+    ASSERT_EQ(rc, 0);
+
+    pldm_pdr_destroy(inPDRRepo);
+    pldm_pdr_destroy(outPDRRepo);
+}
+
+TEST(setStateEffecterStatesHandler, testBadRequest)
+{
+    std::array<uint8_t, sizeof(pldm_msg_hdr) + PLDM_GET_PDR_REQ_BYTES>
+        requestPayload{};
+    auto req = reinterpret_cast<pldm_msg*>(requestPayload.data());
+    size_t requestPayloadLength = requestPayload.size() - sizeof(pldm_msg_hdr);
+
+    MockdBusHandler mockedUtils;
+    EXPECT_CALL(mockedUtils, getService(StrEq("/foo/bar"), _))
+        .Times(5)
+        .WillRepeatedly(Return("foo.bar"));
+
+    auto inPDRRepo = pldm_pdr_init();
+    auto outPDRRepo = pldm_pdr_init();
+    Repo outRepo(outPDRRepo);
+    auto event = sdeventplus::Event::get_default();
+    Handler handler(&mockedUtils, "./pdr_jsons/state_effecter/good", inPDRRepo,
+                    nullptr, nullptr, nullptr, nullptr, event);
+    handler.getPDR(req, requestPayloadLength);
+    Repo inRepo(inPDRRepo);
+    getRepoByType(inRepo, outRepo, PLDM_STATE_EFFECTER_PDR);
+    pdr_utils::PdrEntry e;
+    auto record1 = pdr::getRecordByHandle(outRepo, 2, e);
+    ASSERT_NE(record1, nullptr);
+    pldm_state_effecter_pdr* pdr =
+        reinterpret_cast<pldm_state_effecter_pdr*>(e.data);
+    EXPECT_EQ(pdr->hdr.type, PLDM_STATE_EFFECTER_PDR);
+
+    std::vector<set_effecter_state_field> stateField;
+    stateField.push_back({PLDM_REQUEST_SET, 3});
+    stateField.push_back({PLDM_REQUEST_SET, 4});
+
+    auto rc = platform_state_effecter::setStateEffecterStatesHandler<
+        MockdBusHandler, Handler>(mockedUtils, handler, 0x1, stateField);
+    ASSERT_EQ(rc, PLDM_PLATFORM_SET_EFFECTER_UNSUPPORTED_SENSORSTATE);
+
+    rc = platform_state_effecter::setStateEffecterStatesHandler<MockdBusHandler,
+                                                                Handler>(
+        mockedUtils, handler, 0x9, stateField);
+    ASSERT_EQ(rc, PLDM_PLATFORM_INVALID_EFFECTER_ID);
+
+    stateField.push_back({PLDM_REQUEST_SET, 4});
+    rc = platform_state_effecter::setStateEffecterStatesHandler<MockdBusHandler,
+                                                                Handler>(
+        mockedUtils, handler, 0x1, stateField);
+    ASSERT_EQ(rc, PLDM_ERROR_INVALID_DATA);
+
+    pldm_pdr_destroy(inPDRRepo);
+    pldm_pdr_destroy(outPDRRepo);
+}
+
+TEST(setNumericEffecterValueHandler, testGoodRequest)
+{
+    MockdBusHandler mockedUtils;
+    EXPECT_CALL(mockedUtils, getService(StrEq("/foo/bar"), _))
+        .Times(5)
+        .WillRepeatedly(Return("foo.bar"));
+
+    auto inPDRRepo = pldm_pdr_init();
+    auto numericEffecterPdrRepo = pldm_pdr_init();
+    Repo numericEffecterPDRs(numericEffecterPdrRepo);
+    auto event = sdeventplus::Event::get_default();
+    Handler handler(&mockedUtils, "./pdr_jsons/state_effecter/good", inPDRRepo,
+                    nullptr, nullptr, nullptr, nullptr, event);
+    Repo inRepo(inPDRRepo);
+    getRepoByType(inRepo, numericEffecterPDRs, PLDM_NUMERIC_EFFECTER_PDR);
+
+    pdr_utils::PdrEntry e;
+    auto record4 = pdr::getRecordByHandle(numericEffecterPDRs, 4, e);
+    ASSERT_NE(record4, nullptr);
+
+    pldm_numeric_effecter_value_pdr* pdr =
+        reinterpret_cast<pldm_numeric_effecter_value_pdr*>(e.data);
+    EXPECT_EQ(pdr->hdr.type, PLDM_NUMERIC_EFFECTER_PDR);
+
+    uint16_t effecterId = 3;
+    uint32_t effecterValue = 2100000000; // 2036-07-18 21:20:00
+    PropertyValue propertyValue = static_cast<uint32_t>(effecterValue);
+
+    DBusMapping dbusMapping{"/foo/bar", "xyz.openbmc_project.Foo.Bar",
+                            "propertyName", "uint64_t"};
+    EXPECT_CALL(mockedUtils, setDbusProperty(dbusMapping, propertyValue))
+        .Times(1);
+
+    auto rc = platform_numeric_effecter::setNumericEffecterValueHandler<
+        MockdBusHandler, Handler>(
+        mockedUtils, handler, effecterId, PLDM_EFFECTER_DATA_SIZE_UINT32,
+        reinterpret_cast<uint8_t*>(&effecterValue), 4);
+    ASSERT_EQ(rc, 0);
+
+    pldm_pdr_destroy(inPDRRepo);
+    pldm_pdr_destroy(numericEffecterPdrRepo);
+}
+
+TEST(setNumericEffecterValueHandler, testBadRequest)
+{
+    MockdBusHandler mockedUtils;
+    EXPECT_CALL(mockedUtils, getService(StrEq("/foo/bar"), _))
+        .Times(5)
+        .WillRepeatedly(Return("foo.bar"));
+
+    auto inPDRRepo = pldm_pdr_init();
+    auto numericEffecterPdrRepo = pldm_pdr_init();
+    Repo numericEffecterPDRs(numericEffecterPdrRepo);
+    auto event = sdeventplus::Event::get_default();
+    Handler handler(&mockedUtils, "./pdr_jsons/state_effecter/good", inPDRRepo,
+                    nullptr, nullptr, nullptr, nullptr, event);
+    Repo inRepo(inPDRRepo);
+    getRepoByType(inRepo, numericEffecterPDRs, PLDM_NUMERIC_EFFECTER_PDR);
+
+    pdr_utils::PdrEntry e;
+    auto record4 = pdr::getRecordByHandle(numericEffecterPDRs, 4, e);
+    ASSERT_NE(record4, nullptr);
+
+    pldm_numeric_effecter_value_pdr* pdr =
+        reinterpret_cast<pldm_numeric_effecter_value_pdr*>(e.data);
+    EXPECT_EQ(pdr->hdr.type, PLDM_NUMERIC_EFFECTER_PDR);
+
+    uint16_t effecterId = 3;
+    uint64_t effecterValue = 9876543210;
+    auto rc = platform_numeric_effecter::setNumericEffecterValueHandler<
+        MockdBusHandler, Handler>(
+        mockedUtils, handler, effecterId, PLDM_EFFECTER_DATA_SIZE_SINT32,
+        reinterpret_cast<uint8_t*>(&effecterValue), 3);
+    ASSERT_EQ(rc, PLDM_ERROR_INVALID_DATA);
+
+    pldm_pdr_destroy(inPDRRepo);
+    pldm_pdr_destroy(numericEffecterPdrRepo);
+}
+
+TEST(parseStateSensor, allScenarios)
+{
+    // Sample state sensor with SensorID - 1, EntityType - Processor Module(67)
+    // State Set ID - Operational Running Status(11), Supported States - 3,4
+    std::vector<uint8_t> sample1PDR{0x00, 0x00, 0x00, 0x00, 0x01, 0x04, 0x00,
+                                    0x00, 0x17, 0x00, 0x00, 0x00, 0x01, 0x00,
+                                    0x43, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00,
+                                    0x00, 0x01, 0x0b, 0x00, 0x01, 0x18};
+
+    const auto& [terminusHandle1, sensorID1, sensorInfo1] =
+        parseStateSensorPDR(sample1PDR);
+    const auto& [containerID1, entityType1, entityInstance1] =
+        std::get<0>(sensorInfo1);
+    const auto& states1 = std::get<1>(sensorInfo1);
+    CompositeSensorStates statesCmp1{{3u, 4u}};
+
+    ASSERT_EQ(le16toh(terminusHandle1), 0u);
+    ASSERT_EQ(le16toh(sensorID1), 1u);
+    ASSERT_EQ(le16toh(containerID1), 0u);
+    ASSERT_EQ(le16toh(entityType1), 67u);
+    ASSERT_EQ(le16toh(entityInstance1), 1u);
+    ASSERT_EQ(states1, statesCmp1);
+
+    // Sample state sensor with SensorID - 2, EntityType - System Firmware(31)
+    // State Set ID - Availability(2), Supported States - 3,4,9,10,11,13
+    std::vector<uint8_t> sample2PDR{0x00, 0x00, 0x00, 0x00, 0x01, 0x04, 0x00,
+                                    0x00, 0x17, 0x00, 0x00, 0x00, 0x02, 0x00,
+                                    0x1F, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00,
+                                    0x00, 0x01, 0x02, 0x00, 0x02, 0x18, 0x2E};
+
+    const auto& [terminusHandle2, sensorID2, sensorInfo2] =
+        parseStateSensorPDR(sample2PDR);
+    const auto& [containerID2, entityType2, entityInstance2] =
+        std::get<0>(sensorInfo2);
+    const auto& states2 = std::get<1>(sensorInfo2);
+    CompositeSensorStates statesCmp2{{3u, 4u, 9u, 10u, 11u, 13u}};
+
+    ASSERT_EQ(le16toh(terminusHandle2), 0u);
+    ASSERT_EQ(le16toh(sensorID2), 2u);
+    ASSERT_EQ(le16toh(containerID2), 0u);
+    ASSERT_EQ(le16toh(entityType2), 31u);
+    ASSERT_EQ(le16toh(entityInstance2), 1u);
+    ASSERT_EQ(states2, statesCmp2);
+
+    // Sample state sensor with SensorID - 3, EntityType - Virtual Machine
+    // Manager(33), Composite State Sensor -2 , State Set ID - Link State(33),
+    // Supported States - 1,2, State Set ID - Configuration State(15),
+    // Supported States - 1,2,3,4
+    std::vector<uint8_t> sample3PDR{
+        0x00, 0x00, 0x00, 0x00, 0x01, 0x04, 0x00, 0x00, 0x17, 0x00, 0x00,
+        0x00, 0x03, 0x00, 0x21, 0x00, 0x02, 0x00, 0x01, 0x00, 0x00, 0x00,
+        0x02, 0x21, 0x00, 0x01, 0x06, 0x0F, 0x00, 0x01, 0x1E};
+
+    const auto& [terminusHandle3, sensorID3, sensorInfo3] =
+        parseStateSensorPDR(sample3PDR);
+    const auto& [containerID3, entityType3, entityInstance3] =
+        std::get<0>(sensorInfo3);
+    const auto& states3 = std::get<1>(sensorInfo3);
+    CompositeSensorStates statesCmp3{{1u, 2u}, {1u, 2u, 3u, 4u}};
+
+    ASSERT_EQ(le16toh(terminusHandle3), 0u);
+    ASSERT_EQ(le16toh(sensorID3), 3u);
+    ASSERT_EQ(le16toh(containerID3), 1u);
+    ASSERT_EQ(le16toh(entityType3), 33u);
+    ASSERT_EQ(le16toh(entityInstance3), 2u);
+    ASSERT_EQ(states3, statesCmp3);
+}
+
+TEST(StateSensorHandler, allScenarios)
+{
+    using namespace pldm::responder::events;
+
+    StateSensorHandler handler{"./event_jsons/good"};
+    constexpr uint8_t eventState0 = 0;
+    constexpr uint8_t eventState1 = 1;
+    constexpr uint8_t eventState2 = 2;
+    constexpr uint8_t eventState3 = 3;
+
+    // Event Entry 1
+    {
+        StateSensorEntry entry{1, 64, 1, 0};
+        const auto& [dbusMapping, eventStateMap] = handler.getEventInfo(entry);
+        DBusMapping mapping{"/xyz/abc/def",
+                            "xyz.openbmc_project.example1.value", "value1",
+                            "string"};
+        ASSERT_EQ(mapping == dbusMapping, true);
+
+        const auto& propValue0 = eventStateMap.at(eventState0);
+        const auto& propValue1 = eventStateMap.at(eventState1);
+        const auto& propValue2 = eventStateMap.at(eventState2);
+        PropertyValue value0{std::in_place_type<std::string>,
+                             "xyz.openbmc_project.State.Normal"};
+        PropertyValue value1{std::in_place_type<std::string>,
+                             "xyz.openbmc_project.State.Critical"};
+        PropertyValue value2{std::in_place_type<std::string>,
+                             "xyz.openbmc_project.State.Fatal"};
+        ASSERT_EQ(value0 == propValue0, true);
+        ASSERT_EQ(value1 == propValue1, true);
+        ASSERT_EQ(value2 == propValue2, true);
+    }
+
+    // Event Entry 2
+    {
+        StateSensorEntry entry{1, 64, 1, 1};
+        const auto& [dbusMapping, eventStateMap] = handler.getEventInfo(entry);
+        DBusMapping mapping{"/xyz/abc/def",
+                            "xyz.openbmc_project.example2.value", "value2",
+                            "uint8_t"};
+        ASSERT_EQ(mapping == dbusMapping, true);
+
+        const auto& propValue0 = eventStateMap.at(eventState2);
+        const auto& propValue1 = eventStateMap.at(eventState3);
+        PropertyValue value0{std::in_place_type<uint8_t>, 9};
+        PropertyValue value1{std::in_place_type<uint8_t>, 10};
+        ASSERT_EQ(value0 == propValue0, true);
+        ASSERT_EQ(value1 == propValue1, true);
+    }
+
+    // Event Entry 3
+    {
+        StateSensorEntry entry{2, 67, 2, 0};
+        const auto& [dbusMapping, eventStateMap] = handler.getEventInfo(entry);
+        DBusMapping mapping{"/xyz/abc/ghi",
+                            "xyz.openbmc_project.example3.value", "value3",
+                            "bool"};
+        ASSERT_EQ(mapping == dbusMapping, true);
+
+        const auto& propValue0 = eventStateMap.at(eventState0);
+        const auto& propValue1 = eventStateMap.at(eventState1);
+        PropertyValue value0{std::in_place_type<bool>, false};
+        PropertyValue value1{std::in_place_type<bool>, true};
+        ASSERT_EQ(value0 == propValue0, true);
+        ASSERT_EQ(value1 == propValue1, true);
+    }
+
+    // Invalid Entry
+    {
+        StateSensorEntry entry{0, 0, 0, 0};
+        ASSERT_THROW(handler.getEventInfo(entry), std::out_of_range);
+    }
+}
+
+TEST(TerminusLocatorPDR, BMCTerminusLocatorPDR)
+{
+    auto inPDRRepo = pldm_pdr_init();
+    auto outPDRRepo = pldm_pdr_init();
+    Repo outRepo(outPDRRepo);
+    MockdBusHandler mockedUtils;
+    auto event = sdeventplus::Event::get_default();
+    Handler handler(&mockedUtils, "", inPDRRepo, nullptr, nullptr, nullptr,
+                    nullptr, event);
+    Repo inRepo(inPDRRepo);
+    getRepoByType(inRepo, outRepo, PLDM_TERMINUS_LOCATOR_PDR);
+
+    // 1 BMC terminus locator PDR in the PDR repository
+    ASSERT_EQ(outRepo.getRecordCount(), 1);
+
+    pdr_utils::PdrEntry entry;
+    auto record = pdr::getRecordByHandle(outRepo, 1, entry);
+    ASSERT_NE(record, nullptr);
+
+    auto pdr = reinterpret_cast<const pldm_terminus_locator_pdr*>(entry.data);
+    EXPECT_EQ(pdr->hdr.record_handle, 1);
+    EXPECT_EQ(pdr->hdr.version, 1);
+    EXPECT_EQ(pdr->hdr.type, PLDM_TERMINUS_LOCATOR_PDR);
+    EXPECT_EQ(pdr->hdr.record_change_num, 0);
+    EXPECT_EQ(pdr->hdr.length,
+              sizeof(pldm_terminus_locator_pdr) - sizeof(pldm_pdr_hdr));
+    EXPECT_EQ(pdr->terminus_handle, BmcPldmTerminusHandle);
+    EXPECT_EQ(pdr->validity, PLDM_TL_PDR_VALID);
+    EXPECT_EQ(pdr->tid, BmcTerminusId);
+    EXPECT_EQ(pdr->container_id, 0);
+    EXPECT_EQ(pdr->terminus_locator_type, PLDM_TERMINUS_LOCATOR_TYPE_MCTP_EID);
+    EXPECT_EQ(pdr->terminus_locator_value_size,
+              sizeof(pldm_terminus_locator_type_mctp_eid));
+    auto locatorValue =
+        reinterpret_cast<const pldm_terminus_locator_type_mctp_eid*>(
+            pdr->terminus_locator_value);
+    EXPECT_EQ(locatorValue->eid, BmcMctpEid);
+    pldm_pdr_destroy(inPDRRepo);
+    pldm_pdr_destroy(outPDRRepo);
+}
+
+TEST(getStateSensorReadingsHandler, testGoodRequest)
+{
+    MockdBusHandler mockedUtils;
+    EXPECT_CALL(mockedUtils, getService(StrEq("/foo/bar"), _))
+        .Times(1)
+        .WillRepeatedly(Return("foo.bar"));
+
+    auto inPDRRepo = pldm_pdr_init();
+    auto outPDRRepo = pldm_pdr_init();
+    Repo outRepo(outPDRRepo);
+    auto event = sdeventplus::Event::get_default();
+    Handler handler(&mockedUtils, "./pdr_jsons/state_sensor/good", inPDRRepo,
+                    nullptr, nullptr, nullptr, nullptr, event);
+    Repo inRepo(inPDRRepo);
+    getRepoByType(inRepo, outRepo, PLDM_STATE_SENSOR_PDR);
+    pdr_utils::PdrEntry e;
+    auto record = pdr::getRecordByHandle(outRepo, 2, e);
+    ASSERT_NE(record, nullptr);
+    pldm_state_sensor_pdr* pdr =
+        reinterpret_cast<pldm_state_sensor_pdr*>(e.data);
+    EXPECT_EQ(pdr->hdr.type, PLDM_STATE_SENSOR_PDR);
+
+    std::vector<get_sensor_state_field> stateField;
+    uint8_t compSensorCnt{};
+    uint8_t sensorRearmCnt = 1;
+
+    MockdBusHandler handlerObj;
+    EXPECT_CALL(handlerObj,
+                getDbusPropertyVariant(StrEq("/foo/bar"), StrEq("propertyName"),
+                                       StrEq("xyz.openbmc_project.Foo.Bar")))
+        .WillOnce(Return(
+            PropertyValue(std::string("xyz.openbmc_project.Foo.Bar.V0"))));
+
+    auto rc = platform_state_sensor::getStateSensorReadingsHandler<
+        MockdBusHandler, Handler>(handlerObj, handler, 0x1, sensorRearmCnt,
+                                  compSensorCnt, stateField);
+    ASSERT_EQ(rc, 0);
+    ASSERT_EQ(compSensorCnt, 1);
+    ASSERT_EQ(stateField[0].sensor_op_state, PLDM_SENSOR_UNAVAILABLE);
+    ASSERT_EQ(stateField[0].present_state, PLDM_SENSOR_NORMAL);
+    ASSERT_EQ(stateField[0].previous_state, PLDM_SENSOR_UNKNOWN);
+    ASSERT_EQ(stateField[0].event_state, PLDM_SENSOR_UNKNOWN);
+
+    pldm_pdr_destroy(inPDRRepo);
+    pldm_pdr_destroy(outPDRRepo);
+}
+
+TEST(getStateSensorReadingsHandler, testBadRequest)
+{
+    MockdBusHandler mockedUtils;
+    EXPECT_CALL(mockedUtils, getService(StrEq("/foo/bar"), _))
+        .Times(1)
+        .WillRepeatedly(Return("foo.bar"));
+
+    auto inPDRRepo = pldm_pdr_init();
+    auto outPDRRepo = pldm_pdr_init();
+    Repo outRepo(outPDRRepo);
+    auto event = sdeventplus::Event::get_default();
+    Handler handler(&mockedUtils, "./pdr_jsons/state_sensor/good", inPDRRepo,
+                    nullptr, nullptr, nullptr, nullptr, event);
+    Repo inRepo(inPDRRepo);
+    getRepoByType(inRepo, outRepo, PLDM_STATE_SENSOR_PDR);
+    pdr_utils::PdrEntry e;
+    auto record = pdr::getRecordByHandle(outRepo, 2, e);
+    ASSERT_NE(record, nullptr);
+    pldm_state_sensor_pdr* pdr =
+        reinterpret_cast<pldm_state_sensor_pdr*>(e.data);
+    EXPECT_EQ(pdr->hdr.type, PLDM_STATE_SENSOR_PDR);
+
+    std::vector<get_sensor_state_field> stateField;
+    uint8_t compSensorCnt{};
+    uint8_t sensorRearmCnt = 3;
+
+    MockdBusHandler handlerObj;
+    auto rc = platform_state_sensor::getStateSensorReadingsHandler<
+        MockdBusHandler, Handler>(handlerObj, handler, 0x1, sensorRearmCnt,
+                                  compSensorCnt, stateField);
+    ASSERT_EQ(rc, PLDM_PLATFORM_REARM_UNAVAILABLE_IN_PRESENT_STATE);
+
+    pldm_pdr_destroy(inPDRRepo);
+    pldm_pdr_destroy(outPDRRepo);
+}
diff --git a/libpldmresponder/test/meson.build b/libpldmresponder/test/meson.build
new file mode 100644
index 0000000..623e28e
--- /dev/null
+++ b/libpldmresponder/test/meson.build
@@ -0,0 +1,46 @@
+tests = [
+  'libpldmresponder_base_test',
+  'libpldmresponder_bios_test',
+  'libpldmresponder_bios_attribute_test',
+  'libpldmresponder_bios_config_test',
+  'libpldmresponder_bios_enum_attribute_test',
+  'libpldmresponder_bios_integer_attribute_test',
+  'libpldmresponder_bios_string_attribute_test',
+  'libpldmresponder_bios_table_test',
+  'libpldmresponder_fru_test',
+  'libpldmresponder_platform_test',
+  'libpldmresponder_pdr_effecter_test',
+  'libpldmresponder_pdr_sensor_test',
+]
+
+if get_option('oem-ibm').enabled()
+  tests += [
+    '../../oem/ibm/test/libpldmresponder_fileio_test',
+    '../../oem/ibm/test/libpldmresponder_oem_platform_test'
+  ]
+endif
+
+  dep_src_files = [
+  '../../pldmd/instance_id.cpp',
+  '../../pldmd/dbus_impl_requester.cpp'
+  ]
+dep_src = declare_dependency(sources: dep_src_files)
+
+foreach t : tests
+  test(t, executable(t.underscorify(), t + '.cpp',
+                     implicit_include_directories: false,
+                     link_args: dynamic_linker,
+                     build_rpath: get_option('oe-sdk').enabled() ? rpath : '',
+                     dependencies: [
+                         dep_src,
+                         libpldm_dep,
+                         libpldmresponder,
+                         libpldmutils,
+                         gtest,
+                         gmock,
+                         nlohmann_json,
+                         phosphor_dbus_interfaces,
+                         sdeventplus,
+                         sdbusplus]),
+       workdir: meson.current_source_dir())
+endforeach
diff --git a/libpldmresponder/test/mocked_bios.hpp b/libpldmresponder/test/mocked_bios.hpp
new file mode 100644
index 0000000..6741306
--- /dev/null
+++ b/libpldmresponder/test/mocked_bios.hpp
@@ -0,0 +1,58 @@
+#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));
+
+    MOCK_METHOD(std::string, findString, (const uint16_t), (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/libpldmresponder/test/pdr_jsons/state_effecter/good/effecter_pdr.json b/libpldmresponder/test/pdr_jsons/state_effecter/good/effecter_pdr.json
new file mode 100644
index 0000000..1514a59
--- /dev/null
+++ b/libpldmresponder/test/pdr_jsons/state_effecter/good/effecter_pdr.json
@@ -0,0 +1,127 @@
+{
+    "effecterPDRs": [
+        {
+            "pdrType": 11,
+            "entries": [
+                {
+                    "entity_path": "/xyz/openbmc_project/foo",
+                    "type": 33,
+                    "instance": 0,
+                    "container": 0,
+                    "effecters": [
+                        {
+                            "set": {
+                                "id": 196,
+                                "size": 1,
+                                "states": [
+                                    1
+                                ]
+                            },
+                            "dbus": {
+                                "path": "/foo/bar",
+                                "interface": "xyz.openbmc_project.Foo.Bar",
+                                "property_name": "propertyName",
+                                "property_type": "string",
+                                "property_values": [
+                                    "xyz.openbmc_project.Foo.Bar.V1"
+                                ]
+                            }
+                        },
+                        {
+                            "set": {
+                                "id": 196,
+                                "size": 1,
+                                "states": [
+                                    1,
+                                    2
+                                ]
+                            },
+                            "dbus": {
+                                "path": "/foo/bar",
+                                "interface": "xyz.openbmc_project.Foo.Bar",
+                                "property_name": "propertyName",
+                                "property_type": "string",
+                                "property_values": [
+                                    "xyz.openbmc_project.Foo.Bar.V1",
+                                    "xyz.openbmc_project.Foo.Bar.V2"
+                                ]
+                            }
+                        }
+                    ]
+                },
+                {
+                    "entity_path": "/xyz/openbmc_project/foo",
+                    "type": 100,
+                    "instance": 0,
+                    "container": 0,
+                    "effecters": [
+                        {
+                            "set": {
+                                "id": 197,
+                                "size": 1,
+                                "states": [
+                                    1
+                                ]
+                            },
+                            "dbus": {
+                                "path": "/foo/bar",
+                                "interface": "xyz.openbmc_project.Foo.Bar",
+                                "property_name": "propertyName",
+                                "property_type": "string",
+                                "property_values": [
+                                    "xyz.openbmc_project.Foo.Bar.V1"
+                                ]
+                            }
+                        },
+                        {
+                            "set": {
+                                "id": 198,
+                                "size": 2,
+                                "states": [
+                                    1,
+                                    2,
+                                    5,
+                                    15
+                                ]
+                            },
+                            "dbus": {
+                                "path": "/foo/bar",
+                                "interface": "xyz.openbmc_project.Foo.Bar.Baz",
+                                "property_name": "propertyName",
+                                "property_type": "string",
+                                "property_values": [
+                                    "xyz.openbmc_project.Foo.Bar.Baz.V1",
+                                    "xyz.openbmc_project.Foo.Bar.Baz.V2",
+                                    "xyz.openbmc_project.Foo.Bar.Baz.V5",
+                                    "xyz.openbmc_project.Foo.Bar.Baz.V15"
+                                ]
+                            }
+                        }
+                    ]
+                }
+            ]
+        },
+        {
+            "pdrType": 9,
+            "entries": [
+                {
+                    "entity_path": "/xyz/openbmc_project/foo",
+                    "type": 0,
+                    "instance": 0,
+                    "container": 0,
+                    "base_unit": 21,
+                    "rate_unit": 3,
+                    "effecter_resolution_init": 1,
+                    "effecter_data_size": 4,
+                    "range_field_format": 4,
+                    "dbus": {
+                        "path": "/foo/bar",
+                        "interface": "xyz.openbmc_project.Foo.Bar",
+                        "property_name": "propertyName",
+                        "property_type": "uint64_t"
+                    }
+                }
+            ]
+        }
+    ]
+}
\ No newline at end of file
diff --git a/libpldmresponder/test/pdr_jsons/state_effecter/malformed/effecter_pdr.json b/libpldmresponder/test/pdr_jsons/state_effecter/malformed/effecter_pdr.json
new file mode 100644
index 0000000..826e27a
--- /dev/null
+++ b/libpldmresponder/test/pdr_jsons/state_effecter/malformed/effecter_pdr.json
@@ -0,0 +1,127 @@
+{
+    "effecterPDRs": [
+        {
+            "pdrType": 11,
+            "entries": [
+                {
+                    "entity_path": "/xyz/openbmc_project/foo",
+                    "type": 33
+                    "instance": 0,
+                    "container": 0,
+                    "effecters": [
+                        {
+                            "set": {
+                                "id": 196,
+                                "size": 1,
+                                "states": [
+                                    1
+                                ]
+                            },
+                            "dbus": {
+                                "path": "/foo/bar",
+                                "interface": "xyz.openbmc_project.Foo.Bar",
+                                "property_name": "propertyName",
+                                "property_type": "string",
+                                "property_values": [
+                                    "xyz.openbmc_project.Foo.Bar.V1"
+                                ]
+                            }
+                        },
+                        {
+                            "set": {
+                                "id": 196,
+                                "size": 1,
+                                "states": [
+                                    1,
+                                    2
+                                ]
+                            },
+                            "dbus": {
+                                "path": "/foo/bar",
+                                "interface": "xyz.openbmc_project.Foo.Bar",
+                                "property_name": "propertyName",
+                                "property_type": "string",
+                                "property_values": [
+                                    "xyz.openbmc_project.Foo.Bar.V1",
+                                    "xyz.openbmc_project.Foo.Bar.V2"
+                                ]
+                            }
+                        }
+                    ]
+                },
+                {
+                    "entity_path": "/xyz/openbmc_project/foo",
+                    "type": 100,
+                    "instance": 0,
+                    "container": 0,
+                    "effecters": [
+                        {
+                            "set": {
+                                "id": 197,
+                                "size": 1,
+                                "states": [
+                                    1
+                                ]
+                            },
+                            "dbus": {
+                                "path": "/foo/bar",
+                                "interface": "xyz.openbmc_project.Foo.Bar",
+                                "property_name": "propertyName",
+                                "property_type": "string",
+                                "property_values": [
+                                    "xyz.openbmc_project.Foo.Bar.V1"
+                                ]
+                            }
+                        },
+                        {
+                            "set": {
+                                "id": 198,
+                                "size": 2,
+                                "states": [
+                                    1,
+                                    2,
+                                    5,
+                                    15
+                                ]
+                            },
+                            "dbus": {
+                                "path": "/foo/bar",
+                                "interface": "xyz.openbmc_project.Foo.Bar.Baz",
+                                "property_name": "propertyName",
+                                "property_type": "string",
+                                "property_values": [
+                                    "xyz.openbmc_project.Foo.Bar.Baz.V1",
+                                    "xyz.openbmc_project.Foo.Bar.Baz.V2",
+                                    "xyz.openbmc_project.Foo.Bar.Baz.V5",
+                                    "xyz.openbmc_project.Foo.Bar.Baz.V15"
+                                ]
+                            }
+                        }
+                    ]
+                }
+            ]
+        },
+        {
+            "pdrType": 9,
+            "entries": [
+                {
+                    "entity_path": "/xyz/openbmc_project/foo",
+                    "type": 0,
+                    "instance": 0,
+                    "container": 0,
+                    "base_unit": 21,
+                    "rate_unit": 3,
+                    "effecter_resolution_init": 1,
+                    "effecter_data_size": 4,
+                    "range_field_format": 4,
+                    "dbus": {
+                        "path": "/foo/bar",
+                        "interface": "xyz.openbmc_project.Foo.Bar",
+                        "property_name": "propertyName",
+                        "property_type": "uint64_t"
+                    }
+                }
+            ]
+        }
+    ]
+}
\ No newline at end of file
diff --git a/libpldmresponder/test/pdr_jsons/state_sensor/good/sensor_pdr.json b/libpldmresponder/test/pdr_jsons/state_sensor/good/sensor_pdr.json
new file mode 100644
index 0000000..5e1141a
--- /dev/null
+++ b/libpldmresponder/test/pdr_jsons/state_sensor/good/sensor_pdr.json
@@ -0,0 +1,36 @@
+{
+  "sensorPDRs": [
+    {
+      "pdrType": 4,
+      "entries": [
+        {
+          "type": 5,
+          "instance": 0,
+          "container": 0,
+          "sensors": [
+            {
+              "set": {
+                "id": 1,
+                "size": 1,
+                "states": [
+                  0,
+                  5
+                ]
+              },
+              "dbus": {
+                "path": "/foo/bar",
+                "interface": "xyz.openbmc_project.Foo.Bar",
+                "property_name": "propertyName",
+                "property_type": "string",
+                "property_values": [
+                  "xyz.openbmc_project.Foo.Bar.V0",
+                  "xyz.openbmc_project.Foo.Bar.V5"
+                ]
+              }
+            }
+          ]
+        }
+      ]
+    }
+  ]
+}
\ No newline at end of file
diff --git a/libpldmresponder/test/pdr_jsons/state_sensor/malformed/sensor_pdr.json b/libpldmresponder/test/pdr_jsons/state_sensor/malformed/sensor_pdr.json
new file mode 100644
index 0000000..6d5a941
--- /dev/null
+++ b/libpldmresponder/test/pdr_jsons/state_sensor/malformed/sensor_pdr.json
@@ -0,0 +1,44 @@
+# This JSON is tied with BMC's PDRs. Each entry is used to identify a group of
+# composite sensors.
+{
+  "sensorPDRs": [
+    {
+      # StateSensorPDR
+      # Each sensor in each group of composite sensors has a separate entry and the
+      # supported event states, up to eight.
+      # The "dbus" section contains information about the corresponding D-Bus
+      # property for the sensor and "property_values" are the D-Bus property values
+      # for each corresponding entry in the "states".
+      "pdrType": 4
+      "entries": [
+        {
+          "type": 5,
+          "instance": 0,
+          "container": 0,
+          "sensors": [
+            {
+              "set": {
+                "id": 1,
+                "size": 1,
+                "states": [
+                  0,
+                  5
+                ]
+              },
+              "dbus": {
+                "path": "/foo/bar",
+                "interface": "xyz.openbmc_project.Foo.Bar",
+                "property_name": "propertyName",
+                "property_type": "string",
+                "property_values": [
+                  "xyz.openbmc_project.Foo.Bar.V0",
+                  "xyz.openbmc_project.Foo.Bar.V5"
+                ]
+              }
+            }
+          ]
+        }
+      ]
+    }
+  ]
+}
\ No newline at end of file