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