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