123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589 |
- // Copyright (c) 2012 The Chromium Authors. All rights reserved.
- // Use of this source code is governed by a BSD-style license that can be
- // found in the LICENSE file.
- #include "net/proxy_resolution/proxy_config.h"
- #include "base/json/json_writer.h"
- #include "base/values.h"
- #include "net/base/proxy_string_util.h"
- #include "net/proxy_resolution/proxy_config_service_common_unittest.h"
- #include "net/proxy_resolution/proxy_info.h"
- #include "testing/gtest/include/gtest/gtest.h"
- namespace net {
- namespace {
- void ExpectProxyServerEquals(const char* expectation,
- const ProxyList& proxy_servers) {
- if (expectation == nullptr) {
- EXPECT_TRUE(proxy_servers.IsEmpty());
- } else {
- EXPECT_EQ(expectation, proxy_servers.ToPacString());
- }
- }
- TEST(ProxyConfigTest, Equals) {
- // Test |ProxyConfig::auto_detect|.
- ProxyConfig config1;
- config1.set_auto_detect(true);
- ProxyConfig config2;
- config2.set_auto_detect(false);
- EXPECT_FALSE(config1.Equals(config2));
- EXPECT_FALSE(config2.Equals(config1));
- config2.set_auto_detect(true);
- EXPECT_TRUE(config1.Equals(config2));
- EXPECT_TRUE(config2.Equals(config1));
- // Test |ProxyConfig::pac_url|.
- config2.set_pac_url(GURL("http://wpad/wpad.dat"));
- EXPECT_FALSE(config1.Equals(config2));
- EXPECT_FALSE(config2.Equals(config1));
- config1.set_pac_url(GURL("http://wpad/wpad.dat"));
- EXPECT_TRUE(config1.Equals(config2));
- EXPECT_TRUE(config2.Equals(config1));
- // Test |ProxyConfig::proxy_rules|.
- config2.proxy_rules().type = ProxyConfig::ProxyRules::Type::PROXY_LIST;
- config2.proxy_rules().single_proxies.SetSingleProxyServer(
- ProxyUriToProxyServer("myproxy:80", ProxyServer::SCHEME_HTTP));
- EXPECT_FALSE(config1.Equals(config2));
- EXPECT_FALSE(config2.Equals(config1));
- config1.proxy_rules().type = ProxyConfig::ProxyRules::Type::PROXY_LIST;
- config1.proxy_rules().single_proxies.SetSingleProxyServer(
- ProxyUriToProxyServer("myproxy:100", ProxyServer::SCHEME_HTTP));
- EXPECT_FALSE(config1.Equals(config2));
- EXPECT_FALSE(config2.Equals(config1));
- config1.proxy_rules().single_proxies.SetSingleProxyServer(
- ProxyUriToProxyServer("myproxy", ProxyServer::SCHEME_HTTP));
- EXPECT_TRUE(config1.Equals(config2));
- EXPECT_TRUE(config2.Equals(config1));
- // Test |ProxyConfig::bypass_rules|.
- config2.proxy_rules().bypass_rules.AddRuleFromString("*.google.com");
- EXPECT_FALSE(config1.Equals(config2));
- EXPECT_FALSE(config2.Equals(config1));
- config1.proxy_rules().bypass_rules.AddRuleFromString("*.google.com");
- EXPECT_TRUE(config1.Equals(config2));
- EXPECT_TRUE(config2.Equals(config1));
- // Test |ProxyConfig::proxy_rules.reverse_bypass|.
- config2.proxy_rules().reverse_bypass = true;
- EXPECT_FALSE(config1.Equals(config2));
- EXPECT_FALSE(config2.Equals(config1));
- config1.proxy_rules().reverse_bypass = true;
- EXPECT_TRUE(config1.Equals(config2));
- EXPECT_TRUE(config2.Equals(config1));
- }
- struct ProxyConfigToValueTestCase {
- ProxyConfig config;
- const char* expected_value_json;
- };
- class ProxyConfigToValueTest
- : public ::testing::TestWithParam<ProxyConfigToValueTestCase> {};
- TEST_P(ProxyConfigToValueTest, ToValueJSON) {
- const ProxyConfigToValueTestCase& test_case = GetParam();
- base::Value value = test_case.config.ToValue();
- std::string json_string;
- ASSERT_TRUE(base::JSONWriter::Write(value, &json_string));
- EXPECT_EQ(std::string(test_case.expected_value_json), json_string);
- }
- ProxyConfigToValueTestCase GetTestCaseDirect() {
- return {ProxyConfig::CreateDirect(), "{}"};
- }
- ProxyConfigToValueTestCase GetTestCaseAutoDetect() {
- return {ProxyConfig::CreateAutoDetect(), "{\"auto_detect\":true}"};
- }
- ProxyConfigToValueTestCase GetTestCasePacUrl() {
- ProxyConfig config;
- config.set_pac_url(GURL("http://www.example.com/test.pac"));
- return {std::move(config),
- "{\"pac_url\":\"http://www.example.com/test.pac\"}"};
- }
- ProxyConfigToValueTestCase GetTestCasePacUrlMandatory() {
- ProxyConfig config;
- config.set_pac_url(GURL("http://www.example.com/test.pac"));
- config.set_pac_mandatory(true);
- return {std::move(config),
- "{\"pac_mandatory\":true,\"pac_url\":\"http://www.example.com/"
- "test.pac\"}"};
- }
- ProxyConfigToValueTestCase GetTestCasePacUrlAndAutoDetect() {
- ProxyConfig config = ProxyConfig::CreateAutoDetect();
- config.set_pac_url(GURL("http://www.example.com/test.pac"));
- return {
- std::move(config),
- "{\"auto_detect\":true,\"pac_url\":\"http://www.example.com/test.pac\"}"};
- }
- ProxyConfigToValueTestCase GetTestCaseSingleProxy() {
- ProxyConfig config;
- config.proxy_rules().ParseFromString("https://proxy1:8080");
- return {std::move(config), "{\"single_proxy\":[\"https://proxy1:8080\"]}"};
- }
- ProxyConfigToValueTestCase GetTestCaseSingleProxyWithBypass() {
- ProxyConfig config;
- config.proxy_rules().ParseFromString("https://proxy1:8080");
- config.proxy_rules().bypass_rules.AddRuleFromString("*.google.com");
- config.proxy_rules().bypass_rules.AddRuleFromString("192.168.0.1/16");
- return {std::move(config),
- "{\"bypass_list\":[\"*.google.com\",\"192.168.0.1/"
- "16\"],\"single_proxy\":[\"https://proxy1:8080\"]}"};
- }
- ProxyConfigToValueTestCase GetTestCaseSingleProxyWithReversedBypass() {
- ProxyConfig config;
- config.proxy_rules().ParseFromString("https://proxy1:8080");
- config.proxy_rules().bypass_rules.AddRuleFromString("*.google.com");
- config.proxy_rules().reverse_bypass = true;
- return {std::move(config),
- "{\"bypass_list\":[\"*.google.com\"],\"reverse_bypass\":true,"
- "\"single_proxy\":[\"https://proxy1:8080\"]}"};
- }
- ProxyConfigToValueTestCase GetTestCaseProxyPerScheme() {
- ProxyConfig config;
- config.proxy_rules().ParseFromString(
- "http=https://proxy1:8080;https=socks5://proxy2");
- config.proxy_rules().bypass_rules.AddRuleFromString("*.google.com");
- config.set_pac_url(GURL("http://wpad/wpad.dat"));
- config.set_auto_detect(true);
- return {
- std::move(config),
- "{\"auto_detect\":true,\"bypass_list\":[\"*.google.com\"],\"pac_url\":"
- "\"http://wpad/wpad.dat\",\"proxy_per_scheme\":{\"http\":[\"https://"
- "proxy1:8080\"],\"https\":[\"socks5://proxy2:1080\"]}}"};
- }
- ProxyConfigToValueTestCase GetTestCaseSingleProxyList() {
- ProxyConfig config;
- config.proxy_rules().ParseFromString(
- "https://proxy1:8080,http://proxy2,direct://");
- return {std::move(config),
- "{\"single_proxy\":[\"https://proxy1:8080\",\"proxy2:80\",\"direct://"
- "\"]}"};
- }
- INSTANTIATE_TEST_SUITE_P(
- All,
- ProxyConfigToValueTest,
- testing::Values(GetTestCaseDirect(),
- GetTestCaseAutoDetect(),
- GetTestCasePacUrl(),
- GetTestCasePacUrlMandatory(),
- GetTestCasePacUrlAndAutoDetect(),
- GetTestCaseSingleProxy(),
- GetTestCaseSingleProxyWithBypass(),
- GetTestCaseSingleProxyWithReversedBypass(),
- GetTestCaseProxyPerScheme(),
- GetTestCaseSingleProxyList()));
- TEST(ProxyConfigTest, ParseProxyRules) {
- const struct {
- const char* proxy_rules;
- ProxyConfig::ProxyRules::Type type;
- // These will be PAC-stle strings, eg 'PROXY foo.com'
- const char* single_proxy;
- const char* proxy_for_http;
- const char* proxy_for_https;
- const char* proxy_for_ftp;
- const char* fallback_proxy;
- } tests[] = {
- // One HTTP proxy for all schemes.
- {
- "myproxy:80",
- ProxyConfig::ProxyRules::Type::PROXY_LIST,
- "PROXY myproxy:80",
- nullptr,
- nullptr,
- nullptr,
- nullptr,
- },
- // Multiple HTTP proxies for all schemes.
- {
- "myproxy:80,https://myotherproxy",
- ProxyConfig::ProxyRules::Type::PROXY_LIST,
- "PROXY myproxy:80;HTTPS myotherproxy:443",
- nullptr,
- nullptr,
- nullptr,
- nullptr,
- },
- // Only specify a proxy server for "http://" urls.
- {
- "http=myproxy:80",
- ProxyConfig::ProxyRules::Type::PROXY_LIST_PER_SCHEME,
- nullptr,
- "PROXY myproxy:80",
- nullptr,
- nullptr,
- nullptr,
- },
- // Specify an HTTP proxy for "ftp://" and a SOCKS proxy for "https://"
- // urls.
- {
- "ftp=ftp-proxy ; https=socks4://foopy",
- ProxyConfig::ProxyRules::Type::PROXY_LIST_PER_SCHEME,
- nullptr,
- nullptr,
- "SOCKS foopy:1080",
- "PROXY ftp-proxy:80",
- nullptr,
- },
- // Give a scheme-specific proxy as well as a non-scheme specific.
- // The first entry "foopy" takes precedance marking this list as
- // Type::PROXY_LIST.
- {
- "foopy ; ftp=ftp-proxy",
- ProxyConfig::ProxyRules::Type::PROXY_LIST,
- "PROXY foopy:80",
- nullptr,
- nullptr,
- nullptr,
- nullptr,
- },
- // Give a scheme-specific proxy as well as a non-scheme specific.
- // The first entry "ftp=ftp-proxy" takes precedance marking this list as
- // Type::PROXY_LIST_PER_SCHEME.
- {
- "ftp=ftp-proxy ; foopy",
- ProxyConfig::ProxyRules::Type::PROXY_LIST_PER_SCHEME,
- nullptr,
- nullptr,
- nullptr,
- "PROXY ftp-proxy:80",
- nullptr,
- },
- // Include a list of entries for a single scheme.
- {
- "ftp=ftp1,ftp2,ftp3",
- ProxyConfig::ProxyRules::Type::PROXY_LIST_PER_SCHEME,
- nullptr,
- nullptr,
- nullptr,
- "PROXY ftp1:80;PROXY ftp2:80;PROXY ftp3:80",
- nullptr,
- },
- // Include multiple entries for the same scheme -- they accumulate.
- {
- "http=http1,http2; http=http3",
- ProxyConfig::ProxyRules::Type::PROXY_LIST_PER_SCHEME,
- nullptr,
- "PROXY http1:80;PROXY http2:80;PROXY http3:80",
- nullptr,
- nullptr,
- nullptr,
- },
- // Include lists of entries for multiple schemes.
- {
- "ftp=ftp1,ftp2,ftp3 ; http=http1,http2; ",
- ProxyConfig::ProxyRules::Type::PROXY_LIST_PER_SCHEME,
- nullptr,
- "PROXY http1:80;PROXY http2:80",
- nullptr,
- "PROXY ftp1:80;PROXY ftp2:80;PROXY ftp3:80",
- nullptr,
- },
- // Include non-default proxy schemes.
- {
- "http=https://secure_proxy; ftp=socks4://socks_proxy; "
- "https=socks://foo",
- ProxyConfig::ProxyRules::Type::PROXY_LIST_PER_SCHEME,
- nullptr,
- "HTTPS secure_proxy:443",
- "SOCKS5 foo:1080",
- "SOCKS socks_proxy:1080",
- nullptr,
- },
- // Only SOCKS proxy present, others being blank.
- {
- "socks=foopy",
- ProxyConfig::ProxyRules::Type::PROXY_LIST_PER_SCHEME,
- nullptr,
- nullptr,
- nullptr,
- nullptr,
- "SOCKS foopy:1080",
- },
- // SOCKS proxy present along with other proxies too
- {
- "http=httpproxy ; https=httpsproxy ; ftp=ftpproxy ; socks=foopy ",
- ProxyConfig::ProxyRules::Type::PROXY_LIST_PER_SCHEME,
- nullptr,
- "PROXY httpproxy:80",
- "PROXY httpsproxy:80",
- "PROXY ftpproxy:80",
- "SOCKS foopy:1080",
- },
- // SOCKS proxy (with modifier) present along with some proxies
- // (FTP being blank)
- {
- "http=httpproxy ; https=httpsproxy ; socks=socks5://foopy ",
- ProxyConfig::ProxyRules::Type::PROXY_LIST_PER_SCHEME,
- nullptr,
- "PROXY httpproxy:80",
- "PROXY httpsproxy:80",
- nullptr,
- "SOCKS5 foopy:1080",
- },
- // Include unsupported schemes -- they are discarded.
- {
- "crazy=foopy ; foo=bar ; https=myhttpsproxy",
- ProxyConfig::ProxyRules::Type::PROXY_LIST_PER_SCHEME,
- nullptr,
- nullptr,
- "PROXY myhttpsproxy:80",
- nullptr,
- nullptr,
- },
- // direct:// as first option for a scheme.
- {
- "http=direct://,myhttpproxy; https=direct://",
- ProxyConfig::ProxyRules::Type::PROXY_LIST_PER_SCHEME,
- nullptr,
- "DIRECT;PROXY myhttpproxy:80",
- "DIRECT",
- nullptr,
- nullptr,
- },
- // direct:// as a second option for a scheme.
- {
- "http=myhttpproxy,direct://",
- ProxyConfig::ProxyRules::Type::PROXY_LIST_PER_SCHEME,
- nullptr,
- "PROXY myhttpproxy:80;DIRECT",
- nullptr,
- nullptr,
- nullptr,
- },
- };
- ProxyConfig config;
- for (const auto& test : tests) {
- config.proxy_rules().ParseFromString(test.proxy_rules);
- EXPECT_EQ(test.type, config.proxy_rules().type);
- ExpectProxyServerEquals(test.single_proxy,
- config.proxy_rules().single_proxies);
- ExpectProxyServerEquals(test.proxy_for_http,
- config.proxy_rules().proxies_for_http);
- ExpectProxyServerEquals(test.proxy_for_https,
- config.proxy_rules().proxies_for_https);
- ExpectProxyServerEquals(test.proxy_for_ftp,
- config.proxy_rules().proxies_for_ftp);
- ExpectProxyServerEquals(test.fallback_proxy,
- config.proxy_rules().fallback_proxies);
- }
- }
- TEST(ProxyConfigTest, ProxyRulesSetBypassFlag) {
- // Test whether the did_bypass_proxy() flag is set in proxy info correctly.
- ProxyConfig::ProxyRules rules;
- ProxyInfo result;
- rules.ParseFromString("http=httpproxy:80");
- rules.bypass_rules.AddRuleFromString(".com");
- rules.Apply(GURL("http://example.com"), &result);
- EXPECT_TRUE(result.is_direct_only());
- EXPECT_TRUE(result.did_bypass_proxy());
- rules.Apply(GURL("http://example.org"), &result);
- EXPECT_FALSE(result.is_direct());
- EXPECT_FALSE(result.did_bypass_proxy());
- // Try with reversed bypass rules.
- rules.reverse_bypass = true;
- rules.Apply(GURL("http://example.org"), &result);
- EXPECT_TRUE(result.is_direct_only());
- EXPECT_TRUE(result.did_bypass_proxy());
- rules.Apply(GURL("http://example.com"), &result);
- EXPECT_FALSE(result.is_direct());
- EXPECT_FALSE(result.did_bypass_proxy());
- }
- static const char kWsUrl[] = "ws://example.com/echo";
- static const char kWssUrl[] = "wss://example.com/echo";
- class ProxyConfigWebSocketTest : public ::testing::Test {
- protected:
- void ParseFromString(const std::string& rules) {
- rules_.ParseFromString(rules);
- }
- void Apply(const GURL& gurl) { rules_.Apply(gurl, &info_); }
- std::string ToPacString() const { return info_.ToPacString(); }
- static GURL WsUrl() { return GURL(kWsUrl); }
- static GURL WssUrl() { return GURL(kWssUrl); }
- ProxyConfig::ProxyRules rules_;
- ProxyInfo info_;
- };
- // If a single proxy is set for all protocols, WebSocket uses it.
- TEST_F(ProxyConfigWebSocketTest, UsesProxy) {
- ParseFromString("proxy:3128");
- Apply(WsUrl());
- EXPECT_EQ("PROXY proxy:3128", ToPacString());
- }
- // See RFC6455 Section 4.1. item 3, "_Proxy Usage_". Note that this favors a
- // SOCKSv4 proxy (although technically the spec only notes SOCKSv5).
- TEST_F(ProxyConfigWebSocketTest, PrefersSocksV4) {
- ParseFromString(
- "http=proxy:3128 ; https=sslproxy:3128 ; socks=socksproxy:1080");
- Apply(WsUrl());
- EXPECT_EQ("SOCKS socksproxy:1080", ToPacString());
- }
- // See RFC6455 Section 4.1. item 3, "_Proxy Usage_".
- TEST_F(ProxyConfigWebSocketTest, PrefersSocksV5) {
- ParseFromString(
- "http=proxy:3128 ; https=sslproxy:3128 ; socks=socks5://socksproxy:1080");
- Apply(WsUrl());
- EXPECT_EQ("SOCKS5 socksproxy:1080", ToPacString());
- }
- TEST_F(ProxyConfigWebSocketTest, PrefersHttpsToHttp) {
- ParseFromString("http=proxy:3128 ; https=sslproxy:3128");
- Apply(WssUrl());
- EXPECT_EQ("PROXY sslproxy:3128", ToPacString());
- }
- // Tests when a proxy-per-url-scheme configuration was used, and proxies are
- // specified for http://, https://, and a fallback proxy (non-SOCKS).
- // Even though the fallback proxy is not SOCKS, it is still favored over the
- // proxy for http://* and https://*.
- TEST_F(ProxyConfigWebSocketTest, PrefersNonSocksFallbackOverHttps) {
- // The notation for "socks=" is abused to set the "fallback proxy".
- ParseFromString(
- "http=proxy:3128 ; https=sslproxy:3128; socks=https://httpsproxy");
- EXPECT_EQ("HTTPS httpsproxy:443", rules_.fallback_proxies.ToPacString());
- Apply(WssUrl());
- EXPECT_EQ("HTTPS httpsproxy:443", ToPacString());
- }
- // Tests when a proxy-per-url-scheme configuration was used, and the fallback
- // proxy is a non-SOCKS proxy, and no proxy was given for https://* or
- // http://*. The fallback proxy is used.
- TEST_F(ProxyConfigWebSocketTest, UsesNonSocksFallbackProxy) {
- // The notation for "socks=" is abused to set the "fallback proxy".
- ParseFromString("ftp=ftpproxy:3128; socks=https://httpsproxy");
- EXPECT_EQ("HTTPS httpsproxy:443", rules_.fallback_proxies.ToPacString());
- Apply(WssUrl());
- EXPECT_EQ("HTTPS httpsproxy:443", ToPacString());
- }
- TEST_F(ProxyConfigWebSocketTest, PrefersHttpsEvenForWs) {
- ParseFromString("http=proxy:3128 ; https=sslproxy:3128");
- Apply(WsUrl());
- EXPECT_EQ("PROXY sslproxy:3128", ToPacString());
- }
- TEST_F(ProxyConfigWebSocketTest, PrefersHttpToDirect) {
- ParseFromString("http=proxy:3128");
- Apply(WssUrl());
- EXPECT_EQ("PROXY proxy:3128", ToPacString());
- }
- TEST_F(ProxyConfigWebSocketTest, IgnoresFtpProxy) {
- ParseFromString("ftp=ftpproxy:3128");
- Apply(WssUrl());
- EXPECT_EQ("DIRECT", ToPacString());
- }
- TEST_F(ProxyConfigWebSocketTest, ObeysBypassRules) {
- ParseFromString("http=proxy:3128 ; https=sslproxy:3128");
- rules_.bypass_rules.AddRuleFromString(".chromium.org");
- Apply(GURL("wss://codereview.chromium.org/feed"));
- EXPECT_EQ("DIRECT", ToPacString());
- }
- TEST_F(ProxyConfigWebSocketTest, ObeysLocalBypass) {
- ParseFromString("http=proxy:3128 ; https=sslproxy:3128");
- rules_.bypass_rules.AddRuleFromString("<local>");
- Apply(GURL("ws://localhost/feed"));
- EXPECT_EQ("DIRECT", ToPacString());
- }
- } // namespace
- } // namespace net
|