using testing::Return;
using testing::WithArg;
using testing::WithArgs;
+using testing::WithoutArgs;
namespace syncer {
using sessions::SyncSession;
sync_pb::GetUpdatesCallerInfo::GetUpdatesSource,
SyncSession*));
MOCK_METHOD2(PollSyncShare, bool(ModelTypeSet, sessions::SyncSession*));
+ MOCK_METHOD2(RetrySyncShare, bool(ModelTypeSet, sessions::SyncSession*));
};
MockSyncer::MockSyncer()
workers_.push_back(make_scoped_refptr(new FakeModelWorker(GROUP_DB)));
workers_.push_back(make_scoped_refptr(new FakeModelWorker(GROUP_PASSIVE)));
- std::vector<ModelSafeWorker*> workers;
- for (std::vector<scoped_refptr<FakeModelWorker> >::iterator it =
- workers_.begin(); it != workers_.end(); ++it) {
- workers.push_back(it->get());
- }
-
connection_.reset(new MockConnectionManager(directory(),
&cancelation_signal_));
connection_->SetServerReachable();
+
+ model_type_registry_.reset(new ModelTypeRegistry(workers_, directory()));
+
context_.reset(new SyncSessionContext(
- connection_.get(), directory(), workers,
+ connection_.get(), directory(),
extensions_activity_.get(),
std::vector<SyncEngineEventListener*>(), NULL, NULL,
+ model_type_registry_.get(),
true, // enable keystore encryption
false, // force enable pre-commit GU avoidance
"fake_invalidator_client_id"));
- context_->set_routing_info(routing_info_);
+ context_->SetRoutingInfo(routing_info_);
context_->set_notifications_enabled(true);
context_->set_account_name("Test");
scheduler_.reset(
return scheduler_->nudge_tracker_.GetThrottledTypes();
}
+ base::TimeDelta GetRetryTimerDelay() {
+ EXPECT_TRUE(scheduler_->retry_timer_.IsRunning());
+ return scheduler_->retry_timer_.GetCurrentDelay();
+ }
+
private:
syncable::Directory* directory() {
return dir_maker_.directory();
TestDirectorySetterUpper dir_maker_;
CancelationSignal cancelation_signal_;
scoped_ptr<MockConnectionManager> connection_;
+ scoped_ptr<ModelTypeRegistry> model_type_registry_;
scoped_ptr<SyncSessionContext> context_;
scoped_ptr<SyncSchedulerImpl> scheduler_;
MockSyncer* syncer_;
MockDelayProvider* delay_;
- std::vector<scoped_refptr<FakeModelWorker> > workers_;
+ std::vector<scoped_refptr<ModelSafeWorker> > workers_;
scoped_refptr<ExtensionsActivity> extensions_activity_;
ModelSafeRoutingInfo routing_info_;
base::WeakPtrFactory<SyncSchedulerTest> weak_ptr_factory_;
return true;
}
+ACTION_P(StopScheduler, scheduler) {
+ scheduler->Stop();
+}
+
ACTION(AddFailureAndQuitLoopNow) {
ADD_FAILURE();
QuitLoopNow();
StartSyncScheduler(SyncScheduler::CONFIGURATION_MODE);
- CallbackCounter counter;
+ CallbackCounter ready_counter;
+ CallbackCounter retry_counter;
ConfigurationParams params(
GetUpdatesCallerInfo::RECONFIGURATION,
model_types,
TypesToRoutingInfo(model_types),
- base::Bind(&CallbackCounter::Callback, base::Unretained(&counter)));
- ASSERT_TRUE(scheduler()->ScheduleConfiguration(params));
- ASSERT_EQ(1, counter.times_called());
+ base::Bind(&CallbackCounter::Callback, base::Unretained(&ready_counter)),
+ base::Bind(&CallbackCounter::Callback, base::Unretained(&retry_counter)));
+ scheduler()->ScheduleConfiguration(params);
+ PumpLoop();
+ ASSERT_EQ(1, ready_counter.times_called());
+ ASSERT_EQ(0, retry_counter.times_called());
}
// Simulate a failure and make sure the config request is retried.
EXPECT_CALL(*syncer(), ConfigureSyncShare(_,_,_))
.WillOnce(DoAll(Invoke(sessions::test_util::SimulateConfigureFailed),
+ RecordSyncShare(×)))
+ .WillOnce(DoAll(Invoke(sessions::test_util::SimulateConfigureFailed),
RecordSyncShare(×)));
- CallbackCounter counter;
+ CallbackCounter ready_counter;
+ CallbackCounter retry_counter;
ConfigurationParams params(
GetUpdatesCallerInfo::RECONFIGURATION,
model_types,
TypesToRoutingInfo(model_types),
- base::Bind(&CallbackCounter::Callback, base::Unretained(&counter)));
- ASSERT_FALSE(scheduler()->ScheduleConfiguration(params));
- ASSERT_EQ(0, counter.times_called());
+ base::Bind(&CallbackCounter::Callback, base::Unretained(&ready_counter)),
+ base::Bind(&CallbackCounter::Callback, base::Unretained(&retry_counter)));
+ scheduler()->ScheduleConfiguration(params);
+ RunLoop();
+ ASSERT_EQ(0, ready_counter.times_called());
+ ASSERT_EQ(1, retry_counter.times_called());
+
+ // RunLoop() will trigger TryCanaryJob which will retry configuration.
+ // Since retry_task was already called it shouldn't be called again.
+ RunLoop();
+ ASSERT_EQ(0, ready_counter.times_called());
+ ASSERT_EQ(1, retry_counter.times_called());
Mock::VerifyAndClearExpectations(syncer());
RecordSyncShare(×)));
RunLoop();
- ASSERT_EQ(1, counter.times_called());
+ ASSERT_EQ(1, ready_counter.times_called());
+}
+
+// Simuilate SyncSchedulerImpl::Stop being called in the middle of Configure.
+// This can happen if server returns NOT_MY_BIRTHDAY.
+TEST_F(SyncSchedulerTest, ConfigWithStop) {
+ UseMockDelayProvider();
+ EXPECT_CALL(*delay(), GetDelay(_))
+ .WillRepeatedly(Return(TimeDelta::FromMilliseconds(1)));
+ SyncShareTimes times;
+ const ModelTypeSet model_types(BOOKMARKS);
+
+ StartSyncScheduler(SyncScheduler::CONFIGURATION_MODE);
+
+ // Make ConfigureSyncShare call scheduler->Stop(). It is not supposed to call
+ // retry_task or dereference configuration params.
+ EXPECT_CALL(*syncer(), ConfigureSyncShare(_,_,_))
+ .WillOnce(DoAll(Invoke(sessions::test_util::SimulateConfigureFailed),
+ StopScheduler(scheduler()),
+ RecordSyncShare(×)));
+
+ CallbackCounter ready_counter;
+ CallbackCounter retry_counter;
+ ConfigurationParams params(
+ GetUpdatesCallerInfo::RECONFIGURATION,
+ model_types,
+ TypesToRoutingInfo(model_types),
+ base::Bind(&CallbackCounter::Callback, base::Unretained(&ready_counter)),
+ base::Bind(&CallbackCounter::Callback, base::Unretained(&retry_counter)));
+ scheduler()->ScheduleConfiguration(params);
+ PumpLoop();
+ ASSERT_EQ(0, ready_counter.times_called());
+ ASSERT_EQ(0, retry_counter.times_called());
}
// Issue a nudge when the config has failed. Make sure both the config and
EXPECT_CALL(*syncer(), ConfigureSyncShare(_,_,_))
.WillOnce(DoAll(Invoke(sessions::test_util::SimulateConfigureFailed),
RecordSyncShare(×)));
- CallbackCounter counter;
+ CallbackCounter ready_counter;
+ CallbackCounter retry_counter;
ConfigurationParams params(
GetUpdatesCallerInfo::RECONFIGURATION,
model_types,
TypesToRoutingInfo(model_types),
- base::Bind(&CallbackCounter::Callback, base::Unretained(&counter)));
- ASSERT_FALSE(scheduler()->ScheduleConfiguration(params));
- ASSERT_EQ(0, counter.times_called());
+ base::Bind(&CallbackCounter::Callback, base::Unretained(&ready_counter)),
+ base::Bind(&CallbackCounter::Callback, base::Unretained(&retry_counter)));
+ scheduler()->ScheduleConfiguration(params);
+ RunLoop();
+ ASSERT_EQ(0, ready_counter.times_called());
+ ASSERT_EQ(1, retry_counter.times_called());
Mock::VerifyAndClearExpectations(syncer());
// Ask for a nudge while dealing with repeated configure failure.
// for the first retry attempt from the config job (after
// waiting ~+/- 50ms).
Mock::VerifyAndClearExpectations(syncer());
- ASSERT_EQ(0, counter.times_called());
+ ASSERT_EQ(0, ready_counter.times_called());
// Let the next configure retry succeed.
EXPECT_CALL(*syncer(), ConfigureSyncShare(_,_,_))
.WillOnce(DoAll(Invoke(sessions::test_util::SimulateNormalSuccess),
RecordSyncShare(×)));
StartSyncScheduler(SyncScheduler::NORMAL_MODE);
+ PumpLoop();
}
// Test that nudges are coalesced.
SyncShareTimes times;
TimeDelta poll_interval(TimeDelta::FromMilliseconds(30));
EXPECT_CALL(*syncer(), PollSyncShare(_,_)).Times(AtLeast(kMinNumSamples))
- .WillRepeatedly(DoAll(Invoke(sessions::test_util::SimulatePollSuccess),
- RecordSyncShareMultiple(×, kMinNumSamples)));
+ .WillRepeatedly(
+ DoAll(Invoke(sessions::test_util::SimulatePollRetrySuccess),
+ RecordSyncShareMultiple(×, kMinNumSamples)));
scheduler()->OnReceivedLongPollIntervalUpdate(poll_interval);
SyncShareTimes times;
TimeDelta poll_interval(TimeDelta::FromMilliseconds(30));
EXPECT_CALL(*syncer(), PollSyncShare(_,_)).Times(AtLeast(kMinNumSamples))
- .WillRepeatedly(DoAll(Invoke(sessions::test_util::SimulatePollSuccess),
- RecordSyncShareMultiple(×, kMinNumSamples)));
+ .WillRepeatedly(
+ DoAll(Invoke(sessions::test_util::SimulatePollRetrySuccess),
+ RecordSyncShareMultiple(×, kMinNumSamples)));
scheduler()->OnReceivedShortPollIntervalUpdate(poll_interval);
scheduler()->SetNotificationsEnabled(false);
sessions::test_util::SimulatePollIntervalUpdate(poll2)),
Return(true)))
.WillRepeatedly(
- DoAll(Invoke(sessions::test_util::SimulatePollSuccess),
+ DoAll(Invoke(sessions::test_util::SimulatePollRetrySuccess),
WithArg<1>(
RecordSyncShareMultiple(×, kMinNumSamples))));
StartSyncScheduler(SyncScheduler::CONFIGURATION_MODE);
- CallbackCounter counter;
+ CallbackCounter ready_counter;
+ CallbackCounter retry_counter;
ConfigurationParams params(
GetUpdatesCallerInfo::RECONFIGURATION,
types,
TypesToRoutingInfo(types),
- base::Bind(&CallbackCounter::Callback, base::Unretained(&counter)));
- ASSERT_FALSE(scheduler()->ScheduleConfiguration(params));
- ASSERT_EQ(0, counter.times_called());
+ base::Bind(&CallbackCounter::Callback, base::Unretained(&ready_counter)),
+ base::Bind(&CallbackCounter::Callback, base::Unretained(&retry_counter)));
+ scheduler()->ScheduleConfiguration(params);
+ PumpLoop();
+ ASSERT_EQ(0, ready_counter.times_called());
+ ASSERT_EQ(1, retry_counter.times_called());
+
}
TEST_F(SyncSchedulerTest, ThrottlingExpiresFromPoll) {
Return(true)))
.RetiresOnSaturation();
EXPECT_CALL(*syncer(), PollSyncShare(_,_))
- .WillRepeatedly(DoAll(Invoke(sessions::test_util::SimulatePollSuccess),
- RecordSyncShareMultiple(×, kMinNumSamples)));
+ .WillRepeatedly(
+ DoAll(Invoke(sessions::test_util::SimulatePollRetrySuccess),
+ RecordSyncShareMultiple(×, kMinNumSamples)));
TimeTicks optimal_start = TimeTicks::Now() + poll + throttle1;
StartSyncScheduler(SyncScheduler::NORMAL_MODE);
StartSyncScheduler(SyncScheduler::NORMAL_MODE);
scheduler()->ScheduleLocalNudge(zero(), types, FROM_HERE);
- PumpLoop();
+ PumpLoop(); // To get PerformDelayedNudge called.
+ PumpLoop(); // To get TrySyncSessionJob called
EXPECT_TRUE(scheduler()->IsCurrentlyThrottled());
RunLoop();
EXPECT_FALSE(scheduler()->IsCurrentlyThrottled());
const ModelTypeSet types(BOOKMARKS);
StartSyncScheduler(SyncScheduler::CONFIGURATION_MODE);
- CallbackCounter counter;
+ CallbackCounter ready_counter;
+ CallbackCounter retry_counter;
ConfigurationParams params(
GetUpdatesCallerInfo::RECONFIGURATION,
types,
TypesToRoutingInfo(types),
- base::Bind(&CallbackCounter::Callback, base::Unretained(&counter)));
- EXPECT_FALSE(scheduler()->ScheduleConfiguration(params));
- EXPECT_EQ(0, counter.times_called());
+ base::Bind(&CallbackCounter::Callback, base::Unretained(&ready_counter)),
+ base::Bind(&CallbackCounter::Callback, base::Unretained(&retry_counter)));
+ scheduler()->ScheduleConfiguration(params);
+ PumpLoop();
+ EXPECT_EQ(0, ready_counter.times_called());
+ EXPECT_EQ(1, retry_counter.times_called());
EXPECT_TRUE(scheduler()->IsCurrentlyThrottled());
RunLoop();
StartSyncScheduler(SyncScheduler::NORMAL_MODE);
scheduler()->ScheduleLocalNudge(zero(), types, FROM_HERE);
- PumpLoop();
+ PumpLoop(); // To get PerformDelayedNudge called.
+ PumpLoop(); // To get TrySyncSessionJob called
EXPECT_TRUE(GetThrottledTypes().HasAll(types));
// This won't cause a sync cycle because the types are throttled.
StartSyncScheduler(SyncScheduler::NORMAL_MODE);
scheduler()->ScheduleLocalNudge(zero(), throttled_types, FROM_HERE);
- PumpLoop();
+ PumpLoop(); // To get PerformDelayedNudge called.
+ PumpLoop(); // To get TrySyncSessionJob called
EXPECT_TRUE(GetThrottledTypes().HasAll(throttled_types));
// Ignore invalidations for throttled types.
.WillOnce(DoAll(Invoke(sessions::test_util::SimulateConfigureSuccess),
RecordSyncShare(×)))
.RetiresOnSaturation();
- CallbackCounter counter;
+ CallbackCounter ready_counter;
+ CallbackCounter retry_counter;
ConfigurationParams params(
GetUpdatesCallerInfo::RECONFIGURATION,
config_types,
TypesToRoutingInfo(config_types),
- base::Bind(&CallbackCounter::Callback, base::Unretained(&counter)));
- ASSERT_TRUE(scheduler()->ScheduleConfiguration(params));
- ASSERT_EQ(1, counter.times_called());
+ base::Bind(&CallbackCounter::Callback, base::Unretained(&ready_counter)),
+ base::Bind(&CallbackCounter::Callback, base::Unretained(&retry_counter)));
+ scheduler()->ScheduleConfiguration(params);
+ RunLoop();
+ ASSERT_EQ(1, ready_counter.times_called());
+ ASSERT_EQ(0, retry_counter.times_called());
+
Mock::VerifyAndClearExpectations(syncer());
// Switch to NORMAL_MODE to ensure NUDGES were properly saved and run.
// TODO(tim): Figure out how to remove this dangerous need to reset
// routing info between mode switches.
- context()->set_routing_info(routing_info());
+ context()->SetRoutingInfo(routing_info());
StartSyncScheduler(SyncScheduler::NORMAL_MODE);
- PumpLoop();
+ RunLoop();
+ Mock::VerifyAndClearExpectations(syncer());
}
class BackoffTriggersSyncSchedulerTest : public SyncSchedulerTest {
StartSyncScheduler(SyncScheduler::CONFIGURATION_MODE);
ModelTypeSet types(BOOKMARKS);
- CallbackCounter counter;
+ CallbackCounter ready_counter;
+ CallbackCounter retry_counter;
ConfigurationParams params(
GetUpdatesCallerInfo::RECONFIGURATION,
types,
TypesToRoutingInfo(types),
- base::Bind(&CallbackCounter::Callback, base::Unretained(&counter)));
+ base::Bind(&CallbackCounter::Callback, base::Unretained(&ready_counter)),
+ base::Bind(&CallbackCounter::Callback, base::Unretained(&retry_counter)));
scheduler()->ScheduleConfiguration(params);
RunLoop();
StartSyncScheduler(SyncScheduler::CONFIGURATION_MODE);
- CallbackCounter counter;
+ CallbackCounter ready_counter;
+ CallbackCounter retry_counter;
ConfigurationParams params(
GetUpdatesCallerInfo::RECONFIGURATION,
types,
TypesToRoutingInfo(types),
- base::Bind(&CallbackCounter::Callback, base::Unretained(&counter)));
- ASSERT_FALSE(scheduler()->ScheduleConfiguration(params));
- ASSERT_EQ(0, counter.times_called());
+ base::Bind(&CallbackCounter::Callback, base::Unretained(&ready_counter)),
+ base::Bind(&CallbackCounter::Callback, base::Unretained(&retry_counter)));
+ scheduler()->ScheduleConfiguration(params);
+ PumpLoop();
+ ASSERT_EQ(0, ready_counter.times_called());
+ ASSERT_EQ(1, retry_counter.times_called());
+
}
// Test that backoff is shaping traffic properly with consecutive errors.
// Now let the Poll timer do its thing.
EXPECT_CALL(*syncer(), PollSyncShare(_,_))
.WillRepeatedly(DoAll(
- Invoke(sessions::test_util::SimulatePollSuccess),
+ Invoke(sessions::test_util::SimulatePollRetrySuccess),
RecordSyncShareMultiple(×, kMinNumSamples)));
RunLoop();
Mock::VerifyAndClearExpectations(syncer());
UseMockDelayProvider(); // Will cause test failure if backoff is initiated.
EXPECT_CALL(*syncer(), PollSyncShare(_,_))
- .WillOnce(DoAll(Invoke(sessions::test_util::SimulatePollFailed),
+ .WillOnce(DoAll(Invoke(sessions::test_util::SimulatePollRetryFailed),
RecordSyncShare(×)))
- .WillOnce(DoAll(Invoke(sessions::test_util::SimulatePollSuccess),
+ .WillOnce(DoAll(Invoke(sessions::test_util::SimulatePollRetrySuccess),
RecordSyncShare(×)));
StartSyncScheduler(SyncScheduler::NORMAL_MODE);
Return(true)));
scheduler()->ScheduleLocalNudge(zero(), ModelTypeSet(BOOKMARKS), FROM_HERE);
-
- PumpLoop(); // Run the nudge, that will fail and schedule a quick retry.
+ PumpLoop(); // To get PerformDelayedNudge called.
+ PumpLoop(); // Run the nudge, that will fail and schedule a quick retry.
ASSERT_TRUE(scheduler()->IsBackingOff());
// Before we run the scheduled canary, trigger a server connection change.
scheduler()->ScheduleLocalNudge(zero(), ModelTypeSet(BOOKMARKS), FROM_HERE);
- PumpLoop(); // Run the nudge, that will fail and schedule a quick retry.
+ PumpLoop(); // To get PerformDelayedNudge called.
+ PumpLoop(); // Run the nudge, that will fail and schedule a quick retry.
ASSERT_TRUE(scheduler()->IsBackingOff());
// Before we run the scheduled canary, trigger a server connection change.
scheduler()->OnConnectionStatusChange();
+ PumpLoop();
connection()->SetServerReachable();
connection()->UpdateConnectionStatus();
scheduler()->ScheduleLocalNudge(zero(), ModelTypeSet(BOOKMARKS), FROM_HERE);
connection()->UpdateConnectionStatus();
ModelTypeSet model_types(BOOKMARKS);
- CallbackCounter counter;
+ CallbackCounter ready_counter;
+ CallbackCounter retry_counter;
ConfigurationParams params(
GetUpdatesCallerInfo::RECONFIGURATION,
model_types,
TypesToRoutingInfo(model_types),
- base::Bind(&CallbackCounter::Callback, base::Unretained(&counter)));
+ base::Bind(&CallbackCounter::Callback, base::Unretained(&ready_counter)),
+ base::Bind(&CallbackCounter::Callback, base::Unretained(&retry_counter)));
scheduler()->ScheduleConfiguration(params);
scheduler()->OnConnectionStatusChange();
::testing::InSequence seq;
EXPECT_CALL(*syncer(), PollSyncShare(_,_))
- .WillRepeatedly(DoAll(Invoke(sessions::test_util::SimulatePollSuccess),
- RecordSyncShareMultiple(×, kMinNumSamples)));
+ .WillRepeatedly(
+ DoAll(Invoke(sessions::test_util::SimulatePollRetrySuccess),
+ RecordSyncShareMultiple(×, kMinNumSamples)));
connection()->SetServerStatus(HttpResponse::SYNC_AUTH_ERROR);
StartSyncScheduler(SyncScheduler::NORMAL_MODE);
// but after poll finished with auth error from poll timer it should retry
// poll once more
EXPECT_CALL(*syncer(), PollSyncShare(_,_))
- .WillOnce(DoAll(Invoke(sessions::test_util::SimulatePollSuccess),
+ .WillOnce(DoAll(Invoke(sessions::test_util::SimulatePollRetrySuccess),
RecordSyncShare(×)));
scheduler()->OnCredentialsUpdated();
connection()->SetServerStatus(HttpResponse::SERVER_CONNECTION_OK);
+ RunLoop();
+ StopSyncScheduler();
+}
+
+TEST_F(SyncSchedulerTest, SuccessfulRetry) {
+ StartSyncScheduler(SyncScheduler::NORMAL_MODE);
+
+ SyncShareTimes times;
+ base::TimeDelta delay = base::TimeDelta::FromMilliseconds(1);
+ scheduler()->OnReceivedGuRetryDelay(delay);
+ EXPECT_EQ(delay, GetRetryTimerDelay());
+
+ EXPECT_CALL(*syncer(), RetrySyncShare(_,_))
+ .WillOnce(
+ DoAll(Invoke(sessions::test_util::SimulatePollRetrySuccess),
+ RecordSyncShare(×)));
+
+ // Run to wait for retrying.
+ RunLoop();
+
+ StopSyncScheduler();
+}
+
+TEST_F(SyncSchedulerTest, FailedRetry) {
+ UseMockDelayProvider();
+ EXPECT_CALL(*delay(), GetDelay(_))
+ .WillRepeatedly(Return(TimeDelta::FromMilliseconds(1)));
+
+ StartSyncScheduler(SyncScheduler::NORMAL_MODE);
+
+ base::TimeDelta delay = base::TimeDelta::FromMilliseconds(1);
+ scheduler()->OnReceivedGuRetryDelay(delay);
+
+ EXPECT_CALL(*syncer(), RetrySyncShare(_,_))
+ .WillOnce(
+ DoAll(Invoke(sessions::test_util::SimulatePollRetryFailed),
+ QuitLoopNowAction()));
+
+ // Run to wait for retrying.
+ RunLoop();
+
+ EXPECT_TRUE(scheduler()->IsBackingOff());
+ EXPECT_CALL(*syncer(), RetrySyncShare(_,_))
+ .WillOnce(
+ DoAll(Invoke(sessions::test_util::SimulatePollRetrySuccess),
+ QuitLoopNowAction()));
+
+ // Run to wait for second retrying.
+ RunLoop();
+
+ StopSyncScheduler();
+}
+
+ACTION_P2(VerifyRetryTimerDelay, scheduler_test, expected_delay) {
+ EXPECT_EQ(expected_delay, scheduler_test->GetRetryTimerDelay());
+}
+
+TEST_F(SyncSchedulerTest, ReceiveNewRetryDelay) {
+ StartSyncScheduler(SyncScheduler::NORMAL_MODE);
+
+ SyncShareTimes times;
+ base::TimeDelta delay1 = base::TimeDelta::FromMilliseconds(100);
+ base::TimeDelta delay2 = base::TimeDelta::FromMilliseconds(200);
+
+ scheduler()->ScheduleLocalRefreshRequest(zero(), ModelTypeSet(BOOKMARKS),
+ FROM_HERE);
+ scheduler()->OnReceivedGuRetryDelay(delay1);
+ EXPECT_EQ(delay1, GetRetryTimerDelay());
+
+ EXPECT_CALL(*syncer(), NormalSyncShare(_,_,_))
+ .WillOnce(DoAll(
+ WithoutArgs(VerifyRetryTimerDelay(this, delay1)),
+ WithArg<2>(sessions::test_util::SimulateGuRetryDelayCommand(delay2)),
+ RecordSyncShare(×)));
+
+ // Run nudge GU.
+ RunLoop();
+ EXPECT_EQ(delay2, GetRetryTimerDelay());
+
+ EXPECT_CALL(*syncer(), RetrySyncShare(_,_))
+ .WillOnce(DoAll(Invoke(sessions::test_util::SimulatePollRetrySuccess),
+ RecordSyncShare(×)));
+
+ // Run to wait for retrying.
+ RunLoop();
+
StopSyncScheduler();
}