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