• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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