blob: 8a0ca19e091cbb6573a303bb2c94430ea3e2a873 [file] [log] [blame]
Darin Petkov1023a602010-08-30 13:47:51 -07001// Copyright (c) 2010 The Chromium OS Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#include <gtest/gtest.h>
6
7#include "update_engine/update_attempter_mock.h"
8#include "update_engine/update_check_scheduler.h"
9
10using std::string;
11using testing::_;
12using testing::AllOf;
13using testing::Ge;
14using testing::Le;
15using testing::MockFunction;
16using testing::Return;
17
18namespace chromeos_update_engine {
19
20namespace {
21void FuzzRange(int interval, int fuzz, int* interval_min, int* interval_max) {
22 *interval_min = interval - fuzz / 2;
23 *interval_max = interval + fuzz - fuzz / 2;
24}
25} // namespace {}
26
27// Test a subclass rather than the main class directly so that we can mock out
28// GLib and utils in tests. There're explicit unit test for the wrapper methods.
29class UpdateCheckSchedulerUnderTest : public UpdateCheckScheduler {
30 public:
31 UpdateCheckSchedulerUnderTest(UpdateAttempter* update_attempter)
32 : UpdateCheckScheduler(update_attempter) {}
33
34 MOCK_METHOD2(GTimeoutAddSeconds, guint(guint seconds, GSourceFunc function));
35 MOCK_METHOD0(IsBootDeviceRemovable, bool());
36 MOCK_METHOD0(IsOfficialBuild, bool());
37};
38
39class UpdateCheckSchedulerTest : public ::testing::Test {
40 protected:
41 virtual void SetUp() {
42 test_ = this;
43 loop_ = NULL;
44 scheduler_.reset(new UpdateCheckSchedulerUnderTest(&attempter_));
45 EXPECT_EQ(&attempter_, scheduler_->update_attempter_);
46 EXPECT_FALSE(scheduler_->enabled_);
47 EXPECT_FALSE(scheduler_->scheduled_);
48 EXPECT_EQ(0, scheduler_->last_interval_);
49 }
50
51 virtual void TearDown() {
52 test_ = NULL;
53 loop_ = NULL;
54 scheduler_.reset(NULL);
55 }
56
57 static gboolean SourceCallback(gpointer data) {
58 g_main_loop_quit(test_->loop_);
59 // Forwards the call to the function mock so that expectations can be set.
60 return test_->source_callback_.Call(data);
61 }
62
63 scoped_ptr<UpdateCheckSchedulerUnderTest> scheduler_;
64 UpdateAttempterMock attempter_;
65 MockFunction<gboolean(gpointer data)> source_callback_;
66 GMainLoop* loop_;
67 static UpdateCheckSchedulerTest* test_;
68};
69
70UpdateCheckSchedulerTest* UpdateCheckSchedulerTest::test_ = NULL;
71
72TEST_F(UpdateCheckSchedulerTest, CanScheduleTest) {
73 EXPECT_FALSE(scheduler_->CanSchedule());
74 scheduler_->enabled_ = true;
75 EXPECT_TRUE(scheduler_->CanSchedule());
76 scheduler_->scheduled_ = true;
77 EXPECT_FALSE(scheduler_->CanSchedule());
78 scheduler_->enabled_ = false;
79 EXPECT_FALSE(scheduler_->CanSchedule());
80}
81
82TEST_F(UpdateCheckSchedulerTest, ComputeNextIntervalAndFuzzBackoffTest) {
83 int interval, fuzz;
84 attempter_.set_http_response_code(500);
85 int last_interval = UpdateCheckScheduler::kTimeoutPeriodic + 50;
86 scheduler_->last_interval_ = last_interval;
87 scheduler_->ComputeNextIntervalAndFuzz(&interval, &fuzz);
88 EXPECT_EQ(2 * last_interval, interval);
89 EXPECT_EQ(2 * last_interval, fuzz);
90
91 attempter_.set_http_response_code(503);
92 last_interval = UpdateCheckScheduler::kTimeoutMaxBackoff / 2 + 1;
93 scheduler_->last_interval_ = last_interval;
94 scheduler_->ComputeNextIntervalAndFuzz(&interval, &fuzz);
95 EXPECT_EQ(UpdateCheckScheduler::kTimeoutMaxBackoff, interval);
96 EXPECT_EQ(UpdateCheckScheduler::kTimeoutMaxBackoff, fuzz);
97}
98
99TEST_F(UpdateCheckSchedulerTest, ComputeNextIntervalAndFuzzTest) {
100 int interval, fuzz;
101 scheduler_->ComputeNextIntervalAndFuzz(&interval, &fuzz);
102 EXPECT_EQ(UpdateCheckScheduler::kTimeoutPeriodic, interval);
103 EXPECT_EQ(UpdateCheckScheduler::kTimeoutRegularFuzz, fuzz);
104}
105
106TEST_F(UpdateCheckSchedulerTest, GTimeoutAddSecondsTest) {
107 loop_ = g_main_loop_new(g_main_context_default(), FALSE);
108 // Invokes the actual GLib wrapper method rather than the subclass mock.
109 scheduler_->UpdateCheckScheduler::GTimeoutAddSeconds(0, SourceCallback);
110 EXPECT_CALL(source_callback_, Call(scheduler_.get())).Times(1);
111 g_main_loop_run(loop_);
112 g_main_loop_unref(loop_);
113}
114
115TEST_F(UpdateCheckSchedulerTest, IsBootDeviceRemovableTest) {
116 // Invokes the actual utils wrapper method rather than the subclass mock.
117 EXPECT_FALSE(scheduler_->UpdateCheckScheduler::IsBootDeviceRemovable());
118}
119
120TEST_F(UpdateCheckSchedulerTest, IsOfficialBuildTest) {
121 // Invokes the actual utils wrapper method rather than the subclass mock.
122 EXPECT_TRUE(scheduler_->UpdateCheckScheduler::IsOfficialBuild());
123}
124
125TEST_F(UpdateCheckSchedulerTest, RunBootDeviceRemovableTest) {
126 scheduler_->enabled_ = true;
127 EXPECT_CALL(*scheduler_, IsOfficialBuild()).Times(1).WillOnce(Return(true));
128 EXPECT_CALL(*scheduler_, IsBootDeviceRemovable())
129 .Times(1)
130 .WillOnce(Return(true));
131 scheduler_->Run();
132 EXPECT_FALSE(scheduler_->enabled_);
133 EXPECT_EQ(NULL, attempter_.update_check_scheduler());
134}
135
136TEST_F(UpdateCheckSchedulerTest, RunNonOfficialBuildTest) {
137 scheduler_->enabled_ = true;
138 EXPECT_CALL(*scheduler_, IsOfficialBuild()).Times(1).WillOnce(Return(false));
139 scheduler_->Run();
140 EXPECT_FALSE(scheduler_->enabled_);
141 EXPECT_EQ(NULL, attempter_.update_check_scheduler());
142}
143
144TEST_F(UpdateCheckSchedulerTest, RunTest) {
145 int interval_min, interval_max;
146 FuzzRange(UpdateCheckScheduler::kTimeoutOnce,
147 UpdateCheckScheduler::kTimeoutRegularFuzz,
148 &interval_min,
149 &interval_max);
150 EXPECT_CALL(*scheduler_, IsOfficialBuild()).Times(1).WillOnce(Return(true));
151 EXPECT_CALL(*scheduler_, IsBootDeviceRemovable())
152 .Times(1)
153 .WillOnce(Return(false));
154 EXPECT_CALL(*scheduler_,
155 GTimeoutAddSeconds(AllOf(Ge(interval_min), Le(interval_max)),
156 scheduler_->StaticCheck)).Times(1);
157 scheduler_->Run();
158 EXPECT_TRUE(scheduler_->enabled_);
159 EXPECT_EQ(scheduler_.get(), attempter_.update_check_scheduler());
160}
161
162TEST_F(UpdateCheckSchedulerTest, ScheduleCheckDisabledTest) {
163 EXPECT_CALL(*scheduler_, GTimeoutAddSeconds(_, _)).Times(0);
164 scheduler_->ScheduleCheck(250, 30);
165 EXPECT_EQ(0, scheduler_->last_interval_);
166 EXPECT_FALSE(scheduler_->scheduled_);
167}
168
169TEST_F(UpdateCheckSchedulerTest, ScheduleCheckEnabledTest) {
170 int interval_min, interval_max;
171 FuzzRange(100, 10, &interval_min,&interval_max);
172 EXPECT_CALL(*scheduler_,
173 GTimeoutAddSeconds(AllOf(Ge(interval_min), Le(interval_max)),
174 scheduler_->StaticCheck)).Times(1);
175 scheduler_->enabled_ = true;
176 scheduler_->ScheduleCheck(100, 10);
177 EXPECT_EQ(100, scheduler_->last_interval_);
178 EXPECT_TRUE(scheduler_->scheduled_);
179}
180
181TEST_F(UpdateCheckSchedulerTest, ScheduleCheckNegativeIntervalTest) {
182 EXPECT_CALL(*scheduler_, GTimeoutAddSeconds(0, scheduler_->StaticCheck))
183 .Times(1);
184 scheduler_->enabled_ = true;
185 scheduler_->ScheduleCheck(-50, 20);
186 EXPECT_TRUE(scheduler_->scheduled_);
187}
188
189TEST_F(UpdateCheckSchedulerTest, ScheduleNextCheckDisabledTest) {
190 EXPECT_CALL(*scheduler_, GTimeoutAddSeconds(_, _)).Times(0);
191 scheduler_->ScheduleNextCheck();
192}
193
194TEST_F(UpdateCheckSchedulerTest, ScheduleNextCheckEnabledTest) {
195 int interval_min, interval_max;
196 FuzzRange(UpdateCheckScheduler::kTimeoutPeriodic,
197 UpdateCheckScheduler::kTimeoutRegularFuzz,
198 &interval_min,
199 &interval_max);
200 EXPECT_CALL(*scheduler_,
201 GTimeoutAddSeconds(AllOf(Ge(interval_min), Le(interval_max)),
202 scheduler_->StaticCheck)).Times(1);
203 scheduler_->enabled_ = true;
204 scheduler_->ScheduleNextCheck();
205}
206
207TEST_F(UpdateCheckSchedulerTest, SetUpdateStatusIdleDisabledTest) {
208 EXPECT_CALL(*scheduler_, GTimeoutAddSeconds(_, _)).Times(0);
209 scheduler_->SetUpdateStatus(UPDATE_STATUS_IDLE);
210}
211
212TEST_F(UpdateCheckSchedulerTest, SetUpdateStatusIdleEnabledTest) {
213 int interval_min, interval_max;
214 FuzzRange(UpdateCheckScheduler::kTimeoutPeriodic,
215 UpdateCheckScheduler::kTimeoutRegularFuzz,
216 &interval_min,
217 &interval_max);
218 EXPECT_CALL(*scheduler_,
219 GTimeoutAddSeconds(AllOf(Ge(interval_min), Le(interval_max)),
220 scheduler_->StaticCheck)).Times(1);
221 scheduler_->enabled_ = true;
222 scheduler_->SetUpdateStatus(UPDATE_STATUS_IDLE);
223}
224
225TEST_F(UpdateCheckSchedulerTest, SetUpdateStatusNonIdleTest) {
226 EXPECT_CALL(*scheduler_, GTimeoutAddSeconds(_, _)).Times(0);
227 scheduler_->SetUpdateStatus(UPDATE_STATUS_DOWNLOADING);
228 scheduler_->enabled_ = true;
229 scheduler_->SetUpdateStatus(UPDATE_STATUS_DOWNLOADING);
230}
231
232TEST_F(UpdateCheckSchedulerTest, StaticCheckTest) {
233 scheduler_->scheduled_ = true;
234 EXPECT_CALL(attempter_, Update("", "")).Times(1);
235 UpdateCheckSchedulerUnderTest::StaticCheck(scheduler_.get());
236}
237
238} // namespace chromeos_update_engine