Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(1294)

Side by Side Diff: net/base/network_quality_estimator_unittest.cc

Issue 1898603002: Move Network Quality Estimator files to //net/nqe (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Rebased, removed //net/socket/OWNERS Created 4 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « net/base/network_quality_estimator.cc ('k') | net/base/socket_performance_watcher.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(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
OLDNEW
« no previous file with comments | « net/base/network_quality_estimator.cc ('k') | net/base/socket_performance_watcher.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698