blob: cbea53c374dc80a92a27c0d13ded569eb39e096c [file] [log] [blame]
Lei YUf77189f2019-08-07 14:26:30 +08001#include "item_updater.hpp"
2#include "mocked_utils.hpp"
3
4#include <sdbusplus/test/sdbus_mock.hpp>
5
6#include <gmock/gmock.h>
7#include <gtest/gtest.h>
8
9using namespace phosphor::software::updater;
10using ::testing::_;
Lei YU58c26e32019-09-27 17:52:06 +080011using ::testing::Pointee;
Lei YUf77189f2019-08-07 14:26:30 +080012using ::testing::Return;
13using ::testing::ReturnArg;
14using ::testing::StrEq;
15
16using std::experimental::any;
Lei YUf77189f2019-08-07 14:26:30 +080017
18class TestItemUpdater : public ::testing::Test
19{
20 public:
Lei YUa2c2cd72019-08-09 15:54:10 +080021 using Properties = ItemUpdater::Properties;
22 using PropertyType = utils::UtilsInterface::PropertyType;
23
Lei YUf77189f2019-08-07 14:26:30 +080024 TestItemUpdater() :
25 mockedUtils(
26 reinterpret_cast<const utils::MockedUtils&>(utils::getUtils()))
27 {
28 ON_CALL(mockedUtils, getVersionId(_)).WillByDefault(ReturnArg<0>());
Lei YUff83c2a2019-09-12 13:55:18 +080029 ON_CALL(mockedUtils, getPropertyImpl(_, _, _, _, StrEq(PRESENT)))
30 .WillByDefault(Return(any(PropertyType(true))));
Lei YUf77189f2019-08-07 14:26:30 +080031 }
32
33 ~TestItemUpdater()
34 {
Lei YUc09155b2019-10-11 17:30:48 +080035 utils::freeUtils();
Lei YUf77189f2019-08-07 14:26:30 +080036 }
37
38 const auto& GetActivations()
39 {
40 return itemUpdater->activations;
41 }
42
43 std::string getObjPath(const std::string& versionId)
44 {
45 return std::string(dBusPath) + "/" + versionId;
46 }
47
Lei YUa2c2cd72019-08-09 15:54:10 +080048 void onPsuInventoryChanged(const std::string& psuPath,
49 const Properties& properties)
50 {
51 itemUpdater->onPsuInventoryChanged(psuPath, properties);
52 }
53
Lei YU58c26e32019-09-27 17:52:06 +080054 void scanDirectory(const fs::path& p)
55 {
56 itemUpdater->scanDirectory(p);
57 }
58
Lei YUf77189f2019-08-07 14:26:30 +080059 static constexpr auto dBusPath = SOFTWARE_OBJPATH;
60 sdbusplus::SdBusMock sdbusMock;
61 sdbusplus::bus::bus mockedBus = sdbusplus::get_mocked_new(&sdbusMock);
62 const utils::MockedUtils& mockedUtils;
63 std::unique_ptr<ItemUpdater> itemUpdater;
64};
65
66TEST_F(TestItemUpdater, ctordtor)
67{
Lei YU65207482019-10-11 16:39:36 +080068 EXPECT_CALL(mockedUtils, getLatestVersion(_)).Times(1);
Lei YUf77189f2019-08-07 14:26:30 +080069 itemUpdater = std::make_unique<ItemUpdater>(mockedBus, dBusPath);
70}
71
72TEST_F(TestItemUpdater, NotCreateObjectOnNotPresent)
73{
74 constexpr auto psuPath = "/com/example/inventory/psu0";
75 constexpr auto service = "com.example.Software.Psu";
76 constexpr auto version = "version0";
77 std::string objPath = getObjPath(version);
78 EXPECT_CALL(mockedUtils, getPSUInventoryPath(_))
79 .WillOnce(Return(std::vector<std::string>({psuPath})));
80 EXPECT_CALL(mockedUtils, getService(_, StrEq(psuPath), _))
81 .WillOnce(Return(service));
Lei YU5f3584d2019-08-27 16:28:53 +080082 EXPECT_CALL(mockedUtils, getVersion(StrEq(psuPath)))
83 .WillOnce(Return(std::string(version)));
Lei YUf77189f2019-08-07 14:26:30 +080084 EXPECT_CALL(mockedUtils, getPropertyImpl(_, StrEq(service), StrEq(psuPath),
85 _, StrEq(PRESENT)))
86 .WillOnce(Return(any(PropertyType(false)))); // not present
87
88 // The item updater itself
89 EXPECT_CALL(sdbusMock, sd_bus_emit_object_added(_, StrEq(dBusPath)))
90 .Times(1);
91
92 // No activation/version objects are created
93 EXPECT_CALL(sdbusMock, sd_bus_emit_object_added(_, StrEq(objPath)))
94 .Times(0);
95 itemUpdater = std::make_unique<ItemUpdater>(mockedBus, dBusPath);
96}
97
98TEST_F(TestItemUpdater, CreateOnePSUOnPresent)
99{
100 constexpr auto psuPath = "/com/example/inventory/psu0";
101 constexpr auto service = "com.example.Software.Psu";
102 constexpr auto version = "version0";
103 std::string objPath = getObjPath(version);
104 EXPECT_CALL(mockedUtils, getPSUInventoryPath(_))
105 .WillOnce(Return(std::vector<std::string>({psuPath})));
106 EXPECT_CALL(mockedUtils, getService(_, StrEq(psuPath), _))
107 .WillOnce(Return(service));
Lei YU5f3584d2019-08-27 16:28:53 +0800108 EXPECT_CALL(mockedUtils, getVersion(StrEq(psuPath)))
109 .WillOnce(Return(std::string(version)));
Lei YUf77189f2019-08-07 14:26:30 +0800110 EXPECT_CALL(mockedUtils, getPropertyImpl(_, StrEq(service), StrEq(psuPath),
111 _, StrEq(PRESENT)))
112 .WillOnce(Return(any(PropertyType(true)))); // present
113
114 // The item updater itself
115 EXPECT_CALL(sdbusMock, sd_bus_emit_object_added(_, StrEq(dBusPath)))
116 .Times(1);
117
118 // activation and version object will be added
119 EXPECT_CALL(sdbusMock, sd_bus_emit_object_added(_, StrEq(objPath)))
120 .Times(2);
121 itemUpdater = std::make_unique<ItemUpdater>(mockedBus, dBusPath);
122}
123
124TEST_F(TestItemUpdater, CreateTwoPSUsWithSameVersion)
125{
126 constexpr auto psu0 = "/com/example/inventory/psu0";
127 constexpr auto psu1 = "/com/example/inventory/psu1";
128 constexpr auto service = "com.example.Software.Psu";
129 auto version0 = std::string("version0");
130 auto version1 = std::string("version0");
131 auto objPath0 = getObjPath(version0);
132 auto objPath1 = getObjPath(version1);
133
134 EXPECT_CALL(mockedUtils, getPSUInventoryPath(_))
135 .WillOnce(Return(std::vector<std::string>({psu0, psu1})));
136 EXPECT_CALL(mockedUtils, getService(_, StrEq(psu0), _))
137 .WillOnce(Return(service));
138 EXPECT_CALL(mockedUtils, getService(_, StrEq(psu1), _))
139 .WillOnce(Return(service));
Lei YU5f3584d2019-08-27 16:28:53 +0800140 EXPECT_CALL(mockedUtils, getVersion(StrEq(psu0)))
141 .WillOnce(Return(std::string(version0)));
Lei YUf77189f2019-08-07 14:26:30 +0800142 EXPECT_CALL(mockedUtils, getPropertyImpl(_, StrEq(service), StrEq(psu0), _,
143 StrEq(PRESENT)))
144 .WillOnce(Return(any(PropertyType(true)))); // present
Lei YU5f3584d2019-08-27 16:28:53 +0800145 EXPECT_CALL(mockedUtils, getVersion(StrEq(psu1)))
146 .WillOnce(Return(std::string(version1)));
Lei YUf77189f2019-08-07 14:26:30 +0800147 EXPECT_CALL(mockedUtils, getPropertyImpl(_, StrEq(service), StrEq(psu1), _,
148 StrEq(PRESENT)))
149 .WillOnce(Return(any(PropertyType(true)))); // present
150
151 // The item updater itself
152 EXPECT_CALL(sdbusMock, sd_bus_emit_object_added(_, StrEq(dBusPath)))
153 .Times(1);
154
155 // activation and version object will be added
156 EXPECT_CALL(sdbusMock, sd_bus_emit_object_added(_, StrEq(objPath0)))
157 .Times(2);
158 itemUpdater = std::make_unique<ItemUpdater>(mockedBus, dBusPath);
159
160 // Verify there is only one activation and it has two associations
161 const auto& activations = GetActivations();
162 EXPECT_EQ(1u, activations.size());
163 const auto& activation = activations.find(version0)->second;
164 const auto& assocs = activation->associations();
165 EXPECT_EQ(2u, assocs.size());
166 EXPECT_EQ(psu0, std::get<2>(assocs[0]));
167 EXPECT_EQ(psu1, std::get<2>(assocs[1]));
168}
169
170TEST_F(TestItemUpdater, CreateTwoPSUsWithDifferentVersion)
171{
172 constexpr auto psu0 = "/com/example/inventory/psu0";
173 constexpr auto psu1 = "/com/example/inventory/psu1";
174 constexpr auto service = "com.example.Software.Psu";
175 auto version0 = std::string("version0");
176 auto version1 = std::string("version1");
177 auto objPath0 = getObjPath(version0);
178 auto objPath1 = getObjPath(version1);
179
180 EXPECT_CALL(mockedUtils, getPSUInventoryPath(_))
181 .WillOnce(Return(std::vector<std::string>({psu0, psu1})));
182 EXPECT_CALL(mockedUtils, getService(_, StrEq(psu0), _))
183 .WillOnce(Return(service));
184 EXPECT_CALL(mockedUtils, getService(_, StrEq(psu1), _))
185 .WillOnce(Return(service));
Lei YU5f3584d2019-08-27 16:28:53 +0800186 EXPECT_CALL(mockedUtils, getVersion(StrEq(psu0)))
187 .WillOnce(Return(std::string(version0)));
Lei YUf77189f2019-08-07 14:26:30 +0800188 EXPECT_CALL(mockedUtils, getPropertyImpl(_, StrEq(service), StrEq(psu0), _,
189 StrEq(PRESENT)))
190 .WillOnce(Return(any(PropertyType(true)))); // present
Lei YU5f3584d2019-08-27 16:28:53 +0800191 EXPECT_CALL(mockedUtils, getVersion(StrEq(psu1)))
192 .WillOnce(Return(std::string(version1)));
Lei YUf77189f2019-08-07 14:26:30 +0800193 EXPECT_CALL(mockedUtils, getPropertyImpl(_, StrEq(service), StrEq(psu1), _,
194 StrEq(PRESENT)))
195 .WillOnce(Return(any(PropertyType(true)))); // present
196
197 // The item updater itself
198 EXPECT_CALL(sdbusMock, sd_bus_emit_object_added(_, StrEq(dBusPath)))
199 .Times(1);
200
201 // two new activation and version objects will be added
202 EXPECT_CALL(sdbusMock, sd_bus_emit_object_added(_, StrEq(objPath0)))
203 .Times(2);
204 EXPECT_CALL(sdbusMock, sd_bus_emit_object_added(_, StrEq(objPath1)))
205 .Times(2);
206 itemUpdater = std::make_unique<ItemUpdater>(mockedBus, dBusPath);
207
208 // Verify there are two activations and each with one association
209 const auto& activations = GetActivations();
210 EXPECT_EQ(2u, activations.size());
211 const auto& activation0 = activations.find(version0)->second;
212 const auto& assocs0 = activation0->associations();
213 EXPECT_EQ(1u, assocs0.size());
214 EXPECT_EQ(psu0, std::get<2>(assocs0[0]));
215
216 const auto& activation1 = activations.find(version1)->second;
217 const auto& assocs1 = activation1->associations();
218 EXPECT_EQ(1u, assocs1.size());
219 EXPECT_EQ(psu1, std::get<2>(assocs1[0]));
220}
Lei YUa2c2cd72019-08-09 15:54:10 +0800221
222TEST_F(TestItemUpdater, OnOnePSURemoved)
223{
224 constexpr auto psuPath = "/com/example/inventory/psu0";
225 constexpr auto service = "com.example.Software.Psu";
226 constexpr auto version = "version0";
227 std::string objPath = getObjPath(version);
228 EXPECT_CALL(mockedUtils, getPSUInventoryPath(_))
229 .WillOnce(Return(std::vector<std::string>({psuPath})));
230 EXPECT_CALL(mockedUtils, getService(_, StrEq(psuPath), _))
231 .WillOnce(Return(service));
Lei YU5f3584d2019-08-27 16:28:53 +0800232 EXPECT_CALL(mockedUtils, getVersion(StrEq(psuPath)))
233 .WillOnce(Return(std::string(version)));
Lei YUa2c2cd72019-08-09 15:54:10 +0800234 EXPECT_CALL(mockedUtils, getPropertyImpl(_, StrEq(service), StrEq(psuPath),
235 _, StrEq(PRESENT)))
236 .WillOnce(Return(any(PropertyType(true)))); // present
237
238 // The item updater itself
239 EXPECT_CALL(sdbusMock, sd_bus_emit_object_added(_, StrEq(dBusPath)))
240 .Times(1);
241
242 // activation and version object will be added
243 EXPECT_CALL(sdbusMock, sd_bus_emit_object_added(_, StrEq(objPath)))
244 .Times(2);
245 itemUpdater = std::make_unique<ItemUpdater>(mockedBus, dBusPath);
246
247 // the activation and version object will be removed
248 Properties p{{PRESENT, PropertyType(false)}};
249 EXPECT_CALL(sdbusMock, sd_bus_emit_object_removed(_, StrEq(objPath)))
250 .Times(2);
251 onPsuInventoryChanged(psuPath, p);
252
253 // on exit, item updater is removed
254 EXPECT_CALL(sdbusMock, sd_bus_emit_object_removed(_, StrEq(dBusPath)))
255 .Times(1);
256}
257
258TEST_F(TestItemUpdater, OnOnePSUAdded)
259{
260 constexpr auto psuPath = "/com/example/inventory/psu0";
261 constexpr auto service = "com.example.Software.Psu";
262 constexpr auto version = "version0";
263 std::string objPath = getObjPath(version);
264 EXPECT_CALL(mockedUtils, getPSUInventoryPath(_))
265 .WillOnce(Return(std::vector<std::string>({psuPath})));
266 EXPECT_CALL(mockedUtils, getService(_, StrEq(psuPath), _))
267 .WillOnce(Return(service));
Lei YU5f3584d2019-08-27 16:28:53 +0800268 EXPECT_CALL(mockedUtils, getVersion(StrEq(psuPath)))
269 .WillOnce(Return(std::string(version)));
Lei YUa2c2cd72019-08-09 15:54:10 +0800270 EXPECT_CALL(mockedUtils, getPropertyImpl(_, StrEq(service), StrEq(psuPath),
271 _, StrEq(PRESENT)))
272 .WillOnce(Return(any(PropertyType(false)))); // not present
273
274 // The item updater itself
275 EXPECT_CALL(sdbusMock, sd_bus_emit_object_added(_, StrEq(dBusPath)))
276 .Times(1);
277
278 // No activation/version objects are created
279 EXPECT_CALL(sdbusMock, sd_bus_emit_object_added(_, StrEq(objPath)))
280 .Times(0);
281 itemUpdater = std::make_unique<ItemUpdater>(mockedBus, dBusPath);
282
283 // The PSU is present and version is added in a single call
Lei YUdcaf8932019-09-09 16:09:35 +0800284 Properties propAdded{{PRESENT, PropertyType(true)}};
285 EXPECT_CALL(mockedUtils, getVersion(StrEq(psuPath)))
286 .WillOnce(Return(std::string(version)));
Lei YUa2c2cd72019-08-09 15:54:10 +0800287 EXPECT_CALL(sdbusMock, sd_bus_emit_object_added(_, StrEq(objPath)))
288 .Times(2);
289 onPsuInventoryChanged(psuPath, propAdded);
290}
291
292TEST_F(TestItemUpdater, OnOnePSURemovedAndAdded)
293{
294 constexpr auto psuPath = "/com/example/inventory/psu0";
295 constexpr auto service = "com.example.Software.Psu";
296 constexpr auto version = "version0";
297 std::string objPath = getObjPath(version);
298 EXPECT_CALL(mockedUtils, getPSUInventoryPath(_))
299 .WillOnce(Return(std::vector<std::string>({psuPath})));
300 EXPECT_CALL(mockedUtils, getService(_, StrEq(psuPath), _))
301 .WillOnce(Return(service));
Lei YU5f3584d2019-08-27 16:28:53 +0800302 EXPECT_CALL(mockedUtils, getVersion(StrEq(psuPath)))
303 .WillOnce(Return(std::string(version)));
Lei YUa2c2cd72019-08-09 15:54:10 +0800304 EXPECT_CALL(mockedUtils, getPropertyImpl(_, StrEq(service), StrEq(psuPath),
305 _, StrEq(PRESENT)))
306 .WillOnce(Return(any(PropertyType(true)))); // present
307
308 // The item updater itself
309 EXPECT_CALL(sdbusMock, sd_bus_emit_object_added(_, StrEq(dBusPath)))
310 .Times(1);
311
312 // activation and version object will be added
313 EXPECT_CALL(sdbusMock, sd_bus_emit_object_added(_, StrEq(objPath)))
314 .Times(2);
315 itemUpdater = std::make_unique<ItemUpdater>(mockedBus, dBusPath);
316
317 // the activation and version object will be removed
318 Properties propRemoved{{PRESENT, PropertyType(false)}};
319 EXPECT_CALL(sdbusMock, sd_bus_emit_object_removed(_, StrEq(objPath)))
320 .Times(2);
321 onPsuInventoryChanged(psuPath, propRemoved);
322
323 Properties propAdded{{PRESENT, PropertyType(true)}};
Lei YUdcaf8932019-09-09 16:09:35 +0800324 EXPECT_CALL(mockedUtils, getVersion(StrEq(psuPath)))
325 .WillOnce(Return(std::string(version)));
Lei YUa2c2cd72019-08-09 15:54:10 +0800326 EXPECT_CALL(sdbusMock, sd_bus_emit_object_added(_, StrEq(objPath)))
327 .Times(2);
328 onPsuInventoryChanged(psuPath, propAdded);
Lei YUa2c2cd72019-08-09 15:54:10 +0800329
330 // on exit, objects are removed
331 EXPECT_CALL(sdbusMock, sd_bus_emit_object_removed(_, StrEq(objPath)))
332 .Times(2);
333 EXPECT_CALL(sdbusMock, sd_bus_emit_object_removed(_, StrEq(dBusPath)))
334 .Times(1);
335}
336
337TEST_F(TestItemUpdater,
338 TwoPSUsWithSameVersionRemovedAndAddedWithDifferntVersion)
339{
340 constexpr auto psu0 = "/com/example/inventory/psu0";
341 constexpr auto psu1 = "/com/example/inventory/psu1";
342 constexpr auto service = "com.example.Software.Psu";
343 auto version0 = std::string("version0");
344 auto version1 = std::string("version0");
345 auto objPath0 = getObjPath(version0);
346 auto objPath1 = getObjPath(version1);
347
348 EXPECT_CALL(mockedUtils, getPSUInventoryPath(_))
349 .WillOnce(Return(std::vector<std::string>({psu0, psu1})));
350 EXPECT_CALL(mockedUtils, getService(_, StrEq(psu0), _))
351 .WillOnce(Return(service));
352 EXPECT_CALL(mockedUtils, getService(_, StrEq(psu1), _))
353 .WillOnce(Return(service));
Lei YU5f3584d2019-08-27 16:28:53 +0800354 EXPECT_CALL(mockedUtils, getVersion(StrEq(psu0)))
355 .WillOnce(Return(std::string(version0)));
Lei YUa2c2cd72019-08-09 15:54:10 +0800356 EXPECT_CALL(mockedUtils, getPropertyImpl(_, StrEq(service), StrEq(psu0), _,
357 StrEq(PRESENT)))
358 .WillOnce(Return(any(PropertyType(true)))); // present
Lei YU5f3584d2019-08-27 16:28:53 +0800359 EXPECT_CALL(mockedUtils, getVersion(StrEq(psu1)))
360 .WillOnce(Return(std::string(version1)));
Lei YUa2c2cd72019-08-09 15:54:10 +0800361 EXPECT_CALL(mockedUtils, getPropertyImpl(_, StrEq(service), StrEq(psu1), _,
362 StrEq(PRESENT)))
363 .WillOnce(Return(any(PropertyType(true)))); // present
364
365 // The item updater itself
366 EXPECT_CALL(sdbusMock, sd_bus_emit_object_added(_, StrEq(dBusPath)))
367 .Times(1);
368
369 // activation and version object will be added
370 EXPECT_CALL(sdbusMock, sd_bus_emit_object_added(_, StrEq(objPath0)))
371 .Times(2);
372 itemUpdater = std::make_unique<ItemUpdater>(mockedBus, dBusPath);
373
374 // Verify there is only one activation and it has two associations
375 const auto& activations = GetActivations();
376 EXPECT_EQ(1u, activations.size());
377 const auto& activation = activations.find(version0)->second;
378 auto assocs = activation->associations();
379 EXPECT_EQ(2u, assocs.size());
380 EXPECT_EQ(psu0, std::get<2>(assocs[0]));
381 EXPECT_EQ(psu1, std::get<2>(assocs[1]));
382
383 // PSU0 is removed, only associations shall be updated
384 Properties propRemoved{{PRESENT, PropertyType(false)}};
385 onPsuInventoryChanged(psu0, propRemoved);
386 assocs = activation->associations();
387 EXPECT_EQ(1u, assocs.size());
388 EXPECT_EQ(psu1, std::get<2>(assocs[0]));
389
390 // PSU1 is removed, the activation and version object shall be removed
391 EXPECT_CALL(sdbusMock, sd_bus_emit_object_removed(_, StrEq(objPath0)))
392 .Times(2);
393 onPsuInventoryChanged(psu1, propRemoved);
394
395 // Add PSU0 and PSU1 back, but PSU1 with a different version
396 version1 = "version1";
397 objPath1 = getObjPath(version1);
Lei YUdcaf8932019-09-09 16:09:35 +0800398 Properties propAdded0{{PRESENT, PropertyType(true)}};
399 Properties propAdded1{{PRESENT, PropertyType(true)}};
400 EXPECT_CALL(mockedUtils, getVersion(StrEq(psu0)))
401 .WillOnce(Return(std::string(version0)));
402 EXPECT_CALL(mockedUtils, getVersion(StrEq(psu1)))
403 .WillOnce(Return(std::string(version1)));
Lei YUa2c2cd72019-08-09 15:54:10 +0800404 EXPECT_CALL(sdbusMock, sd_bus_emit_object_added(_, StrEq(objPath0)))
405 .Times(2);
406 EXPECT_CALL(sdbusMock, sd_bus_emit_object_added(_, StrEq(objPath1)))
407 .Times(2);
408 onPsuInventoryChanged(psu0, propAdded0);
409 onPsuInventoryChanged(psu1, propAdded1);
410
411 // on exit, objects are removed
412 EXPECT_CALL(sdbusMock, sd_bus_emit_object_removed(_, StrEq(objPath0)))
413 .Times(2);
414 EXPECT_CALL(sdbusMock, sd_bus_emit_object_removed(_, StrEq(objPath1)))
415 .Times(2);
416 EXPECT_CALL(sdbusMock, sd_bus_emit_object_removed(_, StrEq(dBusPath)))
417 .Times(1);
418}
Lei YU58c26e32019-09-27 17:52:06 +0800419
420TEST_F(TestItemUpdater, scanDirOnNoPSU)
421{
422 constexpr auto psuPath = "/com/example/inventory/psu0";
423 constexpr auto service = "com.example.Software.Psu";
424 constexpr auto version = "version0";
425 std::string objPath = getObjPath(version);
426 EXPECT_CALL(mockedUtils, getPSUInventoryPath(_))
427 .WillOnce(Return(std::vector<std::string>({psuPath})));
428 EXPECT_CALL(mockedUtils, getService(_, StrEq(psuPath), _))
429 .WillOnce(Return(service));
430 EXPECT_CALL(mockedUtils, getVersion(StrEq(psuPath)))
431 .WillOnce(Return(std::string(version)));
432 EXPECT_CALL(mockedUtils, getPropertyImpl(_, StrEq(service), StrEq(psuPath),
433 _, StrEq(PRESENT)))
434 .WillOnce(Return(any(PropertyType(false)))); // not present
435
436 // The item updater itself
437 EXPECT_CALL(sdbusMock, sd_bus_emit_object_added(_, StrEq(dBusPath)))
438 .Times(1);
439
440 // No activation/version objects are created
441 EXPECT_CALL(sdbusMock, sd_bus_emit_object_added(_, StrEq(objPath)))
442 .Times(0);
443 itemUpdater = std::make_unique<ItemUpdater>(mockedBus, dBusPath);
444
445 // The valid image in test/psu-images-one-valid-one-invalid/model-1/
446 auto objPathValid = getObjPath("psu-test.v0.4");
447 auto objPathInvalid = getObjPath("psu-test.v0.5");
448 // activation and version object will be added on scan dir
449 EXPECT_CALL(sdbusMock, sd_bus_emit_object_added(_, StrEq(objPathValid)))
450 .Times(2);
451 EXPECT_CALL(sdbusMock, sd_bus_emit_object_added(_, StrEq(objPathInvalid)))
452 .Times(0);
453 scanDirectory("./psu-images-one-valid-one-invalid");
454}
455
456TEST_F(TestItemUpdater, scanDirOnSamePSUVersion)
457{
458 constexpr auto psuPath = "/com/example/inventory/psu0";
459 constexpr auto service = "com.example.Software.Psu";
460 constexpr auto version = "version0";
461 std::string objPath = getObjPath(version);
462 EXPECT_CALL(mockedUtils, getPSUInventoryPath(_))
463 .WillOnce(Return(std::vector<std::string>({psuPath})));
464 EXPECT_CALL(mockedUtils, getService(_, StrEq(psuPath), _))
465 .WillOnce(Return(service));
466 EXPECT_CALL(mockedUtils, getVersion(StrEq(psuPath)))
467 .WillOnce(Return(std::string(version)));
468 EXPECT_CALL(mockedUtils, getPropertyImpl(_, StrEq(service), StrEq(psuPath),
469 _, StrEq(PRESENT)))
470 .WillOnce(Return(any(PropertyType(true)))); // present
471
472 // The item updater itself
473 EXPECT_CALL(sdbusMock, sd_bus_emit_object_added(_, StrEq(dBusPath)))
474 .Times(1);
475
476 // activation and version object will be added
477 EXPECT_CALL(sdbusMock, sd_bus_emit_object_added(_, StrEq(objPath)))
478 .Times(2);
479 itemUpdater = std::make_unique<ItemUpdater>(mockedBus, dBusPath);
480
481 // The valid image in test/psu-images-valid-version0/model-3/ has the same
482 // version as the running PSU, so no objects will be created, but only the
483 // path will be set to the version object
484 EXPECT_CALL(sdbusMock, sd_bus_emit_object_added(_, StrEq(objPath)))
485 .Times(0);
486 EXPECT_CALL(sdbusMock, sd_bus_emit_properties_changed_strv(
487 _, StrEq(objPath),
488 StrEq("xyz.openbmc_project.Common.FilePath"),
489 Pointee(StrEq("Path"))))
490 .Times(1);
491 scanDirectory("./psu-images-valid-version0");
492}
Lei YUffb36532019-10-15 13:55:24 +0800493
494TEST_F(TestItemUpdater, OnUpdateDoneOnTwoPSUsWithSameVersion)
495{
496 // Simulate there are two PSUs with same version, and updated to a new
497 // version
498 constexpr auto psu0 = "/com/example/inventory/psu0";
499 constexpr auto psu1 = "/com/example/inventory/psu1";
500 constexpr auto service = "com.example.Software.Psu";
501 auto version0 = std::string("version0");
502 auto version1 = std::string("version0");
503 auto objPath0 = getObjPath(version0);
504 auto objPath1 = getObjPath(version1);
505
506 EXPECT_CALL(mockedUtils, getPSUInventoryPath(_))
507 .WillOnce(Return(std::vector<std::string>({psu0, psu1})));
508 EXPECT_CALL(mockedUtils, getService(_, StrEq(psu0), _))
509 .WillOnce(Return(service));
510 EXPECT_CALL(mockedUtils, getService(_, StrEq(psu1), _))
511 .WillOnce(Return(service));
512 EXPECT_CALL(mockedUtils, getVersion(StrEq(psu0)))
513 .WillOnce(Return(std::string(version0)));
514 EXPECT_CALL(mockedUtils, getPropertyImpl(_, StrEq(service), StrEq(psu0), _,
515 StrEq(PRESENT)))
516 .WillOnce(Return(any(PropertyType(true)))); // present
517 EXPECT_CALL(mockedUtils, getVersion(StrEq(psu1)))
518 .WillOnce(Return(std::string(version1)));
519 EXPECT_CALL(mockedUtils, getPropertyImpl(_, StrEq(service), StrEq(psu1), _,
520 StrEq(PRESENT)))
521 .WillOnce(Return(any(PropertyType(true)))); // present
522
523 itemUpdater = std::make_unique<ItemUpdater>(mockedBus, dBusPath);
524
525 // Now there is one activation and it has two associations
526 auto& activations = GetActivations();
527 auto& activation = activations.find(version0)->second;
528 auto assocs = activation->associations();
529 EXPECT_EQ(2u, assocs.size());
530 EXPECT_EQ(psu0, std::get<2>(assocs[0]));
531 EXPECT_EQ(psu1, std::get<2>(assocs[1]));
532
533 EXPECT_CALL(mockedUtils, isAssociated(StrEq(psu0), _))
534 .WillOnce(Return(true));
535 itemUpdater->onUpdateDone("A new version", psu0);
536
537 // Now the activation should have one assoiation
538 assocs = activation->associations();
539 EXPECT_EQ(1u, assocs.size());
540 EXPECT_EQ(psu1, std::get<2>(assocs[0]));
541
542 EXPECT_CALL(mockedUtils, isAssociated(StrEq(psu1), _))
543 .WillOnce(Return(true));
544 itemUpdater->onUpdateDone("A new version", psu1);
545
546 // Now the activation shall be erased
547 EXPECT_EQ(0u, activations.size());
548}
549
550TEST_F(TestItemUpdater, OnUpdateDoneOnTwoPSUsWithDifferentVersion)
551{
552 // Simulate there are two PSUs with different version, and updated to a new
553 // version
554 constexpr auto psu0 = "/com/example/inventory/psu0";
555 constexpr auto psu1 = "/com/example/inventory/psu1";
556 constexpr auto service = "com.example.Software.Psu";
557 auto version0 = std::string("version0");
558 auto version1 = std::string("version1");
559 auto objPath0 = getObjPath(version0);
560 auto objPath1 = getObjPath(version1);
561
562 EXPECT_CALL(mockedUtils, getPSUInventoryPath(_))
563 .WillOnce(Return(std::vector<std::string>({psu0, psu1})));
564 EXPECT_CALL(mockedUtils, getService(_, StrEq(psu0), _))
565 .WillOnce(Return(service));
566 EXPECT_CALL(mockedUtils, getService(_, StrEq(psu1), _))
567 .WillOnce(Return(service));
568 EXPECT_CALL(mockedUtils, getVersion(StrEq(psu0)))
569 .WillOnce(Return(std::string(version0)));
570 EXPECT_CALL(mockedUtils, getPropertyImpl(_, StrEq(service), StrEq(psu0), _,
571 StrEq(PRESENT)))
572 .WillOnce(Return(any(PropertyType(true)))); // present
573 EXPECT_CALL(mockedUtils, getVersion(StrEq(psu1)))
574 .WillOnce(Return(std::string(version1)));
575 EXPECT_CALL(mockedUtils, getPropertyImpl(_, StrEq(service), StrEq(psu1), _,
576 StrEq(PRESENT)))
577 .WillOnce(Return(any(PropertyType(true)))); // present
578
579 itemUpdater = std::make_unique<ItemUpdater>(mockedBus, dBusPath);
580
581 // There are two activations and each with one association
582 const auto& activations = GetActivations();
583 EXPECT_EQ(2u, activations.size());
584
585 EXPECT_CALL(mockedUtils, isAssociated(StrEq(psu0), _))
586 .WillOnce(Return(true));
587 // After psu0 is done, only one activation should be left
588 itemUpdater->onUpdateDone("A new version", psu0);
589 EXPECT_EQ(1u, activations.size());
590 const auto& activation1 = activations.find(version1)->second;
591 const auto& assocs1 = activation1->associations();
592 EXPECT_EQ(1u, assocs1.size());
593 EXPECT_EQ(psu1, std::get<2>(assocs1[0]));
594
595 EXPECT_CALL(mockedUtils, isAssociated(StrEq(psu1), _))
596 .WillOnce(Return(true));
597 // After psu1 is done, no activation should be left
598 itemUpdater->onUpdateDone("A new version", psu1);
599 EXPECT_EQ(0u, activations.size());
600}