| Index: net/url_request/url_request_throttler_unittest.cc
|
| diff --git a/net/url_request/url_request_throttler_unittest.cc b/net/url_request/url_request_throttler_unittest.cc
|
| index f6227b32ebabfbfec6c9a481b9ce5251b17180a7..354adb96349a80c5f5c1c2f367b1c50270cf0ed7 100644
|
| --- a/net/url_request/url_request_throttler_unittest.cc
|
| +++ b/net/url_request/url_request_throttler_unittest.cc
|
| @@ -3,6 +3,7 @@
|
| // found in the LICENSE file.
|
|
|
| #include "base/memory/scoped_ptr.h"
|
| +#include "base/metrics/histogram.h"
|
| #include "base/pickle.h"
|
| #include "base/stringprintf.h"
|
| #include "base/string_number_conversions.h"
|
| @@ -19,6 +20,10 @@ using base::TimeTicks;
|
| namespace net {
|
|
|
| namespace {
|
| +
|
| +using base::Histogram;
|
| +using base::StatisticsRecorder;
|
| +
|
| class MockURLRequestThrottlerManager;
|
|
|
| class MockBackoffEntry : public BackoffEntry {
|
| @@ -29,7 +34,7 @@ class MockBackoffEntry : public BackoffEntry {
|
|
|
| virtual ~MockBackoffEntry() {}
|
|
|
| - TimeTicks GetTimeNow() const {
|
| + virtual TimeTicks ImplGetTimeNow() const OVERRIDE {
|
| return fake_now_;
|
| }
|
|
|
| @@ -45,7 +50,7 @@ class MockURLRequestThrottlerEntry : public URLRequestThrottlerEntry {
|
| public :
|
| explicit MockURLRequestThrottlerEntry(
|
| net::URLRequestThrottlerManager* manager)
|
| - : net::URLRequestThrottlerEntry(manager),
|
| + : net::URLRequestThrottlerEntry(manager, ""),
|
| mock_backoff_entry_(&backoff_policy_) {
|
| InitPolicy();
|
| }
|
| @@ -54,7 +59,7 @@ class MockURLRequestThrottlerEntry : public URLRequestThrottlerEntry {
|
| const TimeTicks& exponential_backoff_release_time,
|
| const TimeTicks& sliding_window_release_time,
|
| const TimeTicks& fake_now)
|
| - : net::URLRequestThrottlerEntry(manager),
|
| + : net::URLRequestThrottlerEntry(manager, ""),
|
| fake_time_now_(fake_now),
|
| mock_backoff_entry_(&backoff_policy_) {
|
| InitPolicy();
|
| @@ -86,13 +91,13 @@ class MockURLRequestThrottlerEntry : public URLRequestThrottlerEntry {
|
| fake_time_now_ = time_now;
|
| mock_backoff_entry_.SetFakeNow(time_now);
|
|
|
| - GetBackoffEntry()->InformOfRequest(true); // Sets failure count to 0.
|
| + GetBackoffEntry()->Reset();
|
| GetBackoffEntry()->SetCustomReleaseTime(time_now);
|
| set_sliding_window_release_time(time_now);
|
| }
|
|
|
| // Overridden for tests.
|
| - virtual TimeTicks GetTimeNow() const { return fake_time_now_; }
|
| + virtual TimeTicks ImplGetTimeNow() const OVERRIDE { return fake_time_now_; }
|
|
|
| void set_exponential_backoff_release_time(
|
| const base::TimeTicks& release_time) {
|
| @@ -219,15 +224,66 @@ struct GurlAndString {
|
| class URLRequestThrottlerEntryTest : public testing::Test {
|
| protected:
|
| virtual void SetUp();
|
| +
|
| + // After calling this function, histogram snapshots in |samples_| contain
|
| + // only the delta caused by the test case currently running.
|
| + void CalculateHistogramDeltas();
|
| +
|
| TimeTicks now_;
|
| MockURLRequestThrottlerManager manager_; // Dummy object, not used.
|
| scoped_refptr<MockURLRequestThrottlerEntry> entry_;
|
| +
|
| + std::map<std::string, Histogram::SampleSet> original_samples_;
|
| + std::map<std::string, Histogram::SampleSet> samples_;
|
| +};
|
| +
|
| +// List of all histograms we care about in these unit tests.
|
| +const char* kHistogramNames[] = {
|
| + "Throttling.CustomRetryAfterMs",
|
| + "Throttling.FailureCountAtSuccess",
|
| + "Throttling.HttpResponseCode",
|
| + "Throttling.PerceivedDowntime",
|
| + "Throttling.RequestThrottled",
|
| + "Throttling.SiteOptedOut",
|
| };
|
|
|
| void URLRequestThrottlerEntryTest::SetUp() {
|
| now_ = TimeTicks::Now();
|
| entry_ = new MockURLRequestThrottlerEntry(&manager_);
|
| entry_->ResetToBlank(now_);
|
| +
|
| + for (size_t i = 0; i < arraysize(kHistogramNames); ++i) {
|
| + // Must retrieve original samples for each histogram for comparison
|
| + // as other tests may affect them.
|
| + const char* name = kHistogramNames[i];
|
| + Histogram::SampleSet& original = original_samples_[name];
|
| + Histogram* histogram;
|
| + if (StatisticsRecorder::FindHistogram(name, &histogram)) {
|
| + histogram->SnapshotSample(&original);
|
| + }
|
| + }
|
| +}
|
| +
|
| +void URLRequestThrottlerEntryTest::CalculateHistogramDeltas() {
|
| + for (size_t i = 0; i < arraysize(kHistogramNames); ++i) {
|
| + const char* name = kHistogramNames[i];
|
| + Histogram::SampleSet& original = original_samples_[name];
|
| + Histogram::SampleSet& sample = samples_[name];
|
| +
|
| + Histogram* histogram;
|
| + if (StatisticsRecorder::FindHistogram(name, &histogram)) {
|
| + ASSERT_EQ(Histogram::kUmaTargetedHistogramFlag, histogram->flags());
|
| +
|
| + histogram->SnapshotSample(&sample);
|
| + // Ensure |original| size is same as |sample|, then subtract original
|
| + // values.
|
| + original.Resize(*histogram);
|
| + sample.Subtract(original);
|
| + }
|
| + }
|
| +
|
| + // Ensure we don't accidentally use the originals in our tests.
|
| + original_samples_.clear();
|
| }
|
|
|
| std::ostream& operator<<(std::ostream& out, const base::TimeTicks& time) {
|
| @@ -238,6 +294,10 @@ TEST_F(URLRequestThrottlerEntryTest, InterfaceDuringExponentialBackoff) {
|
| entry_->set_exponential_backoff_release_time(
|
| entry_->fake_time_now_ + TimeDelta::FromMilliseconds(1));
|
| EXPECT_TRUE(entry_->IsDuringExponentialBackoff());
|
| +
|
| + CalculateHistogramDeltas();
|
| + ASSERT_EQ(0, samples_["Throttling.RequestThrottled"].counts(0));
|
| + ASSERT_EQ(1, samples_["Throttling.RequestThrottled"].counts(1));
|
| }
|
|
|
| TEST_F(URLRequestThrottlerEntryTest, InterfaceNotDuringExponentialBackoff) {
|
| @@ -246,6 +306,10 @@ TEST_F(URLRequestThrottlerEntryTest, InterfaceNotDuringExponentialBackoff) {
|
| entry_->set_exponential_backoff_release_time(
|
| entry_->fake_time_now_ - TimeDelta::FromMilliseconds(1));
|
| EXPECT_FALSE(entry_->IsDuringExponentialBackoff());
|
| +
|
| + CalculateHistogramDeltas();
|
| + ASSERT_EQ(2, samples_["Throttling.RequestThrottled"].counts(0));
|
| + ASSERT_EQ(0, samples_["Throttling.RequestThrottled"].counts(1));
|
| }
|
|
|
| TEST_F(URLRequestThrottlerEntryTest, InterfaceUpdateRetryAfter) {
|
| @@ -258,13 +322,18 @@ TEST_F(URLRequestThrottlerEntryTest, InterfaceUpdateRetryAfter) {
|
| "increase release_time";
|
|
|
| entry_->ResetToBlank(now_);
|
| - header_w_delay_header.fake_retry_value_ = "-5.5";
|
| + MockURLRequestThrottlerHeaderAdapter header_w_negative_header(
|
| + "-5.5", "", 200);
|
| + entry_->UpdateWithResponse("", &header_w_negative_header);
|
| EXPECT_EQ(entry_->GetExponentialBackoffReleaseTime(), entry_->fake_time_now_)
|
| << "When given a negative value, it should not change the release_time";
|
| +
|
| + CalculateHistogramDeltas();
|
| + ASSERT_EQ(1, samples_["Throttling.CustomRetryAfterMs"].TotalCount());
|
| }
|
|
|
| TEST_F(URLRequestThrottlerEntryTest, InterfaceUpdateFailure) {
|
| - MockURLRequestThrottlerHeaderAdapter failure_response(505);
|
| + MockURLRequestThrottlerHeaderAdapter failure_response(503);
|
| entry_->UpdateWithResponse("", &failure_response);
|
| EXPECT_GT(entry_->GetExponentialBackoffReleaseTime(), entry_->fake_time_now_)
|
| << "A failure should increase the release_time";
|
| @@ -278,12 +347,19 @@ TEST_F(URLRequestThrottlerEntryTest, InterfaceUpdateSuccess) {
|
| }
|
|
|
| TEST_F(URLRequestThrottlerEntryTest, InterfaceUpdateSuccessThenFailure) {
|
| - MockURLRequestThrottlerHeaderAdapter failure_response(500);
|
| + MockURLRequestThrottlerHeaderAdapter failure_response(503);
|
| MockURLRequestThrottlerHeaderAdapter success_response(200);
|
| entry_->UpdateWithResponse("", &success_response);
|
| entry_->UpdateWithResponse("", &failure_response);
|
| EXPECT_GT(entry_->GetExponentialBackoffReleaseTime(), entry_->fake_time_now_)
|
| << "This scenario should add delay";
|
| + entry_->UpdateWithResponse("", &success_response);
|
| +
|
| + CalculateHistogramDeltas();
|
| + ASSERT_EQ(1, samples_["Throttling.HttpResponseCode"].counts(503));
|
| + ASSERT_EQ(2, samples_["Throttling.HttpResponseCode"].counts(200));
|
| + ASSERT_EQ(1, samples_["Throttling.FailureCountAtSuccess"].counts(1));
|
| + ASSERT_EQ(1, samples_["Throttling.PerceivedDowntime"].TotalCount());
|
| }
|
|
|
| TEST_F(URLRequestThrottlerEntryTest, IsEntryReallyOutdated) {
|
| @@ -308,7 +384,7 @@ TEST_F(URLRequestThrottlerEntryTest, IsEntryReallyOutdated) {
|
|
|
| TEST_F(URLRequestThrottlerEntryTest, MaxAllowedBackoff) {
|
| for (int i = 0; i < 30; ++i) {
|
| - MockURLRequestThrottlerHeaderAdapter response_adapter(505);
|
| + MockURLRequestThrottlerHeaderAdapter response_adapter(503);
|
| entry_->UpdateWithResponse("", &response_adapter);
|
| }
|
|
|
| @@ -318,7 +394,7 @@ TEST_F(URLRequestThrottlerEntryTest, MaxAllowedBackoff) {
|
| }
|
|
|
| TEST_F(URLRequestThrottlerEntryTest, MalformedContent) {
|
| - MockURLRequestThrottlerHeaderAdapter response_adapter(505);
|
| + MockURLRequestThrottlerHeaderAdapter response_adapter(503);
|
| for (int i = 0; i < 5; ++i)
|
| entry_->UpdateWithResponse("", &response_adapter);
|
|
|
| @@ -329,7 +405,7 @@ TEST_F(URLRequestThrottlerEntryTest, MalformedContent) {
|
| // UpdateWithResponse to pair with ReceivedContentWasMalformed() since that
|
| // is what happens in practice (if a body is received, then a non-500
|
| // response must also have been received).
|
| - entry_->ReceivedContentWasMalformed();
|
| + entry_->ReceivedContentWasMalformed(200);
|
| MockURLRequestThrottlerHeaderAdapter success_adapter(200);
|
| entry_->UpdateWithResponse("", &success_adapter);
|
| EXPECT_GT(entry_->GetExponentialBackoffReleaseTime(), release_after_failures);
|
| @@ -386,6 +462,9 @@ TEST(URLRequestThrottlerManager, IsUrlStandardised) {
|
| GurlAndString(GURL("http://www.example.com/index.php?code=1#superEntry"),
|
| std::string("http://www.example.com/index.php"),
|
| __LINE__),
|
| + GurlAndString(GURL("http://www.example.com/index.php#superEntry"),
|
| + std::string("http://www.example.com/index.php"),
|
| + __LINE__),
|
| GurlAndString(GURL("http://www.example.com:1234/"),
|
| std::string("http://www.example.com:1234/"),
|
| __LINE__)};
|
| @@ -485,4 +564,36 @@ TEST(URLRequestThrottlerManager, OptOutHeader) {
|
| ExpectEntryAllowsAllOnErrorIfOptedOut(localhost_entry, true);
|
| }
|
|
|
| +TEST(URLRequestThrottlerManager, ClearOnNetworkChange) {
|
| + for (int i = 0; i < 3; ++i) {
|
| + MockURLRequestThrottlerManager manager;
|
| + scoped_refptr<net::URLRequestThrottlerEntryInterface> entry_before =
|
| + manager.RegisterRequestUrl(GURL("http://www.example.com/"));
|
| + MockURLRequestThrottlerHeaderAdapter failure_adapter(503);
|
| + for (int j = 0; j < 10; ++j) {
|
| + // Host doesn't really matter in this scenario so we skip it.
|
| + entry_before->UpdateWithResponse("", &failure_adapter);
|
| + }
|
| + EXPECT_TRUE(entry_before->IsDuringExponentialBackoff());
|
| +
|
| + switch (i) {
|
| + case 0:
|
| + manager.OnIPAddressChanged();
|
| + break;
|
| + case 1:
|
| + manager.OnOnlineStateChanged(true);
|
| + break;
|
| + case 2:
|
| + manager.OnOnlineStateChanged(false);
|
| + break;
|
| + default:
|
| + FAIL();
|
| + }
|
| +
|
| + scoped_refptr<net::URLRequestThrottlerEntryInterface> entry_after =
|
| + manager.RegisterRequestUrl(GURL("http://www.example.com/"));
|
| + EXPECT_FALSE(entry_after->IsDuringExponentialBackoff());
|
| + }
|
| +}
|
| +
|
| } // namespace net
|
|
|