Chromium Code Reviews| Index: net/http/broken_alternative_services_unittest.cc |
| diff --git a/net/http/broken_alternative_services_unittest.cc b/net/http/broken_alternative_services_unittest.cc |
| new file mode 100644 |
| index 0000000000000000000000000000000000000000..70131164ceb64cb80d00ebeb446822c89e6ff5ce |
| --- /dev/null |
| +++ b/net/http/broken_alternative_services_unittest.cc |
| @@ -0,0 +1,269 @@ |
| +// Copyright (c) 2017 The Chromium Authors. All rights reserved. |
| +// Use of this source code is governed by a BSD-style license that can be |
| +// found in the LICENSE file. |
| + |
| +#include "net/http/broken_alternative_services.h" |
| + |
| +#include <algorithm> |
| +#include <vector> |
| + |
| +#include "base/test/test_mock_time_task_runner.h" |
| +#include "base/time/tick_clock.h" |
| +#include "testing/gtest/include/gtest/gtest.h" |
| + |
| +namespace net { |
| + |
| +namespace { |
| + |
| +const base::TimeDelta BROKEN_ALT_SVC_EXPIRE_DELAYS[10] = { |
| + base::TimeDelta::FromMinutes(5), base::TimeDelta::FromMinutes(10), |
| + base::TimeDelta::FromMinutes(20), base::TimeDelta::FromMinutes(40), |
| + base::TimeDelta::FromMinutes(80), base::TimeDelta::FromMinutes(160), |
| + base::TimeDelta::FromMinutes(320), base::TimeDelta::FromMinutes(640), |
| + base::TimeDelta::FromMinutes(1280), base::TimeDelta::FromMinutes(2560)}; |
| + |
| +class BrokenAlternativeServicesTest |
| + : public BrokenAlternativeServices::Delegate, |
| + public ::testing::Test { |
| + public: |
| + BrokenAlternativeServicesTest() |
| + : test_task_runner_(new base::TestMockTimeTaskRunner()), |
| + test_task_runner_context_(test_task_runner_), |
| + broken_services_clock_(test_task_runner_->GetMockTickClock()), |
| + broken_services_(this, broken_services_clock_.get()) {} |
| + |
| + // BrokenAlternativeServices::Delegate implementation |
| + void OnExpireBrokenAlternativeService( |
| + const AlternativeService& expired_alternative_service) override { |
| + expired_alt_svcs_.push_back(expired_alternative_service); |
| + } |
| + |
| + // All tests will run inside the scope of |test_task_runner_context_|, which |
| + // means any task posted to the main message loop will run on |
| + // |test_task_runner_|. |
|
Ryan Hamilton
2017/05/30 21:32:28
nice comment!
wangyix1
2017/05/30 23:57:49
Acknowledged.
|
| + scoped_refptr<base::TestMockTimeTaskRunner> test_task_runner_; |
| + base::TestMockTimeTaskRunner::ScopedContext test_task_runner_context_; |
| + |
| + std::unique_ptr<base::TickClock> broken_services_clock_; |
| + BrokenAlternativeServices broken_services_; |
| + |
| + std::vector<AlternativeService> expired_alt_svcs_; |
| +}; |
| + |
| +TEST_F(BrokenAlternativeServicesTest, MarkBroken) { |
| + const AlternativeService alternative_service1(kProtoHTTP2, "foo", 443); |
| + const AlternativeService alternative_service2(kProtoHTTP2, "foo", 1234); |
| + |
| + EXPECT_FALSE( |
| + broken_services_.IsAlternativeServiceBroken(alternative_service1)); |
| + EXPECT_FALSE( |
| + broken_services_.IsAlternativeServiceBroken(alternative_service2)); |
| + |
| + broken_services_.MarkAlternativeServiceBroken(alternative_service1); |
| + |
| + EXPECT_TRUE( |
| + broken_services_.IsAlternativeServiceBroken(alternative_service1)); |
| + EXPECT_FALSE( |
| + broken_services_.IsAlternativeServiceBroken(alternative_service2)); |
| + |
| + broken_services_.MarkAlternativeServiceBroken(alternative_service2); |
| + |
| + EXPECT_TRUE( |
| + broken_services_.IsAlternativeServiceBroken(alternative_service1)); |
| + EXPECT_TRUE( |
| + broken_services_.IsAlternativeServiceBroken(alternative_service2)); |
| + |
| + broken_services_.ConfirmAlternativeService(alternative_service1); |
| + |
| + EXPECT_FALSE( |
| + broken_services_.IsAlternativeServiceBroken(alternative_service1)); |
| + EXPECT_TRUE( |
| + broken_services_.IsAlternativeServiceBroken(alternative_service2)); |
| + |
| + broken_services_.ConfirmAlternativeService(alternative_service2); |
| + |
| + EXPECT_FALSE( |
| + broken_services_.IsAlternativeServiceBroken(alternative_service1)); |
| + EXPECT_FALSE( |
| + broken_services_.IsAlternativeServiceBroken(alternative_service2)); |
| + |
| + EXPECT_EQ(0u, expired_alt_svcs_.size()); |
| +} |
| + |
| +TEST_F(BrokenAlternativeServicesTest, MarkRecentlyBroken) { |
| + const AlternativeService alternative_service(kProtoHTTP2, "foo", 443); |
| + |
| + EXPECT_FALSE( |
| + broken_services_.IsAlternativeServiceBroken(alternative_service)); |
| + EXPECT_FALSE(broken_services_.WasAlternativeServiceRecentlyBroken( |
| + alternative_service)); |
| + |
| + broken_services_.MarkAlternativeServiceRecentlyBroken(alternative_service); |
| + EXPECT_FALSE( |
| + broken_services_.IsAlternativeServiceBroken(alternative_service)); |
| + EXPECT_TRUE(broken_services_.WasAlternativeServiceRecentlyBroken( |
| + alternative_service)); |
| + |
| + broken_services_.ConfirmAlternativeService(alternative_service); |
| + EXPECT_FALSE( |
| + broken_services_.IsAlternativeServiceBroken(alternative_service)); |
| + EXPECT_FALSE(broken_services_.WasAlternativeServiceRecentlyBroken( |
| + alternative_service)); |
| +} |
| + |
| +TEST_F(BrokenAlternativeServicesTest, ExpireBrokenAlternateProtocolMappings) { |
| + AlternativeService alternative_service(kProtoQUIC, "foo", 443); |
| + |
| + broken_services_.MarkAlternativeServiceBroken(alternative_service); |
| + |
| + // |broken_services_| should have posted task to expire the brokenness of |
| + // |alternative_service|. |
| + EXPECT_EQ(1u, test_task_runner_->GetPendingTaskCount()); |
| + |
| + // Advance time until one time quantum before |alternative_service1|'s |
| + // brokenness expires |
| + test_task_runner_->FastForwardBy(base::TimeDelta::FromMinutes(5) - |
| + base::TimeDelta::FromInternalValue(1)); |
| + |
| + // Ensure |alternative_service| is still marked broken. |
| + EXPECT_TRUE(broken_services_.IsAlternativeServiceBroken(alternative_service)); |
| + EXPECT_EQ(0u, expired_alt_svcs_.size()); |
| + EXPECT_EQ(1u, test_task_runner_->GetPendingTaskCount()); |
| + |
| + // Advance time by one time quantum |
| + test_task_runner_->FastForwardBy(base::TimeDelta::FromInternalValue(1)); |
| + |
| + // Ensure |alternative_service| brokenness has expired but is still |
| + // considered recently broken |
| + EXPECT_FALSE( |
| + broken_services_.IsAlternativeServiceBroken(alternative_service)); |
| + EXPECT_FALSE(test_task_runner_->HasPendingTask()); |
| + EXPECT_EQ(1u, expired_alt_svcs_.size()); |
| + EXPECT_EQ(alternative_service, expired_alt_svcs_[0]); |
| + EXPECT_TRUE(broken_services_.WasAlternativeServiceRecentlyBroken( |
| + alternative_service)); |
| +} |
| + |
| +TEST_F(BrokenAlternativeServicesTest, ExponentialBackoff) { |
| + // Tests the exponential backoff of the computed expiration delay when an |
| + // alt svc is marked broken. After being marked broken 10 times, the max |
| + // expiration delay will have been reached and exponential backoff will no |
| + // longer apply. |
| + |
| + AlternativeService alternative_service(kProtoQUIC, "foo", 443); |
| + |
| + for (int i = 0; i < 11; ++i) { |
| + broken_services_.MarkAlternativeServiceBroken(alternative_service); |
| + |
| + // Advance time until one time quantum before |alternative_service1|'s |
| + // brokenness expires |
| + test_task_runner_->FastForwardBy( |
| + BROKEN_ALT_SVC_EXPIRE_DELAYS[std::min(i, 9)] - |
| + base::TimeDelta::FromInternalValue(1)); |
| + |
| + EXPECT_TRUE( |
| + broken_services_.IsAlternativeServiceBroken(alternative_service)); |
| + |
| + // Advance time by one time quantum. |alternative_service| should no longer |
| + // be broken. |
| + test_task_runner_->FastForwardBy(base::TimeDelta::FromInternalValue(1)); |
| + |
| + EXPECT_FALSE( |
| + broken_services_.IsAlternativeServiceBroken(alternative_service)); |
| + } |
| +} |
| + |
| +TEST_F(BrokenAlternativeServicesTest, RemoveExpiredBrokenAltSvc) { |
| + // This test will mark broken an alternative service A that has already been |
| + // marked broken many times, then immediately mark another alternative service |
| + // B as broken for the first time. Because A's been marked broken many times |
| + // already, its brokenness will be scheduled to expire much further in the |
| + // future than B, even though it was marked broken before B. This test makes |
| + // sure that even though A was marked broken before B, B's brokenness should |
| + // expire before A. |
| + |
| + AlternativeService alternative_service1(kProtoQUIC, "foo", 443); |
| + AlternativeService alternative_service2(kProtoQUIC, "bar", 443); |
| + |
| + // Repeately mark |alternative_service1| broken and let brokenness expire. |
| + // Do this a few times. |
| + for (int i = 0; i < 3; ++i) { |
| + broken_services_.MarkAlternativeServiceBroken(alternative_service1); |
| + |
| + // |broken_services_| should have posted task to expire the brokenness of |
| + // |alternative_service|. |
| + EXPECT_EQ(1u, test_task_runner_->GetPendingTaskCount()); |
| + |
| + // Advance time by just enough so that |alternative_service|'s brokenness |
| + // expires. |
| + test_task_runner_->FastForwardBy(BROKEN_ALT_SVC_EXPIRE_DELAYS[i]); |
| + |
| + // Ensure |broken_services_| notifies the delegate of expired broken alt |
| + // svcs. |
| + EXPECT_EQ(i + 1, (int)expired_alt_svcs_.size()); |
| + EXPECT_EQ(alternative_service1, expired_alt_svcs_[i]); |
| + } |
| + expired_alt_svcs_.clear(); |
| + |
| + // Mark |alternative_service1| broken (will be given longer expiration delay), |
| + // then mark |alternative_service2| broken (will be given shorter expiration |
| + // delay). |
| + broken_services_.MarkAlternativeServiceBroken(alternative_service1); |
| + broken_services_.MarkAlternativeServiceBroken(alternative_service2); |
| + |
| + EXPECT_TRUE( |
| + broken_services_.IsAlternativeServiceBroken(alternative_service1)); |
| + EXPECT_TRUE( |
| + broken_services_.IsAlternativeServiceBroken(alternative_service2)); |
| + |
| + // Advance time until one time quantum before |alternative_service2|'s |
| + // brokenness expires. |
| + test_task_runner_->FastForwardBy(BROKEN_ALT_SVC_EXPIRE_DELAYS[0] - |
| + base::TimeDelta::FromInternalValue(1)); |
| + |
| + EXPECT_TRUE( |
| + broken_services_.IsAlternativeServiceBroken(alternative_service1)); |
| + EXPECT_TRUE( |
| + broken_services_.IsAlternativeServiceBroken(alternative_service2)); |
| + EXPECT_EQ(0u, expired_alt_svcs_.size()); |
| + |
| + // Advance time by one time quantum. |alternative_service2| should no longer |
| + // be broken. |
| + test_task_runner_->FastForwardBy(base::TimeDelta::FromInternalValue(1)); |
| + |
| + EXPECT_TRUE( |
| + broken_services_.IsAlternativeServiceBroken(alternative_service1)); |
| + EXPECT_FALSE( |
| + broken_services_.IsAlternativeServiceBroken(alternative_service2)); |
| + EXPECT_EQ(1u, expired_alt_svcs_.size()); |
| + EXPECT_EQ(alternative_service2, expired_alt_svcs_[0]); |
| + |
| + // Advance time until one time quantum before |alternative_service1|'s |
| + // brokenness expires |
| + test_task_runner_->FastForwardBy(BROKEN_ALT_SVC_EXPIRE_DELAYS[3] - |
| + BROKEN_ALT_SVC_EXPIRE_DELAYS[0] - |
| + base::TimeDelta::FromInternalValue(1)); |
| + |
| + EXPECT_TRUE( |
| + broken_services_.IsAlternativeServiceBroken(alternative_service1)); |
| + EXPECT_FALSE( |
| + broken_services_.IsAlternativeServiceBroken(alternative_service2)); |
| + EXPECT_EQ(1u, expired_alt_svcs_.size()); |
| + EXPECT_EQ(alternative_service2, expired_alt_svcs_[0]); |
| + |
| + // Advance time by one time quantum. |alternative_service1| should no longer |
| + // be broken. |
| + test_task_runner_->FastForwardBy(base::TimeDelta::FromInternalValue(1)); |
| + |
| + EXPECT_FALSE( |
| + broken_services_.IsAlternativeServiceBroken(alternative_service1)); |
| + EXPECT_FALSE( |
| + broken_services_.IsAlternativeServiceBroken(alternative_service2)); |
| + EXPECT_EQ(2u, expired_alt_svcs_.size()); |
| + EXPECT_EQ(alternative_service2, expired_alt_svcs_[0]); |
| + EXPECT_EQ(alternative_service1, expired_alt_svcs_[1]); |
| +} |
| + |
| +} // namespace |
| + |
| +} // namespace net |