[SOC_RESET_ME] Add the event handler - part1

Implement SOC_RESET_ME event handler baseline function:
cold reset the host, will ingore the reset quest in case the request
received within reset quiescent period setup by previous reset request.
log request and process result in journal.

tested using bios with tested ebf, with following journal
```
#CN 1
root@mvt18-nfd11:~# journalctl -u *pldmd*0* -o json | jq -r '. | select(.SOC_RESET_ME != null and .SOC_RESET_ME == "request") | with_entries(select(.key | startswith("SOC_RESET_ME"))) '{
  "SOC_RESET_ME_QUIESCENT_PERIOD": "4",
  "SOC_RESET_ME_RESET_REASON": "TEST",
  "SOC_RESET_ME_RESET_TYPE": "0",
  "SOC_RESET_ME": "request",
  "SOC_RESET_ME_SOCID": "1",
  "SOC_RESET_ME_INTERNAL_INFO": "0x0102030405060708"
}
{
  "SOC_RESET_ME_RESET_REASON": "TEST",
  "SOC_RESET_ME_RESET_TYPE": "0",
  "SOC_RESET_ME_SOCID": "1",
  "SOC_RESET_ME_INTERNAL_INFO": "0x0102030405060708",
  "SOC_RESET_ME": "request",
  "SOC_RESET_ME_QUIESCENT_PERIOD": "4"
}
{
  "SOC_RESET_ME": "request",
  "SOC_RESET_ME_SOCID": "1",
  "SOC_RESET_ME_QUIESCENT_PERIOD": "4",
  "SOC_RESET_ME_RESET_REASON": "TEST",
  "SOC_RESET_ME_RESET_TYPE": "0",
  "SOC_RESET_ME_INTERNAL_INFO": "0x0102030405060708"
}
{
  "SOC_RESET_ME_SOCID": "1",
  "SOC_RESET_ME": "request",
  "SOC_RESET_ME_INTERNAL_INFO": "0x0102030405060708",
  "SOC_RESET_ME_RESET_REASON": "TEST",
  "SOC_RESET_ME_RESET_TYPE": "0",
  "SOC_RESET_ME_QUIESCENT_PERIOD": "4"
}
{
  "SOC_RESET_ME": "request",
  "SOC_RESET_ME_SOCID": "1",
  "SOC_RESET_ME_QUIESCENT_PERIOD": "4",
  "SOC_RESET_ME_INTERNAL_INFO": "0x0102030405060708",
  "SOC_RESET_ME_RESET_TYPE": "0",
  "SOC_RESET_ME_RESET_REASON": "TEST"
}

# CN2
root@mvt18-nfd11:~# journalctl -u *pldmd*1* -o json | jq -r '. | select(.SOC_RESET_ME != null and .SOC_RESET_ME == "request") | with_entries(select(.key | startswith("SOC_RESET_ME"))) '{
  "SOC_RESET_ME": "request",
  "SOC_RESET_ME_RESET_TYPE": "0",
  "SOC_RESET_ME_RESET_REASON": "TEST",
  "SOC_RESET_ME_SOCID": "2",
  "SOC_RESET_ME_INTERNAL_INFO": "0x0102030405060708",
  "SOC_RESET_ME_QUIESCENT_PERIOD": "4"
}
{
  "SOC_RESET_ME_SOCID": "2",
  "SOC_RESET_ME_RESET_TYPE": "0",
  "SOC_RESET_ME_INTERNAL_INFO": "0x0102030405060708",
  "SOC_RESET_ME_QUIESCENT_PERIOD": "4",
  "SOC_RESET_ME": "request",
  "SOC_RESET_ME_RESET_REASON": "TEST"
}
{
  "SOC_RESET_ME": "request",
  "SOC_RESET_ME_RESET_TYPE": "0",
  "SOC_RESET_ME_SOCID": "2",
  "SOC_RESET_ME_INTERNAL_INFO": "0x0102030405060708",
  "SOC_RESET_ME_RESET_REASON": "TEST",
  "SOC_RESET_ME_QUIESCENT_PERIOD": "4"
}
{
  "SOC_RESET_ME": "request",
  "SOC_RESET_ME_SOCID": "2",
  "SOC_RESET_ME_INTERNAL_INFO": "0x0102030405060708",
  "SOC_RESET_ME_RESET_REASON": "TEST",
  "SOC_RESET_ME_RESET_TYPE": "0",
  "SOC_RESET_ME_QUIESCENT_PERIOD": "4"
}
{
  "SOC_RESET_ME_INTERNAL_INFO": "0x0102030405060708",
  "SOC_RESET_ME_RESET_REASON": "TEST",
  "SOC_RESET_ME_RESET_TYPE": "0",
  "SOC_RESET_ME": "request",
  "SOC_RESET_ME_QUIESCENT_PERIOD": "4",
  "SOC_RESET_ME_SOCID": "2"
}
root@mvt18-nfd11:~#
```
Google-Bug-Id: 303898284
Change-Id: I345ae18e6dff6c89c587903d5f306e1321885442
Signed-off-by: Dan Zhang <zhdaniel@google.com>
diff --git a/meson.build b/meson.build
index 8acb6b2..3dce8c1 100644
--- a/meson.build
+++ b/meson.build
@@ -11,9 +11,20 @@
 
 install_headers(handler_hdrs, subdir: 'pldm-oem-google')
 
