blob: 6f8bb6d22dd2d60b2d955577fff24398d920ff94 [file] [log] [blame]
#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