1// Copyright (c) 2009 The Chromium Authors. All rights reserved.
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 "base/basictypes.h"
6#include "net/proxy/proxy_server.h"
7#include "testing/gtest/include/gtest/gtest.h"
8
9// Test the creation of ProxyServer using ProxyServer::FromURI, which parses
10// inputs of the form [<scheme>"://"]<host>[":"<port>]. Verify that each part
11// was labelled correctly, and the accessors all give the right data.
12TEST(ProxyServerTest, FromURI) {
13  const struct {
14    const char* input_uri;
15    const char* expected_uri;
16    net::ProxyServer::Scheme expected_scheme;
17    const char* expected_host;
18    int expected_port;
19    const char* expected_host_and_port;
20    const char* expected_pac_string;
21  } tests[] = {
22    // HTTP proxy URIs:
23    {
24       "foopy:10",  // No scheme.
25       "foopy:10",
26       net::ProxyServer::SCHEME_HTTP,
27       "foopy",
28       10,
29       "foopy:10",
30       "PROXY foopy:10"
31    },
32    {
33       "http://foopy",  // No port.
34       "foopy:80",
35       net::ProxyServer::SCHEME_HTTP,
36       "foopy",
37       80,
38       "foopy:80",
39       "PROXY foopy:80"
40    },
41    {
42       "http://foopy:10",
43       "foopy:10",
44       net::ProxyServer::SCHEME_HTTP,
45       "foopy",
46       10,
47       "foopy:10",
48       "PROXY foopy:10"
49    },
50
51    // IPv6 HTTP proxy URIs:
52    {
53       "[FEDC:BA98:7654:3210:FEDC:BA98:7654:3210]:10",  // No scheme.
54       "[FEDC:BA98:7654:3210:FEDC:BA98:7654:3210]:10",
55       net::ProxyServer::SCHEME_HTTP,
56       "FEDC:BA98:7654:3210:FEDC:BA98:7654:3210",
57       10,
58       "[FEDC:BA98:7654:3210:FEDC:BA98:7654:3210]:10",
59       "PROXY [FEDC:BA98:7654:3210:FEDC:BA98:7654:3210]:10"
60    },
61    {
62       "http://[3ffe:2a00:100:7031::1]",  // No port.
63       "[3ffe:2a00:100:7031::1]:80",
64       net::ProxyServer::SCHEME_HTTP,
65       "3ffe:2a00:100:7031::1",
66       80,
67       "[3ffe:2a00:100:7031::1]:80",
68       "PROXY [3ffe:2a00:100:7031::1]:80"
69    },
70    {
71       "http://[::192.9.5.5]",
72       "[::192.9.5.5]:80",
73       net::ProxyServer::SCHEME_HTTP,
74       "::192.9.5.5",
75       80,
76       "[::192.9.5.5]:80",
77       "PROXY [::192.9.5.5]:80"
78    },
79    {
80       "http://[::FFFF:129.144.52.38]:80",
81       "[::FFFF:129.144.52.38]:80",
82       net::ProxyServer::SCHEME_HTTP,
83       "::FFFF:129.144.52.38",
84       80,
85       "[::FFFF:129.144.52.38]:80",
86       "PROXY [::FFFF:129.144.52.38]:80"
87    },
88
89    // SOCKS4 proxy URIs:
90    {
91       "socks4://foopy",  // No port.
92       "socks4://foopy:1080",
93       net::ProxyServer::SCHEME_SOCKS4,
94       "foopy",
95       1080,
96       "foopy:1080",
97       "SOCKS foopy:1080"
98    },
99    {
100       "socks4://foopy:10",
101       "socks4://foopy:10",
102       net::ProxyServer::SCHEME_SOCKS4,
103       "foopy",
104       10,
105       "foopy:10",
106       "SOCKS foopy:10"
107    },
108
109    // SOCKS5 proxy URIs
110    {
111       "socks5://foopy",  // No port.
112       "socks5://foopy:1080",
113       net::ProxyServer::SCHEME_SOCKS5,
114       "foopy",
115       1080,
116       "foopy:1080",
117       "SOCKS5 foopy:1080"
118    },
119    {
120       "socks5://foopy:10",
121       "socks5://foopy:10",
122       net::ProxyServer::SCHEME_SOCKS5,
123       "foopy",
124       10,
125       "foopy:10",
126       "SOCKS5 foopy:10"
127    },
128
129    // SOCKS proxy URIs (should default to SOCKS4)
130    {
131       "socks://foopy",  // No port.
132       "socks4://foopy:1080",
133       net::ProxyServer::SCHEME_SOCKS4,
134       "foopy",
135       1080,
136       "foopy:1080",
137       "SOCKS foopy:1080"
138    },
139    {
140       "socks://foopy:10",
141       "socks4://foopy:10",
142       net::ProxyServer::SCHEME_SOCKS4,
143       "foopy",
144       10,
145       "foopy:10",
146       "SOCKS foopy:10"
147    },
148  };
149
150  for (size_t i = 0; i < ARRAYSIZE_UNSAFE(tests); ++i) {
151    net::ProxyServer uri =
152        net::ProxyServer::FromURI(tests[i].input_uri,
153                                  net::ProxyServer::SCHEME_HTTP);
154    EXPECT_TRUE(uri.is_valid());
155    EXPECT_FALSE(uri.is_direct());
156    EXPECT_EQ(tests[i].expected_uri, uri.ToURI());
157    EXPECT_EQ(tests[i].expected_scheme, uri.scheme());
158    EXPECT_EQ(tests[i].expected_host, uri.HostNoBrackets());
159    EXPECT_EQ(tests[i].expected_port, uri.port());
160    EXPECT_EQ(tests[i].expected_host_and_port, uri.host_and_port());
161    EXPECT_EQ(tests[i].expected_pac_string, uri.ToPacString());
162  }
163}
164
165TEST(ProxyServerTest, DefaultConstructor) {
166  net::ProxyServer proxy_server;
167  EXPECT_FALSE(proxy_server.is_valid());
168}
169
170// Test parsing of the special URI form "direct://". Analagous to the "DIRECT"
171// entry in a PAC result.
172TEST(ProxyServerTest, Direct) {
173  net::ProxyServer uri =
174      net::ProxyServer::FromURI("direct://", net::ProxyServer::SCHEME_HTTP);
175  EXPECT_TRUE(uri.is_valid());
176  EXPECT_TRUE(uri.is_direct());
177  EXPECT_EQ("direct://", uri.ToURI());
178  EXPECT_EQ("DIRECT", uri.ToPacString());
179}
180
181// Test parsing some invalid inputs.
182TEST(ProxyServerTest, Invalid) {
183  const char* tests[] = {
184    "",
185    "   ",
186    "dddf:",   // not a valid port
187    "dddd:d",  // not a valid port
188    "http://",  // not a valid host/port.
189    "direct://xyz",  // direct is not allowed a host/port.
190    "http:/",  // ambiguous, but will fail because of bad port.
191    "http:",  // ambiguous, but will fail because of bad port.
192    "https://blah",  // "https" is not a valid proxy scheme.
193  };
194
195  for (size_t i = 0; i < ARRAYSIZE_UNSAFE(tests); ++i) {
196    net::ProxyServer uri =
197        net::ProxyServer::FromURI(tests[i], net::ProxyServer::SCHEME_HTTP);
198    EXPECT_FALSE(uri.is_valid());
199    EXPECT_FALSE(uri.is_direct());
200    EXPECT_FALSE(uri.is_http());
201    EXPECT_FALSE(uri.is_socks());
202  }
203}
204
205// Test that LWS (SP | HT) is disregarded from the ends.
206TEST(ProxyServerTest, Whitespace) {
207  const char* tests[] = {
208    "  foopy:80",
209    "foopy:80   \t",
210    "  \tfoopy:80  ",
211  };
212
213  for (size_t i = 0; i < ARRAYSIZE_UNSAFE(tests); ++i) {
214    net::ProxyServer uri =
215        net::ProxyServer::FromURI(tests[i], net::ProxyServer::SCHEME_HTTP);
216    EXPECT_EQ("foopy:80", uri.ToURI());
217  }
218}
219
220// Test parsing a ProxyServer from a PAC representation.
221TEST(ProxyServerTest, FromPACString) {
222  const struct {
223    const char* input_pac;
224    const char* expected_uri;
225  } tests[] = {
226    {
227       "PROXY foopy:10",
228       "foopy:10",
229    },
230    {
231       "   PROXY    foopy:10   ",
232       "foopy:10",
233    },
234    {
235       "pRoXy foopy:10",
236       "foopy:10",
237    },
238    {
239       "PROXY foopy",  // No port.
240       "foopy:80",
241    },
242    {
243       "socks foopy",
244       "socks4://foopy:1080",
245    },
246    {
247       "socks4 foopy",
248       "socks4://foopy:1080",
249    },
250    {
251       "socks5 foopy",
252       "socks5://foopy:1080",
253    },
254    {
255       "socks5 foopy:11",
256       "socks5://foopy:11",
257    },
258    {
259       " direct  ",
260       "direct://",
261    },
262  };
263
264  for (size_t i = 0; i < ARRAYSIZE_UNSAFE(tests); ++i) {
265    net::ProxyServer uri = net::ProxyServer::FromPacString(tests[i].input_pac);
266    EXPECT_TRUE(uri.is_valid());
267    EXPECT_EQ(tests[i].expected_uri, uri.ToURI());
268  }
269}
270
271// Test parsing a ProxyServer from an invalid PAC representation.
272TEST(ProxyServerTest, FromPACStringInvalid) {
273  const char* tests[] = {
274    "PROXY",  // missing host/port.
275    "SOCKS",  // missing host/port.
276    "DIRECT foopy:10",  // direct cannot have host/port.
277  };
278
279  for (size_t i = 0; i < ARRAYSIZE_UNSAFE(tests); ++i) {
280    net::ProxyServer uri = net::ProxyServer::FromPacString(tests[i]);
281    EXPECT_FALSE(uri.is_valid());
282  }
283}
284