+phosphor_logging_dep = dependency('phosphor-logging')
+sdbusplus_dep = dependency('sdbusplus')
+
+pldm_oem_google_lib_pre = declare_dependency (
+  include_directories: '.',
+  dependencies: [
+    phosphor_logging_dep,
+    sdbusplus_dep,
+  ],
+)
 pldm_oem_google_lib = static_library('pldm-oem-google',
     'src/pldm-oem-google.cpp',
     'src/soc-reset-me.cpp',
+    dependencies: pldm_oem_google_lib_pre,
     install: true)
 
 pkg = import('pkgconfig')
@@ -24,6 +35,7 @@
 
 pldm_oem_google_dep = declare_dependency(
     include_directories: '.',
+    dependencies: pldm_oem_google_lib_pre,
     link_with: pldm_oem_google_lib)
 
 if not get_option('tests').disabled()
diff --git a/src/soc-reset-me.cpp b/src/soc-reset-me.cpp
index 4ea9585..25e0964 100644
--- a/src/soc-reset-me.cpp
+++ b/src/soc-reset-me.cpp
@@ -15,8 +15,15 @@
  */
 #include "soc-reset-me.hpp"
 
-#include <exception>
+#include "phosphor-logging/lg2/flags.hpp"
 
+#include <phosphor-logging/lg2.hpp>
+
+#include <chrono>
+#include <exception>
+#include <string>
+#include <variant>
+using namespace std::literals;
 namespace pldm_oem_google
 {
 namespace soc_reset_me
@@ -53,5 +60,132 @@
     return ret;
 }
 
