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