| #include "app.hpp" |
| #include "bmcweb_config.h" |
| |
| #include "async_resp.hpp" |
| #include "http_response.hpp" |
| #include "nlohmann/json.hpp" |
| #include "systems.hpp" |
| #include "snapshot_fixture.hpp" |
| |
| #include <memory> |
| #include <vector> |
| |
| #include <gmock/gmock.h> // IWYU pragma: keep |
| #include <gtest/gtest.h> // IWYU pragma: keep |
| |
| // IWYU pragma: no_include <gtest/gtest-message.h> |
| // IWYU pragma: no_include <gtest/gtest-test-part.h> |
| // IWYU pragma: no_include "gtest/gtest_pred_impl.h" |
| // IWYU pragma: no_include <gmock/gmock-matchers.h> |
| // IWYU pragma: no_include <gtest/gtest-matchers.h> |
| |
| namespace redfish |
| { |
| namespace |
| { |
| |
| using ::dbus::utility::DbusVariantType; |
| using ::managedStore::KeyType; |
| using ::managedStore::ManagedObjectStoreContext; |
| using ::managedStore::ManagedType; |
| using ::managedStore::SimulateFailedAsyncPostDbusCallThreadSafeAction; |
| using ::managedStore::SimulateSuccessfulAsyncPostDbusCallThreadSafeAction; |
| using ::managedStore::ValueType; |
| using ::testing::An; |
| using ::testing::_; |
| |
| TEST(HandlerSystemTest, VerifyCreateResetActionInfoResponse) |
| { |
| auto shareAsyncResp = std::make_shared<bmcweb::AsyncResp>(); |
| |
| createResetActionInfoResponse(shareAsyncResp, "test"); |
| nlohmann::json& json = shareAsyncResp->res.jsonValue; |
| EXPECT_EQ(json["@odata.id"], "/redfish/v1/Systems/test/ResetActionInfo"); |
| EXPECT_EQ(json["@odata.type"], "#ActionInfo.v1_1_2.ActionInfo"); |
| EXPECT_EQ(json["Name"], "Reset Action Info"); |
| EXPECT_EQ(json["Id"], "ResetActionInfo"); |
| |
| nlohmann::json::array_t parameters; |
| nlohmann::json::object_t parameter; |
| |
| parameter["Name"] = "ResetType"; |
| parameter["Required"] = true; |
| parameter["DataType"] = "String"; |
| parameter["Delay"] = "Number"; |
| nlohmann::json::array_t allowableValues; |
| allowableValues.emplace_back("On"); |
| allowableValues.emplace_back("ForceOff"); |
| allowableValues.emplace_back("ForceOn"); |
| allowableValues.emplace_back("ForceRestart"); |
| allowableValues.emplace_back("GracefulRestart"); |
| allowableValues.emplace_back("GracefulShutdown"); |
| allowableValues.emplace_back("PowerCycle"); |
| allowableValues.emplace_back("Nmi"); |
| allowableValues.emplace_back("ReallyGracefulShutDownTechDebt"); |
| parameter["AllowableValues"] = std::move(allowableValues); |
| parameters.emplace_back(std::move(parameter)); |
| |
| nlohmann::json::object_t delayParameter; |
| delayParameter["Name"] = "Delay"; |
| delayParameter["Required"] = false; |
| delayParameter["DataType"] = "Number"; |
| parameters.emplace_back(std::move(delayParameter)); |
| EXPECT_EQ(json["Parameters"], parameters); |
| } |
| |
| TEST(GetSystemResetCommandFromInputTest, TestOnAndForceOnReturnCorrectly) |
| { |
| SystemResetCommand systemResetCommandOn = GetSystemResetCommandFromInput("On"); |
| EXPECT_EQ(systemResetCommandOn.command, "xyz.openbmc_project.State.Host.Transition.On"); |
| EXPECT_TRUE(systemResetCommandOn.hostCommand); |
| EXPECT_TRUE(systemResetCommandOn.validCommand); |
| |
| SystemResetCommand systemResetCommandForceOn = GetSystemResetCommandFromInput("ForceOn"); |
| EXPECT_EQ(systemResetCommandForceOn.command, "xyz.openbmc_project.State.Host.Transition.On"); |
| EXPECT_TRUE(systemResetCommandForceOn.hostCommand); |
| EXPECT_TRUE(systemResetCommandForceOn.validCommand); |
| } |
| |
| TEST(GetSystemResetCommandFromInputTest, TestForceOffReturnCorrectly) |
| { |
| SystemResetCommand systemResetCommandOn = GetSystemResetCommandFromInput("ForceOff"); |
| EXPECT_EQ(systemResetCommandOn.command, "xyz.openbmc_project.State.Chassis.Transition.Off"); |
| EXPECT_FALSE(systemResetCommandOn.hostCommand); |
| EXPECT_TRUE(systemResetCommandOn.validCommand); |
| } |
| |
| TEST(GetSystemResetCommandFromInputTest, TestForceRestartReturnCorrectly) |
| { |
| SystemResetCommand systemResetCommandOn = GetSystemResetCommandFromInput("ForceRestart"); |
| EXPECT_EQ(systemResetCommandOn.command, "xyz.openbmc_project.State.Host.Transition.ForceWarmReboot"); |
| EXPECT_TRUE(systemResetCommandOn.hostCommand); |
| EXPECT_TRUE(systemResetCommandOn.validCommand); |
| } |
| |
| TEST(GetSystemResetCommandFromInputTest, TestGracefulShutdownReturnCorrectly) |
| { |
| SystemResetCommand systemResetCommandOn = GetSystemResetCommandFromInput("GracefulShutdown"); |
| EXPECT_EQ(systemResetCommandOn.command, "xyz.openbmc_project.State.Host.Transition.Off"); |
| EXPECT_TRUE(systemResetCommandOn.hostCommand); |
| EXPECT_TRUE(systemResetCommandOn.validCommand); |
| } |
| |
| TEST(GetSystemResetCommandFromInputTest, TestGracefulRestartReturnCorrectly) |
| { |
| SystemResetCommand systemResetCommandOn = GetSystemResetCommandFromInput("GracefulRestart"); |
| EXPECT_EQ(systemResetCommandOn.command, "xyz.openbmc_project.State.Host.Transition.GracefulWarmReboot"); |
| EXPECT_TRUE(systemResetCommandOn.hostCommand); |
| EXPECT_TRUE(systemResetCommandOn.validCommand); |
| } |
| |
| TEST(GetSystemResetCommandFromInputTest, TestPowerCycleReturnCorrectly) |
| { |
| SystemResetCommand systemResetCommandOn = GetSystemResetCommandFromInput("PowerCycle"); |
| EXPECT_EQ(systemResetCommandOn.command, "xyz.openbmc_project.State.Host.Transition.Reboot"); |
| EXPECT_TRUE(systemResetCommandOn.hostCommand); |
| EXPECT_TRUE(systemResetCommandOn.validCommand); |
| } |
| |
| TEST(GetSystemResetCommandFromInputTest, TestReallyGracefulShutDownTechDebtReturnCorrectly) |
| { |
| SystemResetCommand systemResetCommandOn = GetSystemResetCommandFromInput("ReallyGracefulShutDownTechDebt"); |
| EXPECT_EQ(systemResetCommandOn.command, "xyz.openbmc_project.State.Host.Transition.ReallyGracefulShutDown"); |
| EXPECT_TRUE(systemResetCommandOn.hostCommand); |
| EXPECT_TRUE(systemResetCommandOn.validCommand); |
| } |
| |
| TEST(GetSystemResetCommandFromInputTest, TestInvalidInput) |
| { |
| SystemResetCommand systemResetCommandOn = GetSystemResetCommandFromInput("SomeInvalidInput"); |
| EXPECT_FALSE(systemResetCommandOn.validCommand); |
| } |
| |
| TEST(GetSystemSuffixHelperTest, TestAllInputs) |
| { |
| // Empty, invalid strings |
| EXPECT_EQ("", getSystemSuffix("")); |
| EXPECT_EQ("", getSystemSuffix("asdf")); |
| EXPECT_EQ("", getSystemSuffix("syste")); |
| // Valid Systems/ |
| EXPECT_EQ("", getSystemSuffix("system")); |
| EXPECT_EQ("1", getSystemSuffix("system1")); |
| EXPECT_EQ("13", getSystemSuffix("system13")); |
| EXPECT_EQ("FUTURE", getSystemSuffix("systemFUTURE")); |
| } |
| |
| TEST(HandlerSystemTest, HelpersValuesEnable) |
| { |
| auto shareAsyncResp = std::make_shared<bmcweb::AsyncResp>(); |
| nlohmann::json& json = shareAsyncResp->res.jsonValue; |
| |
| json["MemorySummary"]["Status"]["State"] = "Disabled"; |
| json["ProcessorSummary"]["Count"] = 1; |
| json["ProcessorSummary"]["Status"]["State"] = "Disabled"; |
| |
| updateDimmProperties(shareAsyncResp, true); |
| modifyCpuPresenceState(shareAsyncResp, true); |
| modifyCpuFunctionalState(shareAsyncResp, true); |
| |
| EXPECT_EQ(json["MemorySummary"]["Status"]["State"], "Enabled"); |
| EXPECT_EQ(json["ProcessorSummary"]["Count"], 2); |
| EXPECT_EQ(json["ProcessorSummary"]["Status"]["State"], "Enabled"); |
| } |
| |
| TEST_F(SnapshotFixture, PostSystemResetAsNMIOnDBusCallFailed){ |
| EXPECT_CALL(*managedStore::GetManagedObjectStore(), |
| PostDbusCallToIoContextThreadSafe(_, An<absl::AnyInvocable<void(const boost::system::error_code&)>&&>(), |
| "xyz.openbmc_project.Control.Host.NMI", "/xyz/openbmc_project/control/host0/nmi", |
| "xyz.openbmc_project.Control.Host.NMI", "NMI")) |
| .Times(1) |
| .WillOnce(SimulateFailedAsyncPostDbusCallThreadSafeAction:: |
| SimulateFailedAsyncPostDbusCall()); |
| |
| handlePostComputerSystemReset(app_, CreateRequest("{\"ResetType\":\"Nmi\"}"), share_async_resp_, "system"); |
| |
| RunIoUntilDone(); |
| |
| EXPECT_EQ(share_async_resp_->res.result(), boost::beast::http::status::internal_server_error); |
| } |
| |
| TEST_F(SnapshotFixture, PostSystemResetAsNMIOnDBusCallSuccess){ |
| EXPECT_CALL(*managedStore::GetManagedObjectStore(), |
| PostDbusCallToIoContextThreadSafe(_, An<absl::AnyInvocable<void(const boost::system::error_code&)>&&>(), |
| "xyz.openbmc_project.Control.Host.NMI", "/xyz/openbmc_project/control/host0/nmi", |
| "xyz.openbmc_project.Control.Host.NMI", "NMI")) |
| .Times(1) |
| .WillOnce(SimulateSuccessfulAsyncPostDbusCallThreadSafeAction:: |
| SimulateSuccessfulAsyncPostDbusCall()); |
| |
| handlePostComputerSystemReset(app_, CreateRequest("{\"ResetType\":\"Nmi\"}"), share_async_resp_, "system"); |
| |
| RunIoUntilDone(); |
| |
| EXPECT_EQ(share_async_resp_->res.result(), boost::beast::http::status::ok); |
| } |
| |
| TEST_F(SnapshotFixture, PostSystemResetSingleSystemHostResetOnFail){ |
| EXPECT_CALL(*managedStore::GetManagedObjectStore(), |
| PostDbusCallToIoContextThreadSafe(_, An<absl::AnyInvocable<void(const boost::system::error_code&)>&&>(), |
| "xyz.openbmc_project.State.Host", "/xyz/openbmc_project/state/host0", |
| "org.freedesktop.DBus.Properties", "Set", "xyz.openbmc_project.State.Host", "RequestedHostTransition", |
| dbus::utility::DbusVariantType("xyz.openbmc_project.State.Host.Transition.On"))) |
| .Times(1) |
| .WillOnce(SimulateFailedAsyncPostDbusCallThreadSafeAction:: |
| SimulateFailedAsyncPostDbusCall()); |
| |
| handlePostComputerSystemReset(app_, CreateRequest("{\"ResetType\":\"ForceOn\"}"), share_async_resp_, "system"); |
| |
| RunIoUntilDone(); |
| |
| EXPECT_EQ(share_async_resp_->res.result(), boost::beast::http::status::internal_server_error); |
| } |
| |
| TEST_F(SnapshotFixture, PostSystemResetSingleSystemHostResetOnSuccess){ |
| EXPECT_CALL(*managedStore::GetManagedObjectStore(), |
| PostDbusCallToIoContextThreadSafe(_, An<absl::AnyInvocable<void(const boost::system::error_code&)>&&>(), |
| "xyz.openbmc_project.State.Host", "/xyz/openbmc_project/state/host0", |
| "org.freedesktop.DBus.Properties", "Set", "xyz.openbmc_project.State.Host", "RequestedHostTransition", |
| dbus::utility::DbusVariantType("xyz.openbmc_project.State.Host.Transition.On"))) |
| .Times(1) |
| .WillOnce(SimulateSuccessfulAsyncPostDbusCallThreadSafeAction:: |
| SimulateSuccessfulAsyncPostDbusCall()); |
| |
| handlePostComputerSystemReset(app_, CreateRequest("{\"ResetType\":\"ForceOn\"}"), share_async_resp_, "system"); |
| |
| RunIoUntilDone(); |
| |
| EXPECT_EQ(share_async_resp_->res.result(), boost::beast::http::status::ok); |
| } |
| |
| TEST_F(SnapshotFixture, PostSystemResetSingleSystemChassisResetOnFail){ |
| EXPECT_CALL(*managedStore::GetManagedObjectStore(), |
| PostDbusCallToIoContextThreadSafe(_, An<absl::AnyInvocable<void(const boost::system::error_code&)>&&>(), |
| "xyz.openbmc_project.State.Chassis", "/xyz/openbmc_project/state/chassis0", |
| "org.freedesktop.DBus.Properties", "Set", "xyz.openbmc_project.State.Chassis", "RequestedPowerTransition", |
| dbus::utility::DbusVariantType("xyz.openbmc_project.State.Chassis.Transition.Off"))) |
| .Times(1) |
| .WillOnce(SimulateFailedAsyncPostDbusCallThreadSafeAction:: |
| SimulateFailedAsyncPostDbusCall()); |
| |
| handlePostComputerSystemReset(app_, CreateRequest("{\"ResetType\":\"ForceOff\"}"), share_async_resp_, "system"); |
| |
| RunIoUntilDone(); |
| |
| EXPECT_EQ(share_async_resp_->res.result(), boost::beast::http::status::internal_server_error); |
| } |
| |
| TEST_F(SnapshotFixture, PostSystemResetSingleSystemChassisResetOnSuccess){ |
| EXPECT_CALL(*managedStore::GetManagedObjectStore(), |
| PostDbusCallToIoContextThreadSafe(_, An<absl::AnyInvocable<void(const boost::system::error_code&)>&&>(), |
| "xyz.openbmc_project.State.Chassis", "/xyz/openbmc_project/state/chassis0", |
| "org.freedesktop.DBus.Properties", "Set", "xyz.openbmc_project.State.Chassis", "RequestedPowerTransition", |
| dbus::utility::DbusVariantType("xyz.openbmc_project.State.Chassis.Transition.Off"))) |
| .Times(1) |
| .WillOnce(SimulateSuccessfulAsyncPostDbusCallThreadSafeAction:: |
| SimulateSuccessfulAsyncPostDbusCall()); |
| |
| handlePostComputerSystemReset(app_, CreateRequest("{\"ResetType\":\"ForceOff\"}"), share_async_resp_, "system"); |
| |
| RunIoUntilDone(); |
| |
| EXPECT_EQ(share_async_resp_->res.result(), boost::beast::http::status::ok); |
| } |
| |
| TEST_F(SnapshotFixture, CheckComputerSystemHostStateSingleHost) |
| { |
| KeyType key( |
| ManagedType::kManagedProperty, "xyz.openbmc_project.State.Host", |
| sdbusplus::message::object_path("/xyz/openbmc_project/state/host0"), |
| "xyz.openbmc_project.State.Host", "CurrentHostState"); |
| const std::array<std::tuple<std::string, std::string, std::string>, 6> |
| testCases{ |
| {{"xyz.openbmc_project.State.Host.HostState.Running", "On", |
| "Enabled"}, |
| {"xyz.openbmc_project.State.Host.HostState.Quiesced", "On", |
| "Quiesced"}, |
| {"xyz.openbmc_project.State.Host.HostState.DiagnosticMode", "On", |
| "InTest"}, |
| {"xyz.openbmc_project.State.Host.HostState.TransitioningToRunning", |
| "PoweringOn", "Starting"}, |
| {"xyz.openbmc_project.State.Host.HostState.TransitioningToOff", |
| "PoweringOff", "Disabled"}, |
| {"xyz.openbmc_project.State.Host.HostState.OtherDummy", "Off", |
| "Disabled"}}}; |
| for (auto testCase : testCases) |
| { |
| const auto [currentHostState, powerState, status] = testCase; |
| DbusVariantType targetState = currentHostState; |
| std::shared_ptr<ValueType> mockHostStateValue = |
| managedStore::MockManagedStoreTest::CreateValueType( |
| std::move(targetState)); |
| ASSERT_TRUE( |
| managedStore::GetManagedObjectStore() |
| ->upsertMockObjectIntoManagedStore(key, mockHostStateValue) |
| .ok()); |
| handleComputerSystem(share_async_resp_, "", "system", false); |
| |
| RunIoUntilDone(); |
| |
| nlohmann::json& json = share_async_resp_->res.jsonValue; |
| EXPECT_TRUE(json.contains("PowerState")); |
| EXPECT_TRUE(json.contains("Status")); |
| EXPECT_EQ(json["PowerState"], powerState); |
| EXPECT_TRUE(json["Status"].contains("State")); |
| EXPECT_EQ(json["Status"]["State"], status); |
| } |
| } |
| |
| TEST_F(SnapshotFixture, PostSystemResetSingleSystemChassisResetOnSuccessDelay){ |
| handlePostComputerSystemReset(app_, CreateRequest("{\"ResetType\":\"ForceOff\", \"Delay\":1} "), share_async_resp_, "system"); |
| |
| RunIoUntilDone(); |
| |
| EXPECT_EQ(share_async_resp_->res.result(), boost::beast::http::status::ok); |
| EXPECT_EQ(share_async_resp_->res.jsonValue["ResetString"], |
| "systemd-run --on-active=1 --timer-property=AccuracySec=100ms -- " |
| "curl -d {\"ResetType\":\"ForceOff\"} -H Content-Type: application/json " |
| "-X POST localhost:80/redfish/v1/Systems/system/Actions/ComputerSystem.Reset"); |
| } |
| |
| TEST_F(SnapshotFixture, PostSystemResetSingleSystemChassisResetOnFailTimeDelay){ |
| handlePostComputerSystemReset(app_, CreateRequest("{\"ResetType\":\"ForceOff\", \"Delay\":901} "), share_async_resp_, "system"); |
| |
| RunIoUntilDone(); |
| |
| EXPECT_EQ(share_async_resp_->res.result(),boost::beast::http::status::bad_request); |
| } |
| |
| TEST_F(SnapshotFixture, PostSystemResetSingleSystemChassisResetOnFailTypeDelay){ |
| handlePostComputerSystemReset(app_, CreateRequest("{\"ResetType\":\"PleaseReset\", \"Delay\":1} "), share_async_resp_, "system"); |
| |
| RunIoUntilDone(); |
| |
| EXPECT_EQ(share_async_resp_->res.result(),boost::beast::http::status::bad_request); |
| } |
| |
| TEST_F(SnapshotFixture, HandleGetSystemBootGuestOSInfo) |
| { |
| handleGetSystemBootGuestOSInfo(app_, CreateRequest(""), share_async_resp_, |
| "system2"); |
| RunIoUntilDone(); |
| |
| nlohmann::json& json = share_async_resp_->res.jsonValue; |
| EXPECT_EQ(json["@odata.id"], |
| "/redfish/v1/System/system2/Oem/Google/BootGuestOSActionInfo"); |
| } |
| |
| TEST_F(SnapshotFixture, handleGetBareMetalInstanceBase) |
| { |
| handleGetBareMetalInstance(app_, CreateRequest(""), share_async_resp_, |
| "system1"); |
| RunIoUntilDone(); |
| |
| nlohmann::json& json = share_async_resp_->res.jsonValue; |
| EXPECT_EQ(json["@odata.id"], |
| "/redfish/v1/Systems/system1/Oem/Google/BareMetalInstance"); |
| EXPECT_EQ(json["@odata.type"], |
| "#GoogleBareMetalInstance.v1_0_0.GoogleBareMetalInstance"); |
| } |
| |
| } // namespace |
| } // namespace redfish |