1 #include "src/associations.hpp" 2 3 #include "src/test/util/asio_server_class.hpp" 4 #include "src/test/util/association_objects.hpp" 5 #include "src/test/util/debug_output.hpp" 6 7 #include <sdbusplus/asio/connection.hpp> 8 #include <sdbusplus/asio/object_server.hpp> 9 10 #include <gtest/gtest.h> 11 12 class TestAssociations : public AsioServerClassTest 13 { 14 }; 15 sdbusplus::asio::object_server* TestAssociations::AsioServerClassTest::server = 16 nullptr; 17 18 // Verify call when path is not in associated owners 19 TEST_F(TestAssociations, SourcePathNotInAssociations) 20 { 21 EXPECT_NE(nullptr, server); 22 std::string sourcePath = "/xyz/openbmc_project/no/association"; 23 AssociationMaps assocMaps; 24 25 removeAssociation(sourcePath, DEFAULT_DBUS_SVC, *server, assocMaps); 26 } 27 28 // Verify call when owner is not in associated owners 29 TEST_F(TestAssociations, OwnerNotInAssociations) 30 { 31 AssociationMaps assocMaps; 32 assocMaps.owners = createDefaultOwnerAssociation(); 33 34 removeAssociation(DEFAULT_SOURCE_PATH, DEFAULT_DBUS_SVC, *server, 35 assocMaps); 36 } 37 38 // Verify call when path is not in associated interfaces 39 TEST_F(TestAssociations, PathNotInAssocInterfaces) 40 { 41 AssociationMaps assocMaps; 42 43 assocMaps.owners = createDefaultOwnerAssociation(); 44 45 removeAssociation(DEFAULT_SOURCE_PATH, DEFAULT_DBUS_SVC, *server, 46 assocMaps); 47 48 EXPECT_TRUE(assocMaps.owners.empty()); 49 } 50 51 // Verify call when path is in associated interfaces 52 TEST_F(TestAssociations, PathIsInAssociatedInterfaces) 53 { 54 // Build up these objects so that an associated interface will match 55 // with the associated owner being removed 56 AssociationMaps assocMaps; 57 assocMaps.owners = createDefaultOwnerAssociation(); 58 assocMaps.ifaces = createDefaultInterfaceAssociation(server); 59 60 removeAssociation(DEFAULT_SOURCE_PATH, DEFAULT_DBUS_SVC, *server, 61 assocMaps); 62 63 // Verify owner association was deleted 64 EXPECT_TRUE(assocMaps.owners.empty()); 65 66 // Verify endpoint was deleted from interface association 67 auto intfEndpoints = 68 std::get<endpointsPos>(assocMaps.ifaces[DEFAULT_FWD_PATH]); 69 EXPECT_EQ(intfEndpoints.size(), 0); 70 intfEndpoints = std::get<endpointsPos>(assocMaps.ifaces[DEFAULT_REV_PATH]); 71 EXPECT_EQ(intfEndpoints.size(), 0); 72 } 73 74 // Verify call when path is in associated interfaces, with extra endpoints 75 TEST_F(TestAssociations, PathIsInAssociatedInterfacesExtraEndpoints) 76 { 77 // Build up these objects so that an associated interface will match 78 // with the associated owner being removed 79 AssociationMaps assocMaps; 80 assocMaps.owners = createDefaultOwnerAssociation(); 81 assocMaps.ifaces = createDefaultInterfaceAssociation(server); 82 83 // Add another endpoint to the assoc interfaces 84 addEndpointToInterfaceAssociation(assocMaps.ifaces); 85 86 removeAssociation(DEFAULT_SOURCE_PATH, DEFAULT_DBUS_SVC, *server, 87 assocMaps); 88 89 // Verify owner association was deleted 90 EXPECT_TRUE(assocMaps.owners.empty()); 91 92 // Verify all endpoints are deleted since source path was deleted 93 auto intfEndpoints = 94 std::get<endpointsPos>(assocMaps.ifaces[DEFAULT_FWD_PATH]); 95 EXPECT_EQ(intfEndpoints.size(), 0); 96 intfEndpoints = std::get<endpointsPos>(assocMaps.ifaces[DEFAULT_REV_PATH]); 97 EXPECT_EQ(intfEndpoints.size(), 0); 98 } 99 100 // Verify no associations or endpoints removed when the change is identical 101 TEST_F(TestAssociations, checkAssociationEndpointRemovesNoEpRemove) 102 { 103 104 AssociationPaths newAssocPaths = { 105 {DEFAULT_FWD_PATH, {DEFAULT_ENDPOINT}}, 106 {DEFAULT_REV_PATH, {DEFAULT_SOURCE_PATH}}}; 107 108 AssociationMaps assocMaps; 109 assocMaps.owners = createDefaultOwnerAssociation(); 110 assocMaps.ifaces = createDefaultInterfaceAssociation(server); 111 112 checkAssociationEndpointRemoves(DEFAULT_SOURCE_PATH, DEFAULT_DBUS_SVC, 113 newAssocPaths, *server, assocMaps); 114 115 // Verify endpoints were not deleted because they matche with what was 116 // in the original 117 auto intfEndpoints = 118 std::get<endpointsPos>(assocMaps.ifaces[DEFAULT_FWD_PATH]); 119 EXPECT_EQ(intfEndpoints.size(), 1); 120 intfEndpoints = std::get<endpointsPos>(assocMaps.ifaces[DEFAULT_REV_PATH]); 121 EXPECT_EQ(intfEndpoints.size(), 1); 122 } 123 124 // Verify endpoint is removed when assoc path is different 125 TEST_F(TestAssociations, checkAssociationEndpointRemovesEpRemoveApDiff) 126 { 127 AssociationPaths newAssocPaths = {{"/different/path", {DEFAULT_ENDPOINT}}}; 128 129 AssociationMaps assocMaps; 130 assocMaps.owners = createDefaultOwnerAssociation(); 131 assocMaps.ifaces = createDefaultInterfaceAssociation(server); 132 133 checkAssociationEndpointRemoves(DEFAULT_SOURCE_PATH, DEFAULT_DBUS_SVC, 134 newAssocPaths, *server, assocMaps); 135 136 // Verify initial endpoints were deleted because the new path 137 auto intfEndpoints = 138 std::get<endpointsPos>(assocMaps.ifaces[DEFAULT_FWD_PATH]); 139 EXPECT_EQ(intfEndpoints.size(), 0); 140 intfEndpoints = std::get<endpointsPos>(assocMaps.ifaces[DEFAULT_REV_PATH]); 141 EXPECT_EQ(intfEndpoints.size(), 0); 142 } 143 144 // Verify endpoint is removed when endpoint is different 145 TEST_F(TestAssociations, checkAssociationEndpointRemovesEpRemoveEpChanged) 146 { 147 AssociationPaths newAssocPaths = { 148 {DEFAULT_FWD_PATH, {DEFAULT_ENDPOINT + "/different"}}, 149 {DEFAULT_REV_PATH, {DEFAULT_SOURCE_PATH + "/different"}}}; 150 151 AssociationMaps assocMaps; 152 assocMaps.owners = createDefaultOwnerAssociation(); 153 assocMaps.ifaces = createDefaultInterfaceAssociation(server); 154 155 checkAssociationEndpointRemoves(DEFAULT_SOURCE_PATH, DEFAULT_DBUS_SVC, 156 newAssocPaths, *server, assocMaps); 157 158 // Verify initial endpoints were deleted because of different endpoints 159 auto intfEndpoints = 160 std::get<endpointsPos>(assocMaps.ifaces[DEFAULT_FWD_PATH]); 161 EXPECT_EQ(intfEndpoints.size(), 0); 162 intfEndpoints = std::get<endpointsPos>(assocMaps.ifaces[DEFAULT_REV_PATH]); 163 EXPECT_EQ(intfEndpoints.size(), 0); 164 } 165 166 // Verify existing endpoint deleted when empty endpoint is provided 167 TEST_F(TestAssociations, associationChangedEmptyEndpoint) 168 { 169 std::vector<Association> associations = { 170 {"inventory_cee", "error_cee", ""}}; 171 interface_map_type interfaceMap; 172 173 AssociationMaps assocMaps; 174 assocMaps.owners = createDefaultOwnerAssociation(); 175 assocMaps.ifaces = createDefaultInterfaceAssociation(server); 176 177 // Empty endpoint will result in deletion of corresponding assocInterface 178 associationChanged(*server, associations, DEFAULT_SOURCE_PATH, 179 DEFAULT_DBUS_SVC, interfaceMap, assocMaps); 180 181 // Both of these should be 0 since we have an invalid endpoint 182 auto intfEndpoints = 183 std::get<endpointsPos>(assocMaps.ifaces[DEFAULT_FWD_PATH]); 184 EXPECT_EQ(intfEndpoints.size(), 0); 185 intfEndpoints = std::get<endpointsPos>(assocMaps.ifaces[DEFAULT_REV_PATH]); 186 EXPECT_EQ(intfEndpoints.size(), 0); 187 188 EXPECT_EQ(assocMaps.pending.size(), 0); 189 } 190 191 // Add a new association with endpoint 192 TEST_F(TestAssociations, associationChangedAddNewAssoc) 193 { 194 std::vector<Association> associations = { 195 {"abc", "def", "/xyz/openbmc_project/new/endpoint"}}; 196 197 AssociationMaps assocMaps; 198 assocMaps.owners = createDefaultOwnerAssociation(); 199 assocMaps.ifaces = createDefaultInterfaceAssociation(server); 200 201 // Make it look like the assoc endpoints are on D-Bus 202 interface_map_type interfaceMap = { 203 {"/new/source/path", {{DEFAULT_DBUS_SVC, {"a"}}}}, 204 {"/xyz/openbmc_project/new/endpoint", {{DEFAULT_DBUS_SVC, {"a"}}}}}; 205 206 associationChanged(*server, associations, "/new/source/path", 207 DEFAULT_DBUS_SVC, interfaceMap, assocMaps); 208 209 // Two source paths 210 EXPECT_EQ(assocMaps.owners.size(), 2); 211 212 // Four interfaces 213 EXPECT_EQ(assocMaps.ifaces.size(), 4); 214 215 // Nothing pending 216 EXPECT_EQ(assocMaps.pending.size(), 0); 217 218 // New endpoint so assocMaps.ifaces should be same size 219 auto intfEndpoints = 220 std::get<endpointsPos>(assocMaps.ifaces[DEFAULT_FWD_PATH]); 221 EXPECT_EQ(intfEndpoints.size(), 1); 222 } 223 224 // Add a new association to empty objects 225 TEST_F(TestAssociations, associationChangedAddNewAssocEmptyObj) 226 { 227 std::string sourcePath = "/logging/entry/1"; 228 std::string owner = "xyz.openbmc_project.Test"; 229 std::vector<Association> associations = { 230 {"inventory_canaeo", "error_canaeo", 231 "/xyz/openbmc_project/inventory/system/chassis"}}; 232 233 // Empty objects because this test will ensure assocOwners adds the 234 // changed association and interface 235 AssociationMaps assocMaps; 236 237 // Make it look like the assoc endpoints are on D-Bus 238 interface_map_type interfaceMap = createDefaultInterfaceMap(); 239 240 associationChanged(*server, associations, DEFAULT_SOURCE_PATH, 241 DEFAULT_DBUS_SVC, interfaceMap, assocMaps); 242 243 // New associations so ensure it now contains a single entry 244 EXPECT_EQ(assocMaps.owners.size(), 1); 245 246 // Nothing pending 247 EXPECT_EQ(assocMaps.pending.size(), 0); 248 249 // Verify corresponding assoc paths each have one endpoint in assoc 250 // interfaces and that those endpoints match 251 auto singleOwner = assocMaps.owners[DEFAULT_SOURCE_PATH]; 252 auto singleIntf = singleOwner[DEFAULT_DBUS_SVC]; 253 for (auto i : singleIntf) 254 { 255 auto intfEndpoints = std::get<endpointsPos>(assocMaps.ifaces[i.first]); 256 EXPECT_EQ(intfEndpoints.size(), 1); 257 EXPECT_EQ(intfEndpoints[0], *i.second.begin()); 258 } 259 } 260 261 // Add a new association to same source path but with new owner 262 TEST_F(TestAssociations, associationChangedAddNewAssocNewOwner) 263 { 264 std::string newOwner = "xyz.openbmc_project.Test2"; 265 std::vector<Association> associations = { 266 {"inventory_canano", "error_canano", 267 "/xyz/openbmc_project/inventory/system/chassis"}}; 268 269 // Make it look like the assoc endpoints are on D-Bus 270 interface_map_type interfaceMap = createDefaultInterfaceMap(); 271 272 AssociationMaps assocMaps; 273 assocMaps.owners = createDefaultOwnerAssociation(); 274 assocMaps.ifaces = createDefaultInterfaceAssociation(server); 275 276 associationChanged(*server, associations, DEFAULT_SOURCE_PATH, newOwner, 277 interfaceMap, assocMaps); 278 279 // New endpoint so assocOwners should be same size 280 EXPECT_EQ(assocMaps.owners.size(), 1); 281 282 // Ensure only one endpoint under first path 283 auto intfEndpoints = 284 std::get<endpointsPos>(assocMaps.ifaces[DEFAULT_FWD_PATH]); 285 EXPECT_EQ(intfEndpoints.size(), 1); 286 287 // Ensure the 2 new association endpoints are under the new owner 288 auto a = assocMaps.owners.find(DEFAULT_SOURCE_PATH); 289 auto o = a->second.find(newOwner); 290 EXPECT_EQ(o->second.size(), 2); 291 292 // Nothing pending 293 EXPECT_EQ(assocMaps.pending.size(), 0); 294 } 295 296 // Add a new association to existing interface path 297 TEST_F(TestAssociations, associationChangedAddNewAssocSameInterface) 298 { 299 std::vector<Association> associations = { 300 {"abc", "error", "/xyz/openbmc_project/inventory/system/chassis"}}; 301 302 // Make it look like the assoc endpoints are on D-Bus 303 interface_map_type interfaceMap = createDefaultInterfaceMap(); 304 305 AssociationMaps assocMaps; 306 assocMaps.owners = createDefaultOwnerAssociation(); 307 assocMaps.ifaces = createDefaultInterfaceAssociation(server); 308 309 associationChanged(*server, associations, DEFAULT_SOURCE_PATH, 310 DEFAULT_DBUS_SVC, interfaceMap, assocMaps); 311 312 // Should have 3 entries in AssociationInterfaces, one is just missing an 313 // endpoint 314 EXPECT_EQ(assocMaps.ifaces.size(), 3); 315 316 // Change to existing interface so it will be removed here 317 auto intfEndpoints = 318 std::get<endpointsPos>(assocMaps.ifaces[DEFAULT_FWD_PATH]); 319 EXPECT_EQ(intfEndpoints.size(), 0); 320 321 // The new endpoint should exist though in it's place 322 intfEndpoints = std::get<endpointsPos>( 323 assocMaps.ifaces[DEFAULT_SOURCE_PATH + "/" + "abc"]); 324 EXPECT_EQ(intfEndpoints.size(), 1); 325 326 // Added to an existing owner path so still 1 327 EXPECT_EQ(assocMaps.owners.size(), 1); 328 329 EXPECT_EQ(assocMaps.pending.size(), 0); 330 } 331 332 // Add 2 pending associations 333 TEST_F(TestAssociations, addPendingAssocs) 334 { 335 AssociationMaps assocMaps; 336 337 addPendingAssociation(DEFAULT_SOURCE_PATH, "inventory", DEFAULT_ENDPOINT, 338 "error", DEFAULT_DBUS_SVC, assocMaps); 339 340 EXPECT_TRUE(assocMaps.ifaces.empty()); 341 EXPECT_TRUE(assocMaps.owners.empty()); 342 343 EXPECT_EQ(assocMaps.pending.size(), 1); 344 345 addPendingAssociation("some/other/path", "inventory", DEFAULT_ENDPOINT, 346 "error", DEFAULT_DBUS_SVC, assocMaps); 347 348 EXPECT_TRUE(assocMaps.ifaces.empty()); 349 EXPECT_TRUE(assocMaps.owners.empty()); 350 351 EXPECT_EQ(assocMaps.pending.size(), 2); 352 } 353 354 // Test adding a new endpoint to a pending association 355 TEST_F(TestAssociations, addPendingAssocsNewEndpoints) 356 { 357 AssociationMaps assocMaps; 358 359 addPendingAssociation(DEFAULT_SOURCE_PATH, "inventory", DEFAULT_ENDPOINT, 360 "error", DEFAULT_DBUS_SVC, assocMaps); 361 362 EXPECT_EQ(assocMaps.pending.size(), 1); 363 364 addPendingAssociation(DEFAULT_SOURCE_PATH, "inventory", 365 "some/other/endpoint", "error", DEFAULT_DBUS_SVC, 366 assocMaps); 367 368 // Same pending path, so still just 1 entry 369 EXPECT_EQ(assocMaps.pending.size(), 1); 370 371 auto assoc = assocMaps.pending.find(DEFAULT_SOURCE_PATH); 372 EXPECT_NE(assoc, assocMaps.pending.end()); 373 374 auto& endpoints = assoc->second; 375 EXPECT_EQ(endpoints.size(), 2); 376 } 377 378 // Test adding a new owner to a pending association 379 TEST_F(TestAssociations, addPendingAssocsNewOwner) 380 { 381 AssociationMaps assocMaps; 382 383 addPendingAssociation(DEFAULT_SOURCE_PATH, "inventory", DEFAULT_ENDPOINT, 384 "error", DEFAULT_DBUS_SVC, assocMaps); 385 386 EXPECT_EQ(assocMaps.pending.size(), 1); 387 388 addPendingAssociation(DEFAULT_SOURCE_PATH, "inventory", DEFAULT_ENDPOINT, 389 "error", "new owner", assocMaps); 390 391 EXPECT_EQ(assocMaps.pending.size(), 1); 392 393 auto assoc = assocMaps.pending.find(DEFAULT_SOURCE_PATH); 394 EXPECT_NE(assoc, assocMaps.pending.end()); 395 396 auto& endpoints = assoc->second; 397 EXPECT_EQ(endpoints.size(), 2); 398 } 399 400 // Add a pending association inside associationChanged 401 TEST_F(TestAssociations, associationChangedPending) 402 { 403 std::vector<Association> associations = { 404 {"abc", "def", "/xyz/openbmc_project/new/endpoint"}}; 405 406 AssociationMaps assocMaps; 407 interface_map_type interfaceMap; 408 409 associationChanged(*server, associations, "/new/source/path", 410 DEFAULT_DBUS_SVC, interfaceMap, assocMaps); 411 412 // No associations were actually added 413 EXPECT_EQ(assocMaps.owners.size(), 0); 414 EXPECT_EQ(assocMaps.ifaces.size(), 0); 415 416 // 1 pending association 417 EXPECT_EQ(assocMaps.pending.size(), 1); 418 } 419 420 // Test removing pending associations 421 TEST_F(TestAssociations, testRemoveFromPendingAssociations) 422 { 423 AssociationMaps assocMaps; 424 425 addPendingAssociation(DEFAULT_SOURCE_PATH, "inventory", DEFAULT_ENDPOINT, 426 "error", DEFAULT_DBUS_SVC, assocMaps); 427 428 addPendingAssociation(DEFAULT_SOURCE_PATH, "inventory", 429 "some/other/endpoint", "error", DEFAULT_DBUS_SVC, 430 assocMaps); 431 432 EXPECT_EQ(assocMaps.pending.size(), 1); 433 434 removeFromPendingAssociations("some/other/endpoint", assocMaps); 435 436 // Still 1 pending entry, but down to 1 endpoint 437 EXPECT_EQ(assocMaps.pending.size(), 1); 438 439 auto assoc = assocMaps.pending.find(DEFAULT_SOURCE_PATH); 440 EXPECT_NE(assoc, assocMaps.pending.end()); 441 auto& endpoints = assoc->second; 442 EXPECT_EQ(endpoints.size(), 1); 443 444 // Now nothing pending 445 removeFromPendingAssociations(DEFAULT_ENDPOINT, assocMaps); 446 EXPECT_EQ(assocMaps.pending.size(), 0); 447 } 448 449 // Test moving a pending association to a real one 450 TEST_F(TestAssociations, checkIfPending) 451 { 452 AssociationMaps assocMaps; 453 interface_map_type interfaceMap = { 454 {DEFAULT_SOURCE_PATH, {{DEFAULT_DBUS_SVC, {"a"}}}}, 455 {DEFAULT_ENDPOINT, {{DEFAULT_DBUS_SVC, {"b"}}}}}; 456 457 addPendingAssociation(DEFAULT_SOURCE_PATH, "inventory_cip", 458 DEFAULT_ENDPOINT, "error_cip", DEFAULT_DBUS_SVC, 459 assocMaps); 460 EXPECT_EQ(assocMaps.pending.size(), 1); 461 462 // Move the pending association to a real association 463 checkIfPendingAssociation(DEFAULT_SOURCE_PATH, interfaceMap, assocMaps, 464 *server); 465 466 EXPECT_TRUE(assocMaps.pending.empty()); 467 EXPECT_EQ(assocMaps.owners.size(), 1); 468 EXPECT_EQ(assocMaps.ifaces.size(), 2); 469 470 // This shouldn't do anything, since /new/path isn't pending 471 checkIfPendingAssociation("/new/path", interfaceMap, assocMaps, *server); 472 EXPECT_TRUE(assocMaps.pending.empty()); 473 EXPECT_EQ(assocMaps.owners.size(), 1); 474 EXPECT_EQ(assocMaps.ifaces.size(), 2); 475 } 476 477 TEST_F(TestAssociations, findAssociations) 478 { 479 std::vector<std::tuple<std::string, Association>> associationData; 480 AssociationMaps assocMaps; 481 482 assocMaps.owners = { 483 {"pathA", 484 {{"ownerA", 485 {{"pathA/typeA", {"endpointA", "endpointB"}}, 486 {"endpointA/type0", {"pathA"}}}}}}, 487 488 {"pathJ", 489 {{"ownerC", 490 {{"pathJ/typeA", {"endpointF"}}, {"endpointF/type0", {"pathJ"}}}}}}, 491 492 {"pathX", 493 {{"ownerB", 494 {{"pathX/typeB", {"endpointA"}}, {"endpointA/type1", {"pathX"}}}}}}}; 495 496 findAssociations("endpointA", assocMaps, associationData); 497 ASSERT_EQ(associationData.size(), 2); 498 499 { 500 auto ad = std::find_if( 501 associationData.begin(), associationData.end(), 502 [](const auto& ad) { return std::get<0>(ad) == "ownerA"; }); 503 ASSERT_NE(ad, associationData.end()); 504 505 auto& a = std::get<1>(*ad); 506 ASSERT_EQ(std::get<0>(a), "type0"); 507 ASSERT_EQ(std::get<1>(a), "typeA"); 508 ASSERT_EQ(std::get<2>(a), "pathA"); 509 } 510 { 511 auto ad = std::find_if( 512 associationData.begin(), associationData.end(), 513 [](const auto& ad) { return std::get<0>(ad) == "ownerB"; }); 514 ASSERT_NE(ad, associationData.end()); 515 516 auto& a = std::get<1>(*ad); 517 ASSERT_EQ(std::get<0>(a), "type1"); 518 ASSERT_EQ(std::get<1>(a), "typeB"); 519 ASSERT_EQ(std::get<2>(a), "pathX"); 520 } 521 } 522 523 TEST_F(TestAssociations, moveAssocToPendingNoOp) 524 { 525 AssociationMaps assocMaps; 526 527 // Not an association, so it shouldn't do anything 528 moveAssociationToPending(DEFAULT_ENDPOINT, assocMaps, *server); 529 530 EXPECT_TRUE(assocMaps.pending.empty()); 531 EXPECT_TRUE(assocMaps.owners.empty()); 532 EXPECT_TRUE(assocMaps.ifaces.empty()); 533 } 534 535 TEST_F(TestAssociations, moveAssocToPending) 536 { 537 AssociationMaps assocMaps; 538 assocMaps.owners = createDefaultOwnerAssociation(); 539 assocMaps.ifaces = createDefaultInterfaceAssociation(server); 540 541 moveAssociationToPending(DEFAULT_ENDPOINT, assocMaps, *server); 542 543 // Check it's now pending 544 EXPECT_EQ(assocMaps.pending.size(), 1); 545 EXPECT_EQ(assocMaps.pending.begin()->first, DEFAULT_ENDPOINT); 546 547 // No more assoc owners 548 EXPECT_TRUE(assocMaps.owners.empty()); 549 550 // Check the association interfaces were removed 551 { 552 auto assocs = assocMaps.ifaces.find(DEFAULT_FWD_PATH); 553 auto& iface = std::get<ifacePos>(assocs->second); 554 auto& endpoints = std::get<endpointsPos>(assocs->second); 555 556 EXPECT_EQ(iface.get(), nullptr); 557 EXPECT_TRUE(endpoints.empty()); 558 } 559 { 560 auto assocs = assocMaps.ifaces.find(DEFAULT_REV_PATH); 561 auto& iface = std::get<ifacePos>(assocs->second); 562 auto& endpoints = std::get<endpointsPos>(assocs->second); 563 564 EXPECT_EQ(iface.get(), nullptr); 565 EXPECT_TRUE(endpoints.empty()); 566 } 567 } 568