1 #include "src/associations.hpp" 2 3 #include "src/test/util/asio_server_class.hpp" 4 #include "src/test/util/association_objects.hpp" 5 #include "src/test/util/debug_output.hpp" 6 7 #include <sdbusplus/asio/connection.hpp> 8 #include <sdbusplus/asio/object_server.hpp> 9 10 #include <gtest/gtest.h> 11 12 class TestAssociations : public AsioServerClassTest 13 { 14 }; 15 sdbusplus::asio::object_server* TestAssociations::AsioServerClassTest::server = 16 nullptr; 17 18 // Verify call when path is not in associated owners 19 TEST_F(TestAssociations, SourcePathNotInAssociations) 20 { 21 EXPECT_NE(nullptr, server); 22 std::string sourcePath = "/xyz/openbmc_project/no/association"; 23 AssociationOwnersType assocOwners; 24 AssociationInterfaces assocInterfaces; 25 26 removeAssociation(sourcePath, DEFAULT_DBUS_SVC, *server, assocOwners, 27 assocInterfaces); 28 } 29 30 // Verify call when owner is not in associated owners 31 TEST_F(TestAssociations, OwnerNotInAssociations) 32 { 33 AssociationInterfaces assocInterfaces; 34 35 auto assocOwners = createDefaultOwnerAssociation(); 36 37 removeAssociation(DEFAULT_SOURCE_PATH, DEFAULT_DBUS_SVC, *server, 38 assocOwners, assocInterfaces); 39 } 40 41 // Verify call when path is not in associated interfaces 42 TEST_F(TestAssociations, PathNotInAssocInterfaces) 43 { 44 AssociationInterfaces assocInterfaces; 45 46 auto assocOwners = createDefaultOwnerAssociation(); 47 48 removeAssociation(DEFAULT_SOURCE_PATH, DEFAULT_DBUS_SVC, *server, 49 assocOwners, assocInterfaces); 50 51 EXPECT_TRUE(assocOwners.empty()); 52 } 53 54 // Verify call when path is in associated interfaces 55 TEST_F(TestAssociations, PathIsInAssociatedInterfaces) 56 { 57 // Build up these objects so that an associated interface will match 58 // with the associated owner being removed 59 auto assocOwners = createDefaultOwnerAssociation(); 60 auto assocInterfaces = createDefaultInterfaceAssociation(server); 61 62 removeAssociation(DEFAULT_SOURCE_PATH, DEFAULT_DBUS_SVC, *server, 63 assocOwners, assocInterfaces); 64 65 // Verify owner association was deleted 66 EXPECT_TRUE(assocOwners.empty()); 67 68 // Verify endpoint was deleted from interface association 69 auto intfEndpoints = 70 std::get<endpointsPos>(assocInterfaces[DEFAULT_FWD_PATH]); 71 EXPECT_EQ(intfEndpoints.size(), 0); 72 intfEndpoints = std::get<endpointsPos>(assocInterfaces[DEFAULT_REV_PATH]); 73 EXPECT_EQ(intfEndpoints.size(), 0); 74 } 75 76 // Verify call when path is in associated interfaces, with extra endpoints 77 TEST_F(TestAssociations, PathIsInAssociatedInterfacesExtraEndpoints) 78 { 79 // Build up these objects so that an associated interface will match 80 // with the associated owner being removed 81 auto assocOwners = createDefaultOwnerAssociation(); 82 auto assocInterfaces = createDefaultInterfaceAssociation(server); 83 84 // Add another endpoint to the assoc interfaces 85 addEndpointToInterfaceAssociation(assocInterfaces); 86 87 removeAssociation(DEFAULT_SOURCE_PATH, DEFAULT_DBUS_SVC, *server, 88 assocOwners, assocInterfaces); 89 90 // Verify owner association was deleted 91 EXPECT_TRUE(assocOwners.empty()); 92 93 // Verify all endpoints are deleted since source path was deleted 94 auto intfEndpoints = 95 std::get<endpointsPos>(assocInterfaces[DEFAULT_FWD_PATH]); 96 EXPECT_EQ(intfEndpoints.size(), 0); 97 intfEndpoints = std::get<endpointsPos>(assocInterfaces[DEFAULT_REV_PATH]); 98 EXPECT_EQ(intfEndpoints.size(), 0); 99 } 100 101 // Verify no associations or endpoints removed when the change is identical 102 TEST_F(TestAssociations, checkAssociationEndpointRemovesNoEpRemove) 103 { 104 105 AssociationPaths newAssocPaths = { 106 {DEFAULT_FWD_PATH, {DEFAULT_ENDPOINT}}, 107 {DEFAULT_REV_PATH, {DEFAULT_SOURCE_PATH}}}; 108 109 auto assocOwners = createDefaultOwnerAssociation(); 110 auto assocInterfaces = createDefaultInterfaceAssociation(server); 111 112 checkAssociationEndpointRemoves(DEFAULT_SOURCE_PATH, DEFAULT_DBUS_SVC, 113 newAssocPaths, *server, assocOwners, 114 assocInterfaces); 115 116 // Verify endpoints were not deleted because they matche with what was 117 // in the original 118 auto intfEndpoints = 119 std::get<endpointsPos>(assocInterfaces[DEFAULT_FWD_PATH]); 120 EXPECT_EQ(intfEndpoints.size(), 1); 121 intfEndpoints = std::get<endpointsPos>(assocInterfaces[DEFAULT_REV_PATH]); 122 EXPECT_EQ(intfEndpoints.size(), 1); 123 } 124 125 // Verify endpoint is removed when assoc path is different 126 TEST_F(TestAssociations, checkAssociationEndpointRemovesEpRemoveApDiff) 127 { 128 AssociationPaths newAssocPaths = {{"/different/path", {DEFAULT_ENDPOINT}}}; 129 130 auto assocOwners = createDefaultOwnerAssociation(); 131 auto assocInterfaces = createDefaultInterfaceAssociation(server); 132 133 checkAssociationEndpointRemoves(DEFAULT_SOURCE_PATH, DEFAULT_DBUS_SVC, 134 newAssocPaths, *server, assocOwners, 135 assocInterfaces); 136 137 // Verify initial endpoints were deleted because the new path 138 auto intfEndpoints = 139 std::get<endpointsPos>(assocInterfaces[DEFAULT_FWD_PATH]); 140 EXPECT_EQ(intfEndpoints.size(), 0); 141 intfEndpoints = std::get<endpointsPos>(assocInterfaces[DEFAULT_REV_PATH]); 142 EXPECT_EQ(intfEndpoints.size(), 0); 143 } 144 145 // Verify endpoint is removed when endpoint is different 146 TEST_F(TestAssociations, checkAssociationEndpointRemovesEpRemoveEpChanged) 147 { 148 AssociationPaths newAssocPaths = { 149 {DEFAULT_FWD_PATH, {DEFAULT_ENDPOINT + "/different"}}, 150 {DEFAULT_REV_PATH, {DEFAULT_SOURCE_PATH + "/different"}}}; 151 152 auto assocOwners = createDefaultOwnerAssociation(); 153 auto assocInterfaces = createDefaultInterfaceAssociation(server); 154 155 checkAssociationEndpointRemoves(DEFAULT_SOURCE_PATH, DEFAULT_DBUS_SVC, 156 newAssocPaths, *server, assocOwners, 157 assocInterfaces); 158 159 // Verify initial endpoints were deleted because of different endpoints 160 auto intfEndpoints = 161 std::get<endpointsPos>(assocInterfaces[DEFAULT_FWD_PATH]); 162 EXPECT_EQ(intfEndpoints.size(), 0); 163 intfEndpoints = std::get<endpointsPos>(assocInterfaces[DEFAULT_REV_PATH]); 164 EXPECT_EQ(intfEndpoints.size(), 0); 165 } 166 167 // Verify existing endpoint deleted when empty endpoint is provided 168 TEST_F(TestAssociations, associationChangedEmptyEndpoint) 169 { 170 std::vector<Association> associations = {{"inventory", "error", ""}}; 171 172 auto assocOwners = createDefaultOwnerAssociation(); 173 auto assocInterfaces = createDefaultInterfaceAssociation(server); 174 175 // Empty endpoint will result in deletion of corresponding assocInterface 176 associationChanged(*server, associations, DEFAULT_SOURCE_PATH, 177 DEFAULT_DBUS_SVC, assocOwners, assocInterfaces); 178 179 // Both of these should be 0 since we have an invalid endpoint 180 auto intfEndpoints = 181 std::get<endpointsPos>(assocInterfaces[DEFAULT_FWD_PATH]); 182 EXPECT_EQ(intfEndpoints.size(), 0); 183 intfEndpoints = std::get<endpointsPos>(assocInterfaces[DEFAULT_REV_PATH]); 184 EXPECT_EQ(intfEndpoints.size(), 0); 185 } 186 187 // Add a new association with endpoint 188 TEST_F(TestAssociations, associationChangedAddNewAssoc) 189 { 190 std::vector<Association> associations = { 191 {"abc", "def", "/xyz/openbmc_project/new/endpoint"}}; 192 193 auto assocOwners = createDefaultOwnerAssociation(); 194 auto assocInterfaces = createDefaultInterfaceAssociation(server); 195 196 associationChanged(*server, associations, "/new/source/path", 197 DEFAULT_DBUS_SVC, assocOwners, assocInterfaces); 198 199 // Two source paths 200 EXPECT_EQ(assocOwners.size(), 2); 201 202 // Four interfaces 203 EXPECT_EQ(assocInterfaces.size(), 4); 204 205 // New endpoint so assocInterfaces should be same size 206 auto intfEndpoints = 207 std::get<endpointsPos>(assocInterfaces[DEFAULT_FWD_PATH]); 208 EXPECT_EQ(intfEndpoints.size(), 1); 209 } 210 211 // Add a new association to empty objects 212 TEST_F(TestAssociations, associationChangedAddNewAssocEmptyObj) 213 { 214 std::string sourcePath = "/logging/entry/1"; 215 std::string owner = "xyz.openbmc_project.Test"; 216 std::vector<Association> associations = { 217 {"inventory", "error", 218 "/xyz/openbmc_project/inventory/system/chassis"}}; 219 220 // Empty objects because this test will ensure assocOwners adds the 221 // changed association and interface 222 AssociationInterfaces assocInterfaces; 223 AssociationOwnersType assocOwners; 224 225 associationChanged(*server, associations, DEFAULT_SOURCE_PATH, 226 DEFAULT_DBUS_SVC, assocOwners, assocInterfaces); 227 228 // New associations so ensure it now contains a single entry 229 EXPECT_EQ(assocOwners.size(), 1); 230 231 // Verify corresponding assoc paths each have one endpoint in assoc 232 // interfaces and that those endpoints match 233 auto singleOwner = assocOwners[DEFAULT_SOURCE_PATH]; 234 auto singleIntf = singleOwner[DEFAULT_DBUS_SVC]; 235 for (auto i : singleIntf) 236 { 237 auto intfEndpoints = std::get<endpointsPos>(assocInterfaces[i.first]); 238 EXPECT_EQ(intfEndpoints.size(), 1); 239 EXPECT_EQ(intfEndpoints[0], *i.second.begin()); 240 } 241 } 242 243 // Add a new association to same source path but with new owner 244 TEST_F(TestAssociations, associationChangedAddNewAssocNewOwner) 245 { 246 std::string newOwner = "xyz.openbmc_project.Test2"; 247 std::vector<Association> associations = { 248 {"inventory", "error", 249 "/xyz/openbmc_project/inventory/system/chassis"}}; 250 251 auto assocOwners = createDefaultOwnerAssociation(); 252 auto assocInterfaces = createDefaultInterfaceAssociation(server); 253 254 associationChanged(*server, associations, DEFAULT_SOURCE_PATH, newOwner, 255 assocOwners, assocInterfaces); 256 257 // New endpoint so assocOwners should be same size 258 EXPECT_EQ(assocOwners.size(), 1); 259 260 // Ensure only one endpoint under first path 261 auto intfEndpoints = 262 std::get<endpointsPos>(assocInterfaces[DEFAULT_FWD_PATH]); 263 EXPECT_EQ(intfEndpoints.size(), 1); 264 265 // Ensure the 2 new association endpoints are under the new owner 266 auto a = assocOwners.find(DEFAULT_SOURCE_PATH); 267 auto o = a->second.find(newOwner); 268 EXPECT_EQ(o->second.size(), 2); 269 } 270 271 // Add a new association to existing interface path 272 TEST_F(TestAssociations, associationChangedAddNewAssocSameInterface) 273 { 274 std::vector<Association> associations = { 275 {"abc", "error", "/xyz/openbmc_project/inventory/system/chassis"}}; 276 277 auto assocOwners = createDefaultOwnerAssociation(); 278 auto assocInterfaces = createDefaultInterfaceAssociation(server); 279 280 associationChanged(*server, associations, DEFAULT_SOURCE_PATH, 281 DEFAULT_DBUS_SVC, assocOwners, assocInterfaces); 282 283 // Should have 3 entries in AssociationInterfaces, one is just missing an 284 // endpoint 285 EXPECT_EQ(assocInterfaces.size(), 3); 286 287 // Change to existing interface so it will be removed here 288 auto intfEndpoints = 289 std::get<endpointsPos>(assocInterfaces[DEFAULT_FWD_PATH]); 290 EXPECT_EQ(intfEndpoints.size(), 0); 291 292 // The new endpoint should exist though in it's place 293 intfEndpoints = std::get<endpointsPos>( 294 assocInterfaces[DEFAULT_SOURCE_PATH + "/" + "abc"]); 295 EXPECT_EQ(intfEndpoints.size(), 1); 296 297 // Added to an existing owner path so still 1 298 EXPECT_EQ(assocOwners.size(), 1); 299 } 300