• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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