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