]> git.lizzy.rs Git - rust.git/blob - src/tools/clippy/tests/integration.rs
Rollup merge of #104965 - zacklukem:p-option-as_ref-docs, r=scottmcm
[rust.git] / src / tools / clippy / tests / integration.rs
1 //! This test is meant to only be run in CI. To run it locally use:
2 //!
3 //! `env INTEGRATION=rust-lang/log cargo test --test integration --features=integration`
4 //!
5 //! You can use a different `INTEGRATION` value to test different repositories.
6 //!
7 //! This test will clone the specified repository and run Clippy on it. The test succeeds, if
8 //! Clippy doesn't produce an ICE. Lint warnings are ignored by this test.
9
10 #![cfg(feature = "integration")]
11 #![cfg_attr(feature = "deny-warnings", deny(warnings))]
12 #![warn(rust_2018_idioms, unused_lifetimes)]
13
14 use std::env;
15 use std::ffi::OsStr;
16 use std::process::Command;
17
18 #[cfg(not(windows))]
19 const CARGO_CLIPPY: &str = "cargo-clippy";
20 #[cfg(windows)]
21 const CARGO_CLIPPY: &str = "cargo-clippy.exe";
22
23 #[cfg_attr(feature = "integration", test)]
24 fn integration_test() {
25     let repo_name = env::var("INTEGRATION").expect("`INTEGRATION` var not set");
26     let repo_url = format!("https://github.com/{repo_name}");
27     let crate_name = repo_name
28         .split('/')
29         .nth(1)
30         .expect("repo name should have format `<org>/<name>`");
31
32     let mut repo_dir = tempfile::tempdir().expect("couldn't create temp dir").into_path();
33     repo_dir.push(crate_name);
34
35     let st = Command::new("git")
36         .args([
37             OsStr::new("clone"),
38             OsStr::new("--depth=1"),
39             OsStr::new(&repo_url),
40             OsStr::new(&repo_dir),
41         ])
42         .status()
43         .expect("unable to run git");
44     assert!(st.success());
45
46     let root_dir = std::path::PathBuf::from(env!("CARGO_MANIFEST_DIR"));
47     let target_dir = std::path::Path::new(&root_dir).join("target");
48     let clippy_binary = target_dir.join(env!("PROFILE")).join(CARGO_CLIPPY);
49
50     let output = Command::new(clippy_binary)
51         .current_dir(repo_dir)
52         .env("RUST_BACKTRACE", "full")
53         .env("CARGO_TARGET_DIR", target_dir)
54         .args([
55             "clippy",
56             "--all-targets",
57             "--all-features",
58             "--",
59             "--cap-lints",
60             "warn",
61             "-Wclippy::pedantic",
62             "-Wclippy::nursery",
63         ])
64         .output()
65         .expect("unable to run clippy");
66
67     let stderr = String::from_utf8_lossy(&output.stderr);
68     if let Some(backtrace_start) = stderr.find("error: internal compiler error") {
69         static BACKTRACE_END_MSG: &str = "end of query stack";
70         let backtrace_end = stderr[backtrace_start..]
71             .find(BACKTRACE_END_MSG)
72             .expect("end of backtrace not found");
73
74         panic!(
75             "internal compiler error\nBacktrace:\n\n{}",
76             &stderr[backtrace_start..backtrace_start + backtrace_end + BACKTRACE_END_MSG.len()]
77         );
78     } else if stderr.contains("query stack during panic") {
79         panic!("query stack during panic in the output");
80     } else if stderr.contains("E0463") {
81         // Encountering E0463 (can't find crate for `x`) did _not_ cause the build to fail in the
82         // past. Even though it should have. That's why we explicitly panic here.
83         // See PR #3552 and issue #3523 for more background.
84         panic!("error: E0463");
85     } else if stderr.contains("E0514") {
86         panic!("incompatible crate versions");
87     } else if stderr.contains("failed to run `rustc` to learn about target-specific information") {
88         panic!("couldn't find librustc_driver, consider setting `LD_LIBRARY_PATH`");
89     } else {
90         assert!(
91             !stderr.contains("toolchain") || !stderr.contains("is not installed"),
92             "missing required toolchain"
93         );
94     }
95
96     match output.status.code() {
97         Some(0) => println!("Compilation successful"),
98         Some(code) => eprintln!("Compilation failed. Exit code: {code}"),
99         None => panic!("Process terminated by signal"),
100     }
101 }