| OLD | NEW |
| (Empty) |
| 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 | |
| 3 // found in the LICENSE file. | |
| 4 | |
| 5 #include "net/base/network_quality_estimator.h" | |
| 6 | |
| 7 #include <stddef.h> | |
| 8 #include <stdint.h> | |
| 9 | |
| 10 #include <limits> | |
| 11 #include <map> | |
| 12 #include <string> | |
| 13 #include <utility> | |
| 14 #include <vector> | |
| 15 | |
| 16 #include "base/files/file_path.h" | |
| 17 #include "base/logging.h" | |
| 18 #include "base/macros.h" | |
| 19 #include "base/memory/scoped_ptr.h" | |
| 20 #include "base/metrics/histogram_samples.h" | |
| 21 #include "base/run_loop.h" | |
| 22 #include "base/strings/string_number_conversions.h" | |
| 23 #include "base/test/histogram_tester.h" | |
| 24 #include "base/time/time.h" | |
| 25 #include "build/build_config.h" | |
| 26 #include "net/base/external_estimate_provider.h" | |
| 27 #include "net/base/load_flags.h" | |
| 28 #include "net/base/network_change_notifier.h" | |
| 29 #include "net/base/socket_performance_watcher.h" | |
| 30 #include "net/base/socket_performance_watcher_factory.h" | |
| 31 #include "net/http/http_status_code.h" | |
| 32 #include "net/test/embedded_test_server/embedded_test_server.h" | |
| 33 #include "net/test/embedded_test_server/http_request.h" | |
| 34 #include "net/test/embedded_test_server/http_response.h" | |
| 35 #include "net/url_request/url_request.h" | |
| 36 #include "net/url_request/url_request_test_util.h" | |
| 37 #include "testing/gtest/include/gtest/gtest.h" | |
| 38 #include "url/gurl.h" | |
| 39 | |
| 40 namespace { | |
| 41 | |
| 42 // Helps in setting the current network type and id. | |
| 43 class TestNetworkQualityEstimator : public net::NetworkQualityEstimator { | |
| 44 public: | |
| 45 TestNetworkQualityEstimator( | |
| 46 const std::map<std::string, std::string>& variation_params, | |
| 47 scoped_ptr<net::ExternalEstimateProvider> external_estimate_provider) | |
| 48 : NetworkQualityEstimator(std::move(external_estimate_provider), | |
| 49 variation_params, | |
| 50 true, | |
| 51 true) { | |
| 52 // Set up embedded test server. | |
| 53 embedded_test_server_.ServeFilesFromDirectory( | |
| 54 base::FilePath(FILE_PATH_LITERAL("net/data/url_request_unittest"))); | |
| 55 EXPECT_TRUE(embedded_test_server_.Start()); | |
| 56 embedded_test_server_.RegisterRequestHandler(base::Bind( | |
| 57 &TestNetworkQualityEstimator::HandleRequest, base::Unretained(this))); | |
| 58 } | |
| 59 | |
| 60 explicit TestNetworkQualityEstimator( | |
| 61 const std::map<std::string, std::string>& variation_params) | |
| 62 : TestNetworkQualityEstimator( | |
| 63 variation_params, | |
| 64 scoped_ptr<net::ExternalEstimateProvider>()) {} | |
| 65 | |
| 66 ~TestNetworkQualityEstimator() override {} | |
| 67 | |
| 68 // Overrides the current network type and id. | |
| 69 // Notifies network quality estimator of change in connection. | |
| 70 void SimulateNetworkChangeTo(net::NetworkChangeNotifier::ConnectionType type, | |
| 71 std::string network_id) { | |
| 72 current_network_type_ = type; | |
| 73 current_network_id_ = network_id; | |
| 74 OnConnectionTypeChanged(type); | |
| 75 } | |
| 76 | |
| 77 // Called by embedded server when a HTTP request is received. | |
| 78 scoped_ptr<net::test_server::HttpResponse> HandleRequest( | |
| 79 const net::test_server::HttpRequest& request) { | |
| 80 scoped_ptr<net::test_server::BasicHttpResponse> http_response( | |
| 81 new net::test_server::BasicHttpResponse()); | |
| 82 http_response->set_code(net::HTTP_OK); | |
| 83 http_response->set_content("hello"); | |
| 84 http_response->set_content_type("text/plain"); | |
| 85 return std::move(http_response); | |
| 86 } | |
| 87 | |
| 88 // Returns a GURL hosted at embedded test server. | |
| 89 const GURL GetEchoURL() const { | |
| 90 return embedded_test_server_.GetURL("/echo.html"); | |
| 91 } | |
| 92 | |
| 93 using NetworkQualityEstimator::ReadCachedNetworkQualityEstimate; | |
| 94 using NetworkQualityEstimator::OnConnectionTypeChanged; | |
| 95 | |
| 96 private: | |
| 97 // NetworkQualityEstimator implementation that returns the overridden network | |
| 98 // id (instead of invoking platform APIs). | |
| 99 NetworkQualityEstimator::NetworkID GetCurrentNetworkID() const override { | |
| 100 return NetworkQualityEstimator::NetworkID(current_network_type_, | |
| 101 current_network_id_); | |
| 102 } | |
| 103 | |
| 104 net::NetworkChangeNotifier::ConnectionType current_network_type_; | |
| 105 std::string current_network_id_; | |
| 106 | |
| 107 // Embedded server used for testing. | |
| 108 net::EmbeddedTestServer embedded_test_server_; | |
| 109 | |
| 110 DISALLOW_COPY_AND_ASSIGN(TestNetworkQualityEstimator); | |
| 111 }; | |
| 112 | |
| 113 class TestRTTObserver : public net::NetworkQualityEstimator::RTTObserver { | |
| 114 public: | |
| 115 struct Observation { | |
| 116 Observation(int32_t ms, | |
| 117 const base::TimeTicks& ts, | |
| 118 net::NetworkQualityEstimator::ObservationSource src) | |
| 119 : rtt_ms(ms), timestamp(ts), source(src) {} | |
| 120 int32_t rtt_ms; | |
| 121 base::TimeTicks timestamp; | |
| 122 net::NetworkQualityEstimator::ObservationSource source; | |
| 123 }; | |
| 124 | |
| 125 std::vector<Observation>& observations() { return observations_; } | |
| 126 | |
| 127 // RttObserver implementation: | |
| 128 void OnRTTObservation( | |
| 129 int32_t rtt_ms, | |
| 130 const base::TimeTicks& timestamp, | |
| 131 net::NetworkQualityEstimator::ObservationSource source) override { | |
| 132 observations_.push_back(Observation(rtt_ms, timestamp, source)); | |
| 133 } | |
| 134 | |
| 135 private: | |
| 136 std::vector<Observation> observations_; | |
| 137 }; | |
| 138 | |
| 139 class TestThroughputObserver | |
| 140 : public net::NetworkQualityEstimator::ThroughputObserver { | |
| 141 public: | |
| 142 struct Observation { | |
| 143 Observation(int32_t kbps, | |
| 144 const base::TimeTicks& ts, | |
| 145 net::NetworkQualityEstimator::ObservationSource src) | |
| 146 : throughput_kbps(kbps), timestamp(ts), source(src) {} | |
| 147 int32_t throughput_kbps; | |
| 148 base::TimeTicks timestamp; | |
| 149 net::NetworkQualityEstimator::ObservationSource source; | |
| 150 }; | |
| 151 | |
| 152 std::vector<Observation>& observations() { return observations_; } | |
| 153 | |
| 154 // ThroughputObserver implementation: | |
| 155 void OnThroughputObservation( | |
| 156 int32_t throughput_kbps, | |
| 157 const base::TimeTicks& timestamp, | |
| 158 net::NetworkQualityEstimator::ObservationSource source) override { | |
| 159 observations_.push_back(Observation(throughput_kbps, timestamp, source)); | |
| 160 } | |
| 161 | |
| 162 private: | |
| 163 std::vector<Observation> observations_; | |
| 164 }; | |
| 165 | |
| 166 } // namespace | |
| 167 | |
| 168 namespace net { | |
| 169 | |
| 170 TEST(NetworkQualityEstimatorTest, TestKbpsRTTUpdates) { | |
| 171 base::HistogramTester histogram_tester; | |
| 172 // Enable requests to local host to be used for network quality estimation. | |
| 173 std::map<std::string, std::string> variation_params; | |
| 174 TestNetworkQualityEstimator estimator(variation_params); | |
| 175 | |
| 176 EXPECT_EQ(NetworkQualityEstimator::InvalidRTT(), | |
| 177 estimator.GetURLRequestRTTEstimateInternal(base::TimeTicks(), 100)); | |
| 178 EXPECT_EQ(NetworkQualityEstimator::kInvalidThroughput, | |
| 179 estimator.GetDownlinkThroughputKbpsEstimateInternal( | |
| 180 base::TimeTicks(), 100)); | |
| 181 | |
| 182 TestDelegate test_delegate; | |
| 183 TestURLRequestContext context(true); | |
| 184 context.set_network_quality_estimator(&estimator); | |
| 185 context.Init(); | |
| 186 | |
| 187 scoped_ptr<URLRequest> request(context.CreateRequest( | |
| 188 estimator.GetEchoURL(), DEFAULT_PRIORITY, &test_delegate)); | |
| 189 request->SetLoadFlags(request->load_flags() | LOAD_MAIN_FRAME); | |
| 190 request->Start(); | |
| 191 base::RunLoop().Run(); | |
| 192 | |
| 193 // Both RTT and downstream throughput should be updated. | |
| 194 EXPECT_NE(NetworkQualityEstimator::InvalidRTT(), | |
| 195 estimator.GetURLRequestRTTEstimateInternal(base::TimeTicks(), 100)); | |
| 196 EXPECT_NE(NetworkQualityEstimator::kInvalidThroughput, | |
| 197 estimator.GetDownlinkThroughputKbpsEstimateInternal( | |
| 198 base::TimeTicks(), 100)); | |
| 199 | |
| 200 base::TimeDelta rtt = NetworkQualityEstimator::InvalidRTT(); | |
| 201 int32_t kbps = NetworkQualityEstimator::kInvalidThroughput; | |
| 202 EXPECT_TRUE(estimator.GetURLRequestRTTEstimate(&rtt)); | |
| 203 EXPECT_TRUE(estimator.GetDownlinkThroughputKbpsEstimate(&kbps)); | |
| 204 EXPECT_NE(NetworkQualityEstimator::InvalidRTT(), rtt); | |
| 205 EXPECT_NE(NetworkQualityEstimator::kInvalidThroughput, kbps); | |
| 206 | |
| 207 EXPECT_NEAR(rtt.InMilliseconds(), | |
| 208 estimator.GetURLRequestRTTEstimateInternal(base::TimeTicks(), 100) | |
| 209 .InMilliseconds(), | |
| 210 1); | |
| 211 | |
| 212 // Check UMA histograms. | |
| 213 histogram_tester.ExpectTotalCount("NQE.PeakKbps.Unknown", 0); | |
| 214 histogram_tester.ExpectTotalCount("NQE.FastestRTT.Unknown", 0); | |
| 215 | |
| 216 histogram_tester.ExpectTotalCount("NQE.RatioEstimatedToActualRTT.Unknown", 0); | |
| 217 | |
| 218 scoped_ptr<URLRequest> request2(context.CreateRequest( | |
| 219 estimator.GetEchoURL(), DEFAULT_PRIORITY, &test_delegate)); | |
| 220 request2->SetLoadFlags(request2->load_flags() | LOAD_MAIN_FRAME); | |
| 221 request2->Start(); | |
| 222 base::RunLoop().Run(); | |
| 223 | |
| 224 histogram_tester.ExpectTotalCount("NQE.RTTObservations.Unknown", 1); | |
| 225 estimator.SimulateNetworkChangeTo( | |
| 226 NetworkChangeNotifier::ConnectionType::CONNECTION_WIFI, "test-1"); | |
| 227 histogram_tester.ExpectTotalCount("NQE.PeakKbps.Unknown", 1); | |
| 228 histogram_tester.ExpectTotalCount("NQE.FastestRTT.Unknown", 1); | |
| 229 | |
| 230 histogram_tester.ExpectTotalCount("NQE.RatioMedianRTT.WiFi", 0); | |
| 231 | |
| 232 histogram_tester.ExpectTotalCount("NQE.RTT.Percentile0.Unknown", 1); | |
| 233 histogram_tester.ExpectTotalCount("NQE.RTT.Percentile10.Unknown", 1); | |
| 234 histogram_tester.ExpectTotalCount("NQE.RTT.Percentile50.Unknown", 1); | |
| 235 histogram_tester.ExpectTotalCount("NQE.RTT.Percentile90.Unknown", 1); | |
| 236 histogram_tester.ExpectTotalCount("NQE.RTT.Percentile100.Unknown", 1); | |
| 237 | |
| 238 EXPECT_EQ(NetworkQualityEstimator::InvalidRTT(), | |
| 239 estimator.GetURLRequestRTTEstimateInternal(base::TimeTicks(), 100)); | |
| 240 EXPECT_EQ(NetworkQualityEstimator::kInvalidThroughput, | |
| 241 estimator.GetDownlinkThroughputKbpsEstimateInternal( | |
| 242 base::TimeTicks(), 100)); | |
| 243 | |
| 244 EXPECT_FALSE(estimator.GetURLRequestRTTEstimate(&rtt)); | |
| 245 EXPECT_FALSE(estimator.GetDownlinkThroughputKbpsEstimate(&kbps)); | |
| 246 EXPECT_EQ(NetworkQualityEstimator::InvalidRTT(), rtt); | |
| 247 EXPECT_EQ(NetworkQualityEstimator::kInvalidThroughput, kbps); | |
| 248 | |
| 249 estimator.SimulateNetworkChangeTo( | |
| 250 NetworkChangeNotifier::ConnectionType::CONNECTION_WIFI, std::string()); | |
| 251 histogram_tester.ExpectTotalCount("NQE.PeakKbps.Unknown", 1); | |
| 252 histogram_tester.ExpectTotalCount("NQE.FastestRTT.Unknown", 1); | |
| 253 | |
| 254 EXPECT_EQ(NetworkQualityEstimator::InvalidRTT(), | |
| 255 estimator.GetURLRequestRTTEstimateInternal(base::TimeTicks(), 100)); | |
| 256 EXPECT_EQ(NetworkQualityEstimator::kInvalidThroughput, | |
| 257 estimator.GetDownlinkThroughputKbpsEstimateInternal( | |
| 258 base::TimeTicks(), 100)); | |
| 259 | |
| 260 EXPECT_FALSE(estimator.GetURLRequestRTTEstimate(&rtt)); | |
| 261 EXPECT_FALSE(estimator.GetDownlinkThroughputKbpsEstimate(&kbps)); | |
| 262 } | |
| 263 | |
| 264 TEST(NetworkQualityEstimatorTest, StoreObservations) { | |
| 265 std::map<std::string, std::string> variation_params; | |
| 266 TestNetworkQualityEstimator estimator(variation_params); | |
| 267 | |
| 268 TestDelegate test_delegate; | |
| 269 TestURLRequestContext context(true); | |
| 270 context.set_network_quality_estimator(&estimator); | |
| 271 context.Init(); | |
| 272 | |
| 273 // Push 10 more observations than the maximum buffer size. | |
| 274 for (size_t i = 0; i < estimator.kMaximumObservationsBufferSize + 10U; ++i) { | |
| 275 scoped_ptr<URLRequest> request(context.CreateRequest( | |
| 276 estimator.GetEchoURL(), DEFAULT_PRIORITY, &test_delegate)); | |
| 277 request->Start(); | |
| 278 base::RunLoop().Run(); | |
| 279 } | |
| 280 | |
| 281 EXPECT_EQ(static_cast<size_t>( | |
| 282 NetworkQualityEstimator::kMaximumObservationsBufferSize), | |
| 283 estimator.downstream_throughput_kbps_observations_.Size()); | |
| 284 EXPECT_EQ(static_cast<size_t>( | |
| 285 NetworkQualityEstimator::kMaximumObservationsBufferSize), | |
| 286 estimator.rtt_observations_.Size()); | |
| 287 | |
| 288 // Verify that the stored observations are cleared on network change. | |
| 289 estimator.SimulateNetworkChangeTo( | |
| 290 NetworkChangeNotifier::ConnectionType::CONNECTION_WIFI, "test-2"); | |
| 291 EXPECT_EQ(0U, estimator.downstream_throughput_kbps_observations_.Size()); | |
| 292 EXPECT_EQ(0U, estimator.rtt_observations_.Size()); | |
| 293 } | |
| 294 | |
| 295 // Verifies that the percentiles are correctly computed. All observations have | |
| 296 // the same timestamp. Kbps percentiles must be in decreasing order. RTT | |
| 297 // percentiles must be in increasing order. | |
| 298 TEST(NetworkQualityEstimatorTest, PercentileSameTimestamps) { | |
| 299 std::map<std::string, std::string> variation_params; | |
| 300 TestNetworkQualityEstimator estimator(variation_params); | |
| 301 base::TimeTicks now = base::TimeTicks::Now(); | |
| 302 | |
| 303 // Network quality should be unavailable when no observations are available. | |
| 304 base::TimeDelta rtt; | |
| 305 EXPECT_FALSE(estimator.GetURLRequestRTTEstimate(&rtt)); | |
| 306 int32_t kbps; | |
| 307 EXPECT_FALSE(estimator.GetDownlinkThroughputKbpsEstimate(&kbps)); | |
| 308 | |
| 309 // Insert samples from {1,2,3,..., 100}. First insert odd samples, then even | |
| 310 // samples. This helps in verifying that the order of samples does not matter. | |
| 311 for (int i = 1; i <= 99; i += 2) { | |
| 312 estimator.downstream_throughput_kbps_observations_.AddObservation( | |
| 313 NetworkQualityEstimator::ThroughputObservation( | |
| 314 i, now, NetworkQualityEstimator::URL_REQUEST)); | |
| 315 estimator.rtt_observations_.AddObservation( | |
| 316 NetworkQualityEstimator::RttObservation( | |
| 317 base::TimeDelta::FromMilliseconds(i), now, | |
| 318 NetworkQualityEstimator::URL_REQUEST)); | |
| 319 EXPECT_TRUE(estimator.GetURLRequestRTTEstimate(&rtt)); | |
| 320 EXPECT_TRUE(estimator.GetDownlinkThroughputKbpsEstimate(&kbps)); | |
| 321 } | |
| 322 | |
| 323 for (int i = 1; i <= 99; i += 2) { | |
| 324 // Insert TCP observation which should not be taken into account when | |
| 325 // computing median RTT at HTTP layer. | |
| 326 estimator.rtt_observations_.AddObservation( | |
| 327 NetworkQualityEstimator::RttObservation( | |
| 328 base::TimeDelta::FromMilliseconds(10000), now, | |
| 329 NetworkQualityEstimator::TCP)); | |
| 330 | |
| 331 // Insert QUIC observation which should not be taken into account when | |
| 332 // computing median RTT at HTTP layer. | |
| 333 estimator.rtt_observations_.AddObservation( | |
| 334 NetworkQualityEstimator::RttObservation( | |
| 335 base::TimeDelta::FromMilliseconds(10000), now, | |
| 336 NetworkQualityEstimator::QUIC)); | |
| 337 } | |
| 338 | |
| 339 for (int i = 2; i <= 100; i += 2) { | |
| 340 estimator.downstream_throughput_kbps_observations_.AddObservation( | |
| 341 NetworkQualityEstimator::ThroughputObservation( | |
| 342 i, now, NetworkQualityEstimator::URL_REQUEST)); | |
| 343 estimator.rtt_observations_.AddObservation( | |
| 344 NetworkQualityEstimator::RttObservation( | |
| 345 base::TimeDelta::FromMilliseconds(i), now, | |
| 346 NetworkQualityEstimator::URL_REQUEST)); | |
| 347 EXPECT_TRUE(estimator.GetURLRequestRTTEstimate(&rtt)); | |
| 348 EXPECT_TRUE(estimator.GetDownlinkThroughputKbpsEstimate(&kbps)); | |
| 349 } | |
| 350 | |
| 351 for (int i = 0; i <= 100; ++i) { | |
| 352 // Checks if the difference between the two integers is less than 1. This is | |
| 353 // required because computed percentiles may be slightly different from | |
| 354 // what is expected due to floating point computation errors and integer | |
| 355 // rounding off errors. | |
| 356 EXPECT_NEAR(estimator.GetDownlinkThroughputKbpsEstimateInternal( | |
| 357 base::TimeTicks(), i), | |
| 358 100 - i, 1); | |
| 359 EXPECT_NEAR(estimator.GetURLRequestRTTEstimateInternal(base::TimeTicks(), i) | |
| 360 .InMilliseconds(), | |
| 361 i, 1); | |
| 362 } | |
| 363 | |
| 364 EXPECT_TRUE(estimator.GetURLRequestRTTEstimate(&rtt)); | |
| 365 EXPECT_TRUE(estimator.GetDownlinkThroughputKbpsEstimate(&kbps)); | |
| 366 // |network_quality| should be equal to the 50 percentile value. | |
| 367 EXPECT_TRUE(estimator.GetDownlinkThroughputKbpsEstimateInternal( | |
| 368 base::TimeTicks(), 50) > 0); | |
| 369 EXPECT_TRUE( | |
| 370 estimator.GetURLRequestRTTEstimateInternal(base::TimeTicks(), 50) != | |
| 371 NetworkQualityEstimator::InvalidRTT()); | |
| 372 } | |
| 373 | |
| 374 // Verifies that the percentiles are correctly computed. Observations have | |
| 375 // different timestamps with half the observations being very old and the rest | |
| 376 // of them being very recent. Percentiles should factor in recent observations | |
| 377 // much more heavily than older samples. Kbps percentiles must be in decreasing | |
| 378 // order. RTT percentiles must be in increasing order. | |
| 379 TEST(NetworkQualityEstimatorTest, PercentileDifferentTimestamps) { | |
| 380 std::map<std::string, std::string> variation_params; | |
| 381 TestNetworkQualityEstimator estimator(variation_params); | |
| 382 base::TimeTicks now = base::TimeTicks::Now(); | |
| 383 base::TimeTicks very_old = now - base::TimeDelta::FromDays(365); | |
| 384 | |
| 385 // First 50 samples have very old timestamp. | |
| 386 for (int i = 1; i <= 50; ++i) { | |
| 387 estimator.downstream_throughput_kbps_observations_.AddObservation( | |
| 388 NetworkQualityEstimator::ThroughputObservation( | |
| 389 i, very_old, NetworkQualityEstimator::URL_REQUEST)); | |
| 390 estimator.rtt_observations_.AddObservation( | |
| 391 NetworkQualityEstimator::RttObservation( | |
| 392 base::TimeDelta::FromMilliseconds(i), very_old, | |
| 393 NetworkQualityEstimator::URL_REQUEST)); | |
| 394 } | |
| 395 | |
| 396 // Next 50 (i.e., from 51 to 100) have recent timestamp. | |
| 397 for (int i = 51; i <= 100; ++i) { | |
| 398 estimator.downstream_throughput_kbps_observations_.AddObservation( | |
| 399 NetworkQualityEstimator::ThroughputObservation( | |
| 400 i, now, NetworkQualityEstimator::URL_REQUEST)); | |
| 401 estimator.rtt_observations_.AddObservation( | |
| 402 NetworkQualityEstimator::RttObservation( | |
| 403 base::TimeDelta::FromMilliseconds(i), now, | |
| 404 NetworkQualityEstimator::URL_REQUEST)); | |
| 405 } | |
| 406 | |
| 407 // Older samples have very little weight. So, all percentiles are >= 51 | |
| 408 // (lowest value among recent observations). | |
| 409 for (int i = 1; i < 100; ++i) { | |
| 410 // Checks if the difference between the two integers is less than 1. This is | |
| 411 // required because computed percentiles may be slightly different from | |
| 412 // what is expected due to floating point computation errors and integer | |
| 413 // rounding off errors. | |
| 414 EXPECT_NEAR(estimator.GetDownlinkThroughputKbpsEstimateInternal( | |
| 415 base::TimeTicks(), i), | |
| 416 51 + 0.49 * (100 - i), 1); | |
| 417 EXPECT_NEAR(estimator.GetURLRequestRTTEstimateInternal(base::TimeTicks(), i) | |
| 418 .InMilliseconds(), | |
| 419 51 + 0.49 * i, 1); | |
| 420 } | |
| 421 | |
| 422 EXPECT_EQ(NetworkQualityEstimator::InvalidRTT(), | |
| 423 estimator.GetURLRequestRTTEstimateInternal( | |
| 424 base::TimeTicks::Now() + base::TimeDelta::FromMinutes(10), 50)); | |
| 425 EXPECT_EQ(NetworkQualityEstimator::kInvalidThroughput, | |
| 426 estimator.GetDownlinkThroughputKbpsEstimateInternal( | |
| 427 base::TimeTicks::Now() + base::TimeDelta::FromMinutes(10), 50)); | |
| 428 } | |
| 429 | |
| 430 // This test notifies NetworkQualityEstimator of received data. Next, | |
| 431 // throughput and RTT percentiles are checked for correctness by doing simple | |
| 432 // verifications. | |
| 433 TEST(NetworkQualityEstimatorTest, ComputedPercentiles) { | |
| 434 std::map<std::string, std::string> variation_params; | |
| 435 TestNetworkQualityEstimator estimator(variation_params); | |
| 436 | |
| 437 EXPECT_EQ(NetworkQualityEstimator::InvalidRTT(), | |
| 438 estimator.GetURLRequestRTTEstimateInternal(base::TimeTicks(), 100)); | |
| 439 EXPECT_EQ(NetworkQualityEstimator::kInvalidThroughput, | |
| 440 estimator.GetDownlinkThroughputKbpsEstimateInternal( | |
| 441 base::TimeTicks(), 100)); | |
| 442 | |
| 443 TestDelegate test_delegate; | |
| 444 TestURLRequestContext context(true); | |
| 445 context.set_network_quality_estimator(&estimator); | |
| 446 context.Init(); | |
| 447 | |
| 448 // Number of observations are more than the maximum buffer size. | |
| 449 for (size_t i = 0; i < estimator.kMaximumObservationsBufferSize + 100U; ++i) { | |
| 450 scoped_ptr<URLRequest> request(context.CreateRequest( | |
| 451 estimator.GetEchoURL(), DEFAULT_PRIORITY, &test_delegate)); | |
| 452 request->Start(); | |
| 453 base::RunLoop().Run(); | |
| 454 } | |
| 455 | |
| 456 // Verify the percentiles through simple tests. | |
| 457 for (int i = 0; i <= 100; ++i) { | |
| 458 EXPECT_GT(estimator.GetDownlinkThroughputKbpsEstimateInternal( | |
| 459 base::TimeTicks(), i), | |
| 460 0); | |
| 461 EXPECT_LT(estimator.GetURLRequestRTTEstimateInternal(base::TimeTicks(), i), | |
| 462 base::TimeDelta::Max()); | |
| 463 | |
| 464 if (i != 0) { | |
| 465 // Throughput percentiles are in decreasing order. | |
| 466 EXPECT_LE(estimator.GetDownlinkThroughputKbpsEstimateInternal( | |
| 467 base::TimeTicks(), i), | |
| 468 estimator.GetDownlinkThroughputKbpsEstimateInternal( | |
| 469 base::TimeTicks(), i - 1)); | |
| 470 | |
| 471 // RTT percentiles are in increasing order. | |
| 472 EXPECT_GE( | |
| 473 estimator.GetURLRequestRTTEstimateInternal(base::TimeTicks(), i), | |
| 474 estimator.GetURLRequestRTTEstimateInternal(base::TimeTicks(), i - 1)); | |
| 475 } | |
| 476 } | |
| 477 } | |
| 478 | |
| 479 TEST(NetworkQualityEstimatorTest, ObtainOperatingParams) { | |
| 480 std::map<std::string, std::string> variation_params; | |
| 481 variation_params["Unknown.DefaultMedianKbps"] = "100"; | |
| 482 variation_params["WiFi.DefaultMedianKbps"] = "200"; | |
| 483 variation_params["2G.DefaultMedianKbps"] = "300"; | |
| 484 | |
| 485 variation_params["Unknown.DefaultMedianRTTMsec"] = "1000"; | |
| 486 variation_params["WiFi.DefaultMedianRTTMsec"] = "2000"; | |
| 487 // Negative variation value should not be used. | |
| 488 variation_params["2G.DefaultMedianRTTMsec"] = "-5"; | |
| 489 | |
| 490 TestNetworkQualityEstimator estimator(variation_params); | |
| 491 EXPECT_EQ(1U, estimator.downstream_throughput_kbps_observations_.Size()); | |
| 492 EXPECT_EQ(1U, estimator.rtt_observations_.Size()); | |
| 493 | |
| 494 base::TimeDelta rtt; | |
| 495 EXPECT_TRUE(estimator.GetURLRequestRTTEstimate(&rtt)); | |
| 496 int32_t kbps; | |
| 497 EXPECT_TRUE(estimator.GetDownlinkThroughputKbpsEstimate(&kbps)); | |
| 498 | |
| 499 EXPECT_EQ(100, kbps); | |
| 500 EXPECT_EQ(base::TimeDelta::FromMilliseconds(1000), rtt); | |
| 501 auto throughput_iterator = | |
| 502 estimator.downstream_throughput_kbps_observations_.observations_.begin(); | |
| 503 EXPECT_EQ(100, (*throughput_iterator).value); | |
| 504 auto rtt_iterator = estimator.rtt_observations_.observations_.begin(); | |
| 505 EXPECT_EQ(base::TimeDelta::FromMilliseconds(1000), (*rtt_iterator).value); | |
| 506 | |
| 507 // Simulate network change to Wi-Fi. | |
| 508 estimator.SimulateNetworkChangeTo( | |
| 509 NetworkChangeNotifier::ConnectionType::CONNECTION_WIFI, "test-1"); | |
| 510 EXPECT_EQ(1U, estimator.downstream_throughput_kbps_observations_.Size()); | |
| 511 EXPECT_EQ(1U, estimator.rtt_observations_.Size()); | |
| 512 | |
| 513 EXPECT_TRUE(estimator.GetURLRequestRTTEstimate(&rtt)); | |
| 514 EXPECT_TRUE(estimator.GetDownlinkThroughputKbpsEstimate(&kbps)); | |
| 515 EXPECT_EQ(200, kbps); | |
| 516 EXPECT_EQ(base::TimeDelta::FromMilliseconds(2000), rtt); | |
| 517 | |
| 518 throughput_iterator = | |
| 519 estimator.downstream_throughput_kbps_observations_.observations_.begin(); | |
| 520 EXPECT_EQ(200, (*throughput_iterator).value); | |
| 521 rtt_iterator = estimator.rtt_observations_.observations_.begin(); | |
| 522 EXPECT_EQ(base::TimeDelta::FromMilliseconds(2000), (*rtt_iterator).value); | |
| 523 | |
| 524 // Peak network quality should not be affected by the network quality | |
| 525 // estimator field trial. | |
| 526 EXPECT_EQ(NetworkQualityEstimator::InvalidRTT(), | |
| 527 estimator.peak_network_quality_.rtt()); | |
| 528 EXPECT_EQ(NetworkQualityEstimator::kInvalidThroughput, | |
| 529 estimator.peak_network_quality_.downstream_throughput_kbps()); | |
| 530 | |
| 531 // Simulate network change to 2G. Only the Kbps default estimate should be | |
| 532 // available. | |
| 533 estimator.SimulateNetworkChangeTo( | |
| 534 NetworkChangeNotifier::ConnectionType::CONNECTION_2G, "test-2"); | |
| 535 EXPECT_EQ(1U, estimator.downstream_throughput_kbps_observations_.Size()); | |
| 536 EXPECT_EQ(0U, estimator.rtt_observations_.Size()); | |
| 537 | |
| 538 EXPECT_FALSE(estimator.GetURLRequestRTTEstimate(&rtt)); | |
| 539 EXPECT_TRUE(estimator.GetDownlinkThroughputKbpsEstimate(&kbps)); | |
| 540 | |
| 541 throughput_iterator = | |
| 542 estimator.downstream_throughput_kbps_observations_.observations_.begin(); | |
| 543 EXPECT_EQ(300, (*throughput_iterator).value); | |
| 544 | |
| 545 // Simulate network change to 3G. Default estimates should be unavailable. | |
| 546 estimator.SimulateNetworkChangeTo( | |
| 547 NetworkChangeNotifier::ConnectionType::CONNECTION_3G, "test-3"); | |
| 548 | |
| 549 EXPECT_FALSE(estimator.GetURLRequestRTTEstimate(&rtt)); | |
| 550 EXPECT_FALSE(estimator.GetDownlinkThroughputKbpsEstimate(&kbps)); | |
| 551 EXPECT_EQ(0U, estimator.downstream_throughput_kbps_observations_.Size()); | |
| 552 EXPECT_EQ(0U, estimator.rtt_observations_.Size()); | |
| 553 } | |
| 554 | |
| 555 TEST(NetworkQualityEstimatorTest, HalfLifeParam) { | |
| 556 // Verifies if |weight_multiplier_per_second_| is set to correct value for | |
| 557 // various values of half life parameter. | |
| 558 std::map<std::string, std::string> variation_params; | |
| 559 { | |
| 560 // Half life parameter is not set. Default value of | |
| 561 // |weight_multiplier_per_second_| should be used. | |
| 562 TestNetworkQualityEstimator estimator(variation_params); | |
| 563 EXPECT_NEAR(0.988, estimator.downstream_throughput_kbps_observations_ | |
| 564 .weight_multiplier_per_second_, | |
| 565 0.001); | |
| 566 } | |
| 567 | |
| 568 variation_params["HalfLifeSeconds"] = "-100"; | |
| 569 { | |
| 570 // Half life parameter is set to a negative value. Default value of | |
| 571 // |weight_multiplier_per_second_| should be used. | |
| 572 TestNetworkQualityEstimator estimator(variation_params); | |
| 573 EXPECT_NEAR(0.988, estimator.downstream_throughput_kbps_observations_ | |
| 574 .weight_multiplier_per_second_, | |
| 575 0.001); | |
| 576 } | |
| 577 | |
| 578 variation_params["HalfLifeSeconds"] = "0"; | |
| 579 { | |
| 580 // Half life parameter is set to zero. Default value of | |
| 581 // |weight_multiplier_per_second_| should be used. | |
| 582 TestNetworkQualityEstimator estimator(variation_params); | |
| 583 EXPECT_NEAR(0.988, estimator.downstream_throughput_kbps_observations_ | |
| 584 .weight_multiplier_per_second_, | |
| 585 0.001); | |
| 586 } | |
| 587 | |
| 588 variation_params["HalfLifeSeconds"] = "10"; | |
| 589 { | |
| 590 // Half life parameter is set to a valid value. | |
| 591 TestNetworkQualityEstimator estimator(variation_params); | |
| 592 EXPECT_NEAR(0.933, estimator.downstream_throughput_kbps_observations_ | |
| 593 .weight_multiplier_per_second_, | |
| 594 0.001); | |
| 595 } | |
| 596 } | |
| 597 | |
| 598 // Test if the network estimates are cached when network change notification | |
| 599 // is invoked. | |
| 600 TEST(NetworkQualityEstimatorTest, TestCaching) { | |
| 601 std::map<std::string, std::string> variation_params; | |
| 602 TestNetworkQualityEstimator estimator(variation_params); | |
| 603 size_t expected_cache_size = 0; | |
| 604 EXPECT_EQ(expected_cache_size, estimator.cached_network_qualities_.size()); | |
| 605 | |
| 606 // Cache entry will not be added for (NONE, ""). | |
| 607 estimator.downstream_throughput_kbps_observations_.AddObservation( | |
| 608 NetworkQualityEstimator::ThroughputObservation( | |
| 609 1, base::TimeTicks::Now(), NetworkQualityEstimator::URL_REQUEST)); | |
| 610 estimator.rtt_observations_.AddObservation( | |
| 611 NetworkQualityEstimator::RttObservation( | |
| 612 base::TimeDelta::FromMilliseconds(1000), base::TimeTicks::Now(), | |
| 613 NetworkQualityEstimator::URL_REQUEST)); | |
| 614 estimator.SimulateNetworkChangeTo( | |
| 615 NetworkChangeNotifier::ConnectionType::CONNECTION_2G, "test-1"); | |
| 616 EXPECT_EQ(expected_cache_size, estimator.cached_network_qualities_.size()); | |
| 617 | |
| 618 // Entry will be added for (2G, "test1"). | |
| 619 // Also, set the network quality for (2G, "test1") so that it is stored in | |
| 620 // the cache. | |
| 621 estimator.downstream_throughput_kbps_observations_.AddObservation( | |
| 622 NetworkQualityEstimator::ThroughputObservation( | |
| 623 1, base::TimeTicks::Now(), NetworkQualityEstimator::URL_REQUEST)); | |
| 624 estimator.rtt_observations_.AddObservation( | |
| 625 NetworkQualityEstimator::RttObservation( | |
| 626 base::TimeDelta::FromMilliseconds(1000), base::TimeTicks::Now(), | |
| 627 NetworkQualityEstimator::URL_REQUEST)); | |
| 628 | |
| 629 estimator.SimulateNetworkChangeTo( | |
| 630 NetworkChangeNotifier::ConnectionType::CONNECTION_3G, "test-1"); | |
| 631 ++expected_cache_size; | |
| 632 EXPECT_EQ(expected_cache_size, estimator.cached_network_qualities_.size()); | |
| 633 | |
| 634 // Entry will be added for (3G, "test1"). | |
| 635 // Also, set the network quality for (3G, "test1") so that it is stored in | |
| 636 // the cache. | |
| 637 estimator.downstream_throughput_kbps_observations_.AddObservation( | |
| 638 NetworkQualityEstimator::ThroughputObservation( | |
| 639 2, base::TimeTicks::Now(), NetworkQualityEstimator::URL_REQUEST)); | |
| 640 estimator.rtt_observations_.AddObservation( | |
| 641 NetworkQualityEstimator::RttObservation( | |
| 642 base::TimeDelta::FromMilliseconds(500), base::TimeTicks::Now(), | |
| 643 NetworkQualityEstimator::URL_REQUEST)); | |
| 644 estimator.SimulateNetworkChangeTo( | |
| 645 NetworkChangeNotifier::ConnectionType::CONNECTION_3G, "test-2"); | |
| 646 ++expected_cache_size; | |
| 647 EXPECT_EQ(expected_cache_size, estimator.cached_network_qualities_.size()); | |
| 648 | |
| 649 // Entry will not be added for (3G, "test2"). | |
| 650 estimator.SimulateNetworkChangeTo( | |
| 651 NetworkChangeNotifier::ConnectionType::CONNECTION_2G, "test-1"); | |
| 652 EXPECT_EQ(expected_cache_size, estimator.cached_network_qualities_.size()); | |
| 653 | |
| 654 // Read the network quality for (2G, "test-1"). | |
| 655 EXPECT_TRUE(estimator.ReadCachedNetworkQualityEstimate()); | |
| 656 | |
| 657 base::TimeDelta rtt; | |
| 658 int32_t kbps; | |
| 659 EXPECT_TRUE(estimator.GetURLRequestRTTEstimate(&rtt)); | |
| 660 EXPECT_TRUE(estimator.GetDownlinkThroughputKbpsEstimate(&kbps)); | |
| 661 EXPECT_EQ(1, kbps); | |
| 662 EXPECT_EQ(base::TimeDelta::FromMilliseconds(1000), rtt); | |
| 663 // No new entry should be added for (2G, "test-1") since it already exists | |
| 664 // in the cache. | |
| 665 estimator.SimulateNetworkChangeTo( | |
| 666 NetworkChangeNotifier::ConnectionType::CONNECTION_3G, "test-1"); | |
| 667 EXPECT_EQ(expected_cache_size, estimator.cached_network_qualities_.size()); | |
| 668 | |
| 669 // Read the network quality for (3G, "test-1"). | |
| 670 EXPECT_TRUE(estimator.ReadCachedNetworkQualityEstimate()); | |
| 671 EXPECT_TRUE(estimator.GetURLRequestRTTEstimate(&rtt)); | |
| 672 EXPECT_TRUE(estimator.GetDownlinkThroughputKbpsEstimate(&kbps)); | |
| 673 EXPECT_EQ(2, kbps); | |
| 674 EXPECT_EQ(base::TimeDelta::FromMilliseconds(500), rtt); | |
| 675 // No new entry should be added for (3G, "test1") since it already exists | |
| 676 // in the cache. | |
| 677 estimator.SimulateNetworkChangeTo( | |
| 678 NetworkChangeNotifier::ConnectionType::CONNECTION_3G, "test-2"); | |
| 679 EXPECT_EQ(expected_cache_size, estimator.cached_network_qualities_.size()); | |
| 680 | |
| 681 // Reading quality of (3G, "test-2") should return false. | |
| 682 EXPECT_FALSE(estimator.ReadCachedNetworkQualityEstimate()); | |
| 683 | |
| 684 // Reading quality of (2G, "test-3") should return false. | |
| 685 estimator.SimulateNetworkChangeTo( | |
| 686 NetworkChangeNotifier::ConnectionType::CONNECTION_2G, "test-3"); | |
| 687 EXPECT_FALSE(estimator.ReadCachedNetworkQualityEstimate()); | |
| 688 } | |
| 689 | |
| 690 // Tests if the cache size remains bounded. Also, ensure that the cache is | |
| 691 // LRU. | |
| 692 TEST(NetworkQualityEstimatorTest, TestLRUCacheMaximumSize) { | |
| 693 std::map<std::string, std::string> variation_params; | |
| 694 TestNetworkQualityEstimator estimator(variation_params); | |
| 695 estimator.SimulateNetworkChangeTo( | |
| 696 net::NetworkChangeNotifier::ConnectionType::CONNECTION_WIFI, | |
| 697 std::string()); | |
| 698 EXPECT_EQ(0U, estimator.cached_network_qualities_.size()); | |
| 699 | |
| 700 // Add 100 more networks than the maximum size of the cache. | |
| 701 size_t network_count = | |
| 702 NetworkQualityEstimator::kMaximumNetworkQualityCacheSize + 100; | |
| 703 | |
| 704 base::TimeTicks update_time_of_network_100; | |
| 705 for (size_t i = 0; i < network_count; ++i) { | |
| 706 estimator.downstream_throughput_kbps_observations_.AddObservation( | |
| 707 NetworkQualityEstimator::ThroughputObservation( | |
| 708 2, base::TimeTicks::Now(), NetworkQualityEstimator::URL_REQUEST)); | |
| 709 estimator.rtt_observations_.AddObservation( | |
| 710 NetworkQualityEstimator::RttObservation( | |
| 711 base::TimeDelta::FromMilliseconds(500), base::TimeTicks::Now(), | |
| 712 NetworkQualityEstimator::URL_REQUEST)); | |
| 713 | |
| 714 if (i == 100) | |
| 715 update_time_of_network_100 = base::TimeTicks::Now(); | |
| 716 | |
| 717 estimator.SimulateNetworkChangeTo( | |
| 718 net::NetworkChangeNotifier::ConnectionType::CONNECTION_WIFI, | |
| 719 base::SizeTToString(i)); | |
| 720 if (i < NetworkQualityEstimator::kMaximumNetworkQualityCacheSize) | |
| 721 EXPECT_EQ(i, estimator.cached_network_qualities_.size()); | |
| 722 EXPECT_LE(estimator.cached_network_qualities_.size(), | |
| 723 static_cast<size_t>( | |
| 724 NetworkQualityEstimator::kMaximumNetworkQualityCacheSize)); | |
| 725 } | |
| 726 // One more call so that the last network is also written to cache. | |
| 727 estimator.downstream_throughput_kbps_observations_.AddObservation( | |
| 728 NetworkQualityEstimator::ThroughputObservation( | |
| 729 2, base::TimeTicks::Now(), NetworkQualityEstimator::URL_REQUEST)); | |
| 730 estimator.rtt_observations_.AddObservation( | |
| 731 NetworkQualityEstimator::RttObservation( | |
| 732 base::TimeDelta::FromMilliseconds(500), base::TimeTicks::Now(), | |
| 733 NetworkQualityEstimator::URL_REQUEST)); | |
| 734 estimator.SimulateNetworkChangeTo( | |
| 735 net::NetworkChangeNotifier::ConnectionType::CONNECTION_WIFI, | |
| 736 base::SizeTToString(network_count - 1)); | |
| 737 EXPECT_EQ(static_cast<size_t>( | |
| 738 NetworkQualityEstimator::kMaximumNetworkQualityCacheSize), | |
| 739 estimator.cached_network_qualities_.size()); | |
| 740 | |
| 741 // Test that the cache is LRU by examining its contents. Networks in cache | |
| 742 // must all be newer than the 100th network. | |
| 743 for (NetworkQualityEstimator::CachedNetworkQualities::iterator it = | |
| 744 estimator.cached_network_qualities_.begin(); | |
| 745 it != estimator.cached_network_qualities_.end(); ++it) { | |
| 746 EXPECT_GE((it->second).last_update_time_, update_time_of_network_100); | |
| 747 } | |
| 748 } | |
| 749 | |
| 750 TEST(NetworkQualityEstimatorTest, TestGetMedianRTTSince) { | |
| 751 std::map<std::string, std::string> variation_params; | |
| 752 TestNetworkQualityEstimator estimator(variation_params); | |
| 753 base::TimeTicks now = base::TimeTicks::Now(); | |
| 754 base::TimeTicks old = now - base::TimeDelta::FromMilliseconds(1); | |
| 755 ASSERT_NE(old, now); | |
| 756 | |
| 757 // First sample has very old timestamp. | |
| 758 estimator.downstream_throughput_kbps_observations_.AddObservation( | |
| 759 NetworkQualityEstimator::ThroughputObservation( | |
| 760 1, old, NetworkQualityEstimator::URL_REQUEST)); | |
| 761 estimator.rtt_observations_.AddObservation( | |
| 762 NetworkQualityEstimator::RttObservation( | |
| 763 base::TimeDelta::FromMilliseconds(1), old, | |
| 764 NetworkQualityEstimator::URL_REQUEST)); | |
| 765 | |
| 766 estimator.downstream_throughput_kbps_observations_.AddObservation( | |
| 767 NetworkQualityEstimator::ThroughputObservation( | |
| 768 100, now, NetworkQualityEstimator::URL_REQUEST)); | |
| 769 estimator.rtt_observations_.AddObservation( | |
| 770 NetworkQualityEstimator::RttObservation( | |
| 771 base::TimeDelta::FromMilliseconds(100), now, | |
| 772 NetworkQualityEstimator::URL_REQUEST)); | |
| 773 | |
| 774 base::TimeDelta rtt; | |
| 775 EXPECT_FALSE(estimator.GetRecentURLRequestRTTMedian( | |
| 776 now + base::TimeDelta::FromSeconds(10), &rtt)); | |
| 777 EXPECT_TRUE(estimator.GetRecentURLRequestRTTMedian(now, &rtt)); | |
| 778 EXPECT_EQ(100, rtt.InMilliseconds()); | |
| 779 | |
| 780 int32_t downstream_throughput_kbps; | |
| 781 EXPECT_FALSE(estimator.GetRecentMedianDownlinkThroughputKbps( | |
| 782 now + base::TimeDelta::FromSeconds(10), &downstream_throughput_kbps)); | |
| 783 EXPECT_TRUE(estimator.GetRecentMedianDownlinkThroughputKbps( | |
| 784 now, &downstream_throughput_kbps)); | |
| 785 EXPECT_EQ(100, downstream_throughput_kbps); | |
| 786 } | |
| 787 | |
| 788 // An external estimate provider that does not have a valid RTT or throughput | |
| 789 // estimate. | |
| 790 class InvalidExternalEstimateProvider : public ExternalEstimateProvider { | |
| 791 public: | |
| 792 InvalidExternalEstimateProvider() : get_rtt_count_(0) {} | |
| 793 ~InvalidExternalEstimateProvider() override {} | |
| 794 | |
| 795 // ExternalEstimateProvider implementation: | |
| 796 bool GetRTT(base::TimeDelta* rtt) const override { | |
| 797 DCHECK(rtt); | |
| 798 get_rtt_count_++; | |
| 799 return false; | |
| 800 } | |
| 801 | |
| 802 // ExternalEstimateProvider implementation: | |
| 803 bool GetDownstreamThroughputKbps( | |
| 804 int32_t* downstream_throughput_kbps) const override { | |
| 805 DCHECK(downstream_throughput_kbps); | |
| 806 return false; | |
| 807 } | |
| 808 | |
| 809 // ExternalEstimateProvider implementation: | |
| 810 bool GetUpstreamThroughputKbps( | |
| 811 int32_t* upstream_throughput_kbps) const override { | |
| 812 // NetworkQualityEstimator does not support upstream throughput. | |
| 813 ADD_FAILURE(); | |
| 814 return false; | |
| 815 } | |
| 816 | |
| 817 // ExternalEstimateProvider implementation: | |
| 818 bool GetTimeSinceLastUpdate( | |
| 819 base::TimeDelta* time_since_last_update) const override { | |
| 820 *time_since_last_update = base::TimeDelta::FromMilliseconds(1); | |
| 821 return true; | |
| 822 } | |
| 823 | |
| 824 // ExternalEstimateProvider implementation: | |
| 825 void SetUpdatedEstimateDelegate(UpdatedEstimateDelegate* delegate) override {} | |
| 826 | |
| 827 // ExternalEstimateProvider implementation: | |
| 828 void Update() const override {} | |
| 829 | |
| 830 size_t get_rtt_count() const { return get_rtt_count_; } | |
| 831 | |
| 832 private: | |
| 833 // Keeps track of number of times different functions were called. | |
| 834 mutable size_t get_rtt_count_; | |
| 835 | |
| 836 DISALLOW_COPY_AND_ASSIGN(InvalidExternalEstimateProvider); | |
| 837 }; | |
| 838 | |
| 839 // Tests if the RTT value from external estimate provider is discarded if the | |
| 840 // external estimate provider is invalid. | |
| 841 TEST(NetworkQualityEstimatorTest, InvalidExternalEstimateProvider) { | |
| 842 InvalidExternalEstimateProvider* invalid_external_estimate_provider = | |
| 843 new InvalidExternalEstimateProvider(); | |
| 844 scoped_ptr<ExternalEstimateProvider> external_estimate_provider( | |
| 845 invalid_external_estimate_provider); | |
| 846 | |
| 847 TestNetworkQualityEstimator estimator(std::map<std::string, std::string>(), | |
| 848 std::move(external_estimate_provider)); | |
| 849 | |
| 850 base::TimeDelta rtt; | |
| 851 int32_t kbps; | |
| 852 EXPECT_EQ(1U, invalid_external_estimate_provider->get_rtt_count()); | |
| 853 EXPECT_FALSE(estimator.GetURLRequestRTTEstimate(&rtt)); | |
| 854 EXPECT_FALSE(estimator.GetDownlinkThroughputKbpsEstimate(&kbps)); | |
| 855 } | |
| 856 | |
| 857 class TestExternalEstimateProvider : public ExternalEstimateProvider { | |
| 858 public: | |
| 859 TestExternalEstimateProvider(base::TimeDelta rtt, | |
| 860 int32_t downstream_throughput_kbps) | |
| 861 : rtt_(rtt), | |
| 862 downstream_throughput_kbps_(downstream_throughput_kbps), | |
| 863 time_since_last_update_(base::TimeDelta::FromSeconds(1)), | |
| 864 get_time_since_last_update_count_(0), | |
| 865 get_rtt_count_(0), | |
| 866 get_downstream_throughput_kbps_count_(0), | |
| 867 update_count_(0) {} | |
| 868 ~TestExternalEstimateProvider() override {} | |
| 869 | |
| 870 // ExternalEstimateProvider implementation: | |
| 871 bool GetRTT(base::TimeDelta* rtt) const override { | |
| 872 *rtt = rtt_; | |
| 873 get_rtt_count_++; | |
| 874 return true; | |
| 875 } | |
| 876 | |
| 877 // ExternalEstimateProvider implementation: | |
| 878 bool GetDownstreamThroughputKbps( | |
| 879 int32_t* downstream_throughput_kbps) const override { | |
| 880 *downstream_throughput_kbps = downstream_throughput_kbps_; | |
| 881 get_downstream_throughput_kbps_count_++; | |
| 882 return true; | |
| 883 } | |
| 884 | |
| 885 // ExternalEstimateProvider implementation: | |
| 886 bool GetUpstreamThroughputKbps( | |
| 887 int32_t* upstream_throughput_kbps) const override { | |
| 888 // NetworkQualityEstimator does not support upstream throughput. | |
| 889 ADD_FAILURE(); | |
| 890 return false; | |
| 891 } | |
| 892 | |
| 893 // ExternalEstimateProvider implementation: | |
| 894 bool GetTimeSinceLastUpdate( | |
| 895 base::TimeDelta* time_since_last_update) const override { | |
| 896 *time_since_last_update = time_since_last_update_; | |
| 897 get_time_since_last_update_count_++; | |
| 898 return true; | |
| 899 } | |
| 900 | |
| 901 // ExternalEstimateProvider implementation: | |
| 902 void SetUpdatedEstimateDelegate(UpdatedEstimateDelegate* delegate) override {} | |
| 903 | |
| 904 // ExternalEstimateProvider implementation: | |
| 905 void Update() const override { update_count_++; } | |
| 906 | |
| 907 void set_time_since_last_update(base::TimeDelta time_since_last_update) { | |
| 908 time_since_last_update_ = time_since_last_update; | |
| 909 } | |
| 910 | |
| 911 size_t get_time_since_last_update_count() const { | |
| 912 return get_time_since_last_update_count_; | |
| 913 } | |
| 914 size_t get_rtt_count() const { return get_rtt_count_; } | |
| 915 size_t get_downstream_throughput_kbps_count() const { | |
| 916 return get_downstream_throughput_kbps_count_; | |
| 917 } | |
| 918 size_t update_count() const { return update_count_; } | |
| 919 | |
| 920 private: | |
| 921 // RTT and downstream throughput estimates. | |
| 922 const base::TimeDelta rtt_; | |
| 923 const int32_t downstream_throughput_kbps_; | |
| 924 | |
| 925 base::TimeDelta time_since_last_update_; | |
| 926 | |
| 927 // Keeps track of number of times different functions were called. | |
| 928 mutable size_t get_time_since_last_update_count_; | |
| 929 mutable size_t get_rtt_count_; | |
| 930 mutable size_t get_downstream_throughput_kbps_count_; | |
| 931 mutable size_t update_count_; | |
| 932 | |
| 933 DISALLOW_COPY_AND_ASSIGN(TestExternalEstimateProvider); | |
| 934 }; | |
| 935 | |
| 936 // Tests if the external estimate provider is called in the constructor and | |
| 937 // on network change notification. | |
| 938 TEST(NetworkQualityEstimatorTest, TestExternalEstimateProvider) { | |
| 939 TestExternalEstimateProvider* test_external_estimate_provider = | |
| 940 new TestExternalEstimateProvider(base::TimeDelta::FromMilliseconds(1), | |
| 941 100); | |
| 942 scoped_ptr<ExternalEstimateProvider> external_estimate_provider( | |
| 943 test_external_estimate_provider); | |
| 944 std::map<std::string, std::string> variation_params; | |
| 945 TestNetworkQualityEstimator estimator(variation_params, | |
| 946 std::move(external_estimate_provider)); | |
| 947 | |
| 948 base::TimeDelta rtt; | |
| 949 int32_t kbps; | |
| 950 EXPECT_TRUE(estimator.GetURLRequestRTTEstimate(&rtt)); | |
| 951 EXPECT_TRUE(estimator.GetDownlinkThroughputKbpsEstimate(&kbps)); | |
| 952 | |
| 953 EXPECT_EQ( | |
| 954 1U, test_external_estimate_provider->get_time_since_last_update_count()); | |
| 955 EXPECT_EQ(1U, test_external_estimate_provider->get_rtt_count()); | |
| 956 EXPECT_EQ( | |
| 957 1U, | |
| 958 test_external_estimate_provider->get_downstream_throughput_kbps_count()); | |
| 959 | |
| 960 // Change network type to WiFi. Number of queries to External estimate | |
| 961 // provider must increment. | |
| 962 estimator.SimulateNetworkChangeTo( | |
| 963 NetworkChangeNotifier::ConnectionType::CONNECTION_WIFI, "test-1"); | |
| 964 EXPECT_TRUE(estimator.GetURLRequestRTTEstimate(&rtt)); | |
| 965 EXPECT_TRUE(estimator.GetDownlinkThroughputKbpsEstimate(&kbps)); | |
| 966 EXPECT_EQ( | |
| 967 2U, test_external_estimate_provider->get_time_since_last_update_count()); | |
| 968 EXPECT_EQ(2U, test_external_estimate_provider->get_rtt_count()); | |
| 969 EXPECT_EQ( | |
| 970 2U, | |
| 971 test_external_estimate_provider->get_downstream_throughput_kbps_count()); | |
| 972 | |
| 973 // Change network type to 2G. Number of queries to External estimate provider | |
| 974 // must increment. | |
| 975 estimator.SimulateNetworkChangeTo( | |
| 976 NetworkChangeNotifier::ConnectionType::CONNECTION_2G, "test-1"); | |
| 977 EXPECT_EQ( | |
| 978 3U, test_external_estimate_provider->get_time_since_last_update_count()); | |
| 979 EXPECT_EQ(3U, test_external_estimate_provider->get_rtt_count()); | |
| 980 EXPECT_EQ( | |
| 981 3U, | |
| 982 test_external_estimate_provider->get_downstream_throughput_kbps_count()); | |
| 983 | |
| 984 // Set the external estimate as old. Network Quality estimator should request | |
| 985 // an update on connection type change. | |
| 986 EXPECT_EQ(0U, test_external_estimate_provider->update_count()); | |
| 987 test_external_estimate_provider->set_time_since_last_update( | |
| 988 base::TimeDelta::Max()); | |
| 989 | |
| 990 estimator.SimulateNetworkChangeTo( | |
| 991 NetworkChangeNotifier::ConnectionType::CONNECTION_2G, "test-2"); | |
| 992 EXPECT_EQ( | |
| 993 4U, test_external_estimate_provider->get_time_since_last_update_count()); | |
| 994 EXPECT_EQ(3U, test_external_estimate_provider->get_rtt_count()); | |
| 995 EXPECT_EQ( | |
| 996 3U, | |
| 997 test_external_estimate_provider->get_downstream_throughput_kbps_count()); | |
| 998 EXPECT_EQ(1U, test_external_estimate_provider->update_count()); | |
| 999 | |
| 1000 // Estimates are unavailable because external estimate provider never | |
| 1001 // notifies network quality estimator of the updated estimates. | |
| 1002 EXPECT_FALSE(estimator.GetURLRequestRTTEstimate(&rtt)); | |
| 1003 EXPECT_FALSE(estimator.GetDownlinkThroughputKbpsEstimate(&kbps)); | |
| 1004 } | |
| 1005 | |
| 1006 // Tests if the estimate from the external estimate provider is merged with the | |
| 1007 // observations collected from the HTTP requests. | |
| 1008 TEST(NetworkQualityEstimatorTest, TestExternalEstimateProviderMergeEstimates) { | |
| 1009 const base::TimeDelta external_estimate_provider_rtt = | |
| 1010 base::TimeDelta::FromMilliseconds(1); | |
| 1011 const int32_t external_estimate_provider_downstream_throughput = 100; | |
| 1012 TestExternalEstimateProvider* test_external_estimate_provider = | |
| 1013 new TestExternalEstimateProvider( | |
| 1014 external_estimate_provider_rtt, | |
| 1015 external_estimate_provider_downstream_throughput); | |
| 1016 scoped_ptr<ExternalEstimateProvider> external_estimate_provider( | |
| 1017 test_external_estimate_provider); | |
| 1018 | |
| 1019 std::map<std::string, std::string> variation_params; | |
| 1020 TestNetworkQualityEstimator estimator(variation_params, | |
| 1021 std::move(external_estimate_provider)); | |
| 1022 | |
| 1023 base::TimeDelta rtt; | |
| 1024 // Estimate provided by network quality estimator should match the estimate | |
| 1025 // provided by external estimate provider. | |
| 1026 EXPECT_TRUE(estimator.GetURLRequestRTTEstimate(&rtt)); | |
| 1027 EXPECT_EQ(external_estimate_provider_rtt, rtt); | |
| 1028 | |
| 1029 int32_t kbps; | |
| 1030 EXPECT_TRUE(estimator.GetDownlinkThroughputKbpsEstimate(&kbps)); | |
| 1031 EXPECT_EQ(external_estimate_provider_downstream_throughput, kbps); | |
| 1032 | |
| 1033 EXPECT_EQ(1U, estimator.rtt_observations_.Size()); | |
| 1034 EXPECT_EQ(1U, estimator.downstream_throughput_kbps_observations_.Size()); | |
| 1035 | |
| 1036 TestDelegate test_delegate; | |
| 1037 TestURLRequestContext context(true); | |
| 1038 context.set_network_quality_estimator(&estimator); | |
| 1039 context.Init(); | |
| 1040 | |
| 1041 scoped_ptr<URLRequest> request(context.CreateRequest( | |
| 1042 estimator.GetEchoURL(), DEFAULT_PRIORITY, &test_delegate)); | |
| 1043 request->Start(); | |
| 1044 base::RunLoop().Run(); | |
| 1045 | |
| 1046 EXPECT_EQ(2U, estimator.rtt_observations_.Size()); | |
| 1047 EXPECT_EQ(2U, estimator.downstream_throughput_kbps_observations_.Size()); | |
| 1048 } | |
| 1049 | |
| 1050 TEST(NetworkQualityEstimatorTest, TestObservers) { | |
| 1051 TestRTTObserver rtt_observer; | |
| 1052 TestThroughputObserver throughput_observer; | |
| 1053 std::map<std::string, std::string> variation_params; | |
| 1054 TestNetworkQualityEstimator estimator(variation_params); | |
| 1055 estimator.AddRTTObserver(&rtt_observer); | |
| 1056 estimator.AddThroughputObserver(&throughput_observer); | |
| 1057 | |
| 1058 TestDelegate test_delegate; | |
| 1059 TestURLRequestContext context(true); | |
| 1060 context.set_network_quality_estimator(&estimator); | |
| 1061 context.Init(); | |
| 1062 | |
| 1063 EXPECT_EQ(0U, rtt_observer.observations().size()); | |
| 1064 EXPECT_EQ(0U, throughput_observer.observations().size()); | |
| 1065 base::TimeTicks then = base::TimeTicks::Now(); | |
| 1066 | |
| 1067 scoped_ptr<URLRequest> request(context.CreateRequest( | |
| 1068 estimator.GetEchoURL(), DEFAULT_PRIORITY, &test_delegate)); | |
| 1069 request->SetLoadFlags(request->load_flags() | LOAD_MAIN_FRAME); | |
| 1070 request->Start(); | |
| 1071 base::RunLoop().Run(); | |
| 1072 | |
| 1073 scoped_ptr<URLRequest> request2(context.CreateRequest( | |
| 1074 estimator.GetEchoURL(), DEFAULT_PRIORITY, &test_delegate)); | |
| 1075 request2->SetLoadFlags(request->load_flags() | LOAD_MAIN_FRAME); | |
| 1076 request2->Start(); | |
| 1077 base::RunLoop().Run(); | |
| 1078 | |
| 1079 // Both RTT and downstream throughput should be updated. | |
| 1080 base::TimeDelta rtt; | |
| 1081 EXPECT_TRUE(estimator.GetURLRequestRTTEstimate(&rtt)); | |
| 1082 | |
| 1083 int32_t throughput; | |
| 1084 EXPECT_TRUE(estimator.GetDownlinkThroughputKbpsEstimate(&throughput)); | |
| 1085 | |
| 1086 EXPECT_EQ(2U, rtt_observer.observations().size()); | |
| 1087 EXPECT_EQ(2U, throughput_observer.observations().size()); | |
| 1088 for (auto observation : rtt_observer.observations()) { | |
| 1089 EXPECT_LE(0, observation.rtt_ms); | |
| 1090 EXPECT_LE(0, (observation.timestamp - then).InMilliseconds()); | |
| 1091 EXPECT_EQ(NetworkQualityEstimator::URL_REQUEST, observation.source); | |
| 1092 } | |
| 1093 for (auto observation : throughput_observer.observations()) { | |
| 1094 EXPECT_LE(0, observation.throughput_kbps); | |
| 1095 EXPECT_LE(0, (observation.timestamp - then).InMilliseconds()); | |
| 1096 EXPECT_EQ(NetworkQualityEstimator::URL_REQUEST, observation.source); | |
| 1097 } | |
| 1098 | |
| 1099 // Verify that observations from TCP and QUIC are passed on to the observers. | |
| 1100 base::TimeDelta tcp_rtt(base::TimeDelta::FromMilliseconds(1)); | |
| 1101 base::TimeDelta quic_rtt(base::TimeDelta::FromMilliseconds(2)); | |
| 1102 | |
| 1103 scoped_ptr<SocketPerformanceWatcher> tcp_watcher = | |
| 1104 estimator.GetSocketPerformanceWatcherFactory() | |
| 1105 ->CreateSocketPerformanceWatcher( | |
| 1106 SocketPerformanceWatcherFactory::PROTOCOL_TCP); | |
| 1107 | |
| 1108 scoped_ptr<SocketPerformanceWatcher> quic_watcher = | |
| 1109 estimator.GetSocketPerformanceWatcherFactory() | |
| 1110 ->CreateSocketPerformanceWatcher( | |
| 1111 SocketPerformanceWatcherFactory::PROTOCOL_QUIC); | |
| 1112 | |
| 1113 tcp_watcher->OnUpdatedRTTAvailable(tcp_rtt); | |
| 1114 quic_watcher->OnUpdatedRTTAvailable(quic_rtt); | |
| 1115 | |
| 1116 base::RunLoop().RunUntilIdle(); | |
| 1117 | |
| 1118 EXPECT_EQ(4U, rtt_observer.observations().size()); | |
| 1119 EXPECT_EQ(2U, throughput_observer.observations().size()); | |
| 1120 | |
| 1121 EXPECT_EQ(tcp_rtt.InMilliseconds(), rtt_observer.observations().at(2).rtt_ms); | |
| 1122 EXPECT_EQ(quic_rtt.InMilliseconds(), | |
| 1123 rtt_observer.observations().at(3).rtt_ms); | |
| 1124 } | |
| 1125 | |
| 1126 // TestTCPSocketRTT requires kernel support for tcp_info struct, and so it is | |
| 1127 // enabled only on certain platforms. | |
| 1128 #if defined(TCP_INFO) || defined(OS_LINUX) | |
| 1129 #define MAYBE_TestTCPSocketRTT TestTCPSocketRTT | |
| 1130 #else | |
| 1131 #define MAYBE_TestTCPSocketRTT DISABLED_TestTCPSocketRTT | |
| 1132 #endif | |
| 1133 // Tests that the TCP socket notifies the Network Quality Estimator of TCP RTTs, | |
| 1134 // which in turn notifies registered RTT observers. | |
| 1135 TEST(NetworkQualityEstimatorTest, MAYBE_TestTCPSocketRTT) { | |
| 1136 TestRTTObserver rtt_observer; | |
| 1137 std::map<std::string, std::string> variation_params; | |
| 1138 TestNetworkQualityEstimator estimator(variation_params); | |
| 1139 estimator.AddRTTObserver(&rtt_observer); | |
| 1140 | |
| 1141 TestDelegate test_delegate; | |
| 1142 TestURLRequestContext context(true); | |
| 1143 context.set_network_quality_estimator(&estimator); | |
| 1144 | |
| 1145 scoped_ptr<HttpNetworkSession::Params> params(new HttpNetworkSession::Params); | |
| 1146 // |estimator| should be notified of TCP RTT observations. | |
| 1147 params->socket_performance_watcher_factory = | |
| 1148 estimator.GetSocketPerformanceWatcherFactory(); | |
| 1149 context.set_http_network_session_params(std::move(params)); | |
| 1150 context.Init(); | |
| 1151 | |
| 1152 EXPECT_EQ(0U, rtt_observer.observations().size()); | |
| 1153 | |
| 1154 // Send two requests. Verify that the completion of each request generates at | |
| 1155 // least one TCP RTT observation. | |
| 1156 for (size_t i = 0; i < 2; ++i) { | |
| 1157 size_t before_count_tcp_rtt_observations = 0; | |
| 1158 for (const auto& observation : rtt_observer.observations()) { | |
| 1159 if (observation.source == NetworkQualityEstimator::TCP) | |
| 1160 ++before_count_tcp_rtt_observations; | |
| 1161 } | |
| 1162 | |
| 1163 scoped_ptr<URLRequest> request(context.CreateRequest( | |
| 1164 estimator.GetEchoURL(), DEFAULT_PRIORITY, &test_delegate)); | |
| 1165 request->Start(); | |
| 1166 base::RunLoop().Run(); | |
| 1167 | |
| 1168 size_t after_count_tcp_rtt_observations = 0; | |
| 1169 for (const auto& observation : rtt_observer.observations()) { | |
| 1170 if (observation.source == NetworkQualityEstimator::TCP) | |
| 1171 ++after_count_tcp_rtt_observations; | |
| 1172 } | |
| 1173 // At least one notification should be received per socket performance | |
| 1174 // watcher. | |
| 1175 EXPECT_LE(1U, after_count_tcp_rtt_observations - | |
| 1176 before_count_tcp_rtt_observations) | |
| 1177 << i; | |
| 1178 } | |
| 1179 } | |
| 1180 | |
| 1181 } // namespace net | |
| OLD | NEW |