| 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..5fe6a59c1685a51ed593dfb70fe7af7a251ef93b 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,20 +145,64 @@ 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_transport_rtt(const base::TimeDelta& transport_rtt) {
|
| + transport_rtt_set_ = true;
|
| + transport_rtt_ = transport_rtt;
|
| + }
|
| +
|
| + // 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::GetTransportRTTEstimate(rtt);
|
| + }
|
| +
|
| + void set_recent_transport_rtt(const base::TimeDelta& recent_transport_rtt) {
|
| + recent_transport_rtt_set_ = true;
|
| + recent_transport_rtt_ = recent_transport_rtt;
|
| + }
|
| +
|
| + // 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);
|
| + }
|
| +
|
| void set_downlink_throughput_kbps(int32_t downlink_throughput_kbps) {
|
| downlink_throughput_kbps_set_ = true;
|
| downlink_throughput_kbps_ = downlink_throughput_kbps;
|
| }
|
|
|
| + // 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_;
|
| @@ -157,6 +211,9 @@ class TestNetworkQualityEstimator : public NetworkQualityEstimator {
|
| return NetworkQualityEstimator::GetDownlinkThroughputKbpsEstimate(kbps);
|
| }
|
|
|
| + // 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_) {
|
| @@ -167,12 +224,27 @@ class TestNetworkQualityEstimator : public NetworkQualityEstimator {
|
| start_time, kbps);
|
| }
|
|
|
| + void SetAccuracyRecordingIntervals(
|
| + const std::vector<base::TimeDelta>& accuracy_recording_intervals) {
|
| + accuracy_recording_intervals_set_ = true;
|
| + accuracy_recording_intervals_ = accuracy_recording_intervals;
|
| + }
|
| +
|
| + const std::vector<base::TimeDelta>& GetAccuracyRecordingIntervals()
|
| + const override {
|
| + if (accuracy_recording_intervals_set_)
|
| + return accuracy_recording_intervals_;
|
| +
|
| + return NetworkQualityEstimator::GetAccuracyRecordingIntervals();
|
| + }
|
| +
|
| using NetworkQualityEstimator::SetTickClockForTesting;
|
| using NetworkQualityEstimator::ReadCachedNetworkQualityEstimate;
|
| using NetworkQualityEstimator::OnConnectionTypeChanged;
|
|
|
| private:
|
| - // NetworkQualityEstimator implementation that returns the overridden network
|
| + // NetworkQualityEstimator implementation that returns the overridden
|
| + // network
|
| // id (instead of invoking platform APIs).
|
| NetworkQualityEstimator::NetworkID GetCurrentNetworkID() const override {
|
| return NetworkQualityEstimator::NetworkID(current_network_type_,
|
| @@ -185,9 +257,21 @@ class TestNetworkQualityEstimator : public NetworkQualityEstimator {
|
| 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_;
|
|
|
| @@ -513,6 +597,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 +668,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 +729,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 +1550,108 @@ TEST(NetworkQualityEstimatorTest, MAYBE_TestTCPSocketRTT) {
|
| "NQE.MainFrame.TransportRTT.Percentile50.Unknown", num_requests);
|
| }
|
|
|
| +#if defined(OS_IOS)
|
| +// Flaky on iOS when |accuracy_recording_delay| is non-zero.
|
| +#define MAYBE_RecordAccuracy DISABLED_RecordAccuracy
|
| +#else
|
| +#define MAYBE_RecordAccuracy RecordAccuracy
|
| +#endif
|
| +// Tests if the NQE accuracy metrics are recorded properly.
|
| +TEST(NetworkQualityEstimatorTest, MAYBE_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 for some time to ensure that the delayed task is posted.
|
| + base::PlatformThread::Sleep(accuracy_recording_delay * 2);
|
| + base::RunLoop().RunUntilIdle();
|
| + }
|
| +
|
| + const int diff = std::abs(test.rtt.InMilliseconds() -
|
| + test.recent_rtt.InMilliseconds());
|
| + const std::string sign_suffix_with_one_sample =
|
| + test.rtt.InMilliseconds() - test.recent_rtt.InMilliseconds() >= 0
|
| + ? "Positive"
|
| + : "Negative";
|
| + const std::string sign_suffix_with_zero_samples =
|
| + test.rtt.InMilliseconds() - test.recent_rtt.InMilliseconds() >= 0
|
| + ? "Negative"
|
| + : "Positive";
|
| + const std::string interval_value =
|
| + base::IntToString(accuracy_recording_delay.InSeconds());
|
| +
|
| + histogram_tester.ExpectUniqueSample(
|
| + "NQE.Accuracy.HttpRTT.EstimatedObservedDiff." +
|
| + sign_suffix_with_one_sample + "." + interval_value + ".60_140",
|
| + diff, 1);
|
| + histogram_tester.ExpectTotalCount(
|
| + "NQE.Accuracy.HttpRTT.EstimatedObservedDiff." +
|
| + sign_suffix_with_zero_samples + "." + interval_value + ".60_140",
|
| + 0);
|
| + histogram_tester.ExpectUniqueSample(
|
| + "NQE.Accuracy.TransportRTT.EstimatedObservedDiff." +
|
| + sign_suffix_with_one_sample + "." + interval_value + ".60_140",
|
| + diff, 1);
|
| + histogram_tester.ExpectTotalCount(
|
| + "NQE.Accuracy.TransportRTT.EstimatedObservedDiff." +
|
| + sign_suffix_with_zero_samples + "." + interval_value + ".60_140",
|
| + 0);
|
| + }
|
| + }
|
| +}
|
| +
|
| } // namespace net
|
|
|