summaryrefslogtreecommitdiffstats
path: root/vendor/url/tests/wpt.rs
diff options
context:
space:
mode:
Diffstat (limited to 'vendor/url/tests/wpt.rs')
-rw-r--r--vendor/url/tests/wpt.rs477
1 files changed, 477 insertions, 0 deletions
diff --git a/vendor/url/tests/wpt.rs b/vendor/url/tests/wpt.rs
new file mode 100644
index 000000000..701044d67
--- /dev/null
+++ b/vendor/url/tests/wpt.rs
@@ -0,0 +1,477 @@
+// Copyright 2013-2014 The rust-url developers.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+//! Data-driven tests imported from web-platform-tests
+
+use std::collections::HashMap;
+use std::fmt::Write;
+use std::panic;
+
+use serde_json::Value;
+use url::Url;
+
+#[derive(Debug, serde::Deserialize)]
+struct UrlTest {
+ input: String,
+ base: Option<String>,
+ #[serde(flatten)]
+ result: UrlTestResult,
+}
+
+#[derive(Debug, serde::Deserialize)]
+#[serde(untagged)]
+#[allow(clippy::large_enum_variant)]
+enum UrlTestResult {
+ Ok(UrlTestOk),
+ Fail(UrlTestFail),
+}
+
+#[derive(Debug, serde::Deserialize)]
+struct UrlTestOk {
+ href: String,
+ protocol: String,
+ username: String,
+ password: String,
+ host: String,
+ hostname: String,
+ port: String,
+ pathname: String,
+ search: String,
+ hash: String,
+}
+
+#[derive(Debug, serde::Deserialize)]
+struct UrlTestFail {
+ failure: bool,
+}
+
+#[derive(Debug, serde::Deserialize)]
+struct SetterTest {
+ href: String,
+ new_value: String,
+ expected: SetterTestExpected,
+}
+
+#[derive(Debug, serde::Deserialize)]
+struct SetterTestExpected {
+ href: Option<String>,
+ protocol: Option<String>,
+ username: Option<String>,
+ password: Option<String>,
+ host: Option<String>,
+ hostname: Option<String>,
+ port: Option<String>,
+ pathname: Option<String>,
+ search: Option<String>,
+ hash: Option<String>,
+}
+
+fn main() {
+ let mut filter = None;
+ let mut args = std::env::args().skip(1);
+ while filter.is_none() {
+ if let Some(arg) = args.next() {
+ if arg == "--test-threads" {
+ args.next();
+ continue;
+ }
+ filter = Some(arg);
+ } else {
+ break;
+ }
+ }
+
+ let mut expected_failures = include_str!("expected_failures.txt")
+ .lines()
+ .collect::<Vec<_>>();
+
+ let mut errors = vec![];
+
+ // Copied from https://github.com/web-platform-tests/wpt/blob/master/url/
+ let url_json: Vec<Value> = serde_json::from_str(include_str!("urltestdata.json"))
+ .expect("JSON parse error in urltestdata.json");
+ let url_tests = url_json
+ .into_iter()
+ .filter(|val| val.is_object())
+ .map(|val| serde_json::from_value::<UrlTest>(val).expect("parsing failed"))
+ .collect::<Vec<_>>();
+
+ let setter_json: HashMap<String, Value> =
+ serde_json::from_str(include_str!("setters_tests.json"))
+ .expect("JSON parse error in setters_tests.json");
+ let setter_tests = setter_json
+ .into_iter()
+ .filter(|(k, _)| k != "comment")
+ .map(|(k, v)| {
+ let test = serde_json::from_value::<Vec<SetterTest>>(v).expect("parsing failed");
+ (k, test)
+ })
+ .collect::<HashMap<_, _>>();
+
+ for url_test in url_tests {
+ let mut name = format!("<{}>", url_test.input.escape_default());
+ if let Some(base) = &url_test.base {
+ write!(&mut name, " against <{}>", base.escape_default()).unwrap();
+ }
+ if should_skip(&name, filter.as_deref()) {
+ continue;
+ }
+ print!("{} ... ", name);
+
+ let res = run_url_test(url_test);
+ report(name, res, &mut errors, &mut expected_failures);
+ }
+
+ for (kind, tests) in setter_tests {
+ for test in tests {
+ let name = format!(
+ "<{}> set {} to <{}>",
+ test.href.escape_default(),
+ kind,
+ test.new_value.escape_default()
+ );
+ if should_skip(&name, filter.as_deref()) {
+ continue;
+ }
+
+ print!("{} ... ", name);
+
+ let res = run_setter_test(&kind, test);
+ report(name, res, &mut errors, &mut expected_failures);
+ }
+ }
+
+ println!();
+ println!("====================");
+ println!();
+
+ if !errors.is_empty() {
+ println!("errors:");
+ println!();
+
+ for (name, err) in errors {
+ println!(" name: {}", name);
+ println!(" err: {}", err);
+ println!();
+ }
+
+ std::process::exit(1);
+ } else {
+ println!("all tests passed");
+ }
+
+ if !expected_failures.is_empty() && filter.is_none() {
+ println!();
+ println!("====================");
+ println!();
+ println!("tests were expected to fail but did not run:");
+ println!();
+
+ for name in expected_failures {
+ println!(" {}", name);
+ }
+
+ println!();
+ println!("if these tests were removed, update expected_failures.txt");
+ println!();
+
+ std::process::exit(1);
+ }
+}
+
+fn should_skip(name: &str, filter: Option<&str>) -> bool {
+ match filter {
+ Some(filter) => !name.contains(filter),
+ None => false,
+ }
+}
+
+fn report(
+ name: String,
+ res: Result<(), String>,
+ errors: &mut Vec<(String, String)>,
+ expected_failures: &mut Vec<&str>,
+) {
+ let expected_failure = expected_failures.contains(&&*name);
+ expected_failures.retain(|&s| s != &*name);
+ match res {
+ Ok(()) => {
+ if expected_failure {
+ println!("🟠 (unexpected success)");
+ errors.push((name, "unexpected success".to_string()));
+ } else {
+ println!("✅");
+ }
+ }
+ Err(err) => {
+ if expected_failure {
+ println!("✅ (expected fail)");
+ } else {
+ println!("❌");
+ errors.push((name, err));
+ }
+ }
+ }
+}
+
+fn run_url_test(
+ UrlTest {
+ base,
+ input,
+ result,
+ }: UrlTest,
+) -> Result<(), String> {
+ let base = match base {
+ Some(base) => {
+ let base = panic::catch_unwind(|| Url::parse(&base))
+ .map_err(|_| "panicked while parsing base".to_string())?
+ .map_err(|e| format!("errored while parsing base: {}", e))?;
+ Some(base)
+ }
+ None => None,
+ };
+
+ let res = panic::catch_unwind(move || Url::options().base_url(base.as_ref()).parse(&input))
+ .map_err(|_| "panicked while parsing input".to_string())?
+ .map_err(|e| format!("errored while parsing input: {}", e));
+
+ match result {
+ UrlTestResult::Ok(ok) => check_url_ok(res, ok),
+ UrlTestResult::Fail(fail) => {
+ assert!(fail.failure);
+ if res.is_ok() {
+ return Err("expected failure, but parsed successfully".to_string());
+ }
+
+ Ok(())
+ }
+ }
+}
+
+fn check_url_ok(res: Result<Url, String>, ok: UrlTestOk) -> Result<(), String> {
+ let url = match res {
+ Ok(url) => url,
+ Err(err) => {
+ return Err(format!("expected success, but errored: {:?}", err));
+ }
+ };
+
+ let href = url::quirks::href(&url);
+ if href != ok.href {
+ return Err(format!("expected href {:?}, but got {:?}", ok.href, href));
+ }
+
+ let protocol = url::quirks::protocol(&url);
+ if protocol != ok.protocol {
+ return Err(format!(
+ "expected protocol {:?}, but got {:?}",
+ ok.protocol, protocol
+ ));
+ }
+
+ let username = url::quirks::username(&url);
+ if username != ok.username {
+ return Err(format!(
+ "expected username {:?}, but got {:?}",
+ ok.username, username
+ ));
+ }
+
+ let password = url::quirks::password(&url);
+ if password != ok.password {
+ return Err(format!(
+ "expected password {:?}, but got {:?}",
+ ok.password, password
+ ));
+ }
+
+ let host = url::quirks::host(&url);
+ if host != ok.host {
+ return Err(format!("expected host {:?}, but got {:?}", ok.host, host));
+ }
+
+ let hostname = url::quirks::hostname(&url);
+ if hostname != ok.hostname {
+ return Err(format!(
+ "expected hostname {:?}, but got {:?}",
+ ok.hostname, hostname
+ ));
+ }
+
+ let port = url::quirks::port(&url);
+ if port != ok.port {
+ return Err(format!("expected port {:?}, but got {:?}", ok.port, port));
+ }
+
+ let pathname = url::quirks::pathname(&url);
+ if pathname != ok.pathname {
+ return Err(format!(
+ "expected pathname {:?}, but got {:?}",
+ ok.pathname, pathname
+ ));
+ }
+
+ let search = url::quirks::search(&url);
+ if search != ok.search {
+ return Err(format!(
+ "expected search {:?}, but got {:?}",
+ ok.search, search
+ ));
+ }
+
+ let hash = url::quirks::hash(&url);
+ if hash != ok.hash {
+ return Err(format!("expected hash {:?}, but got {:?}", ok.hash, hash));
+ }
+
+ Ok(())
+}
+
+fn run_setter_test(
+ kind: &str,
+ SetterTest {
+ href,
+ new_value,
+ expected,
+ }: SetterTest,
+) -> Result<(), String> {
+ let mut url = panic::catch_unwind(|| Url::parse(&href))
+ .map_err(|_| "panicked while parsing href".to_string())?
+ .map_err(|e| format!("errored while parsing href: {}", e))?;
+
+ let url = panic::catch_unwind(move || {
+ match kind {
+ "protocol" => {
+ url::quirks::set_protocol(&mut url, &new_value).ok();
+ }
+ "username" => {
+ url::quirks::set_username(&mut url, &new_value).ok();
+ }
+ "password" => {
+ url::quirks::set_password(&mut url, &new_value).ok();
+ }
+ "host" => {
+ url::quirks::set_host(&mut url, &new_value).ok();
+ }
+ "hostname" => {
+ url::quirks::set_hostname(&mut url, &new_value).ok();
+ }
+ "port" => {
+ url::quirks::set_port(&mut url, &new_value).ok();
+ }
+ "pathname" => url::quirks::set_pathname(&mut url, &new_value),
+ "search" => url::quirks::set_search(&mut url, &new_value),
+ "hash" => url::quirks::set_hash(&mut url, &new_value),
+ _ => panic!("unknown setter kind: {:?}", kind),
+ };
+ url
+ })
+ .map_err(|_| "panicked while setting value".to_string())?;
+
+ if let Some(expected_href) = expected.href {
+ let href = url::quirks::href(&url);
+ if href != expected_href {
+ return Err(format!(
+ "expected href {:?}, but got {:?}",
+ expected_href, href
+ ));
+ }
+ }
+
+ if let Some(expected_protocol) = expected.protocol {
+ let protocol = url::quirks::protocol(&url);
+ if protocol != expected_protocol {
+ return Err(format!(
+ "expected protocol {:?}, but got {:?}",
+ expected_protocol, protocol
+ ));
+ }
+ }
+
+ if let Some(expected_username) = expected.username {
+ let username = url::quirks::username(&url);
+ if username != expected_username {
+ return Err(format!(
+ "expected username {:?}, but got {:?}",
+ expected_username, username
+ ));
+ }
+ }
+
+ if let Some(expected_password) = expected.password {
+ let password = url::quirks::password(&url);
+ if password != expected_password {
+ return Err(format!(
+ "expected password {:?}, but got {:?}",
+ expected_password, password
+ ));
+ }
+ }
+
+ if let Some(expected_host) = expected.host {
+ let host = url::quirks::host(&url);
+ if host != expected_host {
+ return Err(format!(
+ "expected host {:?}, but got {:?}",
+ expected_host, host
+ ));
+ }
+ }
+
+ if let Some(expected_hostname) = expected.hostname {
+ let hostname = url::quirks::hostname(&url);
+ if hostname != expected_hostname {
+ return Err(format!(
+ "expected hostname {:?}, but got {:?}",
+ expected_hostname, hostname
+ ));
+ }
+ }
+
+ if let Some(expected_port) = expected.port {
+ let port = url::quirks::port(&url);
+ if port != expected_port {
+ return Err(format!(
+ "expected port {:?}, but got {:?}",
+ expected_port, port
+ ));
+ }
+ }
+
+ if let Some(expected_pathname) = expected.pathname {
+ let pathname = url::quirks::pathname(&url);
+ if pathname != expected_pathname {
+ return Err(format!(
+ "expected pathname {:?}, but got {:?}",
+ expected_pathname, pathname
+ ));
+ }
+ }
+
+ if let Some(expected_search) = expected.search {
+ let search = url::quirks::search(&url);
+ if search != expected_search {
+ return Err(format!(
+ "expected search {:?}, but got {:?}",
+ expected_search, search
+ ));
+ }
+ }
+
+ if let Some(expected_hash) = expected.hash {
+ let hash = url::quirks::hash(&url);
+ if hash != expected_hash {
+ return Err(format!(
+ "expected hash {:?}, but got {:?}",
+ expected_hash, hash
+ ));
+ }
+ }
+
+ Ok(())
+}