Home | History | Annotate | Download | only in proxy
      1 // Copyright (c) 2006-2008 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 "net/proxy/proxy_list.h"
      6 
      7 #include "net/base/net_log.h"
      8 #include "net/proxy/proxy_retry_info.h"
      9 #include "net/proxy/proxy_server.h"
     10 #include "testing/gtest/include/gtest/gtest.h"
     11 
     12 namespace net {
     13 
     14 namespace {
     15 
     16 // Test parsing from a PAC string.
     17 TEST(ProxyListTest, SetFromPacString) {
     18   const struct {
     19     const char* pac_input;
     20     const char* pac_output;
     21   } tests[] = {
     22     // Valid inputs:
     23     {  "PROXY foopy:10",
     24        "PROXY foopy:10",
     25     },
     26     {  " DIRECT",  // leading space.
     27        "DIRECT",
     28     },
     29     {  "PROXY foopy1 ; proxy foopy2;\t DIRECT",
     30        "PROXY foopy1:80;PROXY foopy2:80;DIRECT",
     31     },
     32     {  "proxy foopy1 ; SOCKS foopy2",
     33        "PROXY foopy1:80;SOCKS foopy2:1080",
     34     },
     35     // Try putting DIRECT first.
     36     {  "DIRECT ; proxy foopy1 ; DIRECT ; SOCKS5 foopy2;DIRECT ",
     37        "DIRECT;PROXY foopy1:80;DIRECT;SOCKS5 foopy2:1080;DIRECT",
     38     },
     39     // Try putting DIRECT consecutively.
     40     {  "DIRECT ; proxy foopy1:80; DIRECT ; DIRECT",
     41        "DIRECT;PROXY foopy1:80;DIRECT;DIRECT",
     42     },
     43 
     44     // Invalid inputs (parts which aren't understood get
     45     // silently discarded):
     46     //
     47     // If the proxy list string parsed to empty, automatically fall-back to
     48     // DIRECT.
     49     {  "PROXY-foopy:10",
     50        "DIRECT",
     51     },
     52     {  "PROXY",
     53        "DIRECT",
     54     },
     55     {  "PROXY foopy1 ; JUNK ; JUNK ; SOCKS5 foopy2 ; ;",
     56        "PROXY foopy1:80;SOCKS5 foopy2:1080",
     57     },
     58   };
     59 
     60   for (size_t i = 0; i < ARRAYSIZE_UNSAFE(tests); ++i) {
     61     ProxyList list;
     62     list.SetFromPacString(tests[i].pac_input);
     63     EXPECT_EQ(tests[i].pac_output, list.ToPacString());
     64     EXPECT_FALSE(list.IsEmpty());
     65   }
     66 }
     67 
     68 TEST(ProxyListTest, RemoveProxiesWithoutScheme) {
     69   const struct {
     70     const char* pac_input;
     71     int filter;
     72     const char* filtered_pac_output;
     73   } tests[] = {
     74     {  "PROXY foopy:10 ; SOCKS5 foopy2 ; SOCKS foopy11 ; PROXY foopy3 ; DIRECT",
     75        // Remove anything that isn't HTTP or DIRECT.
     76        ProxyServer::SCHEME_DIRECT | ProxyServer::SCHEME_HTTP,
     77        "PROXY foopy:10;PROXY foopy3:80;DIRECT",
     78     },
     79     {  "PROXY foopy:10 ; SOCKS5 foopy2",
     80        // Remove anything that isn't HTTP or SOCKS5.
     81        ProxyServer::SCHEME_DIRECT | ProxyServer::SCHEME_SOCKS4,
     82        "",
     83     },
     84   };
     85 
     86   for (size_t i = 0; i < ARRAYSIZE_UNSAFE(tests); ++i) {
     87     ProxyList list;
     88     list.SetFromPacString(tests[i].pac_input);
     89     list.RemoveProxiesWithoutScheme(tests[i].filter);
     90     EXPECT_EQ(tests[i].filtered_pac_output, list.ToPacString());
     91   }
     92 }
     93 
     94 TEST(ProxyListTest, DeprioritizeBadProxies) {
     95   // Retry info that marks a proxy as being bad for a *very* long time (to avoid
     96   // the test depending on the current time.)
     97   ProxyRetryInfo proxy_retry_info;
     98   proxy_retry_info.bad_until =
     99       base::TimeTicks::Now() + base::TimeDelta::FromDays(1);
    100 
    101   // Call DeprioritizeBadProxies with an empty map -- should have no effect.
    102   {
    103     ProxyList list;
    104     list.SetFromPacString("PROXY foopy1:80;PROXY foopy2:80;PROXY foopy3:80");
    105 
    106     ProxyRetryInfoMap retry_info_map;
    107     list.DeprioritizeBadProxies(retry_info_map);
    108     EXPECT_EQ("PROXY foopy1:80;PROXY foopy2:80;PROXY foopy3:80",
    109               list.ToPacString());
    110   }
    111 
    112   // Call DeprioritizeBadProxies with 2 of the three proxies marked as bad.
    113   // These proxies should be retried last.
    114   {
    115     ProxyList list;
    116     list.SetFromPacString("PROXY foopy1:80;PROXY foopy2:80;PROXY foopy3:80");
    117 
    118     ProxyRetryInfoMap retry_info_map;
    119     retry_info_map["foopy1:80"] = proxy_retry_info;
    120     retry_info_map["foopy3:80"] = proxy_retry_info;
    121     retry_info_map["socks5://localhost:1080"] = proxy_retry_info;
    122 
    123     list.DeprioritizeBadProxies(retry_info_map);
    124 
    125     EXPECT_EQ("PROXY foopy2:80;PROXY foopy1:80;PROXY foopy3:80",
    126               list.ToPacString());
    127   }
    128 
    129   // Call DeprioritizeBadProxies where ALL of the proxies are marked as bad.
    130   // This should have no effect on the order.
    131   {
    132     ProxyList list;
    133     list.SetFromPacString("PROXY foopy1:80;PROXY foopy2:80;PROXY foopy3:80");
    134 
    135     ProxyRetryInfoMap retry_info_map;
    136     retry_info_map["foopy1:80"] = proxy_retry_info;
    137     retry_info_map["foopy2:80"] = proxy_retry_info;
    138     retry_info_map["foopy3:80"] = proxy_retry_info;
    139 
    140     list.DeprioritizeBadProxies(retry_info_map);
    141 
    142     EXPECT_EQ("PROXY foopy1:80;PROXY foopy2:80;PROXY foopy3:80",
    143               list.ToPacString());
    144   }
    145 
    146   // Call DeprioritizeBadProxies with 2 of the three proxies marked as bad. Of
    147   // the 2 bad proxies, one is to be reconsidered and should be retried last.
    148   // The other is not to be reconsidered and should be removed from the list.
    149   {
    150     ProxyList list;
    151     list.SetFromPacString("PROXY foopy1:80;PROXY foopy2:80;PROXY foopy3:80");
    152 
    153     ProxyRetryInfoMap retry_info_map;
    154     // |proxy_retry_info.reconsider defaults to true.
    155     retry_info_map["foopy1:80"] = proxy_retry_info;
    156     proxy_retry_info.try_while_bad = false;
    157     retry_info_map["foopy3:80"] = proxy_retry_info;
    158     proxy_retry_info.try_while_bad = true;
    159     retry_info_map["socks5://localhost:1080"] = proxy_retry_info;
    160 
    161     list.DeprioritizeBadProxies(retry_info_map);
    162 
    163     EXPECT_EQ("PROXY foopy2:80;PROXY foopy1:80",
    164               list.ToPacString());
    165   }
    166 }
    167 
    168 TEST(ProxyListTest, UpdateRetryInfoOnFallback) {
    169   ProxyRetryInfo proxy_retry_info;
    170   // Retrying should put the first proxy on the retry list.
    171   {
    172     ProxyList list;
    173     ProxyRetryInfoMap retry_info_map;
    174     BoundNetLog net_log;
    175     list.SetFromPacString("PROXY foopy1:80;PROXY foopy2:80;PROXY foopy3:80");
    176     list.UpdateRetryInfoOnFallback(&retry_info_map,
    177                                    base::TimeDelta::FromSeconds(60),
    178                                    true,
    179                                    ProxyServer(),
    180                                    net_log);
    181     EXPECT_TRUE(retry_info_map.end() != retry_info_map.find("foopy1:80"));
    182     EXPECT_TRUE(retry_info_map.end() == retry_info_map.find("foopy2:80"));
    183     EXPECT_TRUE(retry_info_map.end() == retry_info_map.find("foopy3:80"));
    184   }
    185   // Including another bad proxy should put both the first and the specified
    186   // proxy on the retry list.
    187   {
    188     ProxyList list;
    189     ProxyRetryInfoMap retry_info_map;
    190     BoundNetLog net_log;
    191     ProxyServer proxy_server = ProxyServer::FromURI("foopy3:80",
    192                                                     ProxyServer::SCHEME_HTTP);
    193     list.SetFromPacString("PROXY foopy1:80;PROXY foopy2:80;PROXY foopy3:80");
    194     list.UpdateRetryInfoOnFallback(&retry_info_map,
    195                                    base::TimeDelta::FromSeconds(60),
    196                                    true,
    197                                    proxy_server,
    198                                    net_log);
    199     EXPECT_TRUE(retry_info_map.end() != retry_info_map.find("foopy1:80"));
    200     EXPECT_TRUE(retry_info_map.end() == retry_info_map.find("foopy2:80"));
    201     EXPECT_TRUE(retry_info_map.end() != retry_info_map.find("foopy3:80"));
    202   }
    203   // If the first proxy is DIRECT, nothing is added to the retry list, even
    204   // if another bad proxy is specified.
    205   {
    206     ProxyList list;
    207     ProxyRetryInfoMap retry_info_map;
    208     BoundNetLog net_log;
    209     ProxyServer proxy_server = ProxyServer::FromURI("foopy2:80",
    210                                                     ProxyServer::SCHEME_HTTP);
    211     list.SetFromPacString("DIRECT;PROXY foopy2:80;PROXY foopy3:80");
    212     list.UpdateRetryInfoOnFallback(&retry_info_map,
    213                                    base::TimeDelta::FromSeconds(60),
    214                                    true,
    215                                    proxy_server,
    216                                    net_log);
    217     EXPECT_TRUE(retry_info_map.end() == retry_info_map.find("foopy2:80"));
    218     EXPECT_TRUE(retry_info_map.end() == retry_info_map.find("foopy3:80"));
    219   }
    220 }
    221 
    222 }  // namesapce
    223 
    224 }  // namespace net
    225