blob: afff859f58cc922e938239d75e1f0a3ac907044d [file]
#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