wpt.rs 7.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223
  1. // Copyright 2013-2014 Simon Sapin.
  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. //! Tests copied form https://github.com/w3c/web-platform-tests/blob/master/url/
  9. extern crate test;
  10. extern crate url;
  11. use std::char;
  12. use url::{RelativeSchemeData, SchemeData, Url};
  13. fn run_one(entry: Entry) {
  14. // FIXME: Don’t re-indent to make merging the 1.0 branch easier.
  15. {
  16. let Entry {
  17. input,
  18. base,
  19. scheme: expected_scheme,
  20. username: expected_username,
  21. password: expected_password,
  22. host: expected_host,
  23. port: expected_port,
  24. path: expected_path,
  25. query: expected_query,
  26. fragment: expected_fragment,
  27. expected_failure,
  28. } = entry;
  29. let base = match Url::parse(&base) {
  30. Ok(base) => base,
  31. Err(message) => panic!("Error parsing base {}: {}", base, message)
  32. };
  33. let url = base.join(&input);
  34. if expected_scheme.is_none() {
  35. if url.is_ok() && !expected_failure {
  36. panic!("Expected a parse error for URL {}", input);
  37. }
  38. return
  39. }
  40. let Url { scheme, scheme_data, query, fragment, .. } = match url {
  41. Ok(url) => url,
  42. Err(message) => {
  43. if expected_failure {
  44. return
  45. } else {
  46. panic!("Error parsing URL {}: {}", input, message)
  47. }
  48. }
  49. };
  50. macro_rules! assert_eq {
  51. ($a: expr, $b: expr) => {
  52. {
  53. let a = $a;
  54. let b = $b;
  55. if a != b {
  56. if expected_failure {
  57. return
  58. } else {
  59. panic!("{:?} != {:?}", a, b)
  60. }
  61. }
  62. }
  63. }
  64. }
  65. assert_eq!(Some(scheme), expected_scheme);
  66. match scheme_data {
  67. SchemeData::Relative(RelativeSchemeData {
  68. username, password, host, port, default_port: _, path,
  69. }) => {
  70. assert_eq!(username, expected_username);
  71. assert_eq!(password, expected_password);
  72. let host = host.serialize();
  73. assert_eq!(host, expected_host);
  74. assert_eq!(port, expected_port);
  75. assert_eq!(Some(format!("/{}", str_join(&path, "/"))), expected_path);
  76. },
  77. SchemeData::NonRelative(scheme_data) => {
  78. assert_eq!(Some(scheme_data), expected_path);
  79. assert_eq!(String::new(), expected_username);
  80. assert_eq!(None, expected_password);
  81. assert_eq!(String::new(), expected_host);
  82. assert_eq!(None, expected_port);
  83. },
  84. }
  85. fn opt_prepend(prefix: &str, opt_s: Option<String>) -> Option<String> {
  86. opt_s.map(|s| format!("{}{}", prefix, s))
  87. }
  88. assert_eq!(opt_prepend("?", query), expected_query);
  89. assert_eq!(opt_prepend("#", fragment), expected_fragment);
  90. assert!(!expected_failure, "Unexpected success for {}", input);
  91. }
  92. }
  93. // FIMXE: Remove this when &[&str]::join (the new name) lands in the stable channel.
  94. #[allow(deprecated)]
  95. fn str_join<T: ::std::borrow::Borrow<str>>(pieces: &[T], separator: &str) -> String {
  96. pieces.connect(separator)
  97. }
  98. struct Entry {
  99. input: String,
  100. base: String,
  101. scheme: Option<String>,
  102. username: String,
  103. password: Option<String>,
  104. host: String,
  105. port: Option<u16>,
  106. path: Option<String>,
  107. query: Option<String>,
  108. fragment: Option<String>,
  109. expected_failure: bool,
  110. }
  111. fn parse_test_data(input: &str) -> Vec<Entry> {
  112. let mut tests: Vec<Entry> = Vec::new();
  113. for line in input.lines() {
  114. if line == "" || line.starts_with("#") {
  115. continue
  116. }
  117. let mut pieces = line.split(' ').collect::<Vec<&str>>();
  118. let expected_failure = pieces[0] == "XFAIL";
  119. if expected_failure {
  120. pieces.remove(0);
  121. }
  122. let input = unescape(pieces.remove(0));
  123. let mut test = Entry {
  124. input: input,
  125. base: if pieces.is_empty() || pieces[0] == "" {
  126. tests.last().unwrap().base.clone()
  127. } else {
  128. unescape(pieces.remove(0))
  129. },
  130. scheme: None,
  131. username: String::new(),
  132. password: None,
  133. host: String::new(),
  134. port: None,
  135. path: None,
  136. query: None,
  137. fragment: None,
  138. expected_failure: expected_failure,
  139. };
  140. for piece in pieces {
  141. if piece == "" || piece.starts_with("#") {
  142. continue
  143. }
  144. let colon = piece.find(':').unwrap();
  145. let value = unescape(&piece[colon + 1..]);
  146. match &piece[..colon] {
  147. "s" => test.scheme = Some(value),
  148. "u" => test.username = value,
  149. "pass" => test.password = Some(value),
  150. "h" => test.host = value,
  151. "port" => test.port = Some(value.parse().unwrap()),
  152. "p" => test.path = Some(value),
  153. "q" => test.query = Some(value),
  154. "f" => test.fragment = Some(value),
  155. _ => panic!("Invalid token")
  156. }
  157. }
  158. tests.push(test)
  159. }
  160. tests
  161. }
  162. fn unescape(input: &str) -> String {
  163. let mut output = String::new();
  164. let mut chars = input.chars();
  165. loop {
  166. match chars.next() {
  167. None => return output,
  168. Some(c) => output.push(
  169. if c == '\\' {
  170. match chars.next().unwrap() {
  171. '\\' => '\\',
  172. 'n' => '\n',
  173. 'r' => '\r',
  174. 's' => ' ',
  175. 't' => '\t',
  176. 'f' => '\x0C',
  177. 'u' => {
  178. char::from_u32((((
  179. chars.next().unwrap().to_digit(16).unwrap()) * 16 +
  180. chars.next().unwrap().to_digit(16).unwrap()) * 16 +
  181. chars.next().unwrap().to_digit(16).unwrap()) * 16 +
  182. chars.next().unwrap().to_digit(16).unwrap()).unwrap()
  183. }
  184. _ => panic!("Invalid test data input"),
  185. }
  186. } else {
  187. c
  188. }
  189. )
  190. }
  191. }
  192. }
  193. fn make_test(entry: Entry) -> test::TestDescAndFn {
  194. test::TestDescAndFn {
  195. desc: test::TestDesc {
  196. name: test::DynTestName(format!("{:?} base {:?}", entry.input, entry.base)),
  197. ignore: false,
  198. should_panic: test::ShouldPanic::No,
  199. },
  200. testfn: test::TestFn::dyn_test_fn(move || run_one(entry)),
  201. }
  202. }
  203. fn main() {
  204. test::test_main(
  205. &std::env::args().collect::<Vec<_>>(),
  206. parse_test_data(include_str!("urltestdata.txt")).into_iter().map(make_test).collect(),
  207. )
  208. }