1 #include "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("powered_by", "powering", subchassisPath);
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
TEST(Topology,Empty)51 TEST(Topology, Empty)
52 {
53 Topology topo;
54 BoardMap boards;
55
56 auto assocs = topo.getAssocs(boards);
57
58 EXPECT_EQ(assocs.size(), 0);
59 }
60
TEST(Topology,EmptyExposes)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(), 0);
72 }
73
TEST(Topology,MissingConnectsTo)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(), 0);
94 }
95
TEST(Topology,OtherExposes)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(), 0);
107 }
108
TEST(Topology,NoMatchSubchassis)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(), 0);
121 }
122
TEST(Topology,NoMatchSuperchassis)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(), 0);
134 }
135
TEST(Topology,Basic)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(), 1);
148 EXPECT_EQ(assocs[subchassisPath].size(), 1);
149 EXPECT_EQ(assocs[subchassisPath][0], subchassisAssoc);
150 }
151
TEST(Topology,BasicPower)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(), 2);
164 EXPECT_EQ(assocs[subchassisPath].size(), 1);
165 EXPECT_EQ(assocs[subchassisPath][0], subchassisAssoc);
166 EXPECT_EQ(assocs[superchassisPath].size(), 1);
167 EXPECT_EQ(assocs[superchassisPath][0], powerAssoc);
168 }
169
TEST(Topology,NoNewBoards)170 TEST(Topology, NoNewBoards)
171 {
172 Topology topo;
173 BoardMap boards;
174
175 topo.addBoard(subchassisPath, "Chassis", "BoardA", subchassisExposesItem);
176 topo.addBoard(superchassisPath, "Chassis", "BoardB",
177 superchassisExposesItem);
178
179 // Boards A and B aren't new, so no assocs are returned.
180 auto assocs = topo.getAssocs(boards);
181
182 EXPECT_EQ(assocs.size(), 0);
183 }
184
185 TEST(Topology, 2Subchassis)
186 {
187 Topology topo;
188 BoardMap boards{{subchassisPath, "BoardA"},
189 {subchassisPath + "2", "BoardB"},
190 {superchassisPath, "BoardC"}};
191
192 topo.addBoard(subchassisPath, "Chassis", "BoardA", subchassisExposesItem);
193 topo.addBoard(subchassisPath + "2", "Chassis", "BoardB",
194 subchassisExposesItem);
195 topo.addBoard(superchassisPath, "Chassis", "BoardC",
196 superchassisExposesItem);
197
198 auto assocs = topo.getAssocs(boards);
199
200 EXPECT_EQ(assocs.size(), 2);
201 EXPECT_EQ(assocs[subchassisPath].size(), 1);
202 EXPECT_EQ(assocs[subchassisPath][0], subchassisAssoc);
203 EXPECT_EQ(assocs[subchassisPath + "2"].size(), 1);
204 EXPECT_EQ(assocs[subchassisPath + "2"][0], subchassisAssoc);
205 }
206
TEST(Topology,OneNewBoard)207 TEST(Topology, OneNewBoard)
208 {
209 Topology topo;
210 BoardMap boards{{subchassisPath, "BoardA"}};
211
212 topo.addBoard(subchassisPath, "Chassis", "BoardA", subchassisExposesItem);
213 topo.addBoard(subchassisPath + "2", "Chassis", "BoardB",
214 subchassisExposesItem);
215 topo.addBoard(superchassisPath, "Chassis", "BoardC",
216 superchassisExposesItem);
217
218 // Only the assoc for BoardA should be returned
219 auto assocs = topo.getAssocs(boards);
220
221 EXPECT_EQ(assocs.size(), 1);
222 EXPECT_EQ(assocs[subchassisPath].size(), 1);
223 EXPECT_EQ(assocs[subchassisPath][0], subchassisAssoc);
224 }
225
226 TEST(Topology, 2Superchassis)
227 {
228 const Association subchassisAssoc2 =
229 std::make_tuple("contained_by", "containing", superchassisPath + "2");
230
231 Topology topo;
232 BoardMap boards{{subchassisPath, "BoardA"},
233 {superchassisPath, "BoardB"},
234 {superchassisPath + "2", "BoardC"}};
235
236 topo.addBoard(subchassisPath, "Chassis", "BoardA", subchassisExposesItem);
237 topo.addBoard(superchassisPath, "Chassis", "BoardB",
238 superchassisExposesItem);
239 topo.addBoard(superchassisPath + "2", "Chassis", "BoardC",
240 superchassisExposesItem);
241
242 auto assocs = topo.getAssocs(boards);
243
244 EXPECT_EQ(assocs.size(), 1);
245 EXPECT_EQ(assocs[subchassisPath].size(), 2);
246
247 EXPECT_THAT(assocs[subchassisPath],
248 UnorderedElementsAre(subchassisAssoc, subchassisAssoc2));
249 }
250
251 TEST(Topology, 2SuperchassisAnd2Subchassis)
252 {
253 const Association subchassisAssoc2 =
254 std::make_tuple("contained_by", "containing", superchassisPath + "2");
255
256 Topology topo;
257 BoardMap boards{{subchassisPath, "BoardA"},
258 {subchassisPath + "2", "BoardB"},
259 {superchassisPath, "BoardC"},
260 {superchassisPath + "2", "BoardD"}};
261
262 topo.addBoard(subchassisPath, "Chassis", "BoardA", subchassisExposesItem);
263 topo.addBoard(subchassisPath + "2", "Chassis", "BoardB",
264 subchassisExposesItem);
265 topo.addBoard(superchassisPath, "Chassis", "BoardC",
266 superchassisExposesItem);
267 topo.addBoard(superchassisPath + "2", "Chassis", "BoardD",
268 superchassisExposesItem);
269
270 auto assocs = topo.getAssocs(boards);
271
272 EXPECT_EQ(assocs.size(), 2);
273 EXPECT_EQ(assocs[subchassisPath].size(), 2);
274 EXPECT_EQ(assocs[subchassisPath + "2"].size(), 2);
275
276 EXPECT_THAT(assocs[subchassisPath],
277 UnorderedElementsAre(subchassisAssoc, subchassisAssoc2));
278 EXPECT_THAT(assocs[subchassisPath + "2"],
279 UnorderedElementsAre(subchassisAssoc, subchassisAssoc2));
280 }
281
TEST(Topology,Remove)282 TEST(Topology, Remove)
283 {
284 Topology topo;
285 BoardMap boards{{subchassisPath, "BoardA"},
286 {subchassisPath + "2", "BoardB"},
287 {superchassisPath, "BoardC"}};
288
289 topo.addBoard(subchassisPath, "Chassis", "BoardA", subchassisExposesItem);
290 topo.addBoard(subchassisPath + "2", "Chassis", "BoardB",
291 subchassisExposesItem);
292 topo.addBoard(superchassisPath, "Chassis", "BoardC",
293 superchassisExposesItem);
294
295 {
296 auto assocs = topo.getAssocs(boards);
297
298 EXPECT_EQ(assocs.size(), 2);
299 EXPECT_EQ(assocs[subchassisPath].size(), 1);
300 EXPECT_EQ(assocs[subchassisPath][0], subchassisAssoc);
301 EXPECT_EQ(assocs[subchassisPath + "2"].size(), 1);
302 EXPECT_EQ(assocs[subchassisPath + "2"][0], subchassisAssoc);
303 }
304
305 {
306 topo.remove("BoardA");
307 auto assocs = topo.getAssocs(boards);
308
309 EXPECT_EQ(assocs.size(), 1);
310 EXPECT_EQ(assocs[subchassisPath + "2"].size(), 1);
311 EXPECT_EQ(assocs[subchassisPath + "2"][0], subchassisAssoc);
312 }
313
314 {
315 topo.remove("BoardB");
316 auto assocs = topo.getAssocs(boards);
317
318 EXPECT_EQ(assocs.size(), 0);
319 }
320 }
321