1 // Copyright 2010 The Chromium Authors
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/base/proxy_server.h"
6
7 #include "base/strings/string_number_conversions.h"
8 #include "net/base/proxy_string_util.h"
9 #include "testing/gtest/include/gtest/gtest.h"
10 #include "third_party/abseil-cpp/absl/types/optional.h"
11
12 namespace net {
13
14 namespace {
15
TEST(ProxyServerTest,DefaultConstructor)16 TEST(ProxyServerTest, DefaultConstructor) {
17 ProxyServer proxy_server;
18 EXPECT_FALSE(proxy_server.is_valid());
19 }
20
TEST(ProxyServerTest,FromSchemeHostAndPort)21 TEST(ProxyServerTest, FromSchemeHostAndPort) {
22 const struct {
23 const ProxyServer::Scheme input_scheme;
24 const char* const input_host;
25 const absl::optional<uint16_t> input_port;
26 const char* const input_port_str;
27 const char* const expected_host;
28 const uint16_t expected_port;
29 } tests[] = {
30 {ProxyServer::SCHEME_HTTP, "foopy", 80, "80", "foopy", 80},
31
32 // Non-standard port
33 {ProxyServer::SCHEME_HTTP, "foopy", 10, "10", "foopy", 10},
34 {ProxyServer::SCHEME_HTTP, "foopy", 0, "0", "foopy", 0},
35
36 // Hostname canonicalization
37 {ProxyServer::SCHEME_HTTP, "FoOpY", 80, "80", "foopy", 80},
38 {ProxyServer::SCHEME_HTTP, "f\u00fcpy", 80, "80", "xn--fpy-hoa", 80},
39
40 // IPv4 literal
41 {ProxyServer::SCHEME_HTTP, "1.2.3.4", 80, "80", "1.2.3.4", 80},
42
43 // IPv4 literal canonicalization
44 {ProxyServer::SCHEME_HTTP, "127.1", 80, "80", "127.0.0.1", 80},
45 {ProxyServer::SCHEME_HTTP, "0x7F.0x1", 80, "80", "127.0.0.1", 80},
46 {ProxyServer::SCHEME_HTTP, "0177.01", 80, "80", "127.0.0.1", 80},
47
48 // IPv6 literal
49 {ProxyServer::SCHEME_HTTP, "[3ffe:2a00:100:7031::1]", 80, "80",
50 "[3ffe:2a00:100:7031::1]", 80},
51 {ProxyServer::SCHEME_HTTP, "3ffe:2a00:100:7031::1", 80, "80",
52 "[3ffe:2a00:100:7031::1]", 80},
53
54 // IPv6 literal canonicalization
55 {ProxyServer::SCHEME_HTTP, "FEDC:BA98:7654:3210:FEDC:BA98:7654:3210", 80,
56 "80", "[fedc:ba98:7654:3210:fedc:ba98:7654:3210]", 80},
57 {ProxyServer::SCHEME_HTTP, "::192.9.5.5", 80, "80", "[::c009:505]", 80},
58
59 // Other schemes
60 {ProxyServer::SCHEME_HTTPS, "foopy", 111, "111", "foopy", 111},
61 {ProxyServer::SCHEME_QUIC, "foopy", 111, "111", "foopy", 111},
62 {ProxyServer::SCHEME_SOCKS4, "foopy", 111, "111", "foopy", 111},
63 {ProxyServer::SCHEME_SOCKS5, "foopy", 111, "111", "foopy", 111},
64
65 // Default ports
66 {ProxyServer::SCHEME_HTTP, "foopy", absl::nullopt, "", "foopy", 80},
67 {ProxyServer::SCHEME_HTTPS, "foopy", absl::nullopt, "", "foopy", 443},
68 {ProxyServer::SCHEME_QUIC, "foopy", absl::nullopt, "", "foopy", 443},
69 {ProxyServer::SCHEME_SOCKS4, "foopy", absl::nullopt, "", "foopy", 1080},
70 {ProxyServer::SCHEME_SOCKS5, "foopy", absl::nullopt, "", "foopy", 1080},
71 };
72
73 for (size_t i = 0; i < std::size(tests); ++i) {
74 SCOPED_TRACE(base::NumberToString(i) + ": " + tests[i].input_host + ":" +
75 base::NumberToString(tests[i].input_port.value_or(-1)));
76 auto proxy = ProxyServer::FromSchemeHostAndPort(
77 tests[i].input_scheme, tests[i].input_host, tests[i].input_port);
78
79 ASSERT_TRUE(proxy.is_valid());
80 EXPECT_EQ(proxy.scheme(), tests[i].input_scheme);
81 EXPECT_EQ(proxy.GetHost(), tests[i].expected_host);
82 EXPECT_EQ(proxy.GetPort(), tests[i].expected_port);
83
84 auto proxy_from_string_port = ProxyServer::FromSchemeHostAndPort(
85 tests[i].input_scheme, tests[i].input_host, tests[i].input_port_str);
86 EXPECT_TRUE(proxy_from_string_port.is_valid());
87 EXPECT_EQ(proxy, proxy_from_string_port);
88 }
89 }
90
TEST(ProxyServerTest,InvalidHostname)91 TEST(ProxyServerTest, InvalidHostname) {
92 const char* const tests[]{
93 "",
94 "[]",
95 "[foo]",
96 "foo:",
97 "foo:80",
98 ":",
99 "http://foo",
100 "3ffe:2a00:100:7031::1]",
101 "[3ffe:2a00:100:7031::1",
102 "foo.80",
103 };
104
105 for (size_t i = 0; i < std::size(tests); ++i) {
106 SCOPED_TRACE(base::NumberToString(i) + ": " + tests[i]);
107 auto proxy = ProxyServer::FromSchemeHostAndPort(ProxyServer::SCHEME_HTTP,
108 tests[i], 80);
109 EXPECT_FALSE(proxy.is_valid());
110 }
111 }
112
TEST(ProxyServerTest,InvalidPort)113 TEST(ProxyServerTest, InvalidPort) {
114 const char* const tests[]{
115 "-1",
116 "65536",
117 "foo",
118 "0x35",
119 };
120
121 for (size_t i = 0; i < std::size(tests); ++i) {
122 SCOPED_TRACE(base::NumberToString(i) + ": " + tests[i]);
123 auto proxy = ProxyServer::FromSchemeHostAndPort(ProxyServer::SCHEME_HTTP,
124 "foopy", tests[i]);
125 EXPECT_FALSE(proxy.is_valid());
126 }
127 }
128
TEST(ProxyServerTest,ComparatorAndEquality)129 TEST(ProxyServerTest, ComparatorAndEquality) {
130 const struct {
131 // Inputs.
132 ProxyServer server1;
133 ProxyServer server2;
134
135 // Expectation.
136 // -1 means server1 is less than server2
137 // 0 means server1 equals server2
138 // 1 means server1 is greater than server2
139 int expected_comparison;
140 } kTests[] = {
141 {// Equal.
142 ProxyUriToProxyServer("foo:11", ProxyServer::SCHEME_HTTP),
143 ProxyUriToProxyServer("http://foo:11", ProxyServer::SCHEME_HTTP), 0},
144 {// Port is different.
145 ProxyUriToProxyServer("foo:333", ProxyServer::SCHEME_HTTP),
146 ProxyUriToProxyServer("foo:444", ProxyServer::SCHEME_HTTP), -1},
147 {// Host is different.
148 ProxyUriToProxyServer("foo:33", ProxyServer::SCHEME_HTTP),
149 ProxyUriToProxyServer("bar:33", ProxyServer::SCHEME_HTTP), 1},
150 {// Scheme is different.
151 ProxyUriToProxyServer("socks4://foo:33", ProxyServer::SCHEME_HTTP),
152 ProxyUriToProxyServer("http://foo:33", ProxyServer::SCHEME_HTTP), 1},
153 };
154
155 for (const auto& test : kTests) {
156 EXPECT_TRUE(test.server1.is_valid());
157 EXPECT_TRUE(test.server2.is_valid());
158
159 switch (test.expected_comparison) {
160 case -1:
161 EXPECT_TRUE(test.server1 < test.server2);
162 EXPECT_FALSE(test.server2 < test.server1);
163 EXPECT_FALSE(test.server2 == test.server1);
164 EXPECT_FALSE(test.server1 == test.server2);
165 break;
166 case 0:
167 EXPECT_FALSE(test.server1 < test.server2);
168 EXPECT_FALSE(test.server2 < test.server1);
169 EXPECT_TRUE(test.server2 == test.server1);
170 EXPECT_TRUE(test.server1 == test.server2);
171 break;
172 case 1:
173 EXPECT_FALSE(test.server1 < test.server2);
174 EXPECT_TRUE(test.server2 < test.server1);
175 EXPECT_FALSE(test.server2 == test.server1);
176 EXPECT_FALSE(test.server1 == test.server2);
177 break;
178 default:
179 FAIL() << "Invalid expectation. Can be only -1, 0, 1";
180 }
181 }
182 }
183
184 // Tests the various "is_*()" methods on ProxyServer.
TEST(ProxyServerTest,Properties)185 TEST(ProxyServerTest, Properties) {
186 // HTTP proxy.
187 {
188 auto proxy = PacResultElementToProxyServer("PROXY foo");
189 ASSERT_TRUE(proxy.is_valid());
190 EXPECT_TRUE(proxy.is_http());
191 EXPECT_FALSE(proxy.is_https());
192 EXPECT_TRUE(proxy.is_http_like());
193 EXPECT_FALSE(proxy.is_secure_http_like());
194 }
195
196 // HTTPS proxy.
197 {
198 auto proxy = PacResultElementToProxyServer("HTTPS foo");
199 ASSERT_TRUE(proxy.is_valid());
200 EXPECT_FALSE(proxy.is_http());
201 EXPECT_TRUE(proxy.is_https());
202 EXPECT_TRUE(proxy.is_http_like());
203 EXPECT_TRUE(proxy.is_secure_http_like());
204 }
205
206 // QUIC proxy.
207 {
208 auto proxy = PacResultElementToProxyServer("QUIC foo");
209 ASSERT_TRUE(proxy.is_valid());
210 EXPECT_FALSE(proxy.is_http());
211 EXPECT_FALSE(proxy.is_https());
212 EXPECT_TRUE(proxy.is_http_like());
213 EXPECT_TRUE(proxy.is_secure_http_like());
214 }
215
216 // SOCKS5 proxy.
217 {
218 auto proxy = PacResultElementToProxyServer("SOCKS5 foo");
219 ASSERT_TRUE(proxy.is_valid());
220 EXPECT_FALSE(proxy.is_http());
221 EXPECT_FALSE(proxy.is_https());
222 EXPECT_FALSE(proxy.is_http_like());
223 EXPECT_FALSE(proxy.is_secure_http_like());
224 }
225
226 // DIRECT
227 {
228 auto proxy = PacResultElementToProxyServer("DIRECT");
229 ASSERT_TRUE(proxy.is_valid());
230 EXPECT_FALSE(proxy.is_http());
231 EXPECT_FALSE(proxy.is_https());
232 EXPECT_FALSE(proxy.is_http_like());
233 EXPECT_FALSE(proxy.is_secure_http_like());
234 }
235 }
236
237 } // namespace
238
239 } // namespace net
240