1 // Copyright 2016 The Chromium Authors
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "net/nqe/network_quality_estimator_test_util.h"
6
7 #include "base/files/file_path.h"
8 #include "base/run_loop.h"
9 #include "net/base/load_flags.h"
10 #include "net/log/net_log.h"
11 #include "net/log/net_log_with_source.h"
12 #include "net/log/test_net_log_util.h"
13 #include "net/nqe/network_quality_estimator_params.h"
14 #include "net/test/embedded_test_server/http_response.h"
15 #include "net/traffic_annotation/network_traffic_annotation_test_helper.h"
16 #include "net/url_request/url_request.h"
17 #include "net/url_request/url_request_context.h"
18 #include "net/url_request/url_request_context_builder.h"
19 #include "net/url_request/url_request_test_util.h"
20
21 namespace {
22
23 const base::FilePath::CharType kTestFilePath[] =
24 FILE_PATH_LITERAL("net/data/url_request_unittest");
25
26 } // namespace
27
28 namespace net {
29
TestNetworkQualityEstimator()30 TestNetworkQualityEstimator::TestNetworkQualityEstimator()
31 : TestNetworkQualityEstimator(std::map<std::string, std::string>()) {}
32
TestNetworkQualityEstimator(const std::map<std::string,std::string> & variation_params)33 TestNetworkQualityEstimator::TestNetworkQualityEstimator(
34 const std::map<std::string, std::string>& variation_params)
35 : TestNetworkQualityEstimator(variation_params, true, true) {}
36
TestNetworkQualityEstimator(const std::map<std::string,std::string> & variation_params,bool allow_local_host_requests_for_tests,bool allow_smaller_responses_for_tests)37 TestNetworkQualityEstimator::TestNetworkQualityEstimator(
38 const std::map<std::string, std::string>& variation_params,
39 bool allow_local_host_requests_for_tests,
40 bool allow_smaller_responses_for_tests)
41 : TestNetworkQualityEstimator(variation_params,
42 allow_local_host_requests_for_tests,
43 allow_smaller_responses_for_tests,
44 false) {}
45
TestNetworkQualityEstimator(const std::map<std::string,std::string> & variation_params,bool allow_local_host_requests_for_tests,bool allow_smaller_responses_for_tests,bool suppress_notifications_for_testing)46 TestNetworkQualityEstimator::TestNetworkQualityEstimator(
47 const std::map<std::string, std::string>& variation_params,
48 bool allow_local_host_requests_for_tests,
49 bool allow_smaller_responses_for_tests,
50 bool suppress_notifications_for_testing)
51 : NetworkQualityEstimator(
52 std::make_unique<NetworkQualityEstimatorParams>(variation_params),
53 NetLog::Get()),
54 embedded_test_server_(base::FilePath(kTestFilePath)),
55 suppress_notifications_for_testing_(suppress_notifications_for_testing) {
56 SetUseLocalHostRequestsForTesting(allow_local_host_requests_for_tests);
57 SetUseSmallResponsesForTesting(allow_smaller_responses_for_tests);
58 }
59
TestNetworkQualityEstimator(std::unique_ptr<NetworkQualityEstimatorParams> params)60 TestNetworkQualityEstimator::TestNetworkQualityEstimator(
61 std::unique_ptr<NetworkQualityEstimatorParams> params)
62 : NetworkQualityEstimator(std::move(params), NetLog::Get()),
63 embedded_test_server_(base::FilePath(kTestFilePath)),
64 suppress_notifications_for_testing_(false) {}
65
66 TestNetworkQualityEstimator::~TestNetworkQualityEstimator() = default;
67
RunOneRequest()68 void TestNetworkQualityEstimator::RunOneRequest() {
69 // Set up the embedded test server.
70 if (!embedded_test_server_.Started()) {
71 EXPECT_TRUE(embedded_test_server_.Start());
72 }
73
74 TestDelegate test_delegate;
75 auto builder = CreateTestURLRequestContextBuilder();
76 builder->set_network_quality_estimator(this);
77 auto context = builder->Build();
78 std::unique_ptr<URLRequest> request(
79 context->CreateRequest(GetEchoURL(), DEFAULT_PRIORITY, &test_delegate,
80 TRAFFIC_ANNOTATION_FOR_TESTS));
81 request->SetLoadFlags(request->load_flags() | LOAD_MAIN_FRAME_DEPRECATED);
82 request->Start();
83 base::RunLoop().Run();
84 }
85
SimulateNetworkChange(NetworkChangeNotifier::ConnectionType new_connection_type,const std::string & network_id)86 void TestNetworkQualityEstimator::SimulateNetworkChange(
87 NetworkChangeNotifier::ConnectionType new_connection_type,
88 const std::string& network_id) {
89 current_network_type_ = new_connection_type;
90 current_network_id_ = network_id;
91 OnConnectionTypeChanged(new_connection_type);
92 }
93
GetEchoURL()94 const GURL TestNetworkQualityEstimator::GetEchoURL() {
95 // Set up the embedded test server.
96 if (!embedded_test_server_.Started()) {
97 EXPECT_TRUE(embedded_test_server_.Start());
98 }
99 return embedded_test_server_.GetURL("/simple.html");
100 }
101
GetRedirectURL()102 const GURL TestNetworkQualityEstimator::GetRedirectURL() {
103 // Set up the embedded test server.
104 if (!embedded_test_server_.Started()) {
105 EXPECT_TRUE(embedded_test_server_.Start());
106 }
107 return embedded_test_server_.GetURL("/redirect302-to-https");
108 }
109
110 EffectiveConnectionType
GetEffectiveConnectionType() const111 TestNetworkQualityEstimator::GetEffectiveConnectionType() const {
112 if (effective_connection_type_)
113 return effective_connection_type_.value();
114 return NetworkQualityEstimator::GetEffectiveConnectionType();
115 }
116
117 EffectiveConnectionType
GetRecentEffectiveConnectionTypeUsingMetrics(base::TimeDelta * http_rtt,base::TimeDelta * transport_rtt,base::TimeDelta * end_to_end_rtt,int32_t * downstream_throughput_kbps,size_t * observations_count,size_t * end_to_end_rtt_observation_count) const118 TestNetworkQualityEstimator::GetRecentEffectiveConnectionTypeUsingMetrics(
119 base::TimeDelta* http_rtt,
120 base::TimeDelta* transport_rtt,
121 base::TimeDelta* end_to_end_rtt,
122 int32_t* downstream_throughput_kbps,
123 size_t* observations_count,
124 size_t* end_to_end_rtt_observation_count) const {
125 if (recent_effective_connection_type_) {
126 GetRecentRTT(nqe::internal::OBSERVATION_CATEGORY_HTTP, base::TimeTicks(),
127 http_rtt, nullptr);
128 GetRecentRTT(nqe::internal::OBSERVATION_CATEGORY_TRANSPORT,
129 base::TimeTicks(), transport_rtt, observations_count);
130 GetRecentDownlinkThroughputKbps(base::TimeTicks(),
131 downstream_throughput_kbps);
132 return recent_effective_connection_type_.value();
133 }
134 return NetworkQualityEstimator::GetRecentEffectiveConnectionTypeUsingMetrics(
135 http_rtt, transport_rtt, end_to_end_rtt, downstream_throughput_kbps,
136 observations_count, end_to_end_rtt_observation_count);
137 }
138
GetRecentRTT(nqe::internal::ObservationCategory observation_category,const base::TimeTicks & start_time,base::TimeDelta * rtt,size_t * observations_count) const139 bool TestNetworkQualityEstimator::GetRecentRTT(
140 nqe::internal::ObservationCategory observation_category,
141 const base::TimeTicks& start_time,
142 base::TimeDelta* rtt,
143 size_t* observations_count) const {
144 switch (observation_category) {
145 case nqe::internal::OBSERVATION_CATEGORY_HTTP:
146
147 if (start_time.is_null()) {
148 if (start_time_null_http_rtt_) {
149 *rtt = start_time_null_http_rtt_.value();
150 return true;
151 }
152 return NetworkQualityEstimator::GetRecentRTT(
153 observation_category, start_time, rtt, observations_count);
154 }
155 if (recent_http_rtt_) {
156 *rtt = recent_http_rtt_.value();
157 return true;
158 }
159 break;
160
161 case nqe::internal::OBSERVATION_CATEGORY_TRANSPORT:
162 if (start_time.is_null()) {
163 if (start_time_null_transport_rtt_) {
164 *rtt = start_time_null_transport_rtt_.value();
165 if (transport_rtt_observation_count_last_ect_computation_) {
166 *observations_count =
167 transport_rtt_observation_count_last_ect_computation_.value();
168 }
169 return true;
170 }
171 return NetworkQualityEstimator::GetRecentRTT(
172 observation_category, start_time, rtt, observations_count);
173 }
174
175 if (recent_transport_rtt_) {
176 *rtt = recent_transport_rtt_.value();
177 return true;
178 }
179 break;
180 case nqe::internal::OBSERVATION_CATEGORY_END_TO_END:
181 if (start_time_null_end_to_end_rtt_) {
182 *rtt = start_time_null_end_to_end_rtt_.value();
183 return true;
184 }
185 break;
186 case nqe::internal::OBSERVATION_CATEGORY_COUNT:
187 NOTREACHED();
188 }
189
190 return NetworkQualityEstimator::GetRecentRTT(observation_category, start_time,
191 rtt, observations_count);
192 }
193
GetTransportRTT() const194 absl::optional<base::TimeDelta> TestNetworkQualityEstimator::GetTransportRTT()
195 const {
196 if (start_time_null_transport_rtt_)
197 return start_time_null_transport_rtt_;
198 return NetworkQualityEstimator::GetTransportRTT();
199 }
200
GetRecentDownlinkThroughputKbps(const base::TimeTicks & start_time,int32_t * kbps) const201 bool TestNetworkQualityEstimator::GetRecentDownlinkThroughputKbps(
202 const base::TimeTicks& start_time,
203 int32_t* kbps) const {
204 if (start_time.is_null()) {
205 if (start_time_null_downlink_throughput_kbps_) {
206 *kbps = start_time_null_downlink_throughput_kbps_.value();
207 return true;
208 }
209 return NetworkQualityEstimator::GetRecentDownlinkThroughputKbps(start_time,
210 kbps);
211 }
212
213 if (recent_downlink_throughput_kbps_) {
214 *kbps = recent_downlink_throughput_kbps_.value();
215 return true;
216 }
217 return NetworkQualityEstimator::GetRecentDownlinkThroughputKbps(start_time,
218 kbps);
219 }
220
GetRTTEstimateInternal(base::TimeTicks start_time,nqe::internal::ObservationCategory observation_category,int percentile,size_t * observations_count) const221 base::TimeDelta TestNetworkQualityEstimator::GetRTTEstimateInternal(
222 base::TimeTicks start_time,
223 nqe::internal::ObservationCategory observation_category,
224 int percentile,
225 size_t* observations_count) const {
226 if (rtt_estimate_internal_)
227 return rtt_estimate_internal_.value();
228
229 return NetworkQualityEstimator::GetRTTEstimateInternal(
230 start_time, observation_category, percentile, observations_count);
231 }
232
GetEntriesCount(NetLogEventType type) const233 int TestNetworkQualityEstimator::GetEntriesCount(NetLogEventType type) const {
234 return net_log_observer_.GetEntriesWithType(type).size();
235 }
236
GetNetLogLastStringValue(NetLogEventType type,const std::string & key) const237 std::string TestNetworkQualityEstimator::GetNetLogLastStringValue(
238 NetLogEventType type,
239 const std::string& key) const {
240 auto entries = net_log_observer_.GetEntries();
241
242 for (int i = entries.size() - 1; i >= 0; --i) {
243 if (entries[i].type == type) {
244 auto value = GetOptionalStringValueFromParams(entries[i], key);
245 if (value)
246 return *value;
247 }
248 }
249 return std::string();
250 }
251
GetNetLogLastIntegerValue(NetLogEventType type,const std::string & key) const252 int TestNetworkQualityEstimator::GetNetLogLastIntegerValue(
253 NetLogEventType type,
254 const std::string& key) const {
255 auto entries = net_log_observer_.GetEntries();
256
257 for (int i = entries.size() - 1; i >= 0; --i) {
258 if (entries[i].type == type) {
259 auto value = GetOptionalIntegerValueFromParams(entries[i], key);
260 if (value)
261 return *value;
262 }
263 }
264 return 0;
265 }
266
267 void TestNetworkQualityEstimator::
NotifyObserversOfRTTOrThroughputEstimatesComputed(const net::nqe::internal::NetworkQuality & network_quality)268 NotifyObserversOfRTTOrThroughputEstimatesComputed(
269 const net::nqe::internal::NetworkQuality& network_quality) {
270 for (auto& observer : rtt_and_throughput_estimates_observer_list_) {
271 observer.OnRTTOrThroughputEstimatesComputed(
272 network_quality.http_rtt(), network_quality.transport_rtt(),
273 network_quality.downstream_throughput_kbps());
274 }
275 }
276
277 void TestNetworkQualityEstimator::
SetAndNotifyObserversOfEffectiveConnectionType(EffectiveConnectionType type)278 SetAndNotifyObserversOfEffectiveConnectionType(
279 EffectiveConnectionType type) {
280 set_effective_connection_type(type);
281 for (auto& observer : effective_connection_type_observer_list_)
282 observer.OnEffectiveConnectionTypeChanged(type);
283 }
284
285 absl::optional<net::EffectiveConnectionType>
GetOverrideECT() const286 TestNetworkQualityEstimator::GetOverrideECT() const {
287 return effective_connection_type_;
288 }
289
290 void TestNetworkQualityEstimator::
SetAndNotifyObserversOfP2PActiveConnectionsCountChange(uint32_t count)291 SetAndNotifyObserversOfP2PActiveConnectionsCountChange(uint32_t count) {
292 p2p_connections_count_ = count;
293 for (auto& observer : peer_to_peer_type_observer_list_)
294 observer.OnPeerToPeerConnectionsCountChange(count);
295 }
296
RecordSpdyPingLatency(const HostPortPair & host_port_pair,base::TimeDelta rtt)297 void TestNetworkQualityEstimator::RecordSpdyPingLatency(
298 const HostPortPair& host_port_pair,
299 base::TimeDelta rtt) {
300 ++ping_rtt_received_count_;
301 NetworkQualityEstimator::RecordSpdyPingLatency(host_port_pair, rtt);
302 }
303
params() const304 const NetworkQualityEstimatorParams* TestNetworkQualityEstimator::params()
305 const {
306 return params_.get();
307 }
308
GetCurrentNetworkID() const309 nqe::internal::NetworkID TestNetworkQualityEstimator::GetCurrentNetworkID()
310 const {
311 return nqe::internal::NetworkID(current_network_type_, current_network_id_,
312 INT32_MIN);
313 }
314
LocalHttpTestServer(const base::FilePath & document_root)315 TestNetworkQualityEstimator::LocalHttpTestServer::LocalHttpTestServer(
316 const base::FilePath& document_root) {
317 AddDefaultHandlers(document_root);
318 }
319
NotifyObserversOfRTTOrThroughputComputed() const320 void TestNetworkQualityEstimator::NotifyObserversOfRTTOrThroughputComputed()
321 const {
322 if (suppress_notifications_for_testing_)
323 return;
324
325 NetworkQualityEstimator::NotifyObserversOfRTTOrThroughputComputed();
326 }
327
328 void TestNetworkQualityEstimator::
NotifyRTTAndThroughputEstimatesObserverIfPresent(RTTAndThroughputEstimatesObserver * observer) const329 NotifyRTTAndThroughputEstimatesObserverIfPresent(
330 RTTAndThroughputEstimatesObserver* observer) const {
331 if (suppress_notifications_for_testing_)
332 return;
333
334 NetworkQualityEstimator::NotifyRTTAndThroughputEstimatesObserverIfPresent(
335 observer);
336 }
337
SetStartTimeNullHttpRtt(const base::TimeDelta http_rtt)338 void TestNetworkQualityEstimator::SetStartTimeNullHttpRtt(
339 const base::TimeDelta http_rtt) {
340 start_time_null_http_rtt_ = http_rtt;
341 // Force compute effective connection type so that the new RTT value is
342 // immediately picked up. This ensures that the next call to
343 // GetEffectiveConnectionType() returns the effective connnection type
344 // that was computed based on |http_rtt|.
345 ComputeEffectiveConnectionType();
346 }
347
SetStartTimeNullTransportRtt(const base::TimeDelta transport_rtt)348 void TestNetworkQualityEstimator::SetStartTimeNullTransportRtt(
349 const base::TimeDelta transport_rtt) {
350 start_time_null_transport_rtt_ = transport_rtt;
351 // Force compute effective connection type so that the new RTT value is
352 // immediately picked up. This ensures that the next call to
353 // GetEffectiveConnectionType() returns the effective connnection type
354 // that was computed based on |transport_rtt|.
355 ComputeEffectiveConnectionType();
356 }
357
358 } // namespace net
359