Handle losing association endpoints

If the endpoint path of an association (not the path that has the
org.openbmc.Associations interface) goes off of D-Bus, then remove the 2
association objects and move this association to the list of pending
ones.  That way if it ever comes back, the association objects will be
re-added.

This commit adds a moveAssociationToPending function in the code paths
where the mapper sees D-Bus paths going away.  That function will find
all associations that involve that path, and then remove the actual
association paths and add them to the list of pending ones.

Signed-off-by: Matt Spinler <spinler@us.ibm.com>
Change-Id: I14d5ddf8f65be866c2cedd5f467d65adf8e3af95
diff --git a/src/test/associations.cpp b/src/test/associations.cpp
index 7ac2e79..50706d7 100644
--- a/src/test/associations.cpp
+++ b/src/test/associations.cpp
@@ -517,3 +517,49 @@
         ASSERT_EQ(std::get<2>(a), "pathX");
     }
 }
+
+TEST_F(TestAssociations, moveAssocToPendingNoOp)
+{
+    AssociationMaps assocMaps;
+
+    // Not an association, so it shouldn't do anything
+    moveAssociationToPending(DEFAULT_ENDPOINT, assocMaps, *server);
+
+    EXPECT_TRUE(assocMaps.pending.empty());
+    EXPECT_TRUE(assocMaps.owners.empty());
+    EXPECT_TRUE(assocMaps.ifaces.empty());
+}
+
+TEST_F(TestAssociations, moveAssocToPending)
+{
+    AssociationMaps assocMaps;
+    assocMaps.owners = createDefaultOwnerAssociation();
+    assocMaps.ifaces = createDefaultInterfaceAssociation(server);
+
+    moveAssociationToPending(DEFAULT_ENDPOINT, assocMaps, *server);
+
+    // Check it's now pending
+    EXPECT_EQ(assocMaps.pending.size(), 1);
+    EXPECT_EQ(assocMaps.pending.begin()->first, DEFAULT_ENDPOINT);
+
+    // No more assoc owners
+    EXPECT_TRUE(assocMaps.owners.empty());
+
+    // Check the association interfaces were removed
+    {
+        auto assocs = assocMaps.ifaces.find(DEFAULT_FWD_PATH);
+        auto& iface = std::get<ifacePos>(assocs->second);
+        auto& endpoints = std::get<endpointsPos>(assocs->second);
+
+        EXPECT_EQ(iface.get(), nullptr);
+        EXPECT_TRUE(endpoints.empty());
+    }
+    {
+        auto assocs = assocMaps.ifaces.find(DEFAULT_REV_PATH);
+        auto& iface = std::get<ifacePos>(assocs->second);
+        auto& endpoints = std::get<endpointsPos>(assocs->second);
+
+        EXPECT_EQ(iface.get(), nullptr);
+        EXPECT_TRUE(endpoints.empty());
+    }
+}