blob: 0c40d97734ba28d7bf45e04c128ca8764b52d55a [file] [log] [blame]
Lei YU12c9f4c2019-09-11 15:08:15 +08001#include "activation.hpp"
Lei YU7f2a2152019-09-16 16:50:18 +08002#include "mocked_association_interface.hpp"
Lei YUff83c2a2019-09-12 13:55:18 +08003#include "mocked_utils.hpp"
Lei YU12c9f4c2019-09-11 15:08:15 +08004
5#include <sdbusplus/test/sdbus_mock.hpp>
6
7#include <gmock/gmock.h>
8#include <gtest/gtest.h>
9
10using namespace phosphor::software::updater;
11
Lei YUff83c2a2019-09-12 13:55:18 +080012using ::testing::_;
13using ::testing::Return;
Lei YU9edb7332019-09-19 14:46:19 +080014using ::testing::StrEq;
15
16using std::experimental::any;
Lei YUff83c2a2019-09-12 13:55:18 +080017
Lei YU12c9f4c2019-09-11 15:08:15 +080018class TestActivation : public ::testing::Test
19{
20 public:
Lei YU9edb7332019-09-19 14:46:19 +080021 using PropertyType = utils::UtilsInterface::PropertyType;
Lei YUff83c2a2019-09-12 13:55:18 +080022 using Status = Activation::Status;
23 using RequestedStatus = Activation::RequestedActivations;
24 TestActivation() :
25 mockedUtils(
26 reinterpret_cast<const utils::MockedUtils&>(utils::getUtils()))
Lei YU12c9f4c2019-09-11 15:08:15 +080027 {
Lei YU9edb7332019-09-19 14:46:19 +080028 // By default make it compatible with the test software
29 ON_CALL(mockedUtils, getPropertyImpl(_, _, _, _, StrEq(MANUFACTURER)))
30 .WillByDefault(Return(any(PropertyType(std::string("TestManu")))));
31 ON_CALL(mockedUtils, getPropertyImpl(_, _, _, _, StrEq(MODEL)))
32 .WillByDefault(Return(any(PropertyType(std::string("TestModel")))));
Lei YU12c9f4c2019-09-11 15:08:15 +080033 }
34 ~TestActivation()
35 {
36 }
Lei YUff83c2a2019-09-12 13:55:18 +080037
38 void onUpdateDone()
39 {
40 activation->onUpdateDone();
41 }
42 void onUpdateFailed()
43 {
44 activation->onUpdateFailed();
45 }
46 int getProgress()
47 {
48 return activation->activationProgress->progress();
49 }
Lei YU9edb7332019-09-19 14:46:19 +080050 const auto& getPsuQueue()
51 {
52 return activation->psuQueue;
53 }
54
Lei YU12c9f4c2019-09-11 15:08:15 +080055 sdbusplus::SdBusMock sdbusMock;
56 sdbusplus::bus::bus mockedBus = sdbusplus::get_mocked_new(&sdbusMock);
Lei YUff83c2a2019-09-12 13:55:18 +080057 const utils::MockedUtils& mockedUtils;
Lei YU7f2a2152019-09-16 16:50:18 +080058 MockedAssociationInterface mockedAssociationInterface;
Lei YU12c9f4c2019-09-11 15:08:15 +080059 std::unique_ptr<Activation> activation;
60 std::string versionId = "abcdefgh";
Lei YU9edb7332019-09-19 14:46:19 +080061 std::string extVersion = "manufacturer=TestManu,model=TestModel";
Lei YU7f2a2152019-09-16 16:50:18 +080062 std::string dBusPath = std::string(SOFTWARE_OBJPATH) + "/" + versionId;
Lei YUff83c2a2019-09-12 13:55:18 +080063 Status status = Status::Ready;
Lei YU12c9f4c2019-09-11 15:08:15 +080064 AssociationList associations;
65};
66
67TEST_F(TestActivation, ctordtor)
68{
69 activation = std::make_unique<Activation>(mockedBus, dBusPath, versionId,
Lei YU7f2a2152019-09-16 16:50:18 +080070 extVersion, status, associations,
71 &mockedAssociationInterface);
Lei YU12c9f4c2019-09-11 15:08:15 +080072}
73
74namespace phosphor::software::updater::internal
75{
76extern std::string getUpdateService(const std::string& psuInventoryPath,
77 const std::string& versionId);
78}
79
80TEST_F(TestActivation, getUpdateService)
81{
82 std::string psuInventoryPath = "/com/example/inventory/powersupply1";
83 std::string versionId = "12345678";
84 std::string toCompare = "psu-update@-com-example-inventory-"
85 "powersupply1\\x20-tmp-images-12345678.service";
86
87 auto service = phosphor::software::updater::internal::getUpdateService(
88 psuInventoryPath, versionId);
89 EXPECT_EQ(toCompare, service);
90}
Lei YUff83c2a2019-09-12 13:55:18 +080091
92TEST_F(TestActivation, doUpdateWhenNoPSU)
93{
94 activation = std::make_unique<Activation>(mockedBus, dBusPath, versionId,
Lei YU7f2a2152019-09-16 16:50:18 +080095 extVersion, status, associations,
96 &mockedAssociationInterface);
Lei YUff83c2a2019-09-12 13:55:18 +080097 ON_CALL(mockedUtils, getPSUInventoryPath(_))
98 .WillByDefault(
99 Return(std::vector<std::string>({}))); // No PSU inventory
100 activation->requestedActivation(RequestedStatus::Active);
101
Lei YU7f2a2152019-09-16 16:50:18 +0800102 EXPECT_CALL(mockedAssociationInterface, createActiveAssociation(dBusPath))
103 .Times(0);
104 EXPECT_CALL(mockedAssociationInterface, addFunctionalAssociation(dBusPath))
105 .Times(0);
Lei YUff83c2a2019-09-12 13:55:18 +0800106 EXPECT_EQ(Status::Failed, activation->activation());
107}
108
109TEST_F(TestActivation, doUpdateOnePSUOK)
110{
111 constexpr auto psu0 = "/com/example/inventory/psu0";
112 activation = std::make_unique<Activation>(mockedBus, dBusPath, versionId,
Lei YU7f2a2152019-09-16 16:50:18 +0800113 extVersion, status, associations,
114 &mockedAssociationInterface);
Lei YUff83c2a2019-09-12 13:55:18 +0800115 ON_CALL(mockedUtils, getPSUInventoryPath(_))
116 .WillByDefault(
117 Return(std::vector<std::string>({psu0}))); // One PSU inventory
118 activation->requestedActivation(RequestedStatus::Active);
119
120 EXPECT_EQ(Status::Activating, activation->activation());
121
Lei YU7f2a2152019-09-16 16:50:18 +0800122 EXPECT_CALL(mockedAssociationInterface, createActiveAssociation(dBusPath))
123 .Times(1);
124 EXPECT_CALL(mockedAssociationInterface, addFunctionalAssociation(dBusPath))
125 .Times(1);
Lei YUff83c2a2019-09-12 13:55:18 +0800126 onUpdateDone();
127 EXPECT_EQ(Status::Active, activation->activation());
128}
129
130TEST_F(TestActivation, doUpdateFourPSUsOK)
131{
132 constexpr auto psu0 = "/com/example/inventory/psu0";
133 constexpr auto psu1 = "/com/example/inventory/psu1";
134 constexpr auto psu2 = "/com/example/inventory/psu2";
135 constexpr auto psu3 = "/com/example/inventory/psu3";
136 activation = std::make_unique<Activation>(mockedBus, dBusPath, versionId,
Lei YU7f2a2152019-09-16 16:50:18 +0800137 extVersion, status, associations,
138 &mockedAssociationInterface);
Lei YUff83c2a2019-09-12 13:55:18 +0800139 ON_CALL(mockedUtils, getPSUInventoryPath(_))
140 .WillByDefault(Return(
141 std::vector<std::string>({psu0, psu1, psu2, psu3}))); // 4 PSUs
142 activation->requestedActivation(RequestedStatus::Active);
143
144 EXPECT_EQ(Status::Activating, activation->activation());
145 EXPECT_EQ(10, getProgress());
146
147 onUpdateDone();
148 EXPECT_EQ(Status::Activating, activation->activation());
149 EXPECT_EQ(30, getProgress());
150
151 onUpdateDone();
152 EXPECT_EQ(Status::Activating, activation->activation());
153 EXPECT_EQ(50, getProgress());
154
155 onUpdateDone();
156 EXPECT_EQ(Status::Activating, activation->activation());
157 EXPECT_EQ(70, getProgress());
158
Lei YU7f2a2152019-09-16 16:50:18 +0800159 EXPECT_CALL(mockedAssociationInterface, createActiveAssociation(dBusPath))
160 .Times(1);
161 EXPECT_CALL(mockedAssociationInterface, addFunctionalAssociation(dBusPath))
162 .Times(1);
163
Lei YUff83c2a2019-09-12 13:55:18 +0800164 onUpdateDone();
165 EXPECT_EQ(Status::Active, activation->activation());
166}
167
168TEST_F(TestActivation, doUpdateFourPSUsFailonSecond)
169{
170 constexpr auto psu0 = "/com/example/inventory/psu0";
171 constexpr auto psu1 = "/com/example/inventory/psu1";
172 constexpr auto psu2 = "/com/example/inventory/psu2";
173 constexpr auto psu3 = "/com/example/inventory/psu3";
174 activation = std::make_unique<Activation>(mockedBus, dBusPath, versionId,
Lei YU7f2a2152019-09-16 16:50:18 +0800175 extVersion, status, associations,
176 &mockedAssociationInterface);
Lei YUff83c2a2019-09-12 13:55:18 +0800177 ON_CALL(mockedUtils, getPSUInventoryPath(_))
178 .WillByDefault(Return(
179 std::vector<std::string>({psu0, psu1, psu2, psu3}))); // 4 PSUs
180 activation->requestedActivation(RequestedStatus::Active);
181
182 EXPECT_EQ(Status::Activating, activation->activation());
183 EXPECT_EQ(10, getProgress());
184
185 onUpdateDone();
186 EXPECT_EQ(Status::Activating, activation->activation());
187 EXPECT_EQ(30, getProgress());
188
Lei YU7f2a2152019-09-16 16:50:18 +0800189 EXPECT_CALL(mockedAssociationInterface, createActiveAssociation(dBusPath))
190 .Times(0);
191 EXPECT_CALL(mockedAssociationInterface, addFunctionalAssociation(dBusPath))
192 .Times(0);
Lei YUff83c2a2019-09-12 13:55:18 +0800193 onUpdateFailed();
194 EXPECT_EQ(Status::Failed, activation->activation());
195}
196
197TEST_F(TestActivation, doUpdateOnExceptionFromDbus)
198{
199 constexpr auto psu0 = "/com/example/inventory/psu0";
200 activation = std::make_unique<Activation>(mockedBus, dBusPath, versionId,
Lei YU7f2a2152019-09-16 16:50:18 +0800201 extVersion, status, associations,
202 &mockedAssociationInterface);
Lei YUff83c2a2019-09-12 13:55:18 +0800203 ON_CALL(mockedUtils, getPSUInventoryPath(_))
204 .WillByDefault(
205 Return(std::vector<std::string>({psu0}))); // One PSU inventory
206 ON_CALL(sdbusMock, sd_bus_call(_, _, _, _, nullptr))
207 .WillByDefault(Return(-1)); // Make sdbus call failure
208 activation->requestedActivation(RequestedStatus::Active);
209
210 EXPECT_EQ(Status::Failed, activation->activation());
211}
Lei YU9edb7332019-09-19 14:46:19 +0800212
213TEST_F(TestActivation, doUpdateOnePSUModelNotCompatible)
214{
215 constexpr auto psu0 = "/com/example/inventory/psu0";
216 extVersion = "manufacturer=TestManu,model=DifferentModel";
217 activation = std::make_unique<Activation>(mockedBus, dBusPath, versionId,
218 extVersion, status, associations,
219 &mockedAssociationInterface);
220 ON_CALL(mockedUtils, getPSUInventoryPath(_))
221 .WillByDefault(Return(std::vector<std::string>({psu0})));
222 activation->requestedActivation(RequestedStatus::Active);
223
224 EXPECT_EQ(Status::Failed, activation->activation());
225}
226
227TEST_F(TestActivation, doUpdateOnePSUManufactureNotCompatible)
228{
229 constexpr auto psu0 = "/com/example/inventory/psu0";
230 extVersion = "manufacturer=DifferentManu,model=TestModel";
231 activation = std::make_unique<Activation>(mockedBus, dBusPath, versionId,
232 extVersion, status, associations,
233 &mockedAssociationInterface);
234 ON_CALL(mockedUtils, getPSUInventoryPath(_))
235 .WillByDefault(Return(std::vector<std::string>({psu0})));
236 activation->requestedActivation(RequestedStatus::Active);
237
238 EXPECT_EQ(Status::Failed, activation->activation());
239}
240
241TEST_F(TestActivation, doUpdateOnePSUSelfManufactureIsEmpty)
242{
243 ON_CALL(mockedUtils, getPropertyImpl(_, _, _, _, StrEq(MANUFACTURER)))
244 .WillByDefault(Return(any(PropertyType(std::string("")))));
245 extVersion = "manufacturer=AnyManu,model=TestModel";
246 // Below is the same as doUpdateOnePSUOK case
247 constexpr auto psu0 = "/com/example/inventory/psu0";
248 activation = std::make_unique<Activation>(mockedBus, dBusPath, versionId,
249 extVersion, status, associations,
250 &mockedAssociationInterface);
251 ON_CALL(mockedUtils, getPSUInventoryPath(_))
252 .WillByDefault(
253 Return(std::vector<std::string>({psu0}))); // One PSU inventory
254 activation->requestedActivation(RequestedStatus::Active);
255
256 EXPECT_EQ(Status::Activating, activation->activation());
257
258 EXPECT_CALL(mockedAssociationInterface, createActiveAssociation(dBusPath))
259 .Times(1);
260 EXPECT_CALL(mockedAssociationInterface, addFunctionalAssociation(dBusPath))
261 .Times(1);
262 onUpdateDone();
263 EXPECT_EQ(Status::Active, activation->activation());
264}
265
266TEST_F(TestActivation, doUpdateFourPSUsSecondPSUNotCompatible)
267{
268 constexpr auto psu0 = "/com/example/inventory/psu0";
269 constexpr auto psu1 = "/com/example/inventory/psu1";
270 constexpr auto psu2 = "/com/example/inventory/psu2";
271 constexpr auto psu3 = "/com/example/inventory/psu3";
272 ON_CALL(mockedUtils, getPropertyImpl(_, _, StrEq(psu1), _, StrEq(MODEL)))
273 .WillByDefault(
274 Return(any(PropertyType(std::string("DifferentModel")))));
275 activation = std::make_unique<Activation>(mockedBus, dBusPath, versionId,
276 extVersion, status, associations,
277 &mockedAssociationInterface);
278 ON_CALL(mockedUtils, getPSUInventoryPath(_))
279 .WillByDefault(Return(
280 std::vector<std::string>({psu0, psu1, psu2, psu3}))); // 4 PSUs
281 activation->requestedActivation(RequestedStatus::Active);
282
283 const auto& psuQueue = getPsuQueue();
284 EXPECT_EQ(3u, psuQueue.size());
285
286 // Only 3 PSUs shall be updated, and psu1 shall be skipped
287 EXPECT_EQ(Status::Activating, activation->activation());
288 EXPECT_EQ(10, getProgress());
289
290 onUpdateDone();
291 EXPECT_EQ(Status::Activating, activation->activation());
292 EXPECT_EQ(36, getProgress());
293
294 onUpdateDone();
295 EXPECT_EQ(Status::Activating, activation->activation());
296 EXPECT_EQ(62, getProgress());
297
298 EXPECT_CALL(mockedAssociationInterface, createActiveAssociation(dBusPath))
299 .Times(1);
300 EXPECT_CALL(mockedAssociationInterface, addFunctionalAssociation(dBusPath))
301 .Times(1);
302
303 onUpdateDone();
304 EXPECT_EQ(Status::Active, activation->activation());
305}