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 ¶ms, 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 ¶ms, 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 ¶ms, 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 ¶ms, 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 ¬_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 ¶ms, &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 ¶ms, &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 ¶ms, &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 ¶ms, 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 ¬_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 ¶ms, 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 ¶ms, 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 ¶ms, &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