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

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: review+tests 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 GetBackoffAndReset(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 // SyncerThread won't outlive the test!
143 DISABLE_RUNNABLE_METHOD_REFCOUNT(SyncerThread2Test);
144
145 bool RecordSyncShareImpl(SyncSession* s, SyncShareRecords* record,
146 size_t signal_after) {
147 record->times.push_back(TimeTicks::Now());
148 record->snapshots.push_back(make_linked_ptr(new SyncSessionSnapshot(
149 s->TakeSnapshot())));
150 return record->times.size() >= signal_after;
151 }
152
153 ACTION_P4(RecordSyncShareAndPostSignal, record, signal_after, test, event) {
154 if (RecordSyncShareImpl(arg0, record, signal_after) && event)
155 test->PostSignalTask(event);
156 }
157
158 ACTION_P3(RecordSyncShare, record, signal_after, event) {
159 if (RecordSyncShareImpl(arg0, record, signal_after) && event)
160 event->Signal();
161 }
162
163 ACTION_P(SignalEvent, event) {
164 SyncerThread2Test::SignalWaitableEvent(event);
165 }
166
167 // Test nudge scheduling.
168 TEST_F(SyncerThread2Test, Nudge) {
169 syncer_thread()->Start(SyncerThread::NORMAL_MODE);
170 base::WaitableEvent done(false, false);
171 SyncShareRecords records;
172 syncable::ModelTypeBitSet model_types;
173 model_types[syncable::BOOKMARKS] = true;
174
175 EXPECT_CALL(*syncer(), SyncShare(_))
176 .WillOnce(DoAll(Invoke(sessions::test_util::SimulateSuccess),
177 WithArg<0>(RecordSyncShare(&records, 1U, &done))));
178 syncer_thread()->ScheduleNudge(zero(), NUDGE_SOURCE_LOCAL, model_types);
179 done.TimedWait(timeout());
180
181 EXPECT_EQ(1, records.snapshots.size());
182 EXPECT_EQ(model_types, records.snapshots[0]->source.second);
183 EXPECT_EQ(GetUpdatesCallerInfo::LOCAL, records.snapshots[0]->source.first);
184 }
185
186 // Test that nudges are coalesced.
187 TEST_F(SyncerThread2Test, NudgeCoalescing) {
188 syncer_thread()->Start(SyncerThread::NORMAL_MODE);
189 base::WaitableEvent done(false, false);
190 SyncShareRecords r;
191 EXPECT_CALL(*syncer(), SyncShare(_))
192 .WillOnce(DoAll(Invoke(sessions::test_util::SimulateSuccess),
193 WithArg<0>(RecordSyncShare(&r, 1U, &done))));
194 syncable::ModelTypeBitSet types1, types2, types3;
195 types1[syncable::BOOKMARKS] = true;
196 types2[syncable::AUTOFILL] = true;
197 types3[syncable::THEMES] = true;
198 TimeDelta delay = TimeDelta::FromMilliseconds(20);
199 TimeTicks optimal_time = TimeTicks::Now() + delay;
200 syncer_thread()->ScheduleNudge(delay, NUDGE_SOURCE_UNKNOWN, types1);
201 syncer_thread()->ScheduleNudge(zero(), NUDGE_SOURCE_LOCAL, types2);
202 syncer_thread()->ScheduleNudge(zero(), NUDGE_SOURCE_NOTIFICATION, types3);
203 done.TimedWait(timeout());
204
205 EXPECT_EQ(1, r.snapshots.size());
206 EXPECT_GE(r.times[0], optimal_time);
207 EXPECT_EQ(types1 | types2 | types3, r.snapshots[0]->source.second);
208 EXPECT_EQ(GetUpdatesCallerInfo::NOTIFICATION, r.snapshots[0]->source.first);
209
210 SyncShareRecords r2;
211 EXPECT_CALL(*syncer(), SyncShare(_))
212 .WillOnce(DoAll(Invoke(sessions::test_util::SimulateSuccess),
213 WithArg<0>(RecordSyncShare(&r2, 1U, &done))));
214 syncer_thread()->ScheduleNudge(zero(), NUDGE_SOURCE_NOTIFICATION, types3);
215 done.TimedWait(timeout());
216 EXPECT_EQ(1, r2.snapshots.size());
217 EXPECT_EQ(types3, r2.snapshots[0]->source.second);
218 EXPECT_EQ(GetUpdatesCallerInfo::NOTIFICATION, r2.snapshots[0]->source.first);
219 }
220
221 // Test that polling works as expected.
222 TEST_F(SyncerThread2Test, Polling) {
223 SyncShareRecords records;
224 base::WaitableEvent done(false, false);
225 TimeDelta poll_interval(TimeDelta::FromMilliseconds(30));
226 syncer_thread()->OnReceivedLongPollIntervalUpdate(poll_interval);
227 EXPECT_CALL(*syncer(), SyncShare(_)).Times(AtLeast(kMinNumSamples))
228 .WillRepeatedly(DoAll(Invoke(sessions::test_util::SimulateSuccess),
229 WithArg<0>(RecordSyncShare(&records, kMinNumSamples, &done))));
230
231 TimeTicks optimal_start = TimeTicks::Now() + poll_interval;
232 syncer_thread()->Start(SyncerThread::NORMAL_MODE);
233 done.TimedWait(timeout());
234 syncer_thread()->Stop();
235
236 AnalyzePollRun(records, kMinNumSamples, optimal_start, poll_interval);
237 }
238
239 // Test that the short poll interval is used.
240 TEST_F(SyncerThread2Test, PollNotificationsDisabled) {
241 SyncShareRecords records;
242 base::WaitableEvent done(false, false);
243 TimeDelta poll_interval(TimeDelta::FromMilliseconds(30));
244 syncer_thread()->OnReceivedShortPollIntervalUpdate(poll_interval);
245 syncer_thread()->set_notifications_enabled(false);
246 EXPECT_CALL(*syncer(), SyncShare(_)).Times(AtLeast(kMinNumSamples))
247 .WillRepeatedly(DoAll(Invoke(sessions::test_util::SimulateSuccess),
248 WithArg<0>(RecordSyncShare(&records, kMinNumSamples, &done))));
249
250 TimeTicks optimal_start = TimeTicks::Now() + poll_interval;
251 syncer_thread()->Start(SyncerThread::NORMAL_MODE);
252 done.TimedWait(timeout());
253 syncer_thread()->Stop();
254
255 AnalyzePollRun(records, kMinNumSamples, optimal_start, poll_interval);
256 }
257
258 // Test that polling intervals are updated when needed.
259 TEST_F(SyncerThread2Test, PollIntervalUpdate) {
260 SyncShareRecords records;
261 base::WaitableEvent done(false, false);
262 TimeDelta poll1(TimeDelta::FromMilliseconds(120));
263 TimeDelta poll2(TimeDelta::FromMilliseconds(30));
264 syncer_thread()->OnReceivedLongPollIntervalUpdate(poll1);
265 EXPECT_CALL(*syncer(), SyncShare(_)).Times(AtLeast(kMinNumSamples))
266 .WillOnce(WithArg<0>(
267 sessions::test_util::SimulatePollIntervalUpdate(poll2)))
268 .WillRepeatedly(DoAll(Invoke(sessions::test_util::SimulateSuccess),
269 WithArg<0>(RecordSyncShare(&records, kMinNumSamples, &done))));
270
271 TimeTicks optimal_start = TimeTicks::Now() + poll1 + poll2;
272 syncer_thread()->Start(SyncerThread::NORMAL_MODE);
273 done.TimedWait(timeout());
274 syncer_thread()->Stop();
275
276 AnalyzePollRun(records, kMinNumSamples, optimal_start, poll2);
277 }
278
279 // Test that a sync session is run through to completion.
280 TEST_F(SyncerThread2Test, HasMoreToSync) {
281 syncer_thread()->Start(SyncerThread::NORMAL_MODE);
282 base::WaitableEvent done(false, false);
283 EXPECT_CALL(*syncer(), SyncShare(_))
284 .WillOnce(Invoke(sessions::test_util::SimulateHasMoreToSync))
285 .WillOnce(DoAll(Invoke(sessions::test_util::SimulateSuccess),
286 SignalEvent(&done)));
287 syncer_thread()->ScheduleNudge(zero(), NUDGE_SOURCE_LOCAL, ModelTypeBitSet());
288 done.TimedWait(timeout());
289 // If more nudges are scheduled, they'll be waited on by TearDown, and would
290 // cause our expectation to break.
291 }
292
293 // Test that no syncing occurs when throttled.
294 TEST_F(SyncerThread2Test, ThrottlingDoesThrottle) {
295 syncable::ModelTypeBitSet types;
296 types[syncable::BOOKMARKS] = true;
297 base::WaitableEvent done(false, false);
298 TimeDelta poll(TimeDelta::FromMilliseconds(5));
299 TimeDelta throttle(TimeDelta::FromMinutes(10));
300 syncer_thread()->OnReceivedLongPollIntervalUpdate(poll);
301 EXPECT_CALL(*syncer(), SyncShare(_))
302 .WillOnce(WithArg<0>(sessions::test_util::SimulateThrottled(throttle)));
303
304 syncer_thread()->Start(SyncerThread::NORMAL_MODE);
305 syncer_thread()->ScheduleNudge(zero(), NUDGE_SOURCE_LOCAL, types);
306 FlushLastTask(&done);
307
308 syncer_thread()->Start(SyncerThread::CONFIGURATION_MODE);
309 syncer_thread()->ScheduleConfig(zero(), types);
310 FlushLastTask(&done);
311 }
312
313 TEST_F(SyncerThread2Test, ThrottlingExpires) {
314 SyncShareRecords records;
315 base::WaitableEvent done(false, false);
316 TimeDelta poll(TimeDelta::FromMilliseconds(15));
317 TimeDelta throttle1(TimeDelta::FromMilliseconds(150));
318 TimeDelta throttle2(TimeDelta::FromMinutes(10));
319 syncer_thread()->OnReceivedLongPollIntervalUpdate(poll);
320
321 ::testing::InSequence seq;
322 EXPECT_CALL(*syncer(), SyncShare(_))
323 .WillOnce(WithArg<0>(sessions::test_util::SimulateThrottled(throttle1)))
324 .RetiresOnSaturation();
325 EXPECT_CALL(*syncer(), SyncShare(_))
326 .WillRepeatedly(DoAll(Invoke(sessions::test_util::SimulateSuccess),
327 WithArg<0>(RecordSyncShare(&records, kMinNumSamples, &done))));
328
329 TimeTicks optimal_start = TimeTicks::Now() + poll + throttle1;
330 syncer_thread()->Start(SyncerThread::NORMAL_MODE);
331 done.TimedWait(timeout());
332 syncer_thread()->Stop();
333
334 AnalyzePollRun(records, kMinNumSamples, optimal_start, poll);
335 }
336
337 // Test nudges / polls don't run in config mode and config tasks do.
338 TEST_F(SyncerThread2Test, ConfigurationMode) {
339 TimeDelta poll(TimeDelta::FromMilliseconds(15));
340 base::WaitableEvent done(false, false);
341 syncer_thread()->OnReceivedLongPollIntervalUpdate(poll);
342 EXPECT_CALL(*syncer(), SyncShare(_)).Times(0);
343 syncer_thread()->Start(SyncerThread::CONFIGURATION_MODE);
344 syncable::ModelTypeBitSet nudge_types;
345 nudge_types[syncable::AUTOFILL] = true;
346 syncer_thread()->ScheduleNudge(zero(), NUDGE_SOURCE_LOCAL, nudge_types);
347 syncer_thread()->ScheduleNudge(zero(), NUDGE_SOURCE_LOCAL, nudge_types);
348
349 syncable::ModelTypeBitSet config_types;
350 config_types[syncable::BOOKMARKS] = true;
351 // TODO(tim): This will fail once CONFIGURATION tasks are implemented. Update
352 // the EXPECT when that happens.
353 syncer_thread()->ScheduleConfig(zero(), config_types);
354 FlushLastTask(&done);
355 }
356
357 // Test that exponential backoff is properly triggered.
358 TEST_F(SyncerThread2Test, BackoffTriggers) {
359 base::WaitableEvent done(false, false);
360 UseMockDelayProvider();
361
362 EXPECT_CALL(*syncer(), SyncShare(_))
363 .WillOnce(Invoke(sessions::test_util::SimulateDownloadUpdatesFailed))
364 .WillOnce(DoAll(Invoke(sessions::test_util::SimulateSuccess),
365 SignalEvent(&done)));
366 EXPECT_FALSE(GetBackoffAndReset(&done));
akalin 2011/01/25 06:09:53 according to the gmock docs, results are undefined
tim (not reviewing) 2011/01/25 17:15:22 Not sure what you mean here, can you elaborate? No
akalin 2011/01/25 19:20:14 Oh, I was referring to this line from the gmock do
367 EXPECT_CALL(*syncer(), SyncShare(_))
368 .WillOnce(Invoke(sessions::test_util::SimulateCommitFailed))
369 .WillOnce(DoAll(Invoke(sessions::test_util::SimulateSuccess),
370 SignalEvent(&done)));
371 EXPECT_FALSE(GetBackoffAndReset(&done));
372 EXPECT_CALL(*syncer(), SyncShare(_))
373 .WillOnce(Invoke(sessions::test_util::SimulateDownloadUpdatesFailed))
374 .WillRepeatedly(DoAll(Invoke(
375 sessions::test_util::SimulateDownloadUpdatesFailed),
376 SignalEvent(&done)));
377 EXPECT_TRUE(GetBackoffAndReset(&done));
378 EXPECT_CALL(*syncer(), SyncShare(_))
379 .WillOnce(Invoke(sessions::test_util::SimulateCommitFailed))
380 .WillRepeatedly(DoAll(Invoke(sessions::test_util::SimulateCommitFailed),
381 SignalEvent(&done)));
382 EXPECT_TRUE(GetBackoffAndReset(&done));
383 EXPECT_CALL(*syncer(), SyncShare(_))
384 .WillOnce(Invoke(sessions::test_util::SimulateDownloadUpdatesFailed))
385 .WillOnce(Invoke(sessions::test_util::SimulateDownloadUpdatesFailed))
386 .WillRepeatedly(DoAll(Invoke(sessions::test_util::SimulateSuccess),
387 SignalEvent(&done)));
388 EXPECT_FALSE(GetBackoffAndReset(&done));
389 EXPECT_CALL(*syncer(), SyncShare(_))
390 .WillOnce(Invoke(sessions::test_util::SimulateCommitFailed))
391 .WillOnce(Invoke(sessions::test_util::SimulateCommitFailed))
392 .WillRepeatedly(DoAll(Invoke(sessions::test_util::SimulateSuccess),
393 SignalEvent(&done)));
394 EXPECT_FALSE(GetBackoffAndReset(&done));
395 }
396
397 // Test that no polls or extraneous nudges occur when in backoff.
398 TEST_F(SyncerThread2Test, BackoffDropsJobs) {
399 SyncShareRecords r;
400 TimeDelta poll(TimeDelta::FromMilliseconds(5));
401 base::WaitableEvent done(false, false);
402 syncable::ModelTypeBitSet types;
403 types[syncable::BOOKMARKS] = true;
404 syncer_thread()->OnReceivedLongPollIntervalUpdate(poll);
405 UseMockDelayProvider();
406
407 EXPECT_CALL(*syncer(), SyncShare(_)).Times(2)
408 .WillRepeatedly(DoAll(Invoke(sessions::test_util::SimulateCommitFailed),
409 RecordSyncShareAndPostSignal(&r, 2U, this, &done)));
410 EXPECT_CALL(*delay(), GetDelay(_))
411 .WillRepeatedly(Return(TimeDelta::FromDays(1)));
412
413 syncer_thread()->Start(SyncerThread::NORMAL_MODE);
414 ASSERT_TRUE(done.TimedWait(timeout()));
415 done.Reset();
416
417 Mock::VerifyAndClearExpectations(syncer());
418 EXPECT_EQ(2U, r.snapshots.size());
419 EXPECT_EQ(GetUpdatesCallerInfo::PERIODIC, r.snapshots[0]->source.first);
420 EXPECT_EQ(GetUpdatesCallerInfo::SYNC_CYCLE_CONTINUATION,
421 r.snapshots[1]->source.first);
422
423 EXPECT_CALL(*syncer(), SyncShare(_)).Times(1)
424 .WillOnce(DoAll(Invoke(sessions::test_util::SimulateCommitFailed),
425 RecordSyncShareAndPostSignal(&r, 1U, this, &done)));
426
427 // We schedule a nudge with enough delay (10X poll interval) that at least
428 // one or two polls would have taken place. The nudge should succeed.
429 syncer_thread()->ScheduleNudge(poll * 10, NUDGE_SOURCE_LOCAL, types);
430 ASSERT_TRUE(done.TimedWait(timeout()));
431 done.Reset();
432
433 Mock::VerifyAndClearExpectations(syncer());
434 Mock::VerifyAndClearExpectations(delay());
435 EXPECT_EQ(3U, r.snapshots.size());
436 EXPECT_EQ(GetUpdatesCallerInfo::LOCAL, r.snapshots[2]->source.first);
437
438 EXPECT_CALL(*syncer(), SyncShare(_)).Times(0);
439 EXPECT_CALL(*delay(), GetDelay(_)).Times(0);
440
441 syncer_thread()->Start(SyncerThread::CONFIGURATION_MODE);
442 syncer_thread()->ScheduleConfig(zero(), types);
443 FlushLastTask(&done);
444
445 syncer_thread()->Start(SyncerThread::NORMAL_MODE);
446 syncer_thread()->ScheduleNudge(zero(), NUDGE_SOURCE_LOCAL, types);
447 syncer_thread()->ScheduleNudge(zero(), NUDGE_SOURCE_LOCAL, types);
448 FlushLastTask(&done);
449 }
450
451 // Test that backoff is shaping traffic properly with consecutive errors.
452 TEST_F(SyncerThread2Test, BackoffElevation) {
453 SyncShareRecords r;
454 const TimeDelta poll(TimeDelta::FromMilliseconds(10));
455 base::WaitableEvent done(false, false);
456 syncer_thread()->OnReceivedLongPollIntervalUpdate(poll);
457 UseMockDelayProvider();
458
459 const TimeDelta first = TimeDelta::FromSeconds(1);
460 const TimeDelta second = TimeDelta::FromMilliseconds(10);
461 const TimeDelta third = TimeDelta::FromMilliseconds(20);
462 const TimeDelta fourth = TimeDelta::FromMilliseconds(30);
463 const TimeDelta fifth = TimeDelta::FromDays(1);
464
465 EXPECT_CALL(*syncer(), SyncShare(_)).Times(kMinNumSamples)
466 .WillRepeatedly(DoAll(Invoke(sessions::test_util::SimulateCommitFailed),
467 RecordSyncShareAndPostSignal(&r, kMinNumSamples, this, &done)));
468
469 EXPECT_CALL(*delay(), GetDelay(Eq(first))).WillOnce(Return(second))
470 .RetiresOnSaturation();
471 EXPECT_CALL(*delay(), GetDelay(Eq(second))).WillOnce(Return(third))
472 .RetiresOnSaturation();
473 EXPECT_CALL(*delay(), GetDelay(Eq(third))).WillOnce(Return(fourth))
474 .RetiresOnSaturation();
475 EXPECT_CALL(*delay(), GetDelay(Eq(fourth))).WillOnce(Return(fifth));
476
477 syncer_thread()->Start(SyncerThread::NORMAL_MODE);
478 ASSERT_TRUE(done.TimedWait(timeout()));
479
480 EXPECT_GE(r.times[2] - r.times[1], second);
481 EXPECT_GE(r.times[3] - r.times[2], third);
482 EXPECT_GE(r.times[4] - r.times[3], fourth);
483 }
484
485 // Test that things go back to normal once a canary task makes forward progress
486 // following a succession of failures.
487 TEST_F(SyncerThread2Test, BackoffRelief) {
488 SyncShareRecords r;
489 const TimeDelta poll(TimeDelta::FromMilliseconds(10));
490 base::WaitableEvent done(false, false);
491 syncer_thread()->OnReceivedLongPollIntervalUpdate(poll);
492 UseMockDelayProvider();
493
494 const TimeDelta backoff = TimeDelta::FromMilliseconds(100);
495
496 EXPECT_CALL(*syncer(), SyncShare(_))
497 .WillOnce(Invoke(sessions::test_util::SimulateCommitFailed))
498 .WillOnce(Invoke(sessions::test_util::SimulateCommitFailed))
499 .WillRepeatedly(DoAll(Invoke(sessions::test_util::SimulateSuccess),
500 RecordSyncShareAndPostSignal(&r, kMinNumSamples, this, &done)));
501 EXPECT_CALL(*delay(), GetDelay(_)).WillOnce(Return(backoff));
502
503 // Optimal start for the post-backoff poll party.
504 TimeTicks optimal_start = TimeTicks::Now() + poll + backoff;
505 syncer_thread()->Start(SyncerThread::NORMAL_MODE);
506 done.TimedWait(timeout());
507
508 // Check for healthy polling after backoff is relieved.
509 // Can't use AnalyzePollRun because first sync is a continuation. Bleh.
510 for (size_t i = 0; i < r.times.size(); i++) {
511 SCOPED_TRACE(testing::Message() << "SyncShare # (" << i << ")");
512 TimeTicks optimal_next_sync = optimal_start + poll * i;
513 EXPECT_GE(r.times[i], optimal_next_sync);
514 EXPECT_LT(r.times[i], optimal_next_sync + poll);
515 EXPECT_EQ(i == 0 ? GetUpdatesCallerInfo::SYNC_CYCLE_CONTINUATION
516 : GetUpdatesCallerInfo::PERIODIC,
517 r.snapshots[i]->source.first);
518 }
519 }
520
521 TEST_F(SyncerThread2Test, GetRecommendedDelay) {
522 EXPECT_LE(TimeDelta::FromSeconds(0),
523 SyncerThread::GetRecommendedDelay(TimeDelta::FromSeconds(0)));
524 EXPECT_LE(TimeDelta::FromSeconds(1),
525 SyncerThread::GetRecommendedDelay(TimeDelta::FromSeconds(1)));
526 EXPECT_LE(TimeDelta::FromSeconds(50),
527 SyncerThread::GetRecommendedDelay(TimeDelta::FromSeconds(50)));
528 EXPECT_LE(TimeDelta::FromSeconds(10),
529 SyncerThread::GetRecommendedDelay(TimeDelta::FromSeconds(10)));
530 EXPECT_EQ(TimeDelta::FromSeconds(kMaxBackoffSeconds),
531 SyncerThread::GetRecommendedDelay(
532 TimeDelta::FromSeconds(kMaxBackoffSeconds)));
533 EXPECT_EQ(TimeDelta::FromSeconds(kMaxBackoffSeconds),
534 SyncerThread::GetRecommendedDelay(
535 TimeDelta::FromSeconds(kMaxBackoffSeconds + 1)));
536 }
537
538 // Test config tasks don't run during normal mode.
akalin 2011/01/25 06:09:53 Do you need a TODO here?
539 TEST_F(SyncerThread2Test, DISABLED_NoConfigDuringNormal) {
540 }
541
542 // Test that starting the syncer thread without a valid connection doesn't
543 // break things when a connection is detected.
544 TEST_F(SyncerThread2Test, DISABLED_StartWhenNotConnected) {
545
546 }
547
548 } // namespace s3
549 } // namespace browser_sync
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698