about summary refs log tree commit diff
path: root/src/tools
diff options
context:
space:
mode:
authorSimonas Kazlauskas <git@kazlauskas.me>2021-06-13 18:56:13 +0300
committerSimonas Kazlauskas <git@kazlauskas.me>2021-06-24 23:13:08 +0300
commita8e6a2cd9efa19787dbbb469c202dfb922e799c6 (patch)
tree9b8430161ed004d12671bce8bcd13096a96c6328 /src/tools
parentd95745e5fa39680d97a52d0e07ed7842b163bacc (diff)
downloadrust-a8e6a2cd9efa19787dbbb469c202dfb922e799c6.tar.gz
rust-a8e6a2cd9efa19787dbbb469c202dfb922e799c6.zip
tidy: tests with --target need llvm components
Herein we verify that all of the tests that specify a `--target`
compile-flag, are also annotated with the minimal set of required llvm
components necessary to run that test.
Diffstat (limited to 'src/tools')
-rw-r--r--src/tools/tidy/src/lib.rs1
-rw-r--r--src/tools/tidy/src/main.rs2
-rw-r--r--src/tools/tidy/src/target_specific_tests.rs96
3 files changed, 99 insertions, 0 deletions
diff --git a/src/tools/tidy/src/lib.rs b/src/tools/tidy/src/lib.rs
index fcb27dae9ea..a1c41eb9981 100644
--- a/src/tools/tidy/src/lib.rs
+++ b/src/tools/tidy/src/lib.rs
@@ -47,6 +47,7 @@ pub mod extdeps;
 pub mod features;
 pub mod pal;
 pub mod style;
+pub mod target_specific_tests;
 pub mod ui_tests;
 pub mod unit_tests;
 pub mod unstable_book;
diff --git a/src/tools/tidy/src/main.rs b/src/tools/tidy/src/main.rs
index 10356a2fdc5..440c352ea53 100644
--- a/src/tools/tidy/src/main.rs
+++ b/src/tools/tidy/src/main.rs
@@ -55,6 +55,8 @@ fn main() {
             }
         }
 
+        check!(target_specific_tests, &src_path);
+
         // Checks that are done on the cargo workspace.
         check!(deps, &root_path, &cargo);
         check!(extdeps, &root_path);
diff --git a/src/tools/tidy/src/target_specific_tests.rs b/src/tools/tidy/src/target_specific_tests.rs
new file mode 100644
index 00000000000..8e1749196d2
--- /dev/null
+++ b/src/tools/tidy/src/target_specific_tests.rs
@@ -0,0 +1,96 @@
+//! Tidy check to ensure that all target specific tests (those that require a `--target` flag)
+//! also require the pre-requisite LLVM components to run.
+
+use std::collections::BTreeMap;
+use std::path::Path;
+
+const COMMENT: &str = "//";
+const LLVM_COMPONENTS_HEADER: &str = "needs-llvm-components:";
+const COMPILE_FLAGS_HEADER: &str = "compile-flags:";
+
+/// Iterate through compiletest headers in a test contents.
+///
+/// Adjusted from compiletest/src/header.rs.
+fn iter_header<'a>(contents: &'a str, it: &mut dyn FnMut(Option<&'a str>, &'a str)) {
+    for ln in contents.lines() {
+        let ln = ln.trim();
+        if ln.starts_with(COMMENT) && ln[COMMENT.len()..].trim_start().starts_with('[') {
+            if let Some(close_brace) = ln.find(']') {
+                let open_brace = ln.find('[').unwrap();
+                let lncfg = &ln[open_brace + 1..close_brace];
+                it(Some(lncfg), ln[(close_brace + 1)..].trim_start());
+            } else {
+                panic!("malformed condition directive: expected `//[foo]`, found `{}`", ln)
+            }
+        } else if ln.starts_with(COMMENT) {
+            it(None, ln[COMMENT.len()..].trim_start());
+        }
+    }
+}
+
+#[derive(Default, Debug)]
+struct RevisionInfo<'a> {
+    target_arch: Option<&'a str>,
+    llvm_components: Option<Vec<&'a str>>,
+}
+
+pub fn check(path: &Path, bad: &mut bool) {
+    let tests = path.join("test");
+    super::walk(
+        &tests,
+        &mut |path| path.extension().map(|p| p == "rs") == Some(false),
+        &mut |entry, content| {
+            let file = entry.path().display();
+            let mut header_map = BTreeMap::new();
+            iter_header(content, &mut |cfg, directive| {
+                if let Some(value) = directive.strip_prefix(LLVM_COMPONENTS_HEADER) {
+                    let info = header_map.entry(cfg).or_insert(RevisionInfo::default());
+                    let comp_vec = info.llvm_components.get_or_insert(Vec::new());
+                    for component in value.split(' ') {
+                        let component = component.trim();
+                        if !component.is_empty() {
+                            comp_vec.push(component);
+                        }
+                    }
+                } else if directive.starts_with(COMPILE_FLAGS_HEADER) {
+                    let compile_flags = &directive[COMPILE_FLAGS_HEADER.len()..];
+                    if let Some((_, v)) = compile_flags.split_once("--target") {
+                        if let Some((arch, _)) =
+                            v.trim_start_matches(|c| c == ' ' || c == '=').split_once("-")
+                        {
+                            let info = header_map.entry(cfg).or_insert(RevisionInfo::default());
+                            info.target_arch.replace(arch);
+                        } else {
+                            eprintln!("{}: seems to have a malformed --target value", file);
+                            *bad = true;
+                        }
+                    }
+                }
+            });
+            for (rev, RevisionInfo { target_arch, llvm_components }) in &header_map {
+                let rev = rev.unwrap_or("[unspecified]");
+                match (target_arch, llvm_components) {
+                    (None, None) => {}
+                    (Some(_), None) => {
+                        eprintln!(
+                            "{}: revision {} should specify `{}` as it has `--target` set",
+                            file, rev, LLVM_COMPONENTS_HEADER
+                        );
+                        *bad = true;
+                    }
+                    (None, Some(_)) => {
+                        eprintln!(
+                            "{}: revision {} should not specify `{}` as it doesn't need `--target`",
+                            file, rev, LLVM_COMPONENTS_HEADER
+                        );
+                        *bad = true;
+                    }
+                    (Some(_), Some(_)) => {
+                        // FIXME: check specified components against the target architectures we
+                        // gathered.
+                    }
+                }
+            }
+        },
+    );
+}