@@ -301,6 +301,7 @@ pub enum ColorConfig {
301
301
302
302
pub struct TestOpts {
303
303
pub filter : Option < String > ,
304
+ pub filter_exact : bool ,
304
305
pub run_ignored : bool ,
305
306
pub run_tests : bool ,
306
307
pub bench_benchmarks : bool ,
@@ -317,6 +318,7 @@ impl TestOpts {
317
318
fn new ( ) -> TestOpts {
318
319
TestOpts {
319
320
filter : None ,
321
+ filter_exact : false ,
320
322
run_ignored : false ,
321
323
run_tests : false ,
322
324
bench_benchmarks : false ,
@@ -348,6 +350,7 @@ fn optgroups() -> Vec<getopts::OptGroup> {
348
350
getopts:: optmulti( "" , "skip" , "Skip tests whose names contain FILTER (this flag can \
349
351
be used multiple times)", "FILTER" ) ,
350
352
getopts:: optflag( "q" , "quiet" , "Display one character per test instead of one line" ) ,
353
+ getopts:: optflag( "" , "exact" , "Exactly match filters rather than by substring" ) ,
351
354
getopts:: optopt( "" , "color" , "Configure coloring of output:
352
355
auto = colorize if stdout is a tty and tests are run on serially (default);
353
356
always = always colorize output;
@@ -407,6 +410,7 @@ pub fn parse_opts(args: &[String]) -> Option<OptRes> {
407
410
408
411
let run_ignored = matches. opt_present ( "ignored" ) ;
409
412
let quiet = matches. opt_present ( "quiet" ) ;
413
+ let exact = matches. opt_present ( "exact" ) ;
410
414
411
415
let logfile = matches. opt_str ( "logfile" ) ;
412
416
let logfile = logfile. map ( |s| PathBuf :: from ( & s) ) ;
@@ -448,6 +452,7 @@ pub fn parse_opts(args: &[String]) -> Option<OptRes> {
448
452
449
453
let test_opts = TestOpts {
450
454
filter : filter,
455
+ filter_exact : exact,
451
456
run_ignored : run_ignored,
452
457
run_tests : run_tests,
453
458
bench_benchmarks : bench_benchmarks,
@@ -1118,14 +1123,26 @@ pub fn filter_tests(opts: &TestOpts, tests: Vec<TestDescAndFn>) -> Vec<TestDescA
1118
1123
None => filtered,
1119
1124
Some ( ref filter) => {
1120
1125
filtered. into_iter ( )
1121
- . filter ( |test| test. desc . name . as_slice ( ) . contains ( & filter[ ..] ) )
1126
+ . filter ( |test| {
1127
+ if opts. filter_exact {
1128
+ test. desc . name . as_slice ( ) == & filter[ ..]
1129
+ } else {
1130
+ test. desc . name . as_slice ( ) . contains ( & filter[ ..] )
1131
+ }
1132
+ } )
1122
1133
. collect ( )
1123
1134
}
1124
1135
} ;
1125
1136
1126
1137
// Skip tests that match any of the skip filters
1127
1138
filtered = filtered. into_iter ( )
1128
- . filter ( |t| !opts. skip . iter ( ) . any ( |sf| t. desc . name . as_slice ( ) . contains ( & sf[ ..] ) ) )
1139
+ . filter ( |t| !opts. skip . iter ( ) . any ( |sf| {
1140
+ if opts. filter_exact {
1141
+ t. desc . name . as_slice ( ) == & sf[ ..]
1142
+ } else {
1143
+ t. desc . name . as_slice ( ) . contains ( & sf[ ..] )
1144
+ }
1145
+ } ) )
1129
1146
. collect ( ) ;
1130
1147
1131
1148
// Maybe pull out the ignored test and unignore them
@@ -1654,6 +1671,77 @@ mod tests {
1654
1671
assert ! ( !filtered[ 0 ] . desc. ignore) ;
1655
1672
}
1656
1673
1674
+ #[ test]
1675
+ pub fn exact_filter_match ( ) {
1676
+ fn tests ( ) -> Vec < TestDescAndFn > {
1677
+ vec ! [ "base" ,
1678
+ "base::test" ,
1679
+ "base::test1" ,
1680
+ "base::test2" ,
1681
+ ] . into_iter ( )
1682
+ . map ( |name| TestDescAndFn {
1683
+ desc : TestDesc {
1684
+ name : StaticTestName ( name) ,
1685
+ ignore : false ,
1686
+ should_panic : ShouldPanic :: No ,
1687
+ } ,
1688
+ testfn : DynTestFn ( Box :: new ( move |( ) | { } ) )
1689
+ } )
1690
+ . collect ( )
1691
+ }
1692
+
1693
+ let substr = filter_tests ( & TestOpts {
1694
+ filter : Some ( "base" . into ( ) ) ,
1695
+ ..TestOpts :: new ( )
1696
+ } , tests ( ) ) ;
1697
+ assert_eq ! ( substr. len( ) , 4 ) ;
1698
+
1699
+ let substr = filter_tests ( & TestOpts {
1700
+ filter : Some ( "bas" . into ( ) ) ,
1701
+ ..TestOpts :: new ( )
1702
+ } , tests ( ) ) ;
1703
+ assert_eq ! ( substr. len( ) , 4 ) ;
1704
+
1705
+ let substr = filter_tests ( & TestOpts {
1706
+ filter : Some ( "::test" . into ( ) ) ,
1707
+ ..TestOpts :: new ( )
1708
+ } , tests ( ) ) ;
1709
+ assert_eq ! ( substr. len( ) , 3 ) ;
1710
+
1711
+ let substr = filter_tests ( & TestOpts {
1712
+ filter : Some ( "base::test" . into ( ) ) ,
1713
+ ..TestOpts :: new ( )
1714
+ } , tests ( ) ) ;
1715
+ assert_eq ! ( substr. len( ) , 3 ) ;
1716
+
1717
+ let exact = filter_tests ( & TestOpts {
1718
+ filter : Some ( "base" . into ( ) ) ,
1719
+ filter_exact : true , ..TestOpts :: new ( )
1720
+ } , tests ( ) ) ;
1721
+ assert_eq ! ( exact. len( ) , 1 ) ;
1722
+
1723
+ let exact = filter_tests ( & TestOpts {
1724
+ filter : Some ( "bas" . into ( ) ) ,
1725
+ filter_exact : true ,
1726
+ ..TestOpts :: new ( )
1727
+ } , tests ( ) ) ;
1728
+ assert_eq ! ( exact. len( ) , 0 ) ;
1729
+
1730
+ let exact = filter_tests ( & TestOpts {
1731
+ filter : Some ( "::test" . into ( ) ) ,
1732
+ filter_exact : true ,
1733
+ ..TestOpts :: new ( )
1734
+ } , tests ( ) ) ;
1735
+ assert_eq ! ( exact. len( ) , 0 ) ;
1736
+
1737
+ let exact = filter_tests ( & TestOpts {
1738
+ filter : Some ( "base::test" . into ( ) ) ,
1739
+ filter_exact : true ,
1740
+ ..TestOpts :: new ( )
1741
+ } , tests ( ) ) ;
1742
+ assert_eq ! ( exact. len( ) , 1 ) ;
1743
+ }
1744
+
1657
1745
#[ test]
1658
1746
pub fn sort_tests ( ) {
1659
1747
let mut opts = TestOpts :: new ( ) ;
0 commit comments