+static constexpr struct ResetDBusParams socResetDbusParamsCn1 = {
+    .conn = "xyz.openbmc_project.State.Host1",
+    .path = "/xyz/openbmc_project/state/host1",
+    .intf = "xyz.openbmc_project.State.Host",
+    .prop = "RequestedHostTransition",
+};
+const ResetDBusParams* cn1DbusParams(void)
+{
+    return &socResetDbusParamsCn1;
+}
+
+static constexpr struct ResetDBusParams socResetDbusParamsCn2 = {
+    .conn = "xyz.openbmc_project.State.Host2",
+    .path = "/xyz/openbmc_project/state/host2",
+    .intf = "xyz.openbmc_project.State.Host",
+    .prop = "RequestedHostTransition",
+};
+const ResetDBusParams* cn2DbusParams(void)
+{
+    return &socResetDbusParamsCn2;
+}
+
+SocResetMeHandler::SocResetMeHandler(const SocId id, sdbusplus::bus_t&& b) :
+    socId(id), bus(std::forward<sdbusplus::bus_t>(b)),
+    quiescentEnd(std::chrono::steady_clock::now())
+{
+    switch (socId)
+    {
+        case SocId::cn1:
+            dbusParams = &socResetDbusParamsCn1;
+            break;
+        case SocId::cn2:
+            dbusParams = &socResetDbusParamsCn2;
+            break;
+        default:
+            throw InvalidSoCIdException(static_cast<int>(socId));
+    }
+}
+
+void SocResetMeHandler::handle(
+    [[maybe_unused]] uint8_t requesterTid,
+    [[maybe_unused]] const struct pldm_event_oem_google_soc_reset_me*
+        resetMeMsg,
+    [[maybe_unused]] size_t resetMeMsgLen)
+{
+    auto requestTime = std::chrono::steady_clock::now();
+    auto resetReason = std::string(reinterpret_cast<const char*>(resetMeMsg) +
+                                       sizeof(*resetMeMsg),
+                                   resetMeMsg->descLen);
+    logRequest(resetMeMsg->internalInfo, resetMeMsg->resetType,
+               resetMeMsg->resetQuiesent, resetReason);
+    // Handle the event
+    if (requestTime <= quiescentEnd)
+    {
+        logRequestIgnored(requestTime);
+        return;
+    }
+
+    this->resetSoC(resetMeMsg->resetType);
+
+    quiescentEnd = std::chrono::steady_clock::now() +
+                   std::chrono::seconds(resetMeMsg->resetQuiesent);
+
+    logRequestIssued(requestTime);
+}
+
+std::string SocResetMeHandler::requestedHostTransition(
+    [[maybe_unused]] const uint16_t resetType)
+{
+    return "xyz.openbmc_project.State.Host.Transition.Reboot";
+}
+
+void SocResetMeHandler::resetSoC(const uint16_t resetType)
+{
+    // Create a D-Bus method call to set the property
+    auto methodCall = bus.new_method_call(dbusParams->conn, dbusParams->path,
+                                          "org.freedesktop.DBus.Properties",
+                                          "Set");
+
+    methodCall.append(
+        dbusParams->intf, dbusParams->prop,
+        std::variant<std::string>{this->requestedHostTransition(resetType)});
+
+    bus.call(methodCall);
+}
+
+void SocResetMeHandler::logRequest(uint64_t internalInfo, uint16_t resetType,
+                                   uint32_t quiescentPeriod,
+                                   const std::string& resetReason) const
+{
+    lg2::info(
+        "SOC_RESET_ME requested from {SOC_RESET_ME_SOCID}: {SOC_RESET_ME_RESET_REASON}",
+        "SOC_RESET_ME", "request"sv, "SOC_RESET_ME_SOCID",
+        static_cast<int>(socId), "SOC_RESET_ME_INTERNAL_INFO",
+        (lg2::hex | lg2::field64), internalInfo, "SOC_RESET_ME_RESET_TYPE",
+        resetType, "SOC_RESET_ME_QUIESCENT_PERIOD", quiescentPeriod,
+        "SOC_RESET_ME_RESET_REASON", resetReason);
+}
+
+void SocResetMeHandler::logRequestIgnored(
+    const ResetTimeStamp& requestTime) const
+{
+    lg2::info(
+        "SOC_RESET_ME request from {SOC_RESET_ME_SOCID}@{SOC_RESET_ME_REQUEST_AT} ignored",
+        "SOC_RESET_ME", "ignored"sv, "SOC_RESET_ME_SOCID",
+        static_cast<int>(socId), "SOC_RESET_ME_REQUEST_AT",
+        duration_cast<std::chrono::seconds>(requestTime.time_since_epoch())
+            .count(),
+        "SOC_RESET_ME_QUIESCENT_END",
+        duration_cast<std::chrono::seconds>(quiescentEnd.time_since_epoch())
+            .count());
+}
+
+void SocResetMeHandler::logRequestIssued(
+    const ResetTimeStamp& requestTime) const
+{
+    lg2::info(
+        "SOC_RESET_ME request from {SOC_RESET_ME_SOCID}@{SOC_RESET_ME_REQUEST_AT} issued",
+        "SOC_RESET_ME", "issued"sv, "SOC_RESET_ME_SOCID",
+        static_cast<int>(socId), "SOC_RESET_ME_REQUEST_AT",
+        duration_cast<std::chrono::seconds>(requestTime.time_since_epoch())
+            .count(),
+        "SOC_RESET_ME_QUIESCENT_END",
+        duration_cast<std::chrono::seconds>(quiescentEnd.time_since_epoch())
+            .count());
+}
+
 } // namespace soc_reset_me
 } // namespace pldm_oem_google
