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