xref: /openbmc/phosphor-objmgr/src/test/associations.cpp (revision 883a8929e3fba37460895d41435b9ae286c5406c)
1271b7dd0SAndrew Geissler #include "src/associations.hpp"
2271b7dd0SAndrew Geissler 
3b04f0335SAndrew Geissler #include "src/test/util/asio_server_class.hpp"
4bb7b592eSAndrew Geissler #include "src/test/util/association_objects.hpp"
5491f9ac3SAndrew Geissler #include "src/test/util/debug_output.hpp"
6b04f0335SAndrew Geissler 
7271b7dd0SAndrew Geissler #include <sdbusplus/asio/connection.hpp>
8271b7dd0SAndrew Geissler #include <sdbusplus/asio/object_server.hpp>
9271b7dd0SAndrew Geissler 
10271b7dd0SAndrew Geissler #include <gtest/gtest.h>
11271b7dd0SAndrew Geissler 
12b04f0335SAndrew Geissler class TestAssociations : public AsioServerClassTest
135b4357daSKallas, Pawel {
145b4357daSKallas, Pawel   public:
155b4357daSKallas, Pawel     boost::asio::io_context io;
SetUp()165b4357daSKallas, Pawel     virtual void SetUp()
175b4357daSKallas, Pawel     {
185b4357daSKallas, Pawel         io.run();
195b4357daSKallas, Pawel     }
205b4357daSKallas, Pawel };
21b04f0335SAndrew Geissler sdbusplus::asio::object_server* TestAssociations::AsioServerClassTest::server =
22b04f0335SAndrew Geissler     nullptr;
23271b7dd0SAndrew Geissler 
24271b7dd0SAndrew Geissler // Verify call when path is not in associated owners
TEST_F(TestAssociations,SourcePathNotInAssociations)25271b7dd0SAndrew Geissler TEST_F(TestAssociations, SourcePathNotInAssociations)
26271b7dd0SAndrew Geissler {
27271b7dd0SAndrew Geissler     EXPECT_NE(nullptr, server);
28271b7dd0SAndrew Geissler     std::string sourcePath = "/xyz/openbmc_project/no/association";
29e2359fb7SMatt Spinler     AssociationMaps assocMaps;
30271b7dd0SAndrew Geissler 
315b4357daSKallas, Pawel     removeAssociation(io, sourcePath, defaultDbusSvc, *server, assocMaps);
32271b7dd0SAndrew Geissler }
33271b7dd0SAndrew Geissler 
34271b7dd0SAndrew Geissler // Verify call when owner is not in associated owners
TEST_F(TestAssociations,OwnerNotInAssociations)35271b7dd0SAndrew Geissler TEST_F(TestAssociations, OwnerNotInAssociations)
36271b7dd0SAndrew Geissler {
37e2359fb7SMatt Spinler     AssociationMaps assocMaps;
38e2359fb7SMatt Spinler     assocMaps.owners = createDefaultOwnerAssociation();
39271b7dd0SAndrew Geissler 
405b4357daSKallas, Pawel     removeAssociation(io, defaultSourcePath, defaultDbusSvc, *server,
415b4357daSKallas, Pawel                       assocMaps);
42271b7dd0SAndrew Geissler }
43271b7dd0SAndrew Geissler 
44271b7dd0SAndrew Geissler // Verify call when path is not in associated interfaces
TEST_F(TestAssociations,PathNotInAssocInterfaces)45271b7dd0SAndrew Geissler TEST_F(TestAssociations, PathNotInAssocInterfaces)
46271b7dd0SAndrew Geissler {
47e2359fb7SMatt Spinler     AssociationMaps assocMaps;
48271b7dd0SAndrew Geissler 
49e2359fb7SMatt Spinler     assocMaps.owners = createDefaultOwnerAssociation();
50271b7dd0SAndrew Geissler 
515b4357daSKallas, Pawel     removeAssociation(io, defaultSourcePath, defaultDbusSvc, *server,
525b4357daSKallas, Pawel                       assocMaps);
53271b7dd0SAndrew Geissler 
54e2359fb7SMatt Spinler     EXPECT_TRUE(assocMaps.owners.empty());
55271b7dd0SAndrew Geissler }
56271b7dd0SAndrew Geissler 
57271b7dd0SAndrew Geissler // Verify call when path is in associated interfaces
TEST_F(TestAssociations,PathIsInAssociatedInterfaces)58271b7dd0SAndrew Geissler TEST_F(TestAssociations, PathIsInAssociatedInterfaces)
59271b7dd0SAndrew Geissler {
60271b7dd0SAndrew Geissler     // Build up these objects so that an associated interface will match
61271b7dd0SAndrew Geissler     // with the associated owner being removed
62e2359fb7SMatt Spinler     AssociationMaps assocMaps;
63e2359fb7SMatt Spinler     assocMaps.owners = createDefaultOwnerAssociation();
64e2359fb7SMatt Spinler     assocMaps.ifaces = createDefaultInterfaceAssociation(server);
65271b7dd0SAndrew Geissler 
665b4357daSKallas, Pawel     removeAssociation(io, defaultSourcePath, defaultDbusSvc, *server,
675b4357daSKallas, Pawel                       assocMaps);
68271b7dd0SAndrew Geissler 
69271b7dd0SAndrew Geissler     // Verify owner association was deleted
70e2359fb7SMatt Spinler     EXPECT_TRUE(assocMaps.owners.empty());
71271b7dd0SAndrew Geissler 
72271b7dd0SAndrew Geissler     // Verify endpoint was deleted from interface association
73271b7dd0SAndrew Geissler     auto intfEndpoints =
74a098a37aSBrad Bishop         std::get<endpointsPos>(assocMaps.ifaces[defaultFwdPath]);
75271b7dd0SAndrew Geissler     EXPECT_EQ(intfEndpoints.size(), 0);
76a098a37aSBrad Bishop     intfEndpoints = std::get<endpointsPos>(assocMaps.ifaces[defaultRevPath]);
77271b7dd0SAndrew Geissler     EXPECT_EQ(intfEndpoints.size(), 0);
78271b7dd0SAndrew Geissler }
79271b7dd0SAndrew Geissler 
80271b7dd0SAndrew Geissler // Verify call when path is in associated interfaces, with extra endpoints
TEST_F(TestAssociations,PathIsInAssociatedInterfacesExtraEndpoints)81271b7dd0SAndrew Geissler TEST_F(TestAssociations, PathIsInAssociatedInterfacesExtraEndpoints)
82271b7dd0SAndrew Geissler {
83271b7dd0SAndrew Geissler     // Build up these objects so that an associated interface will match
84271b7dd0SAndrew Geissler     // with the associated owner being removed
85e2359fb7SMatt Spinler     AssociationMaps assocMaps;
86e2359fb7SMatt Spinler     assocMaps.owners = createDefaultOwnerAssociation();
87e2359fb7SMatt Spinler     assocMaps.ifaces = createDefaultInterfaceAssociation(server);
88271b7dd0SAndrew Geissler 
89271b7dd0SAndrew Geissler     // Add another endpoint to the assoc interfaces
90e2359fb7SMatt Spinler     addEndpointToInterfaceAssociation(assocMaps.ifaces);
91271b7dd0SAndrew Geissler 
925b4357daSKallas, Pawel     removeAssociation(io, defaultSourcePath, defaultDbusSvc, *server,
935b4357daSKallas, Pawel                       assocMaps);
94271b7dd0SAndrew Geissler 
95271b7dd0SAndrew Geissler     // Verify owner association was deleted
96e2359fb7SMatt Spinler     EXPECT_TRUE(assocMaps.owners.empty());
97271b7dd0SAndrew Geissler 
98271b7dd0SAndrew Geissler     // Verify all endpoints are deleted since source path was deleted
99271b7dd0SAndrew Geissler     auto intfEndpoints =
100a098a37aSBrad Bishop         std::get<endpointsPos>(assocMaps.ifaces[defaultFwdPath]);
101271b7dd0SAndrew Geissler     EXPECT_EQ(intfEndpoints.size(), 0);
102a098a37aSBrad Bishop     intfEndpoints = std::get<endpointsPos>(assocMaps.ifaces[defaultRevPath]);
103271b7dd0SAndrew Geissler     EXPECT_EQ(intfEndpoints.size(), 0);
104271b7dd0SAndrew Geissler }
105e4ab6c90SAndrew Geissler 
106e4ab6c90SAndrew Geissler // Verify no associations or endpoints removed when the change is identical
TEST_F(TestAssociations,checkAssociationEndpointRemovesNoEpRemove)107e4ab6c90SAndrew Geissler TEST_F(TestAssociations, checkAssociationEndpointRemovesNoEpRemove)
108e4ab6c90SAndrew Geissler {
109a098a37aSBrad Bishop     AssociationPaths newAssocPaths = {{defaultFwdPath, {defaultEndpoint}},
110a098a37aSBrad Bishop                                       {defaultRevPath, {defaultSourcePath}}};
111e4ab6c90SAndrew Geissler 
112e2359fb7SMatt Spinler     AssociationMaps assocMaps;
113e2359fb7SMatt Spinler     assocMaps.owners = createDefaultOwnerAssociation();
114e2359fb7SMatt Spinler     assocMaps.ifaces = createDefaultInterfaceAssociation(server);
115e4ab6c90SAndrew Geissler 
1165b4357daSKallas, Pawel     checkAssociationEndpointRemoves(io, defaultSourcePath, defaultDbusSvc,
117e2359fb7SMatt Spinler                                     newAssocPaths, *server, assocMaps);
118e4ab6c90SAndrew Geissler 
119e4ab6c90SAndrew Geissler     // Verify endpoints were not deleted because they matche with what was
120e4ab6c90SAndrew Geissler     // in the original
121e4ab6c90SAndrew Geissler     auto intfEndpoints =
122a098a37aSBrad Bishop         std::get<endpointsPos>(assocMaps.ifaces[defaultFwdPath]);
123e4ab6c90SAndrew Geissler     EXPECT_EQ(intfEndpoints.size(), 1);
124a098a37aSBrad Bishop     intfEndpoints = std::get<endpointsPos>(assocMaps.ifaces[defaultRevPath]);
125e4ab6c90SAndrew Geissler     EXPECT_EQ(intfEndpoints.size(), 1);
126e4ab6c90SAndrew Geissler }
127e4ab6c90SAndrew Geissler 
128e4ab6c90SAndrew Geissler // Verify endpoint is removed when assoc path is different
TEST_F(TestAssociations,checkAssociationEndpointRemovesEpRemoveApDiff)129e4ab6c90SAndrew Geissler TEST_F(TestAssociations, checkAssociationEndpointRemovesEpRemoveApDiff)
130e4ab6c90SAndrew Geissler {
131a098a37aSBrad Bishop     AssociationPaths newAssocPaths = {{"/different/path", {defaultEndpoint}}};
132e4ab6c90SAndrew Geissler 
133e2359fb7SMatt Spinler     AssociationMaps assocMaps;
134e2359fb7SMatt Spinler     assocMaps.owners = createDefaultOwnerAssociation();
135e2359fb7SMatt Spinler     assocMaps.ifaces = createDefaultInterfaceAssociation(server);
136e4ab6c90SAndrew Geissler 
1375b4357daSKallas, Pawel     checkAssociationEndpointRemoves(io, defaultSourcePath, defaultDbusSvc,
138e2359fb7SMatt Spinler                                     newAssocPaths, *server, assocMaps);
139e4ab6c90SAndrew Geissler 
140e4ab6c90SAndrew Geissler     // Verify initial endpoints were deleted because the new path
141e4ab6c90SAndrew Geissler     auto intfEndpoints =
142a098a37aSBrad Bishop         std::get<endpointsPos>(assocMaps.ifaces[defaultFwdPath]);
143e4ab6c90SAndrew Geissler     EXPECT_EQ(intfEndpoints.size(), 0);
144a098a37aSBrad Bishop     intfEndpoints = std::get<endpointsPos>(assocMaps.ifaces[defaultRevPath]);
145e4ab6c90SAndrew Geissler     EXPECT_EQ(intfEndpoints.size(), 0);
146e4ab6c90SAndrew Geissler }
147e4ab6c90SAndrew Geissler 
148e4ab6c90SAndrew Geissler // Verify endpoint is removed when endpoint is different
TEST_F(TestAssociations,checkAssociationEndpointRemovesEpRemoveEpChanged)149e4ab6c90SAndrew Geissler TEST_F(TestAssociations, checkAssociationEndpointRemovesEpRemoveEpChanged)
150e4ab6c90SAndrew Geissler {
151e4ab6c90SAndrew Geissler     AssociationPaths newAssocPaths = {
152a098a37aSBrad Bishop         {defaultFwdPath, {defaultEndpoint + "/different"}},
153a098a37aSBrad Bishop         {defaultRevPath, {defaultSourcePath + "/different"}}};
154e4ab6c90SAndrew Geissler 
155e2359fb7SMatt Spinler     AssociationMaps assocMaps;
156e2359fb7SMatt Spinler     assocMaps.owners = createDefaultOwnerAssociation();
157e2359fb7SMatt Spinler     assocMaps.ifaces = createDefaultInterfaceAssociation(server);
158e4ab6c90SAndrew Geissler 
1595b4357daSKallas, Pawel     checkAssociationEndpointRemoves(io, defaultSourcePath, defaultDbusSvc,
160e2359fb7SMatt Spinler                                     newAssocPaths, *server, assocMaps);
161e4ab6c90SAndrew Geissler 
162e4ab6c90SAndrew Geissler     // Verify initial endpoints were deleted because of different endpoints
163e4ab6c90SAndrew Geissler     auto intfEndpoints =
164a098a37aSBrad Bishop         std::get<endpointsPos>(assocMaps.ifaces[defaultFwdPath]);
165e4ab6c90SAndrew Geissler     EXPECT_EQ(intfEndpoints.size(), 0);
166a098a37aSBrad Bishop     intfEndpoints = std::get<endpointsPos>(assocMaps.ifaces[defaultRevPath]);
167e4ab6c90SAndrew Geissler     EXPECT_EQ(intfEndpoints.size(), 0);
168e4ab6c90SAndrew Geissler }
169491f9ac3SAndrew Geissler 
170491f9ac3SAndrew Geissler // Verify existing endpoint deleted when empty endpoint is provided
TEST_F(TestAssociations,associationChangedEmptyEndpoint)171491f9ac3SAndrew Geissler TEST_F(TestAssociations, associationChangedEmptyEndpoint)
172491f9ac3SAndrew Geissler {
173eecc196bSAndrew Geissler     std::vector<Association> associations = {
174eecc196bSAndrew Geissler         {"inventory_cee", "error_cee", ""}};
175a098a37aSBrad Bishop     InterfaceMapType interfaceMap;
176491f9ac3SAndrew Geissler 
177e2359fb7SMatt Spinler     AssociationMaps assocMaps;
178e2359fb7SMatt Spinler     assocMaps.owners = createDefaultOwnerAssociation();
179e2359fb7SMatt Spinler     assocMaps.ifaces = createDefaultInterfaceAssociation(server);
180491f9ac3SAndrew Geissler 
181491f9ac3SAndrew Geissler     // Empty endpoint will result in deletion of corresponding assocInterface
1825b4357daSKallas, Pawel     associationChanged(io, *server, associations, defaultSourcePath,
1835b4357daSKallas, Pawel                        defaultDbusSvc, interfaceMap, assocMaps);
184491f9ac3SAndrew Geissler 
1850a560a5cSAndrew Geissler     // Both of these should be 0 since we have an invalid endpoint
186491f9ac3SAndrew Geissler     auto intfEndpoints =
187a098a37aSBrad Bishop         std::get<endpointsPos>(assocMaps.ifaces[defaultFwdPath]);
1880a560a5cSAndrew Geissler     EXPECT_EQ(intfEndpoints.size(), 0);
189a098a37aSBrad Bishop     intfEndpoints = std::get<endpointsPos>(assocMaps.ifaces[defaultRevPath]);
190491f9ac3SAndrew Geissler     EXPECT_EQ(intfEndpoints.size(), 0);
191e0b0e3a2SMatt Spinler 
192e0b0e3a2SMatt Spinler     EXPECT_EQ(assocMaps.pending.size(), 0);
193491f9ac3SAndrew Geissler }
194491f9ac3SAndrew Geissler 
195491f9ac3SAndrew Geissler // Add a new association with endpoint
TEST_F(TestAssociations,associationChangedAddNewAssoc)196491f9ac3SAndrew Geissler TEST_F(TestAssociations, associationChangedAddNewAssoc)
197491f9ac3SAndrew Geissler {
198491f9ac3SAndrew Geissler     std::vector<Association> associations = {
199491f9ac3SAndrew Geissler         {"abc", "def", "/xyz/openbmc_project/new/endpoint"}};
200491f9ac3SAndrew Geissler 
201e2359fb7SMatt Spinler     AssociationMaps assocMaps;
202e2359fb7SMatt Spinler     assocMaps.owners = createDefaultOwnerAssociation();
203e2359fb7SMatt Spinler     assocMaps.ifaces = createDefaultInterfaceAssociation(server);
204491f9ac3SAndrew Geissler 
205e0b0e3a2SMatt Spinler     // Make it look like the assoc endpoints are on D-Bus
206a098a37aSBrad Bishop     InterfaceMapType interfaceMap = {
207a098a37aSBrad Bishop         {"/new/source/path", {{defaultDbusSvc, {"a"}}}},
208a098a37aSBrad Bishop         {"/xyz/openbmc_project/new/endpoint", {{defaultDbusSvc, {"a"}}}}};
209e0b0e3a2SMatt Spinler 
2105b4357daSKallas, Pawel     associationChanged(io, *server, associations, "/new/source/path",
211a098a37aSBrad Bishop                        defaultDbusSvc, interfaceMap, assocMaps);
212491f9ac3SAndrew Geissler 
213491f9ac3SAndrew Geissler     // Two source paths
214e2359fb7SMatt Spinler     EXPECT_EQ(assocMaps.owners.size(), 2);
215491f9ac3SAndrew Geissler 
216491f9ac3SAndrew Geissler     // Four interfaces
217e2359fb7SMatt Spinler     EXPECT_EQ(assocMaps.ifaces.size(), 4);
218491f9ac3SAndrew Geissler 
219e0b0e3a2SMatt Spinler     // Nothing pending
220e0b0e3a2SMatt Spinler     EXPECT_EQ(assocMaps.pending.size(), 0);
221e0b0e3a2SMatt Spinler 
222e2359fb7SMatt Spinler     // New endpoint so assocMaps.ifaces should be same size
223491f9ac3SAndrew Geissler     auto intfEndpoints =
224a098a37aSBrad Bishop         std::get<endpointsPos>(assocMaps.ifaces[defaultFwdPath]);
225491f9ac3SAndrew Geissler     EXPECT_EQ(intfEndpoints.size(), 1);
226491f9ac3SAndrew Geissler }
227491f9ac3SAndrew Geissler 
228491f9ac3SAndrew Geissler // Add a new association to empty objects
TEST_F(TestAssociations,associationChangedAddNewAssocEmptyObj)229491f9ac3SAndrew Geissler TEST_F(TestAssociations, associationChangedAddNewAssocEmptyObj)
230491f9ac3SAndrew Geissler {
231491f9ac3SAndrew Geissler     std::string sourcePath = "/logging/entry/1";
232491f9ac3SAndrew Geissler     std::string owner = "xyz.openbmc_project.Test";
233491f9ac3SAndrew Geissler     std::vector<Association> associations = {
234eecc196bSAndrew Geissler         {"inventory_canaeo", "error_canaeo",
235491f9ac3SAndrew Geissler          "/xyz/openbmc_project/inventory/system/chassis"}};
236491f9ac3SAndrew Geissler 
237491f9ac3SAndrew Geissler     // Empty objects because this test will ensure assocOwners adds the
238491f9ac3SAndrew Geissler     // changed association and interface
239e2359fb7SMatt Spinler     AssociationMaps assocMaps;
240491f9ac3SAndrew Geissler 
241e0b0e3a2SMatt Spinler     // Make it look like the assoc endpoints are on D-Bus
242a098a37aSBrad Bishop     InterfaceMapType interfaceMap = createDefaultInterfaceMap();
243e0b0e3a2SMatt Spinler 
2445b4357daSKallas, Pawel     associationChanged(io, *server, associations, defaultSourcePath,
2455b4357daSKallas, Pawel                        defaultDbusSvc, interfaceMap, assocMaps);
246491f9ac3SAndrew Geissler 
247491f9ac3SAndrew Geissler     // New associations so ensure it now contains a single entry
248e2359fb7SMatt Spinler     EXPECT_EQ(assocMaps.owners.size(), 1);
249491f9ac3SAndrew Geissler 
250e0b0e3a2SMatt Spinler     // Nothing pending
251e0b0e3a2SMatt Spinler     EXPECT_EQ(assocMaps.pending.size(), 0);
252e0b0e3a2SMatt Spinler 
253491f9ac3SAndrew Geissler     // Verify corresponding assoc paths each have one endpoint in assoc
254491f9ac3SAndrew Geissler     // interfaces and that those endpoints match
255a098a37aSBrad Bishop     auto singleOwner = assocMaps.owners[defaultSourcePath];
256a098a37aSBrad Bishop     auto singleIntf = singleOwner[defaultDbusSvc];
257491f9ac3SAndrew Geissler     for (auto i : singleIntf)
258491f9ac3SAndrew Geissler     {
259e2359fb7SMatt Spinler         auto intfEndpoints = std::get<endpointsPos>(assocMaps.ifaces[i.first]);
260491f9ac3SAndrew Geissler         EXPECT_EQ(intfEndpoints.size(), 1);
261491f9ac3SAndrew Geissler         EXPECT_EQ(intfEndpoints[0], *i.second.begin());
262491f9ac3SAndrew Geissler     }
263491f9ac3SAndrew Geissler }
264491f9ac3SAndrew Geissler 
265491f9ac3SAndrew Geissler // Add a new association to same source path but with new owner
TEST_F(TestAssociations,associationChangedAddNewAssocNewOwner)266491f9ac3SAndrew Geissler TEST_F(TestAssociations, associationChangedAddNewAssocNewOwner)
267491f9ac3SAndrew Geissler {
268491f9ac3SAndrew Geissler     std::string newOwner = "xyz.openbmc_project.Test2";
269491f9ac3SAndrew Geissler     std::vector<Association> associations = {
270eecc196bSAndrew Geissler         {"inventory_canano", "error_canano",
271491f9ac3SAndrew Geissler          "/xyz/openbmc_project/inventory/system/chassis"}};
272491f9ac3SAndrew Geissler 
273e0b0e3a2SMatt Spinler     // Make it look like the assoc endpoints are on D-Bus
274a098a37aSBrad Bishop     InterfaceMapType interfaceMap = createDefaultInterfaceMap();
275e0b0e3a2SMatt Spinler 
276e2359fb7SMatt Spinler     AssociationMaps assocMaps;
277e2359fb7SMatt Spinler     assocMaps.owners = createDefaultOwnerAssociation();
278e2359fb7SMatt Spinler     assocMaps.ifaces = createDefaultInterfaceAssociation(server);
279491f9ac3SAndrew Geissler 
2805b4357daSKallas, Pawel     associationChanged(io, *server, associations, defaultSourcePath, newOwner,
281e0b0e3a2SMatt Spinler                        interfaceMap, assocMaps);
282491f9ac3SAndrew Geissler 
283491f9ac3SAndrew Geissler     // New endpoint so assocOwners should be same size
284e2359fb7SMatt Spinler     EXPECT_EQ(assocMaps.owners.size(), 1);
285491f9ac3SAndrew Geissler 
286491f9ac3SAndrew Geissler     // Ensure only one endpoint under first path
287491f9ac3SAndrew Geissler     auto intfEndpoints =
288a098a37aSBrad Bishop         std::get<endpointsPos>(assocMaps.ifaces[defaultFwdPath]);
289491f9ac3SAndrew Geissler     EXPECT_EQ(intfEndpoints.size(), 1);
290491f9ac3SAndrew Geissler 
291491f9ac3SAndrew Geissler     // Ensure the 2 new association endpoints are under the new owner
292a098a37aSBrad Bishop     auto a = assocMaps.owners.find(defaultSourcePath);
293491f9ac3SAndrew Geissler     auto o = a->second.find(newOwner);
294491f9ac3SAndrew Geissler     EXPECT_EQ(o->second.size(), 2);
295e0b0e3a2SMatt Spinler 
296e0b0e3a2SMatt Spinler     // Nothing pending
297e0b0e3a2SMatt Spinler     EXPECT_EQ(assocMaps.pending.size(), 0);
298491f9ac3SAndrew Geissler }
299491f9ac3SAndrew Geissler 
300491f9ac3SAndrew Geissler // Add a new association to existing interface path
TEST_F(TestAssociations,associationChangedAddNewAssocSameInterface)301491f9ac3SAndrew Geissler TEST_F(TestAssociations, associationChangedAddNewAssocSameInterface)
302491f9ac3SAndrew Geissler {
303491f9ac3SAndrew Geissler     std::vector<Association> associations = {
304491f9ac3SAndrew Geissler         {"abc", "error", "/xyz/openbmc_project/inventory/system/chassis"}};
305491f9ac3SAndrew Geissler 
306e0b0e3a2SMatt Spinler     // Make it look like the assoc endpoints are on D-Bus
307a098a37aSBrad Bishop     InterfaceMapType interfaceMap = createDefaultInterfaceMap();
308e0b0e3a2SMatt Spinler 
309e2359fb7SMatt Spinler     AssociationMaps assocMaps;
310e2359fb7SMatt Spinler     assocMaps.owners = createDefaultOwnerAssociation();
311e2359fb7SMatt Spinler     assocMaps.ifaces = createDefaultInterfaceAssociation(server);
312491f9ac3SAndrew Geissler 
3135b4357daSKallas, Pawel     associationChanged(io, *server, associations, defaultSourcePath,
3145b4357daSKallas, Pawel                        defaultDbusSvc, interfaceMap, assocMaps);
315491f9ac3SAndrew Geissler 
316*883a8929SBenjamin Fair     // Should have 2 entries in AssociationInterfaces
317*883a8929SBenjamin Fair     // The one missing an endpoint is not added.
318*883a8929SBenjamin Fair     EXPECT_EQ(assocMaps.ifaces.size(), 2);
319491f9ac3SAndrew Geissler 
320491f9ac3SAndrew Geissler     // Change to existing interface so it will be removed here
321491f9ac3SAndrew Geissler     auto intfEndpoints =
322a098a37aSBrad Bishop         std::get<endpointsPos>(assocMaps.ifaces[defaultFwdPath]);
323491f9ac3SAndrew Geissler     EXPECT_EQ(intfEndpoints.size(), 0);
324491f9ac3SAndrew Geissler 
325491f9ac3SAndrew Geissler     // The new endpoint should exist though in it's place
326491f9ac3SAndrew Geissler     intfEndpoints = std::get<endpointsPos>(
327a098a37aSBrad Bishop         assocMaps.ifaces[defaultSourcePath + "/" + "abc"]);
328491f9ac3SAndrew Geissler     EXPECT_EQ(intfEndpoints.size(), 1);
329491f9ac3SAndrew Geissler 
330491f9ac3SAndrew Geissler     // Added to an existing owner path so still 1
331e2359fb7SMatt Spinler     EXPECT_EQ(assocMaps.owners.size(), 1);
332e0b0e3a2SMatt Spinler 
333e0b0e3a2SMatt Spinler     EXPECT_EQ(assocMaps.pending.size(), 0);
334491f9ac3SAndrew Geissler }
3359f1adbc3SMatt Spinler 
3369f1adbc3SMatt Spinler // Add 2 pending associations
TEST_F(TestAssociations,addPendingAssocs)3379f1adbc3SMatt Spinler TEST_F(TestAssociations, addPendingAssocs)
3389f1adbc3SMatt Spinler {
3399f1adbc3SMatt Spinler     AssociationMaps assocMaps;
3409f1adbc3SMatt Spinler 
341a098a37aSBrad Bishop     addPendingAssociation(defaultSourcePath, "inventory", defaultEndpoint,
342a098a37aSBrad Bishop                           "error", defaultDbusSvc, assocMaps);
3439f1adbc3SMatt Spinler 
3449f1adbc3SMatt Spinler     EXPECT_TRUE(assocMaps.ifaces.empty());
3459f1adbc3SMatt Spinler     EXPECT_TRUE(assocMaps.owners.empty());
3469f1adbc3SMatt Spinler 
3479f1adbc3SMatt Spinler     EXPECT_EQ(assocMaps.pending.size(), 1);
3489f1adbc3SMatt Spinler 
349a098a37aSBrad Bishop     addPendingAssociation("some/other/path", "inventory", defaultEndpoint,
350a098a37aSBrad Bishop                           "error", defaultDbusSvc, assocMaps);
3519f1adbc3SMatt Spinler 
3529f1adbc3SMatt Spinler     EXPECT_TRUE(assocMaps.ifaces.empty());
3539f1adbc3SMatt Spinler     EXPECT_TRUE(assocMaps.owners.empty());
3549f1adbc3SMatt Spinler 
3559f1adbc3SMatt Spinler     EXPECT_EQ(assocMaps.pending.size(), 2);
3569f1adbc3SMatt Spinler }
3579f1adbc3SMatt Spinler 
3589f1adbc3SMatt Spinler // Test adding a new endpoint to a pending association
TEST_F(TestAssociations,addPendingAssocsNewEndpoints)3599f1adbc3SMatt Spinler TEST_F(TestAssociations, addPendingAssocsNewEndpoints)
3609f1adbc3SMatt Spinler {
3619f1adbc3SMatt Spinler     AssociationMaps assocMaps;
3629f1adbc3SMatt Spinler 
363a098a37aSBrad Bishop     addPendingAssociation(defaultSourcePath, "inventory", defaultEndpoint,
364a098a37aSBrad Bishop                           "error", defaultDbusSvc, assocMaps);
3659f1adbc3SMatt Spinler 
3669f1adbc3SMatt Spinler     EXPECT_EQ(assocMaps.pending.size(), 1);
3679f1adbc3SMatt Spinler 
368a098a37aSBrad Bishop     addPendingAssociation(defaultSourcePath, "inventory", "some/other/endpoint",
369a098a37aSBrad Bishop                           "error", defaultDbusSvc, assocMaps);
3709f1adbc3SMatt Spinler 
3719f1adbc3SMatt Spinler     // Same pending path, so still just 1 entry
3729f1adbc3SMatt Spinler     EXPECT_EQ(assocMaps.pending.size(), 1);
3739f1adbc3SMatt Spinler 
374a098a37aSBrad Bishop     auto assoc = assocMaps.pending.find(defaultSourcePath);
3759f1adbc3SMatt Spinler     EXPECT_NE(assoc, assocMaps.pending.end());
3769f1adbc3SMatt Spinler 
3779f1adbc3SMatt Spinler     auto& endpoints = assoc->second;
3789f1adbc3SMatt Spinler     EXPECT_EQ(endpoints.size(), 2);
3799f1adbc3SMatt Spinler }
3809f1adbc3SMatt Spinler 
3819f1adbc3SMatt Spinler // Test adding a new owner to a pending association
TEST_F(TestAssociations,addPendingAssocsNewOwner)3829f1adbc3SMatt Spinler TEST_F(TestAssociations, addPendingAssocsNewOwner)
3839f1adbc3SMatt Spinler {
3849f1adbc3SMatt Spinler     AssociationMaps assocMaps;
3859f1adbc3SMatt Spinler 
386a098a37aSBrad Bishop     addPendingAssociation(defaultSourcePath, "inventory", defaultEndpoint,
387a098a37aSBrad Bishop                           "error", defaultDbusSvc, assocMaps);
3889f1adbc3SMatt Spinler 
3899f1adbc3SMatt Spinler     EXPECT_EQ(assocMaps.pending.size(), 1);
3909f1adbc3SMatt Spinler 
391a098a37aSBrad Bishop     addPendingAssociation(defaultSourcePath, "inventory", defaultEndpoint,
3929f1adbc3SMatt Spinler                           "error", "new owner", assocMaps);
3939f1adbc3SMatt Spinler 
3949f1adbc3SMatt Spinler     EXPECT_EQ(assocMaps.pending.size(), 1);
3959f1adbc3SMatt Spinler 
396a098a37aSBrad Bishop     auto assoc = assocMaps.pending.find(defaultSourcePath);
3979f1adbc3SMatt Spinler     EXPECT_NE(assoc, assocMaps.pending.end());
3989f1adbc3SMatt Spinler 
3999f1adbc3SMatt Spinler     auto& endpoints = assoc->second;
4009f1adbc3SMatt Spinler     EXPECT_EQ(endpoints.size(), 2);
4019f1adbc3SMatt Spinler }
4029f1adbc3SMatt Spinler 
4039f1adbc3SMatt Spinler // Add a pending association inside associationChanged
TEST_F(TestAssociations,associationChangedPending)4049f1adbc3SMatt Spinler TEST_F(TestAssociations, associationChangedPending)
4059f1adbc3SMatt Spinler {
4069f1adbc3SMatt Spinler     std::vector<Association> associations = {
4079f1adbc3SMatt Spinler         {"abc", "def", "/xyz/openbmc_project/new/endpoint"}};
4089f1adbc3SMatt Spinler 
4099f1adbc3SMatt Spinler     AssociationMaps assocMaps;
410a098a37aSBrad Bishop     InterfaceMapType interfaceMap;
4119f1adbc3SMatt Spinler 
4125b4357daSKallas, Pawel     associationChanged(io, *server, associations, "/new/source/path",
413a098a37aSBrad Bishop                        defaultDbusSvc, interfaceMap, assocMaps);
4149f1adbc3SMatt Spinler 
4159f1adbc3SMatt Spinler     // No associations were actually added
4169f1adbc3SMatt Spinler     EXPECT_EQ(assocMaps.owners.size(), 0);
4179f1adbc3SMatt Spinler     EXPECT_EQ(assocMaps.ifaces.size(), 0);
4189f1adbc3SMatt Spinler 
4199f1adbc3SMatt Spinler     // 1 pending association
4209f1adbc3SMatt Spinler     EXPECT_EQ(assocMaps.pending.size(), 1);
4219f1adbc3SMatt Spinler }
422cb9bcdb1SMatt Spinler 
423cb9bcdb1SMatt Spinler // Test removing pending associations
TEST_F(TestAssociations,testRemoveFromPendingAssociations)424cb9bcdb1SMatt Spinler TEST_F(TestAssociations, testRemoveFromPendingAssociations)
425cb9bcdb1SMatt Spinler {
426cb9bcdb1SMatt Spinler     AssociationMaps assocMaps;
427cb9bcdb1SMatt Spinler 
428a098a37aSBrad Bishop     addPendingAssociation(defaultSourcePath, "inventory", defaultEndpoint,
429a098a37aSBrad Bishop                           "error", defaultDbusSvc, assocMaps);
430cb9bcdb1SMatt Spinler 
431a098a37aSBrad Bishop     addPendingAssociation(defaultSourcePath, "inventory", "some/other/endpoint",
432a098a37aSBrad Bishop                           "error", defaultDbusSvc, assocMaps);
433cb9bcdb1SMatt Spinler 
434cb9bcdb1SMatt Spinler     EXPECT_EQ(assocMaps.pending.size(), 1);
435cb9bcdb1SMatt Spinler 
436cb9bcdb1SMatt Spinler     removeFromPendingAssociations("some/other/endpoint", assocMaps);
437cb9bcdb1SMatt Spinler 
438cb9bcdb1SMatt Spinler     // Still 1 pending entry, but down to 1 endpoint
439cb9bcdb1SMatt Spinler     EXPECT_EQ(assocMaps.pending.size(), 1);
440cb9bcdb1SMatt Spinler 
441a098a37aSBrad Bishop     auto assoc = assocMaps.pending.find(defaultSourcePath);
442cb9bcdb1SMatt Spinler     EXPECT_NE(assoc, assocMaps.pending.end());
443cb9bcdb1SMatt Spinler     auto& endpoints = assoc->second;
444cb9bcdb1SMatt Spinler     EXPECT_EQ(endpoints.size(), 1);
445cb9bcdb1SMatt Spinler 
446cb9bcdb1SMatt Spinler     // Now nothing pending
447a098a37aSBrad Bishop     removeFromPendingAssociations(defaultEndpoint, assocMaps);
448cb9bcdb1SMatt Spinler     EXPECT_EQ(assocMaps.pending.size(), 0);
449cb9bcdb1SMatt Spinler }
45011401e2eSMatt Spinler 
45111401e2eSMatt Spinler // Test moving a pending association to a real one
TEST_F(TestAssociations,checkIfPending)45211401e2eSMatt Spinler TEST_F(TestAssociations, checkIfPending)
45311401e2eSMatt Spinler {
45411401e2eSMatt Spinler     AssociationMaps assocMaps;
455a098a37aSBrad Bishop     InterfaceMapType interfaceMap = {
456a098a37aSBrad Bishop         {defaultSourcePath, {{defaultDbusSvc, {"a"}}}},
457a098a37aSBrad Bishop         {defaultEndpoint, {{defaultDbusSvc, {"b"}}}}};
45811401e2eSMatt Spinler 
459a098a37aSBrad Bishop     addPendingAssociation(defaultSourcePath, "inventory_cip", defaultEndpoint,
460a098a37aSBrad Bishop                           "error_cip", defaultDbusSvc, assocMaps);
46111401e2eSMatt Spinler     EXPECT_EQ(assocMaps.pending.size(), 1);
46211401e2eSMatt Spinler 
46311401e2eSMatt Spinler     // Move the pending association to a real association
4645b4357daSKallas, Pawel     checkIfPendingAssociation(io, defaultSourcePath, interfaceMap, assocMaps,
46511401e2eSMatt Spinler                               *server);
46611401e2eSMatt Spinler 
46711401e2eSMatt Spinler     EXPECT_TRUE(assocMaps.pending.empty());
46811401e2eSMatt Spinler     EXPECT_EQ(assocMaps.owners.size(), 1);
46911401e2eSMatt Spinler     EXPECT_EQ(assocMaps.ifaces.size(), 2);
47011401e2eSMatt Spinler 
47111401e2eSMatt Spinler     // This shouldn't do anything, since /new/path isn't pending
4725b4357daSKallas, Pawel     checkIfPendingAssociation(io, "/new/path", interfaceMap, assocMaps,
4735b4357daSKallas, Pawel                               *server);
47411401e2eSMatt Spinler     EXPECT_TRUE(assocMaps.pending.empty());
47511401e2eSMatt Spinler     EXPECT_EQ(assocMaps.owners.size(), 1);
47611401e2eSMatt Spinler     EXPECT_EQ(assocMaps.ifaces.size(), 2);
47711401e2eSMatt Spinler }
4787f8fd1faSMatt Spinler 
TEST_F(TestAssociations,findAssociations)4797f8fd1faSMatt Spinler TEST_F(TestAssociations, findAssociations)
4807f8fd1faSMatt Spinler {
4817f8fd1faSMatt Spinler     std::vector<std::tuple<std::string, Association>> associationData;
4827f8fd1faSMatt Spinler     AssociationMaps assocMaps;
4837f8fd1faSMatt Spinler 
4847f8fd1faSMatt Spinler     assocMaps.owners = {
4857f8fd1faSMatt Spinler         {"pathA",
4867f8fd1faSMatt Spinler          {{"ownerA",
4877f8fd1faSMatt Spinler            {{"pathA/typeA", {"endpointA", "endpointB"}},
4887f8fd1faSMatt Spinler             {"endpointA/type0", {"pathA"}}}}}},
4897f8fd1faSMatt Spinler 
4907f8fd1faSMatt Spinler         {"pathJ",
4917f8fd1faSMatt Spinler          {{"ownerC",
4927f8fd1faSMatt Spinler            {{"pathJ/typeA", {"endpointF"}}, {"endpointF/type0", {"pathJ"}}}}}},
4937f8fd1faSMatt Spinler 
4947f8fd1faSMatt Spinler         {"pathX",
4957f8fd1faSMatt Spinler          {{"ownerB",
4967f8fd1faSMatt Spinler            {{"pathX/typeB", {"endpointA"}}, {"endpointA/type1", {"pathX"}}}}}}};
4977f8fd1faSMatt Spinler 
4987f8fd1faSMatt Spinler     findAssociations("endpointA", assocMaps, associationData);
4997f8fd1faSMatt Spinler     ASSERT_EQ(associationData.size(), 2);
5007f8fd1faSMatt Spinler 
5017f8fd1faSMatt Spinler     {
50247b68cbcSPatrick Williams         auto ad = std::find_if(
50347b68cbcSPatrick Williams             associationData.begin(), associationData.end(),
50447b68cbcSPatrick Williams             [](const auto& ad) { return std::get<0>(ad) == "ownerA"; });
5057f8fd1faSMatt Spinler         ASSERT_NE(ad, associationData.end());
5067f8fd1faSMatt Spinler 
5077f8fd1faSMatt Spinler         auto& a = std::get<1>(*ad);
5087f8fd1faSMatt Spinler         ASSERT_EQ(std::get<0>(a), "type0");
5097f8fd1faSMatt Spinler         ASSERT_EQ(std::get<1>(a), "typeA");
5107f8fd1faSMatt Spinler         ASSERT_EQ(std::get<2>(a), "pathA");
5117f8fd1faSMatt Spinler     }
5127f8fd1faSMatt Spinler     {
51347b68cbcSPatrick Williams         auto ad = std::find_if(
51447b68cbcSPatrick Williams             associationData.begin(), associationData.end(),
51547b68cbcSPatrick Williams             [](const auto& ad) { return std::get<0>(ad) == "ownerB"; });
5167f8fd1faSMatt Spinler         ASSERT_NE(ad, associationData.end());
5177f8fd1faSMatt Spinler 
5187f8fd1faSMatt Spinler         auto& a = std::get<1>(*ad);
5197f8fd1faSMatt Spinler         ASSERT_EQ(std::get<0>(a), "type1");
5207f8fd1faSMatt Spinler         ASSERT_EQ(std::get<1>(a), "typeB");
5217f8fd1faSMatt Spinler         ASSERT_EQ(std::get<2>(a), "pathX");
5227f8fd1faSMatt Spinler     }
5237f8fd1faSMatt Spinler }
5249c3d2859SMatt Spinler 
TEST_F(TestAssociations,moveAssocToPendingNoOp)5259c3d2859SMatt Spinler TEST_F(TestAssociations, moveAssocToPendingNoOp)
5269c3d2859SMatt Spinler {
5279c3d2859SMatt Spinler     AssociationMaps assocMaps;
5289c3d2859SMatt Spinler 
5299c3d2859SMatt Spinler     // Not an association, so it shouldn't do anything
5305b4357daSKallas, Pawel     moveAssociationToPending(io, defaultEndpoint, assocMaps, *server);
5319c3d2859SMatt Spinler 
5329c3d2859SMatt Spinler     EXPECT_TRUE(assocMaps.pending.empty());
5339c3d2859SMatt Spinler     EXPECT_TRUE(assocMaps.owners.empty());
5349c3d2859SMatt Spinler     EXPECT_TRUE(assocMaps.ifaces.empty());
5359c3d2859SMatt Spinler }
5369c3d2859SMatt Spinler 
TEST_F(TestAssociations,moveAssocToPending)5379c3d2859SMatt Spinler TEST_F(TestAssociations, moveAssocToPending)
5389c3d2859SMatt Spinler {
5399c3d2859SMatt Spinler     AssociationMaps assocMaps;
5409c3d2859SMatt Spinler     assocMaps.owners = createDefaultOwnerAssociation();
5419c3d2859SMatt Spinler     assocMaps.ifaces = createDefaultInterfaceAssociation(server);
5429c3d2859SMatt Spinler 
5435b4357daSKallas, Pawel     moveAssociationToPending(io, defaultEndpoint, assocMaps, *server);
5449c3d2859SMatt Spinler 
5459c3d2859SMatt Spinler     // Check it's now pending
5469c3d2859SMatt Spinler     EXPECT_EQ(assocMaps.pending.size(), 1);
547a098a37aSBrad Bishop     EXPECT_EQ(assocMaps.pending.begin()->first, defaultEndpoint);
5489c3d2859SMatt Spinler 
5499c3d2859SMatt Spinler     // No more assoc owners
5509c3d2859SMatt Spinler     EXPECT_TRUE(assocMaps.owners.empty());
5519c3d2859SMatt Spinler 
5529c3d2859SMatt Spinler     // Check the association interfaces were removed
5539c3d2859SMatt Spinler     {
554a098a37aSBrad Bishop         auto assocs = assocMaps.ifaces.find(defaultFwdPath);
5559c3d2859SMatt Spinler         auto& iface = std::get<ifacePos>(assocs->second);
5569c3d2859SMatt Spinler         auto& endpoints = std::get<endpointsPos>(assocs->second);
5579c3d2859SMatt Spinler 
5589c3d2859SMatt Spinler         EXPECT_EQ(iface.get(), nullptr);
5599c3d2859SMatt Spinler         EXPECT_TRUE(endpoints.empty());
5609c3d2859SMatt Spinler     }
5619c3d2859SMatt Spinler     {
562a098a37aSBrad Bishop         auto assocs = assocMaps.ifaces.find(defaultRevPath);
5639c3d2859SMatt Spinler         auto& iface = std::get<ifacePos>(assocs->second);
5649c3d2859SMatt Spinler         auto& endpoints = std::get<endpointsPos>(assocs->second);
5659c3d2859SMatt Spinler 
5669c3d2859SMatt Spinler         EXPECT_EQ(iface.get(), nullptr);
5679c3d2859SMatt Spinler         EXPECT_TRUE(endpoints.empty());
5689c3d2859SMatt Spinler     }
5699c3d2859SMatt Spinler }
570