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

Unified Diff: chrome/browser/sync/engine/syncer_thread2_unittest.cc

Issue 6812004: sync: Make nudge + config jobs reliable in SyncerThread2 (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Fix CR feedback and all the unittests. Created 9 years, 8 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 side-by-side diff with in-line comments
Download patch
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
« chrome/browser/sync/engine/syncer_thread2.cc ('K') | « chrome/browser/sync/engine/syncer_thread2.cc ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698