]> git.lizzy.rs Git - rust.git/blob - src/tools/cargotest/main.rs
Merge commit 'a98e7ab8b94485be6bd03e0c6b8682ecab5b52e6' into clippyup
[rust.git] / src / tools / cargotest / main.rs
1 use std::env;
2 use std::fs;
3 use std::path::{Path, PathBuf};
4 use std::process::Command;
5
6 struct Test {
7     repo: &'static str,
8     name: &'static str,
9     sha: &'static str,
10     lock: Option<&'static str>,
11     packages: &'static [&'static str],
12     features: Option<&'static [&'static str]>,
13     manifest_path: Option<&'static str>,
14 }
15
16 const TEST_REPOS: &[Test] = &[
17     Test {
18         name: "iron",
19         repo: "https://github.com/iron/iron",
20         sha: "cf056ea5e8052c1feea6141e40ab0306715a2c33",
21         lock: None,
22         packages: &[],
23         features: None,
24         manifest_path: None,
25     },
26     Test {
27         name: "ripgrep",
28         repo: "https://github.com/BurntSushi/ripgrep",
29         sha: "3de31f752729525d85a3d1575ac1978733b3f7e7",
30         lock: None,
31         packages: &[],
32         features: None,
33         manifest_path: None,
34     },
35     Test {
36         name: "tokei",
37         repo: "https://github.com/XAMPPRocky/tokei",
38         sha: "fdf3f8cb279a7aeac0696c87e5d8b0cd946e4f9e",
39         lock: None,
40         packages: &[],
41         features: None,
42         manifest_path: None,
43     },
44     Test {
45         name: "xsv",
46         repo: "https://github.com/BurntSushi/xsv",
47         sha: "3de6c04269a7d315f7e9864b9013451cd9580a08",
48         lock: None,
49         packages: &[],
50         features: None,
51         manifest_path: None,
52     },
53     Test {
54         name: "servo",
55         repo: "https://github.com/servo/servo",
56         sha: "caac107ae8145ef2fd20365e2b8fadaf09c2eb3b",
57         lock: None,
58         // Only test Stylo a.k.a. Quantum CSS, the parts of Servo going into Firefox.
59         // This takes much less time to build than all of Servo and supports stable Rust.
60         packages: &["selectors"],
61         features: None,
62         manifest_path: None,
63     },
64     Test {
65         name: "diesel",
66         repo: "https://github.com/diesel-rs/diesel",
67         sha: "91493fe47175076f330ce5fc518f0196c0476f56",
68         lock: None,
69         packages: &[],
70         // Test the embeded sqlite variant of diesel
71         // This does not require any dependency to be present,
72         // sqlite will be compiled as part of the build process
73         features: Some(&["sqlite", "libsqlite3-sys/bundled"]),
74         // We are only interested in testing diesel itself
75         // not any other crate present in the diesel workspace
76         // (This is required to set the feature flags above)
77         manifest_path: Some("diesel/Cargo.toml"),
78     },
79 ];
80
81 fn main() {
82     let args = env::args().collect::<Vec<_>>();
83     let cargo = &args[1];
84     let out_dir = Path::new(&args[2]);
85     let cargo = &Path::new(cargo);
86
87     for test in TEST_REPOS.iter().rev() {
88         if args[3..].is_empty() || args[3..].iter().any(|s| s.contains(test.name)) {
89             test_repo(cargo, out_dir, test);
90         }
91     }
92 }
93
94 fn test_repo(cargo: &Path, out_dir: &Path, test: &Test) {
95     println!("testing {}", test.repo);
96     let dir = clone_repo(test, out_dir);
97     if let Some(lockfile) = test.lock {
98         fs::write(&dir.join("Cargo.lock"), lockfile).unwrap();
99     }
100     if !run_cargo_test(cargo, &dir, test.packages, test.features, test.manifest_path) {
101         panic!("tests failed for {}", test.repo);
102     }
103 }
104
105 fn clone_repo(test: &Test, out_dir: &Path) -> PathBuf {
106     let out_dir = out_dir.join(test.name);
107
108     if !out_dir.join(".git").is_dir() {
109         let status = Command::new("git").arg("init").arg(&out_dir).status().unwrap();
110         assert!(status.success());
111     }
112
113     // Try progressively deeper fetch depths to find the commit
114     let mut found = false;
115     for depth in &[0, 1, 10, 100, 1000, 100000] {
116         if *depth > 0 {
117             let status = Command::new("git")
118                 .arg("fetch")
119                 .arg(test.repo)
120                 .arg("master")
121                 .arg(&format!("--depth={}", depth))
122                 .current_dir(&out_dir)
123                 .status()
124                 .unwrap();
125             assert!(status.success());
126         }
127
128         let status = Command::new("git")
129             .arg("reset")
130             .arg(test.sha)
131             .arg("--hard")
132             .current_dir(&out_dir)
133             .status()
134             .unwrap();
135
136         if status.success() {
137             found = true;
138             break;
139         }
140     }
141
142     if !found {
143         panic!("unable to find commit {}", test.sha)
144     }
145     let status =
146         Command::new("git").arg("clean").arg("-fdx").current_dir(&out_dir).status().unwrap();
147     assert!(status.success());
148
149     out_dir
150 }
151
152 fn run_cargo_test(
153     cargo_path: &Path,
154     crate_path: &Path,
155     packages: &[&str],
156     features: Option<&[&str]>,
157     manifest_path: Option<&str>,
158 ) -> bool {
159     let mut command = Command::new(cargo_path);
160     command.arg("test");
161
162     if let Some(path) = manifest_path {
163         command.arg(format!("--manifest-path={}", path));
164     }
165
166     if let Some(features) = features {
167         command.arg("--no-default-features");
168         for feature in features {
169             command.arg(format!("--features={}", feature));
170         }
171     }
172
173     for name in packages {
174         command.arg("-p").arg(name);
175     }
176
177     let status = command
178         // Disable rust-lang/cargo's cross-compile tests
179         .env("CFG_DISABLE_CROSS_TESTS", "1")
180         // Relax #![deny(warnings)] in some crates
181         .env("RUSTFLAGS", "--cap-lints warn")
182         .current_dir(crate_path)
183         .status()
184         .unwrap();
185
186     status.success()
187 }