| use std::path::{Path, PathBuf}; |
| use std::process::Command; |
| use std::{env, fs}; |
| |
| struct Test { |
| repo: &'static str, |
| name: &'static str, |
| sha: &'static str, |
| lock: Option<&'static str>, |
| packages: &'static [&'static str], |
| features: Option<&'static [&'static str]>, |
| manifest_path: Option<&'static str>, |
| /// `filters` are passed to libtest (i.e., after a `--` in the `cargo test` invocation). |
| filters: &'static [&'static str], |
| } |
| |
| const TEST_REPOS: &[Test] = &[ |
| Test { |
| name: "iron", |
| repo: "https://github.com/iron/iron", |
| sha: "cf056ea5e8052c1feea6141e40ab0306715a2c33", |
| lock: None, |
| packages: &[], |
| features: None, |
| manifest_path: None, |
| filters: &[], |
| }, |
| Test { |
| name: "ripgrep", |
| repo: "https://github.com/BurntSushi/ripgrep", |
| sha: "ced5b92aa93eb47e892bd2fd26ab454008721730", |
| lock: None, |
| packages: &[], |
| features: None, |
| manifest_path: None, |
| filters: &[], |
| }, |
| Test { |
| name: "tokei", |
| repo: "https://github.com/XAMPPRocky/tokei", |
| sha: "fdf3f8cb279a7aeac0696c87e5d8b0cd946e4f9e", |
| lock: None, |
| packages: &[], |
| features: None, |
| manifest_path: None, |
| filters: &[], |
| }, |
| Test { |
| name: "xsv", |
| repo: "https://github.com/BurntSushi/xsv", |
| sha: "3de6c04269a7d315f7e9864b9013451cd9580a08", |
| lock: None, |
| packages: &[], |
| features: None, |
| manifest_path: None, |
| // Many tests here use quickcheck and some of them can fail randomly, so only run deterministic tests. |
| filters: &[ |
| "test_flatten::", |
| "test_fmt::", |
| "test_headers::", |
| "test_index::", |
| "test_join::", |
| "test_partition::", |
| "test_search::", |
| "test_select::", |
| "test_slice::", |
| "test_split::", |
| "test_stats::", |
| "test_table::", |
| ], |
| }, |
| Test { |
| name: "servo", |
| repo: "https://github.com/servo/servo", |
| sha: "785a344e32db58d4e631fd3cae17fd1f29a721ab", |
| lock: None, |
| // Only test Stylo a.k.a. Quantum CSS, the parts of Servo going into Firefox. |
| // This takes much less time to build than all of Servo and supports stable Rust. |
| packages: &["selectors"], |
| features: None, |
| manifest_path: None, |
| filters: &[], |
| }, |
| Test { |
| name: "diesel", |
| repo: "https://github.com/diesel-rs/diesel", |
| sha: "91493fe47175076f330ce5fc518f0196c0476f56", |
| lock: None, |
| packages: &[], |
| // Test the embedded sqlite variant of diesel |
| // This does not require any dependency to be present, |
| // sqlite will be compiled as part of the build process |
| features: Some(&["sqlite", "libsqlite3-sys/bundled"]), |
| // We are only interested in testing diesel itself |
| // not any other crate present in the diesel workspace |
| // (This is required to set the feature flags above) |
| manifest_path: Some("diesel/Cargo.toml"), |
| filters: &[], |
| }, |
| ]; |
| |
| fn main() { |
| let args = env::args().collect::<Vec<_>>(); |
| let cargo = &args[1]; |
| let out_dir = Path::new(&args[2]); |
| let cargo = &Path::new(cargo); |
| |
| for test in TEST_REPOS.iter().rev() { |
| if args[3..].is_empty() || args[3..].iter().any(|s| s.contains(test.name)) { |
| test_repo(cargo, out_dir, test); |
| } |
| } |
| } |
| |
| fn test_repo(cargo: &Path, out_dir: &Path, test: &Test) { |
| println!("testing {}", test.repo); |
| let dir = clone_repo(test, out_dir); |
| if let Some(lockfile) = test.lock { |
| fs::write(&dir.join("Cargo.lock"), lockfile).unwrap(); |
| } |
| if !run_cargo_test(cargo, &dir, test.packages, test.features, test.manifest_path, test.filters) |
| { |
| panic!("tests failed for {}", test.repo); |
| } |
| } |
| |
| fn clone_repo(test: &Test, out_dir: &Path) -> PathBuf { |
| let out_dir = out_dir.join(test.name); |
| |
| if !out_dir.join(".git").is_dir() { |
| let status = Command::new("git").arg("init").arg(&out_dir).status().unwrap(); |
| assert!(status.success()); |
| } |
| |
| // Try progressively deeper fetch depths to find the commit |
| let mut found = false; |
| for depth in &[0, 1, 10, 100, 1000, 100000] { |
| if *depth > 0 { |
| let status = Command::new("git") |
| .arg("fetch") |
| .arg(test.repo) |
| .arg(test.sha) |
| .arg(&format!("--depth={}", depth)) |
| .current_dir(&out_dir) |
| .status() |
| .unwrap(); |
| assert!(status.success()); |
| } |
| |
| let status = Command::new("git") |
| .arg("reset") |
| .arg(test.sha) |
| .arg("--hard") |
| .current_dir(&out_dir) |
| .status() |
| .unwrap(); |
| |
| if status.success() { |
| found = true; |
| break; |
| } |
| } |
| |
| if !found { |
| panic!("unable to find commit {}", test.sha) |
| } |
| let status = |
| Command::new("git").arg("clean").arg("-fdx").current_dir(&out_dir).status().unwrap(); |
| assert!(status.success()); |
| |
| out_dir |
| } |
| |
| fn run_cargo_test( |
| cargo_path: &Path, |
| crate_path: &Path, |
| packages: &[&str], |
| features: Option<&[&str]>, |
| manifest_path: Option<&str>, |
| filters: &[&str], |
| ) -> bool { |
| let mut command = Command::new(cargo_path); |
| command.arg("test"); |
| |
| if let Some(path) = manifest_path { |
| command.arg(format!("--manifest-path={}", path)); |
| } |
| |
| if let Some(features) = features { |
| command.arg("--no-default-features"); |
| for feature in features { |
| command.arg(format!("--features={}", feature)); |
| } |
| } |
| |
| for name in packages { |
| command.arg("-p").arg(name); |
| } |
| |
| command.arg("--"); |
| command.args(filters); |
| |
| let status = command |
| // Disable rust-lang/cargo's cross-compile tests |
| .env("CFG_DISABLE_CROSS_TESTS", "1") |
| // Relax #![deny(warnings)] in some crates |
| .env("RUSTFLAGS", "--cap-lints warn") |
| // servo tries to use 'lld-link.exe' on windows, but we don't |
| // have lld on our PATH in CI. Override it to use 'link.exe' |
| .env("CARGO_TARGET_X86_64_PC_WINDOWS_MSVC_LINKER", "link.exe") |
| .env("CARGO_TARGET_I686_PC_WINDOWS_MSVC_LINKER", "link.exe") |
| .current_dir(crate_path) |
| .status() |
| .unwrap(); |
| |
| status.success() |
| } |