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