]> git.proxmox.com Git - rustc.git/blob - src/tools/tidy/src/ui_tests.rs
New upstream version 1.75.0+dfsg1
[rustc.git] / src / tools / tidy / src / ui_tests.rs
1 //! Tidy check to ensure below in UI test directories:
2 //! - the number of entries in each directory must be less than `ENTRY_LIMIT`
3 //! - there are no stray `.stderr` files
4
5 use ignore::Walk;
6 use std::collections::HashMap;
7 use std::ffi::OsStr;
8 use std::fs;
9 use std::path::{Path, PathBuf};
10
11 const ENTRY_LIMIT: usize = 900;
12 // FIXME: The following limits should be reduced eventually.
13 const ISSUES_ENTRY_LIMIT: usize = 1854;
14 const ROOT_ENTRY_LIMIT: usize = 867;
15
16 const EXPECTED_TEST_FILE_EXTENSIONS: &[&str] = &[
17 "rs", // test source files
18 "stderr", // expected stderr file, corresponds to a rs file
19 "stdout", // expected stdout file, corresponds to a rs file
20 "fixed", // expected source file after applying fixes
21 "md", // test directory descriptions
22 "ftl", // translation tests
23 ];
24
25 const EXTENSION_EXCEPTION_PATHS: &[&str] = &[
26 "tests/ui/asm/named-asm-labels.s", // loading an external asm file to test named labels lint
27 "tests/ui/check-cfg/my-awesome-platform.json", // testing custom targets with cfgs
28 "tests/ui/commandline-argfile-badutf8.args", // passing args via a file
29 "tests/ui/commandline-argfile.args", // passing args via a file
30 "tests/ui/crate-loading/auxiliary/libfoo.rlib", // testing loading a manually created rlib
31 "tests/ui/include-macros/data.bin", // testing including data with the include macros
32 "tests/ui/include-macros/file.txt", // testing including data with the include macros
33 "tests/ui/macros/macro-expanded-include/file.txt", // testing including data with the include macros
34 "tests/ui/macros/not-utf8.bin", // testing including data with the include macros
35 "tests/ui/macros/syntax-extension-source-utils-files/includeme.fragment", // more include
36 "tests/ui/unused-crate-deps/test.mk", // why would you use make
37 "tests/ui/proc-macro/auxiliary/included-file.txt", // more include
38 "tests/ui/invalid/foo.natvis.xml", // sample debugger visualizer
39 ];
40
41 fn check_entries(tests_path: &Path, bad: &mut bool) {
42 let mut directories: HashMap<PathBuf, usize> = HashMap::new();
43
44 for dir in Walk::new(&tests_path.join("ui")) {
45 if let Ok(entry) = dir {
46 let parent = entry.path().parent().unwrap().to_path_buf();
47 *directories.entry(parent).or_default() += 1;
48 }
49 }
50
51 let (mut max, mut max_root, mut max_issues) = (0usize, 0usize, 0usize);
52 for (dir_path, count) in directories {
53 // Use special values for these dirs.
54 let is_root = tests_path.join("ui") == dir_path;
55 let is_issues_dir = tests_path.join("ui/issues") == dir_path;
56 let (limit, maxcnt) = if is_root {
57 (ROOT_ENTRY_LIMIT, &mut max_root)
58 } else if is_issues_dir {
59 (ISSUES_ENTRY_LIMIT, &mut max_issues)
60 } else {
61 (ENTRY_LIMIT, &mut max)
62 };
63 *maxcnt = (*maxcnt).max(count);
64 if count > limit {
65 tidy_error!(
66 bad,
67 "following path contains more than {} entries, \
68 you should move the test to some relevant subdirectory (current: {}): {}",
69 limit,
70 count,
71 dir_path.display()
72 );
73 }
74 }
75 if ROOT_ENTRY_LIMIT > max_root {
76 tidy_error!(
77 bad,
78 "`ROOT_ENTRY_LIMIT` is too high (is {ROOT_ENTRY_LIMIT}, should be {max_root})"
79 );
80 }
81 if ISSUES_ENTRY_LIMIT > max_issues {
82 tidy_error!(
83 bad,
84 "`ISSUES_ENTRY_LIMIT` is too high (is {ISSUES_ENTRY_LIMIT}, should be {max_issues})"
85 );
86 }
87 }
88
89 pub fn check(path: &Path, bad: &mut bool) {
90 check_entries(&path, bad);
91 let (ui, ui_fulldeps) = (path.join("ui"), path.join("ui-fulldeps"));
92 let paths = [ui.as_path(), ui_fulldeps.as_path()];
93 crate::walk::walk_no_read(&paths, |_, _| false, &mut |entry| {
94 let file_path = entry.path();
95 if let Some(ext) = file_path.extension().and_then(OsStr::to_str) {
96 // files that are neither an expected extension or an exception should not exist
97 // they're probably typos or not meant to exist
98 if !(EXPECTED_TEST_FILE_EXTENSIONS.contains(&ext)
99 || EXTENSION_EXCEPTION_PATHS.iter().any(|path| file_path.ends_with(path)))
100 {
101 tidy_error!(bad, "file {} has unexpected extension {}", file_path.display(), ext);
102 }
103 if ext == "stderr" || ext == "stdout" || ext == "fixed" {
104 // Test output filenames have one of the formats:
105 // ```
106 // $testname.stderr
107 // $testname.$mode.stderr
108 // $testname.$revision.stderr
109 // $testname.$revision.$mode.stderr
110 // ```
111 //
112 // For now, just make sure that there is a corresponding
113 // `$testname.rs` file.
114 //
115 // NB: We do not use file_stem() as some file names have multiple `.`s and we
116 // must strip all of them.
117 let testname =
118 file_path.file_name().unwrap().to_str().unwrap().split_once('.').unwrap().0;
119 if !file_path.with_file_name(testname).with_extension("rs").exists()
120 && !testname.contains("ignore-tidy")
121 {
122 tidy_error!(bad, "Stray file with UI testing output: {:?}", file_path);
123 }
124
125 if let Ok(metadata) = fs::metadata(file_path) {
126 if metadata.len() == 0 {
127 tidy_error!(bad, "Empty file with UI testing output: {:?}", file_path);
128 }
129 }
130 }
131 }
132 });
133 }