aboutsummaryrefslogtreecommitdiff
path: root/tests/unit.rs
diff options
context:
space:
mode:
Diffstat (limited to 'tests/unit.rs')
-rw-r--r--tests/unit.rs439
1 files changed, 438 insertions, 1 deletions
diff --git a/tests/unit.rs b/tests/unit.rs
index 4c25198..13055a4 100644
--- a/tests/unit.rs
+++ b/tests/unit.rs
@@ -12,7 +12,7 @@ use std::borrow::Cow;
use std::cell::{Cell, RefCell};
use std::net::{Ipv4Addr, Ipv6Addr};
use std::path::{Path, PathBuf};
-use url::{form_urlencoded, Host, Url};
+use url::{form_urlencoded, Host, Origin, Url};
#[test]
fn size() {
@@ -518,6 +518,209 @@ fn test_origin_hash() {
}
#[test]
+fn test_origin_blob_equality() {
+ let origin = &Url::parse("http://example.net/").unwrap().origin();
+ let blob_origin = &Url::parse("blob:http://example.net/").unwrap().origin();
+
+ assert_eq!(origin, blob_origin);
+}
+
+#[test]
+fn test_origin_opaque() {
+ assert!(!Origin::new_opaque().is_tuple());
+ assert!(!&Url::parse("blob:malformed//").unwrap().origin().is_tuple())
+}
+
+#[test]
+fn test_origin_unicode_serialization() {
+ let data = [
+ ("http://πŸ˜….com", "http://πŸ˜….com"),
+ ("ftp://πŸ˜…:πŸ™‚@πŸ™‚.com", "ftp://πŸ™‚.com"),
+ ("https://user@πŸ˜….com", "https://πŸ˜….com"),
+ ("http://πŸ˜….πŸ™‚:40", "http://πŸ˜….πŸ™‚:40"),
+ ];
+ for &(unicode_url, expected_serialization) in &data {
+ let origin = Url::parse(unicode_url).unwrap().origin();
+ assert_eq!(origin.unicode_serialization(), *expected_serialization);
+ }
+
+ let ascii_origins = [
+ Url::parse("http://example.net/").unwrap().origin(),
+ Url::parse("http://example.net:80/").unwrap().origin(),
+ Url::parse("http://example.net:81/").unwrap().origin(),
+ Url::parse("http://example.net").unwrap().origin(),
+ Url::parse("http://example.net/hello").unwrap().origin(),
+ Url::parse("https://example.net").unwrap().origin(),
+ Url::parse("ftp://example.net").unwrap().origin(),
+ Url::parse("file://example.net").unwrap().origin(),
+ Url::parse("http://user@example.net/").unwrap().origin(),
+ Url::parse("http://user:pass@example.net/")
+ .unwrap()
+ .origin(),
+ Url::parse("http://127.0.0.1").unwrap().origin(),
+ ];
+ for ascii_origin in &ascii_origins {
+ assert_eq!(
+ ascii_origin.ascii_serialization(),
+ ascii_origin.unicode_serialization()
+ );
+ }
+}
+
+#[test]
+fn test_socket_addrs() {
+ use std::net::ToSocketAddrs;
+
+ let data = [
+ ("https://127.0.0.1/", "127.0.0.1", 443),
+ ("https://127.0.0.1:9742/", "127.0.0.1", 9742),
+ ("custom-protocol://127.0.0.1:9742/", "127.0.0.1", 9742),
+ ("custom-protocol://127.0.0.1/", "127.0.0.1", 9743),
+ ("https://[::1]/", "::1", 443),
+ ("https://[::1]:9742/", "::1", 9742),
+ ("custom-protocol://[::1]:9742/", "::1", 9742),
+ ("custom-protocol://[::1]/", "::1", 9743),
+ ("https://localhost/", "localhost", 443),
+ ("https://localhost:9742/", "localhost", 9742),
+ ("custom-protocol://localhost:9742/", "localhost", 9742),
+ ("custom-protocol://localhost/", "localhost", 9743),
+ ];
+
+ for (url_string, host, port) in &data {
+ let url = url::Url::parse(url_string).unwrap();
+ let addrs = url
+ .socket_addrs(|| match url.scheme() {
+ "custom-protocol" => Some(9743),
+ _ => None,
+ })
+ .unwrap();
+ assert_eq!(
+ Some(addrs[0]),
+ (*host, *port).to_socket_addrs().unwrap().next()
+ );
+ }
+}
+
+#[test]
+fn test_no_base_url() {
+ let mut no_base_url = Url::parse("mailto:test@example.net").unwrap();
+
+ assert!(no_base_url.cannot_be_a_base());
+ assert!(no_base_url.path_segments().is_none());
+ assert!(no_base_url.path_segments_mut().is_err());
+ assert!(no_base_url.set_host(Some("foo")).is_err());
+ assert!(no_base_url
+ .set_ip_host("127.0.0.1".parse().unwrap())
+ .is_err());
+
+ no_base_url.set_path("/foo");
+ assert_eq!(no_base_url.path(), "%2Ffoo");
+}
+
+#[test]
+fn test_domain() {
+ let url = Url::parse("https://127.0.0.1/").unwrap();
+ assert_eq!(url.domain(), None);
+
+ let url = Url::parse("mailto:test@example.net").unwrap();
+ assert_eq!(url.domain(), None);
+
+ let url = Url::parse("https://example.com/").unwrap();
+ assert_eq!(url.domain(), Some("example.com"));
+}
+
+#[test]
+fn test_query() {
+ let url = Url::parse("https://example.com/products?page=2#fragment").unwrap();
+ assert_eq!(url.query(), Some("page=2"));
+ assert_eq!(
+ url.query_pairs().next(),
+ Some((Cow::Borrowed("page"), Cow::Borrowed("2")))
+ );
+
+ let url = Url::parse("https://example.com/products").unwrap();
+ assert!(url.query().is_none());
+ assert_eq!(url.query_pairs().count(), 0);
+
+ let url = Url::parse("https://example.com/?country=espaΓ±ol").unwrap();
+ assert_eq!(url.query(), Some("country=espa%C3%B1ol"));
+ assert_eq!(
+ url.query_pairs().next(),
+ Some((Cow::Borrowed("country"), Cow::Borrowed("espaΓ±ol")))
+ );
+
+ let url = Url::parse("https://example.com/products?page=2&sort=desc").unwrap();
+ assert_eq!(url.query(), Some("page=2&sort=desc"));
+ let mut pairs = url.query_pairs();
+ assert_eq!(pairs.count(), 2);
+ assert_eq!(
+ pairs.next(),
+ Some((Cow::Borrowed("page"), Cow::Borrowed("2")))
+ );
+ assert_eq!(
+ pairs.next(),
+ Some((Cow::Borrowed("sort"), Cow::Borrowed("desc")))
+ );
+}
+
+#[test]
+fn test_fragment() {
+ let url = Url::parse("https://example.com/#fragment").unwrap();
+ assert_eq!(url.fragment(), Some("fragment"));
+
+ let url = Url::parse("https://example.com/").unwrap();
+ assert_eq!(url.fragment(), None);
+}
+
+#[test]
+fn test_set_ip_host() {
+ let mut url = Url::parse("http://example.com").unwrap();
+
+ url.set_ip_host("127.0.0.1".parse().unwrap()).unwrap();
+ assert_eq!(url.host_str(), Some("127.0.0.1"));
+
+ url.set_ip_host("::1".parse().unwrap()).unwrap();
+ assert_eq!(url.host_str(), Some("[::1]"));
+}
+
+#[test]
+fn test_set_href() {
+ use url::quirks::set_href;
+
+ let mut url = Url::parse("https://existing.url").unwrap();
+
+ assert!(set_href(&mut url, "mal//formed").is_err());
+
+ assert!(set_href(
+ &mut url,
+ "https://user:pass@domain.com:9742/path/file.ext?key=val&key2=val2#fragment"
+ )
+ .is_ok());
+ assert_eq!(
+ url,
+ Url::parse("https://user:pass@domain.com:9742/path/file.ext?key=val&key2=val2#fragment")
+ .unwrap()
+ );
+}
+
+#[test]
+fn test_domain_encoding_quirks() {
+ use url::quirks::{domain_to_ascii, domain_to_unicode};
+
+ let data = [
+ ("http://example.com", "", ""),
+ ("πŸ˜….πŸ™‚", "xn--j28h.xn--938h", "πŸ˜….πŸ™‚"),
+ ("example.com", "example.com", "example.com"),
+ ("mailto:test@example.net", "", ""),
+ ];
+
+ for url in &data {
+ assert_eq!(domain_to_ascii(url.0), url.1);
+ assert_eq!(domain_to_unicode(url.0), url.2);
+ }
+}
+
+#[test]
fn test_windows_unc_path() {
if !cfg!(windows) {
return;
@@ -582,6 +785,38 @@ fn test_syntax_violation_callback_lifetimes() {
}
#[test]
+fn test_syntax_violation_callback_types() {
+ use url::SyntaxViolation::*;
+
+ let data = [
+ ("http://mozilla.org/\\foo", Backslash, "backslash"),
+ (" http://mozilla.org", C0SpaceIgnored, "leading or trailing control or space character are ignored in URLs"),
+ ("http://user:pass@mozilla.org", EmbeddedCredentials, "embedding authentication information (username or password) in an URL is not recommended"),
+ ("http:///mozilla.org", ExpectedDoubleSlash, "expected //"),
+ ("file:/foo.txt", ExpectedFileDoubleSlash, "expected // after file:"),
+ ("file://mozilla.org/c:/file.txt", FileWithHostAndWindowsDrive, "file: with host and Windows drive letter"),
+ ("http://mozilla.org/^", NonUrlCodePoint, "non-URL code point"),
+ ("http://mozilla.org/#\00", NullInFragment, "NULL characters are ignored in URL fragment identifiers"),
+ ("http://mozilla.org/%1", PercentDecode, "expected 2 hex digits after %"),
+ ("http://mozilla.org\t/foo", TabOrNewlineIgnored, "tabs or newlines are ignored in URLs"),
+ ("http://user@:pass@mozilla.org", UnencodedAtSign, "unencoded @ sign in username or password")
+ ];
+
+ for test_case in &data {
+ let violation = Cell::new(None);
+ Url::options()
+ .syntax_violation_callback(Some(&|v| violation.set(Some(v))))
+ .parse(test_case.0)
+ .unwrap();
+
+ let v = violation.take();
+ assert_eq!(v, Some(test_case.1));
+ assert_eq!(v.unwrap().description(), test_case.2);
+ assert_eq!(v.unwrap().to_string(), test_case.2);
+ }
+}
+
+#[test]
fn test_options_reuse() {
use url::SyntaxViolation::*;
let violations = RefCell::new(Vec::new());
@@ -679,3 +914,205 @@ fn pop_if_empty_in_bounds() {
segments.pop_if_empty();
segments.pop();
}
+
+#[test]
+fn test_slicing() {
+ use url::Position::*;
+
+ #[derive(Default)]
+ struct ExpectedSlices<'a> {
+ full: &'a str,
+ scheme: &'a str,
+ username: &'a str,
+ password: &'a str,
+ host: &'a str,
+ port: &'a str,
+ path: &'a str,
+ query: &'a str,
+ fragment: &'a str,
+ }
+
+ let data = [
+ ExpectedSlices {
+ full: "https://user:pass@domain.com:9742/path/file.ext?key=val&key2=val2#fragment",
+ scheme: "https",
+ username: "user",
+ password: "pass",
+ host: "domain.com",
+ port: "9742",
+ path: "/path/file.ext",
+ query: "key=val&key2=val2",
+ fragment: "fragment",
+ },
+ ExpectedSlices {
+ full: "https://domain.com:9742/path/file.ext#fragment",
+ scheme: "https",
+ host: "domain.com",
+ port: "9742",
+ path: "/path/file.ext",
+ fragment: "fragment",
+ ..Default::default()
+ },
+ ExpectedSlices {
+ full: "https://domain.com:9742/path/file.ext",
+ scheme: "https",
+ host: "domain.com",
+ port: "9742",
+ path: "/path/file.ext",
+ ..Default::default()
+ },
+ ExpectedSlices {
+ full: "blob:blob-info",
+ scheme: "blob",
+ path: "blob-info",
+ ..Default::default()
+ },
+ ];
+
+ for expected_slices in &data {
+ let url = Url::parse(expected_slices.full).unwrap();
+ assert_eq!(&url[..], expected_slices.full);
+ assert_eq!(&url[BeforeScheme..AfterScheme], expected_slices.scheme);
+ assert_eq!(
+ &url[BeforeUsername..AfterUsername],
+ expected_slices.username
+ );
+ assert_eq!(
+ &url[BeforePassword..AfterPassword],
+ expected_slices.password
+ );
+ assert_eq!(&url[BeforeHost..AfterHost], expected_slices.host);
+ assert_eq!(&url[BeforePort..AfterPort], expected_slices.port);
+ assert_eq!(&url[BeforePath..AfterPath], expected_slices.path);
+ assert_eq!(&url[BeforeQuery..AfterQuery], expected_slices.query);
+ assert_eq!(
+ &url[BeforeFragment..AfterFragment],
+ expected_slices.fragment
+ );
+ assert_eq!(&url[..AfterFragment], expected_slices.full);
+ }
+}
+
+#[test]
+fn test_make_relative() {
+ let tests = [
+ (
+ "http://127.0.0.1:8080/test",
+ "http://127.0.0.1:8080/test",
+ "",
+ ),
+ (
+ "http://127.0.0.1:8080/test",
+ "http://127.0.0.1:8080/test/",
+ "test/",
+ ),
+ (
+ "http://127.0.0.1:8080/test/",
+ "http://127.0.0.1:8080/test",
+ "../test",
+ ),
+ (
+ "http://127.0.0.1:8080/",
+ "http://127.0.0.1:8080/?foo=bar#123",
+ "?foo=bar#123",
+ ),
+ (
+ "http://127.0.0.1:8080/",
+ "http://127.0.0.1:8080/test/video",
+ "test/video",
+ ),
+ (
+ "http://127.0.0.1:8080/test",
+ "http://127.0.0.1:8080/test/video",
+ "test/video",
+ ),
+ (
+ "http://127.0.0.1:8080/test/",
+ "http://127.0.0.1:8080/test/video",
+ "video",
+ ),
+ (
+ "http://127.0.0.1:8080/test",
+ "http://127.0.0.1:8080/test2/video",
+ "test2/video",
+ ),
+ (
+ "http://127.0.0.1:8080/test/",
+ "http://127.0.0.1:8080/test2/video",
+ "../test2/video",
+ ),
+ (
+ "http://127.0.0.1:8080/test/bla",
+ "http://127.0.0.1:8080/test2/video",
+ "../test2/video",
+ ),
+ (
+ "http://127.0.0.1:8080/test/bla/",
+ "http://127.0.0.1:8080/test2/video",
+ "../../test2/video",
+ ),
+ (
+ "http://127.0.0.1:8080/test/?foo=bar#123",
+ "http://127.0.0.1:8080/test/video",
+ "video",
+ ),
+ (
+ "http://127.0.0.1:8080/test/",
+ "http://127.0.0.1:8080/test/video?baz=meh#456",
+ "video?baz=meh#456",
+ ),
+ (
+ "http://127.0.0.1:8080/test",
+ "http://127.0.0.1:8080/test?baz=meh#456",
+ "?baz=meh#456",
+ ),
+ (
+ "http://127.0.0.1:8080/test/",
+ "http://127.0.0.1:8080/test?baz=meh#456",
+ "../test?baz=meh#456",
+ ),
+ (
+ "http://127.0.0.1:8080/test/",
+ "http://127.0.0.1:8080/test/?baz=meh#456",
+ "?baz=meh#456",
+ ),
+ (
+ "http://127.0.0.1:8080/test/?foo=bar#123",
+ "http://127.0.0.1:8080/test/video?baz=meh#456",
+ "video?baz=meh#456",
+ ),
+ ];
+
+ for (base, uri, relative) in &tests {
+ let base_uri = url::Url::parse(base).unwrap();
+ let relative_uri = url::Url::parse(uri).unwrap();
+ let make_relative = base_uri.make_relative(&relative_uri).unwrap();
+ assert_eq!(
+ make_relative, *relative,
+ "base: {}, uri: {}, relative: {}",
+ base, uri, relative
+ );
+ assert_eq!(
+ base_uri.join(&relative).unwrap().as_str(),
+ *uri,
+ "base: {}, uri: {}, relative: {}",
+ base,
+ uri,
+ relative
+ );
+ }
+
+ let error_tests = [
+ ("http://127.0.0.1:8080/", "https://127.0.0.1:8080/test/"),
+ ("http://127.0.0.1:8080/", "http://127.0.0.1:8081/test/"),
+ ("http://127.0.0.1:8080/", "http://127.0.0.2:8080/test/"),
+ ("mailto:a@example.com", "mailto:b@example.com"),
+ ];
+
+ for (base, uri) in &error_tests {
+ let base_uri = url::Url::parse(base).unwrap();
+ let relative_uri = url::Url::parse(uri).unwrap();
+ let make_relative = base_uri.make_relative(&relative_uri);
+ assert_eq!(make_relative, None, "base: {}, uri: {}", base, uri);
+ }
+}