about summary refs log tree commit diff
diff options
context:
space:
mode:
authorMazdak Farrokhzad <twingoow@gmail.com>2019-07-28 03:01:51 +0200
committerGitHub <noreply@github.com>2019-07-28 03:01:51 +0200
commitc3c03098d8fc1679762810fa2d18926baca47148 (patch)
tree2a9fd54455265a248eaa582c8d781a5b005de5f2
parentfb6fdd4682235be20b8839d2ed39fac7e082d74e (diff)
parentaecaa03cf607d92d5ef5346400dd5302de8e5303 (diff)
downloadrust-c3c03098d8fc1679762810fa2d18926baca47148.tar.gz
rust-c3c03098d8fc1679762810fa2d18926baca47148.zip
Rollup merge of #62996 - petrochenkov:outest, r=Mark-Simulacrum
tidy: Add a check for inline unit tests

As described in https://github.com/rust-lang/rust/issues/61097.

There's a large whitelist right now, because in many crates the tests are not outlined yet.
~This PR only outlines tests in one crate (`rustc_lexer`) as an example.~

r? @Mark-Simulacrum
-rw-r--r--src/tools/tidy/src/lib.rs2
-rw-r--r--src/tools/tidy/src/libcoretest.rs28
-rw-r--r--src/tools/tidy/src/main.rs2
-rw-r--r--src/tools/tidy/src/unit_tests.rs95
4 files changed, 97 insertions, 30 deletions
diff --git a/src/tools/tidy/src/lib.rs b/src/tools/tidy/src/lib.rs
index 06c1a8c18ba..3d40bdced63 100644
--- a/src/tools/tidy/src/lib.rs
+++ b/src/tools/tidy/src/lib.rs
@@ -38,8 +38,8 @@ pub mod pal;
 pub mod deps;
 pub mod extdeps;
 pub mod ui_tests;
+pub mod unit_tests;
 pub mod unstable_book;
