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