]> git.lizzy.rs Git - rust.git/blob - src/tools/cargotest/main.rs
Rollup merge of #73945 - est31:unused_externs, r=Mark-Simulacrum
[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         test_repo(cargo, out_dir, test);
89     }
90 }
91
92 fn test_repo(cargo: &Path, out_dir: &Path, test: &Test) {
93     println!("testing {}", test.repo);
94     let dir = clone_repo(test, out_dir);
95     if let Some(lockfile) = test.lock {
96         fs::write(&dir.join("Cargo.lock"), lockfile).unwrap();
97     }
98     if !run_cargo_test(cargo, &dir, test.packages, test.features, test.manifest_path) {
99         panic!("tests failed for {}", test.repo);
100     }
101 }
102
103 fn clone_repo(test: &Test, out_dir: &Path) -> PathBuf {
104     let out_dir = out_dir.join(test.name);
105
106     if !out_dir.join(".git").is_dir() {
107         let status = Command::new("git").arg("init").arg(&out_dir).status().unwrap();
108         assert!(status.success());
109     }
110
111     // Try progressively deeper fetch depths to find the commit
112     let mut found = false;
113     for depth in &[0, 1, 10, 100, 1000, 100000] {
114         if *depth > 0 {
115             let status = Command::new("git")
116                 .arg("fetch")
117                 .arg(test.repo)
118                 .arg("master")
119                 .arg(&format!("--depth={}", depth))
120                 .current_dir(&out_dir)
121                 .status()
122                 .unwrap();
123             assert!(status.success());
124         }
125
126         let status = Command::new("git")
127             .arg("reset")
128             .arg(test.sha)
129             .arg("--hard")
130             .current_dir(&out_dir)
131             .status()
132             .unwrap();
133
134         if status.success() {
135             found = true;
136             break;
137         }
138     }
139
140     if !found {
141         panic!("unable to find commit {}", test.sha)
142     }
143     let status =
144         Command::new("git").arg("clean").arg("-fdx").current_dir(&out_dir).status().unwrap();
145     assert!(status.success());
146
147     out_dir
148 }
149
150 fn run_cargo_test(
151     cargo_path: &Path,
152     crate_path: &Path,
153     packages: &[&str],
154     features: Option<&[&str]>,
155     manifest_path: Option<&str>,
156 ) -> bool {
157     let mut command = Command::new(cargo_path);
158     command.arg("test");
159
160     if let Some(path) = manifest_path {
161         command.arg(format!("--manifest-path={}", path));
162     }
163
164     if let Some(features) = features {
165         command.arg("--no-default-features");
166         for feature in features {
167             command.arg(format!("--features={}", feature));
168         }
169     }
170
171     for name in packages {
172         command.arg("-p").arg(name);
173     }
174
175     let status = command
176         // Disable rust-lang/cargo's cross-compile tests
177         .env("CFG_DISABLE_CROSS_TESTS", "1")
178         // Relax #![deny(warnings)] in some crates
179         .env("RUSTFLAGS", "--cap-lints warn")
180         .current_dir(crate_path)
181         .status()
182         .unwrap();
183
184     status.success()
185 }