Index: chrome/browser/sync/engine/sync_scheduler_unittest.cc |
diff --git a/chrome/browser/sync/engine/sync_scheduler_unittest.cc b/chrome/browser/sync/engine/sync_scheduler_unittest.cc |
deleted file mode 100644 |
index a6c48d620147f6fce4f556e4be9c86ab38bd5445..0000000000000000000000000000000000000000 |
--- a/chrome/browser/sync/engine/sync_scheduler_unittest.cc |
+++ /dev/null |
@@ -1,1165 +0,0 @@ |
-// Copyright (c) 2012 The Chromium Authors. All rights reserved. |
-// Use of this source code is governed by a BSD-style license that can be |
-// found in the LICENSE file. |
- |
-#include "base/bind.h" |
-#include "base/callback.h" |
-#include "base/compiler_specific.h" |
-#include "base/memory/weak_ptr.h" |
-#include "base/message_loop.h" |
-#include "base/test/test_timeouts.h" |
-#include "chrome/browser/sync/engine/sync_scheduler.h" |
-#include "chrome/browser/sync/engine/syncer.h" |
-#include "chrome/browser/sync/sessions/test_util.h" |
-#include "chrome/browser/sync/test/engine/fake_model_safe_worker_registrar.h" |
-#include "chrome/browser/sync/test/engine/mock_connection_manager.h" |
-#include "chrome/browser/sync/test/engine/test_directory_setter_upper.h" |
-#include "chrome/browser/sync/test/fake_extensions_activity_monitor.h" |
-#include "testing/gtest/include/gtest/gtest.h" |
-#include "testing/gmock/include/gmock/gmock.h" |
- |
-using base::TimeDelta; |
-using base::TimeTicks; |
-using testing::_; |
-using testing::AtLeast; |
-using testing::DoAll; |
-using testing::Eq; |
-using testing::Invoke; |
-using testing::Mock; |
-using testing::Return; |
-using testing::WithArg; |
- |
-namespace browser_sync { |
-using sessions::SyncSession; |
-using sessions::SyncSessionContext; |
-using sessions::SyncSessionSnapshot; |
-using syncable::ModelTypeSet; |
-using sync_pb::GetUpdatesCallerInfo; |
- |
-class MockSyncer : public Syncer { |
- public: |
- MOCK_METHOD3(SyncShare, void(sessions::SyncSession*, SyncerStep, |
- SyncerStep)); |
-}; |
- |
-// Used when tests want to record syncing activity to examine later. |
-struct SyncShareRecords { |
- std::vector<TimeTicks> times; |
- std::vector<linked_ptr<SyncSessionSnapshot> > snapshots; |
-}; |
- |
-void QuitLoopNow() { |
- // We use QuitNow() instead of Quit() as the latter may get stalled |
- // indefinitely in the presence of repeated timers with low delays |
- // and a slow test (e.g., ThrottlingDoesThrottle [which has a poll |
- // delay of 5ms] run under TSAN on the trybots). |
- MessageLoop::current()->QuitNow(); |
-} |
- |
-void RunLoop() { |
- MessageLoop::current()->Run(); |
-} |
- |
-void PumpLoop() { |
- // Do it this way instead of RunAllPending to pump loop exactly once |
- // (necessary in the presence of timers; see comment in |
- // QuitLoopNow). |
- MessageLoop::current()->PostTask(FROM_HERE, base::Bind(&QuitLoopNow)); |
- RunLoop(); |
-} |
- |
-// Convenient to use in tests wishing to analyze SyncShare calls over time. |
-static const size_t kMinNumSamples = 5; |
-class SyncSchedulerTest : public testing::Test { |
- public: |
- SyncSchedulerTest() |
- : weak_ptr_factory_(ALLOW_THIS_IN_INITIALIZER_LIST(this)), |
- context_(NULL), |
- syncer_(NULL), |
- delay_(NULL) {} |
- |
- class MockDelayProvider : public SyncScheduler::DelayProvider { |
- public: |
- MOCK_METHOD1(GetDelay, TimeDelta(const TimeDelta&)); |
- }; |
- |
- virtual void SetUp() { |
- dir_maker_.SetUp(); |
- syncer_ = new MockSyncer(); |
- delay_ = NULL; |
- ModelSafeRoutingInfo routing_info; |
- routing_info[syncable::BOOKMARKS] = GROUP_UI; |
- routing_info[syncable::AUTOFILL] = GROUP_DB; |
- routing_info[syncable::THEMES] = GROUP_UI; |
- routing_info[syncable::NIGORI] = GROUP_PASSIVE; |
- registrar_.reset(new FakeModelSafeWorkerRegistrar(routing_info)); |
- connection_.reset(new MockConnectionManager(directory())); |
- connection_->SetServerReachable(); |
- context_ = new SyncSessionContext( |
- connection_.get(), directory(), registrar_.get(), |
- &extensions_activity_monitor_, |
- std::vector<SyncEngineEventListener*>(), NULL); |
- context_->set_notifications_enabled(true); |
- context_->set_account_name("Test"); |
- scheduler_.reset( |
- new SyncScheduler("TestSyncScheduler", context_, syncer_)); |
- } |
- |
- SyncScheduler* scheduler() { return scheduler_.get(); } |
- MockSyncer* syncer() { return syncer_; } |
- MockDelayProvider* delay() { return delay_; } |
- MockConnectionManager* connection() { return connection_.get(); } |
- TimeDelta zero() { return TimeDelta::FromSeconds(0); } |
- TimeDelta timeout() { |
- return TimeDelta::FromMilliseconds(TestTimeouts::action_timeout_ms()); |
- } |
- |
- virtual void TearDown() { |
- PumpLoop(); |
- scheduler_.reset(); |
- PumpLoop(); |
- dir_maker_.TearDown(); |
- } |
- |
- void AnalyzePollRun(const SyncShareRecords& records, size_t min_num_samples, |
- const TimeTicks& optimal_start, const TimeDelta& poll_interval) { |
- const std::vector<TimeTicks>& data(records.times); |
- EXPECT_GE(data.size(), min_num_samples); |
- for (size_t i = 0; i < data.size(); i++) { |
- SCOPED_TRACE(testing::Message() << "SyncShare # (" << i << ")"); |
- TimeTicks optimal_next_sync = optimal_start + poll_interval * i; |
- EXPECT_GE(data[i], optimal_next_sync); |
- EXPECT_EQ(GetUpdatesCallerInfo::PERIODIC, |
- records.snapshots[i]->source.updates_source); |
- } |
- } |
- |
- void DoQuitLoopNow() { |
- QuitLoopNow(); |
- } |
- |
- void StartSyncScheduler(SyncScheduler::Mode mode) { |
- scheduler()->Start( |
- mode, |
- base::Bind(&SyncSchedulerTest::DoQuitLoopNow, |
- weak_ptr_factory_.GetWeakPtr())); |
- } |
- |
- // This stops the scheduler synchronously. |
- void StopSyncScheduler() { |
- scheduler()->RequestStop(base::Bind(&SyncSchedulerTest::DoQuitLoopNow, |
- weak_ptr_factory_.GetWeakPtr())); |
- RunLoop(); |
- } |
- |
- bool RunAndGetBackoff() { |
- ModelTypeSet nudge_types; |
- StartSyncScheduler(SyncScheduler::NORMAL_MODE); |
- RunLoop(); |
- |
- scheduler()->ScheduleNudge( |
- zero(), NUDGE_SOURCE_LOCAL, nudge_types, FROM_HERE); |
- RunLoop(); |
- |
- return scheduler()->IsBackingOff(); |
- } |
- |
- void UseMockDelayProvider() { |
- delay_ = new MockDelayProvider(); |
- scheduler_->delay_provider_.reset(delay_); |
- } |
- |
- // Compare a ModelTypeSet to a ModelTypePayloadMap, ignoring |
- // payload values. |
- bool CompareModelTypeSetToModelTypePayloadMap( |
- ModelTypeSet lhs, |
- const syncable::ModelTypePayloadMap& rhs) { |
- size_t count = 0; |
- for (syncable::ModelTypePayloadMap::const_iterator i = rhs.begin(); |
- i != rhs.end(); ++i, ++count) { |
- if (!lhs.Has(i->first)) |
- return false; |
- } |
- if (lhs.Size() != count) |
- return false; |
- return true; |
- } |
- |
- SyncSessionContext* context() { return context_; } |
- |
- private: |
- syncable::Directory* directory() { |
- return dir_maker_.directory(); |
- } |
- |
- base::WeakPtrFactory<SyncSchedulerTest> weak_ptr_factory_; |
- MessageLoop message_loop_; |
- TestDirectorySetterUpper dir_maker_; |
- scoped_ptr<SyncScheduler> scheduler_; |
- scoped_ptr<MockConnectionManager> connection_; |
- SyncSessionContext* context_; |
- MockSyncer* syncer_; |
- MockDelayProvider* delay_; |
- scoped_ptr<FakeModelSafeWorkerRegistrar> registrar_; |
- FakeExtensionsActivityMonitor extensions_activity_monitor_; |
-}; |
- |
-class BackoffTriggersSyncSchedulerTest : public SyncSchedulerTest { |
- void SetUp() { |
- SyncSchedulerTest::SetUp(); |
- UseMockDelayProvider(); |
- EXPECT_CALL(*delay(), GetDelay(_)) |
- .WillRepeatedly(Return(TimeDelta::FromMilliseconds(1))); |
- } |
- |
- void TearDown() { |
- StopSyncScheduler(); |
- SyncSchedulerTest::TearDown(); |
- } |
-}; |
- |
-void RecordSyncShareImpl(SyncSession* s, SyncShareRecords* record) { |
- record->times.push_back(TimeTicks::Now()); |
- record->snapshots.push_back(make_linked_ptr(new SyncSessionSnapshot( |
- s->TakeSnapshot()))); |
-} |
- |
-ACTION_P(RecordSyncShare, record) { |
- RecordSyncShareImpl(arg0, record); |
- QuitLoopNow(); |
-} |
- |
-ACTION_P2(RecordSyncShareMultiple, record, quit_after) { |
- RecordSyncShareImpl(arg0, record); |
- EXPECT_LE(record->times.size(), quit_after); |
- if (record->times.size() >= quit_after) { |
- QuitLoopNow(); |
- } |
-} |
- |
-ACTION(AddFailureAndQuitLoopNow) { |
- ADD_FAILURE(); |
- QuitLoopNow(); |
-} |
- |
-ACTION(QuitLoopNowAction) { |
- QuitLoopNow(); |
-} |
- |
-// Test nudge scheduling. |
-TEST_F(SyncSchedulerTest, Nudge) { |
- SyncShareRecords records; |
- ModelTypeSet model_types(syncable::BOOKMARKS); |
- |
- EXPECT_CALL(*syncer(), SyncShare(_,_,_)) |
- .WillOnce(DoAll(Invoke(sessions::test_util::SimulateSuccess), |
- WithArg<0>(RecordSyncShare(&records)))) |
- .RetiresOnSaturation(); |
- |
- StartSyncScheduler(SyncScheduler::NORMAL_MODE); |
- RunLoop(); |
- |
- scheduler()->ScheduleNudge( |
- zero(), NUDGE_SOURCE_LOCAL, model_types, FROM_HERE); |
- RunLoop(); |
- |
- ASSERT_EQ(1U, records.snapshots.size()); |
- EXPECT_TRUE(CompareModelTypeSetToModelTypePayloadMap(model_types, |
- records.snapshots[0]->source.types)); |
- EXPECT_EQ(GetUpdatesCallerInfo::LOCAL, |
- records.snapshots[0]->source.updates_source); |
- |
- Mock::VerifyAndClearExpectations(syncer()); |
- |
- // Make sure a second, later, nudge is unaffected by first (no coalescing). |
- SyncShareRecords records2; |
- model_types.Remove(syncable::BOOKMARKS); |
- model_types.Put(syncable::AUTOFILL); |
- EXPECT_CALL(*syncer(), SyncShare(_,_,_)) |
- .WillOnce(DoAll(Invoke(sessions::test_util::SimulateSuccess), |
- WithArg<0>(RecordSyncShare(&records2)))); |
- scheduler()->ScheduleNudge( |
- zero(), NUDGE_SOURCE_LOCAL, model_types, FROM_HERE); |
- RunLoop(); |
- |
- ASSERT_EQ(1U, records2.snapshots.size()); |
- EXPECT_TRUE(CompareModelTypeSetToModelTypePayloadMap(model_types, |
- records2.snapshots[0]->source.types)); |
- EXPECT_EQ(GetUpdatesCallerInfo::LOCAL, |
- records2.snapshots[0]->source.updates_source); |
-} |
- |
-// Make sure a regular config command is scheduled fine in the absence of any |
-// errors. |
-TEST_F(SyncSchedulerTest, Config) { |
- SyncShareRecords records; |
- const ModelTypeSet model_types(syncable::BOOKMARKS); |
- |
- EXPECT_CALL(*syncer(), SyncShare(_,_,_)) |
- .WillOnce(DoAll(Invoke(sessions::test_util::SimulateSuccess), |
- WithArg<0>(RecordSyncShare(&records)))); |
- |
- StartSyncScheduler(SyncScheduler::CONFIGURATION_MODE); |
- RunLoop(); |
- |
- scheduler()->ScheduleConfig( |
- model_types, GetUpdatesCallerInfo::RECONFIGURATION); |
- RunLoop(); |
- |
- ASSERT_EQ(1U, records.snapshots.size()); |
- EXPECT_TRUE(CompareModelTypeSetToModelTypePayloadMap(model_types, |
- records.snapshots[0]->source.types)); |
- EXPECT_EQ(GetUpdatesCallerInfo::RECONFIGURATION, |
- records.snapshots[0]->source.updates_source); |
-} |
- |
-// Simulate a failure and make sure the config request is retried. |
-TEST_F(SyncSchedulerTest, ConfigWithBackingOff) { |
- UseMockDelayProvider(); |
- EXPECT_CALL(*delay(), GetDelay(_)) |
- .WillRepeatedly(Return(TimeDelta::FromMilliseconds(1))); |
- SyncShareRecords records; |
- const ModelTypeSet model_types(syncable::BOOKMARKS); |
- |
- EXPECT_CALL(*syncer(), SyncShare(_,_,_)) |
- .WillOnce(DoAll(Invoke(sessions::test_util::SimulateCommitFailed), |
- WithArg<0>(RecordSyncShare(&records)))) |
- .WillOnce(DoAll(Invoke(sessions::test_util::SimulateSuccess), |
- WithArg<0>(RecordSyncShare(&records)))); |
- |
- StartSyncScheduler(SyncScheduler::CONFIGURATION_MODE); |
- RunLoop(); |
- |
- ASSERT_EQ(0U, records.snapshots.size()); |
- scheduler()->ScheduleConfig( |
- model_types, GetUpdatesCallerInfo::RECONFIGURATION); |
- RunLoop(); |
- |
- ASSERT_EQ(1U, records.snapshots.size()); |
- RunLoop(); |
- |
- ASSERT_EQ(2U, records.snapshots.size()); |
- EXPECT_TRUE(CompareModelTypeSetToModelTypePayloadMap(model_types, |
- records.snapshots[1]->source.types)); |
- EXPECT_EQ(GetUpdatesCallerInfo::RECONFIGURATION, |
- records.snapshots[1]->source.updates_source); |
-} |
- |
-// Issue 2 config commands. Second one right after the first has failed |
-// and make sure LATEST is executed. |
-TEST_F(SyncSchedulerTest, MultipleConfigWithBackingOff) { |
- const ModelTypeSet |
- model_types1(syncable::BOOKMARKS), |
- model_types2(syncable::AUTOFILL); |
- UseMockDelayProvider(); |
- EXPECT_CALL(*delay(), GetDelay(_)) |
- .WillRepeatedly(Return(TimeDelta::FromMilliseconds(30))); |
- SyncShareRecords records; |
- |
- EXPECT_CALL(*syncer(), SyncShare(_,_,_)) |
- .WillOnce(DoAll(Invoke(sessions::test_util::SimulateCommitFailed), |
- WithArg<0>(RecordSyncShare(&records)))) |
- .WillOnce(DoAll(Invoke(sessions::test_util::SimulateCommitFailed), |
- WithArg<0>(RecordSyncShare(&records)))) |
- .WillOnce(DoAll(Invoke(sessions::test_util::SimulateSuccess), |
- WithArg<0>(RecordSyncShare(&records)))); |
- |
- StartSyncScheduler(SyncScheduler::CONFIGURATION_MODE); |
- RunLoop(); |
- |
- ASSERT_EQ(0U, records.snapshots.size()); |
- scheduler()->ScheduleConfig( |
- model_types1, GetUpdatesCallerInfo::RECONFIGURATION); |
- RunLoop(); |
- |
- ASSERT_EQ(1U, records.snapshots.size()); |
- scheduler()->ScheduleConfig( |
- model_types2, GetUpdatesCallerInfo::RECONFIGURATION); |
- RunLoop(); |
- |
- ASSERT_EQ(2U, records.snapshots.size()); |
- RunLoop(); |
- |
- ASSERT_EQ(3U, records.snapshots.size()); |
- EXPECT_TRUE(CompareModelTypeSetToModelTypePayloadMap(model_types2, |
- records.snapshots[2]->source.types)); |
- EXPECT_EQ(GetUpdatesCallerInfo::RECONFIGURATION, |
- records.snapshots[2]->source.updates_source); |
-} |
- |
-// Issue a nudge when the config has failed. Make sure both the config and |
-// nudge are executed. |
-TEST_F(SyncSchedulerTest, NudgeWithConfigWithBackingOff) { |
- const ModelTypeSet model_types(syncable::BOOKMARKS); |
- UseMockDelayProvider(); |
- EXPECT_CALL(*delay(), GetDelay(_)) |
- .WillRepeatedly(Return(TimeDelta::FromMilliseconds(50))); |
- SyncShareRecords records; |
- |
- EXPECT_CALL(*syncer(), SyncShare(_,_,_)) |
- .WillOnce(DoAll(Invoke(sessions::test_util::SimulateCommitFailed), |
- WithArg<0>(RecordSyncShare(&records)))) |
- .WillOnce(DoAll(Invoke(sessions::test_util::SimulateCommitFailed), |
- WithArg<0>(RecordSyncShare(&records)))) |
- .WillOnce(DoAll(Invoke(sessions::test_util::SimulateSuccess), |
- WithArg<0>(RecordSyncShare(&records)))) |
- .WillOnce(DoAll(Invoke(sessions::test_util::SimulateSuccess), |
- WithArg<0>(RecordSyncShare(&records)))); |
- |
- StartSyncScheduler(SyncScheduler::CONFIGURATION_MODE); |
- RunLoop(); |
- |
- ASSERT_EQ(0U, records.snapshots.size()); |
- scheduler()->ScheduleConfig( |
- model_types, GetUpdatesCallerInfo::RECONFIGURATION); |
- RunLoop(); |
- |
- ASSERT_EQ(1U, records.snapshots.size()); |
- scheduler()->ScheduleNudge( |
- zero(), NUDGE_SOURCE_LOCAL, model_types, FROM_HERE); |
- RunLoop(); |
- |
- ASSERT_EQ(2U, records.snapshots.size()); |
- RunLoop(); |
- |
- // Now change the mode so nudge can execute. |
- ASSERT_EQ(3U, records.snapshots.size()); |
- StartSyncScheduler(SyncScheduler::NORMAL_MODE); |
- RunLoop(); |
- |
- ASSERT_EQ(4U, records.snapshots.size()); |
- |
- EXPECT_TRUE(CompareModelTypeSetToModelTypePayloadMap(model_types, |
- records.snapshots[2]->source.types)); |
- EXPECT_EQ(GetUpdatesCallerInfo::RECONFIGURATION, |
- records.snapshots[2]->source.updates_source); |
- |
- EXPECT_TRUE(CompareModelTypeSetToModelTypePayloadMap(model_types, |
- records.snapshots[3]->source.types)); |
- EXPECT_EQ(GetUpdatesCallerInfo::LOCAL, |
- records.snapshots[3]->source.updates_source); |
- |
-} |
- |
-// Test that nudges are coalesced. |
-TEST_F(SyncSchedulerTest, NudgeCoalescing) { |
- StartSyncScheduler(SyncScheduler::NORMAL_MODE); |
- RunLoop(); |
- |
- SyncShareRecords r; |
- EXPECT_CALL(*syncer(), SyncShare(_,_,_)) |
- .WillOnce(DoAll(Invoke(sessions::test_util::SimulateSuccess), |
- WithArg<0>(RecordSyncShare(&r)))); |
- const ModelTypeSet |
- types1(syncable::BOOKMARKS), |
- types2(syncable::AUTOFILL), |
- types3(syncable::THEMES); |
- TimeDelta delay = zero(); |
- TimeTicks optimal_time = TimeTicks::Now() + delay; |
- scheduler()->ScheduleNudge( |
- delay, NUDGE_SOURCE_UNKNOWN, types1, FROM_HERE); |
- scheduler()->ScheduleNudge( |
- zero(), NUDGE_SOURCE_LOCAL, types2, FROM_HERE); |
- RunLoop(); |
- |
- ASSERT_EQ(1U, r.snapshots.size()); |
- EXPECT_GE(r.times[0], optimal_time); |
- EXPECT_TRUE(CompareModelTypeSetToModelTypePayloadMap( |
- Union(types1, types2), r.snapshots[0]->source.types)); |
- EXPECT_EQ(GetUpdatesCallerInfo::LOCAL, |
- r.snapshots[0]->source.updates_source); |
- |
- Mock::VerifyAndClearExpectations(syncer()); |
- |
- SyncShareRecords r2; |
- EXPECT_CALL(*syncer(), SyncShare(_,_,_)) |
- .WillOnce(DoAll(Invoke(sessions::test_util::SimulateSuccess), |
- WithArg<0>(RecordSyncShare(&r2)))); |
- scheduler()->ScheduleNudge( |
- zero(), NUDGE_SOURCE_NOTIFICATION, types3, FROM_HERE); |
- RunLoop(); |
- |
- ASSERT_EQ(1U, r2.snapshots.size()); |
- EXPECT_TRUE(CompareModelTypeSetToModelTypePayloadMap(types3, |
- r2.snapshots[0]->source.types)); |
- EXPECT_EQ(GetUpdatesCallerInfo::NOTIFICATION, |
- r2.snapshots[0]->source.updates_source); |
-} |
- |
-// Test that nudges are coalesced. |
-TEST_F(SyncSchedulerTest, NudgeCoalescingWithDifferentTimings) { |
- StartSyncScheduler(SyncScheduler::NORMAL_MODE); |
- RunLoop(); |
- |
- SyncShareRecords r; |
- EXPECT_CALL(*syncer(), SyncShare(_,_,_)) |
- .WillOnce(DoAll(Invoke(sessions::test_util::SimulateSuccess), |
- WithArg<0>(RecordSyncShare(&r)))); |
- syncable::ModelTypeSet types1(syncable::BOOKMARKS), |
- types2(syncable::AUTOFILL), types3; |
- |
- // Create a huge time delay. |
- TimeDelta delay = TimeDelta::FromDays(1); |
- |
- scheduler()->ScheduleNudge( |
- delay, NUDGE_SOURCE_UNKNOWN, types1, FROM_HERE); |
- |
- scheduler()->ScheduleNudge( |
- zero(), NUDGE_SOURCE_UNKNOWN, types2, FROM_HERE); |
- |
- TimeTicks min_time = TimeTicks::Now(); |
- TimeTicks max_time = TimeTicks::Now() + delay; |
- |
- RunLoop(); |
- |
- // Make sure the sync has happened. |
- ASSERT_EQ(1U, r.snapshots.size()); |
- EXPECT_TRUE(CompareModelTypeSetToModelTypePayloadMap( |
- Union(types1, types2), r.snapshots[0]->source.types)); |
- |
- // Make sure the sync happened at the right time. |
- EXPECT_GE(r.times[0], min_time); |
- EXPECT_LE(r.times[0], max_time); |
-} |
- |
-// Test nudge scheduling. |
-TEST_F(SyncSchedulerTest, NudgeWithPayloads) { |
- StartSyncScheduler(SyncScheduler::NORMAL_MODE); |
- RunLoop(); |
- |
- SyncShareRecords records; |
- syncable::ModelTypePayloadMap model_types_with_payloads; |
- model_types_with_payloads[syncable::BOOKMARKS] = "test"; |
- |
- EXPECT_CALL(*syncer(), SyncShare(_,_,_)) |
- .WillOnce(DoAll(Invoke(sessions::test_util::SimulateSuccess), |
- WithArg<0>(RecordSyncShare(&records)))) |
- .RetiresOnSaturation(); |
- scheduler()->ScheduleNudgeWithPayloads( |
- zero(), NUDGE_SOURCE_LOCAL, model_types_with_payloads, FROM_HERE); |
- RunLoop(); |
- |
- ASSERT_EQ(1U, records.snapshots.size()); |
- EXPECT_EQ(model_types_with_payloads, records.snapshots[0]->source.types); |
- EXPECT_EQ(GetUpdatesCallerInfo::LOCAL, |
- records.snapshots[0]->source.updates_source); |
- |
- Mock::VerifyAndClearExpectations(syncer()); |
- |
- // Make sure a second, later, nudge is unaffected by first (no coalescing). |
- SyncShareRecords records2; |
- model_types_with_payloads.erase(syncable::BOOKMARKS); |
- model_types_with_payloads[syncable::AUTOFILL] = "test2"; |
- EXPECT_CALL(*syncer(), SyncShare(_,_,_)) |
- .WillOnce(DoAll(Invoke(sessions::test_util::SimulateSuccess), |
- WithArg<0>(RecordSyncShare(&records2)))); |
- scheduler()->ScheduleNudgeWithPayloads( |
- zero(), NUDGE_SOURCE_LOCAL, model_types_with_payloads, FROM_HERE); |
- RunLoop(); |
- |
- ASSERT_EQ(1U, records2.snapshots.size()); |
- EXPECT_EQ(model_types_with_payloads, records2.snapshots[0]->source.types); |
- EXPECT_EQ(GetUpdatesCallerInfo::LOCAL, |
- records2.snapshots[0]->source.updates_source); |
-} |
- |
-// Test that nudges are coalesced. |
-TEST_F(SyncSchedulerTest, NudgeWithPayloadsCoalescing) { |
- StartSyncScheduler(SyncScheduler::NORMAL_MODE); |
- RunLoop(); |
- |
- SyncShareRecords r; |
- EXPECT_CALL(*syncer(), SyncShare(_,_,_)) |
- .WillOnce(DoAll(Invoke(sessions::test_util::SimulateSuccess), |
- WithArg<0>(RecordSyncShare(&r)))); |
- syncable::ModelTypePayloadMap types1, types2, types3; |
- types1[syncable::BOOKMARKS] = "test1"; |
- types2[syncable::AUTOFILL] = "test2"; |
- types3[syncable::THEMES] = "test3"; |
- TimeDelta delay = zero(); |
- TimeTicks optimal_time = TimeTicks::Now() + delay; |
- scheduler()->ScheduleNudgeWithPayloads( |
- delay, NUDGE_SOURCE_UNKNOWN, types1, FROM_HERE); |
- scheduler()->ScheduleNudgeWithPayloads( |
- zero(), NUDGE_SOURCE_LOCAL, types2, FROM_HERE); |
- RunLoop(); |
- |
- ASSERT_EQ(1U, r.snapshots.size()); |
- EXPECT_GE(r.times[0], optimal_time); |
- syncable::ModelTypePayloadMap coalesced_types; |
- syncable::CoalescePayloads(&coalesced_types, types1); |
- syncable::CoalescePayloads(&coalesced_types, types2); |
- EXPECT_EQ(coalesced_types, r.snapshots[0]->source.types); |
- EXPECT_EQ(GetUpdatesCallerInfo::LOCAL, |
- r.snapshots[0]->source.updates_source); |
- |
- Mock::VerifyAndClearExpectations(syncer()); |
- |
- SyncShareRecords r2; |
- EXPECT_CALL(*syncer(), SyncShare(_,_,_)) |
- .WillOnce(DoAll(Invoke(sessions::test_util::SimulateSuccess), |
- WithArg<0>(RecordSyncShare(&r2)))); |
- scheduler()->ScheduleNudgeWithPayloads( |
- zero(), NUDGE_SOURCE_NOTIFICATION, types3, FROM_HERE); |
- RunLoop(); |
- |
- ASSERT_EQ(1U, r2.snapshots.size()); |
- EXPECT_EQ(types3, r2.snapshots[0]->source.types); |
- EXPECT_EQ(GetUpdatesCallerInfo::NOTIFICATION, |
- r2.snapshots[0]->source.updates_source); |
-} |
- |
-// Test that polling works as expected. |
-TEST_F(SyncSchedulerTest, Polling) { |
- SyncShareRecords records; |
- TimeDelta poll_interval(TimeDelta::FromMilliseconds(30)); |
- EXPECT_CALL(*syncer(), SyncShare(_,_,_)).Times(AtLeast(kMinNumSamples)) |
- .WillRepeatedly(DoAll(Invoke(sessions::test_util::SimulateSuccess), |
- WithArg<0>(RecordSyncShareMultiple(&records, kMinNumSamples)))); |
- |
- scheduler()->OnReceivedLongPollIntervalUpdate(poll_interval); |
- |
- TimeTicks optimal_start = TimeTicks::Now() + poll_interval; |
- StartSyncScheduler(SyncScheduler::NORMAL_MODE); |
- RunLoop(); |
- |
- // Run again to wait for polling. |
- RunLoop(); |
- |
- StopSyncScheduler(); |
- AnalyzePollRun(records, kMinNumSamples, optimal_start, poll_interval); |
-} |
- |
-// Test that the short poll interval is used. |
-TEST_F(SyncSchedulerTest, PollNotificationsDisabled) { |
- SyncShareRecords records; |
- TimeDelta poll_interval(TimeDelta::FromMilliseconds(30)); |
- EXPECT_CALL(*syncer(), SyncShare(_,_,_)).Times(AtLeast(kMinNumSamples)) |
- .WillRepeatedly(DoAll(Invoke(sessions::test_util::SimulateSuccess), |
- WithArg<0>(RecordSyncShareMultiple(&records, kMinNumSamples)))); |
- |
- scheduler()->OnReceivedShortPollIntervalUpdate(poll_interval); |
- scheduler()->set_notifications_enabled(false); |
- |
- TimeTicks optimal_start = TimeTicks::Now() + poll_interval; |
- StartSyncScheduler(SyncScheduler::NORMAL_MODE); |
- RunLoop(); |
- |
- // Run again to wait for polling. |
- RunLoop(); |
- |
- StopSyncScheduler(); |
- AnalyzePollRun(records, kMinNumSamples, optimal_start, poll_interval); |
-} |
- |
-// Test that polling intervals are updated when needed. |
-TEST_F(SyncSchedulerTest, PollIntervalUpdate) { |
- SyncShareRecords records; |
- TimeDelta poll1(TimeDelta::FromMilliseconds(120)); |
- TimeDelta poll2(TimeDelta::FromMilliseconds(30)); |
- scheduler()->OnReceivedLongPollIntervalUpdate(poll1); |
- EXPECT_CALL(*syncer(), SyncShare(_,_,_)).Times(AtLeast(kMinNumSamples)) |
- .WillOnce(WithArg<0>( |
- sessions::test_util::SimulatePollIntervalUpdate(poll2))) |
- .WillRepeatedly( |
- DoAll(Invoke(sessions::test_util::SimulateSuccess), |
- WithArg<0>( |
- RecordSyncShareMultiple(&records, kMinNumSamples)))); |
- |
- TimeTicks optimal_start = TimeTicks::Now() + poll1 + poll2; |
- StartSyncScheduler(SyncScheduler::NORMAL_MODE); |
- RunLoop(); |
- |
- // Run again to wait for polling. |
- RunLoop(); |
- |
- StopSyncScheduler(); |
- AnalyzePollRun(records, kMinNumSamples, optimal_start, poll2); |
-} |
- |
-// Test that the sessions commit delay is updated when needed. |
-TEST_F(SyncSchedulerTest, SessionsCommitDelay) { |
- SyncShareRecords records; |
- TimeDelta delay1(TimeDelta::FromMilliseconds(120)); |
- TimeDelta delay2(TimeDelta::FromMilliseconds(30)); |
- scheduler()->OnReceivedSessionsCommitDelay(delay1); |
- |
- EXPECT_CALL(*syncer(), SyncShare(_,_,_)) |
- .WillOnce( |
- DoAll( |
- WithArg<0>( |
- sessions::test_util::SimulateSessionsCommitDelayUpdate( |
- delay2)), |
- Invoke(sessions::test_util::SimulateSuccess), |
- QuitLoopNowAction())); |
- |
- EXPECT_EQ(delay1, scheduler()->sessions_commit_delay()); |
- StartSyncScheduler(SyncScheduler::NORMAL_MODE); |
- RunLoop(); |
- |
- EXPECT_EQ(delay1, scheduler()->sessions_commit_delay()); |
- const ModelTypeSet model_types(syncable::BOOKMARKS); |
- scheduler()->ScheduleNudge( |
- zero(), NUDGE_SOURCE_LOCAL, model_types, FROM_HERE); |
- RunLoop(); |
- |
- EXPECT_EQ(delay2, scheduler()->sessions_commit_delay()); |
- StopSyncScheduler(); |
-} |
- |
-// Test that a sync session is run through to completion. |
-TEST_F(SyncSchedulerTest, HasMoreToSync) { |
- EXPECT_CALL(*syncer(), SyncShare(_,_,_)) |
- .WillOnce(Invoke(sessions::test_util::SimulateHasMoreToSync)) |
- .WillOnce(DoAll(Invoke(sessions::test_util::SimulateSuccess), |
- QuitLoopNowAction())); |
- StartSyncScheduler(SyncScheduler::NORMAL_MODE); |
- RunLoop(); |
- |
- scheduler()->ScheduleNudge( |
- zero(), NUDGE_SOURCE_LOCAL, ModelTypeSet(), FROM_HERE); |
- RunLoop(); |
- // If more nudges are scheduled, they'll be waited on by TearDown, and would |
- // cause our expectation to break. |
-} |
- |
-// Test that no syncing occurs when throttled. |
-TEST_F(SyncSchedulerTest, ThrottlingDoesThrottle) { |
- const ModelTypeSet types(syncable::BOOKMARKS); |
- TimeDelta poll(TimeDelta::FromMilliseconds(5)); |
- TimeDelta throttle(TimeDelta::FromMinutes(10)); |
- scheduler()->OnReceivedLongPollIntervalUpdate(poll); |
- EXPECT_CALL(*syncer(), SyncShare(_,_,_)) |
- .WillOnce(WithArg<0>(sessions::test_util::SimulateThrottled(throttle))) |
- .WillRepeatedly(AddFailureAndQuitLoopNow()); |
- |
- StartSyncScheduler(SyncScheduler::NORMAL_MODE); |
- RunLoop(); |
- |
- scheduler()->ScheduleNudge( |
- zero(), NUDGE_SOURCE_LOCAL, types, FROM_HERE); |
- PumpLoop(); |
- |
- StartSyncScheduler(SyncScheduler::CONFIGURATION_MODE); |
- RunLoop(); |
- |
- scheduler()->ScheduleConfig( |
- types, GetUpdatesCallerInfo::RECONFIGURATION); |
- PumpLoop(); |
-} |
- |
-TEST_F(SyncSchedulerTest, ThrottlingExpires) { |
- SyncShareRecords records; |
- TimeDelta poll(TimeDelta::FromMilliseconds(15)); |
- TimeDelta throttle1(TimeDelta::FromMilliseconds(150)); |
- scheduler()->OnReceivedLongPollIntervalUpdate(poll); |
- |
- ::testing::InSequence seq; |
- EXPECT_CALL(*syncer(), SyncShare(_,_,_)) |
- .WillOnce(WithArg<0>(sessions::test_util::SimulateThrottled(throttle1))) |
- .RetiresOnSaturation(); |
- EXPECT_CALL(*syncer(), SyncShare(_,_,_)) |
- .WillRepeatedly(DoAll(Invoke(sessions::test_util::SimulateSuccess), |
- WithArg<0>(RecordSyncShareMultiple(&records, kMinNumSamples)))); |
- |
- TimeTicks optimal_start = TimeTicks::Now() + poll + throttle1; |
- StartSyncScheduler(SyncScheduler::NORMAL_MODE); |
- RunLoop(); |
- |
- // Run again to wait for polling. |
- RunLoop(); |
- |
- StopSyncScheduler(); |
- AnalyzePollRun(records, kMinNumSamples, optimal_start, poll); |
-} |
- |
-// Test nudges / polls don't run in config mode and config tasks do. |
-TEST_F(SyncSchedulerTest, ConfigurationMode) { |
- TimeDelta poll(TimeDelta::FromMilliseconds(15)); |
- SyncShareRecords records; |
- scheduler()->OnReceivedLongPollIntervalUpdate(poll); |
- EXPECT_CALL(*syncer(), SyncShare(_,_,_)) |
- .WillOnce((Invoke(sessions::test_util::SimulateSuccess), |
- WithArg<0>(RecordSyncShare(&records)))); |
- |
- StartSyncScheduler(SyncScheduler::CONFIGURATION_MODE); |
- RunLoop(); |
- |
- const ModelTypeSet nudge_types(syncable::AUTOFILL); |
- scheduler()->ScheduleNudge( |
- zero(), NUDGE_SOURCE_LOCAL, nudge_types, FROM_HERE); |
- scheduler()->ScheduleNudge( |
- zero(), NUDGE_SOURCE_LOCAL, nudge_types, FROM_HERE); |
- |
- const ModelTypeSet config_types(syncable::BOOKMARKS); |
- |
- scheduler()->ScheduleConfig( |
- config_types, GetUpdatesCallerInfo::RECONFIGURATION); |
- RunLoop(); |
- |
- ASSERT_EQ(1U, records.snapshots.size()); |
- EXPECT_TRUE(CompareModelTypeSetToModelTypePayloadMap(config_types, |
- records.snapshots[0]->source.types)); |
-} |
- |
-// Have the sycner fail during commit. Expect that the scheduler enters |
-// backoff. |
-TEST_F(BackoffTriggersSyncSchedulerTest, FailCommitOnce) { |
- EXPECT_CALL(*syncer(), SyncShare(_,_,_)) |
- .WillOnce(DoAll(Invoke(sessions::test_util::SimulateCommitFailed), |
- QuitLoopNowAction())); |
- EXPECT_TRUE(RunAndGetBackoff()); |
-} |
- |
-// Have the syncer fail during download updates and succeed on the first |
-// retry. Expect that this clears the backoff state. |
-TEST_F(BackoffTriggersSyncSchedulerTest, FailDownloadOnceThenSucceed) { |
- EXPECT_CALL(*syncer(), SyncShare(_,_,_)) |
- .WillOnce(Invoke(sessions::test_util::SimulateDownloadUpdatesFailed)) |
- .WillOnce(DoAll(Invoke(sessions::test_util::SimulateSuccess), |
- QuitLoopNowAction())); |
- EXPECT_FALSE(RunAndGetBackoff()); |
-} |
- |
-// Have the syncer fail during commit and succeed on the first retry. Expect |
-// that this clears the backoff state. |
-TEST_F(BackoffTriggersSyncSchedulerTest, FailCommitOnceThenSucceed) { |
- EXPECT_CALL(*syncer(), SyncShare(_,_,_)) |
- .WillOnce(Invoke(sessions::test_util::SimulateCommitFailed)) |
- .WillOnce(DoAll(Invoke(sessions::test_util::SimulateSuccess), |
- QuitLoopNowAction())); |
- EXPECT_FALSE(RunAndGetBackoff()); |
-} |
- |
-// Have the syncer fail to download updates and fail again on the retry. |
-// Expect this will leave the scheduler in backoff. |
-TEST_F(BackoffTriggersSyncSchedulerTest, FailDownloadTwice) { |
- EXPECT_CALL(*syncer(), SyncShare(_,_,_)) |
- .WillOnce(Invoke(sessions::test_util::SimulateDownloadUpdatesFailed)) |
- .WillRepeatedly(DoAll( |
- Invoke(sessions::test_util::SimulateDownloadUpdatesFailed), |
- QuitLoopNowAction())); |
- EXPECT_TRUE(RunAndGetBackoff()); |
-} |
- |
-// Test that no polls or extraneous nudges occur when in backoff. |
-TEST_F(SyncSchedulerTest, BackoffDropsJobs) { |
- SyncShareRecords r; |
- TimeDelta poll(TimeDelta::FromMilliseconds(5)); |
- const ModelTypeSet types(syncable::BOOKMARKS); |
- scheduler()->OnReceivedLongPollIntervalUpdate(poll); |
- UseMockDelayProvider(); |
- |
- EXPECT_CALL(*syncer(), SyncShare(_,_,_)).Times(1) |
- .WillRepeatedly(DoAll(Invoke(sessions::test_util::SimulateCommitFailed), |
- RecordSyncShareMultiple(&r, 1U))); |
- EXPECT_CALL(*delay(), GetDelay(_)). |
- WillRepeatedly(Return(TimeDelta::FromDays(1))); |
- |
- StartSyncScheduler(SyncScheduler::NORMAL_MODE); |
- RunLoop(); |
- |
- // This nudge should fail and put us into backoff. Thanks to our mock |
- // GetDelay() setup above, this will be a long backoff. |
- scheduler()->ScheduleNudge(zero(), NUDGE_SOURCE_LOCAL, types, FROM_HERE); |
- RunLoop(); |
- |
- Mock::VerifyAndClearExpectations(syncer()); |
- ASSERT_EQ(1U, r.snapshots.size()); |
- EXPECT_EQ(GetUpdatesCallerInfo::LOCAL, r.snapshots[0]->source.updates_source); |
- |
- EXPECT_CALL(*syncer(), SyncShare(_,_,_)).Times(1) |
- .WillOnce(DoAll(Invoke(sessions::test_util::SimulateCommitFailed), |
- RecordSyncShare(&r))); |
- |
- // We schedule a nudge with enough delay (10X poll interval) that at least |
- // one or two polls would have taken place. The nudge should succeed. |
- scheduler()->ScheduleNudge(poll * 10, NUDGE_SOURCE_LOCAL, types, FROM_HERE); |
- RunLoop(); |
- |
- Mock::VerifyAndClearExpectations(syncer()); |
- Mock::VerifyAndClearExpectations(delay()); |
- ASSERT_EQ(2U, r.snapshots.size()); |
- EXPECT_EQ(GetUpdatesCallerInfo::LOCAL, r.snapshots[1]->source.updates_source); |
- |
- EXPECT_CALL(*syncer(), SyncShare(_,_,_)).Times(0); |
- EXPECT_CALL(*delay(), GetDelay(_)).Times(0); |
- |
- StartSyncScheduler(SyncScheduler::CONFIGURATION_MODE); |
- RunLoop(); |
- |
- scheduler()->ScheduleConfig( |
- types, GetUpdatesCallerInfo::RECONFIGURATION); |
- PumpLoop(); |
- |
- StartSyncScheduler(SyncScheduler::NORMAL_MODE); |
- RunLoop(); |
- |
- scheduler()->ScheduleNudge( |
- zero(), NUDGE_SOURCE_LOCAL, types, FROM_HERE); |
- scheduler()->ScheduleNudge( |
- zero(), NUDGE_SOURCE_LOCAL, types, FROM_HERE); |
- PumpLoop(); |
-} |
- |
-// Test that backoff is shaping traffic properly with consecutive errors. |
-TEST_F(SyncSchedulerTest, BackoffElevation) { |
- SyncShareRecords r; |
- UseMockDelayProvider(); |
- |
- EXPECT_CALL(*syncer(), SyncShare(_,_,_)).Times(kMinNumSamples) |
- .WillRepeatedly(DoAll(Invoke(sessions::test_util::SimulateCommitFailed), |
- RecordSyncShareMultiple(&r, kMinNumSamples))); |
- |
- const TimeDelta first = TimeDelta::FromSeconds(1); |
- const TimeDelta second = TimeDelta::FromMilliseconds(2); |
- const TimeDelta third = TimeDelta::FromMilliseconds(3); |
- const TimeDelta fourth = TimeDelta::FromMilliseconds(4); |
- const TimeDelta fifth = TimeDelta::FromMilliseconds(5); |
- const TimeDelta sixth = TimeDelta::FromDays(1); |
- |
- EXPECT_CALL(*delay(), GetDelay(Eq(first))).WillOnce(Return(second)) |
- .RetiresOnSaturation(); |
- EXPECT_CALL(*delay(), GetDelay(Eq(second))).WillOnce(Return(third)) |
- .RetiresOnSaturation(); |
- EXPECT_CALL(*delay(), GetDelay(Eq(third))).WillOnce(Return(fourth)) |
- .RetiresOnSaturation(); |
- EXPECT_CALL(*delay(), GetDelay(Eq(fourth))).WillOnce(Return(fifth)) |
- .RetiresOnSaturation(); |
- EXPECT_CALL(*delay(), GetDelay(Eq(fifth))).WillOnce(Return(sixth)); |
- |
- StartSyncScheduler(SyncScheduler::NORMAL_MODE); |
- RunLoop(); |
- |
- // Run again with a nudge. |
- scheduler()->ScheduleNudge( |
- zero(), NUDGE_SOURCE_LOCAL, ModelTypeSet(), FROM_HERE); |
- RunLoop(); |
- |
- ASSERT_EQ(kMinNumSamples, r.snapshots.size()); |
- EXPECT_GE(r.times[1] - r.times[0], second); |
- EXPECT_GE(r.times[2] - r.times[1], third); |
- EXPECT_GE(r.times[3] - r.times[2], fourth); |
- EXPECT_GE(r.times[4] - r.times[3], fifth); |
-} |
- |
-// Test that things go back to normal once a retry makes forward progress. |
-TEST_F(SyncSchedulerTest, BackoffRelief) { |
- SyncShareRecords r; |
- const TimeDelta poll(TimeDelta::FromMilliseconds(10)); |
- scheduler()->OnReceivedLongPollIntervalUpdate(poll); |
- UseMockDelayProvider(); |
- |
- const TimeDelta backoff = TimeDelta::FromMilliseconds(5); |
- |
- EXPECT_CALL(*syncer(), SyncShare(_,_,_)) |
- .WillOnce(DoAll(Invoke(sessions::test_util::SimulateCommitFailed), |
- RecordSyncShareMultiple(&r, kMinNumSamples))) |
- .WillRepeatedly(DoAll(Invoke(sessions::test_util::SimulateSuccess), |
- RecordSyncShareMultiple(&r, kMinNumSamples))); |
- EXPECT_CALL(*delay(), GetDelay(_)).WillOnce(Return(backoff)); |
- |
- // Optimal start for the post-backoff poll party. |
- TimeTicks optimal_start = TimeTicks::Now(); |
- StartSyncScheduler(SyncScheduler::NORMAL_MODE); |
- RunLoop(); |
- |
- // Run again to wait for polling. |
- scheduler()->ScheduleNudge(zero(), NUDGE_SOURCE_LOCAL, |
- ModelTypeSet(), FROM_HERE); |
- RunLoop(); |
- |
- StopSyncScheduler(); |
- |
- EXPECT_EQ(kMinNumSamples, r.times.size()); |
- |
- // The first nudge ran as soon as possible. It failed. |
- TimeTicks optimal_job_time = optimal_start; |
- EXPECT_GE(r.times[0], optimal_job_time); |
- EXPECT_EQ(GetUpdatesCallerInfo::LOCAL, |
- r.snapshots[0]->source.updates_source); |
- |
- // It was followed by a successful retry nudge shortly afterward. |
- optimal_job_time = optimal_job_time + backoff; |
- EXPECT_GE(r.times[1], optimal_job_time); |
- EXPECT_EQ(GetUpdatesCallerInfo::LOCAL, |
- r.snapshots[1]->source.updates_source); |
- // After that, we went back to polling. |
- for (size_t i = 2; i < r.snapshots.size(); i++) { |
- optimal_job_time = optimal_job_time + poll; |
- SCOPED_TRACE(testing::Message() << "SyncShare # (" << i << ")"); |
- EXPECT_GE(r.times[i], optimal_job_time); |
- EXPECT_EQ(GetUpdatesCallerInfo::PERIODIC, |
- r.snapshots[i]->source.updates_source); |
- } |
-} |
- |
-// Test that poll failures are ignored. They should have no effect on |
-// subsequent poll attempts, nor should they trigger a backoff/retry. |
-TEST_F(SyncSchedulerTest, TransientPollFailure) { |
- SyncShareRecords r; |
- const TimeDelta poll_interval(TimeDelta::FromMilliseconds(10)); |
- scheduler()->OnReceivedLongPollIntervalUpdate(poll_interval); |
- UseMockDelayProvider(); // Will cause test failure if backoff is initiated. |
- |
- EXPECT_CALL(*syncer(), SyncShare(_,_,_)) |
- .WillOnce(DoAll(Invoke(sessions::test_util::SimulateCommitFailed), |
- RecordSyncShare(&r))) |
- .WillOnce(DoAll(Invoke(sessions::test_util::SimulateSuccess), |
- RecordSyncShare(&r))); |
- |
- StartSyncScheduler(SyncScheduler::NORMAL_MODE); |
- RunLoop(); |
- |
- // Run the unsucessful poll. The failed poll should not trigger backoff. |
- RunLoop(); |
- EXPECT_FALSE(scheduler()->IsBackingOff()); |
- |
- // Run the successful poll. |
- RunLoop(); |
- EXPECT_FALSE(scheduler()->IsBackingOff()); |
- |
- // Verify the the two SyncShare() calls were made one poll interval apart. |
- ASSERT_EQ(2U, r.snapshots.size()); |
- EXPECT_GE(r.times[1] - r.times[0], poll_interval); |
-} |
- |
-TEST_F(SyncSchedulerTest, GetRecommendedDelay) { |
- EXPECT_LE(TimeDelta::FromSeconds(0), |
- SyncScheduler::GetRecommendedDelay(TimeDelta::FromSeconds(0))); |
- EXPECT_LE(TimeDelta::FromSeconds(1), |
- SyncScheduler::GetRecommendedDelay(TimeDelta::FromSeconds(1))); |
- EXPECT_LE(TimeDelta::FromSeconds(50), |
- SyncScheduler::GetRecommendedDelay(TimeDelta::FromSeconds(50))); |
- EXPECT_LE(TimeDelta::FromSeconds(10), |
- SyncScheduler::GetRecommendedDelay(TimeDelta::FromSeconds(10))); |
- EXPECT_EQ(TimeDelta::FromSeconds(kMaxBackoffSeconds), |
- SyncScheduler::GetRecommendedDelay( |
- TimeDelta::FromSeconds(kMaxBackoffSeconds))); |
- EXPECT_EQ(TimeDelta::FromSeconds(kMaxBackoffSeconds), |
- SyncScheduler::GetRecommendedDelay( |
- TimeDelta::FromSeconds(kMaxBackoffSeconds + 1))); |
-} |
- |
-// Test that appropriate syncer steps are requested for each job type. |
-TEST_F(SyncSchedulerTest, SyncerSteps) { |
- // Nudges. |
- EXPECT_CALL(*syncer(), SyncShare(_, SYNCER_BEGIN, SYNCER_END)) |
- .Times(1); |
- StartSyncScheduler(SyncScheduler::NORMAL_MODE); |
- RunLoop(); |
- |
- scheduler()->ScheduleNudge( |
- zero(), NUDGE_SOURCE_LOCAL, ModelTypeSet(), FROM_HERE); |
- PumpLoop(); |
- // Pump again to run job. |
- PumpLoop(); |
- |
- StopSyncScheduler(); |
- Mock::VerifyAndClearExpectations(syncer()); |
- |
- // ClearUserData. |
- EXPECT_CALL(*syncer(), SyncShare(_, CLEAR_PRIVATE_DATA, CLEAR_PRIVATE_DATA)) |
- .Times(1); |
- StartSyncScheduler(SyncScheduler::NORMAL_MODE); |
- RunLoop(); |
- |
- scheduler()->ScheduleClearUserData(); |
- PumpLoop(); |
- PumpLoop(); |
- |
- StopSyncScheduler(); |
- Mock::VerifyAndClearExpectations(syncer()); |
- |
- // Configuration. |
- EXPECT_CALL(*syncer(), SyncShare(_, DOWNLOAD_UPDATES, APPLY_UPDATES)); |
- StartSyncScheduler(SyncScheduler::CONFIGURATION_MODE); |
- RunLoop(); |
- |
- scheduler()->ScheduleConfig( |
- ModelTypeSet(), GetUpdatesCallerInfo::RECONFIGURATION); |
- PumpLoop(); |
- PumpLoop(); |
- |
- StopSyncScheduler(); |
- Mock::VerifyAndClearExpectations(syncer()); |
- |
- // Cleanup disabled types. |
- EXPECT_CALL(*syncer(), |
- SyncShare(_, CLEANUP_DISABLED_TYPES, CLEANUP_DISABLED_TYPES)); |
- StartSyncScheduler(SyncScheduler::NORMAL_MODE); |
- RunLoop(); |
- |
- scheduler()->ScheduleCleanupDisabledTypes(); |
- // Only need to pump once, as ScheduleCleanupDisabledTypes() |
- // schedules the job directly. |
- PumpLoop(); |
- |
- StopSyncScheduler(); |
- Mock::VerifyAndClearExpectations(syncer()); |
- |
- // Poll. |
- EXPECT_CALL(*syncer(), SyncShare(_, SYNCER_BEGIN, SYNCER_END)) |
- .Times(AtLeast(1)) |
- .WillRepeatedly(QuitLoopNowAction()); |
- const TimeDelta poll(TimeDelta::FromMilliseconds(10)); |
- scheduler()->OnReceivedLongPollIntervalUpdate(poll); |
- |
- StartSyncScheduler(SyncScheduler::NORMAL_MODE); |
- RunLoop(); |
- |
- // Run again to wait for polling. |
- RunLoop(); |
- |
- StopSyncScheduler(); |
- Mock::VerifyAndClearExpectations(syncer()); |
-} |
- |
-// Test config tasks don't run during normal mode. |
-// TODO(tim): Implement this test and then the functionality! |
-TEST_F(SyncSchedulerTest, DISABLED_NoConfigDuringNormal) { |
-} |
- |
-// Test that starting the syncer thread without a valid connection doesn't |
-// break things when a connection is detected. |
-TEST_F(SyncSchedulerTest, StartWhenNotConnected) { |
- connection()->SetServerNotReachable(); |
- EXPECT_CALL(*syncer(), SyncShare(_,_,_)) |
- .WillOnce(Invoke(sessions::test_util::SimulateDownloadUpdatesFailed)) |
- .WillOnce(QuitLoopNowAction()); |
- StartSyncScheduler(SyncScheduler::NORMAL_MODE); |
- MessageLoop::current()->RunAllPending(); |
- |
- scheduler()->ScheduleNudge( |
- zero(), NUDGE_SOURCE_LOCAL, ModelTypeSet(), FROM_HERE); |
- // Should save the nudge for until after the server is reachable. |
- MessageLoop::current()->RunAllPending(); |
- |
- connection()->SetServerReachable(); |
- scheduler()->OnConnectionStatusChange(); |
- MessageLoop::current()->RunAllPending(); |
-} |
- |
-TEST_F(SyncSchedulerTest, SetsPreviousRoutingInfo) { |
- ModelSafeRoutingInfo info; |
- EXPECT_TRUE(info == context()->previous_session_routing_info()); |
- ModelSafeRoutingInfo expected; |
- context()->registrar()->GetModelSafeRoutingInfo(&expected); |
- ASSERT_FALSE(expected.empty()); |
- EXPECT_CALL(*syncer(), SyncShare(_,_,_)).Times(1); |
- |
- StartSyncScheduler(SyncScheduler::NORMAL_MODE); |
- RunLoop(); |
- |
- scheduler()->ScheduleNudge( |
- zero(), NUDGE_SOURCE_LOCAL, ModelTypeSet(), FROM_HERE); |
- PumpLoop(); |
- // Pump again to run job. |
- PumpLoop(); |
- |
- StopSyncScheduler(); |
- |
- EXPECT_TRUE(expected == context()->previous_session_routing_info()); |
-} |
- |
-} // namespace browser_sync |