blob: b7dfbb341e82ac83348ff999c60ae5a3ab044795 [file] [log] [blame]
Willy Tuaba14d32023-01-31 14:19:59 -08001#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
14using ::testing::ElementsAre;
15
16class 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 }};
Willy Tu58881d02022-10-02 20:46:45 +000036
37 AssociationMaps associationMap = {
38 .ifaces =
39 {
40 {
41 "/test/object_path_0/descendent",
42 {
43 std::shared_ptr<sdbusplus::asio::dbus_interface>(),
44 {
45 "/test/object_path_0/child",
46 "/test/object_path_0/child/grandchild",
47 },
48 },
49 },
50 {
51 "/test/object_path_0/child/descendent",
52 {
53 std::shared_ptr<sdbusplus::asio::dbus_interface>(),
54 {
55 "/test/object_path_0/child/grandchild",
56 },
57 },
58 },
59 },
60 .owners = {},
61 .pending = {},
62 };
Willy Tuaba14d32023-01-31 14:19:59 -080063};
64
65TEST_F(TestHandler, AddObjectMapResult)
66{
67 std::vector<InterfaceMapType::value_type> interfaceMaps;
68 addObjectMapResult(interfaceMaps, "test_object_path",
69 std::pair<std::string, InterfaceNames>(
70 "test_object_connection_0", {
71 "test_interface_0",
72 "test_interface_1",
73 }));
74
75 addObjectMapResult(interfaceMaps, "test_object_path",
76 std::pair<std::string, InterfaceNames>(
77 "test_object_connection_1", {
78 "test_interface_0",
79 "test_interface_1",
80 }));
81 ASSERT_EQ(interfaceMaps.size(), 1);
82
83 auto entry = std::find_if(
84 interfaceMaps.begin(), interfaceMaps.end(),
85 [](const auto& i) { return "test_object_path" == i.first; });
86 ASSERT_NE(entry, interfaceMap.end());
87 for (const auto& [_, interfaces] : entry->second)
88 {
89 ASSERT_THAT(interfaces,
90 ElementsAre("test_interface_0", "test_interface_1"));
91 }
92
93 // Change the interface, but expect it to be unchanged
94 addObjectMapResult(interfaceMaps, "test_object_path",
95 std::pair<std::string, InterfaceNames>(
96 "test_object_connection_0", {"test_interface_2"}));
97 addObjectMapResult(interfaceMaps, "test_object_path",
98 std::pair<std::string, InterfaceNames>(
99 "test_object_connection_1", {"test_interface_2"}));
100 entry = std::find_if(
101 interfaceMaps.begin(), interfaceMaps.end(),
102 [](const auto& i) { return "test_object_path" == i.first; });
103 ASSERT_NE(entry, interfaceMaps.end());
104 for (const auto& [_, interfaces] : entry->second)
105 {
106 ASSERT_THAT(interfaces,
107 ElementsAre("test_interface_0", "test_interface_1"));
108 }
109}
110
111TEST_F(TestHandler, getAncestorsBad)
112{
113 std::string path = "/test/object_path_0/child/grandchild";
114 std::vector<std::string> interfaces = {"bad_interface"};
115 std::vector<InterfaceMapType::value_type> ancestors =
116 getAncestors(interfaceMap, path, interfaces);
117 ASSERT_TRUE(ancestors.empty());
118
119 path = "/invalid_path";
120 EXPECT_THROW(
121 getAncestors(interfaceMap, path, interfaces),
122 sdbusplus::xyz::openbmc_project::Common::Error::ResourceNotFound);
123}
124
125TEST_F(TestHandler, getAncestorsGood)
126{
127 std::string path = "/test/object_path_0/child/grandchild";
128 std::vector<std::string> interfaces = {"test_interface_0",
129 "test_interface_1"};
130 std::vector<InterfaceMapType::value_type> ancestors =
131 getAncestors(interfaceMap, path, interfaces);
132 ASSERT_EQ(ancestors.size(), 2);
133
134 // Grand Parent
135 EXPECT_EQ(ancestors[0].first, "/test/object_path_0");
136 ASSERT_EQ(ancestors[0].second.size(), 1);
137 auto grandParent = ancestors[0].second.find("test_object_connection_0");
138 ASSERT_NE(grandParent, ancestors[0].second.end());
139 ASSERT_THAT(grandParent->second, ElementsAre("test_interface_0"));
140
141 // Parent
142 ASSERT_EQ(ancestors[1].first, "/test/object_path_0/child");
143 ASSERT_EQ(ancestors[1].second.size(), 1);
144 auto parent = ancestors[1].second.find("test_object_connection_1");
145 ASSERT_NE(parent, ancestors[1].second.end());
146 ASSERT_THAT(parent->second, ElementsAre("test_interface_1"));
147}
148
149TEST_F(TestHandler, getObjectBad)
150{
151 std::string path = "/test/object_path_0";
152 std::vector<std::string> interfaces = {"bad_interface"};
153 EXPECT_THROW(
154 getObject(interfaceMap, path, interfaces),
155 sdbusplus::xyz::openbmc_project::Common::Error::ResourceNotFound);
156
157 path = "/invalid_path";
158 EXPECT_THROW(
159 getObject(interfaceMap, path, interfaces),
160 sdbusplus::xyz::openbmc_project::Common::Error::ResourceNotFound);
161
162 path = "/";
163 EXPECT_THROW(
164 getObject(interfaceMap, path, interfaces),
165 sdbusplus::xyz::openbmc_project::Common::Error::ResourceNotFound);
166}
167
168TEST_F(TestHandler, getObjectGood)
169{
170 std::string path = "/test/object_path_0";
171 std::vector<std::string> interfaces = {"test_interface_0",
172 "test_interface_1"};
173 ConnectionNames connection = getObject(interfaceMap, path, interfaces);
174 auto object = connection.find("test_object_connection_0");
175 ASSERT_NE(object, connection.end());
176 ASSERT_THAT(object->second, ElementsAre("test_interface_0"));
177
178 path = "/test/object_path_0/child";
179 connection = getObject(interfaceMap, path, interfaces);
180 object = connection.find("test_object_connection_1");
181 ASSERT_NE(object, connection.end());
182 ASSERT_THAT(object->second, ElementsAre("test_interface_1"));
183}
184
185TEST_F(TestHandler, getSubTreeBad)
186{
187 std::string path = "/test/object_path_0";
188 std::vector<std::string> interfaces = {"bad_interface"};
189 std::vector<InterfaceMapType::value_type> subtree =
190 getSubTree(interfaceMap, path, 0, interfaces);
191 ASSERT_TRUE(subtree.empty());
192
193 path = "/invalid_path";
194 EXPECT_THROW(
195 getSubTree(interfaceMap, path, 0, interfaces),
196 sdbusplus::xyz::openbmc_project::Common::Error::ResourceNotFound);
197}
198
199void verifySubtree(std::span<InterfaceMapType::value_type> subtree)
200{
201 ASSERT_EQ(subtree.size(), 2);
202 ConnectionNames connection = subtree[0].second;
203 auto object = connection.find("test_object_connection_1");
204 ASSERT_NE(object, connection.end());
205 ASSERT_THAT(object->second, ElementsAre("test_interface_1"));
206
207 connection = subtree[1].second;
208 object = connection.find("test_object_connection_3");
209 ASSERT_NE(object, connection.end());
210 ASSERT_THAT(object->second, ElementsAre("test_interface_3"));
211}
212
213TEST_F(TestHandler, getSubTreeGood)
214{
215 std::string path0 = "/test/object_path_0";
216 std::string path1 = "/test/object_path_0/child/grandchild";
217 std::vector<std::string> interfaces = {"test_interface_1",
218 "test_interface_3"};
219 // Root
220 std::vector<InterfaceMapType::value_type> subtree =
221 getSubTree(interfaceMap, "/", 0, interfaces);
222 verifySubtree(subtree);
223
224 // Path0
225 subtree = getSubTree(interfaceMap, path0, 0, interfaces);
226 verifySubtree(subtree);
227
228 // Path0 with Depth path of 1
229 subtree = getSubTree(interfaceMap, path0, 1, interfaces);
230 ASSERT_EQ(subtree.size(), 1);
231 ConnectionNames connection = subtree[0].second;
232 auto object = connection.find("test_object_connection_1");
233 ASSERT_NE(object, connection.end());
234 ASSERT_THAT(object->second, ElementsAre("test_interface_1"));
235
236 // Path1
237 subtree = getSubTree(interfaceMap, path1, 0, interfaces);
238 ASSERT_EQ(subtree.size(), 1);
239 connection = subtree[0].second;
240 object = connection.find("test_object_connection_3");
241 ASSERT_NE(object, connection.end());
242 ASSERT_THAT(object->second, ElementsAre("test_interface_3"));
243}
244
245TEST_F(TestHandler, getSubTreePathsBad)
246{
247 std::string path = "/test/object_path_0";
248 std::vector<std::string> interfaces = {"bad_interface"};
249 std::vector<std::string> subtreePath =
250 getSubTreePaths(interfaceMap, path, 0, interfaces);
251 ASSERT_TRUE(subtreePath.empty());
252
253 path = "/invalid_path";
254 EXPECT_THROW(
255 getSubTreePaths(interfaceMap, path, 0, interfaces),
256 sdbusplus::xyz::openbmc_project::Common::Error::ResourceNotFound);
257}
258
259TEST_F(TestHandler, getSubTreePathsGood)
260{
261 std::string path0 = "/test/object_path_0";
262 std::string path1 = "/test/object_path_0/child/grandchild";
263 std::vector<std::string> interfaces = {"test_interface_1",
264 "test_interface_3"};
265 // Root
266 std::vector<std::string> subtreePath =
267 getSubTreePaths(interfaceMap, "/", 0, interfaces);
268 ASSERT_THAT(subtreePath,
269 ElementsAre("/test/object_path_0/child",
270 "/test/object_path_0/child/grandchild/dog"));
271
272 // Path0
273 subtreePath = getSubTreePaths(interfaceMap, path0, 0, interfaces);
274 ASSERT_THAT(subtreePath,
275 ElementsAre("/test/object_path_0/child",
276 "/test/object_path_0/child/grandchild/dog"));
277
278 // Path0 + Depth path of 1
279 subtreePath = getSubTreePaths(interfaceMap, path0, 1, interfaces);
280 ASSERT_THAT(subtreePath, ElementsAre("/test/object_path_0/child"));
281
282 // Path1
283 subtreePath = getSubTreePaths(interfaceMap, path1, 0, interfaces);
284 ASSERT_THAT(subtreePath,
285 ElementsAre("/test/object_path_0/child/grandchild/dog"));
286}
Willy Tu58881d02022-10-02 20:46:45 +0000287
288TEST_F(TestHandler, getAssociatedSubTreeBad)
289{
290 sdbusplus::message::object_path path("/test/object_path_0");
291 sdbusplus::message::object_path validAssociatedPath = path / "descendent";
292 std::vector<std::string> invalidInterfaces = {"test_interface_3"};
293 std::vector<std::string> validInterfaces = {"test_interface_1",
294 "test_interface_2"};
295 // Associated path, but invalid interface
296 ASSERT_TRUE(getAssociatedSubTree(interfaceMap, associationMap,
297 validAssociatedPath, path, 0,
298 invalidInterfaces)
299 .empty());
300
301 // Valid interface, not associated
302 ASSERT_TRUE(getAssociatedSubTree(interfaceMap, associationMap, path / "dog",
303 path, 0, validInterfaces)
304 .empty());
305
306 // Invalid path, with valid association
307 path = sdbusplus::message::object_path("/invalid_path");
308 EXPECT_THROW(
309 getAssociatedSubTree(interfaceMap, associationMap, validAssociatedPath,
310 path, 0, validInterfaces),
311 sdbusplus::xyz::openbmc_project::Common::Error::ResourceNotFound);
312}
313
314TEST_F(TestHandler, getAssociatedSubTreeGood)
315{
316 sdbusplus::message::object_path path0("/test/object_path_0");
317 sdbusplus::message::object_path path1("/test/object_path_0/child");
318 sdbusplus::message::object_path associatedPath = path0 / "descendent";
319 std::vector<std::string> interfaces = {"test_interface_1",
320 "test_interface_2",
321 // Not associated to path
322 "test_interface_3"};
323
324 // Path0
325 std::vector<InterfaceMapType::value_type> subtree = getAssociatedSubTree(
326 interfaceMap, associationMap, associatedPath, path0, 0, interfaces);
327 ASSERT_EQ(subtree.size(), 2);
328 ConnectionNames connection = subtree[0].second;
329 auto object = connection.find("test_object_connection_1");
330 ASSERT_NE(object, connection.end());
331 ASSERT_THAT(object->second, ElementsAre("test_interface_1"));
332
333 connection = subtree[1].second;
334 object = connection.find("test_object_connection_2");
335 ASSERT_NE(object, connection.end());
336 ASSERT_THAT(object->second, ElementsAre("test_interface_2"));
337
338 // Path0 with Depth path of 1
339 subtree = getAssociatedSubTree(interfaceMap, associationMap, associatedPath,
340 path0, 1, interfaces);
341 ASSERT_EQ(subtree.size(), 1);
342 connection = subtree[0].second;
343 object = connection.find("test_object_connection_1");
344 ASSERT_NE(object, connection.end());
345 ASSERT_THAT(object->second, ElementsAre("test_interface_1"));
346
347 // Path1
348 subtree = getAssociatedSubTree(interfaceMap, associationMap,
349 path1 / "descendent", path1, 0, interfaces);
350 ASSERT_EQ(subtree.size(), 1);
351 connection = subtree[0].second;
352 object = connection.find("test_object_connection_2");
353 ASSERT_NE(object, connection.end());
354 ASSERT_THAT(object->second, ElementsAre("test_interface_2"));
355}
356
357TEST_F(TestHandler, getAssociatedSubTreePathsBad)
358{
359 sdbusplus::message::object_path path("/test/object_path_0");
360 sdbusplus::message::object_path validAssociatedPath = path / "descendent";
361 std::vector<std::string> invalidInterfaces = {"test_interface_3"};
362 std::vector<std::string> validInterfaces = {"test_interface_1",
363 "test_interface_2"};
364 // Associated path, but invalid interface
365 ASSERT_TRUE(getAssociatedSubTreePaths(interfaceMap, associationMap,
366 validAssociatedPath, path, 0,
367 invalidInterfaces)
368 .empty());
369
370 // Valid interface, not associated
371 ASSERT_TRUE(getAssociatedSubTreePaths(interfaceMap, associationMap,
372 path / "dog", path, 0,
373 validInterfaces)
374 .empty());
375
376 // Invalid path, with valid association
377 path = sdbusplus::message::object_path("/invalid_path");
378 EXPECT_THROW(
379 getAssociatedSubTreePaths(interfaceMap, associationMap,
380 validAssociatedPath, path, 0,
381 validInterfaces),
382 sdbusplus::xyz::openbmc_project::Common::Error::ResourceNotFound);
383}
384
385TEST_F(TestHandler, getAssociatedSubTreePathsGood)
386{
387 sdbusplus::message::object_path path0("/test/object_path_0");
388 sdbusplus::message::object_path path1("/test/object_path_0/child");
389 sdbusplus::message::object_path associatedPath = path0 / "descendent";
390 std::vector<std::string> interfaces = {"test_interface_1",
391 "test_interface_2",
392 // Not associated to path
393 "test_interface_3"};
394
395 // Path0
396 std::vector<std::string> subtreePath = getAssociatedSubTreePaths(
397 interfaceMap, associationMap, associatedPath, path0, 0, interfaces);
398 ASSERT_THAT(subtreePath,
399 ElementsAre("/test/object_path_0/child",
400 "/test/object_path_0/child/grandchild"));
401
402 // Path0 with Depth path of 1
403 subtreePath = getAssociatedSubTreePaths(
404 interfaceMap, associationMap, associatedPath, path0, 1, interfaces);
405 ASSERT_THAT(subtreePath, ElementsAre("/test/object_path_0/child"));
406
407 // Path1
408 subtreePath =
409 getAssociatedSubTreePaths(interfaceMap, associationMap,
410 path1 / "descendent", path1, 0, interfaces);
411 ASSERT_THAT(subtreePath,
412 ElementsAre("/test/object_path_0/child/grandchild"));
413}