Home | History | Annotate | Download | only in engine
      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_thread.h"
     10 #include "chrome/browser/sync/sessions/test_util.h"
     11 #include "chrome/test/sync/engine/mock_connection_manager.h"
     12 #include "chrome/test/sync/engine/test_directory_setter_upper.h"
     13 #include "testing/gtest/include/gtest/gtest.h"
     14 #include "testing/gmock/include/gmock/gmock.h"
     15 
     16 using base::TimeDelta;
     17 using base::TimeTicks;
     18 using testing::_;
     19 using testing::AtLeast;
     20 using testing::DoAll;
     21 using testing::Eq;
     22 using testing::Invoke;
     23 using testing::Mock;
     24 using testing::Return;
     25 using testing::WithArg;
     26 
     27 namespace browser_sync {
     28 using sessions::SyncSession;
     29 using sessions::SyncSessionContext;
     30 using sessions::SyncSessionSnapshot;
     31 using syncable::ModelTypeBitSet;
     32 using sync_pb::GetUpdatesCallerInfo;
     33 
     34 class MockSyncer : public Syncer {
     35  public:
     36   MOCK_METHOD3(SyncShare, void(sessions::SyncSession*, SyncerStep,
     37                                SyncerStep));
     38 };
     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 class SyncerThread2Test : public testing::Test {
     49  public:
     50   class MockDelayProvider : public SyncerThread::DelayProvider {
     51    public:
     52     MOCK_METHOD1(GetDelay, TimeDelta(const TimeDelta&));
     53   };
     54 
     55   virtual void SetUp() {
     56     syncdb_.SetUp();
     57     syncer_ = new MockSyncer();
     58     delay_ = NULL;
     59     registrar_.reset(MockModelSafeWorkerRegistrar::PassiveBookmarks());
     60     connection_.reset(new MockConnectionManager(syncdb_.manager(), "Test"));
     61     connection_->SetServerReachable();
     62     context_ = new SyncSessionContext(connection_.get(), syncdb_.manager(),
     63         registrar_.get(), std::vector<SyncEngineEventListener*>());
     64     context_->set_notifications_enabled(true);
     65     context_->set_account_name("Test");
     66     syncer_thread_.reset(new SyncerThread(context_, syncer_));
     67   }
     68 
     69   virtual void SetUpWithTypes(syncable::ModelTypeBitSet types) {
     70     syncdb_.SetUp();
     71     syncer_ = new MockSyncer();
     72     delay_ = NULL;
     73     registrar_.reset(MockModelSafeWorkerRegistrar::PassiveForTypes(types));
     74     connection_.reset(new MockConnectionManager(syncdb_.manager(), "Test"));
     75     connection_->SetServerReachable();
     76     context_ = new SyncSessionContext(connection_.get(), syncdb_.manager(),
     77         registrar_.get(), std::vector<SyncEngineEventListener*>());
     78     context_->set_notifications_enabled(true);
     79     context_->set_account_name("Test");
     80     syncer_thread_.reset(new SyncerThread(context_, syncer_));
     81   }
     82 
     83   SyncerThread* syncer_thread() { return syncer_thread_.get(); }
     84   MockSyncer* syncer() { return syncer_; }
     85   MockDelayProvider* delay() { return delay_; }
     86   MockConnectionManager* connection() { return connection_.get(); }
     87   TimeDelta zero() { return TimeDelta::FromSeconds(0); }
     88   TimeDelta timeout() {
     89     return TimeDelta::FromMilliseconds(TestTimeouts::action_timeout_ms());
     90   }
     91 
     92   virtual void TearDown() {
     93     syncer_thread()->Stop();
     94     syncdb_.TearDown();
     95   }
     96 
     97   void AnalyzePollRun(const SyncShareRecords& records, size_t min_num_samples,
     98       const TimeTicks& optimal_start, const TimeDelta& poll_interval) {
     99     const std::vector<TimeTicks>& data(records.times);
    100     EXPECT_GE(data.size(), min_num_samples);
    101     for (size_t i = 0; i < data.size(); i++) {
    102       SCOPED_TRACE(testing::Message() << "SyncShare # (" << i << ")");
    103       TimeTicks optimal_next_sync = optimal_start + poll_interval * i;
    104       EXPECT_GE(data[i], optimal_next_sync);
    105       EXPECT_EQ(GetUpdatesCallerInfo::PERIODIC,
    106                 records.snapshots[i]->source.updates_source);
    107     }
    108   }
    109 
    110   bool GetBackoffAndResetTest(base::WaitableEvent* done) {
    111     syncable::ModelTypeBitSet nudge_types;
    112     syncer_thread()->Start(SyncerThread::NORMAL_MODE, NULL);
    113     syncer_thread()->ScheduleNudge(zero(), NUDGE_SOURCE_LOCAL, nudge_types,
    114                                    FROM_HERE);
    115     done->TimedWait(timeout());
    116     TearDown();
    117     done->Reset();
    118     Mock::VerifyAndClearExpectations(syncer());
    119     bool backing_off = syncer_thread()->IsBackingOff();
    120     SetUp();
    121     UseMockDelayProvider();
    122     EXPECT_CALL(*delay(), GetDelay(_))
    123         .WillRepeatedly(Return(TimeDelta::FromMilliseconds(1)));
    124     return backing_off;
    125   }
    126 
    127   void UseMockDelayProvider() {
    128     delay_ = new MockDelayProvider();
    129     syncer_thread_->delay_provider_.reset(delay_);
    130   }
    131 
    132   void PostSignalTask(base::WaitableEvent* done) {
    133     syncer_thread_->thread_.message_loop()->PostTask(FROM_HERE,
    134         NewRunnableFunction(&SyncerThread2Test::SignalWaitableEvent, done));
    135   }
    136 
    137   void FlushLastTask(base::WaitableEvent* done) {
    138     PostSignalTask(done);
    139     done->TimedWait(timeout());
    140     done->Reset();
    141   }
    142 
    143   static void SignalWaitableEvent(base::WaitableEvent* event) {
    144     event->Signal();
    145   }
    146 
    147   static void QuitMessageLoop() {
    148     MessageLoop::current()->Quit();
    149   }
    150 
    151   // Compare a ModelTypeBitSet to a ModelTypePayloadMap, ignoring
    152   // payload values.
    153   bool CompareModelTypeBitSetToModelTypePayloadMap(
    154       const syncable::ModelTypeBitSet& lhs,
    155       const syncable::ModelTypePayloadMap& rhs) {
    156     size_t count = 0;
    157     for (syncable::ModelTypePayloadMap::const_iterator i = rhs.begin();
    158          i != rhs.end(); ++i, ++count) {
    159       if (!lhs.test(i->first))
    160         return false;
    161     }
    162     if (lhs.count() != count)
    163       return false;
    164     return true;
    165   }
    166 
    167   SyncSessionContext* context() { return context_; }
    168 
    169  private:
    170   scoped_ptr<SyncerThread> syncer_thread_;
    171   scoped_ptr<MockConnectionManager> connection_;
    172   SyncSessionContext* context_;
    173   MockSyncer* syncer_;
    174   MockDelayProvider* delay_;
    175   scoped_ptr<MockModelSafeWorkerRegistrar> registrar_;
    176   MockDirectorySetterUpper syncdb_;
    177 };
    178 
    179 bool RecordSyncShareImpl(SyncSession* s, SyncShareRecords* record,
    180                          size_t signal_after) {
    181   record->times.push_back(TimeTicks::Now());
    182   record->snapshots.push_back(make_linked_ptr(new SyncSessionSnapshot(
    183       s->TakeSnapshot())));
    184   return record->times.size() >= signal_after;
    185 }
    186 
    187 ACTION_P4(RecordSyncShareAndPostSignal, record, signal_after, test, event) {
    188   if (RecordSyncShareImpl(arg0, record, signal_after) && event)
    189     test->PostSignalTask(event);
    190 }
    191 
    192 ACTION_P3(RecordSyncShare, record, signal_after, event) {
    193   if (RecordSyncShareImpl(arg0, record, signal_after) && event)
    194     event->Signal();
    195 }
    196 
    197 ACTION_P(SignalEvent, event) {
    198   SyncerThread2Test::SignalWaitableEvent(event);
    199 }
    200 
    201 // Test nudge scheduling.
    202 TEST_F(SyncerThread2Test, Nudge) {
    203   syncer_thread()->Start(SyncerThread::NORMAL_MODE, NULL);
    204   base::WaitableEvent done(false, false);
    205   SyncShareRecords records;
    206   syncable::ModelTypeBitSet model_types;
    207   model_types[syncable::BOOKMARKS] = true;
    208 
    209   EXPECT_CALL(*syncer(), SyncShare(_,_,_))
    210       .WillOnce(DoAll(Invoke(sessions::test_util::SimulateSuccess),
    211           WithArg<0>(RecordSyncShare(&records, 1U, &done))))
    212       .RetiresOnSaturation();
    213   syncer_thread()->ScheduleNudge(zero(), NUDGE_SOURCE_LOCAL, model_types,
    214                                  FROM_HERE);
    215   done.TimedWait(timeout());
    216 
    217   EXPECT_EQ(1U, records.snapshots.size());
    218   EXPECT_TRUE(CompareModelTypeBitSetToModelTypePayloadMap(model_types,
    219       records.snapshots[0]->source.types));
    220   EXPECT_EQ(GetUpdatesCallerInfo::LOCAL,
    221             records.snapshots[0]->source.updates_source);
    222 
    223   // Make sure a second, later, nudge is unaffected by first (no coalescing).
    224   SyncShareRecords records2;
    225   model_types[syncable::BOOKMARKS] = false;
    226   model_types[syncable::AUTOFILL] = true;
    227   EXPECT_CALL(*syncer(), SyncShare(_,_,_))
    228       .WillOnce(DoAll(Invoke(sessions::test_util::SimulateSuccess),
    229           WithArg<0>(RecordSyncShare(&records2, 1U, &done))));
    230   syncer_thread()->ScheduleNudge(zero(), NUDGE_SOURCE_LOCAL, model_types,
    231                                  FROM_HERE);
    232   done.TimedWait(timeout());
    233 
    234   EXPECT_EQ(1U, records2.snapshots.size());
    235   EXPECT_TRUE(CompareModelTypeBitSetToModelTypePayloadMap(model_types,
    236       records2.snapshots[0]->source.types));
    237   EXPECT_EQ(GetUpdatesCallerInfo::LOCAL,
    238             records2.snapshots[0]->source.updates_source);
    239 }
    240 
    241 // Make sure a regular config command is scheduled fine in the absence of any
    242 // errors.
    243 TEST_F(SyncerThread2Test, Config) {
    244   base::WaitableEvent done(false, false);
    245   SyncShareRecords records;
    246   syncable::ModelTypeBitSet model_types;
    247   model_types[syncable::BOOKMARKS] = true;
    248 
    249   EXPECT_CALL(*syncer(), SyncShare(_,_,_))
    250       .WillOnce(DoAll(Invoke(sessions::test_util::SimulateSuccess),
    251           WithArg<0>(RecordSyncShare(&records, 1U, &done))));
    252 
    253   syncer_thread()->Start(SyncerThread::CONFIGURATION_MODE, NULL);
    254 
    255   syncer_thread()->ScheduleConfig(model_types);
    256   done.TimedWait(timeout());
    257 
    258   EXPECT_EQ(1U, records.snapshots.size());
    259   EXPECT_TRUE(CompareModelTypeBitSetToModelTypePayloadMap(model_types,
    260       records.snapshots[0]->source.types));
    261   EXPECT_EQ(GetUpdatesCallerInfo::FIRST_UPDATE,
    262             records.snapshots[0]->source.updates_source);
    263 }
    264 
    265 // Simulate a failure and make sure the config request is retried.
    266 TEST_F(SyncerThread2Test, ConfigWithBackingOff) {
    267   base::WaitableEvent done(false, false);
    268   base::WaitableEvent* dummy = NULL;
    269   UseMockDelayProvider();
    270   EXPECT_CALL(*delay(), GetDelay(_))
    271       .WillRepeatedly(Return(TimeDelta::FromMilliseconds(1)));
    272   SyncShareRecords records;
    273   syncable::ModelTypeBitSet model_types;
    274   model_types[syncable::BOOKMARKS] = true;
    275 
    276   EXPECT_CALL(*syncer(), SyncShare(_,_,_))
    277       .WillOnce(DoAll(Invoke(sessions::test_util::SimulateCommitFailed),
    278           WithArg<0>(RecordSyncShare(&records, 1U, dummy))))
    279       .WillOnce(DoAll(Invoke(sessions::test_util::SimulateSuccess),
    280           WithArg<0>(RecordSyncShare(&records, 1U, &done))));
    281 
    282   syncer_thread()->Start(SyncerThread::CONFIGURATION_MODE, NULL);
    283 
    284   syncer_thread()->ScheduleConfig(model_types);
    285   done.TimedWait(timeout());
    286 
    287   EXPECT_EQ(2U, records.snapshots.size());
    288   EXPECT_TRUE(CompareModelTypeBitSetToModelTypePayloadMap(model_types,
    289       records.snapshots[1]->source.types));
    290   EXPECT_EQ(GetUpdatesCallerInfo::SYNC_CYCLE_CONTINUATION,
    291             records.snapshots[1]->source.updates_source);
    292 }
    293 
    294 // Issue 2 config commands. Second one right after the first has failed
    295 // and make sure LATEST is executed.
    296 TEST_F(SyncerThread2Test, MultipleConfigWithBackingOff) {
    297   syncable::ModelTypeBitSet model_types1, model_types2;
    298   model_types1[syncable::BOOKMARKS] = true;
    299   model_types2[syncable::AUTOFILL] = true;
    300   SetUpWithTypes(model_types1 | model_types2);
    301   base::WaitableEvent done(false, false);
    302   base::WaitableEvent done1(false, false);
    303   base::WaitableEvent* dummy = NULL;
    304   UseMockDelayProvider();
    305   EXPECT_CALL(*delay(), GetDelay(_))
    306       .WillRepeatedly(Return(TimeDelta::FromMilliseconds(30)));
    307   SyncShareRecords records;
    308 
    309   EXPECT_CALL(*syncer(), SyncShare(_,_,_))
    310       .WillOnce(DoAll(Invoke(sessions::test_util::SimulateCommitFailed),
    311           WithArg<0>(RecordSyncShare(&records, 1U, dummy))))
    312       .WillOnce(DoAll(Invoke(sessions::test_util::SimulateCommitFailed),
    313           WithArg<0>(RecordSyncShare(&records, 1U, &done1))))
    314       .WillOnce(DoAll(Invoke(sessions::test_util::SimulateSuccess),
    315           WithArg<0>(RecordSyncShare(&records, 1U, &done))));
    316 
    317   syncer_thread()->Start(SyncerThread::CONFIGURATION_MODE, NULL);
    318 
    319   syncer_thread()->ScheduleConfig(model_types1);
    320 
    321   // done1 indicates the first config failed.
    322   done1.TimedWait(timeout());
    323   syncer_thread()->ScheduleConfig(model_types2);
    324   done.TimedWait(timeout());
    325 
    326   EXPECT_EQ(3U, records.snapshots.size());
    327   EXPECT_TRUE(CompareModelTypeBitSetToModelTypePayloadMap(model_types2,
    328       records.snapshots[2]->source.types));
    329   EXPECT_EQ(GetUpdatesCallerInfo::FIRST_UPDATE,
    330             records.snapshots[2]->source.updates_source);
    331 }
    332 
    333 // Issue a nudge when the config has failed. Make sure both the config and
    334 // nudge are executed.
    335 TEST_F(SyncerThread2Test, NudgeWithConfigWithBackingOff) {
    336   syncable::ModelTypeBitSet model_types;
    337   model_types[syncable::BOOKMARKS] = true;
    338   base::WaitableEvent done(false, false);
    339   base::WaitableEvent done1(false, false);
    340   base::WaitableEvent done2(false, false);
    341   base::WaitableEvent* dummy = NULL;
    342   UseMockDelayProvider();
    343   EXPECT_CALL(*delay(), GetDelay(_))
    344       .WillRepeatedly(Return(TimeDelta::FromMilliseconds(50)));
    345   SyncShareRecords records;
    346 
    347   EXPECT_CALL(*syncer(), SyncShare(_,_,_))
    348       .WillOnce(DoAll(Invoke(sessions::test_util::SimulateCommitFailed),
    349           WithArg<0>(RecordSyncShare(&records, 1U, dummy))))
    350       .WillOnce(DoAll(Invoke(sessions::test_util::SimulateCommitFailed),
    351           WithArg<0>(RecordSyncShare(&records, 1U, &done1))))
    352       .WillOnce(DoAll(Invoke(sessions::test_util::SimulateSuccess),
    353           WithArg<0>(RecordSyncShare(&records, 1U, &done2))))
    354       .WillOnce(DoAll(Invoke(sessions::test_util::SimulateSuccess),
    355           WithArg<0>(RecordSyncShare(&records, 1U, &done))));
    356 
    357   syncer_thread()->Start(SyncerThread::CONFIGURATION_MODE, NULL);
    358 
    359   syncer_thread()->ScheduleConfig(model_types);
    360   done1.TimedWait(timeout());
    361   syncer_thread()->ScheduleNudge(zero(), NUDGE_SOURCE_LOCAL, model_types,
    362                                  FROM_HERE);
    363 
    364   // done2 indicates config suceeded. Now change the mode so nudge can execute.
    365   done2.TimedWait(timeout());
    366   syncer_thread()->Start(SyncerThread::NORMAL_MODE, NULL);
    367   done.TimedWait(timeout());
    368   EXPECT_EQ(4U, records.snapshots.size());
    369 
    370   EXPECT_TRUE(CompareModelTypeBitSetToModelTypePayloadMap(model_types,
    371       records.snapshots[2]->source.types));
    372   EXPECT_EQ(GetUpdatesCallerInfo::SYNC_CYCLE_CONTINUATION,
    373             records.snapshots[2]->source.updates_source);
    374 
    375   EXPECT_TRUE(CompareModelTypeBitSetToModelTypePayloadMap(model_types,
    376       records.snapshots[3]->source.types));
    377   EXPECT_EQ(GetUpdatesCallerInfo::LOCAL,
    378             records.snapshots[3]->source.updates_source);
    379 
    380 }
    381 
    382 
    383 // Test that nudges are coalesced.
    384 TEST_F(SyncerThread2Test, NudgeCoalescing) {
    385   syncer_thread()->Start(SyncerThread::NORMAL_MODE, NULL);
    386   base::WaitableEvent done(false, false);
    387   SyncShareRecords r;
    388   EXPECT_CALL(*syncer(), SyncShare(_,_,_))
    389       .WillOnce(DoAll(Invoke(sessions::test_util::SimulateSuccess),
    390            WithArg<0>(RecordSyncShare(&r, 1U, &done))));
    391   syncable::ModelTypeBitSet types1, types2, types3;
    392   types1[syncable::BOOKMARKS] = true;
    393   types2[syncable::AUTOFILL] = true;
    394   types3[syncable::THEMES] = true;
    395   TimeDelta delay = TimeDelta::FromMilliseconds(
    396       TestTimeouts::tiny_timeout_ms());
    397   TimeTicks optimal_time = TimeTicks::Now() + delay;
    398   syncer_thread()->ScheduleNudge(delay, NUDGE_SOURCE_UNKNOWN, types1,
    399                                  FROM_HERE);
    400   syncer_thread()->ScheduleNudge(zero(), NUDGE_SOURCE_LOCAL, types2,
    401                                  FROM_HERE);
    402   done.TimedWait(timeout());
    403 
    404   EXPECT_EQ(1U, r.snapshots.size());
    405   EXPECT_GE(r.times[0], optimal_time);
    406   EXPECT_TRUE(CompareModelTypeBitSetToModelTypePayloadMap(
    407       types1 | types2, r.snapshots[0]->source.types));
    408   EXPECT_EQ(GetUpdatesCallerInfo::LOCAL,
    409             r.snapshots[0]->source.updates_source);
    410 
    411   SyncShareRecords r2;
    412   EXPECT_CALL(*syncer(), SyncShare(_,_,_))
    413       .WillOnce(DoAll(Invoke(sessions::test_util::SimulateSuccess),
    414            WithArg<0>(RecordSyncShare(&r2, 1U, &done))));
    415   syncer_thread()->ScheduleNudge(zero(), NUDGE_SOURCE_NOTIFICATION, types3,
    416                                  FROM_HERE);
    417   done.TimedWait(timeout());
    418   EXPECT_EQ(1U, r2.snapshots.size());
    419   EXPECT_TRUE(CompareModelTypeBitSetToModelTypePayloadMap(types3,
    420       r2.snapshots[0]->source.types));
    421   EXPECT_EQ(GetUpdatesCallerInfo::NOTIFICATION,
    422             r2.snapshots[0]->source.updates_source);
    423 }
    424 
    425 // Test nudge scheduling.
    426 TEST_F(SyncerThread2Test, NudgeWithPayloads) {
    427   syncer_thread()->Start(SyncerThread::NORMAL_MODE, NULL);
    428   base::WaitableEvent done(false, false);
    429   SyncShareRecords records;
    430   syncable::ModelTypePayloadMap model_types_with_payloads;
    431   model_types_with_payloads[syncable::BOOKMARKS] = "test";
    432 
    433   EXPECT_CALL(*syncer(), SyncShare(_,_,_))
    434       .WillOnce(DoAll(Invoke(sessions::test_util::SimulateSuccess),
    435           WithArg<0>(RecordSyncShare(&records, 1U, &done))))
    436       .RetiresOnSaturation();
    437   syncer_thread()->ScheduleNudgeWithPayloads(zero(), NUDGE_SOURCE_LOCAL,
    438       model_types_with_payloads, FROM_HERE);
    439   done.TimedWait(timeout());
    440 
    441   EXPECT_EQ(1U, records.snapshots.size());
    442   EXPECT_EQ(model_types_with_payloads, records.snapshots[0]->source.types);
    443   EXPECT_EQ(GetUpdatesCallerInfo::LOCAL,
    444             records.snapshots[0]->source.updates_source);
    445 
    446   // Make sure a second, later, nudge is unaffected by first (no coalescing).
    447   SyncShareRecords records2;
    448   model_types_with_payloads.erase(syncable::BOOKMARKS);
    449   model_types_with_payloads[syncable::AUTOFILL] = "test2";
    450   EXPECT_CALL(*syncer(), SyncShare(_,_,_))
    451       .WillOnce(DoAll(Invoke(sessions::test_util::SimulateSuccess),
    452           WithArg<0>(RecordSyncShare(&records2, 1U, &done))));
    453   syncer_thread()->ScheduleNudgeWithPayloads(zero(), NUDGE_SOURCE_LOCAL,
    454       model_types_with_payloads, FROM_HERE);
    455   done.TimedWait(timeout());
    456 
    457   EXPECT_EQ(1U, records2.snapshots.size());
    458   EXPECT_EQ(model_types_with_payloads, records2.snapshots[0]->source.types);
    459   EXPECT_EQ(GetUpdatesCallerInfo::LOCAL,
    460             records2.snapshots[0]->source.updates_source);
    461 }
    462 
    463 // Test that nudges are coalesced.
    464 TEST_F(SyncerThread2Test, NudgeWithPayloadsCoalescing) {
    465   syncer_thread()->Start(SyncerThread::NORMAL_MODE, NULL);
    466   base::WaitableEvent done(false, false);
    467   SyncShareRecords r;
    468   EXPECT_CALL(*syncer(), SyncShare(_,_,_))
    469       .WillOnce(DoAll(Invoke(sessions::test_util::SimulateSuccess),
    470            WithArg<0>(RecordSyncShare(&r, 1U, &done))));
    471   syncable::ModelTypePayloadMap types1, types2, types3;
    472   types1[syncable::BOOKMARKS] = "test1";
    473   types2[syncable::AUTOFILL] = "test2";
    474   types3[syncable::THEMES] = "test3";
    475   TimeDelta delay = TimeDelta::FromMilliseconds(
    476       TestTimeouts::tiny_timeout_ms());
    477   TimeTicks optimal_time = TimeTicks::Now() + delay;
    478   syncer_thread()->ScheduleNudgeWithPayloads(delay, NUDGE_SOURCE_UNKNOWN,
    479       types1, FROM_HERE);
    480   syncer_thread()->ScheduleNudgeWithPayloads(zero(), NUDGE_SOURCE_LOCAL,
    481       types2, FROM_HERE);
    482   done.TimedWait(timeout());
    483 
    484   EXPECT_EQ(1U, r.snapshots.size());
    485   EXPECT_GE(r.times[0], optimal_time);
    486   syncable::ModelTypePayloadMap coalesced_types;
    487   syncable::CoalescePayloads(&coalesced_types, types1);
    488   syncable::CoalescePayloads(&coalesced_types, types2);
    489   EXPECT_EQ(coalesced_types, r.snapshots[0]->source.types);
    490   EXPECT_EQ(GetUpdatesCallerInfo::LOCAL,
    491             r.snapshots[0]->source.updates_source);
    492 
    493   SyncShareRecords r2;
    494   EXPECT_CALL(*syncer(), SyncShare(_,_,_))
    495       .WillOnce(DoAll(Invoke(sessions::test_util::SimulateSuccess),
    496            WithArg<0>(RecordSyncShare(&r2, 1U, &done))));
    497   syncer_thread()->ScheduleNudgeWithPayloads(zero(), NUDGE_SOURCE_NOTIFICATION,
    498       types3, FROM_HERE);
    499   done.TimedWait(timeout());
    500   EXPECT_EQ(1U, r2.snapshots.size());
    501   EXPECT_EQ(types3, r2.snapshots[0]->source.types);
    502   EXPECT_EQ(GetUpdatesCallerInfo::NOTIFICATION,
    503             r2.snapshots[0]->source.updates_source);
    504 }
    505 
    506 // Test that polling works as expected.
    507 TEST_F(SyncerThread2Test, Polling) {
    508   SyncShareRecords records;
    509   base::WaitableEvent done(false, false);
    510   TimeDelta poll_interval(TimeDelta::FromMilliseconds(30));
    511   syncer_thread()->OnReceivedLongPollIntervalUpdate(poll_interval);
    512   EXPECT_CALL(*syncer(), SyncShare(_,_,_)).Times(AtLeast(kMinNumSamples))
    513       .WillRepeatedly(DoAll(Invoke(sessions::test_util::SimulateSuccess),
    514            WithArg<0>(RecordSyncShare(&records, kMinNumSamples, &done))));
    515 
    516   TimeTicks optimal_start = TimeTicks::Now() + poll_interval;
    517   syncer_thread()->Start(SyncerThread::NORMAL_MODE, NULL);
    518   done.TimedWait(timeout());
    519   syncer_thread()->Stop();
    520 
    521   AnalyzePollRun(records, kMinNumSamples, optimal_start, poll_interval);
    522 }
    523 
    524 // Test that the short poll interval is used.
    525 TEST_F(SyncerThread2Test, PollNotificationsDisabled) {
    526   SyncShareRecords records;
    527   base::WaitableEvent done(false, false);
    528   TimeDelta poll_interval(TimeDelta::FromMilliseconds(30));
    529   syncer_thread()->OnReceivedShortPollIntervalUpdate(poll_interval);
    530   syncer_thread()->set_notifications_enabled(false);
    531   EXPECT_CALL(*syncer(), SyncShare(_,_,_)).Times(AtLeast(kMinNumSamples))
    532       .WillRepeatedly(DoAll(Invoke(sessions::test_util::SimulateSuccess),
    533            WithArg<0>(RecordSyncShare(&records, kMinNumSamples, &done))));
    534 
    535   TimeTicks optimal_start = TimeTicks::Now() + poll_interval;
    536   syncer_thread()->Start(SyncerThread::NORMAL_MODE, NULL);
    537   done.TimedWait(timeout());
    538   syncer_thread()->Stop();
    539 
    540   AnalyzePollRun(records, kMinNumSamples, optimal_start, poll_interval);
    541 }
    542 
    543 // Test that polling intervals are updated when needed.
    544 TEST_F(SyncerThread2Test, PollIntervalUpdate) {
    545   SyncShareRecords records;
    546   base::WaitableEvent done(false, false);
    547   TimeDelta poll1(TimeDelta::FromMilliseconds(120));
    548   TimeDelta poll2(TimeDelta::FromMilliseconds(30));
    549   syncer_thread()->OnReceivedLongPollIntervalUpdate(poll1);
    550   EXPECT_CALL(*syncer(), SyncShare(_,_,_)).Times(AtLeast(kMinNumSamples))
    551       .WillOnce(WithArg<0>(
    552           sessions::test_util::SimulatePollIntervalUpdate(poll2)))
    553       .WillRepeatedly(DoAll(Invoke(sessions::test_util::SimulateSuccess),
    554            WithArg<0>(RecordSyncShare(&records, kMinNumSamples, &done))));
    555 
    556   TimeTicks optimal_start = TimeTicks::Now() + poll1 + poll2;
    557   syncer_thread()->Start(SyncerThread::NORMAL_MODE, NULL);
    558   done.TimedWait(timeout());
    559   syncer_thread()->Stop();
    560 
    561   AnalyzePollRun(records, kMinNumSamples, optimal_start, poll2);
    562 }
    563 
    564 // Test that a sync session is run through to completion.
    565 TEST_F(SyncerThread2Test, HasMoreToSync) {
    566   syncer_thread()->Start(SyncerThread::NORMAL_MODE, NULL);
    567   base::WaitableEvent done(false, false);
    568   EXPECT_CALL(*syncer(), SyncShare(_,_,_))
    569       .WillOnce(Invoke(sessions::test_util::SimulateHasMoreToSync))
    570       .WillOnce(DoAll(Invoke(sessions::test_util::SimulateSuccess),
    571                       SignalEvent(&done)));
    572   syncer_thread()->ScheduleNudge(zero(), NUDGE_SOURCE_LOCAL, ModelTypeBitSet(),
    573                                  FROM_HERE);
    574   done.TimedWait(timeout());
    575   // If more nudges are scheduled, they'll be waited on by TearDown, and would
    576   // cause our expectation to break.
    577 }
    578 
    579 // Test that no syncing occurs when throttled.
    580 TEST_F(SyncerThread2Test, ThrottlingDoesThrottle) {
    581   syncable::ModelTypeBitSet types;
    582   types[syncable::BOOKMARKS] = true;
    583   base::WaitableEvent done(false, false);
    584   TimeDelta poll(TimeDelta::FromMilliseconds(5));
    585   TimeDelta throttle(TimeDelta::FromMinutes(10));
    586   syncer_thread()->OnReceivedLongPollIntervalUpdate(poll);
    587   EXPECT_CALL(*syncer(), SyncShare(_,_,_))
    588       .WillOnce(WithArg<0>(sessions::test_util::SimulateThrottled(throttle)));
    589 
    590   syncer_thread()->Start(SyncerThread::NORMAL_MODE, NULL);
    591   syncer_thread()->ScheduleNudge(zero(), NUDGE_SOURCE_LOCAL, types,
    592                                  FROM_HERE);
    593   FlushLastTask(&done);
    594 
    595   syncer_thread()->Start(SyncerThread::CONFIGURATION_MODE, NULL);
    596   syncer_thread()->ScheduleConfig(types);
    597   FlushLastTask(&done);
    598 }
    599 
    600 TEST_F(SyncerThread2Test, ThrottlingExpires) {
    601   SyncShareRecords records;
    602   base::WaitableEvent done(false, false);
    603   TimeDelta poll(TimeDelta::FromMilliseconds(15));
    604   TimeDelta throttle1(TimeDelta::FromMilliseconds(150));
    605   TimeDelta throttle2(TimeDelta::FromMinutes(10));
    606   syncer_thread()->OnReceivedLongPollIntervalUpdate(poll);
    607 
    608   ::testing::InSequence seq;
    609   EXPECT_CALL(*syncer(), SyncShare(_,_,_))
    610       .WillOnce(WithArg<0>(sessions::test_util::SimulateThrottled(throttle1)))
    611       .RetiresOnSaturation();
    612   EXPECT_CALL(*syncer(), SyncShare(_,_,_))
    613       .WillRepeatedly(DoAll(Invoke(sessions::test_util::SimulateSuccess),
    614            WithArg<0>(RecordSyncShare(&records, kMinNumSamples, &done))));
    615 
    616   TimeTicks optimal_start = TimeTicks::Now() + poll + throttle1;
    617   syncer_thread()->Start(SyncerThread::NORMAL_MODE, NULL);
    618   done.TimedWait(timeout());
    619   syncer_thread()->Stop();
    620 
    621   AnalyzePollRun(records, kMinNumSamples, optimal_start, poll);
    622 }
    623 
    624 // Test nudges / polls don't run in config mode and config tasks do.
    625 TEST_F(SyncerThread2Test, ConfigurationMode) {
    626   TimeDelta poll(TimeDelta::FromMilliseconds(15));
    627   SyncShareRecords records;
    628   base::WaitableEvent done(false, false);
    629   base::WaitableEvent* dummy = NULL;
    630   syncer_thread()->OnReceivedLongPollIntervalUpdate(poll);
    631   EXPECT_CALL(*syncer(), SyncShare(_,_,_))
    632       .WillOnce((Invoke(sessions::test_util::SimulateSuccess),
    633            WithArg<0>(RecordSyncShare(&records, 1U, dummy))));
    634   syncer_thread()->Start(SyncerThread::CONFIGURATION_MODE, NULL);
    635   syncable::ModelTypeBitSet nudge_types;
    636   nudge_types[syncable::AUTOFILL] = true;
    637   syncer_thread()->ScheduleNudge(zero(), NUDGE_SOURCE_LOCAL, nudge_types,
    638                                  FROM_HERE);
    639   syncer_thread()->ScheduleNudge(zero(), NUDGE_SOURCE_LOCAL, nudge_types,
    640                                  FROM_HERE);
    641 
    642   syncable::ModelTypeBitSet config_types;
    643   config_types[syncable::BOOKMARKS] = true;
    644   // TODO(tim): This will fail once CONFIGURATION tasks are implemented. Update
    645   // the EXPECT when that happens.
    646   syncer_thread()->ScheduleConfig(config_types);
    647   FlushLastTask(&done);
    648   syncer_thread()->Stop();
    649 
    650   EXPECT_EQ(1U, records.snapshots.size());
    651   EXPECT_TRUE(CompareModelTypeBitSetToModelTypePayloadMap(config_types,
    652       records.snapshots[0]->source.types));
    653 }
    654 
    655 // Test that exponential backoff is properly triggered.
    656 TEST_F(SyncerThread2Test, BackoffTriggers) {
    657   base::WaitableEvent done(false, false);
    658   UseMockDelayProvider();
    659 
    660   EXPECT_CALL(*syncer(), SyncShare(_,_,_))
    661       .WillOnce(Invoke(sessions::test_util::SimulateDownloadUpdatesFailed))
    662       .WillOnce(DoAll(Invoke(sessions::test_util::SimulateSuccess),
    663           SignalEvent(&done)));
    664   EXPECT_FALSE(GetBackoffAndResetTest(&done));
    665   // Note GetBackoffAndResetTest clears mocks and re-instantiates the syncer.
    666   EXPECT_CALL(*syncer(), SyncShare(_,_,_))
    667       .WillOnce(Invoke(sessions::test_util::SimulateCommitFailed))
    668       .WillOnce(DoAll(Invoke(sessions::test_util::SimulateSuccess),
    669           SignalEvent(&done)));
    670   EXPECT_FALSE(GetBackoffAndResetTest(&done));
    671   EXPECT_CALL(*syncer(), SyncShare(_,_,_))
    672       .WillOnce(Invoke(sessions::test_util::SimulateDownloadUpdatesFailed))
    673       .WillRepeatedly(DoAll(Invoke(
    674           sessions::test_util::SimulateDownloadUpdatesFailed),
    675           SignalEvent(&done)));
    676   EXPECT_TRUE(GetBackoffAndResetTest(&done));
    677   EXPECT_CALL(*syncer(), SyncShare(_,_,_))
    678       .WillOnce(Invoke(sessions::test_util::SimulateCommitFailed))
    679       .WillRepeatedly(DoAll(Invoke(sessions::test_util::SimulateCommitFailed),
    680           SignalEvent(&done)));
    681   EXPECT_TRUE(GetBackoffAndResetTest(&done));
    682   EXPECT_CALL(*syncer(), SyncShare(_,_,_))
    683       .WillOnce(Invoke(sessions::test_util::SimulateDownloadUpdatesFailed))
    684       .WillOnce(Invoke(sessions::test_util::SimulateDownloadUpdatesFailed))
    685       .WillRepeatedly(DoAll(Invoke(sessions::test_util::SimulateSuccess),
    686           SignalEvent(&done)));
    687   EXPECT_FALSE(GetBackoffAndResetTest(&done));
    688   EXPECT_CALL(*syncer(), SyncShare(_,_,_))
    689       .WillOnce(Invoke(sessions::test_util::SimulateCommitFailed))
    690       .WillOnce(Invoke(sessions::test_util::SimulateCommitFailed))
    691       .WillRepeatedly(DoAll(Invoke(sessions::test_util::SimulateSuccess),
    692           SignalEvent(&done)));
    693   EXPECT_FALSE(GetBackoffAndResetTest(&done));
    694 }
    695 
    696 // Test that no polls or extraneous nudges occur when in backoff.
    697 TEST_F(SyncerThread2Test, BackoffDropsJobs) {
    698   SyncShareRecords r;
    699   TimeDelta poll(TimeDelta::FromMilliseconds(5));
    700   base::WaitableEvent done(false, false);
    701   syncable::ModelTypeBitSet types;
    702   types[syncable::BOOKMARKS] = true;
    703   syncer_thread()->OnReceivedLongPollIntervalUpdate(poll);
    704   UseMockDelayProvider();
    705 
    706   EXPECT_CALL(*syncer(), SyncShare(_,_,_)).Times(2)
    707       .WillRepeatedly(DoAll(Invoke(sessions::test_util::SimulateCommitFailed),
    708           RecordSyncShareAndPostSignal(&r, 2U, this, &done)));
    709   EXPECT_CALL(*delay(), GetDelay(_))
    710       .WillRepeatedly(Return(TimeDelta::FromDays(1)));
    711 
    712   syncer_thread()->Start(SyncerThread::NORMAL_MODE, NULL);
    713   ASSERT_TRUE(done.TimedWait(timeout()));
    714   done.Reset();
    715 
    716   Mock::VerifyAndClearExpectations(syncer());
    717   EXPECT_EQ(2U, r.snapshots.size());
    718   EXPECT_EQ(GetUpdatesCallerInfo::PERIODIC,
    719             r.snapshots[0]->source.updates_source);
    720   EXPECT_EQ(GetUpdatesCallerInfo::SYNC_CYCLE_CONTINUATION,
    721             r.snapshots[1]->source.updates_source);
    722 
    723   EXPECT_CALL(*syncer(), SyncShare(_,_,_)).Times(1)
    724       .WillOnce(DoAll(Invoke(sessions::test_util::SimulateCommitFailed),
    725           RecordSyncShareAndPostSignal(&r, 1U, this, &done)));
    726 
    727   // We schedule a nudge with enough delay (10X poll interval) that at least
    728   // one or two polls would have taken place.  The nudge should succeed.
    729   syncer_thread()->ScheduleNudge(poll * 10, NUDGE_SOURCE_LOCAL, types,
    730                                  FROM_HERE);
    731   ASSERT_TRUE(done.TimedWait(timeout()));
    732   done.Reset();
    733 
    734   Mock::VerifyAndClearExpectations(syncer());
    735   Mock::VerifyAndClearExpectations(delay());
    736   EXPECT_EQ(3U, r.snapshots.size());
    737   EXPECT_EQ(GetUpdatesCallerInfo::LOCAL,
    738             r.snapshots[2]->source.updates_source);
    739 
    740   EXPECT_CALL(*syncer(), SyncShare(_,_,_)).Times(0);
    741   EXPECT_CALL(*delay(), GetDelay(_)).Times(0);
    742 
    743   syncer_thread()->Start(SyncerThread::CONFIGURATION_MODE, NULL);
    744   syncer_thread()->ScheduleConfig(types);
    745   FlushLastTask(&done);
    746 
    747   syncer_thread()->Start(SyncerThread::NORMAL_MODE, NULL);
    748   syncer_thread()->ScheduleNudge(zero(), NUDGE_SOURCE_LOCAL, types,
    749                                  FROM_HERE);
    750   syncer_thread()->ScheduleNudge(zero(), NUDGE_SOURCE_LOCAL, types,
    751                                  FROM_HERE);
    752   FlushLastTask(&done);
    753 }
    754 
    755 // Test that backoff is shaping traffic properly with consecutive errors.
    756 TEST_F(SyncerThread2Test, BackoffElevation) {
    757   SyncShareRecords r;
    758   const TimeDelta poll(TimeDelta::FromMilliseconds(10));
    759   base::WaitableEvent done(false, false);
    760   syncer_thread()->OnReceivedLongPollIntervalUpdate(poll);
    761   UseMockDelayProvider();
    762 
    763   const TimeDelta first = TimeDelta::FromSeconds(1);
    764   const TimeDelta second = TimeDelta::FromMilliseconds(10);
    765   const TimeDelta third = TimeDelta::FromMilliseconds(20);
    766   const TimeDelta fourth = TimeDelta::FromMilliseconds(30);
    767   const TimeDelta fifth = TimeDelta::FromDays(1);
    768 
    769   EXPECT_CALL(*syncer(), SyncShare(_,_,_)).Times(kMinNumSamples)
    770       .WillRepeatedly(DoAll(Invoke(sessions::test_util::SimulateCommitFailed),
    771           RecordSyncShareAndPostSignal(&r, kMinNumSamples, this, &done)));
    772 
    773   EXPECT_CALL(*delay(), GetDelay(Eq(first))).WillOnce(Return(second))
    774       .RetiresOnSaturation();
    775   EXPECT_CALL(*delay(), GetDelay(Eq(second))).WillOnce(Return(third))
    776       .RetiresOnSaturation();
    777   EXPECT_CALL(*delay(), GetDelay(Eq(third))).WillOnce(Return(fourth))
    778       .RetiresOnSaturation();
    779   EXPECT_CALL(*delay(), GetDelay(Eq(fourth))).WillOnce(Return(fifth));
    780 
    781   syncer_thread()->Start(SyncerThread::NORMAL_MODE, NULL);
    782   ASSERT_TRUE(done.TimedWait(timeout()));
    783 
    784   EXPECT_GE(r.times[2] - r.times[1], second);
    785   EXPECT_GE(r.times[3] - r.times[2], third);
    786   EXPECT_GE(r.times[4] - r.times[3], fourth);
    787 }
    788 
    789 // Test that things go back to normal once a canary task makes forward progress
    790 // following a succession of failures.
    791 TEST_F(SyncerThread2Test, BackoffRelief) {
    792   SyncShareRecords r;
    793   const TimeDelta poll(TimeDelta::FromMilliseconds(10));
    794   base::WaitableEvent done(false, false);
    795   syncer_thread()->OnReceivedLongPollIntervalUpdate(poll);
    796   UseMockDelayProvider();
    797 
    798   const TimeDelta backoff = TimeDelta::FromMilliseconds(100);
    799 
    800   EXPECT_CALL(*syncer(), SyncShare(_,_,_))
    801       .WillOnce(Invoke(sessions::test_util::SimulateCommitFailed))
    802       .WillOnce(Invoke(sessions::test_util::SimulateCommitFailed))
    803       .WillRepeatedly(DoAll(Invoke(sessions::test_util::SimulateSuccess),
    804           RecordSyncShareAndPostSignal(&r, kMinNumSamples, this, &done)));
    805   EXPECT_CALL(*delay(), GetDelay(_)).WillOnce(Return(backoff));
    806 
    807   // Optimal start for the post-backoff poll party.
    808   TimeTicks optimal_start = TimeTicks::Now() + poll + backoff;
    809   syncer_thread()->Start(SyncerThread::NORMAL_MODE, NULL);
    810   done.TimedWait(timeout());
    811   syncer_thread()->Stop();
    812 
    813   // Check for healthy polling after backoff is relieved.
    814   // Can't use AnalyzePollRun because first sync is a continuation. Bleh.
    815   for (size_t i = 0; i < r.times.size(); i++) {
    816     SCOPED_TRACE(testing::Message() << "SyncShare # (" << i << ")");
    817     TimeTicks optimal_next_sync = optimal_start + poll * i;
    818     EXPECT_GE(r.times[i], optimal_next_sync);
    819     EXPECT_EQ(i == 0 ? GetUpdatesCallerInfo::SYNC_CYCLE_CONTINUATION
    820                      : GetUpdatesCallerInfo::PERIODIC,
    821               r.snapshots[i]->source.updates_source);
    822   }
    823 }
    824 
    825 TEST_F(SyncerThread2Test, GetRecommendedDelay) {
    826   EXPECT_LE(TimeDelta::FromSeconds(0),
    827             SyncerThread::GetRecommendedDelay(TimeDelta::FromSeconds(0)));
    828   EXPECT_LE(TimeDelta::FromSeconds(1),
    829             SyncerThread::GetRecommendedDelay(TimeDelta::FromSeconds(1)));
    830   EXPECT_LE(TimeDelta::FromSeconds(50),
    831             SyncerThread::GetRecommendedDelay(TimeDelta::FromSeconds(50)));
    832   EXPECT_LE(TimeDelta::FromSeconds(10),
    833             SyncerThread::GetRecommendedDelay(TimeDelta::FromSeconds(10)));
    834   EXPECT_EQ(TimeDelta::FromSeconds(kMaxBackoffSeconds),
    835             SyncerThread::GetRecommendedDelay(
    836                 TimeDelta::FromSeconds(kMaxBackoffSeconds)));
    837   EXPECT_EQ(TimeDelta::FromSeconds(kMaxBackoffSeconds),
    838             SyncerThread::GetRecommendedDelay(
    839                 TimeDelta::FromSeconds(kMaxBackoffSeconds + 1)));
    840 }
    841 
    842 // Test that appropriate syncer steps are requested for each job type.
    843 TEST_F(SyncerThread2Test, SyncerSteps) {
    844   // Nudges.
    845   base::WaitableEvent done(false, false);
    846   EXPECT_CALL(*syncer(), SyncShare(_, SYNCER_BEGIN, SYNCER_END))
    847       .Times(1);
    848   syncer_thread()->Start(SyncerThread::NORMAL_MODE, NULL);
    849   syncer_thread()->ScheduleNudge(zero(), NUDGE_SOURCE_LOCAL, ModelTypeBitSet(),
    850                                  FROM_HERE);
    851   FlushLastTask(&done);
    852   syncer_thread()->Stop();
    853   Mock::VerifyAndClearExpectations(syncer());
    854 
    855   // ClearUserData.
    856   EXPECT_CALL(*syncer(), SyncShare(_, CLEAR_PRIVATE_DATA, SYNCER_END))
    857       .Times(1);
    858   syncer_thread()->Start(SyncerThread::NORMAL_MODE, NULL);
    859   syncer_thread()->ScheduleClearUserData();
    860   FlushLastTask(&done);
    861   syncer_thread()->Stop();
    862   Mock::VerifyAndClearExpectations(syncer());
    863   // Configuration.
    864   EXPECT_CALL(*syncer(), SyncShare(_, DOWNLOAD_UPDATES, APPLY_UPDATES));
    865   syncer_thread()->Start(SyncerThread::CONFIGURATION_MODE, NULL);
    866   syncer_thread()->ScheduleConfig(ModelTypeBitSet());
    867   FlushLastTask(&done);
    868   syncer_thread()->Stop();
    869   Mock::VerifyAndClearExpectations(syncer());
    870 
    871   // Poll.
    872   EXPECT_CALL(*syncer(), SyncShare(_, SYNCER_BEGIN, SYNCER_END))
    873       .Times(AtLeast(1))
    874       .WillRepeatedly(SignalEvent(&done));
    875   const TimeDelta poll(TimeDelta::FromMilliseconds(10));
    876   syncer_thread()->OnReceivedLongPollIntervalUpdate(poll);
    877   syncer_thread()->Start(SyncerThread::NORMAL_MODE, NULL);
    878   done.TimedWait(timeout());
    879   syncer_thread()->Stop();
    880   Mock::VerifyAndClearExpectations(syncer());
    881   done.Reset();
    882 }
    883 
    884 // Test config tasks don't run during normal mode.
    885 // TODO(tim): Implement this test and then the functionality!
    886 TEST_F(SyncerThread2Test, DISABLED_NoConfigDuringNormal) {
    887 }
    888 
    889 // Test that starting the syncer thread without a valid connection doesn't
    890 // break things when a connection is detected.
    891 TEST_F(SyncerThread2Test, StartWhenNotConnected) {
    892   base::WaitableEvent done(false, false);
    893   MessageLoop cur;
    894   connection()->SetServerNotReachable();
    895   EXPECT_CALL(*syncer(), SyncShare(_,_,_)).WillOnce(SignalEvent(&done));
    896   syncer_thread()->Start(SyncerThread::NORMAL_MODE, NULL);
    897   syncer_thread()->ScheduleNudge(zero(), NUDGE_SOURCE_LOCAL, ModelTypeBitSet(),
    898                                  FROM_HERE);
    899   FlushLastTask(&done);
    900 
    901   connection()->SetServerReachable();
    902   cur.PostTask(FROM_HERE, NewRunnableFunction(
    903       &SyncerThread2Test::QuitMessageLoop));
    904   cur.Run();
    905 
    906   // By now, the server connection event should have been posted to the
    907   // SyncerThread.
    908   FlushLastTask(&done);
    909   done.TimedWait(timeout());
    910 }
    911 
    912 TEST_F(SyncerThread2Test, SetsPreviousRoutingInfo) {
    913   base::WaitableEvent done(false, false);
    914   ModelSafeRoutingInfo info;
    915   EXPECT_TRUE(info == context()->previous_session_routing_info());
    916   ModelSafeRoutingInfo expected;
    917   context()->registrar()->GetModelSafeRoutingInfo(&expected);
    918   ASSERT_FALSE(expected.empty());
    919   EXPECT_CALL(*syncer(), SyncShare(_,_,_)).Times(1);
    920 
    921   syncer_thread()->Start(SyncerThread::NORMAL_MODE, NULL);
    922   syncer_thread()->ScheduleNudge(zero(), NUDGE_SOURCE_LOCAL, ModelTypeBitSet(),
    923                                  FROM_HERE);
    924   FlushLastTask(&done);
    925   syncer_thread()->Stop();
    926 
    927   EXPECT_TRUE(expected == context()->previous_session_routing_info());
    928 }
    929 
    930 }  // namespace browser_sync
    931 
    932 // SyncerThread won't outlive the test!
    933 DISABLE_RUNNABLE_METHOD_REFCOUNT(browser_sync::SyncerThread2Test);
    934