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