syncer_thread_unittest.cc revision c407dc5cd9bdc5668497f21b26b09d988ab439de
1// Copyright (c) 2009 The Chromium Authors. All rights reserved. 2// Use of this source code is governed by a BSD-style license that can be 3// found in the LICENSE file. 4 5#include <list> 6#include <map> 7#include <set> 8 9#include "base/lock.h" 10#include "base/scoped_ptr.h" 11#include "base/time.h" 12#include "base/waitable_event.h" 13#include "chrome/browser/sync/engine/model_safe_worker.h" 14#include "chrome/browser/sync/engine/syncer_thread.h" 15#include "chrome/browser/sync/engine/syncer_types.h" 16#include "chrome/browser/sync/sessions/sync_session_context.h" 17#include "chrome/browser/sync/util/channel.h" 18#include "chrome/test/sync/engine/mock_connection_manager.h" 19#include "chrome/test/sync/engine/test_directory_setter_upper.h" 20#include "testing/gmock/include/gmock/gmock.h" 21#include "testing/gtest/include/gtest/gtest.h" 22 23using base::TimeTicks; 24using base::TimeDelta; 25using base::WaitableEvent; 26using testing::_; 27using testing::AnyNumber; 28using testing::Field; 29 30namespace browser_sync { 31using sessions::SyncSessionContext; 32 33typedef testing::Test SyncerThreadTest; 34typedef SyncerThread::WaitInterval WaitInterval; 35 36ACTION_P(SignalEvent, event) { 37 event->Signal(); 38} 39 40class ListenerMock : public ChannelEventHandler<SyncerEvent> { 41 public: 42 MOCK_METHOD1(HandleChannelEvent, void(const SyncerEvent&)); 43}; 44 45class SyncerThreadWithSyncerTest : public testing::Test, 46 public ModelSafeWorkerRegistrar, 47 public ChannelEventHandler<SyncerEvent> { 48 public: 49 SyncerThreadWithSyncerTest() 50 : max_wait_time_(TimeDelta::FromSeconds(10)), 51 sync_cycle_ended_event_(false, false) {} 52 virtual void SetUp() { 53 metadb_.SetUp(); 54 connection_.reset(new MockConnectionManager(metadb_.manager(), 55 metadb_.name())); 56 allstatus_.reset(new AllStatus()); 57 worker_ = new ModelSafeWorker(); 58 SyncSessionContext* context = new SyncSessionContext(connection_.get(), 59 NULL, metadb_.manager(), this); 60 syncer_thread_ = new SyncerThread(context, allstatus_.get()); 61 syncer_event_hookup_.reset( 62 syncer_thread_->relay_channel()->AddObserver(this)); 63 allstatus_->WatchSyncerThread(syncer_thread_); 64 syncer_thread_->SetConnected(true); 65 syncable::ModelTypeBitSet expected_types; 66 expected_types[syncable::BOOKMARKS] = true; 67 connection_->ExpectGetUpdatesRequestTypes(expected_types); 68 } 69 virtual void TearDown() { 70 syncer_event_hookup_.reset(); 71 allstatus_.reset(); 72 syncer_thread_ = NULL; 73 connection_.reset(); 74 metadb_.TearDown(); 75 } 76 77 // ModelSafeWorkerRegistrar implementation. 78 virtual void GetWorkers(std::vector<ModelSafeWorker*>* out) { 79 out->push_back(worker_.get()); 80 } 81 82 virtual void GetModelSafeRoutingInfo(ModelSafeRoutingInfo* out) { 83 // We're just testing the sync engine here, so we shunt everything to 84 // the SyncerThread. 85 (*out)[syncable::BOOKMARKS] = GROUP_PASSIVE; 86 } 87 88 ManuallyOpenedTestDirectorySetterUpper* metadb() { return &metadb_; } 89 MockConnectionManager* connection() { return connection_.get(); } 90 SyncerThread* syncer_thread() { return syncer_thread_; } 91 92 // Waits an indefinite amount of sync cycles for the syncer thread to become 93 // throttled. Only call this if a throttle is supposed to occur! 94 bool WaitForThrottle() { 95 int max_cycles = 5; 96 while (max_cycles && !syncer_thread()->IsSyncingCurrentlySilenced()) { 97 sync_cycle_ended_event_.TimedWait(max_wait_time_); 98 max_cycles--; 99 } 100 101 return syncer_thread()->IsSyncingCurrentlySilenced(); 102 } 103 104 void WaitForDisconnect() { 105 // Wait for the SyncerThread to detect loss of connection, up to a max of 106 // 10 seconds to timeout the test. 107 AutoLock lock(syncer_thread()->lock_); 108 TimeTicks start = TimeTicks::Now(); 109 TimeDelta ten_seconds = TimeDelta::FromSeconds(10); 110 while (syncer_thread()->vault_.connected_) { 111 syncer_thread()->vault_field_changed_.TimedWait(ten_seconds); 112 if (TimeTicks::Now() - start > ten_seconds) 113 break; 114 } 115 EXPECT_FALSE(syncer_thread()->vault_.connected_); 116 } 117 118 bool Pause(ListenerMock* listener) { 119 WaitableEvent event(false, false); 120 { 121 AutoLock lock(syncer_thread()->lock_); 122 EXPECT_CALL(*listener, HandleChannelEvent( 123 Field(&SyncerEvent::what_happened, SyncerEvent::PAUSED))). 124 WillOnce(SignalEvent(&event)); 125 } 126 if (!syncer_thread()->RequestPause()) 127 return false; 128 return event.TimedWait(max_wait_time_); 129 } 130 131 bool Resume(ListenerMock* listener) { 132 WaitableEvent event(false, false); 133 { 134 AutoLock lock(syncer_thread()->lock_); 135 EXPECT_CALL(*listener, HandleChannelEvent( 136 Field(&SyncerEvent::what_happened, SyncerEvent::RESUMED))). 137 WillOnce(SignalEvent(&event)); 138 } 139 if (!syncer_thread()->RequestResume()) 140 return false; 141 return event.TimedWait(max_wait_time_); 142 } 143 144 void PreventThreadFromPolling() { 145 const TimeDelta poll_interval = TimeDelta::FromMinutes(5); 146 syncer_thread()->SetSyncerShortPollInterval(poll_interval); 147 } 148 149 private: 150 151 void HandleChannelEvent(const SyncerEvent& event) { 152 if (event.what_happened == SyncerEvent::SYNC_CYCLE_ENDED) 153 sync_cycle_ended_event_.Signal(); 154 } 155 156 protected: 157 TimeDelta max_wait_time_; 158 159 private: 160 ManuallyOpenedTestDirectorySetterUpper metadb_; 161 scoped_ptr<MockConnectionManager> connection_; 162 scoped_ptr<AllStatus> allstatus_; 163 scoped_refptr<SyncerThread> syncer_thread_; 164 scoped_refptr<ModelSafeWorker> worker_; 165 scoped_ptr<ChannelHookup<SyncerEvent> > syncer_event_hookup_; 166 base::WaitableEvent sync_cycle_ended_event_; 167 DISALLOW_COPY_AND_ASSIGN(SyncerThreadWithSyncerTest); 168}; 169 170class SyncShareIntercept 171 : public MockConnectionManager::ResponseCodeOverrideRequestor, 172 public MockConnectionManager::MidCommitObserver { 173 public: 174 SyncShareIntercept() : sync_occured_(false, false), 175 allow_multiple_interceptions_(true) {} 176 virtual ~SyncShareIntercept() {} 177 virtual void Observe() { 178 if (!allow_multiple_interceptions_ && !times_sync_occured_.empty()) 179 FAIL() << "Multiple sync shares occured."; 180 times_sync_occured_.push_back(TimeTicks::Now()); 181 sync_occured_.Signal(); 182 } 183 184 // ResponseCodeOverrideRequestor implementation. This assumes any override 185 // requested is intended to silence the SyncerThread. 186 virtual void OnOverrideComplete() { 187 // We should not see any syncing. 188 allow_multiple_interceptions_ = false; 189 times_sync_occured_.clear(); 190 } 191 192 void WaitForSyncShare(int at_least_this_many, TimeDelta max_wait) { 193 while (at_least_this_many-- > 0) 194 sync_occured_.TimedWait(max_wait); 195 } 196 std::vector<TimeTicks> times_sync_occured() const { 197 return times_sync_occured_; 198 } 199 200 void Reset() { 201 allow_multiple_interceptions_ = true; 202 times_sync_occured_.clear(); 203 sync_occured_.Reset(); 204 } 205 private: 206 std::vector<TimeTicks> times_sync_occured_; 207 base::WaitableEvent sync_occured_; 208 bool allow_multiple_interceptions_; 209 DISALLOW_COPY_AND_ASSIGN(SyncShareIntercept); 210}; 211 212TEST_F(SyncerThreadTest, Construction) { 213 SyncSessionContext* context = new SyncSessionContext(NULL, NULL, NULL, NULL); 214 scoped_refptr<SyncerThread> syncer_thread(new SyncerThread(context, NULL)); 215} 216 217TEST_F(SyncerThreadTest, StartStop) { 218 SyncSessionContext* context = new SyncSessionContext(NULL, NULL, NULL, NULL); 219 scoped_refptr<SyncerThread> syncer_thread(new SyncerThread(context, NULL)); 220 EXPECT_TRUE(syncer_thread->Start()); 221 EXPECT_TRUE(syncer_thread->Stop(2000)); 222 223 // Do it again for good measure. I caught some bugs by adding this so 224 // I would recommend keeping it. 225 EXPECT_TRUE(syncer_thread->Start()); 226 EXPECT_TRUE(syncer_thread->Stop(2000)); 227} 228 229TEST_F(SyncerThreadTest, CalculateSyncWaitTime) { 230 SyncSessionContext* context = new SyncSessionContext(NULL, NULL, NULL, NULL); 231 scoped_refptr<SyncerThread> syncer_thread(new SyncerThread(context, NULL)); 232 syncer_thread->DisableIdleDetection(); 233 234 // Syncer_polling_interval_ is less than max poll interval. 235 TimeDelta syncer_polling_interval = TimeDelta::FromSeconds(1); 236 237 syncer_thread->SetSyncerPollingInterval(syncer_polling_interval); 238 239 // user_idle_ms is less than 10 * (syncer_polling_interval*1000). 240 ASSERT_EQ(syncer_polling_interval.InMilliseconds(), 241 syncer_thread->CalculateSyncWaitTime(1000, 0)); 242 ASSERT_EQ(syncer_polling_interval.InMilliseconds(), 243 syncer_thread->CalculateSyncWaitTime(1000, 1)); 244 245 // user_idle_ms is ge than 10 * (syncer_polling_interval*1000). 246 int last_poll_time = 2000; 247 ASSERT_TRUE(last_poll_time <= 248 syncer_thread->CalculateSyncWaitTime(last_poll_time, 10000)); 249 ASSERT_TRUE(last_poll_time * 3 >= 250 syncer_thread->CalculateSyncWaitTime(last_poll_time, 10000)); 251 ASSERT_TRUE(last_poll_time <= 252 syncer_thread->CalculateSyncWaitTime(last_poll_time, 100000)); 253 ASSERT_TRUE(last_poll_time * 3 >= 254 syncer_thread->CalculateSyncWaitTime(last_poll_time, 100000)); 255 256 // Maximum backoff time should be syncer_max_interval. 257 int near_threshold = SyncerThread::kDefaultMaxPollIntervalMs / 2 - 1; 258 int threshold = SyncerThread::kDefaultMaxPollIntervalMs; 259 int over_threshold = SyncerThread::kDefaultMaxPollIntervalMs + 1; 260 ASSERT_TRUE(near_threshold <= 261 syncer_thread->CalculateSyncWaitTime(near_threshold, 10000)); 262 ASSERT_TRUE(SyncerThread::kDefaultMaxPollIntervalMs >= 263 syncer_thread->CalculateSyncWaitTime(near_threshold, 10000)); 264 ASSERT_TRUE(SyncerThread::kDefaultMaxPollIntervalMs == 265 syncer_thread->CalculateSyncWaitTime(threshold, 10000)); 266 ASSERT_TRUE(SyncerThread::kDefaultMaxPollIntervalMs == 267 syncer_thread->CalculateSyncWaitTime(over_threshold, 10000)); 268 269 // Possible idle time must be capped by syncer_max_interval. 270 int over_sync_max_interval = 271 SyncerThread::kDefaultMaxPollIntervalMs + 1; 272 syncer_polling_interval = TimeDelta::FromSeconds( 273 over_sync_max_interval / 100); // so 1000* is right 274 syncer_thread->SetSyncerPollingInterval(syncer_polling_interval); 275 ASSERT_EQ(syncer_polling_interval.InSeconds() * 1000, 276 syncer_thread->CalculateSyncWaitTime(1000, over_sync_max_interval)); 277 syncer_polling_interval = TimeDelta::FromSeconds(1); 278 syncer_thread->SetSyncerPollingInterval(syncer_polling_interval); 279 ASSERT_TRUE(last_poll_time <= 280 syncer_thread->CalculateSyncWaitTime(last_poll_time, 281 over_sync_max_interval)); 282 ASSERT_TRUE(last_poll_time * 3 >= 283 syncer_thread->CalculateSyncWaitTime(last_poll_time, 284 over_sync_max_interval)); 285} 286 287TEST_F(SyncerThreadTest, CalculatePollingWaitTime) { 288 // Set up the environment. 289 int user_idle_milliseconds_param = 0; 290 SyncSessionContext* context = new SyncSessionContext(NULL, NULL, NULL, NULL); 291 scoped_refptr<SyncerThread> syncer_thread(new SyncerThread(context, NULL)); 292 syncer_thread->DisableIdleDetection(); 293 // Hold the lock to appease asserts in code. 294 AutoLock lock(syncer_thread->lock_); 295 296 // Notifications disabled should result in a polling interval of 297 // kDefaultShortPollInterval. 298 { 299 AllStatus::Status status = {}; 300 status.notifications_enabled = 0; 301 bool continue_sync_cycle_param = false; 302 303 // No work and no backoff. 304 WaitInterval interval = syncer_thread->CalculatePollingWaitTime( 305 status, 306 0, 307 &user_idle_milliseconds_param, 308 &continue_sync_cycle_param, 309 false); 310 311 ASSERT_EQ(SyncerThread::kDefaultShortPollIntervalSeconds, 312 interval.poll_delta.InSeconds()); 313 ASSERT_EQ(WaitInterval::NORMAL, interval.mode); 314 ASSERT_FALSE(interval.had_nudge_during_backoff); 315 ASSERT_FALSE(continue_sync_cycle_param); 316 317 // In this case the continue_sync_cycle is turned off. 318 continue_sync_cycle_param = true; 319 interval = syncer_thread->CalculatePollingWaitTime( 320 status, 321 0, 322 &user_idle_milliseconds_param, 323 &continue_sync_cycle_param, 324 false); 325 326 ASSERT_EQ(SyncerThread::kDefaultShortPollIntervalSeconds, 327 interval.poll_delta.InSeconds()); 328 ASSERT_EQ(WaitInterval::NORMAL, interval.mode); 329 ASSERT_FALSE(interval.had_nudge_during_backoff); 330 ASSERT_FALSE(continue_sync_cycle_param); 331 } 332 333 // Notifications enabled should result in a polling interval of 334 // SyncerThread::kDefaultLongPollIntervalSeconds. 335 { 336 AllStatus::Status status = {}; 337 status.notifications_enabled = 1; 338 bool continue_sync_cycle_param = false; 339 340 // No work and no backoff. 341 WaitInterval interval = syncer_thread->CalculatePollingWaitTime( 342 status, 343 0, 344 &user_idle_milliseconds_param, 345 &continue_sync_cycle_param, 346 false); 347 348 ASSERT_EQ(SyncerThread::kDefaultLongPollIntervalSeconds, 349 interval.poll_delta.InSeconds()); 350 ASSERT_EQ(WaitInterval::NORMAL, interval.mode); 351 ASSERT_FALSE(interval.had_nudge_during_backoff); 352 ASSERT_FALSE(continue_sync_cycle_param); 353 354 // In this case the continue_sync_cycle is turned off. 355 continue_sync_cycle_param = true; 356 interval = syncer_thread->CalculatePollingWaitTime( 357 status, 358 0, 359 &user_idle_milliseconds_param, 360 &continue_sync_cycle_param, 361 false); 362 363 ASSERT_EQ(SyncerThread::kDefaultLongPollIntervalSeconds, 364 interval.poll_delta.InSeconds()); 365 ASSERT_EQ(WaitInterval::NORMAL, interval.mode); 366 ASSERT_FALSE(interval.had_nudge_during_backoff); 367 ASSERT_FALSE(continue_sync_cycle_param); 368 } 369 370 // There are two states which can cause a continuation, either the updates 371 // available do not match the updates received, or the unsynced count is 372 // non-zero. 373 { 374 AllStatus::Status status = {}; 375 status.updates_available = 1; 376 status.updates_received = 0; 377 bool continue_sync_cycle_param = false; 378 379 WaitInterval interval = syncer_thread->CalculatePollingWaitTime( 380 status, 381 0, 382 &user_idle_milliseconds_param, 383 &continue_sync_cycle_param, 384 false); 385 386 ASSERT_LE(0, interval.poll_delta.InSeconds()); 387 ASSERT_EQ(WaitInterval::NORMAL, interval.mode); 388 ASSERT_FALSE(interval.had_nudge_during_backoff); 389 ASSERT_TRUE(continue_sync_cycle_param); 390 391 continue_sync_cycle_param = false; 392 interval = syncer_thread->CalculatePollingWaitTime( 393 status, 394 0, 395 &user_idle_milliseconds_param, 396 &continue_sync_cycle_param, 397 false); 398 399 ASSERT_GE(3, interval.poll_delta.InSeconds()); 400 ASSERT_EQ(WaitInterval::NORMAL, interval.mode); 401 ASSERT_FALSE(interval.had_nudge_during_backoff); 402 ASSERT_TRUE(continue_sync_cycle_param); 403 404 interval = syncer_thread->CalculatePollingWaitTime( 405 status, 406 0, 407 &user_idle_milliseconds_param, 408 &continue_sync_cycle_param, 409 false); 410 411 ASSERT_LE(0, interval.poll_delta.InSeconds()); 412 ASSERT_EQ(WaitInterval::EXPONENTIAL_BACKOFF, interval.mode); 413 ASSERT_FALSE(interval.had_nudge_during_backoff); 414 415 interval = syncer_thread->CalculatePollingWaitTime( 416 status, 417 0, 418 &user_idle_milliseconds_param, 419 &continue_sync_cycle_param, 420 false); 421 422 ASSERT_GE(2, interval.poll_delta.InSeconds()); 423 ASSERT_EQ(WaitInterval::EXPONENTIAL_BACKOFF, interval.mode); 424 ASSERT_FALSE(interval.had_nudge_during_backoff); 425 ASSERT_TRUE(continue_sync_cycle_param); 426 427 status.updates_received = 1; 428 interval = syncer_thread->CalculatePollingWaitTime( 429 status, 430 0, 431 &user_idle_milliseconds_param, 432 &continue_sync_cycle_param, 433 false); 434 435 ASSERT_EQ(SyncerThread::kDefaultShortPollIntervalSeconds, 436 interval.poll_delta.InSeconds()); 437 ASSERT_EQ(WaitInterval::NORMAL, interval.mode); 438 ASSERT_FALSE(interval.had_nudge_during_backoff); 439 ASSERT_FALSE(continue_sync_cycle_param); 440 } 441 442 { 443 AllStatus::Status status = {}; 444 status.unsynced_count = 1; 445 bool continue_sync_cycle_param = false; 446 447 WaitInterval interval = syncer_thread->CalculatePollingWaitTime( 448 status, 449 0, 450 &user_idle_milliseconds_param, 451 &continue_sync_cycle_param, 452 false); 453 454 ASSERT_LE(0, interval.poll_delta.InSeconds()); 455 ASSERT_EQ(WaitInterval::NORMAL, interval.mode); 456 ASSERT_FALSE(interval.had_nudge_during_backoff); 457 ASSERT_TRUE(continue_sync_cycle_param); 458 459 continue_sync_cycle_param = false; 460 interval = syncer_thread->CalculatePollingWaitTime( 461 status, 462 0, 463 &user_idle_milliseconds_param, 464 &continue_sync_cycle_param, 465 false); 466 467 ASSERT_GE(2, interval.poll_delta.InSeconds()); 468 ASSERT_EQ(WaitInterval::NORMAL, interval.mode); 469 ASSERT_FALSE(interval.had_nudge_during_backoff); 470 ASSERT_TRUE(continue_sync_cycle_param); 471 472 status.unsynced_count = 0; 473 interval = syncer_thread->CalculatePollingWaitTime( 474 status, 475 4, 476 &user_idle_milliseconds_param, 477 &continue_sync_cycle_param, 478 false); 479 480 ASSERT_EQ(SyncerThread::kDefaultShortPollIntervalSeconds, 481 interval.poll_delta.InSeconds()); 482 ASSERT_EQ(WaitInterval::NORMAL, interval.mode); 483 ASSERT_FALSE(interval.had_nudge_during_backoff); 484 ASSERT_FALSE(continue_sync_cycle_param); 485 } 486 487 // Regression for exponential backoff reset when the syncer is nudged. 488 { 489 AllStatus::Status status = {}; 490 status.unsynced_count = 1; 491 bool continue_sync_cycle_param = false; 492 493 // Expect move from default polling interval to exponential backoff due to 494 // unsynced_count != 0. 495 WaitInterval interval = syncer_thread->CalculatePollingWaitTime( 496 status, 497 3600, 498 &user_idle_milliseconds_param, 499 &continue_sync_cycle_param, 500 false); 501 502 ASSERT_LE(0, interval.poll_delta.InSeconds()); 503 ASSERT_EQ(WaitInterval::NORMAL, interval.mode); 504 ASSERT_FALSE(interval.had_nudge_during_backoff); 505 ASSERT_TRUE(continue_sync_cycle_param); 506 507 continue_sync_cycle_param = false; 508 interval = syncer_thread->CalculatePollingWaitTime( 509 status, 510 3600, 511 &user_idle_milliseconds_param, 512 &continue_sync_cycle_param, 513 false); 514 515 ASSERT_GE(2, interval.poll_delta.InSeconds()); 516 ASSERT_EQ(WaitInterval::NORMAL, interval.mode); 517 ASSERT_FALSE(interval.had_nudge_during_backoff); 518 ASSERT_TRUE(continue_sync_cycle_param); 519 520 // Expect exponential backoff. 521 interval = syncer_thread->CalculatePollingWaitTime( 522 status, 523 2, 524 &user_idle_milliseconds_param, 525 &continue_sync_cycle_param, 526 false); 527 528 ASSERT_LE(2, interval.poll_delta.InSeconds()); 529 ASSERT_EQ(WaitInterval::EXPONENTIAL_BACKOFF, interval.mode); 530 ASSERT_FALSE(interval.had_nudge_during_backoff); 531 ASSERT_TRUE(continue_sync_cycle_param); 532 533 interval = syncer_thread->CalculatePollingWaitTime( 534 status, 535 2, 536 &user_idle_milliseconds_param, 537 &continue_sync_cycle_param, 538 false); 539 540 ASSERT_GE(6, interval.poll_delta.InSeconds()); 541 ASSERT_EQ(WaitInterval::EXPONENTIAL_BACKOFF, interval.mode); 542 ASSERT_FALSE(interval.had_nudge_during_backoff); 543 ASSERT_TRUE(continue_sync_cycle_param); 544 545 syncer_thread->vault_.current_wait_interval_ = interval; 546 547 interval = syncer_thread->CalculatePollingWaitTime( 548 status, 549 static_cast<int>(interval.poll_delta.InSeconds()), 550 &user_idle_milliseconds_param, 551 &continue_sync_cycle_param, 552 true); 553 554 // Don't change poll on a failed nudge during backoff. 555 ASSERT_TRUE(syncer_thread->vault_.current_wait_interval_.poll_delta == 556 interval.poll_delta); 557 ASSERT_EQ(WaitInterval::EXPONENTIAL_BACKOFF, interval.mode); 558 ASSERT_TRUE(interval.had_nudge_during_backoff); 559 ASSERT_TRUE(continue_sync_cycle_param); 560 561 // If we got a nudge and we weren't in backoff mode, we see exponential 562 // backoff. 563 syncer_thread->vault_.current_wait_interval_.mode = WaitInterval::NORMAL; 564 interval = syncer_thread->CalculatePollingWaitTime( 565 status, 566 2, 567 &user_idle_milliseconds_param, 568 &continue_sync_cycle_param, 569 true); 570 571 // 5 and 3 are bounds on the backoff randomization formula given input of 2. 572 ASSERT_GE(5, interval.poll_delta.InSeconds()); 573 ASSERT_LE(3, interval.poll_delta.InSeconds()); 574 ASSERT_EQ(WaitInterval::EXPONENTIAL_BACKOFF, interval.mode); 575 ASSERT_FALSE(interval.had_nudge_during_backoff); 576 ASSERT_TRUE(continue_sync_cycle_param); 577 578 // And if another interval expires, we get a bigger backoff. 579 WaitInterval new_interval = syncer_thread->CalculatePollingWaitTime( 580 status, 581 static_cast<int>(interval.poll_delta.InSeconds()), 582 &user_idle_milliseconds_param, 583 &continue_sync_cycle_param, 584 false); 585 586 ASSERT_GE(12, new_interval.poll_delta.InSeconds()); 587 ASSERT_LE(5, new_interval.poll_delta.InSeconds()); 588 ASSERT_EQ(WaitInterval::EXPONENTIAL_BACKOFF, interval.mode); 589 ASSERT_FALSE(new_interval.had_nudge_during_backoff); 590 ASSERT_TRUE(continue_sync_cycle_param); 591 592 // A nudge resets the continue_sync_cycle_param value, so our backoff 593 // should return to the minimum. 594 continue_sync_cycle_param = false; 595 interval = syncer_thread->CalculatePollingWaitTime( 596 status, 597 3600, 598 &user_idle_milliseconds_param, 599 &continue_sync_cycle_param, 600 true); 601 602 ASSERT_LE(0, interval.poll_delta.InSeconds()); 603 ASSERT_EQ(WaitInterval::NORMAL, interval.mode); 604 ASSERT_FALSE(interval.had_nudge_during_backoff); 605 ASSERT_TRUE(continue_sync_cycle_param); 606 607 continue_sync_cycle_param = false; 608 interval = syncer_thread->CalculatePollingWaitTime( 609 status, 610 3600, 611 &user_idle_milliseconds_param, 612 &continue_sync_cycle_param, 613 true); 614 615 ASSERT_GE(2, interval.poll_delta.InSeconds()); 616 ASSERT_EQ(WaitInterval::NORMAL, interval.mode); 617 ASSERT_FALSE(interval.had_nudge_during_backoff); 618 ASSERT_TRUE(continue_sync_cycle_param); 619 620 // Setting unsynced_count = 0 returns us to the default polling interval. 621 status.unsynced_count = 0; 622 interval = syncer_thread->CalculatePollingWaitTime( 623 status, 624 4, 625 &user_idle_milliseconds_param, 626 &continue_sync_cycle_param, 627 true); 628 629 ASSERT_EQ(SyncerThread::kDefaultShortPollIntervalSeconds, 630 interval.poll_delta.InSeconds()); 631 ASSERT_EQ(WaitInterval::NORMAL, interval.mode); 632 ASSERT_FALSE(interval.had_nudge_during_backoff); 633 ASSERT_FALSE(continue_sync_cycle_param); 634 } 635} 636 637TEST_F(SyncerThreadWithSyncerTest, Polling) { 638 SyncShareIntercept interceptor; 639 connection()->SetMidCommitObserver(&interceptor); 640 641 const TimeDelta poll_interval = TimeDelta::FromSeconds(1); 642 syncer_thread()->SetSyncerShortPollInterval(poll_interval); 643 EXPECT_TRUE(syncer_thread()->Start()); 644 645 // Calling Open() should cause the SyncerThread to create a Syncer. 646 metadb()->Open(); 647 648 TimeDelta two_polls = poll_interval + poll_interval; 649 // We could theoretically return immediately from the wait if the interceptor 650 // was already signaled for a SyncShare (the first one comes quick). 651 interceptor.WaitForSyncShare(1, two_polls); 652 EXPECT_FALSE(interceptor.times_sync_occured().empty()); 653 654 // Wait for at least 2 more SyncShare operations. 655 interceptor.WaitForSyncShare(2, two_polls); 656 EXPECT_TRUE(syncer_thread()->Stop(2000)); 657 658 // Now analyze the run. 659 std::vector<TimeTicks> data = interceptor.times_sync_occured(); 660 661 EXPECT_GE(data.size(), static_cast<unsigned int>(3)); 662 for (unsigned int i = 0; i < data.size() - 1; i++) { 663 TimeTicks optimal_next_sync = data[i] + poll_interval; 664 EXPECT_TRUE(data[i + 1] >= optimal_next_sync); 665 // This should be reliable, as there are no blocking or I/O operations 666 // except the explicit 2 second wait, so if it takes longer than this 667 // there is a problem. 668 EXPECT_TRUE(data[i + 1] < optimal_next_sync + poll_interval); 669 } 670} 671 672TEST_F(SyncerThreadWithSyncerTest, Nudge) { 673 SyncShareIntercept interceptor; 674 connection()->SetMidCommitObserver(&interceptor); 675 // We don't want a poll to happen during this test (except the first one). 676 PreventThreadFromPolling(); 677 EXPECT_TRUE(syncer_thread()->Start()); 678 metadb()->Open(); 679 const TimeDelta poll_interval = TimeDelta::FromMinutes(5); 680 interceptor.WaitForSyncShare(1, poll_interval + poll_interval); 681 682 EXPECT_EQ(static_cast<unsigned int>(1), 683 interceptor.times_sync_occured().size()); 684 // The SyncerThread should be waiting for the poll now. Nudge it to sync 685 // immediately (5ms). 686 syncer_thread()->NudgeSyncer(5, SyncerThread::kUnknown); 687 interceptor.WaitForSyncShare(1, TimeDelta::FromSeconds(1)); 688 EXPECT_EQ(static_cast<unsigned int>(2), 689 interceptor.times_sync_occured().size()); 690 691 // SyncerThread should be waiting again. Signal it to stop. 692 EXPECT_TRUE(syncer_thread()->Stop(2000)); 693} 694 695TEST_F(SyncerThreadWithSyncerTest, Throttling) { 696 SyncShareIntercept interceptor; 697 connection()->SetMidCommitObserver(&interceptor); 698 const TimeDelta poll_interval = TimeDelta::FromMilliseconds(10); 699 syncer_thread()->SetSyncerShortPollInterval(poll_interval); 700 701 EXPECT_TRUE(syncer_thread()->Start()); 702 metadb()->Open(); 703 704 // Wait for some healthy syncing. 705 interceptor.WaitForSyncShare(4, poll_interval + poll_interval); 706 707 // Tell the server to throttle a single request, which should be all it takes 708 // to silence our syncer (for 2 hours, so we shouldn't hit that in this test). 709 // This will atomically visit the interceptor so it can switch to throttled 710 // mode and fail on multiple requests. 711 connection()->ThrottleNextRequest(&interceptor); 712 713 // Try to trigger a sync (we have a really short poll interval already). 714 syncer_thread()->NudgeSyncer(0, SyncerThread::kUnknown); 715 syncer_thread()->NudgeSyncer(0, SyncerThread::kUnknown); 716 717 // Wait until the syncer thread reports that it is throttled. Any further 718 // sync share interceptions will result in failure. If things are broken, 719 // we may never halt. 720 ASSERT_TRUE(WaitForThrottle()); 721 EXPECT_TRUE(syncer_thread()->IsSyncingCurrentlySilenced()); 722 723 EXPECT_TRUE(syncer_thread()->Stop(2000)); 724} 725 726TEST_F(SyncerThreadWithSyncerTest, StopSyncPermanently) { 727 // The SyncerThread should request an exit from the Syncer and set 728 // conditions for termination. 729 const TimeDelta poll_interval = TimeDelta::FromMilliseconds(10); 730 syncer_thread()->SetSyncerShortPollInterval(poll_interval); 731 732 ListenerMock listener; 733 WaitableEvent sync_cycle_ended_event(false, false); 734 WaitableEvent syncer_thread_exiting_event(false, false); 735 scoped_ptr<ChannelHookup<SyncerEvent> > hookup; 736 hookup.reset(syncer_thread()->relay_channel()->AddObserver(&listener)); 737 738 EXPECT_CALL(listener, HandleChannelEvent( 739 Field(&SyncerEvent::what_happened, SyncerEvent::STATUS_CHANGED))). 740 Times(AnyNumber()); 741 742 EXPECT_CALL(listener, HandleChannelEvent( 743 Field(&SyncerEvent::what_happened, SyncerEvent::SYNC_CYCLE_ENDED))). 744 Times(AnyNumber()). 745 WillOnce(SignalEvent(&sync_cycle_ended_event)); 746 747 EXPECT_CALL(listener, HandleChannelEvent( 748 Field(&SyncerEvent::what_happened, 749 SyncerEvent::STOP_SYNCING_PERMANENTLY))); 750 EXPECT_CALL(listener, HandleChannelEvent( 751 Field(&SyncerEvent::what_happened, SyncerEvent::SYNCER_THREAD_EXITING))). 752 WillOnce(SignalEvent(&syncer_thread_exiting_event)); 753 754 EXPECT_TRUE(syncer_thread()->Start()); 755 metadb()->Open(); 756 ASSERT_TRUE(sync_cycle_ended_event.TimedWait(max_wait_time_)); 757 758 connection()->set_store_birthday("NotYourLuckyDay"); 759 ASSERT_TRUE(syncer_thread_exiting_event.TimedWait(max_wait_time_)); 760 EXPECT_TRUE(syncer_thread()->Stop(0)); 761} 762 763TEST_F(SyncerThreadWithSyncerTest, AuthInvalid) { 764 SyncShareIntercept interceptor; 765 connection()->SetMidCommitObserver(&interceptor); 766 const TimeDelta poll_interval = TimeDelta::FromMilliseconds(1); 767 768 syncer_thread()->SetSyncerShortPollInterval(poll_interval); 769 EXPECT_TRUE(syncer_thread()->Start()); 770 metadb()->Open(); 771 772 // Wait for some healthy syncing. 773 interceptor.WaitForSyncShare(2, TimeDelta::FromSeconds(10)); 774 EXPECT_GE(interceptor.times_sync_occured().size(), 2U); 775 776 // Atomically start returning auth invalid and set the interceptor to fail 777 // on any sync. 778 connection()->FailWithAuthInvalid(&interceptor); 779 WaitForDisconnect(); 780 781 // Try to trigger a sync (the interceptor will assert if one occurs). 782 syncer_thread()->NudgeSyncer(0, SyncerThread::kUnknown); 783 syncer_thread()->NudgeSyncer(0, SyncerThread::kUnknown); 784 785 // Wait several poll intervals but don't expect any syncing besides the cycle 786 // that lost the connection. 787 interceptor.WaitForSyncShare(1, TimeDelta::FromSeconds(1)); 788 EXPECT_EQ(1U, interceptor.times_sync_occured().size()); 789 790 // Simulate a valid re-authentication and expect resumption of syncing. 791 interceptor.Reset(); 792 ASSERT_TRUE(interceptor.times_sync_occured().empty()); 793 connection()->StopFailingWithAuthInvalid(NULL); 794 ServerConnectionEvent e = {ServerConnectionEvent::STATUS_CHANGED, 795 HttpResponse::SERVER_CONNECTION_OK, 796 true}; 797 connection()->channel()->NotifyListeners(e); 798 799 interceptor.WaitForSyncShare(1, TimeDelta::FromSeconds(10)); 800 EXPECT_FALSE(interceptor.times_sync_occured().empty()); 801 802 EXPECT_TRUE(syncer_thread()->Stop(2000)); 803} 804 805// TODO(skrul): The "Pause" and "PauseWhenNotConnected" tests are 806// marked FLAKY because they sometimes fail on the Windows buildbots. 807// I have been unable to reproduce this hang after extensive testing 808// on a local Windows machine so these tests will remain flaky in 809// order to help diagnose the problem. 810TEST_F(SyncerThreadWithSyncerTest, FLAKY_Pause) { 811 WaitableEvent sync_cycle_ended_event(false, false); 812 WaitableEvent paused_event(false, false); 813 WaitableEvent resumed_event(false, false); 814 PreventThreadFromPolling(); 815 816 ListenerMock listener; 817 scoped_ptr<ChannelHookup<SyncerEvent> > hookup; 818 hookup.reset(syncer_thread()->relay_channel()->AddObserver(&listener)); 819 820 EXPECT_CALL(listener, HandleChannelEvent( 821 Field(&SyncerEvent::what_happened, SyncerEvent::STATUS_CHANGED))). 822 Times(AnyNumber()); 823 824 // Wait for the initial sync to complete. 825 EXPECT_CALL(listener, HandleChannelEvent( 826 Field(&SyncerEvent::what_happened, SyncerEvent::SYNC_CYCLE_ENDED))). 827 WillOnce(SignalEvent(&sync_cycle_ended_event)); 828 EXPECT_CALL(listener, HandleChannelEvent( 829 Field(&SyncerEvent::what_happened, SyncerEvent::SYNCER_THREAD_EXITING))); 830 ASSERT_TRUE(syncer_thread()->Start()); 831 metadb()->Open(); 832 ASSERT_TRUE(sync_cycle_ended_event.TimedWait(max_wait_time_)); 833 834 // Request a pause. 835 ASSERT_TRUE(Pause(&listener)); 836 837 // Resuming the pause. 838 ASSERT_TRUE(Resume(&listener)); 839 840 // Not paused, should fail. 841 EXPECT_FALSE(syncer_thread()->RequestResume()); 842 843 // Request a pause. 844 ASSERT_TRUE(Pause(&listener)); 845 846 // Nudge the syncer, this should do nothing while we are paused. 847 syncer_thread()->NudgeSyncer(0, SyncerThread::kUnknown); 848 849 // Resuming will cause the nudge to be processed and a sync cycle to run. 850 EXPECT_CALL(listener, HandleChannelEvent( 851 Field(&SyncerEvent::what_happened, SyncerEvent::SYNC_CYCLE_ENDED))). 852 WillOnce(SignalEvent(&sync_cycle_ended_event)); 853 ASSERT_TRUE(Resume(&listener)); 854 ASSERT_TRUE(sync_cycle_ended_event.TimedWait(max_wait_time_)); 855 856 EXPECT_TRUE(syncer_thread()->Stop(2000)); 857} 858 859TEST_F(SyncerThreadWithSyncerTest, StartWhenNotConnected) { 860 WaitableEvent sync_cycle_ended_event(false, false); 861 WaitableEvent event(false, false); 862 ListenerMock listener; 863 scoped_ptr<ChannelHookup<SyncerEvent> > hookup; 864 hookup.reset(syncer_thread()->relay_channel()->AddObserver(&listener)); 865 PreventThreadFromPolling(); 866 867 EXPECT_CALL(listener, HandleChannelEvent( 868 Field(&SyncerEvent::what_happened, SyncerEvent::STATUS_CHANGED))). 869 Times(AnyNumber()); 870 EXPECT_CALL(listener, HandleChannelEvent( 871 Field(&SyncerEvent::what_happened, SyncerEvent::SYNCER_THREAD_EXITING))); 872 873 connection()->SetServerNotReachable(); 874 metadb()->Open(); 875 876 // Syncer thread will always go through once cycle at the start, 877 // then it will wait for a connection. 878 EXPECT_CALL(listener, HandleChannelEvent( 879 Field(&SyncerEvent::what_happened, SyncerEvent::SYNC_CYCLE_ENDED))). 880 WillOnce(SignalEvent(&sync_cycle_ended_event)); 881 EXPECT_CALL(listener, HandleChannelEvent( 882 Field(&SyncerEvent::what_happened, SyncerEvent::WAITING_FOR_CONNECTION))). 883 WillOnce(SignalEvent(&event)); 884 ASSERT_TRUE(syncer_thread()->Start()); 885 ASSERT_TRUE(sync_cycle_ended_event.TimedWait(max_wait_time_)); 886 ASSERT_TRUE(event.TimedWait(max_wait_time_)); 887 888 // Connect, will put the syncer thread into its usually poll wait. 889 EXPECT_CALL(listener, HandleChannelEvent( 890 Field(&SyncerEvent::what_happened, SyncerEvent::CONNECTED))). 891 WillOnce(SignalEvent(&event)); 892 connection()->SetServerReachable(); 893 ASSERT_TRUE(event.TimedWait(max_wait_time_)); 894 895 // Nudge the syncer to complete a cycle. 896 EXPECT_CALL(listener, HandleChannelEvent( 897 Field(&SyncerEvent::what_happened, SyncerEvent::SYNC_CYCLE_ENDED))). 898 WillOnce(SignalEvent(&sync_cycle_ended_event)); 899 syncer_thread()->NudgeSyncer(0, SyncerThread::kUnknown); 900 ASSERT_TRUE(sync_cycle_ended_event.TimedWait(max_wait_time_)); 901 902 EXPECT_TRUE(syncer_thread()->Stop(2000)); 903} 904 905// TODO(skrul): See TODO comment on the "Pause" test above for an 906// explanation of the usage of FLAKY here. 907// TODO(pinkerton): disabled due to hanging on test bots http://crbug.com/39070 908TEST_F(SyncerThreadWithSyncerTest, DISABLED_PauseWhenNotConnected) { 909 WaitableEvent sync_cycle_ended_event(false, false); 910 WaitableEvent event(false, false); 911 ListenerMock listener; 912 scoped_ptr<ChannelHookup<SyncerEvent> > hookup; 913 hookup.reset(syncer_thread()->relay_channel()->AddObserver(&listener)); 914 PreventThreadFromPolling(); 915 916 EXPECT_CALL(listener, HandleChannelEvent( 917 Field(&SyncerEvent::what_happened, SyncerEvent::STATUS_CHANGED))). 918 Times(AnyNumber()); 919 920 // Put the thread into a "waiting for connection" state. 921 connection()->SetServerNotReachable(); 922 EXPECT_CALL(listener, HandleChannelEvent( 923 Field(&SyncerEvent::what_happened, SyncerEvent::SYNC_CYCLE_ENDED))). 924 WillOnce(SignalEvent(&sync_cycle_ended_event)); 925 EXPECT_CALL(listener, HandleChannelEvent( 926 Field(&SyncerEvent::what_happened, SyncerEvent::WAITING_FOR_CONNECTION))). 927 WillOnce(SignalEvent(&event)); 928 metadb()->Open(); 929 ASSERT_TRUE(syncer_thread()->Start()); 930 ASSERT_TRUE(sync_cycle_ended_event.TimedWait(max_wait_time_)); 931 ASSERT_TRUE(event.TimedWait(max_wait_time_)); 932 933 // Pause and resume the thread while waiting for a connection. 934 ASSERT_TRUE(Pause(&listener)); 935 ASSERT_TRUE(Resume(&listener)); 936 937 // Make a connection and let the syncer cycle. 938 EXPECT_CALL(listener, HandleChannelEvent( 939 Field(&SyncerEvent::what_happened, SyncerEvent::SYNC_CYCLE_ENDED))). 940 WillOnce(SignalEvent(&sync_cycle_ended_event)); 941 EXPECT_CALL(listener, HandleChannelEvent( 942 Field(&SyncerEvent::what_happened, SyncerEvent::CONNECTED))). 943 WillOnce(SignalEvent(&event)); 944 connection()->SetServerReachable(); 945 ASSERT_TRUE(event.TimedWait(max_wait_time_)); 946 syncer_thread()->NudgeSyncer(0, SyncerThread::kUnknown); 947 ASSERT_TRUE(sync_cycle_ended_event.TimedWait(max_wait_time_)); 948 949 // Disconnect and get into the waiting for a connection state. 950 EXPECT_CALL(listener, HandleChannelEvent( 951 Field(&SyncerEvent::what_happened, SyncerEvent::WAITING_FOR_CONNECTION))). 952 WillOnce(SignalEvent(&event)); 953 connection()->SetServerNotReachable(); 954 ASSERT_TRUE(event.TimedWait(max_wait_time_)); 955 956 // Pause so we can test getting a connection while paused. 957 ASSERT_TRUE(Pause(&listener)); 958 959 // Get a connection then resume. 960 EXPECT_CALL(listener, HandleChannelEvent( 961 Field(&SyncerEvent::what_happened, SyncerEvent::CONNECTED))). 962 WillOnce(SignalEvent(&event)); 963 connection()->SetServerReachable(); 964 ASSERT_TRUE(event.TimedWait(max_wait_time_)); 965 966 ASSERT_TRUE(Resume(&listener)); 967 968 // Cycle the syncer to show we are not longer paused. 969 EXPECT_CALL(listener, HandleChannelEvent( 970 Field(&SyncerEvent::what_happened, SyncerEvent::SYNC_CYCLE_ENDED))). 971 WillOnce(SignalEvent(&sync_cycle_ended_event)); 972 EXPECT_CALL(listener, HandleChannelEvent( 973 Field(&SyncerEvent::what_happened, SyncerEvent::SYNCER_THREAD_EXITING))); 974 975 syncer_thread()->NudgeSyncer(0, SyncerThread::kUnknown); 976 ASSERT_TRUE(sync_cycle_ended_event.TimedWait(max_wait_time_)); 977 978 EXPECT_TRUE(syncer_thread()->Stop(2000)); 979} 980 981TEST_F(SyncerThreadWithSyncerTest, PauseResumeWhenNotRunning) { 982 WaitableEvent sync_cycle_ended_event(false, false); 983 WaitableEvent event(false, false); 984 ListenerMock listener; 985 scoped_ptr<ChannelHookup<SyncerEvent> > hookup; 986 hookup.reset(syncer_thread()->relay_channel()->AddObserver(&listener)); 987 PreventThreadFromPolling(); 988 989 EXPECT_CALL(listener, HandleChannelEvent( 990 Field(&SyncerEvent::what_happened, SyncerEvent::STATUS_CHANGED))). 991 Times(AnyNumber()); 992 993 // Pause and resume the syncer while not running 994 ASSERT_TRUE(Pause(&listener)); 995 ASSERT_TRUE(Resume(&listener)); 996 997 // Pause the thread then start the syncer. 998 ASSERT_TRUE(Pause(&listener)); 999 metadb()->Open(); 1000 ASSERT_TRUE(syncer_thread()->Start()); 1001 1002 // Resume and let the syncer cycle. 1003 EXPECT_CALL(listener, HandleChannelEvent( 1004 Field(&SyncerEvent::what_happened, SyncerEvent::SYNC_CYCLE_ENDED))). 1005 WillOnce(SignalEvent(&sync_cycle_ended_event)); 1006 EXPECT_CALL(listener, HandleChannelEvent( 1007 Field(&SyncerEvent::what_happened, SyncerEvent::SYNCER_THREAD_EXITING))); 1008 1009 ASSERT_TRUE(Resume(&listener)); 1010 ASSERT_TRUE(sync_cycle_ended_event.TimedWait(max_wait_time_)); 1011 EXPECT_TRUE(syncer_thread()->Stop(2000)); 1012} 1013 1014} // namespace browser_sync 1015