Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(353)

Side by Side Diff: chrome/browser/sync/engine/syncer_thread2_unittest.cc

Issue 5939006: sync: beginnings of MessageLoop based SyncerThread (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: linux compile Created 9 years, 11 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
(Empty)
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
3 // found in the LICENSE file.
4
5 #include "base/synchronization/waitable_event.h"
6 #include "base/test/test_timeouts.h"
7 #include "chrome/browser/sync/engine/mock_model_safe_workers.h"
8 #include "chrome/browser/sync/engine/syncer.h"
9 #include "chrome/browser/sync/engine/syncer_thread2.h"
10 #include "chrome/browser/sync/sessions/test_util.h"
11 #include "chrome/test/sync/engine/test_directory_setter_upper.h"
12 #include "testing/gtest/include/gtest/gtest.h"
13 #include "testing/gmock/include/gmock/gmock.h"
14
15 using base::TimeDelta;
16 using base::TimeTicks;
17 using testing::_;
18 using testing::AtLeast;
19 using testing::DoAll;
20 using testing::Eq;
21 using testing::Invoke;
22 using testing::Mock;
23 using testing::Return;
24 using testing::WithArg;
25
26 namespace browser_sync {
27 using sessions::SyncSession;
28 using sessions::SyncSessionContext;
29 using sessions::SyncSessionSnapshot;
30 using syncable::ModelTypeBitSet;
31 using sync_pb::GetUpdatesCallerInfo;
32
33 class MockSyncer : public Syncer {
34 public:
35 MOCK_METHOD1(SyncShare, void(sessions::SyncSession*));
36 };
37
38 namespace s3 {
39
40 // Used when tests want to record syncing activity to examine later.
41 struct SyncShareRecords {
42 std::vector<TimeTicks> times;
43 std::vector<linked_ptr<SyncSessionSnapshot> > snapshots;
44 };
45
46 // Convenient to use in tests wishing to analyze SyncShare calls over time.
47 static const size_t kMinNumSamples = 5;
48
49 class SyncerThread2Test : public testing::Test {
50 public:
51 class MockDelayProvider : public SyncerThread::DelayProvider {
52 public:
53 MOCK_METHOD1(GetDelay, TimeDelta(const TimeDelta&));
54 };
55
56 virtual void SetUp() {
57 syncdb_.SetUp();
58 syncer_ = new MockSyncer();
59 delay_ = NULL;
60 registrar_.reset(MockModelSafeWorkerRegistrar::PassiveBookmarks());
61 context_ = new SyncSessionContext(NULL, syncdb_.manager(),
62 registrar_.get(), std::vector<SyncEngineEventListener*>());
63 context_->set_notifications_enabled(true);
64 context_->set_account_name("Test");
65 syncer_thread_.reset(new SyncerThread(context_, syncer_));
66 // TODO(tim): Once the SCM is hooked up, remove this.
67 syncer_thread_->server_connection_ok_ = true;
68 }
69
70 SyncerThread* syncer_thread() { return syncer_thread_.get(); }
71 MockSyncer* syncer() { return syncer_; }
72 MockDelayProvider* delay() { return delay_; }
73 TimeDelta zero() { return TimeDelta::FromSeconds(0); }
74 TimeDelta timeout() {
75 return TimeDelta::FromMilliseconds(TestTimeouts::action_timeout_ms());
76 }
77
78 virtual void TearDown() {
79 syncer_thread()->Stop();
80 syncdb_.TearDown();
81 }
82
83 void AnalyzePollRun(const SyncShareRecords& records, size_t min_num_samples,
84 const TimeTicks& optimal_start, const TimeDelta& poll_interval) {
85 const std::vector<TimeTicks>& data(records.times);
86 EXPECT_GE(data.size(), min_num_samples);
87 for (size_t i = 0; i < data.size(); i++) {
88 SCOPED_TRACE(testing::Message() << "SyncShare # (" << i << ")");
89 TimeTicks optimal_next_sync = optimal_start + poll_interval * i;
90 EXPECT_GE(data[i], optimal_next_sync);
91 EXPECT_LT(data[i], optimal_next_sync + poll_interval);
92 EXPECT_EQ(GetUpdatesCallerInfo::PERIODIC,
93 records.snapshots[i]->source.first);
94 }
95 }
96
97 bool GetBackoffAndResetTest(base::WaitableEvent* done) {
98 syncable::ModelTypeBitSet nudge_types;
99 syncer_thread()->Start(SyncerThread::NORMAL_MODE);
100 syncer_thread()->ScheduleNudge(zero(), NUDGE_SOURCE_LOCAL, nudge_types);
101 done->TimedWait(timeout());
102 TearDown();
103 done->Reset();
104 Mock::VerifyAndClearExpectations(syncer());
105 bool backing_off = syncer_thread()->IsBackingOff();
106 SetUp();
107 UseMockDelayProvider();
108 EXPECT_CALL(*delay(), GetDelay(_))
109 .WillRepeatedly(Return(TimeDelta::FromMilliseconds(1)));
110 return backing_off;
111 }
112
113 void UseMockDelayProvider() {
114 delay_ = new MockDelayProvider();
115 syncer_thread_->delay_provider_.reset(delay_);
116 }
117
118 void PostSignalTask(base::WaitableEvent* done) {
119 syncer_thread_->thread_.message_loop()->PostTask(FROM_HERE,
120 NewRunnableFunction(&SyncerThread2Test::SignalWaitableEvent, done));
121 }
122
123 void FlushLastTask(base::WaitableEvent* done) {
124 PostSignalTask(done);
125 done->TimedWait(timeout());
126 done->Reset();
127 }
128
129 static void SignalWaitableEvent(base::WaitableEvent* event) {
130 event->Signal();
131 }
132
133 private:
134 scoped_ptr<SyncerThread> syncer_thread_;
135 SyncSessionContext* context_;
136 MockSyncer* syncer_;
137 MockDelayProvider* delay_;
138 scoped_ptr<MockModelSafeWorkerRegistrar> registrar_;
139 MockDirectorySetterUpper syncdb_;
140 };
141
142 bool RecordSyncShareImpl(SyncSession* s, SyncShareRecords* record,
143 size_t signal_after) {
144 record->times.push_back(TimeTicks::Now());
145 record->snapshots.push_back(make_linked_ptr(new SyncSessionSnapshot(
146 s->TakeSnapshot())));
147 return record->times.size() >= signal_after;
148 }
149
150 ACTION_P4(RecordSyncShareAndPostSignal, record, signal_after, test, event) {
151 if (RecordSyncShareImpl(arg0, record, signal_after) && event)
152 test->PostSignalTask(event);
153 }
154
155 ACTION_P3(RecordSyncShare, record, signal_after, event) {
156 if (RecordSyncShareImpl(arg0, record, signal_after) && event)
157 event->Signal();
158 }
159
160 ACTION_P(SignalEvent, event) {
161 SyncerThread2Test::SignalWaitableEvent(event);
162 }
163
164 // Test nudge scheduling.
165 TEST_F(SyncerThread2Test, Nudge) {
166 syncer_thread()->Start(SyncerThread::NORMAL_MODE);
167 base::WaitableEvent done(false, false);
168 SyncShareRecords records;
169 syncable::ModelTypeBitSet model_types;
170 model_types[syncable::BOOKMARKS] = true;
171
172 EXPECT_CALL(*syncer(), SyncShare(_))
173 .WillOnce(DoAll(Invoke(sessions::test_util::SimulateSuccess),
174 WithArg<0>(RecordSyncShare(&records, 1U, &done))));
175 syncer_thread()->ScheduleNudge(zero(), NUDGE_SOURCE_LOCAL, model_types);
176 done.TimedWait(timeout());
177
178 EXPECT_EQ(1U, records.snapshots.size());
179 EXPECT_EQ(model_types, records.snapshots[0]->source.second);
180 EXPECT_EQ(GetUpdatesCallerInfo::LOCAL, records.snapshots[0]->source.first);
181 }
182
183 // Test that nudges are coalesced.
184 TEST_F(SyncerThread2Test, NudgeCoalescing) {
185 syncer_thread()->Start(SyncerThread::NORMAL_MODE);
186 base::WaitableEvent done(false, false);
187 SyncShareRecords r;
188 EXPECT_CALL(*syncer(), SyncShare(_))
189 .WillOnce(DoAll(Invoke(sessions::test_util::SimulateSuccess),
190 WithArg<0>(RecordSyncShare(&r, 1U, &done))));
191 syncable::ModelTypeBitSet types1, types2, types3;
192 types1[syncable::BOOKMARKS] = true;
193 types2[syncable::AUTOFILL] = true;
194 types3[syncable::THEMES] = true;
195 TimeDelta delay = TimeDelta::FromMilliseconds(20);
196 TimeTicks optimal_time = TimeTicks::Now() + delay;
197 syncer_thread()->ScheduleNudge(delay, NUDGE_SOURCE_UNKNOWN, types1);
198 syncer_thread()->ScheduleNudge(zero(), NUDGE_SOURCE_LOCAL, types2);
199 syncer_thread()->ScheduleNudge(zero(), NUDGE_SOURCE_NOTIFICATION, types3);
200 done.TimedWait(timeout());
201
202 EXPECT_EQ(1U, r.snapshots.size());
203 EXPECT_GE(r.times[0], optimal_time);
204 EXPECT_EQ(types1 | types2 | types3, r.snapshots[0]->source.second);
205 EXPECT_EQ(GetUpdatesCallerInfo::NOTIFICATION, r.snapshots[0]->source.first);
206
207 SyncShareRecords r2;
208 EXPECT_CALL(*syncer(), SyncShare(_))
209 .WillOnce(DoAll(Invoke(sessions::test_util::SimulateSuccess),
210 WithArg<0>(RecordSyncShare(&r2, 1U, &done))));
211 syncer_thread()->ScheduleNudge(zero(), NUDGE_SOURCE_NOTIFICATION, types3);
212 done.TimedWait(timeout());
213 EXPECT_EQ(1U, r2.snapshots.size());
214 EXPECT_EQ(types3, r2.snapshots[0]->source.second);
215 EXPECT_EQ(GetUpdatesCallerInfo::NOTIFICATION, r2.snapshots[0]->source.first);
216 }
217
218 // Test that polling works as expected.
219 TEST_F(SyncerThread2Test, Polling) {
220 SyncShareRecords records;
221 base::WaitableEvent done(false, false);
222 TimeDelta poll_interval(TimeDelta::FromMilliseconds(30));
223 syncer_thread()->OnReceivedLongPollIntervalUpdate(poll_interval);
224 EXPECT_CALL(*syncer(), SyncShare(_)).Times(AtLeast(kMinNumSamples))
225 .WillRepeatedly(DoAll(Invoke(sessions::test_util::SimulateSuccess),
226 WithArg<0>(RecordSyncShare(&records, kMinNumSamples, &done))));
227
228 TimeTicks optimal_start = TimeTicks::Now() + poll_interval;
229 syncer_thread()->Start(SyncerThread::NORMAL_MODE);
230 done.TimedWait(timeout());
231 syncer_thread()->Stop();
232
233 AnalyzePollRun(records, kMinNumSamples, optimal_start, poll_interval);
234 }
235
236 // Test that the short poll interval is used.
237 TEST_F(SyncerThread2Test, PollNotificationsDisabled) {
238 SyncShareRecords records;
239 base::WaitableEvent done(false, false);
240 TimeDelta poll_interval(TimeDelta::FromMilliseconds(30));
241 syncer_thread()->OnReceivedShortPollIntervalUpdate(poll_interval);
242 syncer_thread()->set_notifications_enabled(false);
243 EXPECT_CALL(*syncer(), SyncShare(_)).Times(AtLeast(kMinNumSamples))
244 .WillRepeatedly(DoAll(Invoke(sessions::test_util::SimulateSuccess),
245 WithArg<0>(RecordSyncShare(&records, kMinNumSamples, &done))));
246
247 TimeTicks optimal_start = TimeTicks::Now() + poll_interval;
248 syncer_thread()->Start(SyncerThread::NORMAL_MODE);
249 done.TimedWait(timeout());
250 syncer_thread()->Stop();
251
252 AnalyzePollRun(records, kMinNumSamples, optimal_start, poll_interval);
253 }
254
255 // Test that polling intervals are updated when needed.
256 TEST_F(SyncerThread2Test, PollIntervalUpdate) {
257 SyncShareRecords records;
258 base::WaitableEvent done(false, false);
259 TimeDelta poll1(TimeDelta::FromMilliseconds(120));
260 TimeDelta poll2(TimeDelta::FromMilliseconds(30));
261 syncer_thread()->OnReceivedLongPollIntervalUpdate(poll1);
262 EXPECT_CALL(*syncer(), SyncShare(_)).Times(AtLeast(kMinNumSamples))
263 .WillOnce(WithArg<0>(
264 sessions::test_util::SimulatePollIntervalUpdate(poll2)))
265 .WillRepeatedly(DoAll(Invoke(sessions::test_util::SimulateSuccess),
266 WithArg<0>(RecordSyncShare(&records, kMinNumSamples, &done))));
267
268 TimeTicks optimal_start = TimeTicks::Now() + poll1 + poll2;
269 syncer_thread()->Start(SyncerThread::NORMAL_MODE);
270 done.TimedWait(timeout());
271 syncer_thread()->Stop();
272
273 AnalyzePollRun(records, kMinNumSamples, optimal_start, poll2);
274 }
275
276 // Test that a sync session is run through to completion.
277 TEST_F(SyncerThread2Test, HasMoreToSync) {
278 syncer_thread()->Start(SyncerThread::NORMAL_MODE);
279 base::WaitableEvent done(false, false);
280 EXPECT_CALL(*syncer(), SyncShare(_))
281 .WillOnce(Invoke(sessions::test_util::SimulateHasMoreToSync))
282 .WillOnce(DoAll(Invoke(sessions::test_util::SimulateSuccess),
283 SignalEvent(&done)));
284 syncer_thread()->ScheduleNudge(zero(), NUDGE_SOURCE_LOCAL, ModelTypeBitSet());
285 done.TimedWait(timeout());
286 // If more nudges are scheduled, they'll be waited on by TearDown, and would
287 // cause our expectation to break.
288 }
289
290 // Test that no syncing occurs when throttled.
291 TEST_F(SyncerThread2Test, ThrottlingDoesThrottle) {
292 syncable::ModelTypeBitSet types;
293 types[syncable::BOOKMARKS] = true;
294 base::WaitableEvent done(false, false);
295 TimeDelta poll(TimeDelta::FromMilliseconds(5));
296 TimeDelta throttle(TimeDelta::FromMinutes(10));
297 syncer_thread()->OnReceivedLongPollIntervalUpdate(poll);
298 EXPECT_CALL(*syncer(), SyncShare(_))
299 .WillOnce(WithArg<0>(sessions::test_util::SimulateThrottled(throttle)));
300
301 syncer_thread()->Start(SyncerThread::NORMAL_MODE);
302 syncer_thread()->ScheduleNudge(zero(), NUDGE_SOURCE_LOCAL, types);
303 FlushLastTask(&done);
304
305 syncer_thread()->Start(SyncerThread::CONFIGURATION_MODE);
306 syncer_thread()->ScheduleConfig(zero(), types);
307 FlushLastTask(&done);
308 }
309
310 TEST_F(SyncerThread2Test, ThrottlingExpires) {
311 SyncShareRecords records;
312 base::WaitableEvent done(false, false);
313 TimeDelta poll(TimeDelta::FromMilliseconds(15));
314 TimeDelta throttle1(TimeDelta::FromMilliseconds(150));
315 TimeDelta throttle2(TimeDelta::FromMinutes(10));
316 syncer_thread()->OnReceivedLongPollIntervalUpdate(poll);
317
318 ::testing::InSequence seq;
319 EXPECT_CALL(*syncer(), SyncShare(_))
320 .WillOnce(WithArg<0>(sessions::test_util::SimulateThrottled(throttle1)))
321 .RetiresOnSaturation();
322 EXPECT_CALL(*syncer(), SyncShare(_))
323 .WillRepeatedly(DoAll(Invoke(sessions::test_util::SimulateSuccess),
324 WithArg<0>(RecordSyncShare(&records, kMinNumSamples, &done))));
325
326 TimeTicks optimal_start = TimeTicks::Now() + poll + throttle1;
327 syncer_thread()->Start(SyncerThread::NORMAL_MODE);
328 done.TimedWait(timeout());
329 syncer_thread()->Stop();
330
331 AnalyzePollRun(records, kMinNumSamples, optimal_start, poll);
332 }
333
334 // Test nudges / polls don't run in config mode and config tasks do.
335 TEST_F(SyncerThread2Test, ConfigurationMode) {
336 TimeDelta poll(TimeDelta::FromMilliseconds(15));
337 base::WaitableEvent done(false, false);
338 syncer_thread()->OnReceivedLongPollIntervalUpdate(poll);
339 EXPECT_CALL(*syncer(), SyncShare(_)).Times(0);
340 syncer_thread()->Start(SyncerThread::CONFIGURATION_MODE);
341 syncable::ModelTypeBitSet nudge_types;
342 nudge_types[syncable::AUTOFILL] = true;
343 syncer_thread()->ScheduleNudge(zero(), NUDGE_SOURCE_LOCAL, nudge_types);
344 syncer_thread()->ScheduleNudge(zero(), NUDGE_SOURCE_LOCAL, nudge_types);
345
346 syncable::ModelTypeBitSet config_types;
347 config_types[syncable::BOOKMARKS] = true;
348 // TODO(tim): This will fail once CONFIGURATION tasks are implemented. Update
349 // the EXPECT when that happens.
350 syncer_thread()->ScheduleConfig(zero(), config_types);
351 FlushLastTask(&done);
352 }
353
354 // Test that exponential backoff is properly triggered.
355 TEST_F(SyncerThread2Test, BackoffTriggers) {
356 base::WaitableEvent done(false, false);
357 UseMockDelayProvider();
358
359 EXPECT_CALL(*syncer(), SyncShare(_))
360 .WillOnce(Invoke(sessions::test_util::SimulateDownloadUpdatesFailed))
361 .WillOnce(DoAll(Invoke(sessions::test_util::SimulateSuccess),
362 SignalEvent(&done)));
363 EXPECT_FALSE(GetBackoffAndResetTest(&done));
364 // Note GetBackoffAndResetTest clears mocks and re-instantiates the syncer.
365 EXPECT_CALL(*syncer(), SyncShare(_))
366 .WillOnce(Invoke(sessions::test_util::SimulateCommitFailed))
367 .WillOnce(DoAll(Invoke(sessions::test_util::SimulateSuccess),
368 SignalEvent(&done)));
369 EXPECT_FALSE(GetBackoffAndResetTest(&done));
370 EXPECT_CALL(*syncer(), SyncShare(_))
371 .WillOnce(Invoke(sessions::test_util::SimulateDownloadUpdatesFailed))
372 .WillRepeatedly(DoAll(Invoke(
373 sessions::test_util::SimulateDownloadUpdatesFailed),
374 SignalEvent(&done)));
375 EXPECT_TRUE(GetBackoffAndResetTest(&done));
376 EXPECT_CALL(*syncer(), SyncShare(_))
377 .WillOnce(Invoke(sessions::test_util::SimulateCommitFailed))
378 .WillRepeatedly(DoAll(Invoke(sessions::test_util::SimulateCommitFailed),
379 SignalEvent(&done)));
380 EXPECT_TRUE(GetBackoffAndResetTest(&done));
381 EXPECT_CALL(*syncer(), SyncShare(_))
382 .WillOnce(Invoke(sessions::test_util::SimulateDownloadUpdatesFailed))
383 .WillOnce(Invoke(sessions::test_util::SimulateDownloadUpdatesFailed))
384 .WillRepeatedly(DoAll(Invoke(sessions::test_util::SimulateSuccess),
385 SignalEvent(&done)));
386 EXPECT_FALSE(GetBackoffAndResetTest(&done));
387 EXPECT_CALL(*syncer(), SyncShare(_))
388 .WillOnce(Invoke(sessions::test_util::SimulateCommitFailed))
389 .WillOnce(Invoke(sessions::test_util::SimulateCommitFailed))
390 .WillRepeatedly(DoAll(Invoke(sessions::test_util::SimulateSuccess),
391 SignalEvent(&done)));
392 EXPECT_FALSE(GetBackoffAndResetTest(&done));
393 }
394
395 // Test that no polls or extraneous nudges occur when in backoff.
396 TEST_F(SyncerThread2Test, BackoffDropsJobs) {
397 SyncShareRecords r;
398 TimeDelta poll(TimeDelta::FromMilliseconds(5));
399 base::WaitableEvent done(false, false);
400 syncable::ModelTypeBitSet types;
401 types[syncable::BOOKMARKS] = true;
402 syncer_thread()->OnReceivedLongPollIntervalUpdate(poll);
403 UseMockDelayProvider();
404
405 EXPECT_CALL(*syncer(), SyncShare(_)).Times(2)
406 .WillRepeatedly(DoAll(Invoke(sessions::test_util::SimulateCommitFailed),
407 RecordSyncShareAndPostSignal(&r, 2U, this, &done)));
408 EXPECT_CALL(*delay(), GetDelay(_))
409 .WillRepeatedly(Return(TimeDelta::FromDays(1)));
410
411 syncer_thread()->Start(SyncerThread::NORMAL_MODE);
412 ASSERT_TRUE(done.TimedWait(timeout()));
413 done.Reset();
414
415 Mock::VerifyAndClearExpectations(syncer());
416 EXPECT_EQ(2U, r.snapshots.size());
417 EXPECT_EQ(GetUpdatesCallerInfo::PERIODIC, r.snapshots[0]->source.first);
418 EXPECT_EQ(GetUpdatesCallerInfo::SYNC_CYCLE_CONTINUATION,
419 r.snapshots[1]->source.first);
420
421 EXPECT_CALL(*syncer(), SyncShare(_)).Times(1)
422 .WillOnce(DoAll(Invoke(sessions::test_util::SimulateCommitFailed),
423 RecordSyncShareAndPostSignal(&r, 1U, this, &done)));
424
425 // We schedule a nudge with enough delay (10X poll interval) that at least
426 // one or two polls would have taken place. The nudge should succeed.
427 syncer_thread()->ScheduleNudge(poll * 10, NUDGE_SOURCE_LOCAL, types);
428 ASSERT_TRUE(done.TimedWait(timeout()));
429 done.Reset();
430
431 Mock::VerifyAndClearExpectations(syncer());
432 Mock::VerifyAndClearExpectations(delay());
433 EXPECT_EQ(3U, r.snapshots.size());
434 EXPECT_EQ(GetUpdatesCallerInfo::LOCAL, r.snapshots[2]->source.first);
435
436 EXPECT_CALL(*syncer(), SyncShare(_)).Times(0);
437 EXPECT_CALL(*delay(), GetDelay(_)).Times(0);
438
439 syncer_thread()->Start(SyncerThread::CONFIGURATION_MODE);
440 syncer_thread()->ScheduleConfig(zero(), types);
441 FlushLastTask(&done);
442
443 syncer_thread()->Start(SyncerThread::NORMAL_MODE);
444 syncer_thread()->ScheduleNudge(zero(), NUDGE_SOURCE_LOCAL, types);
445 syncer_thread()->ScheduleNudge(zero(), NUDGE_SOURCE_LOCAL, types);
446 FlushLastTask(&done);
447 }
448
449 // Test that backoff is shaping traffic properly with consecutive errors.
450 TEST_F(SyncerThread2Test, BackoffElevation) {
451 SyncShareRecords r;
452 const TimeDelta poll(TimeDelta::FromMilliseconds(10));
453 base::WaitableEvent done(false, false);
454 syncer_thread()->OnReceivedLongPollIntervalUpdate(poll);
455 UseMockDelayProvider();
456
457 const TimeDelta first = TimeDelta::FromSeconds(1);
458 const TimeDelta second = TimeDelta::FromMilliseconds(10);
459 const TimeDelta third = TimeDelta::FromMilliseconds(20);
460 const TimeDelta fourth = TimeDelta::FromMilliseconds(30);
461 const TimeDelta fifth = TimeDelta::FromDays(1);
462
463 EXPECT_CALL(*syncer(), SyncShare(_)).Times(kMinNumSamples)
464 .WillRepeatedly(DoAll(Invoke(sessions::test_util::SimulateCommitFailed),
465 RecordSyncShareAndPostSignal(&r, kMinNumSamples, this, &done)));
466
467 EXPECT_CALL(*delay(), GetDelay(Eq(first))).WillOnce(Return(second))
468 .RetiresOnSaturation();
469 EXPECT_CALL(*delay(), GetDelay(Eq(second))).WillOnce(Return(third))
470 .RetiresOnSaturation();
471 EXPECT_CALL(*delay(), GetDelay(Eq(third))).WillOnce(Return(fourth))
472 .RetiresOnSaturation();
473 EXPECT_CALL(*delay(), GetDelay(Eq(fourth))).WillOnce(Return(fifth));
474
475 syncer_thread()->Start(SyncerThread::NORMAL_MODE);
476 ASSERT_TRUE(done.TimedWait(timeout()));
477
478 EXPECT_GE(r.times[2] - r.times[1], second);
479 EXPECT_GE(r.times[3] - r.times[2], third);
480 EXPECT_GE(r.times[4] - r.times[3], fourth);
481 }
482
483 // Test that things go back to normal once a canary task makes forward progress
484 // following a succession of failures.
485 TEST_F(SyncerThread2Test, BackoffRelief) {
486 SyncShareRecords r;
487 const TimeDelta poll(TimeDelta::FromMilliseconds(10));
488 base::WaitableEvent done(false, false);
489 syncer_thread()->OnReceivedLongPollIntervalUpdate(poll);
490 UseMockDelayProvider();
491
492 const TimeDelta backoff = TimeDelta::FromMilliseconds(100);
493
494 EXPECT_CALL(*syncer(), SyncShare(_))
495 .WillOnce(Invoke(sessions::test_util::SimulateCommitFailed))
496 .WillOnce(Invoke(sessions::test_util::SimulateCommitFailed))
497 .WillRepeatedly(DoAll(Invoke(sessions::test_util::SimulateSuccess),
498 RecordSyncShareAndPostSignal(&r, kMinNumSamples, this, &done)));
499 EXPECT_CALL(*delay(), GetDelay(_)).WillOnce(Return(backoff));
500
501 // Optimal start for the post-backoff poll party.
502 TimeTicks optimal_start = TimeTicks::Now() + poll + backoff;
503 syncer_thread()->Start(SyncerThread::NORMAL_MODE);
504 done.TimedWait(timeout());
505
506 // Check for healthy polling after backoff is relieved.
507 // Can't use AnalyzePollRun because first sync is a continuation. Bleh.
508 for (size_t i = 0; i < r.times.size(); i++) {
509 SCOPED_TRACE(testing::Message() << "SyncShare # (" << i << ")");
510 TimeTicks optimal_next_sync = optimal_start + poll * i;
511 EXPECT_GE(r.times[i], optimal_next_sync);
512 EXPECT_LT(r.times[i], optimal_next_sync + poll);
513 EXPECT_EQ(i == 0 ? GetUpdatesCallerInfo::SYNC_CYCLE_CONTINUATION
514 : GetUpdatesCallerInfo::PERIODIC,
515 r.snapshots[i]->source.first);
516 }
517 }
518
519 TEST_F(SyncerThread2Test, GetRecommendedDelay) {
520 EXPECT_LE(TimeDelta::FromSeconds(0),
521 SyncerThread::GetRecommendedDelay(TimeDelta::FromSeconds(0)));
522 EXPECT_LE(TimeDelta::FromSeconds(1),
523 SyncerThread::GetRecommendedDelay(TimeDelta::FromSeconds(1)));
524 EXPECT_LE(TimeDelta::FromSeconds(50),
525 SyncerThread::GetRecommendedDelay(TimeDelta::FromSeconds(50)));
526 EXPECT_LE(TimeDelta::FromSeconds(10),
527 SyncerThread::GetRecommendedDelay(TimeDelta::FromSeconds(10)));
528 EXPECT_EQ(TimeDelta::FromSeconds(kMaxBackoffSeconds),
529 SyncerThread::GetRecommendedDelay(
530 TimeDelta::FromSeconds(kMaxBackoffSeconds)));
531 EXPECT_EQ(TimeDelta::FromSeconds(kMaxBackoffSeconds),
532 SyncerThread::GetRecommendedDelay(
533 TimeDelta::FromSeconds(kMaxBackoffSeconds + 1)));
534 }
535
536 // Test config tasks don't run during normal mode.
537 // TODO(tim): Implement this test and then the functionality!
538 TEST_F(SyncerThread2Test, DISABLED_NoConfigDuringNormal) {
539 }
540
541 // Test that starting the syncer thread without a valid connection doesn't
542 // break things when a connection is detected.
543 // Test config tasks don't run during normal mode.
544 // TODO(tim): Implement this test and then the functionality!
545 TEST_F(SyncerThread2Test, DISABLED_StartWhenNotConnected) {
546
547 }
548
549 } // namespace s3
550 } // namespace browser_sync
551
552 // SyncerThread won't outlive the test!
553 DISABLE_RUNNABLE_METHOD_REFCOUNT(browser_sync::s3::SyncerThread2Test);
554
OLDNEW
« no previous file with comments | « chrome/browser/sync/engine/syncer_thread2.cc ('k') | chrome/browser/sync/engine/syncer_thread_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698