OLD | NEW |
| (Empty) |
1 // Copyright (c) 2012 The Chromium 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 "base/callback.h" | |
6 #include "base/compiler_specific.h" | |
7 #include "base/memory/ref_counted.h" | |
8 #include "base/memory/scoped_ptr.h" | |
9 #include "base/message_loop.h" | |
10 #include "base/test/test_simple_task_runner.h" | |
11 #include "chrome/browser/policy/cloud_policy_constants.h" | |
12 #include "chrome/browser/policy/cloud_policy_refresh_scheduler.h" | |
13 #include "chrome/browser/policy/mock_cloud_policy_client.h" | |
14 #include "chrome/browser/policy/mock_cloud_policy_store.h" | |
15 #include "chrome/browser/prefs/browser_prefs.h" | |
16 #include "policy/policy_constants.h" | |
17 #include "testing/gmock/include/gmock/gmock.h" | |
18 #include "testing/gtest/include/gtest/gtest.h" | |
19 | |
20 namespace em = enterprise_management; | |
21 | |
22 using testing::DoAll; | |
23 using testing::Mock; | |
24 using testing::Return; | |
25 using testing::SaveArg; | |
26 using testing::_; | |
27 | |
28 namespace policy { | |
29 | |
30 namespace { | |
31 const int64 kPolicyRefreshRate = 4 * 60 * 60 * 1000; | |
32 } // namespace | |
33 | |
34 class CloudPolicyRefreshSchedulerTest : public testing::Test { | |
35 protected: | |
36 CloudPolicyRefreshSchedulerTest() | |
37 : task_runner_(new base::TestSimpleTaskRunner()), | |
38 network_change_notifier_(net::NetworkChangeNotifier::CreateMock()) {} | |
39 | |
40 virtual void SetUp() OVERRIDE { | |
41 client_.SetDMToken("token"); | |
42 | |
43 // Set up the protobuf timestamp to be one minute in the past. Since the | |
44 // protobuf field only has millisecond precision, we convert the actual | |
45 // value back to get a millisecond-clamped time stamp for the checks below. | |
46 store_.policy_.reset(new em::PolicyData()); | |
47 store_.policy_->set_timestamp( | |
48 ((base::Time::NowFromSystemTime() - base::TimeDelta::FromMinutes(1)) - | |
49 base::Time::UnixEpoch()).InMilliseconds()); | |
50 last_refresh_ = | |
51 base::Time::UnixEpoch() + | |
52 base::TimeDelta::FromMilliseconds(store_.policy_->timestamp()); | |
53 } | |
54 | |
55 CloudPolicyRefreshScheduler* CreateRefreshScheduler() { | |
56 CloudPolicyRefreshScheduler* scheduler = | |
57 new CloudPolicyRefreshScheduler(&client_, &store_, task_runner_); | |
58 scheduler->SetRefreshDelay(kPolicyRefreshRate); | |
59 return scheduler; | |
60 } | |
61 | |
62 void NotifyIPAddressChanged() { | |
63 net::NetworkChangeNotifier::NotifyObserversOfIPAddressChangeForTests(); | |
64 loop_.RunUntilIdle(); | |
65 } | |
66 | |
67 base::TimeDelta GetLastDelay() const { | |
68 const std::deque<base::TestPendingTask>& pending_tasks = | |
69 task_runner_->GetPendingTasks(); | |
70 return | |
71 pending_tasks.empty() ? base::TimeDelta() : pending_tasks.back().delay; | |
72 } | |
73 | |
74 void CheckTiming(int64 expected_delay_ms) const { | |
75 EXPECT_FALSE(task_runner_->GetPendingTasks().empty()); | |
76 base::Time now(base::Time::NowFromSystemTime()); | |
77 base::TimeDelta expected_delay( | |
78 base::TimeDelta::FromMilliseconds(expected_delay_ms)); | |
79 EXPECT_GE(GetLastDelay(), expected_delay - (now - last_refresh_)); | |
80 EXPECT_LE(GetLastDelay(), expected_delay); | |
81 } | |
82 | |
83 MessageLoop loop_; | |
84 MockCloudPolicyClient client_; | |
85 MockCloudPolicyStore store_; | |
86 scoped_refptr<base::TestSimpleTaskRunner> task_runner_; | |
87 scoped_ptr<net::NetworkChangeNotifier> network_change_notifier_; | |
88 | |
89 // Base time for the refresh that the scheduler should be using. | |
90 base::Time last_refresh_; | |
91 }; | |
92 | |
93 TEST_F(CloudPolicyRefreshSchedulerTest, InitialRefreshNoPolicy) { | |
94 store_.policy_.reset(); | |
95 scoped_ptr<CloudPolicyRefreshScheduler> scheduler(CreateRefreshScheduler()); | |
96 EXPECT_FALSE(task_runner_->GetPendingTasks().empty()); | |
97 EXPECT_EQ(GetLastDelay(), base::TimeDelta()); | |
98 EXPECT_CALL(client_, FetchPolicy()).Times(1); | |
99 task_runner_->RunUntilIdle(); | |
100 } | |
101 | |
102 TEST_F(CloudPolicyRefreshSchedulerTest, InitialRefreshUnmanaged) { | |
103 store_.policy_->set_state(em::PolicyData::UNMANAGED); | |
104 scoped_ptr<CloudPolicyRefreshScheduler> scheduler(CreateRefreshScheduler()); | |
105 CheckTiming(CloudPolicyRefreshScheduler::kUnmanagedRefreshDelayMs); | |
106 EXPECT_CALL(client_, FetchPolicy()).Times(1); | |
107 task_runner_->RunUntilIdle(); | |
108 } | |
109 | |
110 TEST_F(CloudPolicyRefreshSchedulerTest, InitialRefreshManagedNotYetFetched) { | |
111 scoped_ptr<CloudPolicyRefreshScheduler> scheduler(CreateRefreshScheduler()); | |
112 EXPECT_FALSE(task_runner_->GetPendingTasks().empty()); | |
113 EXPECT_EQ(GetLastDelay(), base::TimeDelta()); | |
114 EXPECT_CALL(client_, FetchPolicy()).Times(1); | |
115 task_runner_->RunUntilIdle(); | |
116 } | |
117 | |
118 TEST_F(CloudPolicyRefreshSchedulerTest, InitialRefreshManagedAlreadyFetched) { | |
119 last_refresh_ = base::Time::NowFromSystemTime(); | |
120 client_.SetPolicy(PolicyNamespaceKey(dm_protocol::kChromeUserPolicyType, | |
121 std::string()), | |
122 em::PolicyFetchResponse()); | |
123 scoped_ptr<CloudPolicyRefreshScheduler> scheduler(CreateRefreshScheduler()); | |
124 CheckTiming(kPolicyRefreshRate); | |
125 EXPECT_CALL(client_, FetchPolicy()).Times(1); | |
126 task_runner_->RunUntilIdle(); | |
127 } | |
128 | |
129 TEST_F(CloudPolicyRefreshSchedulerTest, Unregistered) { | |
130 client_.SetDMToken(""); | |
131 scoped_ptr<CloudPolicyRefreshScheduler> scheduler(CreateRefreshScheduler()); | |
132 client_.NotifyPolicyFetched(); | |
133 client_.NotifyRegistrationStateChanged(); | |
134 client_.NotifyClientError(); | |
135 scheduler->SetRefreshDelay(12 * 60 * 60 * 1000); | |
136 store_.NotifyStoreLoaded(); | |
137 store_.NotifyStoreError(); | |
138 EXPECT_TRUE(task_runner_->GetPendingTasks().empty()); | |
139 } | |
140 | |
141 TEST_F(CloudPolicyRefreshSchedulerTest, RefreshSoonRateLimit) { | |
142 scoped_ptr<CloudPolicyRefreshScheduler> scheduler(CreateRefreshScheduler()); | |
143 // Max out the request rate. | |
144 for (int i = 0; i < 5; ++i) { | |
145 EXPECT_CALL(client_, FetchPolicy()).Times(1); | |
146 scheduler->RefreshSoon(); | |
147 task_runner_->RunUntilIdle(); | |
148 Mock::VerifyAndClearExpectations(&client_); | |
149 } | |
150 // The next refresh is throttled. | |
151 EXPECT_CALL(client_, FetchPolicy()).Times(0); | |
152 scheduler->RefreshSoon(); | |
153 task_runner_->RunPendingTasks(); | |
154 Mock::VerifyAndClearExpectations(&client_); | |
155 } | |
156 | |
157 class CloudPolicyRefreshSchedulerSteadyStateTest | |
158 : public CloudPolicyRefreshSchedulerTest { | |
159 protected: | |
160 CloudPolicyRefreshSchedulerSteadyStateTest() | |
161 : refresh_scheduler_(&client_, &store_, task_runner_) {} | |
162 | |
163 virtual void SetUp() OVERRIDE { | |
164 refresh_scheduler_.SetRefreshDelay(kPolicyRefreshRate); | |
165 CloudPolicyRefreshSchedulerTest::SetUp(); | |
166 last_refresh_ = base::Time::NowFromSystemTime(); | |
167 client_.NotifyPolicyFetched(); | |
168 CheckTiming(kPolicyRefreshRate); | |
169 } | |
170 | |
171 CloudPolicyRefreshScheduler refresh_scheduler_; | |
172 }; | |
173 | |
174 TEST_F(CloudPolicyRefreshSchedulerSteadyStateTest, OnPolicyFetched) { | |
175 client_.NotifyPolicyFetched(); | |
176 CheckTiming(kPolicyRefreshRate); | |
177 } | |
178 | |
179 TEST_F(CloudPolicyRefreshSchedulerSteadyStateTest, OnRegistrationStateChanged) { | |
180 client_.SetDMToken("new_token"); | |
181 client_.NotifyRegistrationStateChanged(); | |
182 EXPECT_EQ(GetLastDelay(), base::TimeDelta()); | |
183 | |
184 task_runner_->ClearPendingTasks(); | |
185 client_.SetDMToken(""); | |
186 client_.NotifyRegistrationStateChanged(); | |
187 EXPECT_TRUE(task_runner_->GetPendingTasks().empty()); | |
188 } | |
189 | |
190 TEST_F(CloudPolicyRefreshSchedulerSteadyStateTest, OnStoreLoaded) { | |
191 store_.NotifyStoreLoaded(); | |
192 CheckTiming(kPolicyRefreshRate); | |
193 } | |
194 | |
195 TEST_F(CloudPolicyRefreshSchedulerSteadyStateTest, OnStoreError) { | |
196 task_runner_->ClearPendingTasks(); | |
197 store_.NotifyStoreError(); | |
198 EXPECT_TRUE(task_runner_->GetPendingTasks().empty()); | |
199 } | |
200 | |
201 TEST_F(CloudPolicyRefreshSchedulerSteadyStateTest, RefreshDelayChange) { | |
202 const int delay_short_ms = 5 * 60 * 1000; | |
203 refresh_scheduler_.SetRefreshDelay(delay_short_ms); | |
204 CheckTiming(CloudPolicyRefreshScheduler::kRefreshDelayMinMs); | |
205 | |
206 const int delay_ms = 12 * 60 * 60 * 1000; | |
207 refresh_scheduler_.SetRefreshDelay(delay_ms); | |
208 CheckTiming(delay_ms); | |
209 | |
210 const int delay_long_ms = 2 * 24 * 60 * 60 * 1000; | |
211 refresh_scheduler_.SetRefreshDelay(delay_long_ms); | |
212 CheckTiming(CloudPolicyRefreshScheduler::kRefreshDelayMaxMs); | |
213 } | |
214 | |
215 TEST_F(CloudPolicyRefreshSchedulerSteadyStateTest, OnIPAddressChanged) { | |
216 NotifyIPAddressChanged(); | |
217 CheckTiming(kPolicyRefreshRate); | |
218 | |
219 client_.SetStatus(DM_STATUS_REQUEST_FAILED); | |
220 NotifyIPAddressChanged(); | |
221 EXPECT_EQ(GetLastDelay(), base::TimeDelta()); | |
222 } | |
223 | |
224 struct ClientErrorTestParam { | |
225 DeviceManagementStatus client_error; | |
226 int64 expected_delay_ms; | |
227 int backoff_factor; | |
228 }; | |
229 | |
230 static const ClientErrorTestParam kClientErrorTestCases[] = { | |
231 { DM_STATUS_REQUEST_INVALID, | |
232 CloudPolicyRefreshScheduler::kUnmanagedRefreshDelayMs, 1 }, | |
233 { DM_STATUS_REQUEST_FAILED, | |
234 CloudPolicyRefreshScheduler::kInitialErrorRetryDelayMs, 2 }, | |
235 { DM_STATUS_TEMPORARY_UNAVAILABLE, | |
236 CloudPolicyRefreshScheduler::kInitialErrorRetryDelayMs, 2 }, | |
237 { DM_STATUS_HTTP_STATUS_ERROR, | |
238 CloudPolicyRefreshScheduler::kUnmanagedRefreshDelayMs, 1 }, | |
239 { DM_STATUS_RESPONSE_DECODING_ERROR, | |
240 CloudPolicyRefreshScheduler::kUnmanagedRefreshDelayMs, 1 }, | |
241 { DM_STATUS_SERVICE_MANAGEMENT_NOT_SUPPORTED, | |
242 CloudPolicyRefreshScheduler::kUnmanagedRefreshDelayMs, 1 }, | |
243 { DM_STATUS_SERVICE_DEVICE_NOT_FOUND, | |
244 -1, 1 }, | |
245 { DM_STATUS_SERVICE_MANAGEMENT_TOKEN_INVALID, | |
246 -1, 1 }, | |
247 { DM_STATUS_SERVICE_ACTIVATION_PENDING, | |
248 kPolicyRefreshRate, 1 }, | |
249 { DM_STATUS_SERVICE_INVALID_SERIAL_NUMBER, | |
250 -1, 1 }, | |
251 { DM_STATUS_SERVICE_MISSING_LICENSES, | |
252 -1, 1 }, | |
253 { DM_STATUS_SERVICE_DEVICE_ID_CONFLICT, | |
254 -1, 1 }, | |
255 { DM_STATUS_SERVICE_POLICY_NOT_FOUND, | |
256 kPolicyRefreshRate, 1 }, | |
257 }; | |
258 | |
259 class CloudPolicyRefreshSchedulerClientErrorTest | |
260 : public CloudPolicyRefreshSchedulerSteadyStateTest, | |
261 public testing::WithParamInterface<ClientErrorTestParam> { | |
262 }; | |
263 | |
264 TEST_P(CloudPolicyRefreshSchedulerClientErrorTest, OnClientError) { | |
265 client_.SetStatus(GetParam().client_error); | |
266 task_runner_->ClearPendingTasks(); | |
267 | |
268 // See whether the error triggers the right refresh delay. | |
269 int64 expected_delay_ms = GetParam().expected_delay_ms; | |
270 client_.NotifyClientError(); | |
271 if (expected_delay_ms >= 0) { | |
272 CheckTiming(expected_delay_ms); | |
273 | |
274 // Check whether exponential backoff is working as expected and capped at | |
275 // the regular refresh rate (if applicable). | |
276 do { | |
277 expected_delay_ms *= GetParam().backoff_factor; | |
278 last_refresh_ = base::Time::NowFromSystemTime(); | |
279 client_.NotifyClientError(); | |
280 CheckTiming(std::max(std::min(expected_delay_ms, kPolicyRefreshRate), | |
281 GetParam().expected_delay_ms)); | |
282 } while (GetParam().backoff_factor > 1 && | |
283 expected_delay_ms <= kPolicyRefreshRate); | |
284 } else { | |
285 EXPECT_EQ(base::TimeDelta(), GetLastDelay()); | |
286 EXPECT_TRUE(task_runner_->GetPendingTasks().empty()); | |
287 } | |
288 } | |
289 | |
290 INSTANTIATE_TEST_CASE_P(CloudPolicyRefreshSchedulerClientErrorTest, | |
291 CloudPolicyRefreshSchedulerClientErrorTest, | |
292 testing::ValuesIn(kClientErrorTestCases)); | |
293 | |
294 } // namespace policy | |
OLD | NEW |