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 = std::make_tuple("powered_by", "powering", 16 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 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 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 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 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 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 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 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 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 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 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 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