1f77189f7SLei YU #include "item_updater.hpp"
2f77189f7SLei YU #include "mocked_utils.hpp"
3f77189f7SLei YU
4f77189f7SLei YU #include <sdbusplus/test/sdbus_mock.hpp>
5f77189f7SLei YU
6f77189f7SLei YU #include <gmock/gmock.h>
7f77189f7SLei YU #include <gtest/gtest.h>
8f77189f7SLei YU
9f77189f7SLei YU using namespace phosphor::software::updater;
10f77189f7SLei YU using ::testing::_;
111517f5f6SLei YU using ::testing::ContainerEq;
1258c26e3fSLei YU using ::testing::Pointee;
13f77189f7SLei YU using ::testing::Return;
14f77189f7SLei YU using ::testing::ReturnArg;
15f77189f7SLei YU using ::testing::StrEq;
16f77189f7SLei YU
17b5f9b829SPatrick Williams using std::any;
18f77189f7SLei YU
19f77189f7SLei YU class TestItemUpdater : public ::testing::Test
20f77189f7SLei YU {
21f77189f7SLei YU public:
22a2c2cd72SLei YU using Properties = ItemUpdater::Properties;
23a2c2cd72SLei YU using PropertyType = utils::UtilsInterface::PropertyType;
24a2c2cd72SLei YU
TestItemUpdater()25f77189f7SLei YU TestItemUpdater() :
26f77189f7SLei YU mockedUtils(
27f77189f7SLei YU reinterpret_cast<const utils::MockedUtils&>(utils::getUtils()))
28f77189f7SLei YU {
29f77189f7SLei YU ON_CALL(mockedUtils, getVersionId(_)).WillByDefault(ReturnArg<0>());
30ff83c2a0SLei YU ON_CALL(mockedUtils, getPropertyImpl(_, _, _, _, StrEq(PRESENT)))
31ff83c2a0SLei YU .WillByDefault(Return(any(PropertyType(true))));
32f77189f7SLei YU }
33f77189f7SLei YU
~TestItemUpdater()34f77189f7SLei YU ~TestItemUpdater()
35f77189f7SLei YU {
36c09155bbSLei YU utils::freeUtils();
37f77189f7SLei YU }
38f77189f7SLei YU
GetActivations()391517f5f6SLei YU auto& GetActivations()
40f77189f7SLei YU {
41f77189f7SLei YU return itemUpdater->activations;
42f77189f7SLei YU }
43f77189f7SLei YU
getObjPath(const std::string & versionId)44f77189f7SLei YU std::string getObjPath(const std::string& versionId)
45f77189f7SLei YU {
46f77189f7SLei YU return std::string(dBusPath) + "/" + versionId;
47f77189f7SLei YU }
48f77189f7SLei YU
onPsuInventoryChanged(const std::string & psuPath,const Properties & properties)49a2c2cd72SLei YU void onPsuInventoryChanged(const std::string& psuPath,
50a2c2cd72SLei YU const Properties& properties)
51a2c2cd72SLei YU {
52a2c2cd72SLei YU itemUpdater->onPsuInventoryChanged(psuPath, properties);
53a2c2cd72SLei YU }
54a2c2cd72SLei YU
scanDirectory(const fs::path & p)5558c26e3fSLei YU void scanDirectory(const fs::path& p)
5658c26e3fSLei YU {
5758c26e3fSLei YU itemUpdater->scanDirectory(p);
5858c26e3fSLei YU }
5958c26e3fSLei YU
60f77189f7SLei YU static constexpr auto dBusPath = SOFTWARE_OBJPATH;
61f77189f7SLei YU sdbusplus::SdBusMock sdbusMock;
62374fae56SPatrick Williams sdbusplus::bus_t mockedBus = sdbusplus::get_mocked_new(&sdbusMock);
63f77189f7SLei YU const utils::MockedUtils& mockedUtils;
64f77189f7SLei YU std::unique_ptr<ItemUpdater> itemUpdater;
651517f5f6SLei YU Properties propAdded{{PRESENT, PropertyType(true)}};
661517f5f6SLei YU Properties propRemoved{{PRESENT, PropertyType(false)}};
671517f5f6SLei YU Properties propModel{{MODEL, PropertyType(std::string("dummyModel"))}};
68f77189f7SLei YU };
69f77189f7SLei YU
TEST_F(TestItemUpdater,ctordtor)70f77189f7SLei YU TEST_F(TestItemUpdater, ctordtor)
71f77189f7SLei YU {
726520748dSLei YU EXPECT_CALL(mockedUtils, getLatestVersion(_)).Times(1);
73f77189f7SLei YU itemUpdater = std::make_unique<ItemUpdater>(mockedBus, dBusPath);
74f77189f7SLei YU }
75f77189f7SLei YU
TEST_F(TestItemUpdater,NotCreateObjectOnNotPresent)76f77189f7SLei YU TEST_F(TestItemUpdater, NotCreateObjectOnNotPresent)
77f77189f7SLei YU {
78f77189f7SLei YU constexpr auto psuPath = "/com/example/inventory/psu0";
79f77189f7SLei YU constexpr auto service = "com.example.Software.Psu";
80f77189f7SLei YU constexpr auto version = "version0";
81f77189f7SLei YU std::string objPath = getObjPath(version);
82f77189f7SLei YU EXPECT_CALL(mockedUtils, getPSUInventoryPath(_))
83f77189f7SLei YU .WillOnce(Return(std::vector<std::string>({psuPath})));
84f77189f7SLei YU EXPECT_CALL(mockedUtils, getService(_, StrEq(psuPath), _))
85f77189f7SLei YU .WillOnce(Return(service));
865f3584d4SLei YU EXPECT_CALL(mockedUtils, getVersion(StrEq(psuPath)))
875f3584d4SLei YU .WillOnce(Return(std::string(version)));
88f77189f7SLei YU EXPECT_CALL(mockedUtils, getPropertyImpl(_, StrEq(service), StrEq(psuPath),
89f77189f7SLei YU _, StrEq(PRESENT)))
90f77189f7SLei YU .WillOnce(Return(any(PropertyType(false)))); // not present
91*760053d8SFaisal Awada EXPECT_CALL(mockedUtils, getPropertyImpl(_, StrEq(service), StrEq(psuPath),
92*760053d8SFaisal Awada _, StrEq(MODEL)))
93*760053d8SFaisal Awada .WillOnce(Return(any(PropertyType(std::string("")))));
94f77189f7SLei YU
95f77189f7SLei YU // The item updater itself
96f77189f7SLei YU EXPECT_CALL(sdbusMock, sd_bus_emit_object_added(_, StrEq(dBusPath)))
97f77189f7SLei YU .Times(1);
98f77189f7SLei YU
99f77189f7SLei YU // No activation/version objects are created
100f77189f7SLei YU EXPECT_CALL(sdbusMock, sd_bus_emit_object_added(_, StrEq(objPath)))
101f77189f7SLei YU .Times(0);
102f77189f7SLei YU itemUpdater = std::make_unique<ItemUpdater>(mockedBus, dBusPath);
103f77189f7SLei YU }
104f77189f7SLei YU
TEST_F(TestItemUpdater,CreateOnePSUOnPresent)105f77189f7SLei YU TEST_F(TestItemUpdater, CreateOnePSUOnPresent)
106f77189f7SLei YU {
107f77189f7SLei YU constexpr auto psuPath = "/com/example/inventory/psu0";
108f77189f7SLei YU constexpr auto service = "com.example.Software.Psu";
109f77189f7SLei YU constexpr auto version = "version0";
110f77189f7SLei YU std::string objPath = getObjPath(version);
111f77189f7SLei YU EXPECT_CALL(mockedUtils, getPSUInventoryPath(_))
112f77189f7SLei YU .WillOnce(Return(std::vector<std::string>({psuPath})));
113f77189f7SLei YU EXPECT_CALL(mockedUtils, getService(_, StrEq(psuPath), _))
114f77189f7SLei YU .WillOnce(Return(service));
1155f3584d4SLei YU EXPECT_CALL(mockedUtils, getVersion(StrEq(psuPath)))
1165f3584d4SLei YU .WillOnce(Return(std::string(version)));
117f77189f7SLei YU EXPECT_CALL(mockedUtils, getPropertyImpl(_, StrEq(service), StrEq(psuPath),
118f77189f7SLei YU _, StrEq(PRESENT)))
119f77189f7SLei YU .WillOnce(Return(any(PropertyType(true)))); // present
120*760053d8SFaisal Awada EXPECT_CALL(mockedUtils, getPropertyImpl(_, StrEq(service), StrEq(psuPath),
121*760053d8SFaisal Awada _, StrEq(MODEL)))
122*760053d8SFaisal Awada .WillOnce(Return(any(PropertyType(std::string("dummyModel")))));
123f77189f7SLei YU
124f77189f7SLei YU // The item updater itself
125f77189f7SLei YU EXPECT_CALL(sdbusMock, sd_bus_emit_object_added(_, StrEq(dBusPath)))
126f77189f7SLei YU .Times(1);
127f77189f7SLei YU
128f77189f7SLei YU // activation and version object will be added
129f77189f7SLei YU EXPECT_CALL(sdbusMock, sd_bus_emit_object_added(_, StrEq(objPath)))
130f77189f7SLei YU .Times(2);
131f77189f7SLei YU itemUpdater = std::make_unique<ItemUpdater>(mockedBus, dBusPath);
132f77189f7SLei YU }
133f77189f7SLei YU
TEST_F(TestItemUpdater,CreateTwoPSUsWithSameVersion)134f77189f7SLei YU TEST_F(TestItemUpdater, CreateTwoPSUsWithSameVersion)
135f77189f7SLei YU {
136f77189f7SLei YU constexpr auto psu0 = "/com/example/inventory/psu0";
137f77189f7SLei YU constexpr auto psu1 = "/com/example/inventory/psu1";
138f77189f7SLei YU constexpr auto service = "com.example.Software.Psu";
139f77189f7SLei YU auto version0 = std::string("version0");
140f77189f7SLei YU auto version1 = std::string("version0");
141f77189f7SLei YU auto objPath0 = getObjPath(version0);
142f77189f7SLei YU auto objPath1 = getObjPath(version1);
143f77189f7SLei YU
144f77189f7SLei YU EXPECT_CALL(mockedUtils, getPSUInventoryPath(_))
145f77189f7SLei YU .WillOnce(Return(std::vector<std::string>({psu0, psu1})));
146f77189f7SLei YU EXPECT_CALL(mockedUtils, getService(_, StrEq(psu0), _))
147f77189f7SLei YU .WillOnce(Return(service));
148f77189f7SLei YU EXPECT_CALL(mockedUtils, getService(_, StrEq(psu1), _))
149f77189f7SLei YU .WillOnce(Return(service));
1505f3584d4SLei YU EXPECT_CALL(mockedUtils, getVersion(StrEq(psu0)))
1515f3584d4SLei YU .WillOnce(Return(std::string(version0)));
152f77189f7SLei YU EXPECT_CALL(mockedUtils, getPropertyImpl(_, StrEq(service), StrEq(psu0), _,
153f77189f7SLei YU StrEq(PRESENT)))
154f77189f7SLei YU .WillOnce(Return(any(PropertyType(true)))); // present
155*760053d8SFaisal Awada EXPECT_CALL(mockedUtils, getPropertyImpl(_, StrEq(service), StrEq(psu0), _,
156*760053d8SFaisal Awada StrEq(MODEL)))
157*760053d8SFaisal Awada .WillOnce(Return(any(PropertyType(std::string("dummyModel0")))));
1585f3584d4SLei YU EXPECT_CALL(mockedUtils, getVersion(StrEq(psu1)))
1595f3584d4SLei YU .WillOnce(Return(std::string(version1)));
160f77189f7SLei YU EXPECT_CALL(mockedUtils, getPropertyImpl(_, StrEq(service), StrEq(psu1), _,
161f77189f7SLei YU StrEq(PRESENT)))
162f77189f7SLei YU .WillOnce(Return(any(PropertyType(true)))); // present
163*760053d8SFaisal Awada EXPECT_CALL(mockedUtils, getPropertyImpl(_, StrEq(service), StrEq(psu1), _,
164*760053d8SFaisal Awada StrEq(MODEL)))
165*760053d8SFaisal Awada .WillOnce(Return(any(PropertyType(std::string("dummyModel1")))));
166f77189f7SLei YU
167f77189f7SLei YU // The item updater itself
168f77189f7SLei YU EXPECT_CALL(sdbusMock, sd_bus_emit_object_added(_, StrEq(dBusPath)))
169f77189f7SLei YU .Times(1);
170f77189f7SLei YU
171f77189f7SLei YU // activation and version object will be added
172f77189f7SLei YU EXPECT_CALL(sdbusMock, sd_bus_emit_object_added(_, StrEq(objPath0)))
173f77189f7SLei YU .Times(2);
174f77189f7SLei YU itemUpdater = std::make_unique<ItemUpdater>(mockedBus, dBusPath);
175f77189f7SLei YU
176f77189f7SLei YU // Verify there is only one activation and it has two associations
177f77189f7SLei YU const auto& activations = GetActivations();
178f77189f7SLei YU EXPECT_EQ(1u, activations.size());
179f77189f7SLei YU const auto& activation = activations.find(version0)->second;
180f77189f7SLei YU const auto& assocs = activation->associations();
181f77189f7SLei YU EXPECT_EQ(2u, assocs.size());
182f77189f7SLei YU EXPECT_EQ(psu0, std::get<2>(assocs[0]));
183f77189f7SLei YU EXPECT_EQ(psu1, std::get<2>(assocs[1]));
184f77189f7SLei YU }
185f77189f7SLei YU
TEST_F(TestItemUpdater,CreateTwoPSUsWithDifferentVersion)186f77189f7SLei YU TEST_F(TestItemUpdater, CreateTwoPSUsWithDifferentVersion)
187f77189f7SLei YU {
188f77189f7SLei YU constexpr auto psu0 = "/com/example/inventory/psu0";
189f77189f7SLei YU constexpr auto psu1 = "/com/example/inventory/psu1";
190f77189f7SLei YU constexpr auto service = "com.example.Software.Psu";
191f77189f7SLei YU auto version0 = std::string("version0");
192f77189f7SLei YU auto version1 = std::string("version1");
193f77189f7SLei YU auto objPath0 = getObjPath(version0);
194f77189f7SLei YU auto objPath1 = getObjPath(version1);
195f77189f7SLei YU
196f77189f7SLei YU EXPECT_CALL(mockedUtils, getPSUInventoryPath(_))
197f77189f7SLei YU .WillOnce(Return(std::vector<std::string>({psu0, psu1})));
198f77189f7SLei YU EXPECT_CALL(mockedUtils, getService(_, StrEq(psu0), _))
199f77189f7SLei YU .WillOnce(Return(service));
200f77189f7SLei YU EXPECT_CALL(mockedUtils, getService(_, StrEq(psu1), _))
201f77189f7SLei YU .WillOnce(Return(service));
2025f3584d4SLei YU EXPECT_CALL(mockedUtils, getVersion(StrEq(psu0)))
2035f3584d4SLei YU .WillOnce(Return(std::string(version0)));
204f77189f7SLei YU EXPECT_CALL(mockedUtils, getPropertyImpl(_, StrEq(service), StrEq(psu0), _,
205f77189f7SLei YU StrEq(PRESENT)))
206f77189f7SLei YU .WillOnce(Return(any(PropertyType(true)))); // present
207*760053d8SFaisal Awada EXPECT_CALL(mockedUtils, getPropertyImpl(_, StrEq(service), StrEq(psu0), _,
208*760053d8SFaisal Awada StrEq(MODEL)))
209*760053d8SFaisal Awada .WillOnce(Return(any(PropertyType(std::string("dummyModel0")))));
2105f3584d4SLei YU EXPECT_CALL(mockedUtils, getVersion(StrEq(psu1)))
2115f3584d4SLei YU .WillOnce(Return(std::string(version1)));
212f77189f7SLei YU EXPECT_CALL(mockedUtils, getPropertyImpl(_, StrEq(service), StrEq(psu1), _,
213f77189f7SLei YU StrEq(PRESENT)))
214f77189f7SLei YU .WillOnce(Return(any(PropertyType(true)))); // present
215*760053d8SFaisal Awada EXPECT_CALL(mockedUtils, getPropertyImpl(_, StrEq(service), StrEq(psu1), _,
216*760053d8SFaisal Awada StrEq(MODEL)))
217*760053d8SFaisal Awada .WillOnce(Return(any(PropertyType(std::string("dummyModel1")))));
218f77189f7SLei YU
219f77189f7SLei YU // The item updater itself
220f77189f7SLei YU EXPECT_CALL(sdbusMock, sd_bus_emit_object_added(_, StrEq(dBusPath)))
221f77189f7SLei YU .Times(1);
222f77189f7SLei YU
223f77189f7SLei YU // two new activation and version objects will be added
224f77189f7SLei YU EXPECT_CALL(sdbusMock, sd_bus_emit_object_added(_, StrEq(objPath0)))
225f77189f7SLei YU .Times(2);
226f77189f7SLei YU EXPECT_CALL(sdbusMock, sd_bus_emit_object_added(_, StrEq(objPath1)))
227f77189f7SLei YU .Times(2);
228f77189f7SLei YU itemUpdater = std::make_unique<ItemUpdater>(mockedBus, dBusPath);
229f77189f7SLei YU
230f77189f7SLei YU // Verify there are two activations and each with one association
231f77189f7SLei YU const auto& activations = GetActivations();
232f77189f7SLei YU EXPECT_EQ(2u, activations.size());
233f77189f7SLei YU const auto& activation0 = activations.find(version0)->second;
234f77189f7SLei YU const auto& assocs0 = activation0->associations();
235f77189f7SLei YU EXPECT_EQ(1u, assocs0.size());
236f77189f7SLei YU EXPECT_EQ(psu0, std::get<2>(assocs0[0]));
237f77189f7SLei YU
238f77189f7SLei YU const auto& activation1 = activations.find(version1)->second;
239f77189f7SLei YU const auto& assocs1 = activation1->associations();
240f77189f7SLei YU EXPECT_EQ(1u, assocs1.size());
241f77189f7SLei YU EXPECT_EQ(psu1, std::get<2>(assocs1[0]));
242f77189f7SLei YU }
243a2c2cd72SLei YU
TEST_F(TestItemUpdater,OnOnePSURemoved)244a2c2cd72SLei YU TEST_F(TestItemUpdater, OnOnePSURemoved)
245a2c2cd72SLei YU {
246a2c2cd72SLei YU constexpr auto psuPath = "/com/example/inventory/psu0";
247a2c2cd72SLei YU constexpr auto service = "com.example.Software.Psu";
248a2c2cd72SLei YU constexpr auto version = "version0";
249a2c2cd72SLei YU std::string objPath = getObjPath(version);
250a2c2cd72SLei YU EXPECT_CALL(mockedUtils, getPSUInventoryPath(_))
251a2c2cd72SLei YU .WillOnce(Return(std::vector<std::string>({psuPath})));
252a2c2cd72SLei YU EXPECT_CALL(mockedUtils, getService(_, StrEq(psuPath), _))
253a2c2cd72SLei YU .WillOnce(Return(service));
2545f3584d4SLei YU EXPECT_CALL(mockedUtils, getVersion(StrEq(psuPath)))
2555f3584d4SLei YU .WillOnce(Return(std::string(version)));
256a2c2cd72SLei YU EXPECT_CALL(mockedUtils, getPropertyImpl(_, StrEq(service), StrEq(psuPath),
257a2c2cd72SLei YU _, StrEq(PRESENT)))
258a2c2cd72SLei YU .WillOnce(Return(any(PropertyType(true)))); // present
259*760053d8SFaisal Awada EXPECT_CALL(mockedUtils, getPropertyImpl(_, StrEq(service), StrEq(psuPath),
260*760053d8SFaisal Awada _, StrEq(MODEL)))
261*760053d8SFaisal Awada .WillOnce(Return(any(PropertyType(std::string("dummyModel")))));
262a2c2cd72SLei YU
263a2c2cd72SLei YU // The item updater itself
264a2c2cd72SLei YU EXPECT_CALL(sdbusMock, sd_bus_emit_object_added(_, StrEq(dBusPath)))
265a2c2cd72SLei YU .Times(1);
266a2c2cd72SLei YU
267a2c2cd72SLei YU // activation and version object will be added
268a2c2cd72SLei YU EXPECT_CALL(sdbusMock, sd_bus_emit_object_added(_, StrEq(objPath)))
269a2c2cd72SLei YU .Times(2);
270a2c2cd72SLei YU itemUpdater = std::make_unique<ItemUpdater>(mockedBus, dBusPath);
271a2c2cd72SLei YU
272a2c2cd72SLei YU // the activation and version object will be removed
273a2c2cd72SLei YU Properties p{{PRESENT, PropertyType(false)}};
274a2c2cd72SLei YU EXPECT_CALL(sdbusMock, sd_bus_emit_object_removed(_, StrEq(objPath)))
275a2c2cd72SLei YU .Times(2);
276a2c2cd72SLei YU onPsuInventoryChanged(psuPath, p);
277a2c2cd72SLei YU
278a2c2cd72SLei YU // on exit, item updater is removed
279a2c2cd72SLei YU EXPECT_CALL(sdbusMock, sd_bus_emit_object_removed(_, StrEq(dBusPath)))
280a2c2cd72SLei YU .Times(1);
281a2c2cd72SLei YU }
282a2c2cd72SLei YU
TEST_F(TestItemUpdater,OnOnePSUAdded)283a2c2cd72SLei YU TEST_F(TestItemUpdater, OnOnePSUAdded)
284a2c2cd72SLei YU {
285a2c2cd72SLei YU constexpr auto psuPath = "/com/example/inventory/psu0";
286a2c2cd72SLei YU constexpr auto service = "com.example.Software.Psu";
287a2c2cd72SLei YU constexpr auto version = "version0";
288a2c2cd72SLei YU std::string objPath = getObjPath(version);
289a2c2cd72SLei YU EXPECT_CALL(mockedUtils, getPSUInventoryPath(_))
290a2c2cd72SLei YU .WillOnce(Return(std::vector<std::string>({psuPath})));
291a2c2cd72SLei YU EXPECT_CALL(mockedUtils, getService(_, StrEq(psuPath), _))
292a2c2cd72SLei YU .WillOnce(Return(service));
2935f3584d4SLei YU EXPECT_CALL(mockedUtils, getVersion(StrEq(psuPath)))
2945f3584d4SLei YU .WillOnce(Return(std::string(version)));
295a2c2cd72SLei YU EXPECT_CALL(mockedUtils, getPropertyImpl(_, StrEq(service), StrEq(psuPath),
296a2c2cd72SLei YU _, StrEq(PRESENT)))
297a2c2cd72SLei YU .WillOnce(Return(any(PropertyType(false)))); // not present
298*760053d8SFaisal Awada EXPECT_CALL(mockedUtils, getPropertyImpl(_, StrEq(service), StrEq(psuPath),
299*760053d8SFaisal Awada _, StrEq(MODEL)))
300*760053d8SFaisal Awada .WillOnce(Return(any(PropertyType(std::string("")))));
301a2c2cd72SLei YU
302a2c2cd72SLei YU // The item updater itself
303a2c2cd72SLei YU EXPECT_CALL(sdbusMock, sd_bus_emit_object_added(_, StrEq(dBusPath)))
304a2c2cd72SLei YU .Times(1);
305a2c2cd72SLei YU
306a2c2cd72SLei YU // No activation/version objects are created
307a2c2cd72SLei YU EXPECT_CALL(sdbusMock, sd_bus_emit_object_added(_, StrEq(objPath)))
308a2c2cd72SLei YU .Times(0);
309a2c2cd72SLei YU itemUpdater = std::make_unique<ItemUpdater>(mockedBus, dBusPath);
310a2c2cd72SLei YU
311a2c2cd72SLei YU // The PSU is present and version is added in a single call
3121517f5f6SLei YU Properties propAddedAndModel{
3131517f5f6SLei YU {PRESENT, PropertyType(true)},
3141517f5f6SLei YU {MODEL, PropertyType(std::string("testModel"))}};
315dcaf8934SLei YU EXPECT_CALL(mockedUtils, getVersion(StrEq(psuPath)))
316dcaf8934SLei YU .WillOnce(Return(std::string(version)));
317a2c2cd72SLei YU EXPECT_CALL(sdbusMock, sd_bus_emit_object_added(_, StrEq(objPath)))
318a2c2cd72SLei YU .Times(2);
3191517f5f6SLei YU onPsuInventoryChanged(psuPath, propAddedAndModel);
320a2c2cd72SLei YU }
321a2c2cd72SLei YU
TEST_F(TestItemUpdater,OnOnePSURemovedAndAddedWithLatestVersion)3221517f5f6SLei YU TEST_F(TestItemUpdater, OnOnePSURemovedAndAddedWithLatestVersion)
323a2c2cd72SLei YU {
324a2c2cd72SLei YU constexpr auto psuPath = "/com/example/inventory/psu0";
325a2c2cd72SLei YU constexpr auto service = "com.example.Software.Psu";
326a2c2cd72SLei YU constexpr auto version = "version0";
327a2c2cd72SLei YU std::string objPath = getObjPath(version);
3281517f5f6SLei YU ON_CALL(mockedUtils, getPSUInventoryPath(_))
3291517f5f6SLei YU .WillByDefault(Return(std::vector<std::string>({psuPath})));
330a2c2cd72SLei YU EXPECT_CALL(mockedUtils, getService(_, StrEq(psuPath), _))
331a2c2cd72SLei YU .WillOnce(Return(service));
3325f3584d4SLei YU EXPECT_CALL(mockedUtils, getVersion(StrEq(psuPath)))
3335f3584d4SLei YU .WillOnce(Return(std::string(version)));
334a2c2cd72SLei YU EXPECT_CALL(mockedUtils, getPropertyImpl(_, StrEq(service), StrEq(psuPath),
335a2c2cd72SLei YU _, StrEq(PRESENT)))
336a2c2cd72SLei YU .WillOnce(Return(any(PropertyType(true)))); // present
337*760053d8SFaisal Awada EXPECT_CALL(mockedUtils, getPropertyImpl(_, StrEq(service), StrEq(psuPath),
338*760053d8SFaisal Awada _, StrEq(MODEL)))
339*760053d8SFaisal Awada .WillOnce(Return(any(PropertyType(std::string("dummyModel")))));
340a2c2cd72SLei YU
341a2c2cd72SLei YU // The item updater itself
342a2c2cd72SLei YU EXPECT_CALL(sdbusMock, sd_bus_emit_object_added(_, StrEq(dBusPath)))
343a2c2cd72SLei YU .Times(1);
344a2c2cd72SLei YU
345a2c2cd72SLei YU // activation and version object will be added
346a2c2cd72SLei YU EXPECT_CALL(sdbusMock, sd_bus_emit_object_added(_, StrEq(objPath)))
347a2c2cd72SLei YU .Times(2);
348a2c2cd72SLei YU itemUpdater = std::make_unique<ItemUpdater>(mockedBus, dBusPath);
349a2c2cd72SLei YU
350a2c2cd72SLei YU // the activation and version object will be removed
351a2c2cd72SLei YU EXPECT_CALL(sdbusMock, sd_bus_emit_object_removed(_, StrEq(objPath)))
352a2c2cd72SLei YU .Times(2);
353a2c2cd72SLei YU onPsuInventoryChanged(psuPath, propRemoved);
354a2c2cd72SLei YU
355dcaf8934SLei YU EXPECT_CALL(mockedUtils, getVersion(StrEq(psuPath)))
356dcaf8934SLei YU .WillOnce(Return(std::string(version)));
357a2c2cd72SLei YU EXPECT_CALL(sdbusMock, sd_bus_emit_object_added(_, StrEq(objPath)))
358a2c2cd72SLei YU .Times(2);
3591517f5f6SLei YU
3601517f5f6SLei YU // On PSU inserted, it shall check if it's the latest version
3611517f5f6SLei YU std::set<std::string> expectedVersions = {version};
3621517f5f6SLei YU EXPECT_CALL(mockedUtils, getLatestVersion(ContainerEq(expectedVersions)))
3631517f5f6SLei YU .WillOnce(Return(version));
3641517f5f6SLei YU EXPECT_CALL(mockedUtils, isAssociated(StrEq(psuPath), _))
3651517f5f6SLei YU .WillOnce(Return(true));
3661517f5f6SLei YU EXPECT_CALL(sdbusMock, sd_bus_message_new_method_call(_, _, _, _, _,
3671517f5f6SLei YU StrEq("StartUnit")))
3681517f5f6SLei YU .Times(0);
369a2c2cd72SLei YU onPsuInventoryChanged(psuPath, propAdded);
3701517f5f6SLei YU onPsuInventoryChanged(psuPath, propModel);
371a2c2cd72SLei YU
372a2c2cd72SLei YU // on exit, objects are removed
373a2c2cd72SLei YU EXPECT_CALL(sdbusMock, sd_bus_emit_object_removed(_, StrEq(objPath)))
374a2c2cd72SLei YU .Times(2);
375a2c2cd72SLei YU EXPECT_CALL(sdbusMock, sd_bus_emit_object_removed(_, StrEq(dBusPath)))
376a2c2cd72SLei YU .Times(1);
377a2c2cd72SLei YU }
378a2c2cd72SLei YU
TEST_F(TestItemUpdater,TwoPSUsWithSameVersionRemovedAndAddedWithDifferntVersion)379a2c2cd72SLei YU TEST_F(TestItemUpdater,
380a2c2cd72SLei YU TwoPSUsWithSameVersionRemovedAndAddedWithDifferntVersion)
381a2c2cd72SLei YU {
382a2c2cd72SLei YU constexpr auto psu0 = "/com/example/inventory/psu0";
383a2c2cd72SLei YU constexpr auto psu1 = "/com/example/inventory/psu1";
384a2c2cd72SLei YU constexpr auto service = "com.example.Software.Psu";
385a2c2cd72SLei YU auto version0 = std::string("version0");
386a2c2cd72SLei YU auto version1 = std::string("version0");
387a2c2cd72SLei YU auto objPath0 = getObjPath(version0);
388a2c2cd72SLei YU auto objPath1 = getObjPath(version1);
389a2c2cd72SLei YU
390a2c2cd72SLei YU EXPECT_CALL(mockedUtils, getPSUInventoryPath(_))
391a2c2cd72SLei YU .WillOnce(Return(std::vector<std::string>({psu0, psu1})));
392a2c2cd72SLei YU EXPECT_CALL(mockedUtils, getService(_, StrEq(psu0), _))
393a2c2cd72SLei YU .WillOnce(Return(service));
394a2c2cd72SLei YU EXPECT_CALL(mockedUtils, getService(_, StrEq(psu1), _))
395a2c2cd72SLei YU .WillOnce(Return(service));
3965f3584d4SLei YU EXPECT_CALL(mockedUtils, getVersion(StrEq(psu0)))
3975f3584d4SLei YU .WillOnce(Return(std::string(version0)));
398a2c2cd72SLei YU EXPECT_CALL(mockedUtils, getPropertyImpl(_, StrEq(service), StrEq(psu0), _,
399a2c2cd72SLei YU StrEq(PRESENT)))
400a2c2cd72SLei YU .WillOnce(Return(any(PropertyType(true)))); // present
401*760053d8SFaisal Awada EXPECT_CALL(mockedUtils, getPropertyImpl(_, StrEq(service), StrEq(psu0), _,
402*760053d8SFaisal Awada StrEq(MODEL)))
403*760053d8SFaisal Awada .WillOnce(Return(any(PropertyType(std::string("dummyModel0")))));
4045f3584d4SLei YU EXPECT_CALL(mockedUtils, getVersion(StrEq(psu1)))
4055f3584d4SLei YU .WillOnce(Return(std::string(version1)));
406a2c2cd72SLei YU EXPECT_CALL(mockedUtils, getPropertyImpl(_, StrEq(service), StrEq(psu1), _,
407a2c2cd72SLei YU StrEq(PRESENT)))
408a2c2cd72SLei YU .WillOnce(Return(any(PropertyType(true)))); // present
409*760053d8SFaisal Awada EXPECT_CALL(mockedUtils, getPropertyImpl(_, StrEq(service), StrEq(psu1), _,
410*760053d8SFaisal Awada StrEq(MODEL)))
411*760053d8SFaisal Awada .WillOnce(Return(any(PropertyType(std::string("dummyModel1")))));
412a2c2cd72SLei YU
413a2c2cd72SLei YU // The item updater itself
414a2c2cd72SLei YU EXPECT_CALL(sdbusMock, sd_bus_emit_object_added(_, StrEq(dBusPath)))
415a2c2cd72SLei YU .Times(1);
416a2c2cd72SLei YU
417a2c2cd72SLei YU // activation and version object will be added
418a2c2cd72SLei YU EXPECT_CALL(sdbusMock, sd_bus_emit_object_added(_, StrEq(objPath0)))
419a2c2cd72SLei YU .Times(2);
420a2c2cd72SLei YU itemUpdater = std::make_unique<ItemUpdater>(mockedBus, dBusPath);
421a2c2cd72SLei YU
422a2c2cd72SLei YU // Verify there is only one activation and it has two associations
423a2c2cd72SLei YU const auto& activations = GetActivations();
424a2c2cd72SLei YU EXPECT_EQ(1u, activations.size());
425a2c2cd72SLei YU const auto& activation = activations.find(version0)->second;
426a2c2cd72SLei YU auto assocs = activation->associations();
427a2c2cd72SLei YU EXPECT_EQ(2u, assocs.size());
428a2c2cd72SLei YU EXPECT_EQ(psu0, std::get<2>(assocs[0]));
429a2c2cd72SLei YU EXPECT_EQ(psu1, std::get<2>(assocs[1]));
430a2c2cd72SLei YU
431a2c2cd72SLei YU // PSU0 is removed, only associations shall be updated
432a2c2cd72SLei YU onPsuInventoryChanged(psu0, propRemoved);
433a2c2cd72SLei YU assocs = activation->associations();
434a2c2cd72SLei YU EXPECT_EQ(1u, assocs.size());
435a2c2cd72SLei YU EXPECT_EQ(psu1, std::get<2>(assocs[0]));
436a2c2cd72SLei YU
437a2c2cd72SLei YU // PSU1 is removed, the activation and version object shall be removed
438a2c2cd72SLei YU EXPECT_CALL(sdbusMock, sd_bus_emit_object_removed(_, StrEq(objPath0)))
439a2c2cd72SLei YU .Times(2);
440a2c2cd72SLei YU onPsuInventoryChanged(psu1, propRemoved);
441a2c2cd72SLei YU
442a2c2cd72SLei YU // Add PSU0 and PSU1 back, but PSU1 with a different version
443a2c2cd72SLei YU version1 = "version1";
444a2c2cd72SLei YU objPath1 = getObjPath(version1);
445dcaf8934SLei YU EXPECT_CALL(mockedUtils, getVersion(StrEq(psu0)))
446dcaf8934SLei YU .WillOnce(Return(std::string(version0)));
447dcaf8934SLei YU EXPECT_CALL(mockedUtils, getVersion(StrEq(psu1)))
448dcaf8934SLei YU .WillOnce(Return(std::string(version1)));
449a2c2cd72SLei YU EXPECT_CALL(sdbusMock, sd_bus_emit_object_added(_, StrEq(objPath0)))
450a2c2cd72SLei YU .Times(2);
451a2c2cd72SLei YU EXPECT_CALL(sdbusMock, sd_bus_emit_object_added(_, StrEq(objPath1)))
452a2c2cd72SLei YU .Times(2);
4531517f5f6SLei YU onPsuInventoryChanged(psu0, propAdded);
4541517f5f6SLei YU onPsuInventoryChanged(psu1, propModel);
4551517f5f6SLei YU onPsuInventoryChanged(psu1, propAdded);
4561517f5f6SLei YU onPsuInventoryChanged(psu0, propModel);
457a2c2cd72SLei YU
458a2c2cd72SLei YU // on exit, objects are removed
459a2c2cd72SLei YU EXPECT_CALL(sdbusMock, sd_bus_emit_object_removed(_, StrEq(objPath0)))
460a2c2cd72SLei YU .Times(2);
461a2c2cd72SLei YU EXPECT_CALL(sdbusMock, sd_bus_emit_object_removed(_, StrEq(objPath1)))
462a2c2cd72SLei YU .Times(2);
463a2c2cd72SLei YU EXPECT_CALL(sdbusMock, sd_bus_emit_object_removed(_, StrEq(dBusPath)))
464a2c2cd72SLei YU .Times(1);
465a2c2cd72SLei YU }
46658c26e3fSLei YU
TEST_F(TestItemUpdater,scanDirOnNoPSU)46758c26e3fSLei YU TEST_F(TestItemUpdater, scanDirOnNoPSU)
46858c26e3fSLei YU {
46958c26e3fSLei YU constexpr auto psuPath = "/com/example/inventory/psu0";
47058c26e3fSLei YU constexpr auto service = "com.example.Software.Psu";
47158c26e3fSLei YU constexpr auto version = "version0";
47258c26e3fSLei YU std::string objPath = getObjPath(version);
47358c26e3fSLei YU EXPECT_CALL(mockedUtils, getPSUInventoryPath(_))
47458c26e3fSLei YU .WillOnce(Return(std::vector<std::string>({psuPath})));
47558c26e3fSLei YU EXPECT_CALL(mockedUtils, getService(_, StrEq(psuPath), _))
47658c26e3fSLei YU .WillOnce(Return(service));
47758c26e3fSLei YU EXPECT_CALL(mockedUtils, getVersion(StrEq(psuPath)))
47858c26e3fSLei YU .WillOnce(Return(std::string(version)));
47958c26e3fSLei YU EXPECT_CALL(mockedUtils, getPropertyImpl(_, StrEq(service), StrEq(psuPath),
48058c26e3fSLei YU _, StrEq(PRESENT)))
48158c26e3fSLei YU .WillOnce(Return(any(PropertyType(false)))); // not present
482*760053d8SFaisal Awada EXPECT_CALL(mockedUtils, getPropertyImpl(_, StrEq(service), StrEq(psuPath),
483*760053d8SFaisal Awada _, StrEq(MODEL)))
484*760053d8SFaisal Awada .WillOnce(Return(any(PropertyType(std::string("")))));
48558c26e3fSLei YU
48658c26e3fSLei YU // The item updater itself
48758c26e3fSLei YU EXPECT_CALL(sdbusMock, sd_bus_emit_object_added(_, StrEq(dBusPath)))
48858c26e3fSLei YU .Times(1);
48958c26e3fSLei YU
49058c26e3fSLei YU // No activation/version objects are created
49158c26e3fSLei YU EXPECT_CALL(sdbusMock, sd_bus_emit_object_added(_, StrEq(objPath)))
49258c26e3fSLei YU .Times(0);
49358c26e3fSLei YU itemUpdater = std::make_unique<ItemUpdater>(mockedBus, dBusPath);
49458c26e3fSLei YU
49558c26e3fSLei YU // The valid image in test/psu-images-one-valid-one-invalid/model-1/
49658c26e3fSLei YU auto objPathValid = getObjPath("psu-test.v0.4");
49758c26e3fSLei YU auto objPathInvalid = getObjPath("psu-test.v0.5");
49858c26e3fSLei YU // activation and version object will be added on scan dir
49958c26e3fSLei YU EXPECT_CALL(sdbusMock, sd_bus_emit_object_added(_, StrEq(objPathValid)))
500*760053d8SFaisal Awada .Times(0);
50158c26e3fSLei YU EXPECT_CALL(sdbusMock, sd_bus_emit_object_added(_, StrEq(objPathInvalid)))
50258c26e3fSLei YU .Times(0);
50358c26e3fSLei YU scanDirectory("./psu-images-one-valid-one-invalid");
50458c26e3fSLei YU }
50558c26e3fSLei YU
TEST_F(TestItemUpdater,scanDirOnSamePSUVersion)50658c26e3fSLei YU TEST_F(TestItemUpdater, scanDirOnSamePSUVersion)
50758c26e3fSLei YU {
50858c26e3fSLei YU constexpr auto psuPath = "/com/example/inventory/psu0";
50958c26e3fSLei YU constexpr auto service = "com.example.Software.Psu";
51058c26e3fSLei YU constexpr auto version = "version0";
51158c26e3fSLei YU std::string objPath = getObjPath(version);
51258c26e3fSLei YU EXPECT_CALL(mockedUtils, getPSUInventoryPath(_))
51358c26e3fSLei YU .WillOnce(Return(std::vector<std::string>({psuPath})));
51458c26e3fSLei YU EXPECT_CALL(mockedUtils, getService(_, StrEq(psuPath), _))
51558c26e3fSLei YU .WillOnce(Return(service));
51658c26e3fSLei YU EXPECT_CALL(mockedUtils, getVersion(StrEq(psuPath)))
51758c26e3fSLei YU .WillOnce(Return(std::string(version)));
51858c26e3fSLei YU EXPECT_CALL(mockedUtils, getPropertyImpl(_, StrEq(service), StrEq(psuPath),
51958c26e3fSLei YU _, StrEq(PRESENT)))
52058c26e3fSLei YU .WillOnce(Return(any(PropertyType(true)))); // present
521*760053d8SFaisal Awada EXPECT_CALL(mockedUtils, getPropertyImpl(_, StrEq(service), StrEq(psuPath),
522*760053d8SFaisal Awada _, StrEq(MODEL)))
523*760053d8SFaisal Awada .WillOnce(Return(any(PropertyType(std::string("dummyModel")))));
52458c26e3fSLei YU
52558c26e3fSLei YU // The item updater itself
52658c26e3fSLei YU EXPECT_CALL(sdbusMock, sd_bus_emit_object_added(_, StrEq(dBusPath)))
52758c26e3fSLei YU .Times(1);
52858c26e3fSLei YU
52958c26e3fSLei YU // activation and version object will be added
53058c26e3fSLei YU EXPECT_CALL(sdbusMock, sd_bus_emit_object_added(_, StrEq(objPath)))
53158c26e3fSLei YU .Times(2);
53258c26e3fSLei YU itemUpdater = std::make_unique<ItemUpdater>(mockedBus, dBusPath);
53358c26e3fSLei YU
53458c26e3fSLei YU // The valid image in test/psu-images-valid-version0/model-3/ has the same
53558c26e3fSLei YU // version as the running PSU, so no objects will be created, but only the
53658c26e3fSLei YU // path will be set to the version object
53758c26e3fSLei YU EXPECT_CALL(sdbusMock, sd_bus_emit_object_added(_, StrEq(objPath)))
53858c26e3fSLei YU .Times(0);
53958c26e3fSLei YU EXPECT_CALL(sdbusMock, sd_bus_emit_properties_changed_strv(
54058c26e3fSLei YU _, StrEq(objPath),
54158c26e3fSLei YU StrEq("xyz.openbmc_project.Common.FilePath"),
54258c26e3fSLei YU Pointee(StrEq("Path"))))
543*760053d8SFaisal Awada .Times(0);
54458c26e3fSLei YU scanDirectory("./psu-images-valid-version0");
54558c26e3fSLei YU }
546ffb36539SLei YU
TEST_F(TestItemUpdater,OnUpdateDoneOnTwoPSUsWithSameVersion)547ffb36539SLei YU TEST_F(TestItemUpdater, OnUpdateDoneOnTwoPSUsWithSameVersion)
548ffb36539SLei YU {
549ffb36539SLei YU // Simulate there are two PSUs with same version, and updated to a new
550ffb36539SLei YU // version
551ffb36539SLei YU constexpr auto psu0 = "/com/example/inventory/psu0";
552ffb36539SLei YU constexpr auto psu1 = "/com/example/inventory/psu1";
553ffb36539SLei YU constexpr auto service = "com.example.Software.Psu";
554ffb36539SLei YU auto version0 = std::string("version0");
555ffb36539SLei YU auto version1 = std::string("version0");
556ffb36539SLei YU auto objPath0 = getObjPath(version0);
557ffb36539SLei YU auto objPath1 = getObjPath(version1);
558ffb36539SLei YU
559ffb36539SLei YU EXPECT_CALL(mockedUtils, getPSUInventoryPath(_))
560ffb36539SLei YU .WillOnce(Return(std::vector<std::string>({psu0, psu1})));
561ffb36539SLei YU EXPECT_CALL(mockedUtils, getService(_, StrEq(psu0), _))
562ffb36539SLei YU .WillOnce(Return(service));
563ffb36539SLei YU EXPECT_CALL(mockedUtils, getService(_, StrEq(psu1), _))
564ffb36539SLei YU .WillOnce(Return(service));
565ffb36539SLei YU EXPECT_CALL(mockedUtils, getVersion(StrEq(psu0)))
566ffb36539SLei YU .WillOnce(Return(std::string(version0)));
567ffb36539SLei YU EXPECT_CALL(mockedUtils, getPropertyImpl(_, StrEq(service), StrEq(psu0), _,
568ffb36539SLei YU StrEq(PRESENT)))
569ffb36539SLei YU .WillOnce(Return(any(PropertyType(true)))); // present
570*760053d8SFaisal Awada EXPECT_CALL(mockedUtils, getPropertyImpl(_, StrEq(service), StrEq(psu0), _,
571*760053d8SFaisal Awada StrEq(MODEL)))
572*760053d8SFaisal Awada .WillOnce(Return(any(PropertyType(std::string("dummyModel0")))));
573ffb36539SLei YU EXPECT_CALL(mockedUtils, getVersion(StrEq(psu1)))
574ffb36539SLei YU .WillOnce(Return(std::string(version1)));
575ffb36539SLei YU EXPECT_CALL(mockedUtils, getPropertyImpl(_, StrEq(service), StrEq(psu1), _,
576ffb36539SLei YU StrEq(PRESENT)))
577ffb36539SLei YU .WillOnce(Return(any(PropertyType(true)))); // present
578*760053d8SFaisal Awada EXPECT_CALL(mockedUtils, getPropertyImpl(_, StrEq(service), StrEq(psu1), _,
579*760053d8SFaisal Awada StrEq(MODEL)))
580*760053d8SFaisal Awada .WillOnce(Return(any(PropertyType(std::string("dummyModel1")))));
581ffb36539SLei YU
582ffb36539SLei YU itemUpdater = std::make_unique<ItemUpdater>(mockedBus, dBusPath);
583ffb36539SLei YU
5841517f5f6SLei YU std::string newVersionId = "NewVersionId";
5851517f5f6SLei YU AssociationList associations;
5861517f5f6SLei YU auto dummyActivation = std::make_unique<Activation>(
5871517f5f6SLei YU mockedBus, dBusPath, newVersionId, "", Activation::Status::Active,
5881517f5f6SLei YU associations, "", itemUpdater.get(), itemUpdater.get());
5891517f5f6SLei YU
590ffb36539SLei YU // Now there is one activation and it has two associations
591ffb36539SLei YU auto& activations = GetActivations();
5921517f5f6SLei YU activations.emplace(newVersionId, std::move(dummyActivation));
593ffb36539SLei YU auto& activation = activations.find(version0)->second;
594ffb36539SLei YU auto assocs = activation->associations();
595ffb36539SLei YU EXPECT_EQ(2u, assocs.size());
596ffb36539SLei YU EXPECT_EQ(psu0, std::get<2>(assocs[0]));
597ffb36539SLei YU EXPECT_EQ(psu1, std::get<2>(assocs[1]));
598ffb36539SLei YU
599ffb36539SLei YU EXPECT_CALL(mockedUtils, isAssociated(StrEq(psu0), _))
600ffb36539SLei YU .WillOnce(Return(true));
6011517f5f6SLei YU itemUpdater->onUpdateDone(newVersionId, psu0);
602ffb36539SLei YU
60333cf9f08SManojkiran Eda // Now the activation should have one association
604ffb36539SLei YU assocs = activation->associations();
605ffb36539SLei YU EXPECT_EQ(1u, assocs.size());
606ffb36539SLei YU EXPECT_EQ(psu1, std::get<2>(assocs[0]));
607ffb36539SLei YU
608ffb36539SLei YU EXPECT_CALL(mockedUtils, isAssociated(StrEq(psu1), _))
609ffb36539SLei YU .WillOnce(Return(true));
6101517f5f6SLei YU itemUpdater->onUpdateDone(newVersionId, psu1);
611ffb36539SLei YU
6121517f5f6SLei YU // Now the activation shall be erased and only the dummy one is left
6131517f5f6SLei YU EXPECT_EQ(1u, activations.size());
6141517f5f6SLei YU EXPECT_NE(activations.find(newVersionId), activations.end());
615ffb36539SLei YU }
616ffb36539SLei YU
TEST_F(TestItemUpdater,OnUpdateDoneOnTwoPSUsWithDifferentVersion)617ffb36539SLei YU TEST_F(TestItemUpdater, OnUpdateDoneOnTwoPSUsWithDifferentVersion)
618ffb36539SLei YU {
619ffb36539SLei YU // Simulate there are two PSUs with different version, and updated to a new
620ffb36539SLei YU // version
621ffb36539SLei YU constexpr auto psu0 = "/com/example/inventory/psu0";
622ffb36539SLei YU constexpr auto psu1 = "/com/example/inventory/psu1";
623ffb36539SLei YU constexpr auto service = "com.example.Software.Psu";
624ffb36539SLei YU auto version0 = std::string("version0");
625ffb36539SLei YU auto version1 = std::string("version1");
626ffb36539SLei YU auto objPath0 = getObjPath(version0);
627ffb36539SLei YU auto objPath1 = getObjPath(version1);
628ffb36539SLei YU
629ffb36539SLei YU EXPECT_CALL(mockedUtils, getPSUInventoryPath(_))
630ffb36539SLei YU .WillOnce(Return(std::vector<std::string>({psu0, psu1})));
631ffb36539SLei YU EXPECT_CALL(mockedUtils, getService(_, StrEq(psu0), _))
632ffb36539SLei YU .WillOnce(Return(service));
633ffb36539SLei YU EXPECT_CALL(mockedUtils, getService(_, StrEq(psu1), _))
634ffb36539SLei YU .WillOnce(Return(service));
635ffb36539SLei YU EXPECT_CALL(mockedUtils, getVersion(StrEq(psu0)))
636ffb36539SLei YU .WillOnce(Return(std::string(version0)));
637ffb36539SLei YU EXPECT_CALL(mockedUtils, getPropertyImpl(_, StrEq(service), StrEq(psu0), _,
638ffb36539SLei YU StrEq(PRESENT)))
639ffb36539SLei YU .WillOnce(Return(any(PropertyType(true)))); // present
640*760053d8SFaisal Awada EXPECT_CALL(mockedUtils, getPropertyImpl(_, StrEq(service), StrEq(psu0), _,
641*760053d8SFaisal Awada StrEq(MODEL)))
642*760053d8SFaisal Awada .WillOnce(Return(any(PropertyType(std::string("dummyModel0")))));
643ffb36539SLei YU EXPECT_CALL(mockedUtils, getVersion(StrEq(psu1)))
644ffb36539SLei YU .WillOnce(Return(std::string(version1)));
645ffb36539SLei YU EXPECT_CALL(mockedUtils, getPropertyImpl(_, StrEq(service), StrEq(psu1), _,
646ffb36539SLei YU StrEq(PRESENT)))
647ffb36539SLei YU .WillOnce(Return(any(PropertyType(true)))); // present
648*760053d8SFaisal Awada EXPECT_CALL(mockedUtils, getPropertyImpl(_, StrEq(service), StrEq(psu1), _,
649*760053d8SFaisal Awada StrEq(MODEL)))
650*760053d8SFaisal Awada .WillOnce(Return(any(PropertyType(std::string("dummyModel1")))));
651ffb36539SLei YU
652ffb36539SLei YU itemUpdater = std::make_unique<ItemUpdater>(mockedBus, dBusPath);
653ffb36539SLei YU
6541517f5f6SLei YU std::string newVersionId = "NewVersionId";
6551517f5f6SLei YU AssociationList associations;
6561517f5f6SLei YU auto dummyActivation = std::make_unique<Activation>(
6571517f5f6SLei YU mockedBus, dBusPath, newVersionId, "", Activation::Status::Active,
6581517f5f6SLei YU associations, "", itemUpdater.get(), itemUpdater.get());
6591517f5f6SLei YU
6601517f5f6SLei YU auto& activations = GetActivations();
6611517f5f6SLei YU activations.emplace(newVersionId, std::move(dummyActivation));
662ffb36539SLei YU
663ffb36539SLei YU EXPECT_CALL(mockedUtils, isAssociated(StrEq(psu0), _))
664ffb36539SLei YU .WillOnce(Return(true));
6651517f5f6SLei YU
6661517f5f6SLei YU // After psu0 is done, two activations should be left
6671517f5f6SLei YU itemUpdater->onUpdateDone(newVersionId, psu0);
6681517f5f6SLei YU EXPECT_EQ(2u, activations.size());
669ffb36539SLei YU const auto& activation1 = activations.find(version1)->second;
670ffb36539SLei YU const auto& assocs1 = activation1->associations();
671ffb36539SLei YU EXPECT_EQ(1u, assocs1.size());
672ffb36539SLei YU EXPECT_EQ(psu1, std::get<2>(assocs1[0]));
673ffb36539SLei YU
674ffb36539SLei YU EXPECT_CALL(mockedUtils, isAssociated(StrEq(psu1), _))
675ffb36539SLei YU .WillOnce(Return(true));
6761517f5f6SLei YU // After psu1 is done, only the dummy activation should be left
6771517f5f6SLei YU itemUpdater->onUpdateDone(newVersionId, psu1);
6781517f5f6SLei YU EXPECT_EQ(1u, activations.size());
6791517f5f6SLei YU EXPECT_NE(activations.find(newVersionId), activations.end());
6801517f5f6SLei YU }
6811517f5f6SLei YU
TEST_F(TestItemUpdater,OnOnePSURemovedAndAddedWithOldVersion)6821517f5f6SLei YU TEST_F(TestItemUpdater, OnOnePSURemovedAndAddedWithOldVersion)
6831517f5f6SLei YU {
6841517f5f6SLei YU constexpr auto psuPath = "/com/example/inventory/psu0";
6851517f5f6SLei YU constexpr auto service = "com.example.Software.Psu";
6861517f5f6SLei YU constexpr auto version = "version0";
6871517f5f6SLei YU std::string versionId =
6881517f5f6SLei YU version; // In testing versionId is the same as version
6891517f5f6SLei YU std::string objPath = getObjPath(version);
6901517f5f6SLei YU ON_CALL(mockedUtils, getPSUInventoryPath(_))
6911517f5f6SLei YU .WillByDefault(Return(std::vector<std::string>({psuPath})));
692*760053d8SFaisal Awada EXPECT_CALL(mockedUtils, getService(_, StrEq(psuPath), _))
693*760053d8SFaisal Awada .WillOnce(Return(service))
694*760053d8SFaisal Awada .WillOnce(Return(service));
6951517f5f6SLei YU EXPECT_CALL(mockedUtils, getVersion(StrEq(psuPath)))
6961517f5f6SLei YU .WillOnce(Return(std::string(version)));
6971517f5f6SLei YU ON_CALL(mockedUtils, getPropertyImpl(_, StrEq(service), StrEq(psuPath), _,
6981517f5f6SLei YU StrEq(PRESENT)))
6991517f5f6SLei YU .WillByDefault(Return(any(PropertyType(true)))); // present
700*760053d8SFaisal Awada ON_CALL(mockedUtils,
701*760053d8SFaisal Awada getPropertyImpl(_, StrEq(service), StrEq(psuPath), _, StrEq(MODEL)))
702*760053d8SFaisal Awada .WillByDefault(Return(any(PropertyType(std::string("dummyModel")))));
7031517f5f6SLei YU itemUpdater = std::make_unique<ItemUpdater>(mockedBus, dBusPath);
7041517f5f6SLei YU
7051517f5f6SLei YU // Add an association to simulate that it has image in BMC filesystem
7061517f5f6SLei YU auto& activation = GetActivations().find(versionId)->second;
7071517f5f6SLei YU auto assocs = activation->associations();
7081517f5f6SLei YU assocs.emplace_back(ACTIVATION_FWD_ASSOCIATION, ACTIVATION_REV_ASSOCIATION,
7091517f5f6SLei YU "SomePath");
7101517f5f6SLei YU activation->associations(assocs);
7111517f5f6SLei YU activation->path("SomeFilePath");
7121517f5f6SLei YU
7131517f5f6SLei YU onPsuInventoryChanged(psuPath, propRemoved);
7141517f5f6SLei YU
7151517f5f6SLei YU // On PSU inserted, it checks and finds a newer version
7161517f5f6SLei YU auto oldVersion = "old-version";
7171517f5f6SLei YU EXPECT_CALL(mockedUtils, getVersion(StrEq(psuPath)))
7181517f5f6SLei YU .WillOnce(Return(std::string(oldVersion)));
7191517f5f6SLei YU EXPECT_CALL(mockedUtils, getPropertyImpl(_, StrEq(service), StrEq(psuPath),
7201517f5f6SLei YU _, StrEq(MANUFACTURER)))
7211517f5f6SLei YU .WillOnce(
7221517f5f6SLei YU Return(any(PropertyType(std::string(""))))); // Checking compatible
7231517f5f6SLei YU EXPECT_CALL(mockedUtils, getPropertyImpl(_, StrEq(service), StrEq(psuPath),
7241517f5f6SLei YU _, StrEq(MODEL)))
7251517f5f6SLei YU .WillOnce(
7261517f5f6SLei YU Return(any(PropertyType(std::string(""))))); // Checking compatible
7271517f5f6SLei YU std::set<std::string> expectedVersions = {version, oldVersion};
7281517f5f6SLei YU EXPECT_CALL(mockedUtils, getLatestVersion(ContainerEq(expectedVersions)))
7291517f5f6SLei YU .WillOnce(Return(version));
7301517f5f6SLei YU ON_CALL(mockedUtils, isAssociated(StrEq(psuPath), _))
7311517f5f6SLei YU .WillByDefault(Return(false));
7321517f5f6SLei YU EXPECT_CALL(sdbusMock, sd_bus_message_new_method_call(_, _, _, _, _,
7331517f5f6SLei YU StrEq("StartUnit")))
7348afeee56SLei YU .Times(3); // There are 3 systemd units are started, enable bmc reboot
7358afeee56SLei YU // guard, start activation, and disable bmc reboot guard
7361517f5f6SLei YU onPsuInventoryChanged(psuPath, propAdded);
7371517f5f6SLei YU onPsuInventoryChanged(psuPath, propModel);
738ffb36539SLei YU }
739