| OLD | NEW |
| 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "base/bind.h" | 5 #include "base/bind.h" |
| 6 #include "base/callback.h" | 6 #include "base/callback.h" |
| 7 #include "base/compiler_specific.h" | 7 #include "base/compiler_specific.h" |
| 8 #include "base/memory/weak_ptr.h" | 8 #include "base/memory/weak_ptr.h" |
| 9 #include "base/run_loop.h" | 9 #include "base/run_loop.h" |
| 10 #include "base/test/test_timeouts.h" | 10 #include "base/test/test_timeouts.h" |
| (...skipping 176 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 187 SCOPED_TRACE(testing::Message() << "SyncShare # (" << i << ")"); | 187 SCOPED_TRACE(testing::Message() << "SyncShare # (" << i << ")"); |
| 188 TimeTicks optimal_next_sync = optimal_start + poll_interval * i; | 188 TimeTicks optimal_next_sync = optimal_start + poll_interval * i; |
| 189 EXPECT_GE(times[i], optimal_next_sync); | 189 EXPECT_GE(times[i], optimal_next_sync); |
| 190 } | 190 } |
| 191 } | 191 } |
| 192 | 192 |
| 193 void DoQuitLoopNow() { | 193 void DoQuitLoopNow() { |
| 194 QuitLoopNow(); | 194 QuitLoopNow(); |
| 195 } | 195 } |
| 196 | 196 |
| 197 void StartSyncScheduler(SyncScheduler::Mode mode) { | 197 void StartSyncConfiguration() { |
| 198 scheduler()->Start(mode); | 198 scheduler()->Start(SyncScheduler::CONFIGURATION_MODE, base::Time()); |
| 199 } |
| 200 |
| 201 void StartSyncScheduler(base::Time last_poll_time) { |
| 202 scheduler()->Start(SyncScheduler::NORMAL_MODE, last_poll_time); |
| 199 } | 203 } |
| 200 | 204 |
| 201 // This stops the scheduler synchronously. | 205 // This stops the scheduler synchronously. |
| 202 void StopSyncScheduler() { | 206 void StopSyncScheduler() { |
| 203 base::MessageLoop::current()->PostTask( | 207 base::MessageLoop::current()->PostTask( |
| 204 FROM_HERE, | 208 FROM_HERE, |
| 205 base::Bind(&SyncSchedulerTest::DoQuitLoopNow, | 209 base::Bind(&SyncSchedulerTest::DoQuitLoopNow, |
| 206 weak_ptr_factory_.GetWeakPtr())); | 210 weak_ptr_factory_.GetWeakPtr())); |
| 207 RunLoop(); | 211 RunLoop(); |
| 208 } | 212 } |
| 209 | 213 |
| 210 bool RunAndGetBackoff() { | 214 bool RunAndGetBackoff() { |
| 211 ModelTypeSet nudge_types(THEMES); | 215 ModelTypeSet nudge_types(THEMES); |
| 212 StartSyncScheduler(SyncScheduler::NORMAL_MODE); | 216 StartSyncScheduler(base::Time()); |
| 213 | 217 |
| 214 scheduler()->ScheduleLocalNudge(nudge_types, FROM_HERE); | 218 scheduler()->ScheduleLocalNudge(nudge_types, FROM_HERE); |
| 215 RunLoop(); | 219 RunLoop(); |
| 216 | 220 |
| 217 return scheduler()->IsBackingOff(); | 221 return scheduler()->IsBackingOff(); |
| 218 } | 222 } |
| 219 | 223 |
| 220 void UseMockDelayProvider() { | 224 void UseMockDelayProvider() { |
| 221 delay_ = new MockDelayProvider(); | 225 delay_ = new MockDelayProvider(); |
| 222 scheduler_->delay_provider_.reset(delay_); | 226 scheduler_->delay_provider_.reset(delay_); |
| (...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 257 std::vector<scoped_refptr<ModelSafeWorker> > workers_; | 261 std::vector<scoped_refptr<ModelSafeWorker> > workers_; |
| 258 scoped_refptr<ExtensionsActivity> extensions_activity_; | 262 scoped_refptr<ExtensionsActivity> extensions_activity_; |
| 259 ModelSafeRoutingInfo routing_info_; | 263 ModelSafeRoutingInfo routing_info_; |
| 260 base::WeakPtrFactory<SyncSchedulerTest> weak_ptr_factory_; | 264 base::WeakPtrFactory<SyncSchedulerTest> weak_ptr_factory_; |
| 261 }; | 265 }; |
| 262 | 266 |
| 263 void RecordSyncShareImpl(SyncShareTimes* times) { | 267 void RecordSyncShareImpl(SyncShareTimes* times) { |
| 264 times->push_back(TimeTicks::Now()); | 268 times->push_back(TimeTicks::Now()); |
| 265 } | 269 } |
| 266 | 270 |
| 267 ACTION_P(RecordSyncShare, times) { | 271 ACTION_P2(RecordSyncShare, times, success) { |
| 268 RecordSyncShareImpl(times); | 272 RecordSyncShareImpl(times); |
| 269 if (base::MessageLoop::current()->is_running()) | 273 if (base::MessageLoop::current()->is_running()) |
| 270 QuitLoopNow(); | 274 QuitLoopNow(); |
| 271 return true; | 275 return success; |
| 272 } | 276 } |
| 273 | 277 |
| 274 ACTION_P2(RecordSyncShareMultiple, times, quit_after) { | 278 ACTION_P3(RecordSyncShareMultiple, times, quit_after, success) { |
| 275 RecordSyncShareImpl(times); | 279 RecordSyncShareImpl(times); |
| 276 EXPECT_LE(times->size(), quit_after); | 280 EXPECT_LE(times->size(), quit_after); |
| 277 if (times->size() >= quit_after && | 281 if (times->size() >= quit_after && |
| 278 base::MessageLoop::current()->is_running()) { | 282 base::MessageLoop::current()->is_running()) { |
| 279 QuitLoopNow(); | 283 QuitLoopNow(); |
| 280 } | 284 } |
| 281 return true; | 285 return success; |
| 282 } | 286 } |
| 283 | 287 |
| 284 ACTION_P(StopScheduler, scheduler) { | 288 ACTION_P(StopScheduler, scheduler) { |
| 285 scheduler->Stop(); | 289 scheduler->Stop(); |
| 286 } | 290 } |
| 287 | 291 |
| 288 ACTION(AddFailureAndQuitLoopNow) { | 292 ACTION(AddFailureAndQuitLoopNow) { |
| 289 ADD_FAILURE(); | 293 ADD_FAILURE(); |
| 290 QuitLoopNow(); | 294 QuitLoopNow(); |
| 291 return true; | 295 return true; |
| 292 } | 296 } |
| 293 | 297 |
| 294 ACTION(QuitLoopNowAction) { | 298 ACTION_P(QuitLoopNowAction, success) { |
| 295 QuitLoopNow(); | 299 QuitLoopNow(); |
| 296 return true; | 300 return success; |
| 297 } | 301 } |
| 298 | 302 |
| 299 // Test nudge scheduling. | 303 // Test nudge scheduling. |
| 300 TEST_F(SyncSchedulerTest, Nudge) { | 304 TEST_F(SyncSchedulerTest, Nudge) { |
| 301 SyncShareTimes times; | 305 SyncShareTimes times; |
| 302 ModelTypeSet model_types(THEMES); | 306 ModelTypeSet model_types(THEMES); |
| 303 | 307 |
| 304 EXPECT_CALL(*syncer(), NormalSyncShare(_,_,_)) | 308 EXPECT_CALL(*syncer(), NormalSyncShare(_,_,_)) |
| 305 .WillOnce(DoAll(Invoke(sessions::test_util::SimulateNormalSuccess), | 309 .WillOnce(DoAll(Invoke(sessions::test_util::SimulateNormalSuccess), |
| 306 RecordSyncShare(×))) | 310 RecordSyncShare(×, true))) |
| 307 .RetiresOnSaturation(); | 311 .RetiresOnSaturation(); |
| 308 | 312 |
| 309 StartSyncScheduler(SyncScheduler::NORMAL_MODE); | 313 StartSyncScheduler(base::Time()); |
| 310 | 314 |
| 311 scheduler()->ScheduleLocalNudge(model_types, FROM_HERE); | 315 scheduler()->ScheduleLocalNudge(model_types, FROM_HERE); |
| 312 RunLoop(); | 316 RunLoop(); |
| 313 | 317 |
| 314 Mock::VerifyAndClearExpectations(syncer()); | 318 Mock::VerifyAndClearExpectations(syncer()); |
| 315 | 319 |
| 316 // Make sure a second, later, nudge is unaffected by first (no coalescing). | 320 // Make sure a second, later, nudge is unaffected by first (no coalescing). |
| 317 SyncShareTimes times2; | 321 SyncShareTimes times2; |
| 318 model_types.Remove(THEMES); | 322 model_types.Remove(THEMES); |
| 319 model_types.Put(TYPED_URLS); | 323 model_types.Put(TYPED_URLS); |
| 320 EXPECT_CALL(*syncer(), NormalSyncShare(_,_,_)) | 324 EXPECT_CALL(*syncer(), NormalSyncShare(_,_,_)) |
| 321 .WillOnce(DoAll(Invoke(sessions::test_util::SimulateNormalSuccess), | 325 .WillOnce(DoAll(Invoke(sessions::test_util::SimulateNormalSuccess), |
| 322 RecordSyncShare(×2))); | 326 RecordSyncShare(×2, true))); |
| 323 scheduler()->ScheduleLocalNudge(model_types, FROM_HERE); | 327 scheduler()->ScheduleLocalNudge(model_types, FROM_HERE); |
| 324 RunLoop(); | 328 RunLoop(); |
| 325 } | 329 } |
| 326 | 330 |
| 327 // Make sure a regular config command is scheduled fine in the absence of any | 331 // Make sure a regular config command is scheduled fine in the absence of any |
| 328 // errors. | 332 // errors. |
| 329 TEST_F(SyncSchedulerTest, Config) { | 333 TEST_F(SyncSchedulerTest, Config) { |
| 330 SyncShareTimes times; | 334 SyncShareTimes times; |
| 331 const ModelTypeSet model_types(THEMES); | 335 const ModelTypeSet model_types(THEMES); |
| 332 | 336 |
| 333 EXPECT_CALL(*syncer(), ConfigureSyncShare(_,_,_)) | 337 EXPECT_CALL(*syncer(), ConfigureSyncShare(_,_,_)) |
| 334 .WillOnce(DoAll(Invoke(sessions::test_util::SimulateConfigureSuccess), | 338 .WillOnce(DoAll(Invoke(sessions::test_util::SimulateConfigureSuccess), |
| 335 RecordSyncShare(×))); | 339 RecordSyncShare(×, true))); |
| 336 | 340 |
| 337 StartSyncScheduler(SyncScheduler::CONFIGURATION_MODE); | 341 StartSyncConfiguration(); |
| 338 | 342 |
| 339 CallbackCounter ready_counter; | 343 CallbackCounter ready_counter; |
| 340 CallbackCounter retry_counter; | 344 CallbackCounter retry_counter; |
| 341 ConfigurationParams params( | 345 ConfigurationParams params( |
| 342 GetUpdatesCallerInfo::RECONFIGURATION, | 346 GetUpdatesCallerInfo::RECONFIGURATION, |
| 343 model_types, | 347 model_types, |
| 344 TypesToRoutingInfo(model_types), | 348 TypesToRoutingInfo(model_types), |
| 345 base::Bind(&CallbackCounter::Callback, base::Unretained(&ready_counter)), | 349 base::Bind(&CallbackCounter::Callback, base::Unretained(&ready_counter)), |
| 346 base::Bind(&CallbackCounter::Callback, base::Unretained(&retry_counter))); | 350 base::Bind(&CallbackCounter::Callback, base::Unretained(&retry_counter))); |
| 347 scheduler()->ScheduleConfiguration(params); | 351 scheduler()->ScheduleConfiguration(params); |
| 348 PumpLoop(); | 352 PumpLoop(); |
| 349 ASSERT_EQ(1, ready_counter.times_called()); | 353 ASSERT_EQ(1, ready_counter.times_called()); |
| 350 ASSERT_EQ(0, retry_counter.times_called()); | 354 ASSERT_EQ(0, retry_counter.times_called()); |
| 351 } | 355 } |
| 352 | 356 |
| 353 // Simulate a failure and make sure the config request is retried. | 357 // Simulate a failure and make sure the config request is retried. |
| 354 TEST_F(SyncSchedulerTest, ConfigWithBackingOff) { | 358 TEST_F(SyncSchedulerTest, ConfigWithBackingOff) { |
| 355 UseMockDelayProvider(); | 359 UseMockDelayProvider(); |
| 356 EXPECT_CALL(*delay(), GetDelay(_)) | 360 EXPECT_CALL(*delay(), GetDelay(_)) |
| 357 .WillRepeatedly(Return(TimeDelta::FromMilliseconds(20))); | 361 .WillRepeatedly(Return(TimeDelta::FromMilliseconds(20))); |
| 358 SyncShareTimes times; | 362 SyncShareTimes times; |
| 359 const ModelTypeSet model_types(THEMES); | 363 const ModelTypeSet model_types(THEMES); |
| 360 | 364 |
| 361 StartSyncScheduler(SyncScheduler::CONFIGURATION_MODE); | 365 StartSyncConfiguration(); |
| 362 | 366 |
| 363 EXPECT_CALL(*syncer(), ConfigureSyncShare(_,_,_)) | 367 EXPECT_CALL(*syncer(), ConfigureSyncShare(_,_,_)) |
| 364 .WillOnce(DoAll(Invoke(sessions::test_util::SimulateConfigureFailed), | 368 .WillOnce(DoAll(Invoke(sessions::test_util::SimulateConfigureFailed), |
| 365 RecordSyncShare(×))) | 369 RecordSyncShare(×, false))) |
| 366 .WillOnce(DoAll(Invoke(sessions::test_util::SimulateConfigureFailed), | 370 .WillOnce(DoAll(Invoke(sessions::test_util::SimulateConfigureFailed), |
| 367 RecordSyncShare(×))); | 371 RecordSyncShare(×, false))); |
| 368 | 372 |
| 369 CallbackCounter ready_counter; | 373 CallbackCounter ready_counter; |
| 370 CallbackCounter retry_counter; | 374 CallbackCounter retry_counter; |
| 371 ConfigurationParams params( | 375 ConfigurationParams params( |
| 372 GetUpdatesCallerInfo::RECONFIGURATION, | 376 GetUpdatesCallerInfo::RECONFIGURATION, |
| 373 model_types, | 377 model_types, |
| 374 TypesToRoutingInfo(model_types), | 378 TypesToRoutingInfo(model_types), |
| 375 base::Bind(&CallbackCounter::Callback, base::Unretained(&ready_counter)), | 379 base::Bind(&CallbackCounter::Callback, base::Unretained(&ready_counter)), |
| 376 base::Bind(&CallbackCounter::Callback, base::Unretained(&retry_counter))); | 380 base::Bind(&CallbackCounter::Callback, base::Unretained(&retry_counter))); |
| 377 scheduler()->ScheduleConfiguration(params); | 381 scheduler()->ScheduleConfiguration(params); |
| 378 RunLoop(); | 382 RunLoop(); |
| 379 ASSERT_EQ(0, ready_counter.times_called()); | 383 ASSERT_EQ(0, ready_counter.times_called()); |
| 380 ASSERT_EQ(1, retry_counter.times_called()); | 384 ASSERT_EQ(1, retry_counter.times_called()); |
| 381 | 385 |
| 382 // RunLoop() will trigger TryCanaryJob which will retry configuration. | 386 // RunLoop() will trigger TryCanaryJob which will retry configuration. |
| 383 // Since retry_task was already called it shouldn't be called again. | 387 // Since retry_task was already called it shouldn't be called again. |
| 384 RunLoop(); | 388 RunLoop(); |
| 385 ASSERT_EQ(0, ready_counter.times_called()); | 389 ASSERT_EQ(0, ready_counter.times_called()); |
| 386 ASSERT_EQ(1, retry_counter.times_called()); | 390 ASSERT_EQ(1, retry_counter.times_called()); |
| 387 | 391 |
| 388 Mock::VerifyAndClearExpectations(syncer()); | 392 Mock::VerifyAndClearExpectations(syncer()); |
| 389 | 393 |
| 390 EXPECT_CALL(*syncer(), ConfigureSyncShare(_,_,_)) | 394 EXPECT_CALL(*syncer(), ConfigureSyncShare(_,_,_)) |
| 391 .WillOnce(DoAll(Invoke(sessions::test_util::SimulateConfigureSuccess), | 395 .WillOnce(DoAll(Invoke(sessions::test_util::SimulateConfigureSuccess), |
| 392 RecordSyncShare(×))); | 396 RecordSyncShare(×, true))); |
| 393 RunLoop(); | 397 RunLoop(); |
| 394 | 398 |
| 395 ASSERT_EQ(1, ready_counter.times_called()); | 399 ASSERT_EQ(1, ready_counter.times_called()); |
| 396 } | 400 } |
| 397 | 401 |
| 398 // Simuilate SyncSchedulerImpl::Stop being called in the middle of Configure. | 402 // Simuilate SyncSchedulerImpl::Stop being called in the middle of Configure. |
| 399 // This can happen if server returns NOT_MY_BIRTHDAY. | 403 // This can happen if server returns NOT_MY_BIRTHDAY. |
| 400 TEST_F(SyncSchedulerTest, ConfigWithStop) { | 404 TEST_F(SyncSchedulerTest, ConfigWithStop) { |
| 401 UseMockDelayProvider(); | 405 UseMockDelayProvider(); |
| 402 EXPECT_CALL(*delay(), GetDelay(_)) | 406 EXPECT_CALL(*delay(), GetDelay(_)) |
| 403 .WillRepeatedly(Return(TimeDelta::FromMilliseconds(20))); | 407 .WillRepeatedly(Return(TimeDelta::FromMilliseconds(20))); |
| 404 SyncShareTimes times; | 408 SyncShareTimes times; |
| 405 const ModelTypeSet model_types(THEMES); | 409 const ModelTypeSet model_types(THEMES); |
| 406 | 410 |
| 407 StartSyncScheduler(SyncScheduler::CONFIGURATION_MODE); | 411 StartSyncConfiguration(); |
| 408 | 412 |
| 409 // Make ConfigureSyncShare call scheduler->Stop(). It is not supposed to call | 413 // Make ConfigureSyncShare call scheduler->Stop(). It is not supposed to call |
| 410 // retry_task or dereference configuration params. | 414 // retry_task or dereference configuration params. |
| 411 EXPECT_CALL(*syncer(), ConfigureSyncShare(_,_,_)) | 415 EXPECT_CALL(*syncer(), ConfigureSyncShare(_,_,_)) |
| 412 .WillOnce(DoAll(Invoke(sessions::test_util::SimulateConfigureFailed), | 416 .WillOnce(DoAll(Invoke(sessions::test_util::SimulateConfigureFailed), |
| 413 StopScheduler(scheduler()), | 417 StopScheduler(scheduler()), |
| 414 RecordSyncShare(×))); | 418 RecordSyncShare(×, false))); |
| 415 | 419 |
| 416 CallbackCounter ready_counter; | 420 CallbackCounter ready_counter; |
| 417 CallbackCounter retry_counter; | 421 CallbackCounter retry_counter; |
| 418 ConfigurationParams params( | 422 ConfigurationParams params( |
| 419 GetUpdatesCallerInfo::RECONFIGURATION, | 423 GetUpdatesCallerInfo::RECONFIGURATION, |
| 420 model_types, | 424 model_types, |
| 421 TypesToRoutingInfo(model_types), | 425 TypesToRoutingInfo(model_types), |
| 422 base::Bind(&CallbackCounter::Callback, base::Unretained(&ready_counter)), | 426 base::Bind(&CallbackCounter::Callback, base::Unretained(&ready_counter)), |
| 423 base::Bind(&CallbackCounter::Callback, base::Unretained(&retry_counter))); | 427 base::Bind(&CallbackCounter::Callback, base::Unretained(&retry_counter))); |
| 424 scheduler()->ScheduleConfiguration(params); | 428 scheduler()->ScheduleConfiguration(params); |
| 425 PumpLoop(); | 429 PumpLoop(); |
| 426 ASSERT_EQ(0, ready_counter.times_called()); | 430 ASSERT_EQ(0, ready_counter.times_called()); |
| 427 ASSERT_EQ(0, retry_counter.times_called()); | 431 ASSERT_EQ(0, retry_counter.times_called()); |
| 428 } | 432 } |
| 429 | 433 |
| 430 // Issue a nudge when the config has failed. Make sure both the config and | 434 // Issue a nudge when the config has failed. Make sure both the config and |
| 431 // nudge are executed. | 435 // nudge are executed. |
| 432 TEST_F(SyncSchedulerTest, NudgeWithConfigWithBackingOff) { | 436 TEST_F(SyncSchedulerTest, NudgeWithConfigWithBackingOff) { |
| 433 const ModelTypeSet model_types(THEMES); | 437 const ModelTypeSet model_types(THEMES); |
| 434 UseMockDelayProvider(); | 438 UseMockDelayProvider(); |
| 435 EXPECT_CALL(*delay(), GetDelay(_)) | 439 EXPECT_CALL(*delay(), GetDelay(_)) |
| 436 .WillRepeatedly(Return(TimeDelta::FromMilliseconds(50))); | 440 .WillRepeatedly(Return(TimeDelta::FromMilliseconds(50))); |
| 437 SyncShareTimes times; | 441 SyncShareTimes times; |
| 438 | 442 |
| 439 StartSyncScheduler(SyncScheduler::CONFIGURATION_MODE); | 443 StartSyncConfiguration(); |
| 440 | 444 |
| 441 // Request a configure and make sure it fails. | 445 // Request a configure and make sure it fails. |
| 442 EXPECT_CALL(*syncer(), ConfigureSyncShare(_,_,_)) | 446 EXPECT_CALL(*syncer(), ConfigureSyncShare(_,_,_)) |
| 443 .WillOnce(DoAll(Invoke(sessions::test_util::SimulateConfigureFailed), | 447 .WillOnce(DoAll(Invoke(sessions::test_util::SimulateConfigureFailed), |
| 444 RecordSyncShare(×))); | 448 RecordSyncShare(×, false))); |
| 445 CallbackCounter ready_counter; | 449 CallbackCounter ready_counter; |
| 446 CallbackCounter retry_counter; | 450 CallbackCounter retry_counter; |
| 447 ConfigurationParams params( | 451 ConfigurationParams params( |
| 448 GetUpdatesCallerInfo::RECONFIGURATION, | 452 GetUpdatesCallerInfo::RECONFIGURATION, |
| 449 model_types, | 453 model_types, |
| 450 TypesToRoutingInfo(model_types), | 454 TypesToRoutingInfo(model_types), |
| 451 base::Bind(&CallbackCounter::Callback, base::Unretained(&ready_counter)), | 455 base::Bind(&CallbackCounter::Callback, base::Unretained(&ready_counter)), |
| 452 base::Bind(&CallbackCounter::Callback, base::Unretained(&retry_counter))); | 456 base::Bind(&CallbackCounter::Callback, base::Unretained(&retry_counter))); |
| 453 scheduler()->ScheduleConfiguration(params); | 457 scheduler()->ScheduleConfiguration(params); |
| 454 RunLoop(); | 458 RunLoop(); |
| 455 ASSERT_EQ(0, ready_counter.times_called()); | 459 ASSERT_EQ(0, ready_counter.times_called()); |
| 456 ASSERT_EQ(1, retry_counter.times_called()); | 460 ASSERT_EQ(1, retry_counter.times_called()); |
| 457 Mock::VerifyAndClearExpectations(syncer()); | 461 Mock::VerifyAndClearExpectations(syncer()); |
| 458 | 462 |
| 459 // Ask for a nudge while dealing with repeated configure failure. | 463 // Ask for a nudge while dealing with repeated configure failure. |
| 460 EXPECT_CALL(*syncer(), ConfigureSyncShare(_,_,_)) | 464 EXPECT_CALL(*syncer(), ConfigureSyncShare(_,_,_)) |
| 461 .WillOnce(DoAll(Invoke(sessions::test_util::SimulateConfigureFailed), | 465 .WillOnce(DoAll(Invoke(sessions::test_util::SimulateConfigureFailed), |
| 462 RecordSyncShare(×))); | 466 RecordSyncShare(×, false))); |
| 463 scheduler()->ScheduleLocalNudge(model_types, FROM_HERE); | 467 scheduler()->ScheduleLocalNudge(model_types, FROM_HERE); |
| 464 RunLoop(); | 468 RunLoop(); |
| 465 // Note that we're not RunLoop()ing for the NUDGE we just scheduled, but | 469 // Note that we're not RunLoop()ing for the NUDGE we just scheduled, but |
| 466 // for the first retry attempt from the config job (after | 470 // for the first retry attempt from the config job (after |
| 467 // waiting ~+/- 50ms). | 471 // waiting ~+/- 50ms). |
| 468 Mock::VerifyAndClearExpectations(syncer()); | 472 Mock::VerifyAndClearExpectations(syncer()); |
| 469 ASSERT_EQ(0, ready_counter.times_called()); | 473 ASSERT_EQ(0, ready_counter.times_called()); |
| 470 | 474 |
| 471 // Let the next configure retry succeed. | 475 // Let the next configure retry succeed. |
| 472 EXPECT_CALL(*syncer(), ConfigureSyncShare(_,_,_)) | 476 EXPECT_CALL(*syncer(), ConfigureSyncShare(_,_,_)) |
| 473 .WillOnce(DoAll(Invoke(sessions::test_util::SimulateConfigureSuccess), | 477 .WillOnce(DoAll(Invoke(sessions::test_util::SimulateConfigureSuccess), |
| 474 RecordSyncShare(×))); | 478 RecordSyncShare(×, true))); |
| 475 RunLoop(); | 479 RunLoop(); |
| 476 | 480 |
| 477 // Now change the mode so nudge can execute. | 481 // Now change the mode so nudge can execute. |
| 478 EXPECT_CALL(*syncer(), NormalSyncShare(_,_,_)) | 482 EXPECT_CALL(*syncer(), NormalSyncShare(_,_,_)) |
| 479 .WillOnce(DoAll(Invoke(sessions::test_util::SimulateNormalSuccess), | 483 .WillOnce(DoAll(Invoke(sessions::test_util::SimulateNormalSuccess), |
| 480 RecordSyncShare(×))); | 484 RecordSyncShare(×, true))); |
| 481 StartSyncScheduler(SyncScheduler::NORMAL_MODE); | 485 StartSyncScheduler(base::Time()); |
| 482 PumpLoop(); | 486 PumpLoop(); |
| 483 } | 487 } |
| 484 | 488 |
| 485 // Test that nudges are coalesced. | 489 // Test that nudges are coalesced. |
| 486 TEST_F(SyncSchedulerTest, NudgeCoalescing) { | 490 TEST_F(SyncSchedulerTest, NudgeCoalescing) { |
| 487 StartSyncScheduler(SyncScheduler::NORMAL_MODE); | 491 StartSyncScheduler(base::Time()); |
| 488 | 492 |
| 489 SyncShareTimes times; | 493 SyncShareTimes times; |
| 490 EXPECT_CALL(*syncer(), NormalSyncShare(_,_,_)) | 494 EXPECT_CALL(*syncer(), NormalSyncShare(_,_,_)) |
| 491 .WillOnce(DoAll(Invoke(sessions::test_util::SimulateNormalSuccess), | 495 .WillOnce(DoAll(Invoke(sessions::test_util::SimulateNormalSuccess), |
| 492 RecordSyncShare(×))); | 496 RecordSyncShare(×, true))); |
| 493 const ModelTypeSet types1(THEMES), types2(TYPED_URLS), types3(THEMES); | 497 const ModelTypeSet types1(THEMES), types2(TYPED_URLS), types3(THEMES); |
| 494 TimeTicks optimal_time = TimeTicks::Now() + default_delay(); | 498 TimeTicks optimal_time = TimeTicks::Now() + default_delay(); |
| 495 scheduler()->ScheduleLocalNudge(types1, FROM_HERE); | 499 scheduler()->ScheduleLocalNudge(types1, FROM_HERE); |
| 496 scheduler()->ScheduleLocalNudge(types2, FROM_HERE); | 500 scheduler()->ScheduleLocalNudge(types2, FROM_HERE); |
| 497 RunLoop(); | 501 RunLoop(); |
| 498 | 502 |
| 499 ASSERT_EQ(1U, times.size()); | 503 ASSERT_EQ(1U, times.size()); |
| 500 EXPECT_GE(times[0], optimal_time); | 504 EXPECT_GE(times[0], optimal_time); |
| 501 | 505 |
| 502 Mock::VerifyAndClearExpectations(syncer()); | 506 Mock::VerifyAndClearExpectations(syncer()); |
| 503 | 507 |
| 504 SyncShareTimes times2; | 508 SyncShareTimes times2; |
| 505 EXPECT_CALL(*syncer(), NormalSyncShare(_,_,_)) | 509 EXPECT_CALL(*syncer(), NormalSyncShare(_,_,_)) |
| 506 .WillOnce(DoAll(Invoke(sessions::test_util::SimulateNormalSuccess), | 510 .WillOnce(DoAll(Invoke(sessions::test_util::SimulateNormalSuccess), |
| 507 RecordSyncShare(×2))); | 511 RecordSyncShare(×2, true))); |
| 508 scheduler()->ScheduleLocalNudge(types3, FROM_HERE); | 512 scheduler()->ScheduleLocalNudge(types3, FROM_HERE); |
| 509 RunLoop(); | 513 RunLoop(); |
| 510 } | 514 } |
| 511 | 515 |
| 512 // Test that nudges are coalesced. | 516 // Test that nudges are coalesced. |
| 513 TEST_F(SyncSchedulerTest, NudgeCoalescingWithDifferentTimings) { | 517 TEST_F(SyncSchedulerTest, NudgeCoalescingWithDifferentTimings) { |
| 514 StartSyncScheduler(SyncScheduler::NORMAL_MODE); | 518 StartSyncScheduler(base::Time()); |
| 515 | 519 |
| 516 SyncShareTimes times; | 520 SyncShareTimes times; |
| 517 EXPECT_CALL(*syncer(), NormalSyncShare(_,_,_)) | 521 EXPECT_CALL(*syncer(), NormalSyncShare(_,_,_)) |
| 518 .WillOnce(DoAll(Invoke(sessions::test_util::SimulateNormalSuccess), | 522 .WillOnce(DoAll(Invoke(sessions::test_util::SimulateNormalSuccess), |
| 519 RecordSyncShare(×))); | 523 RecordSyncShare(×, true))); |
| 520 ModelTypeSet types1(THEMES), types2(TYPED_URLS), types3; | 524 ModelTypeSet types1(THEMES), types2(TYPED_URLS), types3; |
| 521 | 525 |
| 522 // Create a huge time delay. | 526 // Create a huge time delay. |
| 523 TimeDelta delay = TimeDelta::FromDays(1); | 527 TimeDelta delay = TimeDelta::FromDays(1); |
| 524 | 528 |
| 525 std::map<ModelType, TimeDelta> delay_map; | 529 std::map<ModelType, TimeDelta> delay_map; |
| 526 delay_map[types1.First().Get()] = delay; | 530 delay_map[types1.First().Get()] = delay; |
| 527 scheduler()->OnReceivedCustomNudgeDelays(delay_map); | 531 scheduler()->OnReceivedCustomNudgeDelays(delay_map); |
| 528 scheduler()->ScheduleLocalNudge(types1, FROM_HERE); | 532 scheduler()->ScheduleLocalNudge(types1, FROM_HERE); |
| 529 scheduler()->ScheduleLocalNudge(types2, FROM_HERE); | 533 scheduler()->ScheduleLocalNudge(types2, FROM_HERE); |
| 530 | 534 |
| 531 TimeTicks min_time = TimeTicks::Now(); | 535 TimeTicks min_time = TimeTicks::Now(); |
| 532 TimeTicks max_time = TimeTicks::Now() + delay; | 536 TimeTicks max_time = TimeTicks::Now() + delay; |
| 533 | 537 |
| 534 RunLoop(); | 538 RunLoop(); |
| 535 Mock::VerifyAndClearExpectations(syncer()); | 539 Mock::VerifyAndClearExpectations(syncer()); |
| 536 | 540 |
| 537 // Make sure the sync happened at the right time. | 541 // Make sure the sync happened at the right time. |
| 538 ASSERT_EQ(1U, times.size()); | 542 ASSERT_EQ(1U, times.size()); |
| 539 EXPECT_GE(times[0], min_time); | 543 EXPECT_GE(times[0], min_time); |
| 540 EXPECT_LE(times[0], max_time); | 544 EXPECT_LE(times[0], max_time); |
| 541 } | 545 } |
| 542 | 546 |
| 543 // Test nudge scheduling. | 547 // Test nudge scheduling. |
| 544 TEST_F(SyncSchedulerTest, NudgeWithStates) { | 548 TEST_F(SyncSchedulerTest, NudgeWithStates) { |
| 545 StartSyncScheduler(SyncScheduler::NORMAL_MODE); | 549 StartSyncScheduler(base::Time()); |
| 546 | 550 |
| 547 SyncShareTimes times1; | 551 SyncShareTimes times1; |
| 548 EXPECT_CALL(*syncer(), NormalSyncShare(_,_,_)) | 552 EXPECT_CALL(*syncer(), NormalSyncShare(_,_,_)) |
| 549 .WillOnce(DoAll(Invoke(sessions::test_util::SimulateNormalSuccess), | 553 .WillOnce(DoAll(Invoke(sessions::test_util::SimulateNormalSuccess), |
| 550 RecordSyncShare(×1))) | 554 RecordSyncShare(×1, true))) |
| 551 .RetiresOnSaturation(); | 555 .RetiresOnSaturation(); |
| 552 scheduler()->ScheduleInvalidationNudge( | 556 scheduler()->ScheduleInvalidationNudge( |
| 553 THEMES, BuildInvalidation(10, "test"), FROM_HERE); | 557 THEMES, BuildInvalidation(10, "test"), FROM_HERE); |
| 554 RunLoop(); | 558 RunLoop(); |
| 555 | 559 |
| 556 Mock::VerifyAndClearExpectations(syncer()); | 560 Mock::VerifyAndClearExpectations(syncer()); |
| 557 | 561 |
| 558 // Make sure a second, later, nudge is unaffected by first (no coalescing). | 562 // Make sure a second, later, nudge is unaffected by first (no coalescing). |
| 559 SyncShareTimes times2; | 563 SyncShareTimes times2; |
| 560 EXPECT_CALL(*syncer(), NormalSyncShare(_,_,_)) | 564 EXPECT_CALL(*syncer(), NormalSyncShare(_,_,_)) |
| 561 .WillOnce(DoAll(Invoke(sessions::test_util::SimulateNormalSuccess), | 565 .WillOnce(DoAll(Invoke(sessions::test_util::SimulateNormalSuccess), |
| 562 RecordSyncShare(×2))); | 566 RecordSyncShare(×2, true))); |
| 563 scheduler()->ScheduleInvalidationNudge( | 567 scheduler()->ScheduleInvalidationNudge( |
| 564 TYPED_URLS, BuildInvalidation(10, "test2"), FROM_HERE); | 568 TYPED_URLS, BuildInvalidation(10, "test2"), FROM_HERE); |
| 565 RunLoop(); | 569 RunLoop(); |
| 566 } | 570 } |
| 567 | 571 |
| 568 // Test that polling works as expected. | 572 // Test that polling works as expected. |
| 569 TEST_F(SyncSchedulerTest, Polling) { | 573 TEST_F(SyncSchedulerTest, Polling) { |
| 570 SyncShareTimes times; | 574 SyncShareTimes times; |
| 571 TimeDelta poll_interval(TimeDelta::FromMilliseconds(30)); | 575 TimeDelta poll_interval(TimeDelta::FromMilliseconds(30)); |
| 572 EXPECT_CALL(*syncer(), PollSyncShare(_,_)).Times(AtLeast(kMinNumSamples)) | 576 EXPECT_CALL(*syncer(), PollSyncShare(_,_)).Times(AtLeast(kMinNumSamples)) |
| 573 .WillRepeatedly( | 577 .WillRepeatedly( |
| 574 DoAll(Invoke(sessions::test_util::SimulatePollSuccess), | 578 DoAll(Invoke(sessions::test_util::SimulatePollSuccess), |
| 575 RecordSyncShareMultiple(×, kMinNumSamples))); | 579 RecordSyncShareMultiple(×, kMinNumSamples, true))); |
| 576 | 580 |
| 577 scheduler()->OnReceivedLongPollIntervalUpdate(poll_interval); | 581 scheduler()->OnReceivedLongPollIntervalUpdate(poll_interval); |
| 578 | 582 |
| 579 TimeTicks optimal_start = TimeTicks::Now() + poll_interval; | 583 TimeTicks optimal_start = TimeTicks::Now() + poll_interval; |
| 580 StartSyncScheduler(SyncScheduler::NORMAL_MODE); | 584 StartSyncScheduler(base::Time()); |
| 581 | 585 |
| 582 // Run again to wait for polling. | 586 // Run again to wait for polling. |
| 583 RunLoop(); | 587 RunLoop(); |
| 588 |
| 589 StopSyncScheduler(); |
| 590 AnalyzePollRun(times, kMinNumSamples, optimal_start, poll_interval); |
| 591 } |
| 592 |
| 593 // Test that we reuse the previous poll time on startup, triggering the first |
| 594 // poll based on when the last one happened. Subsequent polls should have the |
| 595 // normal delay. |
| 596 TEST_F(SyncSchedulerTest, PollingPersistence) { |
| 597 SyncShareTimes times; |
| 598 // Use a large poll interval that wouldn't normally get hit on its own for |
| 599 // some time yet. |
| 600 TimeDelta poll_interval(TimeDelta::FromMilliseconds(500)); |
| 601 EXPECT_CALL(*syncer(), PollSyncShare(_,_)).Times(AtLeast(kMinNumSamples)) |
| 602 .WillRepeatedly( |
| 603 DoAll(Invoke(sessions::test_util::SimulatePollSuccess), |
| 604 RecordSyncShareMultiple(×, kMinNumSamples, true))); |
| 605 |
| 606 scheduler()->OnReceivedLongPollIntervalUpdate(poll_interval); |
| 607 |
| 608 // Set the start time to now, as the poll was overdue. |
| 609 TimeTicks optimal_start = TimeTicks::Now(); |
| 610 StartSyncScheduler(base::Time::Now() - poll_interval); |
| 611 |
| 612 // Run again to wait for polling. |
| 613 RunLoop(); |
| 614 |
| 615 StopSyncScheduler(); |
| 616 AnalyzePollRun(times, kMinNumSamples, optimal_start, poll_interval); |
| 617 } |
| 618 |
| 619 // Test that if the persisted poll is in the future, it's ignored (the case |
| 620 // where the local time has been modified). |
| 621 TEST_F(SyncSchedulerTest, PollingPersistenceBadClock) { |
| 622 SyncShareTimes times; |
| 623 TimeDelta poll_interval(TimeDelta::FromMilliseconds(30)); |
| 624 EXPECT_CALL(*syncer(), PollSyncShare(_,_)).Times(AtLeast(kMinNumSamples)) |
| 625 .WillRepeatedly( |
| 626 DoAll(Invoke(sessions::test_util::SimulatePollSuccess), |
| 627 RecordSyncShareMultiple(×, kMinNumSamples, true))); |
| 628 |
| 629 scheduler()->OnReceivedLongPollIntervalUpdate(poll_interval); |
| 630 |
| 631 // Set the start time to |poll_interval| in the future. |
| 632 TimeTicks optimal_start = TimeTicks::Now() + poll_interval; |
| 633 StartSyncScheduler(base::Time::Now() + base::TimeDelta::FromMinutes(10)); |
| 634 |
| 635 // Run again to wait for polling. |
| 636 RunLoop(); |
| 584 | 637 |
| 585 StopSyncScheduler(); | 638 StopSyncScheduler(); |
| 586 AnalyzePollRun(times, kMinNumSamples, optimal_start, poll_interval); | 639 AnalyzePollRun(times, kMinNumSamples, optimal_start, poll_interval); |
| 587 } | 640 } |
| 588 | 641 |
| 589 // Test that the short poll interval is used. | 642 // Test that the short poll interval is used. |
| 590 TEST_F(SyncSchedulerTest, PollNotificationsDisabled) { | 643 TEST_F(SyncSchedulerTest, PollNotificationsDisabled) { |
| 591 SyncShareTimes times; | 644 SyncShareTimes times; |
| 592 TimeDelta poll_interval(TimeDelta::FromMilliseconds(30)); | 645 TimeDelta poll_interval(TimeDelta::FromMilliseconds(30)); |
| 593 EXPECT_CALL(*syncer(), PollSyncShare(_,_)).Times(AtLeast(kMinNumSamples)) | 646 EXPECT_CALL(*syncer(), PollSyncShare(_,_)).Times(AtLeast(kMinNumSamples)) |
| 594 .WillRepeatedly( | 647 .WillRepeatedly( |
| 595 DoAll(Invoke(sessions::test_util::SimulatePollSuccess), | 648 DoAll(Invoke(sessions::test_util::SimulatePollSuccess), |
| 596 RecordSyncShareMultiple(×, kMinNumSamples))); | 649 RecordSyncShareMultiple(×, kMinNumSamples, true))); |
| 597 | 650 |
| 598 scheduler()->OnReceivedShortPollIntervalUpdate(poll_interval); | 651 scheduler()->OnReceivedShortPollIntervalUpdate(poll_interval); |
| 599 scheduler()->SetNotificationsEnabled(false); | 652 scheduler()->SetNotificationsEnabled(false); |
| 600 | 653 |
| 601 TimeTicks optimal_start = TimeTicks::Now() + poll_interval; | 654 TimeTicks optimal_start = TimeTicks::Now() + poll_interval; |
| 602 StartSyncScheduler(SyncScheduler::NORMAL_MODE); | 655 StartSyncScheduler(base::Time()); |
| 603 | 656 |
| 604 // Run again to wait for polling. | 657 // Run again to wait for polling. |
| 605 RunLoop(); | 658 RunLoop(); |
| 606 | 659 |
| 607 StopSyncScheduler(); | 660 StopSyncScheduler(); |
| 608 AnalyzePollRun(times, kMinNumSamples, optimal_start, poll_interval); | 661 AnalyzePollRun(times, kMinNumSamples, optimal_start, poll_interval); |
| 609 } | 662 } |
| 610 | 663 |
| 611 // Test that polling intervals are updated when needed. | 664 // Test that polling intervals are updated when needed. |
| 612 TEST_F(SyncSchedulerTest, PollIntervalUpdate) { | 665 TEST_F(SyncSchedulerTest, PollIntervalUpdate) { |
| 613 SyncShareTimes times; | 666 SyncShareTimes times; |
| 614 TimeDelta poll1(TimeDelta::FromMilliseconds(120)); | 667 TimeDelta poll1(TimeDelta::FromMilliseconds(120)); |
| 615 TimeDelta poll2(TimeDelta::FromMilliseconds(30)); | 668 TimeDelta poll2(TimeDelta::FromMilliseconds(30)); |
| 616 scheduler()->OnReceivedLongPollIntervalUpdate(poll1); | 669 scheduler()->OnReceivedLongPollIntervalUpdate(poll1); |
| 617 EXPECT_CALL(*syncer(), PollSyncShare(_,_)).Times(AtLeast(kMinNumSamples)) | 670 EXPECT_CALL(*syncer(), PollSyncShare(_,_)).Times(AtLeast(kMinNumSamples)) |
| 618 .WillOnce(DoAll( | 671 .WillOnce(DoAll( |
| 619 WithArgs<0,1>( | 672 WithArgs<0,1>( |
| 620 sessions::test_util::SimulatePollIntervalUpdate(poll2)), | 673 sessions::test_util::SimulatePollIntervalUpdate(poll2)), |
| 621 Return(true))) | 674 Return(true))) |
| 622 .WillRepeatedly( | 675 .WillRepeatedly( |
| 623 DoAll(Invoke(sessions::test_util::SimulatePollSuccess), | 676 DoAll(Invoke(sessions::test_util::SimulatePollSuccess), |
| 624 WithArg<1>( | 677 WithArg<1>( |
| 625 RecordSyncShareMultiple(×, kMinNumSamples)))); | 678 RecordSyncShareMultiple(×, kMinNumSamples, true)))); |
| 626 | 679 |
| 627 TimeTicks optimal_start = TimeTicks::Now() + poll1 + poll2; | 680 TimeTicks optimal_start = TimeTicks::Now() + poll1 + poll2; |
| 628 StartSyncScheduler(SyncScheduler::NORMAL_MODE); | 681 StartSyncScheduler(base::Time()); |
| 629 | 682 |
| 630 // Run again to wait for polling. | 683 // Run again to wait for polling. |
| 631 RunLoop(); | 684 RunLoop(); |
| 632 | 685 |
| 633 StopSyncScheduler(); | 686 StopSyncScheduler(); |
| 634 AnalyzePollRun(times, kMinNumSamples, optimal_start, poll2); | 687 AnalyzePollRun(times, kMinNumSamples, optimal_start, poll2); |
| 635 } | 688 } |
| 636 | 689 |
| 637 // Test that no syncing occurs when throttled. | 690 // Test that no syncing occurs when throttled. |
| 638 TEST_F(SyncSchedulerTest, ThrottlingDoesThrottle) { | 691 TEST_F(SyncSchedulerTest, ThrottlingDoesThrottle) { |
| 639 const ModelTypeSet types(THEMES); | 692 const ModelTypeSet types(THEMES); |
| 640 TimeDelta poll(TimeDelta::FromMilliseconds(20)); | 693 TimeDelta poll(TimeDelta::FromMilliseconds(20)); |
| 641 TimeDelta throttle(TimeDelta::FromMinutes(10)); | 694 TimeDelta throttle(TimeDelta::FromMinutes(10)); |
| 642 scheduler()->OnReceivedLongPollIntervalUpdate(poll); | 695 scheduler()->OnReceivedLongPollIntervalUpdate(poll); |
| 643 | 696 |
| 644 EXPECT_CALL(*syncer(), ConfigureSyncShare(_,_,_)) | 697 EXPECT_CALL(*syncer(), ConfigureSyncShare(_,_,_)) |
| 645 .WillOnce(DoAll( | 698 .WillOnce(DoAll( |
| 646 WithArg<2>(sessions::test_util::SimulateThrottled(throttle)), | 699 WithArg<2>(sessions::test_util::SimulateThrottled(throttle)), |
| 647 Return(true))) | 700 Return(false))) |
| 648 .WillRepeatedly(AddFailureAndQuitLoopNow()); | 701 .WillRepeatedly(AddFailureAndQuitLoopNow()); |
| 649 | 702 |
| 650 StartSyncScheduler(SyncScheduler::NORMAL_MODE); | 703 StartSyncScheduler(base::Time()); |
| 651 | 704 |
| 652 scheduler()->ScheduleLocalNudge(types, FROM_HERE); | 705 scheduler()->ScheduleLocalNudge(types, FROM_HERE); |
| 653 PumpLoop(); | 706 PumpLoop(); |
| 654 | 707 |
| 655 StartSyncScheduler(SyncScheduler::CONFIGURATION_MODE); | 708 StartSyncConfiguration(); |
| 656 | 709 |
| 657 CallbackCounter ready_counter; | 710 CallbackCounter ready_counter; |
| 658 CallbackCounter retry_counter; | 711 CallbackCounter retry_counter; |
| 659 ConfigurationParams params( | 712 ConfigurationParams params( |
| 660 GetUpdatesCallerInfo::RECONFIGURATION, | 713 GetUpdatesCallerInfo::RECONFIGURATION, |
| 661 types, | 714 types, |
| 662 TypesToRoutingInfo(types), | 715 TypesToRoutingInfo(types), |
| 663 base::Bind(&CallbackCounter::Callback, base::Unretained(&ready_counter)), | 716 base::Bind(&CallbackCounter::Callback, base::Unretained(&ready_counter)), |
| 664 base::Bind(&CallbackCounter::Callback, base::Unretained(&retry_counter))); | 717 base::Bind(&CallbackCounter::Callback, base::Unretained(&retry_counter))); |
| 665 scheduler()->ScheduleConfiguration(params); | 718 scheduler()->ScheduleConfiguration(params); |
| 666 PumpLoop(); | 719 PumpLoop(); |
| 667 ASSERT_EQ(0, ready_counter.times_called()); | 720 ASSERT_EQ(0, ready_counter.times_called()); |
| 668 ASSERT_EQ(1, retry_counter.times_called()); | 721 ASSERT_EQ(1, retry_counter.times_called()); |
| 669 | 722 |
| 670 } | 723 } |
| 671 | 724 |
| 672 TEST_F(SyncSchedulerTest, ThrottlingExpiresFromPoll) { | 725 TEST_F(SyncSchedulerTest, ThrottlingExpiresFromPoll) { |
| 673 SyncShareTimes times; | 726 SyncShareTimes times; |
| 674 TimeDelta poll(TimeDelta::FromMilliseconds(15)); | 727 TimeDelta poll(TimeDelta::FromMilliseconds(15)); |
| 675 TimeDelta throttle1(TimeDelta::FromMilliseconds(150)); | 728 TimeDelta throttle1(TimeDelta::FromMilliseconds(150)); |
| 676 scheduler()->OnReceivedLongPollIntervalUpdate(poll); | 729 scheduler()->OnReceivedLongPollIntervalUpdate(poll); |
| 677 | 730 |
| 678 ::testing::InSequence seq; | 731 ::testing::InSequence seq; |
| 679 EXPECT_CALL(*syncer(), PollSyncShare(_,_)) | 732 EXPECT_CALL(*syncer(), PollSyncShare(_,_)) |
| 680 .WillOnce(DoAll( | 733 .WillOnce(DoAll( |
| 681 WithArg<1>(sessions::test_util::SimulateThrottled(throttle1)), | 734 WithArg<1>(sessions::test_util::SimulateThrottled(throttle1)), |
| 682 Return(true))) | 735 Return(false))) |
| 683 .RetiresOnSaturation(); | 736 .RetiresOnSaturation(); |
| 684 EXPECT_CALL(*syncer(), PollSyncShare(_,_)) | 737 EXPECT_CALL(*syncer(), PollSyncShare(_,_)) |
| 685 .WillRepeatedly( | 738 .WillRepeatedly( |
| 686 DoAll(Invoke(sessions::test_util::SimulatePollSuccess), | 739 DoAll(Invoke(sessions::test_util::SimulatePollSuccess), |
| 687 RecordSyncShareMultiple(×, kMinNumSamples))); | 740 RecordSyncShareMultiple(×, kMinNumSamples, true))); |
| 688 | 741 |
| 689 TimeTicks optimal_start = TimeTicks::Now() + poll + throttle1; | 742 TimeTicks optimal_start = TimeTicks::Now() + poll + throttle1; |
| 690 StartSyncScheduler(SyncScheduler::NORMAL_MODE); | 743 StartSyncScheduler(base::Time()); |
| 691 | 744 |
| 692 // Run again to wait for polling. | 745 // Run again to wait for polling. |
| 693 RunLoop(); | 746 RunLoop(); |
| 694 | 747 |
| 695 StopSyncScheduler(); | 748 StopSyncScheduler(); |
| 696 AnalyzePollRun(times, kMinNumSamples, optimal_start, poll); | 749 AnalyzePollRun(times, kMinNumSamples, optimal_start, poll); |
| 697 } | 750 } |
| 698 | 751 |
| 699 TEST_F(SyncSchedulerTest, ThrottlingExpiresFromNudge) { | 752 TEST_F(SyncSchedulerTest, ThrottlingExpiresFromNudge) { |
| 700 SyncShareTimes times; | 753 SyncShareTimes times; |
| 701 TimeDelta poll(TimeDelta::FromDays(1)); | 754 TimeDelta poll(TimeDelta::FromDays(1)); |
| 702 TimeDelta throttle1(TimeDelta::FromMilliseconds(150)); | 755 TimeDelta throttle1(TimeDelta::FromMilliseconds(150)); |
| 703 scheduler()->OnReceivedLongPollIntervalUpdate(poll); | 756 scheduler()->OnReceivedLongPollIntervalUpdate(poll); |
| 704 | 757 |
| 705 ::testing::InSequence seq; | 758 ::testing::InSequence seq; |
| 706 EXPECT_CALL(*syncer(), NormalSyncShare(_,_,_)) | 759 EXPECT_CALL(*syncer(), NormalSyncShare(_,_,_)) |
| 707 .WillOnce(DoAll( | 760 .WillOnce(DoAll( |
| 708 WithArg<2>(sessions::test_util::SimulateThrottled(throttle1)), | 761 WithArg<2>(sessions::test_util::SimulateThrottled(throttle1)), |
| 709 Return(true))) | 762 Return(false))) |
| 710 .RetiresOnSaturation(); | 763 .RetiresOnSaturation(); |
| 711 EXPECT_CALL(*syncer(), NormalSyncShare(_,_,_)) | 764 EXPECT_CALL(*syncer(), NormalSyncShare(_,_,_)) |
| 712 .WillOnce(DoAll(Invoke(sessions::test_util::SimulateNormalSuccess), | 765 .WillOnce(DoAll(Invoke(sessions::test_util::SimulateNormalSuccess), |
| 713 QuitLoopNowAction())); | 766 QuitLoopNowAction(true))); |
| 714 | 767 |
| 715 const ModelTypeSet types(THEMES); | 768 const ModelTypeSet types(THEMES); |
| 716 StartSyncScheduler(SyncScheduler::NORMAL_MODE); | 769 StartSyncScheduler(base::Time()); |
| 717 scheduler()->ScheduleLocalNudge(types, FROM_HERE); | 770 scheduler()->ScheduleLocalNudge(types, FROM_HERE); |
| 718 | 771 |
| 719 PumpLoop(); // To get PerformDelayedNudge called. | 772 PumpLoop(); // To get PerformDelayedNudge called. |
| 720 PumpLoop(); // To get TrySyncSessionJob called | 773 PumpLoop(); // To get TrySyncSessionJob called |
| 721 EXPECT_TRUE(scheduler()->IsCurrentlyThrottled()); | 774 EXPECT_TRUE(scheduler()->IsCurrentlyThrottled()); |
| 722 RunLoop(); | 775 RunLoop(); |
| 723 EXPECT_FALSE(scheduler()->IsCurrentlyThrottled()); | 776 EXPECT_FALSE(scheduler()->IsCurrentlyThrottled()); |
| 724 | 777 |
| 725 StopSyncScheduler(); | 778 StopSyncScheduler(); |
| 726 } | 779 } |
| 727 | 780 |
| 728 TEST_F(SyncSchedulerTest, ThrottlingExpiresFromConfigure) { | 781 TEST_F(SyncSchedulerTest, ThrottlingExpiresFromConfigure) { |
| 729 SyncShareTimes times; | 782 SyncShareTimes times; |
| 730 TimeDelta poll(TimeDelta::FromDays(1)); | 783 TimeDelta poll(TimeDelta::FromDays(1)); |
| 731 TimeDelta throttle1(TimeDelta::FromMilliseconds(150)); | 784 TimeDelta throttle1(TimeDelta::FromMilliseconds(150)); |
| 732 scheduler()->OnReceivedLongPollIntervalUpdate(poll); | 785 scheduler()->OnReceivedLongPollIntervalUpdate(poll); |
| 733 | 786 |
| 734 ::testing::InSequence seq; | 787 ::testing::InSequence seq; |
| 735 EXPECT_CALL(*syncer(), ConfigureSyncShare(_,_,_)) | 788 EXPECT_CALL(*syncer(), ConfigureSyncShare(_,_,_)) |
| 736 .WillOnce(DoAll( | 789 .WillOnce(DoAll( |
| 737 WithArg<2>(sessions::test_util::SimulateThrottled(throttle1)), | 790 WithArg<2>(sessions::test_util::SimulateThrottled(throttle1)), |
| 738 Return(true))) | 791 Return(false))) |
| 739 .RetiresOnSaturation(); | 792 .RetiresOnSaturation(); |
| 740 EXPECT_CALL(*syncer(), ConfigureSyncShare(_,_,_)) | 793 EXPECT_CALL(*syncer(), ConfigureSyncShare(_,_,_)) |
| 741 .WillOnce(DoAll(Invoke(sessions::test_util::SimulateConfigureSuccess), | 794 .WillOnce(DoAll(Invoke(sessions::test_util::SimulateConfigureSuccess), |
| 742 QuitLoopNowAction())); | 795 QuitLoopNowAction(true))); |
| 743 | 796 |
| 744 const ModelTypeSet types(THEMES); | 797 const ModelTypeSet types(THEMES); |
| 745 StartSyncScheduler(SyncScheduler::CONFIGURATION_MODE); | 798 StartSyncConfiguration(); |
| 746 | 799 |
| 747 CallbackCounter ready_counter; | 800 CallbackCounter ready_counter; |
| 748 CallbackCounter retry_counter; | 801 CallbackCounter retry_counter; |
| 749 ConfigurationParams params( | 802 ConfigurationParams params( |
| 750 GetUpdatesCallerInfo::RECONFIGURATION, | 803 GetUpdatesCallerInfo::RECONFIGURATION, |
| 751 types, | 804 types, |
| 752 TypesToRoutingInfo(types), | 805 TypesToRoutingInfo(types), |
| 753 base::Bind(&CallbackCounter::Callback, base::Unretained(&ready_counter)), | 806 base::Bind(&CallbackCounter::Callback, base::Unretained(&ready_counter)), |
| 754 base::Bind(&CallbackCounter::Callback, base::Unretained(&retry_counter))); | 807 base::Bind(&CallbackCounter::Callback, base::Unretained(&retry_counter))); |
| 755 scheduler()->ScheduleConfiguration(params); | 808 scheduler()->ScheduleConfiguration(params); |
| (...skipping 17 matching lines...) Expand all Loading... |
| 773 TimeDelta throttle1(TimeDelta::FromSeconds(60)); | 826 TimeDelta throttle1(TimeDelta::FromSeconds(60)); |
| 774 scheduler()->OnReceivedLongPollIntervalUpdate(poll); | 827 scheduler()->OnReceivedLongPollIntervalUpdate(poll); |
| 775 | 828 |
| 776 const ModelTypeSet types(THEMES); | 829 const ModelTypeSet types(THEMES); |
| 777 | 830 |
| 778 ::testing::InSequence seq; | 831 ::testing::InSequence seq; |
| 779 EXPECT_CALL(*syncer(), NormalSyncShare(_,_,_)) | 832 EXPECT_CALL(*syncer(), NormalSyncShare(_,_,_)) |
| 780 .WillOnce(DoAll( | 833 .WillOnce(DoAll( |
| 781 WithArg<2>( | 834 WithArg<2>( |
| 782 sessions::test_util::SimulateTypesThrottled(types, throttle1)), | 835 sessions::test_util::SimulateTypesThrottled(types, throttle1)), |
| 783 Return(true))) | 836 Return(false))) |
| 784 .RetiresOnSaturation(); | 837 .RetiresOnSaturation(); |
| 785 | 838 |
| 786 StartSyncScheduler(SyncScheduler::NORMAL_MODE); | 839 StartSyncScheduler(base::Time()); |
| 787 scheduler()->ScheduleLocalNudge(types, FROM_HERE); | 840 scheduler()->ScheduleLocalNudge(types, FROM_HERE); |
| 788 PumpLoop(); // To get PerformDelayedNudge called. | 841 PumpLoop(); // To get PerformDelayedNudge called. |
| 789 PumpLoop(); // To get TrySyncSessionJob called | 842 PumpLoop(); // To get TrySyncSessionJob called |
| 790 EXPECT_TRUE(GetThrottledTypes().HasAll(types)); | 843 EXPECT_TRUE(GetThrottledTypes().HasAll(types)); |
| 791 | 844 |
| 792 // This won't cause a sync cycle because the types are throttled. | 845 // This won't cause a sync cycle because the types are throttled. |
| 793 scheduler()->ScheduleLocalNudge(types, FROM_HERE); | 846 scheduler()->ScheduleLocalNudge(types, FROM_HERE); |
| 794 PumpLoop(); | 847 PumpLoop(); |
| 795 | 848 |
| 796 StopSyncScheduler(); | 849 StopSyncScheduler(); |
| (...skipping 11 matching lines...) Expand all Loading... |
| 808 | 861 |
| 809 const ModelTypeSet throttled_types(THEMES); | 862 const ModelTypeSet throttled_types(THEMES); |
| 810 const ModelTypeSet unthrottled_types(PREFERENCES); | 863 const ModelTypeSet unthrottled_types(PREFERENCES); |
| 811 | 864 |
| 812 ::testing::InSequence seq; | 865 ::testing::InSequence seq; |
| 813 EXPECT_CALL(*syncer(), NormalSyncShare(_,_,_)) | 866 EXPECT_CALL(*syncer(), NormalSyncShare(_,_,_)) |
| 814 .WillOnce(DoAll( | 867 .WillOnce(DoAll( |
| 815 WithArg<2>( | 868 WithArg<2>( |
| 816 sessions::test_util::SimulateTypesThrottled( | 869 sessions::test_util::SimulateTypesThrottled( |
| 817 throttled_types, throttle1)), | 870 throttled_types, throttle1)), |
| 818 Return(true))) | 871 Return(false))) |
| 819 .RetiresOnSaturation(); | 872 .RetiresOnSaturation(); |
| 820 | 873 |
| 821 StartSyncScheduler(SyncScheduler::NORMAL_MODE); | 874 StartSyncScheduler(base::Time()); |
| 822 scheduler()->ScheduleLocalNudge(throttled_types, FROM_HERE); | 875 scheduler()->ScheduleLocalNudge(throttled_types, FROM_HERE); |
| 823 PumpLoop(); // To get PerformDelayedNudge called. | 876 PumpLoop(); // To get PerformDelayedNudge called. |
| 824 PumpLoop(); // To get TrySyncSessionJob called | 877 PumpLoop(); // To get TrySyncSessionJob called |
| 825 EXPECT_TRUE(GetThrottledTypes().HasAll(throttled_types)); | 878 EXPECT_TRUE(GetThrottledTypes().HasAll(throttled_types)); |
| 826 | 879 |
| 827 // Ignore invalidations for throttled types. | 880 // Ignore invalidations for throttled types. |
| 828 scheduler()->ScheduleInvalidationNudge( | 881 scheduler()->ScheduleInvalidationNudge( |
| 829 THEMES, BuildInvalidation(10, "test"), FROM_HERE); | 882 THEMES, BuildInvalidation(10, "test"), FROM_HERE); |
| 830 PumpLoop(); | 883 PumpLoop(); |
| 831 | 884 |
| 832 // Ignore refresh requests for throttled types. | 885 // Ignore refresh requests for throttled types. |
| 833 scheduler()->ScheduleLocalRefreshRequest(throttled_types, FROM_HERE); | 886 scheduler()->ScheduleLocalRefreshRequest(throttled_types, FROM_HERE); |
| 834 PumpLoop(); | 887 PumpLoop(); |
| 835 | 888 |
| 836 Mock::VerifyAndClearExpectations(syncer()); | 889 Mock::VerifyAndClearExpectations(syncer()); |
| 837 | 890 |
| 838 // Local nudges for non-throttled types will trigger a sync. | 891 // Local nudges for non-throttled types will trigger a sync. |
| 839 EXPECT_CALL(*syncer(), NormalSyncShare(_,_,_)) | 892 EXPECT_CALL(*syncer(), NormalSyncShare(_,_,_)) |
| 840 .WillRepeatedly(DoAll(Invoke(sessions::test_util::SimulateNormalSuccess), | 893 .WillRepeatedly(DoAll(Invoke(sessions::test_util::SimulateNormalSuccess), |
| 841 RecordSyncShare(×))); | 894 RecordSyncShare(×, true))); |
| 842 scheduler()->ScheduleLocalNudge(unthrottled_types, FROM_HERE); | 895 scheduler()->ScheduleLocalNudge(unthrottled_types, FROM_HERE); |
| 843 RunLoop(); | 896 RunLoop(); |
| 844 Mock::VerifyAndClearExpectations(syncer()); | 897 Mock::VerifyAndClearExpectations(syncer()); |
| 845 | 898 |
| 846 StopSyncScheduler(); | 899 StopSyncScheduler(); |
| 847 } | 900 } |
| 848 | 901 |
| 849 // Test nudges / polls don't run in config mode and config tasks do. | 902 // Test nudges / polls don't run in config mode and config tasks do. |
| 850 TEST_F(SyncSchedulerTest, ConfigurationMode) { | 903 TEST_F(SyncSchedulerTest, ConfigurationMode) { |
| 851 TimeDelta poll(TimeDelta::FromMilliseconds(15)); | 904 TimeDelta poll(TimeDelta::FromMilliseconds(15)); |
| 852 SyncShareTimes times; | 905 SyncShareTimes times; |
| 853 scheduler()->OnReceivedLongPollIntervalUpdate(poll); | 906 scheduler()->OnReceivedLongPollIntervalUpdate(poll); |
| 854 | 907 |
| 855 StartSyncScheduler(SyncScheduler::CONFIGURATION_MODE); | 908 StartSyncConfiguration(); |
| 856 | 909 |
| 857 const ModelTypeSet nudge_types(TYPED_URLS); | 910 const ModelTypeSet nudge_types(TYPED_URLS); |
| 858 scheduler()->ScheduleLocalNudge(nudge_types, FROM_HERE); | 911 scheduler()->ScheduleLocalNudge(nudge_types, FROM_HERE); |
| 859 scheduler()->ScheduleLocalNudge(nudge_types, FROM_HERE); | 912 scheduler()->ScheduleLocalNudge(nudge_types, FROM_HERE); |
| 860 | 913 |
| 861 const ModelTypeSet config_types(THEMES); | 914 const ModelTypeSet config_types(THEMES); |
| 862 | 915 |
| 863 EXPECT_CALL(*syncer(), ConfigureSyncShare(_,_,_)) | 916 EXPECT_CALL(*syncer(), ConfigureSyncShare(_,_,_)) |
| 864 .WillOnce(DoAll(Invoke(sessions::test_util::SimulateConfigureSuccess), | 917 .WillOnce(DoAll(Invoke(sessions::test_util::SimulateConfigureSuccess), |
| 865 RecordSyncShare(×))) | 918 RecordSyncShare(×, true))) |
| 866 .RetiresOnSaturation(); | 919 .RetiresOnSaturation(); |
| 867 CallbackCounter ready_counter; | 920 CallbackCounter ready_counter; |
| 868 CallbackCounter retry_counter; | 921 CallbackCounter retry_counter; |
| 869 ConfigurationParams params( | 922 ConfigurationParams params( |
| 870 GetUpdatesCallerInfo::RECONFIGURATION, | 923 GetUpdatesCallerInfo::RECONFIGURATION, |
| 871 config_types, | 924 config_types, |
| 872 TypesToRoutingInfo(config_types), | 925 TypesToRoutingInfo(config_types), |
| 873 base::Bind(&CallbackCounter::Callback, base::Unretained(&ready_counter)), | 926 base::Bind(&CallbackCounter::Callback, base::Unretained(&ready_counter)), |
| 874 base::Bind(&CallbackCounter::Callback, base::Unretained(&retry_counter))); | 927 base::Bind(&CallbackCounter::Callback, base::Unretained(&retry_counter))); |
| 875 scheduler()->ScheduleConfiguration(params); | 928 scheduler()->ScheduleConfiguration(params); |
| 876 RunLoop(); | 929 RunLoop(); |
| 877 ASSERT_EQ(1, ready_counter.times_called()); | 930 ASSERT_EQ(1, ready_counter.times_called()); |
| 878 ASSERT_EQ(0, retry_counter.times_called()); | 931 ASSERT_EQ(0, retry_counter.times_called()); |
| 879 | 932 |
| 880 Mock::VerifyAndClearExpectations(syncer()); | 933 Mock::VerifyAndClearExpectations(syncer()); |
| 881 | 934 |
| 882 // Switch to NORMAL_MODE to ensure NUDGES were properly saved and run. | 935 // Switch to NORMAL_MODE to ensure NUDGES were properly saved and run. |
| 883 scheduler()->OnReceivedLongPollIntervalUpdate(TimeDelta::FromDays(1)); | 936 scheduler()->OnReceivedLongPollIntervalUpdate(TimeDelta::FromDays(1)); |
| 884 SyncShareTimes times2; | 937 SyncShareTimes times2; |
| 885 EXPECT_CALL(*syncer(), NormalSyncShare(_,_,_)) | 938 EXPECT_CALL(*syncer(), NormalSyncShare(_,_,_)) |
| 886 .WillOnce(DoAll(Invoke(sessions::test_util::SimulateNormalSuccess), | 939 .WillOnce(DoAll(Invoke(sessions::test_util::SimulateNormalSuccess), |
| 887 RecordSyncShare(×2))); | 940 RecordSyncShare(×2, true))); |
| 888 | 941 |
| 889 // TODO(tim): Figure out how to remove this dangerous need to reset | 942 // TODO(tim): Figure out how to remove this dangerous need to reset |
| 890 // routing info between mode switches. | 943 // routing info between mode switches. |
| 891 context()->SetRoutingInfo(routing_info()); | 944 context()->SetRoutingInfo(routing_info()); |
| 892 StartSyncScheduler(SyncScheduler::NORMAL_MODE); | 945 StartSyncScheduler(base::Time()); |
| 893 | 946 |
| 894 RunLoop(); | 947 RunLoop(); |
| 895 Mock::VerifyAndClearExpectations(syncer()); | 948 Mock::VerifyAndClearExpectations(syncer()); |
| 896 } | 949 } |
| 897 | 950 |
| 898 class BackoffTriggersSyncSchedulerTest : public SyncSchedulerTest { | 951 class BackoffTriggersSyncSchedulerTest : public SyncSchedulerTest { |
| 899 void SetUp() override { | 952 void SetUp() override { |
| 900 SyncSchedulerTest::SetUp(); | 953 SyncSchedulerTest::SetUp(); |
| 901 UseMockDelayProvider(); | 954 UseMockDelayProvider(); |
| 902 EXPECT_CALL(*delay(), GetDelay(_)) | 955 EXPECT_CALL(*delay(), GetDelay(_)) |
| 903 .WillRepeatedly(Return(TimeDelta::FromMilliseconds(10))); | 956 .WillRepeatedly(Return(TimeDelta::FromMilliseconds(10))); |
| 904 } | 957 } |
| 905 | 958 |
| 906 void TearDown() override { | 959 void TearDown() override { |
| 907 StopSyncScheduler(); | 960 StopSyncScheduler(); |
| 908 SyncSchedulerTest::TearDown(); | 961 SyncSchedulerTest::TearDown(); |
| 909 } | 962 } |
| 910 }; | 963 }; |
| 911 | 964 |
| 912 // Have the sycner fail during commit. Expect that the scheduler enters | 965 // Have the syncer fail during commit. Expect that the scheduler enters |
| 913 // backoff. | 966 // backoff. |
| 914 TEST_F(BackoffTriggersSyncSchedulerTest, FailCommitOnce) { | 967 TEST_F(BackoffTriggersSyncSchedulerTest, FailCommitOnce) { |
| 915 EXPECT_CALL(*syncer(), NormalSyncShare(_,_,_)) | 968 EXPECT_CALL(*syncer(), NormalSyncShare(_,_,_)) |
| 916 .WillOnce(DoAll(Invoke(sessions::test_util::SimulateCommitFailed), | 969 .WillOnce(DoAll(Invoke(sessions::test_util::SimulateCommitFailed), |
| 917 QuitLoopNowAction())); | 970 QuitLoopNowAction(false))); |
| 918 EXPECT_TRUE(RunAndGetBackoff()); | 971 EXPECT_TRUE(RunAndGetBackoff()); |
| 919 } | 972 } |
| 920 | 973 |
| 921 // Have the syncer fail during download updates and succeed on the first | 974 // Have the syncer fail during download updates and succeed on the first |
| 922 // retry. Expect that this clears the backoff state. | 975 // retry. Expect that this clears the backoff state. |
| 923 TEST_F(BackoffTriggersSyncSchedulerTest, FailDownloadOnceThenSucceed) { | 976 TEST_F(BackoffTriggersSyncSchedulerTest, FailDownloadOnceThenSucceed) { |
| 924 EXPECT_CALL(*syncer(), NormalSyncShare(_,_,_)) | 977 EXPECT_CALL(*syncer(), NormalSyncShare(_,_,_)) |
| 925 .WillOnce(DoAll( | 978 .WillOnce(DoAll( |
| 926 Invoke(sessions::test_util::SimulateDownloadUpdatesFailed), | 979 Invoke(sessions::test_util::SimulateDownloadUpdatesFailed), |
| 927 Return(true))) | 980 Return(false))) |
| 928 .WillOnce(DoAll(Invoke(sessions::test_util::SimulateNormalSuccess), | 981 .WillOnce(DoAll(Invoke(sessions::test_util::SimulateNormalSuccess), |
| 929 QuitLoopNowAction())); | 982 QuitLoopNowAction(true))); |
| 930 EXPECT_FALSE(RunAndGetBackoff()); | 983 EXPECT_FALSE(RunAndGetBackoff()); |
| 931 } | 984 } |
| 932 | 985 |
| 933 // Have the syncer fail during commit and succeed on the first retry. Expect | 986 // Have the syncer fail during commit and succeed on the first retry. Expect |
| 934 // that this clears the backoff state. | 987 // that this clears the backoff state. |
| 935 TEST_F(BackoffTriggersSyncSchedulerTest, FailCommitOnceThenSucceed) { | 988 TEST_F(BackoffTriggersSyncSchedulerTest, FailCommitOnceThenSucceed) { |
| 936 EXPECT_CALL(*syncer(), NormalSyncShare(_,_,_)) | 989 EXPECT_CALL(*syncer(), NormalSyncShare(_,_,_)) |
| 937 .WillOnce(DoAll( | 990 .WillOnce(DoAll( |
| 938 Invoke(sessions::test_util::SimulateCommitFailed), | 991 Invoke(sessions::test_util::SimulateCommitFailed), |
| 939 Return(true))) | 992 Return(false))) |
| 940 .WillOnce(DoAll(Invoke(sessions::test_util::SimulateNormalSuccess), | 993 .WillOnce(DoAll(Invoke(sessions::test_util::SimulateNormalSuccess), |
| 941 QuitLoopNowAction())); | 994 QuitLoopNowAction(true))); |
| 942 EXPECT_FALSE(RunAndGetBackoff()); | 995 EXPECT_FALSE(RunAndGetBackoff()); |
| 943 } | 996 } |
| 944 | 997 |
| 945 // Have the syncer fail to download updates and fail again on the retry. | 998 // Have the syncer fail to download updates and fail again on the retry. |
| 946 // Expect this will leave the scheduler in backoff. | 999 // Expect this will leave the scheduler in backoff. |
| 947 TEST_F(BackoffTriggersSyncSchedulerTest, FailDownloadTwice) { | 1000 TEST_F(BackoffTriggersSyncSchedulerTest, FailDownloadTwice) { |
| 948 EXPECT_CALL(*syncer(), NormalSyncShare(_,_,_)) | 1001 EXPECT_CALL(*syncer(), NormalSyncShare(_,_,_)) |
| 949 .WillOnce(DoAll( | 1002 .WillOnce(DoAll( |
| 950 Invoke(sessions::test_util::SimulateDownloadUpdatesFailed), | 1003 Invoke(sessions::test_util::SimulateDownloadUpdatesFailed), |
| 951 Return(true))) | 1004 Return(false))) |
| 952 .WillRepeatedly(DoAll( | 1005 .WillRepeatedly(DoAll( |
| 953 Invoke(sessions::test_util::SimulateDownloadUpdatesFailed), | 1006 Invoke(sessions::test_util::SimulateDownloadUpdatesFailed), |
| 954 QuitLoopNowAction())); | 1007 QuitLoopNowAction(false))); |
| 955 EXPECT_TRUE(RunAndGetBackoff()); | 1008 EXPECT_TRUE(RunAndGetBackoff()); |
| 956 } | 1009 } |
| 957 | 1010 |
| 958 // Have the syncer fail to get the encryption key yet succeed in downloading | 1011 // Have the syncer fail to get the encryption key yet succeed in downloading |
| 959 // updates. Expect this will leave the scheduler in backoff. | 1012 // updates. Expect this will leave the scheduler in backoff. |
| 960 TEST_F(BackoffTriggersSyncSchedulerTest, FailGetEncryptionKey) { | 1013 TEST_F(BackoffTriggersSyncSchedulerTest, FailGetEncryptionKey) { |
| 961 EXPECT_CALL(*syncer(), ConfigureSyncShare(_,_,_)) | 1014 EXPECT_CALL(*syncer(), ConfigureSyncShare(_,_,_)) |
| 962 .WillOnce(DoAll( | 1015 .WillOnce(DoAll( |
| 963 Invoke(sessions::test_util::SimulateGetEncryptionKeyFailed), | 1016 Invoke(sessions::test_util::SimulateGetEncryptionKeyFailed), |
| 964 Return(true))) | 1017 Return(false))) |
| 965 .WillRepeatedly(DoAll( | 1018 .WillRepeatedly(DoAll( |
| 966 Invoke(sessions::test_util::SimulateGetEncryptionKeyFailed), | 1019 Invoke(sessions::test_util::SimulateGetEncryptionKeyFailed), |
| 967 QuitLoopNowAction())); | 1020 QuitLoopNowAction(false))); |
| 968 StartSyncScheduler(SyncScheduler::CONFIGURATION_MODE); | 1021 StartSyncConfiguration(); |
| 969 | 1022 |
| 970 ModelTypeSet types(THEMES); | 1023 ModelTypeSet types(THEMES); |
| 971 CallbackCounter ready_counter; | 1024 CallbackCounter ready_counter; |
| 972 CallbackCounter retry_counter; | 1025 CallbackCounter retry_counter; |
| 973 ConfigurationParams params( | 1026 ConfigurationParams params( |
| 974 GetUpdatesCallerInfo::RECONFIGURATION, | 1027 GetUpdatesCallerInfo::RECONFIGURATION, |
| 975 types, | 1028 types, |
| 976 TypesToRoutingInfo(types), | 1029 TypesToRoutingInfo(types), |
| 977 base::Bind(&CallbackCounter::Callback, base::Unretained(&ready_counter)), | 1030 base::Bind(&CallbackCounter::Callback, base::Unretained(&ready_counter)), |
| 978 base::Bind(&CallbackCounter::Callback, base::Unretained(&retry_counter))); | 1031 base::Bind(&CallbackCounter::Callback, base::Unretained(&retry_counter))); |
| 979 scheduler()->ScheduleConfiguration(params); | 1032 scheduler()->ScheduleConfiguration(params); |
| 980 RunLoop(); | 1033 RunLoop(); |
| 981 | 1034 |
| 982 EXPECT_TRUE(scheduler()->IsBackingOff()); | 1035 EXPECT_TRUE(scheduler()->IsBackingOff()); |
| 983 } | 1036 } |
| 984 | 1037 |
| 985 // Test that no polls or extraneous nudges occur when in backoff. | 1038 // Test that no polls or extraneous nudges occur when in backoff. |
| 986 TEST_F(SyncSchedulerTest, BackoffDropsJobs) { | 1039 TEST_F(SyncSchedulerTest, BackoffDropsJobs) { |
| 987 SyncShareTimes times; | 1040 SyncShareTimes times; |
| 988 TimeDelta poll(TimeDelta::FromMilliseconds(10)); | 1041 TimeDelta poll(TimeDelta::FromMilliseconds(10)); |
| 989 const ModelTypeSet types(THEMES); | 1042 const ModelTypeSet types(THEMES); |
| 990 scheduler()->OnReceivedLongPollIntervalUpdate(poll); | 1043 scheduler()->OnReceivedLongPollIntervalUpdate(poll); |
| 991 UseMockDelayProvider(); | 1044 UseMockDelayProvider(); |
| 992 | 1045 |
| 993 EXPECT_CALL(*syncer(), NormalSyncShare(_,_,_)) | 1046 EXPECT_CALL(*syncer(), NormalSyncShare(_,_,_)) |
| 994 .WillOnce(DoAll(Invoke(sessions::test_util::SimulateCommitFailed), | 1047 .WillOnce(DoAll(Invoke(sessions::test_util::SimulateCommitFailed), |
| 995 RecordSyncShareMultiple(×, 1U))); | 1048 RecordSyncShareMultiple(×, 1U, false))); |
| 996 EXPECT_CALL(*delay(), GetDelay(_)). | 1049 EXPECT_CALL(*delay(), GetDelay(_)). |
| 997 WillRepeatedly(Return(TimeDelta::FromDays(1))); | 1050 WillRepeatedly(Return(TimeDelta::FromDays(1))); |
| 998 | 1051 |
| 999 StartSyncScheduler(SyncScheduler::NORMAL_MODE); | 1052 StartSyncScheduler(base::Time()); |
| 1000 | 1053 |
| 1001 // This nudge should fail and put us into backoff. Thanks to our mock | 1054 // This nudge should fail and put us into backoff. Thanks to our mock |
| 1002 // GetDelay() setup above, this will be a long backoff. | 1055 // GetDelay() setup above, this will be a long backoff. |
| 1003 scheduler()->ScheduleLocalNudge(types, FROM_HERE); | 1056 scheduler()->ScheduleLocalNudge(types, FROM_HERE); |
| 1004 RunLoop(); | 1057 RunLoop(); |
| 1005 | 1058 |
| 1006 // From this point forward, no SyncShare functions should be invoked. | 1059 // From this point forward, no SyncShare functions should be invoked. |
| 1007 Mock::VerifyAndClearExpectations(syncer()); | 1060 Mock::VerifyAndClearExpectations(syncer()); |
| 1008 | 1061 |
| 1009 // Wait a while (10x poll interval) so a few poll jobs will be attempted. | 1062 // Wait a while (10x poll interval) so a few poll jobs will be attempted. |
| 1010 PumpLoopFor(poll * 10); | 1063 PumpLoopFor(poll * 10); |
| 1011 | 1064 |
| 1012 // Try (and fail) to schedule a nudge. | 1065 // Try (and fail) to schedule a nudge. |
| 1013 scheduler()->ScheduleLocalNudge(types, FROM_HERE); | 1066 scheduler()->ScheduleLocalNudge(types, FROM_HERE); |
| 1014 | 1067 |
| 1015 Mock::VerifyAndClearExpectations(syncer()); | 1068 Mock::VerifyAndClearExpectations(syncer()); |
| 1016 Mock::VerifyAndClearExpectations(delay()); | 1069 Mock::VerifyAndClearExpectations(delay()); |
| 1017 | 1070 |
| 1018 EXPECT_CALL(*delay(), GetDelay(_)).Times(0); | 1071 EXPECT_CALL(*delay(), GetDelay(_)).Times(0); |
| 1019 | 1072 |
| 1020 StartSyncScheduler(SyncScheduler::CONFIGURATION_MODE); | 1073 StartSyncConfiguration(); |
| 1021 | 1074 |
| 1022 CallbackCounter ready_counter; | 1075 CallbackCounter ready_counter; |
| 1023 CallbackCounter retry_counter; | 1076 CallbackCounter retry_counter; |
| 1024 ConfigurationParams params( | 1077 ConfigurationParams params( |
| 1025 GetUpdatesCallerInfo::RECONFIGURATION, | 1078 GetUpdatesCallerInfo::RECONFIGURATION, |
| 1026 types, | 1079 types, |
| 1027 TypesToRoutingInfo(types), | 1080 TypesToRoutingInfo(types), |
| 1028 base::Bind(&CallbackCounter::Callback, base::Unretained(&ready_counter)), | 1081 base::Bind(&CallbackCounter::Callback, base::Unretained(&ready_counter)), |
| 1029 base::Bind(&CallbackCounter::Callback, base::Unretained(&retry_counter))); | 1082 base::Bind(&CallbackCounter::Callback, base::Unretained(&retry_counter))); |
| 1030 scheduler()->ScheduleConfiguration(params); | 1083 scheduler()->ScheduleConfiguration(params); |
| 1031 PumpLoop(); | 1084 PumpLoop(); |
| 1032 ASSERT_EQ(0, ready_counter.times_called()); | 1085 ASSERT_EQ(0, ready_counter.times_called()); |
| 1033 ASSERT_EQ(1, retry_counter.times_called()); | 1086 ASSERT_EQ(1, retry_counter.times_called()); |
| 1034 | 1087 |
| 1035 } | 1088 } |
| 1036 | 1089 |
| 1037 // Test that backoff is shaping traffic properly with consecutive errors. | 1090 // Test that backoff is shaping traffic properly with consecutive errors. |
| 1038 TEST_F(SyncSchedulerTest, BackoffElevation) { | 1091 TEST_F(SyncSchedulerTest, BackoffElevation) { |
| 1039 SyncShareTimes times; | 1092 SyncShareTimes times; |
| 1040 UseMockDelayProvider(); | 1093 UseMockDelayProvider(); |
| 1041 | 1094 |
| 1042 EXPECT_CALL(*syncer(), NormalSyncShare(_,_,_)).Times(kMinNumSamples) | 1095 EXPECT_CALL(*syncer(), NormalSyncShare(_,_,_)).Times(kMinNumSamples) |
| 1043 .WillRepeatedly(DoAll(Invoke(sessions::test_util::SimulateCommitFailed), | 1096 .WillRepeatedly(DoAll(Invoke(sessions::test_util::SimulateCommitFailed), |
| 1044 RecordSyncShareMultiple(×, kMinNumSamples))); | 1097 RecordSyncShareMultiple(×, kMinNumSamples, false))); |
| 1045 | 1098 |
| 1046 const TimeDelta first = TimeDelta::FromSeconds(kInitialBackoffRetrySeconds); | 1099 const TimeDelta first = TimeDelta::FromSeconds(kInitialBackoffRetrySeconds); |
| 1047 const TimeDelta second = TimeDelta::FromMilliseconds(20); | 1100 const TimeDelta second = TimeDelta::FromMilliseconds(20); |
| 1048 const TimeDelta third = TimeDelta::FromMilliseconds(30); | 1101 const TimeDelta third = TimeDelta::FromMilliseconds(30); |
| 1049 const TimeDelta fourth = TimeDelta::FromMilliseconds(40); | 1102 const TimeDelta fourth = TimeDelta::FromMilliseconds(40); |
| 1050 const TimeDelta fifth = TimeDelta::FromMilliseconds(50); | 1103 const TimeDelta fifth = TimeDelta::FromMilliseconds(50); |
| 1051 const TimeDelta sixth = TimeDelta::FromDays(1); | 1104 const TimeDelta sixth = TimeDelta::FromDays(1); |
| 1052 | 1105 |
| 1053 EXPECT_CALL(*delay(), GetDelay(first)).WillOnce(Return(second)) | 1106 EXPECT_CALL(*delay(), GetDelay(first)).WillOnce(Return(second)) |
| 1054 .RetiresOnSaturation(); | 1107 .RetiresOnSaturation(); |
| 1055 EXPECT_CALL(*delay(), GetDelay(second)).WillOnce(Return(third)) | 1108 EXPECT_CALL(*delay(), GetDelay(second)).WillOnce(Return(third)) |
| 1056 .RetiresOnSaturation(); | 1109 .RetiresOnSaturation(); |
| 1057 EXPECT_CALL(*delay(), GetDelay(third)).WillOnce(Return(fourth)) | 1110 EXPECT_CALL(*delay(), GetDelay(third)).WillOnce(Return(fourth)) |
| 1058 .RetiresOnSaturation(); | 1111 .RetiresOnSaturation(); |
| 1059 EXPECT_CALL(*delay(), GetDelay(fourth)).WillOnce(Return(fifth)) | 1112 EXPECT_CALL(*delay(), GetDelay(fourth)).WillOnce(Return(fifth)) |
| 1060 .RetiresOnSaturation(); | 1113 .RetiresOnSaturation(); |
| 1061 EXPECT_CALL(*delay(), GetDelay(fifth)).WillOnce(Return(sixth)); | 1114 EXPECT_CALL(*delay(), GetDelay(fifth)).WillOnce(Return(sixth)); |
| 1062 | 1115 |
| 1063 StartSyncScheduler(SyncScheduler::NORMAL_MODE); | 1116 StartSyncScheduler(base::Time()); |
| 1064 | 1117 |
| 1065 // Run again with a nudge. | 1118 // Run again with a nudge. |
| 1066 scheduler()->ScheduleLocalNudge(ModelTypeSet(THEMES), FROM_HERE); | 1119 scheduler()->ScheduleLocalNudge(ModelTypeSet(THEMES), FROM_HERE); |
| 1067 RunLoop(); | 1120 RunLoop(); |
| 1068 | 1121 |
| 1069 ASSERT_EQ(kMinNumSamples, times.size()); | 1122 ASSERT_EQ(kMinNumSamples, times.size()); |
| 1070 EXPECT_GE(times[1] - times[0], second); | 1123 EXPECT_GE(times[1] - times[0], second); |
| 1071 EXPECT_GE(times[2] - times[1], third); | 1124 EXPECT_GE(times[2] - times[1], third); |
| 1072 EXPECT_GE(times[3] - times[2], fourth); | 1125 EXPECT_GE(times[3] - times[2], fourth); |
| 1073 EXPECT_GE(times[4] - times[3], fifth); | 1126 EXPECT_GE(times[4] - times[3], fifth); |
| 1074 } | 1127 } |
| 1075 | 1128 |
| 1076 // Test that things go back to normal once a retry makes forward progress. | 1129 // Test that things go back to normal once a retry makes forward progress. |
| 1077 TEST_F(SyncSchedulerTest, BackoffRelief) { | 1130 TEST_F(SyncSchedulerTest, BackoffRelief) { |
| 1078 SyncShareTimes times; | 1131 SyncShareTimes times; |
| 1079 const TimeDelta poll(TimeDelta::FromMilliseconds(10)); | |
| 1080 scheduler()->OnReceivedLongPollIntervalUpdate(poll); | |
| 1081 UseMockDelayProvider(); | 1132 UseMockDelayProvider(); |
| 1082 | 1133 |
| 1083 const TimeDelta backoff = TimeDelta::FromMilliseconds(10); | 1134 const TimeDelta backoff = TimeDelta::FromMilliseconds(10); |
| 1084 EXPECT_CALL(*delay(), GetDelay(_)).WillOnce(Return(backoff)); | 1135 EXPECT_CALL(*delay(), GetDelay(_)).WillOnce(Return(backoff)); |
| 1085 | 1136 |
| 1086 // Optimal start for the post-backoff poll party. | 1137 // Optimal start for the post-backoff poll party. |
| 1087 TimeTicks optimal_start = TimeTicks::Now(); | 1138 TimeTicks optimal_start = TimeTicks::Now(); |
| 1088 StartSyncScheduler(SyncScheduler::NORMAL_MODE); | 1139 StartSyncScheduler(base::Time()); |
| 1089 | 1140 |
| 1090 // Kick off the test with a failed nudge. | 1141 // Kick off the test with a failed nudge. |
| 1091 EXPECT_CALL(*syncer(), NormalSyncShare(_,_,_)) | 1142 EXPECT_CALL(*syncer(), NormalSyncShare(_,_,_)) |
| 1092 .WillOnce(DoAll(Invoke(sessions::test_util::SimulateCommitFailed), | 1143 .WillOnce(DoAll(Invoke(sessions::test_util::SimulateCommitFailed), |
| 1093 RecordSyncShare(×))); | 1144 RecordSyncShare(×, false))); |
| 1094 scheduler()->ScheduleLocalNudge(ModelTypeSet(THEMES), FROM_HERE); | 1145 scheduler()->ScheduleLocalNudge(ModelTypeSet(THEMES), FROM_HERE); |
| 1095 RunLoop(); | 1146 RunLoop(); |
| 1096 Mock::VerifyAndClearExpectations(syncer()); | 1147 Mock::VerifyAndClearExpectations(syncer()); |
| 1097 TimeTicks optimal_job_time = optimal_start; | 1148 TimeTicks optimal_job_time = optimal_start; |
| 1098 ASSERT_EQ(1U, times.size()); | 1149 ASSERT_EQ(1U, times.size()); |
| 1099 EXPECT_GE(times[0], optimal_job_time); | 1150 EXPECT_GE(times[0], optimal_job_time); |
| 1100 | 1151 |
| 1101 // The retry succeeds. | 1152 // The retry succeeds. |
| 1102 EXPECT_CALL(*syncer(), NormalSyncShare(_,_,_)) | 1153 EXPECT_CALL(*syncer(), NormalSyncShare(_,_,_)) |
| 1103 .WillOnce(DoAll( | 1154 .WillOnce(DoAll( |
| 1104 Invoke(sessions::test_util::SimulateNormalSuccess), | 1155 Invoke(sessions::test_util::SimulateNormalSuccess), |
| 1105 RecordSyncShare(×))); | 1156 RecordSyncShare(×, true))); |
| 1106 RunLoop(); | 1157 RunLoop(); |
| 1107 Mock::VerifyAndClearExpectations(syncer()); | 1158 Mock::VerifyAndClearExpectations(syncer()); |
| 1108 optimal_job_time = optimal_job_time + backoff; | 1159 optimal_job_time = optimal_job_time + backoff; |
| 1109 ASSERT_EQ(2U, times.size()); | 1160 ASSERT_EQ(2U, times.size()); |
| 1110 EXPECT_GE(times[1], optimal_job_time); | 1161 EXPECT_GE(times[1], optimal_job_time); |
| 1111 | 1162 |
| 1112 // Now let the Poll timer do its thing. | 1163 // Now let the Poll timer do its thing. |
| 1113 EXPECT_CALL(*syncer(), PollSyncShare(_,_)) | 1164 EXPECT_CALL(*syncer(), PollSyncShare(_,_)) |
| 1114 .WillRepeatedly(DoAll( | 1165 .WillRepeatedly(DoAll( |
| 1115 Invoke(sessions::test_util::SimulatePollSuccess), | 1166 Invoke(sessions::test_util::SimulatePollSuccess), |
| 1116 RecordSyncShareMultiple(×, kMinNumSamples))); | 1167 RecordSyncShareMultiple(×, kMinNumSamples, true))); |
| 1168 const TimeDelta poll(TimeDelta::FromMilliseconds(10)); |
| 1169 scheduler()->OnReceivedLongPollIntervalUpdate(poll); |
| 1170 |
| 1171 // The new optimal time is now, since the desired poll should have happened |
| 1172 // in the past. |
| 1173 optimal_job_time = base::TimeTicks::Now(); |
| 1117 RunLoop(); | 1174 RunLoop(); |
| 1118 Mock::VerifyAndClearExpectations(syncer()); | 1175 Mock::VerifyAndClearExpectations(syncer()); |
| 1119 ASSERT_EQ(kMinNumSamples, times.size()); | 1176 ASSERT_EQ(kMinNumSamples, times.size()); |
| 1120 for (size_t i = 2; i < times.size(); i++) { | 1177 for (size_t i = 2; i < times.size(); i++) { |
| 1121 optimal_job_time = optimal_job_time + poll; | |
| 1122 SCOPED_TRACE(testing::Message() << "SyncShare # (" << i << ")"); | 1178 SCOPED_TRACE(testing::Message() << "SyncShare # (" << i << ")"); |
| 1123 EXPECT_GE(times[i], optimal_job_time); | 1179 EXPECT_GE(times[i], optimal_job_time); |
| 1180 optimal_job_time = optimal_job_time + poll; |
| 1124 } | 1181 } |
| 1125 | 1182 |
| 1126 StopSyncScheduler(); | 1183 StopSyncScheduler(); |
| 1127 } | 1184 } |
| 1128 | 1185 |
| 1129 // Test that poll failures are ignored. They should have no effect on | 1186 // Test that poll failures are treated like any other failure. They should |
| 1130 // subsequent poll attempts, nor should they trigger a backoff/retry. | 1187 // result in retry with backoff. |
| 1131 TEST_F(SyncSchedulerTest, TransientPollFailure) { | 1188 TEST_F(SyncSchedulerTest, TransientPollFailure) { |
| 1132 SyncShareTimes times; | 1189 SyncShareTimes times; |
| 1133 const TimeDelta poll_interval(TimeDelta::FromMilliseconds(10)); | 1190 const TimeDelta poll_interval(TimeDelta::FromMilliseconds(10)); |
| 1134 scheduler()->OnReceivedLongPollIntervalUpdate(poll_interval); | 1191 scheduler()->OnReceivedLongPollIntervalUpdate(poll_interval); |
| 1135 UseMockDelayProvider(); // Will cause test failure if backoff is initiated. | 1192 UseMockDelayProvider(); // Will cause test failure if backoff is initiated. |
| 1193 EXPECT_CALL(*delay(), GetDelay(_)) |
| 1194 .WillRepeatedly(Return(TimeDelta::FromMilliseconds(0))); |
| 1136 | 1195 |
| 1137 EXPECT_CALL(*syncer(), PollSyncShare(_,_)) | 1196 EXPECT_CALL(*syncer(), PollSyncShare(_,_)) |
| 1138 .WillOnce(DoAll(Invoke(sessions::test_util::SimulatePollFailed), | 1197 .WillOnce(DoAll(Invoke(sessions::test_util::SimulatePollFailed), |
| 1139 RecordSyncShare(×))) | 1198 RecordSyncShare(×, false))) |
| 1140 .WillOnce(DoAll(Invoke(sessions::test_util::SimulatePollSuccess), | 1199 .WillOnce(DoAll(Invoke(sessions::test_util::SimulatePollSuccess), |
| 1141 RecordSyncShare(×))); | 1200 RecordSyncShare(×, true))); |
| 1142 | 1201 |
| 1143 StartSyncScheduler(SyncScheduler::NORMAL_MODE); | 1202 StartSyncScheduler(base::Time()); |
| 1144 | 1203 |
| 1145 // Run the unsucessful poll. The failed poll should not trigger backoff. | 1204 // Run the unsucessful poll. The failed poll should not trigger backoff. |
| 1146 RunLoop(); | 1205 RunLoop(); |
| 1147 EXPECT_FALSE(scheduler()->IsBackingOff()); | 1206 EXPECT_TRUE(scheduler()->IsBackingOff()); |
| 1148 | 1207 |
| 1149 // Run the successful poll. | 1208 // Run the successful poll. |
| 1150 RunLoop(); | 1209 RunLoop(); |
| 1151 EXPECT_FALSE(scheduler()->IsBackingOff()); | 1210 EXPECT_FALSE(scheduler()->IsBackingOff()); |
| 1152 } | 1211 } |
| 1153 | 1212 |
| 1154 // Test that starting the syncer thread without a valid connection doesn't | 1213 // Test that starting the syncer thread without a valid connection doesn't |
| 1155 // break things when a connection is detected. | 1214 // break things when a connection is detected. |
| 1156 TEST_F(SyncSchedulerTest, StartWhenNotConnected) { | 1215 TEST_F(SyncSchedulerTest, StartWhenNotConnected) { |
| 1157 connection()->SetServerNotReachable(); | 1216 connection()->SetServerNotReachable(); |
| 1158 connection()->UpdateConnectionStatus(); | 1217 connection()->UpdateConnectionStatus(); |
| 1159 EXPECT_CALL(*syncer(), NormalSyncShare(_,_,_)) | 1218 EXPECT_CALL(*syncer(), NormalSyncShare(_,_,_)) |
| 1160 .WillOnce(DoAll(Invoke(sessions::test_util::SimulateConnectionFailure), | 1219 .WillOnce(DoAll(Invoke(sessions::test_util::SimulateConnectionFailure), |
| 1161 Return(true))) | 1220 Return(false))) |
| 1162 .WillOnce(DoAll(Invoke(sessions::test_util::SimulateNormalSuccess), | 1221 .WillOnce(DoAll(Invoke(sessions::test_util::SimulateNormalSuccess), |
| 1163 Return(true))); | 1222 Return(true))); |
| 1164 StartSyncScheduler(SyncScheduler::NORMAL_MODE); | 1223 StartSyncScheduler(base::Time()); |
| 1165 | 1224 |
| 1166 scheduler()->ScheduleLocalNudge(ModelTypeSet(THEMES), FROM_HERE); | 1225 scheduler()->ScheduleLocalNudge(ModelTypeSet(THEMES), FROM_HERE); |
| 1167 // Should save the nudge for until after the server is reachable. | 1226 // Should save the nudge for until after the server is reachable. |
| 1168 base::RunLoop().RunUntilIdle(); | 1227 base::RunLoop().RunUntilIdle(); |
| 1169 | 1228 |
| 1170 scheduler()->OnConnectionStatusChange(); | 1229 scheduler()->OnConnectionStatusChange(); |
| 1171 connection()->SetServerReachable(); | 1230 connection()->SetServerReachable(); |
| 1172 connection()->UpdateConnectionStatus(); | 1231 connection()->UpdateConnectionStatus(); |
| 1173 base::RunLoop().RunUntilIdle(); | 1232 base::RunLoop().RunUntilIdle(); |
| 1174 } | 1233 } |
| 1175 | 1234 |
| 1176 TEST_F(SyncSchedulerTest, ServerConnectionChangeDuringBackoff) { | 1235 TEST_F(SyncSchedulerTest, ServerConnectionChangeDuringBackoff) { |
| 1177 UseMockDelayProvider(); | 1236 UseMockDelayProvider(); |
| 1178 EXPECT_CALL(*delay(), GetDelay(_)) | 1237 EXPECT_CALL(*delay(), GetDelay(_)) |
| 1179 .WillRepeatedly(Return(TimeDelta::FromMilliseconds(0))); | 1238 .WillRepeatedly(Return(TimeDelta::FromMilliseconds(0))); |
| 1180 | 1239 |
| 1181 StartSyncScheduler(SyncScheduler::NORMAL_MODE); | 1240 StartSyncScheduler(base::Time()); |
| 1182 connection()->SetServerNotReachable(); | 1241 connection()->SetServerNotReachable(); |
| 1183 connection()->UpdateConnectionStatus(); | 1242 connection()->UpdateConnectionStatus(); |
| 1184 | 1243 |
| 1185 EXPECT_CALL(*syncer(), NormalSyncShare(_,_,_)) | 1244 EXPECT_CALL(*syncer(), NormalSyncShare(_,_,_)) |
| 1186 .WillOnce(DoAll(Invoke(sessions::test_util::SimulateConnectionFailure), | 1245 .WillOnce(DoAll(Invoke(sessions::test_util::SimulateConnectionFailure), |
| 1187 Return(true))) | 1246 Return(false))) |
| 1188 .WillOnce(DoAll(Invoke(sessions::test_util::SimulateNormalSuccess), | 1247 .WillOnce(DoAll(Invoke(sessions::test_util::SimulateNormalSuccess), |
| 1189 Return(true))); | 1248 Return(true))); |
| 1190 | 1249 |
| 1191 scheduler()->ScheduleLocalNudge(ModelTypeSet(THEMES), FROM_HERE); | 1250 scheduler()->ScheduleLocalNudge(ModelTypeSet(THEMES), FROM_HERE); |
| 1192 PumpLoop(); // To get PerformDelayedNudge called. | 1251 PumpLoop(); // To get PerformDelayedNudge called. |
| 1193 PumpLoop(); // Run the nudge, that will fail and schedule a quick retry. | 1252 PumpLoop(); // Run the nudge, that will fail and schedule a quick retry. |
| 1194 ASSERT_TRUE(scheduler()->IsBackingOff()); | 1253 ASSERT_TRUE(scheduler()->IsBackingOff()); |
| 1195 | 1254 |
| 1196 // Before we run the scheduled canary, trigger a server connection change. | 1255 // Before we run the scheduled canary, trigger a server connection change. |
| 1197 scheduler()->OnConnectionStatusChange(); | 1256 scheduler()->OnConnectionStatusChange(); |
| 1198 connection()->SetServerReachable(); | 1257 connection()->SetServerReachable(); |
| 1199 connection()->UpdateConnectionStatus(); | 1258 connection()->UpdateConnectionStatus(); |
| 1200 base::RunLoop().RunUntilIdle(); | 1259 base::RunLoop().RunUntilIdle(); |
| 1201 } | 1260 } |
| 1202 | 1261 |
| 1203 // This was supposed to test the scenario where we receive a nudge while a | 1262 // This was supposed to test the scenario where we receive a nudge while a |
| 1204 // connection change canary is scheduled, but has not run yet. Since we've made | 1263 // connection change canary is scheduled, but has not run yet. Since we've made |
| 1205 // the connection change canary synchronous, this is no longer possible. | 1264 // the connection change canary synchronous, this is no longer possible. |
| 1206 TEST_F(SyncSchedulerTest, ConnectionChangeCanaryPreemptedByNudge) { | 1265 TEST_F(SyncSchedulerTest, ConnectionChangeCanaryPreemptedByNudge) { |
| 1207 UseMockDelayProvider(); | 1266 UseMockDelayProvider(); |
| 1208 EXPECT_CALL(*delay(), GetDelay(_)) | 1267 EXPECT_CALL(*delay(), GetDelay(_)) |
| 1209 .WillRepeatedly(Return(TimeDelta::FromMilliseconds(0))); | 1268 .WillRepeatedly(Return(TimeDelta::FromMilliseconds(0))); |
| 1210 | 1269 |
| 1211 StartSyncScheduler(SyncScheduler::NORMAL_MODE); | 1270 StartSyncScheduler(base::Time()); |
| 1212 connection()->SetServerNotReachable(); | 1271 connection()->SetServerNotReachable(); |
| 1213 connection()->UpdateConnectionStatus(); | 1272 connection()->UpdateConnectionStatus(); |
| 1214 | 1273 |
| 1215 EXPECT_CALL(*syncer(), NormalSyncShare(_,_,_)) | 1274 EXPECT_CALL(*syncer(), NormalSyncShare(_,_,_)) |
| 1216 .WillOnce(DoAll(Invoke(sessions::test_util::SimulateConnectionFailure), | 1275 .WillOnce(DoAll(Invoke(sessions::test_util::SimulateConnectionFailure), |
| 1217 Return(true))) | 1276 Return(false))) |
| 1218 .WillOnce(DoAll(Invoke(sessions::test_util::SimulateNormalSuccess), | 1277 .WillOnce(DoAll(Invoke(sessions::test_util::SimulateNormalSuccess), |
| 1219 Return(true))) | 1278 Return(true))) |
| 1220 .WillOnce(DoAll(Invoke(sessions::test_util::SimulateNormalSuccess), | 1279 .WillOnce(DoAll(Invoke(sessions::test_util::SimulateNormalSuccess), |
| 1221 QuitLoopNowAction())); | 1280 QuitLoopNowAction(true))); |
| 1222 | 1281 |
| 1223 scheduler()->ScheduleLocalNudge(ModelTypeSet(THEMES), FROM_HERE); | 1282 scheduler()->ScheduleLocalNudge(ModelTypeSet(THEMES), FROM_HERE); |
| 1224 | 1283 |
| 1225 PumpLoop(); // To get PerformDelayedNudge called. | 1284 PumpLoop(); // To get PerformDelayedNudge called. |
| 1226 PumpLoop(); // Run the nudge, that will fail and schedule a quick retry. | 1285 PumpLoop(); // Run the nudge, that will fail and schedule a quick retry. |
| 1227 ASSERT_TRUE(scheduler()->IsBackingOff()); | 1286 ASSERT_TRUE(scheduler()->IsBackingOff()); |
| 1228 | 1287 |
| 1229 // Before we run the scheduled canary, trigger a server connection change. | 1288 // Before we run the scheduled canary, trigger a server connection change. |
| 1230 scheduler()->OnConnectionStatusChange(); | 1289 scheduler()->OnConnectionStatusChange(); |
| 1231 PumpLoop(); | 1290 PumpLoop(); |
| 1232 connection()->SetServerReachable(); | 1291 connection()->SetServerReachable(); |
| 1233 connection()->UpdateConnectionStatus(); | 1292 connection()->UpdateConnectionStatus(); |
| 1234 scheduler()->ScheduleLocalNudge(ModelTypeSet(THEMES), FROM_HERE); | 1293 scheduler()->ScheduleLocalNudge(ModelTypeSet(THEMES), FROM_HERE); |
| 1235 base::RunLoop().RunUntilIdle(); | 1294 base::RunLoop().RunUntilIdle(); |
| 1236 } | 1295 } |
| 1237 | 1296 |
| 1238 // Tests that we don't crash trying to run two canaries at once if we receive | 1297 // Tests that we don't crash trying to run two canaries at once if we receive |
| 1239 // extra connection status change notifications. See crbug.com/190085. | 1298 // extra connection status change notifications. See crbug.com/190085. |
| 1240 TEST_F(SyncSchedulerTest, DoubleCanaryInConfigure) { | 1299 TEST_F(SyncSchedulerTest, DoubleCanaryInConfigure) { |
| 1241 EXPECT_CALL(*syncer(), ConfigureSyncShare(_,_,_)) | 1300 EXPECT_CALL(*syncer(), ConfigureSyncShare(_,_,_)) |
| 1242 .WillRepeatedly(DoAll( | 1301 .WillRepeatedly(DoAll( |
| 1243 Invoke(sessions::test_util::SimulateConfigureConnectionFailure), | 1302 Invoke(sessions::test_util::SimulateConfigureConnectionFailure), |
| 1244 Return(true))); | 1303 Return(true))); |
| 1245 StartSyncScheduler(SyncScheduler::CONFIGURATION_MODE); | 1304 StartSyncConfiguration(); |
| 1246 connection()->SetServerNotReachable(); | 1305 connection()->SetServerNotReachable(); |
| 1247 connection()->UpdateConnectionStatus(); | 1306 connection()->UpdateConnectionStatus(); |
| 1248 | 1307 |
| 1249 ModelTypeSet model_types(THEMES); | 1308 ModelTypeSet model_types(THEMES); |
| 1250 CallbackCounter ready_counter; | 1309 CallbackCounter ready_counter; |
| 1251 CallbackCounter retry_counter; | 1310 CallbackCounter retry_counter; |
| 1252 ConfigurationParams params( | 1311 ConfigurationParams params( |
| 1253 GetUpdatesCallerInfo::RECONFIGURATION, | 1312 GetUpdatesCallerInfo::RECONFIGURATION, |
| 1254 model_types, | 1313 model_types, |
| 1255 TypesToRoutingInfo(model_types), | 1314 TypesToRoutingInfo(model_types), |
| 1256 base::Bind(&CallbackCounter::Callback, base::Unretained(&ready_counter)), | 1315 base::Bind(&CallbackCounter::Callback, base::Unretained(&ready_counter)), |
| 1257 base::Bind(&CallbackCounter::Callback, base::Unretained(&retry_counter))); | 1316 base::Bind(&CallbackCounter::Callback, base::Unretained(&retry_counter))); |
| 1258 scheduler()->ScheduleConfiguration(params); | 1317 scheduler()->ScheduleConfiguration(params); |
| 1259 | 1318 |
| 1260 scheduler()->OnConnectionStatusChange(); | 1319 scheduler()->OnConnectionStatusChange(); |
| 1261 scheduler()->OnConnectionStatusChange(); | 1320 scheduler()->OnConnectionStatusChange(); |
| 1262 | 1321 |
| 1263 PumpLoop(); // Run the nudge, that will fail and schedule a quick retry. | 1322 PumpLoop(); // Run the nudge, that will fail and schedule a quick retry. |
| 1264 } | 1323 } |
| 1265 | 1324 |
| 1266 TEST_F(SyncSchedulerTest, PollFromCanaryAfterAuthError) { | 1325 TEST_F(SyncSchedulerTest, PollFromCanaryAfterAuthError) { |
| 1267 SyncShareTimes times; | 1326 SyncShareTimes times; |
| 1268 TimeDelta poll(TimeDelta::FromMilliseconds(15)); | 1327 TimeDelta poll(TimeDelta::FromMilliseconds(15)); |
| 1269 scheduler()->OnReceivedLongPollIntervalUpdate(poll); | 1328 scheduler()->OnReceivedLongPollIntervalUpdate(poll); |
| 1270 | 1329 |
| 1271 ::testing::InSequence seq; | 1330 ::testing::InSequence seq; |
| 1272 EXPECT_CALL(*syncer(), PollSyncShare(_,_)) | 1331 EXPECT_CALL(*syncer(), PollSyncShare(_,_)) |
| 1273 .WillRepeatedly( | 1332 .WillRepeatedly( |
| 1274 DoAll(Invoke(sessions::test_util::SimulatePollSuccess), | 1333 DoAll(Invoke(sessions::test_util::SimulatePollSuccess), |
| 1275 RecordSyncShareMultiple(×, kMinNumSamples))); | 1334 RecordSyncShareMultiple(×, kMinNumSamples, true))); |
| 1276 | 1335 |
| 1277 connection()->SetServerStatus(HttpResponse::SYNC_AUTH_ERROR); | 1336 connection()->SetServerStatus(HttpResponse::SYNC_AUTH_ERROR); |
| 1278 StartSyncScheduler(SyncScheduler::NORMAL_MODE); | 1337 StartSyncScheduler(base::Time()); |
| 1279 | 1338 |
| 1280 // Run to wait for polling. | 1339 // Run to wait for polling. |
| 1281 RunLoop(); | 1340 RunLoop(); |
| 1282 | 1341 |
| 1283 // Normally OnCredentialsUpdated calls TryCanaryJob that doesn't run Poll, | 1342 // Normally OnCredentialsUpdated calls TryCanaryJob that doesn't run Poll, |
| 1284 // but after poll finished with auth error from poll timer it should retry | 1343 // but after poll finished with auth error from poll timer it should retry |
| 1285 // poll once more | 1344 // poll once more |
| 1286 EXPECT_CALL(*syncer(), PollSyncShare(_,_)) | 1345 EXPECT_CALL(*syncer(), PollSyncShare(_,_)) |
| 1287 .WillOnce(DoAll(Invoke(sessions::test_util::SimulatePollSuccess), | 1346 .WillOnce(DoAll(Invoke(sessions::test_util::SimulatePollSuccess), |
| 1288 RecordSyncShare(×))); | 1347 RecordSyncShare(×, true))); |
| 1289 scheduler()->OnCredentialsUpdated(); | 1348 scheduler()->OnCredentialsUpdated(); |
| 1290 connection()->SetServerStatus(HttpResponse::SERVER_CONNECTION_OK); | 1349 connection()->SetServerStatus(HttpResponse::SERVER_CONNECTION_OK); |
| 1291 RunLoop(); | 1350 RunLoop(); |
| 1292 StopSyncScheduler(); | 1351 StopSyncScheduler(); |
| 1293 } | 1352 } |
| 1294 | 1353 |
| 1295 TEST_F(SyncSchedulerTest, SuccessfulRetry) { | 1354 TEST_F(SyncSchedulerTest, SuccessfulRetry) { |
| 1296 StartSyncScheduler(SyncScheduler::NORMAL_MODE); | 1355 StartSyncScheduler(base::Time()); |
| 1297 | 1356 |
| 1298 SyncShareTimes times; | 1357 SyncShareTimes times; |
| 1299 base::TimeDelta delay = base::TimeDelta::FromMilliseconds(10); | 1358 base::TimeDelta delay = base::TimeDelta::FromMilliseconds(10); |
| 1300 scheduler()->OnReceivedGuRetryDelay(delay); | 1359 scheduler()->OnReceivedGuRetryDelay(delay); |
| 1301 EXPECT_EQ(delay, GetRetryTimerDelay()); | 1360 EXPECT_EQ(delay, GetRetryTimerDelay()); |
| 1302 | 1361 |
| 1303 EXPECT_CALL(*syncer(), NormalSyncShare(_,_,_)) | 1362 EXPECT_CALL(*syncer(), NormalSyncShare(_,_,_)) |
| 1304 .WillOnce( | 1363 .WillOnce( |
| 1305 DoAll(Invoke(sessions::test_util::SimulateNormalSuccess), | 1364 DoAll(Invoke(sessions::test_util::SimulateNormalSuccess), |
| 1306 RecordSyncShare(×))); | 1365 RecordSyncShare(×, true))); |
| 1307 | 1366 |
| 1308 // Run to wait for retrying. | 1367 // Run to wait for retrying. |
| 1309 RunLoop(); | 1368 RunLoop(); |
| 1310 | 1369 |
| 1311 StopSyncScheduler(); | 1370 StopSyncScheduler(); |
| 1312 } | 1371 } |
| 1313 | 1372 |
| 1314 TEST_F(SyncSchedulerTest, FailedRetry) { | 1373 TEST_F(SyncSchedulerTest, FailedRetry) { |
| 1374 SyncShareTimes times; |
| 1375 |
| 1315 UseMockDelayProvider(); | 1376 UseMockDelayProvider(); |
| 1316 EXPECT_CALL(*delay(), GetDelay(_)) | 1377 EXPECT_CALL(*delay(), GetDelay(_)) |
| 1317 .WillRepeatedly(Return(TimeDelta::FromMilliseconds(10))); | 1378 .WillRepeatedly(Return(TimeDelta::FromMilliseconds(10))); |
| 1318 | 1379 |
| 1319 StartSyncScheduler(SyncScheduler::NORMAL_MODE); | 1380 StartSyncScheduler(base::Time()); |
| 1320 | 1381 |
| 1321 base::TimeDelta delay = base::TimeDelta::FromMilliseconds(10); | 1382 base::TimeDelta delay = base::TimeDelta::FromMilliseconds(10); |
| 1322 scheduler()->OnReceivedGuRetryDelay(delay); | 1383 scheduler()->OnReceivedGuRetryDelay(delay); |
| 1323 | 1384 |
| 1324 EXPECT_CALL(*syncer(), NormalSyncShare(_,_,_)) | 1385 EXPECT_CALL(*syncer(), NormalSyncShare(_,_,_)) |
| 1325 .WillOnce( | 1386 .WillOnce( |
| 1326 DoAll(Invoke(sessions::test_util::SimulateDownloadUpdatesFailed), | 1387 DoAll(Invoke(sessions::test_util::SimulateDownloadUpdatesFailed), |
| 1327 QuitLoopNowAction())); | 1388 RecordSyncShare(×, false))); |
| 1328 | 1389 |
| 1329 // Run to wait for retrying. | 1390 // Run to wait for retrying. |
| 1330 RunLoop(); | 1391 RunLoop(); |
| 1331 | 1392 |
| 1332 EXPECT_TRUE(scheduler()->IsBackingOff()); | 1393 EXPECT_TRUE(scheduler()->IsBackingOff()); |
| 1333 EXPECT_CALL(*syncer(), NormalSyncShare(_,_,_)) | 1394 EXPECT_CALL(*syncer(), NormalSyncShare(_,_,_)) |
| 1334 .WillOnce( | 1395 .WillOnce( |
| 1335 DoAll(Invoke(sessions::test_util::SimulateNormalSuccess), | 1396 DoAll(Invoke(sessions::test_util::SimulateNormalSuccess), |
| 1336 QuitLoopNowAction())); | 1397 RecordSyncShare(×, true))); |
| 1337 | 1398 |
| 1338 // Run to wait for second retrying. | 1399 // Run to wait for second retrying. |
| 1339 RunLoop(); | 1400 RunLoop(); |
| 1340 | 1401 |
| 1341 StopSyncScheduler(); | 1402 StopSyncScheduler(); |
| 1342 } | 1403 } |
| 1343 | 1404 |
| 1344 ACTION_P2(VerifyRetryTimerDelay, scheduler_test, expected_delay) { | 1405 ACTION_P2(VerifyRetryTimerDelay, scheduler_test, expected_delay) { |
| 1345 EXPECT_EQ(expected_delay, scheduler_test->GetRetryTimerDelay()); | 1406 EXPECT_EQ(expected_delay, scheduler_test->GetRetryTimerDelay()); |
| 1346 } | 1407 } |
| 1347 | 1408 |
| 1348 TEST_F(SyncSchedulerTest, ReceiveNewRetryDelay) { | 1409 TEST_F(SyncSchedulerTest, ReceiveNewRetryDelay) { |
| 1349 StartSyncScheduler(SyncScheduler::NORMAL_MODE); | 1410 StartSyncScheduler(base::Time()); |
| 1350 | 1411 |
| 1351 SyncShareTimes times; | 1412 SyncShareTimes times; |
| 1352 base::TimeDelta delay1 = base::TimeDelta::FromMilliseconds(100); | 1413 base::TimeDelta delay1 = base::TimeDelta::FromMilliseconds(100); |
| 1353 base::TimeDelta delay2 = base::TimeDelta::FromMilliseconds(200); | 1414 base::TimeDelta delay2 = base::TimeDelta::FromMilliseconds(200); |
| 1354 | 1415 |
| 1355 scheduler()->ScheduleLocalNudge(ModelTypeSet(THEMES), FROM_HERE); | 1416 scheduler()->ScheduleLocalNudge(ModelTypeSet(THEMES), FROM_HERE); |
| 1356 scheduler()->OnReceivedGuRetryDelay(delay1); | 1417 scheduler()->OnReceivedGuRetryDelay(delay1); |
| 1357 EXPECT_EQ(delay1, GetRetryTimerDelay()); | 1418 EXPECT_EQ(delay1, GetRetryTimerDelay()); |
| 1358 | 1419 |
| 1359 EXPECT_CALL(*syncer(), NormalSyncShare(_,_,_)) | 1420 EXPECT_CALL(*syncer(), NormalSyncShare(_,_,_)) |
| 1360 .WillOnce(DoAll( | 1421 .WillOnce(DoAll( |
| 1361 WithoutArgs(VerifyRetryTimerDelay(this, delay1)), | 1422 WithoutArgs(VerifyRetryTimerDelay(this, delay1)), |
| 1362 WithArg<2>(sessions::test_util::SimulateGuRetryDelayCommand(delay2)), | 1423 WithArg<2>(sessions::test_util::SimulateGuRetryDelayCommand(delay2)), |
| 1363 RecordSyncShare(×))); | 1424 RecordSyncShare(×, true))); |
| 1364 | 1425 |
| 1365 // Run nudge GU. | 1426 // Run nudge GU. |
| 1366 RunLoop(); | 1427 RunLoop(); |
| 1367 EXPECT_EQ(delay2, GetRetryTimerDelay()); | 1428 EXPECT_EQ(delay2, GetRetryTimerDelay()); |
| 1368 | 1429 |
| 1369 EXPECT_CALL(*syncer(), NormalSyncShare(_,_,_)) | 1430 EXPECT_CALL(*syncer(), NormalSyncShare(_,_,_)) |
| 1370 .WillOnce(DoAll(Invoke(sessions::test_util::SimulateNormalSuccess), | 1431 .WillOnce(DoAll(Invoke(sessions::test_util::SimulateNormalSuccess), |
| 1371 RecordSyncShare(×))); | 1432 RecordSyncShare(×, true))); |
| 1372 | 1433 |
| 1373 // Run to wait for retrying. | 1434 // Run to wait for retrying. |
| 1374 RunLoop(); | 1435 RunLoop(); |
| 1375 | 1436 |
| 1376 StopSyncScheduler(); | 1437 StopSyncScheduler(); |
| 1377 } | 1438 } |
| 1378 | 1439 |
| 1379 } // namespace syncer | 1440 } // namespace syncer |
| OLD | NEW |