blob: 0c45a37689afeac001a690daa75cdc554fbb34ba [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 YU99301372019-09-29 16:27:12 +080062 std::string filePath = "";
Lei YU7f2a2152019-09-16 16:50:18 +080063 std::string dBusPath = std::string(SOFTWARE_OBJPATH) + "/" + versionId;
Lei YUff83c2a2019-09-12 13:55:18 +080064 Status status = Status::Ready;
Lei YU12c9f4c2019-09-11 15:08:15 +080065 AssociationList associations;
66};
67
68TEST_F(TestActivation, ctordtor)
69{
Lei YU99301372019-09-29 16:27:12 +080070 activation = std::make_unique<Activation>(
71 mockedBus, dBusPath, versionId, extVersion, status, associations,
72 &mockedAssociationInterface, filePath);
Lei YU12c9f4c2019-09-11 15:08:15 +080073}
74
Lei YU58c26e32019-09-27 17:52:06 +080075TEST_F(TestActivation, ctorWithInvalidExtVersion)
76{
77 extVersion = "invalid text";
78 activation = std::make_unique<Activation>(
79 mockedBus, dBusPath, versionId, extVersion, status, associations,
80 &mockedAssociationInterface, filePath);
81}
82
Lei YU12c9f4c2019-09-11 15:08:15 +080083namespace phosphor::software::updater::internal
84{
85extern std::string getUpdateService(const std::string& psuInventoryPath,
86 const std::string& versionId);
87}
88
89TEST_F(TestActivation, getUpdateService)
90{
91 std::string psuInventoryPath = "/com/example/inventory/powersupply1";
92 std::string versionId = "12345678";
93 std::string toCompare = "psu-update@-com-example-inventory-"
94 "powersupply1\\x20-tmp-images-12345678.service";
95
96 auto service = phosphor::software::updater::internal::getUpdateService(
97 psuInventoryPath, versionId);
98 EXPECT_EQ(toCompare, service);
99}
Lei YUff83c2a2019-09-12 13:55:18 +0800100
101TEST_F(TestActivation, doUpdateWhenNoPSU)
102{
Lei YU99301372019-09-29 16:27:12 +0800103 activation = std::make_unique<Activation>(
104 mockedBus, dBusPath, versionId, extVersion, status, associations,
105 &mockedAssociationInterface, filePath);
Lei YUff83c2a2019-09-12 13:55:18 +0800106 ON_CALL(mockedUtils, getPSUInventoryPath(_))
107 .WillByDefault(
108 Return(std::vector<std::string>({}))); // No PSU inventory
109 activation->requestedActivation(RequestedStatus::Active);
110
Lei YU7f2a2152019-09-16 16:50:18 +0800111 EXPECT_CALL(mockedAssociationInterface, createActiveAssociation(dBusPath))
112 .Times(0);
113 EXPECT_CALL(mockedAssociationInterface, addFunctionalAssociation(dBusPath))
114 .Times(0);
Lei YUff83c2a2019-09-12 13:55:18 +0800115 EXPECT_EQ(Status::Failed, activation->activation());
116}
117
118TEST_F(TestActivation, doUpdateOnePSUOK)
119{
120 constexpr auto psu0 = "/com/example/inventory/psu0";
Lei YU99301372019-09-29 16:27:12 +0800121 activation = std::make_unique<Activation>(
122 mockedBus, dBusPath, versionId, extVersion, status, associations,
123 &mockedAssociationInterface, filePath);
Lei YUff83c2a2019-09-12 13:55:18 +0800124 ON_CALL(mockedUtils, getPSUInventoryPath(_))
125 .WillByDefault(
126 Return(std::vector<std::string>({psu0}))); // One PSU inventory
127 activation->requestedActivation(RequestedStatus::Active);
128
129 EXPECT_EQ(Status::Activating, activation->activation());
130
Lei YU7f2a2152019-09-16 16:50:18 +0800131 EXPECT_CALL(mockedAssociationInterface, createActiveAssociation(dBusPath))
132 .Times(1);
133 EXPECT_CALL(mockedAssociationInterface, addFunctionalAssociation(dBusPath))
134 .Times(1);
Lei YUff83c2a2019-09-12 13:55:18 +0800135 onUpdateDone();
136 EXPECT_EQ(Status::Active, activation->activation());
137}
138
139TEST_F(TestActivation, doUpdateFourPSUsOK)
140{
141 constexpr auto psu0 = "/com/example/inventory/psu0";
142 constexpr auto psu1 = "/com/example/inventory/psu1";
143 constexpr auto psu2 = "/com/example/inventory/psu2";
144 constexpr auto psu3 = "/com/example/inventory/psu3";
Lei YU99301372019-09-29 16:27:12 +0800145 activation = std::make_unique<Activation>(
146 mockedBus, dBusPath, versionId, extVersion, status, associations,
147 &mockedAssociationInterface, filePath);
Lei YUff83c2a2019-09-12 13:55:18 +0800148 ON_CALL(mockedUtils, getPSUInventoryPath(_))
149 .WillByDefault(Return(
150 std::vector<std::string>({psu0, psu1, psu2, psu3}))); // 4 PSUs
151 activation->requestedActivation(RequestedStatus::Active);
152
153 EXPECT_EQ(Status::Activating, activation->activation());
154 EXPECT_EQ(10, getProgress());
155
156 onUpdateDone();
157 EXPECT_EQ(Status::Activating, activation->activation());
158 EXPECT_EQ(30, getProgress());
159
160 onUpdateDone();
161 EXPECT_EQ(Status::Activating, activation->activation());
162 EXPECT_EQ(50, getProgress());
163
164 onUpdateDone();
165 EXPECT_EQ(Status::Activating, activation->activation());
166 EXPECT_EQ(70, getProgress());
167
Lei YU7f2a2152019-09-16 16:50:18 +0800168 EXPECT_CALL(mockedAssociationInterface, createActiveAssociation(dBusPath))
169 .Times(1);
170 EXPECT_CALL(mockedAssociationInterface, addFunctionalAssociation(dBusPath))
171 .Times(1);
172
Lei YUff83c2a2019-09-12 13:55:18 +0800173 onUpdateDone();
174 EXPECT_EQ(Status::Active, activation->activation());
175}
176
177TEST_F(TestActivation, doUpdateFourPSUsFailonSecond)
178{
179 constexpr auto psu0 = "/com/example/inventory/psu0";
180 constexpr auto psu1 = "/com/example/inventory/psu1";
181 constexpr auto psu2 = "/com/example/inventory/psu2";
182 constexpr auto psu3 = "/com/example/inventory/psu3";
Lei YU99301372019-09-29 16:27:12 +0800183 activation = std::make_unique<Activation>(
184 mockedBus, dBusPath, versionId, extVersion, status, associations,
185 &mockedAssociationInterface, filePath);
Lei YUff83c2a2019-09-12 13:55:18 +0800186 ON_CALL(mockedUtils, getPSUInventoryPath(_))
187 .WillByDefault(Return(
188 std::vector<std::string>({psu0, psu1, psu2, psu3}))); // 4 PSUs
189 activation->requestedActivation(RequestedStatus::Active);
190
191 EXPECT_EQ(Status::Activating, activation->activation());
192 EXPECT_EQ(10, getProgress());
193
194 onUpdateDone();
195 EXPECT_EQ(Status::Activating, activation->activation());
196 EXPECT_EQ(30, getProgress());
197
Lei YU7f2a2152019-09-16 16:50:18 +0800198 EXPECT_CALL(mockedAssociationInterface, createActiveAssociation(dBusPath))
199 .Times(0);
200 EXPECT_CALL(mockedAssociationInterface, addFunctionalAssociation(dBusPath))
201 .Times(0);
Lei YUff83c2a2019-09-12 13:55:18 +0800202 onUpdateFailed();
203 EXPECT_EQ(Status::Failed, activation->activation());
204}
205
206TEST_F(TestActivation, doUpdateOnExceptionFromDbus)
207{
208 constexpr auto psu0 = "/com/example/inventory/psu0";
Lei YU99301372019-09-29 16:27:12 +0800209 activation = std::make_unique<Activation>(
210 mockedBus, dBusPath, versionId, extVersion, status, associations,
211 &mockedAssociationInterface, filePath);
Lei YUff83c2a2019-09-12 13:55:18 +0800212 ON_CALL(mockedUtils, getPSUInventoryPath(_))
213 .WillByDefault(
214 Return(std::vector<std::string>({psu0}))); // One PSU inventory
215 ON_CALL(sdbusMock, sd_bus_call(_, _, _, _, nullptr))
216 .WillByDefault(Return(-1)); // Make sdbus call failure
217 activation->requestedActivation(RequestedStatus::Active);
218
219 EXPECT_EQ(Status::Failed, activation->activation());
220}
Lei YU9edb7332019-09-19 14:46:19 +0800221
222TEST_F(TestActivation, doUpdateOnePSUModelNotCompatible)
223{
224 constexpr auto psu0 = "/com/example/inventory/psu0";
225 extVersion = "manufacturer=TestManu,model=DifferentModel";
Lei YU99301372019-09-29 16:27:12 +0800226 activation = std::make_unique<Activation>(
227 mockedBus, dBusPath, versionId, extVersion, status, associations,
228 &mockedAssociationInterface, filePath);
Lei YU9edb7332019-09-19 14:46:19 +0800229 ON_CALL(mockedUtils, getPSUInventoryPath(_))
230 .WillByDefault(Return(std::vector<std::string>({psu0})));
231 activation->requestedActivation(RequestedStatus::Active);
232
233 EXPECT_EQ(Status::Failed, activation->activation());
234}
235
236TEST_F(TestActivation, doUpdateOnePSUManufactureNotCompatible)
237{
238 constexpr auto psu0 = "/com/example/inventory/psu0";
239 extVersion = "manufacturer=DifferentManu,model=TestModel";
Lei YU99301372019-09-29 16:27:12 +0800240 activation = std::make_unique<Activation>(
241 mockedBus, dBusPath, versionId, extVersion, status, associations,
242 &mockedAssociationInterface, filePath);
Lei YU9edb7332019-09-19 14:46:19 +0800243 ON_CALL(mockedUtils, getPSUInventoryPath(_))
244 .WillByDefault(Return(std::vector<std::string>({psu0})));
245 activation->requestedActivation(RequestedStatus::Active);
246
247 EXPECT_EQ(Status::Failed, activation->activation());
248}
249
250TEST_F(TestActivation, doUpdateOnePSUSelfManufactureIsEmpty)
251{
252 ON_CALL(mockedUtils, getPropertyImpl(_, _, _, _, StrEq(MANUFACTURER)))
253 .WillByDefault(Return(any(PropertyType(std::string("")))));
254 extVersion = "manufacturer=AnyManu,model=TestModel";
255 // Below is the same as doUpdateOnePSUOK case
256 constexpr auto psu0 = "/com/example/inventory/psu0";
Lei YU99301372019-09-29 16:27:12 +0800257 activation = std::make_unique<Activation>(
258 mockedBus, dBusPath, versionId, extVersion, status, associations,
259 &mockedAssociationInterface, filePath);
Lei YU9edb7332019-09-19 14:46:19 +0800260 ON_CALL(mockedUtils, getPSUInventoryPath(_))
261 .WillByDefault(
262 Return(std::vector<std::string>({psu0}))); // One PSU inventory
263 activation->requestedActivation(RequestedStatus::Active);
264
265 EXPECT_EQ(Status::Activating, activation->activation());
266
267 EXPECT_CALL(mockedAssociationInterface, createActiveAssociation(dBusPath))
268 .Times(1);
269 EXPECT_CALL(mockedAssociationInterface, addFunctionalAssociation(dBusPath))
270 .Times(1);
271 onUpdateDone();
272 EXPECT_EQ(Status::Active, activation->activation());
273}
274
275TEST_F(TestActivation, doUpdateFourPSUsSecondPSUNotCompatible)
276{
277 constexpr auto psu0 = "/com/example/inventory/psu0";
278 constexpr auto psu1 = "/com/example/inventory/psu1";
279 constexpr auto psu2 = "/com/example/inventory/psu2";
280 constexpr auto psu3 = "/com/example/inventory/psu3";
281 ON_CALL(mockedUtils, getPropertyImpl(_, _, StrEq(psu1), _, StrEq(MODEL)))
282 .WillByDefault(
283 Return(any(PropertyType(std::string("DifferentModel")))));
Lei YU99301372019-09-29 16:27:12 +0800284 activation = std::make_unique<Activation>(
285 mockedBus, dBusPath, versionId, extVersion, status, associations,
286 &mockedAssociationInterface, filePath);
Lei YU9edb7332019-09-19 14:46:19 +0800287 ON_CALL(mockedUtils, getPSUInventoryPath(_))
288 .WillByDefault(Return(
289 std::vector<std::string>({psu0, psu1, psu2, psu3}))); // 4 PSUs
290 activation->requestedActivation(RequestedStatus::Active);
291
292 const auto& psuQueue = getPsuQueue();
293 EXPECT_EQ(3u, psuQueue.size());
294
295 // Only 3 PSUs shall be updated, and psu1 shall be skipped
296 EXPECT_EQ(Status::Activating, activation->activation());
297 EXPECT_EQ(10, getProgress());
298
299 onUpdateDone();
300 EXPECT_EQ(Status::Activating, activation->activation());
301 EXPECT_EQ(36, getProgress());
302
303 onUpdateDone();
304 EXPECT_EQ(Status::Activating, activation->activation());
305 EXPECT_EQ(62, getProgress());
306
307 EXPECT_CALL(mockedAssociationInterface, createActiveAssociation(dBusPath))
308 .Times(1);
309 EXPECT_CALL(mockedAssociationInterface, addFunctionalAssociation(dBusPath))
310 .Times(1);
311
312 onUpdateDone();
313 EXPECT_EQ(Status::Active, activation->activation());
314}