diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-05-30 18:31:44 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-05-30 18:31:44 +0000 |
commit | c23a457e72abe608715ac76f076f47dc42af07a5 (patch) | |
tree | 2772049aaf84b5c9d0ed12ec8d86812f7a7904b6 /vendor/url/tests/wpt.rs | |
parent | Releasing progress-linux version 1.73.0+dfsg1-1~progress7.99u1. (diff) | |
download | rustc-c23a457e72abe608715ac76f076f47dc42af07a5.tar.xz rustc-c23a457e72abe608715ac76f076f47dc42af07a5.zip |
Merging upstream version 1.74.1+dfsg1.
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'vendor/url/tests/wpt.rs')
-rw-r--r-- | vendor/url/tests/wpt.rs | 477 |
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(()) +} |