// Copyright (c) 2010 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 "base/basictypes.h" #include "net/proxy/proxy_server.h" #include "testing/gtest/include/gtest/gtest.h" // Test the creation of ProxyServer using ProxyServer::FromURI, which parses // inputs of the form [<scheme>"://"]<host>[":"<port>]. Verify that each part // was labelled correctly, and the accessors all give the right data. TEST(ProxyServerTest, FromURI) { const struct { const char* input_uri; const char* expected_uri; net::ProxyServer::Scheme expected_scheme; const char* expected_host; int expected_port; const char* expected_pac_string; } tests[] = { // HTTP proxy URIs: { "foopy:10", // No scheme. "foopy:10", net::ProxyServer::SCHEME_HTTP, "foopy", 10, "PROXY foopy:10" }, { "http://foopy", // No port. "foopy:80", net::ProxyServer::SCHEME_HTTP, "foopy", 80, "PROXY foopy:80" }, { "http://foopy:10", "foopy:10", net::ProxyServer::SCHEME_HTTP, "foopy", 10, "PROXY foopy:10" }, // IPv6 HTTP proxy URIs: { "[FEDC:BA98:7654:3210:FEDC:BA98:7654:3210]:10", // No scheme. "[FEDC:BA98:7654:3210:FEDC:BA98:7654:3210]:10", net::ProxyServer::SCHEME_HTTP, "FEDC:BA98:7654:3210:FEDC:BA98:7654:3210", 10, "PROXY [FEDC:BA98:7654:3210:FEDC:BA98:7654:3210]:10" }, { "http://[3ffe:2a00:100:7031::1]", // No port. "[3ffe:2a00:100:7031::1]:80", net::ProxyServer::SCHEME_HTTP, "3ffe:2a00:100:7031::1", 80, "PROXY [3ffe:2a00:100:7031::1]:80" }, { "http://[::192.9.5.5]", "[::192.9.5.5]:80", net::ProxyServer::SCHEME_HTTP, "::192.9.5.5", 80, "PROXY [::192.9.5.5]:80" }, { "http://[::FFFF:129.144.52.38]:80", "[::FFFF:129.144.52.38]:80", net::ProxyServer::SCHEME_HTTP, "::FFFF:129.144.52.38", 80, "PROXY [::FFFF:129.144.52.38]:80" }, // SOCKS4 proxy URIs: { "socks4://foopy", // No port. "socks4://foopy:1080", net::ProxyServer::SCHEME_SOCKS4, "foopy", 1080, "SOCKS foopy:1080" }, { "socks4://foopy:10", "socks4://foopy:10", net::ProxyServer::SCHEME_SOCKS4, "foopy", 10, "SOCKS foopy:10" }, // SOCKS5 proxy URIs { "socks5://foopy", // No port. "socks5://foopy:1080", net::ProxyServer::SCHEME_SOCKS5, "foopy", 1080, "SOCKS5 foopy:1080" }, { "socks5://foopy:10", "socks5://foopy:10", net::ProxyServer::SCHEME_SOCKS5, "foopy", 10, "SOCKS5 foopy:10" }, // SOCKS proxy URIs (should default to SOCKS5) { "socks://foopy", // No port. "socks5://foopy:1080", net::ProxyServer::SCHEME_SOCKS5, "foopy", 1080, "SOCKS5 foopy:1080" }, { "socks://foopy:10", "socks5://foopy:10", net::ProxyServer::SCHEME_SOCKS5, "foopy", 10, "SOCKS5 foopy:10" }, // HTTPS proxy URIs: { "https://foopy", // No port "https://foopy:443", net::ProxyServer::SCHEME_HTTPS, "foopy", 443, "HTTPS foopy:443" }, { "https://foopy:10", // Non-standard port "https://foopy:10", net::ProxyServer::SCHEME_HTTPS, "foopy", 10, "HTTPS foopy:10" }, { "https://1.2.3.4:10", // IP Address "https://1.2.3.4:10", net::ProxyServer::SCHEME_HTTPS, "1.2.3.4", 10, "HTTPS 1.2.3.4:10" }, }; for (size_t i = 0; i < ARRAYSIZE_UNSAFE(tests); ++i) { net::ProxyServer uri = net::ProxyServer::FromURI(tests[i].input_uri, net::ProxyServer::SCHEME_HTTP); EXPECT_TRUE(uri.is_valid()); EXPECT_FALSE(uri.is_direct()); EXPECT_EQ(tests[i].expected_uri, uri.ToURI()); EXPECT_EQ(tests[i].expected_scheme, uri.scheme()); EXPECT_EQ(tests[i].expected_host, uri.host_port_pair().host()); EXPECT_EQ(tests[i].expected_port, uri.host_port_pair().port()); EXPECT_EQ(tests[i].expected_pac_string, uri.ToPacString()); } } TEST(ProxyServerTest, DefaultConstructor) { net::ProxyServer proxy_server; EXPECT_FALSE(proxy_server.is_valid()); } // Test parsing of the special URI form "direct://". Analagous to the "DIRECT" // entry in a PAC result. TEST(ProxyServerTest, Direct) { net::ProxyServer uri = net::ProxyServer::FromURI("direct://", net::ProxyServer::SCHEME_HTTP); EXPECT_TRUE(uri.is_valid()); EXPECT_TRUE(uri.is_direct()); EXPECT_EQ("direct://", uri.ToURI()); EXPECT_EQ("DIRECT", uri.ToPacString()); } // Test parsing some invalid inputs. TEST(ProxyServerTest, Invalid) { const char* tests[] = { "", " ", "dddf:", // not a valid port "dddd:d", // not a valid port "http://", // not a valid host/port. "direct://xyz", // direct is not allowed a host/port. "http:/", // ambiguous, but will fail because of bad port. "http:", // ambiguous, but will fail because of bad port. }; for (size_t i = 0; i < ARRAYSIZE_UNSAFE(tests); ++i) { net::ProxyServer uri = net::ProxyServer::FromURI(tests[i], net::ProxyServer::SCHEME_HTTP); EXPECT_FALSE(uri.is_valid()); EXPECT_FALSE(uri.is_direct()); EXPECT_FALSE(uri.is_http()); EXPECT_FALSE(uri.is_socks()); } } // Test that LWS (SP | HT) is disregarded from the ends. TEST(ProxyServerTest, Whitespace) { const char* tests[] = { " foopy:80", "foopy:80 \t", " \tfoopy:80 ", }; for (size_t i = 0; i < ARRAYSIZE_UNSAFE(tests); ++i) { net::ProxyServer uri = net::ProxyServer::FromURI(tests[i], net::ProxyServer::SCHEME_HTTP); EXPECT_EQ("foopy:80", uri.ToURI()); } } // Test parsing a ProxyServer from a PAC representation. TEST(ProxyServerTest, FromPACString) { const struct { const char* input_pac; const char* expected_uri; } tests[] = { { "PROXY foopy:10", "foopy:10", }, { " PROXY foopy:10 ", "foopy:10", }, { "pRoXy foopy:10", "foopy:10", }, { "PROXY foopy", // No port. "foopy:80", }, { "socks foopy", "socks4://foopy:1080", }, { "socks4 foopy", "socks4://foopy:1080", }, { "socks5 foopy", "socks5://foopy:1080", }, { "socks5 foopy:11", "socks5://foopy:11", }, { " direct ", "direct://", }, { "https foopy", "https://foopy:443", }, { "https foopy:10", "https://foopy:10", }, }; for (size_t i = 0; i < ARRAYSIZE_UNSAFE(tests); ++i) { net::ProxyServer uri = net::ProxyServer::FromPacString(tests[i].input_pac); EXPECT_TRUE(uri.is_valid()); EXPECT_EQ(tests[i].expected_uri, uri.ToURI()); } } // Test parsing a ProxyServer from an invalid PAC representation. TEST(ProxyServerTest, FromPACStringInvalid) { const char* tests[] = { "PROXY", // missing host/port. "HTTPS", // missing host/port. "SOCKS", // missing host/port. "DIRECT foopy:10", // direct cannot have host/port. }; for (size_t i = 0; i < ARRAYSIZE_UNSAFE(tests); ++i) { net::ProxyServer uri = net::ProxyServer::FromPacString(tests[i]); EXPECT_FALSE(uri.is_valid()); } } TEST(ProxyServerTest, ComparatorAndEquality) { struct { // Inputs. const char* server1; const char* server2; // Expectation. // -1 means server1 is less than server2 // 0 means server1 equals server2 // 1 means server1 is greater than server2 int expected_comparison; } tests[] = { { // Equal. "foo:11", "http://foo:11", 0 }, { // Port is different. "foo:333", "foo:444", -1 }, { // Host is different. "foo:33", "bar:33", 1 }, { // Scheme is different. "socks4://foo:33", "http://foo:33", 1 }, }; for (size_t i = 0; i < ARRAYSIZE_UNSAFE(tests); ++i) { // Parse the expected inputs to ProxyServer instances. const net::ProxyServer server1 = net::ProxyServer::FromURI( tests[i].server1, net::ProxyServer::SCHEME_HTTP); const net::ProxyServer server2 = net::ProxyServer::FromURI( tests[i].server2, net::ProxyServer::SCHEME_HTTP); switch (tests[i].expected_comparison) { case -1: EXPECT_TRUE(server1 < server2); EXPECT_FALSE(server2 < server1); EXPECT_FALSE(server2 == server1); break; case 0: EXPECT_FALSE(server1 < server2); EXPECT_FALSE(server2 < server1); EXPECT_TRUE(server2 == server1); break; case 1: EXPECT_FALSE(server1 < server2); EXPECT_TRUE(server2 < server1); EXPECT_FALSE(server2 == server1); break; default: FAIL() << "Invalid expectation. Can be only -1, 0, 1"; } } }