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