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.
5 #include "components/data_reduction_proxy/common/data_reduction_proxy_headers.h"
9 #include "components/data_reduction_proxy/common/data_reduction_proxy_headers_test_utils.h"
10 #include "net/http/http_response_headers.h"
11 #include "net/proxy/proxy_service.h"
12 #include "testing/gtest/include/gtest/gtest.h"
14 namespace data_reduction_proxy {
16 class DataReductionProxyHeadersTest : public testing::Test {};
18 TEST_F(DataReductionProxyHeadersTest, GetDataReductionProxyActionValue) {
21 std::string action_key;
23 std::string expected_action_value;
26 "Content-Length: 999\n",
32 "connection: keep-alive\n"
33 "Content-Length: 999\n",
39 "connection: keep-alive\n"
40 "Chrome-Proxy: bypass=86400\n"
41 "Content-Length: 999\n",
47 "connection: keep-alive\n"
48 "Chrome-Proxy: bypass86400\n"
49 "Content-Length: 999\n",
55 "connection: keep-alive\n"
56 "Chrome-Proxy: bypass=0\n"
57 "Content-Length: 999\n",
63 "connection: keep-alive\n"
64 "Chrome-Proxy: bypass=1500\n"
65 "Chrome-Proxy: bypass=86400\n"
66 "Content-Length: 999\n",
72 "connection: keep-alive\n"
73 "Chrome-Proxy: block=1500, block=3600\n"
74 "Content-Length: 999\n",
80 "connection: proxy-bypass\n"
81 "Chrome-Proxy: key=123 \n"
82 "Content-Length: 999\n",
88 "connection: proxy-bypass\n"
89 "Chrome-Proxy: block-once\n"
90 "Content-Length: 999\n",
96 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(tests); ++i) {
97 std::string headers(tests[i].headers);
98 HeadersToRaw(&headers);
99 scoped_refptr<net::HttpResponseHeaders> parsed(
100 new net::HttpResponseHeaders(headers));
102 std::string action_value;
103 bool has_action_key = GetDataReductionProxyActionValue(
104 parsed.get(), tests[i].action_key, &action_value);
105 EXPECT_EQ(tests[i].expected_result, has_action_key);
106 if (has_action_key) {
107 EXPECT_EQ(tests[i].expected_action_value, action_value);
112 TEST_F(DataReductionProxyHeadersTest, GetProxyBypassInfo) {
115 bool expected_result;
116 int64 expected_retry_delay;
117 bool expected_bypass_all;
118 bool expected_mark_proxies_as_bad;
120 { "HTTP/1.1 200 OK\n"
121 "Content-Length: 999\n",
127 { "HTTP/1.1 200 OK\n"
128 "connection: keep-alive\n"
129 "Content-Length: 999\n",
135 { "HTTP/1.1 200 OK\n"
136 "connection: keep-alive\n"
137 "Chrome-Proxy: bypass=86400\n"
138 "Content-Length: 999\n",
144 { "HTTP/1.1 200 OK\n"
145 "connection: keep-alive\n"
146 "Chrome-Proxy: bypass=-1\n"
147 "Content-Length: 999\n",
153 { "HTTP/1.1 200 OK\n"
154 "connection: keep-alive\n"
155 "Chrome-Proxy: bypass=xyz\n"
156 "Content-Length: 999\n",
162 { "HTTP/1.1 200 OK\n"
163 "connection: keep-alive\n"
164 "Chrome-Proxy: bypass\n"
165 "Content-Length: 999\n",
171 { "HTTP/1.1 200 OK\n"
172 "connection: keep-alive\n"
173 "Chrome-Proxy: foo=abc, bypass=86400\n"
174 "Content-Length: 999\n",
180 { "HTTP/1.1 200 OK\n"
181 "connection: keep-alive\n"
182 "Chrome-Proxy: bypass=86400, bar=abc\n"
183 "Content-Length: 999\n",
189 { "HTTP/1.1 200 OK\n"
190 "connection: keep-alive\n"
191 "Chrome-Proxy: bypass=3600\n"
192 "Chrome-Proxy: bypass=86400\n"
193 "Content-Length: 999\n",
199 { "HTTP/1.1 200 OK\n"
200 "connection: keep-alive\n"
201 "Chrome-Proxy: bypass=3600, bypass=86400\n"
202 "Content-Length: 999\n",
208 { "HTTP/1.1 200 OK\n"
209 "connection: keep-alive\n"
210 "Chrome-Proxy: bypass=, bypass=86400\n"
211 "Content-Length: 999\n",
217 { "HTTP/1.1 200 OK\n"
218 "connection: keep-alive\n"
219 "Chrome-Proxy: bypass\n"
220 "Chrome-Proxy: bypass=86400\n"
221 "Content-Length: 999\n",
227 { "HTTP/1.1 200 OK\n"
228 "connection: keep-alive\n"
229 "Chrome-Proxy: block=, block=3600\n"
230 "Content-Length: 999\n",
236 { "HTTP/1.1 200 OK\n"
237 "connection: keep-alive\n"
238 "Chrome-Proxy: bypass=86400, block=3600\n"
239 "Content-Length: 999\n",
245 { "HTTP/1.1 200 OK\n"
246 "connection: proxy-bypass\n"
247 "Chrome-Proxy: block=, bypass=86400\n"
248 "Content-Length: 999\n",
254 { "HTTP/1.1 200 OK\n"
255 "connection: proxy-bypass\n"
256 "Chrome-Proxy: block=-1\n"
257 "Content-Length: 999\n",
263 { "HTTP/1.1 200 OK\n"
264 "connection: proxy-bypass\n"
265 "Chrome-Proxy: block=99999999999999999999\n"
266 "Content-Length: 999\n",
272 { "HTTP/1.1 200 OK\n"
273 "connection: keep-alive\n"
274 "Chrome-Proxy: block-once\n"
275 "Content-Length: 999\n",
281 { "HTTP/1.1 200 OK\n"
282 "connection: keep-alive\n"
283 "Chrome-Proxy: block-once=\n"
284 "Content-Length: 999\n",
290 { "HTTP/1.1 200 OK\n"
291 "connection: keep-alive\n"
292 "Chrome-Proxy: block-once=10\n"
293 "Content-Length: 999\n",
299 { "HTTP/1.1 200 OK\n"
300 "connection: keep-alive\n"
301 "Chrome-Proxy: block-once, bypass=86400, block=3600\n"
302 "Content-Length: 999\n",
308 { "HTTP/1.1 200 OK\n"
309 "connection: keep-alive\n"
310 "Chrome-Proxy: block-once\n"
311 "Chrome-Proxy: bypass=86400, block=3600\n"
312 "Content-Length: 999\n",
318 { "HTTP/1.1 200 OK\n"
319 "connection: keep-alive\n"
320 "Chrome-Proxy: block-once, bypass=86400\n"
321 "Content-Length: 999\n",
327 { "HTTP/1.1 200 OK\n"
328 "connection: keep-alive\n"
329 "Chrome-Proxy: block-once, block=3600\n"
330 "Content-Length: 999\n",
336 { "HTTP/1.1 200 OK\n"
337 "connection: keep-alive\n"
338 "Chrome-Proxy: bypass=, block=, block-once\n"
339 "Content-Length: 999\n",
346 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(tests); ++i) {
347 std::string headers(tests[i].headers);
348 HeadersToRaw(&headers);
349 scoped_refptr<net::HttpResponseHeaders> parsed(
350 new net::HttpResponseHeaders(headers));
352 DataReductionProxyInfo data_reduction_proxy_info;
354 tests[i].expected_result,
355 ParseHeadersAndSetProxyInfo(parsed.get(), &data_reduction_proxy_info));
356 EXPECT_EQ(tests[i].expected_retry_delay,
357 data_reduction_proxy_info.bypass_duration.InSeconds());
358 EXPECT_EQ(tests[i].expected_bypass_all,
359 data_reduction_proxy_info.bypass_all);
360 EXPECT_EQ(tests[i].expected_mark_proxies_as_bad,
361 data_reduction_proxy_info.mark_proxies_as_bad);
365 TEST_F(DataReductionProxyHeadersTest, ParseHeadersAndSetProxyInfo) {
366 std::string headers =
368 "connection: keep-alive\n"
369 "Chrome-Proxy: bypass=0\n"
370 "Content-Length: 999\n";
371 HeadersToRaw(&headers);
372 scoped_refptr<net::HttpResponseHeaders> parsed(
373 new net::HttpResponseHeaders(headers));
375 DataReductionProxyInfo data_reduction_proxy_info;
377 ParseHeadersAndSetProxyInfo(parsed.get(), &data_reduction_proxy_info));
378 EXPECT_LE(60, data_reduction_proxy_info.bypass_duration.InSeconds());
379 EXPECT_GE(5 * 60, data_reduction_proxy_info.bypass_duration.InSeconds());
380 EXPECT_FALSE(data_reduction_proxy_info.bypass_all);
383 TEST_F(DataReductionProxyHeadersTest, HasDataReductionProxyViaHeader) {
386 bool expected_result;
387 bool expected_has_intermediary;
388 bool ignore_intermediary;
390 { "HTTP/1.1 200 OK\n"
391 "Via: 1.1 Chrome-Proxy\n",
396 { "HTTP/1.1 200 OK\n"
402 { "HTTP/1.1 200 OK\n"
403 "Via: 1.1 Chrome-Compression-Proxy\n",
408 { "HTTP/1.1 200 OK\n"
409 "Via: 1.0 Chrome-Compression-Proxy\n",
414 { "HTTP/1.1 200 OK\n"
415 "Via: 1.1 Foo-Bar, 1.1 Chrome-Compression-Proxy\n",
420 { "HTTP/1.1 200 OK\n"
421 "Via: 1.1 Chrome-Compression-Proxy, 1.1 Bar-Foo\n",
426 { "HTTP/1.1 200 OK\n"
427 "Via: 1.1 chrome-compression-proxy\n",
432 { "HTTP/1.1 200 OK\n"
434 "Via: 1.1 Chrome-Compression-Proxy\n",
439 { "HTTP/1.1 200 OK\n"
440 "Via: 1.1 Chrome-Compression-Proxy\n"
441 "Via: 1.1 Foo-Bar\n",
446 { "HTTP/1.1 200 OK\n"
447 "Via: 1.1 Chrome-Proxy\n",
452 { "HTTP/1.1 200 OK\n"
453 "Via: 1.1 Chrome Compression Proxy\n",
458 { "HTTP/1.1 200 OK\n"
459 "Via: 1.1 Foo-Bar, 1.1 Chrome Compression Proxy\n",
464 { "HTTP/1.1 200 OK\n"
465 "Via: 1.1 Chrome Compression Proxy, 1.1 Bar-Foo\n",
470 { "HTTP/1.1 200 OK\n"
471 "Via: 1.1 chrome compression proxy\n",
476 { "HTTP/1.1 200 OK\n"
478 "Via: 1.1 Chrome Compression Proxy\n",
483 { "HTTP/1.1 200 OK\n"
484 "Via: 1.1 Chrome Compression Proxy\n"
485 "Via: 1.1 Foo-Bar\n",
490 { "HTTP/1.1 200 OK\n"
491 "Via: 1.1 Chrome Compression Proxy\n"
492 "Via: 1.1 Foo-Bar\n",
498 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(tests); ++i) {
499 std::string headers(tests[i].headers);
500 HeadersToRaw(&headers);
501 scoped_refptr<net::HttpResponseHeaders> parsed(
502 new net::HttpResponseHeaders(headers));
504 bool has_chrome_proxy_via_header, has_intermediary;
505 if (tests[i].ignore_intermediary) {
506 has_chrome_proxy_via_header =
507 HasDataReductionProxyViaHeader(parsed.get(), NULL);
510 has_chrome_proxy_via_header =
511 HasDataReductionProxyViaHeader(parsed.get(), &has_intermediary);
513 EXPECT_EQ(tests[i].expected_result, has_chrome_proxy_via_header);
514 if (has_chrome_proxy_via_header && !tests[i].ignore_intermediary) {
515 EXPECT_EQ(tests[i].expected_has_intermediary, has_intermediary);
520 TEST_F(DataReductionProxyHeadersTest, GetDataReductionProxyBypassEventType) {
523 DataReductionProxyBypassType expected_result;
525 { "HTTP/1.1 200 OK\n"
526 "Chrome-Proxy: bypass=0\n"
527 "Via: 1.1 Chrome-Compression-Proxy\n",
528 BYPASS_EVENT_TYPE_MEDIUM,
530 { "HTTP/1.1 200 OK\n"
531 "Chrome-Proxy: bypass=1\n"
532 "Via: 1.1 Chrome-Compression-Proxy\n",
533 BYPASS_EVENT_TYPE_SHORT,
535 { "HTTP/1.1 200 OK\n"
536 "Chrome-Proxy: bypass=59\n"
537 "Via: 1.1 Chrome-Compression-Proxy\n",
538 BYPASS_EVENT_TYPE_SHORT,
540 { "HTTP/1.1 200 OK\n"
541 "Chrome-Proxy: bypass=60\n"
542 "Via: 1.1 Chrome-Compression-Proxy\n",
543 BYPASS_EVENT_TYPE_MEDIUM,
545 { "HTTP/1.1 200 OK\n"
546 "Chrome-Proxy: bypass=300\n"
547 "Via: 1.1 Chrome-Compression-Proxy\n",
548 BYPASS_EVENT_TYPE_MEDIUM,
550 { "HTTP/1.1 200 OK\n"
551 "Chrome-Proxy: bypass=301\n"
552 "Via: 1.1 Chrome-Compression-Proxy\n",
553 BYPASS_EVENT_TYPE_LONG,
555 { "HTTP/1.1 200 OK\n"
556 "Chrome-Proxy: block-once\n"
557 "Via: 1.1 Chrome-Compression-Proxy\n",
558 BYPASS_EVENT_TYPE_CURRENT,
560 { "HTTP/1.1 500 Internal Server Error\n"
561 "Via: 1.1 Chrome-Compression-Proxy\n",
562 BYPASS_EVENT_TYPE_STATUS_500_HTTP_INTERNAL_SERVER_ERROR,
564 { "HTTP/1.1 501 Not Implemented\n"
565 "Via: 1.1 Chrome-Compression-Proxy\n",
566 BYPASS_EVENT_TYPE_MAX,
568 { "HTTP/1.1 502 Bad Gateway\n"
569 "Via: 1.1 Chrome-Compression-Proxy\n",
570 BYPASS_EVENT_TYPE_STATUS_502_HTTP_BAD_GATEWAY,
572 { "HTTP/1.1 503 Service Unavailable\n"
573 "Via: 1.1 Chrome-Compression-Proxy\n",
574 BYPASS_EVENT_TYPE_STATUS_503_HTTP_SERVICE_UNAVAILABLE,
576 { "HTTP/1.1 504 Gateway Timeout\n"
577 "Via: 1.1 Chrome-Compression-Proxy\n",
578 BYPASS_EVENT_TYPE_MAX,
580 { "HTTP/1.1 505 HTTP Version Not Supported\n"
581 "Via: 1.1 Chrome-Compression-Proxy\n",
582 BYPASS_EVENT_TYPE_MAX,
584 { "HTTP/1.1 304 Not Modified\n",
585 BYPASS_EVENT_TYPE_MAX,
587 { "HTTP/1.1 200 OK\n",
588 BYPASS_EVENT_TYPE_MISSING_VIA_HEADER_OTHER,
590 { "HTTP/1.1 200 OK\n"
591 "Chrome-Proxy: bypass=59\n",
592 BYPASS_EVENT_TYPE_SHORT,
594 { "HTTP/1.1 502 Bad Gateway\n",
595 BYPASS_EVENT_TYPE_STATUS_502_HTTP_BAD_GATEWAY,
597 { "HTTP/1.1 502 Bad Gateway\n"
598 "Chrome-Proxy: bypass=59\n",
599 BYPASS_EVENT_TYPE_SHORT,
601 { "HTTP/1.1 502 Bad Gateway\n"
602 "Chrome-Proxy: bypass=59\n",
603 BYPASS_EVENT_TYPE_SHORT,
605 { "HTTP/1.1 414 Request-URI Too Long\n",
606 BYPASS_EVENT_TYPE_MISSING_VIA_HEADER_4XX,
608 { "HTTP/1.1 414 Request-URI Too Long\n"
609 "Via: 1.1 Chrome-Compression-Proxy\n",
610 BYPASS_EVENT_TYPE_MAX,
612 { "HTTP/1.1 407 Proxy Authentication Required\n",
613 BYPASS_EVENT_TYPE_MALFORMED_407,
615 { "HTTP/1.1 407 Proxy Authentication Required\n"
616 "Proxy-Authenticate: Basic\n"
617 "Via: 1.1 Chrome-Compression-Proxy\n",
618 BYPASS_EVENT_TYPE_MAX,
621 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(tests); ++i) {
622 std::string headers(tests[i].headers);
623 HeadersToRaw(&headers);
624 scoped_refptr<net::HttpResponseHeaders> parsed(
625 new net::HttpResponseHeaders(headers));
626 DataReductionProxyInfo chrome_proxy_info;
628 tests[i].expected_result,
629 GetDataReductionProxyBypassType(parsed.get(), &chrome_proxy_info));
633 TEST_F(DataReductionProxyHeadersTest,
634 GetDataReductionProxyActionFingerprintChromeProxy) {
638 bool expected_fingerprint_exist;
639 std::string expected_fingerprint;
641 { "fingerprint doesn't exist",
643 "Chrome-Proxy: bypass=0\n",
647 { "fingerprint occurs once",
649 "Chrome-Proxy: bypass=1, fcp=fp\n",
653 { "fingerprint occurs twice",
655 "Chrome-Proxy: bypass=2, fcp=fp1, fcp=fp2\n",
660 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(tests); ++i) {
661 std::string headers(tests[i].headers);
662 HeadersToRaw(&headers);
663 scoped_refptr<net::HttpResponseHeaders> parsed(
664 new net::HttpResponseHeaders(headers));
666 std::string fingerprint;
667 bool fingerprint_exist = GetDataReductionProxyActionFingerprintChromeProxy(
668 parsed.get(), &fingerprint);
669 EXPECT_EQ(tests[i].expected_fingerprint_exist, fingerprint_exist)
672 if (fingerprint_exist)
673 EXPECT_EQ(tests[i].expected_fingerprint, fingerprint) << tests[i].label;
677 TEST_F(DataReductionProxyHeadersTest,
678 GetDataReductionProxyActionFingerprintVia) {
682 bool expected_fingerprint_exist;
683 std::string expected_fingerprint;
685 { "fingerprint doesn't exist",
687 "Chrome-Proxy: bypass=0\n",
691 { "fingerprint occurs once",
693 "Chrome-Proxy: bypass=1, fvia=fvia\n",
697 { "fingerprint occurs twice",
699 "Chrome-Proxy: bypass=2, fvia=fvia1, fvia=fvia2\n",
704 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(tests); ++i) {
705 std::string headers(tests[i].headers);
706 HeadersToRaw(&headers);
707 scoped_refptr<net::HttpResponseHeaders> parsed(
708 new net::HttpResponseHeaders(headers));
710 std::string fingerprint;
711 bool fingerprint_exist =
712 GetDataReductionProxyActionFingerprintVia(parsed.get(), &fingerprint);
713 EXPECT_EQ(tests[i].expected_fingerprint_exist, fingerprint_exist)
716 if (fingerprint_exist)
717 EXPECT_EQ(tests[i].expected_fingerprint, fingerprint) << tests[i].label;
721 TEST_F(DataReductionProxyHeadersTest,
722 GetDataReductionProxyActionFingerprintOtherHeaders) {
726 bool expected_fingerprint_exist;
727 std::string expected_fingerprint;
729 { "fingerprint doesn't exist",
731 "Chrome-Proxy: bypass=0\n",
735 { "fingerprint occurs once",
737 "Chrome-Proxy: bypass=1, foh=foh\n",
741 { "fingerprint occurs twice",
743 "Chrome-Proxy: bypass=2, foh=foh1, foh=foh2\n",
748 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(tests); ++i) {
749 std::string headers(tests[i].headers);
750 HeadersToRaw(&headers);
751 scoped_refptr<net::HttpResponseHeaders> parsed(
752 new net::HttpResponseHeaders(headers));
754 std::string fingerprint;
755 bool fingerprint_exist = GetDataReductionProxyActionFingerprintOtherHeaders(
756 parsed.get(), &fingerprint);
757 EXPECT_EQ(tests[i].expected_fingerprint_exist, fingerprint_exist)
760 if (fingerprint_exist)
761 EXPECT_EQ(tests[i].expected_fingerprint, fingerprint) << tests[i].label;
765 TEST_F(DataReductionProxyHeadersTest,
766 GetDataReductionProxyActionFingerprintContentLength) {
770 bool expected_fingerprint_exist;
771 std::string expected_fingerprint;
773 { "fingerprint doesn't exist",
775 "Chrome-Proxy: bypass=0\n",
779 { "fingerprint occurs once",
781 "Chrome-Proxy: bypass=1, fcl=fcl\n",
785 { "fingerprint occurs twice",
787 "Chrome-Proxy: bypass=2, fcl=fcl1, fcl=fcl2\n",
792 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(tests); ++i) {
793 std::string headers(tests[i].headers);
794 HeadersToRaw(&headers);
795 scoped_refptr<net::HttpResponseHeaders> parsed(
796 new net::HttpResponseHeaders(headers));
798 std::string fingerprint;
799 bool fingerprint_exist =
800 GetDataReductionProxyActionFingerprintContentLength(parsed.get(),
802 EXPECT_EQ(tests[i].expected_fingerprint_exist, fingerprint_exist)
805 if (fingerprint_exist)
806 EXPECT_EQ(tests[i].expected_fingerprint, fingerprint) << tests[i].label;
810 TEST_F(DataReductionProxyHeadersTest,
811 GetDataReductionProxyHeaderWithFingerprintRemoved) {
815 std::string expected_output_values_string;
818 "Checks the case that there is no Chrome-Proxy header's fingerprint.",
820 "Chrome-Proxy: 1,2,3,5\n",
824 "Checks the case that there is Chrome-Proxy header's fingerprint.",
826 "Chrome-Proxy: 1,2,3,fcp=4,5\n",
830 "Checks the case that there is Chrome-Proxy header's fingerprint, and it"
831 "occurs at the end.",
833 "Chrome-Proxy: 1,2,3,fcp=4,",
837 "Checks the case that there is Chrome-Proxy header's fingerprint, and it"
838 "occurs at the beginning.",
840 "Chrome-Proxy: fcp=1,2,3,",
844 "Checks the case that value is longer than prefix.",
846 "Chrome-Proxy: fcp=1,fcp!=1,fcp!=2,fcpfcp=3",
847 "fcp!=1,fcp!=2,fcpfcp=3,",
850 "Checks the case that value is shorter than prefix but similar.",
852 "Chrome-Proxy: fcp=1,fcp,fcp=",
857 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(test); ++i) {
858 std::string headers(test[i].headers);
859 HeadersToRaw(&headers);
860 scoped_refptr<net::HttpResponseHeaders> parsed(
861 new net::HttpResponseHeaders(headers));
863 std::vector<std::string> output_values;
864 GetDataReductionProxyHeaderWithFingerprintRemoved(parsed.get(),
867 std::string output_values_string;
868 for (size_t j = 0; j < output_values.size(); ++j)
869 output_values_string += output_values[j] + ",";
871 EXPECT_EQ(test[i].expected_output_values_string, output_values_string)
876 } // namespace data_reduction_proxy