xref: /openbmc/entity-manager/test/test_topology.cpp (revision 4e1142d6f418f48ea260132ebb5a4995b2310c90)
1 #include "entity_manager/topology.hpp"
2 
3 #include "gmock/gmock.h"
4 #include "gtest/gtest.h"
5 
6 using ::testing::UnorderedElementsAre;
7 
8 const std::string subchassisPath =
9     "/xyz/openbmc_project/inventory/system/chassis/Subchassis";
10 const std::string superchassisPath =
11     "/xyz/openbmc_project/inventory/system/chassis/Superchassis";
12 
13 const Association subchassisAssoc =
14     std::make_tuple("contained_by", "containing", superchassisPath);
15 const Association powerAssoc =
16     std::make_tuple("powering", "powered_by", superchassisPath);
17 
18 const nlohmann::json subchassisExposesItem = nlohmann::json::parse(R"(
19     {
20         "ConnectsToType": "BackplanePort",
21         "Name": "MyDownstreamPort",
22         "Type": "DownstreamPort"
23     }
24 )");
25 
26 const nlohmann::json powerExposesItem = nlohmann::json::parse(R"(
27     {
28         "ConnectsToType": "BackplanePort",
29         "Name": "MyDownstreamPort",
30         "Type": "DownstreamPort",
31         "PowerPort": true
32     }
33 )");
34 
35 const nlohmann::json superchassisExposesItem = nlohmann::json::parse(R"(
36     {
37         "Name": "MyBackplanePort",
38         "Type": "BackplanePort"
39     }
40 )");
41 
42 const nlohmann::json otherExposesItem = nlohmann::json::parse(R"(
43     {
44         "Name": "MyExposes",
45         "Type": "OtherType"
46     }
47 )");
48 
49 using BoardMap = std::map<std::string, std::string>;
50 
51 TEST(Topology, Empty)
52 {
53     Topology topo;
54     BoardMap boards;
55 
56     auto assocs = topo.getAssocs(boards);
57 
58     EXPECT_EQ(assocs.size(), 0U);
59 }
60 
61 TEST(Topology, EmptyExposes)
62 {
63     Topology topo;
64     BoardMap boards{{subchassisPath, "BoardA"}, {superchassisPath, "BoardB"}};
65 
66     topo.addBoard(subchassisPath, "Chassis", "BoardA", nlohmann::json());
67     topo.addBoard(superchassisPath, "Chassis", "BoardB", nlohmann::json());
68 
69     auto assocs = topo.getAssocs(boards);
70 
71     EXPECT_EQ(assocs.size(), 0U);
72 }
73 
74 TEST(Topology, MissingConnectsTo)
75 {
76     const nlohmann::json subchassisMissingConnectsTo = nlohmann::json::parse(R"(
77         {
78             "Name": "MyDownstreamPort",
79             "Type": "DownstreamPort"
80         }
81     )");
82 
83     Topology topo;
84     BoardMap boards{{subchassisPath, "BoardA"}, {superchassisPath, "BoardB"}};
85 
86     topo.addBoard(subchassisPath, "Chassis", "BoardA",
87                   subchassisMissingConnectsTo);
88     topo.addBoard(superchassisPath, "Chassis", "BoardB",
89                   superchassisExposesItem);
90 
91     auto assocs = topo.getAssocs(boards);
92 
93     EXPECT_EQ(assocs.size(), 0U);
94 }
95 
96 TEST(Topology, OtherExposes)
97 {
98     Topology topo;
99     BoardMap boards{{subchassisPath, "BoardA"}, {superchassisPath, "BoardB"}};
100 
101     topo.addBoard(subchassisPath, "Chassis", "BoardA", otherExposesItem);
102     topo.addBoard(superchassisPath, "Chassis", "BoardB", otherExposesItem);
103 
104     auto assocs = topo.getAssocs(boards);
105 
106     EXPECT_EQ(assocs.size(), 0U);
107 }
108 
109 TEST(Topology, NoMatchSubchassis)
110 {
111     Topology topo;
112     BoardMap boards{{subchassisPath, "BoardA"}, {superchassisPath, "BoardB"}};
113 
114     topo.addBoard(subchassisPath, "Chassis", "BoardA", otherExposesItem);
115     topo.addBoard(superchassisPath, "Chassis", "BoardB",
116                   superchassisExposesItem);
117 
118     auto assocs = topo.getAssocs(boards);
119 
120     EXPECT_EQ(assocs.size(), 0U);
121 }
122 
123 TEST(Topology, NoMatchSuperchassis)
124 {
125     Topology topo;
126     BoardMap boards{{subchassisPath, "BoardA"}, {superchassisPath, "BoardB"}};
127 
128     topo.addBoard(subchassisPath, "Chassis", "BoardA", subchassisExposesItem);
129     topo.addBoard(superchassisPath, "Chassis", "BoardB", otherExposesItem);
130 
131     auto assocs = topo.getAssocs(boards);
132 
133     EXPECT_EQ(assocs.size(), 0U);
134 }
135 
136 TEST(Topology, Basic)
137 {
138     Topology topo;
139     BoardMap boards{{subchassisPath, "BoardA"}, {superchassisPath, "BoardB"}};
140 
141     topo.addBoard(subchassisPath, "Chassis", "BoardA", subchassisExposesItem);
142     topo.addBoard(superchassisPath, "Chassis", "BoardB",
143                   superchassisExposesItem);
144 
145     auto assocs = topo.getAssocs(boards);
146 
147     EXPECT_EQ(assocs.size(), 1U);
148     EXPECT_EQ(assocs[subchassisPath].size(), 1U);
149     EXPECT_EQ(assocs[subchassisPath][0], subchassisAssoc);
150 }
151 
152 TEST(Topology, BasicPower)
153 {
154     Topology topo;
155     BoardMap boards{{subchassisPath, "BoardA"}, {superchassisPath, "BoardB"}};
156 
157     topo.addBoard(subchassisPath, "Chassis", "BoardA", powerExposesItem);
158     topo.addBoard(superchassisPath, "Chassis", "BoardB",
159                   superchassisExposesItem);
160 
161     auto assocs = topo.getAssocs(boards);
162 
163     EXPECT_EQ(assocs.size(), 1U);
164     EXPECT_EQ(assocs[subchassisPath].size(), 2U);
165     EXPECT_EQ(assocs[subchassisPath][0], subchassisAssoc);
166     EXPECT_EQ(assocs[subchassisPath][1], powerAssoc);
167 }
168 
169 TEST(Topology, NoNewBoards)
170 {
171     Topology topo;
172     BoardMap boards;
173 
174     topo.addBoard(subchassisPath, "Chassis", "BoardA", subchassisExposesItem);
175     topo.addBoard(superchassisPath, "Chassis", "BoardB",
176                   superchassisExposesItem);
177 
178     // Boards A and B aren't new, so no assocs are returned.
179     auto assocs = topo.getAssocs(boards);
180 
181     EXPECT_EQ(assocs.size(), 0U);
182 }
183 
184 TEST(Topology, 2Subchassis)
185 {
186     Topology topo;
187     BoardMap boards{{subchassisPath, "BoardA"},
188                     {subchassisPath + "2", "BoardB"},
189                     {superchassisPath, "BoardC"}};
190 
191     topo.addBoard(subchassisPath, "Chassis", "BoardA", subchassisExposesItem);
192     topo.addBoard(subchassisPath + "2", "Chassis", "BoardB",
193                   subchassisExposesItem);
194     topo.addBoard(superchassisPath, "Chassis", "BoardC",
195                   superchassisExposesItem);
196 
197     auto assocs = topo.getAssocs(boards);
198 
199     EXPECT_EQ(assocs.size(), 2U);
200     EXPECT_EQ(assocs[subchassisPath].size(), 1U);
201     EXPECT_EQ(assocs[subchassisPath][0], subchassisAssoc);
202     EXPECT_EQ(assocs[subchassisPath + "2"].size(), 1U);
203     EXPECT_EQ(assocs[subchassisPath + "2"][0], subchassisAssoc);
204 }
205 
206 TEST(Topology, OneNewBoard)
207 {
208     Topology topo;
209     BoardMap boards{{subchassisPath, "BoardA"}};
210 
211     topo.addBoard(subchassisPath, "Chassis", "BoardA", subchassisExposesItem);
212     topo.addBoard(subchassisPath + "2", "Chassis", "BoardB",
213                   subchassisExposesItem);
214     topo.addBoard(superchassisPath, "Chassis", "BoardC",
215                   superchassisExposesItem);
216 
217     // Only the assoc for BoardA should be returned
218     auto assocs = topo.getAssocs(boards);
219 
220     EXPECT_EQ(assocs.size(), 1U);
221     EXPECT_EQ(assocs[subchassisPath].size(), 1U);
222     EXPECT_EQ(assocs[subchassisPath][0], subchassisAssoc);
223 }
224 
225 TEST(Topology, 2Superchassis)
226 {
227     const Association subchassisAssoc2 =
228         std::make_tuple("contained_by", "containing", superchassisPath + "2");
229 
230     Topology topo;
231     BoardMap boards{{subchassisPath, "BoardA"},
232                     {superchassisPath, "BoardB"},
233                     {superchassisPath + "2", "BoardC"}};
234 
235     topo.addBoard(subchassisPath, "Chassis", "BoardA", subchassisExposesItem);
236     topo.addBoard(superchassisPath, "Chassis", "BoardB",
237                   superchassisExposesItem);
238     topo.addBoard(superchassisPath + "2", "Chassis", "BoardC",
239                   superchassisExposesItem);
240 
241     auto assocs = topo.getAssocs(boards);
242 
243     EXPECT_EQ(assocs.size(), 1U);
244     EXPECT_EQ(assocs[subchassisPath].size(), 2U);
245 
246     EXPECT_THAT(assocs[subchassisPath],
247                 UnorderedElementsAre(subchassisAssoc, subchassisAssoc2));
248 }
249 
250 TEST(Topology, 2SuperchassisAnd2Subchassis)
251 {
252     const Association subchassisAssoc2 =
253         std::make_tuple("contained_by", "containing", superchassisPath + "2");
254 
255     Topology topo;
256     BoardMap boards{{subchassisPath, "BoardA"},
257                     {subchassisPath + "2", "BoardB"},
258                     {superchassisPath, "BoardC"},
259                     {superchassisPath + "2", "BoardD"}};
260 
261     topo.addBoard(subchassisPath, "Chassis", "BoardA", subchassisExposesItem);
262     topo.addBoard(subchassisPath + "2", "Chassis", "BoardB",
263                   subchassisExposesItem);
264     topo.addBoard(superchassisPath, "Chassis", "BoardC",
265                   superchassisExposesItem);
266     topo.addBoard(superchassisPath + "2", "Chassis", "BoardD",
267                   superchassisExposesItem);
268 
269     auto assocs = topo.getAssocs(boards);
270 
271     EXPECT_EQ(assocs.size(), 2U);
272     EXPECT_EQ(assocs[subchassisPath].size(), 2U);
273     EXPECT_EQ(assocs[subchassisPath + "2"].size(), 2U);
274 
275     EXPECT_THAT(assocs[subchassisPath],
276                 UnorderedElementsAre(subchassisAssoc, subchassisAssoc2));
277     EXPECT_THAT(assocs[subchassisPath + "2"],
278                 UnorderedElementsAre(subchassisAssoc, subchassisAssoc2));
279 }
280 
281 TEST(Topology, Remove)
282 {
283     Topology topo;
284     BoardMap boards{{subchassisPath, "BoardA"},
285                     {subchassisPath + "2", "BoardB"},
286                     {superchassisPath, "BoardC"}};
287 
288     topo.addBoard(subchassisPath, "Chassis", "BoardA", subchassisExposesItem);
289     topo.addBoard(subchassisPath + "2", "Chassis", "BoardB",
290                   subchassisExposesItem);
291     topo.addBoard(superchassisPath, "Chassis", "BoardC",
292                   superchassisExposesItem);
293 
294     {
295         auto assocs = topo.getAssocs(boards);
296 
297         EXPECT_EQ(assocs.size(), 2U);
298         EXPECT_EQ(assocs[subchassisPath].size(), 1U);
299         EXPECT_EQ(assocs[subchassisPath][0], subchassisAssoc);
300         EXPECT_EQ(assocs[subchassisPath + "2"].size(), 1U);
301         EXPECT_EQ(assocs[subchassisPath + "2"][0], subchassisAssoc);
302     }
303 
304     {
305         topo.remove("BoardA");
306         auto assocs = topo.getAssocs(boards);
307 
308         EXPECT_EQ(assocs.size(), 1U);
309         EXPECT_EQ(assocs[subchassisPath + "2"].size(), 1U);
310         EXPECT_EQ(assocs[subchassisPath + "2"][0], subchassisAssoc);
311     }
312 
313     {
314         topo.remove("BoardB");
315         auto assocs = topo.getAssocs(boards);
316 
317         EXPECT_EQ(assocs.size(), 0U);
318     }
319 }
320