unit-test: Test associationChanged()

Testing: 100% coverage of associations.cpp

Change-Id: I978eb37acfbee0a5b6d497cab473691318184aaf
Signed-off-by: Andrew Geissler <geissonator@yahoo.com>
diff --git a/src/test/associations.cpp b/src/test/associations.cpp
index 8b2fadf..20d7ba7 100644
--- a/src/test/associations.cpp
+++ b/src/test/associations.cpp
@@ -2,6 +2,7 @@
 
 #include "src/test/util/asio_server_class.hpp"
 #include "src/test/util/association_objects.hpp"
+#include "src/test/util/debug_output.hpp"
 
 #include <sdbusplus/asio/connection.hpp>
 #include <sdbusplus/asio/object_server.hpp>
@@ -162,3 +163,141 @@
     intfEndpoints = std::get<endpointsPos>(assocInterfaces[DEFAULT_REV_PATH]);
     EXPECT_EQ(intfEndpoints.size(), 0);
 }
+
+// Verify existing endpoint deleted when empty endpoint is provided
+TEST_F(TestAssociations, associationChangedEmptyEndpoint)
+{
+    std::vector<Association> associations = {{"inventory", "error", ""}};
+
+    auto assocOwners = createDefaultOwnerAssociation();
+    auto assocInterfaces = createDefaultInterfaceAssociation(server);
+
+    // Empty endpoint will result in deletion of corresponding assocInterface
+    associationChanged(*server, associations, DEFAULT_SOURCE_PATH,
+                       DEFAULT_DBUS_SVC, assocOwners, assocInterfaces);
+
+    // TODO - This test case found a bug where the endpoint validity
+    // is not checked on the FWD path and is used by default, resulting
+    // in there being a "" endpoint value. Will fix this in next commit
+    // to keep the refactor of the code separate from the fix
+    // (i.e. both of these should be 0 since we have an invalid endpoint)
+    auto intfEndpoints =
+        std::get<endpointsPos>(assocInterfaces[DEFAULT_FWD_PATH]);
+    EXPECT_EQ(intfEndpoints.size(), 1);
+    intfEndpoints = std::get<endpointsPos>(assocInterfaces[DEFAULT_REV_PATH]);
+    EXPECT_EQ(intfEndpoints.size(), 0);
+}
+
+// Add a new association with endpoint
+TEST_F(TestAssociations, associationChangedAddNewAssoc)
+{
+    std::vector<Association> associations = {
+        {"abc", "def", "/xyz/openbmc_project/new/endpoint"}};
+
+    auto assocOwners = createDefaultOwnerAssociation();
+    auto assocInterfaces = createDefaultInterfaceAssociation(server);
+
+    associationChanged(*server, associations, "/new/source/path",
+                       DEFAULT_DBUS_SVC, assocOwners, assocInterfaces);
+
+    // Two source paths
+    EXPECT_EQ(assocOwners.size(), 2);
+
+    // Four interfaces
+    EXPECT_EQ(assocInterfaces.size(), 4);
+
+    // New endpoint so assocInterfaces should be same size
+    auto intfEndpoints =
+        std::get<endpointsPos>(assocInterfaces[DEFAULT_FWD_PATH]);
+    EXPECT_EQ(intfEndpoints.size(), 1);
+}
+
+// Add a new association to empty objects
+TEST_F(TestAssociations, associationChangedAddNewAssocEmptyObj)
+{
+    std::string sourcePath = "/logging/entry/1";
+    std::string owner = "xyz.openbmc_project.Test";
+    std::vector<Association> associations = {
+        {"inventory", "error",
+         "/xyz/openbmc_project/inventory/system/chassis"}};
+
+    // Empty objects because this test will ensure assocOwners adds the
+    // changed association and interface
+    AssociationInterfaces assocInterfaces;
+    AssociationOwnersType assocOwners;
+
+    associationChanged(*server, associations, DEFAULT_SOURCE_PATH,
+                       DEFAULT_DBUS_SVC, assocOwners, assocInterfaces);
+
+    // New associations so ensure it now contains a single entry
+    EXPECT_EQ(assocOwners.size(), 1);
+
+    // Verify corresponding assoc paths each have one endpoint in assoc
+    // interfaces and that those endpoints match
+    auto singleOwner = assocOwners[DEFAULT_SOURCE_PATH];
+    auto singleIntf = singleOwner[DEFAULT_DBUS_SVC];
+    for (auto i : singleIntf)
+    {
+        auto intfEndpoints = std::get<endpointsPos>(assocInterfaces[i.first]);
+        EXPECT_EQ(intfEndpoints.size(), 1);
+        EXPECT_EQ(intfEndpoints[0], *i.second.begin());
+    }
+}
+
+// Add a new association to same source path but with new owner
+TEST_F(TestAssociations, associationChangedAddNewAssocNewOwner)
+{
+    std::string newOwner = "xyz.openbmc_project.Test2";
+    std::vector<Association> associations = {
+        {"inventory", "error",
+         "/xyz/openbmc_project/inventory/system/chassis"}};
+
+    auto assocOwners = createDefaultOwnerAssociation();
+    auto assocInterfaces = createDefaultInterfaceAssociation(server);
+
+    associationChanged(*server, associations, DEFAULT_SOURCE_PATH, newOwner,
+                       assocOwners, assocInterfaces);
+
+    // New endpoint so assocOwners should be same size
+    EXPECT_EQ(assocOwners.size(), 1);
+
+    // Ensure only one endpoint under first path
+    auto intfEndpoints =
+        std::get<endpointsPos>(assocInterfaces[DEFAULT_FWD_PATH]);
+    EXPECT_EQ(intfEndpoints.size(), 1);
+
+    // Ensure the 2 new association endpoints are under the new owner
+    auto a = assocOwners.find(DEFAULT_SOURCE_PATH);
+    auto o = a->second.find(newOwner);
+    EXPECT_EQ(o->second.size(), 2);
+}
+
+// Add a new association to existing interface path
+TEST_F(TestAssociations, associationChangedAddNewAssocSameInterface)
+{
+    std::vector<Association> associations = {
+        {"abc", "error", "/xyz/openbmc_project/inventory/system/chassis"}};
+
+    auto assocOwners = createDefaultOwnerAssociation();
+    auto assocInterfaces = createDefaultInterfaceAssociation(server);
+
+    associationChanged(*server, associations, DEFAULT_SOURCE_PATH,
+                       DEFAULT_DBUS_SVC, assocOwners, assocInterfaces);
+
+    // Should have 3 entries in AssociationInterfaces, one is just missing an
+    // endpoint
+    EXPECT_EQ(assocInterfaces.size(), 3);
+
+    // Change to existing interface so it will be removed here
+    auto intfEndpoints =
+        std::get<endpointsPos>(assocInterfaces[DEFAULT_FWD_PATH]);
+    EXPECT_EQ(intfEndpoints.size(), 0);
+
+    // The new endpoint should exist though in it's place
+    intfEndpoints = std::get<endpointsPos>(
+        assocInterfaces[DEFAULT_SOURCE_PATH + "/" + "abc"]);
+    EXPECT_EQ(intfEndpoints.size(), 1);
+
+    // Added to an existing owner path so still 1
+    EXPECT_EQ(assocOwners.size(), 1);
+}