Roll src/third_party/WebKit eac3800:0237a66 (svn 202606:202607)
[chromium-blink-merge.git] / net / base / network_quality_estimator_unittest.cc
blob3f6854b00d7a2fe52e8199c996ff4769a8fc3cba
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.
5 #include "net/base/network_quality_estimator.h"
7 #include <stdint.h>
9 #include <limits>
10 #include <map>
12 #include "base/basictypes.h"
13 #include "base/files/file_path.h"
14 #include "base/logging.h"
15 #include "base/memory/scoped_ptr.h"
16 #include "base/metrics/histogram_samples.h"
17 #include "base/run_loop.h"
18 #include "base/strings/string_number_conversions.h"
19 #include "base/test/histogram_tester.h"
20 #include "base/time/time.h"
21 #include "build/build_config.h"
22 #include "net/base/external_estimate_provider.h"
23 #include "net/base/load_flags.h"
24 #include "net/base/network_change_notifier.h"
25 #include "net/http/http_status_code.h"
26 #include "net/test/embedded_test_server/embedded_test_server.h"
27 #include "net/test/embedded_test_server/http_request.h"
28 #include "net/test/embedded_test_server/http_response.h"
29 #include "net/url_request/url_request_test_util.h"
30 #include "testing/gtest/include/gtest/gtest.h"
31 #include "url/gurl.h"
33 namespace {
35 // Helps in setting the current network type and id.
36 class TestNetworkQualityEstimator : public net::NetworkQualityEstimator {
37 public:
38 TestNetworkQualityEstimator(
39 const std::map<std::string, std::string>& variation_params,
40 scoped_ptr<net::ExternalEstimateProvider> external_estimate_provider)
41 : NetworkQualityEstimator(external_estimate_provider.Pass(),
42 variation_params,
43 true,
44 true) {
45 // Set up embedded test server.
46 embedded_test_server_.ServeFilesFromDirectory(
47 base::FilePath(FILE_PATH_LITERAL("net/data/url_request_unittest")));
48 EXPECT_TRUE(embedded_test_server_.InitializeAndWaitUntilReady());
49 embedded_test_server_.RegisterRequestHandler(base::Bind(
50 &TestNetworkQualityEstimator::HandleRequest, base::Unretained(this)));
53 explicit TestNetworkQualityEstimator(
54 const std::map<std::string, std::string>& variation_params)
55 : TestNetworkQualityEstimator(
56 variation_params,
57 scoped_ptr<net::ExternalEstimateProvider>()) {}
59 ~TestNetworkQualityEstimator() override {}
61 // Overrides the current network type and id.
62 // Notifies network quality estimator of change in connection.
63 void SimulateNetworkChangeTo(net::NetworkChangeNotifier::ConnectionType type,
64 std::string network_id) {
65 current_network_type_ = type;
66 current_network_id_ = network_id;
67 OnConnectionTypeChanged(type);
70 // Called by embedded server when a HTTP request is received.
71 scoped_ptr<net::test_server::HttpResponse> HandleRequest(
72 const net::test_server::HttpRequest& request) {
73 scoped_ptr<net::test_server::BasicHttpResponse> http_response(
74 new net::test_server::BasicHttpResponse());
75 http_response->set_code(net::HTTP_OK);
76 http_response->set_content("hello");
77 http_response->set_content_type("text/plain");
78 return http_response.Pass();
81 // Returns a GURL hosted at embedded test server.
82 const GURL GetEchoURL() const {
83 return embedded_test_server_.GetURL("/echo.html");
86 using NetworkQualityEstimator::ReadCachedNetworkQualityEstimate;
87 using NetworkQualityEstimator::OnConnectionTypeChanged;
89 private:
90 // NetworkQualityEstimator implementation that returns the overridden network
91 // id (instead of invoking platform APIs).
92 NetworkQualityEstimator::NetworkID GetCurrentNetworkID() const override {
93 return NetworkQualityEstimator::NetworkID(current_network_type_,
94 current_network_id_);
97 net::NetworkChangeNotifier::ConnectionType current_network_type_;
98 std::string current_network_id_;
100 // Embedded server used for testing.
101 net::test_server::EmbeddedTestServer embedded_test_server_;
103 DISALLOW_COPY_AND_ASSIGN(TestNetworkQualityEstimator);
106 } // namespace
108 namespace net {
110 TEST(NetworkQualityEstimatorTest, TestKbpsRTTUpdates) {
111 base::HistogramTester histogram_tester;
112 // Enable requests to local host to be used for network quality estimation.
113 std::map<std::string, std::string> variation_params;
114 TestNetworkQualityEstimator estimator(variation_params);
116 EXPECT_EQ(NetworkQualityEstimator::InvalidRTT(),
117 estimator.GetRTTEstimateInternal(base::TimeTicks(), 100));
118 EXPECT_EQ(NetworkQualityEstimator::kInvalidThroughput,
119 estimator.GetDownlinkThroughputKbpsEstimateInternal(
120 base::TimeTicks(), 100));
122 TestDelegate test_delegate;
123 TestURLRequestContext context(true);
124 context.set_network_quality_estimator(&estimator);
125 context.Init();
127 scoped_ptr<URLRequest> request(context.CreateRequest(
128 estimator.GetEchoURL(), DEFAULT_PRIORITY, &test_delegate));
129 request->SetLoadFlags(request->load_flags() | LOAD_MAIN_FRAME);
130 request->Start();
131 base::RunLoop().Run();
133 // Both RTT and downstream throughput should be updated.
134 EXPECT_NE(NetworkQualityEstimator::InvalidRTT(),
135 estimator.GetRTTEstimateInternal(base::TimeTicks(), 100));
136 EXPECT_NE(NetworkQualityEstimator::kInvalidThroughput,
137 estimator.GetDownlinkThroughputKbpsEstimateInternal(
138 base::TimeTicks(), 100));
140 base::TimeDelta rtt = NetworkQualityEstimator::InvalidRTT();
141 int32_t kbps = NetworkQualityEstimator::kInvalidThroughput;
142 EXPECT_TRUE(estimator.GetRTTEstimate(&rtt));
143 EXPECT_TRUE(estimator.GetDownlinkThroughputKbpsEstimate(&kbps));
144 EXPECT_NE(NetworkQualityEstimator::InvalidRTT(), rtt);
145 EXPECT_NE(NetworkQualityEstimator::kInvalidThroughput, kbps);
147 EXPECT_NEAR(
148 rtt.InMilliseconds(),
149 estimator.GetRTTEstimateInternal(base::TimeTicks(), 100).InMilliseconds(),
152 // Check UMA histograms.
153 histogram_tester.ExpectTotalCount("NQE.PeakKbps.Unknown", 0);
154 histogram_tester.ExpectTotalCount("NQE.FastestRTT.Unknown", 0);
156 histogram_tester.ExpectTotalCount("NQE.RatioEstimatedToActualRTT.Unknown", 0);
158 scoped_ptr<URLRequest> request2(context.CreateRequest(
159 estimator.GetEchoURL(), DEFAULT_PRIORITY, &test_delegate));
160 request2->SetLoadFlags(request2->load_flags() | LOAD_MAIN_FRAME);
161 request2->Start();
162 base::RunLoop().Run();
164 histogram_tester.ExpectTotalCount("NQE.RTTObservations.Unknown", 1);
165 estimator.SimulateNetworkChangeTo(
166 NetworkChangeNotifier::ConnectionType::CONNECTION_WIFI, "test-1");
167 histogram_tester.ExpectTotalCount("NQE.PeakKbps.Unknown", 1);
168 histogram_tester.ExpectTotalCount("NQE.FastestRTT.Unknown", 1);
170 histogram_tester.ExpectTotalCount("NQE.RatioMedianRTT.WiFi", 0);
172 histogram_tester.ExpectTotalCount("NQE.RTT.Percentile0.Unknown", 1);
173 histogram_tester.ExpectTotalCount("NQE.RTT.Percentile10.Unknown", 1);
174 histogram_tester.ExpectTotalCount("NQE.RTT.Percentile50.Unknown", 1);
175 histogram_tester.ExpectTotalCount("NQE.RTT.Percentile90.Unknown", 1);
176 histogram_tester.ExpectTotalCount("NQE.RTT.Percentile100.Unknown", 1);
178 EXPECT_EQ(NetworkQualityEstimator::InvalidRTT(),
179 estimator.GetRTTEstimateInternal(base::TimeTicks(), 100));
180 EXPECT_EQ(NetworkQualityEstimator::kInvalidThroughput,
181 estimator.GetDownlinkThroughputKbpsEstimateInternal(
182 base::TimeTicks(), 100));
184 EXPECT_FALSE(estimator.GetRTTEstimate(&rtt));
185 EXPECT_FALSE(estimator.GetDownlinkThroughputKbpsEstimate(&kbps));
186 EXPECT_EQ(NetworkQualityEstimator::InvalidRTT(), rtt);
187 EXPECT_EQ(NetworkQualityEstimator::kInvalidThroughput, kbps);
189 estimator.SimulateNetworkChangeTo(
190 NetworkChangeNotifier::ConnectionType::CONNECTION_WIFI, std::string());
191 histogram_tester.ExpectTotalCount("NQE.PeakKbps.Unknown", 1);
192 histogram_tester.ExpectTotalCount("NQE.FastestRTT.Unknown", 1);
194 EXPECT_EQ(NetworkQualityEstimator::InvalidRTT(),
195 estimator.GetRTTEstimateInternal(base::TimeTicks(), 100));
196 EXPECT_EQ(NetworkQualityEstimator::kInvalidThroughput,
197 estimator.GetDownlinkThroughputKbpsEstimateInternal(
198 base::TimeTicks(), 100));
200 EXPECT_FALSE(estimator.GetRTTEstimate(&rtt));
201 EXPECT_FALSE(estimator.GetDownlinkThroughputKbpsEstimate(&kbps));
204 TEST(NetworkQualityEstimatorTest, StoreObservations) {
205 std::map<std::string, std::string> variation_params;
206 TestNetworkQualityEstimator estimator(variation_params);
208 TestDelegate test_delegate;
209 TestURLRequestContext context(true);
210 context.set_network_quality_estimator(&estimator);
211 context.Init();
213 // Push 10 more observations than the maximum buffer size.
214 for (size_t i = 0; i < estimator.kMaximumObservationsBufferSize + 10U; ++i) {
215 scoped_ptr<URLRequest> request(context.CreateRequest(
216 estimator.GetEchoURL(), DEFAULT_PRIORITY, &test_delegate));
217 request->Start();
218 base::RunLoop().Run();
221 EXPECT_EQ(static_cast<size_t>(
222 NetworkQualityEstimator::kMaximumObservationsBufferSize),
223 estimator.downstream_throughput_kbps_observations_.Size());
224 EXPECT_EQ(static_cast<size_t>(
225 NetworkQualityEstimator::kMaximumObservationsBufferSize),
226 estimator.rtt_msec_observations_.Size());
228 // Verify that the stored observations are cleared on network change.
229 estimator.SimulateNetworkChangeTo(
230 NetworkChangeNotifier::ConnectionType::CONNECTION_WIFI, "test-2");
231 EXPECT_EQ(0U, estimator.downstream_throughput_kbps_observations_.Size());
232 EXPECT_EQ(0U, estimator.rtt_msec_observations_.Size());
235 // Verifies that the percentiles are correctly computed. All observations have
236 // the same timestamp. Kbps percentiles must be in decreasing order. RTT
237 // percentiles must be in increasing order.
238 TEST(NetworkQualityEstimatorTest, PercentileSameTimestamps) {
239 std::map<std::string, std::string> variation_params;
240 TestNetworkQualityEstimator estimator(variation_params);
241 base::TimeTicks now = base::TimeTicks::Now();
243 // Network quality should be unavailable when no observations are available.
244 base::TimeDelta rtt;
245 EXPECT_FALSE(estimator.GetRTTEstimate(&rtt));
246 int32_t kbps;
247 EXPECT_FALSE(estimator.GetDownlinkThroughputKbpsEstimate(&kbps));
249 // Insert samples from {1,2,3,..., 100}. First insert odd samples, then even
250 // samples. This helps in verifying that the order of samples does not matter.
251 for (int i = 1; i <= 99; i += 2) {
252 estimator.downstream_throughput_kbps_observations_.AddObservation(
253 NetworkQualityEstimator::Observation(i, now));
254 estimator.rtt_msec_observations_.AddObservation(
255 NetworkQualityEstimator::Observation(i, now));
256 EXPECT_TRUE(estimator.GetRTTEstimate(&rtt));
257 EXPECT_TRUE(estimator.GetDownlinkThroughputKbpsEstimate(&kbps));
260 for (int i = 2; i <= 100; i += 2) {
261 estimator.downstream_throughput_kbps_observations_.AddObservation(
262 NetworkQualityEstimator::Observation(i, now));
263 estimator.rtt_msec_observations_.AddObservation(
264 NetworkQualityEstimator::Observation(i, now));
265 EXPECT_TRUE(estimator.GetRTTEstimate(&rtt));
266 EXPECT_TRUE(estimator.GetDownlinkThroughputKbpsEstimate(&kbps));
269 for (int i = 0; i <= 100; ++i) {
270 // Checks if the difference between the two integers is less than 1. This is
271 // required because computed percentiles may be slightly different from
272 // what is expected due to floating point computation errors and integer
273 // rounding off errors.
274 EXPECT_NEAR(estimator.GetDownlinkThroughputKbpsEstimateInternal(
275 base::TimeTicks(), i),
276 100 - i, 1);
277 EXPECT_NEAR(
278 estimator.GetRTTEstimateInternal(base::TimeTicks(), i).InMilliseconds(),
279 i, 1);
282 EXPECT_TRUE(estimator.GetRTTEstimate(&rtt));
283 EXPECT_TRUE(estimator.GetDownlinkThroughputKbpsEstimate(&kbps));
284 // |network_quality| should be equal to the 50 percentile value.
285 EXPECT_TRUE(estimator.GetDownlinkThroughputKbpsEstimateInternal(
286 base::TimeTicks(), 50) > 0);
287 EXPECT_TRUE(estimator.GetRTTEstimateInternal(base::TimeTicks(), 50) !=
288 NetworkQualityEstimator::InvalidRTT());
291 // Verifies that the percentiles are correctly computed. Observations have
292 // different timestamps with half the observations being very old and the rest
293 // of them being very recent. Percentiles should factor in recent observations
294 // much more heavily than older samples. Kbps percentiles must be in decreasing
295 // order. RTT percentiles must be in increasing order.
296 TEST(NetworkQualityEstimatorTest, PercentileDifferentTimestamps) {
297 std::map<std::string, std::string> variation_params;
298 TestNetworkQualityEstimator estimator(variation_params);
299 base::TimeTicks now = base::TimeTicks::Now();
300 base::TimeTicks very_old = base::TimeTicks::UnixEpoch();
302 // First 50 samples have very old timestamp.
303 for (int i = 1; i <= 50; ++i) {
304 estimator.downstream_throughput_kbps_observations_.AddObservation(
305 NetworkQualityEstimator::Observation(i, very_old));
306 estimator.rtt_msec_observations_.AddObservation(
307 NetworkQualityEstimator::Observation(i, very_old));
310 // Next 50 (i.e., from 51 to 100) have recent timestamp.
311 for (int i = 51; i <= 100; ++i) {
312 estimator.downstream_throughput_kbps_observations_.AddObservation(
313 NetworkQualityEstimator::Observation(i, now));
314 estimator.rtt_msec_observations_.AddObservation(
315 NetworkQualityEstimator::Observation(i, now));
318 // Older samples have very little weight. So, all percentiles are >= 51
319 // (lowest value among recent observations).
320 for (int i = 1; i < 100; ++i) {
321 // Checks if the difference between the two integers is less than 1. This is
322 // required because computed percentiles may be slightly different from
323 // what is expected due to floating point computation errors and integer
324 // rounding off errors.
325 EXPECT_NEAR(estimator.GetDownlinkThroughputKbpsEstimateInternal(
326 base::TimeTicks(), i),
327 51 + 0.49 * (100 - i), 1);
328 EXPECT_NEAR(
329 estimator.GetRTTEstimateInternal(base::TimeTicks(), i).InMilliseconds(),
330 51 + 0.49 * i, 1);
333 EXPECT_EQ(NetworkQualityEstimator::InvalidRTT(),
334 estimator.GetRTTEstimateInternal(
335 base::TimeTicks::Now() + base::TimeDelta::FromMinutes(10), 50));
336 EXPECT_EQ(NetworkQualityEstimator::kInvalidThroughput,
337 estimator.GetDownlinkThroughputKbpsEstimateInternal(
338 base::TimeTicks::Now() + base::TimeDelta::FromMinutes(10), 50));
341 // This test notifies NetworkQualityEstimator of received data. Next,
342 // throughput and RTT percentiles are checked for correctness by doing simple
343 // verifications.
344 TEST(NetworkQualityEstimatorTest, ComputedPercentiles) {
345 std::map<std::string, std::string> variation_params;
346 TestNetworkQualityEstimator estimator(variation_params);
348 EXPECT_EQ(NetworkQualityEstimator::InvalidRTT(),
349 estimator.GetRTTEstimateInternal(base::TimeTicks(), 100));
350 EXPECT_EQ(NetworkQualityEstimator::kInvalidThroughput,
351 estimator.GetDownlinkThroughputKbpsEstimateInternal(
352 base::TimeTicks(), 100));
354 TestDelegate test_delegate;
355 TestURLRequestContext context(true);
356 context.set_network_quality_estimator(&estimator);
357 context.Init();
359 // Number of observations are more than the maximum buffer size.
360 for (size_t i = 0; i < estimator.kMaximumObservationsBufferSize + 100U; ++i) {
361 scoped_ptr<URLRequest> request(context.CreateRequest(
362 estimator.GetEchoURL(), DEFAULT_PRIORITY, &test_delegate));
363 request->Start();
364 base::RunLoop().Run();
367 // Verify the percentiles through simple tests.
368 for (int i = 0; i <= 100; ++i) {
369 EXPECT_GT(estimator.GetDownlinkThroughputKbpsEstimateInternal(
370 base::TimeTicks(), i),
372 EXPECT_LT(estimator.GetRTTEstimateInternal(base::TimeTicks(), i),
373 base::TimeDelta::Max());
375 if (i != 0) {
376 // Throughput percentiles are in decreasing order.
377 EXPECT_LE(estimator.GetDownlinkThroughputKbpsEstimateInternal(
378 base::TimeTicks(), i),
379 estimator.GetDownlinkThroughputKbpsEstimateInternal(
380 base::TimeTicks(), i - 1));
382 // RTT percentiles are in increasing order.
383 EXPECT_GE(estimator.GetRTTEstimateInternal(base::TimeTicks(), i),
384 estimator.GetRTTEstimateInternal(base::TimeTicks(), i - 1));
389 TEST(NetworkQualityEstimatorTest, ObtainOperatingParams) {
390 std::map<std::string, std::string> variation_params;
391 variation_params["Unknown.DefaultMedianKbps"] = "100";
392 variation_params["WiFi.DefaultMedianKbps"] = "200";
393 variation_params["2G.DefaultMedianKbps"] = "300";
395 variation_params["Unknown.DefaultMedianRTTMsec"] = "1000";
396 variation_params["WiFi.DefaultMedianRTTMsec"] = "2000";
397 // Negative variation value should not be used.
398 variation_params["2G.DefaultMedianRTTMsec"] = "-5";
400 TestNetworkQualityEstimator estimator(variation_params);
401 EXPECT_EQ(1U, estimator.downstream_throughput_kbps_observations_.Size());
402 EXPECT_EQ(1U, estimator.rtt_msec_observations_.Size());
404 base::TimeDelta rtt;
405 EXPECT_TRUE(estimator.GetRTTEstimate(&rtt));
406 int32_t kbps;
407 EXPECT_TRUE(estimator.GetDownlinkThroughputKbpsEstimate(&kbps));
409 EXPECT_EQ(100, kbps);
410 EXPECT_EQ(base::TimeDelta::FromMilliseconds(1000), rtt);
411 auto it =
412 estimator.downstream_throughput_kbps_observations_.observations_.begin();
413 EXPECT_EQ(100, (*it).value);
414 it = estimator.rtt_msec_observations_.observations_.begin();
415 EXPECT_EQ(1000, (*it).value);
417 // Simulate network change to Wi-Fi.
418 estimator.SimulateNetworkChangeTo(
419 NetworkChangeNotifier::ConnectionType::CONNECTION_WIFI, "test-1");
420 EXPECT_EQ(1U, estimator.downstream_throughput_kbps_observations_.Size());
421 EXPECT_EQ(1U, estimator.rtt_msec_observations_.Size());
423 EXPECT_TRUE(estimator.GetRTTEstimate(&rtt));
424 EXPECT_TRUE(estimator.GetDownlinkThroughputKbpsEstimate(&kbps));
425 EXPECT_EQ(200, kbps);
426 EXPECT_EQ(base::TimeDelta::FromMilliseconds(2000), rtt);
428 it = estimator.downstream_throughput_kbps_observations_.observations_.begin();
429 EXPECT_EQ(200, (*it).value);
430 it = estimator.rtt_msec_observations_.observations_.begin();
431 EXPECT_EQ(2000, (*it).value);
433 // Peak network quality should not be affected by the network quality
434 // estimator field trial.
435 EXPECT_EQ(NetworkQualityEstimator::InvalidRTT(),
436 estimator.peak_network_quality_.rtt());
437 EXPECT_EQ(NetworkQualityEstimator::kInvalidThroughput,
438 estimator.peak_network_quality_.downstream_throughput_kbps());
440 // Simulate network change to 2G. Only the Kbps default estimate should be
441 // available.
442 estimator.SimulateNetworkChangeTo(
443 NetworkChangeNotifier::ConnectionType::CONNECTION_2G, "test-2");
444 EXPECT_EQ(1U, estimator.downstream_throughput_kbps_observations_.Size());
445 EXPECT_EQ(0U, estimator.rtt_msec_observations_.Size());
447 EXPECT_FALSE(estimator.GetRTTEstimate(&rtt));
448 EXPECT_TRUE(estimator.GetDownlinkThroughputKbpsEstimate(&kbps));
450 it = estimator.downstream_throughput_kbps_observations_.observations_.begin();
451 EXPECT_EQ(300, (*it).value);
453 // Simulate network change to 3G. Default estimates should be unavailable.
454 estimator.SimulateNetworkChangeTo(
455 NetworkChangeNotifier::ConnectionType::CONNECTION_3G, "test-3");
457 EXPECT_FALSE(estimator.GetRTTEstimate(&rtt));
458 EXPECT_FALSE(estimator.GetDownlinkThroughputKbpsEstimate(&kbps));
459 EXPECT_EQ(0U, estimator.downstream_throughput_kbps_observations_.Size());
460 EXPECT_EQ(0U, estimator.rtt_msec_observations_.Size());
463 TEST(NetworkQualityEstimatorTest, HalfLifeParam) {
464 // Verifies if |weight_multiplier_per_second_| is set to correct value for
465 // various values of half life parameter.
466 std::map<std::string, std::string> variation_params;
468 // Half life parameter is not set. Default value of
469 // |weight_multiplier_per_second_| should be used.
470 TestNetworkQualityEstimator estimator(variation_params);
471 EXPECT_NEAR(0.988, estimator.downstream_throughput_kbps_observations_
472 .weight_multiplier_per_second_,
473 0.001);
476 variation_params["HalfLifeSeconds"] = "-100";
478 // Half life parameter is set to a negative value. Default value of
479 // |weight_multiplier_per_second_| should be used.
480 TestNetworkQualityEstimator estimator(variation_params);
481 EXPECT_NEAR(0.988, estimator.downstream_throughput_kbps_observations_
482 .weight_multiplier_per_second_,
483 0.001);
486 variation_params["HalfLifeSeconds"] = "0";
488 // Half life parameter is set to zero. Default value of
489 // |weight_multiplier_per_second_| should be used.
490 TestNetworkQualityEstimator estimator(variation_params);
491 EXPECT_NEAR(0.988, estimator.downstream_throughput_kbps_observations_
492 .weight_multiplier_per_second_,
493 0.001);
496 variation_params["HalfLifeSeconds"] = "10";
498 // Half life parameter is set to a valid value.
499 TestNetworkQualityEstimator estimator(variation_params);
500 EXPECT_NEAR(0.933, estimator.downstream_throughput_kbps_observations_
501 .weight_multiplier_per_second_,
502 0.001);
506 // Test if the network estimates are cached when network change notification
507 // is invoked.
508 TEST(NetworkQualityEstimatorTest, TestCaching) {
509 std::map<std::string, std::string> variation_params;
510 TestNetworkQualityEstimator estimator(variation_params);
511 size_t expected_cache_size = 0;
512 EXPECT_EQ(expected_cache_size, estimator.cached_network_qualities_.size());
514 // Cache entry will not be added for (NONE, "").
515 estimator.downstream_throughput_kbps_observations_.AddObservation(
516 NetworkQualityEstimator::Observation(1, base::TimeTicks::Now()));
517 estimator.rtt_msec_observations_.AddObservation(
518 NetworkQualityEstimator::Observation(1000, base::TimeTicks::Now()));
519 estimator.SimulateNetworkChangeTo(
520 NetworkChangeNotifier::ConnectionType::CONNECTION_2G, "test-1");
521 EXPECT_EQ(expected_cache_size, estimator.cached_network_qualities_.size());
523 // Entry will be added for (2G, "test1").
524 // Also, set the network quality for (2G, "test1") so that it is stored in
525 // the cache.
526 estimator.downstream_throughput_kbps_observations_.AddObservation(
527 NetworkQualityEstimator::Observation(1, base::TimeTicks::Now()));
528 estimator.rtt_msec_observations_.AddObservation(
529 NetworkQualityEstimator::Observation(1000, base::TimeTicks::Now()));
531 estimator.SimulateNetworkChangeTo(
532 NetworkChangeNotifier::ConnectionType::CONNECTION_3G, "test-1");
533 ++expected_cache_size;
534 EXPECT_EQ(expected_cache_size, estimator.cached_network_qualities_.size());
536 // Entry will be added for (3G, "test1").
537 // Also, set the network quality for (3G, "test1") so that it is stored in
538 // the cache.
539 estimator.downstream_throughput_kbps_observations_.AddObservation(
540 NetworkQualityEstimator::Observation(2, base::TimeTicks::Now()));
541 estimator.rtt_msec_observations_.AddObservation(
542 NetworkQualityEstimator::Observation(500, base::TimeTicks::Now()));
543 estimator.SimulateNetworkChangeTo(
544 NetworkChangeNotifier::ConnectionType::CONNECTION_3G, "test-2");
545 ++expected_cache_size;
546 EXPECT_EQ(expected_cache_size, estimator.cached_network_qualities_.size());
548 // Entry will not be added for (3G, "test2").
549 estimator.SimulateNetworkChangeTo(
550 NetworkChangeNotifier::ConnectionType::CONNECTION_2G, "test-1");
551 EXPECT_EQ(expected_cache_size, estimator.cached_network_qualities_.size());
553 // Read the network quality for (2G, "test-1").
554 EXPECT_TRUE(estimator.ReadCachedNetworkQualityEstimate());
556 base::TimeDelta rtt;
557 int32_t kbps;
558 EXPECT_TRUE(estimator.GetRTTEstimate(&rtt));
559 EXPECT_TRUE(estimator.GetDownlinkThroughputKbpsEstimate(&kbps));
560 EXPECT_EQ(1, kbps);
561 EXPECT_EQ(base::TimeDelta::FromMilliseconds(1000), rtt);
562 // No new entry should be added for (2G, "test-1") since it already exists
563 // in the cache.
564 estimator.SimulateNetworkChangeTo(
565 NetworkChangeNotifier::ConnectionType::CONNECTION_3G, "test-1");
566 EXPECT_EQ(expected_cache_size, estimator.cached_network_qualities_.size());
568 // Read the network quality for (3G, "test-1").
569 EXPECT_TRUE(estimator.ReadCachedNetworkQualityEstimate());
570 EXPECT_TRUE(estimator.GetRTTEstimate(&rtt));
571 EXPECT_TRUE(estimator.GetDownlinkThroughputKbpsEstimate(&kbps));
572 EXPECT_EQ(2, kbps);
573 EXPECT_EQ(base::TimeDelta::FromMilliseconds(500), rtt);
574 // No new entry should be added for (3G, "test1") since it already exists
575 // in the cache.
576 estimator.SimulateNetworkChangeTo(
577 NetworkChangeNotifier::ConnectionType::CONNECTION_3G, "test-2");
578 EXPECT_EQ(expected_cache_size, estimator.cached_network_qualities_.size());
580 // Reading quality of (3G, "test-2") should return false.
581 EXPECT_FALSE(estimator.ReadCachedNetworkQualityEstimate());
583 // Reading quality of (2G, "test-3") should return false.
584 estimator.SimulateNetworkChangeTo(
585 NetworkChangeNotifier::ConnectionType::CONNECTION_2G, "test-3");
586 EXPECT_FALSE(estimator.ReadCachedNetworkQualityEstimate());
589 // Tests if the cache size remains bounded. Also, ensure that the cache is
590 // LRU.
591 TEST(NetworkQualityEstimatorTest, TestLRUCacheMaximumSize) {
592 std::map<std::string, std::string> variation_params;
593 TestNetworkQualityEstimator estimator(variation_params);
594 estimator.SimulateNetworkChangeTo(
595 net::NetworkChangeNotifier::ConnectionType::CONNECTION_WIFI,
596 std::string());
597 EXPECT_EQ(0U, estimator.cached_network_qualities_.size());
599 // Add 100 more networks than the maximum size of the cache.
600 size_t network_count =
601 NetworkQualityEstimator::kMaximumNetworkQualityCacheSize + 100;
603 base::TimeTicks update_time_of_network_100;
604 for (size_t i = 0; i < network_count; ++i) {
605 estimator.downstream_throughput_kbps_observations_.AddObservation(
606 NetworkQualityEstimator::Observation(2, base::TimeTicks::Now()));
607 estimator.rtt_msec_observations_.AddObservation(
608 NetworkQualityEstimator::Observation(500, base::TimeTicks::Now()));
610 if (i == 100)
611 update_time_of_network_100 = base::TimeTicks::Now();
613 estimator.SimulateNetworkChangeTo(
614 net::NetworkChangeNotifier::ConnectionType::CONNECTION_WIFI,
615 base::SizeTToString(i));
616 if (i < NetworkQualityEstimator::kMaximumNetworkQualityCacheSize)
617 EXPECT_EQ(i, estimator.cached_network_qualities_.size());
618 EXPECT_LE(estimator.cached_network_qualities_.size(),
619 static_cast<size_t>(
620 NetworkQualityEstimator::kMaximumNetworkQualityCacheSize));
622 // One more call so that the last network is also written to cache.
623 estimator.downstream_throughput_kbps_observations_.AddObservation(
624 NetworkQualityEstimator::Observation(2, base::TimeTicks::Now()));
625 estimator.rtt_msec_observations_.AddObservation(
626 NetworkQualityEstimator::Observation(500, base::TimeTicks::Now()));
627 estimator.SimulateNetworkChangeTo(
628 net::NetworkChangeNotifier::ConnectionType::CONNECTION_WIFI,
629 base::SizeTToString(network_count - 1));
630 EXPECT_EQ(static_cast<size_t>(
631 NetworkQualityEstimator::kMaximumNetworkQualityCacheSize),
632 estimator.cached_network_qualities_.size());
634 // Test that the cache is LRU by examining its contents. Networks in cache
635 // must all be newer than the 100th network.
636 for (NetworkQualityEstimator::CachedNetworkQualities::iterator it =
637 estimator.cached_network_qualities_.begin();
638 it != estimator.cached_network_qualities_.end(); ++it) {
639 EXPECT_GE((it->second).last_update_time_, update_time_of_network_100);
643 TEST(NetworkQualityEstimatorTest, TestGetMedianRTTSince) {
644 std::map<std::string, std::string> variation_params;
645 TestNetworkQualityEstimator estimator(variation_params);
646 base::TimeTicks now = base::TimeTicks::Now();
647 base::TimeTicks old =
648 base::TimeTicks::Now() - base::TimeDelta::FromMilliseconds(1);
650 // First sample has very old timestamp.
651 estimator.downstream_throughput_kbps_observations_.AddObservation(
652 NetworkQualityEstimator::Observation(1, old));
653 estimator.rtt_msec_observations_.AddObservation(
654 NetworkQualityEstimator::Observation(1, old));
656 estimator.downstream_throughput_kbps_observations_.AddObservation(
657 NetworkQualityEstimator::Observation(100, now));
658 estimator.rtt_msec_observations_.AddObservation(
659 NetworkQualityEstimator::Observation(100, now));
661 base::TimeDelta rtt;
662 EXPECT_FALSE(estimator.GetRecentMedianRTT(
663 now + base::TimeDelta::FromSeconds(10), &rtt));
664 EXPECT_TRUE(estimator.GetRecentMedianRTT(now, &rtt));
665 EXPECT_EQ(100, rtt.InMilliseconds());
667 int32_t downstream_throughput_kbps;
668 EXPECT_FALSE(estimator.GetRecentMedianDownlinkThroughputKbps(
669 now + base::TimeDelta::FromSeconds(10), &downstream_throughput_kbps));
670 EXPECT_TRUE(estimator.GetRecentMedianDownlinkThroughputKbps(
671 now, &downstream_throughput_kbps));
672 EXPECT_EQ(100, downstream_throughput_kbps);
675 // An external estimate provider that does not have a valid RTT or throughput
676 // estimate.
677 class InvalidExternalEstimateProvider : public ExternalEstimateProvider {
678 public:
679 InvalidExternalEstimateProvider() : get_rtt_count_(0) {}
680 ~InvalidExternalEstimateProvider() override {}
682 // ExternalEstimateProvider implementation:
683 bool GetRTT(base::TimeDelta* rtt) const override {
684 DCHECK(rtt);
685 get_rtt_count_++;
686 return false;
689 // ExternalEstimateProvider implementation:
690 bool GetDownstreamThroughputKbps(
691 int32_t* downstream_throughput_kbps) const override {
692 DCHECK(downstream_throughput_kbps);
693 return false;
696 // ExternalEstimateProvider implementation:
697 bool GetUpstreamThroughputKbps(
698 int32_t* upstream_throughput_kbps) const override {
699 // NetworkQualityEstimator does not support upstream throughput.
700 ADD_FAILURE();
701 return false;
704 // ExternalEstimateProvider implementation:
705 bool GetTimeSinceLastUpdate(
706 base::TimeDelta* time_since_last_update) const override {
707 *time_since_last_update = base::TimeDelta::FromMilliseconds(1);
708 return true;
711 // ExternalEstimateProvider implementation:
712 void SetUpdatedEstimateDelegate(UpdatedEstimateDelegate* delegate) override {}
714 // ExternalEstimateProvider implementation:
715 void Update() const override {}
717 size_t get_rtt_count() const { return get_rtt_count_; }
719 private:
720 // Keeps track of number of times different functions were called.
721 mutable size_t get_rtt_count_;
723 DISALLOW_COPY_AND_ASSIGN(InvalidExternalEstimateProvider);
726 // Tests if the RTT value from external estimate provider is discarded if the
727 // external estimate provider is invalid.
728 TEST(NetworkQualityEstimatorTest, InvalidExternalEstimateProvider) {
729 InvalidExternalEstimateProvider* invalid_external_estimate_provider =
730 new InvalidExternalEstimateProvider();
731 scoped_ptr<ExternalEstimateProvider> external_estimate_provider(
732 invalid_external_estimate_provider);
734 TestNetworkQualityEstimator estimator(std::map<std::string, std::string>(),
735 external_estimate_provider.Pass());
737 base::TimeDelta rtt;
738 int32_t kbps;
739 EXPECT_EQ(1U, invalid_external_estimate_provider->get_rtt_count());
740 EXPECT_FALSE(estimator.GetRTTEstimate(&rtt));
741 EXPECT_FALSE(estimator.GetDownlinkThroughputKbpsEstimate(&kbps));
744 class TestExternalEstimateProvider : public ExternalEstimateProvider {
745 public:
746 TestExternalEstimateProvider(base::TimeDelta rtt,
747 int32_t downstream_throughput_kbps)
748 : rtt_(rtt),
749 downstream_throughput_kbps_(downstream_throughput_kbps),
750 time_since_last_update_(base::TimeDelta::FromSeconds(1)),
751 get_time_since_last_update_count_(0),
752 get_rtt_count_(0),
753 get_downstream_throughput_kbps_count_(0),
754 update_count_(0) {}
755 ~TestExternalEstimateProvider() override {}
757 // ExternalEstimateProvider implementation:
758 bool GetRTT(base::TimeDelta* rtt) const override {
759 *rtt = rtt_;
760 get_rtt_count_++;
761 return true;
764 // ExternalEstimateProvider implementation:
765 bool GetDownstreamThroughputKbps(
766 int32_t* downstream_throughput_kbps) const override {
767 *downstream_throughput_kbps = downstream_throughput_kbps_;
768 get_downstream_throughput_kbps_count_++;
769 return true;
772 // ExternalEstimateProvider implementation:
773 bool GetUpstreamThroughputKbps(
774 int32_t* upstream_throughput_kbps) const override {
775 // NetworkQualityEstimator does not support upstream throughput.
776 ADD_FAILURE();
777 return false;
780 // ExternalEstimateProvider implementation:
781 bool GetTimeSinceLastUpdate(
782 base::TimeDelta* time_since_last_update) const override {
783 *time_since_last_update = time_since_last_update_;
784 get_time_since_last_update_count_++;
785 return true;
788 // ExternalEstimateProvider implementation:
789 void SetUpdatedEstimateDelegate(UpdatedEstimateDelegate* delegate) override {}
791 // ExternalEstimateProvider implementation:
792 void Update() const override { update_count_++; }
794 void set_time_since_last_update(base::TimeDelta time_since_last_update) {
795 time_since_last_update_ = time_since_last_update;
798 size_t get_time_since_last_update_count() const {
799 return get_time_since_last_update_count_;
801 size_t get_rtt_count() const { return get_rtt_count_; }
802 size_t get_downstream_throughput_kbps_count() const {
803 return get_downstream_throughput_kbps_count_;
805 size_t update_count() const { return update_count_; }
807 private:
808 // RTT and downstream throughput estimates.
809 const base::TimeDelta rtt_;
810 const int32_t downstream_throughput_kbps_;
812 base::TimeDelta time_since_last_update_;
814 // Keeps track of number of times different functions were called.
815 mutable size_t get_time_since_last_update_count_;
816 mutable size_t get_rtt_count_;
817 mutable size_t get_downstream_throughput_kbps_count_;
818 mutable size_t update_count_;
820 DISALLOW_COPY_AND_ASSIGN(TestExternalEstimateProvider);
823 // Tests if the external estimate provider is called in the constructor and
824 // on network change notification.
825 TEST(NetworkQualityEstimatorTest, TestExternalEstimateProvider) {
826 TestExternalEstimateProvider* test_external_estimate_provider =
827 new TestExternalEstimateProvider(base::TimeDelta::FromMilliseconds(1),
828 100);
829 scoped_ptr<ExternalEstimateProvider> external_estimate_provider(
830 test_external_estimate_provider);
831 std::map<std::string, std::string> variation_params;
832 TestNetworkQualityEstimator estimator(variation_params,
833 external_estimate_provider.Pass());
835 base::TimeDelta rtt;
836 int32_t kbps;
837 EXPECT_TRUE(estimator.GetRTTEstimate(&rtt));
838 EXPECT_TRUE(estimator.GetDownlinkThroughputKbpsEstimate(&kbps));
840 EXPECT_EQ(
841 1U, test_external_estimate_provider->get_time_since_last_update_count());
842 EXPECT_EQ(1U, test_external_estimate_provider->get_rtt_count());
843 EXPECT_EQ(
845 test_external_estimate_provider->get_downstream_throughput_kbps_count());
847 // Change network type to WiFi. Number of queries to External estimate
848 // provider must increment.
849 estimator.SimulateNetworkChangeTo(
850 NetworkChangeNotifier::ConnectionType::CONNECTION_WIFI, "test-1");
851 EXPECT_TRUE(estimator.GetRTTEstimate(&rtt));
852 EXPECT_TRUE(estimator.GetDownlinkThroughputKbpsEstimate(&kbps));
853 EXPECT_EQ(
854 2U, test_external_estimate_provider->get_time_since_last_update_count());
855 EXPECT_EQ(2U, test_external_estimate_provider->get_rtt_count());
856 EXPECT_EQ(
858 test_external_estimate_provider->get_downstream_throughput_kbps_count());
860 // Change network type to 2G. Number of queries to External estimate provider
861 // must increment.
862 estimator.SimulateNetworkChangeTo(
863 NetworkChangeNotifier::ConnectionType::CONNECTION_2G, "test-1");
864 EXPECT_EQ(
865 3U, test_external_estimate_provider->get_time_since_last_update_count());
866 EXPECT_EQ(3U, test_external_estimate_provider->get_rtt_count());
867 EXPECT_EQ(
869 test_external_estimate_provider->get_downstream_throughput_kbps_count());
871 // Set the external estimate as old. Network Quality estimator should request
872 // an update on connection type change.
873 EXPECT_EQ(0U, test_external_estimate_provider->update_count());
874 test_external_estimate_provider->set_time_since_last_update(
875 base::TimeDelta::Max());
877 estimator.SimulateNetworkChangeTo(
878 NetworkChangeNotifier::ConnectionType::CONNECTION_2G, "test-2");
879 EXPECT_EQ(
880 4U, test_external_estimate_provider->get_time_since_last_update_count());
881 EXPECT_EQ(3U, test_external_estimate_provider->get_rtt_count());
882 EXPECT_EQ(
884 test_external_estimate_provider->get_downstream_throughput_kbps_count());
885 EXPECT_EQ(1U, test_external_estimate_provider->update_count());
887 // Estimates are unavailable because external estimate provider never
888 // notifies network quality estimator of the updated estimates.
889 EXPECT_FALSE(estimator.GetRTTEstimate(&rtt));
890 EXPECT_FALSE(estimator.GetDownlinkThroughputKbpsEstimate(&kbps));
893 // Tests if the estimate from the external estimate provider is merged with the
894 // observations collected from the HTTP requests.
895 TEST(NetworkQualityEstimatorTest, TestExternalEstimateProviderMergeEstimates) {
896 const base::TimeDelta external_estimate_provider_rtt =
897 base::TimeDelta::FromMilliseconds(1);
898 const int32_t external_estimate_provider_downstream_throughput = 100;
899 TestExternalEstimateProvider* test_external_estimate_provider =
900 new TestExternalEstimateProvider(
901 external_estimate_provider_rtt,
902 external_estimate_provider_downstream_throughput);
903 scoped_ptr<ExternalEstimateProvider> external_estimate_provider(
904 test_external_estimate_provider);
906 std::map<std::string, std::string> variation_params;
907 TestNetworkQualityEstimator estimator(variation_params,
908 external_estimate_provider.Pass());
910 base::TimeDelta rtt;
911 // Estimate provided by network quality estimator should match the estimate
912 // provided by external estimate provider.
913 EXPECT_TRUE(estimator.GetRTTEstimate(&rtt));
914 EXPECT_EQ(external_estimate_provider_rtt, rtt);
916 int32_t kbps;
917 EXPECT_TRUE(estimator.GetDownlinkThroughputKbpsEstimate(&kbps));
918 EXPECT_EQ(external_estimate_provider_downstream_throughput, kbps);
920 EXPECT_EQ(1U, estimator.rtt_msec_observations_.Size());
921 EXPECT_EQ(1U, estimator.downstream_throughput_kbps_observations_.Size());
923 TestDelegate test_delegate;
924 TestURLRequestContext context(true);
925 context.set_network_quality_estimator(&estimator);
926 context.Init();
928 scoped_ptr<URLRequest> request(context.CreateRequest(
929 estimator.GetEchoURL(), DEFAULT_PRIORITY, &test_delegate));
930 request->Start();
931 base::RunLoop().Run();
933 EXPECT_EQ(2U, estimator.rtt_msec_observations_.Size());
934 EXPECT_EQ(2U, estimator.downstream_throughput_kbps_observations_.Size());
937 } // namespace net