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