1 use std::str::FromStr;
2 
3 use super::{ErrorKind, InvalidUri, Port, Uri, URI_CHARS};
4 
5 #[test]
test_char_table()6 fn 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 
14 macro_rules! part {
15     ($s:expr) => {
16         Some(&$s.parse().unwrap())
17     };
18 }
19 
20 macro_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 
57 test_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 
69 test_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 
82 test_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 
95 test_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 
107 test_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 
120 test_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 
133 test_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 
146 test_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 
159 test_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 
172 test_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 
185 test_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 
197 test_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 
209 test_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 
221 test_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 
233 test_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 
245 test_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 
257 test_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 
270 test_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 
283 test_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 
296 test_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 
309 test_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 
322 test_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 
335 test_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 
348 test_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 
361 test_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 
374 test_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 
387 test_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 
400 test_parse! {
401     test_path_permissive,
402     "/foo=bar|baz\\^~%",
403     [],
404 
405     path = "/foo=bar|baz\\^~%",
406 }
407 
408 test_parse! {
409     test_query_permissive,
410     "/?foo={bar|baz}\\^`",
411     [],
412 
413     query = Some("foo={bar|baz}\\^`"),
414 }
415 
416 #[test]
test_uri_parse_error()417 fn 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]
test_max_uri_len()444 fn 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]
test_overflowing_scheme()456 fn 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]
test_max_length_scheme()468 fn 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]
test_uri_to_path_and_query()480 fn 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]
test_authority_uri_parts_round_trip()501 fn 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]
test_partial_eq_path_with_terminating_questionmark()514 fn 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