Chromium Code Reviews| Index: net/base/network_quality_estimator_unittest.cc |
| diff --git a/net/base/network_quality_estimator_unittest.cc b/net/base/network_quality_estimator_unittest.cc |
| index b1ffdebaeb58e378ad6806ba6c2028f26ae2a33a..3a41448a7d48d48a8732754490738668ff780314 100644 |
| --- a/net/base/network_quality_estimator_unittest.cc |
| +++ b/net/base/network_quality_estimator_unittest.cc |
| @@ -10,6 +10,7 @@ |
| #include <map> |
| #include "base/basictypes.h" |
| +#include "base/files/file_path.h" |
| #include "base/logging.h" |
| #include "base/memory/scoped_ptr.h" |
| #include "base/metrics/histogram_samples.h" |
| @@ -21,7 +22,10 @@ |
| #include "net/base/external_estimate_provider.h" |
| #include "net/base/load_flags.h" |
| #include "net/base/network_change_notifier.h" |
| +#include "net/http/http_status_code.h" |
| #include "net/test/embedded_test_server/embedded_test_server.h" |
| +#include "net/test/embedded_test_server/http_request.h" |
| +#include "net/test/embedded_test_server/http_response.h" |
| #include "net/url_request/url_request_test_util.h" |
| #include "testing/gtest/include/gtest/gtest.h" |
| #include "url/gurl.h" |
| @@ -32,11 +36,25 @@ namespace { |
| class TestNetworkQualityEstimator : public net::NetworkQualityEstimator { |
| public: |
| TestNetworkQualityEstimator( |
| - const std::map<std::string, std::string>& variation_params) |
| - : NetworkQualityEstimator(scoped_ptr<net::ExternalEstimateProvider>(), |
| + const std::map<std::string, std::string>& variation_params, |
| + scoped_ptr<net::ExternalEstimateProvider> external_estimate_provider) |
| + : NetworkQualityEstimator(external_estimate_provider.Pass(), |
| variation_params, |
| true, |
| - true) {} |
| + true) { |
| + // Set up embedded test server. |
| + embedded_test_server_.ServeFilesFromDirectory( |
| + base::FilePath(FILE_PATH_LITERAL("net/data/url_request_unittest"))); |
| + DCHECK(embedded_test_server_.InitializeAndWaitUntilReady()); |
| + embedded_test_server_.RegisterRequestHandler(base::Bind( |
| + &TestNetworkQualityEstimator::HandleRequest, base::Unretained(this))); |
| + } |
| + |
| + explicit TestNetworkQualityEstimator( |
| + const std::map<std::string, std::string>& variation_params) |
| + : TestNetworkQualityEstimator( |
| + variation_params, |
| + scoped_ptr<net::ExternalEstimateProvider>()) {} |
| ~TestNetworkQualityEstimator() override {} |
| @@ -49,6 +67,22 @@ class TestNetworkQualityEstimator : public net::NetworkQualityEstimator { |
| OnConnectionTypeChanged(type); |
| } |
| + // Called by embedded server when a HTTP request is received. |
| + scoped_ptr<net::test_server::HttpResponse> HandleRequest( |
| + const net::test_server::HttpRequest& request) { |
| + scoped_ptr<net::test_server::BasicHttpResponse> http_response( |
| + new net::test_server::BasicHttpResponse()); |
| + http_response->set_code(net::HTTP_OK); |
| + http_response->set_content("hello"); |
| + http_response->set_content_type("text/plain"); |
| + return http_response.Pass(); |
| + } |
| + |
| + // Returns a GURL hosted at embedded test server. |
| + const GURL GetEchoURL() const { |
| + return embedded_test_server_.GetURL("/echo.html"); |
| + } |
| + |
| using NetworkQualityEstimator::ReadCachedNetworkQualityEstimate; |
| using NetworkQualityEstimator::OnConnectionTypeChanged; |
| @@ -62,6 +96,11 @@ class TestNetworkQualityEstimator : public net::NetworkQualityEstimator { |
| net::NetworkChangeNotifier::ConnectionType current_network_type_; |
| std::string current_network_id_; |
| + |
| + // Embedded server used for testing. |
| + net::test_server::EmbeddedTestServer embedded_test_server_; |
| + |
| + DISALLOW_COPY_AND_ASSIGN(TestNetworkQualityEstimator); |
| }; |
| } // namespace |
| @@ -69,11 +108,6 @@ class TestNetworkQualityEstimator : public net::NetworkQualityEstimator { |
| namespace net { |
| TEST(NetworkQualityEstimatorTest, TestKbpsRTTUpdates) { |
| - net::test_server::EmbeddedTestServer embedded_test_server; |
| - embedded_test_server.ServeFilesFromDirectory( |
| - base::FilePath(FILE_PATH_LITERAL("net/data/url_request_unittest"))); |
| - ASSERT_TRUE(embedded_test_server.InitializeAndWaitUntilReady()); |
| - |
| base::HistogramTester histogram_tester; |
| // Enable requests to local host to be used for network quality estimation. |
| std::map<std::string, std::string> variation_params; |
| @@ -86,19 +120,19 @@ TEST(NetworkQualityEstimatorTest, TestKbpsRTTUpdates) { |
| base::TimeTicks(), 100)); |
| TestDelegate test_delegate; |
| - TestURLRequestContext context(false); |
| - |
| - scoped_ptr<URLRequest> request( |
| - context.CreateRequest(embedded_test_server.GetURL("/echo.html"), |
| - DEFAULT_PRIORITY, &test_delegate)); |
| + TestNetworkDelegate network_delegate; // Must outlive URLRequest. |
| + TestURLRequestContext context(true); |
| + context.set_network_quality_estimator(&estimator); |
| + context.set_network_delegate(&network_delegate); |
| + context.Init(); |
| + |
| + scoped_ptr<URLRequest> request(context.CreateRequest( |
| + estimator.GetEchoURL(), DEFAULT_PRIORITY, &test_delegate)); |
| request->SetLoadFlags(request->load_flags() | LOAD_MAIN_FRAME); |
| request->Start(); |
| - |
| base::RunLoop().Run(); |
| // Both RTT and downstream throughput should be updated. |
| - estimator.NotifyHeadersReceived(*request); |
| - estimator.NotifyRequestCompleted(*request); |
| EXPECT_NE(NetworkQualityEstimator::InvalidRTT(), |
| estimator.GetRTTEstimateInternal(base::TimeTicks(), 100)); |
| EXPECT_NE(NetworkQualityEstimator::kInvalidThroughput, |
| @@ -123,8 +157,12 @@ TEST(NetworkQualityEstimatorTest, TestKbpsRTTUpdates) { |
| histogram_tester.ExpectTotalCount("NQE.RatioEstimatedToActualRTT.Unknown", 0); |
| - estimator.NotifyHeadersReceived(*request); |
| - estimator.NotifyRequestCompleted(*request); |
| + scoped_ptr<URLRequest> request2(context.CreateRequest( |
| + estimator.GetEchoURL(), DEFAULT_PRIORITY, &test_delegate)); |
| + request2->SetLoadFlags(request2->load_flags() | LOAD_MAIN_FRAME); |
| + request2->Start(); |
| + base::RunLoop().Run(); |
| + |
| histogram_tester.ExpectTotalCount("NQE.RTTObservations.Unknown", 1); |
| estimator.SimulateNetworkChangeTo( |
| NetworkChangeNotifier::ConnectionType::CONNECTION_WIFI, "test-1"); |
| @@ -166,26 +204,22 @@ TEST(NetworkQualityEstimatorTest, TestKbpsRTTUpdates) { |
| } |
| TEST(NetworkQualityEstimatorTest, StoreObservations) { |
| - net::test_server::EmbeddedTestServer embedded_test_server; |
| - embedded_test_server.ServeFilesFromDirectory( |
| - base::FilePath(FILE_PATH_LITERAL("net/data/url_request_unittest"))); |
| - ASSERT_TRUE(embedded_test_server.InitializeAndWaitUntilReady()); |
| - |
| std::map<std::string, std::string> variation_params; |
| TestNetworkQualityEstimator estimator(variation_params); |
| + |
| TestDelegate test_delegate; |
| - TestURLRequestContext context(false); |
| + TestNetworkDelegate network_delegate; // Must outlive URLRequest. |
| + TestURLRequestContext context(true); |
| + context.set_network_quality_estimator(&estimator); |
| + context.set_network_delegate(&network_delegate); |
| + context.Init(); |
| // Push 10 more observations than the maximum buffer size. |
| for (size_t i = 0; i < estimator.kMaximumObservationsBufferSize + 10U; ++i) { |
| - scoped_ptr<URLRequest> request( |
| - context.CreateRequest(embedded_test_server.GetURL("/echo.html"), |
| - DEFAULT_PRIORITY, &test_delegate)); |
| + scoped_ptr<URLRequest> request(context.CreateRequest( |
| + estimator.GetEchoURL(), DEFAULT_PRIORITY, &test_delegate)); |
| request->Start(); |
| base::RunLoop().Run(); |
| - |
| - estimator.NotifyHeadersReceived(*request); |
| - estimator.NotifyRequestCompleted(*request); |
| } |
| EXPECT_EQ(static_cast<size_t>( |
| @@ -200,10 +234,6 @@ TEST(NetworkQualityEstimatorTest, StoreObservations) { |
| NetworkChangeNotifier::ConnectionType::CONNECTION_WIFI, "test-2"); |
| EXPECT_EQ(0U, estimator.downstream_throughput_kbps_observations_.Size()); |
| EXPECT_EQ(0U, estimator.rtt_msec_observations_.Size()); |
| - |
| - scoped_ptr<URLRequest> request( |
| - context.CreateRequest(embedded_test_server.GetURL("/echo.html"), |
| - DEFAULT_PRIORITY, &test_delegate)); |
| } |
| // Verifies that the percentiles are correctly computed. All observations have |
| @@ -316,11 +346,6 @@ TEST(NetworkQualityEstimatorTest, PercentileDifferentTimestamps) { |
| // throughput and RTT percentiles are checked for correctness by doing simple |
| // verifications. |
| TEST(NetworkQualityEstimatorTest, ComputedPercentiles) { |
| - net::test_server::EmbeddedTestServer embedded_test_server; |
| - embedded_test_server.ServeFilesFromDirectory( |
| - base::FilePath(FILE_PATH_LITERAL("net/data/url_request_unittest"))); |
| - ASSERT_TRUE(embedded_test_server.InitializeAndWaitUntilReady()); |
| - |
| std::map<std::string, std::string> variation_params; |
| TestNetworkQualityEstimator estimator(variation_params); |
| @@ -331,19 +356,18 @@ TEST(NetworkQualityEstimatorTest, ComputedPercentiles) { |
| base::TimeTicks(), 100)); |
| TestDelegate test_delegate; |
| - TestURLRequestContext context(false); |
| + TestNetworkDelegate network_delegate; // Must outlive URLRequest. |
| + TestURLRequestContext context(true); |
| + context.set_network_quality_estimator(&estimator); |
| + context.set_network_delegate(&network_delegate); |
| + context.Init(); |
| // Number of observations are more than the maximum buffer size. |
| for (size_t i = 0; i < estimator.kMaximumObservationsBufferSize + 100U; ++i) { |
| - scoped_ptr<URLRequest> request( |
| - context.CreateRequest(embedded_test_server.GetURL("/echo.html"), |
| - DEFAULT_PRIORITY, &test_delegate)); |
| + scoped_ptr<URLRequest> request(context.CreateRequest( |
| + estimator.GetEchoURL(), DEFAULT_PRIORITY, &test_delegate)); |
| request->Start(); |
| base::RunLoop().Run(); |
| - |
| - // Use different number of bytes to create variation. |
| - estimator.NotifyHeadersReceived(*request); |
| - estimator.NotifyRequestCompleted(*request); |
| } |
| // Verify the percentiles through simple tests. |
| @@ -654,4 +678,268 @@ TEST(NetworkQualityEstimatorTest, TestGetMedianRTTSince) { |
| EXPECT_EQ(100, downstream_throughput_kbps); |
| } |
| +// An external estimate provider that does not have a valid RTT or throughput |
| +// estimate. |
| +class InvalidExternalEstimateProvider : public ExternalEstimateProvider { |
| + public: |
| + InvalidExternalEstimateProvider() : get_rtt_count_(0) {} |
| + ~InvalidExternalEstimateProvider() override {} |
| + |
| + // ExternalEstimateProvider implementation: |
| + bool GetRTT(base::TimeDelta* rtt) const override { |
| + DCHECK(rtt); |
| + get_rtt_count_++; |
| + return false; |
| + } |
| + |
| + // ExternalEstimateProvider implementation: |
| + bool GetDownstreamThroughputKbps( |
| + int32_t* downstream_throughput_kbps) const override { |
| + DCHECK(downstream_throughput_kbps); |
| + return false; |
| + } |
| + |
| + // ExternalEstimateProvider implementation: |
| + bool GetUpstreamThroughputKbps( |
| + int32_t* upstream_throughput_kbps) const override { |
| + // NetworkQualityEstimator does not support upstream throughput. |
| + ADD_FAILURE(); |
| + return false; |
| + } |
| + |
| + // ExternalEstimateProvider implementation: |
| + bool GetTimeSinceLastUpdate( |
| + base::TimeDelta* time_since_last_update) const override { |
| + *time_since_last_update = base::TimeDelta::FromMilliseconds(1); |
| + return true; |
| + } |
| + |
| + // ExternalEstimateProvider implementation: |
| + void SetUpdatedEstimateDelegate(UpdatedEstimateDelegate* delegate) override {} |
| + |
| + // ExternalEstimateProvider implementation: |
| + void Update() const override {} |
| + |
| + size_t get_rtt_count() const { return get_rtt_count_; } |
| + |
| + private: |
| + // Keeps track of number of times different functions were called. |
| + mutable size_t get_rtt_count_; |
| + |
| + DISALLOW_COPY_AND_ASSIGN(InvalidExternalEstimateProvider); |
| +}; |
| + |
| +// Tests if the RTT value from external estimate provider is discarded if the |
| +// external estimate provider is invalid. |
| +TEST(NetworkQualityEstimatorTest, InvalidExternalEstimateProvider) { |
| + InvalidExternalEstimateProvider* invalid_external_estimate_provider = |
| + new InvalidExternalEstimateProvider(); |
| + scoped_ptr<ExternalEstimateProvider> external_estimate_provider( |
| + invalid_external_estimate_provider); |
| + |
| + TestNetworkQualityEstimator estimator(std::map<std::string, std::string>(), |
| + external_estimate_provider.Pass()); |
| + |
| + base::TimeDelta rtt; |
| + int32_t kbps; |
| + EXPECT_EQ(1U, invalid_external_estimate_provider->get_rtt_count()); |
| + EXPECT_FALSE(estimator.GetRTTEstimate(&rtt)); |
| + EXPECT_FALSE(estimator.GetDownlinkThroughputKbpsEstimate(&kbps)); |
| +} |
| + |
| +class TestExternalEstimateProvider : public ExternalEstimateProvider { |
| + public: |
| + TestExternalEstimateProvider(base::TimeDelta rtt, |
| + int32_t downstream_throughput_kbps) |
| + : rtt_(rtt), |
| + downstream_throughput_kbps_(downstream_throughput_kbps), |
| + time_since_last_update_(base::TimeDelta::FromSeconds(1)), |
| + get_time_since_last_update_count_(0), |
| + get_rtt_count_(0), |
| + get_downstream_throughput_kbps_count_(0), |
| + update_count_(0) {} |
| + ~TestExternalEstimateProvider() override {} |
| + |
| + // ExternalEstimateProvider implementation: |
| + bool GetRTT(base::TimeDelta* rtt) const override { |
| + *rtt = rtt_; |
| + get_rtt_count_++; |
| + return true; |
| + } |
| + |
| + // ExternalEstimateProvider implementation: |
| + bool GetDownstreamThroughputKbps( |
| + int32_t* downstream_throughput_kbps) const override { |
| + *downstream_throughput_kbps = downstream_throughput_kbps_; |
| + get_downstream_throughput_kbps_count_++; |
| + return true; |
| + } |
| + |
| + // ExternalEstimateProvider implementation: |
| + bool GetUpstreamThroughputKbps( |
| + int32_t* upstream_throughput_kbps) const override { |
| + // NetworkQualityEstimator does not support upstream throughput. |
| + ADD_FAILURE(); |
| + return false; |
| + } |
| + |
| + // ExternalEstimateProvider implementation: |
| + bool GetTimeSinceLastUpdate( |
| + base::TimeDelta* time_since_last_update) const override { |
| + *time_since_last_update = time_since_last_update_; |
| + get_time_since_last_update_count_++; |
| + return true; |
| + } |
| + |
| + // ExternalEstimateProvider implementation: |
| + void SetUpdatedEstimateDelegate(UpdatedEstimateDelegate* delegate) override {} |
| + |
| + // ExternalEstimateProvider implementation: |
| + void Update() const override { update_count_++; } |
| + |
| + void set_time_since_last_update(base::TimeDelta time_since_last_update) { |
| + time_since_last_update_ = time_since_last_update; |
| + } |
| + |
| + size_t get_time_since_last_update_count() const { |
| + return get_time_since_last_update_count_; |
| + } |
| + size_t get_rtt_count() const { return get_rtt_count_; } |
| + size_t get_downstream_throughput_kbps_count() const { |
| + return get_downstream_throughput_kbps_count_; |
| + } |
| + size_t update_count() const { return update_count_; } |
| + |
| + private: |
| + // RTT and downstream throughput estimates. |
| + const base::TimeDelta rtt_; |
| + const int32_t downstream_throughput_kbps_; |
| + |
| + base::TimeDelta time_since_last_update_; |
| + |
| + // Keeps track of number of times different functions were called. |
| + mutable size_t get_time_since_last_update_count_; |
| + mutable size_t get_rtt_count_; |
| + mutable size_t get_downstream_throughput_kbps_count_; |
| + mutable size_t update_count_; |
| + |
| + DISALLOW_COPY_AND_ASSIGN(TestExternalEstimateProvider); |
| +}; |
| + |
| +// Tests if the external estimate provider is called in the constructor and |
| +// on network change notification. |
| +TEST(NetworkQualityEstimatorTest, TestExternalEstimateProvider) { |
| + TestExternalEstimateProvider* test_external_estimate_provider = |
| + new TestExternalEstimateProvider(base::TimeDelta::FromMilliseconds(1), |
| + 100); |
| + scoped_ptr<ExternalEstimateProvider> external_estimate_provider( |
| + test_external_estimate_provider); |
| + std::map<std::string, std::string> variation_params; |
| + TestNetworkQualityEstimator estimator(variation_params, |
| + external_estimate_provider.Pass()); |
| + |
| + base::TimeDelta rtt; |
| + int32_t kbps; |
| + EXPECT_TRUE(estimator.GetRTTEstimate(&rtt)); |
| + EXPECT_TRUE(estimator.GetDownlinkThroughputKbpsEstimate(&kbps)); |
| + |
| + EXPECT_EQ( |
| + 1U, test_external_estimate_provider->get_time_since_last_update_count()); |
| + EXPECT_EQ(1U, test_external_estimate_provider->get_rtt_count()); |
| + EXPECT_EQ( |
| + 1U, |
| + test_external_estimate_provider->get_downstream_throughput_kbps_count()); |
| + |
| + // Change network type to WiFi. Number of queries to External estimate |
| + // provider must increment. |
| + estimator.SimulateNetworkChangeTo( |
| + NetworkChangeNotifier::ConnectionType::CONNECTION_WIFI, "test-1"); |
| + EXPECT_TRUE(estimator.GetRTTEstimate(&rtt)); |
| + EXPECT_TRUE(estimator.GetDownlinkThroughputKbpsEstimate(&kbps)); |
| + EXPECT_EQ( |
| + 2U, test_external_estimate_provider->get_time_since_last_update_count()); |
| + EXPECT_EQ(2U, test_external_estimate_provider->get_rtt_count()); |
| + EXPECT_EQ( |
| + 2U, |
| + test_external_estimate_provider->get_downstream_throughput_kbps_count()); |
| + |
| + // Change network type to 2G. Number of queries to External estimate provider |
| + // must increment. |
| + estimator.SimulateNetworkChangeTo( |
| + NetworkChangeNotifier::ConnectionType::CONNECTION_2G, "test-1"); |
| + EXPECT_EQ( |
| + 3U, test_external_estimate_provider->get_time_since_last_update_count()); |
| + EXPECT_EQ(3U, test_external_estimate_provider->get_rtt_count()); |
| + EXPECT_EQ( |
| + 3U, |
| + test_external_estimate_provider->get_downstream_throughput_kbps_count()); |
| + |
| + // Set the external estimate as old. Network Quality estimator should request |
| + // an update on connection type change. |
| + EXPECT_EQ(0U, test_external_estimate_provider->update_count()); |
| + test_external_estimate_provider->set_time_since_last_update( |
| + base::TimeDelta::Max()); |
| + |
| + estimator.SimulateNetworkChangeTo( |
| + NetworkChangeNotifier::ConnectionType::CONNECTION_2G, "test-2"); |
| + EXPECT_EQ( |
| + 4U, test_external_estimate_provider->get_time_since_last_update_count()); |
| + EXPECT_EQ(3U, test_external_estimate_provider->get_rtt_count()); |
| + EXPECT_EQ( |
| + 3U, |
| + test_external_estimate_provider->get_downstream_throughput_kbps_count()); |
| + EXPECT_EQ(1U, test_external_estimate_provider->update_count()); |
| + |
| + // Estimates are unavailable because external estimate provider never |
| + // notifies network quality estimator of the updated estimates. |
| + EXPECT_FALSE(estimator.GetRTTEstimate(&rtt)); |
| + EXPECT_FALSE(estimator.GetDownlinkThroughputKbpsEstimate(&kbps)); |
| +} |
| + |
| +// Tests if the estimate from the external estimate provider is merged with the |
| +// observations collected from the HTTP requests. |
| +TEST(NetworkQualityEstimatorTest, TestExternalEstimateProviderMergeEstimates) { |
| + const base::TimeDelta external_estimate_provider_rtt = |
| + base::TimeDelta::FromMilliseconds(1); |
| + const int32_t external_estimate_provider_downstream_throughput = 100; |
| + TestExternalEstimateProvider* test_external_estimate_provider = |
| + new TestExternalEstimateProvider( |
| + external_estimate_provider_rtt, |
| + external_estimate_provider_downstream_throughput); |
| + scoped_ptr<ExternalEstimateProvider> external_estimate_provider( |
| + test_external_estimate_provider); |
| + |
| + std::map<std::string, std::string> variation_params; |
| + TestNetworkQualityEstimator estimator(variation_params, |
| + external_estimate_provider.Pass()); |
| + |
| + base::TimeDelta rtt; |
| + // Estimate provided by network quality estimator should match the estimate |
| + // provided by external estimate provider. |
| + EXPECT_TRUE(estimator.GetRTTEstimate(&rtt)); |
| + EXPECT_EQ(external_estimate_provider_rtt, rtt); |
| + |
| + int32_t kbps; |
| + EXPECT_TRUE(estimator.GetDownlinkThroughputKbpsEstimate(&kbps)); |
| + EXPECT_EQ(external_estimate_provider_downstream_throughput, kbps); |
| + |
| + EXPECT_EQ(1U, estimator.rtt_msec_observations_.Size()); |
| + EXPECT_EQ(1U, estimator.downstream_throughput_kbps_observations_.Size()); |
| + |
| + TestDelegate test_delegate; |
| + TestNetworkDelegate network_delegate; // Must outlive URLRequest. |
|
mmenke
2015/09/15 22:36:53
I don't think we need this?
tbansal1
2015/09/15 22:44:47
Removed it. Seems like it is required for LocalHtt
|
| + TestURLRequestContext context(true); |
| + context.set_network_quality_estimator(&estimator); |
| + context.set_network_delegate(&network_delegate); |
| + context.Init(); |
| + |
| + scoped_ptr<URLRequest> request(context.CreateRequest( |
| + estimator.GetEchoURL(), DEFAULT_PRIORITY, &test_delegate)); |
| + request->Start(); |
| + base::RunLoop().Run(); |
| + |
| + EXPECT_EQ(2U, estimator.rtt_msec_observations_.Size()); |
| + EXPECT_EQ(2U, estimator.downstream_throughput_kbps_observations_.Size()); |
| +} |
| + |
| } // namespace net |