Chromium Code Reviews| Index: chrome/browser/sync/engine/syncer_thread2_unittest.cc |
| diff --git a/chrome/browser/sync/engine/syncer_thread2_unittest.cc b/chrome/browser/sync/engine/syncer_thread2_unittest.cc |
| index 02514677e5600d989f5776318786055b2df45b98..b7440216d2f3974b012322095457aac2256cc5d2 100644 |
| --- a/chrome/browser/sync/engine/syncer_thread2_unittest.cc |
| +++ b/chrome/browser/sync/engine/syncer_thread2_unittest.cc |
| @@ -47,7 +47,8 @@ struct SyncShareRecords { |
| // Convenient to use in tests wishing to analyze SyncShare calls over time. |
| static const size_t kMinNumSamples = 5; |
| - |
| +struct SyncerThread::SyncSessionJob; |
| +struct SyncerThread::WaitInterval; |
| class SyncerThread2Test : public testing::Test { |
| public: |
| class MockDelayProvider : public SyncerThread::DelayProvider { |
| @@ -69,6 +70,20 @@ class SyncerThread2Test : public testing::Test { |
| syncer_thread_.reset(new SyncerThread(context_, syncer_)); |
| } |
| + virtual void SetUpWithTypes(syncable::ModelTypeBitSet types) { |
| + syncdb_.SetUp(); |
| + syncer_ = new MockSyncer(); |
| + delay_ = NULL; |
| + registrar_.reset(MockModelSafeWorkerRegistrar::SetPassiveTypes(types)); |
| + connection_.reset(new MockConnectionManager(syncdb_.manager(), "Test")); |
| + connection_->SetServerReachable(); |
| + context_ = new SyncSessionContext(connection_.get(), syncdb_.manager(), |
| + registrar_.get(), std::vector<SyncEngineEventListener*>()); |
| + context_->set_notifications_enabled(true); |
| + context_->set_account_name("Test"); |
| + syncer_thread_.reset(new SyncerThread(context_, syncer_)); |
| + } |
| + |
| SyncerThread* syncer_thread() { return syncer_thread_.get(); } |
| MockSyncer* syncer() { return syncer_; } |
| MockDelayProvider* delay() { return delay_; } |
| @@ -155,8 +170,58 @@ class SyncerThread2Test : public testing::Test { |
| SyncSessionContext* context() { return context_; } |
| - private: |
| + void SetMode(SyncerThread::Mode mode) { |
| + syncer_thread_->mode_ = mode; |
|
tim (not reviewing)
2011/04/09 23:52:58
it seems bad / dangerous to have all these setters
lipalani1
2011/04/12 02:33:00
Moved to a different file.
On 2011/04/09 23:52:58,
|
| + } |
| + |
| + void SetLastSyncedTime(base::TimeTicks ticks) { |
| + syncer_thread_->last_sync_session_end_time_ = ticks; |
| + } |
| + |
| + void SetServerConnection(bool connected) { |
| + syncer_thread_->server_connection_ok_ = connected; |
| + } |
| + |
| + void ResetWaitInterval() { |
| + syncer_thread_->wait_interval_.reset(); |
| + } |
| + |
| + void SetWaitIntervalToThrottled() { |
|
tim (not reviewing)
2011/04/09 23:52:58
the existing tests would set this state naturally
lipalani1
2011/04/12 02:33:00
This is moved to a different file. It is needed th
|
| + syncer_thread_->wait_interval_.reset(new SyncerThread::WaitInterval( |
| + SyncerThread::WaitInterval::THROTTLED, TimeDelta::FromSeconds(1))); |
| + } |
| + |
| + void SetWaitIntervalToExponentialBackoff() { |
| + syncer_thread_->wait_interval_.reset( |
| + new SyncerThread::WaitInterval( |
| + SyncerThread::WaitInterval::EXPONENTIAL_BACKOFF, |
| + TimeDelta::FromSeconds(1))); |
| + } |
| + |
| + SyncerThread::JobProcessDecision DecideOnJob( |
| + const SyncerThread::SyncSessionJob& job) { |
| + return syncer_thread_->DecideOnJob(job); |
| + } |
| + |
| + void InitializeSyncerOnNormalMode() { |
| + SetMode(SyncerThread::NORMAL_MODE); |
| + ResetWaitInterval(); |
| + SetServerConnection(true); |
| + SetLastSyncedTime(base::TimeTicks::Now()); |
| + } |
| + |
| + SyncerThread::JobProcessDecision CreateAndDecideJob( |
| + SyncerThread::SyncSessionJobPurpose purpose) { |
| + struct SyncerThread::SyncSessionJob job; |
| + job.purpose = purpose; |
| + job.scheduled_start = TimeTicks::Now(); |
| + return DecideOnJob(job); |
| + } |
| + |
| + protected: |
| scoped_ptr<SyncerThread> syncer_thread_; |
| + |
| + private: |
| scoped_ptr<MockConnectionManager> connection_; |
| SyncSessionContext* context_; |
| MockSyncer* syncer_; |
| @@ -227,6 +292,134 @@ TEST_F(SyncerThread2Test, Nudge) { |
| records2.snapshots[0]->source.updates_source); |
| } |
| +TEST_F(SyncerThread2Test, Config) { |
| + base::WaitableEvent done(false, false); |
| + SyncShareRecords records; |
| + syncable::ModelTypeBitSet model_types; |
| + model_types[syncable::BOOKMARKS] = true; |
| + |
| + syncer_thread()->Start(SyncerThread::CONFIGURATION_MODE, NULL); |
| + |
| + EXPECT_CALL(*syncer(), SyncShare(_,_,_)) |
|
tim (not reviewing)
2011/04/09 23:52:58
In general it's bad to have the expectations befor
lipalani1
2011/04/12 02:33:00
Good point. Even if they were thread safe expectat
|
| + .WillOnce(DoAll(Invoke(sessions::test_util::SimulateSuccess), |
| + WithArg<0>(RecordSyncShare(&records, 1U, &done)))); |
| + syncer_thread()->ScheduleConfig(model_types); |
| + done.TimedWait(timeout()); |
| + |
| + EXPECT_EQ(1U, records.snapshots.size()); |
| + EXPECT_TRUE(CompareModelTypeBitSetToModelTypePayloadMap(model_types, |
| + records.snapshots[0]->source.types)); |
| + EXPECT_EQ(GetUpdatesCallerInfo::FIRST_UPDATE, |
| + records.snapshots[0]->source.updates_source); |
| +} |
| + |
| +TEST_F(SyncerThread2Test, ConfigWithBackingOff) { |
| + base::WaitableEvent done(false, false); |
| + base::WaitableEvent* dummy = NULL; |
| + UseMockDelayProvider(); |
| + EXPECT_CALL(*delay(), GetDelay(_)) |
| + .WillRepeatedly(Return(TimeDelta::FromMilliseconds(1))); |
| + SyncShareRecords records; |
| + syncable::ModelTypeBitSet model_types; |
| + model_types[syncable::BOOKMARKS] = true; |
| + |
| + syncer_thread()->Start(SyncerThread::CONFIGURATION_MODE, NULL); |
| + |
| + EXPECT_CALL(*syncer(), SyncShare(_,_,_)) |
| + .WillOnce(DoAll(Invoke(sessions::test_util::SimulateCommitFailed), |
| + WithArg<0>(RecordSyncShare(&records, 1U, dummy)))) |
| + .WillOnce(DoAll(Invoke(sessions::test_util::SimulateSuccess), |
| + WithArg<0>(RecordSyncShare(&records, 1U, &done)))); |
| + syncer_thread()->ScheduleConfig(model_types); |
| + done.TimedWait(timeout()); |
| + |
| + EXPECT_EQ(2U, records.snapshots.size()); |
| + EXPECT_TRUE(CompareModelTypeBitSetToModelTypePayloadMap(model_types, |
| + records.snapshots[1]->source.types)); |
| + EXPECT_EQ(GetUpdatesCallerInfo::SYNC_CYCLE_CONTINUATION, |
| + records.snapshots[1]->source.updates_source); |
| +} |
| + |
| +TEST_F(SyncerThread2Test, MultipleConfigWithBackingOff) { |
| + syncable::ModelTypeBitSet model_types1, model_types2; |
| + model_types1[syncable::BOOKMARKS] = true; |
| + model_types2[syncable::AUTOFILL] = true; |
| + SetUpWithTypes(model_types1 | model_types2); |
| + base::WaitableEvent done(false, false); |
| + base::WaitableEvent done1(false, false); |
| + base::WaitableEvent* dummy = NULL; |
| + UseMockDelayProvider(); |
| + EXPECT_CALL(*delay(), GetDelay(_)) |
| + .WillRepeatedly(Return(TimeDelta::FromMilliseconds(30))); |
| + SyncShareRecords records; |
| + |
| + syncer_thread()->Start(SyncerThread::CONFIGURATION_MODE, NULL); |
| + |
| + EXPECT_CALL(*syncer(), SyncShare(_,_,_)) |
| + .WillOnce(DoAll(Invoke(sessions::test_util::SimulateCommitFailed), |
| + WithArg<0>(RecordSyncShare(&records, 1U, dummy)))) |
| + .WillOnce(DoAll(Invoke(sessions::test_util::SimulateCommitFailed), |
| + WithArg<0>(RecordSyncShare(&records, 1U, &done1)))) |
| + .WillOnce(DoAll(Invoke(sessions::test_util::SimulateSuccess), |
| + WithArg<0>(RecordSyncShare(&records, 1U, &done)))); |
| + syncer_thread()->ScheduleConfig(model_types1); |
| + done1.TimedWait(timeout()); |
| + syncer_thread()->ScheduleConfig(model_types2); |
| + done.TimedWait(timeout()); |
| + |
|
tim (not reviewing)
2011/04/09 23:52:58
how come all these tests now wait after each post.
lipalani1
2011/04/12 02:33:00
Comments added explaining the rationale for them.
|
| + EXPECT_EQ(3U, records.snapshots.size()); |
| + EXPECT_TRUE(CompareModelTypeBitSetToModelTypePayloadMap(model_types2, |
| + records.snapshots[2]->source.types)); |
| + EXPECT_EQ(GetUpdatesCallerInfo::FIRST_UPDATE, |
| + records.snapshots[2]->source.updates_source); |
| +} |
| + |
| +TEST_F(SyncerThread2Test, NudgeWithConfigWithBackingOff) { |
|
tim (not reviewing)
2011/04/09 23:52:58
it's not clear what is being tested here versus Ba
lipalani1
2011/04/12 02:33:00
I have added comments. In short backoffdropjobs te
|
| + syncable::ModelTypeBitSet model_types; |
| + model_types[syncable::BOOKMARKS] = true; |
| + base::WaitableEvent done(false, false); |
| + base::WaitableEvent done1(false, false); |
| + base::WaitableEvent done2(false, false); |
| + base::WaitableEvent* dummy = NULL; |
| + UseMockDelayProvider(); |
| + EXPECT_CALL(*delay(), GetDelay(_)) |
| + .WillRepeatedly(Return(TimeDelta::FromMilliseconds(50))); |
| + SyncShareRecords records; |
| + |
| + syncer_thread()->Start(SyncerThread::CONFIGURATION_MODE, NULL); |
| + |
| + EXPECT_CALL(*syncer(), SyncShare(_,_,_)) |
| + .WillOnce(DoAll(Invoke(sessions::test_util::SimulateCommitFailed), |
| + WithArg<0>(RecordSyncShare(&records, 1U, dummy)))) |
| + .WillOnce(DoAll(Invoke(sessions::test_util::SimulateCommitFailed), |
| + WithArg<0>(RecordSyncShare(&records, 1U, &done1)))) |
| + .WillOnce(DoAll(Invoke(sessions::test_util::SimulateSuccess), |
| + WithArg<0>(RecordSyncShare(&records, 1U, &done2)))) |
| + .WillOnce(DoAll(Invoke(sessions::test_util::SimulateSuccess), |
| + WithArg<0>(RecordSyncShare(&records, 1U, &done)))); |
| + |
| + syncer_thread()->ScheduleConfig(model_types); |
| + done1.TimedWait(timeout()); |
| + syncer_thread()->ScheduleNudge(zero(), NUDGE_SOURCE_LOCAL, model_types, |
| + FROM_HERE); |
| + done2.TimedWait(timeout()); |
| + syncer_thread()->Start(SyncerThread::NORMAL_MODE, NULL); |
| + done.TimedWait(timeout()); |
| + EXPECT_EQ(4U, records.snapshots.size()); |
| + |
| + EXPECT_TRUE(CompareModelTypeBitSetToModelTypePayloadMap(model_types, |
| + records.snapshots[2]->source.types)); |
| + EXPECT_EQ(GetUpdatesCallerInfo::SYNC_CYCLE_CONTINUATION, |
| + records.snapshots[2]->source.updates_source); |
| + |
| + EXPECT_TRUE(CompareModelTypeBitSetToModelTypePayloadMap(model_types, |
| + records.snapshots[3]->source.types)); |
| + EXPECT_EQ(GetUpdatesCallerInfo::LOCAL, |
| + records.snapshots[3]->source.updates_source); |
| + |
| +} |
| + |
| + |
| // Test that nudges are coalesced. |
| TEST_F(SyncerThread2Test, NudgeCoalescing) { |
| syncer_thread()->Start(SyncerThread::NORMAL_MODE, NULL); |
| @@ -480,16 +673,19 @@ TEST_F(SyncerThread2Test, ConfigurationMode) { |
| base::WaitableEvent* dummy = NULL; |
| syncer_thread()->OnReceivedLongPollIntervalUpdate(poll); |
| EXPECT_CALL(*syncer(), SyncShare(_,_,_)) |
| - .WillOnce(DoAll(Invoke(sessions::test_util::SimulateSuccess), |
| + .WillOnce((Invoke(sessions::test_util::SimulateSuccess), |
| WithArg<0>(RecordSyncShare(&records, 1U, dummy)))); |
| syncer_thread()->Start(SyncerThread::CONFIGURATION_MODE, NULL); |
| + FlushLastTask(&done); |
|
tim (not reviewing)
2011/04/09 23:52:58
Why are there calls to this sprinkled over this te
lipalani1
2011/04/12 02:33:00
argh. failed to remove something I was playing wit
|
| syncable::ModelTypeBitSet nudge_types; |
| nudge_types[syncable::AUTOFILL] = true; |
| syncer_thread()->ScheduleNudge(zero(), NUDGE_SOURCE_LOCAL, nudge_types, |
| FROM_HERE); |
| + FlushLastTask(&done); |
| syncer_thread()->ScheduleNudge(zero(), NUDGE_SOURCE_LOCAL, nudge_types, |
| FROM_HERE); |
| + FlushLastTask(&done); |
| syncable::ModelTypeBitSet config_types; |
| config_types[syncable::BOOKMARKS] = true; |
| // TODO(tim): This will fail once CONFIGURATION tasks are implemented. Update |
| @@ -743,6 +939,7 @@ TEST_F(SyncerThread2Test, StartWhenNotConnected) { |
| base::WaitableEvent done(false, false); |
| MessageLoop cur; |
| connection()->SetServerNotReachable(); |
| + EXPECT_CALL(*syncer(), SyncShare(_,_,_)).WillOnce(SignalEvent(&done)); |
| syncer_thread()->Start(SyncerThread::NORMAL_MODE, NULL); |
| syncer_thread()->ScheduleNudge(zero(), NUDGE_SOURCE_LOCAL, ModelTypeBitSet(), |
| FROM_HERE); |
| @@ -756,9 +953,6 @@ TEST_F(SyncerThread2Test, StartWhenNotConnected) { |
| // By now, the server connection event should have been posted to the |
| // SyncerThread. |
| FlushLastTask(&done); |
| - EXPECT_CALL(*syncer(), SyncShare(_,_,_)).WillOnce(SignalEvent(&done)); |
| - syncer_thread()->ScheduleNudge(zero(), NUDGE_SOURCE_LOCAL, ModelTypeBitSet(), |
| - FROM_HERE); |
| done.TimedWait(timeout()); |
| } |
| @@ -780,6 +974,135 @@ TEST_F(SyncerThread2Test, SetsPreviousRoutingInfo) { |
| EXPECT_TRUE(expected == context()->previous_session_routing_info()); |
| } |
| +TEST_F(SyncerThread2Test, SaveNudge) { |
| + InitializeSyncerOnNormalMode(); |
| + |
| + // Now set the mode to configure. |
| + SetMode(SyncerThread::CONFIGURATION_MODE); |
| + |
| + SyncerThread::JobProcessDecision decision = |
| + CreateAndDecideJob(SyncerThread::NUDGE); |
| + |
| + DCHECK_EQ(decision, SyncerThread::SAVE); |
| +} |
| + |
| +TEST_F(SyncerThread2Test, ContinueNudge) { |
| + InitializeSyncerOnNormalMode(); |
| + |
| + SyncerThread::JobProcessDecision decision = CreateAndDecideJob( |
| + SyncerThread::NUDGE); |
| + |
| + DCHECK_EQ(decision, SyncerThread::CONTINUE); |
| +} |
| + |
| +TEST_F(SyncerThread2Test, DropPoll) { |
| + InitializeSyncerOnNormalMode(); |
| + SetMode(SyncerThread::CONFIGURATION_MODE); |
| + |
| + SyncerThread::JobProcessDecision decision = CreateAndDecideJob( |
| + SyncerThread::POLL); |
| + |
| + DCHECK_EQ(decision, SyncerThread::DROP); |
| +} |
| + |
| +TEST_F(SyncerThread2Test, ContinuePoll) { |
| + InitializeSyncerOnNormalMode(); |
| + |
| + SyncerThread::JobProcessDecision decision = CreateAndDecideJob( |
| + SyncerThread::POLL); |
| + |
| + DCHECK_EQ(decision, SyncerThread::CONTINUE); |
| +} |
| + |
| +TEST_F(SyncerThread2Test, ContinueConfiguration) { |
| + InitializeSyncerOnNormalMode(); |
| + SetMode(SyncerThread::CONFIGURATION_MODE); |
| + |
| + SyncerThread::JobProcessDecision decision = CreateAndDecideJob( |
| + SyncerThread::CONFIGURATION); |
| + |
| + DCHECK_EQ(decision, SyncerThread::CONTINUE); |
| +} |
| + |
| +TEST_F(SyncerThread2Test, SaveConfigurationWhileThrottled) { |
| + InitializeSyncerOnNormalMode(); |
| + SetMode(SyncerThread::CONFIGURATION_MODE); |
| + |
| + SetWaitIntervalToThrottled(); |
| + |
| + SyncerThread::JobProcessDecision decision = CreateAndDecideJob( |
| + SyncerThread::CONFIGURATION); |
| + |
| + DCHECK_EQ(decision, SyncerThread::SAVE); |
| +} |
| + |
| +TEST_F(SyncerThread2Test, SaveNudgeWhileThrottled) { |
| + InitializeSyncerOnNormalMode(); |
| + SetMode(SyncerThread::CONFIGURATION_MODE); |
| + |
| + SetWaitIntervalToThrottled(); |
| + |
| + SyncerThread::JobProcessDecision decision = CreateAndDecideJob( |
| + SyncerThread::NUDGE); |
| + |
| + DCHECK_EQ(decision, SyncerThread::SAVE); |
| + |
| +} |
| + |
| +TEST_F(SyncerThread2Test, ContinueClearUserDataUnderAllCircumstances) { |
| + InitializeSyncerOnNormalMode(); |
| + |
| + SetMode(SyncerThread::CONFIGURATION_MODE); |
| + SetWaitIntervalToThrottled(); |
| + SyncerThread::JobProcessDecision decision = CreateAndDecideJob( |
| + SyncerThread::CLEAR_USER_DATA); |
| + DCHECK_EQ(decision, SyncerThread::CONTINUE); |
| + |
| + SetMode(SyncerThread::NORMAL_MODE); |
| + SetWaitIntervalToExponentialBackoff(); |
| + decision = CreateAndDecideJob( |
| + SyncerThread::CLEAR_USER_DATA); |
| + DCHECK_EQ(decision, SyncerThread::CONTINUE); |
| +} |
| + |
| +TEST_F(SyncerThread2Test, ContinueNudgeWhileExponentialBackOff) { |
| + InitializeSyncerOnNormalMode(); |
| + SetMode(SyncerThread::NORMAL_MODE); |
| + SetWaitIntervalToExponentialBackoff(); |
| + |
| + SyncerThread::JobProcessDecision decision = CreateAndDecideJob( |
| + SyncerThread::NUDGE); |
| + |
| + DCHECK_EQ(decision, SyncerThread::CONTINUE); |
| +} |
| + |
| +TEST_F(SyncerThread2Test, DropNudgeWhileExponentialBackOff) { |
| + InitializeSyncerOnNormalMode(); |
| + SetMode(SyncerThread::NORMAL_MODE); |
| + SetWaitIntervalToExponentialBackoff(); |
| + |
| + syncer_thread_->wait_interval_->had_nudge = true; |
| + |
| + SyncerThread::JobProcessDecision decision = CreateAndDecideJob( |
| + SyncerThread::NUDGE); |
| + |
| + DCHECK_EQ(decision, SyncerThread::DROP); |
| +} |
| + |
| +TEST_F(SyncerThread2Test, ContinueCanaryJobConfig) { |
| + InitializeSyncerOnNormalMode(); |
| + SetMode(SyncerThread::CONFIGURATION_MODE); |
| + SetWaitIntervalToExponentialBackoff(); |
| + |
| + struct SyncerThread::SyncSessionJob job; |
| + job.purpose = SyncerThread::CONFIGURATION; |
| + job.scheduled_start = TimeTicks::Now(); |
| + job.is_canary_job = true; |
| + SyncerThread::JobProcessDecision decision = DecideOnJob(job); |
| + |
| + DCHECK_EQ(decision, SyncerThread::CONTINUE); |
| +} |
| + |
| } // namespace s3 |
| } // namespace browser_sync |