1 // Copyright 2009 The Go Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style
3 // license that can be found in the LICENSE file.
22 roundtrip
string // expected result of reserializing the URL; empty means same as "in".
25 var urltests
= []URLTest
{
28 "http://www.google.com",
30 Raw
: "http://www.google.com",
32 RawAuthority
: "www.google.com",
33 Host
: "www.google.com",
39 "http://www.google.com/",
41 Raw
: "http://www.google.com/",
43 RawAuthority
: "www.google.com",
44 Host
: "www.google.com",
50 // path with hex escaping
52 "http://www.google.com/file%20one%26two",
54 Raw
: "http://www.google.com/file%20one%26two",
56 RawAuthority
: "www.google.com",
57 Host
: "www.google.com",
58 RawPath
: "/file%20one%26two",
59 Path
: "/file one&two",
61 "http://www.google.com/file%20one&two",
65 "ftp://webmaster@www.google.com/",
67 Raw
: "ftp://webmaster@www.google.com/",
69 RawAuthority
: "webmaster@www.google.com",
70 RawUserinfo
: "webmaster",
71 Host
: "www.google.com",
77 // escape sequence in username
79 "ftp://john%20doe@www.google.com/",
81 Raw
: "ftp://john%20doe@www.google.com/",
83 RawAuthority
: "john%20doe@www.google.com",
84 RawUserinfo
: "john%20doe",
85 Host
: "www.google.com",
89 "ftp://john%20doe@www.google.com/",
93 "http://www.google.com/?q=go+language",
95 Raw
: "http://www.google.com/?q=go+language",
97 RawAuthority
: "www.google.com",
98 Host
: "www.google.com",
99 RawPath
: "/?q=go+language",
101 RawQuery
: "q=go+language",
105 // query with hex escaping: NOT parsed
107 "http://www.google.com/?q=go%20language",
109 Raw
: "http://www.google.com/?q=go%20language",
111 RawAuthority
: "www.google.com",
112 Host
: "www.google.com",
113 RawPath
: "/?q=go%20language",
115 RawQuery
: "q=go%20language",
121 "http://www.google.com/a%20b?q=c+d",
123 Raw
: "http://www.google.com/a%20b?q=c+d",
125 RawAuthority
: "www.google.com",
126 Host
: "www.google.com",
127 RawPath
: "/a%20b?q=c+d",
133 // path without leading /, so no query parsing
135 "http:www.google.com/?q=go+language",
137 Raw
: "http:www.google.com/?q=go+language",
139 RawPath
: "www.google.com/?q=go+language",
140 Path
: "www.google.com/?q=go+language",
143 "http:www.google.com/?q=go+language",
145 // path without leading /, so no query parsing
147 "http:%2f%2fwww.google.com/?q=go+language",
149 Raw
: "http:%2f%2fwww.google.com/?q=go+language",
151 RawPath
: "%2f%2fwww.google.com/?q=go+language",
152 Path
: "//www.google.com/?q=go+language",
155 "http:%2f/www.google.com/?q=go+language",
159 "mailto:/webmaster@golang.org",
161 Raw
: "mailto:/webmaster@golang.org",
163 RawPath
: "/webmaster@golang.org",
164 Path
: "/webmaster@golang.org",
170 "mailto:webmaster@golang.org",
172 Raw
: "mailto:webmaster@golang.org",
174 RawPath
: "webmaster@golang.org",
175 Path
: "webmaster@golang.org",
180 // unescaped :// in query should not create a scheme
182 "/foo?query=http://bad",
184 Raw
: "/foo?query=http://bad",
185 RawPath
: "/foo?query=http://bad",
187 RawQuery
: "query=http://bad",
191 // leading // without scheme shouldn't create an authority
203 "http://user:password@google.com",
205 Raw
: "http://user:password@google.com",
207 RawAuthority
: "user:password@google.com",
208 RawUserinfo
: "user:password",
211 "http://user:******@google.com",
214 "http://user:longerpass@google.com",
216 Raw
: "http://user:longerpass@google.com",
218 RawAuthority
: "user:longerpass@google.com",
219 RawUserinfo
: "user:longerpass",
222 "http://user:******@google.com",
226 var urlnofragtests
= []URLTest
{
228 "http://www.google.com/?q=go+language#foo",
230 Raw
: "http://www.google.com/?q=go+language#foo",
232 RawAuthority
: "www.google.com",
233 Host
: "www.google.com",
234 RawPath
: "/?q=go+language#foo",
236 RawQuery
: "q=go+language#foo",
242 var urlfragtests
= []URLTest
{
244 "http://www.google.com/?q=go+language#foo",
246 Raw
: "http://www.google.com/?q=go+language#foo",
248 RawAuthority
: "www.google.com",
249 Host
: "www.google.com",
250 RawPath
: "/?q=go+language#foo",
252 RawQuery
: "q=go+language",
258 "http://www.google.com/?q=go+language#foo%26bar",
260 Raw
: "http://www.google.com/?q=go+language#foo%26bar",
262 RawAuthority
: "www.google.com",
263 Host
: "www.google.com",
264 RawPath
: "/?q=go+language#foo%26bar",
266 RawQuery
: "q=go+language",
269 "http://www.google.com/?q=go+language#foo&bar",
273 // more useful string for debugging than fmt's struct printer
274 func ufmt(u
*URL
) string {
275 return fmt
.Sprintf("%q, %q, %q, %q, %q, %q, %q, %q, %q",
276 u
.Raw
, u
.Scheme
, u
.RawPath
, u
.RawAuthority
, u
.RawUserinfo
,
277 u
.Host
, u
.Path
, u
.RawQuery
, u
.Fragment
)
280 func DoTest(t
*testing
.T
, parse
func(string) (*URL
, os
.Error
), name
string, tests
[]URLTest
) {
281 for _
, tt
:= range tests
{
282 u
, err
:= parse(tt
.in
)
284 t
.Errorf("%s(%q) returned error %s", name
, tt
.in
, err
)
287 if !reflect
.DeepEqual(u
, tt
.out
) {
288 t
.Errorf("%s(%q):\n\thave %v\n\twant %v\n",
289 name
, tt
.in
, ufmt(u
), ufmt(tt
.out
))
294 func TestParseURL(t
*testing
.T
) {
295 DoTest(t
, ParseURL
, "ParseURL", urltests
)
296 DoTest(t
, ParseURL
, "ParseURL", urlnofragtests
)
299 func TestParseURLReference(t
*testing
.T
) {
300 DoTest(t
, ParseURLReference
, "ParseURLReference", urltests
)
301 DoTest(t
, ParseURLReference
, "ParseURLReference", urlfragtests
)
304 func DoTestString(t
*testing
.T
, parse
func(string) (*URL
, os
.Error
), name
string, tests
[]URLTest
) {
305 for _
, tt
:= range tests
{
306 u
, err
:= parse(tt
.in
)
308 t
.Errorf("%s(%q) returned error %s", name
, tt
.in
, err
)
313 if len(tt
.roundtrip
) > 0 {
314 expected
= tt
.roundtrip
317 t
.Errorf("%s(%q).String() == %q (expected %q)", name
, tt
.in
, s
, expected
)
322 func TestURLString(t
*testing
.T
) {
323 DoTestString(t
, ParseURL
, "ParseURL", urltests
)
324 DoTestString(t
, ParseURL
, "ParseURL", urlnofragtests
)
325 DoTestString(t
, ParseURLReference
, "ParseURLReference", urltests
)
326 DoTestString(t
, ParseURLReference
, "ParseURLReference", urlfragtests
)
329 type URLEscapeTest
struct {
335 var unescapeTests
= []URLEscapeTest
{
367 "%", // not enough characters after %
372 "%a", // not enough characters after %
374 URLEscapeError("%a"),
377 "%1", // not enough characters after %
379 URLEscapeError("%1"),
382 "123%45%6", // not enough characters after %
384 URLEscapeError("%6"),
387 "%zzzzz", // invalid hex digits
389 URLEscapeError("%zz"),
393 func TestURLUnescape(t
*testing
.T
) {
394 for _
, tt
:= range unescapeTests
{
395 actual
, err
:= URLUnescape(tt
.in
)
396 if actual
!= tt
.out ||
(err
!= nil) != (tt
.err
!= nil) {
397 t
.Errorf("URLUnescape(%q) = %q, %s; want %q, %s", tt
.in
, actual
, err
, tt
.out
, tt
.err
)
402 var escapeTests
= []URLEscapeTest
{
424 " ?&=#+%!<>#\"{}|\\^[]`☺\t",
425 "+%3f%26%3d%23%2b%25!%3c%3e%23%22%7b%7d%7c%5c%5e%5b%5d%60%e2%98%ba%09",
430 func TestURLEscape(t
*testing
.T
) {
431 for _
, tt
:= range escapeTests
{
432 actual
:= URLEscape(tt
.in
)
433 if tt
.out
!= actual
{
434 t
.Errorf("URLEscape(%q) = %q, want %q", tt
.in
, actual
, tt
.out
)
437 // for bonus points, verify that escape:unescape is an identity.
438 roundtrip
, err
:= URLUnescape(actual
)
439 if roundtrip
!= tt
.in || err
!= nil {
440 t
.Errorf("URLUnescape(%q) = %q, %s; want %q, %s", actual
, roundtrip
, err
, tt
.in
, "[no error]")
445 type CanonicalPathTest
struct {
450 var canonicalTests
= []CanonicalPathTest
{
461 {"a/../../b", "../b"},
463 {"../.././a", "../../a"},
464 {"/../.././a", "/../../a"},
465 {"a/b/g/../..", "a/"},
468 {"a/b/../../../..", "../.."},
470 {"/../a/b/../../../", "/../../"},
471 {"../a/b/../../../", "../../"},
474 func TestCanonicalPath(t
*testing
.T
) {
475 for _
, tt
:= range canonicalTests
{
476 actual
:= CanonicalPath(tt
.in
)
477 if tt
.out
!= actual
{
478 t
.Errorf("CanonicalPath(%q) = %q, want %q", tt
.in
, actual
, tt
.out
)
483 type UserinfoTest
struct {
489 var userinfoTests
= []UserinfoTest
{
490 {"user", "password", "user:password"},
491 {"foo:bar", "~!@#$%^&*()_+{}|[]\\-=`:;'\"<>?,./",
492 "foo%3abar:~!%40%23$%25%5e&*()_+%7b%7d%7c%5b%5d%5c-=%60%3a;'%22%3c%3e?,.%2f"},
495 func TestEscapeUserinfo(t
*testing
.T
) {
496 for _
, tt
:= range userinfoTests
{
497 if raw
:= EscapeUserinfo(tt
.User
, tt
.Password
); raw
!= tt
.Raw
{
498 t
.Errorf("EscapeUserinfo(%q, %q) = %q, want %q", tt
.User
, tt
.Password
, raw
, tt
.Raw
)
503 func TestUnescapeUserinfo(t
*testing
.T
) {
504 for _
, tt
:= range userinfoTests
{
505 if user
, pass
, err
:= UnescapeUserinfo(tt
.Raw
); user
!= tt
.User || pass
!= tt
.Password || err
!= nil {
506 t
.Errorf("UnescapeUserinfo(%q) = %q, %q, %v, want %q, %q, nil", tt
.Raw
, user
, pass
, err
, tt
.User
, tt
.Password
)