xref: /aosp_15_r20/external/cronet/net/base/proxy_string_util_unittest.cc (revision 6777b5387eb2ff775bb5750e3f5d96f37fb7352b)
1 // Copyright 2021 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_string_util.h"
6 
7 #include "net/base/proxy_chain.h"
8 #include "net/base/proxy_server.h"
9 #include "testing/gtest/include/gtest/gtest.h"
10 
11 namespace net {
12 namespace {
13 
14 // Test the creation of ProxyServer using ProxyUriToProxyServer, which parses
15 // inputs of the form [<scheme>"://"]<host>[":"<port>]. Verify that each part
16 // was labelled correctly, and the accessors all give the right data.
TEST(ProxySpecificationUtilTest,ProxyUriToProxyServer)17 TEST(ProxySpecificationUtilTest, ProxyUriToProxyServer) {
18   const struct {
19     const char* const input_uri;
20     const char* const expected_uri;
21     ProxyServer::Scheme expected_scheme;
22     const char* const expected_host;
23     int expected_port;
24     const char* const expected_pac_string;
25   } tests[] = {
26       // HTTP proxy URIs:
27       {"foopy:10",  // No scheme.
28        "foopy:10", ProxyServer::SCHEME_HTTP, "foopy", 10, "PROXY foopy:10"},
29       {"http://foopy",  // No port.
30        "foopy:80", ProxyServer::SCHEME_HTTP, "foopy", 80, "PROXY foopy:80"},
31       {"http://foopy:10", "foopy:10", ProxyServer::SCHEME_HTTP, "foopy", 10,
32        "PROXY foopy:10"},
33 
34       // IPv6 HTTP proxy URIs:
35       {"[fedc:ba98:7654:3210:fedc:ba98:7654:3210]:10",  // No scheme.
36        "[fedc:ba98:7654:3210:fedc:ba98:7654:3210]:10", ProxyServer::SCHEME_HTTP,
37        "fedc:ba98:7654:3210:fedc:ba98:7654:3210", 10,
38        "PROXY [fedc:ba98:7654:3210:fedc:ba98:7654:3210]:10"},
39       {"http://[3ffe:2a00:100:7031::1]",  // No port.
40        "[3ffe:2a00:100:7031::1]:80", ProxyServer::SCHEME_HTTP,
41        "3ffe:2a00:100:7031::1", 80, "PROXY [3ffe:2a00:100:7031::1]:80"},
42 
43       // SOCKS4 proxy URIs:
44       {"socks4://foopy",  // No port.
45        "socks4://foopy:1080", ProxyServer::SCHEME_SOCKS4, "foopy", 1080,
46        "SOCKS foopy:1080"},
47       {"socks4://foopy:10", "socks4://foopy:10", ProxyServer::SCHEME_SOCKS4,
48        "foopy", 10, "SOCKS foopy:10"},
49 
50       // SOCKS5 proxy URIs:
51       {"socks5://foopy",  // No port.
52        "socks5://foopy:1080", ProxyServer::SCHEME_SOCKS5, "foopy", 1080,
53        "SOCKS5 foopy:1080"},
54       {"socks5://foopy:10", "socks5://foopy:10", ProxyServer::SCHEME_SOCKS5,
55        "foopy", 10, "SOCKS5 foopy:10"},
56 
57       // SOCKS proxy URIs (should default to SOCKS5)
58       {"socks://foopy",  // No port.
59        "socks5://foopy:1080", ProxyServer::SCHEME_SOCKS5, "foopy", 1080,
60        "SOCKS5 foopy:1080"},
61       {"socks://foopy:10", "socks5://foopy:10", ProxyServer::SCHEME_SOCKS5,
62        "foopy", 10, "SOCKS5 foopy:10"},
63 
64       // HTTPS proxy URIs:
65       {"https://foopy",  // No port
66        "https://foopy:443", ProxyServer::SCHEME_HTTPS, "foopy", 443,
67        "HTTPS foopy:443"},
68       {"https://foopy:10",  // Non-standard port
69        "https://foopy:10", ProxyServer::SCHEME_HTTPS, "foopy", 10,
70        "HTTPS foopy:10"},
71       {"https://1.2.3.4:10",  // IP Address
72        "https://1.2.3.4:10", ProxyServer::SCHEME_HTTPS, "1.2.3.4", 10,
73        "HTTPS 1.2.3.4:10"},
74 
75       // Hostname canonicalization:
76       {"[FEDC:BA98:7654:3210:FEDC:BA98:7654:3210]:10",  // No scheme.
77        "[fedc:ba98:7654:3210:fedc:ba98:7654:3210]:10", ProxyServer::SCHEME_HTTP,
78        "fedc:ba98:7654:3210:fedc:ba98:7654:3210", 10,
79        "PROXY [fedc:ba98:7654:3210:fedc:ba98:7654:3210]:10"},
80       {"http://[::192.9.5.5]", "[::c009:505]:80", ProxyServer::SCHEME_HTTP,
81        "::c009:505", 80, "PROXY [::c009:505]:80"},
82       {"http://[::FFFF:129.144.52.38]:80", "[::ffff:8190:3426]:80",
83        ProxyServer::SCHEME_HTTP, "::ffff:8190:3426", 80,
84        "PROXY [::ffff:8190:3426]:80"},
85       {"http://f\u00fcpy:85", "xn--fpy-hoa:85", ProxyServer::SCHEME_HTTP,
86        "xn--fpy-hoa", 85, "PROXY xn--fpy-hoa:85"},
87       {"https://0xA.020.3.4:443", "https://10.16.3.4:443",
88        ProxyServer::SCHEME_HTTPS, "10.16.3.4", 443, "HTTPS 10.16.3.4:443"},
89       {"http://FoO.tEsT:80", "foo.test:80", ProxyServer::SCHEME_HTTP,
90        "foo.test", 80, "PROXY foo.test:80"},
91   };
92 
93   for (const auto& test : tests) {
94     ProxyServer uri =
95         ProxyUriToProxyServer(test.input_uri, ProxyServer::SCHEME_HTTP);
96     EXPECT_TRUE(uri.is_valid());
97     EXPECT_EQ(test.expected_uri, ProxyServerToProxyUri(uri));
98     EXPECT_EQ(test.expected_scheme, uri.scheme());
99     EXPECT_EQ(test.expected_host, uri.host_port_pair().host());
100     EXPECT_EQ(test.expected_port, uri.host_port_pair().port());
101     EXPECT_EQ(test.expected_pac_string, ProxyServerToPacResultElement(uri));
102   }
103 }
104 
105 // Test parsing of the special URI form "direct://".
TEST(ProxySpecificationUtilTest,DirectProxyUriToProxyChain)106 TEST(ProxySpecificationUtilTest, DirectProxyUriToProxyChain) {
107   const char* const uris[] = {
108       "direct://",
109       "DIRECT://",
110       "DiReCt://",
111   };
112 
113   for (const char* uri : uris) {
114     ProxyChain valid_uri = ProxyUriToProxyChain(uri, ProxyServer::SCHEME_HTTP);
115     EXPECT_TRUE(valid_uri.IsValid());
116     EXPECT_TRUE(valid_uri.is_direct());
117   }
118 
119   // Direct is not allowed a host/port.
120   ProxyChain invalid_uri =
121       ProxyUriToProxyChain("direct://xyz", ProxyServer::SCHEME_HTTP);
122   EXPECT_FALSE(invalid_uri.IsValid());
123   EXPECT_FALSE(invalid_uri.is_direct());
124 }
125 
126 // Test parsing some invalid inputs.
TEST(ProxySpecificationUtilTest,InvalidProxyUriToProxyServer)127 TEST(ProxySpecificationUtilTest, InvalidProxyUriToProxyServer) {
128   const char* const tests[] = {
129       "",
130       "   ",
131       "dddf:",         // not a valid port
132       "dddd:d",        // not a valid port
133       "http://",       // not a valid host/port.
134       "direct://",     // direct is not a valid proxy server.
135       "http:/",        // ambiguous, but will fail because of bad port.
136       "http:",         // ambiguous, but will fail because of bad port.
137       "foopy.111",     // Interpreted as invalid IPv4 address.
138       "foo.test/"      // Paths disallowed.
139       "foo.test:123/"  // Paths disallowed.
140       "foo.test/foo"   // Paths disallowed.
141   };
142 
143   for (const char* test : tests) {
144     SCOPED_TRACE(test);
145     ProxyServer uri = ProxyUriToProxyServer(test, ProxyServer::SCHEME_HTTP);
146     EXPECT_FALSE(uri.is_valid());
147     EXPECT_FALSE(uri.is_http());
148     EXPECT_FALSE(uri.is_socks());
149   }
150 }
151 
152 // Test that LWS (SP | HT) is disregarded from the ends.
TEST(ProxySpecificationUtilTest,WhitespaceProxyUriToProxyServer)153 TEST(ProxySpecificationUtilTest, WhitespaceProxyUriToProxyServer) {
154   const char* const tests[] = {
155       "  foopy:80",
156       "foopy:80   \t",
157       "  \tfoopy:80  ",
158   };
159 
160   for (const char* test : tests) {
161     ProxyServer uri = ProxyUriToProxyServer(test, ProxyServer::SCHEME_HTTP);
162     EXPECT_EQ("foopy:80", ProxyServerToProxyUri(uri));
163   }
164 }
165 
166 // Test parsing a ProxyServer from a PAC representation.
TEST(ProxySpecificationUtilTest,PacResultElementToProxyServer)167 TEST(ProxySpecificationUtilTest, PacResultElementToProxyServer) {
168   const struct {
169     const char* const input_pac;
170     const char* const expected_uri;
171   } tests[] = {
172       {
173           "PROXY foopy:10",
174           "foopy:10",
175       },
176       {
177           "   PROXY    foopy:10   ",
178           "foopy:10",
179       },
180       {
181           "pRoXy foopy:10",
182           "foopy:10",
183       },
184       {
185           "PROXY foopy",  // No port.
186           "foopy:80",
187       },
188       {
189           "socks foopy",
190           "socks4://foopy:1080",
191       },
192       {
193           "socks4 foopy",
194           "socks4://foopy:1080",
195       },
196       {
197           "socks5 foopy",
198           "socks5://foopy:1080",
199       },
200       {
201           "socks5 foopy:11",
202           "socks5://foopy:11",
203       },
204       {
205           "https foopy",
206           "https://foopy:443",
207       },
208       {
209           "https foopy:10",
210           "https://foopy:10",
211       },
212       {"PROXY [FEDC:BA98:7654:3210:FEDC:BA98:7654:3210]:10",
213        "[fedc:ba98:7654:3210:fedc:ba98:7654:3210]:10"},
214       {"PROXY f\u00fcpy:85", "xn--fpy-hoa:85"},
215   };
216 
217   for (const auto& test : tests) {
218     SCOPED_TRACE(test.input_pac);
219     ProxyServer server = PacResultElementToProxyServer(test.input_pac);
220     EXPECT_TRUE(server.is_valid());
221     EXPECT_EQ(test.expected_uri, ProxyServerToProxyUri(server));
222 
223     ProxyChain chain = PacResultElementToProxyChain(test.input_pac);
224     EXPECT_TRUE(chain.IsValid());
225     if (!chain.is_direct()) {
226       EXPECT_EQ(test.expected_uri, ProxyServerToProxyUri(chain.First()));
227     }
228   }
229 }
230 
231 // Test parsing a ProxyServer from an invalid PAC representation.
TEST(ProxySpecificationUtilTest,InvalidPacResultElementToProxyServer)232 TEST(ProxySpecificationUtilTest, InvalidPacResultElementToProxyServer) {
233   const char* const tests[] = {
234       "PROXY",                   // missing host/port.
235       "HTTPS",                   // missing host/port.
236       "SOCKS",                   // missing host/port.
237       "DIRECT foopy:10",         // direct cannot have host/port.
238       "INVALIDSCHEME",           // unrecognized scheme.
239       "INVALIDSCHEME foopy:10",  // unrecognized scheme.
240       "HTTP foopy:10",           // http scheme should be "PROXY"
241   };
242 
243   for (const char* test : tests) {
244     SCOPED_TRACE(test);
245     ProxyServer server = PacResultElementToProxyServer(test);
246     EXPECT_FALSE(server.is_valid());
247 
248     ProxyChain chain = PacResultElementToProxyChain(test);
249     EXPECT_FALSE(chain.IsValid());
250   }
251 }
252 
253 }  // namespace
254 }  // namespace net
255