diff options
author | johnme <johnme@chromium.org> | 2015-04-20 10:06:20 -0700 |
---|---|---|
committer | Commit bot <commit-bot@chromium.org> | 2015-04-20 17:06:21 +0000 |
commit | dce40c39e0d44436283fbc43fa9b708153dd04e6 (patch) | |
tree | c680a23267bba048f057cddf9d04a2cb2e099e61 | |
parent | 32be343ac9b22aa66d645aed4c701f127072aaab (diff) | |
download | chromium_src-dce40c39e0d44436283fbc43fa9b708153dd04e6.zip chromium_src-dce40c39e0d44436283fbc43fa9b708153dd04e6.tar.gz chromium_src-dce40c39e0d44436283fbc43fa9b708153dd04e6.tar.bz2 |
Refactor net::BackoffEntry to not require subclassing
Before this patch, net::BackoffEntry had a virtual ImplGetTimeNow method
that tests etc would override to change what time is considered "now".
As suggested by rsleevi in https://codereview.chromium.org/1023473003,
this patch removes that method, and instead makes net::BackoffEntry
accept a base::TickClock in the constructor, to allow overriding the
time without subclassing.
(this will allow future changes to net::BackoffEntry without the
fragile base class problem)
Accordingly, I've removed all subclasses of BackoffEntry, and made them
pass TickClocks instead; in most cases this has been a nice
simplification.
BUG=465399
TBR=stevenjb@chromium.org
Review URL: https://codereview.chromium.org/1076853003
Cr-Commit-Position: refs/heads/master@{#325865}
23 files changed, 219 insertions, 347 deletions
diff --git a/chrome/browser/captive_portal/captive_portal_service.cc b/chrome/browser/captive_portal/captive_portal_service.cc index 6098d80..aa19478 100644 --- a/chrome/browser/captive_portal/captive_portal_service.cc +++ b/chrome/browser/captive_portal/captive_portal_service.cc @@ -10,6 +10,7 @@ #include "base/message_loop/message_loop.h" #include "base/metrics/histogram.h" #include "base/prefs/pref_service.h" +#include "base/time/tick_clock.h" #include "chrome/browser/chrome_notification_types.h" #include "chrome/browser/profiles/profile.h" #include "chrome/common/pref_names.h" @@ -138,24 +139,6 @@ bool ShouldDeferToNativeCaptivePortalDetection() { CaptivePortalService::TestingState CaptivePortalService::testing_state_ = NOT_TESTING; -class CaptivePortalService::RecheckBackoffEntry : public net::BackoffEntry { - public: - explicit RecheckBackoffEntry(CaptivePortalService* captive_portal_service) - : net::BackoffEntry( - &captive_portal_service->recheck_policy().backoff_policy), - captive_portal_service_(captive_portal_service) { - } - - private: - base::TimeTicks ImplGetTimeNow() const override { - return captive_portal_service_->GetCurrentTimeTicks(); - } - - CaptivePortalService* captive_portal_service_; - - DISALLOW_COPY_AND_ASSIGN(RecheckBackoffEntry); -}; - CaptivePortalService::RecheckPolicy::RecheckPolicy() : initial_backoff_no_portal_ms(600 * 1000), initial_backoff_portal_ms(20 * 1000) { @@ -184,13 +167,19 @@ CaptivePortalService::RecheckPolicy::RecheckPolicy() } CaptivePortalService::CaptivePortalService(Profile* profile) + : CaptivePortalService(profile, nullptr) { +} + +CaptivePortalService::CaptivePortalService(Profile* profile, + base::TickClock* clock_for_testing) : profile_(profile), state_(STATE_IDLE), captive_portal_detector_(profile->GetRequestContext()), enabled_(false), last_detection_result_(captive_portal::RESULT_INTERNET_CONNECTED), num_checks_with_same_result_(0), - test_url_(captive_portal::CaptivePortalDetector::kDefaultURL) { + test_url_(captive_portal::CaptivePortalDetector::kDefaultURL), + tick_clock_for_testing_(clock_for_testing) { // The order matters here: // |resolve_errors_with_web_service_| must be initialized and |backoff_entry_| // created before the call to UpdateEnabledState. @@ -348,7 +337,8 @@ void CaptivePortalService::ResetBackoffEntry(CaptivePortalResult result) { recheck_policy_.initial_backoff_no_portal_ms; } - backoff_entry_.reset(new RecheckBackoffEntry(this)); + backoff_entry_.reset(new net::BackoffEntry(&recheck_policy().backoff_policy, + tick_clock_for_testing_)); } void CaptivePortalService::UpdateEnabledState() { @@ -387,10 +377,10 @@ void CaptivePortalService::UpdateEnabledState() { } base::TimeTicks CaptivePortalService::GetCurrentTimeTicks() const { - if (time_ticks_for_testing_.is_null()) - return base::TimeTicks::Now(); + if (tick_clock_for_testing_) + return tick_clock_for_testing_->NowTicks(); else - return time_ticks_for_testing_; + return base::TimeTicks::Now(); } bool CaptivePortalService::DetectionInProgress() const { diff --git a/chrome/browser/captive_portal/captive_portal_service.h b/chrome/browser/captive_portal/captive_portal_service.h index c48ca5d..dbe07de 100644 --- a/chrome/browser/captive_portal/captive_portal_service.h +++ b/chrome/browser/captive_portal/captive_portal_service.h @@ -9,6 +9,7 @@ #include "base/memory/scoped_ptr.h" #include "base/prefs/pref_member.h" #include "base/threading/non_thread_safe.h" +#include "base/time/tick_clock.h" #include "base/time/time.h" #include "base/timer/timer.h" #include "components/captive_portal/captive_portal_detector.h" @@ -48,6 +49,7 @@ class CaptivePortalService : public KeyedService, public base::NonThreadSafe { }; explicit CaptivePortalService(Profile* profile); + CaptivePortalService(Profile* profile, base::TickClock* clock_for_testing); ~CaptivePortalService() override; // Triggers a check for a captive portal. If there's already a check in @@ -79,10 +81,6 @@ class CaptivePortalService : public KeyedService, public base::NonThreadSafe { friend class CaptivePortalServiceTest; friend class CaptivePortalBrowserTest; - // Subclass of BackoffEntry that uses the CaptivePortalService's - // GetCurrentTime function, for unit testing. - class RecheckBackoffEntry; - enum State { // No check is running or pending. STATE_IDLE, @@ -138,7 +136,6 @@ class CaptivePortalService : public KeyedService, public base::NonThreadSafe { // Android, since it lacks the Browser class. void UpdateEnabledState(); - // Returns the current TimeTicks. base::TimeTicks GetCurrentTimeTicks() const; bool DetectionInProgress() const; @@ -152,16 +149,6 @@ class CaptivePortalService : public KeyedService, public base::NonThreadSafe { void set_test_url(const GURL& test_url) { test_url_ = test_url; } - // Sets current test time ticks. Used by unit tests. - void set_time_ticks_for_testing(const base::TimeTicks& time_ticks) { - time_ticks_for_testing_ = time_ticks; - } - - // Advances current test time ticks. Used by unit tests. - void advance_time_ticks_for_testing(const base::TimeDelta& delta) { - time_ticks_for_testing_ += delta; - } - // The profile that owns this CaptivePortalService. Profile* profile_; @@ -207,8 +194,8 @@ class CaptivePortalService : public KeyedService, public base::NonThreadSafe { static TestingState testing_state_; - // Test time ticks used by unit tests. - base::TimeTicks time_ticks_for_testing_; + // Test tick clock used by unit tests. + base::TickClock* tick_clock_for_testing_; // Not owned. DISALLOW_COPY_AND_ASSIGN(CaptivePortalService); }; diff --git a/chrome/browser/captive_portal/captive_portal_service_unittest.cc b/chrome/browser/captive_portal/captive_portal_service_unittest.cc index c835721..0d33548 100644 --- a/chrome/browser/captive_portal/captive_portal_service_unittest.cc +++ b/chrome/browser/captive_portal/captive_portal_service_unittest.cc @@ -9,6 +9,7 @@ #include "base/command_line.h" #include "base/prefs/pref_service.h" #include "base/run_loop.h" +#include "base/test/simple_test_tick_clock.h" #include "base/test/test_timeouts.h" #include "chrome/browser/chrome_notification_types.h" #include "chrome/common/chrome_switches.h" @@ -101,8 +102,9 @@ class CaptivePortalServiceTest : public testing::Test, CaptivePortalService::set_state_for_testing(testing_state); profile_.reset(new TestingProfile()); - service_.reset(new CaptivePortalService(profile_.get())); - service_->set_time_ticks_for_testing(base::TimeTicks::Now()); + tick_clock_.reset(new base::SimpleTestTickClock()); + tick_clock_->Advance(base::TimeTicks::Now() - tick_clock_->NowTicks()); + service_.reset(new CaptivePortalService(profile_.get(), tick_clock_.get())); // Use no delays for most tests. set_initial_backoff_no_portal(base::TimeDelta()); @@ -226,7 +228,7 @@ class CaptivePortalServiceTest : public testing::Test, // Changes test time for the service and service's captive portal // detector. void AdvanceTime(const base::TimeDelta& delta) { - service()->advance_time_ticks_for_testing(delta); + tick_clock_->Advance(delta); CaptivePortalDetectorTestBase::AdvanceTime(delta); } @@ -281,6 +283,7 @@ class CaptivePortalServiceTest : public testing::Test, // Note that the construction order of these matters. scoped_ptr<TestingProfile> profile_; + scoped_ptr<base::SimpleTestTickClock> tick_clock_; scoped_ptr<CaptivePortalService> service_; }; diff --git a/chrome/browser/chromeos/net/network_portal_detector_impl.cc b/chrome/browser/chromeos/net/network_portal_detector_impl.cc index e9f071d..e586981 100644 --- a/chrome/browser/chromeos/net/network_portal_detector_impl.cc +++ b/chrome/browser/chromeos/net/network_portal_detector_impl.cc @@ -398,7 +398,7 @@ base::TimeTicks NetworkPortalDetectorImpl::AttemptStartTime() { return attempt_start_time_; } -base::TimeTicks NetworkPortalDetectorImpl::GetCurrentTimeTicks() { +base::TimeTicks NetworkPortalDetectorImpl::NowTicks() { if (time_ticks_for_testing_.is_null()) return base::TimeTicks::Now(); return time_ticks_for_testing_; @@ -412,7 +412,7 @@ void NetworkPortalDetectorImpl::StartDetection() { DCHECK(is_idle()); ResetStrategyAndCounters(); - detection_start_time_ = GetCurrentTimeTicks(); + detection_start_time_ = NowTicks(); ScheduleAttempt(base::TimeDelta()); } @@ -450,7 +450,7 @@ void NetworkPortalDetectorImpl::StartAttempt() { DCHECK(is_portal_check_pending()); state_ = STATE_CHECKING_FOR_PORTAL; - attempt_start_time_ = GetCurrentTimeTicks(); + attempt_start_time_ = NowTicks(); captive_portal_detector_->DetectCaptivePortal( test_url_, @@ -511,7 +511,7 @@ void NetworkPortalDetectorImpl::OnAttemptCompleted( CaptivePortalState state; state.response_code = response_code; - state.time = GetCurrentTimeTicks(); + state.time = NowTicks(); switch (result) { case captive_portal::RESULT_NO_RESPONSE: if (state.response_code == net::HTTP_PROXY_AUTHENTICATION_REQUIRED) { @@ -623,7 +623,7 @@ void NetworkPortalDetectorImpl::RecordDetectionStats( return; if (!detection_start_time_.is_null()) - RecordDetectionDuration(GetCurrentTimeTicks() - detection_start_time_); + RecordDetectionDuration(NowTicks() - detection_start_time_); RecordDetectionResult(status); switch (status) { diff --git a/chrome/browser/chromeos/net/network_portal_detector_impl.h b/chrome/browser/chromeos/net/network_portal_detector_impl.h index da66a4f..e626041 100644 --- a/chrome/browser/chromeos/net/network_portal_detector_impl.h +++ b/chrome/browser/chromeos/net/network_portal_detector_impl.h @@ -86,7 +86,7 @@ class NetworkPortalDetectorImpl // PortalDetectorStrategy::Delegate implementation: int NoResponseResultCount() override; base::TimeTicks AttemptStartTime() override; - base::TimeTicks GetCurrentTimeTicks() override; + base::TimeTicks NowTicks() override; private: friend class ::NetworkingConfigTest; diff --git a/chromeos/network/portal_detector/network_portal_detector_strategy.cc b/chromeos/network/portal_detector/network_portal_detector_strategy.cc index 1692f81..50b32c2 100644 --- a/chromeos/network/portal_detector/network_portal_detector_strategy.cc +++ b/chromeos/network/portal_detector/network_portal_detector_strategy.cc @@ -92,25 +92,9 @@ class SessionStrategy : public PortalDetectorStrategy { } // namespace -// PortalDetectorStrategy::BackoffEntryImpl ------------------------------------ +// PortalDetectorStrategy::Delegate -------------------------------------------- -class PortalDetectorStrategy::BackoffEntryImpl : public net::BackoffEntry { - public: - BackoffEntryImpl(const net::BackoffEntry::Policy* const policy, - PortalDetectorStrategy::Delegate* delegate) - : net::BackoffEntry(policy), delegate_(delegate) {} - ~BackoffEntryImpl() override {} - - // net::BackoffEntry overrides: - base::TimeTicks ImplGetTimeNow() const override { - return delegate_->GetCurrentTimeTicks(); - } - - private: - PortalDetectorStrategy::Delegate* delegate_; - - DISALLOW_COPY_AND_ASSIGN(BackoffEntryImpl); -}; +PortalDetectorStrategy::Delegate::~Delegate() {} // PortalDetectorStrategy ----------------------------------------------------- @@ -142,7 +126,7 @@ PortalDetectorStrategy::PortalDetectorStrategy(Delegate* delegate) policy_.maximum_backoff_ms = 2 * 60 * 1000; policy_.entry_lifetime_ms = -1; policy_.always_use_initial_delay = true; - backoff_entry_.reset(new BackoffEntryImpl(&policy_, delegate_)); + backoff_entry_.reset(new net::BackoffEntry(&policy_, delegate_)); } PortalDetectorStrategy::~PortalDetectorStrategy() { @@ -187,7 +171,7 @@ void PortalDetectorStrategy::Reset() { void PortalDetectorStrategy::SetPolicyAndReset( const net::BackoffEntry::Policy& policy) { policy_ = policy; - backoff_entry_.reset(new BackoffEntryImpl(&policy_, delegate_)); + backoff_entry_.reset(new net::BackoffEntry(&policy_, delegate_)); } void PortalDetectorStrategy::OnDetectionCompleted() { diff --git a/chromeos/network/portal_detector/network_portal_detector_strategy.h b/chromeos/network/portal_detector/network_portal_detector_strategy.h index ff6e890..3b8b5d3 100644 --- a/chromeos/network/portal_detector/network_portal_detector_strategy.h +++ b/chromeos/network/portal_detector/network_portal_detector_strategy.h @@ -9,6 +9,7 @@ #include "base/compiler_specific.h" #include "base/macros.h" #include "base/memory/scoped_ptr.h" +#include "base/time/tick_clock.h" #include "base/time/time.h" #include "chromeos/chromeos_export.h" #include "net/base/backoff_entry.h" @@ -23,9 +24,9 @@ class CHROMEOS_EXPORT PortalDetectorStrategy { STRATEGY_ID_SESSION }; - class Delegate { + class Delegate : public base::TickClock { public: - virtual ~Delegate() {} + ~Delegate() override; // Returns number of attempts in a row with NO RESPONSE result. // If last detection attempt has different result, returns 0. @@ -33,13 +34,11 @@ class CHROMEOS_EXPORT PortalDetectorStrategy { // Returns time when current attempt was started. virtual base::TimeTicks AttemptStartTime() = 0; - - // Returns current TimeTicks. - virtual base::TimeTicks GetCurrentTimeTicks() = 0; }; virtual ~PortalDetectorStrategy(); + // Lifetime of delegate must enclose lifetime of PortalDetectorStrategy. static scoped_ptr<PortalDetectorStrategy> CreateById(StrategyId id, Delegate* delegate); @@ -65,8 +64,7 @@ class CHROMEOS_EXPORT PortalDetectorStrategy { void OnDetectionCompleted(); protected: - class BackoffEntryImpl; - + // Lifetime of delegate must enclose lifetime of PortalDetectorStrategy. explicit PortalDetectorStrategy(Delegate* delegate); // Interface for subclasses: @@ -74,7 +72,7 @@ class CHROMEOS_EXPORT PortalDetectorStrategy { Delegate* delegate_; net::BackoffEntry::Policy policy_; - scoped_ptr<BackoffEntryImpl> backoff_entry_; + scoped_ptr<net::BackoffEntry> backoff_entry_; private: friend class NetworkPortalDetectorImplTest; diff --git a/components/data_reduction_proxy/core/browser/data_reduction_proxy_config_service_client.cc b/components/data_reduction_proxy/core/browser/data_reduction_proxy_config_service_client.cc index f8e3d9e..af4c571 100644 --- a/components/data_reduction_proxy/core/browser/data_reduction_proxy_config_service_client.cc +++ b/components/data_reduction_proxy/core/browser/data_reduction_proxy_config_service_client.cc @@ -156,7 +156,7 @@ void DataReductionProxyConfigServiceClient::SetConfigRefreshTimer( &DataReductionProxyConfigServiceClient::RetrieveConfig); } -base::Time DataReductionProxyConfigServiceClient::Now() const { +base::Time DataReductionProxyConfigServiceClient::Now() { return base::Time::Now(); } diff --git a/components/data_reduction_proxy/core/browser/data_reduction_proxy_config_service_client.h b/components/data_reduction_proxy/core/browser/data_reduction_proxy_config_service_client.h index e51ea83..8487829 100644 --- a/components/data_reduction_proxy/core/browser/data_reduction_proxy_config_service_client.h +++ b/components/data_reduction_proxy/core/browser/data_reduction_proxy_config_service_client.h @@ -61,7 +61,7 @@ class DataReductionProxyConfigServiceClient { // Returns the current time. // Virtual for testing. - virtual base::Time Now() const; + virtual base::Time Now(); // Constructs a synthetic response based on |params_|. // Virtual for testing. diff --git a/components/data_reduction_proxy/core/browser/data_reduction_proxy_test_utils.cc b/components/data_reduction_proxy/core/browser/data_reduction_proxy_test_utils.cc index 7aff4be..b3c9c4a 100644 --- a/components/data_reduction_proxy/core/browser/data_reduction_proxy_test_utils.cc +++ b/components/data_reduction_proxy/core/browser/data_reduction_proxy_test_utils.cc @@ -113,7 +113,7 @@ base::TimeDelta TestDataReductionProxyConfigServiceClient::GetDelay() const { return config_refresh_timer_.GetCurrentDelay(); } -base::Time TestDataReductionProxyConfigServiceClient::Now() const { +base::Time TestDataReductionProxyConfigServiceClient::Now() { return tick_clock_.Now(); } @@ -128,12 +128,12 @@ TestDataReductionProxyConfigServiceClient::TestTickClock::TestTickClock( } base::TimeTicks -TestDataReductionProxyConfigServiceClient::TestTickClock::NowTicks() const { +TestDataReductionProxyConfigServiceClient::TestTickClock::NowTicks() { return base::TimeTicks::UnixEpoch() + (time_ - base::Time::UnixEpoch()); } base::Time -TestDataReductionProxyConfigServiceClient::TestTickClock::Now() const { +TestDataReductionProxyConfigServiceClient::TestTickClock::Now() { return time_; } @@ -142,19 +142,6 @@ void TestDataReductionProxyConfigServiceClient::TestTickClock::SetTime( time_ = time; } -TestDataReductionProxyConfigServiceClient::TestBackoffEntry::TestBackoffEntry( - const net::BackoffEntry::Policy* const policy, - const TestTickClock* tick_clock) - : net::BackoffEntry(policy), - tick_clock_(tick_clock) { -} - -base::TimeTicks -TestDataReductionProxyConfigServiceClient::TestBackoffEntry::ImplGetTimeNow() - const { - return tick_clock_->NowTicks(); -} - MockDataReductionProxyService::MockDataReductionProxyService( scoped_ptr<DataReductionProxyCompressionStats> compression_stats, DataReductionProxySettings* settings, diff --git a/components/data_reduction_proxy/core/browser/data_reduction_proxy_test_utils.h b/components/data_reduction_proxy/core/browser/data_reduction_proxy_test_utils.h index c7be2e4..b1d29d2 100644 --- a/components/data_reduction_proxy/core/browser/data_reduction_proxy_test_utils.h +++ b/components/data_reduction_proxy/core/browser/data_reduction_proxy_test_utils.h @@ -11,6 +11,8 @@ #include "base/memory/ref_counted.h" #include "base/memory/scoped_ptr.h" #include "base/single_thread_task_runner.h" +#include "base/time/clock.h" +#include "base/time/tick_clock.h" #include "base/time/time.h" #include "components/data_reduction_proxy/core/browser/data_reduction_proxy_bypass_stats.h" #include "components/data_reduction_proxy/core/browser/data_reduction_proxy_config_service_client.h" @@ -104,20 +106,20 @@ class TestDataReductionProxyConfigServiceClient protected: // Overrides of DataReductionProxyConfigServiceClient - base::Time Now() const override; + base::Time Now() override; net::BackoffEntry* GetBackoffEntry() override; private: // A clock which returns a fixed value in both base::Time and base::TimeTicks. - class TestTickClock { + class TestTickClock : public base::Clock, public base::TickClock { public: TestTickClock(const base::Time& initial_time); - // Returns the current base::TimeTicks - base::TimeTicks NowTicks() const; + // base::TickClock implementation. + base::TimeTicks NowTicks() override; - // Returns the current base::Time - base::Time Now() const; + // base::Clock implementation. + base::Time Now() override; // Sets the current time. void SetTime(const base::Time& time); @@ -126,23 +128,8 @@ class TestDataReductionProxyConfigServiceClient base::Time time_; }; - // A net::BackoffEntry which uses an injected base::TickClock to control - // the backoff expiration time. - class TestBackoffEntry : public net::BackoffEntry { - public: - TestBackoffEntry(const BackoffEntry::Policy* const policy, - const TestTickClock* tick_clock); - - protected: - // Override of net::BackoffEntry. - base::TimeTicks ImplGetTimeNow() const override; - - private: - const TestTickClock* tick_clock_; - }; - TestTickClock tick_clock_; - TestBackoffEntry test_backoff_entry_; + net::BackoffEntry test_backoff_entry_; }; // Test version of |DataReductionProxyService|, which permits mocking of various diff --git a/components/domain_reliability/scheduler.cc b/components/domain_reliability/scheduler.cc index d16dfe35..040c4b1 100644 --- a/components/domain_reliability/scheduler.cc +++ b/components/domain_reliability/scheduler.cc @@ -11,6 +11,7 @@ #include "base/values.h" #include "components/domain_reliability/config.h" #include "components/domain_reliability/util.h" +#include "net/base/backoff_entry.h" namespace { @@ -92,7 +93,7 @@ DomainReliabilityScheduler::DomainReliabilityScheduler( for (size_t i = 0; i < num_collectors; ++i) { collectors_.push_back( - new MockableTimeBackoffEntry(&backoff_policy_, time_)); + new net::BackoffEntry(&backoff_policy_, time_)); } } diff --git a/components/domain_reliability/util.cc b/components/domain_reliability/util.cc index 70242aa..06a8942e 100644 --- a/components/domain_reliability/util.cc +++ b/components/domain_reliability/util.cc @@ -196,17 +196,4 @@ scoped_ptr<MockableTime::Timer> ActualTime::CreateTimer() { return scoped_ptr<MockableTime::Timer>(new ActualTimer()); } -MockableTimeBackoffEntry::MockableTimeBackoffEntry( - const net::BackoffEntry::Policy* const policy, - MockableTime* time) - : net::BackoffEntry(policy), - time_(time) { -} - -MockableTimeBackoffEntry::~MockableTimeBackoffEntry() {} - -base::TimeTicks MockableTimeBackoffEntry::ImplGetTimeNow() const { - return time_->NowTicks(); -} - } // namespace domain_reliability diff --git a/components/domain_reliability/util.h b/components/domain_reliability/util.h index 4256b05..832e2fc 100644 --- a/components/domain_reliability/util.h +++ b/components/domain_reliability/util.h @@ -10,11 +10,12 @@ #include "base/callback_forward.h" #include "base/compiler_specific.h" #include "base/memory/scoped_ptr.h" +#include "base/time/clock.h" +#include "base/time/tick_clock.h" #include "base/time/time.h" #include "base/tracked_objects.h" #include "components/domain_reliability/domain_reliability_export.h" #include "components/domain_reliability/uploader.h" -#include "net/base/backoff_entry.h" #include "net/http/http_response_info.h" #include "net/url_request/url_request_status.h" @@ -51,7 +52,8 @@ void GetUploadResultFromResponseDetails( // Mockable wrapper around TimeTicks::Now and Timer. Mock version is in // test_util.h. // TODO(ttuttle): Rename to Time{Provider,Source,?}. -class DOMAIN_RELIABILITY_EXPORT MockableTime { +class DOMAIN_RELIABILITY_EXPORT MockableTime : public base::Clock, + public base::TickClock { public: // Mockable wrapper around (a subset of) base::Timer. class DOMAIN_RELIABILITY_EXPORT Timer { @@ -68,12 +70,13 @@ class DOMAIN_RELIABILITY_EXPORT MockableTime { Timer(); }; - virtual ~MockableTime(); + ~MockableTime() override; + + // Clock impl; returns base::Time::Now() or a mocked version thereof. + base::Time Now() override = 0; + // TickClock impl; returns base::TimeTicks::Now() or a mocked version thereof. + base::TimeTicks NowTicks() override = 0; - // Returns base::Time::Now() or a mocked version thereof. - virtual base::Time Now() = 0; - // Returns base::TimeTicks::Now() or a mocked version thereof. - virtual base::TimeTicks NowTicks() = 0; // Returns a new Timer, or a mocked version thereof. virtual scoped_ptr<MockableTime::Timer> CreateTimer() = 0; @@ -98,21 +101,6 @@ class DOMAIN_RELIABILITY_EXPORT ActualTime : public MockableTime { scoped_ptr<MockableTime::Timer> CreateTimer() override; }; -// A subclass of BackoffEntry that uses a MockableTime to keep track of time. -class MockableTimeBackoffEntry : public net::BackoffEntry { - public: - MockableTimeBackoffEntry(const net::BackoffEntry::Policy* const policy, - MockableTime* time); - - ~MockableTimeBackoffEntry() override; - - protected: - base::TimeTicks ImplGetTimeNow() const override; - - private: - MockableTime* time_; -}; - } // namespace domain_reliability #endif // COMPONENTS_DOMAIN_RELIABILITY_UTIL_H_ diff --git a/components/password_manager/core/browser/affiliation_fetch_throttler.cc b/components/password_manager/core/browser/affiliation_fetch_throttler.cc index 50baaaf..9a52dec 100644 --- a/components/password_manager/core/browser/affiliation_fetch_throttler.cc +++ b/components/password_manager/core/browser/affiliation_fetch_throttler.cc @@ -15,30 +15,6 @@ namespace password_manager { -namespace { - -// Implementation of net::BackoffEntry that allows mocking its tick source. -class BackoffEntryImpl : public net::BackoffEntry { - public: - // |tick_clock| must outlive this instance. - explicit BackoffEntryImpl(const net::BackoffEntry::Policy* const policy, - base::TickClock* tick_clock) - : BackoffEntry(policy), tick_clock_(tick_clock) {} - ~BackoffEntryImpl() override {} - - private: - // net::BackoffEntry: - base::TimeTicks ImplGetTimeNow() const override { - return tick_clock_->NowTicks(); - } - - base::TickClock* tick_clock_; - - DISALLOW_COPY_AND_ASSIGN(BackoffEntryImpl); -}; - -} // namespace - // static const net::BackoffEntry::Policy AffiliationFetchThrottler::kBackoffPolicy = { // Number of initial errors (in sequence) to ignore before going into @@ -82,7 +58,7 @@ AffiliationFetchThrottler::AffiliationFetchThrottler( state_(IDLE), has_network_connectivity_(false), is_fetch_scheduled_(false), - exponential_backoff_(new BackoffEntryImpl(&kBackoffPolicy, tick_clock_)), + exponential_backoff_(new net::BackoffEntry(&kBackoffPolicy, tick_clock_)), weak_ptr_factory_(this) { DCHECK(delegate); // Start observing before querying the current connectivity state, so that if diff --git a/google_apis/gcm/engine/connection_factory_impl_unittest.cc b/google_apis/gcm/engine/connection_factory_impl_unittest.cc index ed23da9..4c0e127 100644 --- a/google_apis/gcm/engine/connection_factory_impl_unittest.cc +++ b/google_apis/gcm/engine/connection_factory_impl_unittest.cc @@ -80,28 +80,6 @@ void ReadContinuation( void WriteContinuation() { } -class TestBackoffEntry : public net::BackoffEntry { - public: - explicit TestBackoffEntry(base::SimpleTestTickClock* tick_clock); - ~TestBackoffEntry() override; - - base::TimeTicks ImplGetTimeNow() const override; - - private: - base::SimpleTestTickClock* tick_clock_; -}; - -TestBackoffEntry::TestBackoffEntry(base::SimpleTestTickClock* tick_clock) - : BackoffEntry(&kTestBackoffPolicy), - tick_clock_(tick_clock) { -} - -TestBackoffEntry::~TestBackoffEntry() {} - -base::TimeTicks TestBackoffEntry::ImplGetTimeNow() const { - return tick_clock_->NowTicks(); -} - // A connection factory that stubs out network requests and overrides the // backoff policy. class TestConnectionFactoryImpl : public ConnectionFactoryImpl { @@ -213,7 +191,8 @@ void TestConnectionFactoryImpl::InitHandler() { scoped_ptr<net::BackoffEntry> TestConnectionFactoryImpl::CreateBackoffEntry( const net::BackoffEntry::Policy* const policy) { - return scoped_ptr<net::BackoffEntry>(new TestBackoffEntry(&tick_clock_)); + return make_scoped_ptr(new net::BackoffEntry(&kTestBackoffPolicy, + &tick_clock_)); } scoped_ptr<ConnectionHandler> diff --git a/net/base/backoff_entry.cc b/net/base/backoff_entry.cc index 0b3a06f..bfcc9dd 100644 --- a/net/base/backoff_entry.cc +++ b/net/base/backoff_entry.cc @@ -12,11 +12,16 @@ #include "base/logging.h" #include "base/numerics/safe_math.h" #include "base/rand_util.h" +#include "base/time/tick_clock.h" namespace net { -BackoffEntry::BackoffEntry(const BackoffEntry::Policy* const policy) - : policy_(policy) { +BackoffEntry::BackoffEntry(const BackoffEntry::Policy* policy) + : BackoffEntry(policy, nullptr) {} + +BackoffEntry::BackoffEntry(const BackoffEntry::Policy* policy, + base::TickClock* clock) + : policy_(policy), clock_(clock) { DCHECK(policy_); Reset(); } @@ -41,7 +46,7 @@ void BackoffEntry::InformOfRequest(bool succeeded) { --failure_count_; // The reason why we are not just cutting the release time to - // ImplGetTimeNow() is on the one hand, it would unset a release + // GetTimeTicksNow() is on the one hand, it would unset a release // time set by SetCustomReleaseTime and on the other we would like // to push every request up to our "horizon" when dealing with // multiple in-flight requests. Ex: If we send three requests and @@ -53,16 +58,16 @@ void BackoffEntry::InformOfRequest(bool succeeded) { if (policy_->always_use_initial_delay) delay = base::TimeDelta::FromMilliseconds(policy_->initial_delay_ms); exponential_backoff_release_time_ = std::max( - ImplGetTimeNow() + delay, exponential_backoff_release_time_); + GetTimeTicksNow() + delay, exponential_backoff_release_time_); } } bool BackoffEntry::ShouldRejectRequest() const { - return exponential_backoff_release_time_ > ImplGetTimeNow(); + return exponential_backoff_release_time_ > GetTimeTicksNow(); } base::TimeDelta BackoffEntry::GetTimeUntilRelease() const { - base::TimeTicks now = ImplGetTimeNow(); + base::TimeTicks now = GetTimeTicksNow(); if (exponential_backoff_release_time_ <= now) return base::TimeDelta(); return exponential_backoff_release_time_ - now; @@ -80,7 +85,7 @@ bool BackoffEntry::CanDiscard() const { if (policy_->entry_lifetime_ms == -1) return false; - base::TimeTicks now = ImplGetTimeNow(); + base::TimeTicks now = GetTimeTicksNow(); int64 unused_since_ms = (now - exponential_backoff_release_time_).InMilliseconds(); @@ -103,19 +108,13 @@ bool BackoffEntry::CanDiscard() const { void BackoffEntry::Reset() { failure_count_ = 0; - - // We leave exponential_backoff_release_time_ unset, meaning 0. We could - // initialize to ImplGetTimeNow() but because it's a virtual method it's - // not safe to call in the constructor (and the constructor calls Reset()). - // The effects are the same, i.e. ShouldRejectRequest() will return false - // right after Reset(). + // For legacy reasons, we reset exponential_backoff_release_time_ to the + // uninitialized state. It would also be reasonable to reset it to + // GetTimeTicksNow(). The effects are the same, i.e. ShouldRejectRequest() + // will return false right after Reset(). exponential_backoff_release_time_ = base::TimeTicks(); } -base::TimeTicks BackoffEntry::ImplGetTimeNow() const { - return base::TimeTicks::Now(); -} - base::TimeTicks BackoffEntry::CalculateReleaseTime() const { int effective_failure_count = std::max(0, failure_count_ - policy_->num_errors_to_ignore); @@ -128,7 +127,7 @@ base::TimeTicks BackoffEntry::CalculateReleaseTime() const { if (effective_failure_count == 0) { // Never reduce previously set release horizon, e.g. due to Retry-After // header. - return std::max(ImplGetTimeNow(), exponential_backoff_release_time_); + return std::max(GetTimeTicksNow(), exponential_backoff_release_time_); } // The delay is calculated with this formula: @@ -144,7 +143,7 @@ base::TimeTicks BackoffEntry::CalculateReleaseTime() const { // Do overflow checking in microseconds, the internal unit of TimeTicks. const int64 kTimeTicksNowUs = - (ImplGetTimeNow() - base::TimeTicks()).InMicroseconds(); + (GetTimeTicksNow() - base::TimeTicks()).InMicroseconds(); base::internal::CheckedNumeric<int64> calculated_release_time_us = delay_ms + 0.5; calculated_release_time_us *= base::Time::kMicrosecondsPerMillisecond; @@ -170,4 +169,8 @@ base::TimeTicks BackoffEntry::CalculateReleaseTime() const { exponential_backoff_release_time_); } +base::TimeTicks BackoffEntry::GetTimeTicksNow() const { + return clock_ ? clock_->NowTicks() : base::TimeTicks::Now(); +} + } // namespace net diff --git a/net/base/backoff_entry.h b/net/base/backoff_entry.h index d8f03d3..dbc7488 100644 --- a/net/base/backoff_entry.h +++ b/net/base/backoff_entry.h @@ -9,6 +9,10 @@ #include "base/time/time.h" #include "net/base/net_export.h" +namespace base { +class TickClock; +} + namespace net { // Provides the core logic needed for randomized exponential back-off @@ -57,7 +61,11 @@ class NET_EXPORT BackoffEntry : NON_EXPORTED_BASE(public base::NonThreadSafe) { // Lifetime of policy must enclose lifetime of BackoffEntry. The // pointer must be valid but is not dereferenced during construction. - explicit BackoffEntry(const Policy* const policy); + explicit BackoffEntry(const Policy* policy); + // Lifetime of policy and clock must enclose lifetime of BackoffEntry. + // |policy| pointer must be valid but isn't dereferenced during construction. + // |clock| pointer may be null. + BackoffEntry(const Policy* policy, base::TickClock* clock); virtual ~BackoffEntry(); // Inform this item that a request for the network resource it is @@ -90,14 +98,13 @@ class NET_EXPORT BackoffEntry : NON_EXPORTED_BASE(public base::NonThreadSafe) { // Returns the failure count for this entry. int failure_count() const { return failure_count_; } - protected: - // Equivalent to TimeTicks::Now(), virtual so unit tests can override. - virtual base::TimeTicks ImplGetTimeNow() const; - private: // Calculates when requests should again be allowed through. base::TimeTicks CalculateReleaseTime() const; + // Equivalent to TimeTicks::Now(), using clock_ if provided. + base::TimeTicks GetTimeTicksNow() const; + // Timestamp calculated by the exponential back-off algorithm at which we are // allowed to start sending requests again. base::TimeTicks exponential_backoff_release_time_; @@ -105,7 +112,9 @@ class NET_EXPORT BackoffEntry : NON_EXPORTED_BASE(public base::NonThreadSafe) { // Counts request errors; decremented on success. int failure_count_; - const Policy* const policy_; + const Policy* const policy_; // Not owned. + + base::TickClock* const clock_; // Not owned. DISALLOW_COPY_AND_ASSIGN(BackoffEntry); }; diff --git a/net/base/backoff_entry_unittest.cc b/net/base/backoff_entry_unittest.cc index 89ec2c4..cca7c45 100644 --- a/net/base/backoff_entry_unittest.cc +++ b/net/base/backoff_entry_unittest.cc @@ -3,6 +3,9 @@ // found in the LICENSE file. #include "net/base/backoff_entry.h" + +#include "base/macros.h" +#include "base/time/tick_clock.h" #include "testing/gtest/include/gtest/gtest.h" namespace { @@ -13,32 +16,22 @@ using net::BackoffEntry; BackoffEntry::Policy base_policy = { 0, 1000, 2.0, 0.0, 20000, 2000, false }; -class TestBackoffEntry : public BackoffEntry { +class TestTickClock : public base::TickClock { public: - explicit TestBackoffEntry(const Policy* const policy) - : BackoffEntry(policy), - now_(TimeTicks()) { - // Work around initialization in constructor not picking up - // fake time. - SetCustomReleaseTime(TimeTicks()); - } + TestTickClock() {} + ~TestTickClock() override {} - ~TestBackoffEntry() override {} - - TimeTicks ImplGetTimeNow() const override { return now_; } - - void set_now(const TimeTicks& now) { - now_ = now; - } + TimeTicks NowTicks() override { return now_ticks_; } + void set_now(TimeTicks now) { now_ticks_ = now; } private: - TimeTicks now_; - - DISALLOW_COPY_AND_ASSIGN(TestBackoffEntry); + TimeTicks now_ticks_; + DISALLOW_COPY_AND_ASSIGN(TestTickClock); }; TEST(BackoffEntryTest, BaseTest) { - TestBackoffEntry entry(&base_policy); + TestTickClock now_ticks; + BackoffEntry entry(&base_policy, &now_ticks); EXPECT_FALSE(entry.ShouldRejectRequest()); EXPECT_EQ(TimeDelta(), entry.GetTimeUntilRelease()); @@ -50,14 +43,16 @@ TEST(BackoffEntryTest, BaseTest) { TEST(BackoffEntryTest, CanDiscardNeverExpires) { BackoffEntry::Policy never_expires_policy = base_policy; never_expires_policy.entry_lifetime_ms = -1; - TestBackoffEntry never_expires(&never_expires_policy); + TestTickClock now_ticks; + BackoffEntry never_expires(&never_expires_policy, &now_ticks); EXPECT_FALSE(never_expires.CanDiscard()); - never_expires.set_now(TimeTicks() + TimeDelta::FromDays(100)); + now_ticks.set_now(TimeTicks() + TimeDelta::FromDays(100)); EXPECT_FALSE(never_expires.CanDiscard()); } TEST(BackoffEntryTest, CanDiscard) { - TestBackoffEntry entry(&base_policy); + TestTickClock now_ticks; + BackoffEntry entry(&base_policy, &now_ticks); // Because lifetime is non-zero, we shouldn't be able to discard yet. EXPECT_FALSE(entry.CanDiscard()); @@ -66,19 +61,18 @@ TEST(BackoffEntryTest, CanDiscard) { EXPECT_FALSE(entry.CanDiscard()); // Test the case where there are errors but we can time out. - entry.set_now( - entry.GetReleaseTime() + TimeDelta::FromMilliseconds(1)); + now_ticks.set_now(entry.GetReleaseTime() + TimeDelta::FromMilliseconds(1)); EXPECT_FALSE(entry.CanDiscard()); - entry.set_now(entry.GetReleaseTime() + TimeDelta::FromMilliseconds( + now_ticks.set_now(entry.GetReleaseTime() + TimeDelta::FromMilliseconds( base_policy.maximum_backoff_ms + 1)); EXPECT_TRUE(entry.CanDiscard()); // Test the final case (no errors, dependent only on specified lifetime). - entry.set_now(entry.GetReleaseTime() + TimeDelta::FromMilliseconds( + now_ticks.set_now(entry.GetReleaseTime() + TimeDelta::FromMilliseconds( base_policy.entry_lifetime_ms - 1)); entry.InformOfRequest(true); EXPECT_FALSE(entry.CanDiscard()); - entry.set_now(entry.GetReleaseTime() + TimeDelta::FromMilliseconds( + now_ticks.set_now(entry.GetReleaseTime() + TimeDelta::FromMilliseconds( base_policy.entry_lifetime_ms)); EXPECT_TRUE(entry.CanDiscard()); } @@ -88,10 +82,11 @@ TEST(BackoffEntryTest, CanDiscardAlwaysDelay) { always_delay_policy.always_use_initial_delay = true; always_delay_policy.entry_lifetime_ms = 0; - TestBackoffEntry entry(&always_delay_policy); + TestTickClock now_ticks; + BackoffEntry entry(&always_delay_policy, &now_ticks); // Because lifetime is non-zero, we shouldn't be able to discard yet. - entry.set_now(entry.GetReleaseTime() + TimeDelta::FromMilliseconds(2000)); + now_ticks.set_now(entry.GetReleaseTime() + TimeDelta::FromMilliseconds(2000)); EXPECT_TRUE(entry.CanDiscard()); // Even with no failures, we wait until the delay before we allow discard. @@ -99,14 +94,15 @@ TEST(BackoffEntryTest, CanDiscardAlwaysDelay) { EXPECT_FALSE(entry.CanDiscard()); // Wait until the delay expires, and we can discard the entry again. - entry.set_now(entry.GetReleaseTime() + TimeDelta::FromMilliseconds(1000)); + now_ticks.set_now(entry.GetReleaseTime() + TimeDelta::FromMilliseconds(1000)); EXPECT_TRUE(entry.CanDiscard()); } TEST(BackoffEntryTest, CanDiscardNotStored) { BackoffEntry::Policy no_store_policy = base_policy; no_store_policy.entry_lifetime_ms = 0; - TestBackoffEntry not_stored(&no_store_policy); + TestTickClock now_ticks; + BackoffEntry not_stored(&no_store_policy, &now_ticks); EXPECT_TRUE(not_stored.CanDiscard()); } @@ -127,28 +123,29 @@ TEST(BackoffEntryTest, ShouldIgnoreFirstTwo) { } TEST(BackoffEntryTest, ReleaseTimeCalculation) { - TestBackoffEntry entry(&base_policy); + TestTickClock now_ticks; + BackoffEntry entry(&base_policy, &now_ticks); // With zero errors, should return "now". TimeTicks result = entry.GetReleaseTime(); - EXPECT_EQ(entry.ImplGetTimeNow(), result); + EXPECT_EQ(now_ticks.NowTicks(), result); // 1 error. entry.InformOfRequest(false); result = entry.GetReleaseTime(); - EXPECT_EQ(entry.ImplGetTimeNow() + TimeDelta::FromMilliseconds(1000), result); + EXPECT_EQ(now_ticks.NowTicks() + TimeDelta::FromMilliseconds(1000), result); EXPECT_EQ(TimeDelta::FromMilliseconds(1000), entry.GetTimeUntilRelease()); // 2 errors. entry.InformOfRequest(false); result = entry.GetReleaseTime(); - EXPECT_EQ(entry.ImplGetTimeNow() + TimeDelta::FromMilliseconds(2000), result); + EXPECT_EQ(now_ticks.NowTicks() + TimeDelta::FromMilliseconds(2000), result); EXPECT_EQ(TimeDelta::FromMilliseconds(2000), entry.GetTimeUntilRelease()); // 3 errors. entry.InformOfRequest(false); result = entry.GetReleaseTime(); - EXPECT_EQ(entry.ImplGetTimeNow() + TimeDelta::FromMilliseconds(4000), result); + EXPECT_EQ(now_ticks.NowTicks() + TimeDelta::FromMilliseconds(4000), result); EXPECT_EQ(TimeDelta::FromMilliseconds(4000), entry.GetTimeUntilRelease()); // 6 errors (to check it doesn't pass maximum). @@ -156,8 +153,7 @@ TEST(BackoffEntryTest, ReleaseTimeCalculation) { entry.InformOfRequest(false); entry.InformOfRequest(false); result = entry.GetReleaseTime(); - EXPECT_EQ( - entry.ImplGetTimeNow() + TimeDelta::FromMilliseconds(20000), result); + EXPECT_EQ(now_ticks.NowTicks() + TimeDelta::FromMilliseconds(20000), result); } TEST(BackoffEntryTest, ReleaseTimeCalculationAlwaysDelay) { @@ -165,7 +161,8 @@ TEST(BackoffEntryTest, ReleaseTimeCalculationAlwaysDelay) { always_delay_policy.always_use_initial_delay = true; always_delay_policy.num_errors_to_ignore = 2; - TestBackoffEntry entry(&always_delay_policy); + TestTickClock now_ticks; + BackoffEntry entry(&always_delay_policy, &now_ticks); // With previous requests, should return "now". TimeTicks result = entry.GetReleaseTime(); @@ -201,21 +198,21 @@ TEST(BackoffEntryTest, ReleaseTimeCalculationWithJitter) { BackoffEntry::Policy jittery_policy = base_policy; jittery_policy.jitter_factor = 0.2; - TestBackoffEntry entry(&jittery_policy); + TestTickClock now_ticks; + BackoffEntry entry(&jittery_policy, &now_ticks); entry.InformOfRequest(false); entry.InformOfRequest(false); entry.InformOfRequest(false); TimeTicks result = entry.GetReleaseTime(); - EXPECT_LE( - entry.ImplGetTimeNow() + TimeDelta::FromMilliseconds(3200), result); - EXPECT_GE( - entry.ImplGetTimeNow() + TimeDelta::FromMilliseconds(4000), result); + EXPECT_LE(now_ticks.NowTicks() + TimeDelta::FromMilliseconds(3200), result); + EXPECT_GE(now_ticks.NowTicks() + TimeDelta::FromMilliseconds(4000), result); } } TEST(BackoffEntryTest, FailureThenSuccess) { - TestBackoffEntry entry(&base_policy); + TestTickClock now_ticks; + BackoffEntry entry(&base_policy, &now_ticks); // Failure count 1, establishes horizon. entry.InformOfRequest(false); @@ -224,7 +221,7 @@ TEST(BackoffEntryTest, FailureThenSuccess) { // Success, failure count 0, should not advance past // the horizon that was already set. - entry.set_now(release_time - TimeDelta::FromMilliseconds(200)); + now_ticks.set_now(release_time - TimeDelta::FromMilliseconds(200)); entry.InformOfRequest(true); EXPECT_EQ(release_time, entry.GetReleaseTime()); @@ -239,7 +236,8 @@ TEST(BackoffEntryTest, FailureThenSuccessAlwaysDelay) { always_delay_policy.always_use_initial_delay = true; always_delay_policy.num_errors_to_ignore = 1; - TestBackoffEntry entry(&always_delay_policy); + TestTickClock now_ticks; + BackoffEntry entry(&always_delay_policy, &now_ticks); // Failure count 1. entry.InformOfRequest(false); @@ -248,7 +246,7 @@ TEST(BackoffEntryTest, FailureThenSuccessAlwaysDelay) { // Failure count 2. entry.InformOfRequest(false); EXPECT_EQ(TimeDelta::FromMilliseconds(2000), entry.GetTimeUntilRelease()); - entry.set_now(entry.GetReleaseTime() + TimeDelta::FromMilliseconds(2000)); + now_ticks.set_now(entry.GetReleaseTime() + TimeDelta::FromMilliseconds(2000)); // Success. We should go back to the original delay. entry.InformOfRequest(true); @@ -257,23 +255,24 @@ TEST(BackoffEntryTest, FailureThenSuccessAlwaysDelay) { // Failure count reaches 2 again. We should increase the delay once more. entry.InformOfRequest(false); EXPECT_EQ(TimeDelta::FromMilliseconds(2000), entry.GetTimeUntilRelease()); - entry.set_now(entry.GetReleaseTime() + TimeDelta::FromMilliseconds(2000)); + now_ticks.set_now(entry.GetReleaseTime() + TimeDelta::FromMilliseconds(2000)); } TEST(BackoffEntryTest, RetainCustomHorizon) { - TestBackoffEntry custom(&base_policy); + TestTickClock now_ticks; + BackoffEntry custom(&base_policy, &now_ticks); TimeTicks custom_horizon = TimeTicks() + TimeDelta::FromDays(3); custom.SetCustomReleaseTime(custom_horizon); custom.InformOfRequest(false); custom.InformOfRequest(true); - custom.set_now(TimeTicks() + TimeDelta::FromDays(2)); + now_ticks.set_now(TimeTicks() + TimeDelta::FromDays(2)); custom.InformOfRequest(false); custom.InformOfRequest(true); EXPECT_EQ(custom_horizon, custom.GetReleaseTime()); // Now check that once we are at or past the custom horizon, // we get normal behavior. - custom.set_now(TimeTicks() + TimeDelta::FromDays(3)); + now_ticks.set_now(TimeTicks() + TimeDelta::FromDays(3)); custom.InformOfRequest(false); EXPECT_EQ( TimeTicks() + TimeDelta::FromDays(3) + TimeDelta::FromMilliseconds(1000), @@ -284,7 +283,8 @@ TEST(BackoffEntryTest, RetainCustomHorizonWhenInitialErrorsIgnored) { // Regression test for a bug discovered during code review. BackoffEntry::Policy lenient_policy = base_policy; lenient_policy.num_errors_to_ignore = 1; - TestBackoffEntry custom(&lenient_policy); + TestTickClock now_ticks; + BackoffEntry custom(&lenient_policy, &now_ticks); TimeTicks custom_horizon = TimeTicks() + TimeDelta::FromDays(3); custom.SetCustomReleaseTime(custom_horizon); custom.InformOfRequest(false); // This must not reset the horizon. @@ -294,13 +294,14 @@ TEST(BackoffEntryTest, RetainCustomHorizonWhenInitialErrorsIgnored) { TEST(BackoffEntryTest, OverflowProtection) { BackoffEntry::Policy large_multiply_policy = base_policy; large_multiply_policy.multiply_factor = 256; - TestBackoffEntry custom(&large_multiply_policy); + TestTickClock now_ticks; + BackoffEntry custom(&large_multiply_policy, &now_ticks); // Trigger enough failures such that more than 11 bits of exponent are used // to represent the exponential backoff intermediate values. Given a multiply // factor of 256 (2^8), 129 iterations is enough: 2^(8*(129-1)) = 2^1024. for (int i = 0; i < 129; ++i) { - custom.set_now(custom.ImplGetTimeNow() + custom.GetTimeUntilRelease()); + now_ticks.set_now(now_ticks.NowTicks() + custom.GetTimeUntilRelease()); custom.InformOfRequest(false); ASSERT_TRUE(custom.ShouldRejectRequest()); } diff --git a/net/url_request/url_request_throttler_simulation_unittest.cc b/net/url_request/url_request_throttler_simulation_unittest.cc index 3999159..80734ae 100644 --- a/net/url_request/url_request_throttler_simulation_unittest.cc +++ b/net/url_request/url_request_throttler_simulation_unittest.cc @@ -303,31 +303,26 @@ class MockURLRequestThrottlerEntry : public URLRequestThrottlerEntry { public: explicit MockURLRequestThrottlerEntry(URLRequestThrottlerManager* manager) : URLRequestThrottlerEntry(manager, std::string()), - mock_backoff_entry_(&backoff_policy_) {} + backoff_entry_(&backoff_policy_, &fake_clock_) {} const BackoffEntry* GetBackoffEntry() const override { - return &mock_backoff_entry_; + return &backoff_entry_; } - BackoffEntry* GetBackoffEntry() override { return &mock_backoff_entry_; } + BackoffEntry* GetBackoffEntry() override { return &backoff_entry_; } - TimeTicks ImplGetTimeNow() const override { return fake_now_; } + TimeTicks ImplGetTimeNow() const override { return fake_clock_.NowTicks(); } void SetFakeNow(const TimeTicks& fake_time) { - fake_now_ = fake_time; - mock_backoff_entry_.set_fake_now(fake_time); - } - - TimeTicks fake_now() const { - return fake_now_; + fake_clock_.set_now(fake_time); } protected: ~MockURLRequestThrottlerEntry() override {} private: - TimeTicks fake_now_; - MockBackoffEntry mock_backoff_entry_; + mutable TestTickClock fake_clock_; + BackoffEntry backoff_entry_; }; // Registry of results for a class of |Requester| objects (e.g. attackers vs. @@ -426,7 +421,7 @@ class Requester : public DiscreteTimeSimulation::Actor { effective_delay += current_jitter; } - if (throttler_entry_->fake_now() - time_of_last_attempt_ > + if (throttler_entry_->ImplGetTimeNow() - time_of_last_attempt_ > effective_delay) { if (!throttler_entry_->ShouldRejectRequest( server_->mock_request(), @@ -441,10 +436,10 @@ class Requester : public DiscreteTimeSimulation::Actor { if (last_attempt_was_failure_) { last_downtime_duration_ = - throttler_entry_->fake_now() - time_of_last_success_; + throttler_entry_->ImplGetTimeNow() - time_of_last_success_; } - time_of_last_success_ = throttler_entry_->fake_now(); + time_of_last_success_ = throttler_entry_->ImplGetTimeNow(); last_attempt_was_failure_ = false; } else { if (results_) @@ -457,7 +452,7 @@ class Requester : public DiscreteTimeSimulation::Actor { last_attempt_was_failure_ = true; } - time_of_last_attempt_ = throttler_entry_->fake_now(); + time_of_last_attempt_ = throttler_entry_->ImplGetTimeNow(); } } diff --git a/net/url_request/url_request_throttler_test_support.cc b/net/url_request/url_request_throttler_test_support.cc index 9d3f4e2..5b39c04 100644 --- a/net/url_request/url_request_throttler_test_support.cc +++ b/net/url_request/url_request_throttler_test_support.cc @@ -8,19 +8,14 @@ namespace net { -MockBackoffEntry::MockBackoffEntry(const BackoffEntry::Policy* const policy) - : BackoffEntry(policy) { -} +TestTickClock::TestTickClock() {} -MockBackoffEntry::~MockBackoffEntry() { -} +TestTickClock::TestTickClock(base::TimeTicks now) : now_ticks_(now) {} -base::TimeTicks MockBackoffEntry::ImplGetTimeNow() const { - return fake_now_; -} +TestTickClock::~TestTickClock() {} -void MockBackoffEntry::set_fake_now(const base::TimeTicks& now) { - fake_now_ = now; +base::TimeTicks TestTickClock::NowTicks() { + return now_ticks_; } MockURLRequestThrottlerHeaderAdapter::MockURLRequestThrottlerHeaderAdapter( diff --git a/net/url_request/url_request_throttler_test_support.h b/net/url_request/url_request_throttler_test_support.h index a710333..9331c4b 100644 --- a/net/url_request/url_request_throttler_test_support.h +++ b/net/url_request/url_request_throttler_test_support.h @@ -7,24 +7,26 @@ #include <string> +#include "base/macros.h" +#include "base/time/tick_clock.h" #include "base/time/time.h" #include "net/base/backoff_entry.h" #include "net/url_request/url_request_throttler_header_interface.h" namespace net { -class MockBackoffEntry : public BackoffEntry { +class TestTickClock : public base::TickClock { public: - explicit MockBackoffEntry(const BackoffEntry::Policy* const policy); - ~MockBackoffEntry() override; + TestTickClock(); + explicit TestTickClock(base::TimeTicks now); + ~TestTickClock() override; - // BackoffEntry overrides. - base::TimeTicks ImplGetTimeNow() const override; - - void set_fake_now(const base::TimeTicks& now); + base::TimeTicks NowTicks() override; + void set_now(base::TimeTicks now) { now_ticks_ = now; } private: - base::TimeTicks fake_now_; + base::TimeTicks now_ticks_; + DISALLOW_COPY_AND_ASSIGN(TestTickClock); }; // Mocks the URLRequestThrottlerHeaderInterface, allowing testing code to diff --git a/net/url_request/url_request_throttler_unittest.cc b/net/url_request/url_request_throttler_unittest.cc index dcafca1..3104a60 100644 --- a/net/url_request/url_request_throttler_unittest.cc +++ b/net/url_request/url_request_throttler_unittest.cc @@ -36,7 +36,7 @@ class MockURLRequestThrottlerEntry : public URLRequestThrottlerEntry { explicit MockURLRequestThrottlerEntry( URLRequestThrottlerManager* manager) : URLRequestThrottlerEntry(manager, std::string()), - mock_backoff_entry_(&backoff_policy_) { + backoff_entry_(&backoff_policy_, &fake_clock_) { InitPolicy(); } MockURLRequestThrottlerEntry( @@ -45,11 +45,10 @@ class MockURLRequestThrottlerEntry : public URLRequestThrottlerEntry { const TimeTicks& sliding_window_release_time, const TimeTicks& fake_now) : URLRequestThrottlerEntry(manager, std::string()), - fake_time_now_(fake_now), - mock_backoff_entry_(&backoff_policy_) { + fake_clock_(fake_now), + backoff_entry_(&backoff_policy_, &fake_clock_) { InitPolicy(); - mock_backoff_entry_.set_fake_now(fake_now); set_exponential_backoff_release_time(exponential_backoff_release_time); set_sliding_window_release_time(sliding_window_release_time); } @@ -64,47 +63,45 @@ class MockURLRequestThrottlerEntry : public URLRequestThrottlerEntry { } const BackoffEntry* GetBackoffEntry() const override { - return &mock_backoff_entry_; + return &backoff_entry_; } - BackoffEntry* GetBackoffEntry() override { return &mock_backoff_entry_; } + BackoffEntry* GetBackoffEntry() override { return &backoff_entry_; } static bool ExplicitUserRequest(int load_flags) { return URLRequestThrottlerEntry::ExplicitUserRequest(load_flags); } void ResetToBlank(const TimeTicks& time_now) { - fake_time_now_ = time_now; - mock_backoff_entry_.set_fake_now(time_now); + fake_clock_.set_now(time_now); GetBackoffEntry()->Reset(); - GetBackoffEntry()->SetCustomReleaseTime(time_now); set_sliding_window_release_time(time_now); } // Overridden for tests. - TimeTicks ImplGetTimeNow() const override { return fake_time_now_; } + TimeTicks ImplGetTimeNow() const override { return fake_clock_.NowTicks(); } - void set_exponential_backoff_release_time( - const base::TimeTicks& release_time) { + void set_fake_now(const TimeTicks& now) { fake_clock_.set_now(now); } + + void set_exponential_backoff_release_time(const TimeTicks& release_time) { GetBackoffEntry()->SetCustomReleaseTime(release_time); } - base::TimeTicks sliding_window_release_time() const { + TimeTicks sliding_window_release_time() const { return URLRequestThrottlerEntry::sliding_window_release_time(); } - void set_sliding_window_release_time( - const base::TimeTicks& release_time) { - URLRequestThrottlerEntry::set_sliding_window_release_time( - release_time); + void set_sliding_window_release_time(const TimeTicks& release_time) { + URLRequestThrottlerEntry::set_sliding_window_release_time(release_time); } - TimeTicks fake_time_now_; - MockBackoffEntry mock_backoff_entry_; - protected: ~MockURLRequestThrottlerEntry() override {} + + private: + mutable TestTickClock fake_clock_; + BackoffEntry backoff_entry_; }; class MockURLRequestThrottlerManager : public URLRequestThrottlerManager { @@ -197,7 +194,7 @@ TEST_F(URLRequestThrottlerEntryTest, CanThrottleRequest) { TestNetworkDelegate d; context_.set_network_delegate(&d); entry_->set_exponential_backoff_release_time( - entry_->fake_time_now_ + TimeDelta::FromMilliseconds(1)); + entry_->ImplGetTimeNow() + TimeDelta::FromMilliseconds(1)); d.set_can_throttle_requests(false); EXPECT_FALSE(entry_->ShouldRejectRequest(*request_, @@ -210,7 +207,7 @@ TEST_F(URLRequestThrottlerEntryTest, CanThrottleRequest) { TEST_F(URLRequestThrottlerEntryTest, InterfaceDuringExponentialBackoff) { base::HistogramTester histogram_tester; entry_->set_exponential_backoff_release_time( - entry_->fake_time_now_ + TimeDelta::FromMilliseconds(1)); + entry_->ImplGetTimeNow() + TimeDelta::FromMilliseconds(1)); EXPECT_TRUE(entry_->ShouldRejectRequest(*request_, context_.network_delegate())); @@ -225,11 +222,11 @@ TEST_F(URLRequestThrottlerEntryTest, InterfaceDuringExponentialBackoff) { TEST_F(URLRequestThrottlerEntryTest, InterfaceNotDuringExponentialBackoff) { base::HistogramTester histogram_tester; - entry_->set_exponential_backoff_release_time(entry_->fake_time_now_); + entry_->set_exponential_backoff_release_time(entry_->ImplGetTimeNow()); EXPECT_FALSE(entry_->ShouldRejectRequest(*request_, context_.network_delegate())); entry_->set_exponential_backoff_release_time( - entry_->fake_time_now_ - TimeDelta::FromMilliseconds(1)); + entry_->ImplGetTimeNow() - TimeDelta::FromMilliseconds(1)); EXPECT_FALSE(entry_->ShouldRejectRequest(*request_, context_.network_delegate())); @@ -240,14 +237,16 @@ TEST_F(URLRequestThrottlerEntryTest, InterfaceNotDuringExponentialBackoff) { TEST_F(URLRequestThrottlerEntryTest, InterfaceUpdateFailure) { MockURLRequestThrottlerHeaderAdapter failure_response(503); entry_->UpdateWithResponse(std::string(), &failure_response); - EXPECT_GT(entry_->GetExponentialBackoffReleaseTime(), entry_->fake_time_now_) + EXPECT_GT(entry_->GetExponentialBackoffReleaseTime(), + entry_->ImplGetTimeNow()) << "A failure should increase the release_time"; } TEST_F(URLRequestThrottlerEntryTest, InterfaceUpdateSuccess) { MockURLRequestThrottlerHeaderAdapter success_response(200); entry_->UpdateWithResponse(std::string(), &success_response); - EXPECT_EQ(entry_->GetExponentialBackoffReleaseTime(), entry_->fake_time_now_) + EXPECT_EQ(entry_->GetExponentialBackoffReleaseTime(), + entry_->ImplGetTimeNow()) << "A success should not add any delay"; } @@ -256,7 +255,8 @@ TEST_F(URLRequestThrottlerEntryTest, InterfaceUpdateSuccessThenFailure) { MockURLRequestThrottlerHeaderAdapter success_response(200); entry_->UpdateWithResponse(std::string(), &success_response); entry_->UpdateWithResponse(std::string(), &failure_response); - EXPECT_GT(entry_->GetExponentialBackoffReleaseTime(), entry_->fake_time_now_) + EXPECT_GT(entry_->GetExponentialBackoffReleaseTime(), + entry_->ImplGetTimeNow()) << "This scenario should add delay"; entry_->UpdateWithResponse(std::string(), &success_response); } @@ -315,13 +315,13 @@ TEST_F(URLRequestThrottlerEntryTest, SlidingWindow) { int sliding_window = URLRequestThrottlerEntry::kDefaultSlidingWindowPeriodMs; - TimeTicks time_1 = entry_->fake_time_now_ + + TimeTicks time_1 = entry_->ImplGetTimeNow() + TimeDelta::FromMilliseconds(sliding_window / 3); - TimeTicks time_2 = entry_->fake_time_now_ + + TimeTicks time_2 = entry_->ImplGetTimeNow() + TimeDelta::FromMilliseconds(2 * sliding_window / 3); - TimeTicks time_3 = entry_->fake_time_now_ + + TimeTicks time_3 = entry_->ImplGetTimeNow() + TimeDelta::FromMilliseconds(sliding_window); - TimeTicks time_4 = entry_->fake_time_now_ + + TimeTicks time_4 = entry_->ImplGetTimeNow() + TimeDelta::FromMilliseconds(sliding_window + 2 * sliding_window / 3); entry_->set_exponential_backoff_release_time(time_1); @@ -332,7 +332,7 @@ TEST_F(URLRequestThrottlerEntryTest, SlidingWindow) { } EXPECT_EQ(time_2, entry_->sliding_window_release_time()); - entry_->fake_time_now_ = time_3; + entry_->set_fake_now(time_3); for (int i = 0; i < (max_send + 1) / 2; ++i) EXPECT_EQ(0, entry_->ReserveSendingTimeForNextRequest(TimeTicks())); |