| OLD | NEW |
| 1 // Copyright 2015 The Chromium Authors. All rights reserved. | 1 // Copyright 2015 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "net/base/network_quality_estimator.h" | 5 #include "net/base/network_quality_estimator.h" |
| 6 | 6 |
| 7 #include <stdint.h> | 7 #include <stdint.h> |
| 8 #include <netinet/tcp.h> |
| 9 |
| 8 #include <limits> | 10 #include <limits> |
| 9 #include <map> | 11 #include <map> |
| 12 #include <string> |
| 10 #include <utility> | 13 #include <utility> |
| 11 #include <vector> | 14 #include <vector> |
| 12 | 15 |
| 13 #include "base/files/file_path.h" | 16 #include "base/files/file_path.h" |
| 14 #include "base/logging.h" | 17 #include "base/logging.h" |
| 15 #include "base/macros.h" | 18 #include "base/macros.h" |
| 16 #include "base/memory/scoped_ptr.h" | 19 #include "base/memory/scoped_ptr.h" |
| 17 #include "base/metrics/histogram_samples.h" | 20 #include "base/metrics/histogram_samples.h" |
| 18 #include "base/run_loop.h" | 21 #include "base/run_loop.h" |
| 19 #include "base/strings/string_number_conversions.h" | 22 #include "base/strings/string_number_conversions.h" |
| 20 #include "base/test/histogram_tester.h" | 23 #include "base/test/histogram_tester.h" |
| 21 #include "base/time/time.h" | 24 #include "base/time/time.h" |
| 22 #include "build/build_config.h" | 25 #include "build/build_config.h" |
| 23 #include "net/base/external_estimate_provider.h" | 26 #include "net/base/external_estimate_provider.h" |
| 24 #include "net/base/load_flags.h" | 27 #include "net/base/load_flags.h" |
| 25 #include "net/base/network_change_notifier.h" | 28 #include "net/base/network_change_notifier.h" |
| 29 #include "net/http/http_network_session.h" |
| 26 #include "net/http/http_status_code.h" | 30 #include "net/http/http_status_code.h" |
| 27 #include "net/test/embedded_test_server/embedded_test_server.h" | 31 #include "net/test/embedded_test_server/embedded_test_server.h" |
| 28 #include "net/test/embedded_test_server/http_request.h" | 32 #include "net/test/embedded_test_server/http_request.h" |
| 29 #include "net/test/embedded_test_server/http_response.h" | 33 #include "net/test/embedded_test_server/http_response.h" |
| 34 #include "net/url_request/url_request.h" |
| 30 #include "net/url_request/url_request_test_util.h" | 35 #include "net/url_request/url_request_test_util.h" |
| 31 #include "testing/gtest/include/gtest/gtest.h" | 36 #include "testing/gtest/include/gtest/gtest.h" |
| 32 #include "url/gurl.h" | 37 #include "url/gurl.h" |
| 33 | 38 |
| 34 namespace { | 39 namespace { |
| 35 | 40 |
| 36 // Helps in setting the current network type and id. | 41 // Helps in setting the current network type and id. |
| 37 class TestNetworkQualityEstimator : public net::NetworkQualityEstimator { | 42 class TestNetworkQualityEstimator : public net::NetworkQualityEstimator { |
| 38 public: | 43 public: |
| 39 TestNetworkQualityEstimator( | 44 TestNetworkQualityEstimator( |
| 40 const std::map<std::string, std::string>& variation_params, | 45 const std::map<std::string, std::string>& variation_params, |
| 41 scoped_ptr<net::ExternalEstimateProvider> external_estimate_provider) | 46 scoped_ptr<net::ExternalEstimateProvider> external_estimate_provider) |
| 42 : NetworkQualityEstimator(std::move(external_estimate_provider), | 47 : NetworkQualityEstimator(std::move(external_estimate_provider), |
| 43 variation_params, | 48 variation_params, |
| 44 true, | 49 true, |
| 45 true) { | 50 true), |
| 51 watcher_reset_notification_received_count_(0) { |
| 46 // Set up embedded test server. | 52 // Set up embedded test server. |
| 47 embedded_test_server_.ServeFilesFromDirectory( | 53 embedded_test_server_.ServeFilesFromDirectory( |
| 48 base::FilePath(FILE_PATH_LITERAL("net/data/url_request_unittest"))); | 54 base::FilePath(FILE_PATH_LITERAL("net/data/url_request_unittest"))); |
| 49 EXPECT_TRUE(embedded_test_server_.Start()); | 55 EXPECT_TRUE(embedded_test_server_.Start()); |
| 50 embedded_test_server_.RegisterRequestHandler(base::Bind( | 56 embedded_test_server_.RegisterRequestHandler(base::Bind( |
| 51 &TestNetworkQualityEstimator::HandleRequest, base::Unretained(this))); | 57 &TestNetworkQualityEstimator::HandleRequest, base::Unretained(this))); |
| 52 } | 58 } |
| 53 | 59 |
| 54 explicit TestNetworkQualityEstimator( | 60 explicit TestNetworkQualityEstimator( |
| 55 const std::map<std::string, std::string>& variation_params) | 61 const std::map<std::string, std::string>& variation_params) |
| (...skipping 21 matching lines...) Expand all Loading... |
| 77 http_response->set_content("hello"); | 83 http_response->set_content("hello"); |
| 78 http_response->set_content_type("text/plain"); | 84 http_response->set_content_type("text/plain"); |
| 79 return std::move(http_response); | 85 return std::move(http_response); |
| 80 } | 86 } |
| 81 | 87 |
| 82 // Returns a GURL hosted at embedded test server. | 88 // Returns a GURL hosted at embedded test server. |
| 83 const GURL GetEchoURL() const { | 89 const GURL GetEchoURL() const { |
| 84 return embedded_test_server_.GetURL("/echo.html"); | 90 return embedded_test_server_.GetURL("/echo.html"); |
| 85 } | 91 } |
| 86 | 92 |
| 93 void OnWatcherReset() override { |
| 94 watcher_reset_notification_received_count_++; |
| 95 } |
| 96 |
| 97 size_t watcher_reset_notification_received_count() const { |
| 98 return watcher_reset_notification_received_count_; |
| 99 } |
| 100 |
| 87 using NetworkQualityEstimator::ReadCachedNetworkQualityEstimate; | 101 using NetworkQualityEstimator::ReadCachedNetworkQualityEstimate; |
| 88 using NetworkQualityEstimator::OnConnectionTypeChanged; | 102 using NetworkQualityEstimator::OnConnectionTypeChanged; |
| 89 | 103 |
| 90 private: | 104 private: |
| 91 // NetworkQualityEstimator implementation that returns the overridden network | 105 // NetworkQualityEstimator implementation that returns the overridden network |
| 92 // id (instead of invoking platform APIs). | 106 // id (instead of invoking platform APIs). |
| 93 NetworkQualityEstimator::NetworkID GetCurrentNetworkID() const override { | 107 NetworkQualityEstimator::NetworkID GetCurrentNetworkID() const override { |
| 94 return NetworkQualityEstimator::NetworkID(current_network_type_, | 108 return NetworkQualityEstimator::NetworkID(current_network_type_, |
| 95 current_network_id_); | 109 current_network_id_); |
| 96 } | 110 } |
| 97 | 111 |
| 98 net::NetworkChangeNotifier::ConnectionType current_network_type_; | 112 net::NetworkChangeNotifier::ConnectionType current_network_type_; |
| 99 std::string current_network_id_; | 113 std::string current_network_id_; |
| 100 | 114 |
| 101 // Embedded server used for testing. | 115 // Embedded server used for testing. |
| 102 net::EmbeddedTestServer embedded_test_server_; | 116 net::EmbeddedTestServer embedded_test_server_; |
| 103 | 117 |
| 118 size_t watcher_reset_notification_received_count_; |
| 119 |
| 104 DISALLOW_COPY_AND_ASSIGN(TestNetworkQualityEstimator); | 120 DISALLOW_COPY_AND_ASSIGN(TestNetworkQualityEstimator); |
| 105 }; | 121 }; |
| 106 | 122 |
| 107 class TestRTTObserver : public net::NetworkQualityEstimator::RTTObserver { | 123 class TestRTTObserver : public net::NetworkQualityEstimator::RTTObserver { |
| 108 public: | 124 public: |
| 109 struct Observation { | 125 struct Observation { |
| 110 Observation(int32_t ms, | 126 Observation(int32_t ms, |
| 111 const base::TimeTicks& ts, | 127 const base::TimeTicks& ts, |
| 112 net::NetworkQualityEstimator::ObservationSource src) | 128 net::NetworkQualityEstimator::ObservationSource src) |
| 113 : rtt_ms(ms), timestamp(ts), source(src) {} | 129 : rtt_ms(ms), timestamp(ts), source(src) {} |
| (...skipping 940 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1054 | 1070 |
| 1055 // Both RTT and downstream throughput should be updated. | 1071 // Both RTT and downstream throughput should be updated. |
| 1056 EXPECT_NE(NetworkQualityEstimator::InvalidRTT(), | 1072 EXPECT_NE(NetworkQualityEstimator::InvalidRTT(), |
| 1057 estimator.GetRTTEstimateInternal(base::TimeTicks(), 100)); | 1073 estimator.GetRTTEstimateInternal(base::TimeTicks(), 100)); |
| 1058 EXPECT_NE(NetworkQualityEstimator::kInvalidThroughput, | 1074 EXPECT_NE(NetworkQualityEstimator::kInvalidThroughput, |
| 1059 estimator.GetDownlinkThroughputKbpsEstimateInternal( | 1075 estimator.GetDownlinkThroughputKbpsEstimateInternal( |
| 1060 base::TimeTicks(), 100)); | 1076 base::TimeTicks(), 100)); |
| 1061 | 1077 |
| 1062 EXPECT_EQ(2U, rtt_observer.observations().size()); | 1078 EXPECT_EQ(2U, rtt_observer.observations().size()); |
| 1063 EXPECT_EQ(2U, throughput_observer.observations().size()); | 1079 EXPECT_EQ(2U, throughput_observer.observations().size()); |
| 1064 for (auto observation : rtt_observer.observations()) { | 1080 for (const auto& observation : rtt_observer.observations()) { |
| 1065 EXPECT_LE(0, observation.rtt_ms); | 1081 EXPECT_LE(0, observation.rtt_ms); |
| 1066 EXPECT_LE(0, (observation.timestamp - then).InMilliseconds()); | 1082 EXPECT_LE(0, (observation.timestamp - then).InMilliseconds()); |
| 1067 EXPECT_EQ(NetworkQualityEstimator::URL_REQUEST, observation.source); | 1083 EXPECT_EQ(NetworkQualityEstimator::URL_REQUEST, observation.source); |
| 1068 } | 1084 } |
| 1069 for (auto observation : throughput_observer.observations()) { | 1085 for (const auto& observation : throughput_observer.observations()) { |
| 1070 EXPECT_LE(0, observation.throughput_kbps); | 1086 EXPECT_LE(0, observation.throughput_kbps); |
| 1071 EXPECT_LE(0, (observation.timestamp - then).InMilliseconds()); | 1087 EXPECT_LE(0, (observation.timestamp - then).InMilliseconds()); |
| 1072 EXPECT_EQ(NetworkQualityEstimator::URL_REQUEST, observation.source); | 1088 EXPECT_EQ(NetworkQualityEstimator::URL_REQUEST, observation.source); |
| 1073 } | 1089 } |
| 1074 | 1090 |
| 1075 // Verify that observations from TCP and QUIC are passed on to the observers. | 1091 // Verify that observations from TCP and QUIC are passed on to the observers. |
| 1076 base::TimeDelta tcp_rtt(base::TimeDelta::FromMilliseconds(1)); | 1092 base::TimeDelta tcp_rtt(base::TimeDelta::FromMilliseconds(1)); |
| 1077 base::TimeDelta quic_rtt(base::TimeDelta::FromMilliseconds(2)); | 1093 base::TimeDelta quic_rtt(base::TimeDelta::FromMilliseconds(2)); |
| 1078 | 1094 |
| 1079 scoped_ptr<SocketPerformanceWatcher> tcp_watcher = | 1095 scoped_ptr<SocketPerformanceWatcher> tcp_watcher = |
| 1080 estimator.CreateSocketPerformanceWatcher( | 1096 estimator.CreateSocketPerformanceWatcher( |
| 1081 SocketPerformanceWatcherFactory::PROTOCOL_TCP); | 1097 SocketPerformanceWatcherFactory::PROTOCOL_TCP); |
| 1082 scoped_ptr<SocketPerformanceWatcher> quic_watcher = | 1098 scoped_ptr<SocketPerformanceWatcher> quic_watcher = |
| 1083 estimator.CreateSocketPerformanceWatcher( | 1099 estimator.CreateSocketPerformanceWatcher( |
| 1084 SocketPerformanceWatcherFactory::PROTOCOL_QUIC); | 1100 SocketPerformanceWatcherFactory::PROTOCOL_QUIC); |
| 1085 tcp_watcher->OnUpdatedRTTAvailable(tcp_rtt); | 1101 tcp_watcher->OnUpdatedRTTAvailable(tcp_rtt); |
| 1086 quic_watcher->OnUpdatedRTTAvailable(quic_rtt); | 1102 quic_watcher->OnUpdatedRTTAvailable(quic_rtt); |
| 1087 | 1103 |
| 1088 EXPECT_EQ(4U, rtt_observer.observations().size()); | 1104 EXPECT_EQ(4U, rtt_observer.observations().size()); |
| 1089 EXPECT_EQ(2U, throughput_observer.observations().size()); | 1105 EXPECT_EQ(2U, throughput_observer.observations().size()); |
| 1090 | 1106 |
| 1091 EXPECT_EQ(tcp_rtt.InMilliseconds(), rtt_observer.observations().at(2).rtt_ms); | 1107 EXPECT_EQ(tcp_rtt.InMilliseconds(), rtt_observer.observations().at(2).rtt_ms); |
| 1092 EXPECT_EQ(quic_rtt.InMilliseconds(), | 1108 EXPECT_EQ(quic_rtt.InMilliseconds(), |
| 1093 rtt_observer.observations().at(3).rtt_ms); | 1109 rtt_observer.observations().at(3).rtt_ms); |
| 1094 } | 1110 } |
| 1095 | 1111 |
| 1112 // TestTCPSocketRTT requires kernel support for tcp_info struct, and so it is |
| 1113 // enabled only on the POSIX platforms. |
| 1114 #if defined(TCP_INFO) |
| 1115 #define MAYBE_TestTCPSocketRTT TestTCPSocketRTT |
| 1116 #else |
| 1117 #define MAYBE_TestTCPSocketRTT DISABLED_TestTCPSocketRTT |
| 1118 #endif |
| 1119 // Tests that the TCP socket notifies the Network Quality Estimator of TCP RTTs, |
| 1120 // which in turn notifies registered RTT observers. |
| 1121 TEST(NetworkQualityEstimatorTest, MAYBE_TestTCPSocketRTT) { |
| 1122 base::HistogramTester histogram_tester; |
| 1123 TestRTTObserver rtt_observer; |
| 1124 std::map<std::string, std::string> variation_params; |
| 1125 TestNetworkQualityEstimator estimator(variation_params); |
| 1126 estimator.AddRTTObserver(&rtt_observer); |
| 1127 |
| 1128 TestDelegate test_delegate; |
| 1129 TestURLRequestContext context(true); |
| 1130 context.set_network_quality_estimator(&estimator); |
| 1131 |
| 1132 scoped_ptr<HttpNetworkSession::Params> params(new HttpNetworkSession::Params); |
| 1133 // |estimator| should be notified of TCP RTT observations. |
| 1134 params->socket_performance_watcher_factory = &estimator; |
| 1135 context.set_http_network_session_params(std::move(params)); |
| 1136 context.Init(); |
| 1137 |
| 1138 EXPECT_EQ(0U, rtt_observer.observations().size()); |
| 1139 EXPECT_EQ(0U, estimator.watcher_reset_notification_received_count()); |
| 1140 |
| 1141 const size_t kNumRequests = 2; |
| 1142 |
| 1143 // Send two requests. Verify that the completion of each request generates at |
| 1144 // least one TCP RTT observation. |
| 1145 for (size_t i = 0; i < kNumRequests; ++i) { |
| 1146 size_t before_count_tcp_rtt_observations = 0; |
| 1147 for (const auto& observation : rtt_observer.observations()) { |
| 1148 if (observation.source == NetworkQualityEstimator::TCP) |
| 1149 ++before_count_tcp_rtt_observations; |
| 1150 } |
| 1151 |
| 1152 scoped_ptr<URLRequest> request(context.CreateRequest( |
| 1153 estimator.GetEchoURL(), DEFAULT_PRIORITY, &test_delegate)); |
| 1154 request->Start(); |
| 1155 base::RunLoop().Run(); |
| 1156 |
| 1157 size_t after_count_tcp_rtt_observations = 0; |
| 1158 for (const auto& observation : rtt_observer.observations()) { |
| 1159 if (observation.source == NetworkQualityEstimator::TCP) |
| 1160 ++after_count_tcp_rtt_observations; |
| 1161 } |
| 1162 // Exactly one notification should be received per socket performance |
| 1163 // watcher because the delay between notifications is currently set to a |
| 1164 // high value. |
| 1165 EXPECT_EQ(1u, after_count_tcp_rtt_observations - |
| 1166 before_count_tcp_rtt_observations) |
| 1167 << i; |
| 1168 } |
| 1169 // At least one reset should be received for each request. |
| 1170 EXPECT_LE(kNumRequests, |
| 1171 estimator.watcher_reset_notification_received_count()); |
| 1172 } |
| 1173 |
| 1096 } // namespace net | 1174 } // namespace net |
| OLD | NEW |