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