]>
git.proxmox.com Git - rustc.git/blob - src/tools/clippy/tests/dogfood.rs
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
9 #![cfg_attr(feature = "deny-warnings", deny(warnings))]
10 #![warn(rust_2018_idioms, unused_lifetimes)]
12 use std
::lazy
::SyncLazy
;
13 use std
::path
::PathBuf
;
14 use std
::process
::Command
;
18 static CLIPPY_PATH
: SyncLazy
<PathBuf
> = SyncLazy
::new(|| {
19 let mut path
= std
::env
::current_exe().unwrap();
20 assert
!(path
.pop()); // deps
21 path
.set_file_name("cargo-clippy");
27 // run clippy on itself and fail the test if lint warnings are reported
28 if cargo
::is_rustc_test_suite() {
31 let root_dir
= PathBuf
::from(env
!("CARGO_MANIFEST_DIR"));
33 let mut command
= Command
::new(&*CLIPPY_PATH
);
35 .current_dir(root_dir
)
36 .env("CARGO_INCREMENTAL", "0")
39 .arg("--all-features")
41 .args(&["-D", "clippy::all"])
42 .args(&["-D", "clippy::pedantic"])
43 .arg("-Cdebuginfo=0"); // disable debuginfo to generate less data in the target dir
45 // internal lints only exist if we build with the internal-lints feature
46 if cfg
!(feature
= "internal-lints") {
47 command
.args(&["-D", "clippy::internal"]);
50 let output
= command
.output().unwrap();
52 println
!("status: {}", output
.status
);
53 println
!("stdout: {}", String
::from_utf8_lossy(&output
.stdout
));
54 println
!("stderr: {}", String
::from_utf8_lossy(&output
.stderr
));
56 assert
!(output
.status
.success());
59 fn test_no_deps_ignores_path_deps_in_workspaces() {
60 if cargo
::is_rustc_test_suite() {
63 let root
= PathBuf
::from(env
!("CARGO_MANIFEST_DIR"));
64 let target_dir
= root
.join("target").join("dogfood");
65 let cwd
= root
.join("clippy_workspace_tests");
67 // Make sure we start with a clean state
70 .env("CARGO_TARGET_DIR", &target_dir
)
72 .args(&["-p", "subcrate"])
73 .args(&["-p", "path_dep"])
77 // `path_dep` is a path dependency of `subcrate` that would trigger a denied lint.
78 // Make sure that with the `--no-deps` argument Clippy does not run on `path_dep`.
79 let output
= Command
::new(&*CLIPPY_PATH
)
81 .env("CARGO_INCREMENTAL", "0")
83 .args(&["-p", "subcrate"])
86 .arg("-Cdebuginfo=0") // disable debuginfo to generate less data in the target dir
87 .args(&["--cfg", r
#"feature="primary_package_test""#])
90 println
!("status: {}", output
.status
);
91 println
!("stdout: {}", String
::from_utf8_lossy(&output
.stdout
));
92 println
!("stderr: {}", String
::from_utf8_lossy(&output
.stderr
));
94 assert
!(output
.status
.success());
96 let lint_path_dep
= || {
97 // Test that without the `--no-deps` argument, `path_dep` is linted.
98 let output
= Command
::new(&*CLIPPY_PATH
)
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("CARGO_INCREMENTAL", "0")
128 .args(&["-p", "subcrate"])
130 .arg("-Cdebuginfo=0") // disable debuginfo to generate less data in the target dir
133 println
!("status: {}", output
.status
);
134 println
!("stdout: {}", String
::from_utf8_lossy(&output
.stdout
));
135 println
!("stderr: {}", String
::from_utf8_lossy(&output
.stderr
));
137 assert
!(output
.status
.success());
142 // Trigger a sucessful build, so Cargo would like to cache the build result.
145 // Make sure there's no spurious rebuild when nothing changes.
146 let stderr
= String
::from_utf8(successful_build().stderr
).unwrap();
147 assert
!(!stderr
.contains("Compiling"));
148 assert
!(!stderr
.contains("Checking"));
149 assert
!(stderr
.contains("Finished"));
151 // Make sure Cargo is aware of the new `--cfg` flag.
156 fn dogfood_subprojects() {
157 // run clippy on remaining subprojects and fail the test if lint warnings are reported
158 if cargo
::is_rustc_test_suite() {
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 run_clippy_for_project(project
);
176 // NOTE: Since tests run in parallel we can't run cargo commands on the same workspace at the
177 // same time, so we test this immediately after the dogfood for workspaces.
178 test_no_deps_ignores_path_deps_in_workspaces();
183 #[cfg(feature = "metadata-collector-lint")]
184 fn run_metadata_collection_lint() {
186 use std
::time
::SystemTime
;
188 // Setup for validation
189 let metadata_output_path
= PathBuf
::from(env
!("CARGO_MANIFEST_DIR")).join("util/gh-pages/lints.json");
190 let start_time
= SystemTime
::now();
192 // Run collection as is
193 std
::env
::set_var("ENABLE_METADATA_COLLECTION", "1");
194 run_clippy_for_project("clippy_lints");
196 // Check if cargo caching got in the way
197 if let Ok(file
) = File
::open(metadata_output_path
) {
198 if let Ok(metadata
) = file
.metadata() {
199 if let Ok(last_modification
) = metadata
.modified() {
200 if last_modification
> start_time
{
201 // The output file has been modified. Most likely by a hungry
202 // metadata collection monster. So We'll return.
209 // Force cargo to invalidate the caches
210 filetime
::set_file_mtime(
211 PathBuf
::from(env
!("CARGO_MANIFEST_DIR")).join("clippy_lints/src/lib.rs"),
212 filetime
::FileTime
::now(),
216 // Running the collection again
217 run_clippy_for_project("clippy_lints");
220 fn run_clippy_for_project(project
: &str) {
221 let root_dir
= PathBuf
::from(env
!("CARGO_MANIFEST_DIR"));
223 let mut command
= Command
::new(&*CLIPPY_PATH
);
226 .current_dir(root_dir
.join(project
))
227 .env("CARGO_INCREMENTAL", "0")
229 .arg("--all-targets")
230 .arg("--all-features")
232 .args(&["-D", "clippy::all"])
233 .args(&["-D", "clippy::pedantic"])
234 .arg("-Cdebuginfo=0"); // disable debuginfo to generate less data in the target dir
236 // internal lints only exist if we build with the internal-lints feature
237 if cfg
!(feature
= "internal-lints") {
238 command
.args(&["-D", "clippy::internal"]);
241 let output
= command
.output().unwrap();
243 println
!("status: {}", output
.status
);
244 println
!("stdout: {}", String
::from_utf8_lossy(&output
.stdout
));
245 println
!("stderr: {}", String
::from_utf8_lossy(&output
.stderr
));
247 assert
!(output
.status
.success());