-pub mod libcoretest;
 
 fn filter_dirs(path: &Path) -> bool {
     let skip = [
diff --git a/src/tools/tidy/src/libcoretest.rs b/src/tools/tidy/src/libcoretest.rs
deleted file mode 100644
index 579a20e1142..00000000000
--- a/src/tools/tidy/src/libcoretest.rs
+++ /dev/null
@@ -1,28 +0,0 @@
-//! Tidy check to ensure `#[test]` is not used directly inside `libcore`.
-//!
-//! `#![no_core]` libraries cannot be tested directly due to duplicating lang
-//! item. All tests must be written externally in `libcore/tests`.
-
-use std::path::Path;
-
-pub fn check(path: &Path, bad: &mut bool) {
-    let libcore_path = path.join("libcore");
-    super::walk(
-        &libcore_path,
-        &mut |subpath| t!(subpath.strip_prefix(&libcore_path)).starts_with("tests"),
-        &mut |entry, contents| {
-            let subpath = entry.path();
-            if let Some("rs") = subpath.extension().and_then(|e| e.to_str()) {
-                let contents = contents.trim();
-                if !contents.starts_with("//") && contents.contains("#[test]") {
-                    tidy_error!(
-                        bad,
-                        "`{}` contains `#[test]`; libcore tests must be placed inside \
-                        `src/libcore/tests/`",
-                        subpath.display()
-                    );
-                }
-            }
-        },
-    );
-}
diff --git a/src/tools/tidy/src/main.rs b/src/tools/tidy/src/main.rs
index 918762ed6e6..19f02f0a96e 100644
--- a/src/tools/tidy/src/main.rs
+++ b/src/tools/tidy/src/main.rs
@@ -27,7 +27,7 @@ fn main() {
     let collected = features::check(&path, &mut bad, verbose);
     pal::check(&path, &mut bad);
     unstable_book::check(&path, collected, &mut bad);
-    libcoretest::check(&path, &mut bad);
+    unit_tests::check(&path, &mut bad);
     if !args.iter().any(|s| *s == "--no-vendor") {
         deps::check(&path, &mut bad);
     }
diff --git a/src/tools/tidy/src/unit_tests.rs b/src/tools/tidy/src/unit_tests.rs
new file mode 100644
index 00000000000..b789e5cfd48
--- /dev/null
+++ b/src/tools/tidy/src/unit_tests.rs
@@ -0,0 +1,95 @@
+//! Tidy check to ensure `#[test]` and `#[bench]` are not used directly inside
+//! `libcore` or `liballoc`.
+//!
+//! `#![no_std]` libraries cannot be tested directly due to duplicating lang
+//! items. All tests and benchmarks must be written externally in `libcore/{tests,benches}`
+//! or `liballoc/{tests,benches}`.
+//!
+//! Outside of libcore and liballoc tests and benchmarks should be outlined into separate files
+//! named `tests.rs` or `benches.rs`, or directories named `tests` or `benches` unconfigured
+//! during normal build.
+
+use std::path::Path;
+
+pub fn check(root_path: &Path, bad: &mut bool) {
+    let libcore = &root_path.join("libcore");
+    let liballoc = &root_path.join("liballoc");
+    let libcore_tests = &root_path.join("libcore/tests");
+    let liballoc_tests = &root_path.join("liballoc/tests");
+    let libcore_benches = &root_path.join("libcore/benches");
+    let liballoc_benches = &root_path.join("liballoc/benches");
+    let is_core_or_alloc = |path: &Path| {
+        let is_core = path.starts_with(libcore) &&
+                      !(path.starts_with(libcore_tests) || path.starts_with(libcore_benches));
+        let is_alloc = path.starts_with(liballoc) &&
+                       !(path.starts_with(liballoc_tests) || path.starts_with(liballoc_benches));
+        is_core || is_alloc
+    };
+    let fixme = [
+        "liballoc",
+        "libpanic_unwind/dwarf",
+        "librustc",
+        "librustc_data_structures",
+        "librustc_incremental/persist",
+        "librustc_lexer/src",
+        "librustc_target/spec",
+        "librustdoc",
+        "libserialize",
+        "libstd",
+        "libsyntax",
+        "libsyntax_pos",
+        "libterm/terminfo",
+        "libtest",
+        "tools/compiletest/src",
+        "tools/tidy/src",
+    ];
+
+    let mut skip = |path: &Path| {
+        let file_name = path.file_name().unwrap_or_default();
+        if path.is_dir() {
+            super::filter_dirs(path) ||
+            path.ends_with("src/test") ||
+            path.ends_with("src/doc") ||
+            (file_name == "tests" || file_name == "benches") && !is_core_or_alloc(path) ||
+            fixme.iter().any(|p| path.ends_with(p))
+        } else {
+            let extension = path.extension().unwrap_or_default();
+            extension != "rs" ||
+            (file_name == "tests.rs" || file_name == "benches.rs") && !is_core_or_alloc(path)
+        }
+    };
+
+    super::walk(
+        root_path,
+        &mut skip,
+        &mut |entry, contents| {
+            let path = entry.path();
+            let is_libcore = path.starts_with(libcore);
+            let is_liballoc = path.starts_with(liballoc);
+            for (i, line) in contents.lines().enumerate() {
+                let line = line.trim();
+                let is_test = || line.contains("#[test]") && !line.contains("`#[test]");
+                let is_bench = || line.contains("#[bench]") && !line.contains("`#[bench]");
+                if !line.starts_with("//") && (is_test() || is_bench()) {
+                    let explanation = if is_libcore {
+                        "libcore unit tests and benchmarks must be placed into \
+                         `libcore/tests` or `libcore/benches`"
+                    } else if is_liballoc {
+                        "liballoc unit tests and benchmarks must be placed into \
+                         `liballoc/tests` or `liballoc/benches`"
+                    } else {
+                        "unit tests and benchmarks must be placed into \
+                         separate files or directories named \
+                         `tests.rs`, `benches.rs`, `tests` or `benches`"
+                    };
+                    let name = if is_test() { "test" } else { "bench" };
+                    tidy_error!(
+                        bad, "`{}:{}` contains `#[{}]`; {}",
+                        path.display(), i + 1, name, explanation,
+                    );
+                    return;
+                }
+            }
+        },
+    );
+}