topology: Attach power assoc to downstream port

When an upstream component (e.g. a Baseboard) changes (FRU data update)
but the downstream component (e.g. a PowerSupply board) remains
unchanged, the topology update may fail to refresh associations because
the downstream board is not reprocessed dues to this line check [1]
which only associates the upstream entity with the downstream ones that
are in the new board list.

This commit instead attaches the powering/powered_by association to the
downstream entity. As a result:

1. If an upstream entity changes and the downstream is removed, the
   association will be removed with the downstream D-Bus object.
2. If an upstream entity changes and the downstream doesn't, the
   association will stay with the upstream D-Bus object (the port
   topology configurations don't change after FRU updates so there's
   no chance that the connection needs to be removed).
3. If a downstream entity changes, the association will be re-attached
   to the downstream object.

Unit test is updated accordingly.

Tested on Mt.Jefferson:

1. Configure an upstream port in Baseboard and a downstream power port
   in a PowerSupply board which connects to the mentioned upstream port.
2. Update FRU data of the Baseboard, after rescaning, the
   powered_by/powering association between the 2 entities still remains.

[1]: https://github.com/openbmc/entity-manager/blob/07fdadae76000e4056afac15c24bb8e80b3c8cd8/src/entity_manager/topology.cpp#L69

Signed-off-by: Hieu Huynh <hieuh@os.amperecomputing.com>
Signed-off-by: Chau Ly <chaul@amperecomputing.com>
Change-Id: I7883ec0229a093db4a03a683baab24b176adfb7e
diff --git a/src/entity_manager/topology.cpp b/src/entity_manager/topology.cpp
index fa95a85..90d8c8d 100644
--- a/src/entity_manager/topology.cpp
+++ b/src/entity_manager/topology.cpp
@@ -72,8 +72,8 @@
                                                         "containing", upstream);
                         if (powerPaths.contains(downstream))
                         {
-                            result[upstream].emplace_back(
-                                "powered_by", "powering", downstream);
+                            result[downstream].emplace_back(
+                                "powering", "powered_by", upstream);
                         }
                     }
                 }
diff --git a/test/test_topology.cpp b/test/test_topology.cpp
index ae6e663..34c708c 100644
--- a/test/test_topology.cpp
+++ b/test/test_topology.cpp
@@ -13,7 +13,7 @@
 const Association subchassisAssoc =
     std::make_tuple("contained_by", "containing", superchassisPath);
 const Association powerAssoc =
-    std::make_tuple("powered_by", "powering", subchassisPath);
+    std::make_tuple("powering", "powered_by", superchassisPath);
 
 const nlohmann::json subchassisExposesItem = nlohmann::json::parse(R"(
     {
@@ -160,11 +160,10 @@
 
     auto assocs = topo.getAssocs(boards);
 
-    EXPECT_EQ(assocs.size(), 2U);
-    EXPECT_EQ(assocs[subchassisPath].size(), 1U);
+    EXPECT_EQ(assocs.size(), 1U);
+    EXPECT_EQ(assocs[subchassisPath].size(), 2U);
     EXPECT_EQ(assocs[subchassisPath][0], subchassisAssoc);
-    EXPECT_EQ(assocs[superchassisPath].size(), 1U);
-    EXPECT_EQ(assocs[superchassisPath][0], powerAssoc);
+    EXPECT_EQ(assocs[subchassisPath][1], powerAssoc);
 }
 
 TEST(Topology, NoNewBoards)