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 |
deleted file mode 100644 |
index d45fcf93cf5b10a13f9e93619d126be1e18abcf6..0000000000000000000000000000000000000000 |
--- a/net/base/network_quality_estimator_unittest.cc |
+++ /dev/null |
@@ -1,1345 +0,0 @@ |
-// Copyright 2015 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/base/network_quality_estimator.h" |
- |
-#include <stddef.h> |
-#include <stdint.h> |
- |
-#include <limits> |
-#include <map> |
-#include <memory> |
-#include <string> |
-#include <utility> |
-#include <vector> |
- |
-#include "base/files/file_path.h" |
-#include "base/logging.h" |
-#include "base/macros.h" |
-#include "base/metrics/histogram_samples.h" |
-#include "base/run_loop.h" |
-#include "base/strings/string_number_conversions.h" |
-#include "base/test/histogram_tester.h" |
-#include "base/time/time.h" |
-#include "build/build_config.h" |
-#include "net/base/external_estimate_provider.h" |
-#include "net/base/load_flags.h" |
-#include "net/base/network_change_notifier.h" |
-#include "net/base/socket_performance_watcher.h" |
-#include "net/base/socket_performance_watcher_factory.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.h" |
-#include "net/url_request/url_request_test_util.h" |
-#include "testing/gtest/include/gtest/gtest.h" |
-#include "url/gurl.h" |
- |
-namespace net { |
- |
-namespace { |
- |
-// Helps in setting the current network type and id. |
-class TestNetworkQualityEstimator : public NetworkQualityEstimator { |
- public: |
- TestNetworkQualityEstimator( |
- const std::map<std::string, std::string>& variation_params, |
- std::unique_ptr<ExternalEstimateProvider> external_estimate_provider) |
- : NetworkQualityEstimator(std::move(external_estimate_provider), |
- variation_params, |
- true, |
- true), |
- url_rtt_set_(false), |
- downlink_throughput_kbps_set_(false) { |
- // Set up embedded test server. |
- embedded_test_server_.ServeFilesFromDirectory( |
- base::FilePath(FILE_PATH_LITERAL("net/data/url_request_unittest"))); |
- EXPECT_TRUE(embedded_test_server_.Start()); |
- 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, |
- std::unique_ptr<ExternalEstimateProvider>()) {} |
- |
- ~TestNetworkQualityEstimator() override {} |
- |
- // Overrides the current network type and id. |
- // Notifies network quality estimator of change in connection. |
- void SimulateNetworkChangeTo(NetworkChangeNotifier::ConnectionType type, |
- std::string network_id) { |
- current_network_type_ = type; |
- current_network_id_ = network_id; |
- OnConnectionTypeChanged(type); |
- } |
- |
- // Called by embedded server when a HTTP request is received. |
- std::unique_ptr<test_server::HttpResponse> HandleRequest( |
- const test_server::HttpRequest& request) { |
- std::unique_ptr<test_server::BasicHttpResponse> http_response( |
- new test_server::BasicHttpResponse()); |
- http_response->set_code(HTTP_OK); |
- http_response->set_content("hello"); |
- http_response->set_content_type("text/plain"); |
- return std::move(http_response); |
- } |
- |
- // Returns a GURL hosted at embedded test server. |
- const GURL GetEchoURL() const { |
- return embedded_test_server_.GetURL("/echo.html"); |
- } |
- |
- void set_url_rtt(const base::TimeDelta& url_rtt) { |
- url_rtt_set_ = true; |
- url_rtt_ = url_rtt; |
- } |
- |
- bool GetURLRequestRTTEstimate(base::TimeDelta* rtt) const override { |
- if (url_rtt_set_) { |
- *rtt = url_rtt_; |
- return true; |
- } |
- return NetworkQualityEstimator::GetURLRequestRTTEstimate(rtt); |
- } |
- |
- void set_downlink_throughput_kbps(int32_t downlink_throughput_kbps) { |
- downlink_throughput_kbps_set_ = true; |
- downlink_throughput_kbps_ = downlink_throughput_kbps; |
- } |
- |
- bool GetDownlinkThroughputKbpsEstimate(int32_t* kbps) const override { |
- if (downlink_throughput_kbps_set_) { |
- *kbps = downlink_throughput_kbps_; |
- return true; |
- } |
- return NetworkQualityEstimator::GetDownlinkThroughputKbpsEstimate(kbps); |
- } |
- |
- using NetworkQualityEstimator::ReadCachedNetworkQualityEstimate; |
- using NetworkQualityEstimator::OnConnectionTypeChanged; |
- |
- private: |
- // NetworkQualityEstimator implementation that returns the overridden network |
- // id (instead of invoking platform APIs). |
- NetworkQualityEstimator::NetworkID GetCurrentNetworkID() const override { |
- return NetworkQualityEstimator::NetworkID(current_network_type_, |
- current_network_id_); |
- } |
- |
- NetworkChangeNotifier::ConnectionType current_network_type_; |
- std::string current_network_id_; |
- |
- bool url_rtt_set_; |
- base::TimeDelta url_rtt_; |
- |
- bool downlink_throughput_kbps_set_; |
- int32_t downlink_throughput_kbps_; |
- |
- // Embedded server used for testing. |
- EmbeddedTestServer embedded_test_server_; |
- |
- DISALLOW_COPY_AND_ASSIGN(TestNetworkQualityEstimator); |
-}; |
- |
-class TestRTTObserver : public NetworkQualityEstimator::RTTObserver { |
- public: |
- struct Observation { |
- Observation(int32_t ms, |
- const base::TimeTicks& ts, |
- NetworkQualityEstimator::ObservationSource src) |
- : rtt_ms(ms), timestamp(ts), source(src) {} |
- int32_t rtt_ms; |
- base::TimeTicks timestamp; |
- NetworkQualityEstimator::ObservationSource source; |
- }; |
- |
- std::vector<Observation>& observations() { return observations_; } |
- |
- // RttObserver implementation: |
- void OnRTTObservation( |
- int32_t rtt_ms, |
- const base::TimeTicks& timestamp, |
- NetworkQualityEstimator::ObservationSource source) override { |
- observations_.push_back(Observation(rtt_ms, timestamp, source)); |
- } |
- |
- private: |
- std::vector<Observation> observations_; |
-}; |
- |
-class TestThroughputObserver |
- : public NetworkQualityEstimator::ThroughputObserver { |
- public: |
- struct Observation { |
- Observation(int32_t kbps, |
- const base::TimeTicks& ts, |
- NetworkQualityEstimator::ObservationSource src) |
- : throughput_kbps(kbps), timestamp(ts), source(src) {} |
- int32_t throughput_kbps; |
- base::TimeTicks timestamp; |
- NetworkQualityEstimator::ObservationSource source; |
- }; |
- |
- std::vector<Observation>& observations() { return observations_; } |
- |
- // ThroughputObserver implementation: |
- void OnThroughputObservation( |
- int32_t throughput_kbps, |
- const base::TimeTicks& timestamp, |
- NetworkQualityEstimator::ObservationSource source) override { |
- observations_.push_back(Observation(throughput_kbps, timestamp, source)); |
- } |
- |
- private: |
- std::vector<Observation> observations_; |
-}; |
- |
-} // namespace |
- |
-TEST(NetworkQualityEstimatorTest, TestKbpsRTTUpdates) { |
- base::HistogramTester histogram_tester; |
- // Enable requests to local host to be used for network quality estimation. |
- std::map<std::string, std::string> variation_params; |
- TestNetworkQualityEstimator estimator(variation_params); |
- |
- base::TimeDelta rtt; |
- int32_t kbps; |
- EXPECT_FALSE(estimator.GetURLRequestRTTEstimate(&rtt)); |
- EXPECT_FALSE(estimator.GetDownlinkThroughputKbpsEstimate(&kbps)); |
- |
- TestDelegate test_delegate; |
- TestURLRequestContext context(true); |
- context.set_network_quality_estimator(&estimator); |
- context.Init(); |
- |
- std::unique_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. |
- EXPECT_TRUE(estimator.GetURLRequestRTTEstimate(&rtt)); |
- EXPECT_TRUE(estimator.GetDownlinkThroughputKbpsEstimate(&kbps)); |
- |
- EXPECT_TRUE(estimator.GetURLRequestRTTEstimate(&rtt)); |
- EXPECT_TRUE(estimator.GetDownlinkThroughputKbpsEstimate(&kbps)); |
- |
- // Check UMA histograms. |
- histogram_tester.ExpectTotalCount("NQE.PeakKbps.Unknown", 0); |
- histogram_tester.ExpectTotalCount("NQE.FastestRTT.Unknown", 0); |
- |
- histogram_tester.ExpectTotalCount("NQE.RatioEstimatedToActualRTT.Unknown", 0); |
- |
- std::unique_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"); |
- histogram_tester.ExpectTotalCount("NQE.PeakKbps.Unknown", 1); |
- histogram_tester.ExpectTotalCount("NQE.FastestRTT.Unknown", 1); |
- |
- histogram_tester.ExpectTotalCount("NQE.RatioMedianRTT.WiFi", 0); |
- |
- histogram_tester.ExpectTotalCount("NQE.RTT.Percentile0.Unknown", 1); |
- histogram_tester.ExpectTotalCount("NQE.RTT.Percentile10.Unknown", 1); |
- histogram_tester.ExpectTotalCount("NQE.RTT.Percentile50.Unknown", 1); |
- histogram_tester.ExpectTotalCount("NQE.RTT.Percentile90.Unknown", 1); |
- histogram_tester.ExpectTotalCount("NQE.RTT.Percentile100.Unknown", 1); |
- |
- EXPECT_FALSE(estimator.GetURLRequestRTTEstimate(&rtt)); |
- EXPECT_FALSE(estimator.GetDownlinkThroughputKbpsEstimate(&kbps)); |
- |
- estimator.SimulateNetworkChangeTo( |
- NetworkChangeNotifier::ConnectionType::CONNECTION_WIFI, std::string()); |
- histogram_tester.ExpectTotalCount("NQE.PeakKbps.Unknown", 1); |
- histogram_tester.ExpectTotalCount("NQE.FastestRTT.Unknown", 1); |
- |
- EXPECT_FALSE(estimator.GetURLRequestRTTEstimate(&rtt)); |
- EXPECT_FALSE(estimator.GetDownlinkThroughputKbpsEstimate(&kbps)); |
-} |
- |
-TEST(NetworkQualityEstimatorTest, StoreObservations) { |
- std::map<std::string, std::string> variation_params; |
- TestNetworkQualityEstimator estimator(variation_params); |
- |
- base::TimeDelta rtt; |
- int32_t kbps; |
- EXPECT_FALSE(estimator.GetURLRequestRTTEstimate(&rtt)); |
- EXPECT_FALSE(estimator.GetDownlinkThroughputKbpsEstimate(&kbps)); |
- |
- TestDelegate test_delegate; |
- TestURLRequestContext context(true); |
- context.set_network_quality_estimator(&estimator); |
- context.Init(); |
- |
- // Push 10 more observations than the maximum buffer size. |
- for (size_t i = 0; i < estimator.kMaximumObservationsBufferSize + 10U; ++i) { |
- std::unique_ptr<URLRequest> request(context.CreateRequest( |
- estimator.GetEchoURL(), DEFAULT_PRIORITY, &test_delegate)); |
- request->Start(); |
- base::RunLoop().Run(); |
- EXPECT_TRUE(estimator.GetURLRequestRTTEstimate(&rtt)); |
- EXPECT_TRUE(estimator.GetDownlinkThroughputKbpsEstimate(&kbps)); |
- } |
- |
- // Verify that the stored observations are cleared on network change. |
- estimator.SimulateNetworkChangeTo( |
- NetworkChangeNotifier::ConnectionType::CONNECTION_WIFI, "test-2"); |
- EXPECT_FALSE(estimator.GetURLRequestRTTEstimate(&rtt)); |
- EXPECT_FALSE(estimator.GetDownlinkThroughputKbpsEstimate(&kbps)); |
-} |
- |
-// Verifies that the percentiles are correctly computed. All observations have |
-// the same timestamp. Kbps percentiles must be in decreasing order. RTT |
-// percentiles must be in increasing order. |
-TEST(NetworkQualityEstimatorTest, PercentileSameTimestamps) { |
- std::map<std::string, std::string> variation_params; |
- TestNetworkQualityEstimator estimator(variation_params); |
- base::TimeTicks now = base::TimeTicks::Now(); |
- |
- // Network quality should be unavailable when no observations are available. |
- base::TimeDelta rtt; |
- EXPECT_FALSE(estimator.GetURLRequestRTTEstimate(&rtt)); |
- int32_t kbps; |
- EXPECT_FALSE(estimator.GetDownlinkThroughputKbpsEstimate(&kbps)); |
- |
- // Insert samples from {1,2,3,..., 100}. First insert odd samples, then even |
- // samples. This helps in verifying that the order of samples does not matter. |
- for (int i = 1; i <= 99; i += 2) { |
- estimator.downstream_throughput_kbps_observations_.AddObservation( |
- NetworkQualityEstimator::ThroughputObservation( |
- i, now, NetworkQualityEstimator::URL_REQUEST)); |
- estimator.rtt_observations_.AddObservation( |
- NetworkQualityEstimator::RttObservation( |
- base::TimeDelta::FromMilliseconds(i), now, |
- NetworkQualityEstimator::URL_REQUEST)); |
- EXPECT_TRUE(estimator.GetURLRequestRTTEstimate(&rtt)); |
- EXPECT_TRUE(estimator.GetDownlinkThroughputKbpsEstimate(&kbps)); |
- } |
- |
- for (int i = 1; i <= 99; i += 2) { |
- // Insert TCP observation which should not be taken into account when |
- // computing median RTT at HTTP layer. |
- estimator.rtt_observations_.AddObservation( |
- NetworkQualityEstimator::RttObservation( |
- base::TimeDelta::FromMilliseconds(10000), now, |
- NetworkQualityEstimator::TCP)); |
- |
- // Insert QUIC observation which should not be taken into account when |
- // computing median RTT at HTTP layer. |
- estimator.rtt_observations_.AddObservation( |
- NetworkQualityEstimator::RttObservation( |
- base::TimeDelta::FromMilliseconds(10000), now, |
- NetworkQualityEstimator::QUIC)); |
- } |
- |
- for (int i = 2; i <= 100; i += 2) { |
- estimator.downstream_throughput_kbps_observations_.AddObservation( |
- NetworkQualityEstimator::ThroughputObservation( |
- i, now, NetworkQualityEstimator::URL_REQUEST)); |
- estimator.rtt_observations_.AddObservation( |
- NetworkQualityEstimator::RttObservation( |
- base::TimeDelta::FromMilliseconds(i), now, |
- NetworkQualityEstimator::URL_REQUEST)); |
- EXPECT_TRUE(estimator.GetURLRequestRTTEstimate(&rtt)); |
- EXPECT_TRUE(estimator.GetDownlinkThroughputKbpsEstimate(&kbps)); |
- } |
- |
- for (int i = 0; i <= 100; ++i) { |
- // Checks if the difference between the two integers is less than 1. This is |
- // required because computed percentiles may be slightly different from |
- // what is expected due to floating point computation errors and integer |
- // rounding off errors. |
- EXPECT_NEAR(estimator.GetDownlinkThroughputKbpsEstimateInternal( |
- base::TimeTicks(), i), |
- 100 - i, 1); |
- std::vector<NetworkQualityEstimator::ObservationSource> |
- disallowed_observation_sources; |
- disallowed_observation_sources.push_back(NetworkQualityEstimator::TCP); |
- disallowed_observation_sources.push_back(NetworkQualityEstimator::QUIC); |
- EXPECT_NEAR(estimator |
- .GetRTTEstimateInternal(disallowed_observation_sources, |
- base::TimeTicks(), i) |
- .InMilliseconds(), |
- i, 1); |
- } |
- |
- EXPECT_TRUE(estimator.GetURLRequestRTTEstimate(&rtt)); |
- EXPECT_TRUE(estimator.GetDownlinkThroughputKbpsEstimate(&kbps)); |
-} |
- |
-// Verifies that the percentiles are correctly computed. Observations have |
-// different timestamps with half the observations being very old and the rest |
-// of them being very recent. Percentiles should factor in recent observations |
-// much more heavily than older samples. Kbps percentiles must be in decreasing |
-// order. RTT percentiles must be in increasing order. |
-TEST(NetworkQualityEstimatorTest, PercentileDifferentTimestamps) { |
- std::map<std::string, std::string> variation_params; |
- TestNetworkQualityEstimator estimator(variation_params); |
- base::TimeTicks now = base::TimeTicks::Now(); |
- base::TimeTicks very_old = now - base::TimeDelta::FromDays(365); |
- |
- // First 50 samples have very old timestamp. |
- for (int i = 1; i <= 50; ++i) { |
- estimator.downstream_throughput_kbps_observations_.AddObservation( |
- NetworkQualityEstimator::ThroughputObservation( |
- i, very_old, NetworkQualityEstimator::URL_REQUEST)); |
- estimator.rtt_observations_.AddObservation( |
- NetworkQualityEstimator::RttObservation( |
- base::TimeDelta::FromMilliseconds(i), very_old, |
- NetworkQualityEstimator::URL_REQUEST)); |
- } |
- |
- // Next 50 (i.e., from 51 to 100) have recent timestamp. |
- for (int i = 51; i <= 100; ++i) { |
- estimator.downstream_throughput_kbps_observations_.AddObservation( |
- NetworkQualityEstimator::ThroughputObservation( |
- i, now, NetworkQualityEstimator::URL_REQUEST)); |
- |
- // Insert TCP observation which should not be taken into account when |
- // computing median RTT at HTTP layer. |
- estimator.rtt_observations_.AddObservation( |
- NetworkQualityEstimator::RttObservation( |
- base::TimeDelta::FromMilliseconds(10000), now, |
- NetworkQualityEstimator::TCP)); |
- |
- estimator.rtt_observations_.AddObservation( |
- NetworkQualityEstimator::RttObservation( |
- base::TimeDelta::FromMilliseconds(i), now, |
- NetworkQualityEstimator::URL_REQUEST)); |
- } |
- |
- std::vector<NetworkQualityEstimator::ObservationSource> |
- disallowed_observation_sources; |
- disallowed_observation_sources.push_back(NetworkQualityEstimator::TCP); |
- disallowed_observation_sources.push_back(NetworkQualityEstimator::QUIC); |
- |
- // Older samples have very little weight. So, all percentiles are >= 51 |
- // (lowest value among recent observations). |
- for (int i = 1; i < 100; ++i) { |
- // Checks if the difference between the two integers is less than 1. This is |
- // required because computed percentiles may be slightly different from |
- // what is expected due to floating point computation errors and integer |
- // rounding off errors. |
- EXPECT_NEAR(estimator.GetDownlinkThroughputKbpsEstimateInternal( |
- base::TimeTicks(), i), |
- 51 + 0.49 * (100 - i), 1); |
- EXPECT_NEAR(estimator |
- .GetRTTEstimateInternal(disallowed_observation_sources, |
- base::TimeTicks(), i) |
- .InMilliseconds(), |
- 51 + 0.49 * i, 1); |
- } |
-} |
- |
-// This test notifies NetworkQualityEstimator of received data. Next, |
-// throughput and RTT percentiles are checked for correctness by doing simple |
-// verifications. |
-TEST(NetworkQualityEstimatorTest, ComputedPercentiles) { |
- std::map<std::string, std::string> variation_params; |
- TestNetworkQualityEstimator estimator(variation_params); |
- |
- std::vector<NetworkQualityEstimator::ObservationSource> |
- disallowed_observation_sources; |
- disallowed_observation_sources.push_back(NetworkQualityEstimator::TCP); |
- disallowed_observation_sources.push_back(NetworkQualityEstimator::QUIC); |
- |
- EXPECT_EQ(NetworkQualityEstimator::InvalidRTT(), |
- estimator.GetRTTEstimateInternal(disallowed_observation_sources, |
- base::TimeTicks(), 100)); |
- EXPECT_EQ(NetworkQualityEstimator::kInvalidThroughput, |
- estimator.GetDownlinkThroughputKbpsEstimateInternal( |
- base::TimeTicks(), 100)); |
- |
- TestDelegate test_delegate; |
- TestURLRequestContext context(true); |
- context.set_network_quality_estimator(&estimator); |
- context.Init(); |
- |
- // Number of observations are more than the maximum buffer size. |
- for (size_t i = 0; i < estimator.kMaximumObservationsBufferSize + 100U; ++i) { |
- std::unique_ptr<URLRequest> request(context.CreateRequest( |
- estimator.GetEchoURL(), DEFAULT_PRIORITY, &test_delegate)); |
- request->Start(); |
- base::RunLoop().Run(); |
- } |
- |
- // Verify the percentiles through simple tests. |
- for (int i = 0; i <= 100; ++i) { |
- EXPECT_GT(estimator.GetDownlinkThroughputKbpsEstimateInternal( |
- base::TimeTicks(), i), |
- 0); |
- EXPECT_LT(estimator.GetRTTEstimateInternal(disallowed_observation_sources, |
- base::TimeTicks(), i), |
- base::TimeDelta::Max()); |
- |
- if (i != 0) { |
- // Throughput percentiles are in decreasing order. |
- EXPECT_LE(estimator.GetDownlinkThroughputKbpsEstimateInternal( |
- base::TimeTicks(), i), |
- estimator.GetDownlinkThroughputKbpsEstimateInternal( |
- base::TimeTicks(), i - 1)); |
- |
- // RTT percentiles are in increasing order. |
- EXPECT_GE(estimator.GetRTTEstimateInternal(disallowed_observation_sources, |
- base::TimeTicks(), i), |
- estimator.GetRTTEstimateInternal(disallowed_observation_sources, |
- base::TimeTicks(), i - 1)); |
- } |
- } |
-} |
- |
-TEST(NetworkQualityEstimatorTest, ObtainOperatingParams) { |
- std::map<std::string, std::string> variation_params; |
- variation_params["Unknown.DefaultMedianKbps"] = "100"; |
- variation_params["WiFi.DefaultMedianKbps"] = "200"; |
- variation_params["2G.DefaultMedianKbps"] = "300"; |
- |
- variation_params["Unknown.DefaultMedianRTTMsec"] = "1000"; |
- variation_params["WiFi.DefaultMedianRTTMsec"] = "2000"; |
- // Negative variation value should not be used. |
- variation_params["2G.DefaultMedianRTTMsec"] = "-5"; |
- |
- TestNetworkQualityEstimator estimator(variation_params); |
- |
- base::TimeDelta rtt; |
- EXPECT_TRUE(estimator.GetURLRequestRTTEstimate(&rtt)); |
- int32_t kbps; |
- EXPECT_TRUE(estimator.GetDownlinkThroughputKbpsEstimate(&kbps)); |
- |
- EXPECT_EQ(100, kbps); |
- EXPECT_EQ(base::TimeDelta::FromMilliseconds(1000), rtt); |
- |
- // Simulate network change to Wi-Fi. |
- estimator.SimulateNetworkChangeTo( |
- NetworkChangeNotifier::ConnectionType::CONNECTION_WIFI, "test-1"); |
- |
- EXPECT_TRUE(estimator.GetURLRequestRTTEstimate(&rtt)); |
- EXPECT_TRUE(estimator.GetDownlinkThroughputKbpsEstimate(&kbps)); |
- EXPECT_EQ(200, kbps); |
- EXPECT_EQ(base::TimeDelta::FromMilliseconds(2000), rtt); |
- |
- // Peak network quality should not be affected by the network quality |
- // estimator field trial. |
- EXPECT_EQ(NetworkQualityEstimator::InvalidRTT(), |
- estimator.peak_network_quality_.rtt()); |
- EXPECT_EQ(NetworkQualityEstimator::kInvalidThroughput, |
- estimator.peak_network_quality_.downstream_throughput_kbps()); |
- |
- // Simulate network change to 2G. Only the Kbps default estimate should be |
- // available. |
- estimator.SimulateNetworkChangeTo( |
- NetworkChangeNotifier::ConnectionType::CONNECTION_2G, "test-2"); |
- |
- EXPECT_FALSE(estimator.GetURLRequestRTTEstimate(&rtt)); |
- EXPECT_TRUE(estimator.GetDownlinkThroughputKbpsEstimate(&kbps)); |
- EXPECT_EQ(300, kbps); |
- |
- // Simulate network change to 3G. Default estimates should be unavailable. |
- estimator.SimulateNetworkChangeTo( |
- NetworkChangeNotifier::ConnectionType::CONNECTION_3G, "test-3"); |
- |
- EXPECT_FALSE(estimator.GetURLRequestRTTEstimate(&rtt)); |
- EXPECT_FALSE(estimator.GetDownlinkThroughputKbpsEstimate(&kbps)); |
-} |
- |
-// Tests that |GetEffectiveConnectionType| returns correct connection type when |
-// no variation params are specified. |
-TEST(NetworkQualityEstimatorTest, ObtainThresholdsNone) { |
- std::map<std::string, std::string> variation_params; |
- |
- TestNetworkQualityEstimator estimator(variation_params); |
- |
- const struct { |
- int32_t rtt_msec; |
- NetworkQualityEstimator::EffectiveConnectionType expected_conn_type; |
- } tests[] = { |
- {5000, NetworkQualityEstimator::EFFECTIVE_CONNECTION_TYPE_BROADBAND}, |
- {20, NetworkQualityEstimator::EFFECTIVE_CONNECTION_TYPE_BROADBAND}, |
- }; |
- |
- for (const auto& test : tests) { |
- estimator.set_url_rtt(base::TimeDelta::FromMilliseconds(test.rtt_msec)); |
- EXPECT_EQ(test.expected_conn_type, estimator.GetEffectiveConnectionType()); |
- } |
-} |
- |
-// Tests that |GetEffectiveConnectionType| returns correct connection type when |
-// only RTT thresholds are specified in the variation params. |
-TEST(NetworkQualityEstimatorTest, ObtainThresholdsOnlyRTT) { |
- std::map<std::string, std::string> variation_params; |
- |
- variation_params["Offline.ThresholdMedianURLRTTMsec"] = "4000"; |
- variation_params["Slow2G.ThresholdMedianURLRTTMsec"] = "2000"; |
- variation_params["2G.ThresholdMedianURLRTTMsec"] = "1000"; |
- variation_params["3G.ThresholdMedianURLRTTMsec"] = "500"; |
- variation_params["4G.ThresholdMedianURLRTTMsec"] = "300"; |
- variation_params["Broadband.ThresholdMedianURLRTTMsec"] = "100"; |
- |
- TestNetworkQualityEstimator estimator(variation_params); |
- |
- const struct { |
- int32_t rtt_msec; |
- NetworkQualityEstimator::EffectiveConnectionType expected_conn_type; |
- } tests[] = { |
- {5000, NetworkQualityEstimator::EFFECTIVE_CONNECTION_TYPE_OFFLINE}, |
- {4000, NetworkQualityEstimator::EFFECTIVE_CONNECTION_TYPE_OFFLINE}, |
- {3000, NetworkQualityEstimator::EFFECTIVE_CONNECTION_TYPE_SLOW_2G}, |
- {2000, NetworkQualityEstimator::EFFECTIVE_CONNECTION_TYPE_SLOW_2G}, |
- {1500, NetworkQualityEstimator::EFFECTIVE_CONNECTION_TYPE_2G}, |
- {1000, NetworkQualityEstimator::EFFECTIVE_CONNECTION_TYPE_2G}, |
- {700, NetworkQualityEstimator::EFFECTIVE_CONNECTION_TYPE_3G}, |
- {500, NetworkQualityEstimator::EFFECTIVE_CONNECTION_TYPE_3G}, |
- {400, NetworkQualityEstimator::EFFECTIVE_CONNECTION_TYPE_4G}, |
- {300, NetworkQualityEstimator::EFFECTIVE_CONNECTION_TYPE_4G}, |
- {200, NetworkQualityEstimator::EFFECTIVE_CONNECTION_TYPE_BROADBAND}, |
- {100, NetworkQualityEstimator::EFFECTIVE_CONNECTION_TYPE_BROADBAND}, |
- {20, NetworkQualityEstimator::EFFECTIVE_CONNECTION_TYPE_BROADBAND}, |
- }; |
- |
- for (const auto& test : tests) { |
- estimator.set_url_rtt(base::TimeDelta::FromMilliseconds(test.rtt_msec)); |
- EXPECT_EQ(test.expected_conn_type, estimator.GetEffectiveConnectionType()); |
- } |
-} |
- |
-// Tests that |GetEffectiveConnectionType| returns correct connection type when |
-// both RTT and throughput thresholds are specified in the variation params. |
-TEST(NetworkQualityEstimatorTest, ObtainThresholdsRTTandThroughput) { |
- std::map<std::string, std::string> variation_params; |
- |
- variation_params["Offline.ThresholdMedianURLRTTMsec"] = "4000"; |
- variation_params["Slow2G.ThresholdMedianURLRTTMsec"] = "2000"; |
- variation_params["2G.ThresholdMedianURLRTTMsec"] = "1000"; |
- variation_params["3G.ThresholdMedianURLRTTMsec"] = "500"; |
- variation_params["4G.ThresholdMedianURLRTTMsec"] = "300"; |
- variation_params["Broadband.ThresholdMedianURLRTTMsec"] = "100"; |
- |
- variation_params["Offline.ThresholdMedianKbps"] = "10"; |
- variation_params["Slow2G.ThresholdMedianKbps"] = "100"; |
- variation_params["2G.ThresholdMedianKbps"] = "300"; |
- variation_params["3G.ThresholdMedianKbps"] = "500"; |
- variation_params["4G.ThresholdMedianKbps"] = "1000"; |
- variation_params["Broadband.ThresholdMedianKbps"] = "2000"; |
- |
- TestNetworkQualityEstimator estimator(variation_params); |
- |
- const struct { |
- int32_t rtt_msec; |
- int32_t downlink_throughput_kbps; |
- NetworkQualityEstimator::EffectiveConnectionType expected_conn_type; |
- } tests[] = { |
- // Set RTT to a very low value to observe the effect of throughput. |
- // Throughout is the bottleneck. |
- {1, 5, NetworkQualityEstimator::EFFECTIVE_CONNECTION_TYPE_OFFLINE}, |
- {1, 10, NetworkQualityEstimator::EFFECTIVE_CONNECTION_TYPE_OFFLINE}, |
- {1, 50, NetworkQualityEstimator::EFFECTIVE_CONNECTION_TYPE_SLOW_2G}, |
- {1, 100, NetworkQualityEstimator::EFFECTIVE_CONNECTION_TYPE_SLOW_2G}, |
- {1, 150, NetworkQualityEstimator::EFFECTIVE_CONNECTION_TYPE_2G}, |
- {1, 300, NetworkQualityEstimator::EFFECTIVE_CONNECTION_TYPE_2G}, |
- {1, 400, NetworkQualityEstimator::EFFECTIVE_CONNECTION_TYPE_3G}, |
- {1, 500, NetworkQualityEstimator::EFFECTIVE_CONNECTION_TYPE_3G}, |
- {1, 700, NetworkQualityEstimator::EFFECTIVE_CONNECTION_TYPE_4G}, |
- {1, 1000, NetworkQualityEstimator::EFFECTIVE_CONNECTION_TYPE_4G}, |
- {1, 1500, NetworkQualityEstimator::EFFECTIVE_CONNECTION_TYPE_BROADBAND}, |
- {1, 2500, NetworkQualityEstimator::EFFECTIVE_CONNECTION_TYPE_BROADBAND}, |
- // Set both RTT and throughput. RTT is the bottleneck. |
- {3000, 25000, NetworkQualityEstimator::EFFECTIVE_CONNECTION_TYPE_SLOW_2G}, |
- {700, 25000, NetworkQualityEstimator::EFFECTIVE_CONNECTION_TYPE_3G}, |
- // Set throughput to an invalid value. |
- {3000, 0, NetworkQualityEstimator::EFFECTIVE_CONNECTION_TYPE_SLOW_2G}, |
- {700, 0, NetworkQualityEstimator::EFFECTIVE_CONNECTION_TYPE_3G}, |
- }; |
- |
- for (const auto& test : tests) { |
- estimator.set_url_rtt(base::TimeDelta::FromMilliseconds(test.rtt_msec)); |
- estimator.set_downlink_throughput_kbps(test.downlink_throughput_kbps); |
- EXPECT_EQ(test.expected_conn_type, estimator.GetEffectiveConnectionType()); |
- } |
-} |
- |
-// Tests if |weight_multiplier_per_second_| is set to correct value for various |
-// values of half life parameter. |
-TEST(NetworkQualityEstimatorTest, HalfLifeParam) { |
- std::map<std::string, std::string> variation_params; |
- |
- const struct { |
- std::string description; |
- std::string variation_params_value; |
- double expected_weight_multiplier; |
- } tests[] = { |
- {"Half life parameter is not set, default value should be used", |
- std::string(), 0.988}, |
- {"Half life parameter is set to negative, default value should be used", |
- "-100", 0.988}, |
- {"Half life parameter is set to zero, default value should be used", "0", |
- 0.988}, |
- {"Half life parameter is set correctly", "10", 0.933}, |
- }; |
- |
- for (const auto& test : tests) { |
- variation_params["HalfLifeSeconds"] = test.variation_params_value; |
- TestNetworkQualityEstimator estimator(variation_params); |
- EXPECT_NEAR(test.expected_weight_multiplier, |
- estimator.weight_multiplier_per_second_, 0.001) |
- << test.description; |
- } |
-} |
- |
-// Test if the network estimates are cached when network change notification |
-// is invoked. |
-TEST(NetworkQualityEstimatorTest, TestCaching) { |
- std::map<std::string, std::string> variation_params; |
- TestNetworkQualityEstimator estimator(variation_params); |
- size_t expected_cache_size = 0; |
- EXPECT_EQ(expected_cache_size, estimator.cached_network_qualities_.size()); |
- |
- // Cache entry will not be added for (NONE, ""). |
- estimator.downstream_throughput_kbps_observations_.AddObservation( |
- NetworkQualityEstimator::ThroughputObservation( |
- 1, base::TimeTicks::Now(), NetworkQualityEstimator::URL_REQUEST)); |
- estimator.rtt_observations_.AddObservation( |
- NetworkQualityEstimator::RttObservation( |
- base::TimeDelta::FromMilliseconds(1000), base::TimeTicks::Now(), |
- NetworkQualityEstimator::URL_REQUEST)); |
- estimator.SimulateNetworkChangeTo( |
- NetworkChangeNotifier::ConnectionType::CONNECTION_2G, "test-1"); |
- EXPECT_EQ(expected_cache_size, estimator.cached_network_qualities_.size()); |
- |
- // Entry will be added for (2G, "test1"). |
- // Also, set the network quality for (2G, "test1") so that it is stored in |
- // the cache. |
- estimator.downstream_throughput_kbps_observations_.AddObservation( |
- NetworkQualityEstimator::ThroughputObservation( |
- 1, base::TimeTicks::Now(), NetworkQualityEstimator::URL_REQUEST)); |
- estimator.rtt_observations_.AddObservation( |
- NetworkQualityEstimator::RttObservation( |
- base::TimeDelta::FromMilliseconds(1000), base::TimeTicks::Now(), |
- NetworkQualityEstimator::URL_REQUEST)); |
- |
- estimator.SimulateNetworkChangeTo( |
- NetworkChangeNotifier::ConnectionType::CONNECTION_3G, "test-1"); |
- ++expected_cache_size; |
- EXPECT_EQ(expected_cache_size, estimator.cached_network_qualities_.size()); |
- |
- // Entry will be added for (3G, "test1"). |
- // Also, set the network quality for (3G, "test1") so that it is stored in |
- // the cache. |
- estimator.downstream_throughput_kbps_observations_.AddObservation( |
- NetworkQualityEstimator::ThroughputObservation( |
- 2, base::TimeTicks::Now(), NetworkQualityEstimator::URL_REQUEST)); |
- estimator.rtt_observations_.AddObservation( |
- NetworkQualityEstimator::RttObservation( |
- base::TimeDelta::FromMilliseconds(500), base::TimeTicks::Now(), |
- NetworkQualityEstimator::URL_REQUEST)); |
- estimator.SimulateNetworkChangeTo( |
- NetworkChangeNotifier::ConnectionType::CONNECTION_3G, "test-2"); |
- ++expected_cache_size; |
- EXPECT_EQ(expected_cache_size, estimator.cached_network_qualities_.size()); |
- |
- // Entry will not be added for (3G, "test2"). |
- estimator.SimulateNetworkChangeTo( |
- NetworkChangeNotifier::ConnectionType::CONNECTION_2G, "test-1"); |
- EXPECT_EQ(expected_cache_size, estimator.cached_network_qualities_.size()); |
- |
- // Read the network quality for (2G, "test-1"). |
- EXPECT_TRUE(estimator.ReadCachedNetworkQualityEstimate()); |
- |
- base::TimeDelta rtt; |
- int32_t kbps; |
- EXPECT_TRUE(estimator.GetURLRequestRTTEstimate(&rtt)); |
- EXPECT_TRUE(estimator.GetDownlinkThroughputKbpsEstimate(&kbps)); |
- EXPECT_EQ(1, kbps); |
- EXPECT_EQ(base::TimeDelta::FromMilliseconds(1000), rtt); |
- // No new entry should be added for (2G, "test-1") since it already exists |
- // in the cache. |
- estimator.SimulateNetworkChangeTo( |
- NetworkChangeNotifier::ConnectionType::CONNECTION_3G, "test-1"); |
- EXPECT_EQ(expected_cache_size, estimator.cached_network_qualities_.size()); |
- |
- // Read the network quality for (3G, "test-1"). |
- EXPECT_TRUE(estimator.ReadCachedNetworkQualityEstimate()); |
- EXPECT_TRUE(estimator.GetURLRequestRTTEstimate(&rtt)); |
- EXPECT_TRUE(estimator.GetDownlinkThroughputKbpsEstimate(&kbps)); |
- EXPECT_EQ(2, kbps); |
- EXPECT_EQ(base::TimeDelta::FromMilliseconds(500), rtt); |
- // No new entry should be added for (3G, "test1") since it already exists |
- // in the cache. |
- estimator.SimulateNetworkChangeTo( |
- NetworkChangeNotifier::ConnectionType::CONNECTION_3G, "test-2"); |
- EXPECT_EQ(expected_cache_size, estimator.cached_network_qualities_.size()); |
- |
- // Reading quality of (3G, "test-2") should return false. |
- EXPECT_FALSE(estimator.ReadCachedNetworkQualityEstimate()); |
- |
- // Reading quality of (2G, "test-3") should return false. |
- estimator.SimulateNetworkChangeTo( |
- NetworkChangeNotifier::ConnectionType::CONNECTION_2G, "test-3"); |
- EXPECT_FALSE(estimator.ReadCachedNetworkQualityEstimate()); |
-} |
- |
-// Tests if the cache size remains bounded. Also, ensure that the cache is |
-// LRU. |
-TEST(NetworkQualityEstimatorTest, TestLRUCacheMaximumSize) { |
- std::map<std::string, std::string> variation_params; |
- TestNetworkQualityEstimator estimator(variation_params); |
- estimator.SimulateNetworkChangeTo( |
- NetworkChangeNotifier::ConnectionType::CONNECTION_WIFI, std::string()); |
- EXPECT_EQ(0U, estimator.cached_network_qualities_.size()); |
- |
- // Add 100 more networks than the maximum size of the cache. |
- size_t network_count = |
- NetworkQualityEstimator::kMaximumNetworkQualityCacheSize + 100; |
- |
- base::TimeTicks update_time_of_network_100; |
- for (size_t i = 0; i < network_count; ++i) { |
- estimator.downstream_throughput_kbps_observations_.AddObservation( |
- NetworkQualityEstimator::ThroughputObservation( |
- 2, base::TimeTicks::Now(), NetworkQualityEstimator::URL_REQUEST)); |
- estimator.rtt_observations_.AddObservation( |
- NetworkQualityEstimator::RttObservation( |
- base::TimeDelta::FromMilliseconds(500), base::TimeTicks::Now(), |
- NetworkQualityEstimator::URL_REQUEST)); |
- |
- if (i == 100) |
- update_time_of_network_100 = base::TimeTicks::Now(); |
- |
- estimator.SimulateNetworkChangeTo( |
- NetworkChangeNotifier::ConnectionType::CONNECTION_WIFI, |
- base::SizeTToString(i)); |
- if (i < NetworkQualityEstimator::kMaximumNetworkQualityCacheSize) |
- EXPECT_EQ(i, estimator.cached_network_qualities_.size()); |
- EXPECT_LE(estimator.cached_network_qualities_.size(), |
- static_cast<size_t>( |
- NetworkQualityEstimator::kMaximumNetworkQualityCacheSize)); |
- } |
- // One more call so that the last network is also written to cache. |
- estimator.downstream_throughput_kbps_observations_.AddObservation( |
- NetworkQualityEstimator::ThroughputObservation( |
- 2, base::TimeTicks::Now(), NetworkQualityEstimator::URL_REQUEST)); |
- estimator.rtt_observations_.AddObservation( |
- NetworkQualityEstimator::RttObservation( |
- base::TimeDelta::FromMilliseconds(500), base::TimeTicks::Now(), |
- NetworkQualityEstimator::URL_REQUEST)); |
- estimator.SimulateNetworkChangeTo( |
- NetworkChangeNotifier::ConnectionType::CONNECTION_WIFI, |
- base::SizeTToString(network_count - 1)); |
- EXPECT_EQ(static_cast<size_t>( |
- NetworkQualityEstimator::kMaximumNetworkQualityCacheSize), |
- estimator.cached_network_qualities_.size()); |
- |
- // Test that the cache is LRU by examining its contents. Networks in cache |
- // must all be newer than the 100th network. |
- for (NetworkQualityEstimator::CachedNetworkQualities::iterator it = |
- estimator.cached_network_qualities_.begin(); |
- it != estimator.cached_network_qualities_.end(); ++it) { |
- EXPECT_GE((it->second).last_update_time_, update_time_of_network_100); |
- } |
-} |
- |
-TEST(NetworkQualityEstimatorTest, TestGetMedianRTTSince) { |
- std::map<std::string, std::string> variation_params; |
- TestNetworkQualityEstimator estimator(variation_params); |
- base::TimeTicks now = base::TimeTicks::Now(); |
- base::TimeTicks old = now - base::TimeDelta::FromMilliseconds(1); |
- ASSERT_NE(old, now); |
- |
- // First sample has very old timestamp. |
- estimator.downstream_throughput_kbps_observations_.AddObservation( |
- NetworkQualityEstimator::ThroughputObservation( |
- 1, old, NetworkQualityEstimator::URL_REQUEST)); |
- estimator.rtt_observations_.AddObservation( |
- NetworkQualityEstimator::RttObservation( |
- base::TimeDelta::FromMilliseconds(1), old, |
- NetworkQualityEstimator::URL_REQUEST)); |
- |
- estimator.downstream_throughput_kbps_observations_.AddObservation( |
- NetworkQualityEstimator::ThroughputObservation( |
- 100, now, NetworkQualityEstimator::URL_REQUEST)); |
- estimator.rtt_observations_.AddObservation( |
- NetworkQualityEstimator::RttObservation( |
- base::TimeDelta::FromMilliseconds(100), now, |
- NetworkQualityEstimator::URL_REQUEST)); |
- |
- const struct { |
- base::TimeTicks start_timestamp; |
- bool expect_network_quality_available; |
- base::TimeDelta expected_url_request_rtt; |
- int32_t expected_downstream_throughput; |
- } tests[] = { |
- {now + base::TimeDelta::FromSeconds(10), false, |
- base::TimeDelta::FromMilliseconds(0), 0}, |
- {now, true, base::TimeDelta::FromMilliseconds(100), 100}, |
- {now - base::TimeDelta::FromMicroseconds(500), true, |
- base::TimeDelta::FromMilliseconds(100), 100}, |
- |
- }; |
- |
- for (const auto& test : tests) { |
- base::TimeDelta url_request_rtt; |
- int32_t downstream_throughput_kbps; |
- EXPECT_EQ(test.expect_network_quality_available, |
- estimator.GetRecentURLRequestRTTMedian(test.start_timestamp, |
- &url_request_rtt)); |
- EXPECT_EQ(test.expect_network_quality_available, |
- estimator.GetRecentMedianDownlinkThroughputKbps( |
- test.start_timestamp, &downstream_throughput_kbps)); |
- |
- if (test.expect_network_quality_available) { |
- EXPECT_EQ(test.expected_url_request_rtt, url_request_rtt); |
- EXPECT_EQ(test.expected_downstream_throughput, |
- 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) { |
- base::HistogramTester histogram_tester; |
- InvalidExternalEstimateProvider* invalid_external_estimate_provider = |
- new InvalidExternalEstimateProvider(); |
- std::unique_ptr<ExternalEstimateProvider> external_estimate_provider( |
- invalid_external_estimate_provider); |
- |
- TestNetworkQualityEstimator estimator(std::map<std::string, std::string>(), |
- std::move(external_estimate_provider)); |
- |
- base::TimeDelta rtt; |
- int32_t kbps; |
- EXPECT_EQ(1U, invalid_external_estimate_provider->get_rtt_count()); |
- EXPECT_FALSE(estimator.GetURLRequestRTTEstimate(&rtt)); |
- EXPECT_FALSE(estimator.GetDownlinkThroughputKbpsEstimate(&kbps)); |
- histogram_tester.ExpectTotalCount("NQE.ExternalEstimateProviderStatus", 3); |
- |
- histogram_tester.ExpectBucketCount( |
- "NQE.ExternalEstimateProviderStatus", |
- 1 /* EXTERNAL_ESTIMATE_PROVIDER_STATUS_AVAILABLE */, 1); |
- histogram_tester.ExpectBucketCount( |
- "NQE.ExternalEstimateProviderStatus", |
- 2 /* EXTERNAL_ESTIMATE_PROVIDER_STATUS_QUERIED */, 1); |
- histogram_tester.ExpectBucketCount( |
- "NQE.ExternalEstimateProviderStatus", |
- 3 /* EXTERNAL_ESTIMATE_PROVIDER_STATUS_QUERY_SUCCESSFUL */, 1); |
- histogram_tester.ExpectTotalCount("NQE.ExternalEstimateProvider.RTT", 0); |
- histogram_tester.ExpectTotalCount( |
- "NQE.ExternalEstimateProvider.DownlinkBandwidth", 0); |
-} |
- |
-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) { |
- base::HistogramTester histogram_tester; |
- TestExternalEstimateProvider* test_external_estimate_provider = |
- new TestExternalEstimateProvider(base::TimeDelta::FromMilliseconds(1), |
- 100); |
- std::unique_ptr<ExternalEstimateProvider> external_estimate_provider( |
- test_external_estimate_provider); |
- std::map<std::string, std::string> variation_params; |
- TestNetworkQualityEstimator estimator(variation_params, |
- std::move(external_estimate_provider)); |
- |
- base::TimeDelta rtt; |
- int32_t kbps; |
- EXPECT_TRUE(estimator.GetURLRequestRTTEstimate(&rtt)); |
- EXPECT_TRUE(estimator.GetDownlinkThroughputKbpsEstimate(&kbps)); |
- |
- histogram_tester.ExpectTotalCount("NQE.ExternalEstimateProviderStatus", 5); |
- |
- histogram_tester.ExpectBucketCount( |
- "NQE.ExternalEstimateProviderStatus", |
- 1 /* EXTERNAL_ESTIMATE_PROVIDER_STATUS_AVAILABLE */, 1); |
- histogram_tester.ExpectBucketCount( |
- "NQE.ExternalEstimateProviderStatus", |
- 2 /* EXTERNAL_ESTIMATE_PROVIDER_STATUS_QUERIED */, 1); |
- histogram_tester.ExpectBucketCount( |
- "NQE.ExternalEstimateProviderStatus", |
- 3 /* EXTERNAL_ESTIMATE_PROVIDER_STATUS_QUERY_SUCCESSFUL */, 1); |
- histogram_tester.ExpectBucketCount( |
- "NQE.ExternalEstimateProviderStatus", |
- 5 /* EXTERNAL_ESTIMATE_PROVIDER_STATUS_RTT_AVAILABLE */, 1); |
- histogram_tester.ExpectBucketCount( |
- "NQE.ExternalEstimateProviderStatus", |
- 6 /* EXTERNAL_ESTIMATE_PROVIDER_STATUS_DOWNLINK_BANDWIDTH_AVAILABLE */, |
- 1); |
- histogram_tester.ExpectTotalCount("NQE.ExternalEstimateProvider.RTT", 1); |
- histogram_tester.ExpectBucketCount("NQE.ExternalEstimateProvider.RTT", 1, 1); |
- |
- histogram_tester.ExpectTotalCount( |
- "NQE.ExternalEstimateProvider.DownlinkBandwidth", 1); |
- histogram_tester.ExpectBucketCount( |
- "NQE.ExternalEstimateProvider.DownlinkBandwidth", 100, 1); |
- |
- 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.GetURLRequestRTTEstimate(&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.GetURLRequestRTTEstimate(&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(10 * 1000); |
- const int32_t external_estimate_provider_downstream_throughput = 100 * 1000; |
- TestExternalEstimateProvider* test_external_estimate_provider = |
- new TestExternalEstimateProvider( |
- external_estimate_provider_rtt, |
- external_estimate_provider_downstream_throughput); |
- std::unique_ptr<ExternalEstimateProvider> external_estimate_provider( |
- test_external_estimate_provider); |
- |
- std::map<std::string, std::string> variation_params; |
- TestNetworkQualityEstimator estimator(variation_params, |
- std::move(external_estimate_provider)); |
- |
- base::TimeDelta rtt; |
- // Estimate provided by network quality estimator should match the estimate |
- // provided by external estimate provider. |
- EXPECT_TRUE(estimator.GetURLRequestRTTEstimate(&rtt)); |
- EXPECT_EQ(external_estimate_provider_rtt, rtt); |
- |
- int32_t kbps; |
- EXPECT_TRUE(estimator.GetDownlinkThroughputKbpsEstimate(&kbps)); |
- EXPECT_EQ(external_estimate_provider_downstream_throughput, kbps); |
- |
- TestDelegate test_delegate; |
- TestURLRequestContext context(true); |
- context.set_network_quality_estimator(&estimator); |
- context.Init(); |
- |
- std::unique_ptr<URLRequest> request(context.CreateRequest( |
- estimator.GetEchoURL(), DEFAULT_PRIORITY, &test_delegate)); |
- request->Start(); |
- base::RunLoop().Run(); |
- |
- EXPECT_TRUE(estimator.GetURLRequestRTTEstimate(&rtt)); |
- EXPECT_NE(external_estimate_provider_rtt, rtt); |
- |
- EXPECT_TRUE(estimator.GetDownlinkThroughputKbpsEstimate(&kbps)); |
- EXPECT_NE(external_estimate_provider_downstream_throughput, kbps); |
-} |
- |
-TEST(NetworkQualityEstimatorTest, TestObservers) { |
- TestRTTObserver rtt_observer; |
- TestThroughputObserver throughput_observer; |
- std::map<std::string, std::string> variation_params; |
- TestNetworkQualityEstimator estimator(variation_params); |
- estimator.AddRTTObserver(&rtt_observer); |
- estimator.AddThroughputObserver(&throughput_observer); |
- |
- TestDelegate test_delegate; |
- TestURLRequestContext context(true); |
- context.set_network_quality_estimator(&estimator); |
- context.Init(); |
- |
- EXPECT_EQ(0U, rtt_observer.observations().size()); |
- EXPECT_EQ(0U, throughput_observer.observations().size()); |
- base::TimeTicks then = base::TimeTicks::Now(); |
- |
- std::unique_ptr<URLRequest> request(context.CreateRequest( |
- estimator.GetEchoURL(), DEFAULT_PRIORITY, &test_delegate)); |
- request->SetLoadFlags(request->load_flags() | LOAD_MAIN_FRAME); |
- request->Start(); |
- base::RunLoop().Run(); |
- |
- std::unique_ptr<URLRequest> request2(context.CreateRequest( |
- estimator.GetEchoURL(), DEFAULT_PRIORITY, &test_delegate)); |
- request2->SetLoadFlags(request->load_flags() | LOAD_MAIN_FRAME); |
- request2->Start(); |
- base::RunLoop().Run(); |
- |
- // Both RTT and downstream throughput should be updated. |
- base::TimeDelta rtt; |
- EXPECT_TRUE(estimator.GetURLRequestRTTEstimate(&rtt)); |
- |
- int32_t throughput; |
- EXPECT_TRUE(estimator.GetDownlinkThroughputKbpsEstimate(&throughput)); |
- |
- EXPECT_EQ(2U, rtt_observer.observations().size()); |
- EXPECT_EQ(2U, throughput_observer.observations().size()); |
- for (const auto& observation : rtt_observer.observations()) { |
- EXPECT_LE(0, observation.rtt_ms); |
- EXPECT_LE(0, (observation.timestamp - then).InMilliseconds()); |
- EXPECT_EQ(NetworkQualityEstimator::URL_REQUEST, observation.source); |
- } |
- for (const auto& observation : throughput_observer.observations()) { |
- EXPECT_LE(0, observation.throughput_kbps); |
- EXPECT_LE(0, (observation.timestamp - then).InMilliseconds()); |
- EXPECT_EQ(NetworkQualityEstimator::URL_REQUEST, observation.source); |
- } |
- |
- // Verify that observations from TCP and QUIC are passed on to the observers. |
- base::TimeDelta tcp_rtt(base::TimeDelta::FromMilliseconds(1)); |
- base::TimeDelta quic_rtt(base::TimeDelta::FromMilliseconds(2)); |
- |
- std::unique_ptr<SocketPerformanceWatcher> tcp_watcher = |
- estimator.GetSocketPerformanceWatcherFactory() |
- ->CreateSocketPerformanceWatcher( |
- SocketPerformanceWatcherFactory::PROTOCOL_TCP); |
- |
- std::unique_ptr<SocketPerformanceWatcher> quic_watcher = |
- estimator.GetSocketPerformanceWatcherFactory() |
- ->CreateSocketPerformanceWatcher( |
- SocketPerformanceWatcherFactory::PROTOCOL_QUIC); |
- |
- tcp_watcher->OnUpdatedRTTAvailable(tcp_rtt); |
- quic_watcher->OnUpdatedRTTAvailable(quic_rtt); |
- |
- base::RunLoop().RunUntilIdle(); |
- |
- EXPECT_EQ(4U, rtt_observer.observations().size()); |
- EXPECT_EQ(2U, throughput_observer.observations().size()); |
- |
- EXPECT_EQ(tcp_rtt.InMilliseconds(), rtt_observer.observations().at(2).rtt_ms); |
- EXPECT_EQ(quic_rtt.InMilliseconds(), |
- rtt_observer.observations().at(3).rtt_ms); |
-} |
- |
-// TestTCPSocketRTT requires kernel support for tcp_info struct, and so it is |
-// enabled only on certain platforms. |
-#if defined(TCP_INFO) || defined(OS_LINUX) |
-#define MAYBE_TestTCPSocketRTT TestTCPSocketRTT |
-#else |
-#define MAYBE_TestTCPSocketRTT DISABLED_TestTCPSocketRTT |
-#endif |
-// Tests that the TCP socket notifies the Network Quality Estimator of TCP RTTs, |
-// which in turn notifies registered RTT observers. |
-TEST(NetworkQualityEstimatorTest, MAYBE_TestTCPSocketRTT) { |
- TestRTTObserver rtt_observer; |
- std::map<std::string, std::string> variation_params; |
- TestNetworkQualityEstimator estimator(variation_params); |
- estimator.AddRTTObserver(&rtt_observer); |
- |
- TestDelegate test_delegate; |
- TestURLRequestContext context(true); |
- context.set_network_quality_estimator(&estimator); |
- |
- std::unique_ptr<HttpNetworkSession::Params> params( |
- new HttpNetworkSession::Params); |
- // |estimator| should be notified of TCP RTT observations. |
- params->socket_performance_watcher_factory = |
- estimator.GetSocketPerformanceWatcherFactory(); |
- context.set_http_network_session_params(std::move(params)); |
- context.Init(); |
- |
- EXPECT_EQ(0U, rtt_observer.observations().size()); |
- base::TimeDelta rtt; |
- EXPECT_FALSE(estimator.GetURLRequestRTTEstimate(&rtt)); |
- |
- // Send two requests. Verify that the completion of each request generates at |
- // least one TCP RTT observation. |
- for (size_t i = 0; i < 2; ++i) { |
- size_t before_count_tcp_rtt_observations = 0; |
- for (const auto& observation : rtt_observer.observations()) { |
- if (observation.source == NetworkQualityEstimator::TCP) |
- ++before_count_tcp_rtt_observations; |
- } |
- |
- std::unique_ptr<URLRequest> request(context.CreateRequest( |
- estimator.GetEchoURL(), DEFAULT_PRIORITY, &test_delegate)); |
- request->Start(); |
- base::RunLoop().Run(); |
- |
- size_t after_count_tcp_rtt_observations = 0; |
- for (const auto& observation : rtt_observer.observations()) { |
- if (observation.source == NetworkQualityEstimator::TCP) |
- ++after_count_tcp_rtt_observations; |
- } |
- // At least one notification should be received per socket performance |
- // watcher. |
- EXPECT_LE(1U, after_count_tcp_rtt_observations - |
- before_count_tcp_rtt_observations) |
- << i; |
- } |
- EXPECT_TRUE(estimator.GetURLRequestRTTEstimate(&rtt)); |
-} |
- |
-} // namespace net |