1 // Copyright 2015 The Chromium Authors
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/nqe/network_quality_estimator.h"
6
7 #include <stddef.h>
8 #include <stdint.h>
9
10 #include <cmath>
11 #include <limits>
12 #include <map>
13 #include <string>
14 #include <utility>
15 #include <vector>
16
17 #include "base/check_op.h"
18 #include "base/containers/adapters.h"
19 #include "base/metrics/histogram_samples.h"
20 #include "base/numerics/safe_conversions.h"
21 #include "base/run_loop.h"
22 #include "base/strings/string_number_conversions.h"
23 #include "base/task/thread_pool/thread_pool_instance.h"
24 #include "base/test/metrics/histogram_tester.h"
25 #include "base/test/simple_test_tick_clock.h"
26 #include "base/threading/platform_thread.h"
27 #include "base/time/time.h"
28 #include "build/build_config.h"
29 #include "build/chromeos_buildflags.h"
30 #include "net/base/load_flags.h"
31 #include "net/base/network_change_notifier.h"
32 #include "net/http/http_response_headers.h"
33 #include "net/http/http_response_info.h"
34 #include "net/http/http_status_code.h"
35 #include "net/log/test_net_log.h"
36 #include "net/nqe/effective_connection_type.h"
37 #include "net/nqe/effective_connection_type_observer.h"
38 #include "net/nqe/network_quality_estimator_test_util.h"
39 #include "net/nqe/network_quality_observation.h"
40 #include "net/nqe/network_quality_observation_source.h"
41 #include "net/nqe/observation_buffer.h"
42 #include "net/nqe/rtt_throughput_estimates_observer.h"
43 #include "net/socket/socket_performance_watcher.h"
44 #include "net/socket/socket_performance_watcher_factory.h"
45 #include "net/test/test_with_task_environment.h"
46 #include "net/traffic_annotation/network_traffic_annotation_test_helper.h"
47 #include "net/url_request/url_request.h"
48 #include "net/url_request/url_request_context.h"
49 #include "net/url_request/url_request_context_builder.h"
50 #include "net/url_request/url_request_test_util.h"
51 #include "testing/gtest/include/gtest/gtest.h"
52 #include "third_party/abseil-cpp/absl/types/optional.h"
53 #include "url/gurl.h"
54
55 namespace {
56
57 // Verifies that the number of samples in the bucket with minimum value
58 // |bucket_min| in |histogram| are at least |expected_min_count_samples|.
ExpectBucketCountAtLeast(base::HistogramTester * histogram_tester,const std::string & histogram,int32_t bucket_min,int32_t expected_min_count_samples)59 void ExpectBucketCountAtLeast(base::HistogramTester* histogram_tester,
60 const std::string& histogram,
61 int32_t bucket_min,
62 int32_t expected_min_count_samples) {
63 std::vector<base::Bucket> buckets =
64 histogram_tester->GetAllSamples(histogram);
65 int actual_count_samples = 0;
66 for (const auto& bucket : buckets) {
67 if (bucket.min == bucket_min)
68 actual_count_samples += bucket.count;
69 }
70 EXPECT_LE(expected_min_count_samples, actual_count_samples)
71 << " histogram=" << histogram << " bucket_min=" << bucket_min
72 << " expected_min_count_samples=" << expected_min_count_samples;
73 }
74
75 } // namespace
76
77 namespace net {
78
79 namespace {
80
81 class TestEffectiveConnectionTypeObserver
82 : public EffectiveConnectionTypeObserver {
83 public:
effective_connection_types()84 std::vector<EffectiveConnectionType>& effective_connection_types() {
85 return effective_connection_types_;
86 }
87
88 // EffectiveConnectionTypeObserver implementation:
OnEffectiveConnectionTypeChanged(EffectiveConnectionType type)89 void OnEffectiveConnectionTypeChanged(EffectiveConnectionType type) override {
90 effective_connection_types_.push_back(type);
91 }
92
93 private:
94 std::vector<EffectiveConnectionType> effective_connection_types_;
95 };
96
97 class TestPeerToPeerConnectionsCountObserver
98 : public PeerToPeerConnectionsCountObserver {
99 public:
count()100 uint32_t count() { return count_; }
101
102 private:
103 // PeerToPeerConnectionsCountObserver:
OnPeerToPeerConnectionsCountChange(uint32_t count)104 void OnPeerToPeerConnectionsCountChange(uint32_t count) override {
105 count_ = count;
106 }
107
108 uint32_t count_ = 0u;
109 };
110
111 class TestRTTAndThroughputEstimatesObserver
112 : public RTTAndThroughputEstimatesObserver {
113 public:
TestRTTAndThroughputEstimatesObserver()114 TestRTTAndThroughputEstimatesObserver()
115 : http_rtt_(nqe::internal::InvalidRTT()),
116 transport_rtt_(nqe::internal::InvalidRTT()) {}
117
118 // RTTAndThroughputEstimatesObserver implementation:
OnRTTOrThroughputEstimatesComputed(base::TimeDelta http_rtt,base::TimeDelta transport_rtt,int32_t downstream_throughput_kbps)119 void OnRTTOrThroughputEstimatesComputed(
120 base::TimeDelta http_rtt,
121 base::TimeDelta transport_rtt,
122 int32_t downstream_throughput_kbps) override {
123 http_rtt_ = http_rtt;
124 transport_rtt_ = transport_rtt;
125 downstream_throughput_kbps_ = downstream_throughput_kbps;
126 notifications_received_++;
127 }
128
notifications_received() const129 int notifications_received() const { return notifications_received_; }
130
http_rtt() const131 base::TimeDelta http_rtt() const { return http_rtt_; }
transport_rtt() const132 base::TimeDelta transport_rtt() const { return transport_rtt_; }
downstream_throughput_kbps() const133 int32_t downstream_throughput_kbps() const {
134 return downstream_throughput_kbps_;
135 }
136
137 private:
138 base::TimeDelta http_rtt_;
139 base::TimeDelta transport_rtt_;
140 int32_t downstream_throughput_kbps_ = nqe::internal::INVALID_RTT_THROUGHPUT;
141 int notifications_received_ = 0;
142 };
143
144 class TestRTTObserver : public NetworkQualityEstimator::RTTObserver {
145 public:
146 struct Observation {
Observationnet::__anon1057f9150211::TestRTTObserver::Observation147 Observation(int32_t ms,
148 const base::TimeTicks& ts,
149 NetworkQualityObservationSource src)
150 : rtt_ms(ms), timestamp(ts), source(src) {}
151 int32_t rtt_ms;
152 base::TimeTicks timestamp;
153 NetworkQualityObservationSource source;
154 };
155
observations()156 std::vector<Observation>& observations() { return observations_; }
157
158 // RttObserver implementation:
OnRTTObservation(int32_t rtt_ms,const base::TimeTicks & timestamp,NetworkQualityObservationSource source)159 void OnRTTObservation(int32_t rtt_ms,
160 const base::TimeTicks& timestamp,
161 NetworkQualityObservationSource source) override {
162 observations_.emplace_back(rtt_ms, timestamp, source);
163 }
164
165 // Returns the last received RTT observation that has source set to |source|.
last_rtt(NetworkQualityObservationSource source)166 base::TimeDelta last_rtt(NetworkQualityObservationSource source) {
167 for (const auto& observation : base::Reversed(observations_)) {
168 if (observation.source == source)
169 return base::Milliseconds(observation.rtt_ms);
170 }
171 return nqe::internal::InvalidRTT();
172 }
173
174 private:
175 std::vector<Observation> observations_;
176 };
177
178 class TestThroughputObserver
179 : public NetworkQualityEstimator::ThroughputObserver {
180 public:
181 struct Observation {
Observationnet::__anon1057f9150211::TestThroughputObserver::Observation182 Observation(int32_t kbps,
183 const base::TimeTicks& ts,
184 NetworkQualityObservationSource src)
185 : throughput_kbps(kbps), timestamp(ts), source(src) {}
186 int32_t throughput_kbps;
187 base::TimeTicks timestamp;
188 NetworkQualityObservationSource source;
189 };
190
observations()191 std::vector<Observation>& observations() { return observations_; }
192
193 // ThroughputObserver implementation:
OnThroughputObservation(int32_t throughput_kbps,const base::TimeTicks & timestamp,NetworkQualityObservationSource source)194 void OnThroughputObservation(
195 int32_t throughput_kbps,
196 const base::TimeTicks& timestamp,
197 NetworkQualityObservationSource source) override {
198 observations_.emplace_back(throughput_kbps, timestamp, source);
199 }
200
201 private:
202 std::vector<Observation> observations_;
203 };
204
205 } // namespace
206
207 using NetworkQualityEstimatorTest = TestWithTaskEnvironment;
208
TEST_F(NetworkQualityEstimatorTest,TestKbpsRTTUpdates)209 TEST_F(NetworkQualityEstimatorTest, TestKbpsRTTUpdates) {
210 base::HistogramTester histogram_tester;
211 // Enable requests to local host to be used for network quality estimation.
212 std::map<std::string, std::string> variation_params;
213 variation_params["throughput_min_requests_in_flight"] = "1";
214 variation_params["add_default_platform_observations"] = "false";
215 TestNetworkQualityEstimator estimator(variation_params);
216
217 estimator.SimulateNetworkChange(
218 NetworkChangeNotifier::ConnectionType::CONNECTION_UNKNOWN, "test");
219
220 base::TimeDelta rtt;
221 int32_t kbps;
222 EXPECT_FALSE(estimator.GetRecentRTT(nqe::internal::OBSERVATION_CATEGORY_HTTP,
223 base::TimeTicks(), &rtt, nullptr));
224 EXPECT_FALSE(
225 estimator.GetRecentDownlinkThroughputKbps(base::TimeTicks(), &kbps));
226
227 TestDelegate test_delegate;
228 auto context_builder = CreateTestURLRequestContextBuilder();
229 context_builder->set_network_quality_estimator(&estimator);
230 context_builder->SuppressSettingSocketPerformanceWatcherFactoryForTesting();
231 auto context = context_builder->Build();
232
233 std::unique_ptr<URLRequest> request(
234 context->CreateRequest(estimator.GetEchoURL(), DEFAULT_PRIORITY,
235 &test_delegate, TRAFFIC_ANNOTATION_FOR_TESTS));
236 request->SetLoadFlags(request->load_flags() | LOAD_MAIN_FRAME_DEPRECATED);
237 request->Start();
238 test_delegate.RunUntilComplete();
239
240 // Pump message loop to allow estimator tasks to be processed.
241 base::RunLoop().RunUntilIdle();
242
243 // Both RTT and downstream throughput should be updated.
244 base::TimeDelta http_rtt;
245 EXPECT_TRUE(estimator.GetRecentRTT(nqe::internal::OBSERVATION_CATEGORY_HTTP,
246 base::TimeTicks(), &http_rtt, nullptr));
247 EXPECT_EQ(http_rtt, estimator.GetHttpRTT().value());
248 EXPECT_TRUE(
249 estimator.GetRecentDownlinkThroughputKbps(base::TimeTicks(), &kbps));
250 EXPECT_EQ(kbps, estimator.GetDownstreamThroughputKbps().value());
251 base::TimeDelta transport_rtt;
252 EXPECT_FALSE(estimator.GetTransportRTT());
253 EXPECT_FALSE(
254 estimator.GetRecentRTT(nqe::internal::OBSERVATION_CATEGORY_TRANSPORT,
255 base::TimeTicks(), &transport_rtt, nullptr));
256
257 // Verify the contents of the net log.
258 EXPECT_LE(
259 2, estimator.GetEntriesCount(NetLogEventType::NETWORK_QUALITY_CHANGED));
260 EXPECT_EQ(http_rtt.InMilliseconds(),
261 estimator.GetNetLogLastIntegerValue(
262 NetLogEventType::NETWORK_QUALITY_CHANGED, "http_rtt_ms"));
263 EXPECT_EQ(-1,
264 estimator.GetNetLogLastIntegerValue(
265 NetLogEventType::NETWORK_QUALITY_CHANGED, "transport_rtt_ms"));
266 EXPECT_EQ(kbps, estimator.GetNetLogLastIntegerValue(
267 NetLogEventType::NETWORK_QUALITY_CHANGED,
268 "downstream_throughput_kbps"));
269
270 // Check UMA histograms.
271 EXPECT_LE(1u,
272 histogram_tester.GetAllSamples("NQE.RTT.OnECTComputation").size());
273
274 histogram_tester.ExpectBucketCount(
275 "NQE.RTT.ObservationSource", NETWORK_QUALITY_OBSERVATION_SOURCE_HTTP, 1);
276
277 std::unique_ptr<URLRequest> request2(
278 context->CreateRequest(estimator.GetEchoURL(), DEFAULT_PRIORITY,
279 &test_delegate, TRAFFIC_ANNOTATION_FOR_TESTS));
280 request2->SetLoadFlags(request2->load_flags() | LOAD_MAIN_FRAME_DEPRECATED);
281 request2->Start();
282 test_delegate.RunUntilComplete();
283
284 estimator.SimulateNetworkChange(
285 NetworkChangeNotifier::ConnectionType::CONNECTION_WIFI, "test-1");
286 histogram_tester.ExpectTotalCount("NQE.RatioMedianRTT.WiFi", 0);
287
288 EXPECT_FALSE(estimator.GetRecentRTT(nqe::internal::OBSERVATION_CATEGORY_HTTP,
289 base::TimeTicks(), &rtt, nullptr));
290 EXPECT_FALSE(
291 estimator.GetRecentDownlinkThroughputKbps(base::TimeTicks(), &kbps));
292
293 estimator.SimulateNetworkChange(
294 NetworkChangeNotifier::ConnectionType::CONNECTION_WIFI, std::string());
295
296 EXPECT_FALSE(estimator.GetRecentRTT(nqe::internal::OBSERVATION_CATEGORY_HTTP,
297 base::TimeTicks(), &rtt, nullptr));
298 EXPECT_FALSE(
299 estimator.GetRecentDownlinkThroughputKbps(base::TimeTicks(), &kbps));
300
301 std::unique_ptr<URLRequest> request3(
302 context->CreateRequest(estimator.GetEchoURL(), DEFAULT_PRIORITY,
303 &test_delegate, TRAFFIC_ANNOTATION_FOR_TESTS));
304 request3->SetLoadFlags(request2->load_flags() | LOAD_MAIN_FRAME_DEPRECATED);
305 request3->Start();
306 test_delegate.RunUntilComplete();
307
308 estimator.SimulateNetworkChange(
309 NetworkChangeNotifier::ConnectionType::CONNECTION_UNKNOWN, "test");
310 }
311
312 // Tests that the network quality estimator writes and reads network quality
313 // from the cache store correctly.
TEST_F(NetworkQualityEstimatorTest,Caching)314 TEST_F(NetworkQualityEstimatorTest, Caching) {
315 for (NetworkChangeNotifier::ConnectionType connection_type :
316 {NetworkChangeNotifier::ConnectionType::CONNECTION_WIFI,
317 NetworkChangeNotifier::ConnectionType::CONNECTION_ETHERNET}) {
318 base::HistogramTester histogram_tester;
319 std::map<std::string, std::string> variation_params;
320 variation_params["throughput_min_requests_in_flight"] = "1";
321 variation_params["add_default_platform_observations"] = "false";
322 TestNetworkQualityEstimator estimator(variation_params);
323
324 const std::string connection_id =
325 connection_type ==
326 NetworkChangeNotifier::ConnectionType::CONNECTION_WIFI
327 ? "test"
328 : "";
329
330 estimator.SimulateNetworkChange(connection_type, connection_id);
331
332 base::TimeDelta rtt;
333 int32_t kbps;
334 EXPECT_FALSE(
335 estimator.GetRecentRTT(nqe::internal::OBSERVATION_CATEGORY_HTTP,
336 base::TimeTicks(), &rtt, nullptr));
337 EXPECT_FALSE(
338 estimator.GetRecentDownlinkThroughputKbps(base::TimeTicks(), &kbps));
339
340 TestDelegate test_delegate;
341 auto context_builder = CreateTestURLRequestContextBuilder();
342 context_builder->set_network_quality_estimator(&estimator);
343 context_builder->SuppressSettingSocketPerformanceWatcherFactoryForTesting();
344 auto context = context_builder->Build();
345
346 // Start two requests so that the network quality is added to cache store at
347 // the beginning of the second request from the network traffic observed
348 // from the first request.
349 for (size_t i = 0; i < 2; ++i) {
350 std::unique_ptr<URLRequest> request(
351 context->CreateRequest(estimator.GetEchoURL(), DEFAULT_PRIORITY,
352 &test_delegate, TRAFFIC_ANNOTATION_FOR_TESTS));
353 request->SetLoadFlags(request->load_flags() | LOAD_MAIN_FRAME_DEPRECATED);
354 request->Start();
355 test_delegate.RunUntilComplete();
356 }
357 histogram_tester.ExpectUniqueSample("NQE.RTT.ObservationSource",
358 NETWORK_QUALITY_OBSERVATION_SOURCE_HTTP,
359 2);
360
361 base::RunLoop().RunUntilIdle();
362
363 // Both RTT and downstream throughput should be updated.
364 EXPECT_TRUE(estimator.GetRecentRTT(nqe::internal::OBSERVATION_CATEGORY_HTTP,
365 base::TimeTicks(), &rtt, nullptr));
366 EXPECT_EQ(rtt, estimator.GetHttpRTT().value());
367 EXPECT_TRUE(
368 estimator.GetRecentDownlinkThroughputKbps(base::TimeTicks(), &kbps));
369 EXPECT_EQ(kbps, estimator.GetDownstreamThroughputKbps().value());
370 EXPECT_NE(EFFECTIVE_CONNECTION_TYPE_UNKNOWN,
371 estimator.GetEffectiveConnectionType());
372 EXPECT_FALSE(
373 estimator.GetRecentRTT(nqe::internal::OBSERVATION_CATEGORY_TRANSPORT,
374 base::TimeTicks(), &rtt, nullptr));
375 EXPECT_FALSE(estimator.GetTransportRTT());
376
377 // Add the observers before changing the network type.
378 TestEffectiveConnectionTypeObserver observer;
379 estimator.AddEffectiveConnectionTypeObserver(&observer);
380 TestRTTObserver rtt_observer;
381 estimator.AddRTTObserver(&rtt_observer);
382 TestThroughputObserver throughput_observer;
383 estimator.AddThroughputObserver(&throughput_observer);
384
385 // |observer| should be notified as soon as it is added.
386 base::RunLoop().RunUntilIdle();
387 EXPECT_EQ(1U, observer.effective_connection_types().size());
388
389 int num_net_log_entries =
390 estimator.GetEntriesCount(NetLogEventType::NETWORK_QUALITY_CHANGED);
391 EXPECT_LE(2, num_net_log_entries);
392
393 estimator.SimulateNetworkChange(connection_type, connection_id);
394 histogram_tester.ExpectBucketCount(
395 "NQE.RTT.ObservationSource",
396 NETWORK_QUALITY_OBSERVATION_SOURCE_HTTP_CACHED_ESTIMATE, 1);
397 histogram_tester.ExpectBucketCount(
398 "NQE.RTT.ObservationSource",
399 NETWORK_QUALITY_OBSERVATION_SOURCE_TRANSPORT_CACHED_ESTIMATE, 1);
400 histogram_tester.ExpectTotalCount("NQE.RTT.ObservationSource", 4);
401
402 // Verify the contents of the net log.
403 EXPECT_LE(
404 1, estimator.GetEntriesCount(NetLogEventType::NETWORK_QUALITY_CHANGED) -
405 num_net_log_entries);
406 EXPECT_NE(-1, estimator.GetNetLogLastIntegerValue(
407 NetLogEventType::NETWORK_QUALITY_CHANGED, "http_rtt_ms"));
408 EXPECT_NE(
409 -1, estimator.GetNetLogLastIntegerValue(
410 NetLogEventType::NETWORK_QUALITY_CHANGED, "transport_rtt_ms"));
411 EXPECT_NE(-1, estimator.GetNetLogLastIntegerValue(
412 NetLogEventType::NETWORK_QUALITY_CHANGED,
413 "downstream_throughput_kbps"));
414 EXPECT_EQ(GetNameForEffectiveConnectionType(
415 estimator.GetEffectiveConnectionType()),
416 estimator.GetNetLogLastStringValue(
417 NetLogEventType::NETWORK_QUALITY_CHANGED,
418 "effective_connection_type"));
419
420 base::RunLoop().RunUntilIdle();
421
422 // Verify that the cached network quality was read, and observers were
423 // notified. |observer| must be notified once right after it was added, and
424 // once again after the cached network quality was read.
425 EXPECT_LE(2U, observer.effective_connection_types().size());
426 EXPECT_EQ(estimator.GetEffectiveConnectionType(),
427 observer.effective_connection_types().back());
428 EXPECT_EQ(2U, rtt_observer.observations().size());
429 EXPECT_EQ(1U, throughput_observer.observations().size());
430 }
431 }
432
433 // Tests that the network quality estimator does not read the network quality
434 // from the cache store when caching is not enabled.
TEST_F(NetworkQualityEstimatorTest,CachingDisabled)435 TEST_F(NetworkQualityEstimatorTest, CachingDisabled) {
436 base::HistogramTester histogram_tester;
437 std::map<std::string, std::string> variation_params;
438 // Do not set |persistent_cache_reading_enabled| variation param.
439 variation_params["persistent_cache_reading_enabled"] = "false";
440 variation_params["throughput_min_requests_in_flight"] = "1";
441 variation_params["add_default_platform_observations"] = "false";
442 TestNetworkQualityEstimator estimator(variation_params);
443
444 estimator.SimulateNetworkChange(
445 NetworkChangeNotifier::ConnectionType::CONNECTION_WIFI, "test");
446
447 base::TimeDelta rtt;
448 int32_t kbps;
449 EXPECT_FALSE(estimator.GetRecentRTT(nqe::internal::OBSERVATION_CATEGORY_HTTP,
450 base::TimeTicks(), &rtt, nullptr));
451 EXPECT_FALSE(
452 estimator.GetRecentDownlinkThroughputKbps(base::TimeTicks(), &kbps));
453
454 TestDelegate test_delegate;
455 auto context_builder = CreateTestURLRequestContextBuilder();
456 context_builder->set_network_quality_estimator(&estimator);
457 context_builder->SuppressSettingSocketPerformanceWatcherFactoryForTesting();
458 auto context = context_builder->Build();
459
460 // Start two requests so that the network quality is added to cache store at
461 // the beginning of the second request from the network traffic observed from
462 // the first request.
463 for (size_t i = 0; i < 2; ++i) {
464 std::unique_ptr<URLRequest> request(
465 context->CreateRequest(estimator.GetEchoURL(), DEFAULT_PRIORITY,
466 &test_delegate, TRAFFIC_ANNOTATION_FOR_TESTS));
467 request->SetLoadFlags(request->load_flags() | LOAD_MAIN_FRAME_DEPRECATED);
468 request->Start();
469 test_delegate.RunUntilComplete();
470 }
471
472 base::RunLoop().RunUntilIdle();
473
474 // Both RTT and downstream throughput should be updated.
475 EXPECT_TRUE(estimator.GetRecentRTT(nqe::internal::OBSERVATION_CATEGORY_HTTP,
476 base::TimeTicks(), &rtt, nullptr));
477 EXPECT_EQ(rtt, estimator.GetHttpRTT().value());
478 EXPECT_TRUE(
479 estimator.GetRecentDownlinkThroughputKbps(base::TimeTicks(), &kbps));
480 EXPECT_EQ(kbps, estimator.GetDownstreamThroughputKbps().value());
481 EXPECT_NE(EFFECTIVE_CONNECTION_TYPE_UNKNOWN,
482 estimator.GetEffectiveConnectionType());
483 EXPECT_FALSE(
484 estimator.GetRecentRTT(nqe::internal::OBSERVATION_CATEGORY_TRANSPORT,
485 base::TimeTicks(), &rtt, nullptr));
486 EXPECT_FALSE(estimator.GetTransportRTT());
487
488 // Add the observers before changing the network type.
489 TestRTTObserver rtt_observer;
490 estimator.AddRTTObserver(&rtt_observer);
491 TestThroughputObserver throughput_observer;
492 estimator.AddThroughputObserver(&throughput_observer);
493
494 estimator.SimulateNetworkChange(
495 NetworkChangeNotifier::ConnectionType::CONNECTION_2G, "test");
496
497 base::RunLoop().RunUntilIdle();
498
499 // Verify that the cached network quality was read, and observers were
500 // notified. |observer| must be notified once right after it was added, and
501 // once again after the cached network quality was read.
502 EXPECT_EQ(0U, rtt_observer.observations().size());
503 EXPECT_EQ(0U, throughput_observer.observations().size());
504 }
505
TEST_F(NetworkQualityEstimatorTest,QuicObservations)506 TEST_F(NetworkQualityEstimatorTest, QuicObservations) {
507 base::HistogramTester histogram_tester;
508 std::map<std::string, std::string> variation_params;
509 variation_params["add_default_platform_observations"] = "false";
510 TestNetworkQualityEstimator estimator(variation_params);
511 estimator.OnUpdatedTransportRTTAvailable(
512 SocketPerformanceWatcherFactory::PROTOCOL_TCP, base::Milliseconds(10),
513 absl::nullopt);
514 estimator.OnUpdatedTransportRTTAvailable(
515 SocketPerformanceWatcherFactory::PROTOCOL_QUIC, base::Milliseconds(10),
516 absl::nullopt);
517 histogram_tester.ExpectBucketCount("NQE.RTT.ObservationSource",
518 NETWORK_QUALITY_OBSERVATION_SOURCE_TCP, 1);
519 histogram_tester.ExpectBucketCount(
520 "NQE.RTT.ObservationSource", NETWORK_QUALITY_OBSERVATION_SOURCE_QUIC, 1);
521 histogram_tester.ExpectTotalCount("NQE.RTT.ObservationSource", 2);
522
523 // Verify that the QUIC RTT samples are used when computing transport RTT
524 // estimate.
525 EXPECT_EQ(base::Milliseconds(10), estimator.GetTransportRTT());
526 EXPECT_FALSE(estimator.GetHttpRTT().has_value());
527 }
528
529 // Verifies that the QUIC RTT samples are used when computing transport RTT
530 // estimate.
TEST_F(NetworkQualityEstimatorTest,QuicObservationsUsedForTransportRTTComputation)531 TEST_F(NetworkQualityEstimatorTest,
532 QuicObservationsUsedForTransportRTTComputation) {
533 base::HistogramTester histogram_tester;
534 std::map<std::string, std::string> variation_params;
535 variation_params["add_default_platform_observations"] = "false";
536 TestNetworkQualityEstimator estimator(variation_params);
537 estimator.OnUpdatedTransportRTTAvailable(
538 SocketPerformanceWatcherFactory::PROTOCOL_QUIC, base::Milliseconds(10),
539 absl::nullopt);
540 histogram_tester.ExpectBucketCount(
541 "NQE.RTT.ObservationSource", NETWORK_QUALITY_OBSERVATION_SOURCE_QUIC, 1);
542 histogram_tester.ExpectTotalCount("NQE.RTT.ObservationSource", 1);
543
544 EXPECT_EQ(base::Milliseconds(10), estimator.GetTransportRTT());
545 EXPECT_FALSE(estimator.GetHttpRTT().has_value());
546 }
547
548 // Verifies that the H2 RTT samples are used when computing transport RTT
549 // estimate.
TEST_F(NetworkQualityEstimatorTest,H2ObservationsUsedForTransportRTTComputation)550 TEST_F(NetworkQualityEstimatorTest,
551 H2ObservationsUsedForTransportRTTComputation) {
552 base::HistogramTester histogram_tester;
553 std::map<std::string, std::string> variation_params;
554 variation_params["add_default_platform_observations"] = "false";
555 TestNetworkQualityEstimator estimator(variation_params);
556 estimator.RecordSpdyPingLatency(
557 net::HostPortPair::FromString("www.test.com:443"),
558 base::Milliseconds(10));
559 histogram_tester.ExpectBucketCount(
560 "NQE.RTT.ObservationSource", NETWORK_QUALITY_OBSERVATION_SOURCE_H2_PINGS,
561 1);
562 histogram_tester.ExpectTotalCount("NQE.RTT.ObservationSource", 1);
563
564 EXPECT_EQ(base::Milliseconds(10), estimator.GetTransportRTT());
565 EXPECT_FALSE(estimator.GetHttpRTT().has_value());
566 }
567
TEST_F(NetworkQualityEstimatorTest,StoreObservations)568 TEST_F(NetworkQualityEstimatorTest, StoreObservations) {
569 std::map<std::string, std::string> variation_params;
570 variation_params["throughput_min_requests_in_flight"] = "1";
571 variation_params["add_default_platform_observations"] = "false";
572 TestNetworkQualityEstimator estimator(variation_params);
573
574 base::TimeDelta rtt;
575 int32_t kbps;
576 EXPECT_FALSE(estimator.GetRecentRTT(nqe::internal::OBSERVATION_CATEGORY_HTTP,
577 base::TimeTicks(), &rtt, nullptr));
578 EXPECT_FALSE(
579 estimator.GetRecentDownlinkThroughputKbps(base::TimeTicks(), &kbps));
580
581 TestDelegate test_delegate;
582 auto context_builder = CreateTestURLRequestContextBuilder();
583 context_builder->set_network_quality_estimator(&estimator);
584 auto context = context_builder->Build();
585
586 const size_t kMaxObservations = 10;
587 for (size_t i = 0; i < kMaxObservations; ++i) {
588 std::unique_ptr<URLRequest> request(
589 context->CreateRequest(estimator.GetEchoURL(), DEFAULT_PRIORITY,
590 &test_delegate, TRAFFIC_ANNOTATION_FOR_TESTS));
591 request->Start();
592 test_delegate.RunUntilComplete();
593
594 // Pump the message loop to process estimator tasks.
595 base::RunLoop().RunUntilIdle();
596
597 EXPECT_TRUE(estimator.GetRecentRTT(nqe::internal::OBSERVATION_CATEGORY_HTTP,
598 base::TimeTicks(), &rtt, nullptr));
599 EXPECT_TRUE(
600 estimator.GetRecentDownlinkThroughputKbps(base::TimeTicks(), &kbps));
601 }
602
603 // Verify that the stored observations are cleared on network change.
604 estimator.SimulateNetworkChange(
605 NetworkChangeNotifier::ConnectionType::CONNECTION_WIFI, "test-2");
606 EXPECT_FALSE(estimator.GetRecentRTT(nqe::internal::OBSERVATION_CATEGORY_HTTP,
607 base::TimeTicks(), &rtt, nullptr));
608 EXPECT_FALSE(
609 estimator.GetRecentDownlinkThroughputKbps(base::TimeTicks(), &kbps));
610 }
611
612 // This test notifies NetworkQualityEstimator of received data. Next,
613 // throughput and RTT percentiles are checked for correctness by doing simple
614 // verifications.
TEST_F(NetworkQualityEstimatorTest,ComputedPercentiles)615 TEST_F(NetworkQualityEstimatorTest, ComputedPercentiles) {
616 std::map<std::string, std::string> variation_params;
617 variation_params["throughput_min_requests_in_flight"] = "1";
618 variation_params["add_default_platform_observations"] = "false";
619 TestNetworkQualityEstimator estimator(variation_params);
620
621 EXPECT_EQ(nqe::internal::InvalidRTT(),
622 estimator.GetRTTEstimateInternal(
623 base::TimeTicks(), nqe::internal::OBSERVATION_CATEGORY_HTTP,
624 100, nullptr));
625 EXPECT_EQ(nqe::internal::INVALID_RTT_THROUGHPUT,
626 estimator.GetDownlinkThroughputKbpsEstimateInternal(
627 base::TimeTicks(), 100));
628
629 TestDelegate test_delegate;
630 auto context_builder = CreateTestURLRequestContextBuilder();
631 context_builder->set_network_quality_estimator(&estimator);
632 auto context = context_builder->Build();
633
634 for (size_t i = 0; i < 10U; ++i) {
635 std::unique_ptr<URLRequest> request(
636 context->CreateRequest(estimator.GetEchoURL(), DEFAULT_PRIORITY,
637 &test_delegate, TRAFFIC_ANNOTATION_FOR_TESTS));
638 request->Start();
639 test_delegate.RunUntilComplete();
640 }
641
642 // Verify the percentiles through simple tests.
643 for (int i = 0; i <= 100; ++i) {
644 EXPECT_GT(estimator.GetDownlinkThroughputKbpsEstimateInternal(
645 base::TimeTicks(), i),
646 0);
647 EXPECT_LT(estimator.GetRTTEstimateInternal(
648 base::TimeTicks(), nqe::internal::OBSERVATION_CATEGORY_HTTP,
649 i, nullptr),
650 base::TimeDelta::Max());
651
652 if (i != 0) {
653 // Throughput percentiles are in decreasing order.
654 EXPECT_LE(estimator.GetDownlinkThroughputKbpsEstimateInternal(
655 base::TimeTicks(), i),
656 estimator.GetDownlinkThroughputKbpsEstimateInternal(
657 base::TimeTicks(), i - 1));
658
659 // RTT percentiles are in increasing order.
660 EXPECT_GE(estimator.GetRTTEstimateInternal(
661 base::TimeTicks(), nqe::internal::OBSERVATION_CATEGORY_HTTP,
662 i, nullptr),
663 estimator.GetRTTEstimateInternal(
664 base::TimeTicks(), nqe::internal::OBSERVATION_CATEGORY_HTTP,
665 i - 1, nullptr));
666 }
667 }
668 }
669
670 // Verifies that the observers receive the notifications when default estimates
671 // are added to the observations.
TEST_F(NetworkQualityEstimatorTest,DefaultObservations)672 TEST_F(NetworkQualityEstimatorTest, DefaultObservations) {
673 base::HistogramTester histogram_tester;
674
675 TestEffectiveConnectionTypeObserver effective_connection_type_observer;
676 TestRTTAndThroughputEstimatesObserver rtt_throughput_estimates_observer;
677 TestRTTObserver rtt_observer;
678 TestThroughputObserver throughput_observer;
679 std::map<std::string, std::string> variation_params;
680 TestNetworkQualityEstimator estimator(variation_params, false, false);
681
682 // Default observations should be added when constructing the |estimator|.
683 histogram_tester.ExpectBucketCount(
684 "NQE.RTT.ObservationSource",
685 NETWORK_QUALITY_OBSERVATION_SOURCE_DEFAULT_HTTP_FROM_PLATFORM, 1);
686 histogram_tester.ExpectBucketCount(
687 "NQE.RTT.ObservationSource",
688 NETWORK_QUALITY_OBSERVATION_SOURCE_DEFAULT_TRANSPORT_FROM_PLATFORM, 1);
689 histogram_tester.ExpectTotalCount("NQE.RTT.ObservationSource", 2);
690
691 // Default observations should be added on connection change.
692 estimator.SimulateNetworkChange(
693 NetworkChangeNotifier::ConnectionType::CONNECTION_UNKNOWN, "unknown-1");
694 histogram_tester.ExpectBucketCount(
695 "NQE.RTT.ObservationSource",
696 NETWORK_QUALITY_OBSERVATION_SOURCE_DEFAULT_HTTP_FROM_PLATFORM, 2);
697 histogram_tester.ExpectBucketCount(
698 "NQE.RTT.ObservationSource",
699 NETWORK_QUALITY_OBSERVATION_SOURCE_DEFAULT_TRANSPORT_FROM_PLATFORM, 2);
700 histogram_tester.ExpectTotalCount("NQE.RTT.ObservationSource", 4);
701
702 base::TimeDelta rtt;
703 int32_t kbps;
704
705 // Default estimates should be available.
706 EXPECT_TRUE(estimator.GetRecentRTT(nqe::internal::OBSERVATION_CATEGORY_HTTP,
707 base::TimeTicks(), &rtt, nullptr));
708 EXPECT_EQ(base::Milliseconds(115), rtt);
709 EXPECT_EQ(rtt, estimator.GetHttpRTT().value());
710 EXPECT_TRUE(
711 estimator.GetRecentRTT(nqe::internal::OBSERVATION_CATEGORY_TRANSPORT,
712 base::TimeTicks(), &rtt, nullptr));
713 EXPECT_EQ(base::Milliseconds(55), rtt);
714 EXPECT_EQ(rtt, estimator.GetTransportRTT().value());
715 EXPECT_TRUE(
716 estimator.GetRecentDownlinkThroughputKbps(base::TimeTicks(), &kbps));
717 EXPECT_EQ(1961, kbps);
718 EXPECT_EQ(kbps, estimator.GetDownstreamThroughputKbps().value());
719
720 estimator.AddEffectiveConnectionTypeObserver(
721 &effective_connection_type_observer);
722 estimator.AddRTTAndThroughputEstimatesObserver(
723 &rtt_throughput_estimates_observer);
724 estimator.AddRTTObserver(&rtt_observer);
725 estimator.AddThroughputObserver(&throughput_observer);
726
727 // Simulate network change to 3G. Default estimates should be available.
728 estimator.SimulateNetworkChange(
729 NetworkChangeNotifier::ConnectionType::CONNECTION_3G, "test-3");
730 EXPECT_TRUE(estimator.GetRecentRTT(nqe::internal::OBSERVATION_CATEGORY_HTTP,
731 base::TimeTicks(), &rtt, nullptr));
732 // Taken from network_quality_estimator_params.cc.
733 EXPECT_EQ(base::Milliseconds(273), rtt);
734 EXPECT_EQ(rtt, estimator.GetHttpRTT().value());
735 EXPECT_TRUE(
736 estimator.GetRecentRTT(nqe::internal::OBSERVATION_CATEGORY_TRANSPORT,
737 base::TimeTicks(), &rtt, nullptr));
738 EXPECT_EQ(base::Milliseconds(209), rtt);
739 EXPECT_EQ(rtt, estimator.GetTransportRTT());
740 EXPECT_TRUE(
741 estimator.GetRecentDownlinkThroughputKbps(base::TimeTicks(), &kbps));
742 EXPECT_EQ(749, kbps);
743 EXPECT_EQ(kbps, estimator.GetDownstreamThroughputKbps().value());
744
745 EXPECT_NE(EFFECTIVE_CONNECTION_TYPE_UNKNOWN,
746 estimator.GetEffectiveConnectionType());
747 EXPECT_EQ(
748 1U,
749 effective_connection_type_observer.effective_connection_types().size());
750 EXPECT_NE(
751 EFFECTIVE_CONNECTION_TYPE_UNKNOWN,
752 effective_connection_type_observer.effective_connection_types().front());
753
754 // Verify the contents of the net log.
755 EXPECT_LE(
756 3, estimator.GetEntriesCount(NetLogEventType::NETWORK_QUALITY_CHANGED));
757 EXPECT_NE(
758 GetNameForEffectiveConnectionType(EFFECTIVE_CONNECTION_TYPE_UNKNOWN),
759 estimator.GetNetLogLastStringValue(
760 NetLogEventType::NETWORK_QUALITY_CHANGED,
761 "effective_connection_type"));
762
763 EXPECT_EQ(4, rtt_throughput_estimates_observer.notifications_received());
764 EXPECT_EQ(base::Milliseconds(273),
765 rtt_throughput_estimates_observer.http_rtt());
766 EXPECT_EQ(base::Milliseconds(209),
767 rtt_throughput_estimates_observer.transport_rtt());
768 EXPECT_EQ(749,
769 rtt_throughput_estimates_observer.downstream_throughput_kbps());
770
771 EXPECT_EQ(2U, rtt_observer.observations().size());
772 EXPECT_EQ(273, rtt_observer.observations().at(0).rtt_ms);
773 EXPECT_EQ(NETWORK_QUALITY_OBSERVATION_SOURCE_DEFAULT_HTTP_FROM_PLATFORM,
774 rtt_observer.observations().at(0).source);
775 EXPECT_EQ(209, rtt_observer.observations().at(1).rtt_ms);
776 EXPECT_EQ(NETWORK_QUALITY_OBSERVATION_SOURCE_DEFAULT_TRANSPORT_FROM_PLATFORM,
777 rtt_observer.observations().at(1).source);
778
779 EXPECT_EQ(1U, throughput_observer.observations().size());
780 EXPECT_EQ(749, throughput_observer.observations().at(0).throughput_kbps);
781 EXPECT_EQ(NETWORK_QUALITY_OBSERVATION_SOURCE_DEFAULT_HTTP_FROM_PLATFORM,
782 throughput_observer.observations().at(0).source);
783 }
784
785 // Verifies that the default observations are added to the set of observations.
786 // If default observations are overridden using field trial parameters, verify
787 // that the overriding values are used.
TEST_F(NetworkQualityEstimatorTest,DefaultObservationsOverridden)788 TEST_F(NetworkQualityEstimatorTest, DefaultObservationsOverridden) {
789 std::map<std::string, std::string> variation_params;
790 variation_params["Unknown.DefaultMedianKbps"] = "100";
791 variation_params["WiFi.DefaultMedianKbps"] = "200";
792 variation_params["2G.DefaultMedianKbps"] = "250";
793
794 variation_params["Unknown.DefaultMedianRTTMsec"] = "1000";
795 variation_params["WiFi.DefaultMedianRTTMsec"] = "2000";
796 // Negative variation value should not be used.
797 variation_params["2G.DefaultMedianRTTMsec"] = "-5";
798
799 variation_params["Unknown.DefaultMedianTransportRTTMsec"] = "500";
800 variation_params["WiFi.DefaultMedianTransportRTTMsec"] = "1000";
801 // Negative variation value should not be used.
802 variation_params["2G.DefaultMedianTransportRTTMsec"] = "-5";
803
804 TestNetworkQualityEstimator estimator(variation_params, false, false);
805 estimator.SimulateNetworkChange(
806 NetworkChangeNotifier::ConnectionType::CONNECTION_UNKNOWN, "unknown-1");
807
808 base::TimeDelta rtt;
809 int32_t kbps;
810
811 EXPECT_TRUE(estimator.GetRecentRTT(nqe::internal::OBSERVATION_CATEGORY_HTTP,
812 base::TimeTicks(), &rtt, nullptr));
813 EXPECT_EQ(base::Milliseconds(1000), rtt);
814 EXPECT_EQ(rtt, estimator.GetHttpRTT().value());
815 EXPECT_TRUE(
816 estimator.GetRecentRTT(nqe::internal::OBSERVATION_CATEGORY_TRANSPORT,
817 base::TimeTicks(), &rtt, nullptr));
818 EXPECT_EQ(base::Milliseconds(500), rtt);
819 EXPECT_EQ(rtt, estimator.GetTransportRTT().value());
820 EXPECT_TRUE(
821 estimator.GetRecentDownlinkThroughputKbps(base::TimeTicks(), &kbps));
822 EXPECT_EQ(100, kbps);
823 EXPECT_EQ(kbps, estimator.GetDownstreamThroughputKbps().value());
824
825 // Simulate network change to Wi-Fi.
826 estimator.SimulateNetworkChange(
827 NetworkChangeNotifier::ConnectionType::CONNECTION_WIFI, "test-1");
828 EXPECT_TRUE(estimator.GetRecentRTT(nqe::internal::OBSERVATION_CATEGORY_HTTP,
829 base::TimeTicks(), &rtt, nullptr));
830 EXPECT_EQ(base::Milliseconds(2000), rtt);
831 EXPECT_EQ(rtt, estimator.GetHttpRTT().value());
832 EXPECT_TRUE(
833 estimator.GetRecentRTT(nqe::internal::OBSERVATION_CATEGORY_TRANSPORT,
834 base::TimeTicks(), &rtt, nullptr));
835 EXPECT_EQ(base::Milliseconds(1000), rtt);
836 EXPECT_EQ(rtt, estimator.GetTransportRTT().value());
837 EXPECT_TRUE(
838 estimator.GetRecentDownlinkThroughputKbps(base::TimeTicks(), &kbps));
839 EXPECT_EQ(200, kbps);
840 EXPECT_EQ(kbps, estimator.GetDownstreamThroughputKbps().value());
841
842 // Simulate network change to 2G. Only the Kbps default estimate should be
843 // available.
844 estimator.SimulateNetworkChange(
845 NetworkChangeNotifier::ConnectionType::CONNECTION_2G, "test-2");
846 EXPECT_TRUE(estimator.GetRecentRTT(nqe::internal::OBSERVATION_CATEGORY_HTTP,
847 base::TimeTicks(), &rtt, nullptr));
848 // Taken from network_quality_estimator_params.cc.
849 EXPECT_EQ(base::Milliseconds(1726), rtt);
850 EXPECT_EQ(rtt, estimator.GetHttpRTT().value());
851 EXPECT_TRUE(
852 estimator.GetRecentRTT(nqe::internal::OBSERVATION_CATEGORY_TRANSPORT,
853 base::TimeTicks(), &rtt, nullptr));
854 EXPECT_EQ(base::Milliseconds(1531), rtt);
855 EXPECT_EQ(rtt, estimator.GetTransportRTT().value());
856 EXPECT_TRUE(
857 estimator.GetRecentDownlinkThroughputKbps(base::TimeTicks(), &kbps));
858 EXPECT_EQ(250, kbps);
859 EXPECT_EQ(kbps, estimator.GetDownstreamThroughputKbps().value());
860
861 // Simulate network change to 3G. Default estimates should be available.
862 estimator.SimulateNetworkChange(
863 NetworkChangeNotifier::ConnectionType::CONNECTION_3G, "test-3");
864 EXPECT_TRUE(estimator.GetRecentRTT(nqe::internal::OBSERVATION_CATEGORY_HTTP,
865 base::TimeTicks(), &rtt, nullptr));
866 EXPECT_EQ(base::Milliseconds(273), rtt);
867 EXPECT_EQ(rtt, estimator.GetHttpRTT().value());
868 EXPECT_TRUE(
869 estimator.GetRecentRTT(nqe::internal::OBSERVATION_CATEGORY_TRANSPORT,
870 base::TimeTicks(), &rtt, nullptr));
871 EXPECT_EQ(base::Milliseconds(209), rtt);
872 EXPECT_EQ(rtt, estimator.GetTransportRTT().value());
873 EXPECT_TRUE(
874 estimator.GetRecentDownlinkThroughputKbps(base::TimeTicks(), &kbps));
875 EXPECT_EQ(749, kbps);
876 EXPECT_EQ(kbps, estimator.GetDownstreamThroughputKbps().value());
877 }
878
879 // Tests that |GetEffectiveConnectionType| returns
880 // EFFECTIVE_CONNECTION_TYPE_OFFLINE when the device is currently offline.
TEST_F(NetworkQualityEstimatorTest,Offline)881 TEST_F(NetworkQualityEstimatorTest, Offline) {
882 std::map<std::string, std::string> variation_params;
883 variation_params["add_default_platform_observations"] = "false";
884 TestNetworkQualityEstimator estimator(variation_params);
885
886 const struct {
887 NetworkChangeNotifier::ConnectionType connection_type;
888 EffectiveConnectionType expected_connection_type;
889 } tests[] = {
890 {NetworkChangeNotifier::CONNECTION_2G, EFFECTIVE_CONNECTION_TYPE_UNKNOWN},
891 {NetworkChangeNotifier::CONNECTION_NONE,
892 EFFECTIVE_CONNECTION_TYPE_OFFLINE},
893 {NetworkChangeNotifier::CONNECTION_3G, EFFECTIVE_CONNECTION_TYPE_UNKNOWN},
894 };
895
896 for (const auto& test : tests) {
897 estimator.SimulateNetworkChange(test.connection_type, "test");
898 EXPECT_EQ(test.expected_connection_type,
899 estimator.GetEffectiveConnectionType());
900 }
901 }
902
903 // Tests that |GetEffectiveConnectionType| returns correct connection type when
904 // only RTT thresholds are specified in the variation params.
TEST_F(NetworkQualityEstimatorTest,ObtainThresholdsOnlyRTT)905 TEST_F(NetworkQualityEstimatorTest, ObtainThresholdsOnlyRTT) {
906 std::map<std::string, std::string> variation_params;
907
908 variation_params["Offline.ThresholdMedianHttpRTTMsec"] = "4000";
909 variation_params["Slow2G.ThresholdMedianHttpRTTMsec"] = "2000";
910 variation_params["2G.ThresholdMedianHttpRTTMsec"] = "1000";
911 variation_params["3G.ThresholdMedianHttpRTTMsec"] = "500";
912
913 TestNetworkQualityEstimator estimator(variation_params);
914
915 // Simulate the connection type as Wi-Fi so that GetEffectiveConnectionType
916 // does not return Offline if the device is offline.
917 estimator.SimulateNetworkChange(NetworkChangeNotifier::CONNECTION_WIFI,
918 "test");
919
920 const struct {
921 int32_t rtt_msec;
922 EffectiveConnectionType expected_ect;
923 } tests[] = {
924 {5000, EFFECTIVE_CONNECTION_TYPE_OFFLINE},
925 {4000, EFFECTIVE_CONNECTION_TYPE_OFFLINE},
926 {3000, EFFECTIVE_CONNECTION_TYPE_SLOW_2G},
927 {2000, EFFECTIVE_CONNECTION_TYPE_SLOW_2G},
928 {1500, EFFECTIVE_CONNECTION_TYPE_2G},
929 {1000, EFFECTIVE_CONNECTION_TYPE_2G},
930 {700, EFFECTIVE_CONNECTION_TYPE_3G},
931 {500, EFFECTIVE_CONNECTION_TYPE_3G},
932 {400, EFFECTIVE_CONNECTION_TYPE_4G},
933 {300, EFFECTIVE_CONNECTION_TYPE_4G},
934 {200, EFFECTIVE_CONNECTION_TYPE_4G},
935 {100, EFFECTIVE_CONNECTION_TYPE_4G},
936 {20, EFFECTIVE_CONNECTION_TYPE_4G},
937 };
938
939 for (const auto& test : tests) {
940 estimator.set_recent_http_rtt(base::Milliseconds(test.rtt_msec));
941 estimator.set_start_time_null_downlink_throughput_kbps(INT32_MAX);
942 estimator.set_recent_downlink_throughput_kbps(INT32_MAX);
943 estimator.SetStartTimeNullHttpRtt(base::Milliseconds(test.rtt_msec));
944 EXPECT_EQ(test.expected_ect, estimator.GetEffectiveConnectionType());
945 }
946 }
947
TEST_F(NetworkQualityEstimatorTest,ClampKbpsBasedOnEct)948 TEST_F(NetworkQualityEstimatorTest, ClampKbpsBasedOnEct) {
949 const int32_t kTypicalDownlinkKbpsEffectiveConnectionType
950 [net::EFFECTIVE_CONNECTION_TYPE_LAST] = {0, 0, 40, 75, 400, 1600};
951
952 const struct {
953 std::string upper_bound_typical_kbps_multiplier;
954 int32_t set_rtt_msec;
955 int32_t set_downstream_kbps;
956 EffectiveConnectionType expected_ect;
957 int32_t expected_downstream_throughput;
958 } tests[] = {
959 // Clamping multiplier set to 3.5 by default.
960 {"", 3000, INT32_MAX, EFFECTIVE_CONNECTION_TYPE_SLOW_2G,
961 base::ClampFloor(kTypicalDownlinkKbpsEffectiveConnectionType
962 [EFFECTIVE_CONNECTION_TYPE_SLOW_2G] *
963 3.5)},
964 // Clamping disabled.
965 {"-1", 3000, INT32_MAX, EFFECTIVE_CONNECTION_TYPE_SLOW_2G, INT32_MAX},
966 // Clamping multiplier overridden to 1000.
967 {"1000.0", 3000, INT32_MAX, EFFECTIVE_CONNECTION_TYPE_SLOW_2G,
968 kTypicalDownlinkKbpsEffectiveConnectionType
969 [EFFECTIVE_CONNECTION_TYPE_SLOW_2G] *
970 1000},
971 // Clamping multiplier overridden to 1000.
972 {"1000.0", 1500, INT32_MAX, EFFECTIVE_CONNECTION_TYPE_2G,
973 kTypicalDownlinkKbpsEffectiveConnectionType
974 [EFFECTIVE_CONNECTION_TYPE_2G] *
975 1000},
976 // Clamping multiplier overridden to 1000.
977 {"1000.0", 700, INT32_MAX, EFFECTIVE_CONNECTION_TYPE_3G,
978 kTypicalDownlinkKbpsEffectiveConnectionType
979 [EFFECTIVE_CONNECTION_TYPE_3G] *
980 1000},
981 // Clamping multiplier set to 3.5 by default.
982 {"", 500, INT32_MAX, EFFECTIVE_CONNECTION_TYPE_3G,
983 base::ClampFloor(kTypicalDownlinkKbpsEffectiveConnectionType
984 [EFFECTIVE_CONNECTION_TYPE_3G] *
985 3.5)},
986 // Clamping ineffective when the observed throughput is lower than the
987 // clamped throughput.
988 {"", 500, 100, EFFECTIVE_CONNECTION_TYPE_3G, 100},
989 // Clamping disabled on 4G ECT.
990 {"1.0", 40, INT32_MAX, EFFECTIVE_CONNECTION_TYPE_4G, INT32_MAX},
991 // Clamping disabled on 4G ECT.
992 {"1.0", 40, 100, EFFECTIVE_CONNECTION_TYPE_4G, 100},
993 };
994
995 for (const auto& test : tests) {
996 std::map<std::string, std::string> variation_params;
997 variation_params["upper_bound_typical_kbps_multiplier"] =
998 test.upper_bound_typical_kbps_multiplier;
999 TestNetworkQualityEstimator estimator(variation_params);
1000
1001 // Simulate the connection type as Wi-Fi so that GetEffectiveConnectionType
1002 // does not return Offline if the device is offline.
1003 estimator.SimulateNetworkChange(NetworkChangeNotifier::CONNECTION_WIFI,
1004 "test");
1005
1006 estimator.set_recent_http_rtt(base::Milliseconds(test.set_rtt_msec));
1007 estimator.set_start_time_null_downlink_throughput_kbps(INT32_MAX);
1008 estimator.set_recent_downlink_throughput_kbps(test.set_downstream_kbps);
1009 estimator.set_start_time_null_downlink_throughput_kbps(
1010 test.set_downstream_kbps);
1011 estimator.SetStartTimeNullHttpRtt(base::Milliseconds(test.set_rtt_msec));
1012 EXPECT_EQ(test.expected_ect, estimator.GetEffectiveConnectionType());
1013 EXPECT_EQ(test.expected_downstream_throughput,
1014 estimator.GetDownstreamThroughputKbps().value());
1015 }
1016 }
1017
1018 // Tests that default HTTP RTT thresholds for different effective
1019 // connection types are correctly set.
TEST_F(NetworkQualityEstimatorTest,DefaultHttpRTTBasedThresholds)1020 TEST_F(NetworkQualityEstimatorTest, DefaultHttpRTTBasedThresholds) {
1021 const struct {
1022 bool override_defaults_using_variation_params;
1023 int32_t http_rtt_msec;
1024 EffectiveConnectionType expected_ect;
1025 } tests[] = {
1026 // When the variation params do not override connection thresholds,
1027 // default values should be used.
1028 {false, 5000, EFFECTIVE_CONNECTION_TYPE_SLOW_2G},
1029 {false, 4000, EFFECTIVE_CONNECTION_TYPE_SLOW_2G},
1030 {false, 3000, EFFECTIVE_CONNECTION_TYPE_SLOW_2G},
1031 {false, 2000, EFFECTIVE_CONNECTION_TYPE_2G},
1032 {false, 1500, EFFECTIVE_CONNECTION_TYPE_2G},
1033 {false, 1000, EFFECTIVE_CONNECTION_TYPE_3G},
1034 {false, 100, EFFECTIVE_CONNECTION_TYPE_4G},
1035 {false, 20, EFFECTIVE_CONNECTION_TYPE_4G},
1036 // Override default thresholds using variation params.
1037 {true, 5000, EFFECTIVE_CONNECTION_TYPE_OFFLINE},
1038 {true, 4000, EFFECTIVE_CONNECTION_TYPE_OFFLINE},
1039 {true, 3000, EFFECTIVE_CONNECTION_TYPE_SLOW_2G},
1040 {true, 2000, EFFECTIVE_CONNECTION_TYPE_SLOW_2G},
1041 {true, 1500, EFFECTIVE_CONNECTION_TYPE_2G},
1042 {true, 1000, EFFECTIVE_CONNECTION_TYPE_2G},
1043 {true, 20, EFFECTIVE_CONNECTION_TYPE_4G},
1044 };
1045
1046 for (const auto& test : tests) {
1047 std::map<std::string, std::string> variation_params;
1048 if (test.override_defaults_using_variation_params) {
1049 variation_params["Offline.ThresholdMedianHttpRTTMsec"] = "4000";
1050 variation_params["Slow2G.ThresholdMedianHttpRTTMsec"] = "2000";
1051 variation_params["2G.ThresholdMedianHttpRTTMsec"] = "1000";
1052 }
1053
1054 TestNetworkQualityEstimator estimator(variation_params);
1055
1056 // Simulate the connection type as Wi-Fi so that GetEffectiveConnectionType
1057 // does not return Offline if the device is offline.
1058 estimator.SimulateNetworkChange(NetworkChangeNotifier::CONNECTION_WIFI,
1059 "test");
1060
1061 estimator.SetStartTimeNullHttpRtt(base::Milliseconds(test.http_rtt_msec));
1062 estimator.set_recent_http_rtt(base::Milliseconds(test.http_rtt_msec));
1063 estimator.set_start_time_null_downlink_throughput_kbps(INT32_MAX);
1064 estimator.set_recent_downlink_throughput_kbps(INT32_MAX);
1065 EXPECT_EQ(test.expected_ect, estimator.GetEffectiveConnectionType());
1066 }
1067 }
1068
1069 // Tests that |GetEffectiveConnectionType| returns correct connection type when
1070 // both HTTP RTT and throughput thresholds are specified in the variation
1071 // params.
TEST_F(NetworkQualityEstimatorTest,ObtainThresholdsHttpRTTandThroughput)1072 TEST_F(NetworkQualityEstimatorTest, ObtainThresholdsHttpRTTandThroughput) {
1073 std::map<std::string, std::string> variation_params;
1074
1075 variation_params["Offline.ThresholdMedianHttpRTTMsec"] = "4000";
1076 variation_params["Slow2G.ThresholdMedianHttpRTTMsec"] = "2000";
1077 variation_params["2G.ThresholdMedianHttpRTTMsec"] = "1000";
1078 variation_params["3G.ThresholdMedianHttpRTTMsec"] = "500";
1079
1080 TestNetworkQualityEstimator estimator(variation_params);
1081
1082 // Simulate the connection type as Wi-Fi so that GetEffectiveConnectionType
1083 // does not return Offline if the device is offline.
1084 estimator.SimulateNetworkChange(NetworkChangeNotifier::CONNECTION_WIFI,
1085 "test");
1086
1087 const struct {
1088 int32_t rtt_msec;
1089 int32_t downlink_throughput_kbps;
1090 EffectiveConnectionType expected_ect;
1091 } tests[] = {
1092 // Set both RTT and throughput. RTT is the bottleneck.
1093 {3000, 25000, EFFECTIVE_CONNECTION_TYPE_SLOW_2G},
1094 {700, 25000, EFFECTIVE_CONNECTION_TYPE_3G},
1095 };
1096
1097 for (const auto& test : tests) {
1098 estimator.SetStartTimeNullHttpRtt(base::Milliseconds(test.rtt_msec));
1099 estimator.set_recent_http_rtt(base::Milliseconds(test.rtt_msec));
1100 estimator.set_start_time_null_downlink_throughput_kbps(
1101 test.downlink_throughput_kbps);
1102 estimator.set_recent_downlink_throughput_kbps(
1103 test.downlink_throughput_kbps);
1104 // Run one main frame request to force recomputation of effective connection
1105 // type.
1106 estimator.RunOneRequest();
1107 EXPECT_EQ(test.expected_ect, estimator.GetEffectiveConnectionType());
1108 }
1109 }
1110
TEST_F(NetworkQualityEstimatorTest,TestGetMetricsSince)1111 TEST_F(NetworkQualityEstimatorTest, TestGetMetricsSince) {
1112 std::map<std::string, std::string> variation_params;
1113
1114 const base::TimeDelta rtt_threshold_3g = base::Milliseconds(30);
1115 const base::TimeDelta rtt_threshold_4g = base::Milliseconds(1);
1116
1117 variation_params["3G.ThresholdMedianHttpRTTMsec"] =
1118 base::NumberToString(rtt_threshold_3g.InMilliseconds());
1119 variation_params["HalfLifeSeconds"] = "300000";
1120 variation_params["add_default_platform_observations"] = "false";
1121
1122 TestNetworkQualityEstimator estimator(variation_params);
1123 base::TimeTicks now = base::TimeTicks::Now();
1124 base::TimeTicks old = now - base::Milliseconds(1);
1125 ASSERT_NE(old, now);
1126
1127 estimator.SimulateNetworkChange(
1128 NetworkChangeNotifier::ConnectionType::CONNECTION_WIFI, "test");
1129
1130 const int32_t old_downlink_kbps = 1;
1131 const base::TimeDelta old_url_rtt = base::Milliseconds(1);
1132 const base::TimeDelta old_tcp_rtt = base::Milliseconds(10);
1133
1134 DCHECK_LT(old_url_rtt, rtt_threshold_3g);
1135 DCHECK_LT(old_tcp_rtt, rtt_threshold_3g);
1136
1137 // First sample has very old timestamp.
1138 for (size_t i = 0; i < 2; ++i) {
1139 estimator.http_downstream_throughput_kbps_observations_.AddObservation(
1140 NetworkQualityEstimator::Observation(
1141 old_downlink_kbps, old, INT32_MIN,
1142 NETWORK_QUALITY_OBSERVATION_SOURCE_HTTP));
1143 estimator.rtt_ms_observations_[nqe::internal::OBSERVATION_CATEGORY_HTTP]
1144 .AddObservation(NetworkQualityEstimator::Observation(
1145 old_url_rtt.InMilliseconds(), old, INT32_MIN,
1146 NETWORK_QUALITY_OBSERVATION_SOURCE_HTTP));
1147 estimator
1148 .rtt_ms_observations_[nqe::internal::OBSERVATION_CATEGORY_TRANSPORT]
1149 .AddObservation(NetworkQualityEstimator::Observation(
1150 old_tcp_rtt.InMilliseconds(), old, INT32_MIN,
1151 NETWORK_QUALITY_OBSERVATION_SOURCE_TCP));
1152 }
1153
1154 const int32_t new_downlink_kbps = 100;
1155 const base::TimeDelta new_url_rtt = base::Milliseconds(100);
1156 const base::TimeDelta new_tcp_rtt = base::Milliseconds(1000);
1157
1158 DCHECK_NE(old_downlink_kbps, new_downlink_kbps);
1159 DCHECK_NE(old_url_rtt, new_url_rtt);
1160 DCHECK_NE(old_tcp_rtt, new_tcp_rtt);
1161 DCHECK_GT(new_url_rtt, rtt_threshold_3g);
1162 DCHECK_GT(new_tcp_rtt, rtt_threshold_3g);
1163 DCHECK_GT(new_url_rtt, rtt_threshold_4g);
1164 DCHECK_GT(new_tcp_rtt, rtt_threshold_4g);
1165
1166 estimator.http_downstream_throughput_kbps_observations_.AddObservation(
1167 NetworkQualityEstimator::Observation(
1168 new_downlink_kbps, now, INT32_MIN,
1169 NETWORK_QUALITY_OBSERVATION_SOURCE_HTTP));
1170 estimator.rtt_ms_observations_[nqe::internal::OBSERVATION_CATEGORY_HTTP]
1171 .AddObservation(NetworkQualityEstimator::Observation(
1172 new_url_rtt.InMilliseconds(), now, INT32_MIN,
1173 NETWORK_QUALITY_OBSERVATION_SOURCE_HTTP));
1174 estimator.rtt_ms_observations_[nqe::internal::OBSERVATION_CATEGORY_TRANSPORT]
1175 .AddObservation(NetworkQualityEstimator::Observation(
1176 new_tcp_rtt.InMilliseconds(), now, INT32_MIN,
1177 NETWORK_QUALITY_OBSERVATION_SOURCE_TCP));
1178
1179 const struct {
1180 base::TimeTicks start_timestamp;
1181 bool expect_network_quality_available;
1182 base::TimeDelta expected_http_rtt;
1183 base::TimeDelta expected_transport_rtt;
1184 int32_t expected_downstream_throughput;
1185 EffectiveConnectionType expected_effective_connection_type;
1186 } tests[] = {
1187 {now + base::Seconds(10), false, base::Milliseconds(0),
1188 base::Milliseconds(0), 0, EFFECTIVE_CONNECTION_TYPE_4G},
1189 {now, true, new_url_rtt, new_tcp_rtt, new_downlink_kbps,
1190 EFFECTIVE_CONNECTION_TYPE_3G},
1191 {old - base::Microseconds(500), true, old_url_rtt, old_tcp_rtt,
1192 old_downlink_kbps, EFFECTIVE_CONNECTION_TYPE_4G},
1193
1194 };
1195 for (const auto& test : tests) {
1196 base::TimeDelta http_rtt;
1197 base::TimeDelta transport_rtt;
1198 int32_t downstream_throughput_kbps;
1199 EXPECT_EQ(test.expect_network_quality_available,
1200 estimator.GetRecentRTT(nqe::internal::OBSERVATION_CATEGORY_HTTP,
1201 test.start_timestamp, &http_rtt, nullptr));
1202 EXPECT_EQ(
1203 test.expect_network_quality_available,
1204 estimator.GetRecentRTT(nqe::internal::OBSERVATION_CATEGORY_TRANSPORT,
1205 test.start_timestamp, &transport_rtt, nullptr));
1206 EXPECT_EQ(test.expect_network_quality_available,
1207 estimator.GetRecentDownlinkThroughputKbps(
1208 test.start_timestamp, &downstream_throughput_kbps));
1209
1210 if (test.expect_network_quality_available) {
1211 EXPECT_EQ(test.expected_http_rtt, http_rtt);
1212 EXPECT_EQ(test.expected_transport_rtt, transport_rtt);
1213 EXPECT_EQ(test.expected_downstream_throughput,
1214 downstream_throughput_kbps);
1215 }
1216 }
1217 }
1218
1219 #if BUILDFLAG(IS_IOS)
1220 // Flaky on iOS: crbug.com/672917.
1221 #define MAYBE_TestThroughputNoRequestOverlap \
1222 DISABLED_TestThroughputNoRequestOverlap
1223 #else
1224 #define MAYBE_TestThroughputNoRequestOverlap TestThroughputNoRequestOverlap
1225 #endif
1226 // Tests if the throughput observation is taken correctly when local and network
1227 // requests do not overlap.
TEST_F(NetworkQualityEstimatorTest,MAYBE_TestThroughputNoRequestOverlap)1228 TEST_F(NetworkQualityEstimatorTest, MAYBE_TestThroughputNoRequestOverlap) {
1229 base::HistogramTester histogram_tester;
1230 std::map<std::string, std::string> variation_params;
1231 variation_params["throughput_min_requests_in_flight"] = "1";
1232 variation_params["add_default_platform_observations"] = "false";
1233
1234 static const struct {
1235 bool allow_small_localhost_requests;
1236 } tests[] = {
1237 {
1238 false,
1239 },
1240 {
1241 true,
1242 },
1243 };
1244
1245 for (const auto& test : tests) {
1246 TestNetworkQualityEstimator estimator(variation_params,
1247 test.allow_small_localhost_requests,
1248 test.allow_small_localhost_requests);
1249
1250 base::TimeDelta rtt;
1251 EXPECT_FALSE(
1252 estimator.GetRecentRTT(nqe::internal::OBSERVATION_CATEGORY_HTTP,
1253 base::TimeTicks(), &rtt, nullptr));
1254 int32_t kbps;
1255 EXPECT_FALSE(
1256 estimator.GetRecentDownlinkThroughputKbps(base::TimeTicks(), &kbps));
1257
1258 TestDelegate test_delegate;
1259 auto context_builder = CreateTestURLRequestContextBuilder();
1260 context_builder->set_network_quality_estimator(&estimator);
1261 auto context = context_builder->Build();
1262
1263 std::unique_ptr<URLRequest> request(
1264 context->CreateRequest(estimator.GetEchoURL(), DEFAULT_PRIORITY,
1265 &test_delegate, TRAFFIC_ANNOTATION_FOR_TESTS));
1266 request->SetLoadFlags(request->load_flags() | LOAD_MAIN_FRAME_DEPRECATED);
1267 request->Start();
1268 test_delegate.RunUntilComplete();
1269
1270 // Pump message loop to allow estimator tasks to be processed.
1271 base::RunLoop().RunUntilIdle();
1272
1273 EXPECT_EQ(test.allow_small_localhost_requests,
1274 estimator.GetRecentRTT(nqe::internal::OBSERVATION_CATEGORY_HTTP,
1275 base::TimeTicks(), &rtt, nullptr));
1276 EXPECT_EQ(
1277 test.allow_small_localhost_requests,
1278 estimator.GetRecentDownlinkThroughputKbps(base::TimeTicks(), &kbps));
1279 }
1280 }
1281
1282 #if BUILDFLAG(IS_IOS)
1283 // Flaky on iOS: crbug.com/672917.
1284 #define MAYBE_TestEffectiveConnectionTypeObserver \
1285 DISABLED_TestEffectiveConnectionTypeObserver
1286 #else
1287 #define MAYBE_TestEffectiveConnectionTypeObserver \
1288 TestEffectiveConnectionTypeObserver
1289 #endif
1290
1291 // Tests that the effective connection type is computed at the specified
1292 // interval, and that the observers are notified of any change.
TEST_F(NetworkQualityEstimatorTest,MAYBE_TestEffectiveConnectionTypeObserver)1293 TEST_F(NetworkQualityEstimatorTest, MAYBE_TestEffectiveConnectionTypeObserver) {
1294 base::HistogramTester histogram_tester;
1295 base::SimpleTestTickClock tick_clock;
1296
1297 TestEffectiveConnectionTypeObserver observer;
1298 std::map<std::string, std::string> variation_params;
1299 variation_params["add_default_platform_observations"] = "false";
1300 TestNetworkQualityEstimator estimator(variation_params);
1301 estimator.AddEffectiveConnectionTypeObserver(&observer);
1302 // |observer| may be notified as soon as it is added. Run the loop to so that
1303 // the notification to |observer| is finished.
1304 base::RunLoop().RunUntilIdle();
1305 estimator.SetTickClockForTesting(&tick_clock);
1306
1307 TestDelegate test_delegate;
1308 auto context_builder = CreateTestURLRequestContextBuilder();
1309 context_builder->set_network_quality_estimator(&estimator);
1310 context_builder->SuppressSettingSocketPerformanceWatcherFactoryForTesting();
1311 auto context = context_builder->Build();
1312
1313 EXPECT_EQ(0U, observer.effective_connection_types().size());
1314
1315 estimator.SetStartTimeNullHttpRtt(base::Milliseconds(1500));
1316 estimator.set_start_time_null_downlink_throughput_kbps(164);
1317
1318 tick_clock.Advance(base::Minutes(60));
1319
1320 std::unique_ptr<URLRequest> request(
1321 context->CreateRequest(estimator.GetEchoURL(), DEFAULT_PRIORITY,
1322 &test_delegate, TRAFFIC_ANNOTATION_FOR_TESTS));
1323 request->SetLoadFlags(request->load_flags() | LOAD_MAIN_FRAME_DEPRECATED);
1324 request->Start();
1325 test_delegate.RunUntilComplete();
1326 EXPECT_EQ(1U, observer.effective_connection_types().size());
1327 EXPECT_LE(
1328 1, estimator.GetEntriesCount(NetLogEventType::NETWORK_QUALITY_CHANGED));
1329
1330 // Verify the contents of the net log.
1331 EXPECT_EQ(GetNameForEffectiveConnectionType(EFFECTIVE_CONNECTION_TYPE_2G),
1332 estimator.GetNetLogLastStringValue(
1333 NetLogEventType::NETWORK_QUALITY_CHANGED,
1334 "effective_connection_type"));
1335 EXPECT_EQ(1500, estimator.GetNetLogLastIntegerValue(
1336 NetLogEventType::NETWORK_QUALITY_CHANGED, "http_rtt_ms"));
1337 EXPECT_EQ(-1,
1338 estimator.GetNetLogLastIntegerValue(
1339 NetLogEventType::NETWORK_QUALITY_CHANGED, "transport_rtt_ms"));
1340 EXPECT_EQ(164, estimator.GetNetLogLastIntegerValue(
1341 NetLogEventType::NETWORK_QUALITY_CHANGED,
1342 "downstream_throughput_kbps"));
1343
1344 // Next request should not trigger recomputation of effective connection type
1345 // since there has been no change in the clock.
1346 std::unique_ptr<URLRequest> request2(
1347 context->CreateRequest(estimator.GetEchoURL(), DEFAULT_PRIORITY,
1348 &test_delegate, TRAFFIC_ANNOTATION_FOR_TESTS));
1349 request2->SetLoadFlags(request->load_flags() | LOAD_MAIN_FRAME_DEPRECATED);
1350 request2->Start();
1351 test_delegate.RunUntilComplete();
1352 EXPECT_EQ(1U, observer.effective_connection_types().size());
1353
1354 // Change in connection type should send out notification to the observers.
1355 estimator.SetStartTimeNullHttpRtt(base::Milliseconds(500));
1356 estimator.SimulateNetworkChange(NetworkChangeNotifier::CONNECTION_WIFI,
1357 "test");
1358 EXPECT_EQ(3U, observer.effective_connection_types().size());
1359
1360 // A change in effective connection type does not trigger notification to the
1361 // observers, since it is not accompanied by any new observation or a network
1362 // change event.
1363 estimator.SetStartTimeNullHttpRtt(base::Milliseconds(100));
1364 EXPECT_EQ(4U, observer.effective_connection_types().size());
1365
1366 TestEffectiveConnectionTypeObserver observer_2;
1367 estimator.AddEffectiveConnectionTypeObserver(&observer_2);
1368 EXPECT_EQ(0U, observer_2.effective_connection_types().size());
1369 base::RunLoop().RunUntilIdle();
1370 // |observer_2| must be notified as soon as it is added.
1371 EXPECT_EQ(1U, observer_2.effective_connection_types().size());
1372
1373 // |observer_3| should not be notified since it unregisters before the
1374 // message loop is run.
1375 TestEffectiveConnectionTypeObserver observer_3;
1376 estimator.AddEffectiveConnectionTypeObserver(&observer_3);
1377 EXPECT_EQ(0U, observer_3.effective_connection_types().size());
1378 estimator.RemoveEffectiveConnectionTypeObserver(&observer_3);
1379 base::RunLoop().RunUntilIdle();
1380 EXPECT_EQ(0U, observer_3.effective_connection_types().size());
1381 }
1382
1383 // Tests that the transport RTT is used for computing the HTTP RTT.
TEST_F(NetworkQualityEstimatorTest,TestTransportRttUsedForHttpRttComputation)1384 TEST_F(NetworkQualityEstimatorTest, TestTransportRttUsedForHttpRttComputation) {
1385 const struct {
1386 base::TimeDelta http_rtt;
1387 base::TimeDelta transport_rtt;
1388 base::TimeDelta expected_http_rtt;
1389 EffectiveConnectionType expected_type;
1390 } tests[] = {
1391 {
1392 base::Milliseconds(200),
1393 base::Milliseconds(100),
1394 base::Milliseconds(200),
1395 EFFECTIVE_CONNECTION_TYPE_4G,
1396 },
1397 {
1398 base::Milliseconds(100),
1399 base::Milliseconds(200),
1400 base::Milliseconds(200),
1401 EFFECTIVE_CONNECTION_TYPE_4G,
1402 },
1403 {
1404 base::Milliseconds(100),
1405 base::Milliseconds(4000),
1406 base::Milliseconds(4000),
1407 EFFECTIVE_CONNECTION_TYPE_SLOW_2G,
1408 },
1409 };
1410
1411 for (const auto& test : tests) {
1412 std::map<std::string, std::string> variation_params;
1413 variation_params["add_default_platform_observations"] = "false";
1414
1415 base::SimpleTestTickClock tick_clock;
1416 tick_clock.Advance(base::Seconds(1));
1417
1418 TestNetworkQualityEstimator estimator(variation_params);
1419 estimator.SetTickClockForTesting(&tick_clock);
1420 estimator.SetStartTimeNullHttpRtt(test.http_rtt);
1421 estimator.SetStartTimeNullTransportRtt(test.transport_rtt);
1422
1423 // Minimum number of transport RTT samples that should be present before
1424 // transport RTT estimate can be used to clamp the HTTP RTT.
1425 estimator.SetTransportRTTAtastECTSampleCount(
1426 estimator.params()->http_rtt_transport_rtt_min_count());
1427
1428 // Add one observation to ensure ECT is not computed for each request.
1429 estimator.AddAndNotifyObserversOfRTT(NetworkQualityEstimator::Observation(
1430 test.http_rtt.InMilliseconds(), tick_clock.NowTicks(), INT32_MIN,
1431 NETWORK_QUALITY_OBSERVATION_SOURCE_HTTP));
1432
1433 EXPECT_EQ(test.expected_http_rtt, estimator.GetHttpRTT());
1434 EXPECT_EQ(test.transport_rtt, estimator.GetTransportRTT());
1435 EXPECT_EQ(test.expected_type, estimator.GetEffectiveConnectionType());
1436 }
1437 }
1438
1439 // Tests that the end to end RTT is used for computing the lower bound for HTTP
1440 // RTT.
TEST_F(NetworkQualityEstimatorTest,TestEndToEndRttUsedForHttpRttComputation)1441 TEST_F(NetworkQualityEstimatorTest, TestEndToEndRttUsedForHttpRttComputation) {
1442 const struct {
1443 base::TimeDelta http_rtt;
1444 base::TimeDelta end_to_end_rtt;
1445 bool is_end_to_end_rtt_sample_count_enough;
1446 base::TimeDelta expected_http_rtt;
1447 EffectiveConnectionType expected_type;
1448 } tests[] = {
1449 {
1450 base::Milliseconds(200),
1451 base::Milliseconds(100),
1452 true,
1453 base::Milliseconds(200),
1454 EFFECTIVE_CONNECTION_TYPE_4G,
1455 },
1456 {
1457 // |http_rtt| is lower than |end_to_end_rtt|. The HTTP RTT estimate
1458 // should be set to |end_to_end_rtt|.
1459 base::Milliseconds(100),
1460 base::Milliseconds(200),
1461 true,
1462 base::Milliseconds(200),
1463 EFFECTIVE_CONNECTION_TYPE_4G,
1464 },
1465 {
1466 // Not enough samples. End to End RTT should not be used.
1467 base::Milliseconds(100),
1468 base::Milliseconds(200),
1469 false,
1470 base::Milliseconds(100),
1471 EFFECTIVE_CONNECTION_TYPE_4G,
1472 },
1473 {
1474 base::Milliseconds(100),
1475 base::Milliseconds(4000),
1476 true,
1477 base::Milliseconds(4000),
1478 EFFECTIVE_CONNECTION_TYPE_SLOW_2G,
1479 },
1480 {
1481 // Verify end to end RTT places an upper bound on HTTP RTT when enough
1482 // samples are present.
1483 base::Milliseconds(3000),
1484 base::Milliseconds(100),
1485 true,
1486 base::Milliseconds(300),
1487 EFFECTIVE_CONNECTION_TYPE_3G,
1488 },
1489 {
1490 // Verify end to end RTT does not place an upper bound on HTTP RTT
1491 // when enough samples are not present.
1492 base::Milliseconds(3000),
1493 base::Milliseconds(100),
1494 false,
1495 base::Milliseconds(3000),
1496 EFFECTIVE_CONNECTION_TYPE_SLOW_2G,
1497 },
1498 };
1499
1500 for (const auto& test : tests) {
1501 std::map<std::string, std::string> variation_params;
1502 variation_params["add_default_platform_observations"] = "false";
1503 variation_params["use_end_to_end_rtt"] = "true";
1504
1505 base::SimpleTestTickClock tick_clock; // Must outlive `estimator`.
1506 tick_clock.Advance(base::Seconds(1));
1507
1508 TestNetworkQualityEstimator estimator(variation_params);
1509 estimator.SetTickClockForTesting(&tick_clock);
1510 estimator.SetStartTimeNullHttpRtt(test.http_rtt);
1511 estimator.set_start_time_null_end_to_end_rtt(test.end_to_end_rtt);
1512
1513 // Minimum number of end to end RTT samples that should be present before
1514 // transport RTT estimate can be used to clamp the HTTP RTT.
1515 if (test.is_end_to_end_rtt_sample_count_enough) {
1516 estimator.set_start_time_null_end_to_end_rtt_observation_count(
1517 estimator.params()->http_rtt_transport_rtt_min_count());
1518 } else {
1519 estimator.set_start_time_null_end_to_end_rtt_observation_count(
1520 estimator.params()->http_rtt_transport_rtt_min_count() - 1);
1521 }
1522
1523 // Ensure ECT is recomputed.
1524 estimator.RunOneRequest();
1525
1526 EXPECT_EQ(test.expected_http_rtt, estimator.GetHttpRTT().value());
1527 EXPECT_EQ(test.expected_type, estimator.GetEffectiveConnectionType());
1528 }
1529 }
1530
1531 // Tests that the network quality is computed at the specified interval, and
1532 // that the network quality observers are notified of any change.
TEST_F(NetworkQualityEstimatorTest,TestRTTAndThroughputEstimatesObserver)1533 TEST_F(NetworkQualityEstimatorTest, TestRTTAndThroughputEstimatesObserver) {
1534 base::HistogramTester histogram_tester;
1535 base::SimpleTestTickClock tick_clock;
1536
1537 TestRTTAndThroughputEstimatesObserver observer;
1538 std::map<std::string, std::string> variation_params;
1539 variation_params["add_default_platform_observations"] = "false";
1540 TestNetworkQualityEstimator estimator(variation_params);
1541 estimator.AddRTTAndThroughputEstimatesObserver(&observer);
1542 estimator.SetTickClockForTesting(&tick_clock);
1543
1544 TestDelegate test_delegate;
1545 auto context_builder = CreateTestURLRequestContextBuilder();
1546 context_builder->set_network_quality_estimator(&estimator);
1547 auto context = context_builder->Build();
1548
1549 EXPECT_EQ(nqe::internal::InvalidRTT(), observer.http_rtt());
1550 EXPECT_EQ(nqe::internal::InvalidRTT(), observer.transport_rtt());
1551 EXPECT_EQ(nqe::internal::INVALID_RTT_THROUGHPUT,
1552 observer.downstream_throughput_kbps());
1553 int notifications_received = observer.notifications_received();
1554 EXPECT_EQ(0, notifications_received);
1555
1556 base::TimeDelta http_rtt(base::Milliseconds(100));
1557 base::TimeDelta transport_rtt(base::Milliseconds(200));
1558 int32_t downstream_throughput_kbps(300);
1559 estimator.SetStartTimeNullHttpRtt(http_rtt);
1560 estimator.SetStartTimeNullTransportRtt(transport_rtt);
1561 estimator.set_start_time_null_downlink_throughput_kbps(
1562 downstream_throughput_kbps);
1563 tick_clock.Advance(base::Minutes(60));
1564
1565 std::unique_ptr<URLRequest> request(
1566 context->CreateRequest(estimator.GetEchoURL(), DEFAULT_PRIORITY,
1567 &test_delegate, TRAFFIC_ANNOTATION_FOR_TESTS));
1568 request->Start();
1569 test_delegate.RunUntilComplete();
1570 EXPECT_EQ(http_rtt, observer.http_rtt());
1571 EXPECT_EQ(transport_rtt, observer.transport_rtt());
1572 EXPECT_EQ(downstream_throughput_kbps, observer.downstream_throughput_kbps());
1573 EXPECT_LE(1, observer.notifications_received() - notifications_received);
1574 notifications_received = observer.notifications_received();
1575
1576 // The next request should not trigger recomputation of RTT or throughput
1577 // since there has been no change in the clock.
1578 std::unique_ptr<URLRequest> request2(
1579 context->CreateRequest(estimator.GetEchoURL(), DEFAULT_PRIORITY,
1580 &test_delegate, TRAFFIC_ANNOTATION_FOR_TESTS));
1581 request2->Start();
1582 test_delegate.RunUntilComplete();
1583 EXPECT_LE(1, observer.notifications_received() - notifications_received);
1584 notifications_received = observer.notifications_received();
1585
1586 // A change in the connection type should send out notification to the
1587 // observers.
1588 estimator.SimulateNetworkChange(NetworkChangeNotifier::CONNECTION_WIFI,
1589 "test");
1590 EXPECT_EQ(http_rtt, observer.http_rtt());
1591 EXPECT_EQ(transport_rtt, observer.transport_rtt());
1592 EXPECT_EQ(downstream_throughput_kbps, observer.downstream_throughput_kbps());
1593 EXPECT_LE(1, observer.notifications_received() - notifications_received);
1594 notifications_received = observer.notifications_received();
1595
1596 // A change in effective connection type does not trigger notification to the
1597 // observers, since it is not accompanied by any new observation or a network
1598 // change event.
1599 estimator.SetStartTimeNullHttpRtt(base::Milliseconds(10000));
1600 estimator.SetStartTimeNullHttpRtt(base::Milliseconds(1));
1601 EXPECT_EQ(2, observer.notifications_received() - notifications_received);
1602
1603 TestRTTAndThroughputEstimatesObserver observer_2;
1604 estimator.AddRTTAndThroughputEstimatesObserver(&observer_2);
1605 EXPECT_EQ(nqe::internal::InvalidRTT(), observer_2.http_rtt());
1606 EXPECT_EQ(nqe::internal::InvalidRTT(), observer_2.transport_rtt());
1607 EXPECT_EQ(nqe::internal::INVALID_RTT_THROUGHPUT,
1608 observer_2.downstream_throughput_kbps());
1609 base::RunLoop().RunUntilIdle();
1610 EXPECT_NE(nqe::internal::InvalidRTT(), observer_2.http_rtt());
1611 EXPECT_NE(nqe::internal::InvalidRTT(), observer_2.transport_rtt());
1612 EXPECT_NE(nqe::internal::INVALID_RTT_THROUGHPUT,
1613 observer_2.downstream_throughput_kbps());
1614
1615 // |observer_3| should not be notified because it is unregisters before the
1616 // message loop is run.
1617 TestRTTAndThroughputEstimatesObserver observer_3;
1618 estimator.AddRTTAndThroughputEstimatesObserver(&observer_3);
1619 EXPECT_EQ(nqe::internal::InvalidRTT(), observer_3.http_rtt());
1620 EXPECT_EQ(nqe::internal::InvalidRTT(), observer_3.transport_rtt());
1621 EXPECT_EQ(nqe::internal::INVALID_RTT_THROUGHPUT,
1622 observer_3.downstream_throughput_kbps());
1623 estimator.RemoveRTTAndThroughputEstimatesObserver(&observer_3);
1624 base::RunLoop().RunUntilIdle();
1625 EXPECT_EQ(nqe::internal::InvalidRTT(), observer_3.http_rtt());
1626 EXPECT_EQ(nqe::internal::InvalidRTT(), observer_3.transport_rtt());
1627 EXPECT_EQ(nqe::internal::INVALID_RTT_THROUGHPUT,
1628 observer_3.downstream_throughput_kbps());
1629 }
1630
1631 // Tests that the effective connection type is computed on every RTT
1632 // observation if the last computed effective connection type was unknown.
TEST_F(NetworkQualityEstimatorTest,UnknownEffectiveConnectionType)1633 TEST_F(NetworkQualityEstimatorTest, UnknownEffectiveConnectionType) {
1634 base::SimpleTestTickClock tick_clock;
1635
1636 TestEffectiveConnectionTypeObserver observer;
1637 std::map<std::string, std::string> variation_params;
1638 variation_params["add_default_platform_observations"] = "false";
1639 TestNetworkQualityEstimator estimator(variation_params);
1640 estimator.SetTickClockForTesting(&tick_clock);
1641 estimator.AddEffectiveConnectionTypeObserver(&observer);
1642 tick_clock.Advance(base::Minutes(60));
1643
1644 size_t expected_effective_connection_type_notifications = 0;
1645 estimator.set_recent_effective_connection_type(
1646 EFFECTIVE_CONNECTION_TYPE_UNKNOWN);
1647 // Run one main frame request to force recomputation of effective connection
1648 // type.
1649 estimator.RunOneRequest();
1650 estimator.SimulateNetworkChange(NetworkChangeNotifier::CONNECTION_WIFI,
1651 "test");
1652
1653 NetworkQualityEstimator::Observation rtt_observation(
1654 5000, tick_clock.NowTicks(), INT32_MIN,
1655 NETWORK_QUALITY_OBSERVATION_SOURCE_HTTP);
1656
1657 for (size_t i = 0; i < 10; ++i) {
1658 estimator.AddAndNotifyObserversOfRTT(rtt_observation);
1659 EXPECT_EQ(expected_effective_connection_type_notifications,
1660 observer.effective_connection_types().size());
1661 }
1662 estimator.set_recent_effective_connection_type(
1663 EFFECTIVE_CONNECTION_TYPE_SLOW_2G);
1664 // Even though there are 10 RTT samples already available, the addition of one
1665 // more RTT sample should trigger recomputation of the effective connection
1666 // type since the last computed effective connection type was unknown.
1667 estimator.AddAndNotifyObserversOfRTT(NetworkQualityEstimator::Observation(
1668 5000, tick_clock.NowTicks(), INT32_MIN,
1669 NETWORK_QUALITY_OBSERVATION_SOURCE_HTTP));
1670 ++expected_effective_connection_type_notifications;
1671 EXPECT_EQ(expected_effective_connection_type_notifications,
1672 observer.effective_connection_types().size());
1673 }
1674
1675 // Tests that the effective connection type is computed regularly depending
1676 // on the number of RTT and bandwidth samples.
TEST_F(NetworkQualityEstimatorTest,AdaptiveRecomputationEffectiveConnectionType)1677 TEST_F(NetworkQualityEstimatorTest,
1678 AdaptiveRecomputationEffectiveConnectionType) {
1679 base::HistogramTester histogram_tester;
1680 base::SimpleTestTickClock tick_clock;
1681
1682 TestEffectiveConnectionTypeObserver observer;
1683 std::map<std::string, std::string> variation_params;
1684 variation_params["add_default_platform_observations"] = "false";
1685 TestNetworkQualityEstimator estimator(variation_params);
1686 estimator.SetTickClockForTesting(&tick_clock);
1687 estimator.SimulateNetworkChange(NetworkChangeNotifier::CONNECTION_WIFI,
1688 "test");
1689 estimator.AddEffectiveConnectionTypeObserver(&observer);
1690 // |observer| may be notified as soon as it is added. Run the loop to so that
1691 // the notification to |observer| is finished.
1692 base::RunLoop().RunUntilIdle();
1693
1694 TestDelegate test_delegate;
1695 auto context_builder = CreateTestURLRequestContextBuilder();
1696 context_builder->set_network_quality_estimator(&estimator);
1697 context_builder->SuppressSettingSocketPerformanceWatcherFactoryForTesting();
1698 auto context = context_builder->Build();
1699
1700 EXPECT_EQ(0U, observer.effective_connection_types().size());
1701
1702 estimator.set_recent_effective_connection_type(EFFECTIVE_CONNECTION_TYPE_2G);
1703 tick_clock.Advance(base::Minutes(60));
1704
1705 std::unique_ptr<URLRequest> request(
1706 context->CreateRequest(estimator.GetEchoURL(), DEFAULT_PRIORITY,
1707 &test_delegate, TRAFFIC_ANNOTATION_FOR_TESTS));
1708 request->SetLoadFlags(request->load_flags() | LOAD_MAIN_FRAME_DEPRECATED);
1709 request->Start();
1710 test_delegate.RunUntilComplete();
1711 EXPECT_EQ(1U, observer.effective_connection_types().size());
1712
1713 size_t expected_effective_connection_type_notifications = 1;
1714 EXPECT_EQ(expected_effective_connection_type_notifications,
1715 observer.effective_connection_types().size());
1716
1717 EXPECT_EQ(
1718 expected_effective_connection_type_notifications,
1719 (estimator.rtt_ms_observations_[nqe::internal::OBSERVATION_CATEGORY_HTTP]
1720 .Size() +
1721 estimator
1722 .rtt_ms_observations_[nqe::internal::OBSERVATION_CATEGORY_TRANSPORT]
1723 .Size()));
1724
1725 // Increase the number of RTT observations. Every time the number of RTT
1726 // observations is more than doubled, effective connection type must be
1727 // recomputed and notified to observers.
1728 for (size_t repetition = 0; repetition < 2; ++repetition) {
1729 // Change the effective connection type so that the observers are
1730 // notified when the effective connection type is recomputed.
1731 if (repetition % 2 == 0) {
1732 estimator.set_recent_effective_connection_type(
1733 EFFECTIVE_CONNECTION_TYPE_SLOW_2G);
1734 } else {
1735 estimator.set_recent_effective_connection_type(
1736 EFFECTIVE_CONNECTION_TYPE_3G);
1737 }
1738 size_t rtt_observations_count =
1739 (estimator
1740 .rtt_ms_observations_[nqe::internal::OBSERVATION_CATEGORY_HTTP]
1741 .Size() +
1742 estimator
1743 .rtt_ms_observations_
1744 [nqe::internal::OBSERVATION_CATEGORY_TRANSPORT]
1745 .Size()) *
1746 0.5;
1747 // Increase the number of RTT observations to more than twice the number
1748 // of current observations. This should trigger recomputation of
1749 // effective connection type.
1750 for (size_t i = 0; i < rtt_observations_count + 1; ++i) {
1751 estimator.AddAndNotifyObserversOfRTT(NetworkQualityEstimator::Observation(
1752 5000, tick_clock.NowTicks(), INT32_MIN,
1753 NETWORK_QUALITY_OBSERVATION_SOURCE_HTTP));
1754
1755 if (i == rtt_observations_count) {
1756 // Effective connection type must be recomputed since the number of RTT
1757 // samples are now more than twice the number of RTT samples that were
1758 // available when effective connection type was last computed.
1759 ++expected_effective_connection_type_notifications;
1760 }
1761 EXPECT_EQ(expected_effective_connection_type_notifications,
1762 observer.effective_connection_types().size());
1763 }
1764 }
1765 }
1766
TEST_F(NetworkQualityEstimatorTest,TestRttThroughputObservers)1767 TEST_F(NetworkQualityEstimatorTest, TestRttThroughputObservers) {
1768 base::HistogramTester histogram_tester;
1769 TestRTTObserver rtt_observer;
1770 TestThroughputObserver throughput_observer;
1771
1772 std::map<std::string, std::string> variation_params;
1773 variation_params["throughput_min_requests_in_flight"] = "1";
1774 variation_params["add_default_platform_observations"] = "false";
1775 TestNetworkQualityEstimator estimator(variation_params);
1776
1777 estimator.AddRTTObserver(&rtt_observer);
1778 estimator.AddThroughputObserver(&throughput_observer);
1779
1780 TestDelegate test_delegate;
1781 auto context_builder = CreateTestURLRequestContextBuilder();
1782 context_builder->set_network_quality_estimator(&estimator);
1783 context_builder->SuppressSettingSocketPerformanceWatcherFactoryForTesting();
1784 auto context = context_builder->Build();
1785
1786 EXPECT_EQ(0U, rtt_observer.observations().size());
1787 EXPECT_EQ(0U, throughput_observer.observations().size());
1788 base::TimeTicks then = base::TimeTicks::Now();
1789
1790 std::unique_ptr<URLRequest> request(
1791 context->CreateRequest(estimator.GetEchoURL(), DEFAULT_PRIORITY,
1792 &test_delegate, TRAFFIC_ANNOTATION_FOR_TESTS));
1793 request->SetLoadFlags(request->load_flags() | LOAD_MAIN_FRAME_DEPRECATED);
1794 request->Start();
1795 test_delegate.RunUntilComplete();
1796
1797 std::unique_ptr<URLRequest> request2(
1798 context->CreateRequest(estimator.GetEchoURL(), DEFAULT_PRIORITY,
1799 &test_delegate, TRAFFIC_ANNOTATION_FOR_TESTS));
1800 request2->SetLoadFlags(request->load_flags() | LOAD_MAIN_FRAME_DEPRECATED);
1801 request2->Start();
1802 test_delegate.RunUntilComplete();
1803
1804 // Pump message loop to allow estimator tasks to be processed.
1805 base::RunLoop().RunUntilIdle();
1806
1807 // Both RTT and downstream throughput should be updated.
1808 base::TimeDelta rtt;
1809 EXPECT_TRUE(estimator.GetRecentRTT(nqe::internal::OBSERVATION_CATEGORY_HTTP,
1810 base::TimeTicks(), &rtt, nullptr));
1811
1812 int32_t throughput;
1813 EXPECT_TRUE(estimator.GetRecentDownlinkThroughputKbps(base::TimeTicks(),
1814 &throughput));
1815
1816 EXPECT_EQ(2U, rtt_observer.observations().size());
1817 EXPECT_EQ(2U, throughput_observer.observations().size());
1818 for (const auto& observation : rtt_observer.observations()) {
1819 EXPECT_LE(0, observation.rtt_ms);
1820 EXPECT_LE(0, (observation.timestamp - then).InMilliseconds());
1821 EXPECT_EQ(NETWORK_QUALITY_OBSERVATION_SOURCE_HTTP, observation.source);
1822 }
1823 for (const auto& observation : throughput_observer.observations()) {
1824 EXPECT_LE(0, observation.throughput_kbps);
1825 EXPECT_LE(0, (observation.timestamp - then).InMilliseconds());
1826 EXPECT_EQ(NETWORK_QUALITY_OBSERVATION_SOURCE_HTTP, observation.source);
1827 }
1828
1829 EXPECT_FALSE(
1830 estimator.GetRecentRTT(nqe::internal::OBSERVATION_CATEGORY_TRANSPORT,
1831 base::TimeTicks(), &rtt, nullptr));
1832
1833 // Verify that observations from TCP and QUIC are passed on to the observers.
1834 base::TimeDelta tcp_rtt(base::Milliseconds(1));
1835 base::TimeDelta quic_rtt(base::Milliseconds(2));
1836
1837 // Use a public IP address so that the socket watcher runs the RTT callback.
1838 IPAddress ip_address;
1839 ASSERT_TRUE(ip_address.AssignFromIPLiteral("157.0.0.1"));
1840
1841 std::unique_ptr<SocketPerformanceWatcher> tcp_watcher =
1842 estimator.GetSocketPerformanceWatcherFactory()
1843 ->CreateSocketPerformanceWatcher(
1844 SocketPerformanceWatcherFactory::PROTOCOL_TCP, ip_address);
1845
1846 std::unique_ptr<SocketPerformanceWatcher> quic_watcher =
1847 estimator.GetSocketPerformanceWatcherFactory()
1848 ->CreateSocketPerformanceWatcher(
1849 SocketPerformanceWatcherFactory::PROTOCOL_QUIC, ip_address);
1850
1851 tcp_watcher->OnUpdatedRTTAvailable(tcp_rtt);
1852 // First RTT sample from QUIC connections is dropped, but the second RTT
1853 // notification should not be dropped.
1854 quic_watcher->OnUpdatedRTTAvailable(quic_rtt);
1855 quic_watcher->OnUpdatedRTTAvailable(quic_rtt);
1856
1857 base::RunLoop().RunUntilIdle();
1858
1859 EXPECT_EQ(4U, rtt_observer.observations().size());
1860 EXPECT_EQ(2U, throughput_observer.observations().size());
1861
1862 EXPECT_EQ(tcp_rtt.InMilliseconds(), rtt_observer.observations().at(2).rtt_ms);
1863 EXPECT_EQ(quic_rtt.InMilliseconds(),
1864 rtt_observer.observations().at(3).rtt_ms);
1865
1866 EXPECT_TRUE(
1867 estimator.GetRecentRTT(nqe::internal::OBSERVATION_CATEGORY_TRANSPORT,
1868 base::TimeTicks(), &rtt, nullptr));
1869
1870 EXPECT_EQ(quic_rtt, estimator.end_to_end_rtt_.value());
1871 EXPECT_LT(
1872 0u, estimator.end_to_end_rtt_observation_count_at_last_ect_computation_);
1873 }
1874
TEST_F(NetworkQualityEstimatorTest,TestGlobalSocketWatcherThrottle)1875 TEST_F(NetworkQualityEstimatorTest, TestGlobalSocketWatcherThrottle) {
1876 base::SimpleTestTickClock tick_clock;
1877 tick_clock.Advance(base::Seconds(1));
1878
1879 std::map<std::string, std::string> variation_params;
1880 variation_params["add_default_platform_observations"] = "false";
1881 TestNetworkQualityEstimator estimator(variation_params);
1882 estimator.SetTickClockForTesting(&tick_clock);
1883
1884 TestRTTObserver rtt_observer;
1885 estimator.AddRTTObserver(&rtt_observer);
1886
1887 const base::TimeDelta tcp_rtt(base::Milliseconds(1));
1888
1889 TestDelegate test_delegate;
1890 auto context_builder = CreateTestURLRequestContextBuilder();
1891 context_builder->set_network_quality_estimator(&estimator);
1892 context_builder->SuppressSettingSocketPerformanceWatcherFactoryForTesting();
1893 auto context = context_builder->Build();
1894
1895 // Use a public IP address so that the socket watcher runs the RTT callback.
1896 IPAddress ip_address;
1897 ASSERT_TRUE(ip_address.AssignFromIPLiteral("157.0.0.1"));
1898 std::unique_ptr<SocketPerformanceWatcher> tcp_watcher =
1899 estimator.GetSocketPerformanceWatcherFactory()
1900 ->CreateSocketPerformanceWatcher(
1901 SocketPerformanceWatcherFactory::PROTOCOL_TCP, ip_address);
1902
1903 EXPECT_EQ(0U, rtt_observer.observations().size());
1904 EXPECT_TRUE(tcp_watcher->ShouldNotifyUpdatedRTT());
1905 std::unique_ptr<URLRequest> request(
1906 context->CreateRequest(estimator.GetEchoURL(), DEFAULT_PRIORITY,
1907 &test_delegate, TRAFFIC_ANNOTATION_FOR_TESTS));
1908 request->SetLoadFlags(request->load_flags() | LOAD_MAIN_FRAME_DEPRECATED);
1909 request->Start();
1910 test_delegate.RunUntilComplete();
1911 EXPECT_EQ(1U, rtt_observer.observations().size());
1912 EXPECT_TRUE(tcp_watcher->ShouldNotifyUpdatedRTT());
1913
1914 tcp_watcher->OnUpdatedRTTAvailable(tcp_rtt);
1915 base::RunLoop().RunUntilIdle();
1916 EXPECT_FALSE(tcp_watcher->ShouldNotifyUpdatedRTT());
1917 EXPECT_EQ(2U, rtt_observer.observations().size());
1918 // Advancing the clock should make it possible to notify new RTT
1919 // notifications.
1920 tick_clock.Advance(
1921 estimator.params()->socket_watchers_min_notification_interval());
1922 EXPECT_TRUE(tcp_watcher->ShouldNotifyUpdatedRTT());
1923
1924 EXPECT_EQ(tcp_rtt.InMilliseconds(), rtt_observer.observations().at(1).rtt_ms);
1925 base::TimeDelta rtt;
1926 EXPECT_TRUE(
1927 estimator.GetRecentRTT(nqe::internal::OBSERVATION_CATEGORY_TRANSPORT,
1928 base::TimeTicks(), &rtt, nullptr));
1929 }
1930
1931 // TestTCPSocketRTT requires kernel support for tcp_info struct, and so it is
1932 // enabled only on certain platforms.
1933 // ChromeOS is disabled due to crbug.com/986904
1934 // TODO(crbug.com/1052397): Revisit once build flag switch of lacros-chrome is
1935 // complete.
1936 #if (defined(TCP_INFO) || \
1937 (BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS_LACROS)) || \
1938 BUILDFLAG(IS_ANDROID)) && \
1939 !BUILDFLAG(IS_CHROMEOS)
1940 #define MAYBE_TestTCPSocketRTT TestTCPSocketRTT
1941 #else
1942 #define MAYBE_TestTCPSocketRTT DISABLED_TestTCPSocketRTT
1943 #endif
1944 // Tests that the TCP socket notifies the Network Quality Estimator of TCP RTTs,
1945 // which in turn notifies registered RTT observers.
TEST_F(NetworkQualityEstimatorTest,MAYBE_TestTCPSocketRTT)1946 TEST_F(NetworkQualityEstimatorTest, MAYBE_TestTCPSocketRTT) {
1947 base::SimpleTestTickClock tick_clock;
1948 tick_clock.Advance(base::Seconds(1));
1949
1950 base::HistogramTester histogram_tester;
1951 TestRTTObserver rtt_observer;
1952
1953 std::map<std::string, std::string> variation_params;
1954 variation_params["persistent_cache_reading_enabled"] = "true";
1955 variation_params["throughput_min_requests_in_flight"] = "1";
1956 TestNetworkQualityEstimator estimator(variation_params, true, true);
1957 estimator.SetTickClockForTesting(&tick_clock);
1958 estimator.SimulateNetworkChange(
1959 NetworkChangeNotifier::ConnectionType::CONNECTION_2G, "test");
1960
1961 estimator.AddRTTObserver(&rtt_observer);
1962 // |observer| may be notified as soon as it is added. Run the loop to so that
1963 // the notification to |observer| is finished.
1964 base::RunLoop().RunUntilIdle();
1965
1966 TestDelegate test_delegate;
1967 auto context_builder = CreateTestURLRequestContextBuilder();
1968 context_builder->set_network_quality_estimator(&estimator);
1969 auto context = context_builder->Build();
1970
1971 EXPECT_EQ(0U, rtt_observer.observations().size());
1972 base::TimeDelta rtt;
1973 EXPECT_TRUE(estimator.GetRecentRTT(nqe::internal::OBSERVATION_CATEGORY_HTTP,
1974 base::TimeTicks(), &rtt, nullptr));
1975 EXPECT_EQ(rtt, estimator.GetHttpRTT().value());
1976 EXPECT_TRUE(
1977 estimator.GetRecentRTT(nqe::internal::OBSERVATION_CATEGORY_TRANSPORT,
1978 base::TimeTicks(), &rtt, nullptr));
1979 EXPECT_EQ(rtt, estimator.GetTransportRTT().value());
1980
1981 // Send two requests. Verify that the completion of each request generates at
1982 // least one TCP RTT observation.
1983 const size_t num_requests = 2;
1984 for (size_t i = 0; i < num_requests; ++i) {
1985 size_t before_count_tcp_rtt_observations = 0;
1986 for (const auto& observation : rtt_observer.observations()) {
1987 if (observation.source == NETWORK_QUALITY_OBSERVATION_SOURCE_TCP)
1988 ++before_count_tcp_rtt_observations;
1989 }
1990
1991 std::unique_ptr<URLRequest> request(
1992 context->CreateRequest(estimator.GetEchoURL(), DEFAULT_PRIORITY,
1993 &test_delegate, TRAFFIC_ANNOTATION_FOR_TESTS));
1994 request->SetLoadFlags(request->load_flags() | LOAD_MAIN_FRAME_DEPRECATED);
1995 request->Start();
1996 tick_clock.Advance(
1997 estimator.params()->socket_watchers_min_notification_interval());
1998
1999 test_delegate.RunUntilComplete();
2000
2001 size_t after_count_tcp_rtt_observations = 0;
2002 for (const auto& observation : rtt_observer.observations()) {
2003 if (observation.source == NETWORK_QUALITY_OBSERVATION_SOURCE_TCP)
2004 ++after_count_tcp_rtt_observations;
2005 }
2006 // At least one notification should be received per socket performance
2007 // watcher.
2008 EXPECT_LE(1U, after_count_tcp_rtt_observations -
2009 before_count_tcp_rtt_observations)
2010 << i;
2011 }
2012 EXPECT_TRUE(estimator.GetRecentRTT(nqe::internal::OBSERVATION_CATEGORY_HTTP,
2013 base::TimeTicks(), &rtt, nullptr));
2014 EXPECT_NE(nqe::internal::InvalidRTT(), estimator.GetHttpRTT().value());
2015 EXPECT_TRUE(
2016 estimator.GetRecentRTT(nqe::internal::OBSERVATION_CATEGORY_TRANSPORT,
2017 base::TimeTicks(), &rtt, nullptr));
2018 EXPECT_EQ(rtt, estimator.GetTransportRTT().value());
2019
2020 estimator.SimulateNetworkChange(
2021 NetworkChangeNotifier::ConnectionType::CONNECTION_WIFI, "test-1");
2022
2023 ExpectBucketCountAtLeast(&histogram_tester, "NQE.RTT.ObservationSource",
2024 NETWORK_QUALITY_OBSERVATION_SOURCE_TCP, 1);
2025 EXPECT_LE(1u,
2026 histogram_tester.GetAllSamples("NQE.RTT.OnECTComputation").size());
2027
2028 estimator.SimulateNetworkChange(
2029 NetworkChangeNotifier::ConnectionType::CONNECTION_2G, "test");
2030 histogram_tester.ExpectBucketCount(
2031 "NQE.RTT.ObservationSource",
2032 NETWORK_QUALITY_OBSERVATION_SOURCE_TRANSPORT_CACHED_ESTIMATE, 1);
2033
2034 estimator.SimulateNetworkChange(
2035 NetworkChangeNotifier::ConnectionType::CONNECTION_WIFI, "test-1");
2036 histogram_tester.ExpectBucketCount(
2037 "NQE.RTT.ObservationSource",
2038 NETWORK_QUALITY_OBSERVATION_SOURCE_TRANSPORT_CACHED_ESTIMATE, 2);
2039 }
2040
2041 class TestNetworkQualitiesCacheObserver
2042 : public nqe::internal::NetworkQualityStore::NetworkQualitiesCacheObserver {
2043 public:
TestNetworkQualitiesCacheObserver()2044 TestNetworkQualitiesCacheObserver()
2045 : network_id_(net::NetworkChangeNotifier::CONNECTION_UNKNOWN,
2046 std::string(),
2047 INT32_MIN) {}
2048
2049 TestNetworkQualitiesCacheObserver(const TestNetworkQualitiesCacheObserver&) =
2050 delete;
2051 TestNetworkQualitiesCacheObserver& operator=(
2052 const TestNetworkQualitiesCacheObserver&) = delete;
2053
2054 ~TestNetworkQualitiesCacheObserver() override = default;
2055
OnChangeInCachedNetworkQuality(const nqe::internal::NetworkID & network_id,const nqe::internal::CachedNetworkQuality & cached_network_quality)2056 void OnChangeInCachedNetworkQuality(
2057 const nqe::internal::NetworkID& network_id,
2058 const nqe::internal::CachedNetworkQuality& cached_network_quality)
2059 override {
2060 network_id_ = network_id;
2061 notification_received_++;
2062 }
2063
get_notification_received_and_reset()2064 size_t get_notification_received_and_reset() {
2065 size_t notification_received = notification_received_;
2066 notification_received_ = 0;
2067 return notification_received;
2068 }
2069
network_id() const2070 nqe::internal::NetworkID network_id() const { return network_id_; }
2071
2072 private:
2073 nqe::internal::NetworkID network_id_;
2074 size_t notification_received_ = 0;
2075 };
2076
TEST_F(NetworkQualityEstimatorTest,CacheObserver)2077 TEST_F(NetworkQualityEstimatorTest, CacheObserver) {
2078 TestNetworkQualitiesCacheObserver observer;
2079 TestNetworkQualityEstimator estimator;
2080
2081 // Add |observer| as a persistent caching observer.
2082 estimator.AddNetworkQualitiesCacheObserver(&observer);
2083
2084 estimator.set_recent_effective_connection_type(EFFECTIVE_CONNECTION_TYPE_3G);
2085 estimator.SimulateNetworkChange(
2086 NetworkChangeNotifier::ConnectionType::CONNECTION_UNKNOWN, "test3g");
2087 estimator.RunOneRequest();
2088 EXPECT_EQ(4u, observer.get_notification_received_and_reset());
2089 EXPECT_EQ("test3g", observer.network_id().id);
2090
2091 estimator.set_recent_effective_connection_type(EFFECTIVE_CONNECTION_TYPE_2G);
2092 estimator.SimulateNetworkChange(
2093 NetworkChangeNotifier::ConnectionType::CONNECTION_2G, "test2g");
2094 // One notification should be received for the previous network
2095 // ("test3g") right before the connection change event. The second
2096 // notification should be received for the second network ("test2g").
2097 base::RunLoop().RunUntilIdle();
2098 EXPECT_EQ(2u, observer.get_notification_received_and_reset());
2099 estimator.RunOneRequest();
2100 EXPECT_EQ("test2g", observer.network_id().id);
2101
2102 estimator.set_recent_effective_connection_type(EFFECTIVE_CONNECTION_TYPE_4G);
2103 // Start multiple requests, but there should be only one notification
2104 // received, since the effective connection type does not change.
2105 estimator.RunOneRequest();
2106 estimator.RunOneRequest();
2107 estimator.RunOneRequest();
2108 EXPECT_EQ(1u, observer.get_notification_received_and_reset());
2109
2110 estimator.set_recent_effective_connection_type(EFFECTIVE_CONNECTION_TYPE_2G);
2111 estimator.RunOneRequest();
2112 EXPECT_EQ(1u, observer.get_notification_received_and_reset());
2113
2114 // Remove |observer|, and it should not receive any notifications.
2115 estimator.RemoveNetworkQualitiesCacheObserver(&observer);
2116 estimator.set_recent_effective_connection_type(EFFECTIVE_CONNECTION_TYPE_3G);
2117 estimator.SimulateNetworkChange(
2118 NetworkChangeNotifier::ConnectionType::CONNECTION_2G, "test2g");
2119 EXPECT_EQ(0u, observer.get_notification_received_and_reset());
2120 estimator.RunOneRequest();
2121 EXPECT_EQ(0u, observer.get_notification_received_and_reset());
2122 }
2123
2124 // Tests that the value of the effective connection type can be forced through
2125 // field trial parameters.
TEST_F(NetworkQualityEstimatorTest,ForceEffectiveConnectionTypeThroughFieldTrial)2126 TEST_F(NetworkQualityEstimatorTest,
2127 ForceEffectiveConnectionTypeThroughFieldTrial) {
2128 for (int i = 0; i < EFFECTIVE_CONNECTION_TYPE_LAST; ++i) {
2129 EffectiveConnectionType ect_type = static_cast<EffectiveConnectionType>(i);
2130 std::map<std::string, std::string> variation_params;
2131 variation_params[kForceEffectiveConnectionType] =
2132 GetNameForEffectiveConnectionType(
2133 static_cast<EffectiveConnectionType>(i));
2134 TestNetworkQualityEstimator estimator(variation_params);
2135
2136 TestEffectiveConnectionTypeObserver ect_observer;
2137 estimator.AddEffectiveConnectionTypeObserver(&ect_observer);
2138 TestRTTAndThroughputEstimatesObserver rtt_throughput_observer;
2139 estimator.AddRTTAndThroughputEstimatesObserver(&rtt_throughput_observer);
2140 // |observer| may be notified as soon as it is added. Run the loop to so
2141 // that the notification to |observer| is finished.
2142 base::RunLoop().RunUntilIdle();
2143
2144 TestDelegate test_delegate;
2145 auto context_builder = CreateTestURLRequestContextBuilder();
2146 context_builder->set_network_quality_estimator(&estimator);
2147 auto context = context_builder->Build();
2148
2149 if (ect_type == EFFECTIVE_CONNECTION_TYPE_UNKNOWN) {
2150 EXPECT_EQ(0U, ect_observer.effective_connection_types().size());
2151 } else {
2152 EXPECT_EQ(1U, ect_observer.effective_connection_types().size());
2153 }
2154
2155 std::unique_ptr<URLRequest> request(
2156 context->CreateRequest(estimator.GetEchoURL(), DEFAULT_PRIORITY,
2157 &test_delegate, TRAFFIC_ANNOTATION_FOR_TESTS));
2158 request->SetLoadFlags(request->load_flags() | LOAD_MAIN_FRAME_DEPRECATED);
2159 request->Start();
2160 test_delegate.RunUntilComplete();
2161
2162 // Pump message loop to allow estimator tasks to be processed.
2163 base::RunLoop().RunUntilIdle();
2164
2165 EXPECT_EQ(i, estimator.GetEffectiveConnectionType());
2166
2167 size_t expected_count =
2168 ect_type == EFFECTIVE_CONNECTION_TYPE_UNKNOWN ? 0 : 1;
2169 ASSERT_EQ(expected_count, ect_observer.effective_connection_types().size());
2170 if (expected_count == 1) {
2171 EffectiveConnectionType last_notified_type =
2172 ect_observer.effective_connection_types().at(
2173 ect_observer.effective_connection_types().size() - 1);
2174 EXPECT_EQ(i, last_notified_type);
2175
2176 if (ect_type == EFFECTIVE_CONNECTION_TYPE_UNKNOWN ||
2177 ect_type == EFFECTIVE_CONNECTION_TYPE_OFFLINE) {
2178 EXPECT_EQ(nqe::internal::InvalidRTT(),
2179 rtt_throughput_observer.http_rtt());
2180 EXPECT_EQ(nqe::internal::InvalidRTT(),
2181 rtt_throughput_observer.transport_rtt());
2182 EXPECT_EQ(nqe::internal::INVALID_RTT_THROUGHPUT,
2183 rtt_throughput_observer.downstream_throughput_kbps());
2184 } else {
2185 EXPECT_EQ(estimator.params_->TypicalNetworkQuality(ect_type).http_rtt(),
2186 rtt_throughput_observer.http_rtt());
2187 EXPECT_EQ(
2188 estimator.params_->TypicalNetworkQuality(ect_type).transport_rtt(),
2189 rtt_throughput_observer.transport_rtt());
2190 EXPECT_EQ(estimator.params_->TypicalNetworkQuality(ect_type)
2191 .downstream_throughput_kbps(),
2192 rtt_throughput_observer.downstream_throughput_kbps());
2193 }
2194 }
2195 }
2196 }
2197
2198 // Tests that the value of the effective connection type can be forced after
2199 // network quality estimator has been initialized.
TEST_F(NetworkQualityEstimatorTest,SimulateNetworkQualityChangeForTesting)2200 TEST_F(NetworkQualityEstimatorTest, SimulateNetworkQualityChangeForTesting) {
2201 for (int i = 0; i < EFFECTIVE_CONNECTION_TYPE_LAST; ++i) {
2202 EffectiveConnectionType ect_type = static_cast<EffectiveConnectionType>(i);
2203 TestNetworkQualityEstimator estimator;
2204
2205 TestEffectiveConnectionTypeObserver ect_observer;
2206 estimator.AddEffectiveConnectionTypeObserver(&ect_observer);
2207
2208 // |observer| may be notified as soon as it is added. Run the loop to so
2209 // that the notification to |observer| is finished.
2210 base::RunLoop().RunUntilIdle();
2211
2212 TestDelegate test_delegate;
2213 auto context_builder = CreateTestURLRequestContextBuilder();
2214 context_builder->set_network_quality_estimator(&estimator);
2215 auto context = context_builder->Build();
2216 estimator.SimulateNetworkQualityChangeForTesting(ect_type);
2217 base::RunLoop().RunUntilIdle();
2218
2219 EXPECT_EQ(ect_type, ect_observer.effective_connection_types().back());
2220 }
2221 }
2222
2223 // Test that the typical network qualities are set correctly.
TEST_F(NetworkQualityEstimatorTest,TypicalNetworkQualities)2224 TEST_F(NetworkQualityEstimatorTest, TypicalNetworkQualities) {
2225 TestNetworkQualityEstimator estimator;
2226 TestDelegate test_delegate;
2227 auto context_builder = CreateTestURLRequestContextBuilder();
2228 context_builder->set_network_quality_estimator(&estimator);
2229 auto context = context_builder->Build();
2230
2231 for (size_t effective_connection_type = EFFECTIVE_CONNECTION_TYPE_SLOW_2G;
2232 effective_connection_type <= EFFECTIVE_CONNECTION_TYPE_4G;
2233 ++effective_connection_type) {
2234 // Set the RTT and throughput values to the typical values for
2235 // |effective_connection_type|. The effective connection type should be
2236 // computed as |effective_connection_type|.
2237 estimator.SetStartTimeNullHttpRtt(
2238 estimator.params_
2239 ->TypicalNetworkQuality(
2240 static_cast<EffectiveConnectionType>(effective_connection_type))
2241 .http_rtt());
2242 estimator.set_start_time_null_downlink_throughput_kbps(INT32_MAX);
2243 estimator.SetStartTimeNullTransportRtt(
2244 estimator.params_
2245 ->TypicalNetworkQuality(
2246 static_cast<EffectiveConnectionType>(effective_connection_type))
2247 .transport_rtt());
2248
2249 EXPECT_EQ(effective_connection_type,
2250 static_cast<size_t>(estimator.GetEffectiveConnectionType()));
2251 }
2252 }
2253
2254 // Verify that the cached network qualities from the prefs are correctly used.
TEST_F(NetworkQualityEstimatorTest,OnPrefsRead)2255 TEST_F(NetworkQualityEstimatorTest, OnPrefsRead) {
2256 base::HistogramTester histogram_tester;
2257
2258 // Construct the read prefs.
2259 std::map<nqe::internal::NetworkID, nqe::internal::CachedNetworkQuality>
2260 read_prefs;
2261 read_prefs[nqe::internal::NetworkID(NetworkChangeNotifier::CONNECTION_WIFI,
2262 "test_ect_2g", INT32_MIN)] =
2263 nqe::internal::CachedNetworkQuality(EFFECTIVE_CONNECTION_TYPE_2G);
2264 read_prefs[nqe::internal::NetworkID(NetworkChangeNotifier::CONNECTION_WIFI,
2265 "test_ect_slow_2g", INT32_MIN)] =
2266 nqe::internal::CachedNetworkQuality(EFFECTIVE_CONNECTION_TYPE_SLOW_2G);
2267 read_prefs[nqe::internal::NetworkID(NetworkChangeNotifier::CONNECTION_4G,
2268 "test_ect_4g", INT32_MIN)] =
2269 nqe::internal::CachedNetworkQuality(EFFECTIVE_CONNECTION_TYPE_4G);
2270
2271 std::map<std::string, std::string> variation_params;
2272 variation_params["persistent_cache_reading_enabled"] = "true";
2273 variation_params["add_default_platform_observations"] = "false";
2274 // Disable default platform values so that the effect of cached estimates
2275 // at the time of startup can be studied in isolation.
2276 TestNetworkQualityEstimator estimator(variation_params, true, true);
2277
2278 // Add observers.
2279 TestRTTObserver rtt_observer;
2280 TestThroughputObserver throughput_observer;
2281 TestRTTAndThroughputEstimatesObserver rtt_throughput_observer;
2282 TestEffectiveConnectionTypeObserver effective_connection_type_observer;
2283 estimator.AddRTTObserver(&rtt_observer);
2284 estimator.AddThroughputObserver(&throughput_observer);
2285 estimator.AddRTTAndThroughputEstimatesObserver(&rtt_throughput_observer);
2286 estimator.AddEffectiveConnectionTypeObserver(
2287 &effective_connection_type_observer);
2288
2289 std::string network_name("test_ect_2g");
2290
2291 estimator.SimulateNetworkChange(
2292 NetworkChangeNotifier::ConnectionType::CONNECTION_WIFI, network_name);
2293 EXPECT_EQ(0u, rtt_observer.observations().size());
2294 EXPECT_EQ(0u, throughput_observer.observations().size());
2295 EXPECT_LE(0, rtt_throughput_observer.notifications_received());
2296
2297 // Simulate reading of prefs.
2298 estimator.OnPrefsRead(read_prefs);
2299 histogram_tester.ExpectUniqueSample("NQE.Prefs.ReadSize", read_prefs.size(),
2300 1);
2301
2302 // Taken from network_quality_estimator_params.cc.
2303 EXPECT_EQ(base::Milliseconds(1800),
2304 rtt_observer.last_rtt(
2305 NETWORK_QUALITY_OBSERVATION_SOURCE_HTTP_CACHED_ESTIMATE));
2306 EXPECT_EQ(base::Milliseconds(1500),
2307 rtt_observer.last_rtt(
2308 NETWORK_QUALITY_OBSERVATION_SOURCE_TRANSPORT_CACHED_ESTIMATE));
2309 EXPECT_EQ(1u, throughput_observer.observations().size());
2310 EXPECT_EQ(base::Milliseconds(1800), rtt_throughput_observer.http_rtt());
2311 EXPECT_EQ(base::Milliseconds(1500), rtt_throughput_observer.transport_rtt());
2312 EXPECT_EQ(75, rtt_throughput_observer.downstream_throughput_kbps());
2313 EXPECT_LE(
2314 1u,
2315 effective_connection_type_observer.effective_connection_types().size());
2316 // Compare the ECT stored in prefs with the observer's last entry.
2317 EXPECT_EQ(
2318 read_prefs[nqe::internal::NetworkID(
2319 NetworkChangeNotifier::CONNECTION_WIFI, network_name,
2320 INT32_MIN)]
2321 .effective_connection_type(),
2322 effective_connection_type_observer.effective_connection_types().back());
2323
2324 // Change to a different connection type.
2325 network_name = "test_ect_slow_2g";
2326 estimator.SimulateNetworkChange(
2327 NetworkChangeNotifier::ConnectionType::CONNECTION_WIFI, network_name);
2328
2329 EXPECT_EQ(base::Milliseconds(3600),
2330 rtt_observer.last_rtt(
2331 NETWORK_QUALITY_OBSERVATION_SOURCE_HTTP_CACHED_ESTIMATE));
2332 EXPECT_EQ(base::Milliseconds(3000),
2333 rtt_observer.last_rtt(
2334 NETWORK_QUALITY_OBSERVATION_SOURCE_TRANSPORT_CACHED_ESTIMATE));
2335 EXPECT_EQ(2U, throughput_observer.observations().size());
2336 EXPECT_EQ(base::Milliseconds(3600), rtt_throughput_observer.http_rtt());
2337 EXPECT_EQ(base::Milliseconds(3000), rtt_throughput_observer.transport_rtt());
2338 EXPECT_EQ(40, rtt_throughput_observer.downstream_throughput_kbps());
2339 EXPECT_LE(
2340 2u,
2341 effective_connection_type_observer.effective_connection_types().size());
2342 // Compare with the last entry.
2343 EXPECT_EQ(
2344 read_prefs[nqe::internal::NetworkID(
2345 NetworkChangeNotifier::CONNECTION_WIFI, network_name,
2346 INT32_MIN)]
2347 .effective_connection_type(),
2348 effective_connection_type_observer.effective_connection_types().back());
2349
2350 // Cleanup.
2351 estimator.RemoveRTTObserver(&rtt_observer);
2352 estimator.RemoveThroughputObserver(&throughput_observer);
2353 estimator.RemoveRTTAndThroughputEstimatesObserver(&rtt_throughput_observer);
2354 estimator.RemoveEffectiveConnectionTypeObserver(
2355 &effective_connection_type_observer);
2356 }
2357
2358 // Verify that the cached network qualities from the prefs are not used if the
2359 // reading of the network quality prefs is not enabled..
TEST_F(NetworkQualityEstimatorTest,OnPrefsReadWithReadingDisabled)2360 TEST_F(NetworkQualityEstimatorTest, OnPrefsReadWithReadingDisabled) {
2361 base::HistogramTester histogram_tester;
2362
2363 // Construct the read prefs.
2364 std::map<nqe::internal::NetworkID, nqe::internal::CachedNetworkQuality>
2365 read_prefs;
2366 read_prefs[nqe::internal::NetworkID(NetworkChangeNotifier::CONNECTION_WIFI,
2367 "test_ect_2g", INT32_MIN)] =
2368 nqe::internal::CachedNetworkQuality(EFFECTIVE_CONNECTION_TYPE_2G);
2369 read_prefs[nqe::internal::NetworkID(NetworkChangeNotifier::CONNECTION_WIFI,
2370 "test_ect_slow_2g", INT32_MIN)] =
2371 nqe::internal::CachedNetworkQuality(EFFECTIVE_CONNECTION_TYPE_SLOW_2G);
2372 read_prefs[nqe::internal::NetworkID(NetworkChangeNotifier::CONNECTION_4G,
2373 "test_ect_4g", INT32_MIN)] =
2374 nqe::internal::CachedNetworkQuality(EFFECTIVE_CONNECTION_TYPE_4G);
2375
2376 std::map<std::string, std::string> variation_params;
2377 variation_params["persistent_cache_reading_enabled"] = "false";
2378 variation_params["add_default_platform_observations"] = "false";
2379
2380 // Disable default platform values so that the effect of cached estimates
2381 // at the time of startup can be studied in isolation.
2382 TestNetworkQualityEstimator estimator(variation_params, true, true);
2383
2384 // Add observers.
2385 TestRTTObserver rtt_observer;
2386 TestThroughputObserver throughput_observer;
2387 TestRTTAndThroughputEstimatesObserver rtt_throughput_observer;
2388 TestEffectiveConnectionTypeObserver effective_connection_type_observer;
2389 estimator.AddRTTObserver(&rtt_observer);
2390 estimator.AddThroughputObserver(&throughput_observer);
2391 estimator.AddRTTAndThroughputEstimatesObserver(&rtt_throughput_observer);
2392 estimator.AddEffectiveConnectionTypeObserver(
2393 &effective_connection_type_observer);
2394
2395 std::string network_name("test_ect_2g");
2396
2397 estimator.SimulateNetworkChange(
2398 NetworkChangeNotifier::ConnectionType::CONNECTION_WIFI, network_name);
2399 EXPECT_EQ(0u, rtt_observer.observations().size());
2400 EXPECT_EQ(0u, throughput_observer.observations().size());
2401 EXPECT_LE(0, rtt_throughput_observer.notifications_received());
2402
2403 // Simulate reading of prefs.
2404 estimator.OnPrefsRead(read_prefs);
2405 histogram_tester.ExpectUniqueSample("NQE.Prefs.ReadSize", read_prefs.size(),
2406 1);
2407
2408 // Force read the network quality store from the store to verify that store
2409 // gets populated even if reading of prefs is not enabled.
2410 nqe::internal::CachedNetworkQuality cached_network_quality;
2411 EXPECT_TRUE(estimator.network_quality_store_->GetById(
2412 nqe::internal::NetworkID(NetworkChangeNotifier::CONNECTION_WIFI,
2413 "test_ect_2g", INT32_MIN),
2414 &cached_network_quality));
2415 EXPECT_EQ(EFFECTIVE_CONNECTION_TYPE_2G,
2416 cached_network_quality.effective_connection_type());
2417
2418 // Taken from network_quality_estimator_params.cc.
2419 EXPECT_EQ(nqe::internal::InvalidRTT(),
2420 rtt_observer.last_rtt(
2421 NETWORK_QUALITY_OBSERVATION_SOURCE_HTTP_CACHED_ESTIMATE));
2422 EXPECT_EQ(nqe::internal::InvalidRTT(),
2423 rtt_observer.last_rtt(
2424 NETWORK_QUALITY_OBSERVATION_SOURCE_TRANSPORT_CACHED_ESTIMATE));
2425 EXPECT_EQ(0u, throughput_observer.observations().size());
2426
2427 EXPECT_EQ(
2428 0u,
2429 effective_connection_type_observer.effective_connection_types().size());
2430
2431 // Change to a different connection type.
2432 network_name = "test_ect_slow_2g";
2433 estimator.SimulateNetworkChange(
2434 NetworkChangeNotifier::ConnectionType::CONNECTION_WIFI, network_name);
2435
2436 EXPECT_EQ(nqe::internal::InvalidRTT(),
2437 rtt_observer.last_rtt(
2438 NETWORK_QUALITY_OBSERVATION_SOURCE_HTTP_CACHED_ESTIMATE));
2439 EXPECT_EQ(nqe::internal::InvalidRTT(),
2440 rtt_observer.last_rtt(
2441 NETWORK_QUALITY_OBSERVATION_SOURCE_TRANSPORT_CACHED_ESTIMATE));
2442 EXPECT_EQ(0U, throughput_observer.observations().size());
2443
2444 // Cleanup.
2445 estimator.RemoveRTTObserver(&rtt_observer);
2446 estimator.RemoveThroughputObserver(&throughput_observer);
2447 estimator.RemoveRTTAndThroughputEstimatesObserver(&rtt_throughput_observer);
2448 estimator.RemoveEffectiveConnectionTypeObserver(
2449 &effective_connection_type_observer);
2450 }
2451
2452 // Verifies that when the cached network qualities from the prefs are available,
2453 // then estimates from the platform or the external estimate provider are not
2454 // used.
TEST_F(NetworkQualityEstimatorTest,ObservationDiscardedIfCachedEstimateAvailable)2455 TEST_F(NetworkQualityEstimatorTest,
2456 ObservationDiscardedIfCachedEstimateAvailable) {
2457 base::HistogramTester histogram_tester;
2458
2459 // Construct the read prefs.
2460 std::map<nqe::internal::NetworkID, nqe::internal::CachedNetworkQuality>
2461 read_prefs;
2462 read_prefs[nqe::internal::NetworkID(NetworkChangeNotifier::CONNECTION_WIFI,
2463 "test_2g", INT32_MIN)] =
2464 nqe::internal::CachedNetworkQuality(EFFECTIVE_CONNECTION_TYPE_2G);
2465
2466 std::map<std::string, std::string> variation_params;
2467 variation_params["persistent_cache_reading_enabled"] = "true";
2468 variation_params["add_default_platform_observations"] = "false";
2469 // Disable default platform values so that the effect of cached estimates
2470 // at the time of startup can be studied in isolation.
2471 TestNetworkQualityEstimator estimator(variation_params, true, true);
2472
2473 // Add observers.
2474 TestRTTObserver rtt_observer;
2475 TestThroughputObserver throughput_observer;
2476 estimator.AddRTTObserver(&rtt_observer);
2477 estimator.AddThroughputObserver(&throughput_observer);
2478
2479 std::string network_name("test_2g");
2480
2481 estimator.SimulateNetworkChange(
2482 NetworkChangeNotifier::ConnectionType::CONNECTION_WIFI, network_name);
2483 EXPECT_EQ(0u, rtt_observer.observations().size());
2484 EXPECT_EQ(0u, throughput_observer.observations().size());
2485 EXPECT_EQ(
2486 0u,
2487 estimator
2488 .rtt_ms_observations_[nqe::internal::OBSERVATION_CATEGORY_TRANSPORT]
2489 .Size());
2490 EXPECT_EQ(0u, estimator.http_downstream_throughput_kbps_observations_.Size());
2491
2492 // Simulate reading of prefs.
2493 estimator.OnPrefsRead(read_prefs);
2494 histogram_tester.ExpectUniqueSample("NQE.Prefs.ReadSize", read_prefs.size(),
2495 1);
2496
2497 // Taken from network_quality_estimator_params.cc.
2498 EXPECT_EQ(base::Milliseconds(1800),
2499 rtt_observer.last_rtt(
2500 NETWORK_QUALITY_OBSERVATION_SOURCE_HTTP_CACHED_ESTIMATE));
2501 EXPECT_EQ(base::Milliseconds(1500),
2502 rtt_observer.last_rtt(
2503 NETWORK_QUALITY_OBSERVATION_SOURCE_TRANSPORT_CACHED_ESTIMATE));
2504 EXPECT_EQ(2u, rtt_observer.observations().size());
2505
2506 // RTT observation with source
2507 // DEPRECATED_NETWORK_QUALITY_OBSERVATION_SOURCE_HTTP_EXTERNAL_ESTIMATE should
2508 // be removed from |estimator.rtt_ms_observations_| when a cached estimate is
2509 // received.
2510 EXPECT_EQ(
2511 1u,
2512 estimator.rtt_ms_observations_[nqe::internal::OBSERVATION_CATEGORY_HTTP]
2513 .Size());
2514 EXPECT_EQ(
2515 1u,
2516 estimator
2517 .rtt_ms_observations_[nqe::internal::OBSERVATION_CATEGORY_TRANSPORT]
2518 .Size());
2519
2520 // When a cached estimate is available, RTT observations from the external
2521 // estimate provider and platform must be discarded.
2522 estimator.AddAndNotifyObserversOfRTT(nqe::internal::Observation(
2523 1, base::TimeTicks::Now(), INT32_MIN,
2524 DEPRECATED_NETWORK_QUALITY_OBSERVATION_SOURCE_HTTP_EXTERNAL_ESTIMATE));
2525 estimator.AddAndNotifyObserversOfRTT(nqe::internal::Observation(
2526 1, base::TimeTicks::Now(), INT32_MIN,
2527 NETWORK_QUALITY_OBSERVATION_SOURCE_DEFAULT_HTTP_FROM_PLATFORM));
2528 EXPECT_EQ(3u, rtt_observer.observations().size());
2529 EXPECT_EQ(
2530 2u,
2531 estimator.rtt_ms_observations_[nqe::internal::OBSERVATION_CATEGORY_HTTP]
2532 .Size());
2533 EXPECT_EQ(
2534 1u,
2535 estimator
2536 .rtt_ms_observations_[nqe::internal::OBSERVATION_CATEGORY_TRANSPORT]
2537 .Size());
2538 estimator.AddAndNotifyObserversOfRTT(
2539 nqe::internal::Observation(1, base::TimeTicks::Now(), INT32_MIN,
2540 NETWORK_QUALITY_OBSERVATION_SOURCE_HTTP));
2541 EXPECT_EQ(4u, rtt_observer.observations().size());
2542 EXPECT_EQ(
2543 3u,
2544 estimator.rtt_ms_observations_[nqe::internal::OBSERVATION_CATEGORY_HTTP]
2545 .Size());
2546 EXPECT_EQ(
2547 1u,
2548 estimator
2549 .rtt_ms_observations_[nqe::internal::OBSERVATION_CATEGORY_TRANSPORT]
2550 .Size());
2551
2552 // When a cached estimate is available, throughput observations from the
2553 // external estimate provider and platform must be discarded.
2554 EXPECT_EQ(1u, throughput_observer.observations().size());
2555 // Throughput observation with source
2556 // DEPRECATED_NETWORK_QUALITY_OBSERVATION_SOURCE_HTTP_EXTERNAL_ESTIMATE should
2557 // be removed from |estimator.downstream_throughput_kbps_observations_| when a
2558 // cached estimate is received.
2559 EXPECT_EQ(1u, estimator.http_downstream_throughput_kbps_observations_.Size());
2560 estimator.AddAndNotifyObserversOfThroughput(nqe::internal::Observation(
2561 1, base::TimeTicks::Now(), INT32_MIN,
2562 DEPRECATED_NETWORK_QUALITY_OBSERVATION_SOURCE_HTTP_EXTERNAL_ESTIMATE));
2563 estimator.AddAndNotifyObserversOfThroughput(nqe::internal::Observation(
2564 1, base::TimeTicks::Now(), INT32_MIN,
2565 NETWORK_QUALITY_OBSERVATION_SOURCE_DEFAULT_HTTP_FROM_PLATFORM));
2566 EXPECT_EQ(2u, throughput_observer.observations().size());
2567 EXPECT_EQ(2u, estimator.http_downstream_throughput_kbps_observations_.Size());
2568 estimator.AddAndNotifyObserversOfThroughput(
2569 nqe::internal::Observation(1, base::TimeTicks::Now(), INT32_MIN,
2570 NETWORK_QUALITY_OBSERVATION_SOURCE_HTTP));
2571 EXPECT_EQ(3u, throughput_observer.observations().size());
2572 EXPECT_EQ(3u, estimator.http_downstream_throughput_kbps_observations_.Size());
2573
2574 base::RunLoop().RunUntilIdle();
2575 }
2576
2577 // Tests that the ECT is computed when more than N RTT samples have been
2578 // received.
TEST_F(NetworkQualityEstimatorTest,MaybeComputeECTAfterNSamples)2579 TEST_F(NetworkQualityEstimatorTest, MaybeComputeECTAfterNSamples) {
2580 base::SimpleTestTickClock tick_clock;
2581 tick_clock.Advance(base::Minutes(1));
2582
2583 std::map<std::string, std::string> variation_params;
2584 variation_params["add_default_platform_observations"] = "false";
2585 TestNetworkQualityEstimator estimator(variation_params);
2586 estimator.DisableOfflineCheckForTesting(true);
2587 base::RunLoop().RunUntilIdle();
2588 estimator.SetTickClockForTesting(&tick_clock);
2589 estimator.SimulateNetworkChange(
2590 NetworkChangeNotifier::ConnectionType::CONNECTION_UNKNOWN, "test");
2591 tick_clock.Advance(base::Minutes(1));
2592
2593 const base::TimeDelta rtt = base::Seconds(1);
2594 uint64_t host = 1u;
2595
2596 // Fill the observation buffer so that ECT computations are not triggered due
2597 // to observation buffer's size increasing to 1.5x.
2598 for (size_t i = 0; i < estimator.params()->observation_buffer_size(); ++i) {
2599 estimator.AddAndNotifyObserversOfRTT(NetworkQualityEstimator::Observation(
2600 rtt.InMilliseconds(), tick_clock.NowTicks(), INT32_MIN,
2601 NETWORK_QUALITY_OBSERVATION_SOURCE_HTTP, host));
2602 }
2603 EXPECT_EQ(rtt, estimator.GetHttpRTT().value());
2604 tick_clock.Advance(base::Minutes(60));
2605
2606 const base::TimeDelta rtt_new = base::Seconds(3);
2607 for (size_t i = 0;
2608 i < estimator.params()->count_new_observations_received_compute_ect();
2609 ++i) {
2610 estimator.AddAndNotifyObserversOfRTT(NetworkQualityEstimator::Observation(
2611 rtt_new.InMilliseconds(), tick_clock.NowTicks(), INT32_MIN,
2612 NETWORK_QUALITY_OBSERVATION_SOURCE_HTTP, host));
2613 }
2614 EXPECT_EQ(rtt_new, estimator.GetHttpRTT().value());
2615 }
2616
2617 // Tests that the hanging request is correctly detected.
TEST_F(NetworkQualityEstimatorTest,HangingRequestUsingHttpOnly)2618 TEST_F(NetworkQualityEstimatorTest, HangingRequestUsingHttpOnly) {
2619 std::map<std::string, std::string> variation_params;
2620 variation_params["add_default_platform_observations"] = "false";
2621 variation_params["hanging_request_http_rtt_upper_bound_http_rtt_multiplier"] =
2622 "6";
2623 variation_params["hanging_request_upper_bound_min_http_rtt_msec"] = "500";
2624
2625 TestNetworkQualityEstimator estimator(variation_params);
2626
2627 // 500 msec.
2628 const int32_t hanging_request_threshold =
2629 estimator.params()
2630 ->hanging_request_upper_bound_min_http_rtt()
2631 .InMilliseconds();
2632
2633 estimator.SetStartTimeNullHttpRtt(base::Milliseconds(5));
2634 base::RunLoop().RunUntilIdle();
2635 estimator.SimulateNetworkChange(
2636 NetworkChangeNotifier::ConnectionType::CONNECTION_UNKNOWN, "test");
2637
2638 const struct {
2639 base::TimeDelta observed_http_rtt;
2640 } tests[] = {
2641 {base::Milliseconds(10)},
2642 {base::Milliseconds(100)},
2643 {base::Milliseconds(hanging_request_threshold - 1)},
2644 {base::Milliseconds(hanging_request_threshold + 1)},
2645 {base::Milliseconds(1000)},
2646 };
2647
2648 for (const auto& test : tests) {
2649 EXPECT_EQ(
2650 test.observed_http_rtt.InMilliseconds() >= hanging_request_threshold,
2651 estimator.IsHangingRequest(test.observed_http_rtt));
2652 }
2653 }
2654
2655 // Tests that the hanging request is correctly detected using end-to-end RTT.
TEST_F(NetworkQualityEstimatorTest,HangingRequestEndToEndUsingHttpOnly)2656 TEST_F(NetworkQualityEstimatorTest, HangingRequestEndToEndUsingHttpOnly) {
2657 std::map<std::string, std::string> variation_params;
2658 variation_params["add_default_platform_observations"] = "false";
2659 variation_params["hanging_request_http_rtt_upper_bound_http_rtt_multiplier"] =
2660 "6";
2661 variation_params["hanging_request_upper_bound_min_http_rtt_msec"] = "500";
2662 variation_params["use_end_to_end_rtt"] = "true";
2663
2664 int end_to_end_rtt_milliseconds = 1000;
2665 int hanging_request_http_rtt_upper_bound_transport_rtt_multiplier = 8;
2666
2667 TestNetworkQualityEstimator estimator(variation_params);
2668 estimator.SetStartTimeNullHttpRtt(base::Milliseconds(10));
2669
2670 base::RunLoop().RunUntilIdle();
2671 estimator.set_start_time_null_end_to_end_rtt(
2672 base::Milliseconds(end_to_end_rtt_milliseconds));
2673 estimator.SimulateNetworkChange(
2674 NetworkChangeNotifier::ConnectionType::CONNECTION_UNKNOWN, "test");
2675
2676 const struct {
2677 base::TimeDelta observed_http_rtt;
2678 bool is_end_to_end_rtt_sample_count_enough;
2679 bool expect_hanging_request;
2680 } tests[] = {
2681 {base::Milliseconds(10), true, false},
2682 {base::Milliseconds(10), false, false},
2683 {base::Milliseconds(100), true, false},
2684 // |observed_http_rtt| is not large enough. Request is expected to be
2685 // classified as not hanging.
2686 {base::Milliseconds(
2687 (end_to_end_rtt_milliseconds *
2688 hanging_request_http_rtt_upper_bound_transport_rtt_multiplier) -
2689 1),
2690 true, false},
2691 // |observed_http_rtt| is large. Request is expected to be classified as
2692 // hanging.
2693 {base::Milliseconds(
2694 (end_to_end_rtt_milliseconds *
2695 hanging_request_http_rtt_upper_bound_transport_rtt_multiplier) +
2696 1),
2697 true, true},
2698 // Not enough end-to-end RTT samples. Request is expected to be classified
2699 // as hanging.
2700 {base::Milliseconds(
2701 end_to_end_rtt_milliseconds *
2702 hanging_request_http_rtt_upper_bound_transport_rtt_multiplier -
2703 1),
2704 false, true},
2705 };
2706
2707 for (const auto& test : tests) {
2708 if (test.is_end_to_end_rtt_sample_count_enough) {
2709 estimator.set_start_time_null_end_to_end_rtt_observation_count(
2710 estimator.params()->http_rtt_transport_rtt_min_count());
2711 } else {
2712 estimator.set_start_time_null_end_to_end_rtt_observation_count(
2713 estimator.params()->http_rtt_transport_rtt_min_count() - 1);
2714 }
2715 EXPECT_EQ(test.expect_hanging_request,
2716 estimator.IsHangingRequest(test.observed_http_rtt));
2717 }
2718 }
2719
TEST_F(NetworkQualityEstimatorTest,HangingRequestUsingTransportAndHttpOnly)2720 TEST_F(NetworkQualityEstimatorTest, HangingRequestUsingTransportAndHttpOnly) {
2721 std::map<std::string, std::string> variation_params;
2722 variation_params["add_default_platform_observations"] = "false";
2723 variation_params
2724 ["hanging_request_http_rtt_upper_bound_transport_rtt_multiplier"] = "8";
2725 variation_params["hanging_request_http_rtt_upper_bound_http_rtt_multiplier"] =
2726 "6";
2727 variation_params["hanging_request_upper_bound_min_http_rtt_msec"] = "500";
2728
2729 const base::TimeDelta transport_rtt = base::Milliseconds(100);
2730
2731 TestNetworkQualityEstimator estimator(variation_params);
2732
2733 // 800 msec.
2734 const int32_t hanging_request_threshold =
2735 transport_rtt.InMilliseconds() *
2736 estimator.params()
2737 ->hanging_request_http_rtt_upper_bound_transport_rtt_multiplier();
2738
2739 estimator.DisableOfflineCheckForTesting(true);
2740 estimator.SetStartTimeNullHttpRtt(base::Milliseconds(5));
2741
2742 for (size_t i = 0; i < 100; ++i) {
2743 // Throw enough transport RTT samples so that transport RTT estimate is
2744 // recomputed.
2745 estimator.AddAndNotifyObserversOfRTT(NetworkQualityEstimator::Observation(
2746 transport_rtt.InMilliseconds(), base::TimeTicks::Now(), INT32_MIN,
2747 NETWORK_QUALITY_OBSERVATION_SOURCE_TCP, 0));
2748 }
2749
2750 base::RunLoop().RunUntilIdle();
2751 EXPECT_EQ(transport_rtt, estimator.GetTransportRTT());
2752
2753 const struct {
2754 base::TimeDelta observed_http_rtt;
2755 } tests[] = {
2756 {base::Milliseconds(100)},
2757 {base::Milliseconds(500)},
2758 {base::Milliseconds(hanging_request_threshold - 1)},
2759 {base::Milliseconds(hanging_request_threshold + 1)},
2760 {base::Milliseconds(1000)},
2761 };
2762
2763 for (const auto& test : tests) {
2764 EXPECT_EQ(
2765 test.observed_http_rtt.InMilliseconds() >= hanging_request_threshold,
2766 estimator.IsHangingRequest(test.observed_http_rtt));
2767 }
2768 }
2769
TEST_F(NetworkQualityEstimatorTest,TestPeerToPeerConnectionsCountObserver)2770 TEST_F(NetworkQualityEstimatorTest, TestPeerToPeerConnectionsCountObserver) {
2771 TestPeerToPeerConnectionsCountObserver observer;
2772 TestNetworkQualityEstimator estimator;
2773
2774 EXPECT_EQ(0u, observer.count());
2775 estimator.OnPeerToPeerConnectionsCountChange(5u);
2776 base::RunLoop().RunUntilIdle();
2777 // |observer| has not yet registered with |estimator|.
2778 EXPECT_EQ(0u, observer.count());
2779
2780 // |observer| should be notified of the current count on registration.
2781 estimator.AddPeerToPeerConnectionsCountObserver(&observer);
2782 base::RunLoop().RunUntilIdle();
2783 EXPECT_EQ(5u, observer.count());
2784
2785 estimator.OnPeerToPeerConnectionsCountChange(3u);
2786 base::RunLoop().RunUntilIdle();
2787 EXPECT_EQ(3u, observer.count());
2788 }
2789
2790 // Tests that the HTTP RTT and ECT are adjusted when the count of transport RTTs
2791 // is low. The test adds only HTTP RTT observations and does not add any
2792 // transport RTT observations. Absence of transport RTT observations should
2793 // trigger adjusting of HTTP RTT if param |add_default_platform_observations| is
2794 // set to true.
TEST_F(NetworkQualityEstimatorTest,AdjustHttpRttBasedOnRttCounts)2795 TEST_F(NetworkQualityEstimatorTest, AdjustHttpRttBasedOnRttCounts) {
2796 for (const bool adjust_rtt_based_on_rtt_counts : {false, true}) {
2797 base::SimpleTestTickClock tick_clock;
2798 tick_clock.Advance(base::Minutes(1));
2799
2800 std::map<std::string, std::string> variation_params;
2801 variation_params["add_default_platform_observations"] = "false";
2802
2803 if (adjust_rtt_based_on_rtt_counts) {
2804 variation_params["adjust_rtt_based_on_rtt_counts"] = "true";
2805 }
2806
2807 TestNetworkQualityEstimator estimator(variation_params);
2808 estimator.DisableOfflineCheckForTesting(true);
2809 base::RunLoop().RunUntilIdle();
2810
2811 base::TimeDelta typical_http_rtt_4g =
2812 estimator.params()
2813 ->TypicalNetworkQuality(EFFECTIVE_CONNECTION_TYPE_4G)
2814 .http_rtt();
2815
2816 estimator.SetTickClockForTesting(&tick_clock);
2817 estimator.SimulateNetworkChange(
2818 NetworkChangeNotifier::ConnectionType::CONNECTION_UNKNOWN, "test");
2819 tick_clock.Advance(base::Minutes(1));
2820
2821 const base::TimeDelta rtt = base::Seconds(1);
2822 uint64_t host = 1u;
2823
2824 // Fill the observation buffer so that ECT computations are not triggered
2825 // due to observation buffer's size increasing to 1.5x.
2826 for (size_t i = 0; i < estimator.params()->observation_buffer_size(); ++i) {
2827 estimator.AddAndNotifyObserversOfRTT(NetworkQualityEstimator::Observation(
2828 rtt.InMilliseconds(), tick_clock.NowTicks(), INT32_MIN,
2829 NETWORK_QUALITY_OBSERVATION_SOURCE_HTTP, host));
2830 }
2831 // If |adjust_rtt_based_on_rtt_counts| is set, then the HTTP RTT should be
2832 // that of a typical 4G connection. Otherwise, the RTT estimate should be
2833 // based only on the RTT of the observations added to the buffer.
2834 EXPECT_EQ(adjust_rtt_based_on_rtt_counts ? typical_http_rtt_4g : rtt,
2835 estimator.GetHttpRTT().value());
2836 tick_clock.Advance(base::Minutes(60));
2837
2838 const base::TimeDelta rtt_new = base::Seconds(3);
2839 for (size_t i = 0;
2840 i < estimator.params()->count_new_observations_received_compute_ect();
2841 ++i) {
2842 estimator.AddAndNotifyObserversOfRTT(NetworkQualityEstimator::Observation(
2843 rtt_new.InMilliseconds(), tick_clock.NowTicks(), INT32_MIN,
2844 NETWORK_QUALITY_OBSERVATION_SOURCE_HTTP, host));
2845 }
2846 EXPECT_EQ(adjust_rtt_based_on_rtt_counts ? typical_http_rtt_4g : rtt_new,
2847 estimator.GetHttpRTT().value());
2848 }
2849 }
2850
2851 } // namespace net
2852