1use std::str::FromStr;
2
3use super::{ErrorKind, InvalidUri, Port, Uri, URI_CHARS};
4
5#[test]
6fn test_char_table() {
7 for (i, &v) in URI_CHARS.iter().enumerate() {
8 if v != 0 {
9 assert_eq!(i, v as usize);
10 }
11 }
12}
13
14macro_rules! part {
15 ($s:expr) => {
16 Some(&$s.parse().unwrap())
17 };
18}
19
20macro_rules! test_parse {
21 (
22 $test_name:ident,
23 $str:expr,
24 $alt:expr,
25 $($method:ident = $value:expr,)*
26 ) => (
27 #[test]
28 fn $test_name() {
29 let orig_str = $str;
30 let uri = match Uri::from_str(orig_str) {
31 Ok(uri) => uri,
32 Err(err) => {
33 panic!("parse error {:?} from {:?}", err, orig_str);
34 },
35 };
36 $(
37 assert_eq!(uri.$method(), $value, "{}: uri = {:?}", stringify!($method), uri);
38 )+
39 assert_eq!(uri, orig_str, "partial eq to original str");
40 assert_eq!(uri, uri.clone(), "clones are equal");
41
42 let new_str = uri.to_string();
43 let new_uri = Uri::from_str(&new_str).expect("to_string output parses again as a Uri");
44 assert_eq!(new_uri, orig_str, "round trip still equals original str");
45
46 const ALT: &'static [&'static str] = &$alt;
47
48 for &alt in ALT.iter() {
49 let other: Uri = alt.parse().unwrap();
50 assert_eq!(uri, *alt);
51 assert_eq!(uri, other);
52 }
53 }
54 );
55}
56
57test_parse! {
58 test_uri_parse_path_and_query,
59 "/some/path/here?and=then&hello#and-bye",
60 [],
61
62 scheme = None,
63 authority = None,
64 path = "/some/path/here",
65 query = Some("and=then&hello"),
66 host = None,
67}
68
69test_parse! {
70 test_uri_parse_absolute_form,
71 "http://127.0.0.1:61761/chunks",
72 [],
73
74 scheme = part!("http"),
75 authority = part!("127.0.0.1:61761"),
76 path = "/chunks",
77 query = None,
78 host = Some("127.0.0.1"),
79 port = Port::from_str("61761").ok(),
80}
81
82test_parse! {
83 test_uri_parse_absolute_form_without_path,
84 "https://127.0.0.1:61761",
85 ["https://127.0.0.1:61761/"],
86
87 scheme = part!("https"),
88 authority = part!("127.0.0.1:61761"),
89 path = "/",
90 query = None,
91 host = Some("127.0.0.1"),
92 port = Port::from_str("61761").ok(),
93}
94
95test_parse! {
96 test_uri_parse_asterisk_form,
97 "*",
98 [],
99
100 scheme = None,
101 authority = None,
102 path = "*",
103 query = None,
104 host = None,
105}
106
107test_parse! {
108 test_uri_parse_authority_no_port,
109 "localhost",
110 ["LOCALHOST", "LocaLHOSt"],
111
112 scheme = None,
113 authority = part!("localhost"),
114 path = "",
115 query = None,
116 port = None,
117 host = Some("localhost"),
118}
119
120test_parse! {
121 test_uri_authority_only_one_character_issue_197,
122 "S",
123 [],
124
125 scheme = None,
126 authority = part!("S"),
127 path = "",
128 query = None,
129 port = None,
130 host = Some("S"),
131}
132
133test_parse! {
134 test_uri_parse_authority_form,
135 "localhost:3000",
136 ["localhosT:3000"],
137
138 scheme = None,
139 authority = part!("localhost:3000"),
140 path = "",
141 query = None,
142 host = Some("localhost"),
143 port = Port::from_str("3000").ok(),
144}
145
146test_parse! {
147 test_uri_parse_absolute_with_default_port_http,
148 "http://127.0.0.1:80",
149 ["http://127.0.0.1:80/"],
150
151 scheme = part!("http"),
152 authority = part!("127.0.0.1:80"),
153 host = Some("127.0.0.1"),
154 path = "/",
155 query = None,
156 port = Port::from_str("80").ok(),
157}
158
159test_parse! {
160 test_uri_parse_absolute_with_default_port_https,
161 "https://127.0.0.1:443",
162 ["https://127.0.0.1:443/"],
163
164 scheme = part!("https"),
165 authority = part!("127.0.0.1:443"),
166 host = Some("127.0.0.1"),
167 path = "/",
168 query = None,
169 port = Port::from_str("443").ok(),
170}
171
172test_parse! {
173 test_uri_parse_fragment_questionmark,
174 "http://127.0.0.1/#?",
175 [],
176
177 scheme = part!("http"),
178 authority = part!("127.0.0.1"),
179 host = Some("127.0.0.1"),
180 path = "/",
181 query = None,
182 port = None,
183}
184
185test_parse! {
186 test_uri_parse_path_with_terminating_questionmark,
187 "http://127.0.0.1/path?",
188 [],
189
190 scheme = part!("http"),
191 authority = part!("127.0.0.1"),
192 path = "/path",
193 query = Some(""),
194 port = None,
195}
196
197test_parse! {
198 test_uri_parse_absolute_form_with_empty_path_and_nonempty_query,
199 "http://127.0.0.1?foo=bar",
200 [],
201
202 scheme = part!("http"),
203 authority = part!("127.0.0.1"),
204 path = "/",
205 query = Some("foo=bar"),
206 port = None,
207}
208
209test_parse! {
210 test_uri_parse_absolute_form_with_empty_path_and_fragment_with_slash,
211 "http://127.0.0.1#foo/bar",
212 [],
213
214 scheme = part!("http"),
215 authority = part!("127.0.0.1"),
216 path = "/",
217 query = None,
218 port = None,
219}
220
221test_parse! {
222 test_uri_parse_absolute_form_with_empty_path_and_fragment_with_questionmark,
223 "http://127.0.0.1#foo?bar",
224 [],
225
226 scheme = part!("http"),
227 authority = part!("127.0.0.1"),
228 path = "/",
229 query = None,
230 port = None,
231}
232
233test_parse! {
234 test_uri_parse_long_host_with_no_scheme,
235 "thequickbrownfoxjumpedoverthelazydogtofindthelargedangerousdragon.localhost",
236 [],
237
238 scheme = None,
239 authority = part!("thequickbrownfoxjumpedoverthelazydogtofindthelargedangerousdragon.localhost"),
240 path = "",
241 query = None,
242 port = None,
243}
244
245test_parse! {
246 test_uri_parse_long_host_with_port_and_no_scheme,
247 "thequickbrownfoxjumpedoverthelazydogtofindthelargedangerousdragon.localhost:1234",
248 [],
249
250 scheme = None,
251 authority = part!("thequickbrownfoxjumpedoverthelazydogtofindthelargedangerousdragon.localhost:1234"),
252 path = "",
253 query = None,
254 port = Port::from_str("1234").ok(),
255}
256
257test_parse! {
258 test_userinfo1,
259 "http://a:b@127.0.0.1:1234/",
260 [],
261
262 scheme = part!("http"),
263 authority = part!("a:b@127.0.0.1:1234"),
264 host = Some("127.0.0.1"),
265 path = "/",
266 query = None,
267 port = Port::from_str("1234").ok(),
268}
269
270test_parse! {
271 test_userinfo2,
272 "http://a:b@127.0.0.1/",
273 [],
274
275 scheme = part!("http"),
276 authority = part!("a:b@127.0.0.1"),
277 host = Some("127.0.0.1"),
278 path = "/",
279 query = None,
280 port = None,
281}
282
283test_parse! {
284 test_userinfo3,
285 "http://a@127.0.0.1/",
286 [],
287
288 scheme = part!("http"),
289 authority = part!("a@127.0.0.1"),
290 host = Some("127.0.0.1"),
291 path = "/",
292 query = None,
293 port = None,
294}
295
296test_parse! {
297 test_userinfo_with_port,
298 "user@localhost:3000",
299 [],
300
301 scheme = None,
302 authority = part!("user@localhost:3000"),
303 path = "",
304 query = None,
305 host = Some("localhost"),
306 port = Port::from_str("3000").ok(),
307}
308
309test_parse! {
310 test_userinfo_pass_with_port,
311 "user:pass@localhost:3000",
312 [],
313
314 scheme = None,
315 authority = part!("user:pass@localhost:3000"),
316 path = "",
317 query = None,
318 host = Some("localhost"),
319 port = Port::from_str("3000").ok(),
320}
321
322test_parse! {
323 test_ipv6,
324 "http://[2001:0db8:85a3:0000:0000:8a2e:0370:7334]/",
325 [],
326
327 scheme = part!("http"),
328 authority = part!("[2001:0db8:85a3:0000:0000:8a2e:0370:7334]"),
329 host = Some("[2001:0db8:85a3:0000:0000:8a2e:0370:7334]"),
330 path = "/",
331 query = None,
332 port = None,
333}
334
335test_parse! {
336 test_ipv6_shorthand,
337 "http://[::1]/",
338 [],
339
340 scheme = part!("http"),
341 authority = part!("[::1]"),
342 host = Some("[::1]"),
343 path = "/",
344 query = None,
345 port = None,
346}
347
348test_parse! {
349 test_ipv6_shorthand2,
350 "http://[::]/",
351 [],
352
353 scheme = part!("http"),
354 authority = part!("[::]"),
355 host = Some("[::]"),
356 path = "/",
357 query = None,
358 port = None,
359}
360
361test_parse! {
362 test_ipv6_shorthand3,
363 "http://[2001:db8::2:1]/",
364 [],
365
366 scheme = part!("http"),
367 authority = part!("[2001:db8::2:1]"),
368 host = Some("[2001:db8::2:1]"),
369 path = "/",
370 query = None,
371 port = None,
372}
373
374test_parse! {
375 test_ipv6_with_port,
376 "http://[2001:0db8:85a3:0000:0000:8a2e:0370:7334]:8008/",
377 [],
378
379 scheme = part!("http"),
380 authority = part!("[2001:0db8:85a3:0000:0000:8a2e:0370:7334]:8008"),
381 host = Some("[2001:0db8:85a3:0000:0000:8a2e:0370:7334]"),
382 path = "/",
383 query = None,
384 port = Port::from_str("8008").ok(),
385}
386
387test_parse! {
388 test_percentage_encoded_path,
389 "/echo/abcdefgh_i-j%20/abcdefg_i-j%20478",
390 [],
391
392 scheme = None,
393 authority = None,
394 host = None,
395 path = "/echo/abcdefgh_i-j%20/abcdefg_i-j%20478",
396 query = None,
397 port = None,
398}
399
400test_parse! {
401 test_path_permissive,
402 "/foo=bar|baz\\^~%",
403 [],
404
405 path = "/foo=bar|baz\\^~%",
406}
407
408test_parse! {
409 test_query_permissive,
410 "/?foo={bar|baz}\\^`",
411 [],
412
413 query = Some("foo={bar|baz}\\^`"),
414}
415
416#[test]
417fn test_uri_parse_error() {
418 fn err(s: &str) {
419 Uri::from_str(s).unwrap_err();
420 }
421
422 err("http://");
423 err("htt:p//host");
424 err("hyper.rs/");
425 err("hyper.rs?key=val");
426 err("?key=val");
427 err("localhost/");
428 err("localhost?key=val");
429 err("\0");
430 err("http://[::1");
431 err("http://::1]");
432 err("localhost:8080:3030");
433 err("@");
434 err("http://username:password@/wut");
435
436 // illegal queries
437 err("/?foo\rbar");
438 err("/?foo\nbar");
439 err("/?<");
440 err("/?>");
441}
442
443#[test]
444fn test_max_uri_len() {
445 let mut uri = vec![];
446 uri.extend(b"http://localhost/");
447 uri.extend(vec![b'a'; 70 * 1024]);
448
449 let uri = String::from_utf8(uri).unwrap();
450 let res: Result<Uri, InvalidUri> = uri.parse();
451
452 assert_eq!(res.unwrap_err().0, ErrorKind::TooLong);
453}
454
455#[test]
456fn test_overflowing_scheme() {
457 let mut uri = vec![];
458 uri.extend(vec![b'a'; 256]);
459 uri.extend(b"://localhost/");
460
461 let uri = String::from_utf8(uri).unwrap();
462 let res: Result<Uri, InvalidUri> = uri.parse();
463
464 assert_eq!(res.unwrap_err().0, ErrorKind::SchemeTooLong);
465}
466
467#[test]
468fn test_max_length_scheme() {
469 let mut uri = vec![];
470 uri.extend(vec![b'a'; 64]);
471 uri.extend(b"://localhost/");
472
473 let uri = String::from_utf8(uri).unwrap();
474 let uri: Uri = uri.parse().unwrap();
475
476 assert_eq!(uri.scheme_str().unwrap().len(), 64);
477}
478
479#[test]
480fn test_uri_to_path_and_query() {
481 let cases = vec![
482 ("/", "/"),
483 ("/foo?bar", "/foo?bar"),
484 ("/foo?bar#nope", "/foo?bar"),
485 ("http://hyper.rs", "/"),
486 ("http://hyper.rs/", "/"),
487 ("http://hyper.rs/path", "/path"),
488 ("http://hyper.rs?query", "/?query"),
489 ("*", "*"),
490 ];
491
492 for case in cases {
493 let uri = Uri::from_str(case.0).unwrap();
494 let s = uri.path_and_query().unwrap().to_string();
495
496 assert_eq!(s, case.1);
497 }
498}
499
500#[test]
501fn test_authority_uri_parts_round_trip() {
502 let s = "hyper.rs";
503 let uri = Uri::from_str(s).expect("first parse");
504 assert_eq!(uri, s);
505 assert_eq!(uri.to_string(), s);
506
507 let parts = uri.into_parts();
508 let uri2 = Uri::from_parts(parts).expect("from_parts");
509 assert_eq!(uri2, s);
510 assert_eq!(uri2.to_string(), s);
511}
512
513#[test]
514fn test_partial_eq_path_with_terminating_questionmark() {
515 let a = "/path";
516 let uri = Uri::from_str("/path?").expect("first parse");
517
518 assert_eq!(uri, a);
519}
520