@@ -600,7 +600,7 @@ struct TestBuildFilter {
600600 /// - --ignored: Only run ignored tests{n}
601601 /// - --include-ignored: Run both ignored and non-ignored tests{n}
602602 /// - --skip PATTERN: Skip tests that match the pattern{n}
603- /// - --exact PATTERN : Only run tests that exactly match the pattern
603+ /// - --exact: Run tests that exactly match patterns after `--`
604604 #[ arg( help_heading = None , value_name = "FILTERS_AND_ARGS" , last = true ) ]
605605 filters : Vec < String > ,
606606}
@@ -670,6 +670,24 @@ impl TestBuildFilter {
670670 run_ignored : & mut Option < RunIgnored > ,
671671 patterns : & mut TestFilterPatterns ,
672672 ) -> Result < ( ) > {
673+ // First scan to see if `--exact` is specified. If so, then everything here will be added to
674+ // `--exact`.
675+ let mut is_exact = false ;
676+ for arg in & self . filters {
677+ if arg == "--" {
678+ break ;
679+ }
680+ if arg == "--exact" {
681+ if is_exact {
682+ return Err ( ExpectedError :: test_binary_args_parse_error (
683+ "duplicated" ,
684+ vec ! [ arg. clone( ) ] ,
685+ ) ) ;
686+ }
687+ is_exact = true ;
688+ }
689+ }
690+
673691 let mut ignore_filters = Vec :: new ( ) ;
674692 let mut read_trailing_filters = false ;
675693
@@ -678,7 +696,11 @@ impl TestBuildFilter {
678696 let mut it = self . filters . iter ( ) ;
679697 while let Some ( arg) = it. next ( ) {
680698 if read_trailing_filters || !arg. starts_with ( '-' ) {
681- patterns. add_substring_pattern ( arg. clone ( ) ) ;
699+ if is_exact {
700+ patterns. add_exact_pattern ( arg. clone ( ) ) ;
701+ } else {
702+ patterns. add_substring_pattern ( arg. clone ( ) ) ;
703+ }
682704 } else if arg == "--include-ignored" {
683705 ignore_filters. push ( ( arg. clone ( ) , RunIgnored :: All ) ) ;
684706 } else if arg == "--ignored" {
@@ -695,14 +717,7 @@ impl TestBuildFilter {
695717
696718 patterns. add_skip_pattern ( skip_arg. clone ( ) ) ;
697719 } else if arg == "--exact" {
698- let exact_arg = it. next ( ) . ok_or_else ( || {
699- ExpectedError :: test_binary_args_parse_error (
700- "missing required argument" ,
701- vec ! [ arg. clone( ) ] ,
702- )
703- } ) ?;
704-
705- patterns. add_exact_pattern ( exact_arg. clone ( ) ) ;
720+ // Already handled above.
706721 } else {
707722 unsupported_args. push ( arg. clone ( ) ) ;
708723 }
@@ -2605,13 +2620,13 @@ mod tests {
26052620 // skip and exact
26062621 // ---
26072622 (
2608- "foo -- --skip my-pattern --skip your-pattern --exact exact1 pattern2" ,
2623+ "foo -- --skip my-pattern --skip your-pattern exact1 --exact pattern2" ,
26092624 {
26102625 let mut patterns = TestFilterPatterns :: default ( ) ;
26112626 patterns. add_skip_pattern ( "my-pattern" . to_owned ( ) ) ;
26122627 patterns. add_skip_pattern ( "your-pattern" . to_owned ( ) ) ;
26132628 patterns. add_exact_pattern ( "exact1" . to_owned ( ) ) ;
2614- patterns. add_substring_pattern ( "pattern2" . to_owned ( ) ) ;
2629+ patterns. add_exact_pattern ( "pattern2" . to_owned ( ) ) ;
26152630 patterns
26162631 } ,
26172632 ) ,
@@ -2622,6 +2637,7 @@ mod tests {
26222637 // ---
26232638 ( "foo -- --include-ignored --include-ignored" , "duplicated" ) ,
26242639 ( "foo -- --ignored --ignored" , "duplicated" ) ,
2640+ ( "foo -- --exact --exact" , "duplicated" ) ,
26252641 // ---
26262642 // mutually exclusive
26272643 // ---
@@ -2631,7 +2647,6 @@ mod tests {
26312647 // missing required argument
26322648 // ---
26332649 ( "foo -- --skip" , "missing required argument" ) ,
2634- ( "foo -- --exact" , "missing required argument" ) ,
26352650 // ---
26362651 // unsupported
26372652 // ---
0 commit comments