blob: f04ce4fd74cb7121b76223d74d247796b3d03ae2 [file] [log] [blame]
Christopher Meisfc9e7fd2025-04-03 13:13:35 +02001#include "entity_manager/topology.hpp"
Benjamin Fairf2f5b7a2022-09-09 19:45:02 +00002
Alexander Hansen32e74182025-08-20 16:16:00 +02003#include <ranges>
4
Benjamin Fairf2f5b7a2022-09-09 19:45:02 +00005#include "gmock/gmock.h"
6#include "gtest/gtest.h"
7
8using ::testing::UnorderedElementsAre;
9
10const std::string subchassisPath =
11 "/xyz/openbmc_project/inventory/system/chassis/Subchassis";
12const std::string superchassisPath =
13 "/xyz/openbmc_project/inventory/system/chassis/Superchassis";
14
15const Association subchassisAssoc =
16 std::make_tuple("contained_by", "containing", superchassisPath);
Patrick Williamsb7077432024-08-16 15:22:21 -040017const Association powerAssoc =
Chau Lya454b302025-07-09 09:22:25 +000018 std::make_tuple("powering", "powered_by", superchassisPath);
Benjamin Fairf2f5b7a2022-09-09 19:45:02 +000019
20const nlohmann::json subchassisExposesItem = nlohmann::json::parse(R"(
21 {
22 "ConnectsToType": "BackplanePort",
23 "Name": "MyDownstreamPort",
24 "Type": "DownstreamPort"
25 }
26)");
27
Jeff Linb02752f2023-12-01 11:23:54 +080028const nlohmann::json powerExposesItem = nlohmann::json::parse(R"(
29 {
30 "ConnectsToType": "BackplanePort",
31 "Name": "MyDownstreamPort",
32 "Type": "DownstreamPort",
33 "PowerPort": true
34 }
35)");
36
Benjamin Fairf2f5b7a2022-09-09 19:45:02 +000037const nlohmann::json superchassisExposesItem = nlohmann::json::parse(R"(
38 {
39 "Name": "MyBackplanePort",
40 "Type": "BackplanePort"
41 }
42)");
43
44const nlohmann::json otherExposesItem = nlohmann::json::parse(R"(
45 {
46 "Name": "MyExposes",
47 "Type": "OtherType"
48 }
49)");
50
Matt Spinler6eb60972023-08-14 16:36:20 -050051using BoardMap = std::map<std::string, std::string>;
52
Benjamin Fairf2f5b7a2022-09-09 19:45:02 +000053TEST(Topology, Empty)
54{
55 Topology topo;
Matt Spinler6eb60972023-08-14 16:36:20 -050056 BoardMap boards;
Benjamin Fairf2f5b7a2022-09-09 19:45:02 +000057
Alexander Hansen32e74182025-08-20 16:16:00 +020058 auto assocs = topo.getAssocs(std::views::keys(boards));
Benjamin Fairf2f5b7a2022-09-09 19:45:02 +000059
Ed Tanousc6af85c2025-04-08 10:13:33 -070060 EXPECT_EQ(assocs.size(), 0U);
Benjamin Fairf2f5b7a2022-09-09 19:45:02 +000061}
62
63TEST(Topology, EmptyExposes)
64{
65 Topology topo;
Matt Spinler6eb60972023-08-14 16:36:20 -050066 BoardMap boards{{subchassisPath, "BoardA"}, {superchassisPath, "BoardB"}};
Benjamin Fairf2f5b7a2022-09-09 19:45:02 +000067
Matt Spinler6eb60972023-08-14 16:36:20 -050068 topo.addBoard(subchassisPath, "Chassis", "BoardA", nlohmann::json());
69 topo.addBoard(superchassisPath, "Chassis", "BoardB", nlohmann::json());
Benjamin Fairf2f5b7a2022-09-09 19:45:02 +000070
Alexander Hansen32e74182025-08-20 16:16:00 +020071 auto assocs = topo.getAssocs(std::views::keys(boards));
Benjamin Fairf2f5b7a2022-09-09 19:45:02 +000072
Ed Tanousc6af85c2025-04-08 10:13:33 -070073 EXPECT_EQ(assocs.size(), 0U);
Benjamin Fairf2f5b7a2022-09-09 19:45:02 +000074}
75
76TEST(Topology, MissingConnectsTo)
77{
78 const nlohmann::json subchassisMissingConnectsTo = nlohmann::json::parse(R"(
79 {
80 "Name": "MyDownstreamPort",
81 "Type": "DownstreamPort"
82 }
83 )");
84
85 Topology topo;
Matt Spinler6eb60972023-08-14 16:36:20 -050086 BoardMap boards{{subchassisPath, "BoardA"}, {superchassisPath, "BoardB"}};
Benjamin Fairf2f5b7a2022-09-09 19:45:02 +000087
Matt Spinler6eb60972023-08-14 16:36:20 -050088 topo.addBoard(subchassisPath, "Chassis", "BoardA",
89 subchassisMissingConnectsTo);
90 topo.addBoard(superchassisPath, "Chassis", "BoardB",
91 superchassisExposesItem);
Benjamin Fairf2f5b7a2022-09-09 19:45:02 +000092
Alexander Hansen32e74182025-08-20 16:16:00 +020093 auto assocs = topo.getAssocs(std::views::keys(boards));
Benjamin Fairf2f5b7a2022-09-09 19:45:02 +000094
Ed Tanousc6af85c2025-04-08 10:13:33 -070095 EXPECT_EQ(assocs.size(), 0U);
Benjamin Fairf2f5b7a2022-09-09 19:45:02 +000096}
97
98TEST(Topology, OtherExposes)
99{
100 Topology topo;
Matt Spinler6eb60972023-08-14 16:36:20 -0500101 BoardMap boards{{subchassisPath, "BoardA"}, {superchassisPath, "BoardB"}};
Benjamin Fairf2f5b7a2022-09-09 19:45:02 +0000102
Matt Spinler6eb60972023-08-14 16:36:20 -0500103 topo.addBoard(subchassisPath, "Chassis", "BoardA", otherExposesItem);
104 topo.addBoard(superchassisPath, "Chassis", "BoardB", otherExposesItem);
Benjamin Fairf2f5b7a2022-09-09 19:45:02 +0000105
Alexander Hansen32e74182025-08-20 16:16:00 +0200106 auto assocs = topo.getAssocs(std::views::keys(boards));
Benjamin Fairf2f5b7a2022-09-09 19:45:02 +0000107
Ed Tanousc6af85c2025-04-08 10:13:33 -0700108 EXPECT_EQ(assocs.size(), 0U);
Benjamin Fairf2f5b7a2022-09-09 19:45:02 +0000109}
110
111TEST(Topology, NoMatchSubchassis)
112{
113 Topology topo;
Matt Spinler6eb60972023-08-14 16:36:20 -0500114 BoardMap boards{{subchassisPath, "BoardA"}, {superchassisPath, "BoardB"}};
Benjamin Fairf2f5b7a2022-09-09 19:45:02 +0000115
Matt Spinler6eb60972023-08-14 16:36:20 -0500116 topo.addBoard(subchassisPath, "Chassis", "BoardA", otherExposesItem);
117 topo.addBoard(superchassisPath, "Chassis", "BoardB",
118 superchassisExposesItem);
Benjamin Fairf2f5b7a2022-09-09 19:45:02 +0000119
Alexander Hansen32e74182025-08-20 16:16:00 +0200120 auto assocs = topo.getAssocs(std::views::keys(boards));
Benjamin Fairf2f5b7a2022-09-09 19:45:02 +0000121
Ed Tanousc6af85c2025-04-08 10:13:33 -0700122 EXPECT_EQ(assocs.size(), 0U);
Benjamin Fairf2f5b7a2022-09-09 19:45:02 +0000123}
124
125TEST(Topology, NoMatchSuperchassis)
126{
127 Topology topo;
Matt Spinler6eb60972023-08-14 16:36:20 -0500128 BoardMap boards{{subchassisPath, "BoardA"}, {superchassisPath, "BoardB"}};
Benjamin Fairf2f5b7a2022-09-09 19:45:02 +0000129
Matt Spinler6eb60972023-08-14 16:36:20 -0500130 topo.addBoard(subchassisPath, "Chassis", "BoardA", subchassisExposesItem);
131 topo.addBoard(superchassisPath, "Chassis", "BoardB", otherExposesItem);
Benjamin Fairf2f5b7a2022-09-09 19:45:02 +0000132
Alexander Hansen32e74182025-08-20 16:16:00 +0200133 auto assocs = topo.getAssocs(std::views::keys(boards));
Benjamin Fairf2f5b7a2022-09-09 19:45:02 +0000134
Ed Tanousc6af85c2025-04-08 10:13:33 -0700135 EXPECT_EQ(assocs.size(), 0U);
Benjamin Fairf2f5b7a2022-09-09 19:45:02 +0000136}
137
138TEST(Topology, Basic)
139{
140 Topology topo;
Matt Spinler6eb60972023-08-14 16:36:20 -0500141 BoardMap boards{{subchassisPath, "BoardA"}, {superchassisPath, "BoardB"}};
Benjamin Fairf2f5b7a2022-09-09 19:45:02 +0000142
Matt Spinler6eb60972023-08-14 16:36:20 -0500143 topo.addBoard(subchassisPath, "Chassis", "BoardA", subchassisExposesItem);
144 topo.addBoard(superchassisPath, "Chassis", "BoardB",
145 superchassisExposesItem);
Benjamin Fairf2f5b7a2022-09-09 19:45:02 +0000146
Alexander Hansen32e74182025-08-20 16:16:00 +0200147 auto assocs = topo.getAssocs(std::views::keys(boards));
Benjamin Fairf2f5b7a2022-09-09 19:45:02 +0000148
Ed Tanousc6af85c2025-04-08 10:13:33 -0700149 EXPECT_EQ(assocs.size(), 1U);
150 EXPECT_EQ(assocs[subchassisPath].size(), 1U);
Alexander Hansen0519f572025-08-19 18:11:04 +0200151 EXPECT_TRUE(assocs[subchassisPath].contains(subchassisAssoc));
Benjamin Fairf2f5b7a2022-09-09 19:45:02 +0000152}
153
Jeff Linb02752f2023-12-01 11:23:54 +0800154TEST(Topology, BasicPower)
155{
156 Topology topo;
157 BoardMap boards{{subchassisPath, "BoardA"}, {superchassisPath, "BoardB"}};
158
159 topo.addBoard(subchassisPath, "Chassis", "BoardA", powerExposesItem);
160 topo.addBoard(superchassisPath, "Chassis", "BoardB",
161 superchassisExposesItem);
162
Alexander Hansen32e74182025-08-20 16:16:00 +0200163 auto assocs = topo.getAssocs(std::views::keys(boards));
Jeff Linb02752f2023-12-01 11:23:54 +0800164
Chau Lya454b302025-07-09 09:22:25 +0000165 EXPECT_EQ(assocs.size(), 1U);
166 EXPECT_EQ(assocs[subchassisPath].size(), 2U);
Alexander Hansen0519f572025-08-19 18:11:04 +0200167 EXPECT_TRUE(assocs[subchassisPath].contains(subchassisAssoc));
168 EXPECT_TRUE(assocs[subchassisPath].contains(powerAssoc));
Jeff Linb02752f2023-12-01 11:23:54 +0800169}
170
Matt Spinler6eb60972023-08-14 16:36:20 -0500171TEST(Topology, NoNewBoards)
172{
173 Topology topo;
174 BoardMap boards;
175
176 topo.addBoard(subchassisPath, "Chassis", "BoardA", subchassisExposesItem);
177 topo.addBoard(superchassisPath, "Chassis", "BoardB",
178 superchassisExposesItem);
179
180 // Boards A and B aren't new, so no assocs are returned.
Alexander Hansen32e74182025-08-20 16:16:00 +0200181 auto assocs = topo.getAssocs(std::views::keys(boards));
Matt Spinler6eb60972023-08-14 16:36:20 -0500182
Ed Tanousc6af85c2025-04-08 10:13:33 -0700183 EXPECT_EQ(assocs.size(), 0U);
Matt Spinler6eb60972023-08-14 16:36:20 -0500184}
185
Benjamin Fairf2f5b7a2022-09-09 19:45:02 +0000186TEST(Topology, 2Subchassis)
187{
188 Topology topo;
Matt Spinler6eb60972023-08-14 16:36:20 -0500189 BoardMap boards{{subchassisPath, "BoardA"},
190 {subchassisPath + "2", "BoardB"},
191 {superchassisPath, "BoardC"}};
Benjamin Fairf2f5b7a2022-09-09 19:45:02 +0000192
Matt Spinler6eb60972023-08-14 16:36:20 -0500193 topo.addBoard(subchassisPath, "Chassis", "BoardA", subchassisExposesItem);
194 topo.addBoard(subchassisPath + "2", "Chassis", "BoardB",
195 subchassisExposesItem);
196 topo.addBoard(superchassisPath, "Chassis", "BoardC",
197 superchassisExposesItem);
Benjamin Fairf2f5b7a2022-09-09 19:45:02 +0000198
Alexander Hansen32e74182025-08-20 16:16:00 +0200199 auto assocs = topo.getAssocs(std::views::keys(boards));
Benjamin Fairf2f5b7a2022-09-09 19:45:02 +0000200
Ed Tanousc6af85c2025-04-08 10:13:33 -0700201 EXPECT_EQ(assocs.size(), 2U);
202 EXPECT_EQ(assocs[subchassisPath].size(), 1U);
Alexander Hansen0519f572025-08-19 18:11:04 +0200203 EXPECT_TRUE(assocs[subchassisPath].contains(subchassisAssoc));
Ed Tanousc6af85c2025-04-08 10:13:33 -0700204 EXPECT_EQ(assocs[subchassisPath + "2"].size(), 1U);
Alexander Hansen0519f572025-08-19 18:11:04 +0200205 EXPECT_TRUE(assocs[subchassisPath + "2"].contains(subchassisAssoc));
Benjamin Fairf2f5b7a2022-09-09 19:45:02 +0000206}
207
Matt Spinler6eb60972023-08-14 16:36:20 -0500208TEST(Topology, OneNewBoard)
209{
210 Topology topo;
211 BoardMap boards{{subchassisPath, "BoardA"}};
212
213 topo.addBoard(subchassisPath, "Chassis", "BoardA", subchassisExposesItem);
214 topo.addBoard(subchassisPath + "2", "Chassis", "BoardB",
215 subchassisExposesItem);
216 topo.addBoard(superchassisPath, "Chassis", "BoardC",
217 superchassisExposesItem);
218
219 // Only the assoc for BoardA should be returned
Alexander Hansen32e74182025-08-20 16:16:00 +0200220 auto assocs = topo.getAssocs(std::views::keys(boards));
Matt Spinler6eb60972023-08-14 16:36:20 -0500221
Ed Tanousc6af85c2025-04-08 10:13:33 -0700222 EXPECT_EQ(assocs.size(), 1U);
223 EXPECT_EQ(assocs[subchassisPath].size(), 1U);
Alexander Hansen0519f572025-08-19 18:11:04 +0200224 EXPECT_TRUE(assocs[subchassisPath].contains(subchassisAssoc));
Matt Spinler6eb60972023-08-14 16:36:20 -0500225}
226
Benjamin Fairf2f5b7a2022-09-09 19:45:02 +0000227TEST(Topology, 2Superchassis)
228{
Alexander Hansen32e74182025-08-20 16:16:00 +0200229 Association subchassisAssoc2 =
Benjamin Fairf2f5b7a2022-09-09 19:45:02 +0000230 std::make_tuple("contained_by", "containing", superchassisPath + "2");
231
232 Topology topo;
Matt Spinler6eb60972023-08-14 16:36:20 -0500233 BoardMap boards{{subchassisPath, "BoardA"},
234 {superchassisPath, "BoardB"},
235 {superchassisPath + "2", "BoardC"}};
Benjamin Fairf2f5b7a2022-09-09 19:45:02 +0000236
Matt Spinler6eb60972023-08-14 16:36:20 -0500237 topo.addBoard(subchassisPath, "Chassis", "BoardA", subchassisExposesItem);
238 topo.addBoard(superchassisPath, "Chassis", "BoardB",
239 superchassisExposesItem);
240 topo.addBoard(superchassisPath + "2", "Chassis", "BoardC",
241 superchassisExposesItem);
Benjamin Fairf2f5b7a2022-09-09 19:45:02 +0000242
Alexander Hansen32e74182025-08-20 16:16:00 +0200243 auto assocs = topo.getAssocs(std::views::keys(boards));
Benjamin Fairf2f5b7a2022-09-09 19:45:02 +0000244
Ed Tanousc6af85c2025-04-08 10:13:33 -0700245 EXPECT_EQ(assocs.size(), 1U);
246 EXPECT_EQ(assocs[subchassisPath].size(), 2U);
Benjamin Fairf2f5b7a2022-09-09 19:45:02 +0000247
248 EXPECT_THAT(assocs[subchassisPath],
249 UnorderedElementsAre(subchassisAssoc, subchassisAssoc2));
250}
251
252TEST(Topology, 2SuperchassisAnd2Subchassis)
253{
Alexander Hansen32e74182025-08-20 16:16:00 +0200254 Association subchassisAssoc2 =
Benjamin Fairf2f5b7a2022-09-09 19:45:02 +0000255 std::make_tuple("contained_by", "containing", superchassisPath + "2");
256
257 Topology topo;
Matt Spinler6eb60972023-08-14 16:36:20 -0500258 BoardMap boards{{subchassisPath, "BoardA"},
259 {subchassisPath + "2", "BoardB"},
260 {superchassisPath, "BoardC"},
261 {superchassisPath + "2", "BoardD"}};
Benjamin Fairf2f5b7a2022-09-09 19:45:02 +0000262
Matt Spinler6eb60972023-08-14 16:36:20 -0500263 topo.addBoard(subchassisPath, "Chassis", "BoardA", subchassisExposesItem);
264 topo.addBoard(subchassisPath + "2", "Chassis", "BoardB",
265 subchassisExposesItem);
266 topo.addBoard(superchassisPath, "Chassis", "BoardC",
267 superchassisExposesItem);
268 topo.addBoard(superchassisPath + "2", "Chassis", "BoardD",
269 superchassisExposesItem);
Benjamin Fairf2f5b7a2022-09-09 19:45:02 +0000270
Alexander Hansen32e74182025-08-20 16:16:00 +0200271 auto assocs = topo.getAssocs(std::views::keys(boards));
Benjamin Fairf2f5b7a2022-09-09 19:45:02 +0000272
Ed Tanousc6af85c2025-04-08 10:13:33 -0700273 EXPECT_EQ(assocs.size(), 2U);
274 EXPECT_EQ(assocs[subchassisPath].size(), 2U);
275 EXPECT_EQ(assocs[subchassisPath + "2"].size(), 2U);
Benjamin Fairf2f5b7a2022-09-09 19:45:02 +0000276
277 EXPECT_THAT(assocs[subchassisPath],
278 UnorderedElementsAre(subchassisAssoc, subchassisAssoc2));
279 EXPECT_THAT(assocs[subchassisPath + "2"],
280 UnorderedElementsAre(subchassisAssoc, subchassisAssoc2));
281}
Matt Spinler6eb60972023-08-14 16:36:20 -0500282
283TEST(Topology, Remove)
284{
285 Topology topo;
286 BoardMap boards{{subchassisPath, "BoardA"},
287 {subchassisPath + "2", "BoardB"},
288 {superchassisPath, "BoardC"}};
289
290 topo.addBoard(subchassisPath, "Chassis", "BoardA", subchassisExposesItem);
291 topo.addBoard(subchassisPath + "2", "Chassis", "BoardB",
292 subchassisExposesItem);
293 topo.addBoard(superchassisPath, "Chassis", "BoardC",
294 superchassisExposesItem);
295
296 {
Alexander Hansen32e74182025-08-20 16:16:00 +0200297 auto assocs = topo.getAssocs(std::views::keys(boards));
Matt Spinler6eb60972023-08-14 16:36:20 -0500298
Ed Tanousc6af85c2025-04-08 10:13:33 -0700299 EXPECT_EQ(assocs.size(), 2U);
300 EXPECT_EQ(assocs[subchassisPath].size(), 1U);
Alexander Hansen0519f572025-08-19 18:11:04 +0200301 EXPECT_TRUE(assocs[subchassisPath].contains(subchassisAssoc));
Ed Tanousc6af85c2025-04-08 10:13:33 -0700302 EXPECT_EQ(assocs[subchassisPath + "2"].size(), 1U);
Alexander Hansen0519f572025-08-19 18:11:04 +0200303 EXPECT_TRUE(assocs[subchassisPath + "2"].contains(subchassisAssoc));
Matt Spinler6eb60972023-08-14 16:36:20 -0500304 }
305
306 {
307 topo.remove("BoardA");
Alexander Hansen32e74182025-08-20 16:16:00 +0200308 auto assocs = topo.getAssocs(std::views::keys(boards));
Matt Spinler6eb60972023-08-14 16:36:20 -0500309
Ed Tanousc6af85c2025-04-08 10:13:33 -0700310 EXPECT_EQ(assocs.size(), 1U);
311 EXPECT_EQ(assocs[subchassisPath + "2"].size(), 1U);
Alexander Hansen0519f572025-08-19 18:11:04 +0200312 EXPECT_TRUE(assocs[subchassisPath + "2"].contains(subchassisAssoc));
Matt Spinler6eb60972023-08-14 16:36:20 -0500313 }
314
315 {
316 topo.remove("BoardB");
Alexander Hansen32e74182025-08-20 16:16:00 +0200317 auto assocs = topo.getAssocs(std::views::keys(boards));
Matt Spinler6eb60972023-08-14 16:36:20 -0500318
Ed Tanousc6af85c2025-04-08 10:13:33 -0700319 EXPECT_EQ(assocs.size(), 0U);
Matt Spinler6eb60972023-08-14 16:36:20 -0500320 }
321}