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/request_priority.h" | 14 #include "net/base/request_priority.h" |
| 15 #include "net/http/http_response_headers.h" | |
| 16 #include "net/http/http_util.h" | |
| 10 #include "net/url_request/url_request.h" | 17 #include "net/url_request/url_request.h" |
| 18 #include "net/url_request/url_request_job_factory_impl.h" | |
| 11 #include "net/url_request/url_request_status.h" | 19 #include "net/url_request/url_request_status.h" |
| 20 #include "net/url_request/url_request_test_job.h" | |
| 12 #include "net/url_request/url_request_test_util.h" | 21 #include "net/url_request/url_request_test_util.h" |
| 13 #include "testing/gmock/include/gmock/gmock.h" | 22 #include "testing/gmock/include/gmock/gmock.h" |
| 14 #include "testing/gtest/include/gtest/gtest.h" | 23 #include "testing/gtest/include/gtest/gtest.h" |
| 15 | 24 |
| 16 using base::MessageLoop; | 25 using base::MessageLoop; |
| 17 using base::MessageLoopProxy; | 26 using base::MessageLoopProxy; |
| 18 using data_reduction_proxy::DataReductionProxyParams; | 27 using data_reduction_proxy::DataReductionProxyParams; |
| 19 using net::TestDelegate; | 28 using net::TestDelegate; |
| 20 using net::TestURLRequestContext; | 29 using net::TestURLRequestContext; |
| 21 using net::URLRequest; | 30 using net::URLRequest; |
| (...skipping 21 matching lines...) Expand all Loading... | |
| 43 | 52 |
| 44 namespace data_reduction_proxy { | 53 namespace data_reduction_proxy { |
| 45 | 54 |
| 46 class DataReductionProxyUsageStatsTest : public testing::Test { | 55 class DataReductionProxyUsageStatsTest : public testing::Test { |
| 47 public: | 56 public: |
| 48 DataReductionProxyUsageStatsTest() | 57 DataReductionProxyUsageStatsTest() |
| 49 : loop_proxy_(MessageLoopProxy::current().get()), | 58 : loop_proxy_(MessageLoopProxy::current().get()), |
| 50 context_(true), | 59 context_(true), |
| 51 unavailable_(false) { | 60 unavailable_(false) { |
| 52 context_.Init(); | 61 context_.Init(); |
| 62 | |
| 63 // The |test_job_factory_| takes ownership of the interceptor. | |
| 64 test_job_interceptor_ = new net::TestJobInterceptor(); | |
| 65 DCHECK(test_job_factory_.SetProtocolHandler(url::kHttpScheme, | |
| 66 test_job_interceptor_)); | |
| 67 context_.set_job_factory(&test_job_factory_); | |
| 68 | |
| 53 mock_url_request_ = context_.CreateRequest(GURL(), net::IDLE, &delegate_, | 69 mock_url_request_ = context_.CreateRequest(GURL(), net::IDLE, &delegate_, |
| 54 NULL); | 70 NULL); |
| 55 } | 71 } |
| 56 | 72 |
| 57 void NotifyUnavailable(bool unavailable) { | 73 void NotifyUnavailable(bool unavailable) { |
| 58 unavailable_ = unavailable; | 74 unavailable_ = unavailable; |
| 59 } | 75 } |
| 60 | 76 |
| 77 scoped_ptr<URLRequest> CreateURLRequestWithResponseHeaders( | |
| 78 const GURL& url, | |
| 79 const std::string& raw_response_headers) { | |
| 80 scoped_ptr<URLRequest> fake_request = context_.CreateRequest(url, net::IDLE, | |
| 81 &delegate_, | |
| 82 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 MessageLoop::current()->RunUntilIdle(); | |
| 95 | |
| 96 DCHECK(fake_request->response_headers() != NULL); | |
| 97 return fake_request.Pass(); | |
| 98 } | |
| 99 | |
| 61 // Required for MessageLoopProxy::current(). | 100 // Required for MessageLoopProxy::current(). |
| 62 base::MessageLoopForUI loop_; | 101 base::MessageLoopForUI loop_; |
| 63 MessageLoopProxy* loop_proxy_; | 102 MessageLoopProxy* loop_proxy_; |
| 64 | 103 |
| 65 protected: | 104 protected: |
| 66 TestURLRequestContext context_; | 105 TestURLRequestContext context_; |
| 67 TestDelegate delegate_; | 106 TestDelegate delegate_; |
| 68 DataReductionProxyParamsMock mock_params_; | 107 DataReductionProxyParamsMock mock_params_; |
| 69 scoped_ptr<URLRequest> mock_url_request_; | 108 scoped_ptr<URLRequest> mock_url_request_; |
| 109 net::TestJobInterceptor* test_job_interceptor_; | |
|
Alexei Svitkine (slow)
2014/09/23 18:20:06
Nit: Add a comment that this is owned by |test_job
sclittle
2014/09/23 19:58:31
Done.
| |
| 110 net::URLRequestJobFactoryImpl test_job_factory_; | |
| 70 bool unavailable_; | 111 bool unavailable_; |
| 71 }; | 112 }; |
| 72 | 113 |
| 73 TEST_F(DataReductionProxyUsageStatsTest, IsDataReductionProxyUnreachable) { | 114 TEST_F(DataReductionProxyUsageStatsTest, IsDataReductionProxyUnreachable) { |
| 74 struct TestCase { | 115 struct TestCase { |
| 75 bool is_proxy_eligible; | 116 bool is_proxy_eligible; |
| 76 bool was_proxy_used; | 117 bool was_proxy_used; |
| 77 bool is_unreachable; | 118 bool is_unreachable; |
| 78 }; | 119 }; |
| 79 const TestCase test_cases[] = { | 120 const TestCase test_cases[] = { |
| (...skipping 30 matching lines...) Expand all Loading... | |
| 110 base::Bind(&DataReductionProxyUsageStatsTest::NotifyUnavailable, | 151 base::Bind(&DataReductionProxyUsageStatsTest::NotifyUnavailable, |
| 111 base::Unretained(this))); | 152 base::Unretained(this))); |
| 112 | 153 |
| 113 usage_stats->OnUrlRequestCompleted(mock_url_request_.get(), false); | 154 usage_stats->OnUrlRequestCompleted(mock_url_request_.get(), false); |
| 114 MessageLoop::current()->RunUntilIdle(); | 155 MessageLoop::current()->RunUntilIdle(); |
| 115 | 156 |
| 116 EXPECT_EQ(test_case.is_unreachable, unavailable_); | 157 EXPECT_EQ(test_case.is_unreachable, unavailable_); |
| 117 } | 158 } |
| 118 } | 159 } |
| 119 | 160 |
| 161 TEST_F(DataReductionProxyUsageStatsTest, | |
| 162 DetectAndRecordMissingViaHeaderResponseCode) { | |
| 163 const std::string kPrimaryHistogramName = | |
| 164 "DataReductionProxy.MissingViaHeader.ResponseCode.Primary"; | |
| 165 const std::string kFallbackHistogramName = | |
| 166 "DataReductionProxy.MissingViaHeader.ResponseCode.Fallback"; | |
| 167 | |
| 168 struct TestCase { | |
| 169 bool is_primary; | |
| 170 const char* headers; | |
| 171 int expected_primary_sample; // -1 indicates no expected sample. | |
| 172 int expected_fallback_sample; // -1 indicates no expected sample. | |
| 173 }; | |
| 174 const TestCase test_cases[] = { | |
| 175 { | |
| 176 true, | |
| 177 "HTTP/1.1 200 OK\n" | |
| 178 "Via: 1.1 Chrome-Compression-Proxy\n", | |
| 179 -1, | |
| 180 -1 | |
| 181 }, | |
| 182 { | |
| 183 false, | |
| 184 "HTTP/1.1 200 OK\n" | |
| 185 "Via: 1.1 Chrome-Compression-Proxy\n", | |
| 186 -1, | |
| 187 -1 | |
| 188 }, | |
| 189 { | |
| 190 true, | |
| 191 "HTTP/1.1 200 OK\n", | |
| 192 200, | |
| 193 -1 | |
| 194 }, | |
| 195 { | |
| 196 false, | |
| 197 "HTTP/1.1 200 OK\n", | |
| 198 -1, | |
| 199 200 | |
| 200 }, | |
| 201 { | |
| 202 true, | |
| 203 "HTTP/1.1 304 Not Modified\n", | |
| 204 304, | |
| 205 -1 | |
| 206 }, | |
| 207 { | |
| 208 false, | |
| 209 "HTTP/1.1 304 Not Modified\n", | |
| 210 -1, | |
| 211 304 | |
| 212 }, | |
| 213 { | |
| 214 true, | |
| 215 "HTTP/1.1 404 Not Found\n", | |
| 216 404, | |
| 217 -1 | |
| 218 }, | |
| 219 { | |
| 220 false, | |
| 221 "HTTP/1.1 404 Not Found\n", | |
| 222 -1, | |
| 223 404 | |
| 224 } | |
| 225 }; | |
| 226 | |
| 227 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(test_cases); ++i) { | |
| 228 base::HistogramTester histogram_tester; | |
| 229 std::string raw_headers(test_cases[i].headers); | |
| 230 HeadersToRaw(&raw_headers); | |
| 231 scoped_refptr<net::HttpResponseHeaders> headers( | |
| 232 new net::HttpResponseHeaders(raw_headers)); | |
| 233 | |
| 234 DataReductionProxyUsageStats::DetectAndRecordMissingViaHeaderResponseCode( | |
| 235 test_cases[i].is_primary, headers.get()); | |
| 236 | |
| 237 if (test_cases[i].expected_primary_sample == -1) { | |
| 238 histogram_tester.ExpectTotalCount(kPrimaryHistogramName, 0); | |
| 239 } else { | |
| 240 histogram_tester.ExpectUniqueSample( | |
| 241 kPrimaryHistogramName, test_cases[i].expected_primary_sample, 1); | |
| 242 } | |
| 243 | |
| 244 if (test_cases[i].expected_fallback_sample == -1) { | |
| 245 histogram_tester.ExpectTotalCount(kFallbackHistogramName, 0); | |
| 246 } else { | |
| 247 histogram_tester.ExpectUniqueSample( | |
| 248 kFallbackHistogramName, test_cases[i].expected_fallback_sample, 1); | |
| 249 } | |
| 250 } | |
| 251 } | |
| 252 | |
| 253 TEST_F(DataReductionProxyUsageStatsTest, RecordMissingViaHeaderBytes) { | |
| 254 const std::string k4xxHistogramName = | |
| 255 "DataReductionProxy.MissingViaHeader.Bytes.4xx"; | |
| 256 const std::string kOtherHistogramName = | |
| 257 "DataReductionProxy.MissingViaHeader.Bytes.Other"; | |
| 258 const int64 kResponseContentLength = 100; | |
| 259 | |
| 260 struct TestCase { | |
| 261 bool was_proxy_used; | |
| 262 const char* headers; | |
| 263 bool is_4xx_sample_expected; | |
| 264 bool is_other_sample_expected; | |
| 265 }; | |
| 266 const TestCase test_cases[] = { | |
| 267 // Nothing should be recorded for requests that don't use the proxy. | |
| 268 { | |
| 269 false, | |
| 270 "HTTP/1.1 404 Not Found\n", | |
| 271 false, | |
| 272 false | |
| 273 }, | |
| 274 { | |
| 275 false, | |
| 276 "HTTP/1.1 200 OK\n", | |
| 277 false, | |
| 278 false | |
| 279 }, | |
| 280 // Nothing should be recorded for responses that have the via header. | |
| 281 { | |
| 282 true, | |
| 283 "HTTP/1.1 404 Not Found\n" | |
| 284 "Via: 1.1 Chrome-Compression-Proxy\n", | |
| 285 false, | |
| 286 false | |
| 287 }, | |
| 288 { | |
| 289 true, | |
| 290 "HTTP/1.1 200 OK\n" | |
| 291 "Via: 1.1 Chrome-Compression-Proxy\n", | |
| 292 false, | |
| 293 false | |
| 294 }, | |
| 295 // 4xx responses that used the proxy and don't have the via header should be | |
| 296 // recorded. | |
| 297 { | |
| 298 true, | |
| 299 "HTTP/1.1 404 Not Found\n", | |
| 300 true, | |
| 301 false | |
| 302 }, | |
| 303 { | |
| 304 true, | |
| 305 "HTTP/1.1 400 Bad Request\n", | |
| 306 true, | |
| 307 false | |
| 308 }, | |
| 309 { | |
| 310 true, | |
| 311 "HTTP/1.1 499 Big Client Error Response Code\n", | |
| 312 true, | |
| 313 false | |
| 314 }, | |
| 315 // Non-4xx responses that used the proxy and don't have the via header | |
| 316 // should be recorded. | |
| 317 { | |
| 318 true, | |
| 319 "HTTP/1.1 200 OK\n", | |
| 320 false, | |
| 321 true | |
| 322 }, | |
| 323 { | |
| 324 true, | |
| 325 "HTTP/1.1 399 Big Redirection Response Code\n", | |
| 326 false, | |
| 327 true | |
| 328 }, | |
| 329 { | |
| 330 true, | |
| 331 "HTTP/1.1 500 Internal Server Error\n", | |
| 332 false, | |
| 333 true | |
| 334 } | |
| 335 }; | |
| 336 | |
| 337 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(test_cases); ++i) { | |
| 338 base::HistogramTester histogram_tester; | |
| 339 scoped_ptr<DataReductionProxyUsageStats> usage_stats( | |
| 340 new DataReductionProxyUsageStats(&mock_params_, loop_proxy_)); | |
| 341 | |
| 342 std::string raw_headers(test_cases[i].headers); | |
| 343 HeadersToRaw(&raw_headers); | |
| 344 | |
| 345 scoped_ptr<URLRequest> fake_request( | |
| 346 CreateURLRequestWithResponseHeaders(GURL("http://www.google.com/"), | |
| 347 raw_headers)); | |
| 348 fake_request->set_received_response_content_length(kResponseContentLength); | |
| 349 | |
| 350 EXPECT_CALL(mock_params_, | |
| 351 WasDataReductionProxyUsed(fake_request.get(), NULL)) | |
| 352 .WillRepeatedly(Return(test_cases[i].was_proxy_used)); | |
| 353 | |
| 354 usage_stats->RecordMissingViaHeaderBytes(fake_request.get()); | |
| 355 | |
| 356 if (test_cases[i].is_4xx_sample_expected) { | |
| 357 histogram_tester.ExpectUniqueSample(k4xxHistogramName, | |
| 358 kResponseContentLength, 1); | |
| 359 } else { | |
| 360 histogram_tester.ExpectTotalCount(k4xxHistogramName, 0); | |
| 361 } | |
| 362 | |
| 363 if (test_cases[i].is_other_sample_expected) { | |
| 364 histogram_tester.ExpectUniqueSample(kOtherHistogramName, | |
| 365 kResponseContentLength, 1); | |
| 366 } else { | |
| 367 histogram_tester.ExpectTotalCount(kOtherHistogramName, 0); | |
| 368 } | |
| 369 } | |
| 370 } | |
| 371 | |
| 120 } // namespace data_reduction_proxy | 372 } // namespace data_reduction_proxy |
| OLD | NEW |