Skip to content

Commit ae6ab06

Browse files
committed
Add fixed_path_existence test
1 parent ea96091 commit ae6ab06

30 files changed

+864
-101
lines changed

Cargo.toml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,11 +46,13 @@ if_chain = "1.0"
4646
itertools = "0.10.1"
4747
quote = "1.0"
4848
serde = { version = "1.0.125", features = ["derive"] }
49+
serde_json = "1.0"
4950
syn = { version = "1.0", features = ["full"] }
5051
futures = "0.3"
5152
parking_lot = "0.11.2"
5253
tokio = { version = "1", features = ["io-util"] }
5354
rustc-semver = "1.1"
55+
walkdir = "2.3"
5456

5557
[build-dependencies]
5658
rustc_tools_util = { version = "0.2", path = "rustc_tools_util" }

clippy_lints/src/lib.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -501,6 +501,9 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf:
501501
{
502502
if std::env::var("ENABLE_METADATA_COLLECTION").eq(&Ok("1".to_string())) {
503503
store.register_late_pass(|| Box::new(utils::internal_lints::metadata_collector::MetadataCollector::new()));
504+
}
505+
506+
if std::env::var("DISABLE_STANDARD_LINTS").eq(&Ok("1".to_string())) {
504507
return;
505508
}
506509
}

tests/dogfood.rs

Lines changed: 194 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -25,43 +25,206 @@ fn dogfood_clippy() {
2525
}
2626
}
2727

