1 //! This test is a part of quality control and makes clippy eat what it produces. Awesome lints and
2 //! long error messages
4 //! See [Eating your own dog food](https://en.wikipedia.org/wiki/Eating_your_own_dog_food) for context
6 // Dogfood cannot run on Windows
10 use std::lazy::SyncLazy;
11 use std::path::PathBuf;
12 use std::process::Command;
16 static CLIPPY_PATH: SyncLazy<PathBuf> = SyncLazy::new(|| cargo::TARGET_LIB.join("cargo-clippy"));
20 // run clippy on itself and fail the test if lint warnings are reported
21 if cargo::is_rustc_test_suite() {
24 let root_dir = PathBuf::from(env!("CARGO_MANIFEST_DIR"));
26 let mut command = Command::new(&*CLIPPY_PATH);
28 .current_dir(root_dir)
29 .env("CLIPPY_DOGFOOD", "1")
30 .env("CARGO_INCREMENTAL", "0")
33 .arg("--all-features")
35 .args(&["-D", "clippy::all"])
36 .args(&["-D", "clippy::pedantic"])
37 .arg("-Cdebuginfo=0"); // disable debuginfo to generate less data in the target dir
39 // internal lints only exist if we build with the internal-lints feature
40 if cfg!(feature = "internal-lints") {
41 command.args(&["-D", "clippy::internal"]);
44 if cfg!(feature = "metadata-collector-lint") {
45 command.args(&["-D", "clippy::internal"]);
48 let output = command.output().unwrap();
50 println!("status: {}", output.status);
51 println!("stdout: {}", String::from_utf8_lossy(&output.stdout));
52 println!("stderr: {}", String::from_utf8_lossy(&output.stderr));
54 assert!(output.status.success());
57 fn test_no_deps_ignores_path_deps_in_workspaces() {
58 if cargo::is_rustc_test_suite() {
61 let root = PathBuf::from(env!("CARGO_MANIFEST_DIR"));
62 let target_dir = root.join("target").join("dogfood");
63 let cwd = root.join("clippy_workspace_tests");
65 // Make sure we start with a clean state
68 .env("CARGO_TARGET_DIR", &target_dir)
70 .args(&["-p", "subcrate"])
71 .args(&["-p", "path_dep"])
75 // `path_dep` is a path dependency of `subcrate` that would trigger a denied lint.
76 // Make sure that with the `--no-deps` argument Clippy does not run on `path_dep`.
77 let output = Command::new(&*CLIPPY_PATH)
79 .env("CLIPPY_DOGFOOD", "1")
80 .env("CARGO_INCREMENTAL", "0")
82 .args(&["-p", "subcrate"])
85 .arg("-Cdebuginfo=0") // disable debuginfo to generate less data in the target dir
86 .args(&["--cfg", r#"feature="primary_package_test""#])
89 println!("status: {}", output.status);
90 println!("stdout: {}", String::from_utf8_lossy(&output.stdout));
91 println!("stderr: {}", String::from_utf8_lossy(&output.stderr));
93 assert!(output.status.success());
95 let lint_path_dep = || {
96 // Test that without the `--no-deps` argument, `path_dep` is linted.
97 let output = Command::new(&*CLIPPY_PATH)
99 .env("CLIPPY_DOGFOOD", "1")
100 .env("CARGO_INCREMENTAL", "0")
102 .args(&["-p", "subcrate"])
104 .arg("-Cdebuginfo=0") // disable debuginfo to generate less data in the target dir
105 .args(&["--cfg", r#"feature="primary_package_test""#])
108 println!("status: {}", output.status);
109 println!("stdout: {}", String::from_utf8_lossy(&output.stdout));
110 println!("stderr: {}", String::from_utf8_lossy(&output.stderr));
112 assert!(!output.status.success());
114 String::from_utf8(output.stderr)
116 .contains("error: empty `loop {}` wastes CPU cycles")
120 // Make sure Cargo is aware of the removal of `--no-deps`.
123 let successful_build = || {
124 let output = Command::new(&*CLIPPY_PATH)
126 .env("CLIPPY_DOGFOOD", "1")
127 .env("CARGO_INCREMENTAL", "0")
129 .args(&["-p", "subcrate"])
131 .arg("-Cdebuginfo=0") // disable debuginfo to generate less data in the target dir
134 println!("status: {}", output.status);
135 println!("stdout: {}", String::from_utf8_lossy(&output.stdout));
136 println!("stderr: {}", String::from_utf8_lossy(&output.stderr));
138 assert!(output.status.success());
143 // Trigger a sucessful build, so Cargo would like to cache the build result.
146 // Make sure there's no spurious rebuild when nothing changes.
147 let stderr = String::from_utf8(successful_build().stderr).unwrap();
148 assert!(!stderr.contains("Compiling"));
149 assert!(!stderr.contains("Checking"));
150 assert!(stderr.contains("Finished"));
152 // Make sure Cargo is aware of the new `--cfg` flag.
157 fn dogfood_subprojects() {
158 // run clippy on remaining subprojects and fail the test if lint warnings are reported
159 if cargo::is_rustc_test_suite() {
162 let root_dir = PathBuf::from(env!("CARGO_MANIFEST_DIR"));
164 // NOTE: `path_dep` crate is omitted on purpose here
166 "clippy_workspace_tests",
167 "clippy_workspace_tests/src",
168 "clippy_workspace_tests/subcrate",
169 "clippy_workspace_tests/subcrate/src",
175 let mut command = Command::new(&*CLIPPY_PATH);
177 .current_dir(root_dir.join(d))
178 .env("CLIPPY_DOGFOOD", "1")
179 .env("CARGO_INCREMENTAL", "0")
181 .arg("--all-targets")
182 .arg("--all-features")
184 .args(&["-D", "clippy::all"])
185 .args(&["-D", "clippy::pedantic"])
186 .arg("-Cdebuginfo=0"); // disable debuginfo to generate less data in the target dir
188 // internal lints only exist if we build with the internal-lints feature
189 if cfg!(feature = "internal-lints") {
190 command.args(&["-D", "clippy::internal"]);
193 let output = command.output().unwrap();
195 println!("status: {}", output.status);
196 println!("stdout: {}", String::from_utf8_lossy(&output.stdout));
197 println!("stderr: {}", String::from_utf8_lossy(&output.stderr));
199 assert!(output.status.success());
202 // NOTE: Since tests run in parallel we can't run cargo commands on the same workspace at the
203 // same time, so we test this immediately after the dogfood for workspaces.
204 test_no_deps_ignores_path_deps_in_workspaces();