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"));
25 let enable_metadata_collection = std::env::var("ENABLE_METADATA_COLLECTION").unwrap_or_else(|_| "0".to_string());
27 let mut command = Command::new(&*CLIPPY_PATH);
29 .current_dir(root_dir)
30 .env("CLIPPY_DOGFOOD", "1")
31 .env("CARGO_INCREMENTAL", "0")
32 .env("ENABLE_METADATA_COLLECTION", &enable_metadata_collection)
35 .arg("--all-features")
37 .args(&["-D", "clippy::all"])
38 .args(&["-D", "clippy::pedantic"])
39 .arg("-Cdebuginfo=0"); // disable debuginfo to generate less data in the target dir
41 // internal lints only exist if we build with the internal-lints feature
42 if cfg!(feature = "internal-lints") {
43 command.args(&["-D", "clippy::internal"]);
46 let output = command.output().unwrap();
48 println!("status: {}", output.status);
49 println!("stdout: {}", String::from_utf8_lossy(&output.stdout));
50 println!("stderr: {}", String::from_utf8_lossy(&output.stderr));
52 assert!(output.status.success());
55 fn test_no_deps_ignores_path_deps_in_workspaces() {
56 if cargo::is_rustc_test_suite() {
59 let root = PathBuf::from(env!("CARGO_MANIFEST_DIR"));
60 let target_dir = root.join("target").join("dogfood");
61 let cwd = root.join("clippy_workspace_tests");
63 // Make sure we start with a clean state
66 .env("CARGO_TARGET_DIR", &target_dir)
68 .args(&["-p", "subcrate"])
69 .args(&["-p", "path_dep"])
73 // `path_dep` is a path dependency of `subcrate` that would trigger a denied lint.
74 // Make sure that with the `--no-deps` argument Clippy does not run on `path_dep`.
75 let output = Command::new(&*CLIPPY_PATH)
77 .env("CLIPPY_DOGFOOD", "1")
78 .env("CARGO_INCREMENTAL", "0")
80 .args(&["-p", "subcrate"])
83 .arg("-Cdebuginfo=0") // disable debuginfo to generate less data in the target dir
84 .args(&["--cfg", r#"feature="primary_package_test""#])
87 println!("status: {}", output.status);
88 println!("stdout: {}", String::from_utf8_lossy(&output.stdout));
89 println!("stderr: {}", String::from_utf8_lossy(&output.stderr));
91 assert!(output.status.success());
93 let lint_path_dep = || {
94 // Test that without the `--no-deps` argument, `path_dep` is linted.
95 let output = Command::new(&*CLIPPY_PATH)
97 .env("CLIPPY_DOGFOOD", "1")
98 .env("CARGO_INCREMENTAL", "0")
100 .args(&["-p", "subcrate"])
102 .arg("-Cdebuginfo=0") // disable debuginfo to generate less data in the target dir
103 .args(&["--cfg", r#"feature="primary_package_test""#])
106 println!("status: {}", output.status);
107 println!("stdout: {}", String::from_utf8_lossy(&output.stdout));
108 println!("stderr: {}", String::from_utf8_lossy(&output.stderr));
110 assert!(!output.status.success());
112 String::from_utf8(output.stderr)
114 .contains("error: empty `loop {}` wastes CPU cycles")
118 // Make sure Cargo is aware of the removal of `--no-deps`.
121 let successful_build = || {
122 let output = Command::new(&*CLIPPY_PATH)
124 .env("CLIPPY_DOGFOOD", "1")
125 .env("CARGO_INCREMENTAL", "0")
127 .args(&["-p", "subcrate"])
129 .arg("-Cdebuginfo=0") // disable debuginfo to generate less data in the target dir
132 println!("status: {}", output.status);
133 println!("stdout: {}", String::from_utf8_lossy(&output.stdout));
134 println!("stderr: {}", String::from_utf8_lossy(&output.stderr));
136 assert!(output.status.success());
141 // Trigger a sucessful build, so Cargo would like to cache the build result.
144 // Make sure there's no spurious rebuild when nothing changes.
145 let stderr = String::from_utf8(successful_build().stderr).unwrap();
146 assert!(!stderr.contains("Compiling"));
147 assert!(!stderr.contains("Checking"));
148 assert!(stderr.contains("Finished"));
150 // Make sure Cargo is aware of the new `--cfg` flag.
155 fn dogfood_subprojects() {
156 // run clippy on remaining subprojects and fail the test if lint warnings are reported
157 if cargo::is_rustc_test_suite() {
160 let root_dir = PathBuf::from(env!("CARGO_MANIFEST_DIR"));
162 // NOTE: `path_dep` crate is omitted on purpose here
164 "clippy_workspace_tests",
165 "clippy_workspace_tests/src",
166 "clippy_workspace_tests/subcrate",
167 "clippy_workspace_tests/subcrate/src",
173 let mut command = Command::new(&*CLIPPY_PATH);
175 .current_dir(root_dir.join(d))
176 .env("CLIPPY_DOGFOOD", "1")
177 .env("CARGO_INCREMENTAL", "0")
179 .arg("--all-targets")
180 .arg("--all-features")
182 .args(&["-D", "clippy::all"])
183 .args(&["-D", "clippy::pedantic"])
184 .arg("-Cdebuginfo=0"); // disable debuginfo to generate less data in the target dir
186 // internal lints only exist if we build with the internal-lints feature
187 if cfg!(feature = "internal-lints") {
188 command.args(&["-D", "clippy::internal"]);
191 let output = command.output().unwrap();
193 println!("status: {}", output.status);
194 println!("stdout: {}", String::from_utf8_lossy(&output.stdout));
195 println!("stderr: {}", String::from_utf8_lossy(&output.stderr));
197 assert!(output.status.success());
200 // NOTE: Since tests run in parallel we can't run cargo commands on the same workspace at the
201 // same time, so we test this immediately after the dogfood for workspaces.
202 test_no_deps_ignores_path_deps_in_workspaces();