PageRenderTime 25ms CodeModel.GetById 11ms RepoModel.GetById 0ms app.codeStats 0ms

/pkg/http/url_test.go

http://golang-china.googlecode.com/
Go | 436 lines | 393 code | 22 blank | 21 comment | 27 complexity | c136df397c5fd5828c4b63ee6b757923 MD5 | raw file
  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.
  4. package http
  5. import (
  6. "fmt"
  7. "os"
  8. "reflect"
  9. "testing"
  10. )
  11. // TODO(rsc):
  12. // test URLUnescape
  13. // test URLEscape
  14. // test ParseURL
  15. type URLTest struct {
  16. in string
  17. out *URL
  18. roundtrip string // expected result of reserializing the URL; empty means same as "in".
  19. }
  20. var urltests = []URLTest{
  21. // no path
  22. URLTest{
  23. "http://www.google.com",
  24. &URL{
  25. Raw: "http://www.google.com",
  26. Scheme: "http",
  27. Authority: "www.google.com",
  28. Host: "www.google.com",
  29. },
  30. "",
  31. },
  32. // path
  33. URLTest{
  34. "http://www.google.com/",
  35. &URL{
  36. Raw: "http://www.google.com/",
  37. Scheme: "http",
  38. Authority: "www.google.com",
  39. Host: "www.google.com",
  40. RawPath: "/",
  41. Path: "/",
  42. },
  43. "",
  44. },
  45. // path with hex escaping
  46. URLTest{
  47. "http://www.google.com/file%20one%26two",
  48. &URL{
  49. Raw: "http://www.google.com/file%20one%26two",
  50. Scheme: "http",
  51. Authority: "www.google.com",
  52. Host: "www.google.com",
  53. RawPath: "/file%20one%26two",
  54. Path: "/file one&two",
  55. },
  56. "http://www.google.com/file%20one%26two",
  57. },
  58. // user
  59. URLTest{
  60. "ftp://webmaster@www.google.com/",
  61. &URL{
  62. Raw: "ftp://webmaster@www.google.com/",
  63. Scheme: "ftp",
  64. Authority: "webmaster@www.google.com",
  65. Userinfo: "webmaster",
  66. Host: "www.google.com",
  67. RawPath: "/",
  68. Path: "/",
  69. },
  70. "",
  71. },
  72. // escape sequence in username
  73. URLTest{
  74. "ftp://john%20doe@www.google.com/",
  75. &URL{
  76. Raw: "ftp://john%20doe@www.google.com/",
  77. Scheme: "ftp",
  78. Authority: "john doe@www.google.com",
  79. Userinfo: "john doe",
  80. Host: "www.google.com",
  81. RawPath: "/",
  82. Path: "/",
  83. },
  84. "ftp://john%20doe@www.google.com/",
  85. },
  86. // query
  87. URLTest{
  88. "http://www.google.com/?q=go+language",
  89. &URL{
  90. Raw: "http://www.google.com/?q=go+language",
  91. Scheme: "http",
  92. Authority: "www.google.com",
  93. Host: "www.google.com",
  94. RawPath: "/?q=go+language",
  95. Path: "/",
  96. RawQuery: "q=go+language",
  97. },
  98. "",
  99. },
  100. // query with hex escaping: NOT parsed
  101. URLTest{
  102. "http://www.google.com/?q=go%20language",
  103. &URL{
  104. Raw: "http://www.google.com/?q=go%20language",
  105. Scheme: "http",
  106. Authority: "www.google.com",
  107. Host: "www.google.com",
  108. RawPath: "/?q=go%20language",
  109. Path: "/",
  110. RawQuery: "q=go%20language",
  111. },
  112. "",
  113. },
  114. // %20 outside query
  115. URLTest{
  116. "http://www.google.com/a%20b?q=c+d",
  117. &URL{
  118. Raw: "http://www.google.com/a%20b?q=c+d",
  119. Scheme: "http",
  120. Authority: "www.google.com",
  121. Host: "www.google.com",
  122. RawPath: "/a%20b?q=c+d",
  123. Path: "/a b",
  124. RawQuery: "q=c+d",
  125. },
  126. "",
  127. },
  128. // path without /, so no query parsing
  129. URLTest{
  130. "http:www.google.com/?q=go+language",
  131. &URL{
  132. Raw: "http:www.google.com/?q=go+language",
  133. Scheme: "http",
  134. RawPath: "www.google.com/?q=go+language",
  135. Path: "www.google.com/?q=go+language",
  136. },
  137. "http:www.google.com/%3fq%3dgo%2blanguage",
  138. },
  139. // non-authority
  140. URLTest{
  141. "mailto:/webmaster@golang.org",
  142. &URL{
  143. Raw: "mailto:/webmaster@golang.org",
  144. Scheme: "mailto",
  145. RawPath: "/webmaster@golang.org",
  146. Path: "/webmaster@golang.org",
  147. },
  148. "",
  149. },
  150. // non-authority
  151. URLTest{
  152. "mailto:webmaster@golang.org",
  153. &URL{
  154. Raw: "mailto:webmaster@golang.org",
  155. Scheme: "mailto",
  156. RawPath: "webmaster@golang.org",
  157. Path: "webmaster@golang.org",
  158. },
  159. "",
  160. },
  161. // unescaped :// in query should not create a scheme
  162. URLTest{
  163. "/foo?query=http://bad",
  164. &URL{
  165. Raw: "/foo?query=http://bad",
  166. RawPath: "/foo?query=http://bad",
  167. Path: "/foo",
  168. RawQuery: "query=http://bad",
  169. },
  170. "",
  171. },
  172. }
  173. var urlnofragtests = []URLTest{
  174. URLTest{
  175. "http://www.google.com/?q=go+language#foo",
  176. &URL{
  177. Raw: "http://www.google.com/?q=go+language#foo",
  178. Scheme: "http",
  179. Authority: "www.google.com",
  180. Host: "www.google.com",
  181. RawPath: "/?q=go+language#foo",
  182. Path: "/",
  183. RawQuery: "q=go+language#foo",
  184. },
  185. "",
  186. },
  187. }
  188. var urlfragtests = []URLTest{
  189. URLTest{
  190. "http://www.google.com/?q=go+language#foo",
  191. &URL{
  192. Raw: "http://www.google.com/?q=go+language#foo",
  193. Scheme: "http",
  194. Authority: "www.google.com",
  195. Host: "www.google.com",
  196. RawPath: "/?q=go+language#foo",
  197. Path: "/",
  198. RawQuery: "q=go+language",
  199. Fragment: "foo",
  200. },
  201. "",
  202. },
  203. URLTest{
  204. "http://www.google.com/?q=go+language#foo%26bar",
  205. &URL{
  206. Raw: "http://www.google.com/?q=go+language#foo%26bar",
  207. Scheme: "http",
  208. Authority: "www.google.com",
  209. Host: "www.google.com",
  210. RawPath: "/?q=go+language#foo%26bar",
  211. Path: "/",
  212. RawQuery: "q=go+language",
  213. Fragment: "foo&bar",
  214. },
  215. "",
  216. },
  217. }
  218. // more useful string for debugging than fmt's struct printer
  219. func ufmt(u *URL) string {
  220. return fmt.Sprintf("%q, %q, %q, %q, %q, %q, %q, %q, %q",
  221. u.Raw, u.Scheme, u.RawPath, u.Authority, u.Userinfo,
  222. u.Host, u.Path, u.RawQuery, u.Fragment)
  223. }
  224. func DoTest(t *testing.T, parse func(string) (*URL, os.Error), name string, tests []URLTest) {
  225. for _, tt := range tests {
  226. u, err := parse(tt.in)
  227. if err != nil {
  228. t.Errorf("%s(%q) returned error %s", name, tt.in, err)
  229. continue
  230. }
  231. if !reflect.DeepEqual(u, tt.out) {
  232. t.Errorf("%s(%q):\n\thave %v\n\twant %v\n",
  233. name, tt.in, ufmt(u), ufmt(tt.out))
  234. }
  235. }
  236. }
  237. func TestParseURL(t *testing.T) {
  238. DoTest(t, ParseURL, "ParseURL", urltests)
  239. DoTest(t, ParseURL, "ParseURL", urlnofragtests)
  240. }
  241. func TestParseURLReference(t *testing.T) {
  242. DoTest(t, ParseURLReference, "ParseURLReference", urltests)
  243. DoTest(t, ParseURLReference, "ParseURLReference", urlfragtests)
  244. }
  245. func DoTestString(t *testing.T, parse func(string) (*URL, os.Error), name string, tests []URLTest) {
  246. for _, tt := range tests {
  247. u, err := parse(tt.in)
  248. if err != nil {
  249. t.Errorf("%s(%q) returned error %s", name, tt.in, err)
  250. continue
  251. }
  252. s := u.String()
  253. expected := tt.in
  254. if len(tt.roundtrip) > 0 {
  255. expected = tt.roundtrip
  256. }
  257. if s != expected {
  258. t.Errorf("%s(%q).String() == %q (expected %q)", name, tt.in, s, expected)
  259. }
  260. }
  261. }
  262. func TestURLString(t *testing.T) {
  263. DoTestString(t, ParseURL, "ParseURL", urltests)
  264. DoTestString(t, ParseURL, "ParseURL", urlfragtests)
  265. DoTestString(t, ParseURL, "ParseURL", urlnofragtests)
  266. DoTestString(t, ParseURLReference, "ParseURLReference", urltests)
  267. DoTestString(t, ParseURLReference, "ParseURLReference", urlfragtests)
  268. DoTestString(t, ParseURLReference, "ParseURLReference", urlnofragtests)
  269. }
  270. type URLEscapeTest struct {
  271. in string
  272. out string
  273. err os.Error
  274. }
  275. var unescapeTests = []URLEscapeTest{
  276. URLEscapeTest{
  277. "",
  278. "",
  279. nil,
  280. },
  281. URLEscapeTest{
  282. "abc",
  283. "abc",
  284. nil,
  285. },
  286. URLEscapeTest{
  287. "1%41",
  288. "1A",
  289. nil,
  290. },
  291. URLEscapeTest{
  292. "1%41%42%43",
  293. "1ABC",
  294. nil,
  295. },
  296. URLEscapeTest{
  297. "%4a",
  298. "J",
  299. nil,
  300. },
  301. URLEscapeTest{
  302. "%6F",
  303. "o",
  304. nil,
  305. },
  306. URLEscapeTest{
  307. "%", // not enough characters after %
  308. "",
  309. URLEscapeError("%"),
  310. },
  311. URLEscapeTest{
  312. "%a", // not enough characters after %
  313. "",
  314. URLEscapeError("%a"),
  315. },
  316. URLEscapeTest{
  317. "%1", // not enough characters after %
  318. "",
  319. URLEscapeError("%1"),
  320. },
  321. URLEscapeTest{
  322. "123%45%6", // not enough characters after %
  323. "",
  324. URLEscapeError("%6"),
  325. },
  326. URLEscapeTest{
  327. "%zzzzz", // invalid hex digits
  328. "",
  329. URLEscapeError("%zz"),
  330. },
  331. }
  332. func TestURLUnescape(t *testing.T) {
  333. for _, tt := range unescapeTests {
  334. actual, err := URLUnescape(tt.in)
  335. if actual != tt.out || (err != nil) != (tt.err != nil) {
  336. t.Errorf("URLUnescape(%q) = %q, %s; want %q, %s", tt.in, actual, err, tt.out, tt.err)
  337. }
  338. }
  339. }
  340. var escapeTests = []URLEscapeTest{
  341. URLEscapeTest{
  342. "",
  343. "",
  344. nil,
  345. },
  346. URLEscapeTest{
  347. "abc",
  348. "abc",
  349. nil,
  350. },
  351. URLEscapeTest{
  352. "one two",
  353. "one+two",
  354. nil,
  355. },
  356. URLEscapeTest{
  357. "10%",
  358. "10%25",
  359. nil,
  360. },
  361. URLEscapeTest{
  362. " ?&=#+%!<>#\"{}|\\^[]`รข&#x2DC;?\t",
  363. "+%3f%26%3d%23%2b%25!%3c%3e%23%22%7b%7d%7c%5c%5e%5b%5d%60%e2%98%ba%09",
  364. nil,
  365. },
  366. }
  367. func TestURLEscape(t *testing.T) {
  368. for _, tt := range escapeTests {
  369. actual := URLEscape(tt.in)
  370. if tt.out != actual {
  371. t.Errorf("URLEscape(%q) = %q, want %q", tt.in, actual, tt.out)
  372. }
  373. // for bonus points, verify that escape:unescape is an identity.
  374. roundtrip, err := URLUnescape(actual)
  375. if roundtrip != tt.in || err != nil {
  376. t.Errorf("URLUnescape(%q) = %q, %s; want %q, %s", actual, roundtrip, err, tt.in, "[no error]")
  377. }
  378. }
  379. }
  380. type CanonicalPathTest struct {
  381. in string
  382. out string
  383. }
  384. var canonicalTests = []CanonicalPathTest{
  385. CanonicalPathTest{"", ""},
  386. CanonicalPathTest{"/", "/"},
  387. CanonicalPathTest{".", ""},
  388. CanonicalPathTest{"./", ""},
  389. CanonicalPathTest{"/a/", "/a/"},
  390. CanonicalPathTest{"a/", "a/"},
  391. CanonicalPathTest{"a/./", "a/"},
  392. CanonicalPathTest{"./a", "a"},
  393. CanonicalPathTest{"/a/../b", "/b"},
  394. CanonicalPathTest{"a/../b", "b"},
  395. CanonicalPathTest{"a/../../b", "../b"},
  396. CanonicalPathTest{"a/.", "a/"},
  397. CanonicalPathTest{"../.././a", "../../a"},
  398. CanonicalPathTest{"/../.././a", "/../../a"},
  399. CanonicalPathTest{"a/b/g/../..", "a/"},
  400. CanonicalPathTest{"a/b/..", "a/"},
  401. CanonicalPathTest{"a/b/.", "a/b/"},
  402. CanonicalPathTest{"a/b/../../../..", "../.."},
  403. CanonicalPathTest{"a./", "a./"},
  404. CanonicalPathTest{"/../a/b/../../../", "/../../"},
  405. CanonicalPathTest{"../a/b/../../../", "../../"},
  406. }
  407. func TestCanonicalPath(t *testing.T) {
  408. for _, tt := range canonicalTests {
  409. actual := CanonicalPath(tt.in)
  410. if tt.out != actual {
  411. t.Errorf("CanonicalPath(%q) = %q, want %q", tt.in, actual, tt.out)
  412. }
  413. }
  414. }