]> git.proxmox.com Git - rustc.git/blob - vendor/url/tests/unit.rs
New upstream version 1.74.1+dfsg1
[rustc.git] / vendor / url / tests / unit.rs
1 // Copyright 2013-2014 The rust-url developers.
2 //
3 // Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
4 // http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
5 // <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
6 // option. This file may not be copied, modified, or distributed
7 // except according to those terms.
8
9 //! Unit tests
10
11 use std::borrow::Cow;
12 use std::cell::{Cell, RefCell};
13 use std::net::{Ipv4Addr, Ipv6Addr};
14 use std::path::{Path, PathBuf};
15 use url::{form_urlencoded, Host, Origin, Url};
16
17 #[test]
18 fn size() {
19 use std::mem::size_of;
20 assert_eq!(size_of::<Url>(), size_of::<Option<Url>>());
21 }
22
23 #[test]
24 fn test_relative() {
25 let base: Url = "sc://%C3%B1".parse().unwrap();
26 let url = base.join("/resources/testharness.js").unwrap();
27 assert_eq!(url.as_str(), "sc://%C3%B1/resources/testharness.js");
28 }
29
30 #[test]
31 fn test_relative_empty() {
32 let base: Url = "sc://%C3%B1".parse().unwrap();
33 let url = base.join("").unwrap();
34 assert_eq!(url.as_str(), "sc://%C3%B1");
35 }
36
37 #[test]
38 fn test_strip_trailing_spaces_from_opaque_path() {
39 let mut url: Url = "data:space ?query".parse().unwrap();
40 url.set_query(None);
41 assert_eq!(url.as_str(), "data:space");
42
43 let mut url: Url = "data:space #hash".parse().unwrap();
44 url.set_fragment(None);
45 assert_eq!(url.as_str(), "data:space");
46 }
47
48 #[test]
49 fn test_set_empty_host() {
50 let mut base: Url = "moz://foo:bar@servo/baz".parse().unwrap();
51 base.set_username("").unwrap();
52 assert_eq!(base.as_str(), "moz://:bar@servo/baz");
53 base.set_host(None).unwrap();
54 assert_eq!(base.as_str(), "moz:/baz");
55 base.set_host(Some("servo")).unwrap();
56 assert_eq!(base.as_str(), "moz://servo/baz");
57
58 let mut base: Url = "file://server/share/foo/bar".parse().unwrap();
59 base.set_host(None).unwrap();
60 assert_eq!(base.as_str(), "file:///share/foo/bar");
61
62 let mut base: Url = "file://server/share/foo/bar".parse().unwrap();
63 base.set_host(Some("foo")).unwrap();
64 assert_eq!(base.as_str(), "file://foo/share/foo/bar");
65 }
66
67 #[test]
68 fn test_set_empty_username_and_password() {
69 let mut base: Url = "moz://foo:bar@servo/baz".parse().unwrap();
70 base.set_username("").unwrap();
71 assert_eq!(base.as_str(), "moz://:bar@servo/baz");
72
73 base.set_password(Some("")).unwrap();
74 assert_eq!(base.as_str(), "moz://servo/baz");
75
76 base.set_password(None).unwrap();
77 assert_eq!(base.as_str(), "moz://servo/baz");
78 }
79
80 #[test]
81 fn test_set_empty_password() {
82 let mut base: Url = "moz://foo:bar@servo/baz".parse().unwrap();
83
84 base.set_password(Some("")).unwrap();
85 assert_eq!(base.as_str(), "moz://foo@servo/baz");
86
87 base.set_password(None).unwrap();
88 assert_eq!(base.as_str(), "moz://foo@servo/baz");
89 }
90
91 #[test]
92 fn test_set_empty_hostname() {
93 use url::quirks;
94 let mut base: Url = "moz://foo@servo/baz".parse().unwrap();
95 assert!(
96 quirks::set_hostname(&mut base, "").is_err(),
97 "setting an empty hostname to a url with a username should fail"
98 );
99 base = "moz://:pass@servo/baz".parse().unwrap();
100 assert!(
101 quirks::set_hostname(&mut base, "").is_err(),
102 "setting an empty hostname to a url with a password should fail"
103 );
104 base = "moz://servo/baz".parse().unwrap();
105 quirks::set_hostname(&mut base, "").unwrap();
106 assert_eq!(base.as_str(), "moz:///baz");
107 }
108
109 #[test]
110 fn test_set_empty_query() {
111 let mut base: Url = "moz://example.com/path?query".parse().unwrap();
112
113 base.set_query(Some(""));
114 assert_eq!(base.as_str(), "moz://example.com/path?");
115
116 base.set_query(None);
117 assert_eq!(base.as_str(), "moz://example.com/path");
118 }
119
120 macro_rules! assert_from_file_path {
121 ($path: expr) => {
122 assert_from_file_path!($path, $path)
123 };
124 ($path: expr, $url_path: expr) => {{
125 let url = Url::from_file_path(Path::new($path)).unwrap();
126 assert_eq!(url.host(), None);
127 assert_eq!(url.path(), $url_path);
128 assert_eq!(url.to_file_path(), Ok(PathBuf::from($path)));
129 }};
130 }
131
132 #[test]
133 fn new_file_paths() {
134 if cfg!(unix) {
135 assert_eq!(Url::from_file_path(Path::new("relative")), Err(()));
136 assert_eq!(Url::from_file_path(Path::new("../relative")), Err(()));
137 }
138 if cfg!(windows) {
139 assert_eq!(Url::from_file_path(Path::new("relative")), Err(()));
140 assert_eq!(Url::from_file_path(Path::new(r"..\relative")), Err(()));
141 assert_eq!(Url::from_file_path(Path::new(r"\drive-relative")), Err(()));
142 assert_eq!(Url::from_file_path(Path::new(r"\\ucn\")), Err(()));
143 }
144
145 if cfg!(unix) {
146 assert_from_file_path!("/foo/bar");
147 assert_from_file_path!("/foo/ba\0r", "/foo/ba%00r");
148 assert_from_file_path!("/foo/ba%00r", "/foo/ba%2500r");
149 }
150 }
151
152 #[test]
153 #[cfg(unix)]
154 fn new_path_bad_utf8() {
155 use std::ffi::OsStr;
156 use std::os::unix::prelude::*;
157
158 let url = Url::from_file_path(Path::new(OsStr::from_bytes(b"/foo/ba\x80r"))).unwrap();
159 let os_str = OsStr::from_bytes(b"/foo/ba\x80r");
160 assert_eq!(url.to_file_path(), Ok(PathBuf::from(os_str)));
161 }
162
163 #[test]
164 fn new_path_windows_fun() {
165 if cfg!(windows) {
166 assert_from_file_path!(r"C:\foo\bar", "/C:/foo/bar");
167 assert_from_file_path!("C:\\foo\\ba\0r", "/C:/foo/ba%00r");
168
169 // Invalid UTF-8
170 assert!(Url::parse("file:///C:/foo/ba%80r")
171 .unwrap()
172 .to_file_path()
173 .is_err());
174
175 // test windows canonicalized path
176 let path = PathBuf::from(r"\\?\C:\foo\bar");
177 assert!(Url::from_file_path(path).is_ok());
178
179 // Percent-encoded drive letter
180 let url = Url::parse("file:///C%3A/foo/bar").unwrap();
181 assert_eq!(url.to_file_path(), Ok(PathBuf::from(r"C:\foo\bar")));
182 }
183 }
184
185 #[test]
186 fn new_directory_paths() {
187 if cfg!(unix) {
188 assert_eq!(Url::from_directory_path(Path::new("relative")), Err(()));
189 assert_eq!(Url::from_directory_path(Path::new("../relative")), Err(()));
190
191 let url = Url::from_directory_path(Path::new("/foo/bar")).unwrap();
192 assert_eq!(url.host(), None);
193 assert_eq!(url.path(), "/foo/bar/");
194 }
195 if cfg!(windows) {
196 assert_eq!(Url::from_directory_path(Path::new("relative")), Err(()));
197 assert_eq!(Url::from_directory_path(Path::new(r"..\relative")), Err(()));
198 assert_eq!(
199 Url::from_directory_path(Path::new(r"\drive-relative")),
200 Err(())
201 );
202 assert_eq!(Url::from_directory_path(Path::new(r"\\ucn\")), Err(()));
203
204 let url = Url::from_directory_path(Path::new(r"C:\foo\bar")).unwrap();
205 assert_eq!(url.host(), None);
206 assert_eq!(url.path(), "/C:/foo/bar/");
207 }
208 }
209
210 #[test]
211 fn path_backslash_fun() {
212 let mut special_url = "http://foobar.com".parse::<Url>().unwrap();
213 special_url.path_segments_mut().unwrap().push("foo\\bar");
214 assert_eq!(special_url.as_str(), "http://foobar.com/foo%5Cbar");
215
216 let mut nonspecial_url = "thing://foobar.com".parse::<Url>().unwrap();
217 nonspecial_url.path_segments_mut().unwrap().push("foo\\bar");
218 assert_eq!(nonspecial_url.as_str(), "thing://foobar.com/foo\\bar");
219 }
220
221 #[test]
222 fn from_str() {
223 assert!("http://testing.com/this".parse::<Url>().is_ok());
224 }
225
226 #[test]
227 fn parse_with_params() {
228 let url = Url::parse_with_params(
229 "http://testing.com/this?dont=clobberme",
230 &[("lang", "rust")],
231 )
232 .unwrap();
233
234 assert_eq!(
235 url.as_str(),
236 "http://testing.com/this?dont=clobberme&lang=rust"
237 );
238 }
239
240 #[test]
241 fn issue_124() {
242 let url: Url = "file:a".parse().unwrap();
243 assert_eq!(url.path(), "/a");
244 let url: Url = "file:...".parse().unwrap();
245 assert_eq!(url.path(), "/...");
246 let url: Url = "file:..".parse().unwrap();
247 assert_eq!(url.path(), "/");
248 }
249
250 #[test]
251 fn test_equality() {
252 use std::collections::hash_map::DefaultHasher;
253 use std::hash::{Hash, Hasher};
254
255 fn check_eq(a: &Url, b: &Url) {
256 assert_eq!(a, b);
257
258 let mut h1 = DefaultHasher::new();
259 a.hash(&mut h1);
260 let mut h2 = DefaultHasher::new();
261 b.hash(&mut h2);
262 assert_eq!(h1.finish(), h2.finish());
263 }
264
265 fn url(s: &str) -> Url {
266 let rv = s.parse().unwrap();
267 check_eq(&rv, &rv);
268 rv
269 }
270
271 // Doesn't care if default port is given.
272 let a: Url = url("https://example.com/");
273 let b: Url = url("https://example.com:443/");
274 check_eq(&a, &b);
275
276 // Different ports
277 let a: Url = url("http://example.com/");
278 let b: Url = url("http://example.com:8080/");
279 assert!(a != b, "{:?} != {:?}", a, b);
280
281 // Different scheme
282 let a: Url = url("http://example.com/");
283 let b: Url = url("https://example.com/");
284 assert_ne!(a, b);
285
286 // Different host
287 let a: Url = url("http://foo.com/");
288 let b: Url = url("http://bar.com/");
289 assert_ne!(a, b);
290
291 // Missing path, automatically substituted. Semantically the same.
292 let a: Url = url("http://foo.com");
293 let b: Url = url("http://foo.com/");
294 check_eq(&a, &b);
295 }
296
297 #[test]
298 fn host() {
299 fn assert_host(input: &str, host: Host<&str>) {
300 assert_eq!(Url::parse(input).unwrap().host(), Some(host));
301 }
302 assert_host("http://www.mozilla.org", Host::Domain("www.mozilla.org"));
303 assert_host(
304 "http://1.35.33.49",
305 Host::Ipv4(Ipv4Addr::new(1, 35, 33, 49)),
306 );
307 assert_host(
308 "http://[2001:0db8:85a3:08d3:1319:8a2e:0370:7344]",
309 Host::Ipv6(Ipv6Addr::new(
310 0x2001, 0x0db8, 0x85a3, 0x08d3, 0x1319, 0x8a2e, 0x0370, 0x7344,
311 )),
312 );
313 assert_host(
314 "http://[::]",
315 Host::Ipv6(Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 0)),
316 );
317 assert_host(
318 "http://[::1]",
319 Host::Ipv6(Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 1)),
320 );
321 assert_host(
322 "http://0x1.0X23.0x21.061",
323 Host::Ipv4(Ipv4Addr::new(1, 35, 33, 49)),
324 );
325 assert_host("http://0x1232131", Host::Ipv4(Ipv4Addr::new(1, 35, 33, 49)));
326 assert_host("http://111", Host::Ipv4(Ipv4Addr::new(0, 0, 0, 111)));
327 assert!(Url::parse("http://1.35.+33.49").is_err());
328 assert!(Url::parse("http://2..2.3").is_err());
329 assert!(Url::parse("http://42.0x1232131").is_err());
330 assert!(Url::parse("http://192.168.0.257").is_err());
331
332 assert_eq!(Host::Domain("foo"), Host::Domain("foo").to_owned());
333 assert_ne!(Host::Domain("foo"), Host::Domain("bar").to_owned());
334 }
335
336 #[test]
337 fn host_serialization() {
338 // libstd’s `Display for Ipv6Addr` serializes 0:0:0:0:0:0:_:_ and 0:0:0:0:0:ffff:_:_
339 // using IPv4-like syntax, as suggested in https://tools.ietf.org/html/rfc5952#section-4
340 // but https://url.spec.whatwg.org/#concept-ipv6-serializer specifies not to.
341
342 // Not [::0.0.0.2] / [::ffff:0.0.0.2]
343 assert_eq!(
344 Url::parse("http://[0::2]").unwrap().host_str(),
345 Some("[::2]")
346 );
347 assert_eq!(
348 Url::parse("http://[0::ffff:0:2]").unwrap().host_str(),
349 Some("[::ffff:0:2]")
350 );
351 }
352
353 #[test]
354 fn test_idna() {
355 assert!("http://goșu.ro".parse::<Url>().is_ok());
356 assert_eq!(
357 Url::parse("http://☃.net/").unwrap().host(),
358 Some(Host::Domain("xn--n3h.net"))
359 );
360 assert!("https://r2---sn-huoa-cvhl.googlevideo.com/crossdomain.xml"
361 .parse::<Url>()
362 .is_ok());
363 }
364
365 #[test]
366 fn test_serialization() {
367 let data = [
368 ("http://example.com/", "http://example.com/"),
369 ("http://addslash.com", "http://addslash.com/"),
370 ("http://@emptyuser.com/", "http://emptyuser.com/"),
371 ("http://:@emptypass.com/", "http://emptypass.com/"),
372 ("http://user@user.com/", "http://user@user.com/"),
373 (
374 "http://user:pass@userpass.com/",
375 "http://user:pass@userpass.com/",
376 ),
377 (
378 "http://slashquery.com/path/?q=something",
379 "http://slashquery.com/path/?q=something",
380 ),
381 (
382 "http://noslashquery.com/path?q=something",
383 "http://noslashquery.com/path?q=something",
384 ),
385 ];
386 for &(input, result) in &data {
387 let url = Url::parse(input).unwrap();
388 assert_eq!(url.as_str(), result);
389 }
390 }
391
392 #[test]
393 fn test_form_urlencoded() {
394 let pairs: &[(Cow<'_, str>, Cow<'_, str>)] = &[
395 ("foo".into(), "é&".into()),
396 ("bar".into(), "".into()),
397 ("foo".into(), "#".into()),
398 ];
399 let encoded = form_urlencoded::Serializer::new(String::new())
400 .extend_pairs(pairs)
401 .finish();
402 assert_eq!(encoded, "foo=%C3%A9%26&bar=&foo=%23");
403 assert_eq!(
404 form_urlencoded::parse(encoded.as_bytes()).collect::<Vec<_>>(),
405 pairs.to_vec()
406 );
407 }
408
409 #[test]
410 fn test_form_serialize() {
411 let encoded = form_urlencoded::Serializer::new(String::new())
412 .append_pair("foo", "é&")
413 .append_pair("bar", "")
414 .append_pair("foo", "#")
415 .append_key_only("json")
416 .finish();
417 assert_eq!(encoded, "foo=%C3%A9%26&bar=&foo=%23&json");
418 }
419
420 #[test]
421 fn form_urlencoded_encoding_override() {
422 let encoded = form_urlencoded::Serializer::new(String::new())
423 .encoding_override(Some(&|s| s.as_bytes().to_ascii_uppercase().into()))
424 .append_pair("foo", "bar")
425 .append_key_only("xml")
426 .finish();
427 assert_eq!(encoded, "FOO=BAR&XML");
428 }
429
430 #[test]
431 /// https://github.com/servo/rust-url/issues/61
432 fn issue_61() {
433 let mut url = Url::parse("http://mozilla.org").unwrap();
434 url.set_scheme("https").unwrap();
435 assert_eq!(url.port(), None);
436 assert_eq!(url.port_or_known_default(), Some(443));
437 url.check_invariants().unwrap();
438 }
439
440 #[test]
441 #[cfg(not(windows))]
442 /// https://github.com/servo/rust-url/issues/197
443 fn issue_197() {
444 let mut url = Url::from_file_path("/").expect("Failed to parse path");
445 url.check_invariants().unwrap();
446 assert_eq!(
447 url,
448 Url::parse("file:///").expect("Failed to parse path + protocol")
449 );
450 url.path_segments_mut()
451 .expect("path_segments_mut")
452 .pop_if_empty();
453 }
454
455 #[test]
456 fn issue_241() {
457 Url::parse("mailto:").unwrap().cannot_be_a_base();
458 }
459
460 #[test]
461 /// https://github.com/servo/rust-url/issues/222
462 fn append_trailing_slash() {
463 let mut url: Url = "http://localhost:6767/foo/bar?a=b".parse().unwrap();
464 url.check_invariants().unwrap();
465 url.path_segments_mut().unwrap().push("");
466 url.check_invariants().unwrap();
467 assert_eq!(url.to_string(), "http://localhost:6767/foo/bar/?a=b");
468 }
469
470 #[test]
471 /// https://github.com/servo/rust-url/issues/227
472 fn extend_query_pairs_then_mutate() {
473 let mut url: Url = "http://localhost:6767/foo/bar".parse().unwrap();
474 url.query_pairs_mut()
475 .extend_pairs(vec![("auth", "my-token")]);
476 url.check_invariants().unwrap();
477 assert_eq!(
478 url.to_string(),
479 "http://localhost:6767/foo/bar?auth=my-token"
480 );
481 url.path_segments_mut().unwrap().push("some_other_path");
482 url.check_invariants().unwrap();
483 assert_eq!(
484 url.to_string(),
485 "http://localhost:6767/foo/bar/some_other_path?auth=my-token"
486 );
487 }
488
489 #[test]
490 /// https://github.com/servo/rust-url/issues/222
491 fn append_empty_segment_then_mutate() {
492 let mut url: Url = "http://localhost:6767/foo/bar?a=b".parse().unwrap();
493 url.check_invariants().unwrap();
494 url.path_segments_mut().unwrap().push("").pop();
495 url.check_invariants().unwrap();
496 assert_eq!(url.to_string(), "http://localhost:6767/foo/bar?a=b");
497 }
498
499 #[test]
500 /// https://github.com/servo/rust-url/issues/243
501 fn test_set_host() {
502 let mut url = Url::parse("https://example.net/hello").unwrap();
503 url.set_host(Some("foo.com")).unwrap();
504 assert_eq!(url.as_str(), "https://foo.com/hello");
505 assert!(url.set_host(None).is_err());
506 assert_eq!(url.as_str(), "https://foo.com/hello");
507 assert!(url.set_host(Some("")).is_err());
508 assert_eq!(url.as_str(), "https://foo.com/hello");
509
510 let mut url = Url::parse("foobar://example.net/hello").unwrap();
511 url.set_host(None).unwrap();
512 assert_eq!(url.as_str(), "foobar:/hello");
513
514 let mut url = Url::parse("foo://ș").unwrap();
515 assert_eq!(url.as_str(), "foo://%C8%99");
516 url.set_host(Some("goșu.ro")).unwrap();
517 assert_eq!(url.as_str(), "foo://go%C8%99u.ro");
518 }
519
520 #[test]
521 // https://github.com/servo/rust-url/issues/166
522 fn test_leading_dots() {
523 assert_eq!(
524 Host::parse(".org").unwrap(),
525 Host::Domain(".org".to_owned())
526 );
527 assert_eq!(Url::parse("file://./foo").unwrap().domain(), Some("."));
528 }
529
530 #[test]
531 /// https://github.com/servo/rust-url/issues/302
532 fn test_origin_hash() {
533 use std::collections::hash_map::DefaultHasher;
534 use std::hash::{Hash, Hasher};
535
536 fn hash<T: Hash>(value: &T) -> u64 {
537 let mut hasher = DefaultHasher::new();
538 value.hash(&mut hasher);
539 hasher.finish()
540 }
541
542 let origin = &Url::parse("http://example.net/").unwrap().origin();
543
544 let origins_to_compare = [
545 Url::parse("http://example.net:80/").unwrap().origin(),
546 Url::parse("http://example.net:81/").unwrap().origin(),
547 Url::parse("http://example.net").unwrap().origin(),
548 Url::parse("http://example.net/hello").unwrap().origin(),
549 Url::parse("https://example.net").unwrap().origin(),
550 Url::parse("ftp://example.net").unwrap().origin(),
551 Url::parse("file://example.net").unwrap().origin(),
552 Url::parse("http://user@example.net/").unwrap().origin(),
553 Url::parse("http://user:pass@example.net/")
554 .unwrap()
555 .origin(),
556 ];
557
558 for origin_to_compare in &origins_to_compare {
559 if origin == origin_to_compare {
560 assert_eq!(hash(origin), hash(origin_to_compare));
561 } else {
562 assert_ne!(hash(origin), hash(origin_to_compare));
563 }
564 }
565
566 let opaque_origin = Url::parse("file://example.net").unwrap().origin();
567 let same_opaque_origin = Url::parse("file://example.net").unwrap().origin();
568 let other_opaque_origin = Url::parse("file://other").unwrap().origin();
569
570 assert_ne!(hash(&opaque_origin), hash(&same_opaque_origin));
571 assert_ne!(hash(&opaque_origin), hash(&other_opaque_origin));
572 }
573
574 #[test]
575 fn test_origin_blob_equality() {
576 let origin = &Url::parse("http://example.net/").unwrap().origin();
577 let blob_origin = &Url::parse("blob:http://example.net/").unwrap().origin();
578
579 assert_eq!(origin, blob_origin);
580 }
581
582 #[test]
583 fn test_origin_opaque() {
584 assert!(!Origin::new_opaque().is_tuple());
585 assert!(!&Url::parse("blob:malformed//").unwrap().origin().is_tuple())
586 }
587
588 #[test]
589 fn test_origin_unicode_serialization() {
590 let data = [
591 ("http://😅.com", "http://😅.com"),
592 ("ftp://😅:🙂@🙂.com", "ftp://🙂.com"),
593 ("https://user@😅.com", "https://😅.com"),
594 ("http://😅.🙂:40", "http://😅.🙂:40"),
595 ];
596 for &(unicode_url, expected_serialization) in &data {
597 let origin = Url::parse(unicode_url).unwrap().origin();
598 assert_eq!(origin.unicode_serialization(), *expected_serialization);
599 }
600
601 let ascii_origins = [
602 Url::parse("http://example.net/").unwrap().origin(),
603 Url::parse("http://example.net:80/").unwrap().origin(),
604 Url::parse("http://example.net:81/").unwrap().origin(),
605 Url::parse("http://example.net").unwrap().origin(),
606 Url::parse("http://example.net/hello").unwrap().origin(),
607 Url::parse("https://example.net").unwrap().origin(),
608 Url::parse("ftp://example.net").unwrap().origin(),
609 Url::parse("file://example.net").unwrap().origin(),
610 Url::parse("http://user@example.net/").unwrap().origin(),
611 Url::parse("http://user:pass@example.net/")
612 .unwrap()
613 .origin(),
614 Url::parse("http://127.0.0.1").unwrap().origin(),
615 ];
616 for ascii_origin in &ascii_origins {
617 assert_eq!(
618 ascii_origin.ascii_serialization(),
619 ascii_origin.unicode_serialization()
620 );
621 }
622 }
623
624 #[test]
625 fn test_socket_addrs() {
626 use std::net::ToSocketAddrs;
627
628 let data = [
629 ("https://127.0.0.1/", "127.0.0.1", 443),
630 ("https://127.0.0.1:9742/", "127.0.0.1", 9742),
631 ("custom-protocol://127.0.0.1:9742/", "127.0.0.1", 9742),
632 ("custom-protocol://127.0.0.1/", "127.0.0.1", 9743),
633 ("https://[::1]/", "::1", 443),
634 ("https://[::1]:9742/", "::1", 9742),
635 ("custom-protocol://[::1]:9742/", "::1", 9742),
636 ("custom-protocol://[::1]/", "::1", 9743),
637 ("https://localhost/", "localhost", 443),
638 ("https://localhost:9742/", "localhost", 9742),
639 ("custom-protocol://localhost:9742/", "localhost", 9742),
640 ("custom-protocol://localhost/", "localhost", 9743),
641 ];
642
643 for (url_string, host, port) in &data {
644 let url = url::Url::parse(url_string).unwrap();
645 let addrs = url
646 .socket_addrs(|| match url.scheme() {
647 "custom-protocol" => Some(9743),
648 _ => None,
649 })
650 .unwrap();
651 assert_eq!(
652 Some(addrs[0]),
653 (*host, *port).to_socket_addrs().unwrap().next()
654 );
655 }
656 }
657
658 #[test]
659 fn test_no_base_url() {
660 let mut no_base_url = Url::parse("mailto:test@example.net").unwrap();
661
662 assert!(no_base_url.cannot_be_a_base());
663 assert!(no_base_url.path_segments().is_none());
664 assert!(no_base_url.path_segments_mut().is_err());
665 assert!(no_base_url.set_host(Some("foo")).is_err());
666 assert!(no_base_url
667 .set_ip_host("127.0.0.1".parse().unwrap())
668 .is_err());
669
670 no_base_url.set_path("/foo");
671 assert_eq!(no_base_url.path(), "%2Ffoo");
672 }
673
674 #[test]
675 fn test_domain() {
676 let url = Url::parse("https://127.0.0.1/").unwrap();
677 assert_eq!(url.domain(), None);
678
679 let url = Url::parse("mailto:test@example.net").unwrap();
680 assert_eq!(url.domain(), None);
681
682 let url = Url::parse("https://example.com/").unwrap();
683 assert_eq!(url.domain(), Some("example.com"));
684 }
685
686 #[test]
687 fn test_query() {
688 let url = Url::parse("https://example.com/products?page=2#fragment").unwrap();
689 assert_eq!(url.query(), Some("page=2"));
690 assert_eq!(
691 url.query_pairs().next(),
692 Some((Cow::Borrowed("page"), Cow::Borrowed("2")))
693 );
694
695 let url = Url::parse("https://example.com/products").unwrap();
696 assert!(url.query().is_none());
697 assert_eq!(url.query_pairs().count(), 0);
698
699 let url = Url::parse("https://example.com/?country=español").unwrap();
700 assert_eq!(url.query(), Some("country=espa%C3%B1ol"));
701 assert_eq!(
702 url.query_pairs().next(),
703 Some((Cow::Borrowed("country"), Cow::Borrowed("español")))
704 );
705
706 let url = Url::parse("https://example.com/products?page=2&sort=desc").unwrap();
707 assert_eq!(url.query(), Some("page=2&sort=desc"));
708 let mut pairs = url.query_pairs();
709 assert_eq!(pairs.count(), 2);
710 assert_eq!(
711 pairs.next(),
712 Some((Cow::Borrowed("page"), Cow::Borrowed("2")))
713 );
714 assert_eq!(
715 pairs.next(),
716 Some((Cow::Borrowed("sort"), Cow::Borrowed("desc")))
717 );
718 }
719
720 #[test]
721 fn test_fragment() {
722 let url = Url::parse("https://example.com/#fragment").unwrap();
723 assert_eq!(url.fragment(), Some("fragment"));
724
725 let url = Url::parse("https://example.com/").unwrap();
726 assert_eq!(url.fragment(), None);
727 }
728
729 #[test]
730 fn test_set_ip_host() {
731 let mut url = Url::parse("http://example.com").unwrap();
732
733 url.set_ip_host("127.0.0.1".parse().unwrap()).unwrap();
734 assert_eq!(url.host_str(), Some("127.0.0.1"));
735
736 url.set_ip_host("::1".parse().unwrap()).unwrap();
737 assert_eq!(url.host_str(), Some("[::1]"));
738 }
739
740 #[test]
741 fn test_set_href() {
742 use url::quirks::set_href;
743
744 let mut url = Url::parse("https://existing.url").unwrap();
745
746 assert!(set_href(&mut url, "mal//formed").is_err());
747
748 assert!(set_href(
749 &mut url,
750 "https://user:pass@domain.com:9742/path/file.ext?key=val&key2=val2#fragment"
751 )
752 .is_ok());
753 assert_eq!(
754 url,
755 Url::parse("https://user:pass@domain.com:9742/path/file.ext?key=val&key2=val2#fragment")
756 .unwrap()
757 );
758 }
759
760 #[test]
761 fn test_domain_encoding_quirks() {
762 use url::quirks::{domain_to_ascii, domain_to_unicode};
763
764 let data = [
765 ("http://example.com", "", ""),
766 ("😅.🙂", "xn--j28h.xn--938h", "😅.🙂"),
767 ("example.com", "example.com", "example.com"),
768 ("mailto:test@example.net", "", ""),
769 ];
770
771 for url in &data {
772 assert_eq!(domain_to_ascii(url.0), url.1);
773 assert_eq!(domain_to_unicode(url.0), url.2);
774 }
775 }
776
777 #[cfg(feature = "expose_internals")]
778 #[test]
779 fn test_expose_internals() {
780 use url::quirks::internal_components;
781 use url::quirks::InternalComponents;
782
783 let url = Url::parse("https://example.com/path/file.ext?key=val&key2=val2#fragment").unwrap();
784 let InternalComponents {
785 scheme_end,
786 username_end,
787 host_start,
788 host_end,
789 port,
790 path_start,
791 query_start,
792 fragment_start,
793 } = internal_components(&url);
794
795 assert_eq!(scheme_end, 5);
796 assert_eq!(username_end, 8);
797 assert_eq!(host_start, 8);
798 assert_eq!(host_end, 19);
799 assert_eq!(port, None);
800 assert_eq!(path_start, 19);
801 assert_eq!(query_start, Some(33));
802 assert_eq!(fragment_start, Some(51));
803 }
804
805 #[test]
806 fn test_windows_unc_path() {
807 if !cfg!(windows) {
808 return;
809 }
810
811 let url = Url::from_file_path(Path::new(r"\\host\share\path\file.txt")).unwrap();
812 assert_eq!(url.as_str(), "file://host/share/path/file.txt");
813
814 let url = Url::from_file_path(Path::new(r"\\höst\share\path\file.txt")).unwrap();
815 assert_eq!(url.as_str(), "file://xn--hst-sna/share/path/file.txt");
816
817 let url = Url::from_file_path(Path::new(r"\\192.168.0.1\share\path\file.txt")).unwrap();
818 assert_eq!(url.host(), Some(Host::Ipv4(Ipv4Addr::new(192, 168, 0, 1))));
819
820 let path = url.to_file_path().unwrap();
821 assert_eq!(path.to_str(), Some(r"\\192.168.0.1\share\path\file.txt"));
822
823 // Another way to write these:
824 let url = Url::from_file_path(Path::new(r"\\?\UNC\host\share\path\file.txt")).unwrap();
825 assert_eq!(url.as_str(), "file://host/share/path/file.txt");
826
827 // Paths starting with "\\.\" (Local Device Paths) are intentionally not supported.
828 let url = Url::from_file_path(Path::new(r"\\.\some\path\file.txt"));
829 assert!(url.is_err());
830 }
831
832 #[test]
833 fn test_syntax_violation_callback() {
834 use url::SyntaxViolation::*;
835 let violation = Cell::new(None);
836 let url = Url::options()
837 .syntax_violation_callback(Some(&|v| violation.set(Some(v))))
838 .parse("http:////mozilla.org:42")
839 .unwrap();
840 assert_eq!(url.port(), Some(42));
841
842 let v = violation.take().unwrap();
843 assert_eq!(v, ExpectedDoubleSlash);
844 assert_eq!(v.description(), "expected //");
845 assert_eq!(v.to_string(), "expected //");
846 }
847
848 #[test]
849 fn test_syntax_violation_callback_lifetimes() {
850 use url::SyntaxViolation::*;
851 let violation = Cell::new(None);
852 let vfn = |s| violation.set(Some(s));
853
854 let url = Url::options()
855 .syntax_violation_callback(Some(&vfn))
856 .parse("http:////mozilla.org:42")
857 .unwrap();
858 assert_eq!(url.port(), Some(42));
859 assert_eq!(violation.take(), Some(ExpectedDoubleSlash));
860
861 let url = Url::options()
862 .syntax_violation_callback(Some(&vfn))
863 .parse("http://mozilla.org\\path")
864 .unwrap();
865 assert_eq!(url.path(), "/path");
866 assert_eq!(violation.take(), Some(Backslash));
867 }
868
869 #[test]
870 fn test_syntax_violation_callback_types() {
871 use url::SyntaxViolation::*;
872
873 let data = [
874 ("http://mozilla.org/\\foo", Backslash, "backslash"),
875 (" http://mozilla.org", C0SpaceIgnored, "leading or trailing control or space character are ignored in URLs"),
876 ("http://user:pass@mozilla.org", EmbeddedCredentials, "embedding authentication information (username or password) in an URL is not recommended"),
877 ("http:///mozilla.org", ExpectedDoubleSlash, "expected //"),
878 ("file:/foo.txt", ExpectedFileDoubleSlash, "expected // after file:"),
879 ("file://mozilla.org/c:/file.txt", FileWithHostAndWindowsDrive, "file: with host and Windows drive letter"),
880 ("http://mozilla.org/^", NonUrlCodePoint, "non-URL code point"),
881 ("http://mozilla.org/#\x000", NullInFragment, "NULL characters are ignored in URL fragment identifiers"),
882 ("http://mozilla.org/%1", PercentDecode, "expected 2 hex digits after %"),
883 ("http://mozilla.org\t/foo", TabOrNewlineIgnored, "tabs or newlines are ignored in URLs"),
884 ("http://user@:pass@mozilla.org", UnencodedAtSign, "unencoded @ sign in username or password")
885 ];
886
887 for test_case in &data {
888 let violation = Cell::new(None);
889 Url::options()
890 .syntax_violation_callback(Some(&|v| violation.set(Some(v))))
891 .parse(test_case.0)
892 .unwrap();
893
894 let v = violation.take();
895 assert_eq!(v, Some(test_case.1));
896 assert_eq!(v.unwrap().description(), test_case.2);
897 assert_eq!(v.unwrap().to_string(), test_case.2);
898 }
899 }
900
901 #[test]
902 fn test_options_reuse() {
903 use url::SyntaxViolation::*;
904 let violations = RefCell::new(Vec::new());
905 let vfn = |v| violations.borrow_mut().push(v);
906
907 let options = Url::options().syntax_violation_callback(Some(&vfn));
908 let url = options.parse("http:////mozilla.org").unwrap();
909
910 let options = options.base_url(Some(&url));
911 let url = options.parse("/sub\\path").unwrap();
912 assert_eq!(url.as_str(), "http://mozilla.org/sub/path");
913 assert_eq!(*violations.borrow(), vec!(ExpectedDoubleSlash, Backslash));
914 }
915
916 /// https://github.com/servo/rust-url/issues/505
917 #[cfg(windows)]
918 #[test]
919 fn test_url_from_file_path() {
920 use std::path::PathBuf;
921 use url::Url;
922
923 let p = PathBuf::from("c:///");
924 let u = Url::from_file_path(p).unwrap();
925 let path = u.to_file_path().unwrap();
926 assert_eq!("C:\\", path.to_str().unwrap());
927 }
928
929 /// https://github.com/servo/rust-url/issues/505
930 #[cfg(not(windows))]
931 #[test]
932 fn test_url_from_file_path() {
933 use std::path::PathBuf;
934 use url::Url;
935
936 let p = PathBuf::from("/c:/");
937 let u = Url::from_file_path(p).unwrap();
938 let path = u.to_file_path().unwrap();
939 assert_eq!("/c:/", path.to_str().unwrap());
940 }
941
942 #[test]
943 fn test_non_special_path() {
944 let mut db_url = url::Url::parse("postgres://postgres@localhost/").unwrap();
945 assert_eq!(db_url.as_str(), "postgres://postgres@localhost/");
946 db_url.set_path("diesel_foo");
947 assert_eq!(db_url.as_str(), "postgres://postgres@localhost/diesel_foo");
948 assert_eq!(db_url.path(), "/diesel_foo");
949 }
950
951 #[test]
952 fn test_non_special_path2() {
953 let mut db_url = url::Url::parse("postgres://postgres@localhost/").unwrap();
954 assert_eq!(db_url.as_str(), "postgres://postgres@localhost/");
955 db_url.set_path("");
956 assert_eq!(db_url.path(), "");
957 assert_eq!(db_url.as_str(), "postgres://postgres@localhost");
958 db_url.set_path("foo");
959 assert_eq!(db_url.path(), "/foo");
960 assert_eq!(db_url.as_str(), "postgres://postgres@localhost/foo");
961 db_url.set_path("/bar");
962 assert_eq!(db_url.path(), "/bar");
963 assert_eq!(db_url.as_str(), "postgres://postgres@localhost/bar");
964 }
965
966 #[test]
967 fn test_non_special_path3() {
968 let mut db_url = url::Url::parse("postgres://postgres@localhost/").unwrap();
969 assert_eq!(db_url.as_str(), "postgres://postgres@localhost/");
970 db_url.set_path("/");
971 assert_eq!(db_url.as_str(), "postgres://postgres@localhost/");
972 assert_eq!(db_url.path(), "/");
973 db_url.set_path("/foo");
974 assert_eq!(db_url.as_str(), "postgres://postgres@localhost/foo");
975 assert_eq!(db_url.path(), "/foo");
976 }
977
978 #[test]
979 fn test_set_scheme_to_file_with_host() {
980 let mut url: Url = "http://localhost:6767/foo/bar".parse().unwrap();
981 let result = url.set_scheme("file");
982 assert_eq!(url.to_string(), "http://localhost:6767/foo/bar");
983 assert_eq!(result, Err(()));
984 }
985
986 #[test]
987 fn no_panic() {
988 let mut url = Url::parse("arhttpsps:/.//eom/dae.com/\\\\t\\:").unwrap();
989 url::quirks::set_hostname(&mut url, "//eom/datcom/\\\\t\\://eom/data.cs").unwrap();
990 }
991
992 #[test]
993 fn test_null_host_with_leading_empty_path_segment() {
994 // since Note in item 3 of URL serializing in the URL Standard
995 // https://url.spec.whatwg.org/#url-serializing
996 let url = Url::parse("m:/.//\\").unwrap();
997 let encoded = url.as_str();
998 let reparsed = Url::parse(encoded).unwrap();
999 assert_eq!(reparsed, url);
1000 }
1001
1002 #[test]
1003 fn pop_if_empty_in_bounds() {
1004 let mut url = Url::parse("m://").unwrap();
1005 let mut segments = url.path_segments_mut().unwrap();
1006 segments.pop_if_empty();
1007 segments.pop();
1008 }
1009
1010 #[test]
1011 fn test_slicing() {
1012 use url::Position::*;
1013
1014 #[derive(Default)]
1015 struct ExpectedSlices<'a> {
1016 full: &'a str,
1017 scheme: &'a str,
1018 username: &'a str,
1019 password: &'a str,
1020 host: &'a str,
1021 port: &'a str,
1022 path: &'a str,
1023 query: &'a str,
1024 fragment: &'a str,
1025 }
1026
1027 let data = [
1028 ExpectedSlices {
1029 full: "https://user:pass@domain.com:9742/path/file.ext?key=val&key2=val2#fragment",
1030 scheme: "https",
1031 username: "user",
1032 password: "pass",
1033 host: "domain.com",
1034 port: "9742",
1035 path: "/path/file.ext",
1036 query: "key=val&key2=val2",
1037 fragment: "fragment",
1038 },
1039 ExpectedSlices {
1040 full: "https://domain.com:9742/path/file.ext#fragment",
1041 scheme: "https",
1042 host: "domain.com",
1043 port: "9742",
1044 path: "/path/file.ext",
1045 fragment: "fragment",
1046 ..Default::default()
1047 },
1048 ExpectedSlices {
1049 full: "https://domain.com:9742/path/file.ext",
1050 scheme: "https",
1051 host: "domain.com",
1052 port: "9742",
1053 path: "/path/file.ext",
1054 ..Default::default()
1055 },
1056 ExpectedSlices {
1057 full: "blob:blob-info",
1058 scheme: "blob",
1059 path: "blob-info",
1060 ..Default::default()
1061 },
1062 ];
1063
1064 for expected_slices in &data {
1065 let url = Url::parse(expected_slices.full).unwrap();
1066 assert_eq!(&url[..], expected_slices.full);
1067 assert_eq!(&url[BeforeScheme..AfterScheme], expected_slices.scheme);
1068 assert_eq!(
1069 &url[BeforeUsername..AfterUsername],
1070 expected_slices.username
1071 );
1072 assert_eq!(
1073 &url[BeforePassword..AfterPassword],
1074 expected_slices.password
1075 );
1076 assert_eq!(&url[BeforeHost..AfterHost], expected_slices.host);
1077 assert_eq!(&url[BeforePort..AfterPort], expected_slices.port);
1078 assert_eq!(&url[BeforePath..AfterPath], expected_slices.path);
1079 assert_eq!(&url[BeforeQuery..AfterQuery], expected_slices.query);
1080 assert_eq!(
1081 &url[BeforeFragment..AfterFragment],
1082 expected_slices.fragment
1083 );
1084 assert_eq!(&url[..AfterFragment], expected_slices.full);
1085 }
1086 }
1087
1088 #[test]
1089 fn test_make_relative() {
1090 let tests = [
1091 (
1092 "http://127.0.0.1:8080/test",
1093 "http://127.0.0.1:8080/test",
1094 "",
1095 ),
1096 (
1097 "http://127.0.0.1:8080/test",
1098 "http://127.0.0.1:8080/test/",
1099 "test/",
1100 ),
1101 (
1102 "http://127.0.0.1:8080/test/",
1103 "http://127.0.0.1:8080/test",
1104 "../test",
1105 ),
1106 (
1107 "http://127.0.0.1:8080/",
1108 "http://127.0.0.1:8080/?foo=bar#123",
1109 "?foo=bar#123",
1110 ),
1111 (
1112 "http://127.0.0.1:8080/",
1113 "http://127.0.0.1:8080/test/video",
1114 "test/video",
1115 ),
1116 (
1117 "http://127.0.0.1:8080/test",
1118 "http://127.0.0.1:8080/test/video",
1119 "test/video",
1120 ),
1121 (
1122 "http://127.0.0.1:8080/test/",
1123 "http://127.0.0.1:8080/test/video",
1124 "video",
1125 ),
1126 (
1127 "http://127.0.0.1:8080/test",
1128 "http://127.0.0.1:8080/test2/video",
1129 "test2/video",
1130 ),
1131 (
1132 "http://127.0.0.1:8080/test/",
1133 "http://127.0.0.1:8080/test2/video",
1134 "../test2/video",
1135 ),
1136 (
1137 "http://127.0.0.1:8080/test/bla",
1138 "http://127.0.0.1:8080/test2/video",
1139 "../test2/video",
1140 ),
1141 (
1142 "http://127.0.0.1:8080/test/bla/",
1143 "http://127.0.0.1:8080/test2/video",
1144 "../../test2/video",
1145 ),
1146 (
1147 "http://127.0.0.1:8080/test/?foo=bar#123",
1148 "http://127.0.0.1:8080/test/video",
1149 "video",
1150 ),
1151 (
1152 "http://127.0.0.1:8080/test/",
1153 "http://127.0.0.1:8080/test/video?baz=meh#456",
1154 "video?baz=meh#456",
1155 ),
1156 (
1157 "http://127.0.0.1:8080/test",
1158 "http://127.0.0.1:8080/test?baz=meh#456",
1159 "?baz=meh#456",
1160 ),
1161 (
1162 "http://127.0.0.1:8080/test/",
1163 "http://127.0.0.1:8080/test?baz=meh#456",
1164 "../test?baz=meh#456",
1165 ),
1166 (
1167 "http://127.0.0.1:8080/test/",
1168 "http://127.0.0.1:8080/test/?baz=meh#456",
1169 "?baz=meh#456",
1170 ),
1171 (
1172 "http://127.0.0.1:8080/test/?foo=bar#123",
1173 "http://127.0.0.1:8080/test/video?baz=meh#456",
1174 "video?baz=meh#456",
1175 ),
1176 (
1177 "http://127.0.0.1:8080/file.txt",
1178 "http://127.0.0.1:8080/test/file.txt",
1179 "test/file.txt",
1180 ),
1181 (
1182 "http://127.0.0.1:8080/not_equal.txt",
1183 "http://127.0.0.1:8080/test/file.txt",
1184 "test/file.txt",
1185 ),
1186 ];
1187
1188 for (base, uri, relative) in &tests {
1189 let base_uri = url::Url::parse(base).unwrap();
1190 let relative_uri = url::Url::parse(uri).unwrap();
1191 let make_relative = base_uri.make_relative(&relative_uri).unwrap();
1192 assert_eq!(
1193 make_relative, *relative,
1194 "base: {}, uri: {}, relative: {}",
1195 base, uri, relative
1196 );
1197 assert_eq!(
1198 base_uri.join(relative).unwrap().as_str(),
1199 *uri,
1200 "base: {}, uri: {}, relative: {}",
1201 base,
1202 uri,
1203 relative
1204 );
1205 }
1206
1207 let error_tests = [
1208 ("http://127.0.0.1:8080/", "https://127.0.0.1:8080/test/"),
1209 ("http://127.0.0.1:8080/", "http://127.0.0.1:8081/test/"),
1210 ("http://127.0.0.1:8080/", "http://127.0.0.2:8080/test/"),
1211 ("mailto:a@example.com", "mailto:b@example.com"),
1212 ];
1213
1214 for (base, uri) in &error_tests {
1215 let base_uri = url::Url::parse(base).unwrap();
1216 let relative_uri = url::Url::parse(uri).unwrap();
1217 let make_relative = base_uri.make_relative(&relative_uri);
1218 assert_eq!(make_relative, None, "base: {}, uri: {}", base, uri);
1219 }
1220 }
1221
1222 #[test]
1223 fn test_has_authority() {
1224 let url = Url::parse("mailto:joe@example.com").unwrap();
1225 assert!(!url.has_authority());
1226 let url = Url::parse("unix:/run/foo.socket").unwrap();
1227 assert!(!url.has_authority());
1228 let url = Url::parse("file:///tmp/foo").unwrap();
1229 assert!(url.has_authority());
1230 let url = Url::parse("http://example.com/tmp/foo").unwrap();
1231 assert!(url.has_authority());
1232 }
1233
1234 #[test]
1235 fn test_authority() {
1236 let url = Url::parse("mailto:joe@example.com").unwrap();
1237 assert_eq!(url.authority(), "");
1238 let url = Url::parse("unix:/run/foo.socket").unwrap();
1239 assert_eq!(url.authority(), "");
1240 let url = Url::parse("file:///tmp/foo").unwrap();
1241 assert_eq!(url.authority(), "");
1242 let url = Url::parse("http://example.com/tmp/foo").unwrap();
1243 assert_eq!(url.authority(), "example.com");
1244 let url = Url::parse("ftp://127.0.0.1:21/").unwrap();
1245 assert_eq!(url.authority(), "127.0.0.1");
1246 let url = Url::parse("ftp://user@127.0.0.1:2121/").unwrap();
1247 assert_eq!(url.authority(), "user@127.0.0.1:2121");
1248 let url = Url::parse("https://:@example.com/").unwrap();
1249 assert_eq!(url.authority(), "example.com");
1250 let url = Url::parse("https://:password@[::1]:8080/").unwrap();
1251 assert_eq!(url.authority(), ":password@[::1]:8080");
1252 let url = Url::parse("gopher://user:@àlex.example.com:70").unwrap();
1253 assert_eq!(url.authority(), "user@%C3%A0lex.example.com:70");
1254 let url = Url::parse("irc://àlex:àlex@àlex.рф.example.com:6667/foo").unwrap();
1255 assert_eq!(
1256 url.authority(),
1257 "%C3%A0lex:%C3%A0lex@%C3%A0lex.%D1%80%D1%84.example.com:6667"
1258 );
1259 let url = Url::parse("https://àlex:àlex@àlex.рф.example.com:443/foo").unwrap();
1260 assert_eq!(
1261 url.authority(),
1262 "%C3%A0lex:%C3%A0lex@xn--lex-8ka.xn--p1ai.example.com"
1263 );
1264 }
1265
1266 #[test]
1267 /// https://github.com/servo/rust-url/issues/838
1268 fn test_file_with_drive() {
1269 let s1 = "fIlE:p:?../";
1270 let url = url::Url::parse(s1).unwrap();
1271 assert_eq!(url.to_string(), "file:///p:?../");
1272 assert_eq!(url.path(), "/p:");
1273
1274 let testcases = [
1275 ("a", "file:///p:/a"),
1276 ("", "file:///p:?../"),
1277 ("?x", "file:///p:?x"),
1278 (".", "file:///p:/"),
1279 ("..", "file:///p:/"),
1280 ("../", "file:///p:/"),
1281 ];
1282
1283 for case in &testcases {
1284 let url2 = url::Url::join(&url, case.0).unwrap();
1285 assert_eq!(url2.to_string(), case.1);
1286 }
1287 }
1288
1289 #[test]
1290 /// Similar to test_file_with_drive, but with a path
1291 /// that could be confused for a drive.
1292 fn test_file_with_drive_and_path() {
1293 let s1 = "fIlE:p:/x|?../";
1294 let url = url::Url::parse(s1).unwrap();
1295 assert_eq!(url.to_string(), "file:///p:/x|?../");
1296 assert_eq!(url.path(), "/p:/x|");
1297 let s2 = "a";
1298 let url2 = url::Url::join(&url, s2).unwrap();
1299 assert_eq!(url2.to_string(), "file:///p:/a");
1300 }
1301
1302 #[test]
1303 fn issue_864() {
1304 let mut url = url::Url::parse("file://").unwrap();
1305 dbg!(&url);
1306 url.set_path("x");
1307 dbg!(&url);
1308 }