blob: 62aefab4108cba3e0ef2cf5b4dae1993da3aedaf [file] [log] [blame]
Andrew Geissler271b7dd2019-02-05 11:23:30 -06001#include "src/associations.hpp"
2
Andrew Geisslerb04f0332019-02-08 14:07:56 -06003#include "src/test/util/asio_server_class.hpp"
Andrew Geisslerbb7b5922019-02-08 14:16:48 -06004#include "src/test/util/association_objects.hpp"
Andrew Geissler491f9ac2019-02-22 15:23:33 -06005#include "src/test/util/debug_output.hpp"
Andrew Geisslerb04f0332019-02-08 14:07:56 -06006
Andrew Geissler271b7dd2019-02-05 11:23:30 -06007#include <sdbusplus/asio/connection.hpp>
8#include <sdbusplus/asio/object_server.hpp>
9
10#include <gtest/gtest.h>
11
Andrew Geisslerb04f0332019-02-08 14:07:56 -060012class TestAssociations : public AsioServerClassTest
Kallas, Pawel5b4357d2022-10-12 15:36:37 +020013{
14 public:
15 boost::asio::io_context io;
16 virtual void SetUp()
17 {
18 io.run();
19 }
20};
Andrew Geisslerb04f0332019-02-08 14:07:56 -060021sdbusplus::asio::object_server* TestAssociations::AsioServerClassTest::server =
22 nullptr;
Andrew Geissler271b7dd2019-02-05 11:23:30 -060023
Andrew Geissler271b7dd2019-02-05 11:23:30 -060024// Verify call when path is not in associated owners
25TEST_F(TestAssociations, SourcePathNotInAssociations)
26{
27 EXPECT_NE(nullptr, server);
28 std::string sourcePath = "/xyz/openbmc_project/no/association";
Matt Spinlere2359fb2019-04-05 14:11:33 -050029 AssociationMaps assocMaps;
Andrew Geissler271b7dd2019-02-05 11:23:30 -060030
Kallas, Pawel5b4357d2022-10-12 15:36:37 +020031 removeAssociation(io, sourcePath, defaultDbusSvc, *server, assocMaps);
Andrew Geissler271b7dd2019-02-05 11:23:30 -060032}
33
34// Verify call when owner is not in associated owners
35TEST_F(TestAssociations, OwnerNotInAssociations)
36{
Matt Spinlere2359fb2019-04-05 14:11:33 -050037 AssociationMaps assocMaps;
38 assocMaps.owners = createDefaultOwnerAssociation();
Andrew Geissler271b7dd2019-02-05 11:23:30 -060039
Kallas, Pawel5b4357d2022-10-12 15:36:37 +020040 removeAssociation(io, defaultSourcePath, defaultDbusSvc, *server,
41 assocMaps);
Andrew Geissler271b7dd2019-02-05 11:23:30 -060042}
43
44// Verify call when path is not in associated interfaces
45TEST_F(TestAssociations, PathNotInAssocInterfaces)
46{
Matt Spinlere2359fb2019-04-05 14:11:33 -050047 AssociationMaps assocMaps;
Andrew Geissler271b7dd2019-02-05 11:23:30 -060048
Matt Spinlere2359fb2019-04-05 14:11:33 -050049 assocMaps.owners = createDefaultOwnerAssociation();
Andrew Geissler271b7dd2019-02-05 11:23:30 -060050
Kallas, Pawel5b4357d2022-10-12 15:36:37 +020051 removeAssociation(io, defaultSourcePath, defaultDbusSvc, *server,
52 assocMaps);
Andrew Geissler271b7dd2019-02-05 11:23:30 -060053
Matt Spinlere2359fb2019-04-05 14:11:33 -050054 EXPECT_TRUE(assocMaps.owners.empty());
Andrew Geissler271b7dd2019-02-05 11:23:30 -060055}
56
57// Verify call when path is in associated interfaces
58TEST_F(TestAssociations, PathIsInAssociatedInterfaces)
59{
60 // Build up these objects so that an associated interface will match
61 // with the associated owner being removed
Matt Spinlere2359fb2019-04-05 14:11:33 -050062 AssociationMaps assocMaps;
63 assocMaps.owners = createDefaultOwnerAssociation();
64 assocMaps.ifaces = createDefaultInterfaceAssociation(server);
Andrew Geissler271b7dd2019-02-05 11:23:30 -060065
Kallas, Pawel5b4357d2022-10-12 15:36:37 +020066 removeAssociation(io, defaultSourcePath, defaultDbusSvc, *server,
67 assocMaps);
Andrew Geissler271b7dd2019-02-05 11:23:30 -060068
69 // Verify owner association was deleted
Matt Spinlere2359fb2019-04-05 14:11:33 -050070 EXPECT_TRUE(assocMaps.owners.empty());
Andrew Geissler271b7dd2019-02-05 11:23:30 -060071
72 // Verify endpoint was deleted from interface association
73 auto intfEndpoints =
Brad Bishopa098a372022-05-05 15:19:04 -040074 std::get<endpointsPos>(assocMaps.ifaces[defaultFwdPath]);
Andrew Geissler271b7dd2019-02-05 11:23:30 -060075 EXPECT_EQ(intfEndpoints.size(), 0);
Brad Bishopa098a372022-05-05 15:19:04 -040076 intfEndpoints = std::get<endpointsPos>(assocMaps.ifaces[defaultRevPath]);
Andrew Geissler271b7dd2019-02-05 11:23:30 -060077 EXPECT_EQ(intfEndpoints.size(), 0);
78}
79
80// Verify call when path is in associated interfaces, with extra endpoints
81TEST_F(TestAssociations, PathIsInAssociatedInterfacesExtraEndpoints)
82{
83 // Build up these objects so that an associated interface will match
84 // with the associated owner being removed
Matt Spinlere2359fb2019-04-05 14:11:33 -050085 AssociationMaps assocMaps;
86 assocMaps.owners = createDefaultOwnerAssociation();
87 assocMaps.ifaces = createDefaultInterfaceAssociation(server);
Andrew Geissler271b7dd2019-02-05 11:23:30 -060088
89 // Add another endpoint to the assoc interfaces
Matt Spinlere2359fb2019-04-05 14:11:33 -050090 addEndpointToInterfaceAssociation(assocMaps.ifaces);
Andrew Geissler271b7dd2019-02-05 11:23:30 -060091
Kallas, Pawel5b4357d2022-10-12 15:36:37 +020092 removeAssociation(io, defaultSourcePath, defaultDbusSvc, *server,
93 assocMaps);
Andrew Geissler271b7dd2019-02-05 11:23:30 -060094
95 // Verify owner association was deleted
Matt Spinlere2359fb2019-04-05 14:11:33 -050096 EXPECT_TRUE(assocMaps.owners.empty());
Andrew Geissler271b7dd2019-02-05 11:23:30 -060097
98 // Verify all endpoints are deleted since source path was deleted
99 auto intfEndpoints =
Brad Bishopa098a372022-05-05 15:19:04 -0400100 std::get<endpointsPos>(assocMaps.ifaces[defaultFwdPath]);
Andrew Geissler271b7dd2019-02-05 11:23:30 -0600101 EXPECT_EQ(intfEndpoints.size(), 0);
Brad Bishopa098a372022-05-05 15:19:04 -0400102 intfEndpoints = std::get<endpointsPos>(assocMaps.ifaces[defaultRevPath]);
Andrew Geissler271b7dd2019-02-05 11:23:30 -0600103 EXPECT_EQ(intfEndpoints.size(), 0);
104}
Andrew Geisslere4ab6c92019-02-21 15:07:27 -0600105
106// Verify no associations or endpoints removed when the change is identical
107TEST_F(TestAssociations, checkAssociationEndpointRemovesNoEpRemove)
108{
Brad Bishopa098a372022-05-05 15:19:04 -0400109 AssociationPaths newAssocPaths = {{defaultFwdPath, {defaultEndpoint}},
110 {defaultRevPath, {defaultSourcePath}}};
Andrew Geisslere4ab6c92019-02-21 15:07:27 -0600111
Matt Spinlere2359fb2019-04-05 14:11:33 -0500112 AssociationMaps assocMaps;
113 assocMaps.owners = createDefaultOwnerAssociation();
114 assocMaps.ifaces = createDefaultInterfaceAssociation(server);
Andrew Geisslere4ab6c92019-02-21 15:07:27 -0600115
Kallas, Pawel5b4357d2022-10-12 15:36:37 +0200116 checkAssociationEndpointRemoves(io, defaultSourcePath, defaultDbusSvc,
Matt Spinlere2359fb2019-04-05 14:11:33 -0500117 newAssocPaths, *server, assocMaps);
Andrew Geisslere4ab6c92019-02-21 15:07:27 -0600118
119 // Verify endpoints were not deleted because they matche with what was
120 // in the original
121 auto intfEndpoints =
Brad Bishopa098a372022-05-05 15:19:04 -0400122 std::get<endpointsPos>(assocMaps.ifaces[defaultFwdPath]);
Andrew Geisslere4ab6c92019-02-21 15:07:27 -0600123 EXPECT_EQ(intfEndpoints.size(), 1);
Brad Bishopa098a372022-05-05 15:19:04 -0400124 intfEndpoints = std::get<endpointsPos>(assocMaps.ifaces[defaultRevPath]);
Andrew Geisslere4ab6c92019-02-21 15:07:27 -0600125 EXPECT_EQ(intfEndpoints.size(), 1);
126}
127
128// Verify endpoint is removed when assoc path is different
129TEST_F(TestAssociations, checkAssociationEndpointRemovesEpRemoveApDiff)
130{
Brad Bishopa098a372022-05-05 15:19:04 -0400131 AssociationPaths newAssocPaths = {{"/different/path", {defaultEndpoint}}};
Andrew Geisslere4ab6c92019-02-21 15:07:27 -0600132
Matt Spinlere2359fb2019-04-05 14:11:33 -0500133 AssociationMaps assocMaps;
134 assocMaps.owners = createDefaultOwnerAssociation();
135 assocMaps.ifaces = createDefaultInterfaceAssociation(server);
Andrew Geisslere4ab6c92019-02-21 15:07:27 -0600136
Kallas, Pawel5b4357d2022-10-12 15:36:37 +0200137 checkAssociationEndpointRemoves(io, defaultSourcePath, defaultDbusSvc,
Matt Spinlere2359fb2019-04-05 14:11:33 -0500138 newAssocPaths, *server, assocMaps);
Andrew Geisslere4ab6c92019-02-21 15:07:27 -0600139
140 // Verify initial endpoints were deleted because the new path
141 auto intfEndpoints =
Brad Bishopa098a372022-05-05 15:19:04 -0400142 std::get<endpointsPos>(assocMaps.ifaces[defaultFwdPath]);
Andrew Geisslere4ab6c92019-02-21 15:07:27 -0600143 EXPECT_EQ(intfEndpoints.size(), 0);
Brad Bishopa098a372022-05-05 15:19:04 -0400144 intfEndpoints = std::get<endpointsPos>(assocMaps.ifaces[defaultRevPath]);
Andrew Geisslere4ab6c92019-02-21 15:07:27 -0600145 EXPECT_EQ(intfEndpoints.size(), 0);
146}
147
148// Verify endpoint is removed when endpoint is different
149TEST_F(TestAssociations, checkAssociationEndpointRemovesEpRemoveEpChanged)
150{
151 AssociationPaths newAssocPaths = {
Brad Bishopa098a372022-05-05 15:19:04 -0400152 {defaultFwdPath, {defaultEndpoint + "/different"}},
153 {defaultRevPath, {defaultSourcePath + "/different"}}};
Andrew Geisslere4ab6c92019-02-21 15:07:27 -0600154
Matt Spinlere2359fb2019-04-05 14:11:33 -0500155 AssociationMaps assocMaps;
156 assocMaps.owners = createDefaultOwnerAssociation();
157 assocMaps.ifaces = createDefaultInterfaceAssociation(server);
Andrew Geisslere4ab6c92019-02-21 15:07:27 -0600158
Kallas, Pawel5b4357d2022-10-12 15:36:37 +0200159 checkAssociationEndpointRemoves(io, defaultSourcePath, defaultDbusSvc,
Matt Spinlere2359fb2019-04-05 14:11:33 -0500160 newAssocPaths, *server, assocMaps);
Andrew Geisslere4ab6c92019-02-21 15:07:27 -0600161
162 // Verify initial endpoints were deleted because of different endpoints
163 auto intfEndpoints =
Brad Bishopa098a372022-05-05 15:19:04 -0400164 std::get<endpointsPos>(assocMaps.ifaces[defaultFwdPath]);
Andrew Geisslere4ab6c92019-02-21 15:07:27 -0600165 EXPECT_EQ(intfEndpoints.size(), 0);
Brad Bishopa098a372022-05-05 15:19:04 -0400166 intfEndpoints = std::get<endpointsPos>(assocMaps.ifaces[defaultRevPath]);
Andrew Geisslere4ab6c92019-02-21 15:07:27 -0600167 EXPECT_EQ(intfEndpoints.size(), 0);
168}
Andrew Geissler491f9ac2019-02-22 15:23:33 -0600169
170// Verify existing endpoint deleted when empty endpoint is provided
171TEST_F(TestAssociations, associationChangedEmptyEndpoint)
172{
Andrew Geisslereecc1962020-06-10 19:58:35 -0500173 std::vector<Association> associations = {
174 {"inventory_cee", "error_cee", ""}};
Brad Bishopa098a372022-05-05 15:19:04 -0400175 InterfaceMapType interfaceMap;
Andrew Geissler491f9ac2019-02-22 15:23:33 -0600176
Matt Spinlere2359fb2019-04-05 14:11:33 -0500177 AssociationMaps assocMaps;
178 assocMaps.owners = createDefaultOwnerAssociation();
179 assocMaps.ifaces = createDefaultInterfaceAssociation(server);
Andrew Geissler491f9ac2019-02-22 15:23:33 -0600180
181 // Empty endpoint will result in deletion of corresponding assocInterface
Kallas, Pawel5b4357d2022-10-12 15:36:37 +0200182 associationChanged(io, *server, associations, defaultSourcePath,
183 defaultDbusSvc, interfaceMap, assocMaps);
Andrew Geissler491f9ac2019-02-22 15:23:33 -0600184
Andrew Geissler0a560a52019-03-22 10:59:07 -0500185 // Both of these should be 0 since we have an invalid endpoint
Andrew Geissler491f9ac2019-02-22 15:23:33 -0600186 auto intfEndpoints =
Brad Bishopa098a372022-05-05 15:19:04 -0400187 std::get<endpointsPos>(assocMaps.ifaces[defaultFwdPath]);
Andrew Geissler0a560a52019-03-22 10:59:07 -0500188 EXPECT_EQ(intfEndpoints.size(), 0);
Brad Bishopa098a372022-05-05 15:19:04 -0400189 intfEndpoints = std::get<endpointsPos>(assocMaps.ifaces[defaultRevPath]);
Andrew Geissler491f9ac2019-02-22 15:23:33 -0600190 EXPECT_EQ(intfEndpoints.size(), 0);
Matt Spinlere0b0e3a2019-04-08 10:39:23 -0500191
192 EXPECT_EQ(assocMaps.pending.size(), 0);
Andrew Geissler491f9ac2019-02-22 15:23:33 -0600193}
194
195// Add a new association with endpoint
196TEST_F(TestAssociations, associationChangedAddNewAssoc)
197{
198 std::vector<Association> associations = {
199 {"abc", "def", "/xyz/openbmc_project/new/endpoint"}};
200
Matt Spinlere2359fb2019-04-05 14:11:33 -0500201 AssociationMaps assocMaps;
202 assocMaps.owners = createDefaultOwnerAssociation();
203 assocMaps.ifaces = createDefaultInterfaceAssociation(server);
Andrew Geissler491f9ac2019-02-22 15:23:33 -0600204
Matt Spinlere0b0e3a2019-04-08 10:39:23 -0500205 // Make it look like the assoc endpoints are on D-Bus
Brad Bishopa098a372022-05-05 15:19:04 -0400206 InterfaceMapType interfaceMap = {
207 {"/new/source/path", {{defaultDbusSvc, {"a"}}}},
208 {"/xyz/openbmc_project/new/endpoint", {{defaultDbusSvc, {"a"}}}}};
Matt Spinlere0b0e3a2019-04-08 10:39:23 -0500209
Kallas, Pawel5b4357d2022-10-12 15:36:37 +0200210 associationChanged(io, *server, associations, "/new/source/path",
Brad Bishopa098a372022-05-05 15:19:04 -0400211 defaultDbusSvc, interfaceMap, assocMaps);
Andrew Geissler491f9ac2019-02-22 15:23:33 -0600212
213 // Two source paths
Matt Spinlere2359fb2019-04-05 14:11:33 -0500214 EXPECT_EQ(assocMaps.owners.size(), 2);
Andrew Geissler491f9ac2019-02-22 15:23:33 -0600215
216 // Four interfaces
Matt Spinlere2359fb2019-04-05 14:11:33 -0500217 EXPECT_EQ(assocMaps.ifaces.size(), 4);
Andrew Geissler491f9ac2019-02-22 15:23:33 -0600218
Matt Spinlere0b0e3a2019-04-08 10:39:23 -0500219 // Nothing pending
220 EXPECT_EQ(assocMaps.pending.size(), 0);
221
Matt Spinlere2359fb2019-04-05 14:11:33 -0500222 // New endpoint so assocMaps.ifaces should be same size
Andrew Geissler491f9ac2019-02-22 15:23:33 -0600223 auto intfEndpoints =
Brad Bishopa098a372022-05-05 15:19:04 -0400224 std::get<endpointsPos>(assocMaps.ifaces[defaultFwdPath]);
Andrew Geissler491f9ac2019-02-22 15:23:33 -0600225 EXPECT_EQ(intfEndpoints.size(), 1);
226}
227
228// Add a new association to empty objects
229TEST_F(TestAssociations, associationChangedAddNewAssocEmptyObj)
230{
231 std::string sourcePath = "/logging/entry/1";
232 std::string owner = "xyz.openbmc_project.Test";
233 std::vector<Association> associations = {
Andrew Geisslereecc1962020-06-10 19:58:35 -0500234 {"inventory_canaeo", "error_canaeo",
Andrew Geissler491f9ac2019-02-22 15:23:33 -0600235 "/xyz/openbmc_project/inventory/system/chassis"}};
236
237 // Empty objects because this test will ensure assocOwners adds the
238 // changed association and interface
Matt Spinlere2359fb2019-04-05 14:11:33 -0500239 AssociationMaps assocMaps;
Andrew Geissler491f9ac2019-02-22 15:23:33 -0600240
Matt Spinlere0b0e3a2019-04-08 10:39:23 -0500241 // Make it look like the assoc endpoints are on D-Bus
Brad Bishopa098a372022-05-05 15:19:04 -0400242 InterfaceMapType interfaceMap = createDefaultInterfaceMap();
Matt Spinlere0b0e3a2019-04-08 10:39:23 -0500243
Kallas, Pawel5b4357d2022-10-12 15:36:37 +0200244 associationChanged(io, *server, associations, defaultSourcePath,
245 defaultDbusSvc, interfaceMap, assocMaps);
Andrew Geissler491f9ac2019-02-22 15:23:33 -0600246
247 // New associations so ensure it now contains a single entry
Matt Spinlere2359fb2019-04-05 14:11:33 -0500248 EXPECT_EQ(assocMaps.owners.size(), 1);
Andrew Geissler491f9ac2019-02-22 15:23:33 -0600249
Matt Spinlere0b0e3a2019-04-08 10:39:23 -0500250 // Nothing pending
251 EXPECT_EQ(assocMaps.pending.size(), 0);
252
Andrew Geissler491f9ac2019-02-22 15:23:33 -0600253 // Verify corresponding assoc paths each have one endpoint in assoc
254 // interfaces and that those endpoints match
Brad Bishopa098a372022-05-05 15:19:04 -0400255 auto singleOwner = assocMaps.owners[defaultSourcePath];
256 auto singleIntf = singleOwner[defaultDbusSvc];
Andrew Geissler491f9ac2019-02-22 15:23:33 -0600257 for (auto i : singleIntf)
258 {
Matt Spinlere2359fb2019-04-05 14:11:33 -0500259 auto intfEndpoints = std::get<endpointsPos>(assocMaps.ifaces[i.first]);
Andrew Geissler491f9ac2019-02-22 15:23:33 -0600260 EXPECT_EQ(intfEndpoints.size(), 1);
261 EXPECT_EQ(intfEndpoints[0], *i.second.begin());
262 }
263}
264
265// Add a new association to same source path but with new owner
266TEST_F(TestAssociations, associationChangedAddNewAssocNewOwner)
267{
268 std::string newOwner = "xyz.openbmc_project.Test2";
269 std::vector<Association> associations = {
Andrew Geisslereecc1962020-06-10 19:58:35 -0500270 {"inventory_canano", "error_canano",
Andrew Geissler491f9ac2019-02-22 15:23:33 -0600271 "/xyz/openbmc_project/inventory/system/chassis"}};
272
Matt Spinlere0b0e3a2019-04-08 10:39:23 -0500273 // Make it look like the assoc endpoints are on D-Bus
Brad Bishopa098a372022-05-05 15:19:04 -0400274 InterfaceMapType interfaceMap = createDefaultInterfaceMap();
Matt Spinlere0b0e3a2019-04-08 10:39:23 -0500275
Matt Spinlere2359fb2019-04-05 14:11:33 -0500276 AssociationMaps assocMaps;
277 assocMaps.owners = createDefaultOwnerAssociation();
278 assocMaps.ifaces = createDefaultInterfaceAssociation(server);
Andrew Geissler491f9ac2019-02-22 15:23:33 -0600279
Kallas, Pawel5b4357d2022-10-12 15:36:37 +0200280 associationChanged(io, *server, associations, defaultSourcePath, newOwner,
Matt Spinlere0b0e3a2019-04-08 10:39:23 -0500281 interfaceMap, assocMaps);
Andrew Geissler491f9ac2019-02-22 15:23:33 -0600282
283 // New endpoint so assocOwners should be same size
Matt Spinlere2359fb2019-04-05 14:11:33 -0500284 EXPECT_EQ(assocMaps.owners.size(), 1);
Andrew Geissler491f9ac2019-02-22 15:23:33 -0600285
286 // Ensure only one endpoint under first path
287 auto intfEndpoints =
Brad Bishopa098a372022-05-05 15:19:04 -0400288 std::get<endpointsPos>(assocMaps.ifaces[defaultFwdPath]);
Andrew Geissler491f9ac2019-02-22 15:23:33 -0600289 EXPECT_EQ(intfEndpoints.size(), 1);
290
291 // Ensure the 2 new association endpoints are under the new owner
Brad Bishopa098a372022-05-05 15:19:04 -0400292 auto a = assocMaps.owners.find(defaultSourcePath);
Andrew Geissler491f9ac2019-02-22 15:23:33 -0600293 auto o = a->second.find(newOwner);
294 EXPECT_EQ(o->second.size(), 2);
Matt Spinlere0b0e3a2019-04-08 10:39:23 -0500295
296 // Nothing pending
297 EXPECT_EQ(assocMaps.pending.size(), 0);
Andrew Geissler491f9ac2019-02-22 15:23:33 -0600298}
299
300// Add a new association to existing interface path
301TEST_F(TestAssociations, associationChangedAddNewAssocSameInterface)
302{
303 std::vector<Association> associations = {
304 {"abc", "error", "/xyz/openbmc_project/inventory/system/chassis"}};
305
Matt Spinlere0b0e3a2019-04-08 10:39:23 -0500306 // Make it look like the assoc endpoints are on D-Bus
Brad Bishopa098a372022-05-05 15:19:04 -0400307 InterfaceMapType interfaceMap = createDefaultInterfaceMap();
Matt Spinlere0b0e3a2019-04-08 10:39:23 -0500308
Matt Spinlere2359fb2019-04-05 14:11:33 -0500309 AssociationMaps assocMaps;
310 assocMaps.owners = createDefaultOwnerAssociation();
311 assocMaps.ifaces = createDefaultInterfaceAssociation(server);
Andrew Geissler491f9ac2019-02-22 15:23:33 -0600312
Kallas, Pawel5b4357d2022-10-12 15:36:37 +0200313 associationChanged(io, *server, associations, defaultSourcePath,
314 defaultDbusSvc, interfaceMap, assocMaps);
Andrew Geissler491f9ac2019-02-22 15:23:33 -0600315
316 // Should have 3 entries in AssociationInterfaces, one is just missing an
317 // endpoint
Matt Spinlere2359fb2019-04-05 14:11:33 -0500318 EXPECT_EQ(assocMaps.ifaces.size(), 3);
Andrew Geissler491f9ac2019-02-22 15:23:33 -0600319
320 // Change to existing interface so it will be removed here
321 auto intfEndpoints =
Brad Bishopa098a372022-05-05 15:19:04 -0400322 std::get<endpointsPos>(assocMaps.ifaces[defaultFwdPath]);
Andrew Geissler491f9ac2019-02-22 15:23:33 -0600323 EXPECT_EQ(intfEndpoints.size(), 0);
324
325 // The new endpoint should exist though in it's place
326 intfEndpoints = std::get<endpointsPos>(
Brad Bishopa098a372022-05-05 15:19:04 -0400327 assocMaps.ifaces[defaultSourcePath + "/" + "abc"]);
Andrew Geissler491f9ac2019-02-22 15:23:33 -0600328 EXPECT_EQ(intfEndpoints.size(), 1);
329
330 // Added to an existing owner path so still 1
Matt Spinlere2359fb2019-04-05 14:11:33 -0500331 EXPECT_EQ(assocMaps.owners.size(), 1);
Matt Spinlere0b0e3a2019-04-08 10:39:23 -0500332
333 EXPECT_EQ(assocMaps.pending.size(), 0);
Andrew Geissler491f9ac2019-02-22 15:23:33 -0600334}
Matt Spinler9f1adbc2019-04-08 10:47:19 -0500335
336// Add 2 pending associations
337TEST_F(TestAssociations, addPendingAssocs)
338{
339 AssociationMaps assocMaps;
340
Brad Bishopa098a372022-05-05 15:19:04 -0400341 addPendingAssociation(defaultSourcePath, "inventory", defaultEndpoint,
342 "error", defaultDbusSvc, assocMaps);
Matt Spinler9f1adbc2019-04-08 10:47:19 -0500343
344 EXPECT_TRUE(assocMaps.ifaces.empty());
345 EXPECT_TRUE(assocMaps.owners.empty());
346
347 EXPECT_EQ(assocMaps.pending.size(), 1);
348
Brad Bishopa098a372022-05-05 15:19:04 -0400349 addPendingAssociation("some/other/path", "inventory", defaultEndpoint,
350 "error", defaultDbusSvc, assocMaps);
Matt Spinler9f1adbc2019-04-08 10:47:19 -0500351
352 EXPECT_TRUE(assocMaps.ifaces.empty());
353 EXPECT_TRUE(assocMaps.owners.empty());
354
355 EXPECT_EQ(assocMaps.pending.size(), 2);
356}
357
358// Test adding a new endpoint to a pending association
359TEST_F(TestAssociations, addPendingAssocsNewEndpoints)
360{
361 AssociationMaps assocMaps;
362
Brad Bishopa098a372022-05-05 15:19:04 -0400363 addPendingAssociation(defaultSourcePath, "inventory", defaultEndpoint,
364 "error", defaultDbusSvc, assocMaps);
Matt Spinler9f1adbc2019-04-08 10:47:19 -0500365
366 EXPECT_EQ(assocMaps.pending.size(), 1);
367
Brad Bishopa098a372022-05-05 15:19:04 -0400368 addPendingAssociation(defaultSourcePath, "inventory", "some/other/endpoint",
369 "error", defaultDbusSvc, assocMaps);
Matt Spinler9f1adbc2019-04-08 10:47:19 -0500370
371 // Same pending path, so still just 1 entry
372 EXPECT_EQ(assocMaps.pending.size(), 1);
373
Brad Bishopa098a372022-05-05 15:19:04 -0400374 auto assoc = assocMaps.pending.find(defaultSourcePath);
Matt Spinler9f1adbc2019-04-08 10:47:19 -0500375 EXPECT_NE(assoc, assocMaps.pending.end());
376
377 auto& endpoints = assoc->second;
378 EXPECT_EQ(endpoints.size(), 2);
379}
380
381// Test adding a new owner to a pending association
382TEST_F(TestAssociations, addPendingAssocsNewOwner)
383{
384 AssociationMaps assocMaps;
385
Brad Bishopa098a372022-05-05 15:19:04 -0400386 addPendingAssociation(defaultSourcePath, "inventory", defaultEndpoint,
387 "error", defaultDbusSvc, assocMaps);
Matt Spinler9f1adbc2019-04-08 10:47:19 -0500388
389 EXPECT_EQ(assocMaps.pending.size(), 1);
390
Brad Bishopa098a372022-05-05 15:19:04 -0400391 addPendingAssociation(defaultSourcePath, "inventory", defaultEndpoint,
Matt Spinler9f1adbc2019-04-08 10:47:19 -0500392 "error", "new owner", assocMaps);
393
394 EXPECT_EQ(assocMaps.pending.size(), 1);
395
Brad Bishopa098a372022-05-05 15:19:04 -0400396 auto assoc = assocMaps.pending.find(defaultSourcePath);
Matt Spinler9f1adbc2019-04-08 10:47:19 -0500397 EXPECT_NE(assoc, assocMaps.pending.end());
398
399 auto& endpoints = assoc->second;
400 EXPECT_EQ(endpoints.size(), 2);
401}
402
403// Add a pending association inside associationChanged
404TEST_F(TestAssociations, associationChangedPending)
405{
406 std::vector<Association> associations = {
407 {"abc", "def", "/xyz/openbmc_project/new/endpoint"}};
408
409 AssociationMaps assocMaps;
Brad Bishopa098a372022-05-05 15:19:04 -0400410 InterfaceMapType interfaceMap;
Matt Spinler9f1adbc2019-04-08 10:47:19 -0500411
Kallas, Pawel5b4357d2022-10-12 15:36:37 +0200412 associationChanged(io, *server, associations, "/new/source/path",
Brad Bishopa098a372022-05-05 15:19:04 -0400413 defaultDbusSvc, interfaceMap, assocMaps);
Matt Spinler9f1adbc2019-04-08 10:47:19 -0500414
415 // No associations were actually added
416 EXPECT_EQ(assocMaps.owners.size(), 0);
417 EXPECT_EQ(assocMaps.ifaces.size(), 0);
418
419 // 1 pending association
420 EXPECT_EQ(assocMaps.pending.size(), 1);
421}
Matt Spinlercb9bcdb2019-04-08 10:58:49 -0500422
423// Test removing pending associations
424TEST_F(TestAssociations, testRemoveFromPendingAssociations)
425{
426 AssociationMaps assocMaps;
427
Brad Bishopa098a372022-05-05 15:19:04 -0400428 addPendingAssociation(defaultSourcePath, "inventory", defaultEndpoint,
429 "error", defaultDbusSvc, assocMaps);
Matt Spinlercb9bcdb2019-04-08 10:58:49 -0500430
Brad Bishopa098a372022-05-05 15:19:04 -0400431 addPendingAssociation(defaultSourcePath, "inventory", "some/other/endpoint",
432 "error", defaultDbusSvc, assocMaps);
Matt Spinlercb9bcdb2019-04-08 10:58:49 -0500433
434 EXPECT_EQ(assocMaps.pending.size(), 1);
435
436 removeFromPendingAssociations("some/other/endpoint", assocMaps);
437
438 // Still 1 pending entry, but down to 1 endpoint
439 EXPECT_EQ(assocMaps.pending.size(), 1);
440
Brad Bishopa098a372022-05-05 15:19:04 -0400441 auto assoc = assocMaps.pending.find(defaultSourcePath);
Matt Spinlercb9bcdb2019-04-08 10:58:49 -0500442 EXPECT_NE(assoc, assocMaps.pending.end());
443 auto& endpoints = assoc->second;
444 EXPECT_EQ(endpoints.size(), 1);
445
446 // Now nothing pending
Brad Bishopa098a372022-05-05 15:19:04 -0400447 removeFromPendingAssociations(defaultEndpoint, assocMaps);
Matt Spinlercb9bcdb2019-04-08 10:58:49 -0500448 EXPECT_EQ(assocMaps.pending.size(), 0);
449}
Matt Spinler11401e22019-04-08 13:13:25 -0500450
451// Test moving a pending association to a real one
452TEST_F(TestAssociations, checkIfPending)
453{
454 AssociationMaps assocMaps;
Brad Bishopa098a372022-05-05 15:19:04 -0400455 InterfaceMapType interfaceMap = {
456 {defaultSourcePath, {{defaultDbusSvc, {"a"}}}},
457 {defaultEndpoint, {{defaultDbusSvc, {"b"}}}}};
Matt Spinler11401e22019-04-08 13:13:25 -0500458
Brad Bishopa098a372022-05-05 15:19:04 -0400459 addPendingAssociation(defaultSourcePath, "inventory_cip", defaultEndpoint,
460 "error_cip", defaultDbusSvc, assocMaps);
Matt Spinler11401e22019-04-08 13:13:25 -0500461 EXPECT_EQ(assocMaps.pending.size(), 1);
462
463 // Move the pending association to a real association
Kallas, Pawel5b4357d2022-10-12 15:36:37 +0200464 checkIfPendingAssociation(io, defaultSourcePath, interfaceMap, assocMaps,
Matt Spinler11401e22019-04-08 13:13:25 -0500465 *server);
466
467 EXPECT_TRUE(assocMaps.pending.empty());
468 EXPECT_EQ(assocMaps.owners.size(), 1);
469 EXPECT_EQ(assocMaps.ifaces.size(), 2);
470
471 // This shouldn't do anything, since /new/path isn't pending
Kallas, Pawel5b4357d2022-10-12 15:36:37 +0200472 checkIfPendingAssociation(io, "/new/path", interfaceMap, assocMaps,
473 *server);
Matt Spinler11401e22019-04-08 13:13:25 -0500474 EXPECT_TRUE(assocMaps.pending.empty());
475 EXPECT_EQ(assocMaps.owners.size(), 1);
476 EXPECT_EQ(assocMaps.ifaces.size(), 2);
477}
Matt Spinler7f8fd1f2019-04-08 15:21:59 -0500478
479TEST_F(TestAssociations, findAssociations)
480{
481 std::vector<std::tuple<std::string, Association>> associationData;
482 AssociationMaps assocMaps;
483
484 assocMaps.owners = {
485 {"pathA",
486 {{"ownerA",
487 {{"pathA/typeA", {"endpointA", "endpointB"}},
488 {"endpointA/type0", {"pathA"}}}}}},
489
490 {"pathJ",
491 {{"ownerC",
492 {{"pathJ/typeA", {"endpointF"}}, {"endpointF/type0", {"pathJ"}}}}}},
493
494 {"pathX",
495 {{"ownerB",
496 {{"pathX/typeB", {"endpointA"}}, {"endpointA/type1", {"pathX"}}}}}}};
497
498 findAssociations("endpointA", assocMaps, associationData);
499 ASSERT_EQ(associationData.size(), 2);
500
501 {
Patrick Williams47b68cb2023-10-20 11:20:07 -0500502 auto ad = std::find_if(
503 associationData.begin(), associationData.end(),
504 [](const auto& ad) { return std::get<0>(ad) == "ownerA"; });
Matt Spinler7f8fd1f2019-04-08 15:21:59 -0500505 ASSERT_NE(ad, associationData.end());
506
507 auto& a = std::get<1>(*ad);
508 ASSERT_EQ(std::get<0>(a), "type0");
509 ASSERT_EQ(std::get<1>(a), "typeA");
510 ASSERT_EQ(std::get<2>(a), "pathA");
511 }
512 {
Patrick Williams47b68cb2023-10-20 11:20:07 -0500513 auto ad = std::find_if(
514 associationData.begin(), associationData.end(),
515 [](const auto& ad) { return std::get<0>(ad) == "ownerB"; });
Matt Spinler7f8fd1f2019-04-08 15:21:59 -0500516 ASSERT_NE(ad, associationData.end());
517
518 auto& a = std::get<1>(*ad);
519 ASSERT_EQ(std::get<0>(a), "type1");
520 ASSERT_EQ(std::get<1>(a), "typeB");
521 ASSERT_EQ(std::get<2>(a), "pathX");
522 }
523}
Matt Spinler9c3d2852019-04-08 15:57:19 -0500524
525TEST_F(TestAssociations, moveAssocToPendingNoOp)
526{
527 AssociationMaps assocMaps;
528
529 // Not an association, so it shouldn't do anything
Kallas, Pawel5b4357d2022-10-12 15:36:37 +0200530 moveAssociationToPending(io, defaultEndpoint, assocMaps, *server);
Matt Spinler9c3d2852019-04-08 15:57:19 -0500531
532 EXPECT_TRUE(assocMaps.pending.empty());
533 EXPECT_TRUE(assocMaps.owners.empty());
534 EXPECT_TRUE(assocMaps.ifaces.empty());
535}
536
537TEST_F(TestAssociations, moveAssocToPending)
538{
539 AssociationMaps assocMaps;
540 assocMaps.owners = createDefaultOwnerAssociation();
541 assocMaps.ifaces = createDefaultInterfaceAssociation(server);
542
Kallas, Pawel5b4357d2022-10-12 15:36:37 +0200543 moveAssociationToPending(io, defaultEndpoint, assocMaps, *server);
Matt Spinler9c3d2852019-04-08 15:57:19 -0500544
545 // Check it's now pending
546 EXPECT_EQ(assocMaps.pending.size(), 1);
Brad Bishopa098a372022-05-05 15:19:04 -0400547 EXPECT_EQ(assocMaps.pending.begin()->first, defaultEndpoint);
Matt Spinler9c3d2852019-04-08 15:57:19 -0500548
549 // No more assoc owners
550 EXPECT_TRUE(assocMaps.owners.empty());
551
552 // Check the association interfaces were removed
553 {
Brad Bishopa098a372022-05-05 15:19:04 -0400554 auto assocs = assocMaps.ifaces.find(defaultFwdPath);
Matt Spinler9c3d2852019-04-08 15:57:19 -0500555 auto& iface = std::get<ifacePos>(assocs->second);
556 auto& endpoints = std::get<endpointsPos>(assocs->second);
557
558 EXPECT_EQ(iface.get(), nullptr);
559 EXPECT_TRUE(endpoints.empty());
560 }
561 {
Brad Bishopa098a372022-05-05 15:19:04 -0400562 auto assocs = assocMaps.ifaces.find(defaultRevPath);
Matt Spinler9c3d2852019-04-08 15:57:19 -0500563 auto& iface = std::get<ifacePos>(assocs->second);
564 auto& endpoints = std::get<endpointsPos>(assocs->second);
565
566 EXPECT_EQ(iface.get(), nullptr);
567 EXPECT_TRUE(endpoints.empty());
568 }
569}