diff --git a/src/soc-reset-me.hpp b/src/soc-reset-me.hpp
index fb671d8..c40faae 100644
--- a/src/soc-reset-me.hpp
+++ b/src/soc-reset-me.hpp
@@ -14,9 +14,16 @@
  * limitations under the License.
  */
 #pragma once
+#include <pldm-oem-google.h>
+
+#include <sdbusplus/bus.hpp>
+
+#include <chrono>
+#include <cstddef>
+#include <cstdint>
+#include <exception>
 #include <optional>
 #include <string>
-
 namespace pldm_oem_google
 {
 namespace soc_reset_me
@@ -59,5 +66,58 @@
     static std::optional<SocId> socId;
 };
 
+struct ResetDBusParams
+{
+    const char* conn;
+    const char* path;
+    const char* intf;
+    const char* prop;
+};
+
+const ResetDBusParams* cn1DbusParams(void);
+const ResetDBusParams* cn2DbusParams(void);
+class SocResetMeHandler
+{
+  public:
+    SocResetMeHandler(const SocId id, sdbusplus::bus_t&& b);
+    ~SocResetMeHandler() = default;
+    virtual void
+        handle(uint8_t requesterTid,
+               const struct pldm_event_oem_google_soc_reset_me* resetMeMsg,
+               size_t resetMeMsgLen);
+
+  protected:
+    friend class SocResetMeHandlerTest;
+    using ResetTimeStamp = std::chrono::time_point<std::chrono::steady_clock>;
+    virtual void resetSoC(const uint16_t resetType);
+    virtual std::string requestedHostTransition(const uint16_t resetType);
+    virtual void logRequest(uint64_t internalInfo, uint16_t resetType,
+                            uint32_t quiescentPeriod,
+                            const std::string& resetReason) const;
+    virtual void logRequestIgnored(const ResetTimeStamp& requestTime) const;
+    virtual void logRequestIssued(const ResetTimeStamp& requestTime) const;
+
+    const SocId socId;
+    const ResetDBusParams* dbusParams;
+
+    sdbusplus::bus_t bus;
+    ResetTimeStamp quiescentEnd;
+};
+
+class InvalidSoCIdException : public std::exception
+{
+  public:
+    InvalidSoCIdException(int invalidId) :
+        errorMessage("SoC ID " + std::to_string(invalidId) + " is invalid")
+    {}
+    const char* what() const noexcept override
+    {
+        return errorMessage.c_str();
+    }
+
+  private:
+    std::string errorMessage;
+};
+
 } // namespace soc_reset_me
 } // namespace pldm_oem_google
