| #include "system_utils.hpp" |
| |
| #include <memory> |
| #include <optional> |
| #include <string> |
| #include <string_view> |
| #include <vector> |
| |
| #include <gtest/gtest.h> |
| #include "async_resp.hpp" |
| #include "storage.hpp" |
| #include "snapshot_fixture.hpp" |
| #include <nlohmann/json.hpp> // IWYU pragma: keep |
| #include "managed_store.hpp" // IWYU pragma: keep |
| #include "managed_store_types.hpp" // IWYU pragma: keep |
| #include "test/g3/mock_managed_store.hpp" // IWYU pragma: keep |
| #include "test/g3/mock_managed_store_test.hpp" // IWYU pragma: keep |
| |
| namespace redfish::system_utils { |
| namespace { |
| |
| class SystemUtilsTest : public SnapshotFixture {}; |
| |
| TEST_F(SystemUtilsTest, IsHardcodedSingleHost) { |
| #ifdef BMCWEB_ALLOW_NON_HARDCODED_SINGLEHOST_SYSTEM |
| EXPECT_FALSE(isHardcodedSingleHost(0)); |
| EXPECT_FALSE(isHardcodedSingleHost(1)); |
| EXPECT_FALSE(isHardcodedSingleHost(2)); |
| #else |
| EXPECT_TRUE(isHardcodedSingleHost(0)); |
| EXPECT_TRUE(isHardcodedSingleHost(1)); |
| EXPECT_FALSE(isHardcodedSingleHost(2)); |
| EXPECT_FALSE(isHardcodedSingleHost(3)); |
| #endif |
| } |
| |
| void VerifyFindSystemPathAndTriggerCallback( |
| const std::string& systemName, |
| const std::vector<std::string>& objects, |
| const boost::beast::http::status expectedStatus, |
| const std::optional<std::string>& expectedPath) { |
| auto asyncResp = std::make_shared<bmcweb::AsyncResp>(); |
| bool callbackTriggered = false; |
| std::string callbackPath; |
| findSystemPathAndTriggerCallback( |
| asyncResp, systemName, objects, |
| [&callbackTriggered, &callbackPath]( |
| const std::shared_ptr<bmcweb::AsyncResp>& /*resp*/, |
| const std::string& path) { |
| callbackTriggered = true; |
| callbackPath = path; |
| }); |
| EXPECT_EQ(asyncResp->res.result(), expectedStatus); |
| if (expectedPath.has_value()) { |
| EXPECT_TRUE(callbackTriggered); |
| EXPECT_EQ(callbackPath, *expectedPath); |
| } else { |
| EXPECT_FALSE(callbackTriggered); |
| } |
| } |
| |
| TEST_F(SystemUtilsTest, FindSystemPathAndTriggerCallback) { |
| #ifdef BMCWEB_ALLOW_NON_HARDCODED_SINGLEHOST_SYSTEM |
| VerifyFindSystemPathAndTriggerCallback( |
| "system1", |
| {"/xyz/openbmc_project/inventory/system1"}, |
| boost::beast::http::status::ok, "/xyz/openbmc_project/inventory/system1"); |
| VerifyFindSystemPathAndTriggerCallback( |
| "system", |
| {"/xyz/openbmc_project/inventory/system1"}, |
| boost::beast::http::status::not_found, std::nullopt); |
| #else |
| VerifyFindSystemPathAndTriggerCallback( |
| "system", {"/xyz/openbmc_project/inventory/system1"}, |
| boost::beast::http::status::ok, ""); |
| VerifyFindSystemPathAndTriggerCallback( |
| "wrongName", {"/xyz/openbmc_project/inventory/system1"}, |
| boost::beast::http::status::not_found, std::nullopt); |
| #endif |
| VerifyFindSystemPathAndTriggerCallback( |
| "system2", |
| {"/xyz/openbmc_project/inventory/system1", |
| "/xyz/openbmc_project/inventory/system2"}, |
| boost::beast::http::status::ok, "/xyz/openbmc_project/inventory/system2"); |
| } |
| |
| TEST_F(SystemUtilsTest, ParseSystemNameToIndex) { |
| // Single host |
| auto index = parseSystemNameToIndex("system", false); |
| ASSERT_TRUE(index.ok()); |
| EXPECT_EQ(*index, 0); |
| |
| #ifdef BMCWEB_ALLOW_NON_HARDCODED_SINGLEHOST_SYSTEM |
| // When fallback is disabled, system1 is parsed to index 0 via fall-through |
| auto index1 = parseSystemNameToIndex("system1", false); |
| ASSERT_TRUE(index1.ok()); |
| EXPECT_EQ(*index1, 0); |
| auto index2 = parseSystemNameToIndex("system2", false); |
| ASSERT_TRUE(index2.ok()); |
| EXPECT_EQ(*index2, 1); |
| #else |
| // When fallback is enabled, system1 is rejected for single host |
| EXPECT_FALSE(parseSystemNameToIndex("system1", false).ok()); |
| EXPECT_FALSE(parseSystemNameToIndex("system2", false).ok()); |
| #endif |
| |
| // host0 is not supported as the service expects system prefix |
| EXPECT_FALSE(parseSystemNameToIndex("host0", false).ok()); |
| |
| EXPECT_FALSE(parseSystemNameToIndex("system0", false).ok()); |
| EXPECT_FALSE(parseSystemNameToIndex("wrongName", false).ok()); |
| |
| // Multiple hosts |
| EXPECT_FALSE(parseSystemNameToIndex("system", true).ok()); |
| EXPECT_FALSE(parseSystemNameToIndex("system0", true).ok()); |
| EXPECT_FALSE(parseSystemNameToIndex("wrongName", true).ok()); |
| |
| EXPECT_TRUE(parseSystemNameToIndex("system1", true).ok()); |
| EXPECT_EQ(parseSystemNameToIndex("system1", true).value_or(-1), 0); |
| |
| EXPECT_TRUE(parseSystemNameToIndex("system2", true).ok()); |
| EXPECT_EQ(parseSystemNameToIndex("system2", true).value_or(-1), 1); |
| } |
| |
| void VerifySystemStorageCollection( |
| SnapshotFixture* fixture, const std::string& systemName, |
| const std::optional<std::string>& storageObjectPath, |
| const std::optional<std::string>& expectedMemberId) { |
| if (storageObjectPath.has_value()) { |
| managedStore::KeyType systemKey( |
| managedStore::ManagedType::kManagedSubtreePaths, |
| "/xyz/openbmc_project/inventory", 0, |
| {"xyz.openbmc_project.Inventory.Item.System"}); |
| std::vector<std::string> mockSystems = { |
| "/xyz/openbmc_project/inventory/" + systemName}; |
| ASSERT_TRUE( |
| dynamic_cast<managedStore::MockSerializedManagedObjectStore*>( |
| managedStore::GetManagedObjectStore()) |
| ->upsertMockObjectIntoManagedStore( |
| systemKey, |
| managedStore::MockManagedStoreTest::CreateValueType( |
| mockSystems)) |
| .ok()); |
| |
| managedStore::KeyType storageKey( |
| managedStore::ManagedType::kManagedAssociatedSubtreePaths, |
| "/xyz/openbmc_project/inventory/" + systemName + "/containing", |
| "/xyz/openbmc_project/inventory", 0, |
| {"xyz.openbmc_project.Inventory.Item.Storage"}); |
| std::vector<std::string> mockStorage = {*storageObjectPath}; |
| ASSERT_TRUE( |
| dynamic_cast<managedStore::MockSerializedManagedObjectStore*>( |
| managedStore::GetManagedObjectStore()) |
| ->upsertMockObjectIntoManagedStore( |
| storageKey, |
| managedStore::MockManagedStoreTest::CreateValueType( |
| mockStorage)) |
| .ok()); |
| } |
| |
| auto asyncResp = std::make_shared<bmcweb::AsyncResp>(); |
| handleGetSystemStorageCollection(asyncResp, systemName); |
| fixture->RunIoUntilDone(); |
| |
| EXPECT_EQ(asyncResp->res.result(), boost::beast::http::status::ok); |
| if (expectedMemberId.has_value()) { |
| EXPECT_EQ(asyncResp->res.jsonValue["Members"].size(), 1); |
| EXPECT_EQ(asyncResp->res.jsonValue["Members"][0]["@odata.id"], |
| *expectedMemberId); |
| } |
| } |
| |
| TEST_F(SystemUtilsTest, HandleGetSystemStorageCollectionTest) { |
| #ifdef BMCWEB_ALLOW_NON_HARDCODED_SINGLEHOST_SYSTEM |
| VerifySystemStorageCollection( |
| this, "system1", "/xyz/openbmc_project/inventory/system1/storage1", |
| "/redfish/v1/Systems/system1/Storage/storage1"); |
| #else |
| VerifySystemStorageCollection(this, "system", std::nullopt, std::nullopt); |
| #endif |
| } |
| |
| } // namespace |
| } // namespace redfish::system_utils |