ronnie
2022-10-23 5a83b14855e763445ac36672c35ddb68300e4b42
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
//
// Copyright (C) 2018 The Android Open Source Project
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//      http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
 
#include "update_engine/update_manager/staging_utils.h"
 
#include <memory>
#include <utility>
 
#include <base/time/time.h>
#include <gtest/gtest.h>
#include <policy/mock_device_policy.h>
 
#include "update_engine/common/constants.h"
#include "update_engine/common/fake_prefs.h"
 
using base::TimeDelta;
using chromeos_update_engine::FakePrefs;
using chromeos_update_engine::kPrefsWallClockStagingWaitPeriod;
using testing::_;
using testing::DoAll;
using testing::Return;
using testing::SetArgPointee;
 
namespace chromeos_update_manager {
 
constexpr TimeDelta kDay = TimeDelta::FromDays(1);
constexpr int kMaxDays = 28;
constexpr int kValidDaySum = 14;
const StagingSchedule valid_schedule = {{2, 0}, {7, 50}, {9, 80}, {14, 100}};
 
class StagingUtilsScheduleTest : public testing::Test {
 protected:
  void SetUp() override {
    test_wait_time_ = TimeDelta();
    test_staging_schedule_ = StagingSchedule();
  }
 
  void SetStagingSchedule(const StagingSchedule& staging_schedule) {
    EXPECT_CALL(device_policy_, GetDeviceUpdateStagingSchedule(_))
        .WillRepeatedly(
            DoAll(SetArgPointee<0>(staging_schedule), Return(true)));
  }
 
  void SetPersistedStagingVal(int64_t wait_time) {
    EXPECT_TRUE(
        fake_prefs_.SetInt64(kPrefsWallClockStagingWaitPeriod, wait_time));
  }
 
  void TestStagingCase(const StagingCase& expected) {
    EXPECT_EQ(expected,
              CalculateStagingCase(&device_policy_,
                                   &fake_prefs_,
                                   &test_wait_time_,
                                   &test_staging_schedule_));
  }
 
  void ExpectNoChanges() {
    EXPECT_EQ(TimeDelta(), test_wait_time_);
    EXPECT_EQ(StagingSchedule(), test_staging_schedule_);
  }
 
  policy::MockDevicePolicy device_policy_;
  TimeDelta test_wait_time_;
  StagingSchedule test_staging_schedule_;
  FakePrefs fake_prefs_;
};
 
// Last element should be 100, if not return false.
TEST_F(StagingUtilsScheduleTest, GetStagingScheduleInvalidLastElem) {
  SetStagingSchedule(StagingSchedule{{2, 10}, {4, 20}, {5, 40}});
  EXPECT_EQ(0, GetStagingSchedule(&device_policy_, &test_staging_schedule_));
  ExpectNoChanges();
}
 
// Percentage should be monotonically increasing.
TEST_F(StagingUtilsScheduleTest, GetStagingScheduleNonMonotonic) {
  SetStagingSchedule(StagingSchedule{{2, 10}, {6, 20}, {11, 20}, {12, 100}});
  EXPECT_EQ(0, GetStagingSchedule(&device_policy_, &test_staging_schedule_));
  ExpectNoChanges();
}
 
// The days should be monotonically increasing.
TEST_F(StagingUtilsScheduleTest, GetStagingScheduleOverMaxDays) {
  SetStagingSchedule(StagingSchedule{{2, 10}, {4, 20}, {15, 30}, {10, 100}});
  EXPECT_EQ(0, GetStagingSchedule(&device_policy_, &test_staging_schedule_));
  ExpectNoChanges();
}
 
TEST_F(StagingUtilsScheduleTest, GetStagingScheduleValid) {
  SetStagingSchedule(valid_schedule);
  EXPECT_EQ(kValidDaySum,
            GetStagingSchedule(&device_policy_, &test_staging_schedule_));
  EXPECT_EQ(test_staging_schedule_, valid_schedule);
}
 
TEST_F(StagingUtilsScheduleTest, StagingOffNoSchedule) {
  // If the function returns false, the schedule shouldn't get used.
  EXPECT_CALL(device_policy_, GetDeviceUpdateStagingSchedule(_))
      .WillRepeatedly(DoAll(SetArgPointee<0>(valid_schedule), Return(false)));
  TestStagingCase(StagingCase::kOff);
  ExpectNoChanges();
}
 
TEST_F(StagingUtilsScheduleTest, StagingOffEmptySchedule) {
  SetStagingSchedule(StagingSchedule());
  TestStagingCase(StagingCase::kOff);
  ExpectNoChanges();
}
 
TEST_F(StagingUtilsScheduleTest, StagingOffInvalidSchedule) {
  // Any invalid schedule should return |StagingCase::kOff|.
  SetStagingSchedule(StagingSchedule{{3, 30}, {6, 40}});
  TestStagingCase(StagingCase::kOff);
  ExpectNoChanges();
}
 
TEST_F(StagingUtilsScheduleTest, StagingOnNoAction) {
  test_wait_time_ = kDay;
  // Same as valid schedule, just using std::pair types.
  StagingSchedule valid_schedule_pairs = {{2, 0}, {7, 50}, {9, 80}, {14, 100}};
  test_staging_schedule_ = valid_schedule_pairs;
  SetStagingSchedule(valid_schedule);
  TestStagingCase(StagingCase::kNoAction);
  // Vars should not be changed.
  EXPECT_EQ(kDay, test_wait_time_);
  EXPECT_EQ(test_staging_schedule_, valid_schedule_pairs);
}
 
TEST_F(StagingUtilsScheduleTest, StagingNoSavedValueChangePolicy) {
  test_wait_time_ = kDay;
  SetStagingSchedule(valid_schedule);
  TestStagingCase(StagingCase::kNoSavedValue);
  // Vars should change since < 2 days should not be possible due to
  // valid_schedule's value.
  EXPECT_NE(kDay, test_wait_time_);
  EXPECT_EQ(test_staging_schedule_, valid_schedule);
  EXPECT_LE(test_wait_time_, kDay * kMaxDays);
}
 
// Tests the case where there was a reboot and there is no persisted value.
TEST_F(StagingUtilsScheduleTest, StagingNoSavedValueNoPersisted) {
  SetStagingSchedule(valid_schedule);
  TestStagingCase(StagingCase::kNoSavedValue);
  // Vars should change since there are no preset values and there is a new
  // staging schedule.
  EXPECT_NE(TimeDelta(), test_wait_time_);
  EXPECT_EQ(test_staging_schedule_, valid_schedule);
  EXPECT_LE(test_wait_time_, kDay * kMaxDays);
}
 
// If there is a pref set and its value is less than the day count, use that
// pref.
TEST_F(StagingUtilsScheduleTest, StagingSetFromPref) {
  SetStagingSchedule(valid_schedule);
  SetPersistedStagingVal(5);
  TestStagingCase(StagingCase::kSetStagingFromPref);
  // Vars should change.
  EXPECT_EQ(kDay * 5, test_wait_time_);
  EXPECT_EQ(test_staging_schedule_, valid_schedule);
}
 
}  // namespace chromeos_update_manager