diff --git a/subprojects/phosphor-dbus-interfaces.wrap b/subprojects/phosphor-dbus-interfaces.wrap
new file mode 100644
index 0000000..a3b7d1e
--- /dev/null
+++ b/subprojects/phosphor-dbus-interfaces.wrap
@@ -0,0 +1,6 @@
+[wrap-git]
+url = https://github.com/openbmc/phosphor-dbus-interfaces.git
+revision = HEAD
+
+[provide]
+phosphor-dbus-interfaces = phosphor_dbus_interfaces_dep
\ No newline at end of file
diff --git a/subprojects/phosphor-logging.wrap b/subprojects/phosphor-logging.wrap
new file mode 100644
index 0000000..6876a6e
--- /dev/null
+++ b/subprojects/phosphor-logging.wrap
@@ -0,0 +1,6 @@
+[wrap-git]
+url = https://github.com/openbmc/phosphor-logging
+revision = HEAD
+
+[provide]
+phosphor-logging = phosphor_logging_dep
diff --git a/subprojects/sdbusplus.wrap b/subprojects/sdbusplus.wrap
new file mode 100644
index 0000000..42cfcee
--- /dev/null
+++ b/subprojects/sdbusplus.wrap
@@ -0,0 +1,6 @@
+[wrap-git]
+url = https://github.com/openbmc/sdbusplus
+revision = HEAD
+
+[provide]
+sdbusplus = sdbusplus_dep
diff --git a/test/test-soc-reset-me.cpp b/test/test-soc-reset-me.cpp
index bb86a0a..03b7fd9 100644
--- a/test/test-soc-reset-me.cpp
+++ b/test/test-soc-reset-me.cpp
@@ -15,8 +15,13 @@
  */
 #include "src/soc-reset-me.hpp"
 
-#include "gtest/gtest.h"
+#include <sdbusplus/test/sdbus_mock.hpp>
 
+#include <gmock/gmock.h>
+#include <gtest/gtest.h>
+
+using ::testing::_;
+using ::testing::StrEq;
 namespace pldm_oem_google
 {
 namespace soc_reset_me
@@ -79,5 +84,204 @@
     EXPECT_FALSE(PeerSoCId::isDefault());
 }
 
