| OLD | NEW |
| 1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2011 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 | |
| 5 #include <list> | |
| 6 #include <map> | |
| 7 | |
| 8 #include "base/memory/scoped_ptr.h" | |
| 9 #include "base/synchronization/lock.h" | |
| 10 #include "base/time.h" | |
| 11 #include "base/synchronization/waitable_event.h" | |
| 12 #include "chrome/browser/sync/engine/model_safe_worker.h" | |
| 13 #include "chrome/browser/sync/engine/syncer_thread.h" | |
| 14 #include "chrome/browser/sync/engine/syncer_types.h" | |
| 15 #include "chrome/browser/sync/sessions/sync_session_context.h" | |
| 16 #include "chrome/browser/sync/util/channel.h" | |
| 17 #include "chrome/test/sync/engine/mock_connection_manager.h" | |
| 18 #include "chrome/test/sync/engine/test_directory_setter_upper.h" | |
| 19 #include "chrome/test/sync/sessions/test_scoped_session_event_listener.h" | |
| 20 #include "testing/gmock/include/gmock/gmock.h" | |
| 21 #include "testing/gtest/include/gtest/gtest.h" | |
| 22 | |
| 23 using base::TimeTicks; | |
| 24 using base::TimeDelta; | |
| 25 using base::WaitableEvent; | |
| 26 using testing::_; | |
| 27 using testing::AnyNumber; | |
| 28 using testing::Field; | |
| 29 | |
| 30 namespace browser_sync { | |
| 31 using sessions::ErrorCounters; | |
| 32 using sessions::TestScopedSessionEventListener; | |
| 33 using sessions::SyncSessionContext; | |
| 34 using sessions::SyncSessionSnapshot; | |
| 35 using sessions::SyncerStatus; | |
| 36 | |
| 37 typedef testing::Test SyncerThreadTest; | |
| 38 typedef SyncerThread::WaitInterval WaitInterval; | |
| 39 | |
| 40 ACTION_P(SignalEvent, event) { | |
| 41 event->Signal(); | |
| 42 } | |
| 43 | |
| 44 SyncSessionSnapshot SessionSnapshotForTest( | |
| 45 int64 num_server_changes_remaining, | |
| 46 int64 unsynced_count) { | |
| 47 std::string download_progress_markers[syncable::MODEL_TYPE_COUNT]; | |
| 48 for (int i = syncable::FIRST_REAL_MODEL_TYPE; | |
| 49 i < syncable::MODEL_TYPE_COUNT; | |
| 50 ++i) { | |
| 51 syncable::ModelType type(syncable::ModelTypeFromInt(i)); | |
| 52 sync_pb::DataTypeProgressMarker token; | |
| 53 token.set_data_type_id( | |
| 54 syncable::GetExtensionFieldNumberFromModelType(type)); | |
| 55 token.set_token("foobar"); | |
| 56 token.SerializeToString(&download_progress_markers[i]); | |
| 57 } | |
| 58 return SyncSessionSnapshot(SyncerStatus(), ErrorCounters(), | |
| 59 num_server_changes_remaining, false, | |
| 60 syncable::ModelTypeBitSet(), download_progress_markers, | |
| 61 false, false, unsynced_count, 0, false, sessions::SyncSourceInfo()); | |
| 62 } | |
| 63 | |
| 64 class ListenerMock : public SyncEngineEventListener { | |
| 65 public: | |
| 66 MOCK_METHOD1(OnSyncEngineEvent, void(const SyncEngineEvent&)); | |
| 67 }; | |
| 68 | |
| 69 class SyncerThreadWithSyncerTest : public testing::Test, | |
| 70 public ModelSafeWorkerRegistrar, | |
| 71 public SyncEngineEventListener { | |
| 72 public: | |
| 73 SyncerThreadWithSyncerTest() | |
| 74 : max_wait_time_(TimeDelta::FromSeconds(10)), | |
| 75 sync_cycle_ended_event_(false, false) {} | |
| 76 virtual void SetUp() { | |
| 77 metadb_.SetUp(); | |
| 78 connection_.reset(new MockConnectionManager(metadb_.manager(), | |
| 79 metadb_.name())); | |
| 80 worker_ = new ModelSafeWorker(); | |
| 81 std::vector<SyncEngineEventListener*> listeners; | |
| 82 listeners.push_back(this); | |
| 83 context_ = new SyncSessionContext(connection_.get(), metadb_.manager(), | |
| 84 this, listeners); | |
| 85 context_->set_account_name(metadb_.name()); | |
| 86 syncer_thread_ = new SyncerThread(context_); | |
| 87 syncer_thread_->SetConnected(true); | |
| 88 syncable::ModelTypeBitSet expected_types; | |
| 89 expected_types[syncable::BOOKMARKS] = true; | |
| 90 connection_->ExpectGetUpdatesRequestTypes(expected_types); | |
| 91 } | |
| 92 virtual void TearDown() { | |
| 93 context_ = NULL; | |
| 94 syncer_thread_ = NULL; | |
| 95 connection_.reset(); | |
| 96 metadb_.TearDown(); | |
| 97 } | |
| 98 | |
| 99 // ModelSafeWorkerRegistrar implementation. | |
| 100 virtual void GetWorkers(std::vector<ModelSafeWorker*>* out) { | |
| 101 out->push_back(worker_.get()); | |
| 102 } | |
| 103 | |
| 104 virtual void GetModelSafeRoutingInfo(ModelSafeRoutingInfo* out) { | |
| 105 // We're just testing the sync engine here, so we shunt everything to | |
| 106 // the SyncerThread. | |
| 107 (*out)[syncable::BOOKMARKS] = GROUP_PASSIVE; | |
| 108 } | |
| 109 | |
| 110 ManuallyOpenedTestDirectorySetterUpper* metadb() { return &metadb_; } | |
| 111 MockConnectionManager* connection() { return connection_.get(); } | |
| 112 SyncerThread* syncer_thread() { return syncer_thread_; } | |
| 113 | |
| 114 // Waits an indefinite amount of sync cycles for the syncer thread to become | |
| 115 // throttled. Only call this if a throttle is supposed to occur! | |
| 116 bool WaitForThrottle() { | |
| 117 int max_cycles = 5; | |
| 118 while (max_cycles && !syncer_thread()->IsSyncingCurrentlySilenced()) { | |
| 119 sync_cycle_ended_event_.TimedWait(max_wait_time_); | |
| 120 max_cycles--; | |
| 121 } | |
| 122 | |
| 123 return syncer_thread()->IsSyncingCurrentlySilenced(); | |
| 124 } | |
| 125 | |
| 126 void WaitForDisconnect() { | |
| 127 // Wait for the SyncerThread to detect loss of connection, up to a max of | |
| 128 // 10 seconds to timeout the test. | |
| 129 base::AutoLock lock(syncer_thread()->lock_); | |
| 130 TimeTicks start = TimeTicks::Now(); | |
| 131 TimeDelta ten_seconds = TimeDelta::FromSeconds(10); | |
| 132 while (syncer_thread()->vault_.connected_) { | |
| 133 syncer_thread()->vault_field_changed_.TimedWait(ten_seconds); | |
| 134 if (TimeTicks::Now() - start > ten_seconds) | |
| 135 break; | |
| 136 } | |
| 137 EXPECT_FALSE(syncer_thread()->vault_.connected_); | |
| 138 } | |
| 139 | |
| 140 bool Pause(ListenerMock* listener) { | |
| 141 WaitableEvent event(false, false); | |
| 142 { | |
| 143 base::AutoLock lock(syncer_thread()->lock_); | |
| 144 EXPECT_CALL(*listener, OnSyncEngineEvent( | |
| 145 Field(&SyncEngineEvent::what_happened, | |
| 146 SyncEngineEvent::SYNCER_THREAD_PAUSED))). | |
| 147 WillOnce(SignalEvent(&event)); | |
| 148 } | |
| 149 if (!syncer_thread()->RequestPause()) | |
| 150 return false; | |
| 151 return event.TimedWait(max_wait_time_); | |
| 152 } | |
| 153 | |
| 154 bool Resume(ListenerMock* listener) { | |
| 155 WaitableEvent event(false, false); | |
| 156 { | |
| 157 base::AutoLock lock(syncer_thread()->lock_); | |
| 158 EXPECT_CALL(*listener, OnSyncEngineEvent( | |
| 159 Field(&SyncEngineEvent::what_happened, | |
| 160 SyncEngineEvent::SYNCER_THREAD_RESUMED))). | |
| 161 WillOnce(SignalEvent(&event)); | |
| 162 } | |
| 163 if (!syncer_thread()->RequestResume()) | |
| 164 return false; | |
| 165 return event.TimedWait(max_wait_time_); | |
| 166 } | |
| 167 | |
| 168 void PreventThreadFromPolling() { | |
| 169 const TimeDelta poll_interval = TimeDelta::FromMinutes(5); | |
| 170 syncer_thread()->SetSyncerShortPollInterval(poll_interval); | |
| 171 } | |
| 172 | |
| 173 // Compare a provided TypePayloadMap to the pending nudge info stored in the | |
| 174 // SyncerThread vault. | |
| 175 bool CompareNudgeTypesToVault(const syncable::ModelTypePayloadMap& lhs) { | |
| 176 const syncable::ModelTypePayloadMap& vault_nudge_types = | |
| 177 syncer_thread()->vault_.pending_nudge_types_; | |
| 178 return lhs == vault_nudge_types; | |
| 179 } | |
| 180 | |
| 181 // Compare a provided ModelTypeBitset to the pending nudge info stored in the | |
| 182 // SyncerThread vault. Nudge info in vault must not have any non-empty | |
| 183 // payloads. | |
| 184 bool CompareNudgeTypesBitSetToVault(const syncable::ModelTypeBitSet& lhs) { | |
| 185 syncable::ModelTypePayloadMap model_types_with_payloads = | |
| 186 syncable::ModelTypePayloadMapFromBitSet(lhs, std::string()); | |
| 187 size_t count = 0; | |
| 188 for (syncable::ModelTypePayloadMap::const_iterator i = | |
| 189 syncer_thread()->vault_.pending_nudge_types_.begin(); | |
| 190 i != syncer_thread()->vault_.pending_nudge_types_.end(); | |
| 191 ++i, ++count) { | |
| 192 if (!lhs.test(i->first)) | |
| 193 return false; | |
| 194 } | |
| 195 if (lhs.count() != count) | |
| 196 return false; | |
| 197 return true; | |
| 198 } | |
| 199 | |
| 200 | |
| 201 private: | |
| 202 | |
| 203 virtual void OnSyncEngineEvent(const SyncEngineEvent& event) { | |
| 204 if (event.what_happened == SyncEngineEvent::SYNC_CYCLE_ENDED) | |
| 205 sync_cycle_ended_event_.Signal(); | |
| 206 } | |
| 207 | |
| 208 protected: | |
| 209 TimeDelta max_wait_time_; | |
| 210 SyncSessionContext* context_; | |
| 211 | |
| 212 private: | |
| 213 ManuallyOpenedTestDirectorySetterUpper metadb_; | |
| 214 scoped_ptr<MockConnectionManager> connection_; | |
| 215 scoped_refptr<SyncerThread> syncer_thread_; | |
| 216 scoped_refptr<ModelSafeWorker> worker_; | |
| 217 base::WaitableEvent sync_cycle_ended_event_; | |
| 218 DISALLOW_COPY_AND_ASSIGN(SyncerThreadWithSyncerTest); | |
| 219 }; | |
| 220 | |
| 221 class SyncShareIntercept | |
| 222 : public MockConnectionManager::ResponseCodeOverrideRequestor, | |
| 223 public MockConnectionManager::MidCommitObserver { | |
| 224 public: | |
| 225 SyncShareIntercept() : sync_occured_(false, false), | |
| 226 allow_multiple_interceptions_(true) {} | |
| 227 virtual ~SyncShareIntercept() {} | |
| 228 virtual void Observe() { | |
| 229 if (!allow_multiple_interceptions_ && !times_sync_occured_.empty()) | |
| 230 FAIL() << "Multiple sync shares occured."; | |
| 231 times_sync_occured_.push_back(TimeTicks::Now()); | |
| 232 sync_occured_.Signal(); | |
| 233 } | |
| 234 | |
| 235 // ResponseCodeOverrideRequestor implementation. This assumes any override | |
| 236 // requested is intended to silence the SyncerThread. | |
| 237 virtual void OnOverrideComplete() { | |
| 238 // We should not see any syncing. | |
| 239 allow_multiple_interceptions_ = false; | |
| 240 times_sync_occured_.clear(); | |
| 241 } | |
| 242 | |
| 243 void WaitForSyncShare(int at_least_this_many, TimeDelta max_wait) { | |
| 244 while (at_least_this_many-- > 0) | |
| 245 sync_occured_.TimedWait(max_wait); | |
| 246 } | |
| 247 std::vector<TimeTicks> times_sync_occured() const { | |
| 248 return times_sync_occured_; | |
| 249 } | |
| 250 | |
| 251 void Reset() { | |
| 252 allow_multiple_interceptions_ = true; | |
| 253 times_sync_occured_.clear(); | |
| 254 sync_occured_.Reset(); | |
| 255 } | |
| 256 private: | |
| 257 std::vector<TimeTicks> times_sync_occured_; | |
| 258 base::WaitableEvent sync_occured_; | |
| 259 bool allow_multiple_interceptions_; | |
| 260 DISALLOW_COPY_AND_ASSIGN(SyncShareIntercept); | |
| 261 }; | |
| 262 | |
| 263 TEST_F(SyncerThreadTest, Construction) { | |
| 264 SyncSessionContext* context = new SyncSessionContext(NULL, NULL, NULL, | |
| 265 std::vector<SyncEngineEventListener*>()); | |
| 266 scoped_refptr<SyncerThread> syncer_thread(new SyncerThread(context)); | |
| 267 } | |
| 268 | |
| 269 TEST_F(SyncerThreadTest, StartStop) { | |
| 270 SyncSessionContext* context = new SyncSessionContext(NULL, NULL, NULL, | |
| 271 std::vector<SyncEngineEventListener*>()); | |
| 272 scoped_refptr<SyncerThread> syncer_thread(new SyncerThread(context)); | |
| 273 EXPECT_TRUE(syncer_thread->Start()); | |
| 274 EXPECT_TRUE(syncer_thread->Stop(2000)); | |
| 275 | |
| 276 // Do it again for good measure. I caught some bugs by adding this so | |
| 277 // I would recommend keeping it. | |
| 278 EXPECT_TRUE(syncer_thread->Start()); | |
| 279 EXPECT_TRUE(syncer_thread->Stop(2000)); | |
| 280 } | |
| 281 | |
| 282 TEST(SyncerThread, GetRecommendedDelay) { | |
| 283 EXPECT_LE(0, SyncerThread::GetRecommendedDelaySeconds(0)); | |
| 284 EXPECT_LE(1, SyncerThread::GetRecommendedDelaySeconds(1)); | |
| 285 EXPECT_LE(50, SyncerThread::GetRecommendedDelaySeconds(50)); | |
| 286 EXPECT_LE(10, SyncerThread::GetRecommendedDelaySeconds(10)); | |
| 287 EXPECT_EQ(SyncerThread::kMaxBackoffSeconds, | |
| 288 SyncerThread::GetRecommendedDelaySeconds( | |
| 289 SyncerThread::kMaxBackoffSeconds)); | |
| 290 EXPECT_EQ(SyncerThread::kMaxBackoffSeconds, | |
| 291 SyncerThread::GetRecommendedDelaySeconds( | |
| 292 SyncerThread::kMaxBackoffSeconds+1)); | |
| 293 } | |
| 294 | |
| 295 TEST_F(SyncerThreadTest, CalculateSyncWaitTime) { | |
| 296 SyncSessionContext* context = new SyncSessionContext(NULL, NULL, NULL, | |
| 297 std::vector<SyncEngineEventListener*>()); | |
| 298 scoped_refptr<SyncerThread> syncer_thread(new SyncerThread(context)); | |
| 299 syncer_thread->DisableIdleDetection(); | |
| 300 | |
| 301 // Syncer_polling_interval_ is less than max poll interval. | |
| 302 TimeDelta syncer_polling_interval = TimeDelta::FromSeconds(1); | |
| 303 | |
| 304 syncer_thread->SetSyncerPollingInterval(syncer_polling_interval); | |
| 305 | |
| 306 // user_idle_ms is less than 10 * (syncer_polling_interval*1000). | |
| 307 ASSERT_EQ(syncer_polling_interval.InMilliseconds(), | |
| 308 syncer_thread->CalculateSyncWaitTime(1000, 0)); | |
| 309 ASSERT_EQ(syncer_polling_interval.InMilliseconds(), | |
| 310 syncer_thread->CalculateSyncWaitTime(1000, 1)); | |
| 311 | |
| 312 // user_idle_ms is ge than 10 * (syncer_polling_interval*1000). | |
| 313 int last_poll_time = 2000; | |
| 314 ASSERT_TRUE(last_poll_time <= | |
| 315 syncer_thread->CalculateSyncWaitTime(last_poll_time, 10000)); | |
| 316 ASSERT_TRUE(last_poll_time * 3 >= | |
| 317 syncer_thread->CalculateSyncWaitTime(last_poll_time, 10000)); | |
| 318 ASSERT_TRUE(last_poll_time <= | |
| 319 syncer_thread->CalculateSyncWaitTime(last_poll_time, 100000)); | |
| 320 ASSERT_TRUE(last_poll_time * 3 >= | |
| 321 syncer_thread->CalculateSyncWaitTime(last_poll_time, 100000)); | |
| 322 | |
| 323 // Maximum backoff time should be syncer_max_interval. | |
| 324 int near_threshold = SyncerThread::kDefaultMaxPollIntervalMs / 2 - 1; | |
| 325 int threshold = SyncerThread::kDefaultMaxPollIntervalMs; | |
| 326 int over_threshold = SyncerThread::kDefaultMaxPollIntervalMs + 1; | |
| 327 ASSERT_TRUE(near_threshold <= | |
| 328 syncer_thread->CalculateSyncWaitTime(near_threshold, 10000)); | |
| 329 ASSERT_TRUE(SyncerThread::kDefaultMaxPollIntervalMs >= | |
| 330 syncer_thread->CalculateSyncWaitTime(near_threshold, 10000)); | |
| 331 ASSERT_TRUE(SyncerThread::kDefaultMaxPollIntervalMs == | |
| 332 syncer_thread->CalculateSyncWaitTime(threshold, 10000)); | |
| 333 ASSERT_TRUE(SyncerThread::kDefaultMaxPollIntervalMs == | |
| 334 syncer_thread->CalculateSyncWaitTime(over_threshold, 10000)); | |
| 335 | |
| 336 // Possible idle time must be capped by syncer_max_interval. | |
| 337 int over_sync_max_interval = | |
| 338 SyncerThread::kDefaultMaxPollIntervalMs + 1; | |
| 339 syncer_polling_interval = TimeDelta::FromSeconds( | |
| 340 over_sync_max_interval / 100); // so 1000* is right | |
| 341 syncer_thread->SetSyncerPollingInterval(syncer_polling_interval); | |
| 342 ASSERT_EQ(syncer_polling_interval.InSeconds() * 1000, | |
| 343 syncer_thread->CalculateSyncWaitTime(1000, over_sync_max_interval)); | |
| 344 syncer_polling_interval = TimeDelta::FromSeconds(1); | |
| 345 syncer_thread->SetSyncerPollingInterval(syncer_polling_interval); | |
| 346 ASSERT_TRUE(last_poll_time <= | |
| 347 syncer_thread->CalculateSyncWaitTime(last_poll_time, | |
| 348 over_sync_max_interval)); | |
| 349 ASSERT_TRUE(last_poll_time * 3 >= | |
| 350 syncer_thread->CalculateSyncWaitTime(last_poll_time, | |
| 351 over_sync_max_interval)); | |
| 352 } | |
| 353 | |
| 354 TEST_F(SyncerThreadTest, CalculatePollingWaitTime) { | |
| 355 // Set up the environment. | |
| 356 int user_idle_milliseconds_param = 0; | |
| 357 SyncSessionContext* context = new SyncSessionContext(NULL, NULL, NULL, | |
| 358 std::vector<SyncEngineEventListener*>()); | |
| 359 scoped_refptr<SyncerThread> syncer_thread(new SyncerThread(context)); | |
| 360 syncer_thread->DisableIdleDetection(); | |
| 361 // Hold the lock to appease asserts in code. | |
| 362 base::AutoLock lock(syncer_thread->lock_); | |
| 363 | |
| 364 // Notifications disabled should result in a polling interval of | |
| 365 // kDefaultShortPollInterval. | |
| 366 { | |
| 367 context->set_notifications_enabled(false); | |
| 368 bool continue_sync_cycle_param = false; | |
| 369 | |
| 370 // No work and no backoff. | |
| 371 WaitInterval interval = syncer_thread->CalculatePollingWaitTime( | |
| 372 0, | |
| 373 &user_idle_milliseconds_param, | |
| 374 &continue_sync_cycle_param, | |
| 375 false); | |
| 376 | |
| 377 ASSERT_EQ(SyncerThread::kDefaultShortPollIntervalSeconds, | |
| 378 interval.poll_delta.InSeconds()); | |
| 379 ASSERT_EQ(WaitInterval::NORMAL, interval.mode); | |
| 380 ASSERT_FALSE(interval.had_nudge_during_backoff); | |
| 381 ASSERT_FALSE(continue_sync_cycle_param); | |
| 382 | |
| 383 // In this case the continue_sync_cycle is turned off. | |
| 384 continue_sync_cycle_param = true; | |
| 385 interval = syncer_thread->CalculatePollingWaitTime( | |
| 386 0, | |
| 387 &user_idle_milliseconds_param, | |
| 388 &continue_sync_cycle_param, | |
| 389 false); | |
| 390 | |
| 391 ASSERT_EQ(SyncerThread::kDefaultShortPollIntervalSeconds, | |
| 392 interval.poll_delta.InSeconds()); | |
| 393 ASSERT_EQ(WaitInterval::NORMAL, interval.mode); | |
| 394 ASSERT_FALSE(interval.had_nudge_during_backoff); | |
| 395 ASSERT_FALSE(continue_sync_cycle_param); | |
| 396 } | |
| 397 | |
| 398 // Notifications enabled should result in a polling interval of | |
| 399 // SyncerThread::kDefaultLongPollIntervalSeconds. | |
| 400 { | |
| 401 context->set_notifications_enabled(true); | |
| 402 bool continue_sync_cycle_param = false; | |
| 403 | |
| 404 // No work and no backoff. | |
| 405 WaitInterval interval = syncer_thread->CalculatePollingWaitTime( | |
| 406 0, | |
| 407 &user_idle_milliseconds_param, | |
| 408 &continue_sync_cycle_param, | |
| 409 false); | |
| 410 | |
| 411 ASSERT_EQ(SyncerThread::kDefaultLongPollIntervalSeconds, | |
| 412 interval.poll_delta.InSeconds()); | |
| 413 ASSERT_EQ(WaitInterval::NORMAL, interval.mode); | |
| 414 ASSERT_FALSE(interval.had_nudge_during_backoff); | |
| 415 ASSERT_FALSE(continue_sync_cycle_param); | |
| 416 | |
| 417 // In this case the continue_sync_cycle is turned off. | |
| 418 continue_sync_cycle_param = true; | |
| 419 interval = syncer_thread->CalculatePollingWaitTime( | |
| 420 0, | |
| 421 &user_idle_milliseconds_param, | |
| 422 &continue_sync_cycle_param, | |
| 423 false); | |
| 424 | |
| 425 ASSERT_EQ(SyncerThread::kDefaultLongPollIntervalSeconds, | |
| 426 interval.poll_delta.InSeconds()); | |
| 427 ASSERT_EQ(WaitInterval::NORMAL, interval.mode); | |
| 428 ASSERT_FALSE(interval.had_nudge_during_backoff); | |
| 429 ASSERT_FALSE(continue_sync_cycle_param); | |
| 430 } | |
| 431 | |
| 432 // There are two states which can cause a continuation, either the updates | |
| 433 // available do not match the updates received, or the unsynced count is | |
| 434 // non-zero. | |
| 435 { | |
| 436 // More server changes remaining to download. | |
| 437 context->set_last_snapshot(SessionSnapshotForTest(1, 0)); | |
| 438 bool continue_sync_cycle_param = false; | |
| 439 | |
| 440 WaitInterval interval = syncer_thread->CalculatePollingWaitTime( | |
| 441 0, | |
| 442 &user_idle_milliseconds_param, | |
| 443 &continue_sync_cycle_param, | |
| 444 false); | |
| 445 | |
| 446 ASSERT_LE(0, interval.poll_delta.InSeconds()); | |
| 447 ASSERT_EQ(WaitInterval::NORMAL, interval.mode); | |
| 448 ASSERT_FALSE(interval.had_nudge_during_backoff); | |
| 449 ASSERT_TRUE(continue_sync_cycle_param); | |
| 450 | |
| 451 continue_sync_cycle_param = false; | |
| 452 interval = syncer_thread->CalculatePollingWaitTime( | |
| 453 0, | |
| 454 &user_idle_milliseconds_param, | |
| 455 &continue_sync_cycle_param, | |
| 456 false); | |
| 457 | |
| 458 ASSERT_GE(3, interval.poll_delta.InSeconds()); | |
| 459 ASSERT_EQ(WaitInterval::NORMAL, interval.mode); | |
| 460 ASSERT_FALSE(interval.had_nudge_during_backoff); | |
| 461 ASSERT_TRUE(continue_sync_cycle_param); | |
| 462 | |
| 463 interval = syncer_thread->CalculatePollingWaitTime( | |
| 464 0, | |
| 465 &user_idle_milliseconds_param, | |
| 466 &continue_sync_cycle_param, | |
| 467 false); | |
| 468 | |
| 469 ASSERT_LE(0, interval.poll_delta.InSeconds()); | |
| 470 ASSERT_EQ(WaitInterval::EXPONENTIAL_BACKOFF, interval.mode); | |
| 471 ASSERT_FALSE(interval.had_nudge_during_backoff); | |
| 472 | |
| 473 interval = syncer_thread->CalculatePollingWaitTime( | |
| 474 0, | |
| 475 &user_idle_milliseconds_param, | |
| 476 &continue_sync_cycle_param, | |
| 477 false); | |
| 478 | |
| 479 ASSERT_GE(2, interval.poll_delta.InSeconds()); | |
| 480 ASSERT_EQ(WaitInterval::EXPONENTIAL_BACKOFF, interval.mode); | |
| 481 ASSERT_FALSE(interval.had_nudge_during_backoff); | |
| 482 ASSERT_TRUE(continue_sync_cycle_param); | |
| 483 | |
| 484 // Now simulate no more server changes remaining. | |
| 485 context->set_last_snapshot(SessionSnapshotForTest(0, 0)); | |
| 486 interval = syncer_thread->CalculatePollingWaitTime( | |
| 487 0, | |
| 488 &user_idle_milliseconds_param, | |
| 489 &continue_sync_cycle_param, | |
| 490 false); | |
| 491 | |
| 492 ASSERT_EQ(SyncerThread::kDefaultLongPollIntervalSeconds, | |
| 493 interval.poll_delta.InSeconds()); | |
| 494 ASSERT_EQ(WaitInterval::NORMAL, interval.mode); | |
| 495 ASSERT_FALSE(interval.had_nudge_during_backoff); | |
| 496 ASSERT_FALSE(continue_sync_cycle_param); | |
| 497 } | |
| 498 | |
| 499 { | |
| 500 // Now try with unsynced local items. | |
| 501 context->set_last_snapshot(SessionSnapshotForTest(0, 1)); | |
| 502 bool continue_sync_cycle_param = false; | |
| 503 | |
| 504 WaitInterval interval = syncer_thread->CalculatePollingWaitTime( | |
| 505 0, | |
| 506 &user_idle_milliseconds_param, | |
| 507 &continue_sync_cycle_param, | |
| 508 false); | |
| 509 | |
| 510 ASSERT_LE(0, interval.poll_delta.InSeconds()); | |
| 511 ASSERT_EQ(WaitInterval::NORMAL, interval.mode); | |
| 512 ASSERT_FALSE(interval.had_nudge_during_backoff); | |
| 513 ASSERT_TRUE(continue_sync_cycle_param); | |
| 514 | |
| 515 continue_sync_cycle_param = false; | |
| 516 interval = syncer_thread->CalculatePollingWaitTime( | |
| 517 0, | |
| 518 &user_idle_milliseconds_param, | |
| 519 &continue_sync_cycle_param, | |
| 520 false); | |
| 521 | |
| 522 ASSERT_GE(2, interval.poll_delta.InSeconds()); | |
| 523 ASSERT_EQ(WaitInterval::NORMAL, interval.mode); | |
| 524 ASSERT_FALSE(interval.had_nudge_during_backoff); | |
| 525 ASSERT_TRUE(continue_sync_cycle_param); | |
| 526 | |
| 527 context->set_last_snapshot(SessionSnapshotForTest(0, 0)); | |
| 528 interval = syncer_thread->CalculatePollingWaitTime( | |
| 529 4, | |
| 530 &user_idle_milliseconds_param, | |
| 531 &continue_sync_cycle_param, | |
| 532 false); | |
| 533 | |
| 534 ASSERT_EQ(SyncerThread::kDefaultLongPollIntervalSeconds, | |
| 535 interval.poll_delta.InSeconds()); | |
| 536 ASSERT_EQ(WaitInterval::NORMAL, interval.mode); | |
| 537 ASSERT_FALSE(interval.had_nudge_during_backoff); | |
| 538 ASSERT_FALSE(continue_sync_cycle_param); | |
| 539 } | |
| 540 | |
| 541 // Regression for exponential backoff reset when the syncer is nudged. | |
| 542 { | |
| 543 context->set_last_snapshot(SessionSnapshotForTest(0, 1)); | |
| 544 bool continue_sync_cycle_param = false; | |
| 545 | |
| 546 // Expect move from default polling interval to exponential backoff due to | |
| 547 // unsynced_count != 0. | |
| 548 WaitInterval interval = syncer_thread->CalculatePollingWaitTime( | |
| 549 3600, | |
| 550 &user_idle_milliseconds_param, | |
| 551 &continue_sync_cycle_param, | |
| 552 false); | |
| 553 | |
| 554 ASSERT_LE(0, interval.poll_delta.InSeconds()); | |
| 555 ASSERT_EQ(WaitInterval::NORMAL, interval.mode); | |
| 556 ASSERT_FALSE(interval.had_nudge_during_backoff); | |
| 557 ASSERT_TRUE(continue_sync_cycle_param); | |
| 558 | |
| 559 continue_sync_cycle_param = false; | |
| 560 interval = syncer_thread->CalculatePollingWaitTime( | |
| 561 3600, | |
| 562 &user_idle_milliseconds_param, | |
| 563 &continue_sync_cycle_param, | |
| 564 false); | |
| 565 | |
| 566 ASSERT_GE(2, interval.poll_delta.InSeconds()); | |
| 567 ASSERT_EQ(WaitInterval::NORMAL, interval.mode); | |
| 568 ASSERT_FALSE(interval.had_nudge_during_backoff); | |
| 569 ASSERT_TRUE(continue_sync_cycle_param); | |
| 570 | |
| 571 // Expect exponential backoff. | |
| 572 interval = syncer_thread->CalculatePollingWaitTime( | |
| 573 2, | |
| 574 &user_idle_milliseconds_param, | |
| 575 &continue_sync_cycle_param, | |
| 576 false); | |
| 577 | |
| 578 ASSERT_LE(2, interval.poll_delta.InSeconds()); | |
| 579 ASSERT_EQ(WaitInterval::EXPONENTIAL_BACKOFF, interval.mode); | |
| 580 ASSERT_FALSE(interval.had_nudge_during_backoff); | |
| 581 ASSERT_TRUE(continue_sync_cycle_param); | |
| 582 | |
| 583 interval = syncer_thread->CalculatePollingWaitTime( | |
| 584 2, | |
| 585 &user_idle_milliseconds_param, | |
| 586 &continue_sync_cycle_param, | |
| 587 false); | |
| 588 | |
| 589 ASSERT_GE(6, interval.poll_delta.InSeconds()); | |
| 590 ASSERT_EQ(WaitInterval::EXPONENTIAL_BACKOFF, interval.mode); | |
| 591 ASSERT_FALSE(interval.had_nudge_during_backoff); | |
| 592 ASSERT_TRUE(continue_sync_cycle_param); | |
| 593 | |
| 594 syncer_thread->vault_.current_wait_interval_ = interval; | |
| 595 | |
| 596 interval = syncer_thread->CalculatePollingWaitTime( | |
| 597 static_cast<int>(interval.poll_delta.InSeconds()), | |
| 598 &user_idle_milliseconds_param, | |
| 599 &continue_sync_cycle_param, | |
| 600 true); | |
| 601 | |
| 602 // Don't change poll on a failed nudge during backoff. | |
| 603 ASSERT_TRUE(syncer_thread->vault_.current_wait_interval_.poll_delta == | |
| 604 interval.poll_delta); | |
| 605 ASSERT_EQ(WaitInterval::EXPONENTIAL_BACKOFF, interval.mode); | |
| 606 ASSERT_TRUE(interval.had_nudge_during_backoff); | |
| 607 ASSERT_TRUE(continue_sync_cycle_param); | |
| 608 | |
| 609 // If we got a nudge and we weren't in backoff mode, we see exponential | |
| 610 // backoff. | |
| 611 syncer_thread->vault_.current_wait_interval_.mode = WaitInterval::NORMAL; | |
| 612 interval = syncer_thread->CalculatePollingWaitTime( | |
| 613 2, | |
| 614 &user_idle_milliseconds_param, | |
| 615 &continue_sync_cycle_param, | |
| 616 true); | |
| 617 | |
| 618 // 5 and 3 are bounds on the backoff randomization formula given input of 2. | |
| 619 ASSERT_GE(5, interval.poll_delta.InSeconds()); | |
| 620 ASSERT_LE(3, interval.poll_delta.InSeconds()); | |
| 621 ASSERT_EQ(WaitInterval::EXPONENTIAL_BACKOFF, interval.mode); | |
| 622 ASSERT_FALSE(interval.had_nudge_during_backoff); | |
| 623 ASSERT_TRUE(continue_sync_cycle_param); | |
| 624 | |
| 625 // And if another interval expires, we get a bigger backoff. | |
| 626 WaitInterval new_interval = syncer_thread->CalculatePollingWaitTime( | |
| 627 static_cast<int>(interval.poll_delta.InSeconds()), | |
| 628 &user_idle_milliseconds_param, | |
| 629 &continue_sync_cycle_param, | |
| 630 false); | |
| 631 | |
| 632 ASSERT_GE(12, new_interval.poll_delta.InSeconds()); | |
| 633 ASSERT_LE(5, new_interval.poll_delta.InSeconds()); | |
| 634 ASSERT_EQ(WaitInterval::EXPONENTIAL_BACKOFF, interval.mode); | |
| 635 ASSERT_FALSE(new_interval.had_nudge_during_backoff); | |
| 636 ASSERT_TRUE(continue_sync_cycle_param); | |
| 637 | |
| 638 // A nudge resets the continue_sync_cycle_param value, so our backoff | |
| 639 // should return to the minimum. | |
| 640 continue_sync_cycle_param = false; | |
| 641 interval = syncer_thread->CalculatePollingWaitTime( | |
| 642 3600, | |
| 643 &user_idle_milliseconds_param, | |
| 644 &continue_sync_cycle_param, | |
| 645 true); | |
| 646 | |
| 647 ASSERT_LE(0, interval.poll_delta.InSeconds()); | |
| 648 ASSERT_EQ(WaitInterval::NORMAL, interval.mode); | |
| 649 ASSERT_FALSE(interval.had_nudge_during_backoff); | |
| 650 ASSERT_TRUE(continue_sync_cycle_param); | |
| 651 | |
| 652 continue_sync_cycle_param = false; | |
| 653 interval = syncer_thread->CalculatePollingWaitTime( | |
| 654 3600, | |
| 655 &user_idle_milliseconds_param, | |
| 656 &continue_sync_cycle_param, | |
| 657 true); | |
| 658 | |
| 659 ASSERT_GE(2, interval.poll_delta.InSeconds()); | |
| 660 ASSERT_EQ(WaitInterval::NORMAL, interval.mode); | |
| 661 ASSERT_FALSE(interval.had_nudge_during_backoff); | |
| 662 ASSERT_TRUE(continue_sync_cycle_param); | |
| 663 | |
| 664 // Setting unsynced_count = 0 returns us to the default polling interval. | |
| 665 context->set_last_snapshot(SessionSnapshotForTest(0, 0)); | |
| 666 interval = syncer_thread->CalculatePollingWaitTime( | |
| 667 4, | |
| 668 &user_idle_milliseconds_param, | |
| 669 &continue_sync_cycle_param, | |
| 670 true); | |
| 671 | |
| 672 ASSERT_EQ(SyncerThread::kDefaultLongPollIntervalSeconds, | |
| 673 interval.poll_delta.InSeconds()); | |
| 674 ASSERT_EQ(WaitInterval::NORMAL, interval.mode); | |
| 675 ASSERT_FALSE(interval.had_nudge_during_backoff); | |
| 676 ASSERT_FALSE(continue_sync_cycle_param); | |
| 677 } | |
| 678 } | |
| 679 | |
| 680 TEST_F(SyncerThreadWithSyncerTest, Polling) { | |
| 681 SyncShareIntercept interceptor; | |
| 682 connection()->SetMidCommitObserver(&interceptor); | |
| 683 | |
| 684 const TimeDelta poll_interval = TimeDelta::FromSeconds(1); | |
| 685 syncer_thread()->SetSyncerShortPollInterval(poll_interval); | |
| 686 EXPECT_TRUE(syncer_thread()->Start()); | |
| 687 | |
| 688 metadb()->Open(); | |
| 689 syncer_thread()->CreateSyncer(metadb()->name()); | |
| 690 | |
| 691 TimeDelta two_polls = poll_interval + poll_interval; | |
| 692 // We could theoretically return immediately from the wait if the interceptor | |
| 693 // was already signaled for a SyncShare (the first one comes quick). | |
| 694 interceptor.WaitForSyncShare(1, two_polls); | |
| 695 EXPECT_FALSE(interceptor.times_sync_occured().empty()); | |
| 696 | |
| 697 // Wait for at least 2 more SyncShare operations. | |
| 698 interceptor.WaitForSyncShare(2, two_polls); | |
| 699 EXPECT_TRUE(syncer_thread()->Stop(2000)); | |
| 700 | |
| 701 // Now analyze the run. | |
| 702 std::vector<TimeTicks> data = interceptor.times_sync_occured(); | |
| 703 | |
| 704 EXPECT_GE(data.size(), static_cast<unsigned int>(3)); | |
| 705 for (unsigned int i = 0; i < data.size() - 1; i++) { | |
| 706 TimeTicks optimal_next_sync = data[i] + poll_interval; | |
| 707 EXPECT_TRUE(data[i + 1] >= optimal_next_sync); | |
| 708 // This should be reliable, as there are no blocking or I/O operations | |
| 709 // except the explicit 2 second wait, so if it takes longer than this | |
| 710 // there is a problem. | |
| 711 EXPECT_TRUE(data[i + 1] < optimal_next_sync + poll_interval); | |
| 712 } | |
| 713 } | |
| 714 | |
| 715 TEST_F(SyncerThreadWithSyncerTest, Nudge) { | |
| 716 SyncShareIntercept interceptor; | |
| 717 connection()->SetMidCommitObserver(&interceptor); | |
| 718 // We don't want a poll to happen during this test (except the first one). | |
| 719 PreventThreadFromPolling(); | |
| 720 EXPECT_TRUE(syncer_thread()->Start()); | |
| 721 metadb()->Open(); | |
| 722 syncer_thread()->CreateSyncer(metadb()->name()); | |
| 723 const TimeDelta poll_interval = TimeDelta::FromMinutes(5); | |
| 724 interceptor.WaitForSyncShare(1, poll_interval + poll_interval); | |
| 725 | |
| 726 EXPECT_EQ(static_cast<unsigned int>(1), | |
| 727 interceptor.times_sync_occured().size()); | |
| 728 // The SyncerThread should be waiting for the poll now. Nudge it to sync | |
| 729 // immediately (5ms). | |
| 730 syncer_thread()->NudgeSyncer(5, SyncerThread::kUnknown); | |
| 731 interceptor.WaitForSyncShare(1, TimeDelta::FromSeconds(1)); | |
| 732 EXPECT_EQ(static_cast<unsigned int>(2), | |
| 733 interceptor.times_sync_occured().size()); | |
| 734 | |
| 735 // SyncerThread should be waiting again. Signal it to stop. | |
| 736 EXPECT_TRUE(syncer_thread()->Stop(2000)); | |
| 737 } | |
| 738 | |
| 739 TEST_F(SyncerThreadWithSyncerTest, NudgeWithDataTypes) { | |
| 740 SyncShareIntercept interceptor; | |
| 741 connection()->SetMidCommitObserver(&interceptor); | |
| 742 // We don't want a poll to happen during this test (except the first one). | |
| 743 PreventThreadFromPolling(); | |
| 744 EXPECT_TRUE(syncer_thread()->Start()); | |
| 745 metadb()->Open(); | |
| 746 syncer_thread()->CreateSyncer(metadb()->name()); | |
| 747 const TimeDelta poll_interval = TimeDelta::FromMinutes(5); | |
| 748 interceptor.WaitForSyncShare(1, poll_interval + poll_interval); | |
| 749 EXPECT_EQ(static_cast<unsigned int>(1), | |
| 750 interceptor.times_sync_occured().size()); | |
| 751 | |
| 752 // The SyncerThread should be waiting for the poll now. Nudge it to sync | |
| 753 // immediately (5ms). | |
| 754 syncable::ModelTypeBitSet model_types; | |
| 755 model_types[syncable::BOOKMARKS] = true; | |
| 756 | |
| 757 // Paused so we can verify the nudge types safely. | |
| 758 syncer_thread()->RequestPause(); | |
| 759 syncer_thread()->NudgeSyncerWithDataTypes(5, | |
| 760 SyncerThread::kUnknown, | |
| 761 model_types); | |
| 762 EXPECT_TRUE(CompareNudgeTypesBitSetToVault(model_types)); | |
| 763 syncer_thread()->RequestResume(); | |
| 764 | |
| 765 interceptor.WaitForSyncShare(1, TimeDelta::FromSeconds(1)); | |
| 766 EXPECT_EQ(static_cast<unsigned int>(2), | |
| 767 interceptor.times_sync_occured().size()); | |
| 768 | |
| 769 // SyncerThread should be waiting again. Signal it to stop. | |
| 770 EXPECT_TRUE(syncer_thread()->Stop(2000)); | |
| 771 EXPECT_TRUE(syncer_thread()->vault_.pending_nudge_types_.empty()); | |
| 772 } | |
| 773 | |
| 774 TEST_F(SyncerThreadWithSyncerTest, NudgeWithDataTypesCoalesced) { | |
| 775 SyncShareIntercept interceptor; | |
| 776 connection()->SetMidCommitObserver(&interceptor); | |
| 777 // We don't want a poll to happen during this test (except the first one). | |
| 778 PreventThreadFromPolling(); | |
| 779 EXPECT_TRUE(syncer_thread()->Start()); | |
| 780 metadb()->Open(); | |
| 781 syncer_thread()->CreateSyncer(metadb()->name()); | |
| 782 const TimeDelta poll_interval = TimeDelta::FromMinutes(5); | |
| 783 interceptor.WaitForSyncShare(1, poll_interval + poll_interval); | |
| 784 EXPECT_EQ(static_cast<unsigned int>(1), | |
| 785 interceptor.times_sync_occured().size()); | |
| 786 | |
| 787 // The SyncerThread should be waiting for the poll now. Nudge it to sync | |
| 788 // immediately (5ms). | |
| 789 syncable::ModelTypeBitSet model_types; | |
| 790 model_types[syncable::BOOKMARKS] = true; | |
| 791 | |
| 792 // Paused so we can verify the nudge types safely. | |
| 793 syncer_thread()->RequestPause(); | |
| 794 syncer_thread()->NudgeSyncerWithDataTypes(100, | |
| 795 SyncerThread::kUnknown, | |
| 796 model_types); | |
| 797 EXPECT_TRUE(CompareNudgeTypesBitSetToVault(model_types)); | |
| 798 | |
| 799 model_types[syncable::BOOKMARKS] = false; | |
| 800 model_types[syncable::AUTOFILL] = true; | |
| 801 syncer_thread()->NudgeSyncerWithDataTypes(0, | |
| 802 SyncerThread::kUnknown, | |
| 803 model_types); | |
| 804 | |
| 805 // Reset BOOKMARKS for expectations. | |
| 806 model_types[syncable::BOOKMARKS] = true; | |
| 807 EXPECT_TRUE(CompareNudgeTypesBitSetToVault(model_types)); | |
| 808 | |
| 809 syncer_thread()->RequestResume(); | |
| 810 | |
| 811 interceptor.WaitForSyncShare(1, TimeDelta::FromSeconds(1)); | |
| 812 EXPECT_EQ(static_cast<unsigned int>(2), | |
| 813 interceptor.times_sync_occured().size()); | |
| 814 | |
| 815 // SyncerThread should be waiting again. Signal it to stop. | |
| 816 EXPECT_TRUE(syncer_thread()->Stop(2000)); | |
| 817 EXPECT_TRUE(syncer_thread()->vault_.pending_nudge_types_.empty()); | |
| 818 } | |
| 819 | |
| 820 TEST_F(SyncerThreadWithSyncerTest, NudgeWithPayloads) { | |
| 821 SyncShareIntercept interceptor; | |
| 822 connection()->SetMidCommitObserver(&interceptor); | |
| 823 // We don't want a poll to happen during this test (except the first one). | |
| 824 PreventThreadFromPolling(); | |
| 825 EXPECT_TRUE(syncer_thread()->Start()); | |
| 826 metadb()->Open(); | |
| 827 syncer_thread()->CreateSyncer(metadb()->name()); | |
| 828 const TimeDelta poll_interval = TimeDelta::FromMinutes(5); | |
| 829 interceptor.WaitForSyncShare(1, poll_interval + poll_interval); | |
| 830 EXPECT_EQ(static_cast<unsigned int>(1), | |
| 831 interceptor.times_sync_occured().size()); | |
| 832 | |
| 833 // The SyncerThread should be waiting for the poll now. Nudge it to sync | |
| 834 // immediately (5ms). | |
| 835 syncable::ModelTypePayloadMap nudge_types; | |
| 836 nudge_types[syncable::BOOKMARKS] = "test"; | |
| 837 connection()->ExpectGetUpdatesRequestPayloads(nudge_types); | |
| 838 | |
| 839 // Paused so we can verify the nudge types safely. | |
| 840 syncer_thread()->RequestPause(); | |
| 841 syncer_thread()->NudgeSyncerWithPayloads(5, | |
| 842 SyncerThread::kUnknown, | |
| 843 nudge_types); | |
| 844 EXPECT_TRUE(CompareNudgeTypesToVault(nudge_types)); | |
| 845 syncer_thread()->RequestResume(); | |
| 846 | |
| 847 interceptor.WaitForSyncShare(1, TimeDelta::FromSeconds(1)); | |
| 848 EXPECT_EQ(static_cast<unsigned int>(2), | |
| 849 interceptor.times_sync_occured().size()); | |
| 850 | |
| 851 // SyncerThread should be waiting again. Signal it to stop. | |
| 852 EXPECT_TRUE(syncer_thread()->Stop(2000)); | |
| 853 EXPECT_TRUE(syncer_thread()->vault_.pending_nudge_types_.empty()); | |
| 854 } | |
| 855 | |
| 856 TEST_F(SyncerThreadWithSyncerTest, NudgeWithPayloadsCoalesced) { | |
| 857 SyncShareIntercept interceptor; | |
| 858 connection()->SetMidCommitObserver(&interceptor); | |
| 859 // We don't want a poll to happen during this test (except the first one). | |
| 860 PreventThreadFromPolling(); | |
| 861 EXPECT_TRUE(syncer_thread()->Start()); | |
| 862 metadb()->Open(); | |
| 863 syncer_thread()->CreateSyncer(metadb()->name()); | |
| 864 const TimeDelta poll_interval = TimeDelta::FromMinutes(5); | |
| 865 interceptor.WaitForSyncShare(1, poll_interval + poll_interval); | |
| 866 EXPECT_EQ(static_cast<unsigned int>(1), | |
| 867 interceptor.times_sync_occured().size()); | |
| 868 | |
| 869 // The SyncerThread should be waiting for the poll now. Nudge it to sync | |
| 870 // immediately (5ms). | |
| 871 syncable::ModelTypePayloadMap nudge_types; | |
| 872 nudge_types[syncable::BOOKMARKS] = "books"; | |
| 873 | |
| 874 // Paused so we can verify the nudge types safely. | |
| 875 syncer_thread()->RequestPause(); | |
| 876 syncer_thread()->NudgeSyncerWithPayloads(100, | |
| 877 SyncerThread::kUnknown, | |
| 878 nudge_types); | |
| 879 EXPECT_TRUE(CompareNudgeTypesToVault(nudge_types)); | |
| 880 | |
| 881 nudge_types.erase(syncable::BOOKMARKS); | |
| 882 nudge_types[syncable::AUTOFILL] = "auto"; | |
| 883 syncer_thread()->NudgeSyncerWithPayloads(0, | |
| 884 SyncerThread::kUnknown, | |
| 885 nudge_types); | |
| 886 | |
| 887 // Reset BOOKMARKS for expectations. | |
| 888 nudge_types[syncable::BOOKMARKS] = "books"; | |
| 889 EXPECT_TRUE(CompareNudgeTypesToVault(nudge_types)); | |
| 890 connection()->ExpectGetUpdatesRequestPayloads(nudge_types); | |
| 891 | |
| 892 syncer_thread()->RequestResume(); | |
| 893 | |
| 894 interceptor.WaitForSyncShare(1, TimeDelta::FromSeconds(1)); | |
| 895 EXPECT_EQ(static_cast<unsigned int>(2), | |
| 896 interceptor.times_sync_occured().size()); | |
| 897 | |
| 898 // SyncerThread should be waiting again. Signal it to stop. | |
| 899 EXPECT_TRUE(syncer_thread()->Stop(2000)); | |
| 900 EXPECT_TRUE(syncer_thread()->vault_.pending_nudge_types_.empty()); | |
| 901 } | |
| 902 | |
| 903 TEST_F(SyncerThreadWithSyncerTest, Throttling) { | |
| 904 SyncShareIntercept interceptor; | |
| 905 connection()->SetMidCommitObserver(&interceptor); | |
| 906 const TimeDelta poll_interval = TimeDelta::FromMilliseconds(10); | |
| 907 syncer_thread()->SetSyncerShortPollInterval(poll_interval); | |
| 908 | |
| 909 EXPECT_TRUE(syncer_thread()->Start()); | |
| 910 metadb()->Open(); | |
| 911 syncer_thread()->CreateSyncer(metadb()->name()); | |
| 912 | |
| 913 // Wait for some healthy syncing. | |
| 914 interceptor.WaitForSyncShare(4, poll_interval + poll_interval); | |
| 915 | |
| 916 // Tell the server to throttle a single request, which should be all it takes | |
| 917 // to silence our syncer (for 2 hours, so we shouldn't hit that in this test). | |
| 918 // This will atomically visit the interceptor so it can switch to throttled | |
| 919 // mode and fail on multiple requests. | |
| 920 connection()->ThrottleNextRequest(&interceptor); | |
| 921 | |
| 922 // Try to trigger a sync (we have a really short poll interval already). | |
| 923 syncer_thread()->NudgeSyncer(0, SyncerThread::kUnknown); | |
| 924 syncer_thread()->NudgeSyncer(0, SyncerThread::kUnknown); | |
| 925 | |
| 926 // Wait until the syncer thread reports that it is throttled. Any further | |
| 927 // sync share interceptions will result in failure. If things are broken, | |
| 928 // we may never halt. | |
| 929 ASSERT_TRUE(WaitForThrottle()); | |
| 930 EXPECT_TRUE(syncer_thread()->IsSyncingCurrentlySilenced()); | |
| 931 | |
| 932 EXPECT_TRUE(syncer_thread()->Stop(2000)); | |
| 933 } | |
| 934 | |
| 935 TEST_F(SyncerThreadWithSyncerTest, StopSyncPermanently) { | |
| 936 // The SyncerThread should request an exit from the Syncer and set | |
| 937 // conditions for termination. | |
| 938 const TimeDelta poll_interval = TimeDelta::FromMilliseconds(10); | |
| 939 syncer_thread()->SetSyncerShortPollInterval(poll_interval); | |
| 940 | |
| 941 ListenerMock listener; | |
| 942 WaitableEvent sync_cycle_ended_event(false, false); | |
| 943 WaitableEvent syncer_thread_exiting_event(false, false); | |
| 944 TestScopedSessionEventListener reg(context_, &listener); | |
| 945 | |
| 946 EXPECT_CALL(listener, OnSyncEngineEvent( | |
| 947 Field(&SyncEngineEvent::what_happened, | |
| 948 SyncEngineEvent::STATUS_CHANGED))). | |
| 949 Times(AnyNumber()); | |
| 950 | |
| 951 EXPECT_CALL(listener, OnSyncEngineEvent( | |
| 952 Field(&SyncEngineEvent::what_happened, | |
| 953 SyncEngineEvent::SYNC_CYCLE_ENDED))). | |
| 954 Times(AnyNumber()). | |
| 955 WillOnce(SignalEvent(&sync_cycle_ended_event)); | |
| 956 | |
| 957 EXPECT_CALL(listener, OnSyncEngineEvent( | |
| 958 Field(&SyncEngineEvent::what_happened, | |
| 959 SyncEngineEvent::STOP_SYNCING_PERMANENTLY))); | |
| 960 EXPECT_CALL(listener, OnSyncEngineEvent( | |
| 961 Field(&SyncEngineEvent::what_happened, | |
| 962 SyncEngineEvent::SYNCER_THREAD_EXITING))). | |
| 963 WillOnce(SignalEvent(&syncer_thread_exiting_event)); | |
| 964 | |
| 965 EXPECT_TRUE(syncer_thread()->Start()); | |
| 966 metadb()->Open(); | |
| 967 syncer_thread()->CreateSyncer(metadb()->name()); | |
| 968 ASSERT_TRUE(sync_cycle_ended_event.TimedWait(max_wait_time_)); | |
| 969 | |
| 970 connection()->set_store_birthday("NotYourLuckyDay"); | |
| 971 ASSERT_TRUE(syncer_thread_exiting_event.TimedWait(max_wait_time_)); | |
| 972 EXPECT_TRUE(syncer_thread()->Stop(0)); | |
| 973 } | |
| 974 | |
| 975 TEST_F(SyncerThreadWithSyncerTest, AuthInvalid) { | |
| 976 SyncShareIntercept interceptor; | |
| 977 connection()->SetMidCommitObserver(&interceptor); | |
| 978 const TimeDelta poll_interval = TimeDelta::FromMilliseconds(1); | |
| 979 | |
| 980 syncer_thread()->SetSyncerShortPollInterval(poll_interval); | |
| 981 EXPECT_TRUE(syncer_thread()->Start()); | |
| 982 metadb()->Open(); | |
| 983 syncer_thread()->CreateSyncer(metadb()->name()); | |
| 984 | |
| 985 // Wait for some healthy syncing. | |
| 986 interceptor.WaitForSyncShare(2, TimeDelta::FromSeconds(10)); | |
| 987 EXPECT_GE(interceptor.times_sync_occured().size(), 2U); | |
| 988 | |
| 989 // Atomically start returning auth invalid and set the interceptor to fail | |
| 990 // on any sync. | |
| 991 connection()->FailWithAuthInvalid(&interceptor); | |
| 992 WaitForDisconnect(); | |
| 993 | |
| 994 // Try to trigger a sync (the interceptor will assert if one occurs). | |
| 995 syncer_thread()->NudgeSyncer(0, SyncerThread::kUnknown); | |
| 996 syncer_thread()->NudgeSyncer(0, SyncerThread::kUnknown); | |
| 997 | |
| 998 // Wait several poll intervals but don't expect any syncing besides the cycle | |
| 999 // that lost the connection. | |
| 1000 interceptor.WaitForSyncShare(1, TimeDelta::FromSeconds(1)); | |
| 1001 EXPECT_EQ(1U, interceptor.times_sync_occured().size()); | |
| 1002 | |
| 1003 // Simulate a valid re-authentication and expect resumption of syncing. | |
| 1004 interceptor.Reset(); | |
| 1005 ASSERT_TRUE(interceptor.times_sync_occured().empty()); | |
| 1006 connection()->StopFailingWithAuthInvalid(NULL); | |
| 1007 ServerConnectionEvent e = {ServerConnectionEvent::STATUS_CHANGED, | |
| 1008 HttpResponse::SERVER_CONNECTION_OK, | |
| 1009 true}; | |
| 1010 connection()->channel()->NotifyListeners(e); | |
| 1011 | |
| 1012 interceptor.WaitForSyncShare(1, TimeDelta::FromSeconds(10)); | |
| 1013 EXPECT_FALSE(interceptor.times_sync_occured().empty()); | |
| 1014 | |
| 1015 EXPECT_TRUE(syncer_thread()->Stop(2000)); | |
| 1016 } | |
| 1017 | |
| 1018 // TODO(zea): Disabled, along with PauseWhenNotConnected, due to stalling on | |
| 1019 // windows, preventing further sync unit tests from running. See crbug/39070. | |
| 1020 TEST_F(SyncerThreadWithSyncerTest, DISABLED_Pause) { | |
| 1021 WaitableEvent sync_cycle_ended_event(false, false); | |
| 1022 WaitableEvent paused_event(false, false); | |
| 1023 WaitableEvent resumed_event(false, false); | |
| 1024 PreventThreadFromPolling(); | |
| 1025 | |
| 1026 ListenerMock listener; | |
| 1027 TestScopedSessionEventListener reg(context_, &listener); | |
| 1028 EXPECT_CALL(listener, OnSyncEngineEvent( | |
| 1029 Field(&SyncEngineEvent::what_happened, | |
| 1030 SyncEngineEvent::STATUS_CHANGED))). | |
| 1031 Times(AnyNumber()); | |
| 1032 | |
| 1033 // Wait for the initial sync to complete. | |
| 1034 EXPECT_CALL(listener, OnSyncEngineEvent( | |
| 1035 Field(&SyncEngineEvent::what_happened, | |
| 1036 SyncEngineEvent::SYNC_CYCLE_ENDED))). | |
| 1037 WillOnce(SignalEvent(&sync_cycle_ended_event)); | |
| 1038 EXPECT_CALL(listener, OnSyncEngineEvent( | |
| 1039 Field(&SyncEngineEvent::what_happened, | |
| 1040 SyncEngineEvent::SYNCER_THREAD_EXITING))); | |
| 1041 | |
| 1042 ASSERT_TRUE(syncer_thread()->Start()); | |
| 1043 metadb()->Open(); | |
| 1044 syncer_thread()->CreateSyncer(metadb()->name()); | |
| 1045 ASSERT_TRUE(sync_cycle_ended_event.TimedWait(max_wait_time_)); | |
| 1046 | |
| 1047 // Request a pause. | |
| 1048 ASSERT_TRUE(Pause(&listener)); | |
| 1049 | |
| 1050 // Resuming the pause. | |
| 1051 ASSERT_TRUE(Resume(&listener)); | |
| 1052 | |
| 1053 // Not paused, should fail. | |
| 1054 EXPECT_FALSE(syncer_thread()->RequestResume()); | |
| 1055 | |
| 1056 // Request a pause. | |
| 1057 ASSERT_TRUE(Pause(&listener)); | |
| 1058 | |
| 1059 // Nudge the syncer, this should do nothing while we are paused. | |
| 1060 syncer_thread()->NudgeSyncer(0, SyncerThread::kUnknown); | |
| 1061 | |
| 1062 // Resuming will cause the nudge to be processed and a sync cycle to run. | |
| 1063 EXPECT_CALL(listener, OnSyncEngineEvent( | |
| 1064 Field(&SyncEngineEvent::what_happened, | |
| 1065 SyncEngineEvent::SYNC_CYCLE_ENDED))). | |
| 1066 WillOnce(SignalEvent(&sync_cycle_ended_event)); | |
| 1067 ASSERT_TRUE(Resume(&listener)); | |
| 1068 ASSERT_TRUE(sync_cycle_ended_event.TimedWait(max_wait_time_)); | |
| 1069 | |
| 1070 EXPECT_TRUE(syncer_thread()->Stop(2000)); | |
| 1071 } | |
| 1072 | |
| 1073 TEST_F(SyncerThreadWithSyncerTest, StartWhenNotConnected) { | |
| 1074 WaitableEvent sync_cycle_ended_event(false, false); | |
| 1075 WaitableEvent event(false, false); | |
| 1076 ListenerMock listener; | |
| 1077 TestScopedSessionEventListener reg(context_, &listener); | |
| 1078 PreventThreadFromPolling(); | |
| 1079 | |
| 1080 EXPECT_CALL(listener, OnSyncEngineEvent( | |
| 1081 Field(&SyncEngineEvent::what_happened, | |
| 1082 SyncEngineEvent::STATUS_CHANGED))). | |
| 1083 Times(AnyNumber()); | |
| 1084 EXPECT_CALL(listener, OnSyncEngineEvent( | |
| 1085 Field(&SyncEngineEvent::what_happened, | |
| 1086 SyncEngineEvent::SYNCER_THREAD_EXITING))); | |
| 1087 | |
| 1088 connection()->SetServerNotReachable(); | |
| 1089 metadb()->Open(); | |
| 1090 syncer_thread()->CreateSyncer(metadb()->name()); | |
| 1091 | |
| 1092 // Syncer thread will always go through once cycle at the start, | |
| 1093 // then it will wait for a connection. | |
| 1094 EXPECT_CALL(listener, OnSyncEngineEvent( | |
| 1095 Field(&SyncEngineEvent::what_happened, | |
| 1096 SyncEngineEvent::SYNC_CYCLE_ENDED))). | |
| 1097 WillOnce(SignalEvent(&sync_cycle_ended_event)); | |
| 1098 EXPECT_CALL(listener, OnSyncEngineEvent( | |
| 1099 Field(&SyncEngineEvent::what_happened, | |
| 1100 SyncEngineEvent::SYNCER_THREAD_WAITING_FOR_CONNECTION))). | |
| 1101 WillOnce(SignalEvent(&event)); | |
| 1102 ASSERT_TRUE(syncer_thread()->Start()); | |
| 1103 ASSERT_TRUE(sync_cycle_ended_event.TimedWait(max_wait_time_)); | |
| 1104 ASSERT_TRUE(event.TimedWait(max_wait_time_)); | |
| 1105 | |
| 1106 // Connect, will put the syncer thread into its usually poll wait. | |
| 1107 EXPECT_CALL(listener, OnSyncEngineEvent( | |
| 1108 Field(&SyncEngineEvent::what_happened, | |
| 1109 SyncEngineEvent::SYNCER_THREAD_CONNECTED))). | |
| 1110 WillOnce(SignalEvent(&event)); | |
| 1111 connection()->SetServerReachable(); | |
| 1112 ASSERT_TRUE(event.TimedWait(max_wait_time_)); | |
| 1113 | |
| 1114 // Nudge the syncer to complete a cycle. | |
| 1115 EXPECT_CALL(listener, OnSyncEngineEvent( | |
| 1116 Field(&SyncEngineEvent::what_happened, | |
| 1117 SyncEngineEvent::SYNC_CYCLE_ENDED))). | |
| 1118 WillOnce(SignalEvent(&sync_cycle_ended_event)); | |
| 1119 syncer_thread()->NudgeSyncer(0, SyncerThread::kUnknown); | |
| 1120 ASSERT_TRUE(sync_cycle_ended_event.TimedWait(max_wait_time_)); | |
| 1121 | |
| 1122 EXPECT_TRUE(syncer_thread()->Stop(2000)); | |
| 1123 } | |
| 1124 | |
| 1125 // See TODO comment on the "Pause" test above. | |
| 1126 TEST_F(SyncerThreadWithSyncerTest, DISABLED_PauseWhenNotConnected) { | |
| 1127 WaitableEvent sync_cycle_ended_event(false, false); | |
| 1128 WaitableEvent event(false, false); | |
| 1129 ListenerMock listener; | |
| 1130 TestScopedSessionEventListener reg(context_, &listener); | |
| 1131 PreventThreadFromPolling(); | |
| 1132 | |
| 1133 EXPECT_CALL(listener, OnSyncEngineEvent( | |
| 1134 Field(&SyncEngineEvent::what_happened, | |
| 1135 SyncEngineEvent::STATUS_CHANGED))). | |
| 1136 Times(AnyNumber()); | |
| 1137 | |
| 1138 // Put the thread into a "waiting for connection" state. | |
| 1139 connection()->SetServerNotReachable(); | |
| 1140 EXPECT_CALL(listener, OnSyncEngineEvent( | |
| 1141 Field(&SyncEngineEvent::what_happened, | |
| 1142 SyncEngineEvent::SYNC_CYCLE_ENDED))). | |
| 1143 WillOnce(SignalEvent(&sync_cycle_ended_event)); | |
| 1144 EXPECT_CALL(listener, OnSyncEngineEvent( | |
| 1145 Field(&SyncEngineEvent::what_happened, | |
| 1146 SyncEngineEvent::SYNCER_THREAD_WAITING_FOR_CONNECTION))). | |
| 1147 WillOnce(SignalEvent(&event)); | |
| 1148 metadb()->Open(); | |
| 1149 syncer_thread()->CreateSyncer(metadb()->name()); | |
| 1150 | |
| 1151 ASSERT_TRUE(syncer_thread()->Start()); | |
| 1152 ASSERT_TRUE(sync_cycle_ended_event.TimedWait(max_wait_time_)); | |
| 1153 ASSERT_TRUE(event.TimedWait(max_wait_time_)); | |
| 1154 | |
| 1155 // Pause and resume the thread while waiting for a connection. | |
| 1156 ASSERT_TRUE(Pause(&listener)); | |
| 1157 ASSERT_TRUE(Resume(&listener)); | |
| 1158 | |
| 1159 // Make a connection and let the syncer cycle. | |
| 1160 EXPECT_CALL(listener, OnSyncEngineEvent( | |
| 1161 Field(&SyncEngineEvent::what_happened, | |
| 1162 SyncEngineEvent::SYNC_CYCLE_ENDED))). | |
| 1163 WillOnce(SignalEvent(&sync_cycle_ended_event)); | |
| 1164 EXPECT_CALL(listener, OnSyncEngineEvent( | |
| 1165 Field(&SyncEngineEvent::what_happened, | |
| 1166 SyncEngineEvent::SYNCER_THREAD_CONNECTED))). | |
| 1167 WillOnce(SignalEvent(&event)); | |
| 1168 connection()->SetServerReachable(); | |
| 1169 ASSERT_TRUE(event.TimedWait(max_wait_time_)); | |
| 1170 syncer_thread()->NudgeSyncer(0, SyncerThread::kUnknown); | |
| 1171 ASSERT_TRUE(sync_cycle_ended_event.TimedWait(max_wait_time_)); | |
| 1172 | |
| 1173 // Disconnect and get into the waiting for a connection state. | |
| 1174 EXPECT_CALL(listener, OnSyncEngineEvent( | |
| 1175 Field(&SyncEngineEvent::what_happened, | |
| 1176 SyncEngineEvent::SYNCER_THREAD_WAITING_FOR_CONNECTION))). | |
| 1177 WillOnce(SignalEvent(&event)); | |
| 1178 connection()->SetServerNotReachable(); | |
| 1179 ASSERT_TRUE(event.TimedWait(max_wait_time_)); | |
| 1180 | |
| 1181 // Pause so we can test getting a connection while paused. | |
| 1182 ASSERT_TRUE(Pause(&listener)); | |
| 1183 | |
| 1184 // Get a connection then resume. | |
| 1185 EXPECT_CALL(listener, OnSyncEngineEvent( | |
| 1186 Field(&SyncEngineEvent::what_happened, | |
| 1187 SyncEngineEvent::SYNCER_THREAD_CONNECTED))). | |
| 1188 WillOnce(SignalEvent(&event)); | |
| 1189 connection()->SetServerReachable(); | |
| 1190 ASSERT_TRUE(event.TimedWait(max_wait_time_)); | |
| 1191 | |
| 1192 ASSERT_TRUE(Resume(&listener)); | |
| 1193 | |
| 1194 // Cycle the syncer to show we are not longer paused. | |
| 1195 EXPECT_CALL(listener, OnSyncEngineEvent( | |
| 1196 Field(&SyncEngineEvent::what_happened, | |
| 1197 SyncEngineEvent::SYNC_CYCLE_ENDED))). | |
| 1198 WillOnce(SignalEvent(&sync_cycle_ended_event)); | |
| 1199 EXPECT_CALL(listener, OnSyncEngineEvent( | |
| 1200 Field(&SyncEngineEvent::what_happened, | |
| 1201 SyncEngineEvent::SYNCER_THREAD_EXITING))); | |
| 1202 | |
| 1203 syncer_thread()->NudgeSyncer(0, SyncerThread::kUnknown); | |
| 1204 ASSERT_TRUE(sync_cycle_ended_event.TimedWait(max_wait_time_)); | |
| 1205 | |
| 1206 EXPECT_TRUE(syncer_thread()->Stop(2000)); | |
| 1207 } | |
| 1208 | |
| 1209 TEST_F(SyncerThreadWithSyncerTest, PauseResumeWhenNotRunning) { | |
| 1210 WaitableEvent sync_cycle_ended_event(false, false); | |
| 1211 WaitableEvent event(false, false); | |
| 1212 ListenerMock listener; | |
| 1213 TestScopedSessionEventListener reg(context_, &listener); | |
| 1214 PreventThreadFromPolling(); | |
| 1215 | |
| 1216 EXPECT_CALL(listener, OnSyncEngineEvent( | |
| 1217 Field(&SyncEngineEvent::what_happened, | |
| 1218 SyncEngineEvent::STATUS_CHANGED))). | |
| 1219 Times(AnyNumber()); | |
| 1220 | |
| 1221 // Pause and resume the syncer while not running | |
| 1222 ASSERT_TRUE(Pause(&listener)); | |
| 1223 ASSERT_TRUE(Resume(&listener)); | |
| 1224 | |
| 1225 // Pause the thread then start the syncer. | |
| 1226 ASSERT_TRUE(Pause(&listener)); | |
| 1227 metadb()->Open(); | |
| 1228 syncer_thread()->CreateSyncer(metadb()->name()); | |
| 1229 ASSERT_TRUE(syncer_thread()->Start()); | |
| 1230 | |
| 1231 // Resume and let the syncer cycle. | |
| 1232 EXPECT_CALL(listener, OnSyncEngineEvent( | |
| 1233 Field(&SyncEngineEvent::what_happened, | |
| 1234 SyncEngineEvent::SYNC_CYCLE_ENDED))). | |
| 1235 WillOnce(SignalEvent(&sync_cycle_ended_event)); | |
| 1236 EXPECT_CALL(listener, OnSyncEngineEvent( | |
| 1237 Field(&SyncEngineEvent::what_happened, | |
| 1238 SyncEngineEvent::SYNCER_THREAD_EXITING))); | |
| 1239 | |
| 1240 ASSERT_TRUE(Resume(&listener)); | |
| 1241 ASSERT_TRUE(sync_cycle_ended_event.TimedWait(max_wait_time_)); | |
| 1242 EXPECT_TRUE(syncer_thread()->Stop(2000)); | |
| 1243 } | |
| 1244 | |
| 1245 } // namespace browser_sync | |
| OLD | NEW |