Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright 2014 The Chromium Authors. All rights reserved. | 1 // Copyright 2014 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 "components/data_reduction_proxy/browser/data_reduction_proxy_usage_sta ts.h" | 5 #include "components/data_reduction_proxy/browser/data_reduction_proxy_usage_sta ts.h" |
| 6 | 6 |
| 7 #include <string> | |
| 8 | |
| 7 #include "base/bind.h" | 9 #include "base/bind.h" |
| 8 #include "base/memory/scoped_ptr.h" | 10 #include "base/memory/scoped_ptr.h" |
| 11 #include "base/metrics/histogram.h" | |
| 12 #include "base/test/histogram_tester.h" | |
| 13 #include "components/data_reduction_proxy/common/data_reduction_proxy_headers_te st_utils.h" | |
| 9 #include "net/base/host_port_pair.h" | 14 #include "net/base/host_port_pair.h" |
| 10 #include "net/base/request_priority.h" | 15 #include "net/base/request_priority.h" |
| 16 #include "net/http/http_response_headers.h" | |
| 17 #include "net/http/http_util.h" | |
| 11 #include "net/url_request/url_request.h" | 18 #include "net/url_request/url_request.h" |
| 19 #include "net/url_request/url_request_job_factory_impl.h" | |
| 12 #include "net/url_request/url_request_status.h" | 20 #include "net/url_request/url_request_status.h" |
| 21 #include "net/url_request/url_request_test_job.h" | |
| 13 #include "net/url_request/url_request_test_util.h" | 22 #include "net/url_request/url_request_test_util.h" |
| 14 #include "testing/gmock/include/gmock/gmock.h" | 23 #include "testing/gmock/include/gmock/gmock.h" |
| 15 #include "testing/gtest/include/gtest/gtest.h" | 24 #include "testing/gtest/include/gtest/gtest.h" |
| 16 | 25 |
| 17 using testing::Return; | 26 using testing::Return; |
| 18 | 27 |
| 19 namespace { | 28 namespace { |
| 20 | 29 |
| 21 class DataReductionProxyParamsMock : | 30 class DataReductionProxyParamsMock : |
| 22 public data_reduction_proxy::DataReductionProxyParams { | 31 public data_reduction_proxy::DataReductionProxyParams { |
| (...skipping 19 matching lines...) Expand all Loading... | |
| 42 | 51 |
| 43 namespace data_reduction_proxy { | 52 namespace data_reduction_proxy { |
| 44 | 53 |
| 45 class DataReductionProxyUsageStatsTest : public testing::Test { | 54 class DataReductionProxyUsageStatsTest : public testing::Test { |
| 46 public: | 55 public: |
| 47 DataReductionProxyUsageStatsTest() | 56 DataReductionProxyUsageStatsTest() |
| 48 : loop_proxy_(base::MessageLoopProxy::current().get()), | 57 : loop_proxy_(base::MessageLoopProxy::current().get()), |
| 49 context_(true), | 58 context_(true), |
| 50 unavailable_(false) { | 59 unavailable_(false) { |
| 51 context_.Init(); | 60 context_.Init(); |
| 61 | |
| 62 // The |test_job_factory_| takes ownership of the interceptor. | |
| 63 test_job_interceptor_ = new net::TestJobInterceptor(); | |
| 64 // This must be a CHECK, and not a DCHECK, so that Valgrind doesn't complain | |
| 65 // that the |test_job_interceptor_| is never freed. | |
| 66 CHECK(test_job_factory_.SetProtocolHandler(url::kHttpScheme, | |
|
sclittle
2014/09/24 04:22:58
This line (and the comment above it) are the only
| |
| 67 test_job_interceptor_)); | |
|
mmenke
2014/09/24 15:31:12
I think it's still a bad idea to put code with sid
sclittle
2014/09/24 17:41:44
Unfortunately, changing this to ASSERT_TRUE doesn'
bengr
2014/09/24 17:46:47
You shouldn't be using DCHECK in tests. See: http:
sclittle
2014/09/24 18:05:14
OK, I've changed it to use EXPECT_TRUE.
| |
| 68 context_.set_job_factory(&test_job_factory_); | |
| 69 | |
| 52 mock_url_request_ = context_.CreateRequest(GURL(), net::IDLE, &delegate_, | 70 mock_url_request_ = context_.CreateRequest(GURL(), net::IDLE, &delegate_, |
| 53 NULL); | 71 NULL); |
| 54 } | 72 } |
| 55 | 73 |
| 56 void NotifyUnavailable(bool unavailable) { | 74 void NotifyUnavailable(bool unavailable) { |
| 57 unavailable_ = unavailable; | 75 unavailable_ = unavailable; |
| 58 } | 76 } |
| 59 | 77 |
| 78 scoped_ptr<net::URLRequest> CreateURLRequestWithResponseHeaders( | |
| 79 const GURL& url, | |
| 80 const std::string& raw_response_headers) { | |
| 81 scoped_ptr<net::URLRequest> fake_request = context_.CreateRequest( | |
| 82 url, net::IDLE, &delegate_, NULL); | |
| 83 | |
| 84 // Create a test job that will fill in the given response headers for the | |
| 85 // |fake_request|. | |
| 86 scoped_refptr<net::URLRequestTestJob> test_job( | |
| 87 new net::URLRequestTestJob(fake_request.get(), | |
| 88 context_.network_delegate(), | |
| 89 raw_response_headers, std::string(), true)); | |
| 90 | |
| 91 // Configure the interceptor to use the test job to handle the next request. | |
| 92 test_job_interceptor_->set_main_intercept_job(test_job.get()); | |
| 93 fake_request->Start(); | |
| 94 base::MessageLoop::current()->RunUntilIdle(); | |
| 95 | |
| 96 DCHECK(fake_request->response_headers() != NULL); | |
| 97 return fake_request.Pass(); | |
| 98 } | |
| 99 | |
| 60 // Required for base::MessageLoopProxy::current(). | 100 // Required for base::MessageLoopProxy::current(). |
| 61 base::MessageLoopForUI loop_; | 101 base::MessageLoopForUI loop_; |
| 62 base::MessageLoopProxy* loop_proxy_; | 102 base::MessageLoopProxy* loop_proxy_; |
| 63 | 103 |
| 64 protected: | 104 protected: |
| 65 net::TestURLRequestContext context_; | 105 net::TestURLRequestContext context_; |
| 66 net::TestDelegate delegate_; | 106 net::TestDelegate delegate_; |
| 67 DataReductionProxyParamsMock mock_params_; | 107 DataReductionProxyParamsMock mock_params_; |
| 68 scoped_ptr<net::URLRequest> mock_url_request_; | 108 scoped_ptr<net::URLRequest> mock_url_request_; |
| 109 // |test_job_interceptor_| is owned by |test_job_factory_|. | |
| 110 net::TestJobInterceptor* test_job_interceptor_; | |
| 111 net::URLRequestJobFactoryImpl test_job_factory_; | |
| 69 bool unavailable_; | 112 bool unavailable_; |
| 70 }; | 113 }; |
| 71 | 114 |
| 72 TEST_F(DataReductionProxyUsageStatsTest, IsDataReductionProxyUnreachable) { | 115 TEST_F(DataReductionProxyUsageStatsTest, IsDataReductionProxyUnreachable) { |
| 73 net::ProxyServer fallback_proxy_server = | 116 net::ProxyServer fallback_proxy_server = |
| 74 net::ProxyServer::FromURI("foo.com", net::ProxyServer::SCHEME_HTTP); | 117 net::ProxyServer::FromURI("foo.com", net::ProxyServer::SCHEME_HTTP); |
| 75 data_reduction_proxy::DataReductionProxyTypeInfo proxy_info; | 118 data_reduction_proxy::DataReductionProxyTypeInfo proxy_info; |
| 76 struct TestCase { | 119 struct TestCase { |
| 77 bool fallback_proxy_server_is_data_reduction_proxy; | 120 bool fallback_proxy_server_is_data_reduction_proxy; |
| 78 bool was_proxy_used; | 121 bool was_proxy_used; |
| (...skipping 101 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 180 usage_stats->OnProxyFallback(fallback_proxy_server, | 223 usage_stats->OnProxyFallback(fallback_proxy_server, |
| 181 net::ERR_PROXY_CONNECTION_FAILED); | 224 net::ERR_PROXY_CONNECTION_FAILED); |
| 182 usage_stats->OnProxyFallback(fallback_proxy_server, | 225 usage_stats->OnProxyFallback(fallback_proxy_server, |
| 183 net::ERR_PROXY_CONNECTION_FAILED); | 226 net::ERR_PROXY_CONNECTION_FAILED); |
| 184 usage_stats->OnProxyFallback(fallback_proxy_server, | 227 usage_stats->OnProxyFallback(fallback_proxy_server, |
| 185 net::ERR_PROXY_CONNECTION_FAILED); | 228 net::ERR_PROXY_CONNECTION_FAILED); |
| 186 base::MessageLoop::current()->RunUntilIdle(); | 229 base::MessageLoop::current()->RunUntilIdle(); |
| 187 EXPECT_TRUE(unavailable_); | 230 EXPECT_TRUE(unavailable_); |
| 188 } | 231 } |
| 189 | 232 |
| 233 TEST_F(DataReductionProxyUsageStatsTest, | |
| 234 DetectAndRecordMissingViaHeaderResponseCode) { | |
| 235 const std::string kPrimaryHistogramName = | |
| 236 "DataReductionProxy.MissingViaHeader.ResponseCode.Primary"; | |
| 237 const std::string kFallbackHistogramName = | |
| 238 "DataReductionProxy.MissingViaHeader.ResponseCode.Fallback"; | |
| 239 | |
| 240 struct TestCase { | |
| 241 bool is_primary; | |
| 242 const char* headers; | |
| 243 int expected_primary_sample; // -1 indicates no expected sample. | |
| 244 int expected_fallback_sample; // -1 indicates no expected sample. | |
| 245 }; | |
| 246 const TestCase test_cases[] = { | |
| 247 { | |
| 248 true, | |
| 249 "HTTP/1.1 200 OK\n" | |
| 250 "Via: 1.1 Chrome-Compression-Proxy\n", | |
| 251 -1, | |
| 252 -1 | |
| 253 }, | |
| 254 { | |
| 255 false, | |
| 256 "HTTP/1.1 200 OK\n" | |
| 257 "Via: 1.1 Chrome-Compression-Proxy\n", | |
| 258 -1, | |
| 259 -1 | |
| 260 }, | |
| 261 { | |
| 262 true, | |
| 263 "HTTP/1.1 200 OK\n", | |
| 264 200, | |
| 265 -1 | |
| 266 }, | |
| 267 { | |
| 268 false, | |
| 269 "HTTP/1.1 200 OK\n", | |
| 270 -1, | |
| 271 200 | |
| 272 }, | |
| 273 { | |
| 274 true, | |
| 275 "HTTP/1.1 304 Not Modified\n", | |
| 276 304, | |
| 277 -1 | |
| 278 }, | |
| 279 { | |
| 280 false, | |
| 281 "HTTP/1.1 304 Not Modified\n", | |
| 282 -1, | |
| 283 304 | |
| 284 }, | |
| 285 { | |
| 286 true, | |
| 287 "HTTP/1.1 404 Not Found\n", | |
| 288 404, | |
| 289 -1 | |
| 290 }, | |
| 291 { | |
| 292 false, | |
| 293 "HTTP/1.1 404 Not Found\n", | |
| 294 -1, | |
| 295 404 | |
| 296 } | |
| 297 }; | |
| 298 | |
| 299 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(test_cases); ++i) { | |
| 300 base::HistogramTester histogram_tester; | |
| 301 std::string raw_headers(test_cases[i].headers); | |
| 302 HeadersToRaw(&raw_headers); | |
| 303 scoped_refptr<net::HttpResponseHeaders> headers( | |
| 304 new net::HttpResponseHeaders(raw_headers)); | |
| 305 | |
| 306 DataReductionProxyUsageStats::DetectAndRecordMissingViaHeaderResponseCode( | |
| 307 test_cases[i].is_primary, headers.get()); | |
| 308 | |
| 309 if (test_cases[i].expected_primary_sample == -1) { | |
| 310 histogram_tester.ExpectTotalCount(kPrimaryHistogramName, 0); | |
| 311 } else { | |
| 312 histogram_tester.ExpectUniqueSample( | |
| 313 kPrimaryHistogramName, test_cases[i].expected_primary_sample, 1); | |
| 314 } | |
| 315 | |
| 316 if (test_cases[i].expected_fallback_sample == -1) { | |
| 317 histogram_tester.ExpectTotalCount(kFallbackHistogramName, 0); | |
| 318 } else { | |
| 319 histogram_tester.ExpectUniqueSample( | |
| 320 kFallbackHistogramName, test_cases[i].expected_fallback_sample, 1); | |
| 321 } | |
| 322 } | |
| 323 } | |
| 324 | |
| 325 TEST_F(DataReductionProxyUsageStatsTest, RecordMissingViaHeaderBytes) { | |
| 326 const std::string k4xxHistogramName = | |
| 327 "DataReductionProxy.MissingViaHeader.Bytes.4xx"; | |
| 328 const std::string kOtherHistogramName = | |
| 329 "DataReductionProxy.MissingViaHeader.Bytes.Other"; | |
| 330 const int64 kResponseContentLength = 100; | |
| 331 | |
| 332 struct TestCase { | |
| 333 bool was_proxy_used; | |
| 334 const char* headers; | |
| 335 bool is_4xx_sample_expected; | |
| 336 bool is_other_sample_expected; | |
| 337 }; | |
| 338 const TestCase test_cases[] = { | |
| 339 // Nothing should be recorded for requests that don't use the proxy. | |
| 340 { | |
| 341 false, | |
| 342 "HTTP/1.1 404 Not Found\n", | |
| 343 false, | |
| 344 false | |
| 345 }, | |
| 346 { | |
| 347 false, | |
| 348 "HTTP/1.1 200 OK\n", | |
| 349 false, | |
| 350 false | |
| 351 }, | |
| 352 // Nothing should be recorded for responses that have the via header. | |
| 353 { | |
| 354 true, | |
| 355 "HTTP/1.1 404 Not Found\n" | |
| 356 "Via: 1.1 Chrome-Compression-Proxy\n", | |
| 357 false, | |
| 358 false | |
| 359 }, | |
| 360 { | |
| 361 true, | |
| 362 "HTTP/1.1 200 OK\n" | |
| 363 "Via: 1.1 Chrome-Compression-Proxy\n", | |
| 364 false, | |
| 365 false | |
| 366 }, | |
| 367 // 4xx responses that used the proxy and don't have the via header should be | |
| 368 // recorded. | |
| 369 { | |
| 370 true, | |
| 371 "HTTP/1.1 404 Not Found\n", | |
| 372 true, | |
| 373 false | |
| 374 }, | |
| 375 { | |
| 376 true, | |
| 377 "HTTP/1.1 400 Bad Request\n", | |
| 378 true, | |
| 379 false | |
| 380 }, | |
| 381 { | |
| 382 true, | |
| 383 "HTTP/1.1 499 Big Client Error Response Code\n", | |
| 384 true, | |
| 385 false | |
| 386 }, | |
| 387 // Non-4xx responses that used the proxy and don't have the via header | |
| 388 // should be recorded. | |
| 389 { | |
| 390 true, | |
| 391 "HTTP/1.1 200 OK\n", | |
| 392 false, | |
| 393 true | |
| 394 }, | |
| 395 { | |
| 396 true, | |
| 397 "HTTP/1.1 399 Big Redirection Response Code\n", | |
| 398 false, | |
| 399 true | |
| 400 }, | |
| 401 { | |
| 402 true, | |
| 403 "HTTP/1.1 500 Internal Server Error\n", | |
| 404 false, | |
| 405 true | |
| 406 } | |
| 407 }; | |
| 408 | |
| 409 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(test_cases); ++i) { | |
| 410 base::HistogramTester histogram_tester; | |
| 411 scoped_ptr<DataReductionProxyUsageStats> usage_stats( | |
| 412 new DataReductionProxyUsageStats(&mock_params_, loop_proxy_)); | |
| 413 | |
| 414 std::string raw_headers(test_cases[i].headers); | |
| 415 HeadersToRaw(&raw_headers); | |
| 416 | |
| 417 scoped_ptr<net::URLRequest> fake_request( | |
| 418 CreateURLRequestWithResponseHeaders(GURL("http://www.google.com/"), | |
| 419 raw_headers)); | |
| 420 fake_request->set_received_response_content_length(kResponseContentLength); | |
| 421 | |
| 422 EXPECT_CALL(mock_params_, | |
| 423 WasDataReductionProxyUsed(fake_request.get(), NULL)) | |
| 424 .WillRepeatedly(Return(test_cases[i].was_proxy_used)); | |
| 425 | |
| 426 usage_stats->RecordMissingViaHeaderBytes(fake_request.get()); | |
| 427 | |
| 428 if (test_cases[i].is_4xx_sample_expected) { | |
| 429 histogram_tester.ExpectUniqueSample(k4xxHistogramName, | |
| 430 kResponseContentLength, 1); | |
| 431 } else { | |
| 432 histogram_tester.ExpectTotalCount(k4xxHistogramName, 0); | |
| 433 } | |
| 434 | |
| 435 if (test_cases[i].is_other_sample_expected) { | |
| 436 histogram_tester.ExpectUniqueSample(kOtherHistogramName, | |
| 437 kResponseContentLength, 1); | |
| 438 } else { | |
| 439 histogram_tester.ExpectTotalCount(kOtherHistogramName, 0); | |
| 440 } | |
| 441 } | |
| 442 } | |
| 443 | |
| 190 } // namespace data_reduction_proxy | 444 } // namespace data_reduction_proxy |
| OLD | NEW |