wpt.rs 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477
  1. // Copyright 2013-2014 The rust-url developers.
  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. //! Data-driven tests imported from web-platform-tests
  9. use std::collections::HashMap;
  10. use std::fmt::Write;
  11. use std::panic;
  12. use serde_json::Value;
  13. use url::Url;
  14. #[derive(Debug, serde::Deserialize)]
  15. struct UrlTest {
  16. input: String,
  17. base: Option<String>,
  18. #[serde(flatten)]
  19. result: UrlTestResult,
  20. }
  21. #[derive(Debug, serde::Deserialize)]
  22. #[serde(untagged)]
  23. #[allow(clippy::large_enum_variant)]
  24. enum UrlTestResult {
  25. Ok(UrlTestOk),
  26. Fail(UrlTestFail),
  27. }
  28. #[derive(Debug, serde::Deserialize)]
  29. struct UrlTestOk {
  30. href: String,
  31. protocol: String,
  32. username: String,
  33. password: String,
  34. host: String,
  35. hostname: String,
  36. port: String,
  37. pathname: String,
  38. search: String,
  39. hash: String,
  40. }
  41. #[derive(Debug, serde::Deserialize)]
  42. struct UrlTestFail {
  43. failure: bool,
  44. }
  45. #[derive(Debug, serde::Deserialize)]
  46. struct SetterTest {
  47. href: String,
  48. new_value: String,
  49. expected: SetterTestExpected,
  50. }
  51. #[derive(Debug, serde::Deserialize)]
  52. struct SetterTestExpected {
  53. href: Option<String>,
  54. protocol: Option<String>,
  55. username: Option<String>,
  56. password: Option<String>,
  57. host: Option<String>,
  58. hostname: Option<String>,
  59. port: Option<String>,
  60. pathname: Option<String>,
  61. search: Option<String>,
  62. hash: Option<String>,
  63. }
  64. fn main() {
  65. let mut filter = None;
  66. let mut args = std::env::args().skip(1);
  67. while filter.is_none() {
  68. if let Some(arg) = args.next() {
  69. if arg == "--test-threads" {
  70. args.next();
  71. continue;
  72. }
  73. filter = Some(arg);
  74. } else {
  75. break;
  76. }
  77. }
  78. let mut expected_failures = include_str!("expected_failures.txt")
  79. .lines()
  80. .collect::<Vec<_>>();
  81. let mut errors = vec![];
  82. // Copied from https://github.com/web-platform-tests/wpt/blob/master/url/
  83. let url_json: Vec<Value> = serde_json::from_str(include_str!("urltestdata.json"))
  84. .expect("JSON parse error in urltestdata.json");
  85. let url_tests = url_json
  86. .into_iter()
  87. .filter(|val| val.is_object())
  88. .map(|val| serde_json::from_value::<UrlTest>(val).expect("parsing failed"))
  89. .collect::<Vec<_>>();
  90. let setter_json: HashMap<String, Value> =
  91. serde_json::from_str(include_str!("setters_tests.json"))
  92. .expect("JSON parse error in setters_tests.json");
  93. let setter_tests = setter_json
  94. .into_iter()
  95. .filter(|(k, _)| k != "comment")
  96. .map(|(k, v)| {
  97. let test = serde_json::from_value::<Vec<SetterTest>>(v).expect("parsing failed");
  98. (k, test)
  99. })
  100. .collect::<HashMap<_, _>>();
  101. for url_test in url_tests {
  102. let mut name = format!("<{}>", url_test.input.escape_default());
  103. if let Some(base) = &url_test.base {
  104. write!(&mut name, " against <{}>", base.escape_default()).unwrap();
  105. }
  106. if should_skip(&name, filter.as_deref()) {
  107. continue;
  108. }
  109. print!("{} ... ", name);
  110. let res = run_url_test(url_test);
  111. report(name, res, &mut errors, &mut expected_failures);
  112. }
  113. for (kind, tests) in setter_tests {
  114. for test in tests {
  115. let name = format!(
  116. "<{}> set {} to <{}>",
  117. test.href.escape_default(),
  118. kind,
  119. test.new_value.escape_default()
  120. );
  121. if should_skip(&name, filter.as_deref()) {
  122. continue;
  123. }
  124. print!("{} ... ", name);
  125. let res = run_setter_test(&kind, test);
  126. report(name, res, &mut errors, &mut expected_failures);
  127. }
  128. }
  129. println!();
  130. println!("====================");
  131. println!();
  132. if !errors.is_empty() {
  133. println!("errors:");
  134. println!();
  135. for (name, err) in errors {
  136. println!(" name: {}", name);
  137. println!(" err: {}", err);
  138. println!();
  139. }
  140. std::process::exit(1);
  141. } else {
  142. println!("all tests passed");
  143. }
  144. if !expected_failures.is_empty() && filter.is_none() {
  145. println!();
  146. println!("====================");
  147. println!();
  148. println!("tests were expected to fail but did not run:");
  149. println!();
  150. for name in expected_failures {
  151. println!(" {}", name);
  152. }
  153. println!();
  154. println!("if these tests were removed, update expected_failures.txt");
  155. println!();
  156. std::process::exit(1);
  157. }
  158. }
  159. fn should_skip(name: &str, filter: Option<&str>) -> bool {
  160. match filter {
  161. Some(filter) => !name.contains(filter),
  162. None => false,
  163. }
  164. }
  165. fn report(
  166. name: String,
  167. res: Result<(), String>,
  168. errors: &mut Vec<(String, String)>,
  169. expected_failures: &mut Vec<&str>,
  170. ) {
  171. let expected_failure = expected_failures.contains(&&*name);
  172. expected_failures.retain(|&s| s != &*name);
  173. match res {
  174. Ok(()) => {
  175. if expected_failure {
  176. println!("🟠 (unexpected success)");
  177. errors.push((name, "unexpected success".to_string()));
  178. } else {
  179. println!("✅");
  180. }
  181. }
  182. Err(err) => {
  183. if expected_failure {
  184. println!("✅ (expected fail)");
  185. } else {
  186. println!("❌");
  187. errors.push((name, err));
  188. }
  189. }
  190. }
  191. }
  192. fn run_url_test(
  193. UrlTest {
  194. base,
  195. input,
  196. result,
  197. }: UrlTest,
  198. ) -> Result<(), String> {
  199. let base = match base {
  200. Some(base) => {
  201. let base = panic::catch_unwind(|| Url::parse(&base))
  202. .map_err(|_| "panicked while parsing base".to_string())?
  203. .map_err(|e| format!("errored while parsing base: {}", e))?;
  204. Some(base)
  205. }
  206. None => None,
  207. };
  208. let res = panic::catch_unwind(move || Url::options().base_url(base.as_ref()).parse(&input))
  209. .map_err(|_| "panicked while parsing input".to_string())?
  210. .map_err(|e| format!("errored while parsing input: {}", e));
  211. match result {
  212. UrlTestResult::Ok(ok) => check_url_ok(res, ok),
  213. UrlTestResult::Fail(fail) => {
  214. assert!(fail.failure);
  215. if res.is_ok() {
  216. return Err("expected failure, but parsed successfully".to_string());
  217. }
  218. Ok(())
  219. }
  220. }
  221. }
  222. fn check_url_ok(res: Result<Url, String>, ok: UrlTestOk) -> Result<(), String> {
  223. let url = match res {
  224. Ok(url) => url,
  225. Err(err) => {
  226. return Err(format!("expected success, but errored: {:?}", err));
  227. }
  228. };
  229. let href = url::quirks::href(&url);
  230. if href != ok.href {
  231. return Err(format!("expected href {:?}, but got {:?}", ok.href, href));
  232. }
  233. let protocol = url::quirks::protocol(&url);
  234. if protocol != ok.protocol {
  235. return Err(format!(
  236. "expected protocol {:?}, but got {:?}",
  237. ok.protocol, protocol
  238. ));
  239. }
  240. let username = url::quirks::username(&url);
  241. if username != ok.username {
  242. return Err(format!(
  243. "expected username {:?}, but got {:?}",
  244. ok.username, username
  245. ));
  246. }
  247. let password = url::quirks::password(&url);
  248. if password != ok.password {
  249. return Err(format!(
  250. "expected password {:?}, but got {:?}",
  251. ok.password, password
  252. ));
  253. }
  254. let host = url::quirks::host(&url);
  255. if host != ok.host {
  256. return Err(format!("expected host {:?}, but got {:?}", ok.host, host));
  257. }
  258. let hostname = url::quirks::hostname(&url);
  259. if hostname != ok.hostname {
  260. return Err(format!(
  261. "expected hostname {:?}, but got {:?}",
  262. ok.hostname, hostname
  263. ));
  264. }
  265. let port = url::quirks::port(&url);
  266. if port != ok.port {
  267. return Err(format!("expected port {:?}, but got {:?}", ok.port, port));
  268. }
  269. let pathname = url::quirks::pathname(&url);
  270. if pathname != ok.pathname {
  271. return Err(format!(
  272. "expected pathname {:?}, but got {:?}",
  273. ok.pathname, pathname
  274. ));
  275. }
  276. let search = url::quirks::search(&url);
  277. if search != ok.search {
  278. return Err(format!(
  279. "expected search {:?}, but got {:?}",
  280. ok.search, search
  281. ));
  282. }
  283. let hash = url::quirks::hash(&url);
  284. if hash != ok.hash {
  285. return Err(format!("expected hash {:?}, but got {:?}", ok.hash, hash));
  286. }
  287. Ok(())
  288. }
  289. fn run_setter_test(
  290. kind: &str,
  291. SetterTest {
  292. href,
  293. new_value,
  294. expected,
  295. }: SetterTest,
  296. ) -> Result<(), String> {
  297. let mut url = panic::catch_unwind(|| Url::parse(&href))
  298. .map_err(|_| "panicked while parsing href".to_string())?
  299. .map_err(|e| format!("errored while parsing href: {}", e))?;
  300. let url = panic::catch_unwind(move || {
  301. match kind {
  302. "protocol" => {
  303. url::quirks::set_protocol(&mut url, &new_value).ok();
  304. }
  305. "username" => {
  306. url::quirks::set_username(&mut url, &new_value).ok();
  307. }
  308. "password" => {
  309. url::quirks::set_password(&mut url, &new_value).ok();
  310. }
  311. "host" => {
  312. url::quirks::set_host(&mut url, &new_value).ok();
  313. }
  314. "hostname" => {
  315. url::quirks::set_hostname(&mut url, &new_value).ok();
  316. }
  317. "port" => {
  318. url::quirks::set_port(&mut url, &new_value).ok();
  319. }
  320. "pathname" => url::quirks::set_pathname(&mut url, &new_value),
  321. "search" => url::quirks::set_search(&mut url, &new_value),
  322. "hash" => url::quirks::set_hash(&mut url, &new_value),
  323. _ => panic!("unknown setter kind: {:?}", kind),
  324. };
  325. url
  326. })
  327. .map_err(|_| "panicked while setting value".to_string())?;
  328. if let Some(expected_href) = expected.href {
  329. let href = url::quirks::href(&url);
  330. if href != expected_href {
  331. return Err(format!(
  332. "expected href {:?}, but got {:?}",
  333. expected_href, href
  334. ));
  335. }
  336. }
  337. if let Some(expected_protocol) = expected.protocol {
  338. let protocol = url::quirks::protocol(&url);
  339. if protocol != expected_protocol {
  340. return Err(format!(
  341. "expected protocol {:?}, but got {:?}",
  342. expected_protocol, protocol
  343. ));
  344. }
  345. }
  346. if let Some(expected_username) = expected.username {
  347. let username = url::quirks::username(&url);
  348. if username != expected_username {
  349. return Err(format!(
  350. "expected username {:?}, but got {:?}",
  351. expected_username, username
  352. ));
  353. }
  354. }
  355. if let Some(expected_password) = expected.password {
  356. let password = url::quirks::password(&url);
  357. if password != expected_password {
  358. return Err(format!(
  359. "expected password {:?}, but got {:?}",
  360. expected_password, password
  361. ));
  362. }
  363. }
  364. if let Some(expected_host) = expected.host {
  365. let host = url::quirks::host(&url);
  366. if host != expected_host {
  367. return Err(format!(
  368. "expected host {:?}, but got {:?}",
  369. expected_host, host
  370. ));
  371. }
  372. }
  373. if let Some(expected_hostname) = expected.hostname {
  374. let hostname = url::quirks::hostname(&url);
  375. if hostname != expected_hostname {
  376. return Err(format!(
  377. "expected hostname {:?}, but got {:?}",
  378. expected_hostname, hostname
  379. ));
  380. }
  381. }
  382. if let Some(expected_port) = expected.port {
  383. let port = url::quirks::port(&url);
  384. if port != expected_port {
  385. return Err(format!(
  386. "expected port {:?}, but got {:?}",
  387. expected_port, port
  388. ));
  389. }
  390. }
  391. if let Some(expected_pathname) = expected.pathname {
  392. let pathname = url::quirks::pathname(&url);
  393. if pathname != expected_pathname {
  394. return Err(format!(
  395. "expected pathname {:?}, but got {:?}",
  396. expected_pathname, pathname
  397. ));
  398. }
  399. }
  400. if let Some(expected_search) = expected.search {
  401. let search = url::quirks::search(&url);
  402. if search != expected_search {
  403. return Err(format!(
  404. "expected search {:?}, but got {:?}",
  405. expected_search, search
  406. ));
  407. }
  408. }
  409. if let Some(expected_hash) = expected.hash {
  410. let hash = url::quirks::hash(&url);
  411. if hash != expected_hash {
  412. return Err(format!(
  413. "expected hash {:?}, but got {:?}",
  414. expected_hash, hash
  415. ));
  416. }
  417. }
  418. Ok(())
  419. }