tests.rs 9.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261
  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. use std::char;
  9. use std::num::from_str_radix;
  10. use std::old_path;
  11. use super::{UrlParser, Url, SchemeData, RelativeSchemeData, Host};
  12. #[test]
  13. fn url_parsing() {
  14. for test in parse_test_data(include_str!("urltestdata.txt")).into_iter() {
  15. let Test {
  16. input,
  17. base,
  18. scheme: expected_scheme,
  19. username: expected_username,
  20. password: expected_password,
  21. host: expected_host,
  22. port: expected_port,
  23. path: expected_path,
  24. query: expected_query,
  25. fragment: expected_fragment,
  26. expected_failure,
  27. } = test;
  28. let base = match Url::parse(base.as_slice()) {
  29. Ok(base) => base,
  30. Err(message) => panic!("Error parsing base {}: {}", base, message)
  31. };
  32. let url = UrlParser::new().base_url(&base).parse(input.as_slice());
  33. if expected_scheme.is_none() {
  34. if url.is_ok() && !expected_failure {
  35. panic!("Expected a parse error for URL {}", input);
  36. }
  37. continue
  38. }
  39. let Url { scheme, scheme_data, query, fragment, .. } = match url {
  40. Ok(url) => url,
  41. Err(message) => {
  42. if expected_failure {
  43. continue
  44. } else {
  45. panic!("Error parsing URL {}: {}", input, message)
  46. }
  47. }
  48. };
  49. macro_rules! assert_eq {
  50. ($a: expr, $b: expr) => {
  51. {
  52. let a = $a;
  53. let b = $b;
  54. if a != b {
  55. if expected_failure {
  56. continue
  57. } else {
  58. panic!("{:?} != {:?}", a, b)
  59. }
  60. }
  61. }
  62. }
  63. }
  64. assert_eq!(Some(scheme), expected_scheme);
  65. match scheme_data {
  66. SchemeData::Relative(RelativeSchemeData {
  67. username, password, host, port, default_port: _, path,
  68. }) => {
  69. assert_eq!(username, expected_username);
  70. assert_eq!(password, expected_password);
  71. let host = host.serialize();
  72. assert_eq!(host, expected_host);
  73. assert_eq!(port, expected_port);
  74. assert_eq!(Some(format!("/{}", path.connect("/"))), expected_path);
  75. },
  76. SchemeData::NonRelative(scheme_data) => {
  77. assert_eq!(Some(scheme_data), expected_path);
  78. assert_eq!(String::new(), expected_username);
  79. assert_eq!(None, expected_password);
  80. assert_eq!(String::new(), expected_host);
  81. assert_eq!(None, expected_port);
  82. },
  83. }
  84. fn opt_prepend(prefix: &str, opt_s: Option<String>) -> Option<String> {
  85. opt_s.map(|s| format!("{}{}", prefix, s))
  86. }
  87. assert_eq!(opt_prepend("?", query), expected_query);
  88. assert_eq!(opt_prepend("#", fragment), expected_fragment);
  89. assert!(!expected_failure, "Unexpected success for {}", input);
  90. }
  91. }
  92. struct Test {
  93. input: String,
  94. base: String,
  95. scheme: Option<String>,
  96. username: String,
  97. password: Option<String>,
  98. host: String,
  99. port: Option<u16>,
  100. path: Option<String>,
  101. query: Option<String>,
  102. fragment: Option<String>,
  103. expected_failure: bool,
  104. }
  105. fn parse_test_data(input: &str) -> Vec<Test> {
  106. let mut tests: Vec<Test> = Vec::new();
  107. for line in input.lines() {
  108. if line == "" || line.starts_with("#") {
  109. continue
  110. }
  111. let mut pieces = line.split(' ').collect::<Vec<&str>>();
  112. let expected_failure = pieces[0] == "XFAIL";
  113. if expected_failure {
  114. pieces.remove(0);
  115. }
  116. let input = unescape(pieces.remove(0));
  117. let mut test = Test {
  118. input: input,
  119. base: if pieces.is_empty() || pieces[0] == "" {
  120. tests.last().unwrap().base.clone()
  121. } else {
  122. unescape(pieces.remove(0))
  123. },
  124. scheme: None,
  125. username: String::new(),
  126. password: None,
  127. host: String::new(),
  128. port: None,
  129. path: None,
  130. query: None,
  131. fragment: None,
  132. expected_failure: expected_failure,
  133. };
  134. for piece in pieces.into_iter() {
  135. if piece == "" || piece.starts_with("#") {
  136. continue
  137. }
  138. let colon = piece.find(':').unwrap();
  139. let value = unescape(&piece[colon + 1..]);
  140. match &piece[..colon] {
  141. "s" => test.scheme = Some(value),
  142. "u" => test.username = value,
  143. "pass" => test.password = Some(value),
  144. "h" => test.host = value,
  145. "port" => test.port = Some(value.parse().unwrap()),
  146. "p" => test.path = Some(value),
  147. "q" => test.query = Some(value),
  148. "f" => test.fragment = Some(value),
  149. _ => panic!("Invalid token")
  150. }
  151. }
  152. tests.push(test)
  153. }
  154. tests
  155. }
  156. fn unescape(input: &str) -> String {
  157. let mut output = String::new();
  158. let mut chars = input.chars();
  159. loop {
  160. match chars.next() {
  161. None => return output,
  162. Some(c) => output.push(
  163. if c == '\\' {
  164. match chars.next().unwrap() {
  165. '\\' => '\\',
  166. 'n' => '\n',
  167. 'r' => '\r',
  168. 's' => ' ',
  169. 't' => '\t',
  170. 'f' => '\x0C',
  171. 'u' => {
  172. let mut hex = String::new();
  173. hex.push(chars.next().unwrap());
  174. hex.push(chars.next().unwrap());
  175. hex.push(chars.next().unwrap());
  176. hex.push(chars.next().unwrap());
  177. from_str_radix(hex.as_slice(), 16).ok()
  178. .and_then(char::from_u32).unwrap()
  179. }
  180. _ => panic!("Invalid test data input"),
  181. }
  182. } else {
  183. c
  184. }
  185. )
  186. }
  187. }
  188. }
  189. #[test]
  190. fn file_paths() {
  191. assert_eq!(Url::from_file_path(&old_path::posix::Path::new("relative")), Err(()));
  192. assert_eq!(Url::from_file_path(&old_path::posix::Path::new("../relative")), Err(()));
  193. assert_eq!(Url::from_file_path(&old_path::windows::Path::new("relative")), Err(()));
  194. assert_eq!(Url::from_file_path(&old_path::windows::Path::new(r"..\relative")), Err(()));
  195. assert_eq!(Url::from_file_path(&old_path::windows::Path::new(r"\drive-relative")), Err(()));
  196. assert_eq!(Url::from_file_path(&old_path::windows::Path::new(r"\\ucn\")), Err(()));
  197. let mut url = Url::from_file_path(&old_path::posix::Path::new("/foo/bar")).unwrap();
  198. assert_eq!(url.host(), Some(&Host::Domain("".to_string())));
  199. assert_eq!(url.path(), Some(["foo".to_string(), "bar".to_string()].as_slice()));
  200. assert!(url.to_file_path() == Ok(old_path::posix::Path::new("/foo/bar")));
  201. url.path_mut().unwrap()[1] = "ba\0r".to_string();
  202. assert!(url.to_file_path::<old_path::posix::Path>() == Err(()));
  203. url.path_mut().unwrap()[1] = "ba%00r".to_string();
  204. assert!(url.to_file_path::<old_path::posix::Path>() == Err(()));
  205. // Invalid UTF-8
  206. url.path_mut().unwrap()[1] = "ba%80r".to_string();
  207. assert!(url.to_file_path() == Ok(old_path::posix::Path::new(
  208. /* note: byte string, invalid UTF-8 */ b"/foo/ba\x80r")));
  209. let mut url = Url::from_file_path(&old_path::windows::Path::new(r"C:\foo\bar")).unwrap();
  210. assert_eq!(url.host(), Some(&Host::Domain("".to_string())));
  211. assert_eq!(url.path(), Some(["C:".to_string(), "foo".to_string(), "bar".to_string()].as_slice()));
  212. assert!(url.to_file_path::<old_path::windows::Path>()
  213. == Ok(old_path::windows::Path::new(r"C:\foo\bar")));
  214. url.path_mut().unwrap()[2] = "ba\0r".to_string();
  215. assert!(url.to_file_path::<old_path::windows::Path>() == Err(()));
  216. url.path_mut().unwrap()[2] = "ba%00r".to_string();
  217. assert!(url.to_file_path::<old_path::windows::Path>() == Err(()));
  218. // Invalid UTF-8
  219. url.path_mut().unwrap()[2] = "ba%80r".to_string();
  220. assert!(url.to_file_path::<old_path::windows::Path>() == Err(()));
  221. }
  222. #[test]
  223. fn directory_paths() {
  224. assert_eq!(Url::from_directory_path(&old_path::posix::Path::new("relative")), Err(()));
  225. assert_eq!(Url::from_directory_path(&old_path::posix::Path::new("../relative")), Err(()));
  226. assert_eq!(Url::from_directory_path(&old_path::windows::Path::new("relative")), Err(()));
  227. assert_eq!(Url::from_directory_path(&old_path::windows::Path::new(r"..\relative")), Err(()));
  228. assert_eq!(Url::from_directory_path(&old_path::windows::Path::new(r"\drive-relative")), Err(()));
  229. assert_eq!(Url::from_directory_path(&old_path::windows::Path::new(r"\\ucn\")), Err(()));
  230. let url = Url::from_directory_path(&old_path::posix::Path::new("/foo/bar")).unwrap();
  231. assert_eq!(url.host(), Some(&Host::Domain("".to_string())));
  232. assert_eq!(url.path(), Some(["foo".to_string(), "bar".to_string(), "".to_string()].as_slice()));
  233. let url = Url::from_directory_path(&old_path::windows::Path::new(r"C:\foo\bar")).unwrap();
  234. assert_eq!(url.host(), Some(&Host::Domain("".to_string())));
  235. assert_eq!(url.path(), Some([
  236. "C:".to_string(), "foo".to_string(), "bar".to_string(), "".to_string()].as_slice()));
  237. }