1aba14d3dSWilly Tu #include "src/handler.hpp"
2aba14d3dSWilly Tu 
3aba14d3dSWilly Tu #include "src/types.hpp"
4aba14d3dSWilly Tu 
5aba14d3dSWilly Tu #include <xyz/openbmc_project/Common/error.hpp>
6aba14d3dSWilly Tu 
7aba14d3dSWilly Tu #include <span>
8aba14d3dSWilly Tu #include <utility>
9aba14d3dSWilly Tu #include <vector>
10aba14d3dSWilly Tu 
11aba14d3dSWilly Tu #include <gmock/gmock.h>
12aba14d3dSWilly Tu #include <gtest/gtest.h>
13aba14d3dSWilly Tu 
14aba14d3dSWilly Tu using ::testing::ElementsAre;
15aba14d3dSWilly Tu 
16aba14d3dSWilly Tu class TestHandler : public testing::Test
17aba14d3dSWilly Tu {
18aba14d3dSWilly Tu   protected:
19aba14d3dSWilly Tu     InterfaceMapType interfaceMap = {
20aba14d3dSWilly Tu         {
21aba14d3dSWilly Tu             "/test/object_path_0",
22aba14d3dSWilly Tu             {{"test_object_connection_0", {"test_interface_0"}}},
23aba14d3dSWilly Tu         },
24aba14d3dSWilly Tu         {
25aba14d3dSWilly Tu             "/test/object_path_0/child",
26aba14d3dSWilly Tu             {{"test_object_connection_1", {"test_interface_1"}}},
27aba14d3dSWilly Tu         },
28aba14d3dSWilly Tu         {
29aba14d3dSWilly Tu             "/test/object_path_0/child/grandchild",
30aba14d3dSWilly Tu             {{"test_object_connection_2", {"test_interface_2"}}},
31aba14d3dSWilly Tu         },
32aba14d3dSWilly Tu         {
33aba14d3dSWilly Tu             "/test/object_path_0/child/grandchild/dog",
34aba14d3dSWilly Tu             {{"test_object_connection_3", {"test_interface_3"}}},
35aba14d3dSWilly Tu         }};
3658881d0bSWilly Tu 
3758881d0bSWilly Tu     AssociationMaps associationMap = {
3858881d0bSWilly Tu         .ifaces =
3958881d0bSWilly Tu             {
4058881d0bSWilly Tu                 {
4158881d0bSWilly Tu                     "/test/object_path_0/descendent",
4258881d0bSWilly Tu                     {
4358881d0bSWilly Tu                         std::shared_ptr<sdbusplus::asio::dbus_interface>(),
4458881d0bSWilly Tu                         {
4558881d0bSWilly Tu                             "/test/object_path_0/child",
4658881d0bSWilly Tu                             "/test/object_path_0/child/grandchild",
4758881d0bSWilly Tu                         },
4858881d0bSWilly Tu                     },
4958881d0bSWilly Tu                 },
5058881d0bSWilly Tu                 {
5158881d0bSWilly Tu                     "/test/object_path_0/child/descendent",
5258881d0bSWilly Tu                     {
5358881d0bSWilly Tu                         std::shared_ptr<sdbusplus::asio::dbus_interface>(),
5458881d0bSWilly Tu                         {
5558881d0bSWilly Tu                             "/test/object_path_0/child/grandchild",
5658881d0bSWilly Tu                         },
5758881d0bSWilly Tu                     },
5858881d0bSWilly Tu                 },
5958881d0bSWilly Tu             },
6058881d0bSWilly Tu         .owners = {},
6158881d0bSWilly Tu         .pending = {},
6258881d0bSWilly Tu     };
63aba14d3dSWilly Tu };
64aba14d3dSWilly Tu 
TEST_F(TestHandler,AddObjectMapResult)65aba14d3dSWilly Tu TEST_F(TestHandler, AddObjectMapResult)
66aba14d3dSWilly Tu {
67aba14d3dSWilly Tu     std::vector<InterfaceMapType::value_type> interfaceMaps;
68aba14d3dSWilly Tu     addObjectMapResult(interfaceMaps, "test_object_path",
69aba14d3dSWilly Tu                        std::pair<std::string, InterfaceNames>(
70aba14d3dSWilly Tu                            "test_object_connection_0", {
71aba14d3dSWilly Tu                                                            "test_interface_0",
72aba14d3dSWilly Tu                                                            "test_interface_1",
73aba14d3dSWilly Tu                                                        }));
74aba14d3dSWilly Tu 
75aba14d3dSWilly Tu     addObjectMapResult(interfaceMaps, "test_object_path",
76aba14d3dSWilly Tu                        std::pair<std::string, InterfaceNames>(
77aba14d3dSWilly Tu                            "test_object_connection_1", {
78aba14d3dSWilly Tu                                                            "test_interface_0",
79aba14d3dSWilly Tu                                                            "test_interface_1",
80aba14d3dSWilly Tu                                                        }));
81aba14d3dSWilly Tu     ASSERT_EQ(interfaceMaps.size(), 1);
82aba14d3dSWilly Tu 
83*47b68cbcSPatrick Williams     auto entry = std::find_if(
84*47b68cbcSPatrick Williams         interfaceMaps.begin(), interfaceMaps.end(),
85*47b68cbcSPatrick Williams         [](const auto& i) { return "test_object_path" == i.first; });
86aba14d3dSWilly Tu     ASSERT_NE(entry, interfaceMap.end());
87aba14d3dSWilly Tu     for (const auto& [_, interfaces] : entry->second)
88aba14d3dSWilly Tu     {
89aba14d3dSWilly Tu         ASSERT_THAT(interfaces,
90aba14d3dSWilly Tu                     ElementsAre("test_interface_0", "test_interface_1"));
91aba14d3dSWilly Tu     }
92aba14d3dSWilly Tu 
93aba14d3dSWilly Tu     // Change the interface, but expect it to be unchanged
94aba14d3dSWilly Tu     addObjectMapResult(interfaceMaps, "test_object_path",
95aba14d3dSWilly Tu                        std::pair<std::string, InterfaceNames>(
96aba14d3dSWilly Tu                            "test_object_connection_0", {"test_interface_2"}));
97aba14d3dSWilly Tu     addObjectMapResult(interfaceMaps, "test_object_path",
98aba14d3dSWilly Tu                        std::pair<std::string, InterfaceNames>(
99aba14d3dSWilly Tu                            "test_object_connection_1", {"test_interface_2"}));
100*47b68cbcSPatrick Williams     entry = std::find_if(
101*47b68cbcSPatrick Williams         interfaceMaps.begin(), interfaceMaps.end(),
102*47b68cbcSPatrick Williams         [](const auto& i) { return "test_object_path" == i.first; });
103aba14d3dSWilly Tu     ASSERT_NE(entry, interfaceMaps.end());
104aba14d3dSWilly Tu     for (const auto& [_, interfaces] : entry->second)
105aba14d3dSWilly Tu     {
106aba14d3dSWilly Tu         ASSERT_THAT(interfaces,
107aba14d3dSWilly Tu                     ElementsAre("test_interface_0", "test_interface_1"));
108aba14d3dSWilly Tu     }
109aba14d3dSWilly Tu }
110aba14d3dSWilly Tu 
TEST_F(TestHandler,getAncestorsBad)111aba14d3dSWilly Tu TEST_F(TestHandler, getAncestorsBad)
112aba14d3dSWilly Tu {
113aba14d3dSWilly Tu     std::string path = "/test/object_path_0/child/grandchild";
114aba14d3dSWilly Tu     std::vector<std::string> interfaces = {"bad_interface"};
115aba14d3dSWilly Tu     std::vector<InterfaceMapType::value_type> ancestors =
116aba14d3dSWilly Tu         getAncestors(interfaceMap, path, interfaces);
117aba14d3dSWilly Tu     ASSERT_TRUE(ancestors.empty());
118aba14d3dSWilly Tu 
119aba14d3dSWilly Tu     path = "/invalid_path";
120aba14d3dSWilly Tu     EXPECT_THROW(
121aba14d3dSWilly Tu         getAncestors(interfaceMap, path, interfaces),
122aba14d3dSWilly Tu         sdbusplus::xyz::openbmc_project::Common::Error::ResourceNotFound);
123aba14d3dSWilly Tu }
124aba14d3dSWilly Tu 
TEST_F(TestHandler,getAncestorsGood)125aba14d3dSWilly Tu TEST_F(TestHandler, getAncestorsGood)
126aba14d3dSWilly Tu {
127aba14d3dSWilly Tu     std::string path = "/test/object_path_0/child/grandchild";
128aba14d3dSWilly Tu     std::vector<std::string> interfaces = {"test_interface_0",
129aba14d3dSWilly Tu                                            "test_interface_1"};
130aba14d3dSWilly Tu     std::vector<InterfaceMapType::value_type> ancestors =
131aba14d3dSWilly Tu         getAncestors(interfaceMap, path, interfaces);
132aba14d3dSWilly Tu     ASSERT_EQ(ancestors.size(), 2);
133aba14d3dSWilly Tu 
134aba14d3dSWilly Tu     // Grand Parent
135aba14d3dSWilly Tu     EXPECT_EQ(ancestors[0].first, "/test/object_path_0");
136aba14d3dSWilly Tu     ASSERT_EQ(ancestors[0].second.size(), 1);
137aba14d3dSWilly Tu     auto grandParent = ancestors[0].second.find("test_object_connection_0");
138aba14d3dSWilly Tu     ASSERT_NE(grandParent, ancestors[0].second.end());
139aba14d3dSWilly Tu     ASSERT_THAT(grandParent->second, ElementsAre("test_interface_0"));
140aba14d3dSWilly Tu 
141aba14d3dSWilly Tu     // Parent
142aba14d3dSWilly Tu     ASSERT_EQ(ancestors[1].first, "/test/object_path_0/child");
143aba14d3dSWilly Tu     ASSERT_EQ(ancestors[1].second.size(), 1);
144aba14d3dSWilly Tu     auto parent = ancestors[1].second.find("test_object_connection_1");
145aba14d3dSWilly Tu     ASSERT_NE(parent, ancestors[1].second.end());
146aba14d3dSWilly Tu     ASSERT_THAT(parent->second, ElementsAre("test_interface_1"));
147aba14d3dSWilly Tu }
148aba14d3dSWilly Tu 
TEST_F(TestHandler,getObjectBad)149aba14d3dSWilly Tu TEST_F(TestHandler, getObjectBad)
150aba14d3dSWilly Tu {
151aba14d3dSWilly Tu     std::string path = "/test/object_path_0";
152aba14d3dSWilly Tu     std::vector<std::string> interfaces = {"bad_interface"};
153aba14d3dSWilly Tu     EXPECT_THROW(
154aba14d3dSWilly Tu         getObject(interfaceMap, path, interfaces),
155aba14d3dSWilly Tu         sdbusplus::xyz::openbmc_project::Common::Error::ResourceNotFound);
156aba14d3dSWilly Tu 
157aba14d3dSWilly Tu     path = "/invalid_path";
158aba14d3dSWilly Tu     EXPECT_THROW(
159aba14d3dSWilly Tu         getObject(interfaceMap, path, interfaces),
160aba14d3dSWilly Tu         sdbusplus::xyz::openbmc_project::Common::Error::ResourceNotFound);
161aba14d3dSWilly Tu 
162aba14d3dSWilly Tu     path = "/";
163aba14d3dSWilly Tu     EXPECT_THROW(
164aba14d3dSWilly Tu         getObject(interfaceMap, path, interfaces),
165aba14d3dSWilly Tu         sdbusplus::xyz::openbmc_project::Common::Error::ResourceNotFound);
166aba14d3dSWilly Tu }
167aba14d3dSWilly Tu 
TEST_F(TestHandler,getObjectGood)168aba14d3dSWilly Tu TEST_F(TestHandler, getObjectGood)
169aba14d3dSWilly Tu {
170aba14d3dSWilly Tu     std::string path = "/test/object_path_0";
171aba14d3dSWilly Tu     std::vector<std::string> interfaces = {"test_interface_0",
172aba14d3dSWilly Tu                                            "test_interface_1"};
173aba14d3dSWilly Tu     ConnectionNames connection = getObject(interfaceMap, path, interfaces);
174aba14d3dSWilly Tu     auto object = connection.find("test_object_connection_0");
175aba14d3dSWilly Tu     ASSERT_NE(object, connection.end());
176aba14d3dSWilly Tu     ASSERT_THAT(object->second, ElementsAre("test_interface_0"));
177aba14d3dSWilly Tu 
178aba14d3dSWilly Tu     path = "/test/object_path_0/child";
179aba14d3dSWilly Tu     connection = getObject(interfaceMap, path, interfaces);
180aba14d3dSWilly Tu     object = connection.find("test_object_connection_1");
181aba14d3dSWilly Tu     ASSERT_NE(object, connection.end());
182aba14d3dSWilly Tu     ASSERT_THAT(object->second, ElementsAre("test_interface_1"));
183aba14d3dSWilly Tu }
184aba14d3dSWilly Tu 
TEST_F(TestHandler,getSubTreeBad)185aba14d3dSWilly Tu TEST_F(TestHandler, getSubTreeBad)
186aba14d3dSWilly Tu {
187aba14d3dSWilly Tu     std::string path = "/test/object_path_0";
188aba14d3dSWilly Tu     std::vector<std::string> interfaces = {"bad_interface"};
189aba14d3dSWilly Tu     std::vector<InterfaceMapType::value_type> subtree =
190aba14d3dSWilly Tu         getSubTree(interfaceMap, path, 0, interfaces);
191aba14d3dSWilly Tu     ASSERT_TRUE(subtree.empty());
192aba14d3dSWilly Tu 
193aba14d3dSWilly Tu     path = "/invalid_path";
194aba14d3dSWilly Tu     EXPECT_THROW(
195aba14d3dSWilly Tu         getSubTree(interfaceMap, path, 0, interfaces),
196aba14d3dSWilly Tu         sdbusplus::xyz::openbmc_project::Common::Error::ResourceNotFound);
197aba14d3dSWilly Tu }
198aba14d3dSWilly Tu 
verifySubtree(std::span<InterfaceMapType::value_type> subtree)199aba14d3dSWilly Tu void verifySubtree(std::span<InterfaceMapType::value_type> subtree)
200aba14d3dSWilly Tu {
201aba14d3dSWilly Tu     ASSERT_EQ(subtree.size(), 2);
202aba14d3dSWilly Tu     ConnectionNames connection = subtree[0].second;
203aba14d3dSWilly Tu     auto object = connection.find("test_object_connection_1");
204aba14d3dSWilly Tu     ASSERT_NE(object, connection.end());
205aba14d3dSWilly Tu     ASSERT_THAT(object->second, ElementsAre("test_interface_1"));
206aba14d3dSWilly Tu 
207aba14d3dSWilly Tu     connection = subtree[1].second;
208aba14d3dSWilly Tu     object = connection.find("test_object_connection_3");
209aba14d3dSWilly Tu     ASSERT_NE(object, connection.end());
210aba14d3dSWilly Tu     ASSERT_THAT(object->second, ElementsAre("test_interface_3"));
211aba14d3dSWilly Tu }
212aba14d3dSWilly Tu 
TEST_F(TestHandler,getSubTreeGood)213aba14d3dSWilly Tu TEST_F(TestHandler, getSubTreeGood)
214aba14d3dSWilly Tu {
215aba14d3dSWilly Tu     std::string path0 = "/test/object_path_0";
216aba14d3dSWilly Tu     std::string path1 = "/test/object_path_0/child/grandchild";
217aba14d3dSWilly Tu     std::vector<std::string> interfaces = {"test_interface_1",
218aba14d3dSWilly Tu                                            "test_interface_3"};
219aba14d3dSWilly Tu     // Root
220aba14d3dSWilly Tu     std::vector<InterfaceMapType::value_type> subtree =
221aba14d3dSWilly Tu         getSubTree(interfaceMap, "/", 0, interfaces);
222aba14d3dSWilly Tu     verifySubtree(subtree);
223aba14d3dSWilly Tu 
224aba14d3dSWilly Tu     // Path0
225aba14d3dSWilly Tu     subtree = getSubTree(interfaceMap, path0, 0, interfaces);
226aba14d3dSWilly Tu     verifySubtree(subtree);
227aba14d3dSWilly Tu 
228aba14d3dSWilly Tu     // Path0 with Depth path of 1
229aba14d3dSWilly Tu     subtree = getSubTree(interfaceMap, path0, 1, interfaces);
230aba14d3dSWilly Tu     ASSERT_EQ(subtree.size(), 1);
231aba14d3dSWilly Tu     ConnectionNames connection = subtree[0].second;
232aba14d3dSWilly Tu     auto object = connection.find("test_object_connection_1");
233aba14d3dSWilly Tu     ASSERT_NE(object, connection.end());
234aba14d3dSWilly Tu     ASSERT_THAT(object->second, ElementsAre("test_interface_1"));
235aba14d3dSWilly Tu 
236aba14d3dSWilly Tu     // Path1
237aba14d3dSWilly Tu     subtree = getSubTree(interfaceMap, path1, 0, interfaces);
238aba14d3dSWilly Tu     ASSERT_EQ(subtree.size(), 1);
239aba14d3dSWilly Tu     connection = subtree[0].second;
240aba14d3dSWilly Tu     object = connection.find("test_object_connection_3");
241aba14d3dSWilly Tu     ASSERT_NE(object, connection.end());
242aba14d3dSWilly Tu     ASSERT_THAT(object->second, ElementsAre("test_interface_3"));
243aba14d3dSWilly Tu }
244aba14d3dSWilly Tu 
TEST_F(TestHandler,getSubTreePathsBad)245aba14d3dSWilly Tu TEST_F(TestHandler, getSubTreePathsBad)
246aba14d3dSWilly Tu {
247aba14d3dSWilly Tu     std::string path = "/test/object_path_0";
248aba14d3dSWilly Tu     std::vector<std::string> interfaces = {"bad_interface"};
249670edd12SPatrick Williams     std::vector<std::string> subtreePath = getSubTreePaths(interfaceMap, path,
250670edd12SPatrick Williams                                                            0, interfaces);
251aba14d3dSWilly Tu     ASSERT_TRUE(subtreePath.empty());
252aba14d3dSWilly Tu 
253aba14d3dSWilly Tu     path = "/invalid_path";
254aba14d3dSWilly Tu     EXPECT_THROW(
255aba14d3dSWilly Tu         getSubTreePaths(interfaceMap, path, 0, interfaces),
256aba14d3dSWilly Tu         sdbusplus::xyz::openbmc_project::Common::Error::ResourceNotFound);
257aba14d3dSWilly Tu }
258aba14d3dSWilly Tu 
TEST_F(TestHandler,getSubTreePathsGood)259aba14d3dSWilly Tu TEST_F(TestHandler, getSubTreePathsGood)
260aba14d3dSWilly Tu {
261aba14d3dSWilly Tu     std::string path0 = "/test/object_path_0";
262aba14d3dSWilly Tu     std::string path1 = "/test/object_path_0/child/grandchild";
263aba14d3dSWilly Tu     std::vector<std::string> interfaces = {"test_interface_1",
264aba14d3dSWilly Tu                                            "test_interface_3"};
265aba14d3dSWilly Tu     // Root
266670edd12SPatrick Williams     std::vector<std::string> subtreePath = getSubTreePaths(interfaceMap, "/", 0,
267670edd12SPatrick Williams                                                            interfaces);
268aba14d3dSWilly Tu     ASSERT_THAT(subtreePath,
269aba14d3dSWilly Tu                 ElementsAre("/test/object_path_0/child",
270aba14d3dSWilly Tu                             "/test/object_path_0/child/grandchild/dog"));
271aba14d3dSWilly Tu 
272aba14d3dSWilly Tu     // Path0
273aba14d3dSWilly Tu     subtreePath = getSubTreePaths(interfaceMap, path0, 0, interfaces);
274aba14d3dSWilly Tu     ASSERT_THAT(subtreePath,
275aba14d3dSWilly Tu                 ElementsAre("/test/object_path_0/child",
276aba14d3dSWilly Tu                             "/test/object_path_0/child/grandchild/dog"));
277aba14d3dSWilly Tu 
278aba14d3dSWilly Tu     // Path0 + Depth path of 1
279aba14d3dSWilly Tu     subtreePath = getSubTreePaths(interfaceMap, path0, 1, interfaces);
280aba14d3dSWilly Tu     ASSERT_THAT(subtreePath, ElementsAre("/test/object_path_0/child"));
281aba14d3dSWilly Tu 
282aba14d3dSWilly Tu     // Path1
283aba14d3dSWilly Tu     subtreePath = getSubTreePaths(interfaceMap, path1, 0, interfaces);
284aba14d3dSWilly Tu     ASSERT_THAT(subtreePath,
285aba14d3dSWilly Tu                 ElementsAre("/test/object_path_0/child/grandchild/dog"));
286aba14d3dSWilly Tu }
28758881d0bSWilly Tu 
TEST_F(TestHandler,getAssociatedSubTreeBad)28858881d0bSWilly Tu TEST_F(TestHandler, getAssociatedSubTreeBad)
28958881d0bSWilly Tu {
29058881d0bSWilly Tu     sdbusplus::message::object_path path("/test/object_path_0");
29158881d0bSWilly Tu     sdbusplus::message::object_path validAssociatedPath = path / "descendent";
29258881d0bSWilly Tu     std::vector<std::string> invalidInterfaces = {"test_interface_3"};
29358881d0bSWilly Tu     std::vector<std::string> validInterfaces = {"test_interface_1",
29458881d0bSWilly Tu                                                 "test_interface_2"};
29558881d0bSWilly Tu     // Associated path, but invalid interface
29658881d0bSWilly Tu     ASSERT_TRUE(getAssociatedSubTree(interfaceMap, associationMap,
29758881d0bSWilly Tu                                      validAssociatedPath, path, 0,
29858881d0bSWilly Tu                                      invalidInterfaces)
29958881d0bSWilly Tu                     .empty());
30058881d0bSWilly Tu 
30158881d0bSWilly Tu     // Valid interface, not associated
30258881d0bSWilly Tu     ASSERT_TRUE(getAssociatedSubTree(interfaceMap, associationMap, path / "dog",
30358881d0bSWilly Tu                                      path, 0, validInterfaces)
30458881d0bSWilly Tu                     .empty());
30558881d0bSWilly Tu 
30658881d0bSWilly Tu     // Invalid path, with valid association
30758881d0bSWilly Tu     path = sdbusplus::message::object_path("/invalid_path");
30858881d0bSWilly Tu     EXPECT_THROW(
30958881d0bSWilly Tu         getAssociatedSubTree(interfaceMap, associationMap, validAssociatedPath,
31058881d0bSWilly Tu                              path, 0, validInterfaces),
31158881d0bSWilly Tu         sdbusplus::xyz::openbmc_project::Common::Error::ResourceNotFound);
31258881d0bSWilly Tu }
31358881d0bSWilly Tu 
TEST_F(TestHandler,getAssociatedSubTreeGood)31458881d0bSWilly Tu TEST_F(TestHandler, getAssociatedSubTreeGood)
31558881d0bSWilly Tu {
31658881d0bSWilly Tu     sdbusplus::message::object_path path0("/test/object_path_0");
31758881d0bSWilly Tu     sdbusplus::message::object_path path1("/test/object_path_0/child");
31858881d0bSWilly Tu     sdbusplus::message::object_path associatedPath = path0 / "descendent";
31958881d0bSWilly Tu     std::vector<std::string> interfaces = {"test_interface_1",
32058881d0bSWilly Tu                                            "test_interface_2",
32158881d0bSWilly Tu                                            // Not associated to path
32258881d0bSWilly Tu                                            "test_interface_3"};
32358881d0bSWilly Tu 
32458881d0bSWilly Tu     // Path0
32558881d0bSWilly Tu     std::vector<InterfaceMapType::value_type> subtree = getAssociatedSubTree(
32658881d0bSWilly Tu         interfaceMap, associationMap, associatedPath, path0, 0, interfaces);
32758881d0bSWilly Tu     ASSERT_EQ(subtree.size(), 2);
32858881d0bSWilly Tu     ConnectionNames connection = subtree[0].second;
32958881d0bSWilly Tu     auto object = connection.find("test_object_connection_1");
33058881d0bSWilly Tu     ASSERT_NE(object, connection.end());
33158881d0bSWilly Tu     ASSERT_THAT(object->second, ElementsAre("test_interface_1"));
33258881d0bSWilly Tu 
33358881d0bSWilly Tu     connection = subtree[1].second;
33458881d0bSWilly Tu     object = connection.find("test_object_connection_2");
33558881d0bSWilly Tu     ASSERT_NE(object, connection.end());
33658881d0bSWilly Tu     ASSERT_THAT(object->second, ElementsAre("test_interface_2"));
33758881d0bSWilly Tu 
33858881d0bSWilly Tu     // Path0 with Depth path of 1
33958881d0bSWilly Tu     subtree = getAssociatedSubTree(interfaceMap, associationMap, associatedPath,
34058881d0bSWilly Tu                                    path0, 1, interfaces);
34158881d0bSWilly Tu     ASSERT_EQ(subtree.size(), 1);
34258881d0bSWilly Tu     connection = subtree[0].second;
34358881d0bSWilly Tu     object = connection.find("test_object_connection_1");
34458881d0bSWilly Tu     ASSERT_NE(object, connection.end());
34558881d0bSWilly Tu     ASSERT_THAT(object->second, ElementsAre("test_interface_1"));
34658881d0bSWilly Tu 
34758881d0bSWilly Tu     // Path1
34858881d0bSWilly Tu     subtree = getAssociatedSubTree(interfaceMap, associationMap,
34958881d0bSWilly Tu                                    path1 / "descendent", path1, 0, interfaces);
35058881d0bSWilly Tu     ASSERT_EQ(subtree.size(), 1);
35158881d0bSWilly Tu     connection = subtree[0].second;
35258881d0bSWilly Tu     object = connection.find("test_object_connection_2");
35358881d0bSWilly Tu     ASSERT_NE(object, connection.end());
35458881d0bSWilly Tu     ASSERT_THAT(object->second, ElementsAre("test_interface_2"));
35558881d0bSWilly Tu }
35658881d0bSWilly Tu 
TEST_F(TestHandler,getAssociatedSubTreePathsBad)35758881d0bSWilly Tu TEST_F(TestHandler, getAssociatedSubTreePathsBad)
35858881d0bSWilly Tu {
35958881d0bSWilly Tu     sdbusplus::message::object_path path("/test/object_path_0");
36058881d0bSWilly Tu     sdbusplus::message::object_path validAssociatedPath = path / "descendent";
36158881d0bSWilly Tu     std::vector<std::string> invalidInterfaces = {"test_interface_3"};
36258881d0bSWilly Tu     std::vector<std::string> validInterfaces = {"test_interface_1",
36358881d0bSWilly Tu                                                 "test_interface_2"};
36458881d0bSWilly Tu     // Associated path, but invalid interface
36558881d0bSWilly Tu     ASSERT_TRUE(getAssociatedSubTreePaths(interfaceMap, associationMap,
36658881d0bSWilly Tu                                           validAssociatedPath, path, 0,
36758881d0bSWilly Tu                                           invalidInterfaces)
36858881d0bSWilly Tu                     .empty());
36958881d0bSWilly Tu 
37058881d0bSWilly Tu     // Valid interface, not associated
37158881d0bSWilly Tu     ASSERT_TRUE(getAssociatedSubTreePaths(interfaceMap, associationMap,
37258881d0bSWilly Tu                                           path / "dog", path, 0,
37358881d0bSWilly Tu                                           validInterfaces)
37458881d0bSWilly Tu                     .empty());
37558881d0bSWilly Tu 
37658881d0bSWilly Tu     // Invalid path, with valid association
37758881d0bSWilly Tu     path = sdbusplus::message::object_path("/invalid_path");
37858881d0bSWilly Tu     EXPECT_THROW(
37958881d0bSWilly Tu         getAssociatedSubTreePaths(interfaceMap, associationMap,
38058881d0bSWilly Tu                                   validAssociatedPath, path, 0,
38158881d0bSWilly Tu                                   validInterfaces),
38258881d0bSWilly Tu         sdbusplus::xyz::openbmc_project::Common::Error::ResourceNotFound);
38358881d0bSWilly Tu }
38458881d0bSWilly Tu 
TEST_F(TestHandler,getAssociatedSubTreePathsGood)38558881d0bSWilly Tu TEST_F(TestHandler, getAssociatedSubTreePathsGood)
38658881d0bSWilly Tu {
38758881d0bSWilly Tu     sdbusplus::message::object_path path0("/test/object_path_0");
38858881d0bSWilly Tu     sdbusplus::message::object_path path1("/test/object_path_0/child");
38958881d0bSWilly Tu     sdbusplus::message::object_path associatedPath = path0 / "descendent";
39058881d0bSWilly Tu     std::vector<std::string> interfaces = {"test_interface_1",
39158881d0bSWilly Tu                                            "test_interface_2",
39258881d0bSWilly Tu                                            // Not associated to path
39358881d0bSWilly Tu                                            "test_interface_3"};
39458881d0bSWilly Tu 
39558881d0bSWilly Tu     // Path0
39658881d0bSWilly Tu     std::vector<std::string> subtreePath = getAssociatedSubTreePaths(
39758881d0bSWilly Tu         interfaceMap, associationMap, associatedPath, path0, 0, interfaces);
39858881d0bSWilly Tu     ASSERT_THAT(subtreePath,
39958881d0bSWilly Tu                 ElementsAre("/test/object_path_0/child",
40058881d0bSWilly Tu                             "/test/object_path_0/child/grandchild"));
40158881d0bSWilly Tu 
40258881d0bSWilly Tu     // Path0 with Depth path of 1
40358881d0bSWilly Tu     subtreePath = getAssociatedSubTreePaths(
40458881d0bSWilly Tu         interfaceMap, associationMap, associatedPath, path0, 1, interfaces);
40558881d0bSWilly Tu     ASSERT_THAT(subtreePath, ElementsAre("/test/object_path_0/child"));
40658881d0bSWilly Tu 
40758881d0bSWilly Tu     // Path1
408670edd12SPatrick Williams     subtreePath = getAssociatedSubTreePaths(interfaceMap, associationMap,
409670edd12SPatrick Williams                                             path1 / "descendent", path1, 0,
410670edd12SPatrick Williams                                             interfaces);
41158881d0bSWilly Tu     ASSERT_THAT(subtreePath,
41258881d0bSWilly Tu                 ElementsAre("/test/object_path_0/child/grandchild"));
41358881d0bSWilly Tu }
414