+// Test fixture for SocResetMeHandler tests
+class SocResetMeHandlerTest : public testing::Test
+{
+  protected:
+    static constexpr auto hostStateReboot =
+        "xyz.openbmc_project.State.Host.Transition.Reboot";
+    static constexpr auto dbusPropIntf = "org.freedesktop.DBus.Properties";
+    ::testing::NiceMock<sdbusplus::SdBusMock> mock;
+    auto dbusParams(SocResetMeHandler& h)
+    {
+        return h.dbusParams;
+    }
+    void resetSoC(SocResetMeHandler& h)
+    {
+        h.resetSoC(SOC_RESET_ME_AUTO);
+    }
+    auto quicentEnd(SocResetMeHandler& h)
+    {
+        return h.quiescentEnd;
+    }
+    void mockQuiecentEnd(SocResetMeHandler& h,
+                         decltype(SocResetMeHandler::quiescentEnd) mocktime)
+    {
+        h.quiescentEnd = mocktime;
+    }
+    void expectNewSetPropMethod(const struct ResetDBusParams* params)
+    {
+        EXPECT_CALL(mock, sd_bus_message_new_method_call(
+                              _, _, StrEq(params->conn), StrEq(params->path),
+                              StrEq(dbusPropIntf), StrEq("Set")))
+            .WillOnce(::testing::Return(0));
+    }
+    void expectMessageAppend(const char* val)
+    {
+        using testing::MatcherCast;
+        using testing::Pointee;
+        using testing::SafeMatcherCast;
+        using ::testing::StrEq;
+        EXPECT_CALL(mock, sd_bus_message_append_basic(
+                              _, SD_BUS_TYPE_STRING,
+                              MatcherCast<const void*>(
+                                  SafeMatcherCast<const char*>(StrEq(val)))))
+            .WillOnce(::testing::Return(0));
+    }
+    void expectSetHostTransactionProp(const struct ResetDBusParams* params)
+    {
+        expectNewSetPropMethod(params);
+        expectMessageAppend(params->intf);
+        expectMessageAppend(params->prop);
+        expectMessageAppend(hostStateReboot);
+        // sync call without timeout
+        EXPECT_CALL(mock, sd_bus_call(_, _, 0, _, _)).Times(1);
+    }
+
+    auto resetMeRequestMsg(uint32_t quiescentPeriod, const char* str)
+    {
+        std::string_view resetReason{str};
+
+        bzero(&data, sizeof(data));
+        memcpy(data + sizeof(struct pldm_event_oem_google_soc_reset_me),
+               resetReason.data(), resetReason.length());
+        auto msg =
+            reinterpret_cast<struct pldm_event_oem_google_soc_reset_me*>(data);
+        msg->descLen = resetReason.length();
+        msg->resetQuiesent = quiescentPeriod;
+        return msg;
+    }
+
+    uint8_t data[sizeof(struct pldm_event_oem_google_soc_reset_me) + 128];
+};
+
+// Test SocResetMeHandler constructor
+TEST_F(SocResetMeHandlerTest, Constructor_InitializeDBusParams)
+{
+    SocResetMeHandler mockCn1Handler(SocId::cn1,
+                                     sdbusplus::get_mocked_new(&mock));
+    EXPECT_EQ(dbusParams(mockCn1Handler), cn1DbusParams());
+    SocResetMeHandler mockCn2Handler(SocId::cn2,
+                                     sdbusplus::get_mocked_new(&mock));
+    EXPECT_EQ(dbusParams(mockCn2Handler), cn2DbusParams());
+    EXPECT_THROW(SocResetMeHandler mockInvalidHander(
+                     SocId::cnDefault, sdbusplus::get_mocked_new(&mock)),
+                 InvalidSoCIdException);
+    EXPECT_THROW(SocResetMeHandler mockInvalidHander(
+                     static_cast<SocId>(-1), sdbusplus::get_mocked_new(&mock)),
+                 InvalidSoCIdException);
+}
+
+class MockSocResetMeHandler : public SocResetMeHandler
+{
+  public:
+    // Constructor taking the same parameters as SocResetMeHandler
+    MockSocResetMeHandler(const SocId id, sdbusplus::bus_t&& b) :
+        SocResetMeHandler(id, std::move(b))
+    {}
+
+    MOCK_METHOD(void, resetSoC, (const uint16_t resetType), (override));
+    MOCK_METHOD(void, logRequest,
+                (uint64_t internalInfo, uint16_t resetType,
+                 uint32_t quiescentPeriod, const std::string& resetReason),
+                (const, override));
+    MOCK_METHOD(void, logRequestIgnored, (const ResetTimeStamp& requestTime),
+                (const, override));
+    MOCK_METHOD(void, logRequestIssued, (const ResetTimeStamp& requestTime),
+                (const, override));
+};
+
+// First time handling shall not in any reset quiecent period
+// so shall reset and update the reset quiecentEnd to
+// handleTime + requestQuiesent
+TEST_F(SocResetMeHandlerTest, HandleSocResetMeFirstTime)
+{
+    using namespace std::chrono;
+    auto reason = "HandleSocResetMeFirstTime";
+    auto msg = resetMeRequestMsg(0, reason);
+
+    MockSocResetMeHandler mockHandler(SocId::cn1,
+                                      sdbusplus::get_mocked_new(&mock));
+    EXPECT_CALL(mockHandler, resetSoC(msg->resetType)).Times(1);
+    EXPECT_CALL(mockHandler, logRequest(msg->internalInfo, msg->resetType,
+                                        msg->resetQuiesent, StrEq(reason)))
+        .Times(1);
+    EXPECT_CALL(mockHandler, logRequestIssued(_)).Times(1);
+    EXPECT_CALL(mockHandler, logRequestIgnored(_)).Times(0);
+
+    mockHandler.handle(0, msg, msg->descLen + sizeof(*msg));
+
+    EXPECT_EQ(
+        duration_cast<seconds>(quicentEnd(mockHandler).time_since_epoch()),
+        duration_cast<seconds>(
+            (steady_clock::now() + seconds(msg->resetQuiesent))
+                .time_since_epoch()));
+}
+
+// Following on handling request out of quiencent
+// reset SoC and update quiecentEnd to handletTime + requestQuiesent
+TEST_F(SocResetMeHandlerTest, HandleSocResetMeOutQuiesent)
+{
+    using namespace std::chrono;
+    auto reason = "HandleSocResetMeOutQuiesent";
+    auto msg = resetMeRequestMsg(10, reason);
+    MockSocResetMeHandler mockHandler(SocId::cn1,
+                                      sdbusplus::get_mocked_new(&mock));
+    auto mocktime = steady_clock::now() - seconds(30);
+    mockQuiecentEnd(mockHandler, mocktime);
+    EXPECT_CALL(mockHandler, resetSoC(msg->resetType)).Times(1);
+    EXPECT_CALL(mockHandler, logRequest(msg->internalInfo, msg->resetType,
+                                        msg->resetQuiesent, StrEq(reason)))
+        .Times(1);
+    EXPECT_CALL(mockHandler, logRequestIssued(_)).Times(1);
+    EXPECT_CALL(mockHandler, logRequestIgnored(_)).Times(0);
+    mockHandler.handle(0, msg, msg->descLen + sizeof(*msg));
+
+    EXPECT_EQ(
+        duration_cast<seconds>(quicentEnd(mockHandler).time_since_epoch()),
+        duration_cast<seconds>(
+            (steady_clock::now() + seconds(msg->resetQuiesent))
+                .time_since_epoch()));
+}
+
+// Following on handling request within quiencent period
+// ingore this request and w/o resetting SoC nor updating quiecentEnd
+TEST_F(SocResetMeHandlerTest, HandleSocResetMeInQuiesent)
+{
+    using namespace std::chrono;
+    auto reason = "HandleSocResetMeInQuiesent";
+    auto msg = resetMeRequestMsg(10, reason);
+
+    MockSocResetMeHandler mockHandler(SocId::cn1,
+                                      sdbusplus::get_mocked_new(&mock));
+    auto mocktime = steady_clock::now() + seconds(30);
+    mockQuiecentEnd(mockHandler, mocktime);
+    EXPECT_CALL(mockHandler, resetSoC(msg->resetType)).Times(0);
+    EXPECT_CALL(mockHandler, logRequest(msg->internalInfo, msg->resetType,
+                                        msg->resetQuiesent, StrEq(reason)))
+        .Times(1);
+    EXPECT_CALL(mockHandler, logRequestIssued(_)).Times(0);
+    EXPECT_CALL(mockHandler, logRequestIgnored(_)).Times(1);
+
+    mockHandler.handle(0, msg, sizeof(*msg) + msg->descLen);
+
+    EXPECT_EQ(quicentEnd(mockHandler), mocktime);
+}
+
+// Test the expected behavior: set the corresponding state transaction property
+TEST_F(SocResetMeHandlerTest, SocResetCn1)
+{
+    expectSetHostTransactionProp(cn1DbusParams());
+    SocResetMeHandler mockHandler(SocId::cn1, sdbusplus::get_mocked_new(&mock));
+    resetSoC(mockHandler);
+}
+
+TEST_F(SocResetMeHandlerTest, SocResetCn2)
+{
+    expectSetHostTransactionProp(cn2DbusParams());
+    SocResetMeHandler mockHandler(SocId::cn2, sdbusplus::get_mocked_new(&mock));
+    resetSoC(mockHandler);
+}
+
 } // namespace soc_reset_me
 } // namespace pldm_oem_google