28-
#[test]
29-
#[ignore]
30-
#[cfg(feature = "internal")]
31-
fn run_metadata_collection_lint() {
32-
use std::fs::File;
33-
use std::time::SystemTime;
34-
35-
// Setup for validation
36-
let metadata_output_path = PathBuf::from(env!("CARGO_MANIFEST_DIR")).join("util/gh-pages/lints.json");
37-
let start_time = SystemTime::now();
38-
39-
// Run collection as is
40-
std::env::set_var("ENABLE_METADATA_COLLECTION", "1");
41-
run_clippy_for_package("clippy_lints", &["-A", "unfulfilled_lint_expectations"]);
42-
43-
// Check if cargo caching got in the way
44-
if let Ok(file) = File::open(metadata_output_path) {
45-
if let Ok(metadata) = file.metadata() {
46-
if let Ok(last_modification) = metadata.modified() {
47-
if last_modification > start_time {
48-
// The output file has been modified. Most likely by a hungry
49-
// metadata collection monster. So We'll return.
50-
return;
28+
#[cfg(all(test, feature = "internal"))]
29+
mod internal {
30+
use super::run_clippy_for_package;
31+
use if_chain::if_chain;
32+
use serde::Deserialize;
33+
use std::collections::HashMap;
34+
use std::ffi::OsStr;
35+
use std::fs::{read_to_string, File};
36+
use std::io::BufReader;
37+
use std::path::PathBuf;
38+
use walkdir::WalkDir;
39+
40+
static UI_TEST_PATH: std::lazy::SyncLazy<PathBuf> =
41+
std::lazy::SyncLazy::new(|| PathBuf::from(env!("CARGO_MANIFEST_DIR")).join("tests/ui"));
42+
43+
static METADATA_OUTPUT_PATH: std::lazy::SyncLazy<PathBuf> =
44+
std::lazy::SyncLazy::new(|| PathBuf::from(env!("CARGO_MANIFEST_DIR")).join("util/gh-pages/lints.json"));
45+
46+
#[derive(Debug, Deserialize)]
47+
pub struct LintMetadata {
48+
id: String,
49+
applicability: Option<ApplicabilityInfo>,
50+
}
51+
52+
#[derive(Debug, Deserialize)]
53+
struct ApplicabilityInfo {
54+
applicability: Option<String>,
55+
}
56+
57+
const MACHINE_APPLICABLE: &str = "MachineApplicable";
58+
59+
const KNOWN_EXCEPTIONS: [&str; 33] = [
60+
"assign_ops2.stderr",
61+
"cast_size_32bit.stderr",
62+
"char_lit_as_u8.stderr",
63+
"cmp_owned/without_suggestion.stderr",
64+
"dbg_macro.stderr",
65+
"deref_addrof_double_trigger.stderr",
66+
"doc/unbalanced_ticks.stderr",
67+
"eprint_with_newline.stderr",
68+
"explicit_counter_loop.stderr",
69+
"iter_skip_next_unfixable.stderr",
70+
"let_and_return.stderr",
71+
"literals.stderr",
72+
"map_flatten.stderr",
73+
"map_unwrap_or.stderr",
74+
"match_bool.stderr",
75+
"mem_replace_macro.stderr",
76+
"needless_arbitrary_self_type_unfixable.stderr",
77+
"needless_borrow_pat.stderr",
78+
"needless_for_each_unfixable.stderr",
79+
"nonminimal_bool.stderr",
80+
"print_literal.stderr",
81+
"print_with_newline.stderr",
82+
"redundant_static_lifetimes_multiple.stderr",
83+
"result_map_unit_fn_unfixable.stderr",
84+
"search_is_some.stderr",
85+
"string_add.stderr",
86+
"toplevel_ref_arg_non_rustfix.stderr",
87+
"unit_arg.stderr",
88+
"unnecessary_clone.stderr",
89+
"unnecessary_lazy_eval_unfixable.stderr",
90+
"write_literal_2.stderr",
91+
"write_literal.stderr",
92+
"write_with_newline.stderr",
93+
];
94+
95+
#[test]
96+
fn known_exceptions_accuracy() {
97+
for filename in KNOWN_EXCEPTIONS {
98+
let stderr_path = UI_TEST_PATH.join(filename);
99+
assert!(
100+
stderr_path.exists(),
101+
"`{}` does not exists",
102+
stderr_path.strip_prefix(env!("CARGO_MANIFEST_DIR")).unwrap().display()
103+
);
104+
let fixed_path = stderr_path.with_extension("fixed");
105+
assert!(
106+
!fixed_path.exists(),
107+
"`{}` exists",
108+
fixed_path.strip_prefix(env!("CARGO_MANIFEST_DIR")).unwrap().display()
109+
);
110+
}
111+
}
112+
113+
#[test]
114+
fn fixed_path_existence() {
115+
collect_metadata(false);
116+
117+
let lints = read_metadata();
118+
119+
let mut lint_map = HashMap::new();
120+
for lint in lints {
121+
lint_map.insert(lint.id, lint.applicability.and_then(|app| app.applicability));
122+
}
123+
124+
for entry in WalkDir::new(&*UI_TEST_PATH) {
125+
let entry = entry.unwrap();
126+
127+
if KNOWN_EXCEPTIONS.contains(&&*entry.path().strip_prefix(&*UI_TEST_PATH).unwrap().to_string_lossy()) {
128+
continue;
129+
}
130+
131+
if entry.path().extension() != Some(OsStr::new("stderr")) {
132+
continue;
133+
};
134+
135+
let stderr_path = entry.path();
136+
137+
let stderr_contents = read_to_string(stderr_path).unwrap();
138+
139+
let lint_ids = stderr_contents.lines().filter_map(|line| {
140+
const PREFIX: &str = "`-D clippy::";
141+
const SUFFIX: &str = "`";
142+
if_chain! {
143+
if let Some(start) = line.find(PREFIX).map(|n| n + PREFIX.len());
144+
if let Some(end) = line[start..].find(SUFFIX);
145+
then {
146+
Some(line[start..][..end].replace('-', "_"))
147+
} else {
148+
None
149+
}
51150
}
151+
});
152+
153+
let mach_app_lint_ids = lint_ids
154+
.filter(|id| {
155+
lint_map
156+
.get(id)
157+
.unwrap()
158+
.as_ref()
159+
.map_or(false, |s| s == MACHINE_APPLICABLE)
160+
})
161+
.collect::<Vec<_>>();
162+
163+
if !mach_app_lint_ids.is_empty() {
164+
let fixed_path = stderr_path.with_extension("fixed");
165+
assert!(
166+
fixed_path.exists(),
167+
"`{}` does not exist though `{}` mentions the following `{}` lints: {:#?}",
168+
fixed_path.strip_prefix(env!("CARGO_MANIFEST_DIR")).unwrap().display(),
169+
stderr_path.strip_prefix(env!("CARGO_MANIFEST_DIR")).unwrap().display(),
170+
MACHINE_APPLICABLE,
171+
mach_app_lint_ids
172+
);
52173
}
53174
}
54175
}
55176

56-
// Force cargo to invalidate the caches
57-
filetime::set_file_mtime(
58-
PathBuf::from(env!("CARGO_MANIFEST_DIR")).join("clippy_lints/src/lib.rs"),
59-
filetime::FileTime::now(),
60-
)
61-
.unwrap();
177+
#[test]
178+
#[ignore]
179+
fn run_metadata_collection_lint() {
180+
collect_metadata(true);
181+
}
182+
183+
fn collect_metadata(disable_standard_lints: bool) {
184+
use std::time::SystemTime;
185+
186+
// Setup for validation
187+
let start_time = SystemTime::now();
62188

63-
// Running the collection again
64-
run_clippy_for_package("clippy_lints", &["-A", "unfulfilled_lint_expectations"]);
189+
// Run collection as is
190+
std::env::set_var("ENABLE_METADATA_COLLECTION", "1");
191+
let args: &[&str] = if disable_standard_lints {
192+
std::env::set_var("DISABLE_STANDARD_LINTS", "1");
193+
&["-A", "unfulfilled_lint_expectations"]
194+
} else {
195+
&[]
196+
};
197+
run_clippy_for_package("clippy_lints", args);
198+
199+
// Check if cargo caching got in the way
200+
if let Ok(file) = File::open(&*METADATA_OUTPUT_PATH) {
201+
if let Ok(metadata) = file.metadata() {
202+
if let Ok(last_modification) = metadata.modified() {
203+
if last_modification > start_time {
204+
// The output file has been modified. Most likely by a hungry
205+
// metadata collection monster. So We'll return.
206+
return;
207+
}
208+
}
209+
}
210+
}
211+
212+
// Force cargo to invalidate the caches
213+
filetime::set_file_mtime(
214+
PathBuf::from(env!("CARGO_MANIFEST_DIR")).join("clippy_lints/src/lib.rs"),
215+
filetime::FileTime::now(),
216+
)
217+
.unwrap();
218+
219+
// Running the collection again
220+
run_clippy_for_package("clippy_lints", args);
221+
}
222+
223+
fn read_metadata() -> Vec<LintMetadata> {
224+
let file = File::open(&*METADATA_OUTPUT_PATH).unwrap();
225+
let reader = BufReader::new(file);
226+
serde_json::from_reader(reader).unwrap()
227+
}
65228
}
66229

67230
fn run_clippy_for_package(project: &str, args: &[&str]) {

tests/ui/crashes/ice-8250.fixed

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
// run-rustfix
2+
fn _f(s: &str) -> Option<()> {
3+
let _ = s[1..].split('.').next()?;
4+
Some(())
5+
}
6+
7+
fn main() {}

tests/ui/crashes/ice-8250.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
// run-rustfix
12
fn _f(s: &str) -> Option<()> {
23
let _ = s[1..].splitn(2, '.').next()?;
34
Some(())

tests/ui/crashes/ice-8250.stderr

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
error: unnecessary use of `splitn`
2-
--> $DIR/ice-8250.rs:2:13
2+
--> $DIR/ice-8250.rs:3:13
33
|
44
LL | let _ = s[1..].splitn(2, '.').next()?;
55
| ^^^^^^^^^^^^^^^^^^^^^ help: try this: `s[1..].split('.')`

0 commit comments

Comments
 (0)