| 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 |