// Copyright 2010 The Chromium Authors // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. #include "net/base/proxy_server.h" #include "base/strings/string_number_conversions.h" #include "net/base/proxy_string_util.h" #include "testing/gtest/include/gtest/gtest.h" #include "third_party/abseil-cpp/absl/types/optional.h" namespace net { namespace { TEST(ProxyServerTest, DefaultConstructor) { ProxyServer proxy_server; EXPECT_FALSE(proxy_server.is_valid()); } TEST(ProxyServerTest, FromSchemeHostAndPort) { const struct { const ProxyServer::Scheme input_scheme; const char* const input_host; const absl::optional input_port; const char* const input_port_str; const char* const expected_host; const uint16_t expected_port; } tests[] = { {ProxyServer::SCHEME_HTTP, "foopy", 80, "80", "foopy", 80}, // Non-standard port {ProxyServer::SCHEME_HTTP, "foopy", 10, "10", "foopy", 10}, {ProxyServer::SCHEME_HTTP, "foopy", 0, "0", "foopy", 0}, // Hostname canonicalization {ProxyServer::SCHEME_HTTP, "FoOpY", 80, "80", "foopy", 80}, {ProxyServer::SCHEME_HTTP, "f\u00fcpy", 80, "80", "xn--fpy-hoa", 80}, // IPv4 literal {ProxyServer::SCHEME_HTTP, "1.2.3.4", 80, "80", "1.2.3.4", 80}, // IPv4 literal canonicalization {ProxyServer::SCHEME_HTTP, "127.1", 80, "80", "127.0.0.1", 80}, {ProxyServer::SCHEME_HTTP, "0x7F.0x1", 80, "80", "127.0.0.1", 80}, {ProxyServer::SCHEME_HTTP, "0177.01", 80, "80", "127.0.0.1", 80}, // IPv6 literal {ProxyServer::SCHEME_HTTP, "[3ffe:2a00:100:7031::1]", 80, "80", "[3ffe:2a00:100:7031::1]", 80}, {ProxyServer::SCHEME_HTTP, "3ffe:2a00:100:7031::1", 80, "80", "[3ffe:2a00:100:7031::1]", 80}, // IPv6 literal canonicalization {ProxyServer::SCHEME_HTTP, "FEDC:BA98:7654:3210:FEDC:BA98:7654:3210", 80, "80", "[fedc:ba98:7654:3210:fedc:ba98:7654:3210]", 80}, {ProxyServer::SCHEME_HTTP, "::192.9.5.5", 80, "80", "[::c009:505]", 80}, // Other schemes {ProxyServer::SCHEME_HTTPS, "foopy", 111, "111", "foopy", 111}, {ProxyServer::SCHEME_QUIC, "foopy", 111, "111", "foopy", 111}, {ProxyServer::SCHEME_SOCKS4, "foopy", 111, "111", "foopy", 111}, {ProxyServer::SCHEME_SOCKS5, "foopy", 111, "111", "foopy", 111}, // Default ports {ProxyServer::SCHEME_HTTP, "foopy", absl::nullopt, "", "foopy", 80}, {ProxyServer::SCHEME_HTTPS, "foopy", absl::nullopt, "", "foopy", 443}, {ProxyServer::SCHEME_QUIC, "foopy", absl::nullopt, "", "foopy", 443}, {ProxyServer::SCHEME_SOCKS4, "foopy", absl::nullopt, "", "foopy", 1080}, {ProxyServer::SCHEME_SOCKS5, "foopy", absl::nullopt, "", "foopy", 1080}, }; for (size_t i = 0; i < std::size(tests); ++i) { SCOPED_TRACE(base::NumberToString(i) + ": " + tests[i].input_host + ":" + base::NumberToString(tests[i].input_port.value_or(-1))); auto proxy = ProxyServer::FromSchemeHostAndPort( tests[i].input_scheme, tests[i].input_host, tests[i].input_port); ASSERT_TRUE(proxy.is_valid()); EXPECT_EQ(proxy.scheme(), tests[i].input_scheme); EXPECT_EQ(proxy.GetHost(), tests[i].expected_host); EXPECT_EQ(proxy.GetPort(), tests[i].expected_port); auto proxy_from_string_port = ProxyServer::FromSchemeHostAndPort( tests[i].input_scheme, tests[i].input_host, tests[i].input_port_str); EXPECT_TRUE(proxy_from_string_port.is_valid()); EXPECT_EQ(proxy, proxy_from_string_port); } } TEST(ProxyServerTest, InvalidHostname) { const char* const tests[]{ "", "[]", "[foo]", "foo:", "foo:80", ":", "http://foo", "3ffe:2a00:100:7031::1]", "[3ffe:2a00:100:7031::1", "foo.80", }; for (size_t i = 0; i < std::size(tests); ++i) { SCOPED_TRACE(base::NumberToString(i) + ": " + tests[i]); auto proxy = ProxyServer::FromSchemeHostAndPort(ProxyServer::SCHEME_HTTP, tests[i], 80); EXPECT_FALSE(proxy.is_valid()); } } TEST(ProxyServerTest, InvalidPort) { const char* const tests[]{ "-1", "65536", "foo", "0x35", }; for (size_t i = 0; i < std::size(tests); ++i) { SCOPED_TRACE(base::NumberToString(i) + ": " + tests[i]); auto proxy = ProxyServer::FromSchemeHostAndPort(ProxyServer::SCHEME_HTTP, "foopy", tests[i]); EXPECT_FALSE(proxy.is_valid()); } } TEST(ProxyServerTest, ComparatorAndEquality) { const struct { // Inputs. ProxyServer server1; ProxyServer server2; // Expectation. // -1 means server1 is less than server2 // 0 means server1 equals server2 // 1 means server1 is greater than server2 int expected_comparison; } kTests[] = { {// Equal. ProxyUriToProxyServer("foo:11", ProxyServer::SCHEME_HTTP), ProxyUriToProxyServer("http://foo:11", ProxyServer::SCHEME_HTTP), 0}, {// Port is different. ProxyUriToProxyServer("foo:333", ProxyServer::SCHEME_HTTP), ProxyUriToProxyServer("foo:444", ProxyServer::SCHEME_HTTP), -1}, {// Host is different. ProxyUriToProxyServer("foo:33", ProxyServer::SCHEME_HTTP), ProxyUriToProxyServer("bar:33", ProxyServer::SCHEME_HTTP), 1}, {// Scheme is different. ProxyUriToProxyServer("socks4://foo:33", ProxyServer::SCHEME_HTTP), ProxyUriToProxyServer("http://foo:33", ProxyServer::SCHEME_HTTP), 1}, }; for (const auto& test : kTests) { EXPECT_TRUE(test.server1.is_valid()); EXPECT_TRUE(test.server2.is_valid()); switch (test.expected_comparison) { case -1: EXPECT_TRUE(test.server1 < test.server2); EXPECT_FALSE(test.server2 < test.server1); EXPECT_FALSE(test.server2 == test.server1); EXPECT_FALSE(test.server1 == test.server2); break; case 0: EXPECT_FALSE(test.server1 < test.server2); EXPECT_FALSE(test.server2 < test.server1); EXPECT_TRUE(test.server2 == test.server1); EXPECT_TRUE(test.server1 == test.server2); break; case 1: EXPECT_FALSE(test.server1 < test.server2); EXPECT_TRUE(test.server2 < test.server1); EXPECT_FALSE(test.server2 == test.server1); EXPECT_FALSE(test.server1 == test.server2); break; default: FAIL() << "Invalid expectation. Can be only -1, 0, 1"; } } } // Tests the various "is_*()" methods on ProxyServer. TEST(ProxyServerTest, Properties) { // HTTP proxy. { auto proxy = PacResultElementToProxyServer("PROXY foo"); ASSERT_TRUE(proxy.is_valid()); EXPECT_TRUE(proxy.is_http()); EXPECT_FALSE(proxy.is_https()); EXPECT_TRUE(proxy.is_http_like()); EXPECT_FALSE(proxy.is_secure_http_like()); } // HTTPS proxy. { auto proxy = PacResultElementToProxyServer("HTTPS foo"); ASSERT_TRUE(proxy.is_valid()); EXPECT_FALSE(proxy.is_http()); EXPECT_TRUE(proxy.is_https()); EXPECT_TRUE(proxy.is_http_like()); EXPECT_TRUE(proxy.is_secure_http_like()); } // QUIC proxy. { auto proxy = PacResultElementToProxyServer("QUIC foo"); ASSERT_TRUE(proxy.is_valid()); EXPECT_FALSE(proxy.is_http()); EXPECT_FALSE(proxy.is_https()); EXPECT_TRUE(proxy.is_http_like()); EXPECT_TRUE(proxy.is_secure_http_like()); } // SOCKS5 proxy. { auto proxy = PacResultElementToProxyServer("SOCKS5 foo"); ASSERT_TRUE(proxy.is_valid()); EXPECT_FALSE(proxy.is_http()); EXPECT_FALSE(proxy.is_https()); EXPECT_FALSE(proxy.is_http_like()); EXPECT_FALSE(proxy.is_secure_http_like()); } // DIRECT { auto proxy = PacResultElementToProxyServer("DIRECT"); ASSERT_TRUE(proxy.is_valid()); EXPECT_FALSE(proxy.is_http()); EXPECT_FALSE(proxy.is_https()); EXPECT_FALSE(proxy.is_http_like()); EXPECT_FALSE(proxy.is_secure_http_like()); } } } // namespace } // namespace net