Home | History | Annotate | Download | only in proxy
      1 // Copyright (c) 2009 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 <vector>
      6 
      7 #include "net/base/net_errors.h"
      8 #include "net/base/load_log.h"
      9 #include "net/base/load_log_util.h"
     10 #include "net/base/load_log_unittest.h"
     11 #include "net/base/test_completion_callback.h"
     12 #include "net/proxy/init_proxy_resolver.h"
     13 #include "net/proxy/proxy_config.h"
     14 #include "net/proxy/proxy_resolver.h"
     15 #include "net/proxy/proxy_script_fetcher.h"
     16 #include "testing/gtest/include/gtest/gtest.h"
     17 
     18 namespace net {
     19 namespace {
     20 
     21 enum Error {
     22   kFailedDownloading = -100,
     23   kFailedParsing = -200,
     24 };
     25 
     26 class Rules {
     27  public:
     28   struct Rule {
     29     Rule(const GURL& url,
     30          int fetch_error,
     31          int set_pac_error)
     32         : url(url),
     33           fetch_error(fetch_error),
     34           set_pac_error(set_pac_error) {
     35     }
     36 
     37     std::string bytes() const {
     38       if (set_pac_error == OK)
     39         return url.spec() + "!valid-script";
     40       if (fetch_error == OK)
     41         return url.spec() + "!invalid-script";
     42       return std::string();
     43     }
     44 
     45     GURL url;
     46     int fetch_error;
     47     int set_pac_error;
     48   };
     49 
     50   Rule AddSuccessRule(const char* url) {
     51     Rule rule(GURL(url), OK /*fetch_error*/, OK /*set_pac_error*/);
     52     rules_.push_back(rule);
     53     return rule;
     54   }
     55 
     56   void AddFailDownloadRule(const char* url) {
     57     rules_.push_back(Rule(GURL(url), kFailedDownloading /*fetch_error*/,
     58         ERR_UNEXPECTED /*set_pac_error*/));
     59   }
     60 
     61   void AddFailParsingRule(const char* url) {
     62     rules_.push_back(Rule(GURL(url), OK /*fetch_error*/,
     63         kFailedParsing /*set_pac_error*/));
     64   }
     65 
     66   const Rule& GetRuleByUrl(const GURL& url) const {
     67     for (RuleList::const_iterator it = rules_.begin(); it != rules_.end();
     68          ++it) {
     69       if (it->url == url)
     70         return *it;
     71     }
     72     CHECK(false) << "Rule not found for " << url;
     73     return rules_[0];
     74   }
     75 
     76   const Rule& GetRuleByBytes(const std::string& bytes) const {
     77     for (RuleList::const_iterator it = rules_.begin(); it != rules_.end();
     78          ++it) {
     79       if (it->bytes() == bytes)
     80         return *it;
     81     }
     82     CHECK(false) << "Rule not found for " << bytes;
     83     return rules_[0];
     84   }
     85 
     86  private:
     87   typedef std::vector<Rule> RuleList;
     88   RuleList rules_;
     89 };
     90 
     91 class RuleBasedProxyScriptFetcher : public ProxyScriptFetcher {
     92  public:
     93   explicit RuleBasedProxyScriptFetcher(const Rules* rules) : rules_(rules) {}
     94 
     95   // ProxyScriptFetcher implementation.
     96   virtual int Fetch(const GURL& url,
     97                     std::string* bytes,
     98                     CompletionCallback* callback) {
     99     const Rules::Rule& rule = rules_->GetRuleByUrl(url);
    100     int rv = rule.fetch_error;
    101     EXPECT_NE(ERR_UNEXPECTED, rv);
    102     if (rv == OK)
    103       *bytes = rule.bytes();
    104     return rv;
    105   }
    106 
    107   virtual void Cancel() {}
    108 
    109  private:
    110   const Rules* rules_;
    111 };
    112 
    113 class RuleBasedProxyResolver : public ProxyResolver {
    114  public:
    115   RuleBasedProxyResolver(const Rules* rules, bool expects_pac_bytes)
    116       : ProxyResolver(expects_pac_bytes), rules_(rules) {}
    117 
    118   // ProxyResolver implementation:
    119   virtual int GetProxyForURL(const GURL& /*url*/,
    120                              ProxyInfo* /*results*/,
    121                              CompletionCallback* /*callback*/,
    122                              RequestHandle* /*request_handle*/,
    123                              LoadLog* /*load_log*/) {
    124     NOTREACHED();
    125     return ERR_UNEXPECTED;
    126   }
    127 
    128   virtual void CancelRequest(RequestHandle request_handle) {
    129     NOTREACHED();
    130   }
    131 
    132   virtual int SetPacScript(const GURL& pac_url,
    133                            const std::string& pac_bytes,
    134                            CompletionCallback* callback) {
    135     const Rules::Rule& rule = expects_pac_bytes() ?
    136         rules_->GetRuleByBytes(pac_bytes) :
    137         rules_->GetRuleByUrl(pac_url);
    138 
    139     int rv = rule.set_pac_error;
    140     EXPECT_NE(ERR_UNEXPECTED, rv);
    141 
    142     if (expects_pac_bytes())
    143       EXPECT_EQ(rule.bytes(), pac_bytes);
    144     else
    145       EXPECT_EQ(rule.url, pac_url);
    146 
    147     if (rv == OK) {
    148       pac_bytes_ = pac_bytes;
    149       pac_url_ = pac_url;
    150     }
    151     return rv;
    152   }
    153 
    154   const std::string& pac_bytes() const { return pac_bytes_; }
    155   const GURL& pac_url() const { return pac_url_; }
    156 
    157  private:
    158   const Rules* rules_;
    159   std::string pac_bytes_;
    160   GURL pac_url_;
    161 };
    162 
    163 // Succeed using custom PAC script.
    164 TEST(InitProxyResolverTest, CustomPacSucceeds) {
    165   Rules rules;
    166   RuleBasedProxyResolver resolver(&rules, true /*expects_pac_bytes*/);
    167   RuleBasedProxyScriptFetcher fetcher(&rules);
    168 
    169   ProxyConfig config;
    170   config.pac_url = GURL("http://custom/proxy.pac");
    171 
    172   Rules::Rule rule = rules.AddSuccessRule("http://custom/proxy.pac");
    173 
    174   TestCompletionCallback callback;
    175   scoped_refptr<LoadLog> log(new LoadLog(LoadLog::kUnbounded));
    176   InitProxyResolver init(&resolver, &fetcher);
    177   EXPECT_EQ(OK, init.Init(config, &callback, log));
    178   EXPECT_EQ(rule.bytes(), resolver.pac_bytes());
    179 
    180   // Check the LoadLog was filled correctly.
    181   EXPECT_EQ(9u, log->entries().size());
    182   EXPECT_TRUE(LogContainsBeginEvent(
    183       *log, 0, LoadLog::TYPE_INIT_PROXY_RESOLVER));
    184   EXPECT_TRUE(LogContainsBeginEvent(
    185       *log, 1, LoadLog::TYPE_INIT_PROXY_RESOLVER_FETCH_PAC_SCRIPT));
    186   EXPECT_TRUE(LogContainsEndEvent(
    187       *log, 4, LoadLog::TYPE_INIT_PROXY_RESOLVER_FETCH_PAC_SCRIPT));
    188   EXPECT_TRUE(LogContainsBeginEvent(
    189       *log, 5, LoadLog::TYPE_INIT_PROXY_RESOLVER_SET_PAC_SCRIPT));
    190   EXPECT_TRUE(LogContainsEndEvent(
    191       *log, 7, LoadLog::TYPE_INIT_PROXY_RESOLVER_SET_PAC_SCRIPT));
    192   EXPECT_TRUE(LogContainsEndEvent(*log, 8, LoadLog::TYPE_INIT_PROXY_RESOLVER));
    193 }
    194 
    195 // Fail downloading the custom PAC script.
    196 TEST(InitProxyResolverTest, CustomPacFails1) {
    197   Rules rules;
    198   RuleBasedProxyResolver resolver(&rules, true /*expects_pac_bytes*/);
    199   RuleBasedProxyScriptFetcher fetcher(&rules);
    200 
    201   ProxyConfig config;
    202   config.pac_url = GURL("http://custom/proxy.pac");
    203 
    204   rules.AddFailDownloadRule("http://custom/proxy.pac");
    205 
    206   TestCompletionCallback callback;
    207   scoped_refptr<LoadLog> log(new LoadLog(LoadLog::kUnbounded));
    208   InitProxyResolver init(&resolver, &fetcher);
    209   EXPECT_EQ(kFailedDownloading, init.Init(config, &callback, log));
    210   EXPECT_EQ("", resolver.pac_bytes());
    211 
    212   // Check the LoadLog was filled correctly.
    213   EXPECT_EQ(6u, log->entries().size());
    214   EXPECT_TRUE(LogContainsBeginEvent(
    215       *log, 0, LoadLog::TYPE_INIT_PROXY_RESOLVER));
    216   EXPECT_TRUE(LogContainsBeginEvent(
    217       *log, 1, LoadLog::TYPE_INIT_PROXY_RESOLVER_FETCH_PAC_SCRIPT));
    218   EXPECT_TRUE(LogContainsEndEvent(
    219       *log, 4, LoadLog::TYPE_INIT_PROXY_RESOLVER_FETCH_PAC_SCRIPT));
    220   EXPECT_TRUE(LogContainsEndEvent(*log, 5, LoadLog::TYPE_INIT_PROXY_RESOLVER));
    221 }
    222 
    223 // Fail parsing the custom PAC script.
    224 TEST(InitProxyResolverTest, CustomPacFails2) {
    225   Rules rules;
    226   RuleBasedProxyResolver resolver(&rules, true /*expects_pac_bytes*/);
    227   RuleBasedProxyScriptFetcher fetcher(&rules);
    228 
    229   ProxyConfig config;
    230   config.pac_url = GURL("http://custom/proxy.pac");
    231 
    232   rules.AddFailParsingRule("http://custom/proxy.pac");
    233 
    234   TestCompletionCallback callback;
    235   InitProxyResolver init(&resolver, &fetcher);
    236   EXPECT_EQ(kFailedParsing, init.Init(config, &callback, NULL));
    237   EXPECT_EQ("", resolver.pac_bytes());
    238 }
    239 
    240 // Fail downloading the custom PAC script, because the fetcher was NULL.
    241 TEST(InitProxyResolverTest, HasNullProxyScriptFetcher) {
    242   Rules rules;
    243   RuleBasedProxyResolver resolver(&rules, true /*expects_pac_bytes*/);
    244 
    245   ProxyConfig config;
    246   config.pac_url = GURL("http://custom/proxy.pac");
    247 
    248   TestCompletionCallback callback;
    249   InitProxyResolver init(&resolver, NULL);
    250   EXPECT_EQ(ERR_UNEXPECTED, init.Init(config, &callback, NULL));
    251   EXPECT_EQ("", resolver.pac_bytes());
    252 }
    253 
    254 // Succeeds in choosing autodetect (wpad).
    255 TEST(InitProxyResolverTest, AutodetectSuccess) {
    256   Rules rules;
    257   RuleBasedProxyResolver resolver(&rules, true /*expects_pac_bytes*/);
    258   RuleBasedProxyScriptFetcher fetcher(&rules);
    259 
    260   ProxyConfig config;
    261   config.auto_detect = true;
    262 
    263   Rules::Rule rule = rules.AddSuccessRule("http://wpad/wpad.dat");
    264 
    265   TestCompletionCallback callback;
    266   InitProxyResolver init(&resolver, &fetcher);
    267   EXPECT_EQ(OK, init.Init(config, &callback, NULL));
    268   EXPECT_EQ(rule.bytes(), resolver.pac_bytes());
    269 }
    270 
    271 // Fails at WPAD (downloading), but succeeds in choosing the custom PAC.
    272 TEST(InitProxyResolverTest, AutodetectFailCustomSuccess1) {
    273   Rules rules;
    274   RuleBasedProxyResolver resolver(&rules, true /*expects_pac_bytes*/);
    275   RuleBasedProxyScriptFetcher fetcher(&rules);
    276 
    277   ProxyConfig config;
    278   config.auto_detect = true;
    279   config.pac_url = GURL("http://custom/proxy.pac");
    280 
    281   rules.AddFailDownloadRule("http://wpad/wpad.dat");
    282   Rules::Rule rule = rules.AddSuccessRule("http://custom/proxy.pac");
    283 
    284   TestCompletionCallback callback;
    285   InitProxyResolver init(&resolver, &fetcher);
    286   EXPECT_EQ(OK, init.Init(config, &callback, NULL));
    287   EXPECT_EQ(rule.bytes(), resolver.pac_bytes());
    288 }
    289 
    290 // Fails at WPAD (parsing), but succeeds in choosing the custom PAC.
    291 TEST(InitProxyResolverTest, AutodetectFailCustomSuccess2) {
    292   Rules rules;
    293   RuleBasedProxyResolver resolver(&rules, true /*expects_pac_bytes*/);
    294   RuleBasedProxyScriptFetcher fetcher(&rules);
    295 
    296   ProxyConfig config;
    297   config.auto_detect = true;
    298   config.pac_url = GURL("http://custom/proxy.pac");
    299 
    300   rules.AddFailParsingRule("http://wpad/wpad.dat");
    301   Rules::Rule rule = rules.AddSuccessRule("http://custom/proxy.pac");
    302 
    303   TestCompletionCallback callback;
    304   scoped_refptr<LoadLog> log(new LoadLog(LoadLog::kUnbounded));
    305   InitProxyResolver init(&resolver, &fetcher);
    306   EXPECT_EQ(OK, init.Init(config, &callback, log));
    307   EXPECT_EQ(rule.bytes(), resolver.pac_bytes());
    308 
    309   // Check the LoadLog was filled correctly.
    310   // (Note that the Fetch and Set states are repeated since both WPAD and custom
    311   // PAC scripts are tried).
    312   EXPECT_EQ(17u, log->entries().size());
    313   EXPECT_TRUE(LogContainsBeginEvent(
    314       *log, 0, LoadLog::TYPE_INIT_PROXY_RESOLVER));
    315   EXPECT_TRUE(LogContainsBeginEvent(
    316       *log, 1, LoadLog::TYPE_INIT_PROXY_RESOLVER_FETCH_PAC_SCRIPT));
    317   EXPECT_TRUE(LogContainsEndEvent(
    318       *log, 4, LoadLog::TYPE_INIT_PROXY_RESOLVER_FETCH_PAC_SCRIPT));
    319   EXPECT_TRUE(LogContainsBeginEvent(
    320       *log, 5, LoadLog::TYPE_INIT_PROXY_RESOLVER_SET_PAC_SCRIPT));
    321   EXPECT_TRUE(LogContainsEndEvent(
    322       *log, 7, LoadLog::TYPE_INIT_PROXY_RESOLVER_SET_PAC_SCRIPT));
    323   EXPECT_TRUE(LogContainsBeginEvent(
    324       *log, 9, LoadLog::TYPE_INIT_PROXY_RESOLVER_FETCH_PAC_SCRIPT));
    325   EXPECT_TRUE(LogContainsEndEvent(
    326       *log, 12, LoadLog::TYPE_INIT_PROXY_RESOLVER_FETCH_PAC_SCRIPT));
    327   EXPECT_TRUE(LogContainsBeginEvent(
    328       *log, 13, LoadLog::TYPE_INIT_PROXY_RESOLVER_SET_PAC_SCRIPT));
    329   EXPECT_TRUE(LogContainsEndEvent(
    330       *log, 15, LoadLog::TYPE_INIT_PROXY_RESOLVER_SET_PAC_SCRIPT));
    331   EXPECT_TRUE(LogContainsEndEvent(*log, 16, LoadLog::TYPE_INIT_PROXY_RESOLVER));
    332 }
    333 
    334 // Fails at WPAD (downloading), and fails at custom PAC (downloading).
    335 TEST(InitProxyResolverTest, AutodetectFailCustomFails1) {
    336   Rules rules;
    337   RuleBasedProxyResolver resolver(&rules, true /*expects_pac_bytes*/);
    338   RuleBasedProxyScriptFetcher fetcher(&rules);
    339 
    340   ProxyConfig config;
    341   config.auto_detect = true;
    342   config.pac_url = GURL("http://custom/proxy.pac");
    343 
    344   rules.AddFailDownloadRule("http://wpad/wpad.dat");
    345   rules.AddFailDownloadRule("http://custom/proxy.pac");
    346 
    347   TestCompletionCallback callback;
    348   InitProxyResolver init(&resolver, &fetcher);
    349   EXPECT_EQ(kFailedDownloading, init.Init(config, &callback, NULL));
    350   EXPECT_EQ("", resolver.pac_bytes());
    351 }
    352 
    353 // Fails at WPAD (downloading), and fails at custom PAC (parsing).
    354 TEST(InitProxyResolverTest, AutodetectFailCustomFails2) {
    355   Rules rules;
    356   RuleBasedProxyResolver resolver(&rules, true /*expects_pac_bytes*/);
    357   RuleBasedProxyScriptFetcher fetcher(&rules);
    358 
    359   ProxyConfig config;
    360   config.auto_detect = true;
    361   config.pac_url = GURL("http://custom/proxy.pac");
    362 
    363   rules.AddFailDownloadRule("http://wpad/wpad.dat");
    364   rules.AddFailParsingRule("http://custom/proxy.pac");
    365 
    366   TestCompletionCallback callback;
    367   InitProxyResolver init(&resolver, &fetcher);
    368   EXPECT_EQ(kFailedParsing, init.Init(config, &callback, NULL));
    369   EXPECT_EQ("", resolver.pac_bytes());
    370 }
    371 
    372 // Fails at WPAD (parsing), but succeeds in choosing the custom PAC.
    373 // This is the same as AutodetectFailCustomSuccess2, but using a ProxyResolver
    374 // that doesn't |expects_pac_bytes|.
    375 TEST(InitProxyResolverTest, AutodetectFailCustomSuccess2_NoFetch) {
    376   Rules rules;
    377   RuleBasedProxyResolver resolver(&rules, false /*expects_pac_bytes*/);
    378   RuleBasedProxyScriptFetcher fetcher(&rules);
    379 
    380   ProxyConfig config;
    381   config.auto_detect = true;
    382   config.pac_url = GURL("http://custom/proxy.pac");
    383 
    384   rules.AddFailParsingRule("");  // Autodetect.
    385   Rules::Rule rule = rules.AddSuccessRule("http://custom/proxy.pac");
    386 
    387   TestCompletionCallback callback;
    388   InitProxyResolver init(&resolver, &fetcher);
    389   EXPECT_EQ(OK, init.Init(config, &callback, NULL));
    390   EXPECT_EQ(rule.url, resolver.pac_url());
    391 }
    392 
    393 }  // namespace
    394 }  // namespace net
    395