1 #include "src/handler.hpp"
2
3 #include "src/types.hpp"
4
5 #include <xyz/openbmc_project/Common/error.hpp>
6
7 #include <span>
8 #include <utility>
9 #include <vector>
10
11 #include <gmock/gmock.h>
12 #include <gtest/gtest.h>
13
14 using ::testing::ElementsAre;
15
16 class TestHandler : public testing::Test
17 {
18 protected:
19 InterfaceMapType interfaceMap = {
20 {
21 "/test/object_path_0",
22 {{"test_object_connection_0", {"test_interface_0"}}},
23 },
24 {
25 "/test/object_path_0/child",
26 {{"test_object_connection_1", {"test_interface_1"}}},
27 },
28 {
29 "/test/object_path_0/child/grandchild",
30 {{"test_object_connection_2", {"test_interface_2"}}},
31 },
32 {
33 "/test/object_path_0/child/grandchild/dog",
34 {{"test_object_connection_3", {"test_interface_3"}}},
35 },
36 {
37 "/test/object_path_0/child1",
38 {{"test_object_connection_4", {"test_interface_4"}}},
39 },
40 {
41 "/test/object_path_0/grandchild/child1",
42 {{"test_object_connection_5", {"test_interface_5"}}},
43 },
44 };
45
46 AssociationMaps associationMap = {
47 .ifaces =
48 {
49 {
50 "/test/object_path_0/descendent",
51 {
52 std::shared_ptr<sdbusplus::asio::dbus_interface>(),
53 {
54 "/test/object_path_0/child",
55 "/test/object_path_0/child/grandchild",
56 },
57 },
58 },
59 {
60 "/test/object_path_0/child/descendent",
61 {
62 std::shared_ptr<sdbusplus::asio::dbus_interface>(),
63 {
64 "/test/object_path_0/child/grandchild",
65 },
66 },
67 },
68 {
69 "/test/object_path_0/grandchild/child1/descendent",
70 {
71 std::shared_ptr<sdbusplus::asio::dbus_interface>(),
72 {
73 "/test/object_path_0/child",
74 },
75 },
76 },
77 {
78 "/test/object_path_0/child1/descendent",
79 {
80 std::shared_ptr<sdbusplus::asio::dbus_interface>(),
81 {
82 "/test/object_path_0/child1",
83 "/test/object_path_0/child1/grandchild",
84 },
85 },
86 },
87 },
88 .owners = {},
89 .pending = {},
90 };
91 };
92
TEST_F(TestHandler,AddObjectMapResult)93 TEST_F(TestHandler, AddObjectMapResult)
94 {
95 std::vector<InterfaceMapType::value_type> interfaceMaps;
96 addObjectMapResult(interfaceMaps, "test_object_path",
97 std::pair<std::string, InterfaceNames>(
98 "test_object_connection_0", {
99 "test_interface_0",
100 "test_interface_1",
101 }));
102
103 addObjectMapResult(interfaceMaps, "test_object_path",
104 std::pair<std::string, InterfaceNames>(
105 "test_object_connection_1", {
106 "test_interface_0",
107 "test_interface_1",
108 }));
109 ASSERT_EQ(interfaceMaps.size(), 1);
110 auto entry = std::find_if(
111 interfaceMaps.begin(), interfaceMaps.end(),
112 [](const auto& i) { return "test_object_path" == i.first; });
113 ASSERT_NE(entry, interfaceMap.end());
114 for (const auto& [_, interfaces] : entry->second)
115 {
116 ASSERT_THAT(interfaces,
117 ElementsAre("test_interface_0", "test_interface_1"));
118 }
119
120 // Change the interface, but expect it to be unchanged
121 addObjectMapResult(interfaceMaps, "test_object_path",
122 std::pair<std::string, InterfaceNames>(
123 "test_object_connection_0", {"test_interface_2"}));
124 addObjectMapResult(interfaceMaps, "test_object_path",
125 std::pair<std::string, InterfaceNames>(
126 "test_object_connection_1", {"test_interface_2"}));
127 entry = std::find_if(
128 interfaceMaps.begin(), interfaceMaps.end(),
129 [](const auto& i) { return "test_object_path" == i.first; });
130 ASSERT_NE(entry, interfaceMaps.end());
131 for (const auto& [_, interfaces] : entry->second)
132 {
133 ASSERT_THAT(interfaces,
134 ElementsAre("test_interface_0", "test_interface_1"));
135 }
136 }
137
TEST_F(TestHandler,getAncestorsBad)138 TEST_F(TestHandler, getAncestorsBad)
139 {
140 std::string path = "/test/object_path_0/child/grandchild";
141 std::vector<std::string> interfaces = {"bad_interface"};
142 std::vector<InterfaceMapType::value_type> ancestors =
143 getAncestors(interfaceMap, path, interfaces);
144 ASSERT_TRUE(ancestors.empty());
145
146 path = "/invalid_path";
147 EXPECT_THROW(
148 getAncestors(interfaceMap, path, interfaces),
149 sdbusplus::xyz::openbmc_project::Common::Error::ResourceNotFound);
150 }
151
TEST_F(TestHandler,getAncestorsGood)152 TEST_F(TestHandler, getAncestorsGood)
153 {
154 std::string path = "/test/object_path_0/child/grandchild";
155 std::vector<std::string> interfaces = {"test_interface_0",
156 "test_interface_1"};
157 std::vector<InterfaceMapType::value_type> ancestors =
158 getAncestors(interfaceMap, path, interfaces);
159 ASSERT_EQ(ancestors.size(), 2);
160
161 // Grand Parent
162 EXPECT_EQ(ancestors[0].first, "/test/object_path_0");
163 ASSERT_EQ(ancestors[0].second.size(), 1);
164 auto grandParent = ancestors[0].second.find("test_object_connection_0");
165 ASSERT_NE(grandParent, ancestors[0].second.end());
166 ASSERT_THAT(grandParent->second, ElementsAre("test_interface_0"));
167
168 // Parent
169 ASSERT_EQ(ancestors[1].first, "/test/object_path_0/child");
170 ASSERT_EQ(ancestors[1].second.size(), 1);
171 auto parent = ancestors[1].second.find("test_object_connection_1");
172 ASSERT_NE(parent, ancestors[1].second.end());
173 ASSERT_THAT(parent->second, ElementsAre("test_interface_1"));
174 }
175
TEST_F(TestHandler,getObjectBad)176 TEST_F(TestHandler, getObjectBad)
177 {
178 std::string path = "/test/object_path_0";
179 std::vector<std::string> interfaces = {"bad_interface"};
180 EXPECT_THROW(
181 getObject(interfaceMap, path, interfaces),
182 sdbusplus::xyz::openbmc_project::Common::Error::ResourceNotFound);
183
184 path = "/invalid_path";
185 EXPECT_THROW(
186 getObject(interfaceMap, path, interfaces),
187 sdbusplus::xyz::openbmc_project::Common::Error::ResourceNotFound);
188
189 path = "/";
190 EXPECT_THROW(
191 getObject(interfaceMap, path, interfaces),
192 sdbusplus::xyz::openbmc_project::Common::Error::ResourceNotFound);
193 }
194
TEST_F(TestHandler,getObjectGood)195 TEST_F(TestHandler, getObjectGood)
196 {
197 std::string path = "/test/object_path_0";
198 std::vector<std::string> interfaces = {"test_interface_0",
199 "test_interface_1"};
200 ConnectionNames connection = getObject(interfaceMap, path, interfaces);
201 auto object = connection.find("test_object_connection_0");
202 ASSERT_NE(object, connection.end());
203 ASSERT_THAT(object->second, ElementsAre("test_interface_0"));
204
205 path = "/test/object_path_0/child";
206 connection = getObject(interfaceMap, path, interfaces);
207 object = connection.find("test_object_connection_1");
208 ASSERT_NE(object, connection.end());
209 ASSERT_THAT(object->second, ElementsAre("test_interface_1"));
210 }
211
TEST_F(TestHandler,getSubTreeBad)212 TEST_F(TestHandler, getSubTreeBad)
213 {
214 std::string path = "/test/object_path_0";
215 std::vector<std::string> interfaces = {"bad_interface"};
216 std::vector<InterfaceMapType::value_type> subtree =
217 getSubTree(interfaceMap, path, 0, interfaces);
218 ASSERT_TRUE(subtree.empty());
219
220 path = "/invalid_path";
221 EXPECT_THROW(
222 getSubTree(interfaceMap, path, 0, interfaces),
223 sdbusplus::xyz::openbmc_project::Common::Error::ResourceNotFound);
224 }
225
verifySubtree(std::span<InterfaceMapType::value_type> subtree)226 void verifySubtree(std::span<InterfaceMapType::value_type> subtree)
227 {
228 ASSERT_EQ(subtree.size(), 2);
229 ConnectionNames connection = subtree[0].second;
230 auto object = connection.find("test_object_connection_1");
231 ASSERT_NE(object, connection.end());
232 ASSERT_THAT(object->second, ElementsAre("test_interface_1"));
233
234 connection = subtree[1].second;
235 object = connection.find("test_object_connection_3");
236 ASSERT_NE(object, connection.end());
237 ASSERT_THAT(object->second, ElementsAre("test_interface_3"));
238 }
239
TEST_F(TestHandler,getSubTreeGood)240 TEST_F(TestHandler, getSubTreeGood)
241 {
242 std::string path0 = "/test/object_path_0";
243 std::string path1 = "/test/object_path_0/child/grandchild";
244 std::vector<std::string> interfaces = {"test_interface_1",
245 "test_interface_3"};
246 // Root
247 std::vector<InterfaceMapType::value_type> subtree =
248 getSubTree(interfaceMap, "/", 0, interfaces);
249 verifySubtree(subtree);
250
251 // Path0
252 subtree = getSubTree(interfaceMap, path0, 0, interfaces);
253 verifySubtree(subtree);
254
255 // Path0 with Depth path of 1
256 subtree = getSubTree(interfaceMap, path0, 1, interfaces);
257 ASSERT_EQ(subtree.size(), 1);
258 ConnectionNames connection = subtree[0].second;
259 auto object = connection.find("test_object_connection_1");
260 ASSERT_NE(object, connection.end());
261 ASSERT_THAT(object->second, ElementsAre("test_interface_1"));
262
263 // Path1
264 subtree = getSubTree(interfaceMap, path1, 0, interfaces);
265 ASSERT_EQ(subtree.size(), 1);
266 connection = subtree[0].second;
267 object = connection.find("test_object_connection_3");
268 ASSERT_NE(object, connection.end());
269 ASSERT_THAT(object->second, ElementsAre("test_interface_3"));
270 }
271
TEST_F(TestHandler,getSubTreePathsBad)272 TEST_F(TestHandler, getSubTreePathsBad)
273 {
274 std::string path = "/test/object_path_0";
275 std::vector<std::string> interfaces = {"bad_interface"};
276 std::vector<std::string> subtreePath =
277 getSubTreePaths(interfaceMap, path, 0, interfaces);
278 ASSERT_TRUE(subtreePath.empty());
279
280 path = "/invalid_path";
281 EXPECT_THROW(
282 getSubTreePaths(interfaceMap, path, 0, interfaces),
283 sdbusplus::xyz::openbmc_project::Common::Error::ResourceNotFound);
284 }
285
TEST_F(TestHandler,getSubTreePathsGood)286 TEST_F(TestHandler, getSubTreePathsGood)
287 {
288 std::string path0 = "/test/object_path_0";
289 std::string path1 = "/test/object_path_0/child/grandchild";
290 std::vector<std::string> interfaces = {"test_interface_1",
291 "test_interface_3"};
292 // Root
293 std::vector<std::string> subtreePath =
294 getSubTreePaths(interfaceMap, "/", 0, interfaces);
295 ASSERT_THAT(subtreePath,
296 ElementsAre("/test/object_path_0/child",
297 "/test/object_path_0/child/grandchild/dog"));
298
299 // Path0
300 subtreePath = getSubTreePaths(interfaceMap, path0, 0, interfaces);
301 ASSERT_THAT(subtreePath,
302 ElementsAre("/test/object_path_0/child",
303 "/test/object_path_0/child/grandchild/dog"));
304
305 // Path0 + Depth path of 1
306 subtreePath = getSubTreePaths(interfaceMap, path0, 1, interfaces);
307 ASSERT_THAT(subtreePath, ElementsAre("/test/object_path_0/child"));
308
309 // Path1
310 subtreePath = getSubTreePaths(interfaceMap, path1, 0, interfaces);
311 ASSERT_THAT(subtreePath,
312 ElementsAre("/test/object_path_0/child/grandchild/dog"));
313 }
314
TEST_F(TestHandler,getAssociatedSubTreeBad)315 TEST_F(TestHandler, getAssociatedSubTreeBad)
316 {
317 sdbusplus::message::object_path path("/test/object_path_0");
318 sdbusplus::message::object_path validAssociatedPath = path / "descendent";
319 std::vector<std::string> invalidInterfaces = {"test_interface_3"};
320 std::vector<std::string> validInterfaces = {"test_interface_1",
321 "test_interface_2"};
322 // Associated path, but invalid interface
323 ASSERT_TRUE(
324 getAssociatedSubTree(interfaceMap, associationMap, validAssociatedPath,
325 path, 0, invalidInterfaces)
326 .empty());
327
328 // Valid interface, not associated
329 ASSERT_TRUE(getAssociatedSubTree(interfaceMap, associationMap, path / "dog",
330 path, 0, validInterfaces)
331 .empty());
332
333 // Invalid path, with valid association
334 path = sdbusplus::message::object_path("/invalid_path");
335 EXPECT_THROW(
336 getAssociatedSubTree(interfaceMap, associationMap, validAssociatedPath,
337 path, 0, validInterfaces),
338 sdbusplus::xyz::openbmc_project::Common::Error::ResourceNotFound);
339 }
340
TEST_F(TestHandler,getAssociatedSubTreeGood)341 TEST_F(TestHandler, getAssociatedSubTreeGood)
342 {
343 sdbusplus::message::object_path path0("/test/object_path_0");
344 sdbusplus::message::object_path path1("/test/object_path_0/child");
345 sdbusplus::message::object_path associatedPath = path0 / "descendent";
346 std::vector<std::string> interfaces = {
347 "test_interface_1", "test_interface_2",
348 // Not associated to path
349 "test_interface_3"};
350
351 // Path0
352 std::vector<InterfaceMapType::value_type> subtree = getAssociatedSubTree(
353 interfaceMap, associationMap, associatedPath, path0, 0, interfaces);
354 ASSERT_EQ(subtree.size(), 2);
355 ConnectionNames connection = subtree[0].second;
356 auto object = connection.find("test_object_connection_1");
357 ASSERT_NE(object, connection.end());
358 ASSERT_THAT(object->second, ElementsAre("test_interface_1"));
359
360 connection = subtree[1].second;
361 object = connection.find("test_object_connection_2");
362 ASSERT_NE(object, connection.end());
363 ASSERT_THAT(object->second, ElementsAre("test_interface_2"));
364
365 // Path0 with Depth path of 1
366 subtree = getAssociatedSubTree(interfaceMap, associationMap, associatedPath,
367 path0, 1, interfaces);
368 ASSERT_EQ(subtree.size(), 1);
369 connection = subtree[0].second;
370 object = connection.find("test_object_connection_1");
371 ASSERT_NE(object, connection.end());
372 ASSERT_THAT(object->second, ElementsAre("test_interface_1"));
373
374 // Path1
375 subtree = getAssociatedSubTree(interfaceMap, associationMap,
376 path1 / "descendent", path1, 0, interfaces);
377 ASSERT_EQ(subtree.size(), 1);
378 connection = subtree[0].second;
379 object = connection.find("test_object_connection_2");
380 ASSERT_NE(object, connection.end());
381 ASSERT_THAT(object->second, ElementsAre("test_interface_2"));
382 }
383
TEST_F(TestHandler,getAssociatedSubTreePathsBad)384 TEST_F(TestHandler, getAssociatedSubTreePathsBad)
385 {
386 sdbusplus::message::object_path path("/test/object_path_0");
387 sdbusplus::message::object_path validAssociatedPath = path / "descendent";
388 std::vector<std::string> invalidInterfaces = {"test_interface_3"};
389 std::vector<std::string> validInterfaces = {"test_interface_1",
390 "test_interface_2"};
391 // Associated path, but invalid interface
392 ASSERT_TRUE(getAssociatedSubTreePaths(interfaceMap, associationMap,
393 validAssociatedPath, path, 0,
394 invalidInterfaces)
395 .empty());
396
397 // Valid interface, not associated
398 ASSERT_TRUE(
399 getAssociatedSubTreePaths(interfaceMap, associationMap, path / "dog",
400 path, 0, validInterfaces)
401 .empty());
402
403 // Invalid path, with valid association
404 path = sdbusplus::message::object_path("/invalid_path");
405 EXPECT_THROW(
406 getAssociatedSubTreePaths(interfaceMap, associationMap,
407 validAssociatedPath, path, 0,
408 validInterfaces),
409 sdbusplus::xyz::openbmc_project::Common::Error::ResourceNotFound);
410 }
411
TEST_F(TestHandler,getAssociatedSubTreePathsGood)412 TEST_F(TestHandler, getAssociatedSubTreePathsGood)
413 {
414 sdbusplus::message::object_path path0("/test/object_path_0");
415 sdbusplus::message::object_path path1("/test/object_path_0/child");
416 sdbusplus::message::object_path associatedPath = path0 / "descendent";
417 std::vector<std::string> interfaces = {
418 "test_interface_1", "test_interface_2",
419 // Not associated to path
420 "test_interface_3"};
421
422 // Path0
423 std::vector<std::string> subtreePath = getAssociatedSubTreePaths(
424 interfaceMap, associationMap, associatedPath, path0, 0, interfaces);
425 ASSERT_THAT(subtreePath,
426 ElementsAre("/test/object_path_0/child",
427 "/test/object_path_0/child/grandchild"));
428
429 // Path0 with Depth path of 1
430 subtreePath = getAssociatedSubTreePaths(
431 interfaceMap, associationMap, associatedPath, path0, 1, interfaces);
432 ASSERT_THAT(subtreePath, ElementsAre("/test/object_path_0/child"));
433
434 // Path1
435 subtreePath =
436 getAssociatedSubTreePaths(interfaceMap, associationMap,
437 path1 / "descendent", path1, 0, interfaces);
438 ASSERT_THAT(subtreePath,
439 ElementsAre("/test/object_path_0/child/grandchild"));
440 }
441
TEST_F(TestHandler,getAssociatedSubTreeByIdBad)442 TEST_F(TestHandler, getAssociatedSubTreeByIdBad)
443 {
444 sdbusplus::message::object_path path("/test/object_path_0");
445 std::vector<std::string> subtreeInterfaces = {"test_interface_1",
446 "test_interface_3"};
447 std::vector<std::string> badsubtreeInterfaces = {"bad_interface"};
448 std::vector<std::string> endpointinvalidInterfaces = {"test_interface_3"};
449 std::vector<std::string> endpointvalidInterfaces = {"test_interface_1",
450 "test_interface_2"};
451 // invalid id
452 ASSERT_TRUE(getAssociatedSubTreeById(interfaceMap, associationMap, "childx",
453 path, subtreeInterfaces, "descendent",
454 endpointvalidInterfaces)
455 .empty());
456
457 // invalid subtreeInterfaces
458 ASSERT_TRUE(getAssociatedSubTreeById(interfaceMap, associationMap, "child",
459 path, badsubtreeInterfaces,
460 "descendent", endpointvalidInterfaces)
461 .empty());
462
463 // invalid endpointinterface
464 ASSERT_TRUE(getAssociatedSubTreeById(interfaceMap, associationMap, "child",
465 path, subtreeInterfaces, "descendent",
466 endpointinvalidInterfaces)
467 .empty());
468 // valid id, but doesn't have specified interface
469 ASSERT_TRUE(getAssociatedSubTreeById(interfaceMap, associationMap,
470 "grandchild", path, subtreeInterfaces,
471 "descendent", endpointvalidInterfaces)
472 .empty());
473
474 // invalid association
475 ASSERT_TRUE(getAssociatedSubTreeById(interfaceMap, associationMap, "child",
476 path, subtreeInterfaces, "dog",
477 endpointinvalidInterfaces)
478 .empty());
479
480 // Invalid path
481 path = sdbusplus::message::object_path("/invalid_path");
482 EXPECT_THROW(
483 getAssociatedSubTreeById(interfaceMap, associationMap, "child", path,
484 subtreeInterfaces, "descendent",
485 endpointvalidInterfaces),
486 sdbusplus::xyz::openbmc_project::Common::Error::ResourceNotFound);
487 }
488
TEST_F(TestHandler,getAssociatedSubTreeByIdGood)489 TEST_F(TestHandler, getAssociatedSubTreeByIdGood)
490 {
491 sdbusplus::message::object_path path0("/test/object_path_0");
492 std::vector<std::string> interfaces = {
493 "test_interface_1", "test_interface_2", "test_interface_3"};
494
495 // Path0
496 std::vector<InterfaceMapType::value_type> subtree =
497 getAssociatedSubTreeById(interfaceMap, associationMap, "child", path0,
498 interfaces, "descendent", interfaces);
499 ASSERT_EQ(subtree.size(), 1);
500 ConnectionNames connection = subtree[0].second;
501 auto object = connection.find("test_object_connection_2");
502 ASSERT_NE(object, connection.end());
503 ASSERT_THAT(object->second, ElementsAre("test_interface_2"));
504
505 std::vector<std::string> interfaces1 = {
506 "test_interface_1", "test_interface_4", "test_interface_5"};
507 // Path0 with Depth path of 0
508 subtree =
509 getAssociatedSubTreeById(interfaceMap, associationMap, "child1", path0,
510 interfaces1, "descendent", interfaces1);
511 ASSERT_EQ(subtree.size(), 2);
512 }
513
TEST_F(TestHandler,getAssociatedSubTreePathsByIdBad)514 TEST_F(TestHandler, getAssociatedSubTreePathsByIdBad)
515 {
516 sdbusplus::message::object_path path("/test/object_path_0");
517 std::vector<std::string> subtreeInterfaces = {"test_interface_1",
518 "test_interface_3"};
519 std::vector<std::string> badsubtreeInterfaces = {"bad_interface"};
520 std::vector<std::string> endpointinvalidInterfaces = {"test_interface_3"};
521 std::vector<std::string> endpointvalidInterfaces = {"test_interface_1",
522 "test_interface_2"};
523 // invalid id
524 ASSERT_TRUE(getAssociatedSubTreePathsById(
525 interfaceMap, associationMap, "childx", path,
526 subtreeInterfaces, "descendent", endpointvalidInterfaces)
527 .empty());
528
529 // invalid subtreeInterfaces
530 ASSERT_TRUE(getAssociatedSubTreePathsById(
531 interfaceMap, associationMap, "child", path,
532 badsubtreeInterfaces, "descendent", endpointvalidInterfaces)
533 .empty());
534
535 // invalid endpointinterface
536 ASSERT_TRUE(getAssociatedSubTreePathsById(
537 interfaceMap, associationMap, "child", path,
538 subtreeInterfaces, "descendent", endpointinvalidInterfaces)
539 .empty());
540 // valid id, but doesn't have specified interface
541 ASSERT_TRUE(getAssociatedSubTreePathsById(
542 interfaceMap, associationMap, "grandchild", path,
543 subtreeInterfaces, "descendent", endpointvalidInterfaces)
544 .empty());
545
546 // invalid association
547 ASSERT_TRUE(getAssociatedSubTreePathsById(interfaceMap, associationMap,
548 "child", path, subtreeInterfaces,
549 "dog", endpointinvalidInterfaces)
550 .empty());
551
552 // Invalid path
553 path = sdbusplus::message::object_path("/invalid_path");
554 EXPECT_THROW(
555 getAssociatedSubTreePathsById(interfaceMap, associationMap, "child",
556 path, subtreeInterfaces, "descendent",
557 endpointvalidInterfaces),
558 sdbusplus::xyz::openbmc_project::Common::Error::ResourceNotFound);
559 }
560
TEST_F(TestHandler,getAssociatedSubTreePathsByIdGood)561 TEST_F(TestHandler, getAssociatedSubTreePathsByIdGood)
562 {
563 sdbusplus::message::object_path path0("/test/object_path_0");
564 std::vector<std::string> interfaces = {
565 "test_interface_1", "test_interface_2", "test_interface_3"};
566
567 // Path0
568 std::vector<std::string> subtreePath = getAssociatedSubTreePathsById(
569 interfaceMap, associationMap, "child", path0, interfaces, "descendent",
570 interfaces);
571 ASSERT_THAT(subtreePath,
572 ElementsAre("/test/object_path_0/child/grandchild"));
573
574 std::vector<std::string> interfaces1 = {
575 "test_interface_1", "test_interface_4", "test_interface_5"};
576 // Path0 with Depth path of 0
577 subtreePath = getAssociatedSubTreePathsById(
578 interfaceMap, associationMap, "child1", path0, interfaces1,
579 "descendent", interfaces1);
580 ASSERT_THAT(subtreePath, ElementsAre("/test/object_path_0/child1",
581 "/test/object_path_0/child"));
582 }
583