]> git.lizzy.rs Git - rust.git/blob - src/tools/tidy/src/unit_tests.rs
Auto merge of #93176 - danielhenrymantilla:stack-pinning-macro, r=m-ou-se
[rust.git] / src / tools / tidy / src / unit_tests.rs
1 //! Tidy check to ensure `#[test]` and `#[bench]` are not used directly inside `core`.
2 //!
3 //! `#![no_core]` libraries cannot be tested directly due to duplicating lang
4 //! items. All tests and benchmarks must be written externally in `core/{tests,benches}`.
5 //!
6 //! Outside of core tests and benchmarks should be outlined into separate files
7 //! named `tests.rs` or `benches.rs`, or directories named `tests` or `benches` unconfigured
8 //! during normal build.
9
10 use std::path::Path;
11
12 pub fn check(root_path: &Path, bad: &mut bool) {
13     let core = &root_path.join("core");
14     let core_tests = &core.join("tests");
15     let core_benches = &core.join("benches");
16     let is_core = |path: &Path| {
17         path.starts_with(core) && !(path.starts_with(core_tests) || path.starts_with(core_benches))
18     };
19
20     let mut skip = |path: &Path| {
21         let file_name = path.file_name().unwrap_or_default();
22         if path.is_dir() {
23             super::filter_dirs(path)
24                 || path.ends_with("src/test")
25                 || path.ends_with("src/doc")
26                 || (file_name == "tests" || file_name == "benches") && !is_core(path)
27         } else {
28             let extension = path.extension().unwrap_or_default();
29             extension != "rs"
30                 || (file_name == "tests.rs" || file_name == "benches.rs") && !is_core(path)
31                 // UI tests with different names
32                 || path.ends_with("src/thread/local/dynamic_tests.rs")
33                 || path.ends_with("src/sync/mpsc/sync_tests.rs")
34         }
35     };
36
37     super::walk(root_path, &mut skip, &mut |entry, contents| {
38         let path = entry.path();
39         let is_core = path.starts_with(core);
40         for (i, line) in contents.lines().enumerate() {
41             let line = line.trim();
42             let is_test = || line.contains("#[test]") && !line.contains("`#[test]");
43             let is_bench = || line.contains("#[bench]") && !line.contains("`#[bench]");
44             if !line.starts_with("//") && (is_test() || is_bench()) {
45                 let explanation = if is_core {
46                     "core unit tests and benchmarks must be placed into \
47                          `core/tests` or `core/benches`"
48                 } else {
49                     "unit tests and benchmarks must be placed into \
50                          separate files or directories named \
51                          `tests.rs`, `benches.rs`, `tests` or `benches`"
52                 };
53                 let name = if is_test() { "test" } else { "bench" };
54                 tidy_error!(
55                     bad,
56                     "`{}:{}` contains `#[{}]`; {}",
57                     path.display(),
58                     i + 1,
59                     name,
60                     explanation,
61                 );
62                 return;
63             }
64         }
65     });
66 }