Skip to content

Commit 2dd05e8

Browse files
committedMar 9, 2024
Error on invalid compiletest directives in Rust test files
1 parent b054da8 commit 2dd05e8

File tree

7 files changed

+171
-31
lines changed

7 files changed

+171
-31
lines changed
 

‎src/tools/compiletest/src/header.rs

+96-31
Original file line numberDiff line numberDiff line change
@@ -680,7 +680,8 @@ pub fn line_directive<'line>(
680680
/// This is generated by collecting directives from ui tests and then extracting their directive
681681
/// names. This is **not** an exhaustive list of all possible directives. Instead, this is a
682682
/// best-effort approximation for diagnostics.
683-
const DIAGNOSTICS_DIRECTIVE_NAMES: &[&str] = &[
683+
const KNOWN_DIRECTIVE_NAMES: &[&str] = &[
684+
// tidy-alphabetical-start
684685
"assembly-output",
685686
"aux-build",
686687
"aux-crate",
@@ -693,6 +694,7 @@ const DIAGNOSTICS_DIRECTIVE_NAMES: &[&str] = &[
693694
"check-stdout",
694695
"check-test-line-numbers-match",
695696
"compile-flags",
697+
"count",
696698
"dont-check-compiler-stderr",
697699
"dont-check-compiler-stdout",
698700
"dont-check-failure-status",
@@ -716,6 +718,7 @@ const DIAGNOSTICS_DIRECTIVE_NAMES: &[&str] = &[
716718
"ignore-compare-mode-polonius",
717719
"ignore-cross-compile",
718720
"ignore-debug",
721+
"ignore-eabi",
719722
"ignore-emscripten",
720723
"ignore-endian-big",
721724
"ignore-freebsd",
@@ -731,14 +734,30 @@ const DIAGNOSTICS_DIRECTIVE_NAMES: &[&str] = &[
731734
"ignore-lldb",
732735
"ignore-llvm-version",
733736
"ignore-loongarch64",
737+
"ignore-macabi",
734738
"ignore-macos",
739+
"ignore-mode-assembly",
740+
"ignore-mode-codegen",
741+
"ignore-mode-codegen-units",
735742
"ignore-mode-coverage-map",
736743
"ignore-mode-coverage-run",
744+
"ignore-mode-debuginfo",
745+
"ignore-mode-incremental",
746+
"ignore-mode-js-doc-test",
747+
"ignore-mode-mir-opt",
748+
"ignore-mode-pretty",
749+
"ignore-mode-run-make",
750+
"ignore-mode-run-pass-valgrind",
751+
"ignore-mode-rustdoc",
752+
"ignore-mode-rustdoc-json",
753+
"ignore-mode-ui",
754+
"ignore-mode-ui-fulldeps",
737755
"ignore-msp430",
738756
"ignore-msvc",
739757
"ignore-musl",
740758
"ignore-netbsd",
741759
"ignore-nightly",
760+
"ignore-none",
742761
"ignore-nto",
743762
"ignore-nvptx64",
744763
"ignore-openbsd",
@@ -750,35 +769,47 @@ const DIAGNOSTICS_DIRECTIVE_NAMES: &[&str] = &[
750769
"ignore-spirv",
751770
"ignore-stable",
752771
"ignore-stage1",
772+
"ignore-stage2",
753773
"ignore-test",
774+
"ignore-thumb",
754775
"ignore-thumbv8m.base-none-eabi",
755776
"ignore-thumbv8m.main-none-eabi",
777+
"ignore-unix",
778+
"ignore-unknown",
756779
"ignore-uwp",
757780
"ignore-vxworks",
781+
"ignore-wasi",
758782
"ignore-wasm",
759783
"ignore-wasm32",
760784
"ignore-wasm32-bare",
785+
"ignore-wasm64",
761786
"ignore-windows",
762787
"ignore-windows-gnu",
788+
"ignore-x32",
763789
"ignore-x86",
790+
"ignore-x86_64",
764791
"ignore-x86_64-apple-darwin",
792+
"ignore-x86_64-unknown-linux-gnu",
765793
"incremental",
766794
"known-bug",
767795
"llvm-cov-flags",
768796
"min-cdb-version",
769797
"min-gdb-version",
770798
"min-lldb-version",
771799
"min-llvm-version",
800+
"min-system-llvm-version",
772801
"needs-asm-support",
773802
"needs-dlltool",
774803
"needs-dynamic-linking",
804+
"needs-git-hash",
775805
"needs-llvm-components",
776806
"needs-profiler-support",
777807
"needs-relocation-model-pic",
778808
"needs-run-enabled",
779809
"needs-rust-lldb",
780810
"needs-sanitizer-address",
781811
"needs-sanitizer-cfi",
812+
"needs-sanitizer-dataflow",
782813
"needs-sanitizer-hwaddress",
783814
"needs-sanitizer-leak",
784815
"needs-sanitizer-memory",
@@ -801,6 +832,7 @@ const DIAGNOSTICS_DIRECTIVE_NAMES: &[&str] = &[
801832
"only-aarch64",
802833
"only-arm",
803834
"only-avr",
835+
"only-beta",
804836
"only-bpf",
805837
"only-cdb",
806838
"only-gnu",
@@ -818,13 +850,15 @@ const DIAGNOSTICS_DIRECTIVE_NAMES: &[&str] = &[
818850
"only-riscv64",
819851
"only-sparc",
820852
"only-sparc64",
853+
"only-stable",
821854
"only-thumb",
822855
"only-wasm32",
823856
"only-wasm32-bare",
824857
"only-windows",
825858
"only-x86",
826859
"only-x86_64",
827860
"only-x86_64-fortanix-unknown-sgx",
861+
"only-x86_64-pc-windows-gnu",
828862
"only-x86_64-pc-windows-msvc",
829863
"only-x86_64-unknown-linux-gnu",
830864
"pp-exact",
@@ -846,6 +880,7 @@ const DIAGNOSTICS_DIRECTIVE_NAMES: &[&str] = &[
846880
"unit-test",
847881
"unset-exec-env",
848882
"unset-rustc-env",
883+
// tidy-alphabetical-end
849884
];
850885

851886
/// The broken-down contents of a line containing a test header directive,
@@ -876,6 +911,22 @@ struct HeaderLine<'ln> {
876911
directive: &'ln str,
877912
}
878913

914+
pub(crate) struct CheckDirectiveResult<'ln> {
915+
is_known_directive: bool,
916+
directive_name: &'ln str,
917+
}
918+
919+
// Returns `(is_known_directive, directive_name)`.
920+
pub(crate) fn check_directive(directive_ln: &str) -> CheckDirectiveResult<'_> {
921+
let directive_name =
922+
directive_ln.split_once([':', ' ']).map(|(pre, _)| pre).unwrap_or(directive_ln);
923+
924+
CheckDirectiveResult {
925+
is_known_directive: KNOWN_DIRECTIVE_NAMES.contains(&directive_name),
926+
directive_name: directive_ln,
927+
}
928+
}
929+
879930
fn iter_header(
880931
mode: Mode,
881932
_suite: &str,
@@ -915,6 +966,7 @@ fn iter_header(
915966
let mut ln = String::new();
916967
let mut line_number = 0;
917968

969+
// Match on error annotations like `//~ERROR`.
918970
static REVISION_MAGIC_COMMENT_RE: Lazy<Regex> =
919971
Lazy::new(|| Regex::new("//(\\[.*\\])?~.*").unwrap());
920972

@@ -933,9 +985,38 @@ fn iter_header(
933985
if ln.starts_with("fn") || ln.starts_with("mod") {
934986
return;
935987

936-
// First try to accept `ui_test` style comments
937-
} else if let Some((header_revision, directive)) = line_directive(comment, ln) {
938-
it(HeaderLine { line_number, original_line, header_revision, directive });
988+
// First try to accept `ui_test` style comments (`//@`)
989+
} else if let Some((header_revision, non_revisioned_directive_line)) =
990+
line_directive(comment, ln)
991+
{
992+
// Perform unknown directive check on Rust files.
993+
if testfile.extension().map(|e| e == "rs").unwrap_or(false) {
994+
let directive_ln = non_revisioned_directive_line.trim();
995+
996+
let CheckDirectiveResult { is_known_directive, .. } = check_directive(directive_ln);
997+
998+
if !is_known_directive {
999+
*poisoned = true;
1000+
1001+
eprintln!(
1002+
"error: detected unknown compiletest test directive `{}` in {}:{}",
1003+
directive_ln,
1004+
testfile.display(),
1005+
line_number,
1006+
);
1007+
1008+
return;
1009+
}
1010+
}
1011+
1012+
it(HeaderLine {
1013+
line_number,
1014+
original_line,
1015+
header_revision,
1016+
directive: non_revisioned_directive_line,
1017+
});
1018+
// Then we try to check for legacy-style candidates, which are not the magic ~ERROR family
1019+
// error annotations.
9391020
} else if !REVISION_MAGIC_COMMENT_RE.is_match(ln) {
9401021
let Some((_, rest)) = line_directive("//", ln) else {
9411022
continue;
@@ -949,34 +1030,18 @@ fn iter_header(
9491030

9501031
let rest = rest.trim_start();
9511032

952-
for candidate in DIAGNOSTICS_DIRECTIVE_NAMES.iter() {
953-
if rest.starts_with(candidate) {
954-
let Some(prefix_removed) = rest.strip_prefix(candidate) else {
955-
// We have a comment that's *successfully* parsed as an legacy-style
956-
// directive. We emit an error here to warn the user.
957-
*poisoned = true;
958-
eprintln!(
959-
"error: detected legacy-style directives in compiletest test: {}:{}, please use `ui_test`-style directives `//@` instead:{:#?}",
960-
testfile.display(),
961-
line_number,
962-
line_directive("//", ln),
963-
);
964-
return;
965-
};
1033+
let CheckDirectiveResult { is_known_directive, directive_name } = check_directive(rest);
9661034

967-
if prefix_removed.starts_with([' ', ':']) {
968-
// We have a comment that's *successfully* parsed as an legacy-style
969-
// directive. We emit an error here to warn the user.
970-
*poisoned = true;
971-
eprintln!(
972-
"error: detected legacy-style directives in compiletest test: {}:{}, please use `ui_test`-style directives `//@` instead:{:#?}",
973-
testfile.display(),
974-
line_number,
975-
line_directive("//", ln),
976-
);
977-
return;
978-
}
979-
}
1035+
if is_known_directive {
1036+
*poisoned = true;
1037+
eprintln!(
1038+
"error: detected legacy-style directive {} in compiletest test: {}:{}, please use `ui_test`-style directives `//@` instead: {:#?}",
1039+
directive_name,
1040+
testfile.display(),
1041+
line_number,
1042+
line_directive("//", ln),
1043+
);
1044+
return;
9801045
}
9811046
}
9821047
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
//@ check-pass
2+
3+
//~ HELP
4+
fn main() {} //~ERROR
5+
//~^ ERROR
6+
//~| ERROR
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
//! ignore-wasm
2+
//@ ignore-wasm
3+
//@ check-pass
4+
// regular comment
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
// ignore-wasm
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
# ignore-owo
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
//@ needs-headpat

‎src/tools/compiletest/src/header/tests.rs

+62
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,8 @@ use std::str::FromStr;
55
use crate::common::{Config, Debugger, Mode};
66
use crate::header::{parse_normalization_string, EarlyProps, HeadersCache};
77

8+
use super::iter_header;
9+
810
fn make_test_description<R: Read>(
911
config: &Config,
1012
name: test::TestName,
@@ -612,3 +614,63 @@ fn threads_support() {
612614
assert_eq!(check_ignore(&config, "//@ needs-threads"), !has_threads)
613615
}
614616
}
617+
618+
fn run_path(poisoned: &mut bool, path: &Path, buf: &[u8]) {
619+
let rdr = std::io::Cursor::new(&buf);
620+
iter_header(Mode::Ui, "ui", poisoned, path, rdr, &mut |_| {});
621+
}
622+
623+
#[test]
624+
fn test_unknown_directive_check() {
625+
let mut poisoned = false;
626+
run_path(
627+
&mut poisoned,
628+
Path::new("a.rs"),
629+
include_bytes!("./test-auxillary/unknown_directive.rs"),
630+
);
631+
assert!(poisoned);
632+
}
633+
634+
#[test]
635+
fn test_known_legacy_directive_check() {
636+
let mut poisoned = false;
637+
run_path(
638+
&mut poisoned,
639+
Path::new("a.rs"),
640+
include_bytes!("./test-auxillary/known_legacy_directive.rs"),
641+
);
642+
assert!(poisoned);
643+
}
644+
645+
#[test]
646+
fn test_known_directive_check_no_error() {
647+
let mut poisoned = false;
648+
run_path(
649+
&mut poisoned,
650+
Path::new("a.rs"),
651+
include_bytes!("./test-auxillary/known_directive.rs"),
652+
);
653+
assert!(!poisoned);
654+
}
655+
656+
#[test]
657+
fn test_error_annotation_no_error() {
658+
let mut poisoned = false;
659+
run_path(
660+
&mut poisoned,
661+
Path::new("a.rs"),
662+
include_bytes!("./test-auxillary/error_annotation.rs"),
663+
);
664+
assert!(!poisoned);
665+
}
666+
667+
#[test]
668+
fn test_non_rs_unknown_directive_not_checked() {
669+
let mut poisoned = false;
670+
run_path(
671+
&mut poisoned,
672+
Path::new("a.Makefile"),
673+
include_bytes!("./test-auxillary/not_rs.Makefile"),
674+
);
675+
assert!(!poisoned);
676+
}

0 commit comments

Comments
 (0)
Please sign in to comment.