| // 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 |