use ignore::Walk;
use std::collections::HashMap;
use std::ffi::OsStr;
use std::fs;
use std::path::{Path, PathBuf};
const ENTRY_LIMIT: usize = 900;
const ISSUES_ENTRY_LIMIT: usize = 1854;
const ROOT_ENTRY_LIMIT: usize = 865;
const EXPECTED_TEST_FILE_EXTENSIONS: &[&str] = &[
"rs", "stderr", "stdout", "fixed", "md", "ftl", ];
const EXTENSION_EXCEPTION_PATHS: &[&str] = &[
"tests/ui/asm/named-asm-labels.s", "tests/ui/check-cfg/my-awesome-platform.json", "tests/ui/commandline-argfile-badutf8.args", "tests/ui/commandline-argfile.args", "tests/ui/crate-loading/auxiliary/libfoo.rlib", "tests/ui/include-macros/data.bin", "tests/ui/include-macros/file.txt", "tests/ui/macros/macro-expanded-include/file.txt", "tests/ui/macros/not-utf8.bin", "tests/ui/macros/syntax-extension-source-utils-files/includeme.fragment", "tests/ui/unused-crate-deps/test.mk", "tests/ui/proc-macro/auxiliary/included-file.txt", "tests/ui/invalid/foo.natvis.xml", ];
fn check_entries(tests_path: &Path, bad: &mut bool) {
let mut directories: HashMap<PathBuf, usize> = HashMap::new();
for dir in Walk::new(&tests_path.join("ui")) {
if let Ok(entry) = dir {
let parent = entry.path().parent().unwrap().to_path_buf();
*directories.entry(parent).or_default() += 1;
}
}
let (mut max, mut max_root, mut max_issues) = (0usize, 0usize, 0usize);
for (dir_path, count) in directories {
let is_root = tests_path.join("ui") == dir_path;
let is_issues_dir = tests_path.join("ui/issues") == dir_path;
let (limit, maxcnt) = if is_root {
(ROOT_ENTRY_LIMIT, &mut max_root)
} else if is_issues_dir {
(ISSUES_ENTRY_LIMIT, &mut max_issues)
} else {
(ENTRY_LIMIT, &mut max)
};
*maxcnt = (*maxcnt).max(count);
if count > limit {
tidy_error!(
bad,
"following path contains more than {} entries, \
you should move the test to some relevant subdirectory (current: {}): {}",
limit,
count,
dir_path.display()
);
}
}
if ROOT_ENTRY_LIMIT > max_root {
tidy_error!(
bad,
"`ROOT_ENTRY_LIMIT` is too high (is {ROOT_ENTRY_LIMIT}, should be {max_root})"
);
}
if ISSUES_ENTRY_LIMIT > max_issues {
tidy_error!(
bad,
"`ISSUES_ENTRY_LIMIT` is too high (is {ISSUES_ENTRY_LIMIT}, should be {max_issues})"
);
}
}
pub fn check(path: &Path, bad: &mut bool) {
check_entries(&path, bad);
let (ui, ui_fulldeps) = (path.join("ui"), path.join("ui-fulldeps"));
let paths = [ui.as_path(), ui_fulldeps.as_path()];
crate::walk::walk_no_read(&paths, |_, _| false, &mut |entry| {
let file_path = entry.path();
if let Some(ext) = file_path.extension().and_then(OsStr::to_str) {
if !(EXPECTED_TEST_FILE_EXTENSIONS.contains(&ext)
|| EXTENSION_EXCEPTION_PATHS.iter().any(|path| file_path.ends_with(path)))
{
tidy_error!(bad, "file {} has unexpected extension {}", file_path.display(), ext);
}
if ext == "stderr" || ext == "stdout" || ext == "fixed" {
let testname =
file_path.file_name().unwrap().to_str().unwrap().split_once('.').unwrap().0;
if !file_path.with_file_name(testname).with_extension("rs").exists()
&& !testname.contains("ignore-tidy")
{
tidy_error!(bad, "Stray file with UI testing output: {:?}", file_path);
}
if let Ok(metadata) = fs::metadata(file_path) {
if metadata.len() == 0 {
tidy_error!(bad, "Empty file with UI testing output: {:?}", file_path);
}
}
}
}
});
}