// Copyright 2013-2014 Simon Sapin. // // Licensed under the Apache License, Version 2.0 or the MIT license // , at your // option. This file may not be copied, modified, or distributed // except according to those terms. //! Tests copied form https://github.com/w3c/web-platform-tests/blob/master/url/ extern crate test; extern crate url; use std::char; use url::Url; fn run_one(entry: Entry) { let Entry { input, base, scheme: expected_scheme, username: expected_username, password: expected_password, host: expected_host, port: expected_port, path: expected_path, query: expected_query, fragment: expected_fragment, expected_failure, } = entry; let base = match Url::parse(&base) { Ok(base) => base, Err(message) => panic!("Error parsing base {}: {}", base, message) }; let expecting_err = expected_scheme.is_none() ^ expected_failure; let url = match base.join(&input) { Ok(url) => url, Err(reason) => { assert!(expecting_err, "Error parsing URL {}: {}", input, reason); return } }; assert!(!expecting_err, "Expected a parse error for URL {}", input); macro_rules! assert_eq { ($a: expr, $b: expr) => { { let a = $a; let b = $b; if a != b { if expected_failure { return } else { panic!("{:?} != {:?} for {:?}", a, b, url) } } } } } assert_eq!(Some(url.scheme().to_owned()), expected_scheme); assert_eq!(url.username(), expected_username); assert_eq!(url.password().map(|s| s.to_owned()), expected_password); assert_eq!(url.host_str().unwrap_or("").to_owned(), expected_host); assert_eq!(url.port(), expected_port); assert_eq!(Some(url.path().to_owned()), expected_path); assert_eq!(url.query().map(|s| format!("?{}", s)), expected_query); assert_eq!(url.fragment().map(|s| format!("#{}", s)), expected_fragment); assert!(!expected_failure, "Unexpected success for {}", input); } struct Entry { input: String, base: String, scheme: Option, username: String, password: Option, host: String, port: Option, path: Option, query: Option, fragment: Option, expected_failure: bool, } fn parse_test_data(input: &str) -> Vec { let mut tests: Vec = Vec::new(); for line in input.lines() { if line == "" || line.starts_with("#") { continue } let mut pieces = line.split(' ').collect::>(); let expected_failure = pieces[0] == "XFAIL"; if expected_failure { pieces.remove(0); } let input = unescape(pieces.remove(0)); let mut test = Entry { input: input, base: if pieces.is_empty() || pieces[0] == "" { tests.last().unwrap().base.clone() } else { unescape(pieces.remove(0)) }, scheme: None, username: String::new(), password: None, host: String::new(), port: None, path: None, query: None, fragment: None, expected_failure: expected_failure, }; for piece in pieces { if piece == "" || piece.starts_with("#") { continue } let colon = piece.find(':').unwrap(); let value = unescape(&piece[colon + 1..]); match &piece[..colon] { "s" => test.scheme = Some(value), "u" => test.username = value, "pass" => test.password = Some(value), "h" => test.host = value, "port" => test.port = Some(value.parse().unwrap()), "p" => test.path = Some(value), "q" => test.query = Some(value), "f" => test.fragment = Some(value), _ => panic!("Invalid token") } } tests.push(test) } tests } fn unescape(input: &str) -> String { let mut output = String::new(); let mut chars = input.chars(); loop { match chars.next() { None => return output, Some(c) => output.push( if c == '\\' { match chars.next().unwrap() { '\\' => '\\', 'n' => '\n', 'r' => '\r', 's' => ' ', 't' => '\t', 'f' => '\x0C', 'u' => { char::from_u32(((( chars.next().unwrap().to_digit(16).unwrap()) * 16 + chars.next().unwrap().to_digit(16).unwrap()) * 16 + chars.next().unwrap().to_digit(16).unwrap()) * 16 + chars.next().unwrap().to_digit(16).unwrap()).unwrap() } _ => panic!("Invalid test data input"), } } else { c } ) } } } fn make_test(entry: Entry) -> test::TestDescAndFn { test::TestDescAndFn { desc: test::TestDesc { name: test::DynTestName(format!("{:?} base {:?}", entry.input, entry.base)), ignore: false, should_panic: test::ShouldPanic::No, }, testfn: test::TestFn::dyn_test_fn(move || run_one(entry)), } } fn main() { test::test_main( &std::env::args().collect::>(), parse_test_data(include_str!("urltestdata.txt")).into_iter().map(make_test).collect(), ) }