1//
2// Copyright (C) 2014 The Android Open Source Project
3//
4// Licensed under the Apache License, Version 2.0 (the "License");
5// you may not use this file except in compliance with the License.
6// You may obtain a copy of the License at
7//
8//      http://www.apache.org/licenses/LICENSE-2.0
9//
10// Unless required by applicable law or agreed to in writing, software
11// distributed under the License is distributed on an "AS IS" BASIS,
12// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13// See the License for the specific language governing permissions and
14// limitations under the License.
15//
16
17#include "update_engine/update_manager/real_updater_provider.h"
18
19#include <memory>
20#include <string>
21
22#include <base/time/time.h>
23#include <gtest/gtest.h>
24#include <update_engine/dbus-constants.h>
25
26#include "update_engine/common/fake_clock.h"
27#include "update_engine/common/fake_prefs.h"
28#include "update_engine/fake_system_state.h"
29#include "update_engine/mock_update_attempter.h"
30#include "update_engine/omaha_request_params.h"
31#include "update_engine/update_manager/umtest_utils.h"
32
33using base::Time;
34using base::TimeDelta;
35using chromeos_update_engine::FakeClock;
36using chromeos_update_engine::FakePrefs;
37using chromeos_update_engine::FakeSystemState;
38using chromeos_update_engine::OmahaRequestParams;
39using std::string;
40using std::unique_ptr;
41using testing::Return;
42using testing::SetArgPointee;
43using testing::_;
44
45namespace {
46
47// Generates a fixed timestamp for use in faking the current time.
48Time FixedTime() {
49  Time::Exploded now_exp;
50  now_exp.year = 2014;
51  now_exp.month = 3;
52  now_exp.day_of_week = 2;
53  now_exp.day_of_month = 18;
54  now_exp.hour = 8;
55  now_exp.minute = 5;
56  now_exp.second = 33;
57  now_exp.millisecond = 675;
58  return Time::FromLocalExploded(now_exp);
59}
60
61// Rounds down a timestamp to the nearest second. This is useful when faking
62// times that are converted to time_t (no sub-second resolution).
63Time RoundedToSecond(Time time) {
64  Time::Exploded exp;
65  time.LocalExplode(&exp);
66  exp.millisecond = 0;
67  return Time::FromLocalExploded(exp);
68}
69
70}  // namespace
71
72namespace chromeos_update_manager {
73
74class UmRealUpdaterProviderTest : public ::testing::Test {
75 protected:
76  void SetUp() override {
77    fake_clock_ = fake_sys_state_.fake_clock();
78    fake_sys_state_.set_prefs(&fake_prefs_);
79    provider_.reset(new RealUpdaterProvider(&fake_sys_state_));
80    ASSERT_NE(nullptr, provider_.get());
81    // Check that provider initializes correctly.
82    ASSERT_TRUE(provider_->Init());
83  }
84
85  // Sets up mock expectations for testing the update completed time reporting.
86  // |valid| determines whether the returned time is valid. Returns the expected
87  // update completed time value.
88  Time SetupUpdateCompletedTime(bool valid) {
89    const TimeDelta kDurationSinceUpdate = TimeDelta::FromMinutes(7);
90    const Time kUpdateBootTime = Time() + kDurationSinceUpdate * 2;
91    const Time kCurrBootTime = (valid ?
92                                kUpdateBootTime + kDurationSinceUpdate :
93                                kUpdateBootTime - kDurationSinceUpdate);
94    const Time kCurrWallclockTime = FixedTime();
95    EXPECT_CALL(*fake_sys_state_.mock_update_attempter(),
96                GetBootTimeAtUpdate(_))
97        .WillOnce(DoAll(SetArgPointee<0>(kUpdateBootTime), Return(true)));
98    fake_clock_->SetBootTime(kCurrBootTime);
99    fake_clock_->SetWallclockTime(kCurrWallclockTime);
100    return kCurrWallclockTime - kDurationSinceUpdate;
101  }
102
103  FakeSystemState fake_sys_state_;
104  FakeClock* fake_clock_;  // Short for fake_sys_state_.fake_clock()
105  FakePrefs fake_prefs_;
106  unique_ptr<RealUpdaterProvider> provider_;
107};
108
109TEST_F(UmRealUpdaterProviderTest, UpdaterStartedTimeIsWallclockTime) {
110  fake_clock_->SetWallclockTime(Time::FromDoubleT(123.456));
111  fake_clock_->SetMonotonicTime(Time::FromDoubleT(456.123));
112  // Run SetUp again to re-setup the provider under test to use these values.
113  SetUp();
114  UmTestUtils::ExpectVariableHasValue(Time::FromDoubleT(123.456),
115                                      provider_->var_updater_started_time());
116}
117
118TEST_F(UmRealUpdaterProviderTest, GetLastCheckedTimeOkay) {
119  EXPECT_CALL(*fake_sys_state_.mock_update_attempter(),
120              GetStatus(_, _, _, _, _))
121      .WillOnce(DoAll(SetArgPointee<0>(FixedTime().ToTimeT()), Return(true)));
122  UmTestUtils::ExpectVariableHasValue(RoundedToSecond(FixedTime()),
123                                      provider_->var_last_checked_time());
124}
125
126TEST_F(UmRealUpdaterProviderTest, GetLastCheckedTimeFailNoValue) {
127  EXPECT_CALL(*fake_sys_state_.mock_update_attempter(),
128              GetStatus(_, _, _, _, _))
129      .WillOnce(Return(false));
130  UmTestUtils::ExpectVariableNotSet(provider_->var_last_checked_time());
131}
132
133TEST_F(UmRealUpdaterProviderTest, GetProgressOkayMin) {
134  EXPECT_CALL(*fake_sys_state_.mock_update_attempter(),
135              GetStatus(_, _, _, _, _))
136      .WillOnce(DoAll(SetArgPointee<1>(0.0), Return(true)));
137  UmTestUtils::ExpectVariableHasValue(0.0, provider_->var_progress());
138}
139
140TEST_F(UmRealUpdaterProviderTest, GetProgressOkayMid) {
141  EXPECT_CALL(*fake_sys_state_.mock_update_attempter(),
142              GetStatus(_, _, _, _, _))
143      .WillOnce(DoAll(SetArgPointee<1>(0.3), Return(true)));
144  UmTestUtils::ExpectVariableHasValue(0.3, provider_->var_progress());
145}
146
147TEST_F(UmRealUpdaterProviderTest, GetProgressOkayMax) {
148  EXPECT_CALL(*fake_sys_state_.mock_update_attempter(),
149              GetStatus(_, _, _, _, _))
150      .WillOnce(DoAll(SetArgPointee<1>(1.0), Return(true)));
151  UmTestUtils::ExpectVariableHasValue(1.0, provider_->var_progress());
152}
153
154TEST_F(UmRealUpdaterProviderTest, GetProgressFailNoValue) {
155  EXPECT_CALL(*fake_sys_state_.mock_update_attempter(),
156              GetStatus(_, _, _, _, _))
157      .WillOnce(Return(false));
158  UmTestUtils::ExpectVariableNotSet(provider_->var_progress());
159}
160
161TEST_F(UmRealUpdaterProviderTest, GetProgressFailTooSmall) {
162  EXPECT_CALL(*fake_sys_state_.mock_update_attempter(),
163              GetStatus(_, _, _, _, _))
164      .WillOnce(DoAll(SetArgPointee<1>(-2.0), Return(true)));
165  UmTestUtils::ExpectVariableNotSet(provider_->var_progress());
166}
167
168TEST_F(UmRealUpdaterProviderTest, GetProgressFailTooBig) {
169  EXPECT_CALL(*fake_sys_state_.mock_update_attempter(),
170              GetStatus(_, _, _, _, _))
171      .WillOnce(DoAll(SetArgPointee<1>(2.0), Return(true)));
172  UmTestUtils::ExpectVariableNotSet(provider_->var_progress());
173}
174
175TEST_F(UmRealUpdaterProviderTest, GetStageOkayIdle) {
176  EXPECT_CALL(*fake_sys_state_.mock_update_attempter(),
177              GetStatus(_, _, _, _, _))
178      .WillOnce(DoAll(SetArgPointee<2>(update_engine::kUpdateStatusIdle),
179                      Return(true)));
180  UmTestUtils::ExpectVariableHasValue(Stage::kIdle, provider_->var_stage());
181}
182
183TEST_F(UmRealUpdaterProviderTest, GetStageOkayCheckingForUpdate) {
184  EXPECT_CALL(*fake_sys_state_.mock_update_attempter(),
185              GetStatus(_, _, _, _, _))
186      .WillOnce(DoAll(
187              SetArgPointee<2>(update_engine::kUpdateStatusCheckingForUpdate),
188              Return(true)));
189  UmTestUtils::ExpectVariableHasValue(Stage::kCheckingForUpdate,
190                                      provider_->var_stage());
191}
192
193TEST_F(UmRealUpdaterProviderTest, GetStageOkayUpdateAvailable) {
194  EXPECT_CALL(*fake_sys_state_.mock_update_attempter(),
195              GetStatus(_, _, _, _, _))
196      .WillOnce(DoAll(
197              SetArgPointee<2>(update_engine::kUpdateStatusUpdateAvailable),
198              Return(true)));
199  UmTestUtils::ExpectVariableHasValue(Stage::kUpdateAvailable,
200                                      provider_->var_stage());
201}
202
203TEST_F(UmRealUpdaterProviderTest, GetStageOkayDownloading) {
204  EXPECT_CALL(*fake_sys_state_.mock_update_attempter(),
205              GetStatus(_, _, _, _, _))
206      .WillOnce(DoAll(SetArgPointee<2>(update_engine::kUpdateStatusDownloading),
207                      Return(true)));
208  UmTestUtils::ExpectVariableHasValue(Stage::kDownloading,
209                                      provider_->var_stage());
210}
211
212TEST_F(UmRealUpdaterProviderTest, GetStageOkayVerifying) {
213  EXPECT_CALL(*fake_sys_state_.mock_update_attempter(),
214              GetStatus(_, _, _, _, _))
215      .WillOnce(DoAll(SetArgPointee<2>(update_engine::kUpdateStatusVerifying),
216                      Return(true)));
217  UmTestUtils::ExpectVariableHasValue(Stage::kVerifying,
218                                      provider_->var_stage());
219}
220
221TEST_F(UmRealUpdaterProviderTest, GetStageOkayFinalizing) {
222  EXPECT_CALL(*fake_sys_state_.mock_update_attempter(),
223              GetStatus(_, _, _, _, _))
224      .WillOnce(DoAll(SetArgPointee<2>(update_engine::kUpdateStatusFinalizing),
225                      Return(true)));
226  UmTestUtils::ExpectVariableHasValue(Stage::kFinalizing,
227                                      provider_->var_stage());
228}
229
230TEST_F(UmRealUpdaterProviderTest, GetStageOkayUpdatedNeedReboot) {
231  EXPECT_CALL(*fake_sys_state_.mock_update_attempter(),
232              GetStatus(_, _, _, _, _))
233      .WillOnce(DoAll(
234              SetArgPointee<2>(update_engine::kUpdateStatusUpdatedNeedReboot),
235              Return(true)));
236  UmTestUtils::ExpectVariableHasValue(Stage::kUpdatedNeedReboot,
237                                      provider_->var_stage());
238}
239
240TEST_F(UmRealUpdaterProviderTest, GetStageOkayReportingErrorEvent) {
241  EXPECT_CALL(*fake_sys_state_.mock_update_attempter(),
242              GetStatus(_, _, _, _, _))
243      .WillOnce(DoAll(
244              SetArgPointee<2>(update_engine::kUpdateStatusReportingErrorEvent),
245              Return(true)));
246  UmTestUtils::ExpectVariableHasValue(Stage::kReportingErrorEvent,
247                                      provider_->var_stage());
248}
249
250TEST_F(UmRealUpdaterProviderTest, GetStageOkayAttemptingRollback) {
251  EXPECT_CALL(*fake_sys_state_.mock_update_attempter(),
252              GetStatus(_, _, _, _, _))
253      .WillOnce(DoAll(
254              SetArgPointee<2>(update_engine::kUpdateStatusAttemptingRollback),
255              Return(true)));
256  UmTestUtils::ExpectVariableHasValue(Stage::kAttemptingRollback,
257                                      provider_->var_stage());
258}
259
260TEST_F(UmRealUpdaterProviderTest, GetStageFailNoValue) {
261  EXPECT_CALL(*fake_sys_state_.mock_update_attempter(),
262              GetStatus(_, _, _, _, _))
263      .WillOnce(Return(false));
264  UmTestUtils::ExpectVariableNotSet(provider_->var_stage());
265}
266
267TEST_F(UmRealUpdaterProviderTest, GetStageFailUnknown) {
268  EXPECT_CALL(*fake_sys_state_.mock_update_attempter(),
269              GetStatus(_, _, _, _, _))
270      .WillOnce(DoAll(SetArgPointee<2>("FooUpdateEngineState"),
271                      Return(true)));
272  UmTestUtils::ExpectVariableNotSet(provider_->var_stage());
273}
274
275TEST_F(UmRealUpdaterProviderTest, GetStageFailEmpty) {
276  EXPECT_CALL(*fake_sys_state_.mock_update_attempter(),
277              GetStatus(_, _, _, _, _))
278      .WillOnce(DoAll(SetArgPointee<2>(""), Return(true)));
279  UmTestUtils::ExpectVariableNotSet(provider_->var_stage());
280}
281
282TEST_F(UmRealUpdaterProviderTest, GetNewVersionOkay) {
283  EXPECT_CALL(*fake_sys_state_.mock_update_attempter(),
284              GetStatus(_, _, _, _, _))
285      .WillOnce(DoAll(SetArgPointee<3>("1.2.0"), Return(true)));
286  UmTestUtils::ExpectVariableHasValue(string("1.2.0"),
287                                      provider_->var_new_version());
288}
289
290TEST_F(UmRealUpdaterProviderTest, GetNewVersionFailNoValue) {
291  EXPECT_CALL(*fake_sys_state_.mock_update_attempter(),
292              GetStatus(_, _, _, _, _))
293      .WillOnce(Return(false));
294  UmTestUtils::ExpectVariableNotSet(provider_->var_new_version());
295}
296
297TEST_F(UmRealUpdaterProviderTest, GetPayloadSizeOkayZero) {
298  EXPECT_CALL(*fake_sys_state_.mock_update_attempter(),
299              GetStatus(_, _, _, _, _))
300      .WillOnce(DoAll(SetArgPointee<4>(static_cast<int64_t>(0)), Return(true)));
301  UmTestUtils::ExpectVariableHasValue(static_cast<int64_t>(0),
302                                      provider_->var_payload_size());
303}
304
305TEST_F(UmRealUpdaterProviderTest, GetPayloadSizeOkayArbitrary) {
306  EXPECT_CALL(*fake_sys_state_.mock_update_attempter(),
307              GetStatus(_, _, _, _, _))
308      .WillOnce(DoAll(SetArgPointee<4>(static_cast<int64_t>(567890)),
309                      Return(true)));
310  UmTestUtils::ExpectVariableHasValue(static_cast<int64_t>(567890),
311                                      provider_->var_payload_size());
312}
313
314TEST_F(UmRealUpdaterProviderTest, GetPayloadSizeOkayTwoGigabytes) {
315  EXPECT_CALL(*fake_sys_state_.mock_update_attempter(),
316              GetStatus(_, _, _, _, _))
317      .WillOnce(DoAll(SetArgPointee<4>(static_cast<int64_t>(1) << 31),
318                      Return(true)));
319  UmTestUtils::ExpectVariableHasValue(static_cast<int64_t>(1) << 31,
320                                      provider_->var_payload_size());
321}
322
323TEST_F(UmRealUpdaterProviderTest, GetPayloadSizeFailNoValue) {
324  EXPECT_CALL(*fake_sys_state_.mock_update_attempter(),
325              GetStatus(_, _, _, _, _))
326      .WillOnce(Return(false));
327  UmTestUtils::ExpectVariableNotSet(provider_->var_payload_size());
328}
329
330TEST_F(UmRealUpdaterProviderTest, GetPayloadSizeFailNegative) {
331  EXPECT_CALL(*fake_sys_state_.mock_update_attempter(),
332              GetStatus(_, _, _, _, _))
333      .WillOnce(DoAll(SetArgPointee<4>(static_cast<int64_t>(-1024)),
334                      Return(true)));
335  UmTestUtils::ExpectVariableNotSet(provider_->var_payload_size());
336}
337
338TEST_F(UmRealUpdaterProviderTest, GetCurrChannelOkay) {
339  const string kChannelName("foo-channel");
340  OmahaRequestParams request_params(&fake_sys_state_);
341  request_params.Init("", "", false);
342  request_params.set_current_channel(kChannelName);
343  fake_sys_state_.set_request_params(&request_params);
344  UmTestUtils::ExpectVariableHasValue(kChannelName,
345                                      provider_->var_curr_channel());
346}
347
348TEST_F(UmRealUpdaterProviderTest, GetCurrChannelFailEmpty) {
349  OmahaRequestParams request_params(&fake_sys_state_);
350  request_params.Init("", "", false);
351  request_params.set_current_channel("");
352  fake_sys_state_.set_request_params(&request_params);
353  UmTestUtils::ExpectVariableNotSet(provider_->var_curr_channel());
354}
355
356TEST_F(UmRealUpdaterProviderTest, GetNewChannelOkay) {
357  const string kChannelName("foo-channel");
358  OmahaRequestParams request_params(&fake_sys_state_);
359  request_params.Init("", "", false);
360  request_params.set_target_channel(kChannelName);
361  fake_sys_state_.set_request_params(&request_params);
362  UmTestUtils::ExpectVariableHasValue(kChannelName,
363                                      provider_->var_new_channel());
364}
365
366TEST_F(UmRealUpdaterProviderTest, GetNewChannelFailEmpty) {
367  OmahaRequestParams request_params(&fake_sys_state_);
368  request_params.Init("", "", false);
369  request_params.set_target_channel("");
370  fake_sys_state_.set_request_params(&request_params);
371  UmTestUtils::ExpectVariableNotSet(provider_->var_new_channel());
372}
373
374TEST_F(UmRealUpdaterProviderTest, GetP2PEnabledOkayPrefDoesntExist) {
375  UmTestUtils::ExpectVariableHasValue(false, provider_->var_p2p_enabled());
376}
377
378TEST_F(UmRealUpdaterProviderTest, GetP2PEnabledOkayPrefReadsFalse) {
379  fake_prefs_.SetBoolean(chromeos_update_engine::kPrefsP2PEnabled, false);
380  UmTestUtils::ExpectVariableHasValue(false, provider_->var_p2p_enabled());
381}
382
383TEST_F(UmRealUpdaterProviderTest, GetP2PEnabledReadWhenInitialized) {
384  fake_prefs_.SetBoolean(chromeos_update_engine::kPrefsP2PEnabled, true);
385  SetUp();
386  UmTestUtils::ExpectVariableHasValue(true, provider_->var_p2p_enabled());
387}
388
389TEST_F(UmRealUpdaterProviderTest, GetP2PEnabledUpdated) {
390  fake_prefs_.SetBoolean(chromeos_update_engine::kPrefsP2PEnabled, false);
391  UmTestUtils::ExpectVariableHasValue(false, provider_->var_p2p_enabled());
392  fake_prefs_.SetBoolean(chromeos_update_engine::kPrefsP2PEnabled, true);
393  UmTestUtils::ExpectVariableHasValue(true, provider_->var_p2p_enabled());
394  fake_prefs_.Delete(chromeos_update_engine::kPrefsP2PEnabled);
395  UmTestUtils::ExpectVariableHasValue(false, provider_->var_p2p_enabled());
396}
397
398TEST_F(UmRealUpdaterProviderTest, GetCellularEnabledOkayPrefDoesntExist) {
399  UmTestUtils::ExpectVariableHasValue(false, provider_->var_cellular_enabled());
400}
401
402TEST_F(UmRealUpdaterProviderTest, GetCellularEnabledOkayPrefReadsTrue) {
403  fake_prefs_.SetBoolean(
404      chromeos_update_engine::kPrefsUpdateOverCellularPermission, true);
405  UmTestUtils::ExpectVariableHasValue(true, provider_->var_cellular_enabled());
406}
407
408TEST_F(UmRealUpdaterProviderTest, GetUpdateCompletedTimeOkay) {
409  Time expected = SetupUpdateCompletedTime(true);
410  UmTestUtils::ExpectVariableHasValue(expected,
411                                      provider_->var_update_completed_time());
412}
413
414TEST_F(UmRealUpdaterProviderTest, GetUpdateCompletedTimeFailNoValue) {
415  EXPECT_CALL(*fake_sys_state_.mock_update_attempter(), GetBootTimeAtUpdate(_))
416      .WillOnce(Return(false));
417  UmTestUtils::ExpectVariableNotSet(provider_->var_update_completed_time());
418}
419
420TEST_F(UmRealUpdaterProviderTest, GetUpdateCompletedTimeFailInvalidValue) {
421  SetupUpdateCompletedTime(false);
422  UmTestUtils::ExpectVariableNotSet(provider_->var_update_completed_time());
423}
424
425TEST_F(UmRealUpdaterProviderTest, GetConsecutiveFailedUpdateChecks) {
426  const unsigned int kNumFailedChecks = 3;
427  EXPECT_CALL(*fake_sys_state_.mock_update_attempter(),
428              consecutive_failed_update_checks())
429      .WillRepeatedly(Return(kNumFailedChecks));
430  UmTestUtils::ExpectVariableHasValue(
431      kNumFailedChecks, provider_->var_consecutive_failed_update_checks());
432}
433
434TEST_F(UmRealUpdaterProviderTest, GetServerDictatedPollInterval) {
435  const unsigned int kPollInterval = 2 * 60 * 60;  // Two hours.
436  EXPECT_CALL(*fake_sys_state_.mock_update_attempter(),
437              server_dictated_poll_interval())
438      .WillRepeatedly(Return(kPollInterval));
439  UmTestUtils::ExpectVariableHasValue(
440      kPollInterval, provider_->var_server_dictated_poll_interval());
441}
442
443}  // namespace chromeos_update_manager
444