blob: 18da213041a5cf39948838dc99ee7f1c5abcc17f [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;
Brad Bishop78585a72025-07-29 15:27:08 -040016 void SetUp() override
Kallas, Pawel5b4357d2022-10-12 15:36:37 +020017 {
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{
Andrew Geissler491f9ac2019-02-22 15:23:33 -0600231 std::vector<Association> associations = {
Andrew Geisslereecc1962020-06-10 19:58:35 -0500232 {"inventory_canaeo", "error_canaeo",
Andrew Geissler491f9ac2019-02-22 15:23:33 -0600233 "/xyz/openbmc_project/inventory/system/chassis"}};
234
235 // Empty objects because this test will ensure assocOwners adds the
236 // changed association and interface
Matt Spinlere2359fb2019-04-05 14:11:33 -0500237 AssociationMaps assocMaps;
Andrew Geissler491f9ac2019-02-22 15:23:33 -0600238
Matt Spinlere0b0e3a2019-04-08 10:39:23 -0500239 // Make it look like the assoc endpoints are on D-Bus
Brad Bishopa098a372022-05-05 15:19:04 -0400240 InterfaceMapType interfaceMap = createDefaultInterfaceMap();
Matt Spinlere0b0e3a2019-04-08 10:39:23 -0500241
Kallas, Pawel5b4357d2022-10-12 15:36:37 +0200242 associationChanged(io, *server, associations, defaultSourcePath,
243 defaultDbusSvc, interfaceMap, assocMaps);
Andrew Geissler491f9ac2019-02-22 15:23:33 -0600244
245 // New associations so ensure it now contains a single entry
Matt Spinlere2359fb2019-04-05 14:11:33 -0500246 EXPECT_EQ(assocMaps.owners.size(), 1);
Andrew Geissler491f9ac2019-02-22 15:23:33 -0600247
Matt Spinlere0b0e3a2019-04-08 10:39:23 -0500248 // Nothing pending
249 EXPECT_EQ(assocMaps.pending.size(), 0);
250
Andrew Geissler491f9ac2019-02-22 15:23:33 -0600251 // Verify corresponding assoc paths each have one endpoint in assoc
252 // interfaces and that those endpoints match
Brad Bishopa098a372022-05-05 15:19:04 -0400253 auto singleOwner = assocMaps.owners[defaultSourcePath];
254 auto singleIntf = singleOwner[defaultDbusSvc];
Andrew Geissler491f9ac2019-02-22 15:23:33 -0600255 for (auto i : singleIntf)
256 {
Matt Spinlere2359fb2019-04-05 14:11:33 -0500257 auto intfEndpoints = std::get<endpointsPos>(assocMaps.ifaces[i.first]);
Andrew Geissler491f9ac2019-02-22 15:23:33 -0600258 EXPECT_EQ(intfEndpoints.size(), 1);
259 EXPECT_EQ(intfEndpoints[0], *i.second.begin());
260 }
261}
262
263// Add a new association to same source path but with new owner
264TEST_F(TestAssociations, associationChangedAddNewAssocNewOwner)
265{
266 std::string newOwner = "xyz.openbmc_project.Test2";
267 std::vector<Association> associations = {
Andrew Geisslereecc1962020-06-10 19:58:35 -0500268 {"inventory_canano", "error_canano",
Andrew Geissler491f9ac2019-02-22 15:23:33 -0600269 "/xyz/openbmc_project/inventory/system/chassis"}};
270
Matt Spinlere0b0e3a2019-04-08 10:39:23 -0500271 // Make it look like the assoc endpoints are on D-Bus
Brad Bishopa098a372022-05-05 15:19:04 -0400272 InterfaceMapType interfaceMap = createDefaultInterfaceMap();
Matt Spinlere0b0e3a2019-04-08 10:39:23 -0500273
Matt Spinlere2359fb2019-04-05 14:11:33 -0500274 AssociationMaps assocMaps;
275 assocMaps.owners = createDefaultOwnerAssociation();
276 assocMaps.ifaces = createDefaultInterfaceAssociation(server);
Andrew Geissler491f9ac2019-02-22 15:23:33 -0600277
Kallas, Pawel5b4357d2022-10-12 15:36:37 +0200278 associationChanged(io, *server, associations, defaultSourcePath, newOwner,
Matt Spinlere0b0e3a2019-04-08 10:39:23 -0500279 interfaceMap, assocMaps);
Andrew Geissler491f9ac2019-02-22 15:23:33 -0600280
281 // New endpoint so assocOwners should be same size
Matt Spinlere2359fb2019-04-05 14:11:33 -0500282 EXPECT_EQ(assocMaps.owners.size(), 1);
Andrew Geissler491f9ac2019-02-22 15:23:33 -0600283
284 // Ensure only one endpoint under first path
285 auto intfEndpoints =
Brad Bishopa098a372022-05-05 15:19:04 -0400286 std::get<endpointsPos>(assocMaps.ifaces[defaultFwdPath]);
Andrew Geissler491f9ac2019-02-22 15:23:33 -0600287 EXPECT_EQ(intfEndpoints.size(), 1);
288
289 // Ensure the 2 new association endpoints are under the new owner
Brad Bishopa098a372022-05-05 15:19:04 -0400290 auto a = assocMaps.owners.find(defaultSourcePath);
Andrew Geissler491f9ac2019-02-22 15:23:33 -0600291 auto o = a->second.find(newOwner);
292 EXPECT_EQ(o->second.size(), 2);
Matt Spinlere0b0e3a2019-04-08 10:39:23 -0500293
294 // Nothing pending
295 EXPECT_EQ(assocMaps.pending.size(), 0);
Andrew Geissler491f9ac2019-02-22 15:23:33 -0600296}
297
298// Add a new association to existing interface path
299TEST_F(TestAssociations, associationChangedAddNewAssocSameInterface)
300{
301 std::vector<Association> associations = {
302 {"abc", "error", "/xyz/openbmc_project/inventory/system/chassis"}};
303
Matt Spinlere0b0e3a2019-04-08 10:39:23 -0500304 // Make it look like the assoc endpoints are on D-Bus
Brad Bishopa098a372022-05-05 15:19:04 -0400305 InterfaceMapType interfaceMap = createDefaultInterfaceMap();
Matt Spinlere0b0e3a2019-04-08 10:39:23 -0500306
Matt Spinlere2359fb2019-04-05 14:11:33 -0500307 AssociationMaps assocMaps;
308 assocMaps.owners = createDefaultOwnerAssociation();
309 assocMaps.ifaces = createDefaultInterfaceAssociation(server);
Andrew Geissler491f9ac2019-02-22 15:23:33 -0600310
Kallas, Pawel5b4357d2022-10-12 15:36:37 +0200311 associationChanged(io, *server, associations, defaultSourcePath,
312 defaultDbusSvc, interfaceMap, assocMaps);
Andrew Geissler491f9ac2019-02-22 15:23:33 -0600313
Benjamin Fair883a8922025-01-22 22:07:23 +0000314 // Should have 2 entries in AssociationInterfaces
315 // The one missing an endpoint is not added.
316 EXPECT_EQ(assocMaps.ifaces.size(), 2);
Andrew Geissler491f9ac2019-02-22 15:23:33 -0600317
318 // Change to existing interface so it will be removed here
319 auto intfEndpoints =
Brad Bishopa098a372022-05-05 15:19:04 -0400320 std::get<endpointsPos>(assocMaps.ifaces[defaultFwdPath]);
Andrew Geissler491f9ac2019-02-22 15:23:33 -0600321 EXPECT_EQ(intfEndpoints.size(), 0);
322
323 // The new endpoint should exist though in it's place
324 intfEndpoints = std::get<endpointsPos>(
Brad Bishopa098a372022-05-05 15:19:04 -0400325 assocMaps.ifaces[defaultSourcePath + "/" + "abc"]);
Andrew Geissler491f9ac2019-02-22 15:23:33 -0600326 EXPECT_EQ(intfEndpoints.size(), 1);
327
328 // Added to an existing owner path so still 1
Matt Spinlere2359fb2019-04-05 14:11:33 -0500329 EXPECT_EQ(assocMaps.owners.size(), 1);
Matt Spinlere0b0e3a2019-04-08 10:39:23 -0500330
331 EXPECT_EQ(assocMaps.pending.size(), 0);
Andrew Geissler491f9ac2019-02-22 15:23:33 -0600332}
Matt Spinler9f1adbc2019-04-08 10:47:19 -0500333
334// Add 2 pending associations
335TEST_F(TestAssociations, addPendingAssocs)
336{
337 AssociationMaps assocMaps;
338
Brad Bishopa098a372022-05-05 15:19:04 -0400339 addPendingAssociation(defaultSourcePath, "inventory", defaultEndpoint,
340 "error", defaultDbusSvc, assocMaps);
Matt Spinler9f1adbc2019-04-08 10:47:19 -0500341
342 EXPECT_TRUE(assocMaps.ifaces.empty());
343 EXPECT_TRUE(assocMaps.owners.empty());
344
345 EXPECT_EQ(assocMaps.pending.size(), 1);
346
Brad Bishopa098a372022-05-05 15:19:04 -0400347 addPendingAssociation("some/other/path", "inventory", defaultEndpoint,
348 "error", defaultDbusSvc, assocMaps);
Matt Spinler9f1adbc2019-04-08 10:47:19 -0500349
350 EXPECT_TRUE(assocMaps.ifaces.empty());
351 EXPECT_TRUE(assocMaps.owners.empty());
352
353 EXPECT_EQ(assocMaps.pending.size(), 2);
354}
355
356// Test adding a new endpoint to a pending association
357TEST_F(TestAssociations, addPendingAssocsNewEndpoints)
358{
359 AssociationMaps assocMaps;
360
Brad Bishopa098a372022-05-05 15:19:04 -0400361 addPendingAssociation(defaultSourcePath, "inventory", defaultEndpoint,
362 "error", defaultDbusSvc, assocMaps);
Matt Spinler9f1adbc2019-04-08 10:47:19 -0500363
364 EXPECT_EQ(assocMaps.pending.size(), 1);
365
Brad Bishopa098a372022-05-05 15:19:04 -0400366 addPendingAssociation(defaultSourcePath, "inventory", "some/other/endpoint",
367 "error", defaultDbusSvc, assocMaps);
Matt Spinler9f1adbc2019-04-08 10:47:19 -0500368
369 // Same pending path, so still just 1 entry
370 EXPECT_EQ(assocMaps.pending.size(), 1);
371
Brad Bishopa098a372022-05-05 15:19:04 -0400372 auto assoc = assocMaps.pending.find(defaultSourcePath);
Matt Spinler9f1adbc2019-04-08 10:47:19 -0500373 EXPECT_NE(assoc, assocMaps.pending.end());
374
375 auto& endpoints = assoc->second;
376 EXPECT_EQ(endpoints.size(), 2);
377}
378
379// Test adding a new owner to a pending association
380TEST_F(TestAssociations, addPendingAssocsNewOwner)
381{
382 AssociationMaps assocMaps;
383
Brad Bishopa098a372022-05-05 15:19:04 -0400384 addPendingAssociation(defaultSourcePath, "inventory", defaultEndpoint,
385 "error", defaultDbusSvc, assocMaps);
Matt Spinler9f1adbc2019-04-08 10:47:19 -0500386
387 EXPECT_EQ(assocMaps.pending.size(), 1);
388
Brad Bishopa098a372022-05-05 15:19:04 -0400389 addPendingAssociation(defaultSourcePath, "inventory", defaultEndpoint,
Matt Spinler9f1adbc2019-04-08 10:47:19 -0500390 "error", "new owner", assocMaps);
391
392 EXPECT_EQ(assocMaps.pending.size(), 1);
393
Brad Bishopa098a372022-05-05 15:19:04 -0400394 auto assoc = assocMaps.pending.find(defaultSourcePath);
Matt Spinler9f1adbc2019-04-08 10:47:19 -0500395 EXPECT_NE(assoc, assocMaps.pending.end());
396
397 auto& endpoints = assoc->second;
398 EXPECT_EQ(endpoints.size(), 2);
399}
400
401// Add a pending association inside associationChanged
402TEST_F(TestAssociations, associationChangedPending)
403{
404 std::vector<Association> associations = {
405 {"abc", "def", "/xyz/openbmc_project/new/endpoint"}};
406
407 AssociationMaps assocMaps;
Brad Bishopa098a372022-05-05 15:19:04 -0400408 InterfaceMapType interfaceMap;
Matt Spinler9f1adbc2019-04-08 10:47:19 -0500409
Kallas, Pawel5b4357d2022-10-12 15:36:37 +0200410 associationChanged(io, *server, associations, "/new/source/path",
Brad Bishopa098a372022-05-05 15:19:04 -0400411 defaultDbusSvc, interfaceMap, assocMaps);
Matt Spinler9f1adbc2019-04-08 10:47:19 -0500412
413 // No associations were actually added
414 EXPECT_EQ(assocMaps.owners.size(), 0);
415 EXPECT_EQ(assocMaps.ifaces.size(), 0);
416
417 // 1 pending association
418 EXPECT_EQ(assocMaps.pending.size(), 1);
419}
Matt Spinlercb9bcdb2019-04-08 10:58:49 -0500420
421// Test removing pending associations
422TEST_F(TestAssociations, testRemoveFromPendingAssociations)
423{
424 AssociationMaps assocMaps;
425
Brad Bishopa098a372022-05-05 15:19:04 -0400426 addPendingAssociation(defaultSourcePath, "inventory", defaultEndpoint,
427 "error", defaultDbusSvc, assocMaps);
Matt Spinlercb9bcdb2019-04-08 10:58:49 -0500428
Brad Bishopa098a372022-05-05 15:19:04 -0400429 addPendingAssociation(defaultSourcePath, "inventory", "some/other/endpoint",
430 "error", defaultDbusSvc, assocMaps);
Matt Spinlercb9bcdb2019-04-08 10:58:49 -0500431
432 EXPECT_EQ(assocMaps.pending.size(), 1);
433
434 removeFromPendingAssociations("some/other/endpoint", assocMaps);
435
436 // Still 1 pending entry, but down to 1 endpoint
437 EXPECT_EQ(assocMaps.pending.size(), 1);
438
Brad Bishopa098a372022-05-05 15:19:04 -0400439 auto assoc = assocMaps.pending.find(defaultSourcePath);
Matt Spinlercb9bcdb2019-04-08 10:58:49 -0500440 EXPECT_NE(assoc, assocMaps.pending.end());
441 auto& endpoints = assoc->second;
442 EXPECT_EQ(endpoints.size(), 1);
443
444 // Now nothing pending
Brad Bishopa098a372022-05-05 15:19:04 -0400445 removeFromPendingAssociations(defaultEndpoint, assocMaps);
Matt Spinlercb9bcdb2019-04-08 10:58:49 -0500446 EXPECT_EQ(assocMaps.pending.size(), 0);
447}
Matt Spinler11401e22019-04-08 13:13:25 -0500448
449// Test moving a pending association to a real one
450TEST_F(TestAssociations, checkIfPending)
451{
452 AssociationMaps assocMaps;
Brad Bishopa098a372022-05-05 15:19:04 -0400453 InterfaceMapType interfaceMap = {
454 {defaultSourcePath, {{defaultDbusSvc, {"a"}}}},
455 {defaultEndpoint, {{defaultDbusSvc, {"b"}}}}};
Matt Spinler11401e22019-04-08 13:13:25 -0500456
Brad Bishopa098a372022-05-05 15:19:04 -0400457 addPendingAssociation(defaultSourcePath, "inventory_cip", defaultEndpoint,
458 "error_cip", defaultDbusSvc, assocMaps);
Matt Spinler11401e22019-04-08 13:13:25 -0500459 EXPECT_EQ(assocMaps.pending.size(), 1);
460
461 // Move the pending association to a real association
Kallas, Pawel5b4357d2022-10-12 15:36:37 +0200462 checkIfPendingAssociation(io, defaultSourcePath, interfaceMap, assocMaps,
Matt Spinler11401e22019-04-08 13:13:25 -0500463 *server);
464
465 EXPECT_TRUE(assocMaps.pending.empty());
466 EXPECT_EQ(assocMaps.owners.size(), 1);
467 EXPECT_EQ(assocMaps.ifaces.size(), 2);
468
469 // This shouldn't do anything, since /new/path isn't pending
Kallas, Pawel5b4357d2022-10-12 15:36:37 +0200470 checkIfPendingAssociation(io, "/new/path", interfaceMap, assocMaps,
471 *server);
Matt Spinler11401e22019-04-08 13:13:25 -0500472 EXPECT_TRUE(assocMaps.pending.empty());
473 EXPECT_EQ(assocMaps.owners.size(), 1);
474 EXPECT_EQ(assocMaps.ifaces.size(), 2);
475}
Matt Spinler7f8fd1f2019-04-08 15:21:59 -0500476
477TEST_F(TestAssociations, findAssociations)
478{
479 std::vector<std::tuple<std::string, Association>> associationData;
480 AssociationMaps assocMaps;
481
482 assocMaps.owners = {
483 {"pathA",
484 {{"ownerA",
485 {{"pathA/typeA", {"endpointA", "endpointB"}},
486 {"endpointA/type0", {"pathA"}}}}}},
487
488 {"pathJ",
489 {{"ownerC",
490 {{"pathJ/typeA", {"endpointF"}}, {"endpointF/type0", {"pathJ"}}}}}},
491
492 {"pathX",
493 {{"ownerB",
494 {{"pathX/typeB", {"endpointA"}}, {"endpointA/type1", {"pathX"}}}}}}};
495
496 findAssociations("endpointA", assocMaps, associationData);
497 ASSERT_EQ(associationData.size(), 2);
498
499 {
Brad Bishop11c0cc32025-07-08 16:04:25 -0400500 auto it = std::find_if(
Patrick Williams47b68cb2023-10-20 11:20:07 -0500501 associationData.begin(), associationData.end(),
502 [](const auto& ad) { return std::get<0>(ad) == "ownerA"; });
Brad Bishop11c0cc32025-07-08 16:04:25 -0400503 ASSERT_NE(it, associationData.end());
Matt Spinler7f8fd1f2019-04-08 15:21:59 -0500504
Brad Bishop11c0cc32025-07-08 16:04:25 -0400505 auto& a = std::get<1>(*it);
Matt Spinler7f8fd1f2019-04-08 15:21:59 -0500506 ASSERT_EQ(std::get<0>(a), "type0");
507 ASSERT_EQ(std::get<1>(a), "typeA");
508 ASSERT_EQ(std::get<2>(a), "pathA");
509 }
510 {
Brad Bishop11c0cc32025-07-08 16:04:25 -0400511 auto it = std::find_if(
Patrick Williams47b68cb2023-10-20 11:20:07 -0500512 associationData.begin(), associationData.end(),
513 [](const auto& ad) { return std::get<0>(ad) == "ownerB"; });
Brad Bishop11c0cc32025-07-08 16:04:25 -0400514 ASSERT_NE(it, associationData.end());
Matt Spinler7f8fd1f2019-04-08 15:21:59 -0500515
Brad Bishop11c0cc32025-07-08 16:04:25 -0400516 auto& a = std::get<1>(*it);
Matt Spinler7f8fd1f2019-04-08 15:21:59 -0500517 ASSERT_EQ(std::get<0>(a), "type1");
518 ASSERT_EQ(std::get<1>(a), "typeB");
519 ASSERT_EQ(std::get<2>(a), "pathX");
520 }
521}
Matt Spinler9c3d2852019-04-08 15:57:19 -0500522
523TEST_F(TestAssociations, moveAssocToPendingNoOp)
524{
525 AssociationMaps assocMaps;
526
527 // Not an association, so it shouldn't do anything
Kallas, Pawel5b4357d2022-10-12 15:36:37 +0200528 moveAssociationToPending(io, defaultEndpoint, assocMaps, *server);
Matt Spinler9c3d2852019-04-08 15:57:19 -0500529
530 EXPECT_TRUE(assocMaps.pending.empty());
531 EXPECT_TRUE(assocMaps.owners.empty());
532 EXPECT_TRUE(assocMaps.ifaces.empty());
533}
534
535TEST_F(TestAssociations, moveAssocToPending)
536{
537 AssociationMaps assocMaps;
538 assocMaps.owners = createDefaultOwnerAssociation();
539 assocMaps.ifaces = createDefaultInterfaceAssociation(server);
540
Kallas, Pawel5b4357d2022-10-12 15:36:37 +0200541 moveAssociationToPending(io, defaultEndpoint, assocMaps, *server);
Matt Spinler9c3d2852019-04-08 15:57:19 -0500542
543 // Check it's now pending
544 EXPECT_EQ(assocMaps.pending.size(), 1);
Brad Bishopa098a372022-05-05 15:19:04 -0400545 EXPECT_EQ(assocMaps.pending.begin()->first, defaultEndpoint);
Matt Spinler9c3d2852019-04-08 15:57:19 -0500546
547 // No more assoc owners
548 EXPECT_TRUE(assocMaps.owners.empty());
549
550 // Check the association interfaces were removed
551 {
Brad Bishopa098a372022-05-05 15:19:04 -0400552 auto assocs = assocMaps.ifaces.find(defaultFwdPath);
Matt Spinler9c3d2852019-04-08 15:57:19 -0500553 auto& iface = std::get<ifacePos>(assocs->second);
554 auto& endpoints = std::get<endpointsPos>(assocs->second);
555
556 EXPECT_EQ(iface.get(), nullptr);
557 EXPECT_TRUE(endpoints.empty());
558 }
559 {
Brad Bishopa098a372022-05-05 15:19:04 -0400560 auto assocs = assocMaps.ifaces.find(defaultRevPath);
Matt Spinler9c3d2852019-04-08 15:57:19 -0500561 auto& iface = std::get<ifacePos>(assocs->second);
562 auto& endpoints = std::get<endpointsPos>(assocs->second);
563
564 EXPECT_EQ(iface.get(), nullptr);
565 EXPECT_TRUE(endpoints.empty());
566 }
567}