xref: /aosp_15_r20/external/cronet/net/nqe/throughput_analyzer_unittest.cc (revision 6777b5387eb2ff775bb5750e3f5d96f37fb7352b)
1*6777b538SAndroid Build Coastguard Worker // Copyright 2016 The Chromium Authors
2*6777b538SAndroid Build Coastguard Worker // Use of this source code is governed by a BSD-style license that can be
3*6777b538SAndroid Build Coastguard Worker // found in the LICENSE file.
4*6777b538SAndroid Build Coastguard Worker 
5*6777b538SAndroid Build Coastguard Worker #include "net/nqe/throughput_analyzer.h"
6*6777b538SAndroid Build Coastguard Worker 
7*6777b538SAndroid Build Coastguard Worker #include <stdint.h>
8*6777b538SAndroid Build Coastguard Worker 
9*6777b538SAndroid Build Coastguard Worker #include <map>
10*6777b538SAndroid Build Coastguard Worker #include <memory>
11*6777b538SAndroid Build Coastguard Worker #include <string>
12*6777b538SAndroid Build Coastguard Worker #include <utility>
13*6777b538SAndroid Build Coastguard Worker #include <vector>
14*6777b538SAndroid Build Coastguard Worker 
15*6777b538SAndroid Build Coastguard Worker #include "base/containers/circular_deque.h"
16*6777b538SAndroid Build Coastguard Worker #include "base/functional/bind.h"
17*6777b538SAndroid Build Coastguard Worker #include "base/functional/callback_helpers.h"
18*6777b538SAndroid Build Coastguard Worker #include "base/location.h"
19*6777b538SAndroid Build Coastguard Worker #include "base/run_loop.h"
20*6777b538SAndroid Build Coastguard Worker #include "base/strings/string_number_conversions.h"
21*6777b538SAndroid Build Coastguard Worker #include "base/task/single_thread_task_runner.h"
22*6777b538SAndroid Build Coastguard Worker #include "base/test/metrics/histogram_tester.h"
23*6777b538SAndroid Build Coastguard Worker #include "base/test/scoped_feature_list.h"
24*6777b538SAndroid Build Coastguard Worker #include "base/test/simple_test_tick_clock.h"
25*6777b538SAndroid Build Coastguard Worker #include "base/test/test_timeouts.h"
26*6777b538SAndroid Build Coastguard Worker #include "base/threading/platform_thread.h"
27*6777b538SAndroid Build Coastguard Worker #include "base/time/default_tick_clock.h"
28*6777b538SAndroid Build Coastguard Worker #include "base/time/time.h"
29*6777b538SAndroid Build Coastguard Worker #include "build/build_config.h"
30*6777b538SAndroid Build Coastguard Worker #include "net/base/features.h"
31*6777b538SAndroid Build Coastguard Worker #include "net/base/isolation_info.h"
32*6777b538SAndroid Build Coastguard Worker #include "net/base/schemeful_site.h"
33*6777b538SAndroid Build Coastguard Worker #include "net/dns/mock_host_resolver.h"
34*6777b538SAndroid Build Coastguard Worker #include "net/nqe/network_quality_estimator.h"
35*6777b538SAndroid Build Coastguard Worker #include "net/nqe/network_quality_estimator_params.h"
36*6777b538SAndroid Build Coastguard Worker #include "net/nqe/network_quality_estimator_test_util.h"
37*6777b538SAndroid Build Coastguard Worker #include "net/nqe/network_quality_estimator_util.h"
38*6777b538SAndroid Build Coastguard Worker #include "net/test/test_with_task_environment.h"
39*6777b538SAndroid Build Coastguard Worker #include "net/traffic_annotation/network_traffic_annotation_test_helper.h"
40*6777b538SAndroid Build Coastguard Worker #include "net/url_request/url_request.h"
41*6777b538SAndroid Build Coastguard Worker #include "net/url_request/url_request_context.h"
42*6777b538SAndroid Build Coastguard Worker #include "net/url_request/url_request_context_builder.h"
43*6777b538SAndroid Build Coastguard Worker #include "net/url_request/url_request_test_util.h"
44*6777b538SAndroid Build Coastguard Worker #include "testing/gtest/include/gtest/gtest.h"
45*6777b538SAndroid Build Coastguard Worker #include "url/gurl.h"
46*6777b538SAndroid Build Coastguard Worker 
47*6777b538SAndroid Build Coastguard Worker namespace net::nqe {
48*6777b538SAndroid Build Coastguard Worker 
49*6777b538SAndroid Build Coastguard Worker namespace {
50*6777b538SAndroid Build Coastguard Worker 
51*6777b538SAndroid Build Coastguard Worker // Creates a mock resolver mapping example.com to a public IP address.
CreateMockHostResolver()52*6777b538SAndroid Build Coastguard Worker std::unique_ptr<HostResolver> CreateMockHostResolver() {
53*6777b538SAndroid Build Coastguard Worker   auto host_resolver = std::make_unique<MockCachingHostResolver>(
54*6777b538SAndroid Build Coastguard Worker       /*cache_invalidation_num=*/0,
55*6777b538SAndroid Build Coastguard Worker       /*default_result=*/ERR_NAME_NOT_RESOLVED);
56*6777b538SAndroid Build Coastguard Worker 
57*6777b538SAndroid Build Coastguard Worker   // local.com resolves to a private IP address.
58*6777b538SAndroid Build Coastguard Worker   host_resolver->rules()->AddRule("local.com", "127.0.0.1");
59*6777b538SAndroid Build Coastguard Worker   host_resolver->LoadIntoCache(url::SchemeHostPort("http", "local.com", 80),
60*6777b538SAndroid Build Coastguard Worker                                NetworkAnonymizationKey(), std::nullopt);
61*6777b538SAndroid Build Coastguard Worker   // Hosts not listed here (e.g., "example.com") are treated as external. See
62*6777b538SAndroid Build Coastguard Worker   // ThroughputAnalyzerTest.PrivateHost below.
63*6777b538SAndroid Build Coastguard Worker 
64*6777b538SAndroid Build Coastguard Worker   return host_resolver;
65*6777b538SAndroid Build Coastguard Worker }
66*6777b538SAndroid Build Coastguard Worker 
67*6777b538SAndroid Build Coastguard Worker class TestThroughputAnalyzer : public internal::ThroughputAnalyzer {
68*6777b538SAndroid Build Coastguard Worker  public:
TestThroughputAnalyzer(NetworkQualityEstimator * network_quality_estimator,NetworkQualityEstimatorParams * params,const base::TickClock * tick_clock)69*6777b538SAndroid Build Coastguard Worker   TestThroughputAnalyzer(NetworkQualityEstimator* network_quality_estimator,
70*6777b538SAndroid Build Coastguard Worker                          NetworkQualityEstimatorParams* params,
71*6777b538SAndroid Build Coastguard Worker                          const base::TickClock* tick_clock)
72*6777b538SAndroid Build Coastguard Worker       : internal::ThroughputAnalyzer(
73*6777b538SAndroid Build Coastguard Worker             network_quality_estimator,
74*6777b538SAndroid Build Coastguard Worker             params,
75*6777b538SAndroid Build Coastguard Worker             base::SingleThreadTaskRunner::GetCurrentDefault(),
76*6777b538SAndroid Build Coastguard Worker             base::BindRepeating(
77*6777b538SAndroid Build Coastguard Worker                 &TestThroughputAnalyzer::OnNewThroughputObservationAvailable,
78*6777b538SAndroid Build Coastguard Worker                 base::Unretained(this)),
79*6777b538SAndroid Build Coastguard Worker             tick_clock,
80*6777b538SAndroid Build Coastguard Worker             NetLogWithSource::Make(NetLogSourceType::NONE)) {}
81*6777b538SAndroid Build Coastguard Worker 
82*6777b538SAndroid Build Coastguard Worker   TestThroughputAnalyzer(const TestThroughputAnalyzer&) = delete;
83*6777b538SAndroid Build Coastguard Worker   TestThroughputAnalyzer& operator=(const TestThroughputAnalyzer&) = delete;
84*6777b538SAndroid Build Coastguard Worker 
85*6777b538SAndroid Build Coastguard Worker   ~TestThroughputAnalyzer() override = default;
86*6777b538SAndroid Build Coastguard Worker 
throughput_observations_received() const87*6777b538SAndroid Build Coastguard Worker   int32_t throughput_observations_received() const {
88*6777b538SAndroid Build Coastguard Worker     return throughput_observations_received_;
89*6777b538SAndroid Build Coastguard Worker   }
90*6777b538SAndroid Build Coastguard Worker 
OnNewThroughputObservationAvailable(int32_t downstream_kbps)91*6777b538SAndroid Build Coastguard Worker   void OnNewThroughputObservationAvailable(int32_t downstream_kbps) {
92*6777b538SAndroid Build Coastguard Worker     throughput_observations_received_++;
93*6777b538SAndroid Build Coastguard Worker   }
94*6777b538SAndroid Build Coastguard Worker 
GetBitsReceived() const95*6777b538SAndroid Build Coastguard Worker   int64_t GetBitsReceived() const override { return bits_received_; }
96*6777b538SAndroid Build Coastguard Worker 
IncrementBitsReceived(int64_t additional_bits_received)97*6777b538SAndroid Build Coastguard Worker   void IncrementBitsReceived(int64_t additional_bits_received) {
98*6777b538SAndroid Build Coastguard Worker     bits_received_ += additional_bits_received;
99*6777b538SAndroid Build Coastguard Worker   }
100*6777b538SAndroid Build Coastguard Worker 
101*6777b538SAndroid Build Coastguard Worker   using internal::ThroughputAnalyzer::CountActiveInFlightRequests;
102*6777b538SAndroid Build Coastguard Worker   using internal::ThroughputAnalyzer::
103*6777b538SAndroid Build Coastguard Worker       disable_throughput_measurements_for_testing;
104*6777b538SAndroid Build Coastguard Worker   using internal::ThroughputAnalyzer::EraseHangingRequests;
105*6777b538SAndroid Build Coastguard Worker   using internal::ThroughputAnalyzer::IsHangingWindow;
106*6777b538SAndroid Build Coastguard Worker 
107*6777b538SAndroid Build Coastguard Worker  private:
108*6777b538SAndroid Build Coastguard Worker   int throughput_observations_received_ = 0;
109*6777b538SAndroid Build Coastguard Worker 
110*6777b538SAndroid Build Coastguard Worker   int64_t bits_received_ = 0;
111*6777b538SAndroid Build Coastguard Worker };
112*6777b538SAndroid Build Coastguard Worker 
113*6777b538SAndroid Build Coastguard Worker using ThroughputAnalyzerTest = TestWithTaskEnvironment;
114*6777b538SAndroid Build Coastguard Worker 
TEST_F(ThroughputAnalyzerTest,PrivateHost)115*6777b538SAndroid Build Coastguard Worker TEST_F(ThroughputAnalyzerTest, PrivateHost) {
116*6777b538SAndroid Build Coastguard Worker   auto host_resolver = CreateMockHostResolver();
117*6777b538SAndroid Build Coastguard Worker   EXPECT_FALSE(nqe::internal::IsPrivateHostForTesting(
118*6777b538SAndroid Build Coastguard Worker       host_resolver.get(), url::SchemeHostPort("http", "example.com", 80),
119*6777b538SAndroid Build Coastguard Worker       NetworkAnonymizationKey()));
120*6777b538SAndroid Build Coastguard Worker   EXPECT_TRUE(nqe::internal::IsPrivateHostForTesting(
121*6777b538SAndroid Build Coastguard Worker       host_resolver.get(), url::SchemeHostPort("http", "local.com", 80),
122*6777b538SAndroid Build Coastguard Worker       NetworkAnonymizationKey()));
123*6777b538SAndroid Build Coastguard Worker }
124*6777b538SAndroid Build Coastguard Worker 
125*6777b538SAndroid Build Coastguard Worker #if BUILDFLAG(IS_IOS) || BUILDFLAG(IS_ANDROID)
126*6777b538SAndroid Build Coastguard Worker // Flaky on iOS: crbug.com/672917.
127*6777b538SAndroid Build Coastguard Worker // Flaky on Android: crbug.com/1223950.
128*6777b538SAndroid Build Coastguard Worker #define MAYBE_MaximumRequests DISABLED_MaximumRequests
129*6777b538SAndroid Build Coastguard Worker #else
130*6777b538SAndroid Build Coastguard Worker #define MAYBE_MaximumRequests MaximumRequests
131*6777b538SAndroid Build Coastguard Worker #endif
TEST_F(ThroughputAnalyzerTest,MAYBE_MaximumRequests)132*6777b538SAndroid Build Coastguard Worker TEST_F(ThroughputAnalyzerTest, MAYBE_MaximumRequests) {
133*6777b538SAndroid Build Coastguard Worker   const struct TestCase {
134*6777b538SAndroid Build Coastguard Worker     GURL url;
135*6777b538SAndroid Build Coastguard Worker     bool is_local;
136*6777b538SAndroid Build Coastguard Worker   } kTestCases[] = {
137*6777b538SAndroid Build Coastguard Worker       {GURL("http://127.0.0.1/test.html"), true /* is_local */},
138*6777b538SAndroid Build Coastguard Worker       {GURL("http://example.com/test.html"), false /* is_local */},
139*6777b538SAndroid Build Coastguard Worker       {GURL("http://local.com/test.html"), true /* is_local */},
140*6777b538SAndroid Build Coastguard Worker   };
141*6777b538SAndroid Build Coastguard Worker 
142*6777b538SAndroid Build Coastguard Worker   for (const auto& test_case : kTestCases) {
143*6777b538SAndroid Build Coastguard Worker     const base::TickClock* tick_clock = base::DefaultTickClock::GetInstance();
144*6777b538SAndroid Build Coastguard Worker     TestNetworkQualityEstimator network_quality_estimator;
145*6777b538SAndroid Build Coastguard Worker     std::map<std::string, std::string> variation_params;
146*6777b538SAndroid Build Coastguard Worker     NetworkQualityEstimatorParams params(variation_params);
147*6777b538SAndroid Build Coastguard Worker     TestThroughputAnalyzer throughput_analyzer(&network_quality_estimator,
148*6777b538SAndroid Build Coastguard Worker                                                &params, tick_clock);
149*6777b538SAndroid Build Coastguard Worker 
150*6777b538SAndroid Build Coastguard Worker     TestDelegate test_delegate;
151*6777b538SAndroid Build Coastguard Worker     auto context_builder = CreateTestURLRequestContextBuilder();
152*6777b538SAndroid Build Coastguard Worker     context_builder->set_host_resolver(CreateMockHostResolver());
153*6777b538SAndroid Build Coastguard Worker     auto context = context_builder->Build();
154*6777b538SAndroid Build Coastguard Worker 
155*6777b538SAndroid Build Coastguard Worker     ASSERT_FALSE(
156*6777b538SAndroid Build Coastguard Worker         throughput_analyzer.disable_throughput_measurements_for_testing());
157*6777b538SAndroid Build Coastguard Worker     base::circular_deque<std::unique_ptr<URLRequest>> requests;
158*6777b538SAndroid Build Coastguard Worker 
159*6777b538SAndroid Build Coastguard Worker     // Start more requests than the maximum number of requests that can be held
160*6777b538SAndroid Build Coastguard Worker     // in the memory.
161*6777b538SAndroid Build Coastguard Worker     EXPECT_EQ(test_case.is_local,
162*6777b538SAndroid Build Coastguard Worker               nqe::internal::IsPrivateHostForTesting(
163*6777b538SAndroid Build Coastguard Worker                   context->host_resolver(), url::SchemeHostPort(test_case.url),
164*6777b538SAndroid Build Coastguard Worker                   NetworkAnonymizationKey()));
165*6777b538SAndroid Build Coastguard Worker     for (size_t i = 0; i < 1000; ++i) {
166*6777b538SAndroid Build Coastguard Worker       std::unique_ptr<URLRequest> request(
167*6777b538SAndroid Build Coastguard Worker           context->CreateRequest(test_case.url, DEFAULT_PRIORITY,
168*6777b538SAndroid Build Coastguard Worker                                  &test_delegate, TRAFFIC_ANNOTATION_FOR_TESTS));
169*6777b538SAndroid Build Coastguard Worker       throughput_analyzer.NotifyStartTransaction(*(request.get()));
170*6777b538SAndroid Build Coastguard Worker       requests.push_back(std::move(request));
171*6777b538SAndroid Build Coastguard Worker     }
172*6777b538SAndroid Build Coastguard Worker     // Too many local requests should cause the |throughput_analyzer| to disable
173*6777b538SAndroid Build Coastguard Worker     // throughput measurements.
174*6777b538SAndroid Build Coastguard Worker     EXPECT_NE(test_case.is_local,
175*6777b538SAndroid Build Coastguard Worker               throughput_analyzer.IsCurrentlyTrackingThroughput());
176*6777b538SAndroid Build Coastguard Worker   }
177*6777b538SAndroid Build Coastguard Worker }
178*6777b538SAndroid Build Coastguard Worker 
179*6777b538SAndroid Build Coastguard Worker #if BUILDFLAG(IS_IOS)
180*6777b538SAndroid Build Coastguard Worker // Flaky on iOS: crbug.com/672917.
181*6777b538SAndroid Build Coastguard Worker #define MAYBE_MaximumRequestsWithNetworkAnonymizationKey \
182*6777b538SAndroid Build Coastguard Worker   DISABLED_MaximumRequestsWithNetworkAnonymizationKey
183*6777b538SAndroid Build Coastguard Worker #else
184*6777b538SAndroid Build Coastguard Worker #define MAYBE_MaximumRequestsWithNetworkAnonymizationKey \
185*6777b538SAndroid Build Coastguard Worker   MaximumRequestsWithNetworkAnonymizationKey
186*6777b538SAndroid Build Coastguard Worker #endif
187*6777b538SAndroid Build Coastguard Worker // Make sure that the NetworkAnonymizationKey is respected when resolving a host
188*6777b538SAndroid Build Coastguard Worker // from the cache.
TEST_F(ThroughputAnalyzerTest,MAYBE_MaximumRequestsWithNetworkAnonymizationKey)189*6777b538SAndroid Build Coastguard Worker TEST_F(ThroughputAnalyzerTest,
190*6777b538SAndroid Build Coastguard Worker        MAYBE_MaximumRequestsWithNetworkAnonymizationKey) {
191*6777b538SAndroid Build Coastguard Worker   const SchemefulSite kSite(GURL("https://foo.test/"));
192*6777b538SAndroid Build Coastguard Worker   const auto kNetworkAnonymizationKey =
193*6777b538SAndroid Build Coastguard Worker       NetworkAnonymizationKey::CreateSameSite(kSite);
194*6777b538SAndroid Build Coastguard Worker   const net::NetworkIsolationKey kNetworkIsolationKey(kSite, kSite);
195*6777b538SAndroid Build Coastguard Worker   const GURL kUrl = GURL("http://foo.test/test.html");
196*6777b538SAndroid Build Coastguard Worker   const url::Origin kSiteOrigin = url::Origin::Create(kSite.GetURL());
197*6777b538SAndroid Build Coastguard Worker 
198*6777b538SAndroid Build Coastguard Worker   base::test::ScopedFeatureList feature_list;
199*6777b538SAndroid Build Coastguard Worker   feature_list.InitAndEnableFeature(
200*6777b538SAndroid Build Coastguard Worker       features::kSplitHostCacheByNetworkIsolationKey);
201*6777b538SAndroid Build Coastguard Worker 
202*6777b538SAndroid Build Coastguard Worker   for (bool use_network_isolation_key : {false, true}) {
203*6777b538SAndroid Build Coastguard Worker     const base::TickClock* tick_clock = base::DefaultTickClock::GetInstance();
204*6777b538SAndroid Build Coastguard Worker     TestNetworkQualityEstimator network_quality_estimator;
205*6777b538SAndroid Build Coastguard Worker     std::map<std::string, std::string> variation_params;
206*6777b538SAndroid Build Coastguard Worker     NetworkQualityEstimatorParams params(variation_params);
207*6777b538SAndroid Build Coastguard Worker     TestThroughputAnalyzer throughput_analyzer(&network_quality_estimator,
208*6777b538SAndroid Build Coastguard Worker                                                &params, tick_clock);
209*6777b538SAndroid Build Coastguard Worker 
210*6777b538SAndroid Build Coastguard Worker     TestDelegate test_delegate;
211*6777b538SAndroid Build Coastguard Worker     auto context_builder = CreateTestURLRequestContextBuilder();
212*6777b538SAndroid Build Coastguard Worker     auto mock_host_resolver = std::make_unique<MockCachingHostResolver>();
213*6777b538SAndroid Build Coastguard Worker 
214*6777b538SAndroid Build Coastguard Worker     // Add an entry to the host cache mapping kUrl to non-local IP when using an
215*6777b538SAndroid Build Coastguard Worker     // empty NetworkAnonymizationKey.
216*6777b538SAndroid Build Coastguard Worker     mock_host_resolver->rules()->AddRule(kUrl.host(), "1.2.3.4");
217*6777b538SAndroid Build Coastguard Worker     mock_host_resolver->LoadIntoCache(url::SchemeHostPort(kUrl),
218*6777b538SAndroid Build Coastguard Worker                                       NetworkAnonymizationKey(), std::nullopt);
219*6777b538SAndroid Build Coastguard Worker 
220*6777b538SAndroid Build Coastguard Worker     // Add an entry to the host cache mapping kUrl to local IP when using
221*6777b538SAndroid Build Coastguard Worker     // kNetworkAnonymizationKey.
222*6777b538SAndroid Build Coastguard Worker     mock_host_resolver->rules()->ClearRules();
223*6777b538SAndroid Build Coastguard Worker     mock_host_resolver->rules()->AddRule(kUrl.host(), "127.0.0.1");
224*6777b538SAndroid Build Coastguard Worker     mock_host_resolver->LoadIntoCache(url::SchemeHostPort(kUrl),
225*6777b538SAndroid Build Coastguard Worker                                       kNetworkAnonymizationKey, std::nullopt);
226*6777b538SAndroid Build Coastguard Worker 
227*6777b538SAndroid Build Coastguard Worker     context_builder->set_host_resolver(std::move(mock_host_resolver));
228*6777b538SAndroid Build Coastguard Worker     auto context = context_builder->Build();
229*6777b538SAndroid Build Coastguard Worker     ASSERT_FALSE(
230*6777b538SAndroid Build Coastguard Worker         throughput_analyzer.disable_throughput_measurements_for_testing());
231*6777b538SAndroid Build Coastguard Worker     base::circular_deque<std::unique_ptr<URLRequest>> requests;
232*6777b538SAndroid Build Coastguard Worker 
233*6777b538SAndroid Build Coastguard Worker     // Start more requests than the maximum number of requests that can be held
234*6777b538SAndroid Build Coastguard Worker     // in the memory.
235*6777b538SAndroid Build Coastguard Worker     EXPECT_EQ(use_network_isolation_key,
236*6777b538SAndroid Build Coastguard Worker               nqe::internal::IsPrivateHostForTesting(
237*6777b538SAndroid Build Coastguard Worker                   context->host_resolver(), url::SchemeHostPort(kUrl),
238*6777b538SAndroid Build Coastguard Worker                   use_network_isolation_key ? kNetworkAnonymizationKey
239*6777b538SAndroid Build Coastguard Worker                                             : NetworkAnonymizationKey()));
240*6777b538SAndroid Build Coastguard Worker     for (size_t i = 0; i < 1000; ++i) {
241*6777b538SAndroid Build Coastguard Worker       std::unique_ptr<URLRequest> request(
242*6777b538SAndroid Build Coastguard Worker           context->CreateRequest(kUrl, DEFAULT_PRIORITY, &test_delegate,
243*6777b538SAndroid Build Coastguard Worker                                  TRAFFIC_ANNOTATION_FOR_TESTS));
244*6777b538SAndroid Build Coastguard Worker       if (use_network_isolation_key) {
245*6777b538SAndroid Build Coastguard Worker         request->set_isolation_info(net::IsolationInfo::Create(
246*6777b538SAndroid Build Coastguard Worker             net::IsolationInfo::RequestType::kOther, kSiteOrigin, kSiteOrigin,
247*6777b538SAndroid Build Coastguard Worker             net::SiteForCookies()));
248*6777b538SAndroid Build Coastguard Worker       }
249*6777b538SAndroid Build Coastguard Worker       throughput_analyzer.NotifyStartTransaction(*(request.get()));
250*6777b538SAndroid Build Coastguard Worker       requests.push_back(std::move(request));
251*6777b538SAndroid Build Coastguard Worker     }
252*6777b538SAndroid Build Coastguard Worker     // Too many local requests should cause the |throughput_analyzer| to disable
253*6777b538SAndroid Build Coastguard Worker     // throughput measurements.
254*6777b538SAndroid Build Coastguard Worker     EXPECT_NE(use_network_isolation_key,
255*6777b538SAndroid Build Coastguard Worker               throughput_analyzer.IsCurrentlyTrackingThroughput());
256*6777b538SAndroid Build Coastguard Worker   }
257*6777b538SAndroid Build Coastguard Worker }
258*6777b538SAndroid Build Coastguard Worker 
259*6777b538SAndroid Build Coastguard Worker // Tests that the throughput observation is taken only if there are sufficient
260*6777b538SAndroid Build Coastguard Worker // number of requests in-flight.
TEST_F(ThroughputAnalyzerTest,TestMinRequestsForThroughputSample)261*6777b538SAndroid Build Coastguard Worker TEST_F(ThroughputAnalyzerTest, TestMinRequestsForThroughputSample) {
262*6777b538SAndroid Build Coastguard Worker   const base::TickClock* tick_clock = base::DefaultTickClock::GetInstance();
263*6777b538SAndroid Build Coastguard Worker   TestNetworkQualityEstimator network_quality_estimator;
264*6777b538SAndroid Build Coastguard Worker   std::map<std::string, std::string> variation_params;
265*6777b538SAndroid Build Coastguard Worker   variation_params["throughput_hanging_requests_cwnd_size_multiplier"] = "-1";
266*6777b538SAndroid Build Coastguard Worker   NetworkQualityEstimatorParams params(variation_params);
267*6777b538SAndroid Build Coastguard Worker   // Set HTTP RTT to a large value so that the throughput observation window
268*6777b538SAndroid Build Coastguard Worker   // is not detected as hanging. In practice, this would be provided by
269*6777b538SAndroid Build Coastguard Worker   // |network_quality_estimator| based on the recent observations.
270*6777b538SAndroid Build Coastguard Worker   network_quality_estimator.SetStartTimeNullHttpRtt(base::Seconds(100));
271*6777b538SAndroid Build Coastguard Worker 
272*6777b538SAndroid Build Coastguard Worker   for (size_t num_requests = 1;
273*6777b538SAndroid Build Coastguard Worker        num_requests <= params.throughput_min_requests_in_flight() + 1;
274*6777b538SAndroid Build Coastguard Worker        ++num_requests) {
275*6777b538SAndroid Build Coastguard Worker     TestThroughputAnalyzer throughput_analyzer(&network_quality_estimator,
276*6777b538SAndroid Build Coastguard Worker                                                &params, tick_clock);
277*6777b538SAndroid Build Coastguard Worker     auto context_builder = CreateTestURLRequestContextBuilder();
278*6777b538SAndroid Build Coastguard Worker     context_builder->set_host_resolver(CreateMockHostResolver());
279*6777b538SAndroid Build Coastguard Worker     auto context = context_builder->Build();
280*6777b538SAndroid Build Coastguard Worker 
281*6777b538SAndroid Build Coastguard Worker     // TestDelegates must be before URLRequests that point to them.
282*6777b538SAndroid Build Coastguard Worker     std::vector<TestDelegate> not_local_test_delegates(num_requests);
283*6777b538SAndroid Build Coastguard Worker     std::vector<std::unique_ptr<URLRequest>> requests_not_local;
284*6777b538SAndroid Build Coastguard Worker     for (auto& delegate : not_local_test_delegates) {
285*6777b538SAndroid Build Coastguard Worker       // We don't care about completion, except for the first one (see below).
286*6777b538SAndroid Build Coastguard Worker       delegate.set_on_complete(base::DoNothing());
287*6777b538SAndroid Build Coastguard Worker       std::unique_ptr<URLRequest> request_not_local(context->CreateRequest(
288*6777b538SAndroid Build Coastguard Worker           GURL("http://example.com/echo.html"), DEFAULT_PRIORITY, &delegate,
289*6777b538SAndroid Build Coastguard Worker           TRAFFIC_ANNOTATION_FOR_TESTS));
290*6777b538SAndroid Build Coastguard Worker       request_not_local->Start();
291*6777b538SAndroid Build Coastguard Worker       requests_not_local.push_back(std::move(request_not_local));
292*6777b538SAndroid Build Coastguard Worker     }
293*6777b538SAndroid Build Coastguard Worker     not_local_test_delegates[0].RunUntilComplete();
294*6777b538SAndroid Build Coastguard Worker 
295*6777b538SAndroid Build Coastguard Worker     EXPECT_EQ(0, throughput_analyzer.throughput_observations_received());
296*6777b538SAndroid Build Coastguard Worker 
297*6777b538SAndroid Build Coastguard Worker     for (const auto& request : requests_not_local) {
298*6777b538SAndroid Build Coastguard Worker       throughput_analyzer.NotifyStartTransaction(*request);
299*6777b538SAndroid Build Coastguard Worker     }
300*6777b538SAndroid Build Coastguard Worker 
301*6777b538SAndroid Build Coastguard Worker     // Increment the bytes received count to emulate the bytes received for
302*6777b538SAndroid Build Coastguard Worker     // |request_local| and |requests_not_local|.
303*6777b538SAndroid Build Coastguard Worker     throughput_analyzer.IncrementBitsReceived(100 * 1000 * 8);
304*6777b538SAndroid Build Coastguard Worker 
305*6777b538SAndroid Build Coastguard Worker     for (const auto& request : requests_not_local) {
306*6777b538SAndroid Build Coastguard Worker       throughput_analyzer.NotifyRequestCompleted(*request);
307*6777b538SAndroid Build Coastguard Worker     }
308*6777b538SAndroid Build Coastguard Worker     base::RunLoop().RunUntilIdle();
309*6777b538SAndroid Build Coastguard Worker 
310*6777b538SAndroid Build Coastguard Worker     int expected_throughput_observations =
311*6777b538SAndroid Build Coastguard Worker         num_requests >= params.throughput_min_requests_in_flight() ? 1 : 0;
312*6777b538SAndroid Build Coastguard Worker     EXPECT_EQ(expected_throughput_observations,
313*6777b538SAndroid Build Coastguard Worker               throughput_analyzer.throughput_observations_received());
314*6777b538SAndroid Build Coastguard Worker   }
315*6777b538SAndroid Build Coastguard Worker }
316*6777b538SAndroid Build Coastguard Worker 
317*6777b538SAndroid Build Coastguard Worker // Tests that the hanging requests are dropped from the |requests_|, and
318*6777b538SAndroid Build Coastguard Worker // throughput observation window is ended.
TEST_F(ThroughputAnalyzerTest,TestHangingRequests)319*6777b538SAndroid Build Coastguard Worker TEST_F(ThroughputAnalyzerTest, TestHangingRequests) {
320*6777b538SAndroid Build Coastguard Worker   static const struct {
321*6777b538SAndroid Build Coastguard Worker     int hanging_request_duration_http_rtt_multiplier;
322*6777b538SAndroid Build Coastguard Worker     base::TimeDelta http_rtt;
323*6777b538SAndroid Build Coastguard Worker     base::TimeDelta requests_hang_duration;
324*6777b538SAndroid Build Coastguard Worker     bool expect_throughput_observation;
325*6777b538SAndroid Build Coastguard Worker   } tests[] = {
326*6777b538SAndroid Build Coastguard Worker       {
327*6777b538SAndroid Build Coastguard Worker           // |requests_hang_duration| is less than 5 times the HTTP RTT.
328*6777b538SAndroid Build Coastguard Worker           // Requests should not be marked as hanging.
329*6777b538SAndroid Build Coastguard Worker           5,
330*6777b538SAndroid Build Coastguard Worker           base::Milliseconds(1000),
331*6777b538SAndroid Build Coastguard Worker           base::Milliseconds(3000),
332*6777b538SAndroid Build Coastguard Worker           true,
333*6777b538SAndroid Build Coastguard Worker       },
334*6777b538SAndroid Build Coastguard Worker       {
335*6777b538SAndroid Build Coastguard Worker           // |requests_hang_duration| is more than 5 times the HTTP RTT.
336*6777b538SAndroid Build Coastguard Worker           // Requests should be marked as hanging.
337*6777b538SAndroid Build Coastguard Worker           5,
338*6777b538SAndroid Build Coastguard Worker           base::Milliseconds(200),
339*6777b538SAndroid Build Coastguard Worker           base::Milliseconds(3000),
340*6777b538SAndroid Build Coastguard Worker           false,
341*6777b538SAndroid Build Coastguard Worker       },
342*6777b538SAndroid Build Coastguard Worker       {
343*6777b538SAndroid Build Coastguard Worker           // |requests_hang_duration| is less than
344*6777b538SAndroid Build Coastguard Worker           // |hanging_request_min_duration_msec|. Requests should not be marked
345*6777b538SAndroid Build Coastguard Worker           // as hanging.
346*6777b538SAndroid Build Coastguard Worker           1,
347*6777b538SAndroid Build Coastguard Worker           base::Milliseconds(100),
348*6777b538SAndroid Build Coastguard Worker           base::Milliseconds(100),
349*6777b538SAndroid Build Coastguard Worker           true,
350*6777b538SAndroid Build Coastguard Worker       },
351*6777b538SAndroid Build Coastguard Worker       {
352*6777b538SAndroid Build Coastguard Worker           // |requests_hang_duration| is more than
353*6777b538SAndroid Build Coastguard Worker           // |hanging_request_min_duration_msec|. Requests should be marked as
354*6777b538SAndroid Build Coastguard Worker           // hanging.
355*6777b538SAndroid Build Coastguard Worker           1,
356*6777b538SAndroid Build Coastguard Worker           base::Milliseconds(2000),
357*6777b538SAndroid Build Coastguard Worker           base::Milliseconds(3100),
358*6777b538SAndroid Build Coastguard Worker           false,
359*6777b538SAndroid Build Coastguard Worker       },
360*6777b538SAndroid Build Coastguard Worker       {
361*6777b538SAndroid Build Coastguard Worker           // |requests_hang_duration| is less than 5 times the HTTP RTT.
362*6777b538SAndroid Build Coastguard Worker           // Requests should not be marked as hanging.
363*6777b538SAndroid Build Coastguard Worker           5,
364*6777b538SAndroid Build Coastguard Worker           base::Seconds(2),
365*6777b538SAndroid Build Coastguard Worker           base::Seconds(1),
366*6777b538SAndroid Build Coastguard Worker           true,
367*6777b538SAndroid Build Coastguard Worker       },
368*6777b538SAndroid Build Coastguard Worker       {
369*6777b538SAndroid Build Coastguard Worker           // HTTP RTT is unavailable. Requests should not be marked as hanging.
370*6777b538SAndroid Build Coastguard Worker           5,
371*6777b538SAndroid Build Coastguard Worker           base::Seconds(-1),
372*6777b538SAndroid Build Coastguard Worker           base::Seconds(-1),
373*6777b538SAndroid Build Coastguard Worker           true,
374*6777b538SAndroid Build Coastguard Worker       },
375*6777b538SAndroid Build Coastguard Worker   };
376*6777b538SAndroid Build Coastguard Worker 
377*6777b538SAndroid Build Coastguard Worker   for (const auto& test : tests) {
378*6777b538SAndroid Build Coastguard Worker     base::HistogramTester histogram_tester;
379*6777b538SAndroid Build Coastguard Worker     const base::TickClock* tick_clock = base::DefaultTickClock::GetInstance();
380*6777b538SAndroid Build Coastguard Worker     TestNetworkQualityEstimator network_quality_estimator;
381*6777b538SAndroid Build Coastguard Worker     if (test.http_rtt >= base::TimeDelta())
382*6777b538SAndroid Build Coastguard Worker       network_quality_estimator.SetStartTimeNullHttpRtt(test.http_rtt);
383*6777b538SAndroid Build Coastguard Worker     std::map<std::string, std::string> variation_params;
384*6777b538SAndroid Build Coastguard Worker     // Set the transport RTT multiplier to a large value so that the hanging
385*6777b538SAndroid Build Coastguard Worker     // request decision is made only on the basis of the HTTP RTT.
386*6777b538SAndroid Build Coastguard Worker     variation_params
387*6777b538SAndroid Build Coastguard Worker         ["hanging_request_http_rtt_upper_bound_transport_rtt_multiplier"] =
388*6777b538SAndroid Build Coastguard Worker             "10000";
389*6777b538SAndroid Build Coastguard Worker     variation_params["throughput_hanging_requests_cwnd_size_multiplier"] = "-1";
390*6777b538SAndroid Build Coastguard Worker     variation_params["hanging_request_duration_http_rtt_multiplier"] =
391*6777b538SAndroid Build Coastguard Worker         base::NumberToString(test.hanging_request_duration_http_rtt_multiplier);
392*6777b538SAndroid Build Coastguard Worker 
393*6777b538SAndroid Build Coastguard Worker     NetworkQualityEstimatorParams params(variation_params);
394*6777b538SAndroid Build Coastguard Worker 
395*6777b538SAndroid Build Coastguard Worker     const size_t num_requests = params.throughput_min_requests_in_flight();
396*6777b538SAndroid Build Coastguard Worker     TestThroughputAnalyzer throughput_analyzer(&network_quality_estimator,
397*6777b538SAndroid Build Coastguard Worker                                                &params, tick_clock);
398*6777b538SAndroid Build Coastguard Worker     auto context_builder = CreateTestURLRequestContextBuilder();
399*6777b538SAndroid Build Coastguard Worker     context_builder->set_host_resolver(CreateMockHostResolver());
400*6777b538SAndroid Build Coastguard Worker     auto context = context_builder->Build();
401*6777b538SAndroid Build Coastguard Worker 
402*6777b538SAndroid Build Coastguard Worker     // TestDelegates must be before URLRequests that point to them.
403*6777b538SAndroid Build Coastguard Worker     std::vector<TestDelegate> not_local_test_delegates(num_requests);
404*6777b538SAndroid Build Coastguard Worker     std::vector<std::unique_ptr<URLRequest>> requests_not_local;
405*6777b538SAndroid Build Coastguard Worker     for (size_t i = 0; i < num_requests; ++i) {
406*6777b538SAndroid Build Coastguard Worker       // We don't care about completion, except for the first one (see below).
407*6777b538SAndroid Build Coastguard Worker       not_local_test_delegates[i].set_on_complete(base::DoNothing());
408*6777b538SAndroid Build Coastguard Worker       std::unique_ptr<URLRequest> request_not_local(context->CreateRequest(
409*6777b538SAndroid Build Coastguard Worker           GURL("http://example.com/echo.html"), DEFAULT_PRIORITY,
410*6777b538SAndroid Build Coastguard Worker           &not_local_test_delegates[i], TRAFFIC_ANNOTATION_FOR_TESTS));
411*6777b538SAndroid Build Coastguard Worker       request_not_local->Start();
412*6777b538SAndroid Build Coastguard Worker       requests_not_local.push_back(std::move(request_not_local));
413*6777b538SAndroid Build Coastguard Worker     }
414*6777b538SAndroid Build Coastguard Worker 
415*6777b538SAndroid Build Coastguard Worker     not_local_test_delegates[0].RunUntilComplete();
416*6777b538SAndroid Build Coastguard Worker 
417*6777b538SAndroid Build Coastguard Worker     EXPECT_EQ(0, throughput_analyzer.throughput_observations_received());
418*6777b538SAndroid Build Coastguard Worker 
419*6777b538SAndroid Build Coastguard Worker     for (size_t i = 0; i < num_requests; ++i) {
420*6777b538SAndroid Build Coastguard Worker       throughput_analyzer.NotifyStartTransaction(*requests_not_local.at(i));
421*6777b538SAndroid Build Coastguard Worker     }
422*6777b538SAndroid Build Coastguard Worker 
423*6777b538SAndroid Build Coastguard Worker     // Increment the bytes received count to emulate the bytes received for
424*6777b538SAndroid Build Coastguard Worker     // |request_local| and |requests_not_local|.
425*6777b538SAndroid Build Coastguard Worker     throughput_analyzer.IncrementBitsReceived(100 * 1000 * 8);
426*6777b538SAndroid Build Coastguard Worker 
427*6777b538SAndroid Build Coastguard Worker     // Mark in-flight requests as hanging requests (if specified in the test
428*6777b538SAndroid Build Coastguard Worker     // params).
429*6777b538SAndroid Build Coastguard Worker     if (test.requests_hang_duration >= base::TimeDelta())
430*6777b538SAndroid Build Coastguard Worker       base::PlatformThread::Sleep(test.requests_hang_duration);
431*6777b538SAndroid Build Coastguard Worker 
432*6777b538SAndroid Build Coastguard Worker     EXPECT_EQ(num_requests, throughput_analyzer.CountActiveInFlightRequests());
433*6777b538SAndroid Build Coastguard Worker 
434*6777b538SAndroid Build Coastguard Worker     for (size_t i = 0; i < num_requests; ++i) {
435*6777b538SAndroid Build Coastguard Worker       throughput_analyzer.NotifyRequestCompleted(*requests_not_local.at(i));
436*6777b538SAndroid Build Coastguard Worker       if (!test.expect_throughput_observation) {
437*6777b538SAndroid Build Coastguard Worker         // All in-flight requests should be marked as hanging, and thus should
438*6777b538SAndroid Build Coastguard Worker         // be deleted from the set of in-flight requests.
439*6777b538SAndroid Build Coastguard Worker         EXPECT_EQ(0u, throughput_analyzer.CountActiveInFlightRequests());
440*6777b538SAndroid Build Coastguard Worker       } else {
441*6777b538SAndroid Build Coastguard Worker         // One request should be deleted at one time.
442*6777b538SAndroid Build Coastguard Worker         EXPECT_EQ(requests_not_local.size() - i - 1,
443*6777b538SAndroid Build Coastguard Worker                   throughput_analyzer.CountActiveInFlightRequests());
444*6777b538SAndroid Build Coastguard Worker       }
445*6777b538SAndroid Build Coastguard Worker     }
446*6777b538SAndroid Build Coastguard Worker 
447*6777b538SAndroid Build Coastguard Worker     base::RunLoop().RunUntilIdle();
448*6777b538SAndroid Build Coastguard Worker 
449*6777b538SAndroid Build Coastguard Worker     EXPECT_EQ(test.expect_throughput_observation,
450*6777b538SAndroid Build Coastguard Worker               throughput_analyzer.throughput_observations_received() > 0);
451*6777b538SAndroid Build Coastguard Worker   }
452*6777b538SAndroid Build Coastguard Worker }
453*6777b538SAndroid Build Coastguard Worker 
454*6777b538SAndroid Build Coastguard Worker // Tests that the check for hanging requests is done at most once per second.
TEST_F(ThroughputAnalyzerTest,TestHangingRequestsCheckedOnlyPeriodically)455*6777b538SAndroid Build Coastguard Worker TEST_F(ThroughputAnalyzerTest, TestHangingRequestsCheckedOnlyPeriodically) {
456*6777b538SAndroid Build Coastguard Worker   base::SimpleTestTickClock tick_clock;
457*6777b538SAndroid Build Coastguard Worker 
458*6777b538SAndroid Build Coastguard Worker   TestNetworkQualityEstimator network_quality_estimator;
459*6777b538SAndroid Build Coastguard Worker   network_quality_estimator.SetStartTimeNullHttpRtt(base::Seconds(1));
460*6777b538SAndroid Build Coastguard Worker   std::map<std::string, std::string> variation_params;
461*6777b538SAndroid Build Coastguard Worker   variation_params["hanging_request_duration_http_rtt_multiplier"] = "5";
462*6777b538SAndroid Build Coastguard Worker   variation_params["hanging_request_min_duration_msec"] = "2000";
463*6777b538SAndroid Build Coastguard Worker   NetworkQualityEstimatorParams params(variation_params);
464*6777b538SAndroid Build Coastguard Worker 
465*6777b538SAndroid Build Coastguard Worker   TestThroughputAnalyzer throughput_analyzer(&network_quality_estimator,
466*6777b538SAndroid Build Coastguard Worker                                              &params, &tick_clock);
467*6777b538SAndroid Build Coastguard Worker 
468*6777b538SAndroid Build Coastguard Worker   TestDelegate test_delegate;
469*6777b538SAndroid Build Coastguard Worker   auto context_builder = CreateTestURLRequestContextBuilder();
470*6777b538SAndroid Build Coastguard Worker   context_builder->set_host_resolver(CreateMockHostResolver());
471*6777b538SAndroid Build Coastguard Worker   auto context = context_builder->Build();
472*6777b538SAndroid Build Coastguard Worker   std::vector<std::unique_ptr<URLRequest>> requests_not_local;
473*6777b538SAndroid Build Coastguard Worker 
474*6777b538SAndroid Build Coastguard Worker   for (size_t i = 0; i < 2; ++i) {
475*6777b538SAndroid Build Coastguard Worker     std::unique_ptr<URLRequest> request_not_local(context->CreateRequest(
476*6777b538SAndroid Build Coastguard Worker         GURL("http://example.com/echo.html"), DEFAULT_PRIORITY, &test_delegate,
477*6777b538SAndroid Build Coastguard Worker         TRAFFIC_ANNOTATION_FOR_TESTS));
478*6777b538SAndroid Build Coastguard Worker     request_not_local->Start();
479*6777b538SAndroid Build Coastguard Worker     requests_not_local.push_back(std::move(request_not_local));
480*6777b538SAndroid Build Coastguard Worker   }
481*6777b538SAndroid Build Coastguard Worker 
482*6777b538SAndroid Build Coastguard Worker   std::unique_ptr<URLRequest> some_other_request(context->CreateRequest(
483*6777b538SAndroid Build Coastguard Worker       GURL("http://example.com/echo.html"), DEFAULT_PRIORITY, &test_delegate,
484*6777b538SAndroid Build Coastguard Worker       TRAFFIC_ANNOTATION_FOR_TESTS));
485*6777b538SAndroid Build Coastguard Worker 
486*6777b538SAndroid Build Coastguard Worker   test_delegate.RunUntilComplete();
487*6777b538SAndroid Build Coastguard Worker 
488*6777b538SAndroid Build Coastguard Worker   // First request starts at t=1. The second request starts at t=2. The first
489*6777b538SAndroid Build Coastguard Worker   // request would be marked as hanging at t=6, and the second request at t=7
490*6777b538SAndroid Build Coastguard Worker   // seconds.
491*6777b538SAndroid Build Coastguard Worker   for (size_t i = 0; i < 2; ++i) {
492*6777b538SAndroid Build Coastguard Worker     tick_clock.Advance(base::Milliseconds(1000));
493*6777b538SAndroid Build Coastguard Worker     throughput_analyzer.NotifyStartTransaction(*requests_not_local.at(i));
494*6777b538SAndroid Build Coastguard Worker   }
495*6777b538SAndroid Build Coastguard Worker 
496*6777b538SAndroid Build Coastguard Worker   EXPECT_EQ(2u, throughput_analyzer.CountActiveInFlightRequests());
497*6777b538SAndroid Build Coastguard Worker   tick_clock.Advance(base::Milliseconds(3500));
498*6777b538SAndroid Build Coastguard Worker   // Current time is t = 5.5 seconds.
499*6777b538SAndroid Build Coastguard Worker   throughput_analyzer.EraseHangingRequests(*some_other_request);
500*6777b538SAndroid Build Coastguard Worker   EXPECT_EQ(2u, throughput_analyzer.CountActiveInFlightRequests());
501*6777b538SAndroid Build Coastguard Worker 
502*6777b538SAndroid Build Coastguard Worker   tick_clock.Advance(base::Milliseconds(1000));
503*6777b538SAndroid Build Coastguard Worker   // Current time is t = 6.5 seconds.  One request should be marked as hanging.
504*6777b538SAndroid Build Coastguard Worker   throughput_analyzer.EraseHangingRequests(*some_other_request);
505*6777b538SAndroid Build Coastguard Worker   EXPECT_EQ(1u, throughput_analyzer.CountActiveInFlightRequests());
506*6777b538SAndroid Build Coastguard Worker 
507*6777b538SAndroid Build Coastguard Worker   // Current time is t = 6.5 seconds. Calling NotifyBytesRead again should not
508*6777b538SAndroid Build Coastguard Worker   // run the hanging request checker since the last check was at t=6.5 seconds.
509*6777b538SAndroid Build Coastguard Worker   throughput_analyzer.EraseHangingRequests(*some_other_request);
510*6777b538SAndroid Build Coastguard Worker   EXPECT_EQ(1u, throughput_analyzer.CountActiveInFlightRequests());
511*6777b538SAndroid Build Coastguard Worker 
512*6777b538SAndroid Build Coastguard Worker   tick_clock.Advance(base::Milliseconds(600));
513*6777b538SAndroid Build Coastguard Worker   // Current time is t = 7.1 seconds. Calling NotifyBytesRead again should not
514*6777b538SAndroid Build Coastguard Worker   // run the hanging request checker since the last check was at t=6.5 seconds
515*6777b538SAndroid Build Coastguard Worker   // (less than 1 second ago).
516*6777b538SAndroid Build Coastguard Worker   throughput_analyzer.EraseHangingRequests(*some_other_request);
517*6777b538SAndroid Build Coastguard Worker   EXPECT_EQ(1u, throughput_analyzer.CountActiveInFlightRequests());
518*6777b538SAndroid Build Coastguard Worker 
519*6777b538SAndroid Build Coastguard Worker   tick_clock.Advance(base::Milliseconds(400));
520*6777b538SAndroid Build Coastguard Worker   // Current time is t = 7.5 seconds. Calling NotifyBytesRead again should run
521*6777b538SAndroid Build Coastguard Worker   // the hanging request checker since the last check was at t=6.5 seconds (at
522*6777b538SAndroid Build Coastguard Worker   // least 1 second ago).
523*6777b538SAndroid Build Coastguard Worker   throughput_analyzer.EraseHangingRequests(*some_other_request);
524*6777b538SAndroid Build Coastguard Worker   EXPECT_EQ(0u, throughput_analyzer.CountActiveInFlightRequests());
525*6777b538SAndroid Build Coastguard Worker }
526*6777b538SAndroid Build Coastguard Worker 
527*6777b538SAndroid Build Coastguard Worker // Tests that the last received time for a request is updated when data is
528*6777b538SAndroid Build Coastguard Worker // received for that request.
TEST_F(ThroughputAnalyzerTest,TestLastReceivedTimeIsUpdated)529*6777b538SAndroid Build Coastguard Worker TEST_F(ThroughputAnalyzerTest, TestLastReceivedTimeIsUpdated) {
530*6777b538SAndroid Build Coastguard Worker   base::SimpleTestTickClock tick_clock;
531*6777b538SAndroid Build Coastguard Worker 
532*6777b538SAndroid Build Coastguard Worker   TestNetworkQualityEstimator network_quality_estimator;
533*6777b538SAndroid Build Coastguard Worker   network_quality_estimator.SetStartTimeNullHttpRtt(base::Seconds(1));
534*6777b538SAndroid Build Coastguard Worker   std::map<std::string, std::string> variation_params;
535*6777b538SAndroid Build Coastguard Worker   variation_params["hanging_request_duration_http_rtt_multiplier"] = "5";
536*6777b538SAndroid Build Coastguard Worker   variation_params["hanging_request_min_duration_msec"] = "2000";
537*6777b538SAndroid Build Coastguard Worker   NetworkQualityEstimatorParams params(variation_params);
538*6777b538SAndroid Build Coastguard Worker 
539*6777b538SAndroid Build Coastguard Worker   TestThroughputAnalyzer throughput_analyzer(&network_quality_estimator,
540*6777b538SAndroid Build Coastguard Worker                                              &params, &tick_clock);
541*6777b538SAndroid Build Coastguard Worker 
542*6777b538SAndroid Build Coastguard Worker   TestDelegate test_delegate;
543*6777b538SAndroid Build Coastguard Worker   auto context_builder = CreateTestURLRequestContextBuilder();
544*6777b538SAndroid Build Coastguard Worker   context_builder->set_host_resolver(CreateMockHostResolver());
545*6777b538SAndroid Build Coastguard Worker   auto context = context_builder->Build();
546*6777b538SAndroid Build Coastguard Worker 
547*6777b538SAndroid Build Coastguard Worker   std::unique_ptr<URLRequest> request_not_local(context->CreateRequest(
548*6777b538SAndroid Build Coastguard Worker       GURL("http://example.com/echo.html"), DEFAULT_PRIORITY, &test_delegate,
549*6777b538SAndroid Build Coastguard Worker       TRAFFIC_ANNOTATION_FOR_TESTS));
550*6777b538SAndroid Build Coastguard Worker   request_not_local->Start();
551*6777b538SAndroid Build Coastguard Worker 
552*6777b538SAndroid Build Coastguard Worker   test_delegate.RunUntilComplete();
553*6777b538SAndroid Build Coastguard Worker 
554*6777b538SAndroid Build Coastguard Worker   std::unique_ptr<URLRequest> some_other_request(context->CreateRequest(
555*6777b538SAndroid Build Coastguard Worker       GURL("http://example.com/echo.html"), DEFAULT_PRIORITY, &test_delegate,
556*6777b538SAndroid Build Coastguard Worker       TRAFFIC_ANNOTATION_FOR_TESTS));
557*6777b538SAndroid Build Coastguard Worker 
558*6777b538SAndroid Build Coastguard Worker   // Start time for the request is t=0 second. The request will be marked as
559*6777b538SAndroid Build Coastguard Worker   // hanging at t=5 seconds.
560*6777b538SAndroid Build Coastguard Worker   throughput_analyzer.NotifyStartTransaction(*request_not_local);
561*6777b538SAndroid Build Coastguard Worker 
562*6777b538SAndroid Build Coastguard Worker   tick_clock.Advance(base::Milliseconds(4000));
563*6777b538SAndroid Build Coastguard Worker   // Current time is t=4.0 seconds.
564*6777b538SAndroid Build Coastguard Worker 
565*6777b538SAndroid Build Coastguard Worker   throughput_analyzer.EraseHangingRequests(*some_other_request);
566*6777b538SAndroid Build Coastguard Worker   EXPECT_EQ(1u, throughput_analyzer.CountActiveInFlightRequests());
567*6777b538SAndroid Build Coastguard Worker 
568*6777b538SAndroid Build Coastguard Worker   //  The request will be marked as hanging at t=9 seconds.
569*6777b538SAndroid Build Coastguard Worker   throughput_analyzer.NotifyBytesRead(*request_not_local);
570*6777b538SAndroid Build Coastguard Worker   tick_clock.Advance(base::Milliseconds(4000));
571*6777b538SAndroid Build Coastguard Worker   // Current time is t=8 seconds.
572*6777b538SAndroid Build Coastguard Worker   throughput_analyzer.EraseHangingRequests(*some_other_request);
573*6777b538SAndroid Build Coastguard Worker   EXPECT_EQ(1u, throughput_analyzer.CountActiveInFlightRequests());
574*6777b538SAndroid Build Coastguard Worker 
575*6777b538SAndroid Build Coastguard Worker   tick_clock.Advance(base::Milliseconds(2000));
576*6777b538SAndroid Build Coastguard Worker   // Current time is t=10 seconds.
577*6777b538SAndroid Build Coastguard Worker   throughput_analyzer.EraseHangingRequests(*some_other_request);
578*6777b538SAndroid Build Coastguard Worker   EXPECT_EQ(0u, throughput_analyzer.CountActiveInFlightRequests());
579*6777b538SAndroid Build Coastguard Worker }
580*6777b538SAndroid Build Coastguard Worker 
581*6777b538SAndroid Build Coastguard Worker // Test that a request that has been hanging for a long time is deleted
582*6777b538SAndroid Build Coastguard Worker // immediately when EraseHangingRequests is called even if the last hanging
583*6777b538SAndroid Build Coastguard Worker // request check was done recently.
TEST_F(ThroughputAnalyzerTest,TestRequestDeletedImmediately)584*6777b538SAndroid Build Coastguard Worker TEST_F(ThroughputAnalyzerTest, TestRequestDeletedImmediately) {
585*6777b538SAndroid Build Coastguard Worker   base::SimpleTestTickClock tick_clock;
586*6777b538SAndroid Build Coastguard Worker 
587*6777b538SAndroid Build Coastguard Worker   TestNetworkQualityEstimator network_quality_estimator;
588*6777b538SAndroid Build Coastguard Worker   network_quality_estimator.SetStartTimeNullHttpRtt(base::Seconds(1));
589*6777b538SAndroid Build Coastguard Worker   std::map<std::string, std::string> variation_params;
590*6777b538SAndroid Build Coastguard Worker   variation_params["hanging_request_duration_http_rtt_multiplier"] = "2";
591*6777b538SAndroid Build Coastguard Worker   NetworkQualityEstimatorParams params(variation_params);
592*6777b538SAndroid Build Coastguard Worker 
593*6777b538SAndroid Build Coastguard Worker   TestThroughputAnalyzer throughput_analyzer(&network_quality_estimator,
594*6777b538SAndroid Build Coastguard Worker                                              &params, &tick_clock);
595*6777b538SAndroid Build Coastguard Worker 
596*6777b538SAndroid Build Coastguard Worker   TestDelegate test_delegate;
597*6777b538SAndroid Build Coastguard Worker   auto context_builder = CreateTestURLRequestContextBuilder();
598*6777b538SAndroid Build Coastguard Worker   context_builder->set_host_resolver(CreateMockHostResolver());
599*6777b538SAndroid Build Coastguard Worker   auto context = context_builder->Build();
600*6777b538SAndroid Build Coastguard Worker 
601*6777b538SAndroid Build Coastguard Worker   std::unique_ptr<URLRequest> request_not_local(context->CreateRequest(
602*6777b538SAndroid Build Coastguard Worker       GURL("http://example.com/echo.html"), DEFAULT_PRIORITY, &test_delegate,
603*6777b538SAndroid Build Coastguard Worker       TRAFFIC_ANNOTATION_FOR_TESTS));
604*6777b538SAndroid Build Coastguard Worker   request_not_local->Start();
605*6777b538SAndroid Build Coastguard Worker 
606*6777b538SAndroid Build Coastguard Worker   test_delegate.RunUntilComplete();
607*6777b538SAndroid Build Coastguard Worker 
608*6777b538SAndroid Build Coastguard Worker   // Start time for the request is t=0 second. The request will be marked as
609*6777b538SAndroid Build Coastguard Worker   // hanging at t=2 seconds.
610*6777b538SAndroid Build Coastguard Worker   throughput_analyzer.NotifyStartTransaction(*request_not_local);
611*6777b538SAndroid Build Coastguard Worker   EXPECT_EQ(1u, throughput_analyzer.CountActiveInFlightRequests());
612*6777b538SAndroid Build Coastguard Worker 
613*6777b538SAndroid Build Coastguard Worker   tick_clock.Advance(base::Milliseconds(2900));
614*6777b538SAndroid Build Coastguard Worker   // Current time is t=2.9 seconds.
615*6777b538SAndroid Build Coastguard Worker 
616*6777b538SAndroid Build Coastguard Worker   throughput_analyzer.EraseHangingRequests(*request_not_local);
617*6777b538SAndroid Build Coastguard Worker   EXPECT_EQ(1u, throughput_analyzer.CountActiveInFlightRequests());
618*6777b538SAndroid Build Coastguard Worker 
619*6777b538SAndroid Build Coastguard Worker   // |request_not_local| should be deleted since it has been idle for 2.4
620*6777b538SAndroid Build Coastguard Worker   // seconds.
621*6777b538SAndroid Build Coastguard Worker   tick_clock.Advance(base::Milliseconds(500));
622*6777b538SAndroid Build Coastguard Worker   throughput_analyzer.NotifyBytesRead(*request_not_local);
623*6777b538SAndroid Build Coastguard Worker   EXPECT_EQ(0u, throughput_analyzer.CountActiveInFlightRequests());
624*6777b538SAndroid Build Coastguard Worker }
625*6777b538SAndroid Build Coastguard Worker 
626*6777b538SAndroid Build Coastguard Worker #if BUILDFLAG(IS_IOS)
627*6777b538SAndroid Build Coastguard Worker // Flaky on iOS: crbug.com/672917.
628*6777b538SAndroid Build Coastguard Worker #define MAYBE_TestThroughputWithMultipleRequestsOverlap \
629*6777b538SAndroid Build Coastguard Worker   DISABLED_TestThroughputWithMultipleRequestsOverlap
630*6777b538SAndroid Build Coastguard Worker #else
631*6777b538SAndroid Build Coastguard Worker #define MAYBE_TestThroughputWithMultipleRequestsOverlap \
632*6777b538SAndroid Build Coastguard Worker   TestThroughputWithMultipleRequestsOverlap
633*6777b538SAndroid Build Coastguard Worker #endif
634*6777b538SAndroid Build Coastguard Worker // Tests if the throughput observation is taken correctly when local and network
635*6777b538SAndroid Build Coastguard Worker // requests overlap.
TEST_F(ThroughputAnalyzerTest,MAYBE_TestThroughputWithMultipleRequestsOverlap)636*6777b538SAndroid Build Coastguard Worker TEST_F(ThroughputAnalyzerTest,
637*6777b538SAndroid Build Coastguard Worker        MAYBE_TestThroughputWithMultipleRequestsOverlap) {
638*6777b538SAndroid Build Coastguard Worker   static const struct {
639*6777b538SAndroid Build Coastguard Worker     bool start_local_request;
640*6777b538SAndroid Build Coastguard Worker     bool local_request_completes_first;
641*6777b538SAndroid Build Coastguard Worker     bool expect_throughput_observation;
642*6777b538SAndroid Build Coastguard Worker   } tests[] = {
643*6777b538SAndroid Build Coastguard Worker       {
644*6777b538SAndroid Build Coastguard Worker           false, false, true,
645*6777b538SAndroid Build Coastguard Worker       },
646*6777b538SAndroid Build Coastguard Worker       {
647*6777b538SAndroid Build Coastguard Worker           true, false, false,
648*6777b538SAndroid Build Coastguard Worker       },
649*6777b538SAndroid Build Coastguard Worker       {
650*6777b538SAndroid Build Coastguard Worker           true, true, true,
651*6777b538SAndroid Build Coastguard Worker       },
652*6777b538SAndroid Build Coastguard Worker   };
653*6777b538SAndroid Build Coastguard Worker 
654*6777b538SAndroid Build Coastguard Worker   for (const auto& test : tests) {
655*6777b538SAndroid Build Coastguard Worker     const base::TickClock* tick_clock = base::DefaultTickClock::GetInstance();
656*6777b538SAndroid Build Coastguard Worker     TestNetworkQualityEstimator network_quality_estimator;
657*6777b538SAndroid Build Coastguard Worker     // Localhost requests are not allowed for estimation purposes.
658*6777b538SAndroid Build Coastguard Worker     std::map<std::string, std::string> variation_params;
659*6777b538SAndroid Build Coastguard Worker     variation_params["throughput_hanging_requests_cwnd_size_multiplier"] = "-1";
660*6777b538SAndroid Build Coastguard Worker     NetworkQualityEstimatorParams params(variation_params);
661*6777b538SAndroid Build Coastguard Worker 
662*6777b538SAndroid Build Coastguard Worker     TestThroughputAnalyzer throughput_analyzer(&network_quality_estimator,
663*6777b538SAndroid Build Coastguard Worker                                                &params, tick_clock);
664*6777b538SAndroid Build Coastguard Worker 
665*6777b538SAndroid Build Coastguard Worker     TestDelegate local_delegate;
666*6777b538SAndroid Build Coastguard Worker     local_delegate.set_on_complete(base::DoNothing());
667*6777b538SAndroid Build Coastguard Worker     auto context_builder = CreateTestURLRequestContextBuilder();
668*6777b538SAndroid Build Coastguard Worker     context_builder->set_host_resolver(CreateMockHostResolver());
669*6777b538SAndroid Build Coastguard Worker     auto context = context_builder->Build();
670*6777b538SAndroid Build Coastguard Worker     std::unique_ptr<URLRequest> request_local;
671*6777b538SAndroid Build Coastguard Worker 
672*6777b538SAndroid Build Coastguard Worker     // TestDelegates must be before URLRequests that point to them.
673*6777b538SAndroid Build Coastguard Worker     std::vector<TestDelegate> not_local_test_delegates(
674*6777b538SAndroid Build Coastguard Worker         params.throughput_min_requests_in_flight());
675*6777b538SAndroid Build Coastguard Worker     std::vector<std::unique_ptr<URLRequest>> requests_not_local;
676*6777b538SAndroid Build Coastguard Worker     for (size_t i = 0; i < params.throughput_min_requests_in_flight(); ++i) {
677*6777b538SAndroid Build Coastguard Worker       // We don't care about completion, except for the first one (see below).
678*6777b538SAndroid Build Coastguard Worker       not_local_test_delegates[i].set_on_complete(base::DoNothing());
679*6777b538SAndroid Build Coastguard Worker       std::unique_ptr<URLRequest> request_not_local(context->CreateRequest(
680*6777b538SAndroid Build Coastguard Worker           GURL("http://example.com/echo.html"), DEFAULT_PRIORITY,
681*6777b538SAndroid Build Coastguard Worker           &not_local_test_delegates[i], TRAFFIC_ANNOTATION_FOR_TESTS));
682*6777b538SAndroid Build Coastguard Worker       request_not_local->Start();
683*6777b538SAndroid Build Coastguard Worker       requests_not_local.push_back(std::move(request_not_local));
684*6777b538SAndroid Build Coastguard Worker     }
685*6777b538SAndroid Build Coastguard Worker 
686*6777b538SAndroid Build Coastguard Worker     if (test.start_local_request) {
687*6777b538SAndroid Build Coastguard Worker       request_local = context->CreateRequest(GURL("http://127.0.0.1/echo.html"),
688*6777b538SAndroid Build Coastguard Worker                                              DEFAULT_PRIORITY, &local_delegate,
689*6777b538SAndroid Build Coastguard Worker                                              TRAFFIC_ANNOTATION_FOR_TESTS);
690*6777b538SAndroid Build Coastguard Worker       request_local->Start();
691*6777b538SAndroid Build Coastguard Worker     }
692*6777b538SAndroid Build Coastguard Worker 
693*6777b538SAndroid Build Coastguard Worker     // Wait until the first not-local request completes.
694*6777b538SAndroid Build Coastguard Worker     not_local_test_delegates[0].RunUntilComplete();
695*6777b538SAndroid Build Coastguard Worker 
696*6777b538SAndroid Build Coastguard Worker     EXPECT_EQ(0, throughput_analyzer.throughput_observations_received());
697*6777b538SAndroid Build Coastguard Worker 
698*6777b538SAndroid Build Coastguard Worker     // If |test.start_local_request| is true, then |request_local| starts
699*6777b538SAndroid Build Coastguard Worker     // before |request_not_local|, and ends after |request_not_local|. Thus,
700*6777b538SAndroid Build Coastguard Worker     // network quality estimator should not get a chance to record throughput
701*6777b538SAndroid Build Coastguard Worker     // observation from |request_not_local| because of ongoing local request
702*6777b538SAndroid Build Coastguard Worker     // at all times.
703*6777b538SAndroid Build Coastguard Worker     if (test.start_local_request)
704*6777b538SAndroid Build Coastguard Worker       throughput_analyzer.NotifyStartTransaction(*request_local);
705*6777b538SAndroid Build Coastguard Worker 
706*6777b538SAndroid Build Coastguard Worker     for (const auto& request : requests_not_local) {
707*6777b538SAndroid Build Coastguard Worker       throughput_analyzer.NotifyStartTransaction(*request);
708*6777b538SAndroid Build Coastguard Worker     }
709*6777b538SAndroid Build Coastguard Worker 
710*6777b538SAndroid Build Coastguard Worker     if (test.local_request_completes_first) {
711*6777b538SAndroid Build Coastguard Worker       ASSERT_TRUE(test.start_local_request);
712*6777b538SAndroid Build Coastguard Worker       throughput_analyzer.NotifyRequestCompleted(*request_local);
713*6777b538SAndroid Build Coastguard Worker     }
714*6777b538SAndroid Build Coastguard Worker 
715*6777b538SAndroid Build Coastguard Worker     // Increment the bytes received count to emulate the bytes received for
716*6777b538SAndroid Build Coastguard Worker     // |request_local| and |requests_not_local|.
717*6777b538SAndroid Build Coastguard Worker     throughput_analyzer.IncrementBitsReceived(100 * 1000 * 8);
718*6777b538SAndroid Build Coastguard Worker 
719*6777b538SAndroid Build Coastguard Worker     for (const auto& request : requests_not_local) {
720*6777b538SAndroid Build Coastguard Worker       throughput_analyzer.NotifyRequestCompleted(*request);
721*6777b538SAndroid Build Coastguard Worker     }
722*6777b538SAndroid Build Coastguard Worker     if (test.start_local_request && !test.local_request_completes_first)
723*6777b538SAndroid Build Coastguard Worker       throughput_analyzer.NotifyRequestCompleted(*request_local);
724*6777b538SAndroid Build Coastguard Worker 
725*6777b538SAndroid Build Coastguard Worker     // Pump the message loop to let analyzer tasks get processed.
726*6777b538SAndroid Build Coastguard Worker     base::RunLoop().RunUntilIdle();
727*6777b538SAndroid Build Coastguard Worker 
728*6777b538SAndroid Build Coastguard Worker     int expected_throughput_observations =
729*6777b538SAndroid Build Coastguard Worker         test.expect_throughput_observation ? 1 : 0;
730*6777b538SAndroid Build Coastguard Worker     EXPECT_EQ(expected_throughput_observations,
731*6777b538SAndroid Build Coastguard Worker               throughput_analyzer.throughput_observations_received());
732*6777b538SAndroid Build Coastguard Worker   }
733*6777b538SAndroid Build Coastguard Worker }
734*6777b538SAndroid Build Coastguard Worker 
735*6777b538SAndroid Build Coastguard Worker // Tests if the throughput observation is taken correctly when two network
736*6777b538SAndroid Build Coastguard Worker // requests overlap.
TEST_F(ThroughputAnalyzerTest,TestThroughputWithNetworkRequestsOverlap)737*6777b538SAndroid Build Coastguard Worker TEST_F(ThroughputAnalyzerTest, TestThroughputWithNetworkRequestsOverlap) {
738*6777b538SAndroid Build Coastguard Worker   static const struct {
739*6777b538SAndroid Build Coastguard Worker     size_t throughput_min_requests_in_flight;
740*6777b538SAndroid Build Coastguard Worker     size_t number_requests_in_flight;
741*6777b538SAndroid Build Coastguard Worker     int64_t increment_bits;
742*6777b538SAndroid Build Coastguard Worker     bool expect_throughput_observation;
743*6777b538SAndroid Build Coastguard Worker   } tests[] = {
744*6777b538SAndroid Build Coastguard Worker       {
745*6777b538SAndroid Build Coastguard Worker           1, 2, 100 * 1000 * 8, true,
746*6777b538SAndroid Build Coastguard Worker       },
747*6777b538SAndroid Build Coastguard Worker       {
748*6777b538SAndroid Build Coastguard Worker           3, 1, 100 * 1000 * 8, false,
749*6777b538SAndroid Build Coastguard Worker       },
750*6777b538SAndroid Build Coastguard Worker       {
751*6777b538SAndroid Build Coastguard Worker           3, 2, 100 * 1000 * 8, false,
752*6777b538SAndroid Build Coastguard Worker       },
753*6777b538SAndroid Build Coastguard Worker       {
754*6777b538SAndroid Build Coastguard Worker           3, 3, 100 * 1000 * 8, true,
755*6777b538SAndroid Build Coastguard Worker       },
756*6777b538SAndroid Build Coastguard Worker       {
757*6777b538SAndroid Build Coastguard Worker           3, 4, 100 * 1000 * 8, true,
758*6777b538SAndroid Build Coastguard Worker       },
759*6777b538SAndroid Build Coastguard Worker       {
760*6777b538SAndroid Build Coastguard Worker           1, 2, 1, false,
761*6777b538SAndroid Build Coastguard Worker       },
762*6777b538SAndroid Build Coastguard Worker   };
763*6777b538SAndroid Build Coastguard Worker 
764*6777b538SAndroid Build Coastguard Worker   for (const auto& test : tests) {
765*6777b538SAndroid Build Coastguard Worker     const base::TickClock* tick_clock = base::DefaultTickClock::GetInstance();
766*6777b538SAndroid Build Coastguard Worker     TestNetworkQualityEstimator network_quality_estimator;
767*6777b538SAndroid Build Coastguard Worker     // Localhost requests are not allowed for estimation purposes.
768*6777b538SAndroid Build Coastguard Worker     std::map<std::string, std::string> variation_params;
769*6777b538SAndroid Build Coastguard Worker     variation_params["throughput_min_requests_in_flight"] =
770*6777b538SAndroid Build Coastguard Worker         base::NumberToString(test.throughput_min_requests_in_flight);
771*6777b538SAndroid Build Coastguard Worker     variation_params["throughput_hanging_requests_cwnd_size_multiplier"] = "-1";
772*6777b538SAndroid Build Coastguard Worker     NetworkQualityEstimatorParams params(variation_params);
773*6777b538SAndroid Build Coastguard Worker     // Set HTTP RTT to a large value so that the throughput observation window
774*6777b538SAndroid Build Coastguard Worker     // is not detected as hanging. In practice, this would be provided by
775*6777b538SAndroid Build Coastguard Worker     // |network_quality_estimator| based on the recent observations.
776*6777b538SAndroid Build Coastguard Worker     network_quality_estimator.SetStartTimeNullHttpRtt(base::Seconds(100));
777*6777b538SAndroid Build Coastguard Worker 
778*6777b538SAndroid Build Coastguard Worker     TestThroughputAnalyzer throughput_analyzer(&network_quality_estimator,
779*6777b538SAndroid Build Coastguard Worker                                                &params, tick_clock);
780*6777b538SAndroid Build Coastguard Worker     auto context_builder = CreateTestURLRequestContextBuilder();
781*6777b538SAndroid Build Coastguard Worker     context_builder->set_host_resolver(CreateMockHostResolver());
782*6777b538SAndroid Build Coastguard Worker     auto context = context_builder->Build();
783*6777b538SAndroid Build Coastguard Worker 
784*6777b538SAndroid Build Coastguard Worker     EXPECT_EQ(0, throughput_analyzer.throughput_observations_received());
785*6777b538SAndroid Build Coastguard Worker 
786*6777b538SAndroid Build Coastguard Worker     // TestDelegates must be before URLRequests that point to them.
787*6777b538SAndroid Build Coastguard Worker     std::vector<TestDelegate> in_flight_test_delegates(
788*6777b538SAndroid Build Coastguard Worker         test.number_requests_in_flight);
789*6777b538SAndroid Build Coastguard Worker     std::vector<std::unique_ptr<URLRequest>> requests_in_flight;
790*6777b538SAndroid Build Coastguard Worker     for (size_t i = 0; i < test.number_requests_in_flight; ++i) {
791*6777b538SAndroid Build Coastguard Worker       // We don't care about completion, except for the first one (see below).
792*6777b538SAndroid Build Coastguard Worker       in_flight_test_delegates[i].set_on_complete(base::DoNothing());
793*6777b538SAndroid Build Coastguard Worker       std::unique_ptr<URLRequest> request_network_1 = context->CreateRequest(
794*6777b538SAndroid Build Coastguard Worker           GURL("http://example.com/echo.html"), DEFAULT_PRIORITY,
795*6777b538SAndroid Build Coastguard Worker           &in_flight_test_delegates[i], TRAFFIC_ANNOTATION_FOR_TESTS);
796*6777b538SAndroid Build Coastguard Worker       requests_in_flight.push_back(std::move(request_network_1));
797*6777b538SAndroid Build Coastguard Worker       requests_in_flight.back()->Start();
798*6777b538SAndroid Build Coastguard Worker     }
799*6777b538SAndroid Build Coastguard Worker 
800*6777b538SAndroid Build Coastguard Worker     in_flight_test_delegates[0].RunUntilComplete();
801*6777b538SAndroid Build Coastguard Worker 
802*6777b538SAndroid Build Coastguard Worker     EXPECT_EQ(0, throughput_analyzer.throughput_observations_received());
803*6777b538SAndroid Build Coastguard Worker 
804*6777b538SAndroid Build Coastguard Worker     for (size_t i = 0; i < test.number_requests_in_flight; ++i) {
805*6777b538SAndroid Build Coastguard Worker       URLRequest* request = requests_in_flight.at(i).get();
806*6777b538SAndroid Build Coastguard Worker       throughput_analyzer.NotifyStartTransaction(*request);
807*6777b538SAndroid Build Coastguard Worker     }
808*6777b538SAndroid Build Coastguard Worker 
809*6777b538SAndroid Build Coastguard Worker     // Increment the bytes received count to emulate the bytes received for
810*6777b538SAndroid Build Coastguard Worker     // |request_network_1| and |request_network_2|.
811*6777b538SAndroid Build Coastguard Worker     throughput_analyzer.IncrementBitsReceived(test.increment_bits);
812*6777b538SAndroid Build Coastguard Worker 
813*6777b538SAndroid Build Coastguard Worker     for (size_t i = 0; i < test.number_requests_in_flight; ++i) {
814*6777b538SAndroid Build Coastguard Worker       URLRequest* request = requests_in_flight.at(i).get();
815*6777b538SAndroid Build Coastguard Worker       throughput_analyzer.NotifyRequestCompleted(*request);
816*6777b538SAndroid Build Coastguard Worker     }
817*6777b538SAndroid Build Coastguard Worker 
818*6777b538SAndroid Build Coastguard Worker     base::RunLoop().RunUntilIdle();
819*6777b538SAndroid Build Coastguard Worker 
820*6777b538SAndroid Build Coastguard Worker     // Only one observation should be taken since two requests overlap.
821*6777b538SAndroid Build Coastguard Worker     if (test.expect_throughput_observation) {
822*6777b538SAndroid Build Coastguard Worker       EXPECT_EQ(1, throughput_analyzer.throughput_observations_received());
823*6777b538SAndroid Build Coastguard Worker     } else {
824*6777b538SAndroid Build Coastguard Worker       EXPECT_EQ(0, throughput_analyzer.throughput_observations_received());
825*6777b538SAndroid Build Coastguard Worker     }
826*6777b538SAndroid Build Coastguard Worker   }
827*6777b538SAndroid Build Coastguard Worker }
828*6777b538SAndroid Build Coastguard Worker 
829*6777b538SAndroid Build Coastguard Worker // Tests if the throughput observation is taken correctly when the start and end
830*6777b538SAndroid Build Coastguard Worker // of network requests overlap, and the minimum number of in flight requests
831*6777b538SAndroid Build Coastguard Worker // when taking an observation is more than 1.
TEST_F(ThroughputAnalyzerTest,TestThroughputWithMultipleNetworkRequests)832*6777b538SAndroid Build Coastguard Worker TEST_F(ThroughputAnalyzerTest, TestThroughputWithMultipleNetworkRequests) {
833*6777b538SAndroid Build Coastguard Worker   const base::test::ScopedRunLoopTimeout increased_run_timeout(
834*6777b538SAndroid Build Coastguard Worker       FROM_HERE, TestTimeouts::action_max_timeout());
835*6777b538SAndroid Build Coastguard Worker 
836*6777b538SAndroid Build Coastguard Worker   const base::TickClock* tick_clock = base::DefaultTickClock::GetInstance();
837*6777b538SAndroid Build Coastguard Worker   TestNetworkQualityEstimator network_quality_estimator;
838*6777b538SAndroid Build Coastguard Worker   std::map<std::string, std::string> variation_params;
839*6777b538SAndroid Build Coastguard Worker   variation_params["throughput_min_requests_in_flight"] = "3";
840*6777b538SAndroid Build Coastguard Worker   variation_params["throughput_hanging_requests_cwnd_size_multiplier"] = "-1";
841*6777b538SAndroid Build Coastguard Worker   NetworkQualityEstimatorParams params(variation_params);
842*6777b538SAndroid Build Coastguard Worker   // Set HTTP RTT to a large value so that the throughput observation window
843*6777b538SAndroid Build Coastguard Worker   // is not detected as hanging. In practice, this would be provided by
844*6777b538SAndroid Build Coastguard Worker   // |network_quality_estimator| based on the recent observations.
845*6777b538SAndroid Build Coastguard Worker   network_quality_estimator.SetStartTimeNullHttpRtt(base::Seconds(100));
846*6777b538SAndroid Build Coastguard Worker 
847*6777b538SAndroid Build Coastguard Worker   TestThroughputAnalyzer throughput_analyzer(&network_quality_estimator,
848*6777b538SAndroid Build Coastguard Worker                                              &params, tick_clock);
849*6777b538SAndroid Build Coastguard Worker   TestDelegate test_delegate;
850*6777b538SAndroid Build Coastguard Worker   auto context_builder = CreateTestURLRequestContextBuilder();
851*6777b538SAndroid Build Coastguard Worker   context_builder->set_host_resolver(CreateMockHostResolver());
852*6777b538SAndroid Build Coastguard Worker   auto context = context_builder->Build();
853*6777b538SAndroid Build Coastguard Worker 
854*6777b538SAndroid Build Coastguard Worker   EXPECT_EQ(0, throughput_analyzer.throughput_observations_received());
855*6777b538SAndroid Build Coastguard Worker 
856*6777b538SAndroid Build Coastguard Worker   std::unique_ptr<URLRequest> request_1 = context->CreateRequest(
857*6777b538SAndroid Build Coastguard Worker       GURL("http://example.com/echo.html"), DEFAULT_PRIORITY, &test_delegate,
858*6777b538SAndroid Build Coastguard Worker       TRAFFIC_ANNOTATION_FOR_TESTS);
859*6777b538SAndroid Build Coastguard Worker   std::unique_ptr<URLRequest> request_2 = context->CreateRequest(
860*6777b538SAndroid Build Coastguard Worker       GURL("http://example.com/echo.html"), DEFAULT_PRIORITY, &test_delegate,
861*6777b538SAndroid Build Coastguard Worker       TRAFFIC_ANNOTATION_FOR_TESTS);
862*6777b538SAndroid Build Coastguard Worker   std::unique_ptr<URLRequest> request_3 = context->CreateRequest(
863*6777b538SAndroid Build Coastguard Worker       GURL("http://example.com/echo.html"), DEFAULT_PRIORITY, &test_delegate,
864*6777b538SAndroid Build Coastguard Worker       TRAFFIC_ANNOTATION_FOR_TESTS);
865*6777b538SAndroid Build Coastguard Worker   std::unique_ptr<URLRequest> request_4 = context->CreateRequest(
866*6777b538SAndroid Build Coastguard Worker       GURL("http://example.com/echo.html"), DEFAULT_PRIORITY, &test_delegate,
867*6777b538SAndroid Build Coastguard Worker       TRAFFIC_ANNOTATION_FOR_TESTS);
868*6777b538SAndroid Build Coastguard Worker 
869*6777b538SAndroid Build Coastguard Worker   request_1->Start();
870*6777b538SAndroid Build Coastguard Worker   request_2->Start();
871*6777b538SAndroid Build Coastguard Worker   request_3->Start();
872*6777b538SAndroid Build Coastguard Worker   request_4->Start();
873*6777b538SAndroid Build Coastguard Worker 
874*6777b538SAndroid Build Coastguard Worker   // We dispatched four requests, so wait for four completions.
875*6777b538SAndroid Build Coastguard Worker   for (int i = 0; i < 4; ++i)
876*6777b538SAndroid Build Coastguard Worker     test_delegate.RunUntilComplete();
877*6777b538SAndroid Build Coastguard Worker 
878*6777b538SAndroid Build Coastguard Worker   EXPECT_EQ(0, throughput_analyzer.throughput_observations_received());
879*6777b538SAndroid Build Coastguard Worker 
880*6777b538SAndroid Build Coastguard Worker   throughput_analyzer.NotifyStartTransaction(*(request_1.get()));
881*6777b538SAndroid Build Coastguard Worker   throughput_analyzer.NotifyStartTransaction(*(request_2.get()));
882*6777b538SAndroid Build Coastguard Worker 
883*6777b538SAndroid Build Coastguard Worker   const size_t increment_bits = 100 * 1000 * 8;
884*6777b538SAndroid Build Coastguard Worker 
885*6777b538SAndroid Build Coastguard Worker   // Increment the bytes received count to emulate the bytes received for
886*6777b538SAndroid Build Coastguard Worker   // |request_1| and |request_2|.
887*6777b538SAndroid Build Coastguard Worker   throughput_analyzer.IncrementBitsReceived(increment_bits);
888*6777b538SAndroid Build Coastguard Worker 
889*6777b538SAndroid Build Coastguard Worker   throughput_analyzer.NotifyRequestCompleted(*(request_1.get()));
890*6777b538SAndroid Build Coastguard Worker   base::RunLoop().RunUntilIdle();
891*6777b538SAndroid Build Coastguard Worker 
892*6777b538SAndroid Build Coastguard Worker   // No observation should be taken since only 1 request is in flight.
893*6777b538SAndroid Build Coastguard Worker   EXPECT_EQ(0, throughput_analyzer.throughput_observations_received());
894*6777b538SAndroid Build Coastguard Worker 
895*6777b538SAndroid Build Coastguard Worker   throughput_analyzer.NotifyStartTransaction(*(request_3.get()));
896*6777b538SAndroid Build Coastguard Worker   throughput_analyzer.NotifyStartTransaction(*(request_4.get()));
897*6777b538SAndroid Build Coastguard Worker   EXPECT_EQ(0, throughput_analyzer.throughput_observations_received());
898*6777b538SAndroid Build Coastguard Worker 
899*6777b538SAndroid Build Coastguard Worker   // 3 requests are in flight which is at least as many as the minimum number of
900*6777b538SAndroid Build Coastguard Worker   // in flight requests required. An observation should be taken.
901*6777b538SAndroid Build Coastguard Worker   throughput_analyzer.IncrementBitsReceived(increment_bits);
902*6777b538SAndroid Build Coastguard Worker 
903*6777b538SAndroid Build Coastguard Worker   // Only one observation should be taken since two requests overlap.
904*6777b538SAndroid Build Coastguard Worker   throughput_analyzer.NotifyRequestCompleted(*(request_2.get()));
905*6777b538SAndroid Build Coastguard Worker   base::RunLoop().RunUntilIdle();
906*6777b538SAndroid Build Coastguard Worker 
907*6777b538SAndroid Build Coastguard Worker   EXPECT_EQ(1, throughput_analyzer.throughput_observations_received());
908*6777b538SAndroid Build Coastguard Worker   throughput_analyzer.NotifyRequestCompleted(*(request_3.get()));
909*6777b538SAndroid Build Coastguard Worker   throughput_analyzer.NotifyRequestCompleted(*(request_4.get()));
910*6777b538SAndroid Build Coastguard Worker   EXPECT_EQ(1, throughput_analyzer.throughput_observations_received());
911*6777b538SAndroid Build Coastguard Worker }
912*6777b538SAndroid Build Coastguard Worker 
TEST_F(ThroughputAnalyzerTest,TestHangingWindow)913*6777b538SAndroid Build Coastguard Worker TEST_F(ThroughputAnalyzerTest, TestHangingWindow) {
914*6777b538SAndroid Build Coastguard Worker   static constexpr size_t kCwndSizeKilobytes = 10 * 1.5;
915*6777b538SAndroid Build Coastguard Worker   static constexpr size_t kCwndSizeBits = kCwndSizeKilobytes * 1000 * 8;
916*6777b538SAndroid Build Coastguard Worker 
917*6777b538SAndroid Build Coastguard Worker   base::SimpleTestTickClock tick_clock;
918*6777b538SAndroid Build Coastguard Worker 
919*6777b538SAndroid Build Coastguard Worker   TestNetworkQualityEstimator network_quality_estimator;
920*6777b538SAndroid Build Coastguard Worker   int64_t http_rtt_msec = 1000;
921*6777b538SAndroid Build Coastguard Worker   network_quality_estimator.SetStartTimeNullHttpRtt(
922*6777b538SAndroid Build Coastguard Worker       base::Milliseconds(http_rtt_msec));
923*6777b538SAndroid Build Coastguard Worker   std::map<std::string, std::string> variation_params;
924*6777b538SAndroid Build Coastguard Worker   variation_params["throughput_hanging_requests_cwnd_size_multiplier"] = "1";
925*6777b538SAndroid Build Coastguard Worker   NetworkQualityEstimatorParams params(variation_params);
926*6777b538SAndroid Build Coastguard Worker 
927*6777b538SAndroid Build Coastguard Worker   TestThroughputAnalyzer throughput_analyzer(&network_quality_estimator,
928*6777b538SAndroid Build Coastguard Worker                                              &params, &tick_clock);
929*6777b538SAndroid Build Coastguard Worker 
930*6777b538SAndroid Build Coastguard Worker   const struct {
931*6777b538SAndroid Build Coastguard Worker     size_t bits_received;
932*6777b538SAndroid Build Coastguard Worker     base::TimeDelta window_duration;
933*6777b538SAndroid Build Coastguard Worker     bool expected_hanging;
934*6777b538SAndroid Build Coastguard Worker   } tests[] = {
935*6777b538SAndroid Build Coastguard Worker       {100, base::Milliseconds(http_rtt_msec), true},
936*6777b538SAndroid Build Coastguard Worker       {kCwndSizeBits - 1, base::Milliseconds(http_rtt_msec), true},
937*6777b538SAndroid Build Coastguard Worker       {kCwndSizeBits + 1, base::Milliseconds(http_rtt_msec), false},
938*6777b538SAndroid Build Coastguard Worker       {2 * (kCwndSizeBits - 1), base::Milliseconds(http_rtt_msec * 2), true},
939*6777b538SAndroid Build Coastguard Worker       {2 * (kCwndSizeBits + 1), base::Milliseconds(http_rtt_msec * 2), false},
940*6777b538SAndroid Build Coastguard Worker       {kCwndSizeBits / 2 - 1, base::Milliseconds(http_rtt_msec / 2), true},
941*6777b538SAndroid Build Coastguard Worker       {kCwndSizeBits / 2 + 1, base::Milliseconds(http_rtt_msec / 2), false},
942*6777b538SAndroid Build Coastguard Worker   };
943*6777b538SAndroid Build Coastguard Worker 
944*6777b538SAndroid Build Coastguard Worker   for (const auto& test : tests) {
945*6777b538SAndroid Build Coastguard Worker     base::HistogramTester histogram_tester;
946*6777b538SAndroid Build Coastguard Worker     EXPECT_EQ(test.expected_hanging,
947*6777b538SAndroid Build Coastguard Worker               throughput_analyzer.IsHangingWindow(test.bits_received,
948*6777b538SAndroid Build Coastguard Worker                                                   test.window_duration));
949*6777b538SAndroid Build Coastguard Worker   }
950*6777b538SAndroid Build Coastguard Worker }
951*6777b538SAndroid Build Coastguard Worker 
952*6777b538SAndroid Build Coastguard Worker }  // namespace
953*6777b538SAndroid Build Coastguard Worker 
954*6777b538SAndroid Build Coastguard Worker }  // namespace net::nqe
955