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