Chromium Code Reviews| Index: net/nqe/network_quality_estimator_unittest.cc |
| diff --git a/net/nqe/network_quality_estimator_unittest.cc b/net/nqe/network_quality_estimator_unittest.cc |
| index a8e7002075c5d9476c05e940a2385a1b7e1e2379..bedfcbf9a71b309b7d753cfdfa3eab8678bff73d 100644 |
| --- a/net/nqe/network_quality_estimator_unittest.cc |
| +++ b/net/nqe/network_quality_estimator_unittest.cc |
| @@ -22,6 +22,7 @@ |
| #include "base/strings/string_number_conversions.h" |
| #include "base/test/histogram_tester.h" |
| #include "base/test/simple_test_tick_clock.h" |
| +#include "base/threading/platform_thread.h" |
| #include "base/time/time.h" |
| #include "build/build_config.h" |
| #include "net/base/load_flags.h" |
| @@ -68,7 +69,11 @@ class TestNetworkQualityEstimator : public NetworkQualityEstimator { |
| effective_connection_type_set_(false), |
| effective_connection_type_(EFFECTIVE_CONNECTION_TYPE_UNKNOWN), |
| current_network_type_(NetworkChangeNotifier::CONNECTION_UNKNOWN), |
| + accuracy_recording_intervals_set_(false), |
| http_rtt_set_(false), |
| + recent_http_rtt_set_(false), |
| + transport_rtt_set_(false), |
| + recent_transport_rtt_set_(false), |
| downlink_throughput_kbps_set_(false) { |
| // Set up embedded test server. |
| embedded_test_server_.ServeFilesFromDirectory( |
| @@ -111,22 +116,27 @@ class TestNetworkQualityEstimator : public NetworkQualityEstimator { |
| return embedded_test_server_.GetURL("/echo.html"); |
| } |
| - void set_http_rtt(const base::TimeDelta& http_rtt) { |
| - http_rtt_set_ = true; |
| - http_rtt_ = http_rtt; |
| - } |
| - |
| void set_effective_connection_type(EffectiveConnectionType type) { |
| effective_connection_type_set_ = true; |
| effective_connection_type_ = type; |
| } |
| + // Returns the effective connection type that was set using |
| + // |set_effective_connection_type|. If connection type has not been set, then |
| + // the base implementation is called. |
| EffectiveConnectionType GetEffectiveConnectionType() const override { |
| if (effective_connection_type_set_) |
| return effective_connection_type_; |
| return NetworkQualityEstimator::GetEffectiveConnectionType(); |
| } |
| + void set_http_rtt(const base::TimeDelta& http_rtt) { |
| + http_rtt_set_ = true; |
| + http_rtt_ = http_rtt; |
| + } |
| + |
| + // Returns the HTTP RTT that was set using |set_http_rtt|. If the HTTP RTT has |
| + // not been set, then the base implementation is called. |
| bool GetHttpRTTEstimate(base::TimeDelta* rtt) const override { |
| if (http_rtt_set_) { |
| *rtt = http_rtt_; |
| @@ -135,66 +145,141 @@ class TestNetworkQualityEstimator : public NetworkQualityEstimator { |
| return NetworkQualityEstimator::GetHttpRTTEstimate(rtt); |
| } |
| + void set_recent_http_rtt(const base::TimeDelta& recent_http_rtt) { |
| + recent_http_rtt_set_ = true; |
| + recent_http_rtt_ = recent_http_rtt; |
| + } |
| + |
| + // Returns the recent HTTP RTT that was set using |set_recent_http_rtt|. If |
| + // the recent HTTP RTT has not been set, then the base implementation is |
| + // called. |
| bool GetRecentHttpRTTMedian(const base::TimeTicks& start_time, |
| base::TimeDelta* rtt) const override { |
| - if (http_rtt_set_) { |
| - *rtt = http_rtt_; |
| + if (recent_http_rtt_set_) { |
| + *rtt = recent_http_rtt_; |
| return true; |
| } |
| return NetworkQualityEstimator::GetRecentHttpRTTMedian(start_time, rtt); |
| } |
| - void set_downlink_throughput_kbps(int32_t downlink_throughput_kbps) { |
| - downlink_throughput_kbps_set_ = true; |
| - downlink_throughput_kbps_ = downlink_throughput_kbps; |
| + void set_transport_rtt(const base::TimeDelta& transport_rtt) { |
| + transport_rtt_set_ = true; |
| + transport_rtt_ = transport_rtt; |
| } |
| - bool GetDownlinkThroughputKbpsEstimate(int32_t* kbps) const override { |
| - if (downlink_throughput_kbps_set_) { |
| - *kbps = downlink_throughput_kbps_; |
| + // Returns the transport RTT that was set using |set_transport_rtt|. If the |
| + // transport RTT has not been set, then the base implementation is called. |
| + bool GetTransportRTTEstimate(base::TimeDelta* rtt) const override { |
| + if (transport_rtt_set_) { |
| + *rtt = transport_rtt_; |
| return true; |
| } |
| - return NetworkQualityEstimator::GetDownlinkThroughputKbpsEstimate(kbps); |
| + return NetworkQualityEstimator::GetTransportRTTEstimate(rtt); |
| } |
| - bool GetRecentMedianDownlinkThroughputKbps(const base::TimeTicks& start_time, |
| - int32_t* kbps) const override { |
| - if (downlink_throughput_kbps_set_) { |
| - *kbps = downlink_throughput_kbps_; |
| - return true; |
| + void set_recent_transport_rtt(const base::TimeDelta& recent_transport_rtt) { |
| + recent_transport_rtt_set_ = true; |
| + recent_transport_rtt_ = recent_transport_rtt; |
| } |
|
Alexei Svitkine (slow)
2016/06/03 20:01:07
Nit: bad indent?
tbansal1
2016/06/03 20:57:20
Done, not sure why git cl format did not catch tha
|
| - return NetworkQualityEstimator::GetRecentMedianDownlinkThroughputKbps( |
| - start_time, kbps); |
| - } |
| - using NetworkQualityEstimator::SetTickClockForTesting; |
| - using NetworkQualityEstimator::ReadCachedNetworkQualityEstimate; |
| - using NetworkQualityEstimator::OnConnectionTypeChanged; |
| + // Returns the recent transport RTT that was set using |
| + // |set_recent_transport_rtt|. If the recent transport RTT has not been set, |
| + // then the base implementation is called. |
| + bool GetRecentTransportRTTMedian(const base::TimeTicks& start_time, |
| + base::TimeDelta* rtt) const override { |
| + if (recent_transport_rtt_set_) { |
| + *rtt = recent_transport_rtt_; |
| + return true; |
| + } |
| + return NetworkQualityEstimator::GetRecentTransportRTTMedian(start_time, |
| + rtt); |
| + } |
| - 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_); |
| - } |
| + void set_downlink_throughput_kbps(int32_t downlink_throughput_kbps) { |
| + downlink_throughput_kbps_set_ = true; |
| + downlink_throughput_kbps_ = downlink_throughput_kbps; |
| + } |
| - bool effective_connection_type_set_; |
| - EffectiveConnectionType effective_connection_type_; |
| + // Returns the downlink throughput that was set using |
| + // |set_downlink_throughput_kbps|. If the downlink throughput has not been |
| + // set, then the base implementation is called. |
| + bool GetDownlinkThroughputKbpsEstimate(int32_t* kbps) const override { |
| + if (downlink_throughput_kbps_set_) { |
| + *kbps = downlink_throughput_kbps_; |
| + return true; |
| + } |
| + return NetworkQualityEstimator::GetDownlinkThroughputKbpsEstimate(kbps); |
| + } |
| - NetworkChangeNotifier::ConnectionType current_network_type_; |
| - std::string current_network_id_; |
| + // Returns the downlink throughput that was set using |
| + // |set_downlink_throughput_kbps|. If the downlink throughput has not been |
| + // set, then the base implementation is called. |
| + bool GetRecentMedianDownlinkThroughputKbps( |
| + const base::TimeTicks& start_time, |
| + int32_t* kbps) const override { |
| + if (downlink_throughput_kbps_set_) { |
| + *kbps = downlink_throughput_kbps_; |
| + return true; |
| + } |
| + return NetworkQualityEstimator::GetRecentMedianDownlinkThroughputKbps( |
| + start_time, kbps); |
| + } |
| - bool http_rtt_set_; |
| - base::TimeDelta http_rtt_; |
| + void SetAccuracyRecordingIntervals( |
| + const std::vector<base::TimeDelta>& accuracy_recording_intervals) { |
| + accuracy_recording_intervals_set_ = true; |
| + accuracy_recording_intervals_ = accuracy_recording_intervals; |
| + } |
| - bool downlink_throughput_kbps_set_; |
| - int32_t downlink_throughput_kbps_; |
| + const std::vector<base::TimeDelta>& GetAccuracyRecordingIntervals() |
| + const override { |
| + if (accuracy_recording_intervals_set_) |
| + return accuracy_recording_intervals_; |
| - // Embedded server used for testing. |
| - EmbeddedTestServer embedded_test_server_; |
| + return NetworkQualityEstimator::GetAccuracyRecordingIntervals(); |
| + } |
| - DISALLOW_COPY_AND_ASSIGN(TestNetworkQualityEstimator); |
| + using NetworkQualityEstimator::SetTickClockForTesting; |
| + 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_); |
| + } |
| + |
| + bool effective_connection_type_set_; |
| + EffectiveConnectionType effective_connection_type_; |
| + |
| + NetworkChangeNotifier::ConnectionType current_network_type_; |
| + std::string current_network_id_; |
| + |
| + bool accuracy_recording_intervals_set_; |
| + std::vector<base::TimeDelta> accuracy_recording_intervals_; |
| + |
| + bool http_rtt_set_; |
| + base::TimeDelta http_rtt_; |
| + |
| + bool recent_http_rtt_set_; |
| + base::TimeDelta recent_http_rtt_; |
| + |
| + bool transport_rtt_set_; |
| + base::TimeDelta transport_rtt_; |
| + |
| + bool recent_transport_rtt_set_; |
| + base::TimeDelta recent_transport_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 TestEffectiveConnectionTypeObserver |
| @@ -513,6 +598,8 @@ TEST(NetworkQualityEstimatorTest, ObtainThresholdsNone) { |
| for (const auto& test : tests) { |
| estimator.set_http_rtt(base::TimeDelta::FromMilliseconds(test.rtt_msec)); |
| + estimator.set_recent_http_rtt( |
| + base::TimeDelta::FromMilliseconds(test.rtt_msec)); |
| EXPECT_EQ(test.expected_conn_type, estimator.GetEffectiveConnectionType()); |
| } |
| } |
| @@ -582,6 +669,8 @@ TEST(NetworkQualityEstimatorTest, ObtainThresholdsOnlyRTT) { |
| for (const auto& test : tests) { |
| estimator.set_http_rtt(base::TimeDelta::FromMilliseconds(test.rtt_msec)); |
| + estimator.set_recent_http_rtt( |
| + base::TimeDelta::FromMilliseconds(test.rtt_msec)); |
| EXPECT_EQ(test.expected_conn_type, estimator.GetEffectiveConnectionType()); |
| } |
| } |
| @@ -641,6 +730,8 @@ TEST(NetworkQualityEstimatorTest, ObtainThresholdsRTTandThroughput) { |
| for (const auto& test : tests) { |
| estimator.set_http_rtt(base::TimeDelta::FromMilliseconds(test.rtt_msec)); |
| + estimator.set_recent_http_rtt( |
| + base::TimeDelta::FromMilliseconds(test.rtt_msec)); |
| estimator.set_downlink_throughput_kbps(test.downlink_throughput_kbps); |
| EXPECT_EQ(test.expected_conn_type, estimator.GetEffectiveConnectionType()); |
| } |
| @@ -1460,4 +1551,113 @@ TEST(NetworkQualityEstimatorTest, MAYBE_TestTCPSocketRTT) { |
| "NQE.MainFrame.TransportRTT.Percentile50.Unknown", num_requests); |
| } |
| +// Tests if the NQE accuracy metrics are recorded properly. |
| +TEST(NetworkQualityEstimatorTest, RecordAccuracy) { |
| + const int expected_rtt_msec = 100; |
| + |
| + const base::TimeDelta accuracy_recording_delays[] = { |
| + base::TimeDelta::FromSeconds(0), base::TimeDelta::FromSeconds(1), |
| + }; |
| + |
| + const struct { |
| + base::TimeDelta rtt; |
| + base::TimeDelta recent_rtt; |
| + } tests[] = { |
| + {base::TimeDelta::FromMilliseconds(expected_rtt_msec), |
| + base::TimeDelta::FromMilliseconds(expected_rtt_msec)}, |
| + {base::TimeDelta::FromMilliseconds(expected_rtt_msec + 1), |
| + base::TimeDelta::FromMilliseconds(expected_rtt_msec)}, |
| + {base::TimeDelta::FromMilliseconds(expected_rtt_msec - 1), |
| + base::TimeDelta::FromMilliseconds(expected_rtt_msec)}, |
| + }; |
| + |
| + for (const auto& accuracy_recording_delay : accuracy_recording_delays) { |
| + for (const auto& test : tests) { |
| + std::unique_ptr<base::SimpleTestTickClock> tick_clock( |
| + new base::SimpleTestTickClock()); |
| + base::SimpleTestTickClock* tick_clock_ptr = tick_clock.get(); |
| + tick_clock_ptr->Advance(base::TimeDelta::FromSeconds(1)); |
| + |
| + std::map<std::string, std::string> variation_params; |
| + TestNetworkQualityEstimator estimator(variation_params); |
| + estimator.SetTickClockForTesting(std::move(tick_clock)); |
| + |
| + std::vector<base::TimeDelta> accuracy_recording_intervals; |
| + accuracy_recording_intervals.push_back(accuracy_recording_delay); |
| + estimator.SetAccuracyRecordingIntervals(accuracy_recording_intervals); |
| + |
| + // RTT is higher than threshold. Network is slow. |
| + // Network was predicted to be slow and actually was slow. |
| + estimator.set_http_rtt(test.rtt); |
| + estimator.set_recent_http_rtt(test.recent_rtt); |
| + estimator.set_transport_rtt(test.rtt); |
| + estimator.set_recent_transport_rtt(test.recent_rtt); |
| + |
| + base::HistogramTester histogram_tester; |
| + |
| + TestDelegate test_delegate; |
| + TestURLRequestContext context(true); |
| + context.set_network_quality_estimator(&estimator); |
| + context.Init(); |
| + |
| + // Start a main-frame request which should cause network quality estimator |
| + // to record accuracy UMA. |
| + 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(); |
| + |
| + if (accuracy_recording_delay != base::TimeDelta()) { |
| + tick_clock_ptr->Advance(accuracy_recording_delay); |
| + |
| + // Sleep to ensure that the delayed task is posted. |
| + base::PlatformThread::Sleep(accuracy_recording_delay); |
| + base::RunLoop().RunUntilIdle(); |
| + } |
| + |
| + const int diff = std::abs(test.rtt.InMilliseconds() - |
| + test.recent_rtt.InMilliseconds()); |
| + const std::string diff_value = |
| + base::IntToString(accuracy_recording_delay.InSeconds()); |
| + |
| + if (test.rtt >= test.recent_rtt) { |
| + histogram_tester.ExpectUniqueSample( |
| + "NQE.Accuracy.HttpRTT.EstimatedActualDiff." + diff_value + |
| + ".60_140", |
| + diff, 1); |
| + histogram_tester.ExpectTotalCount( |
| + "NQE.Accuracy.HttpRTT.ActualEstimatedDiff." + diff_value + |
| + ".60_140", |
| + 0); |
| + histogram_tester.ExpectUniqueSample( |
| + "NQE.Accuracy.TransportRTT.EstimatedActualDiff." + diff_value + |
| + ".60_140", |
| + diff, 1); |
| + histogram_tester.ExpectTotalCount( |
| + "NQE.Accuracy.TransportRTT.ActualEstimatedDiff." + diff_value + |
| + ".60_140", |
| + 0); |
| + } else { |
| + histogram_tester.ExpectTotalCount( |
| + "NQE.Accuracy.HttpRTT.EstimatedActualDiff." + diff_value + |
| + ".60_140", |
| + 0); |
| + histogram_tester.ExpectUniqueSample( |
| + "NQE.Accuracy.HttpRTT.ActualEstimatedDiff." + diff_value + |
| + ".60_140", |
| + diff, 1); |
| + histogram_tester.ExpectTotalCount( |
| + "NQE.Accuracy.TransportRTT.EstimatedActualDiff." + diff_value + |
| + ".60_140", |
| + 0); |
| + histogram_tester.ExpectUniqueSample( |
| + "NQE.Accuracy.TransportRTT.ActualEstimatedDiff." + diff_value + |
| + ".60_140", |
| + diff, 1); |
| + } |
| + } |
| + } |
| +} |
| + |
| } // namespace net |