blob: 341c18f3119407268117cea643897bea52602da9 [file] [log] [blame]
// Copyright 2012 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "components/sync/engine/backoff_delay_provider.h"
#include <memory>
#include "components/sync/engine/cycle/model_neutral_state.h"
#include "components/sync/engine/polling_constants.h"
#include "components/sync/engine/sync_protocol_error.h"
#include "components/sync/engine/syncer_error.h"
#include "net/base/net_errors.h"
#include "net/http/http_status_code.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
namespace syncer {
namespace {
using testing::Gt;
using testing::Lt;
TEST(BackoffDelayProviderTest, GetRecommendedDelay) {
std::unique_ptr<BackoffDelayProvider> delay(
BackoffDelayProvider::FromDefaults());
EXPECT_EQ(base::Seconds(1), delay->GetDelay(base::Seconds(0)));
EXPECT_LE(base::Seconds(1), delay->GetDelay(base::Seconds(1)));
EXPECT_LE(base::Seconds(50), delay->GetDelay(base::Seconds(50)));
EXPECT_LE(base::Seconds(10), delay->GetDelay(base::Seconds(10)));
EXPECT_EQ(kMaxBackoffTime, delay->GetDelay(kMaxBackoffTime));
EXPECT_EQ(kMaxBackoffTime,
delay->GetDelay(kMaxBackoffTime + base::Seconds(1)));
}
TEST(BackoffDelayProviderTest, GetInitialDelay) {
std::unique_ptr<BackoffDelayProvider> delay(
BackoffDelayProvider::FromDefaults());
ModelNeutralState state;
state.last_get_key_failed = true;
EXPECT_EQ(kInitialBackoffRetryTime, delay->GetInitialDelay(state));
state.last_get_key_failed = false;
state.last_download_updates_result =
SyncerError::ProtocolError(MIGRATION_DONE);
EXPECT_EQ(kInitialBackoffImmediateRetryTime, delay->GetInitialDelay(state));
state.last_download_updates_result =
SyncerError::NetworkError(net::ERR_FAILED);
EXPECT_EQ(kInitialBackoffShortRetryTime, delay->GetInitialDelay(state));
state.last_download_updates_result =
SyncerError::ProtocolError(TRANSIENT_ERROR);
EXPECT_EQ(kInitialBackoffRetryTime, delay->GetInitialDelay(state));
state.last_download_updates_result = SyncerError::ProtocolViolationError();
EXPECT_EQ(kInitialBackoffRetryTime, delay->GetInitialDelay(state));
state.last_download_updates_result = SyncerError::Success();
state.commit_result = SyncerError::ProtocolError(MIGRATION_DONE);
EXPECT_EQ(kInitialBackoffImmediateRetryTime, delay->GetInitialDelay(state));
state.commit_result = SyncerError::NetworkError(net::ERR_FAILED);
EXPECT_EQ(kInitialBackoffShortRetryTime, delay->GetInitialDelay(state));
state.commit_result = SyncerError::ProtocolError(CONFLICT);
EXPECT_EQ(kInitialBackoffImmediateRetryTime, delay->GetInitialDelay(state));
}
TEST(BackoffDelayProviderTest, GetInitialDelayWithOverride) {
std::unique_ptr<BackoffDelayProvider> delay(
BackoffDelayProvider::WithShortInitialRetryOverride());
ModelNeutralState state;
state.last_get_key_failed = true;
EXPECT_EQ(kInitialBackoffShortRetryTime, delay->GetInitialDelay(state));
state.last_get_key_failed = false;
state.last_download_updates_result =
SyncerError::ProtocolError(MIGRATION_DONE);
EXPECT_EQ(kInitialBackoffImmediateRetryTime, delay->GetInitialDelay(state));
state.last_download_updates_result =
SyncerError::ProtocolError(TRANSIENT_ERROR);
EXPECT_EQ(kInitialBackoffShortRetryTime, delay->GetInitialDelay(state));
state.last_download_updates_result = SyncerError::ProtocolViolationError();
EXPECT_EQ(kInitialBackoffShortRetryTime, delay->GetInitialDelay(state));
state.last_download_updates_result = SyncerError::Success();
state.commit_result = SyncerError::ProtocolError(MIGRATION_DONE);
EXPECT_EQ(kInitialBackoffImmediateRetryTime, delay->GetInitialDelay(state));
state.commit_result = SyncerError::ProtocolError(CONFLICT);
EXPECT_EQ(kInitialBackoffImmediateRetryTime, delay->GetInitialDelay(state));
}
// This rules out accidents with the constants.
TEST(BackoffDelayProviderTest, GetExponentiallyIncreasingDelay) {
std::unique_ptr<BackoffDelayProvider> delay_provider(
BackoffDelayProvider::FromDefaults());
ASSERT_THAT(kBackoffMultiplyFactor, Gt(1.0));
// Even when the jitter is negative, the delay should grow (overall
// multiplicative factor bigger than 1).
ASSERT_THAT(kBackoffJitterFactor, Lt(kBackoffMultiplyFactor - 1.0));
const base::TimeDelta delay0 = base::Seconds(1);
const base::TimeDelta delay1_min =
delay_provider->GetDelayForTesting(delay0, /*jitter_sign=*/-1);
const base::TimeDelta delay2_min =
delay_provider->GetDelayForTesting(delay1_min, /*jitter_sign=*/-1);
const base::TimeDelta delay1_max =
delay_provider->GetDelayForTesting(delay0, /*jitter_sign=*/1);
const base::TimeDelta delay2_max =
delay_provider->GetDelayForTesting(delay1_max, /*jitter_sign=*/1);
ASSERT_THAT(delay1_min, Lt(delay1_max));
ASSERT_THAT(delay2_min, Lt(delay2_max));
// The minimum value should increase faster than linearly.
EXPECT_THAT(delay1_min, Gt(delay0));
EXPECT_THAT(delay2_min, Gt(delay1_min));
EXPECT_THAT(delay2_min - delay1_min, Gt(delay1_min - delay0));
// The maximum value should increase faster than linearly.
EXPECT_THAT(delay1_max, Gt(delay0));
EXPECT_THAT(delay2_max, Gt(delay1_max));
EXPECT_THAT(delay2_max - delay1_max, Gt(delay1_max - delay0));
}
} // namespace
} // namespace syncer