use std::path::Path; use std::process::{Command, ExitStatus}; fn run(dirname: &str) -> (ExitStatus, String, String) { let output = Command::new(env!("CARGO_BIN_EXE_linkchecker")) .current_dir(Path::new(env!("CARGO_MANIFEST_DIR")).join("tests")) .arg(dirname) .output() .unwrap(); let stdout = String::from_utf8(output.stdout).unwrap(); let stderr = String::from_utf8(output.stderr).unwrap(); (output.status, stdout, stderr) } fn broken_test(dirname: &str, expected: &str) { let (status, stdout, stderr) = run(dirname); assert!(!status.success()); if !contains(expected, &stdout) { panic!( "stdout did not contain expected text: {}\n\ --- stdout:\n\ {}\n\ --- stderr:\n\ {}\n", expected, stdout, stderr ); } } fn contains(expected: &str, actual: &str) -> bool { // Normalize for Windows paths. let actual = actual.replace('\\', "/"); actual.lines().any(|mut line| { for (i, part) in expected.split("[..]").enumerate() { match line.find(part) { Some(j) => { if i == 0 && j != 0 { return false; } line = &line[j + part.len()..]; } None => return false, } } line.is_empty() || expected.ends_with("[..]") }) } fn valid_test(dirname: &str) { let (status, stdout, stderr) = run(dirname); if !status.success() { panic!( "test did not succeed as expected\n\ --- stdout:\n\ {}\n\ --- stderr:\n\ {}\n", stdout, stderr ); } } #[test] fn valid() { valid_test("valid/inner"); } #[test] fn basic_broken() { broken_test("basic_broken", "foo.html:3: broken link - `bar.html`"); } #[test] fn broken_fragment_local() { broken_test( "broken_fragment_local", "foo.html:3: broken link fragment `#somefrag` pointing to `foo.html`", ); } #[test] fn broken_fragment_remote() { broken_test( "broken_fragment_remote/inner", "foo.html:3: broken link fragment `#somefrag` pointing to \ `[..]/broken_fragment_remote/bar.html`", ); } #[test] fn broken_redir() { broken_test( "broken_redir", "foo.html:3: broken redirect from `redir-bad.html` to `sometarget`", ); } #[test] fn directory_link() { broken_test( "directory_link", "foo.html:3: directory link to `somedir` (directory links should use index.html instead)", ); } #[test] fn redirect_loop() { broken_test( "redirect_loop", "foo.html:3: redirect from `redir-bad.html` to `[..]redirect_loop/redir-bad.html` \ which is also a redirect (not supported)", ); }