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 |