OLD | NEW |
1 // Copyright 2016 The Chromium Authors. All rights reserved. | 1 // Copyright 2016 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "net/nqe/throughput_analyzer.h" | 5 #include "net/nqe/throughput_analyzer.h" |
6 | 6 |
7 #include <stdint.h> | 7 #include <stdint.h> |
8 | 8 |
9 #include <deque> | 9 #include <deque> |
| 10 #include <map> |
10 #include <memory> | 11 #include <memory> |
| 12 #include <string> |
11 | 13 |
12 #include "base/bind.h" | 14 #include "base/bind.h" |
13 #include "base/bind_helpers.h" | 15 #include "base/bind_helpers.h" |
14 #include "base/logging.h" | 16 #include "base/logging.h" |
15 #include "base/macros.h" | 17 #include "base/macros.h" |
16 #include "base/run_loop.h" | 18 #include "base/run_loop.h" |
17 #include "base/single_thread_task_runner.h" | 19 #include "base/single_thread_task_runner.h" |
| 20 #include "base/strings/string_number_conversions.h" |
18 #include "base/threading/thread_task_runner_handle.h" | 21 #include "base/threading/thread_task_runner_handle.h" |
19 #include "net/base/url_util.h" | 22 #include "net/base/url_util.h" |
| 23 #include "net/nqe/network_quality_estimator_params.h" |
20 #include "net/traffic_annotation/network_traffic_annotation_test_helper.h" | 24 #include "net/traffic_annotation/network_traffic_annotation_test_helper.h" |
21 #include "net/url_request/url_request.h" | 25 #include "net/url_request/url_request.h" |
22 #include "net/url_request/url_request_test_util.h" | 26 #include "net/url_request/url_request_test_util.h" |
23 #include "testing/gtest/include/gtest/gtest.h" | 27 #include "testing/gtest/include/gtest/gtest.h" |
24 | 28 |
25 namespace net { | 29 namespace net { |
26 | 30 |
27 namespace nqe { | 31 namespace nqe { |
28 | 32 |
29 namespace { | 33 namespace { |
30 | 34 |
31 class TestThroughputAnalyzer : public internal::ThroughputAnalyzer { | 35 class TestThroughputAnalyzer : public internal::ThroughputAnalyzer { |
32 public: | 36 public: |
33 TestThroughputAnalyzer() | 37 explicit TestThroughputAnalyzer( |
| 38 internal::NetworkQualityEstimatorParams* params) |
34 : internal::ThroughputAnalyzer( | 39 : internal::ThroughputAnalyzer( |
| 40 params, |
35 base::ThreadTaskRunnerHandle::Get(), | 41 base::ThreadTaskRunnerHandle::Get(), |
36 base::Bind( | 42 base::Bind( |
37 &TestThroughputAnalyzer::OnNewThroughputObservationAvailable, | 43 &TestThroughputAnalyzer::OnNewThroughputObservationAvailable, |
38 base::Unretained(this)), | 44 base::Unretained(this)), |
39 false, | 45 false, |
40 false), | 46 false), |
41 throughput_observations_received_(0), | 47 throughput_observations_received_(0), |
42 bits_received_(0) {} | 48 bits_received_(0) {} |
43 | 49 |
44 ~TestThroughputAnalyzer() override {} | 50 ~TestThroughputAnalyzer() override {} |
(...skipping 26 matching lines...) Expand all Loading... |
71 const struct { | 77 const struct { |
72 bool use_local_requests; | 78 bool use_local_requests; |
73 } tests[] = {{ | 79 } tests[] = {{ |
74 false, | 80 false, |
75 }, | 81 }, |
76 { | 82 { |
77 true, | 83 true, |
78 }}; | 84 }}; |
79 | 85 |
80 for (const auto& test : tests) { | 86 for (const auto& test : tests) { |
81 TestThroughputAnalyzer throughput_analyzer; | 87 std::map<std::string, std::string> variation_params; |
| 88 internal::NetworkQualityEstimatorParams params(variation_params); |
| 89 TestThroughputAnalyzer throughput_analyzer(¶ms); |
82 | 90 |
83 TestDelegate test_delegate; | 91 TestDelegate test_delegate; |
84 TestURLRequestContext context; | 92 TestURLRequestContext context; |
85 | 93 |
86 ASSERT_FALSE(throughput_analyzer.disable_throughput_measurements()); | 94 ASSERT_FALSE(throughput_analyzer.disable_throughput_measurements()); |
87 std::deque<std::unique_ptr<URLRequest>> requests; | 95 std::deque<std::unique_ptr<URLRequest>> requests; |
88 | 96 |
89 // Start more requests than the maximum number of requests that can be held | 97 // Start more requests than the maximum number of requests that can be held |
90 // in the memory. | 98 // in the memory. |
91 const std::string url = test.use_local_requests | 99 const std::string url = test.use_local_requests |
(...skipping 29 matching lines...) Expand all Loading... |
121 { | 129 { |
122 true, false, false, | 130 true, false, false, |
123 }, | 131 }, |
124 { | 132 { |
125 true, true, true, | 133 true, true, true, |
126 }, | 134 }, |
127 }; | 135 }; |
128 | 136 |
129 for (const auto& test : tests) { | 137 for (const auto& test : tests) { |
130 // Localhost requests are not allowed for estimation purposes. | 138 // Localhost requests are not allowed for estimation purposes. |
131 TestThroughputAnalyzer throughput_analyzer; | 139 std::map<std::string, std::string> variation_params; |
| 140 internal::NetworkQualityEstimatorParams params(variation_params); |
| 141 TestThroughputAnalyzer throughput_analyzer(¶ms); |
132 | 142 |
133 TestDelegate test_delegate; | 143 TestDelegate test_delegate; |
134 TestURLRequestContext context; | 144 TestURLRequestContext context; |
135 | 145 |
136 std::unique_ptr<URLRequest> request_local; | 146 std::unique_ptr<URLRequest> request_local; |
137 | 147 |
138 std::unique_ptr<URLRequest> request_not_local(context.CreateRequest( | 148 std::unique_ptr<URLRequest> request_not_local(context.CreateRequest( |
139 GURL("http://example.com/echo.html"), DEFAULT_PRIORITY, &test_delegate, | 149 GURL("http://example.com/echo.html"), DEFAULT_PRIORITY, &test_delegate, |
140 TRAFFIC_ANNOTATION_FOR_TESTS)); | 150 TRAFFIC_ANNOTATION_FOR_TESTS)); |
141 request_not_local->Start(); | 151 request_not_local->Start(); |
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
179 test.expect_throughput_observation ? 1 : 0; | 189 test.expect_throughput_observation ? 1 : 0; |
180 EXPECT_EQ(expected_throughput_observations, | 190 EXPECT_EQ(expected_throughput_observations, |
181 throughput_analyzer.throughput_observations_received()); | 191 throughput_analyzer.throughput_observations_received()); |
182 } | 192 } |
183 } | 193 } |
184 | 194 |
185 // Tests if the throughput observation is taken correctly when two network | 195 // Tests if the throughput observation is taken correctly when two network |
186 // requests overlap. | 196 // requests overlap. |
187 TEST(ThroughputAnalyzerTest, TestThroughputWithNetworkRequestsOverlap) { | 197 TEST(ThroughputAnalyzerTest, TestThroughputWithNetworkRequestsOverlap) { |
188 static const struct { | 198 static const struct { |
| 199 size_t throughput_min_requests_in_flight; |
| 200 size_t number_requests_in_flight; |
189 int64_t increment_bits; | 201 int64_t increment_bits; |
190 bool expect_throughput_observation; | 202 bool expect_throughput_observation; |
191 } tests[] = { | 203 } tests[] = { |
192 { | 204 { |
193 100 * 1000 * 8, true, | 205 1, 2, 100 * 1000 * 8, true, |
194 }, | 206 }, |
195 { | 207 { |
196 1, false, | 208 3, 1, 100 * 1000 * 8, false, |
| 209 }, |
| 210 { |
| 211 3, 2, 100 * 1000 * 8, false, |
| 212 }, |
| 213 { |
| 214 3, 3, 100 * 1000 * 8, true, |
| 215 }, |
| 216 { |
| 217 3, 4, 100 * 1000 * 8, true, |
| 218 }, |
| 219 { |
| 220 1, 2, 1, false, |
197 }, | 221 }, |
198 }; | 222 }; |
199 | 223 |
200 for (const auto& test : tests) { | 224 for (const auto& test : tests) { |
201 // Localhost requests are not allowed for estimation purposes. | 225 // Localhost requests are not allowed for estimation purposes. |
202 TestThroughputAnalyzer throughput_analyzer; | 226 std::map<std::string, std::string> variation_params; |
| 227 variation_params["throughput_min_requests_in_flight"] = |
| 228 base::IntToString(test.throughput_min_requests_in_flight); |
| 229 internal::NetworkQualityEstimatorParams params(variation_params); |
| 230 TestThroughputAnalyzer throughput_analyzer(¶ms); |
203 TestDelegate test_delegate; | 231 TestDelegate test_delegate; |
204 TestURLRequestContext context; | 232 TestURLRequestContext context; |
205 | 233 |
206 EXPECT_EQ(0, throughput_analyzer.throughput_observations_received()); | 234 EXPECT_EQ(0, throughput_analyzer.throughput_observations_received()); |
207 | 235 |
208 std::unique_ptr<URLRequest> request_network_1 = context.CreateRequest( | 236 std::vector<std::unique_ptr<URLRequest>> requests_in_flight; |
209 GURL("http://example.com/echo.html"), DEFAULT_PRIORITY, &test_delegate, | 237 |
210 TRAFFIC_ANNOTATION_FOR_TESTS); | 238 for (size_t i = 0; i < test.number_requests_in_flight; ++i) { |
211 std::unique_ptr<URLRequest> request_network_2 = context.CreateRequest( | 239 std::unique_ptr<URLRequest> request_network_1 = context.CreateRequest( |
212 GURL("http://example.com/echo.html"), DEFAULT_PRIORITY, &test_delegate, | 240 GURL("http://example.com/echo.html"), DEFAULT_PRIORITY, |
213 TRAFFIC_ANNOTATION_FOR_TESTS); | 241 &test_delegate, TRAFFIC_ANNOTATION_FOR_TESTS); |
214 request_network_1->Start(); | 242 requests_in_flight.push_back(std::move(request_network_1)); |
215 request_network_2->Start(); | 243 requests_in_flight.back()->Start(); |
| 244 } |
216 | 245 |
217 base::RunLoop().Run(); | 246 base::RunLoop().Run(); |
218 | 247 |
219 EXPECT_LE(0, throughput_analyzer.throughput_observations_received()); | 248 EXPECT_EQ(0, throughput_analyzer.throughput_observations_received()); |
220 | 249 |
221 throughput_analyzer.NotifyStartTransaction(*request_network_1); | 250 for (size_t i = 0; i < test.number_requests_in_flight; ++i) { |
222 throughput_analyzer.NotifyStartTransaction(*request_network_2); | 251 URLRequest* request = requests_in_flight.at(i).get(); |
| 252 throughput_analyzer.NotifyStartTransaction(*request); |
| 253 } |
223 | 254 |
224 // Increment the bytes received count to emulate the bytes received for | 255 // Increment the bytes received count to emulate the bytes received for |
225 // |request_network_1| and |request_network_2|. | 256 // |request_network_1| and |request_network_2|. |
226 throughput_analyzer.IncrementBitsReceived(test.increment_bits); | 257 throughput_analyzer.IncrementBitsReceived(test.increment_bits); |
227 | 258 |
228 throughput_analyzer.NotifyRequestCompleted(*request_network_1); | 259 for (size_t i = 0; i < test.number_requests_in_flight; ++i) { |
229 throughput_analyzer.NotifyRequestCompleted(*request_network_2); | 260 URLRequest* request = requests_in_flight.at(i).get(); |
| 261 throughput_analyzer.NotifyRequestCompleted(*request); |
| 262 } |
| 263 |
230 base::RunLoop().RunUntilIdle(); | 264 base::RunLoop().RunUntilIdle(); |
231 | 265 |
232 // Only one observation should be taken since two requests overlap. | 266 // Only one observation should be taken since two requests overlap. |
233 if (test.expect_throughput_observation) { | 267 if (test.expect_throughput_observation) { |
234 EXPECT_EQ(1, throughput_analyzer.throughput_observations_received()); | 268 EXPECT_EQ(1, throughput_analyzer.throughput_observations_received()); |
235 } else { | 269 } else { |
236 EXPECT_EQ(0, throughput_analyzer.throughput_observations_received()); | 270 EXPECT_EQ(0, throughput_analyzer.throughput_observations_received()); |
237 } | 271 } |
238 } | 272 } |
239 } | 273 } |
240 | 274 |
| 275 // Tests if the throughput observation is taken correctly when the start and end |
| 276 // of network requests overlap, and the minimum number of in flight requests |
| 277 // when taking an observation is more than 1. |
| 278 TEST(ThroughputAnalyzerTest, TestThroughputWithMultipleNetworkRequests) { |
| 279 std::map<std::string, std::string> variation_params; |
| 280 variation_params["throughput_min_requests_in_flight"] = "3"; |
| 281 internal::NetworkQualityEstimatorParams params(variation_params); |
| 282 TestThroughputAnalyzer throughput_analyzer(¶ms); |
| 283 TestDelegate test_delegate; |
| 284 TestURLRequestContext context; |
| 285 |
| 286 EXPECT_EQ(0, throughput_analyzer.throughput_observations_received()); |
| 287 |
| 288 std::unique_ptr<URLRequest> request_1 = context.CreateRequest( |
| 289 GURL("http://example.com/echo.html"), DEFAULT_PRIORITY, &test_delegate, |
| 290 TRAFFIC_ANNOTATION_FOR_TESTS); |
| 291 std::unique_ptr<URLRequest> request_2 = context.CreateRequest( |
| 292 GURL("http://example.com/echo.html"), DEFAULT_PRIORITY, &test_delegate, |
| 293 TRAFFIC_ANNOTATION_FOR_TESTS); |
| 294 std::unique_ptr<URLRequest> request_3 = context.CreateRequest( |
| 295 GURL("http://example.com/echo.html"), DEFAULT_PRIORITY, &test_delegate, |
| 296 TRAFFIC_ANNOTATION_FOR_TESTS); |
| 297 std::unique_ptr<URLRequest> request_4 = context.CreateRequest( |
| 298 GURL("http://example.com/echo.html"), DEFAULT_PRIORITY, &test_delegate, |
| 299 TRAFFIC_ANNOTATION_FOR_TESTS); |
| 300 |
| 301 request_1->Start(); |
| 302 request_2->Start(); |
| 303 request_3->Start(); |
| 304 request_4->Start(); |
| 305 |
| 306 base::RunLoop().Run(); |
| 307 |
| 308 EXPECT_EQ(0, throughput_analyzer.throughput_observations_received()); |
| 309 |
| 310 throughput_analyzer.NotifyStartTransaction(*(request_1.get())); |
| 311 throughput_analyzer.NotifyStartTransaction(*(request_2.get())); |
| 312 |
| 313 const size_t increment_bits = 100 * 1000 * 8; |
| 314 |
| 315 // Increment the bytes received count to emulate the bytes received for |
| 316 // |request_1| and |request_2|. |
| 317 throughput_analyzer.IncrementBitsReceived(increment_bits); |
| 318 |
| 319 throughput_analyzer.NotifyRequestCompleted(*(request_1.get())); |
| 320 base::RunLoop().RunUntilIdle(); |
| 321 // No observation should be taken since only 1 request is in flight. |
| 322 EXPECT_EQ(0, throughput_analyzer.throughput_observations_received()); |
| 323 |
| 324 throughput_analyzer.NotifyStartTransaction(*(request_3.get())); |
| 325 throughput_analyzer.NotifyStartTransaction(*(request_4.get())); |
| 326 EXPECT_EQ(0, throughput_analyzer.throughput_observations_received()); |
| 327 |
| 328 // 3 requests are in flight which is at least as many as the minimum number of |
| 329 // in flight requests required. An observation should be taken. |
| 330 throughput_analyzer.IncrementBitsReceived(increment_bits); |
| 331 |
| 332 // Only one observation should be taken since two requests overlap. |
| 333 throughput_analyzer.NotifyRequestCompleted(*(request_2.get())); |
| 334 base::RunLoop().RunUntilIdle(); |
| 335 |
| 336 EXPECT_EQ(1, throughput_analyzer.throughput_observations_received()); |
| 337 throughput_analyzer.NotifyRequestCompleted(*(request_3.get())); |
| 338 throughput_analyzer.NotifyRequestCompleted(*(request_4.get())); |
| 339 EXPECT_EQ(1, throughput_analyzer.throughput_observations_received()); |
| 340 } |
| 341 |
241 } // namespace | 342 } // namespace |
242 | 343 |
243 } // namespace nqe | 344 } // namespace nqe |
244 | 345 |
245 } // namespace net | 346 } // namespace net |
OLD | NEW |