test: topology: new configurations
Add tests for the new topology schema.
New testcases:
- 2 powersupplies powering a board, PSUs and board contained by a
chassis. Similar to a Tyan S8030.
- 4 Blades, each contained by a SubChassis, all 4 SubChassis contained
by a SuperChassis. (modeled after Yv3 [1])
Tested: Topology Unit Tests Pass
References:
[1] https://www.opencompute.org/products/237/wiwynn-yosemite-v3-server
Change-Id: I312c93e669915145bfa6d9738fafc35b4506b728
Signed-off-by: Alexander Hansen <alexander.hansen@9elements.com>
diff --git a/test/test_topology.cpp b/test/test_topology.cpp
index f04ce4f..b8b9c4d 100644
--- a/test/test_topology.cpp
+++ b/test/test_topology.cpp
@@ -319,3 +319,236 @@
EXPECT_EQ(assocs.size(), 0U);
}
}
+
+TEST(Topology, SimilarToTyanS8030)
+{
+ const std::string chassisPath =
+ "/xyz/openbmc_project/inventory/system/chassis/ChassisA";
+ const std::string boardPath =
+ "/xyz/openbmc_project/inventory/system/board/BoardA";
+ const std::string psu0Path =
+ "/xyz/openbmc_project/inventory/system/powersupply/PSU0";
+ const std::string psu1Path =
+ "/xyz/openbmc_project/inventory/system/powersupply/PSU1";
+
+ const nlohmann::json chassisContainExposesItem = nlohmann::json::parse(R"(
+ {
+ "Name": "GenericContainPort",
+ "PortType": "containing",
+ "Type": "Port"
+ }
+)");
+ const nlohmann::json containedByExposesItem = nlohmann::json::parse(R"(
+ {
+ "Name": "GenericContainPort",
+ "PortType": "contained_by",
+ "Type": "Port"
+ }
+)");
+ const nlohmann::json boardPowerExposesItem = nlohmann::json::parse(R"(
+ {
+ "Name": "GenericPowerPort",
+ "PortType": "powered_by",
+ "Type": "Port"
+ }
+)");
+ const nlohmann::json psuPowerExposesItem = nlohmann::json::parse(R"(
+ {
+ "Name": "GenericPowerPort",
+ "PortType": "powering",
+ "Type": "Port"
+ }
+)");
+ Topology topo;
+ BoardMap boards{
+ {chassisPath, "ChassisA"},
+ {boardPath, "BoardA"},
+ {psu0Path, "PSU0"},
+ {psu1Path, "PSU1"},
+ };
+
+ // configure the chassis to be containing something
+ topo.addBoard(chassisPath, "Chassis", "ChassisA",
+ chassisContainExposesItem);
+
+ // configure board to be contained by something
+ topo.addBoard(boardPath, "Board", "BoardA", containedByExposesItem);
+
+ // configure the board to be powered by something
+ topo.addBoard(boardPath, "Board", "BoardA", boardPowerExposesItem);
+
+ // configure the PSUs to be powering something
+ topo.addBoard(psu0Path, "PowerSupply", "PSU0", psuPowerExposesItem);
+ topo.addBoard(psu1Path, "PowerSupply", "PSU1", psuPowerExposesItem);
+
+ // configured PSUs to be contained by something
+ topo.addBoard(psu0Path, "PowerSupply", "PSU0", containedByExposesItem);
+ topo.addBoard(psu1Path, "PowerSupply", "PSU1", containedByExposesItem);
+
+ auto assocs = topo.getAssocs(std::views::keys(boards));
+
+ EXPECT_TRUE(assocs.contains(boardPath));
+ EXPECT_TRUE(assocs.contains(psu0Path));
+ EXPECT_TRUE(assocs.contains(psu0Path));
+
+ // expect chassis to contain board
+ EXPECT_EQ(assocs[boardPath].size(), 1);
+ EXPECT_TRUE(assocs[boardPath].contains(
+ {"contained_by", "containing", chassisPath}));
+
+ // expect powering association from each PSU to the board
+ // and expect each PSU to be contained by the chassis
+ EXPECT_EQ(assocs[psu0Path].size(), 2);
+ EXPECT_TRUE(
+ assocs[psu0Path].contains({"powering", "powered_by", boardPath}));
+ EXPECT_TRUE(
+ assocs[psu0Path].contains({"contained_by", "containing", chassisPath}));
+
+ EXPECT_EQ(assocs[psu1Path].size(), 2);
+ EXPECT_TRUE(
+ assocs[psu1Path].contains({"powering", "powered_by", boardPath}));
+ EXPECT_TRUE(
+ assocs[psu1Path].contains({"contained_by", "containing", chassisPath}));
+}
+
+static nlohmann::json makeExposesItem(const std::string& name,
+ const std::string& assocName)
+{
+ nlohmann::json exposesItem = nlohmann::json::parse(R"(
+ {
+ "Name": "REPLACE",
+ "PortType": "REPLACE",
+ "Type": "Port"
+ }
+)");
+
+ exposesItem["Name"] = name;
+ exposesItem["PortType"] = assocName;
+
+ return exposesItem;
+}
+
+static nlohmann::json makeContainedPortExposesItem(const std::string& name)
+{
+ return makeExposesItem(name, "contained_by");
+}
+
+static nlohmann::json makeContainingPortExposesItem(const std::string& name)
+{
+ return makeExposesItem(name, "containing");
+}
+
+TEST(Topology, SimilarToYosemiteV3)
+{
+ const std::string blade1Path =
+ "/xyz/openbmc_project/inventory/system/board/Blade1";
+ const std::string blade2Path =
+ "/xyz/openbmc_project/inventory/system/board/Blade2";
+ const std::string blade3Path =
+ "/xyz/openbmc_project/inventory/system/board/Blade3";
+ const std::string blade4Path =
+ "/xyz/openbmc_project/inventory/system/board/Blade4";
+ const std::string chassis1Path =
+ "/xyz/openbmc_project/inventory/system/chassis/Blade1Chassis";
+ const std::string chassis2Path =
+ "/xyz/openbmc_project/inventory/system/chassis/Blade2Chassis";
+ const std::string chassis3Path =
+ "/xyz/openbmc_project/inventory/system/chassis/Blade3Chassis";
+ const std::string chassis4Path =
+ "/xyz/openbmc_project/inventory/system/chassis/Blade4Chassis";
+ const std::string superChassisPath =
+ "/xyz/openbmc_project/inventory/system/chassis/SuperChassis";
+
+ const nlohmann::json blade1ExposesItem =
+ makeContainedPortExposesItem("Blade1Port");
+ const nlohmann::json blade2ExposesItem =
+ makeContainedPortExposesItem("Blade2Port");
+ const nlohmann::json blade3ExposesItem =
+ makeContainedPortExposesItem("Blade3Port");
+ const nlohmann::json blade4ExposesItem =
+ makeContainedPortExposesItem("Blade4Port");
+
+ const nlohmann::json chassis1ExposesItem =
+ makeContainingPortExposesItem("Blade1Port");
+ const nlohmann::json chassis2ExposesItem =
+ makeContainingPortExposesItem("Blade2Port");
+ const nlohmann::json chassis3ExposesItem =
+ makeContainingPortExposesItem("Blade3Port");
+ const nlohmann::json chassis4ExposesItem =
+ makeContainingPortExposesItem("Blade4Port");
+
+ const nlohmann::json chassis1ExposesItem2 =
+ makeContainedPortExposesItem("SuperChassisPort");
+ const nlohmann::json chassis2ExposesItem2 =
+ makeContainedPortExposesItem("SuperChassisPort");
+ const nlohmann::json chassis3ExposesItem2 =
+ makeContainedPortExposesItem("SuperChassisPort");
+ const nlohmann::json chassis4ExposesItem2 =
+ makeContainedPortExposesItem("SuperChassisPort");
+
+ const nlohmann::json superChassisExposesItem =
+ makeContainingPortExposesItem("SuperChassisPort");
+
+ Topology topo;
+ BoardMap boards{
+ {blade1Path, "Blade1"},
+ {blade2Path, "Blade2"},
+ {blade3Path, "Blade3"},
+ {blade4Path, "Blade4"},
+ {chassis1Path, "Chassis1"},
+ {chassis2Path, "Chassis2"},
+ {chassis3Path, "Chassis3"},
+ {chassis4Path, "Chassis4"},
+ {superChassisPath, "SuperChassis"},
+ };
+
+ topo.addBoard(blade1Path, "Board", "Blade1", blade1ExposesItem);
+ topo.addBoard(blade2Path, "Board", "Blade2", blade2ExposesItem);
+ topo.addBoard(blade3Path, "Board", "Blade3", blade3ExposesItem);
+ topo.addBoard(blade4Path, "Board", "Blade4", blade4ExposesItem);
+
+ topo.addBoard(chassis1Path, "Chassis", "Chassis1", chassis1ExposesItem);
+ topo.addBoard(chassis2Path, "Chassis", "Chassis2", chassis2ExposesItem);
+ topo.addBoard(chassis3Path, "Chassis", "Chassis3", chassis3ExposesItem);
+ topo.addBoard(chassis4Path, "Chassis", "Chassis4", chassis4ExposesItem);
+
+ topo.addBoard(chassis1Path, "Chassis", "Chassis1", chassis1ExposesItem2);
+ topo.addBoard(chassis2Path, "Chassis", "Chassis2", chassis2ExposesItem2);
+ topo.addBoard(chassis3Path, "Chassis", "Chassis3", chassis3ExposesItem2);
+ topo.addBoard(chassis4Path, "Chassis", "Chassis4", chassis4ExposesItem2);
+
+ topo.addBoard(superChassisPath, "Chassis", "SuperChassis",
+ superChassisExposesItem);
+
+ auto assocs = topo.getAssocs(std::views::keys(boards));
+
+ // all blades are contained by their respective chassis
+ EXPECT_EQ(assocs[blade1Path].size(), 1);
+ EXPECT_TRUE(assocs[blade1Path].contains(
+ {"contained_by", "containing", chassis1Path}));
+
+ EXPECT_EQ(assocs[blade2Path].size(), 1);
+ EXPECT_TRUE(assocs[blade2Path].contains(
+ {"contained_by", "containing", chassis2Path}));
+
+ EXPECT_EQ(assocs[blade3Path].size(), 1);
+ EXPECT_TRUE(assocs[blade3Path].contains(
+ {"contained_by", "containing", chassis3Path}));
+
+ EXPECT_EQ(assocs[blade4Path].size(), 1);
+ EXPECT_TRUE(assocs[blade4Path].contains(
+ {"contained_by", "containing", chassis4Path}));
+
+ // all chassis are contained by the superchassis
+ EXPECT_TRUE(assocs[chassis1Path].contains(
+ {"contained_by", "containing", superChassisPath}));
+
+ EXPECT_TRUE(assocs[chassis2Path].contains(
+ {"contained_by", "containing", superChassisPath}));
+
+ EXPECT_TRUE(assocs[chassis3Path].contains(
+ {"contained_by", "containing", superChassisPath}));
+
+ EXPECT_TRUE(assocs[chassis4Path].contains(
+ {"contained_by", "containing", superChassisPath}));
+}