blob: 0ae9c76c74db44e00637b7c0c29931918ea50f67 [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::_;
11using ::testing::Return;
12using ::testing::ReturnArg;
13using ::testing::StrEq;
14
15using std::experimental::any;
Lei YUf77189f2019-08-07 14:26:30 +080016
17class TestItemUpdater : public ::testing::Test
18{
19 public:
Lei YUa2c2cd72019-08-09 15:54:10 +080020 using Properties = ItemUpdater::Properties;
21 using PropertyType = utils::UtilsInterface::PropertyType;
22
Lei YUf77189f2019-08-07 14:26:30 +080023 TestItemUpdater() :
24 mockedUtils(
25 reinterpret_cast<const utils::MockedUtils&>(utils::getUtils()))
26 {
27 ON_CALL(mockedUtils, getVersionId(_)).WillByDefault(ReturnArg<0>());
28 }
29
30 ~TestItemUpdater()
31 {
32 }
33
34 const auto& GetActivations()
35 {
36 return itemUpdater->activations;
37 }
38
39 std::string getObjPath(const std::string& versionId)
40 {
41 return std::string(dBusPath) + "/" + versionId;
42 }
43
Lei YUa2c2cd72019-08-09 15:54:10 +080044 void onPsuInventoryChanged(const std::string& psuPath,
45 const Properties& properties)
46 {
47 itemUpdater->onPsuInventoryChanged(psuPath, properties);
48 }
49
Lei YUf77189f2019-08-07 14:26:30 +080050 static constexpr auto dBusPath = SOFTWARE_OBJPATH;
51 sdbusplus::SdBusMock sdbusMock;
52 sdbusplus::bus::bus mockedBus = sdbusplus::get_mocked_new(&sdbusMock);
53 const utils::MockedUtils& mockedUtils;
54 std::unique_ptr<ItemUpdater> itemUpdater;
55};
56
57TEST_F(TestItemUpdater, ctordtor)
58{
59 itemUpdater = std::make_unique<ItemUpdater>(mockedBus, dBusPath);
60}
61
62TEST_F(TestItemUpdater, NotCreateObjectOnNotPresent)
63{
64 constexpr auto psuPath = "/com/example/inventory/psu0";
65 constexpr auto service = "com.example.Software.Psu";
66 constexpr auto version = "version0";
67 std::string objPath = getObjPath(version);
68 EXPECT_CALL(mockedUtils, getPSUInventoryPath(_))
69 .WillOnce(Return(std::vector<std::string>({psuPath})));
70 EXPECT_CALL(mockedUtils, getService(_, StrEq(psuPath), _))
71 .WillOnce(Return(service));
Lei YU5f3584d2019-08-27 16:28:53 +080072 EXPECT_CALL(mockedUtils, getVersion(StrEq(psuPath)))
73 .WillOnce(Return(std::string(version)));
Lei YUf77189f2019-08-07 14:26:30 +080074 EXPECT_CALL(mockedUtils, getPropertyImpl(_, StrEq(service), StrEq(psuPath),
75 _, StrEq(PRESENT)))
76 .WillOnce(Return(any(PropertyType(false)))); // not present
77
78 // The item updater itself
79 EXPECT_CALL(sdbusMock, sd_bus_emit_object_added(_, StrEq(dBusPath)))
80 .Times(1);
81
82 // No activation/version objects are created
83 EXPECT_CALL(sdbusMock, sd_bus_emit_object_added(_, StrEq(objPath)))
84 .Times(0);
85 itemUpdater = std::make_unique<ItemUpdater>(mockedBus, dBusPath);
86}
87
88TEST_F(TestItemUpdater, CreateOnePSUOnPresent)
89{
90 constexpr auto psuPath = "/com/example/inventory/psu0";
91 constexpr auto service = "com.example.Software.Psu";
92 constexpr auto version = "version0";
93 std::string objPath = getObjPath(version);
94 EXPECT_CALL(mockedUtils, getPSUInventoryPath(_))
95 .WillOnce(Return(std::vector<std::string>({psuPath})));
96 EXPECT_CALL(mockedUtils, getService(_, StrEq(psuPath), _))
97 .WillOnce(Return(service));
Lei YU5f3584d2019-08-27 16:28:53 +080098 EXPECT_CALL(mockedUtils, getVersion(StrEq(psuPath)))
99 .WillOnce(Return(std::string(version)));
Lei YUf77189f2019-08-07 14:26:30 +0800100 EXPECT_CALL(mockedUtils, getPropertyImpl(_, StrEq(service), StrEq(psuPath),
101 _, StrEq(PRESENT)))
102 .WillOnce(Return(any(PropertyType(true)))); // present
103
104 // The item updater itself
105 EXPECT_CALL(sdbusMock, sd_bus_emit_object_added(_, StrEq(dBusPath)))
106 .Times(1);
107
108 // activation and version object will be added
109 EXPECT_CALL(sdbusMock, sd_bus_emit_object_added(_, StrEq(objPath)))
110 .Times(2);
111 itemUpdater = std::make_unique<ItemUpdater>(mockedBus, dBusPath);
112}
113
114TEST_F(TestItemUpdater, CreateTwoPSUsWithSameVersion)
115{
116 constexpr auto psu0 = "/com/example/inventory/psu0";
117 constexpr auto psu1 = "/com/example/inventory/psu1";
118 constexpr auto service = "com.example.Software.Psu";
119 auto version0 = std::string("version0");
120 auto version1 = std::string("version0");
121 auto objPath0 = getObjPath(version0);
122 auto objPath1 = getObjPath(version1);
123
124 EXPECT_CALL(mockedUtils, getPSUInventoryPath(_))
125 .WillOnce(Return(std::vector<std::string>({psu0, psu1})));
126 EXPECT_CALL(mockedUtils, getService(_, StrEq(psu0), _))
127 .WillOnce(Return(service));
128 EXPECT_CALL(mockedUtils, getService(_, StrEq(psu1), _))
129 .WillOnce(Return(service));
Lei YU5f3584d2019-08-27 16:28:53 +0800130 EXPECT_CALL(mockedUtils, getVersion(StrEq(psu0)))
131 .WillOnce(Return(std::string(version0)));
Lei YUf77189f2019-08-07 14:26:30 +0800132 EXPECT_CALL(mockedUtils, getPropertyImpl(_, StrEq(service), StrEq(psu0), _,
133 StrEq(PRESENT)))
134 .WillOnce(Return(any(PropertyType(true)))); // present
Lei YU5f3584d2019-08-27 16:28:53 +0800135 EXPECT_CALL(mockedUtils, getVersion(StrEq(psu1)))
136 .WillOnce(Return(std::string(version1)));
Lei YUf77189f2019-08-07 14:26:30 +0800137 EXPECT_CALL(mockedUtils, getPropertyImpl(_, StrEq(service), StrEq(psu1), _,
138 StrEq(PRESENT)))
139 .WillOnce(Return(any(PropertyType(true)))); // present
140
141 // The item updater itself
142 EXPECT_CALL(sdbusMock, sd_bus_emit_object_added(_, StrEq(dBusPath)))
143 .Times(1);
144
145 // activation and version object will be added
146 EXPECT_CALL(sdbusMock, sd_bus_emit_object_added(_, StrEq(objPath0)))
147 .Times(2);
148 itemUpdater = std::make_unique<ItemUpdater>(mockedBus, dBusPath);
149
150 // Verify there is only one activation and it has two associations
151 const auto& activations = GetActivations();
152 EXPECT_EQ(1u, activations.size());
153 const auto& activation = activations.find(version0)->second;
154 const auto& assocs = activation->associations();
155 EXPECT_EQ(2u, assocs.size());
156 EXPECT_EQ(psu0, std::get<2>(assocs[0]));
157 EXPECT_EQ(psu1, std::get<2>(assocs[1]));
158}
159
160TEST_F(TestItemUpdater, CreateTwoPSUsWithDifferentVersion)
161{
162 constexpr auto psu0 = "/com/example/inventory/psu0";
163 constexpr auto psu1 = "/com/example/inventory/psu1";
164 constexpr auto service = "com.example.Software.Psu";
165 auto version0 = std::string("version0");
166 auto version1 = std::string("version1");
167 auto objPath0 = getObjPath(version0);
168 auto objPath1 = getObjPath(version1);
169
170 EXPECT_CALL(mockedUtils, getPSUInventoryPath(_))
171 .WillOnce(Return(std::vector<std::string>({psu0, psu1})));
172 EXPECT_CALL(mockedUtils, getService(_, StrEq(psu0), _))
173 .WillOnce(Return(service));
174 EXPECT_CALL(mockedUtils, getService(_, StrEq(psu1), _))
175 .WillOnce(Return(service));
Lei YU5f3584d2019-08-27 16:28:53 +0800176 EXPECT_CALL(mockedUtils, getVersion(StrEq(psu0)))
177 .WillOnce(Return(std::string(version0)));
Lei YUf77189f2019-08-07 14:26:30 +0800178 EXPECT_CALL(mockedUtils, getPropertyImpl(_, StrEq(service), StrEq(psu0), _,
179 StrEq(PRESENT)))
180 .WillOnce(Return(any(PropertyType(true)))); // present
Lei YU5f3584d2019-08-27 16:28:53 +0800181 EXPECT_CALL(mockedUtils, getVersion(StrEq(psu1)))
182 .WillOnce(Return(std::string(version1)));
Lei YUf77189f2019-08-07 14:26:30 +0800183 EXPECT_CALL(mockedUtils, getPropertyImpl(_, StrEq(service), StrEq(psu1), _,
184 StrEq(PRESENT)))
185 .WillOnce(Return(any(PropertyType(true)))); // present
186
187 // The item updater itself
188 EXPECT_CALL(sdbusMock, sd_bus_emit_object_added(_, StrEq(dBusPath)))
189 .Times(1);
190
191 // two new activation and version objects will be added
192 EXPECT_CALL(sdbusMock, sd_bus_emit_object_added(_, StrEq(objPath0)))
193 .Times(2);
194 EXPECT_CALL(sdbusMock, sd_bus_emit_object_added(_, StrEq(objPath1)))
195 .Times(2);
196 itemUpdater = std::make_unique<ItemUpdater>(mockedBus, dBusPath);
197
198 // Verify there are two activations and each with one association
199 const auto& activations = GetActivations();
200 EXPECT_EQ(2u, activations.size());
201 const auto& activation0 = activations.find(version0)->second;
202 const auto& assocs0 = activation0->associations();
203 EXPECT_EQ(1u, assocs0.size());
204 EXPECT_EQ(psu0, std::get<2>(assocs0[0]));
205
206 const auto& activation1 = activations.find(version1)->second;
207 const auto& assocs1 = activation1->associations();
208 EXPECT_EQ(1u, assocs1.size());
209 EXPECT_EQ(psu1, std::get<2>(assocs1[0]));
210}
Lei YUa2c2cd72019-08-09 15:54:10 +0800211
212TEST_F(TestItemUpdater, OnOnePSURemoved)
213{
214 constexpr auto psuPath = "/com/example/inventory/psu0";
215 constexpr auto service = "com.example.Software.Psu";
216 constexpr auto version = "version0";
217 std::string objPath = getObjPath(version);
218 EXPECT_CALL(mockedUtils, getPSUInventoryPath(_))
219 .WillOnce(Return(std::vector<std::string>({psuPath})));
220 EXPECT_CALL(mockedUtils, getService(_, StrEq(psuPath), _))
221 .WillOnce(Return(service));
Lei YU5f3584d2019-08-27 16:28:53 +0800222 EXPECT_CALL(mockedUtils, getVersion(StrEq(psuPath)))
223 .WillOnce(Return(std::string(version)));
Lei YUa2c2cd72019-08-09 15:54:10 +0800224 EXPECT_CALL(mockedUtils, getPropertyImpl(_, StrEq(service), StrEq(psuPath),
225 _, StrEq(PRESENT)))
226 .WillOnce(Return(any(PropertyType(true)))); // present
227
228 // The item updater itself
229 EXPECT_CALL(sdbusMock, sd_bus_emit_object_added(_, StrEq(dBusPath)))
230 .Times(1);
231
232 // activation and version object will be added
233 EXPECT_CALL(sdbusMock, sd_bus_emit_object_added(_, StrEq(objPath)))
234 .Times(2);
235 itemUpdater = std::make_unique<ItemUpdater>(mockedBus, dBusPath);
236
237 // the activation and version object will be removed
238 Properties p{{PRESENT, PropertyType(false)}};
239 EXPECT_CALL(sdbusMock, sd_bus_emit_object_removed(_, StrEq(objPath)))
240 .Times(2);
241 onPsuInventoryChanged(psuPath, p);
242
243 // on exit, item updater is removed
244 EXPECT_CALL(sdbusMock, sd_bus_emit_object_removed(_, StrEq(dBusPath)))
245 .Times(1);
246}
247
248TEST_F(TestItemUpdater, OnOnePSUAdded)
249{
250 constexpr auto psuPath = "/com/example/inventory/psu0";
251 constexpr auto service = "com.example.Software.Psu";
252 constexpr auto version = "version0";
253 std::string objPath = getObjPath(version);
254 EXPECT_CALL(mockedUtils, getPSUInventoryPath(_))
255 .WillOnce(Return(std::vector<std::string>({psuPath})));
256 EXPECT_CALL(mockedUtils, getService(_, StrEq(psuPath), _))
257 .WillOnce(Return(service));
Lei YU5f3584d2019-08-27 16:28:53 +0800258 EXPECT_CALL(mockedUtils, getVersion(StrEq(psuPath)))
259 .WillOnce(Return(std::string(version)));
Lei YUa2c2cd72019-08-09 15:54:10 +0800260 EXPECT_CALL(mockedUtils, getPropertyImpl(_, StrEq(service), StrEq(psuPath),
261 _, StrEq(PRESENT)))
262 .WillOnce(Return(any(PropertyType(false)))); // not present
263
264 // The item updater itself
265 EXPECT_CALL(sdbusMock, sd_bus_emit_object_added(_, StrEq(dBusPath)))
266 .Times(1);
267
268 // No activation/version objects are created
269 EXPECT_CALL(sdbusMock, sd_bus_emit_object_added(_, StrEq(objPath)))
270 .Times(0);
271 itemUpdater = std::make_unique<ItemUpdater>(mockedBus, dBusPath);
272
273 // The PSU is present and version is added in a single call
274 Properties propAdded{{PRESENT, PropertyType(true)},
275 {VERSION, PropertyType(std::string(version))}};
276 EXPECT_CALL(sdbusMock, sd_bus_emit_object_added(_, StrEq(objPath)))
277 .Times(2);
278 onPsuInventoryChanged(psuPath, propAdded);
279}
280
281TEST_F(TestItemUpdater, OnOnePSURemovedAndAdded)
282{
283 constexpr auto psuPath = "/com/example/inventory/psu0";
284 constexpr auto service = "com.example.Software.Psu";
285 constexpr auto version = "version0";
286 std::string objPath = getObjPath(version);
287 EXPECT_CALL(mockedUtils, getPSUInventoryPath(_))
288 .WillOnce(Return(std::vector<std::string>({psuPath})));
289 EXPECT_CALL(mockedUtils, getService(_, StrEq(psuPath), _))
290 .WillOnce(Return(service));
Lei YU5f3584d2019-08-27 16:28:53 +0800291 EXPECT_CALL(mockedUtils, getVersion(StrEq(psuPath)))
292 .WillOnce(Return(std::string(version)));
Lei YUa2c2cd72019-08-09 15:54:10 +0800293 EXPECT_CALL(mockedUtils, getPropertyImpl(_, StrEq(service), StrEq(psuPath),
294 _, StrEq(PRESENT)))
295 .WillOnce(Return(any(PropertyType(true)))); // present
296
297 // The item updater itself
298 EXPECT_CALL(sdbusMock, sd_bus_emit_object_added(_, StrEq(dBusPath)))
299 .Times(1);
300
301 // activation and version object will be added
302 EXPECT_CALL(sdbusMock, sd_bus_emit_object_added(_, StrEq(objPath)))
303 .Times(2);
304 itemUpdater = std::make_unique<ItemUpdater>(mockedBus, dBusPath);
305
306 // the activation and version object will be removed
307 Properties propRemoved{{PRESENT, PropertyType(false)}};
308 EXPECT_CALL(sdbusMock, sd_bus_emit_object_removed(_, StrEq(objPath)))
309 .Times(2);
310 onPsuInventoryChanged(psuPath, propRemoved);
311
312 Properties propAdded{{PRESENT, PropertyType(true)}};
313 Properties propVersion{{VERSION, PropertyType(std::string(version))}};
314 EXPECT_CALL(sdbusMock, sd_bus_emit_object_added(_, StrEq(objPath)))
315 .Times(2);
316 onPsuInventoryChanged(psuPath, propAdded);
317 onPsuInventoryChanged(psuPath, propVersion);
318
319 // on exit, objects are removed
320 EXPECT_CALL(sdbusMock, sd_bus_emit_object_removed(_, StrEq(objPath)))
321 .Times(2);
322 EXPECT_CALL(sdbusMock, sd_bus_emit_object_removed(_, StrEq(dBusPath)))
323 .Times(1);
324}
325
326TEST_F(TestItemUpdater,
327 TwoPSUsWithSameVersionRemovedAndAddedWithDifferntVersion)
328{
329 constexpr auto psu0 = "/com/example/inventory/psu0";
330 constexpr auto psu1 = "/com/example/inventory/psu1";
331 constexpr auto service = "com.example.Software.Psu";
332 auto version0 = std::string("version0");
333 auto version1 = std::string("version0");
334 auto objPath0 = getObjPath(version0);
335 auto objPath1 = getObjPath(version1);
336
337 EXPECT_CALL(mockedUtils, getPSUInventoryPath(_))
338 .WillOnce(Return(std::vector<std::string>({psu0, psu1})));
339 EXPECT_CALL(mockedUtils, getService(_, StrEq(psu0), _))
340 .WillOnce(Return(service));
341 EXPECT_CALL(mockedUtils, getService(_, StrEq(psu1), _))
342 .WillOnce(Return(service));
Lei YU5f3584d2019-08-27 16:28:53 +0800343 EXPECT_CALL(mockedUtils, getVersion(StrEq(psu0)))
344 .WillOnce(Return(std::string(version0)));
Lei YUa2c2cd72019-08-09 15:54:10 +0800345 EXPECT_CALL(mockedUtils, getPropertyImpl(_, StrEq(service), StrEq(psu0), _,
346 StrEq(PRESENT)))
347 .WillOnce(Return(any(PropertyType(true)))); // present
Lei YU5f3584d2019-08-27 16:28:53 +0800348 EXPECT_CALL(mockedUtils, getVersion(StrEq(psu1)))
349 .WillOnce(Return(std::string(version1)));
Lei YUa2c2cd72019-08-09 15:54:10 +0800350 EXPECT_CALL(mockedUtils, getPropertyImpl(_, StrEq(service), StrEq(psu1), _,
351 StrEq(PRESENT)))
352 .WillOnce(Return(any(PropertyType(true)))); // present
353
354 // The item updater itself
355 EXPECT_CALL(sdbusMock, sd_bus_emit_object_added(_, StrEq(dBusPath)))
356 .Times(1);
357
358 // activation and version object will be added
359 EXPECT_CALL(sdbusMock, sd_bus_emit_object_added(_, StrEq(objPath0)))
360 .Times(2);
361 itemUpdater = std::make_unique<ItemUpdater>(mockedBus, dBusPath);
362
363 // Verify there is only one activation and it has two associations
364 const auto& activations = GetActivations();
365 EXPECT_EQ(1u, activations.size());
366 const auto& activation = activations.find(version0)->second;
367 auto assocs = activation->associations();
368 EXPECT_EQ(2u, assocs.size());
369 EXPECT_EQ(psu0, std::get<2>(assocs[0]));
370 EXPECT_EQ(psu1, std::get<2>(assocs[1]));
371
372 // PSU0 is removed, only associations shall be updated
373 Properties propRemoved{{PRESENT, PropertyType(false)}};
374 onPsuInventoryChanged(psu0, propRemoved);
375 assocs = activation->associations();
376 EXPECT_EQ(1u, assocs.size());
377 EXPECT_EQ(psu1, std::get<2>(assocs[0]));
378
379 // PSU1 is removed, the activation and version object shall be removed
380 EXPECT_CALL(sdbusMock, sd_bus_emit_object_removed(_, StrEq(objPath0)))
381 .Times(2);
382 onPsuInventoryChanged(psu1, propRemoved);
383
384 // Add PSU0 and PSU1 back, but PSU1 with a different version
385 version1 = "version1";
386 objPath1 = getObjPath(version1);
387 Properties propAdded0{{PRESENT, PropertyType(true)},
388 {VERSION, PropertyType(std::string(version0))}};
389 Properties propAdded1{{PRESENT, PropertyType(true)},
390 {VERSION, PropertyType(std::string(version1))}};
391 EXPECT_CALL(sdbusMock, sd_bus_emit_object_added(_, StrEq(objPath0)))
392 .Times(2);
393 EXPECT_CALL(sdbusMock, sd_bus_emit_object_added(_, StrEq(objPath1)))
394 .Times(2);
395 onPsuInventoryChanged(psu0, propAdded0);
396 onPsuInventoryChanged(psu1, propAdded1);
397
398 // on exit, objects are removed
399 EXPECT_CALL(sdbusMock, sd_bus_emit_object_removed(_, StrEq(objPath0)))
400 .Times(2);
401 EXPECT_CALL(sdbusMock, sd_bus_emit_object_removed(_, StrEq(objPath1)))
402 .Times(2);
403 EXPECT_CALL(sdbusMock, sd_bus_emit_object_removed(_, StrEq(dBusPath)))
404 .Times(1);
405}