@@ -16,9 +16,12 @@ use crate::{extract_cdb_version, extract_gdb_version};
1616#[ cfg( test) ]
1717mod tests;
1818
19- /// The result of parse_cfg_name_directive.
19+ /// Whether a given property holds true of this test instance. Usually,
20+ /// a property is something about the target (e.g. whether the target is Windows),
21+ /// but it could also be something more general (e.g. whether this test is being
22+ /// cross-compiled.)
2023#[ derive( Clone , Copy , PartialEq , Debug ) ]
21- enum ParsedNameDirective {
24+ enum EvaluatedProp {
2225 /// No match.
2326 NoMatch ,
2427 /// Match.
@@ -228,6 +231,10 @@ impl TestProps {
228231 if !testfile. is_dir ( ) {
229232 let file = File :: open ( testfile) . unwrap ( ) ;
230233
234+ let mut target = config. target . clone ( ) ;
235+ let mut per_prop_normalize_stdout: Vec < ( String , ( String , String ) ) > = Vec :: new ( ) ;
236+ let mut per_prop_normalize_stderr: Vec < ( String , ( String , String ) ) > = Vec :: new ( ) ;
237+
231238 iter_header ( testfile, file, & mut |revision, ln| {
232239 if revision. is_some ( ) && revision != cfg {
233240 return ;
@@ -340,11 +347,16 @@ impl TestProps {
340347 self . ignore_pass = config. parse_ignore_pass ( ln) ;
341348 }
342349
350+ if let Some ( target_override) = config. parse_target_override ( ln) {
351+ target = target_override;
352+ }
353+
343354 if let Some ( rule) = config. parse_custom_normalization ( ln, "normalize-stdout" ) {
344- self . normalize_stdout . push ( rule) ;
355+ per_prop_normalize_stdout . push ( rule) ;
345356 }
357+
346358 if let Some ( rule) = config. parse_custom_normalization ( ln, "normalize-stderr" ) {
347- self . normalize_stderr . push ( rule) ;
359+ per_prop_normalize_stderr . push ( rule) ;
348360 }
349361
350362 if let Some ( code) = config. parse_failure_status ( ln) {
@@ -372,6 +384,17 @@ impl TestProps {
372384 self . incremental = config. parse_incremental ( ln) ;
373385 }
374386 } ) ;
387+ for ( prop, normalization) in per_prop_normalize_stdout {
388+ if config. evaluate_prop_for_target ( & prop, & target) == EvaluatedProp :: Match {
389+ self . normalize_stdout . push ( normalization) ;
390+ }
391+ }
392+
393+ for ( prop, normalization) in per_prop_normalize_stderr {
394+ if config. evaluate_prop_for_target ( & prop, & target) == EvaluatedProp :: Match {
395+ self . normalize_stderr . push ( normalization) ;
396+ }
397+ }
375398 }
376399
377400 if self . failure_status == -1 {
@@ -650,14 +673,15 @@ impl Config {
650673 }
651674 }
652675
653- fn parse_custom_normalization ( & self , mut line : & str , prefix : & str ) -> Option < ( String , String ) > {
654- if self . parse_cfg_name_directive ( line, prefix) == ParsedNameDirective :: Match {
655- let from = parse_normalization_string ( & mut line) ?;
656- let to = parse_normalization_string ( & mut line) ?;
657- Some ( ( from, to) )
658- } else {
659- None
660- }
676+ fn parse_custom_normalization (
677+ & self ,
678+ mut line : & str ,
679+ prefix : & str ,
680+ ) -> Option < ( String , ( String , String ) ) > {
681+ let prop = self . parse_prop_directive ( line, prefix) ?;
682+ let from = parse_normalization_string ( & mut line) ?;
683+ let to = parse_normalization_string ( & mut line) ?;
684+ Some ( ( prop, ( from, to) ) )
661685 }
662686
663687 fn parse_needs_matching_clang ( & self , line : & str ) -> bool {
@@ -670,7 +694,19 @@ impl Config {
670694
671695 /// Parses a name-value directive which contains config-specific information, e.g., `ignore-x86`
672696 /// or `normalize-stderr-32bit`.
673- fn parse_cfg_name_directive ( & self , line : & str , prefix : & str ) -> ParsedNameDirective {
697+ fn parse_prop_directive ( & self , line : & str , prefix : & str ) -> Option < String > {
698+ if !line. as_bytes ( ) . starts_with ( prefix. as_bytes ( ) ) {
699+ return None ;
700+ }
701+ if line. as_bytes ( ) . get ( prefix. len ( ) ) != Some ( & b'-' ) {
702+ return None ;
703+ }
704+
705+ let config = & line[ & prefix. len ( ) + 1 ..] . to_string ( ) ;
706+ Some ( config. to_string ( ) )
707+ }
708+
709+ fn evaluate_prop_for_target ( & self , prop : & str , target : & str ) -> EvaluatedProp {
674710 // This matches optional whitespace, followed by a group containing a series of word
675711 // characters (including '_' and '-'), followed optionally by a sequence consisting
676712 // of a colon, optional whitespace, and another group containing word characters.
@@ -697,28 +733,21 @@ impl Config {
697733 static ref CFG_REGEX : Regex = Regex :: new( r"^\s*([\w-]+)(?::\s*([\w-]+))?" ) . unwrap( ) ;
698734 }
699735
700- if !line. as_bytes ( ) . starts_with ( prefix. as_bytes ( ) ) {
701- return ParsedNameDirective :: NoMatch ;
702- }
703- if line. as_bytes ( ) . get ( prefix. len ( ) ) != Some ( & b'-' ) {
704- return ParsedNameDirective :: NoMatch ;
705- }
706-
707- let captures = CFG_REGEX . captures ( & line[ & prefix. len ( ) + 1 ..] ) . unwrap ( ) ;
736+ let captures = CFG_REGEX . captures ( & prop) . unwrap ( ) ;
708737 let name = captures. get ( 1 ) . unwrap ( ) . as_str ( ) ;
709738 let maybe_value = captures. get ( 2 ) . map ( |v| v. as_str ( ) . trim ( ) ) ;
710739
711740 let is_match = name == "test" ||
712- self . target == name || // triple
713- util:: matches_os ( & self . target , name) || // target
714- util:: matches_env ( & self . target , name) || // env
715- self . target . ends_with ( name) || // target and env
716- name == util:: get_arch ( & self . target ) || // architecture
717- name == util:: get_pointer_width ( & self . target ) || // pointer width
741+ target == name || // triple
742+ util:: matches_os ( target, name) || // target
743+ util:: matches_env ( target, name) || // env
744+ target. ends_with ( name) || // target and env
745+ name == util:: get_arch ( target) || // architecture
746+ name == util:: get_pointer_width ( target) || // pointer width
718747 name == self . stage_id . split ( '-' ) . next ( ) . unwrap ( ) || // stage
719748 name == self . channel || // channel
720- ( self . target != self . host && name == "cross-compile" ) ||
721- ( name == "endian-big" && util:: is_big_endian ( & self . target ) ) ||
749+ ( target != self . host && name == "cross-compile" ) ||
750+ ( name == "endian-big" && util:: is_big_endian ( target) ) ||
722751 ( self . remote_test_client . is_some ( ) && name == "remote" ) ||
723752 match self . compare_mode {
724753 Some ( CompareMode :: Nll ) => name == "compare-mode-nll" ,
@@ -736,14 +765,17 @@ impl Config {
736765 None => false ,
737766 } ||
738767 match name. strip_prefix ( "cfg-" ) {
739- Some ( rustc_cfg_name) => util:: cfg_has ( & self . target_cfg , rustc_cfg_name, maybe_value) ,
768+ Some ( rustc_cfg_name) => {
769+ let cfg_data = util:: fetch_cfg_from_rustc_for_target ( & self . rustc_path , target) ;
770+ util:: cfg_has ( & cfg_data, rustc_cfg_name, maybe_value)
771+ } ,
740772 None => false
741773 } ;
742774
743- if is_match { ParsedNameDirective :: Match } else { ParsedNameDirective :: NoMatch }
775+ if is_match { EvaluatedProp :: Match } else { EvaluatedProp :: NoMatch }
744776 }
745777
746- fn has_cfg_prefix ( & self , line : & str , prefix : & str ) -> bool {
778+ fn has_prop_prefix ( & self , line : & str , prefix : & str ) -> bool {
747779 // returns whether this line contains this prefix or not. For prefix
748780 // "ignore", returns true if line says "ignore-x86_64", "ignore-arch",
749781 // "ignore-android" etc.
@@ -768,6 +800,21 @@ impl Config {
768800 }
769801 }
770802
803+ pub fn parse_target_override ( & self , line : & str ) -> Option < String > {
804+ let flags = self . parse_name_value_directive ( line, "compile-flags" ) ?;
805+ let ( _, tail) = flags. split_once ( "--target" ) ?;
806+ if tail. starts_with ( |c : char | c. is_whitespace ( ) || c == '=' ) {
807+ let tail = & tail[ 1 ..] ;
808+ let target = match tail. split_once ( |c : char | c. is_whitespace ( ) ) {
809+ Some ( ( target, _) ) => target,
810+ None => & tail,
811+ } ;
812+ Some ( target. to_string ( ) )
813+ } else {
814+ None
815+ }
816+ }
817+
771818 pub fn find_rust_src_root ( & self ) -> Option < PathBuf > {
772819 let mut path = self . src_base . clone ( ) ;
773820 let path_postfix = Path :: new ( "src/etc/lldb_batchmode.py" ) ;
@@ -900,6 +947,10 @@ pub fn make_test_description<R: Read>(
900947 let mut ignore = false ;
901948 let mut should_fail = false ;
902949
950+ let mut target = config. target . clone ( ) ;
951+ let mut ignored_props: Vec < String > = Vec :: new ( ) ;
952+ let mut only_test_on_props: Vec < String > = Vec :: new ( ) ;
953+
903954 let rustc_has_profiler_support = env:: var_os ( "RUSTC_PROFILER_SUPPORT" ) . is_some ( ) ;
904955 let rustc_has_sanitizer_support = env:: var_os ( "RUSTC_SANITIZER_SUPPORT" ) . is_some ( ) ;
905956 let has_asm_support = util:: has_asm_support ( & config. target ) ;
@@ -908,7 +959,6 @@ pub fn make_test_description<R: Read>(
908959 let has_msan = util:: MSAN_SUPPORTED_TARGETS . contains ( & & * config. target ) ;
909960 let has_tsan = util:: TSAN_SUPPORTED_TARGETS . contains ( & & * config. target ) ;
910961 let has_hwasan = util:: HWASAN_SUPPORTED_TARGETS . contains ( & & * config. target ) ;
911- // for `-Z gcc-ld=lld`
912962 let has_rust_lld = config
913963 . compile_lib_path
914964 . join ( "rustlib" )
@@ -921,15 +971,16 @@ pub fn make_test_description<R: Read>(
921971 if revision. is_some ( ) && revision != cfg {
922972 return ;
923973 }
924- ignore = match config. parse_cfg_name_directive ( ln, "ignore" ) {
925- ParsedNameDirective :: Match => true ,
926- ParsedNameDirective :: NoMatch => ignore,
927- } ;
928- if config. has_cfg_prefix ( ln, "only" ) {
929- ignore = match config. parse_cfg_name_directive ( ln, "only" ) {
930- ParsedNameDirective :: Match => ignore,
931- ParsedNameDirective :: NoMatch => true ,
932- } ;
974+ if let Some ( target_override) = config. parse_target_override ( ln) {
975+ target = target_override;
976+ }
977+ if let Some ( prop) = config. parse_prop_directive ( ln, "ignore" ) {
978+ ignored_props. push ( prop) ;
979+ }
980+ if config. has_prop_prefix ( ln, "only" ) {
981+ if let Some ( prop) = config. parse_prop_directive ( ln, "only" ) {
982+ only_test_on_props. push ( prop) ;
983+ }
933984 }
934985 ignore |= ignore_llvm ( config, ln) ;
935986 ignore |=
@@ -954,6 +1005,19 @@ pub fn make_test_description<R: Read>(
9541005 should_fail |= config. parse_name_directive ( ln, "should-fail" ) ;
9551006 } ) ;
9561007
1008+ for prop in ignored_props {
1009+ ignore = match config. evaluate_prop_for_target ( & prop, & target) {
1010+ EvaluatedProp :: Match => true ,
1011+ EvaluatedProp :: NoMatch => ignore,
1012+ } ;
1013+ }
1014+ for prop in only_test_on_props {
1015+ ignore = match config. evaluate_prop_for_target ( & prop, & target) {
1016+ EvaluatedProp :: Match => ignore,
1017+ EvaluatedProp :: NoMatch => true ,
1018+ } ;
1019+ }
1020+
9571021 // The `should-fail` annotation doesn't apply to pretty tests,
9581022 // since we run the pretty printer across all tests by default.
9591023 // If desired, we could add a `should-fail-pretty` annotation.
0 commit comments