Home | History | Annotate | Download | only in common
      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/common/data_reduction_proxy_headers.h"
      6 
      7 #include <vector>
      8 
      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"
     13 
     14 namespace data_reduction_proxy {
     15 
     16 class DataReductionProxyHeadersTest : public testing::Test {};
     17 
     18 TEST_F(DataReductionProxyHeadersTest, GetDataReductionProxyActionValue) {
     19   const struct {
     20      const char* headers;
     21      std::string action_key;
     22      bool expected_result;
     23      std::string expected_action_value;
     24   } tests[] = {
     25     { "HTTP/1.1 200 OK\n"
     26       "Content-Length: 999\n",
     27       "a",
     28       false,
     29       "",
     30     },
     31     { "HTTP/1.1 200 OK\n"
     32       "connection: keep-alive\n"
     33       "Content-Length: 999\n",
     34       "a",
     35       false,
     36       "",
     37     },
     38     { "HTTP/1.1 200 OK\n"
     39       "connection: keep-alive\n"
     40       "Chrome-Proxy: bypass=86400\n"
     41       "Content-Length: 999\n",
     42       "bypass",
     43       true,
     44       "86400",
     45     },
     46     { "HTTP/1.1 200 OK\n"
     47       "connection: keep-alive\n"
     48       "Chrome-Proxy: bypass86400\n"
     49       "Content-Length: 999\n",
     50       "bypass",
     51       false,
     52       "",
     53     },
     54     { "HTTP/1.1 200 OK\n"
     55       "connection: keep-alive\n"
     56       "Chrome-Proxy: bypass=0\n"
     57       "Content-Length: 999\n",
     58       "bypass",
     59       true,
     60       "0",
     61     },
     62     { "HTTP/1.1 200 OK\n"
     63       "connection: keep-alive\n"
     64       "Chrome-Proxy: bypass=1500\n"
     65       "Chrome-Proxy: bypass=86400\n"
     66       "Content-Length: 999\n",
     67       "bypass",
     68       true,
     69       "1500",
     70     },
     71     { "HTTP/1.1 200 OK\n"
     72       "connection: keep-alive\n"
     73       "Chrome-Proxy: block=1500, block=3600\n"
     74       "Content-Length: 999\n",
     75       "block",
     76       true,
     77       "1500",
     78     },
     79     { "HTTP/1.1 200 OK\n"
     80       "connection: proxy-bypass\n"
     81       "Chrome-Proxy:    key=123   \n"
     82       "Content-Length: 999\n",
     83       "key",
     84       true,
     85       "123",
     86     },
     87     { "HTTP/1.1 200 OK\n"
     88       "connection: proxy-bypass\n"
     89       "Chrome-Proxy: block-once\n"
     90       "Content-Length: 999\n",
     91       "block-once",
     92       false,
     93       "",
     94     },
     95   };
     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));
    101 
    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);
    108     }
    109   }
    110 }
    111 
    112 TEST_F(DataReductionProxyHeadersTest, GetProxyBypassInfo) {
    113   const struct {
    114      const char* headers;
    115      bool expected_result;
    116      int64 expected_retry_delay;
    117      bool expected_bypass_all;
    118      bool expected_mark_proxies_as_bad;
    119   } tests[] = {
    120     { "HTTP/1.1 200 OK\n"
    121       "Content-Length: 999\n",
    122       false,
    123       0,
    124       false,
    125       false,
    126     },
    127     { "HTTP/1.1 200 OK\n"
    128       "connection: keep-alive\n"
    129       "Content-Length: 999\n",
    130       false,
    131       0,
    132       false,
    133       false,
    134     },
    135     { "HTTP/1.1 200 OK\n"
    136       "connection: keep-alive\n"
    137       "Chrome-Proxy: bypass=86400\n"
    138       "Content-Length: 999\n",
    139       true,
    140       86400,
    141       false,
    142       true,
    143     },
    144     { "HTTP/1.1 200 OK\n"
    145       "connection: keep-alive\n"
    146       "Chrome-Proxy: bypass=-1\n"
    147       "Content-Length: 999\n",
    148       false,
    149       0,
    150       false,
    151       false,
    152     },
    153     { "HTTP/1.1 200 OK\n"
    154       "connection: keep-alive\n"
    155       "Chrome-Proxy: bypass=xyz\n"
    156       "Content-Length: 999\n",
    157       false,
    158       0,
    159       false,
    160       false,
    161     },
    162     { "HTTP/1.1 200 OK\n"
    163       "connection: keep-alive\n"
    164       "Chrome-Proxy: bypass\n"
    165       "Content-Length: 999\n",
    166       false,
    167       0,
    168       false,
    169       false,
    170     },
    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",
    175       true,
    176       86400,
    177       false,
    178       true,
    179     },
    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",
    184       true,
    185       86400,
    186       false,
    187       true,
    188     },
    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",
    194       true,
    195       3600,
    196       false,
    197       true,
    198     },
    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",
    203       true,
    204       3600,
    205       false,
    206       true,
    207     },
    208     { "HTTP/1.1 200 OK\n"
    209       "connection: keep-alive\n"
    210       "Chrome-Proxy: bypass=, bypass=86400\n"
    211       "Content-Length: 999\n",
    212       true,
    213       86400,
    214       false,
    215       true,
    216     },
    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",
    222       true,
    223       86400,
    224       false,
    225       true,
    226     },
    227     { "HTTP/1.1 200 OK\n"
    228       "connection: keep-alive\n"
    229       "Chrome-Proxy: block=, block=3600\n"
    230       "Content-Length: 999\n",
    231       true,
    232       3600,
    233       true,
    234       true,
    235     },
    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",
    240       true,
    241       3600,
    242       true,
    243       true,
    244     },
    245     { "HTTP/1.1 200 OK\n"
    246       "connection: proxy-bypass\n"
    247       "Chrome-Proxy: block=, bypass=86400\n"
    248       "Content-Length: 999\n",
    249       true,
    250       86400,
    251       false,
    252       true,
    253     },
    254     { "HTTP/1.1 200 OK\n"
    255       "connection: proxy-bypass\n"
    256       "Chrome-Proxy: block=-1\n"
    257       "Content-Length: 999\n",
    258       false,
    259       0,
    260       false,
    261       false,
    262     },
    263     { "HTTP/1.1 200 OK\n"
    264       "connection: proxy-bypass\n"
    265       "Chrome-Proxy: block=99999999999999999999\n"
    266       "Content-Length: 999\n",
    267       false,
    268       0,
    269       false,
    270       false,
    271     },
    272     { "HTTP/1.1 200 OK\n"
    273       "connection: keep-alive\n"
    274       "Chrome-Proxy: block-once\n"
    275       "Content-Length: 999\n",
    276       true,
    277       0,
    278       true,
    279       false,
    280     },
    281     { "HTTP/1.1 200 OK\n"
    282       "connection: keep-alive\n"
    283       "Chrome-Proxy: block-once=\n"
    284       "Content-Length: 999\n",
    285       false,
    286       0,
    287       false,
    288       false,
    289     },
    290     { "HTTP/1.1 200 OK\n"
    291       "connection: keep-alive\n"
    292       "Chrome-Proxy: block-once=10\n"
    293       "Content-Length: 999\n",
    294       false,
    295       0,
    296       false,
    297       false,
    298     },
    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",
    303       true,
    304       3600,
    305       true,
    306       true,
    307     },
    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",
    313       true,
    314       3600,
    315       true,
    316       true,
    317     },
    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",
    322       true,
    323       86400,
    324       false,
    325       true,
    326     },
    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",
    331       true,
    332       3600,
    333       true,
    334       true,
    335     },
    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",
    340       true,
    341       0,
    342       true,
    343       false,
    344     },
    345   };
    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));
    351 
    352     DataReductionProxyInfo data_reduction_proxy_info;
    353     EXPECT_EQ(
    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);
    362   }
    363 }
    364 
    365 TEST_F(DataReductionProxyHeadersTest, ParseHeadersAndSetProxyInfo) {
    366   std::string headers =
    367       "HTTP/1.1 200 OK\n"
    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));
    374 
    375   DataReductionProxyInfo data_reduction_proxy_info;
    376   EXPECT_TRUE(
    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);
    381 }
    382 
    383 TEST_F(DataReductionProxyHeadersTest, HasDataReductionProxyViaHeader) {
    384   const struct {
    385     const char* headers;
    386     bool expected_result;
    387     bool expected_has_intermediary;
    388     bool ignore_intermediary;
    389   } tests[] = {
    390     { "HTTP/1.1 200 OK\n"
    391       "Via: 1.1 Chrome-Proxy\n",
    392       false,
    393       false,
    394       false,
    395     },
    396     { "HTTP/1.1 200 OK\n"
    397       "Via: 1\n",
    398       false,
    399       false,
    400       false,
    401     },
    402     { "HTTP/1.1 200 OK\n"
    403       "Via: 1.1 Chrome-Compression-Proxy\n",
    404       true,
    405       true,
    406       false,
    407     },
    408     { "HTTP/1.1 200 OK\n"
    409       "Via: 1.0 Chrome-Compression-Proxy\n",
    410       true,
    411       true,
    412       false,
    413     },
    414     { "HTTP/1.1 200 OK\n"
    415       "Via: 1.1 Foo-Bar, 1.1 Chrome-Compression-Proxy\n",
    416       true,
    417       true,
    418       false,
    419     },
    420     { "HTTP/1.1 200 OK\n"
    421       "Via: 1.1 Chrome-Compression-Proxy, 1.1 Bar-Foo\n",
    422       true,
    423       false,
    424       false,
    425     },
    426     { "HTTP/1.1 200 OK\n"
    427       "Via: 1.1 chrome-compression-proxy\n",
    428       false,
    429       false,
    430       false,
    431     },
    432     { "HTTP/1.1 200 OK\n"
    433       "Via: 1.1 Foo-Bar\n"
    434       "Via: 1.1 Chrome-Compression-Proxy\n",
    435       true,
    436       true,
    437       false,
    438     },
    439     { "HTTP/1.1 200 OK\n"
    440       "Via: 1.1 Chrome-Compression-Proxy\n"
    441       "Via: 1.1 Foo-Bar\n",
    442       true,
    443       false,
    444       false,
    445     },
    446     { "HTTP/1.1 200 OK\n"
    447       "Via: 1.1 Chrome-Proxy\n",
    448       false,
    449       false,
    450       false,
    451     },
    452     { "HTTP/1.1 200 OK\n"
    453       "Via: 1.1 Chrome Compression Proxy\n",
    454       true,
    455       true,
    456       false,
    457     },
    458     { "HTTP/1.1 200 OK\n"
    459       "Via: 1.1 Foo-Bar, 1.1 Chrome Compression Proxy\n",
    460       true,
    461       true,
    462       false,
    463     },
    464     { "HTTP/1.1 200 OK\n"
    465       "Via: 1.1 Chrome Compression Proxy, 1.1 Bar-Foo\n",
    466       true,
    467       false,
    468       false,
    469     },
    470     { "HTTP/1.1 200 OK\n"
    471       "Via: 1.1 chrome compression proxy\n",
    472       false,
    473       false,
    474       false,
    475     },
    476     { "HTTP/1.1 200 OK\n"
    477       "Via: 1.1 Foo-Bar\n"
    478       "Via: 1.1 Chrome Compression Proxy\n",
    479       true,
    480       true,
    481       false,
    482     },
    483     { "HTTP/1.1 200 OK\n"
    484       "Via: 1.1 Chrome Compression Proxy\n"
    485       "Via: 1.1 Foo-Bar\n",
    486       true,
    487       false,
    488       false,
    489     },
    490     { "HTTP/1.1 200 OK\n"
    491       "Via: 1.1 Chrome Compression Proxy\n"
    492       "Via: 1.1 Foo-Bar\n",
    493       true,
    494       false,
    495       true,
    496     },
    497   };
    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));
    503 
    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);
    508     }
    509     else {
    510       has_chrome_proxy_via_header =
    511           HasDataReductionProxyViaHeader(parsed.get(), &has_intermediary);
    512     }
    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);
    516     }
    517   }
    518 }
    519 
    520 TEST_F(DataReductionProxyHeadersTest, GetDataReductionProxyBypassEventType) {
    521   const struct {
    522      const char* headers;
    523      DataReductionProxyBypassType expected_result;
    524   } tests[] = {
    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,
    529     },
    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,
    534     },
    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,
    539     },
    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,
    544     },
    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,
    549     },
    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,
    554     },
    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,
    559     },
    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,
    563     },
    564     { "HTTP/1.1 501 Not Implemented\n"
    565       "Via: 1.1 Chrome-Compression-Proxy\n",
    566       BYPASS_EVENT_TYPE_MAX,
    567     },
    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,
    571     },
    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,
    575     },
    576     { "HTTP/1.1 504 Gateway Timeout\n"
    577       "Via: 1.1 Chrome-Compression-Proxy\n",
    578       BYPASS_EVENT_TYPE_MAX,
    579     },
    580     { "HTTP/1.1 505 HTTP Version Not Supported\n"
    581       "Via: 1.1 Chrome-Compression-Proxy\n",
    582       BYPASS_EVENT_TYPE_MAX,
    583     },
    584     { "HTTP/1.1 304 Not Modified\n",
    585         BYPASS_EVENT_TYPE_MAX,
    586     },
    587     { "HTTP/1.1 200 OK\n",
    588         BYPASS_EVENT_TYPE_MISSING_VIA_HEADER_OTHER,
    589     },
    590     { "HTTP/1.1 200 OK\n"
    591       "Chrome-Proxy: bypass=59\n",
    592       BYPASS_EVENT_TYPE_SHORT,
    593     },
    594     { "HTTP/1.1 502 Bad Gateway\n",
    595         BYPASS_EVENT_TYPE_STATUS_502_HTTP_BAD_GATEWAY,
    596     },
    597     { "HTTP/1.1 502 Bad Gateway\n"
    598       "Chrome-Proxy: bypass=59\n",
    599       BYPASS_EVENT_TYPE_SHORT,
    600     },
    601     { "HTTP/1.1 502 Bad Gateway\n"
    602       "Chrome-Proxy: bypass=59\n",
    603       BYPASS_EVENT_TYPE_SHORT,
    604     },
    605     { "HTTP/1.1 414 Request-URI Too Long\n",
    606         BYPASS_EVENT_TYPE_MISSING_VIA_HEADER_4XX,
    607     },
    608     { "HTTP/1.1 414 Request-URI Too Long\n"
    609       "Via: 1.1 Chrome-Compression-Proxy\n",
    610       BYPASS_EVENT_TYPE_MAX,
    611     },
    612     { "HTTP/1.1 407 Proxy Authentication Required\n",
    613         BYPASS_EVENT_TYPE_MALFORMED_407,
    614     },
    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,
    619     }
    620   };
    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;
    627     EXPECT_EQ(
    628         tests[i].expected_result,
    629         GetDataReductionProxyBypassType(parsed.get(), &chrome_proxy_info));
    630   }
    631 }
    632 
    633 TEST_F(DataReductionProxyHeadersTest,
    634        GetDataReductionProxyActionFingerprintChromeProxy) {
    635   const struct {
    636      std::string label;
    637      const char* headers;
    638      bool expected_fingerprint_exist;
    639      std::string expected_fingerprint;
    640   } tests[] = {
    641     { "fingerprint doesn't exist",
    642       "HTTP/1.1 200 OK\n"
    643       "Chrome-Proxy: bypass=0\n",
    644       false,
    645       "",
    646     },
    647     { "fingerprint occurs once",
    648       "HTTP/1.1 200 OK\n"
    649       "Chrome-Proxy: bypass=1, fcp=fp\n",
    650       true,
    651       "fp",
    652     },
    653     { "fingerprint occurs twice",
    654       "HTTP/1.1 200 OK\n"
    655       "Chrome-Proxy: bypass=2, fcp=fp1, fcp=fp2\n",
    656       true,
    657       "fp1",
    658     },
    659   };
    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));
    665 
    666     std::string fingerprint;
    667     bool fingerprint_exist = GetDataReductionProxyActionFingerprintChromeProxy(
    668         parsed.get(), &fingerprint);
    669     EXPECT_EQ(tests[i].expected_fingerprint_exist, fingerprint_exist)
    670         << tests[i].label;
    671 
    672     if (fingerprint_exist)
    673       EXPECT_EQ(tests[i].expected_fingerprint, fingerprint) << tests[i].label;
    674   }
    675 }
    676 
    677 TEST_F(DataReductionProxyHeadersTest,
    678        GetDataReductionProxyActionFingerprintVia) {
    679   const struct {
    680      std::string label;
    681      const char* headers;
    682      bool expected_fingerprint_exist;
    683      std::string expected_fingerprint;
    684   } tests[] = {
    685     { "fingerprint doesn't exist",
    686       "HTTP/1.1 200 OK\n"
    687       "Chrome-Proxy: bypass=0\n",
    688       false,
    689       "",
    690     },
    691     { "fingerprint occurs once",
    692       "HTTP/1.1 200 OK\n"
    693       "Chrome-Proxy: bypass=1, fvia=fvia\n",
    694       true,
    695       "fvia",
    696     },
    697     { "fingerprint occurs twice",
    698       "HTTP/1.1 200 OK\n"
    699       "Chrome-Proxy: bypass=2, fvia=fvia1, fvia=fvia2\n",
    700       true,
    701       "fvia1",
    702     },
    703   };
    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));
    709 
    710     std::string fingerprint;
    711     bool fingerprint_exist =
    712         GetDataReductionProxyActionFingerprintVia(parsed.get(), &fingerprint);
    713     EXPECT_EQ(tests[i].expected_fingerprint_exist, fingerprint_exist)
    714         << tests[i].label;
    715 
    716     if (fingerprint_exist)
    717       EXPECT_EQ(tests[i].expected_fingerprint, fingerprint) << tests[i].label;
    718   }
    719 }
    720 
    721 TEST_F(DataReductionProxyHeadersTest,
    722        GetDataReductionProxyActionFingerprintOtherHeaders) {
    723   const struct {
    724      std::string label;
    725      const char* headers;
    726      bool expected_fingerprint_exist;
    727      std::string expected_fingerprint;
    728   } tests[] = {
    729     { "fingerprint doesn't exist",
    730       "HTTP/1.1 200 OK\n"
    731       "Chrome-Proxy: bypass=0\n",
    732       false,
    733       "",
    734     },
    735     { "fingerprint occurs once",
    736       "HTTP/1.1 200 OK\n"
    737       "Chrome-Proxy: bypass=1, foh=foh\n",
    738       true,
    739       "foh",
    740     },
    741     { "fingerprint occurs twice",
    742       "HTTP/1.1 200 OK\n"
    743       "Chrome-Proxy: bypass=2, foh=foh1, foh=foh2\n",
    744       true,
    745       "foh1",
    746     },
    747   };
    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));
    753 
    754     std::string fingerprint;
    755     bool fingerprint_exist = GetDataReductionProxyActionFingerprintOtherHeaders(
    756         parsed.get(), &fingerprint);
    757     EXPECT_EQ(tests[i].expected_fingerprint_exist, fingerprint_exist)
    758         << tests[i].label;
    759 
    760     if (fingerprint_exist)
    761       EXPECT_EQ(tests[i].expected_fingerprint, fingerprint) << tests[i].label;
    762   }
    763 }
    764 
    765 TEST_F(DataReductionProxyHeadersTest,
    766        GetDataReductionProxyActionFingerprintContentLength) {
    767   const struct {
    768      std::string label;
    769      const char* headers;
    770      bool expected_fingerprint_exist;
    771      std::string expected_fingerprint;
    772   } tests[] = {
    773     { "fingerprint doesn't exist",
    774       "HTTP/1.1 200 OK\n"
    775       "Chrome-Proxy: bypass=0\n",
    776       false,
    777       "",
    778     },
    779     { "fingerprint occurs once",
    780       "HTTP/1.1 200 OK\n"
    781       "Chrome-Proxy: bypass=1, fcl=fcl\n",
    782       true,
    783       "fcl",
    784     },
    785     { "fingerprint occurs twice",
    786       "HTTP/1.1 200 OK\n"
    787       "Chrome-Proxy: bypass=2, fcl=fcl1, fcl=fcl2\n",
    788       true,
    789       "fcl1",
    790     },
    791   };
    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));
    797 
    798     std::string fingerprint;
    799     bool fingerprint_exist =
    800         GetDataReductionProxyActionFingerprintContentLength(parsed.get(),
    801                                                             &fingerprint);
    802     EXPECT_EQ(tests[i].expected_fingerprint_exist, fingerprint_exist)
    803         << tests[i].label;
    804 
    805     if (fingerprint_exist)
    806       EXPECT_EQ(tests[i].expected_fingerprint, fingerprint) << tests[i].label;
    807   }
    808 }
    809 
    810 TEST_F(DataReductionProxyHeadersTest,
    811        GetDataReductionProxyHeaderWithFingerprintRemoved) {
    812   const struct {
    813     std::string label;
    814     const char* headers;
    815     std::string expected_output_values_string;
    816   } test[] = {
    817     {
    818       "Checks the case that there is no Chrome-Proxy header's fingerprint.",
    819       "HTTP/1.1 200 OK\n"
    820       "Chrome-Proxy: 1,2,3,5\n",
    821       "1,2,3,5,",
    822     },
    823     {
    824       "Checks the case that there is Chrome-Proxy header's fingerprint.",
    825       "HTTP/1.1 200 OK\n"
    826       "Chrome-Proxy: 1,2,3,fcp=4,5\n",
    827       "1,2,3,5,",
    828     },
    829     {
    830       "Checks the case that there is Chrome-Proxy header's fingerprint, and it"
    831       "occurs at the end.",
    832       "HTTP/1.1 200 OK\n"
    833       "Chrome-Proxy: 1,2,3,fcp=4,",
    834       "1,2,3,",
    835     },
    836     {
    837       "Checks the case that there is Chrome-Proxy header's fingerprint, and it"
    838       "occurs at the beginning.",
    839       "HTTP/1.1 200 OK\n"
    840       "Chrome-Proxy: fcp=1,2,3,",
    841       "2,3,",
    842     },
    843     {
    844       "Checks the case that value is longer than prefix.",
    845       "HTTP/1.1 200 OK\n"
    846       "Chrome-Proxy: fcp=1,fcp!=1,fcp!=2,fcpfcp=3",
    847       "fcp!=1,fcp!=2,fcpfcp=3,",
    848     },
    849     {
    850       "Checks the case that value is shorter than prefix but similar.",
    851       "HTTP/1.1 200 OK\n"
    852       "Chrome-Proxy: fcp=1,fcp,fcp=",
    853       "fcp,fcp=,",
    854     },
    855   };
    856 
    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));
    862 
    863     std::vector<std::string> output_values;
    864     GetDataReductionProxyHeaderWithFingerprintRemoved(parsed.get(),
    865                                                       &output_values);
    866 
    867     std::string output_values_string;
    868     for (size_t j = 0; j < output_values.size(); ++j)
    869       output_values_string += output_values[j] + ",";
    870 
    871     EXPECT_EQ(test[i].expected_output_values_string, output_values_string)
    872         << test[i].label;
    873   }
    874 }
    875 
    876 }  // namespace data_reduction_proxy
    877