Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(244)

Side by Side Diff: chrome/browser/policy/cloud/cloud_policy_refresh_scheduler_unittest.cc

Issue 109743002: Move policy code into components/policy. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: moar fixes Created 7 years ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
(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/message_loop.h"
10 #include "base/test/test_simple_task_runner.h"
11 #include "chrome/browser/policy/cloud/cloud_policy_constants.h"
12 #include "chrome/browser/policy/cloud/cloud_policy_refresh_scheduler.h"
13 #include "chrome/browser/policy/cloud/mock_cloud_policy_client.h"
14 #include "chrome/browser/policy/cloud/mock_cloud_policy_store.h"
15 #include "policy/policy_constants.h"
16 #include "testing/gmock/include/gmock/gmock.h"
17 #include "testing/gtest/include/gtest/gtest.h"
18
19 namespace em = enterprise_management;
20
21 using testing::Mock;
22
23 namespace policy {
24
25 namespace {
26
27 const int64 kPolicyRefreshRate = 4 * 60 * 60 * 1000;
28
29 const int64 kInitialCacheAgeMinutes = 1;
30
31 } // namespace
32
33 class CloudPolicyRefreshSchedulerTest : public testing::Test {
34 protected:
35 CloudPolicyRefreshSchedulerTest()
36 : task_runner_(new base::TestSimpleTaskRunner()),
37 network_change_notifier_(net::NetworkChangeNotifier::CreateMock()) {}
38
39 virtual void SetUp() OVERRIDE {
40 client_.SetDMToken("token");
41
42 // Set up the protobuf timestamp to be one minute in the past. Since the
43 // protobuf field only has millisecond precision, we convert the actual
44 // value back to get a millisecond-clamped time stamp for the checks below.
45 store_.policy_.reset(new em::PolicyData());
46 base::Time now = base::Time::NowFromSystemTime();
47 base::TimeDelta initial_age =
48 base::TimeDelta::FromMinutes(kInitialCacheAgeMinutes);
49 store_.policy_->set_timestamp(
50 ((now - initial_age) - base::Time::UnixEpoch()).InMilliseconds());
51 last_update_ =
52 base::Time::UnixEpoch() +
53 base::TimeDelta::FromMilliseconds(store_.policy_->timestamp());
54 }
55
56 CloudPolicyRefreshScheduler* CreateRefreshScheduler() {
57 EXPECT_EQ(0u, task_runner_->GetPendingTasks().size());
58 CloudPolicyRefreshScheduler* scheduler =
59 new CloudPolicyRefreshScheduler(&client_, &store_, task_runner_);
60 scheduler->SetRefreshDelay(kPolicyRefreshRate);
61 // If the store has policy, run the wait-for-invalidations timeout task.
62 if (store_.has_policy()) {
63 EXPECT_EQ(1u, task_runner_->GetPendingTasks().size());
64 task_runner_->RunPendingTasks();
65 }
66 return scheduler;
67 }
68
69 void NotifyIPAddressChanged() {
70 net::NetworkChangeNotifier::NotifyObserversOfIPAddressChangeForTests();
71 loop_.RunUntilIdle();
72 }
73
74 base::TimeDelta GetLastDelay() const {
75 const std::deque<base::TestPendingTask>& pending_tasks =
76 task_runner_->GetPendingTasks();
77 return
78 pending_tasks.empty() ? base::TimeDelta() : pending_tasks.back().delay;
79 }
80
81 void CheckTiming(int64 expected_delay_ms) const {
82 CheckTimingWithAge(base::TimeDelta::FromMilliseconds(expected_delay_ms),
83 base::TimeDelta());
84 }
85
86 // Checks that the latest refresh scheduled used an offset of
87 // |offset_from_last_refresh| from the time of the previous refresh.
88 // |cache_age| is how old the cache was when the refresh was issued.
89 void CheckTimingWithAge(const base::TimeDelta& offset_from_last_refresh,
90 const base::TimeDelta& cache_age) const {
91 EXPECT_FALSE(task_runner_->GetPendingTasks().empty());
92 base::Time now(base::Time::NowFromSystemTime());
93 // |last_update_| was updated and then a refresh was scheduled at time S,
94 // so |last_update_| is a bit before that.
95 // Now is a bit later, N.
96 // GetLastDelay() + S is the time when the refresh will run, T.
97 // |cache_age| is the age of the cache at time S. It was thus created at
98 // S - cache_age.
99 //
100 // Schematically:
101 //
102 // . S . N . . . . . . . T . . . .
103 // | | |
104 // set "last_refresh_" and then scheduled the next refresh; the cache
105 // was "cache_age" old at this point.
106 // | |
107 // some time elapsed on the test execution since then;
108 // this is the current time, "now"
109 // |
110 // the refresh will execute at this time
111 //
112 // So the exact delay is T - S - |cache_age|, but we don't have S here.
113 //
114 // |last_update_| was a bit before S, so if
115 // elapsed = now - |last_update_| then the delay is more than
116 // |offset_from_last_refresh| - elapsed.
117 //
118 // The delay is also less than offset_from_last_refresh, because some time
119 // already elapsed. Additionally, if the cache was already considered old
120 // when the schedule was performed then its age at that time has been
121 // discounted from the delay. So the delay is a bit less than
122 // |offset_from_last_refresh - cache_age|.
123 EXPECT_GE(GetLastDelay(), offset_from_last_refresh - (now - last_update_));
124 EXPECT_LE(GetLastDelay(), offset_from_last_refresh - cache_age);
125 }
126
127 void CheckInitialRefresh(bool with_invalidations) const {
128 #if defined(OS_ANDROID)
129 // Android takes the cache age into account for the initial fetch.
130 // Usually the cache age is ignored for the initial refresh, but Android
131 // uses it to restrain from refreshing on every startup.
132 base::TimeDelta rate = base::TimeDelta::FromMilliseconds(
133 with_invalidations
134 ? CloudPolicyRefreshScheduler::kWithInvalidationsRefreshDelayMs
135 : kPolicyRefreshRate);
136 CheckTimingWithAge(rate,
137 base::TimeDelta::FromMinutes(kInitialCacheAgeMinutes));
138 #else
139 // Other platforms refresh immediately.
140 EXPECT_EQ(base::TimeDelta(), GetLastDelay());
141 #endif
142 }
143
144 base::MessageLoop loop_;
145 MockCloudPolicyClient client_;
146 MockCloudPolicyStore store_;
147 scoped_refptr<base::TestSimpleTaskRunner> task_runner_;
148 scoped_ptr<net::NetworkChangeNotifier> network_change_notifier_;
149
150 // Base time for the refresh that the scheduler should be using.
151 base::Time last_update_;
152 };
153
154 TEST_F(CloudPolicyRefreshSchedulerTest, InitialRefreshNoPolicy) {
155 store_.policy_.reset();
156 scoped_ptr<CloudPolicyRefreshScheduler> scheduler(CreateRefreshScheduler());
157 EXPECT_FALSE(task_runner_->GetPendingTasks().empty());
158 EXPECT_EQ(GetLastDelay(), base::TimeDelta());
159 EXPECT_CALL(client_, FetchPolicy()).Times(1);
160 task_runner_->RunUntilIdle();
161 }
162
163 TEST_F(CloudPolicyRefreshSchedulerTest, InitialRefreshUnmanaged) {
164 store_.policy_->set_state(em::PolicyData::UNMANAGED);
165 scoped_ptr<CloudPolicyRefreshScheduler> scheduler(CreateRefreshScheduler());
166 CheckTiming(CloudPolicyRefreshScheduler::kUnmanagedRefreshDelayMs);
167 EXPECT_CALL(client_, FetchPolicy()).Times(1);
168 task_runner_->RunUntilIdle();
169 }
170
171 TEST_F(CloudPolicyRefreshSchedulerTest, InitialRefreshManagedNotYetFetched) {
172 scoped_ptr<CloudPolicyRefreshScheduler> scheduler(CreateRefreshScheduler());
173 EXPECT_FALSE(task_runner_->GetPendingTasks().empty());
174 CheckInitialRefresh(false);
175 EXPECT_CALL(client_, FetchPolicy()).Times(1);
176 task_runner_->RunUntilIdle();
177 }
178
179 TEST_F(CloudPolicyRefreshSchedulerTest, InitialRefreshManagedAlreadyFetched) {
180 last_update_ = base::Time::NowFromSystemTime();
181 client_.SetPolicy(PolicyNamespaceKey(dm_protocol::kChromeUserPolicyType,
182 std::string()),
183 em::PolicyFetchResponse());
184 scoped_ptr<CloudPolicyRefreshScheduler> scheduler(CreateRefreshScheduler());
185 CheckTiming(kPolicyRefreshRate);
186 EXPECT_CALL(client_, FetchPolicy()).Times(1);
187 task_runner_->RunUntilIdle();
188 }
189
190 TEST_F(CloudPolicyRefreshSchedulerTest, Unregistered) {
191 client_.SetDMToken(std::string());
192 scoped_ptr<CloudPolicyRefreshScheduler> scheduler(CreateRefreshScheduler());
193 client_.NotifyPolicyFetched();
194 client_.NotifyRegistrationStateChanged();
195 client_.NotifyClientError();
196 scheduler->SetRefreshDelay(12 * 60 * 60 * 1000);
197 store_.NotifyStoreLoaded();
198 store_.NotifyStoreError();
199 EXPECT_TRUE(task_runner_->GetPendingTasks().empty());
200 }
201
202 TEST_F(CloudPolicyRefreshSchedulerTest, RefreshSoonRateLimit) {
203 scoped_ptr<CloudPolicyRefreshScheduler> scheduler(CreateRefreshScheduler());
204 // Max out the request rate.
205 for (int i = 0; i < 5; ++i) {
206 EXPECT_CALL(client_, FetchPolicy()).Times(1);
207 scheduler->RefreshSoon();
208 task_runner_->RunUntilIdle();
209 Mock::VerifyAndClearExpectations(&client_);
210 }
211 // The next refresh is throttled.
212 EXPECT_CALL(client_, FetchPolicy()).Times(0);
213 scheduler->RefreshSoon();
214 task_runner_->RunPendingTasks();
215 Mock::VerifyAndClearExpectations(&client_);
216 }
217
218 TEST_F(CloudPolicyRefreshSchedulerTest, InvalidationsAvailable) {
219 scoped_ptr<CloudPolicyRefreshScheduler> scheduler(
220 new CloudPolicyRefreshScheduler(&client_, &store_, task_runner_));
221 scheduler->SetRefreshDelay(kPolicyRefreshRate);
222
223 // The scheduler is currently waiting for the invalidations service to
224 // initialize.
225 EXPECT_EQ(1u, task_runner_->GetPendingTasks().size());
226
227 // Signal that invalidations are available. The scheduler is currently
228 // waiting for any pending invalidations to be received.
229 scheduler->SetInvalidationServiceAvailability(true);
230 EXPECT_EQ(2u, task_runner_->GetPendingTasks().size());
231
232 // Run the invalidation service timeout task.
233 EXPECT_CALL(client_, FetchPolicy()).Times(0);
234 task_runner_->RunPendingTasks();
235 Mock::VerifyAndClearExpectations(&client_);
236
237 // The initial refresh is scheduled.
238 EXPECT_EQ(1u, task_runner_->GetPendingTasks().size());
239 CheckInitialRefresh(true);
240
241 EXPECT_CALL(client_, FetchPolicy()).Times(1);
242 task_runner_->RunPendingTasks();
243 Mock::VerifyAndClearExpectations(&client_);
244
245 // Complete that fetch.
246 last_update_ = base::Time::NowFromSystemTime();
247 client_.NotifyPolicyFetched();
248
249 // The next refresh has been scheduled using a lower refresh rate.
250 EXPECT_EQ(1u, task_runner_->GetPendingTasks().size());
251 CheckTiming(CloudPolicyRefreshScheduler::kWithInvalidationsRefreshDelayMs);
252 }
253
254 TEST_F(CloudPolicyRefreshSchedulerTest, InvalidationsNotAvailable) {
255 scoped_ptr<CloudPolicyRefreshScheduler> scheduler(
256 new CloudPolicyRefreshScheduler(&client_, &store_, task_runner_));
257 scheduler->SetRefreshDelay(kPolicyRefreshRate);
258
259 // The scheduler is currently waiting for the invalidations service to
260 // initialize.
261 EXPECT_EQ(1u, task_runner_->GetPendingTasks().size());
262
263 // Signal that invalidations are not available. The scheduler will keep
264 // waiting for us.
265 for (int i = 0; i < 10; ++i) {
266 scheduler->SetInvalidationServiceAvailability(false);
267 EXPECT_EQ(1u, task_runner_->GetPendingTasks().size());
268 }
269
270 // Run the timeout task.
271 EXPECT_CALL(client_, FetchPolicy()).Times(0);
272 task_runner_->RunPendingTasks();
273 Mock::VerifyAndClearExpectations(&client_);
274
275 // This scheduled the initial refresh.
276 CheckInitialRefresh(false);
277
278 // Perform that fetch now.
279 EXPECT_CALL(client_, FetchPolicy()).Times(1);
280 task_runner_->RunPendingTasks();
281 Mock::VerifyAndClearExpectations(&client_);
282
283 // Complete that fetch.
284 last_update_ = base::Time::NowFromSystemTime();
285 client_.NotifyPolicyFetched();
286
287 // The next refresh has been scheduled at the normal rate.
288 EXPECT_EQ(1u, task_runner_->GetPendingTasks().size());
289 CheckTiming(kPolicyRefreshRate);
290 }
291
292 TEST_F(CloudPolicyRefreshSchedulerTest, InvalidationsOffAndOn) {
293 scoped_ptr<CloudPolicyRefreshScheduler> scheduler(
294 new CloudPolicyRefreshScheduler(&client_, &store_, task_runner_));
295 scheduler->SetRefreshDelay(kPolicyRefreshRate);
296 scheduler->SetInvalidationServiceAvailability(true);
297 // Initial fetch.
298 EXPECT_CALL(client_, FetchPolicy()).Times(1);
299 task_runner_->RunUntilIdle();
300 Mock::VerifyAndClearExpectations(&client_);
301 last_update_ = base::Time::NowFromSystemTime();
302 client_.NotifyPolicyFetched();
303
304 // The next refresh has been scheduled using a lower refresh rate.
305 // Flush that task.
306 CheckTiming(CloudPolicyRefreshScheduler::kWithInvalidationsRefreshDelayMs);
307 EXPECT_CALL(client_, FetchPolicy()).Times(1);
308 task_runner_->RunPendingTasks();
309 Mock::VerifyAndClearExpectations(&client_);
310
311 // If the service goes down and comes back up before the timeout then a
312 // refresh is rescheduled at the lower rate again; after executing all
313 // pending tasks only 1 fetch is performed.
314 EXPECT_CALL(client_, FetchPolicy()).Times(0);
315 scheduler->SetInvalidationServiceAvailability(false);
316 scheduler->SetInvalidationServiceAvailability(true);
317 // Run the invalidation service timeout task.
318 task_runner_->RunPendingTasks();
319 Mock::VerifyAndClearExpectations(&client_);
320 // The next refresh has been scheduled using a lower refresh rate.
321 EXPECT_CALL(client_, FetchPolicy()).Times(1);
322 CheckTiming(CloudPolicyRefreshScheduler::kWithInvalidationsRefreshDelayMs);
323 task_runner_->RunPendingTasks();
324 Mock::VerifyAndClearExpectations(&client_);
325 }
326
327 TEST_F(CloudPolicyRefreshSchedulerTest, InvalidationsDisconnected) {
328 scoped_ptr<CloudPolicyRefreshScheduler> scheduler(
329 new CloudPolicyRefreshScheduler(&client_, &store_, task_runner_));
330 scheduler->SetRefreshDelay(kPolicyRefreshRate);
331 scheduler->SetInvalidationServiceAvailability(true);
332 // Initial fetch.
333 EXPECT_CALL(client_, FetchPolicy()).Times(1);
334 task_runner_->RunUntilIdle();
335 Mock::VerifyAndClearExpectations(&client_);
336 last_update_ = base::Time::NowFromSystemTime();
337 client_.NotifyPolicyFetched();
338
339 // The next refresh has been scheduled using a lower refresh rate.
340 // Flush that task.
341 CheckTiming(CloudPolicyRefreshScheduler::kWithInvalidationsRefreshDelayMs);
342 EXPECT_CALL(client_, FetchPolicy()).Times(1);
343 task_runner_->RunPendingTasks();
344 Mock::VerifyAndClearExpectations(&client_);
345
346 // If the service goes down then the refresh scheduler falls back on the
347 // default polling rate after a timeout.
348 EXPECT_CALL(client_, FetchPolicy()).Times(0);
349 scheduler->SetInvalidationServiceAvailability(false);
350 task_runner_->RunPendingTasks();
351 Mock::VerifyAndClearExpectations(&client_);
352 // The next refresh has been scheduled at the normal rate.
353 CheckTiming(kPolicyRefreshRate);
354 }
355
356 class CloudPolicyRefreshSchedulerSteadyStateTest
357 : public CloudPolicyRefreshSchedulerTest {
358 protected:
359 CloudPolicyRefreshSchedulerSteadyStateTest() {}
360
361 virtual void SetUp() OVERRIDE {
362 refresh_scheduler_.reset(CreateRefreshScheduler());
363 refresh_scheduler_->SetRefreshDelay(kPolicyRefreshRate);
364 CloudPolicyRefreshSchedulerTest::SetUp();
365 last_update_ = base::Time::NowFromSystemTime();
366 client_.NotifyPolicyFetched();
367 CheckTiming(kPolicyRefreshRate);
368 }
369
370 scoped_ptr<CloudPolicyRefreshScheduler> refresh_scheduler_;
371 };
372
373 TEST_F(CloudPolicyRefreshSchedulerSteadyStateTest, OnPolicyFetched) {
374 client_.NotifyPolicyFetched();
375 CheckTiming(kPolicyRefreshRate);
376 }
377
378 TEST_F(CloudPolicyRefreshSchedulerSteadyStateTest, OnRegistrationStateChanged) {
379 client_.SetDMToken("new_token");
380 client_.NotifyRegistrationStateChanged();
381 EXPECT_EQ(GetLastDelay(), base::TimeDelta());
382
383 task_runner_->ClearPendingTasks();
384 client_.SetDMToken(std::string());
385 client_.NotifyRegistrationStateChanged();
386 EXPECT_TRUE(task_runner_->GetPendingTasks().empty());
387 }
388
389 TEST_F(CloudPolicyRefreshSchedulerSteadyStateTest, OnStoreLoaded) {
390 store_.NotifyStoreLoaded();
391 CheckTiming(kPolicyRefreshRate);
392 }
393
394 TEST_F(CloudPolicyRefreshSchedulerSteadyStateTest, OnStoreError) {
395 task_runner_->ClearPendingTasks();
396 store_.NotifyStoreError();
397 EXPECT_TRUE(task_runner_->GetPendingTasks().empty());
398 }
399
400 TEST_F(CloudPolicyRefreshSchedulerSteadyStateTest, RefreshDelayChange) {
401 const int delay_short_ms = 5 * 60 * 1000;
402 refresh_scheduler_->SetRefreshDelay(delay_short_ms);
403 CheckTiming(CloudPolicyRefreshScheduler::kRefreshDelayMinMs);
404
405 const int delay_ms = 12 * 60 * 60 * 1000;
406 refresh_scheduler_->SetRefreshDelay(delay_ms);
407 CheckTiming(delay_ms);
408
409 const int delay_long_ms = 20 * 24 * 60 * 60 * 1000;
410 refresh_scheduler_->SetRefreshDelay(delay_long_ms);
411 CheckTiming(CloudPolicyRefreshScheduler::kRefreshDelayMaxMs);
412 }
413
414 TEST_F(CloudPolicyRefreshSchedulerSteadyStateTest, OnIPAddressChanged) {
415 NotifyIPAddressChanged();
416 CheckTiming(kPolicyRefreshRate);
417
418 client_.SetStatus(DM_STATUS_REQUEST_FAILED);
419 NotifyIPAddressChanged();
420 EXPECT_EQ(GetLastDelay(), base::TimeDelta());
421 }
422
423 struct ClientErrorTestParam {
424 DeviceManagementStatus client_error;
425 int64 expected_delay_ms;
426 int backoff_factor;
427 };
428
429 static const ClientErrorTestParam kClientErrorTestCases[] = {
430 { DM_STATUS_REQUEST_INVALID,
431 CloudPolicyRefreshScheduler::kUnmanagedRefreshDelayMs, 1 },
432 { DM_STATUS_REQUEST_FAILED,
433 CloudPolicyRefreshScheduler::kInitialErrorRetryDelayMs, 2 },
434 { DM_STATUS_TEMPORARY_UNAVAILABLE,
435 CloudPolicyRefreshScheduler::kInitialErrorRetryDelayMs, 2 },
436 { DM_STATUS_HTTP_STATUS_ERROR,
437 CloudPolicyRefreshScheduler::kUnmanagedRefreshDelayMs, 1 },
438 { DM_STATUS_RESPONSE_DECODING_ERROR,
439 CloudPolicyRefreshScheduler::kUnmanagedRefreshDelayMs, 1 },
440 { DM_STATUS_SERVICE_MANAGEMENT_NOT_SUPPORTED,
441 CloudPolicyRefreshScheduler::kUnmanagedRefreshDelayMs, 1 },
442 { DM_STATUS_SERVICE_DEVICE_NOT_FOUND,
443 -1, 1 },
444 { DM_STATUS_SERVICE_MANAGEMENT_TOKEN_INVALID,
445 -1, 1 },
446 { DM_STATUS_SERVICE_ACTIVATION_PENDING,
447 kPolicyRefreshRate, 1 },
448 { DM_STATUS_SERVICE_INVALID_SERIAL_NUMBER,
449 -1, 1 },
450 { DM_STATUS_SERVICE_MISSING_LICENSES,
451 -1, 1 },
452 { DM_STATUS_SERVICE_DEVICE_ID_CONFLICT,
453 -1, 1 },
454 { DM_STATUS_SERVICE_POLICY_NOT_FOUND,
455 kPolicyRefreshRate, 1 },
456 };
457
458 class CloudPolicyRefreshSchedulerClientErrorTest
459 : public CloudPolicyRefreshSchedulerSteadyStateTest,
460 public testing::WithParamInterface<ClientErrorTestParam> {
461 };
462
463 TEST_P(CloudPolicyRefreshSchedulerClientErrorTest, OnClientError) {
464 client_.SetStatus(GetParam().client_error);
465 task_runner_->ClearPendingTasks();
466
467 // See whether the error triggers the right refresh delay.
468 int64 expected_delay_ms = GetParam().expected_delay_ms;
469 client_.NotifyClientError();
470 if (expected_delay_ms >= 0) {
471 CheckTiming(expected_delay_ms);
472
473 // Check whether exponential backoff is working as expected and capped at
474 // the regular refresh rate (if applicable).
475 do {
476 expected_delay_ms *= GetParam().backoff_factor;
477 last_update_ = base::Time::NowFromSystemTime();
478 client_.NotifyClientError();
479 CheckTiming(std::max(std::min(expected_delay_ms, kPolicyRefreshRate),
480 GetParam().expected_delay_ms));
481 } while (GetParam().backoff_factor > 1 &&
482 expected_delay_ms <= kPolicyRefreshRate);
483 } else {
484 EXPECT_EQ(base::TimeDelta(), GetLastDelay());
485 EXPECT_TRUE(task_runner_->GetPendingTasks().empty());
486 }
487 }
488
489 INSTANTIATE_TEST_CASE_P(CloudPolicyRefreshSchedulerClientErrorTest,
490 CloudPolicyRefreshSchedulerClientErrorTest,
491 testing::ValuesIn(kClientErrorTestCases));
492
493 } // namespace policy
OLDNEW
« no previous file with comments | « chrome/browser/policy/cloud/cloud_policy_refresh_scheduler.cc ('k') | chrome/browser/policy/cloud/cloud_policy_service.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698