blob: f89475ac86d01978ae4ef4c7af8c1a7bba2f2149 [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 }
Lei YUe8945ea2019-09-29 17:25:31 +080054 std::string getUpdateService(const std::string& psuInventoryPath)
55 {
56 return activation->getUpdateService(psuInventoryPath);
57 }
Lei YU9edb7332019-09-19 14:46:19 +080058
Lei YU12c9f4c2019-09-11 15:08:15 +080059 sdbusplus::SdBusMock sdbusMock;
60 sdbusplus::bus::bus mockedBus = sdbusplus::get_mocked_new(&sdbusMock);
Lei YUff83c2a2019-09-12 13:55:18 +080061 const utils::MockedUtils& mockedUtils;
Lei YU7f2a2152019-09-16 16:50:18 +080062 MockedAssociationInterface mockedAssociationInterface;
Lei YU12c9f4c2019-09-11 15:08:15 +080063 std::unique_ptr<Activation> activation;
64 std::string versionId = "abcdefgh";
Lei YU9edb7332019-09-19 14:46:19 +080065 std::string extVersion = "manufacturer=TestManu,model=TestModel";
Lei YU99301372019-09-29 16:27:12 +080066 std::string filePath = "";
Lei YU7f2a2152019-09-16 16:50:18 +080067 std::string dBusPath = std::string(SOFTWARE_OBJPATH) + "/" + versionId;
Lei YUff83c2a2019-09-12 13:55:18 +080068 Status status = Status::Ready;
Lei YU12c9f4c2019-09-11 15:08:15 +080069 AssociationList associations;
70};
71
72TEST_F(TestActivation, ctordtor)
73{
Lei YU99301372019-09-29 16:27:12 +080074 activation = std::make_unique<Activation>(
75 mockedBus, dBusPath, versionId, extVersion, status, associations,
76 &mockedAssociationInterface, filePath);
Lei YU12c9f4c2019-09-11 15:08:15 +080077}
78
Lei YU58c26e32019-09-27 17:52:06 +080079TEST_F(TestActivation, ctorWithInvalidExtVersion)
80{
81 extVersion = "invalid text";
82 activation = std::make_unique<Activation>(
83 mockedBus, dBusPath, versionId, extVersion, status, associations,
84 &mockedAssociationInterface, filePath);
85}
86
Lei YU12c9f4c2019-09-11 15:08:15 +080087TEST_F(TestActivation, getUpdateService)
88{
89 std::string psuInventoryPath = "/com/example/inventory/powersupply1";
Lei YU12c9f4c2019-09-11 15:08:15 +080090 std::string toCompare = "psu-update@-com-example-inventory-"
91 "powersupply1\\x20-tmp-images-12345678.service";
Lei YUe8945ea2019-09-29 17:25:31 +080092 versionId = "12345678";
93 filePath = "/tmp/images/12345678";
Lei YU12c9f4c2019-09-11 15:08:15 +080094
Lei YUe8945ea2019-09-29 17:25:31 +080095 activation = std::make_unique<Activation>(
96 mockedBus, dBusPath, versionId, extVersion, status, associations,
97 &mockedAssociationInterface, filePath);
98
99 auto service = getUpdateService(psuInventoryPath);
Lei YU12c9f4c2019-09-11 15:08:15 +0800100 EXPECT_EQ(toCompare, service);
101}
Lei YUff83c2a2019-09-12 13:55:18 +0800102
103TEST_F(TestActivation, doUpdateWhenNoPSU)
104{
Lei YU99301372019-09-29 16:27:12 +0800105 activation = std::make_unique<Activation>(
106 mockedBus, dBusPath, versionId, extVersion, status, associations,
107 &mockedAssociationInterface, filePath);
Lei YUff83c2a2019-09-12 13:55:18 +0800108 ON_CALL(mockedUtils, getPSUInventoryPath(_))
109 .WillByDefault(
110 Return(std::vector<std::string>({}))); // No PSU inventory
111 activation->requestedActivation(RequestedStatus::Active);
112
Lei YU7f2a2152019-09-16 16:50:18 +0800113 EXPECT_CALL(mockedAssociationInterface, createActiveAssociation(dBusPath))
114 .Times(0);
115 EXPECT_CALL(mockedAssociationInterface, addFunctionalAssociation(dBusPath))
116 .Times(0);
Lei YUff83c2a2019-09-12 13:55:18 +0800117 EXPECT_EQ(Status::Failed, activation->activation());
118}
119
120TEST_F(TestActivation, doUpdateOnePSUOK)
121{
122 constexpr auto psu0 = "/com/example/inventory/psu0";
Lei YU99301372019-09-29 16:27:12 +0800123 activation = std::make_unique<Activation>(
124 mockedBus, dBusPath, versionId, extVersion, status, associations,
125 &mockedAssociationInterface, filePath);
Lei YUff83c2a2019-09-12 13:55:18 +0800126 ON_CALL(mockedUtils, getPSUInventoryPath(_))
127 .WillByDefault(
128 Return(std::vector<std::string>({psu0}))); // One PSU inventory
129 activation->requestedActivation(RequestedStatus::Active);
130
131 EXPECT_EQ(Status::Activating, activation->activation());
132
Lei YU7f2a2152019-09-16 16:50:18 +0800133 EXPECT_CALL(mockedAssociationInterface, createActiveAssociation(dBusPath))
134 .Times(1);
135 EXPECT_CALL(mockedAssociationInterface, addFunctionalAssociation(dBusPath))
136 .Times(1);
Lei YUff83c2a2019-09-12 13:55:18 +0800137 onUpdateDone();
138 EXPECT_EQ(Status::Active, activation->activation());
139}
140
141TEST_F(TestActivation, doUpdateFourPSUsOK)
142{
143 constexpr auto psu0 = "/com/example/inventory/psu0";
144 constexpr auto psu1 = "/com/example/inventory/psu1";
145 constexpr auto psu2 = "/com/example/inventory/psu2";
146 constexpr auto psu3 = "/com/example/inventory/psu3";
Lei YU99301372019-09-29 16:27:12 +0800147 activation = std::make_unique<Activation>(
148 mockedBus, dBusPath, versionId, extVersion, status, associations,
149 &mockedAssociationInterface, filePath);
Lei YUff83c2a2019-09-12 13:55:18 +0800150 ON_CALL(mockedUtils, getPSUInventoryPath(_))
151 .WillByDefault(Return(
152 std::vector<std::string>({psu0, psu1, psu2, psu3}))); // 4 PSUs
153 activation->requestedActivation(RequestedStatus::Active);
154
155 EXPECT_EQ(Status::Activating, activation->activation());
156 EXPECT_EQ(10, getProgress());
157
158 onUpdateDone();
159 EXPECT_EQ(Status::Activating, activation->activation());
160 EXPECT_EQ(30, getProgress());
161
162 onUpdateDone();
163 EXPECT_EQ(Status::Activating, activation->activation());
164 EXPECT_EQ(50, getProgress());
165
166 onUpdateDone();
167 EXPECT_EQ(Status::Activating, activation->activation());
168 EXPECT_EQ(70, getProgress());
169
Lei YU7f2a2152019-09-16 16:50:18 +0800170 EXPECT_CALL(mockedAssociationInterface, createActiveAssociation(dBusPath))
171 .Times(1);
172 EXPECT_CALL(mockedAssociationInterface, addFunctionalAssociation(dBusPath))
173 .Times(1);
174
Lei YUff83c2a2019-09-12 13:55:18 +0800175 onUpdateDone();
176 EXPECT_EQ(Status::Active, activation->activation());
177}
178
179TEST_F(TestActivation, doUpdateFourPSUsFailonSecond)
180{
181 constexpr auto psu0 = "/com/example/inventory/psu0";
182 constexpr auto psu1 = "/com/example/inventory/psu1";
183 constexpr auto psu2 = "/com/example/inventory/psu2";
184 constexpr auto psu3 = "/com/example/inventory/psu3";
Lei YU99301372019-09-29 16:27:12 +0800185 activation = std::make_unique<Activation>(
186 mockedBus, dBusPath, versionId, extVersion, status, associations,
187 &mockedAssociationInterface, filePath);
Lei YUff83c2a2019-09-12 13:55:18 +0800188 ON_CALL(mockedUtils, getPSUInventoryPath(_))
189 .WillByDefault(Return(
190 std::vector<std::string>({psu0, psu1, psu2, psu3}))); // 4 PSUs
191 activation->requestedActivation(RequestedStatus::Active);
192
193 EXPECT_EQ(Status::Activating, activation->activation());
194 EXPECT_EQ(10, getProgress());
195
196 onUpdateDone();
197 EXPECT_EQ(Status::Activating, activation->activation());
198 EXPECT_EQ(30, getProgress());
199
Lei YU7f2a2152019-09-16 16:50:18 +0800200 EXPECT_CALL(mockedAssociationInterface, createActiveAssociation(dBusPath))
201 .Times(0);
202 EXPECT_CALL(mockedAssociationInterface, addFunctionalAssociation(dBusPath))
203 .Times(0);
Lei YUff83c2a2019-09-12 13:55:18 +0800204 onUpdateFailed();
205 EXPECT_EQ(Status::Failed, activation->activation());
206}
207
208TEST_F(TestActivation, doUpdateOnExceptionFromDbus)
209{
210 constexpr auto psu0 = "/com/example/inventory/psu0";
Lei YU99301372019-09-29 16:27:12 +0800211 activation = std::make_unique<Activation>(
212 mockedBus, dBusPath, versionId, extVersion, status, associations,
213 &mockedAssociationInterface, filePath);
Lei YUff83c2a2019-09-12 13:55:18 +0800214 ON_CALL(mockedUtils, getPSUInventoryPath(_))
215 .WillByDefault(
216 Return(std::vector<std::string>({psu0}))); // One PSU inventory
217 ON_CALL(sdbusMock, sd_bus_call(_, _, _, _, nullptr))
218 .WillByDefault(Return(-1)); // Make sdbus call failure
219 activation->requestedActivation(RequestedStatus::Active);
220
221 EXPECT_EQ(Status::Failed, activation->activation());
222}
Lei YU9edb7332019-09-19 14:46:19 +0800223
224TEST_F(TestActivation, doUpdateOnePSUModelNotCompatible)
225{
226 constexpr auto psu0 = "/com/example/inventory/psu0";
227 extVersion = "manufacturer=TestManu,model=DifferentModel";
Lei YU99301372019-09-29 16:27:12 +0800228 activation = std::make_unique<Activation>(
229 mockedBus, dBusPath, versionId, extVersion, status, associations,
230 &mockedAssociationInterface, filePath);
Lei YU9edb7332019-09-19 14:46:19 +0800231 ON_CALL(mockedUtils, getPSUInventoryPath(_))
232 .WillByDefault(Return(std::vector<std::string>({psu0})));
233 activation->requestedActivation(RequestedStatus::Active);
234
235 EXPECT_EQ(Status::Failed, activation->activation());
236}
237
238TEST_F(TestActivation, doUpdateOnePSUManufactureNotCompatible)
239{
240 constexpr auto psu0 = "/com/example/inventory/psu0";
241 extVersion = "manufacturer=DifferentManu,model=TestModel";
Lei YU99301372019-09-29 16:27:12 +0800242 activation = std::make_unique<Activation>(
243 mockedBus, dBusPath, versionId, extVersion, status, associations,
244 &mockedAssociationInterface, filePath);
Lei YU9edb7332019-09-19 14:46:19 +0800245 ON_CALL(mockedUtils, getPSUInventoryPath(_))
246 .WillByDefault(Return(std::vector<std::string>({psu0})));
247 activation->requestedActivation(RequestedStatus::Active);
248
249 EXPECT_EQ(Status::Failed, activation->activation());
250}
251
252TEST_F(TestActivation, doUpdateOnePSUSelfManufactureIsEmpty)
253{
254 ON_CALL(mockedUtils, getPropertyImpl(_, _, _, _, StrEq(MANUFACTURER)))
255 .WillByDefault(Return(any(PropertyType(std::string("")))));
256 extVersion = "manufacturer=AnyManu,model=TestModel";
257 // Below is the same as doUpdateOnePSUOK case
258 constexpr auto psu0 = "/com/example/inventory/psu0";
Lei YU99301372019-09-29 16:27:12 +0800259 activation = std::make_unique<Activation>(
260 mockedBus, dBusPath, versionId, extVersion, status, associations,
261 &mockedAssociationInterface, filePath);
Lei YU9edb7332019-09-19 14:46:19 +0800262 ON_CALL(mockedUtils, getPSUInventoryPath(_))
263 .WillByDefault(
264 Return(std::vector<std::string>({psu0}))); // One PSU inventory
265 activation->requestedActivation(RequestedStatus::Active);
266
267 EXPECT_EQ(Status::Activating, activation->activation());
268
269 EXPECT_CALL(mockedAssociationInterface, createActiveAssociation(dBusPath))
270 .Times(1);
271 EXPECT_CALL(mockedAssociationInterface, addFunctionalAssociation(dBusPath))
272 .Times(1);
273 onUpdateDone();
274 EXPECT_EQ(Status::Active, activation->activation());
275}
276
277TEST_F(TestActivation, doUpdateFourPSUsSecondPSUNotCompatible)
278{
279 constexpr auto psu0 = "/com/example/inventory/psu0";
280 constexpr auto psu1 = "/com/example/inventory/psu1";
281 constexpr auto psu2 = "/com/example/inventory/psu2";
282 constexpr auto psu3 = "/com/example/inventory/psu3";
283 ON_CALL(mockedUtils, getPropertyImpl(_, _, StrEq(psu1), _, StrEq(MODEL)))
284 .WillByDefault(
285 Return(any(PropertyType(std::string("DifferentModel")))));
Lei YU99301372019-09-29 16:27:12 +0800286 activation = std::make_unique<Activation>(
287 mockedBus, dBusPath, versionId, extVersion, status, associations,
288 &mockedAssociationInterface, filePath);
Lei YU9edb7332019-09-19 14:46:19 +0800289 ON_CALL(mockedUtils, getPSUInventoryPath(_))
290 .WillByDefault(Return(
291 std::vector<std::string>({psu0, psu1, psu2, psu3}))); // 4 PSUs
292 activation->requestedActivation(RequestedStatus::Active);
293
294 const auto& psuQueue = getPsuQueue();
295 EXPECT_EQ(3u, psuQueue.size());
296
297 // Only 3 PSUs shall be updated, and psu1 shall be skipped
298 EXPECT_EQ(Status::Activating, activation->activation());
299 EXPECT_EQ(10, getProgress());
300
301 onUpdateDone();
302 EXPECT_EQ(Status::Activating, activation->activation());
303 EXPECT_EQ(36, getProgress());
304
305 onUpdateDone();
306 EXPECT_EQ(Status::Activating, activation->activation());
307 EXPECT_EQ(62, getProgress());
308
309 EXPECT_CALL(mockedAssociationInterface, createActiveAssociation(dBusPath))
310 .Times(1);
311 EXPECT_CALL(mockedAssociationInterface, addFunctionalAssociation(dBusPath))
312 .Times(1);
313
314 onUpdateDone();
315 EXPECT_EQ(Status::Active, activation->activation());
316}