Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(517)

Side by Side Diff: components/data_reduction_proxy/core/browser/data_reduction_proxy_usage_stats_unittest.cc

Issue 956223002: Rename DataReductionProxyUsageStats to DataReductionProxyBypassStats (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: nits Created 5 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(Empty)
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
3 // found in the LICENSE file.
4
5 #include "components/data_reduction_proxy/core/browser/data_reduction_proxy_usag e_stats.h"
6
7 #include <set>
8 #include <string>
9 #include <vector>
10
11 #include "base/bind.h"
12 #include "base/memory/scoped_ptr.h"
13 #include "base/metrics/histogram.h"
14 #include "base/prefs/testing_pref_service.h"
15 #include "base/test/histogram_tester.h"
16 #include "components/data_reduction_proxy/core/browser/data_reduction_proxy_conf ig_test_utils.h"
17 #include "components/data_reduction_proxy/core/browser/data_reduction_proxy_conf igurator.h"
18 #include "components/data_reduction_proxy/core/browser/data_reduction_proxy_io_d ata.h"
19 #include "components/data_reduction_proxy/core/browser/data_reduction_proxy_netw ork_delegate.h"
20 #include "components/data_reduction_proxy/core/browser/data_reduction_proxy_pref s.h"
21 #include "components/data_reduction_proxy/core/browser/data_reduction_proxy_test _utils.h"
22 #include "components/data_reduction_proxy/core/common/data_reduction_proxy_heade rs_test_utils.h"
23 #include "components/data_reduction_proxy/core/common/data_reduction_proxy_param s_test_utils.h"
24 #include "components/data_reduction_proxy/core/common/data_reduction_proxy_pref_ names.h"
25 #include "net/base/host_port_pair.h"
26 #include "net/base/load_flags.h"
27 #include "net/base/net_errors.h"
28 #include "net/base/net_log.h"
29 #include "net/base/request_priority.h"
30 #include "net/dns/mock_host_resolver.h"
31 #include "net/http/http_response_headers.h"
32 #include "net/http/http_util.h"
33 #include "net/socket/socket_test_util.h"
34 #include "net/url_request/url_request.h"
35 #include "net/url_request/url_request_context_getter.h"
36 #include "net/url_request/url_request_context_storage.h"
37 #include "net/url_request/url_request_intercepting_job_factory.h"
38 #include "net/url_request/url_request_interceptor.h"
39 #include "net/url_request/url_request_job_factory_impl.h"
40 #include "net/url_request/url_request_status.h"
41 #include "net/url_request/url_request_test_job.h"
42 #include "net/url_request/url_request_test_util.h"
43 #include "testing/gmock/include/gmock/gmock.h"
44 #include "testing/gtest/include/gtest/gtest.h"
45
46 using net::MockRead;
47 using net::MockWrite;
48 using testing::Return;
49
50 namespace data_reduction_proxy {
51
52 namespace {
53
54 const std::string kBody = "hello";
55 const std::string kNextBody = "hello again";
56 const std::string kErrorBody = "bad";
57
58 } // namespace
59
60 class DataReductionProxyUsageStatsTest : public testing::Test {
61 public:
62 DataReductionProxyUsageStatsTest()
63 : context_(true) {
64 context_.Init();
65
66 // The |test_job_factory_| takes ownership of the interceptor.
67 test_job_interceptor_ = new net::TestJobInterceptor();
68 EXPECT_TRUE(test_job_factory_.SetProtocolHandler(url::kHttpScheme,
69 test_job_interceptor_));
70
71 context_.set_job_factory(&test_job_factory_);
72
73 test_context_ =
74 DataReductionProxyTestContext::Builder()
75 .WithParamsFlags(DataReductionProxyParams::kAllowed |
76 DataReductionProxyParams::kFallbackAllowed |
77 DataReductionProxyParams::kPromoAllowed)
78 .WithParamsDefinitions(
79 TestDataReductionProxyParams::HAS_EVERYTHING &
80 ~TestDataReductionProxyParams::HAS_DEV_ORIGIN &
81 ~TestDataReductionProxyParams::HAS_DEV_FALLBACK_ORIGIN)
82 .WithMockConfig()
83 .Build();
84 mock_url_request_ = context_.CreateRequest(GURL(), net::IDLE, &delegate_);
85 }
86
87 scoped_ptr<net::URLRequest> CreateURLRequestWithResponseHeaders(
88 const GURL& url,
89 const std::string& raw_response_headers) {
90 scoped_ptr<net::URLRequest> fake_request = context_.CreateRequest(
91 url, net::IDLE, &delegate_);
92
93 // Create a test job that will fill in the given response headers for the
94 // |fake_request|.
95 scoped_refptr<net::URLRequestTestJob> test_job(
96 new net::URLRequestTestJob(fake_request.get(),
97 context_.network_delegate(),
98 raw_response_headers, std::string(), true));
99
100 // Configure the interceptor to use the test job to handle the next request.
101 test_job_interceptor_->set_main_intercept_job(test_job.get());
102 fake_request->Start();
103 test_context_->RunUntilIdle();
104
105 EXPECT_TRUE(fake_request->response_headers() != NULL);
106 return fake_request.Pass();
107 }
108
109 bool IsUnreachable() const {
110 return test_context_->settings()->IsDataReductionProxyUnreachable();
111 }
112
113 protected:
114 scoped_ptr<DataReductionProxyUsageStats> BuildUsageStats() {
115 return make_scoped_ptr(
116 new DataReductionProxyUsageStats(
117 test_context_->config(),
118 test_context_->unreachable_callback(),
119 test_context_->task_runner())).Pass();
120 }
121
122 net::URLRequest* url_request() {
123 return mock_url_request_.get();
124 }
125
126 MockDataReductionProxyConfig* config() const {
127 return test_context_->mock_config();
128 }
129
130 void RunUntilIdle() {
131 test_context_->RunUntilIdle();
132 }
133
134 private:
135 net::TestURLRequestContext context_;
136 net::TestDelegate delegate_;
137 scoped_ptr<net::URLRequest> mock_url_request_;
138 // |test_job_interceptor_| is owned by |test_job_factory_|.
139 net::TestJobInterceptor* test_job_interceptor_;
140 net::URLRequestJobFactoryImpl test_job_factory_;
141 scoped_ptr<DataReductionProxyTestContext> test_context_;
142 };
143
144 TEST_F(DataReductionProxyUsageStatsTest, IsDataReductionProxyUnreachable) {
145 net::ProxyServer fallback_proxy_server =
146 net::ProxyServer::FromURI("foo.com", net::ProxyServer::SCHEME_HTTP);
147 data_reduction_proxy::DataReductionProxyTypeInfo proxy_info;
148 struct TestCase {
149 bool fallback_proxy_server_is_data_reduction_proxy;
150 bool was_proxy_used;
151 bool is_unreachable;
152 };
153 const TestCase test_cases[] = {
154 {
155 false,
156 false,
157 false
158 },
159 {
160 false,
161 true,
162 false
163 },
164 {
165 true,
166 true,
167 false
168 },
169 {
170 true,
171 false,
172 true
173 }
174 };
175 for (size_t i = 0; i < arraysize(test_cases); ++i) {
176 TestCase test_case = test_cases[i];
177
178 EXPECT_CALL(*config(), IsDataReductionProxy(testing::_, testing::_))
179 .WillRepeatedly(testing::Return(
180 test_case.fallback_proxy_server_is_data_reduction_proxy));
181 EXPECT_CALL(*config(),
182 WasDataReductionProxyUsed(url_request(), testing::_))
183 .WillRepeatedly(testing::Return(test_case.was_proxy_used));
184
185 scoped_ptr<DataReductionProxyUsageStats> usage_stats = BuildUsageStats();
186
187 usage_stats->OnProxyFallback(fallback_proxy_server,
188 net::ERR_PROXY_CONNECTION_FAILED);
189 usage_stats->OnUrlRequestCompleted(url_request(), false);
190 RunUntilIdle();
191
192 EXPECT_EQ(test_case.is_unreachable, IsUnreachable());
193 }
194 }
195
196 TEST_F(DataReductionProxyUsageStatsTest, ProxyUnreachableThenReachable) {
197 net::ProxyServer fallback_proxy_server =
198 net::ProxyServer::FromURI("foo.com", net::ProxyServer::SCHEME_HTTP);
199 scoped_ptr<DataReductionProxyUsageStats> usage_stats = BuildUsageStats();
200 EXPECT_CALL(*config(), IsDataReductionProxy(testing::_, testing::_))
201 .WillOnce(testing::Return(true));
202 EXPECT_CALL(*config(),
203 WasDataReductionProxyUsed(url_request(), testing::_))
204 .WillOnce(testing::Return(true));
205
206 // proxy falls back
207 usage_stats->OnProxyFallback(fallback_proxy_server,
208 net::ERR_PROXY_CONNECTION_FAILED);
209 RunUntilIdle();
210 EXPECT_TRUE(IsUnreachable());
211
212 // proxy succeeds
213 usage_stats->OnUrlRequestCompleted(url_request(), false);
214 RunUntilIdle();
215 EXPECT_FALSE(IsUnreachable());
216 }
217
218 TEST_F(DataReductionProxyUsageStatsTest, ProxyReachableThenUnreachable) {
219 net::ProxyServer fallback_proxy_server =
220 net::ProxyServer::FromURI("foo.com", net::ProxyServer::SCHEME_HTTP);
221 scoped_ptr<DataReductionProxyUsageStats> usage_stats = BuildUsageStats();
222 EXPECT_CALL(*config(),
223 WasDataReductionProxyUsed(url_request(), testing::_))
224 .WillOnce(testing::Return(true));
225 EXPECT_CALL(*config(), IsDataReductionProxy(testing::_, testing::_))
226 .WillRepeatedly(testing::Return(true));
227
228 // Proxy succeeds.
229 usage_stats->OnUrlRequestCompleted(url_request(), false);
230 RunUntilIdle();
231 EXPECT_FALSE(IsUnreachable());
232
233 // Then proxy falls back indefinitely.
234 usage_stats->OnProxyFallback(fallback_proxy_server,
235 net::ERR_PROXY_CONNECTION_FAILED);
236 usage_stats->OnProxyFallback(fallback_proxy_server,
237 net::ERR_PROXY_CONNECTION_FAILED);
238 usage_stats->OnProxyFallback(fallback_proxy_server,
239 net::ERR_PROXY_CONNECTION_FAILED);
240 usage_stats->OnProxyFallback(fallback_proxy_server,
241 net::ERR_PROXY_CONNECTION_FAILED);
242 RunUntilIdle();
243 EXPECT_TRUE(IsUnreachable());
244 }
245
246 TEST_F(DataReductionProxyUsageStatsTest,
247 DetectAndRecordMissingViaHeaderResponseCode) {
248 const std::string kPrimaryHistogramName =
249 "DataReductionProxy.MissingViaHeader.ResponseCode.Primary";
250 const std::string kFallbackHistogramName =
251 "DataReductionProxy.MissingViaHeader.ResponseCode.Fallback";
252
253 struct TestCase {
254 bool is_primary;
255 const char* headers;
256 int expected_primary_sample; // -1 indicates no expected sample.
257 int expected_fallback_sample; // -1 indicates no expected sample.
258 };
259 const TestCase test_cases[] = {
260 {
261 true,
262 "HTTP/1.1 200 OK\n"
263 "Via: 1.1 Chrome-Compression-Proxy\n",
264 -1,
265 -1
266 },
267 {
268 false,
269 "HTTP/1.1 200 OK\n"
270 "Via: 1.1 Chrome-Compression-Proxy\n",
271 -1,
272 -1
273 },
274 {
275 true,
276 "HTTP/1.1 200 OK\n",
277 200,
278 -1
279 },
280 {
281 false,
282 "HTTP/1.1 200 OK\n",
283 -1,
284 200
285 },
286 {
287 true,
288 "HTTP/1.1 304 Not Modified\n",
289 304,
290 -1
291 },
292 {
293 false,
294 "HTTP/1.1 304 Not Modified\n",
295 -1,
296 304
297 },
298 {
299 true,
300 "HTTP/1.1 404 Not Found\n",
301 404,
302 -1
303 },
304 {
305 false,
306 "HTTP/1.1 404 Not Found\n",
307 -1,
308 404
309 }
310 };
311
312 for (size_t i = 0; i < arraysize(test_cases); ++i) {
313 base::HistogramTester histogram_tester;
314 std::string raw_headers(test_cases[i].headers);
315 HeadersToRaw(&raw_headers);
316 scoped_refptr<net::HttpResponseHeaders> headers(
317 new net::HttpResponseHeaders(raw_headers));
318
319 DataReductionProxyUsageStats::DetectAndRecordMissingViaHeaderResponseCode(
320 test_cases[i].is_primary, headers.get());
321
322 if (test_cases[i].expected_primary_sample == -1) {
323 histogram_tester.ExpectTotalCount(kPrimaryHistogramName, 0);
324 } else {
325 histogram_tester.ExpectUniqueSample(
326 kPrimaryHistogramName, test_cases[i].expected_primary_sample, 1);
327 }
328
329 if (test_cases[i].expected_fallback_sample == -1) {
330 histogram_tester.ExpectTotalCount(kFallbackHistogramName, 0);
331 } else {
332 histogram_tester.ExpectUniqueSample(
333 kFallbackHistogramName, test_cases[i].expected_fallback_sample, 1);
334 }
335 }
336 }
337
338 TEST_F(DataReductionProxyUsageStatsTest, RecordMissingViaHeaderBytes) {
339 const std::string k4xxHistogramName =
340 "DataReductionProxy.MissingViaHeader.Bytes.4xx";
341 const std::string kOtherHistogramName =
342 "DataReductionProxy.MissingViaHeader.Bytes.Other";
343 const int64 kResponseContentLength = 100;
344
345 struct TestCase {
346 bool was_proxy_used;
347 const char* headers;
348 bool is_4xx_sample_expected;
349 bool is_other_sample_expected;
350 };
351 const TestCase test_cases[] = {
352 // Nothing should be recorded for requests that don't use the proxy.
353 {
354 false,
355 "HTTP/1.1 404 Not Found\n",
356 false,
357 false
358 },
359 {
360 false,
361 "HTTP/1.1 200 OK\n",
362 false,
363 false
364 },
365 // Nothing should be recorded for responses that have the via header.
366 {
367 true,
368 "HTTP/1.1 404 Not Found\n"
369 "Via: 1.1 Chrome-Compression-Proxy\n",
370 false,
371 false
372 },
373 {
374 true,
375 "HTTP/1.1 200 OK\n"
376 "Via: 1.1 Chrome-Compression-Proxy\n",
377 false,
378 false
379 },
380 // 4xx responses that used the proxy and don't have the via header should be
381 // recorded.
382 {
383 true,
384 "HTTP/1.1 404 Not Found\n",
385 true,
386 false
387 },
388 {
389 true,
390 "HTTP/1.1 400 Bad Request\n",
391 true,
392 false
393 },
394 {
395 true,
396 "HTTP/1.1 499 Big Client Error Response Code\n",
397 true,
398 false
399 },
400 // Non-4xx responses that used the proxy and don't have the via header
401 // should be recorded.
402 {
403 true,
404 "HTTP/1.1 200 OK\n",
405 false,
406 true
407 },
408 {
409 true,
410 "HTTP/1.1 399 Big Redirection Response Code\n",
411 false,
412 true
413 },
414 {
415 true,
416 "HTTP/1.1 500 Internal Server Error\n",
417 false,
418 true
419 }
420 };
421
422 for (size_t i = 0; i < arraysize(test_cases); ++i) {
423 base::HistogramTester histogram_tester;
424 scoped_ptr<DataReductionProxyUsageStats> usage_stats = BuildUsageStats();
425
426 std::string raw_headers(test_cases[i].headers);
427 HeadersToRaw(&raw_headers);
428
429 scoped_ptr<net::URLRequest> fake_request(
430 CreateURLRequestWithResponseHeaders(GURL("http://www.google.com/"),
431 raw_headers));
432 fake_request->set_received_response_content_length(kResponseContentLength);
433
434 EXPECT_CALL(*config(),
435 WasDataReductionProxyUsed(fake_request.get(), testing::_))
436 .WillRepeatedly(Return(test_cases[i].was_proxy_used));
437
438 usage_stats->RecordMissingViaHeaderBytes(*fake_request);
439
440 if (test_cases[i].is_4xx_sample_expected) {
441 histogram_tester.ExpectUniqueSample(k4xxHistogramName,
442 kResponseContentLength, 1);
443 } else {
444 histogram_tester.ExpectTotalCount(k4xxHistogramName, 0);
445 }
446
447 if (test_cases[i].is_other_sample_expected) {
448 histogram_tester.ExpectUniqueSample(kOtherHistogramName,
449 kResponseContentLength, 1);
450 } else {
451 histogram_tester.ExpectTotalCount(kOtherHistogramName, 0);
452 }
453 }
454 }
455
456 TEST_F(DataReductionProxyUsageStatsTest, RequestCompletionErrorCodes) {
457 const std::string kPrimaryHistogramName =
458 "DataReductionProxy.RequestCompletionErrorCodes.Primary";
459 const std::string kFallbackHistogramName =
460 "DataReductionProxy.RequestCompletionErrorCodes.Fallback";
461 const std::string kPrimaryMainFrameHistogramName =
462 "DataReductionProxy.RequestCompletionErrorCodes.MainFrame.Primary";
463 const std::string kFallbackMainFrameHistogramName =
464 "DataReductionProxy.RequestCompletionErrorCodes.MainFrame.Fallback";
465
466 struct TestCase {
467 bool was_proxy_used;
468 bool is_load_bypass_proxy;
469 bool is_fallback;
470 bool is_main_frame;
471 net::Error net_error;
472 };
473
474 const TestCase test_cases[] = {
475 {false, true, false, true, net::OK},
476 {false, true, false, false, net::ERR_TOO_MANY_REDIRECTS},
477 {false, false, false, true, net::OK},
478 {false, false, false, false, net::ERR_TOO_MANY_REDIRECTS},
479 {true, false, false, true, net::OK},
480 {true, false, false, true, net::ERR_TOO_MANY_REDIRECTS},
481 {true, false, false, false, net::OK},
482 {true, false, false, false, net::ERR_TOO_MANY_REDIRECTS},
483 {true, false, true, true, net::OK},
484 {true, false, true, true, net::ERR_TOO_MANY_REDIRECTS},
485 {true, false, true, false, net::OK},
486 {true, false, true, false, net::ERR_TOO_MANY_REDIRECTS}
487 };
488
489 for (size_t i = 0; i < arraysize(test_cases); ++i) {
490 base::HistogramTester histogram_tester;
491 scoped_ptr<DataReductionProxyUsageStats> usage_stats = BuildUsageStats();
492
493 std::string raw_headers("HTTP/1.1 200 OK\n"
494 "Via: 1.1 Chrome-Compression-Proxy\n");
495 HeadersToRaw(&raw_headers);
496 scoped_ptr<net::URLRequest> fake_request(
497 CreateURLRequestWithResponseHeaders(GURL("http://www.google.com/"),
498 raw_headers));
499 if (test_cases[i].is_load_bypass_proxy) {
500 fake_request->SetLoadFlags(fake_request->load_flags() |
501 net::LOAD_BYPASS_PROXY);
502 }
503 if (test_cases[i].is_main_frame) {
504 fake_request->SetLoadFlags(fake_request->load_flags() |
505 net::LOAD_MAIN_FRAME);
506 }
507
508 int net_error_int = static_cast<int>(test_cases[i].net_error);
509 if (test_cases[i].net_error != net::OK) {
510 fake_request->CancelWithError(net_error_int);
511 }
512
513 DataReductionProxyTypeInfo proxy_info;
514 proxy_info.is_fallback = test_cases[i].is_fallback;
515 EXPECT_CALL(*config(), WasDataReductionProxyUsed(fake_request.get(),
516 testing::NotNull()))
517 .WillRepeatedly(testing::DoAll(testing::SetArgPointee<1>(proxy_info),
518 Return(test_cases[i].was_proxy_used)));
519
520 usage_stats->OnUrlRequestCompleted(fake_request.get(), false);
521
522 if (test_cases[i].was_proxy_used && !test_cases[i].is_load_bypass_proxy &&
523 !test_cases[i].is_fallback) {
524 histogram_tester.ExpectUniqueSample(
525 kPrimaryHistogramName, -net_error_int, 1);
526 } else {
527 histogram_tester.ExpectTotalCount(kPrimaryHistogramName, 0);
528 }
529 if (test_cases[i].was_proxy_used && !test_cases[i].is_load_bypass_proxy &&
530 test_cases[i].is_fallback) {
531 histogram_tester.ExpectUniqueSample(
532 kFallbackHistogramName, -net_error_int, 1);
533 } else {
534 histogram_tester.ExpectTotalCount(kFallbackHistogramName, 0);
535 }
536 if (test_cases[i].was_proxy_used && !test_cases[i].is_load_bypass_proxy &&
537 !test_cases[i].is_fallback && test_cases[i].is_main_frame) {
538 histogram_tester.ExpectUniqueSample(
539 kPrimaryMainFrameHistogramName, -net_error_int, 1);
540 } else {
541 histogram_tester.ExpectTotalCount(kPrimaryMainFrameHistogramName, 0);
542 }
543 if (test_cases[i].was_proxy_used && !test_cases[i].is_load_bypass_proxy &&
544 test_cases[i].is_fallback && test_cases[i].is_main_frame) {
545 histogram_tester.ExpectUniqueSample(
546 kFallbackMainFrameHistogramName, -net_error_int, 1);
547 } else {
548 histogram_tester.ExpectTotalCount(kFallbackMainFrameHistogramName, 0);
549 }
550 }
551 }
552
553 // End-to-end tests for the DataReductionProxy.BypassedBytes histograms.
554 class DataReductionProxyUsageStatsEndToEndTest : public testing::Test {
555 public:
556 DataReductionProxyUsageStatsEndToEndTest()
557 : context_(true), context_storage_(&context_) {}
558
559 ~DataReductionProxyUsageStatsEndToEndTest() override {
560 drp_test_context_->io_data()->ShutdownOnUIThread();
561 drp_test_context_->RunUntilIdle();
562 }
563
564 void SetUp() override {
565 // Only use the primary data reduction proxy in order to make it easier to
566 // test bypassed bytes due to proxy fallbacks. This way, a test just needs
567 // to cause one proxy fallback in order for the data reduction proxy to be
568 // fully bypassed.
569 drp_test_context_ =
570 DataReductionProxyTestContext::Builder()
571 .WithParamsFlags(DataReductionProxyParams::kAllowed)
572 .WithParamsDefinitions(
573 TestDataReductionProxyParams::HAS_EVERYTHING &
574 ~TestDataReductionProxyParams::HAS_DEV_ORIGIN &
575 ~TestDataReductionProxyParams::HAS_DEV_FALLBACK_ORIGIN)
576 .WithURLRequestContext(&context_)
577 .WithMockClientSocketFactory(&mock_socket_factory_)
578 .Build();
579 drp_test_context_->AttachToURLRequestContext(&context_storage_);
580 context_.set_client_socket_factory(&mock_socket_factory_);
581 }
582
583 // Create and execute a fake request using the data reduction proxy stack.
584 // Passing in nullptr for |retry_response_headers| indicates that the request
585 // is not expected to be retried.
586 void CreateAndExecuteRequest(const GURL& url,
587 const char* initial_response_headers,
588 const char* initial_response_body,
589 const char* retry_response_headers,
590 const char* retry_response_body) {
591 // Support HTTPS URLs.
592 net::SSLSocketDataProvider ssl_socket_data_provider(net::ASYNC, net::OK);
593 if (url.SchemeIsSecure()) {
594 mock_socket_factory_.AddSSLSocketDataProvider(&ssl_socket_data_provider);
595 }
596
597 // Prepare for the initial response.
598 MockRead initial_data_reads[] = {
599 MockRead(initial_response_headers),
600 MockRead(initial_response_body),
601 MockRead(net::SYNCHRONOUS, net::OK),
602 };
603 net::StaticSocketDataProvider initial_socket_data_provider(
604 initial_data_reads, arraysize(initial_data_reads), nullptr, 0);
605 mock_socket_factory_.AddSocketDataProvider(&initial_socket_data_provider);
606
607 // Prepare for the response from retrying the request, if applicable.
608 // |retry_data_reads| and |retry_socket_data_provider| are out here so that
609 // they stay in scope for when the request is executed.
610 std::vector<MockRead> retry_data_reads;
611 scoped_ptr<net::StaticSocketDataProvider> retry_socket_data_provider;
612 if (retry_response_headers) {
613 retry_data_reads.push_back(MockRead(retry_response_headers));
614 retry_data_reads.push_back(MockRead(retry_response_body));
615 retry_data_reads.push_back(MockRead(net::SYNCHRONOUS, net::OK));
616
617 retry_socket_data_provider.reset(new net::StaticSocketDataProvider(
618 &retry_data_reads.front(), retry_data_reads.size(), nullptr, 0));
619 mock_socket_factory_.AddSocketDataProvider(
620 retry_socket_data_provider.get());
621 }
622
623 scoped_ptr<net::URLRequest> request(
624 context_.CreateRequest(url, net::IDLE, &delegate_));
625 request->set_method("GET");
626 request->SetLoadFlags(net::LOAD_NORMAL);
627 request->Start();
628 drp_test_context_->RunUntilIdle();
629 }
630
631 void set_proxy_service(net::ProxyService* proxy_service) {
632 context_.set_proxy_service(proxy_service);
633 }
634
635 void set_host_resolver(net::HostResolver* host_resolver) {
636 context_.set_host_resolver(host_resolver);
637 }
638
639 const DataReductionProxySettings* settings() const {
640 return drp_test_context_->settings();
641 }
642
643 TestDataReductionProxyConfig* config() const {
644 return drp_test_context_->config();
645 }
646
647 void ClearBadProxies() {
648 context_.proxy_service()->ClearBadProxiesCache();
649 }
650
651 void InitializeContext() {
652 context_.Init();
653 drp_test_context_->EnableDataReductionProxyWithSecureProxyCheckSuccess();
654 }
655
656 void ExpectOtherBypassedBytesHistogramsEmpty(
657 const base::HistogramTester& histogram_tester,
658 const std::set<std::string>& excluded_histograms) const {
659 const std::string kHistograms[] = {
660 "DataReductionProxy.BypassedBytes.NotBypassed",
661 "DataReductionProxy.BypassedBytes.SSL",
662 "DataReductionProxy.BypassedBytes.LocalBypassRules",
663 "DataReductionProxy.BypassedBytes.ProxyOverridden",
664 "DataReductionProxy.BypassedBytes.Current",
665 "DataReductionProxy.BypassedBytes.ShortAll",
666 "DataReductionProxy.BypassedBytes.ShortTriggeringRequest",
667 "DataReductionProxy.BypassedBytes.ShortAudioVideo",
668 "DataReductionProxy.BypassedBytes.MediumAll",
669 "DataReductionProxy.BypassedBytes.MediumTriggeringRequest",
670 "DataReductionProxy.BypassedBytes.LongAll",
671 "DataReductionProxy.BypassedBytes.LongTriggeringRequest",
672 "DataReductionProxy.BypassedBytes.MissingViaHeader4xx",
673 "DataReductionProxy.BypassedBytes.MissingViaHeaderOther",
674 "DataReductionProxy.BypassedBytes.Malformed407",
675 "DataReductionProxy.BypassedBytes.Status500HttpInternalServerError",
676 "DataReductionProxy.BypassedBytes.Status502HttpBadGateway",
677 "DataReductionProxy.BypassedBytes.Status503HttpServiceUnavailable",
678 "DataReductionProxy.BypassedBytes.NetworkErrorOther",
679 };
680
681 for (const std::string& histogram : kHistograms) {
682 if (excluded_histograms.find(histogram) ==
683 excluded_histograms.end()) {
684 histogram_tester.ExpectTotalCount(histogram, 0);
685 }
686 }
687 }
688
689 void ExpectOtherBypassedBytesHistogramsEmpty(
690 const base::HistogramTester& histogram_tester,
691 const std::string& excluded_histogram) const {
692 std::set<std::string> excluded_histograms;
693 excluded_histograms.insert(excluded_histogram);
694 ExpectOtherBypassedBytesHistogramsEmpty(histogram_tester,
695 excluded_histograms);
696 }
697
698 void ExpectOtherBypassedBytesHistogramsEmpty(
699 const base::HistogramTester& histogram_tester,
700 const std::string& first_excluded_histogram,
701 const std::string& second_excluded_histogram) const {
702 std::set<std::string> excluded_histograms;
703 excluded_histograms.insert(first_excluded_histogram);
704 excluded_histograms.insert(second_excluded_histogram);
705 ExpectOtherBypassedBytesHistogramsEmpty(histogram_tester,
706 excluded_histograms);
707 }
708
709 private:
710 net::TestDelegate delegate_;
711 net::MockClientSocketFactory mock_socket_factory_;
712 net::TestURLRequestContext context_;
713 net::URLRequestContextStorage context_storage_;
714 scoped_ptr<DataReductionProxyTestContext> drp_test_context_;
715 };
716
717 TEST_F(DataReductionProxyUsageStatsEndToEndTest, BypassedBytesNoRetry) {
718 struct TestCase {
719 GURL url;
720 const char* histogram_name;
721 const char* initial_response_headers;
722 };
723 const TestCase test_cases[] = {
724 { GURL("http://foo.com"),
725 "DataReductionProxy.BypassedBytes.NotBypassed",
726 "HTTP/1.1 200 OK\r\n"
727 "Via: 1.1 Chrome-Compression-Proxy\r\n\r\n",
728 },
729 { GURL("https://foo.com"),
730 "DataReductionProxy.BypassedBytes.SSL",
731 "HTTP/1.1 200 OK\r\n\r\n",
732 },
733 { GURL("http://localhost"),
734 "DataReductionProxy.BypassedBytes.LocalBypassRules",
735 "HTTP/1.1 200 OK\r\n\r\n",
736 },
737 };
738
739 InitializeContext();
740 for (const TestCase& test_case : test_cases) {
741 ClearBadProxies();
742 base::HistogramTester histogram_tester;
743 CreateAndExecuteRequest(test_case.url, test_case.initial_response_headers,
744 kBody.c_str(), nullptr, nullptr);
745
746 histogram_tester.ExpectUniqueSample(test_case.histogram_name, kBody.size(),
747 1);
748 ExpectOtherBypassedBytesHistogramsEmpty(histogram_tester,
749 test_case.histogram_name);
750 }
751 }
752
753 TEST_F(DataReductionProxyUsageStatsEndToEndTest, BypassedBytesProxyOverridden) {
754 scoped_ptr<net::ProxyService> proxy_service(
755 net::ProxyService::CreateFixed("http://test.com:80"));
756 set_proxy_service(proxy_service.get());
757 InitializeContext();
758
759 base::HistogramTester histogram_tester;
760 CreateAndExecuteRequest(GURL("http://foo.com"), "HTTP/1.1 200 OK\r\n\r\n",
761 kBody.c_str(), nullptr, nullptr);
762
763 histogram_tester.ExpectUniqueSample(
764 "DataReductionProxy.BypassedBytes.ProxyOverridden", kBody.size(), 1);
765 ExpectOtherBypassedBytesHistogramsEmpty(
766 histogram_tester, "DataReductionProxy.BypassedBytes.ProxyOverridden");
767 }
768
769 TEST_F(DataReductionProxyUsageStatsEndToEndTest, BypassedBytesCurrent) {
770 InitializeContext();
771 base::HistogramTester histogram_tester;
772 CreateAndExecuteRequest(GURL("http://foo.com"),
773 "HTTP/1.1 502 Bad Gateway\r\n"
774 "Via: 1.1 Chrome-Compression-Proxy\r\n"
775 "Chrome-Proxy: block-once\r\n\r\n",
776 kErrorBody.c_str(), "HTTP/1.1 200 OK\r\n\r\n",
777 kBody.c_str());
778
779 histogram_tester.ExpectUniqueSample(
780 "DataReductionProxy.BypassedBytes.Current", kBody.size(), 1);
781 ExpectOtherBypassedBytesHistogramsEmpty(
782 histogram_tester, "DataReductionProxy.BypassedBytes.Current");
783 }
784
785 TEST_F(DataReductionProxyUsageStatsEndToEndTest, BypassedBytesShortAudioVideo) {
786 InitializeContext();
787 base::HistogramTester histogram_tester;
788 CreateAndExecuteRequest(GURL("http://foo.com"),
789 "HTTP/1.1 502 Bad Gateway\r\n"
790 "Via: 1.1 Chrome-Compression-Proxy\r\n"
791 "Chrome-Proxy: block=1\r\n\r\n",
792 kErrorBody.c_str(),
793 "HTTP/1.1 200 OK\r\n"
794 "Content-Type: video/mp4\r\n\r\n",
795 kBody.c_str());
796
797 histogram_tester.ExpectUniqueSample(
798 "DataReductionProxy.BypassedBytes.ShortAudioVideo", kBody.size(), 1);
799 ExpectOtherBypassedBytesHistogramsEmpty(
800 histogram_tester, "DataReductionProxy.BypassedBytes.ShortAudioVideo");
801 }
802
803 TEST_F(DataReductionProxyUsageStatsEndToEndTest, BypassedBytesExplicitBypass) {
804 struct TestCase {
805 const char* triggering_histogram_name;
806 const char* all_histogram_name;
807 const char* initial_response_headers;
808 };
809 const TestCase test_cases[] = {
810 { "DataReductionProxy.BypassedBytes.ShortTriggeringRequest",
811 "DataReductionProxy.BypassedBytes.ShortAll",
812 "HTTP/1.1 502 Bad Gateway\r\n"
813 "Via: 1.1 Chrome-Compression-Proxy\r\n"
814 "Chrome-Proxy: block=1\r\n\r\n",
815 },
816 { "DataReductionProxy.BypassedBytes.MediumTriggeringRequest",
817 "DataReductionProxy.BypassedBytes.MediumAll",
818 "HTTP/1.1 502 Bad Gateway\r\n"
819 "Via: 1.1 Chrome-Compression-Proxy\r\n"
820 "Chrome-Proxy: block=0\r\n\r\n",
821 },
822 { "DataReductionProxy.BypassedBytes.LongTriggeringRequest",
823 "DataReductionProxy.BypassedBytes.LongAll",
824 "HTTP/1.1 502 Bad Gateway\r\n"
825 "Via: 1.1 Chrome-Compression-Proxy\r\n"
826 "Chrome-Proxy: block=3600\r\n\r\n",
827 },
828 };
829
830 InitializeContext();
831 for (const TestCase& test_case : test_cases) {
832 ClearBadProxies();
833 base::HistogramTester histogram_tester;
834
835 CreateAndExecuteRequest(
836 GURL("http://foo.com"), test_case.initial_response_headers,
837 kErrorBody.c_str(), "HTTP/1.1 200 OK\r\n\r\n", kBody.c_str());
838 // The first request caused the proxy to be marked as bad, so this second
839 // request should not come through the proxy.
840 CreateAndExecuteRequest(GURL("http://bar.com"), "HTTP/1.1 200 OK\r\n\r\n",
841 kNextBody.c_str(), nullptr, nullptr);
842
843 histogram_tester.ExpectUniqueSample(test_case.triggering_histogram_name,
844 kBody.size(), 1);
845 histogram_tester.ExpectUniqueSample(test_case.all_histogram_name,
846 kNextBody.size(), 1);
847 ExpectOtherBypassedBytesHistogramsEmpty(histogram_tester,
848 test_case.triggering_histogram_name,
849 test_case.all_histogram_name);
850 }
851 }
852
853 TEST_F(DataReductionProxyUsageStatsEndToEndTest,
854 BypassedBytesClientSideFallback) {
855 struct TestCase {
856 const char* histogram_name;
857 const char* initial_response_headers;
858 };
859 const TestCase test_cases[] = {
860 { "DataReductionProxy.BypassedBytes.MissingViaHeader4xx",
861 "HTTP/1.1 414 Request-URI Too Long\r\n\r\n",
862 },
863 { "DataReductionProxy.BypassedBytes.MissingViaHeaderOther",
864 "HTTP/1.1 200 OK\r\n\r\n",
865 },
866 { "DataReductionProxy.BypassedBytes.Malformed407",
867 "HTTP/1.1 407 Proxy Authentication Required\r\n\r\n",
868 },
869 { "DataReductionProxy.BypassedBytes.Status500HttpInternalServerError",
870 "HTTP/1.1 500 Internal Server Error\r\n\r\n",
871 },
872 { "DataReductionProxy.BypassedBytes.Status502HttpBadGateway",
873 "HTTP/1.1 502 Bad Gateway\r\n\r\n",
874 },
875 { "DataReductionProxy.BypassedBytes.Status503HttpServiceUnavailable",
876 "HTTP/1.1 503 Service Unavailable\r\n\r\n",
877 },
878 };
879
880 InitializeContext();
881 for (const TestCase& test_case : test_cases) {
882 ClearBadProxies();
883 base::HistogramTester histogram_tester;
884
885 CreateAndExecuteRequest(
886 GURL("http://foo.com"), test_case.initial_response_headers,
887 kErrorBody.c_str(), "HTTP/1.1 200 OK\r\n\r\n", kBody.c_str());
888 // The first request caused the proxy to be marked as bad, so this second
889 // request should not come through the proxy.
890 CreateAndExecuteRequest(GURL("http://bar.com"), "HTTP/1.1 200 OK\r\n\r\n",
891 kNextBody.c_str(), nullptr, nullptr);
892
893 histogram_tester.ExpectTotalCount(test_case.histogram_name, 2);
894 histogram_tester.ExpectBucketCount(test_case.histogram_name, kBody.size(),
895 1);
896 histogram_tester.ExpectBucketCount(test_case.histogram_name,
897 kNextBody.size(), 1);
898 ExpectOtherBypassedBytesHistogramsEmpty(histogram_tester,
899 test_case.histogram_name);
900 }
901 }
902
903 TEST_F(DataReductionProxyUsageStatsEndToEndTest, BypassedBytesNetErrorOther) {
904 // Make the data reduction proxy host fail to resolve.
905 scoped_ptr<net::MockHostResolver> host_resolver(new net::MockHostResolver());
906 host_resolver->rules()->AddSimulatedFailure(
907 config()->test_params()->origin().host_port_pair().host());
908 set_host_resolver(host_resolver.get());
909 InitializeContext();
910
911 base::HistogramTester histogram_tester;
912 CreateAndExecuteRequest(GURL("http://foo.com"), "HTTP/1.1 200 OK\r\n\r\n",
913 kBody.c_str(), nullptr, nullptr);
914
915 histogram_tester.ExpectUniqueSample(
916 "DataReductionProxy.BypassedBytes.NetworkErrorOther", kBody.size(), 1);
917 ExpectOtherBypassedBytesHistogramsEmpty(
918 histogram_tester, "DataReductionProxy.BypassedBytes.NetworkErrorOther");
919 histogram_tester.ExpectUniqueSample(
920 "DataReductionProxy.BypassOnNetworkErrorPrimary",
921 -net::ERR_PROXY_CONNECTION_FAILED, 1);
922 }
923
924 } // namespace data_reduction_proxy
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698