@@ -11,8 +11,7 @@ use libtest_mimic::{Arguments, Trial};
1111pub fn runner ( requirements : & [ Requirements ] ) -> ExitCode {
1212 let args = Arguments :: from_args ( ) ;
1313
14- let mut tests: Vec < _ > = requirements. iter ( ) . flat_map ( |req| req. expand ( ) ) . collect ( ) ;
15- tests. sort_unstable_by ( |a, b| a. name ( ) . cmp ( b. name ( ) ) ) ;
14+ let tests = find_tests ( & args, requirements) ;
1615
1716 let conclusion = libtest_mimic:: run ( & args, tests) ;
1817
@@ -25,6 +24,59 @@ pub fn runner(requirements: &[Requirements]) -> ExitCode {
2524 conclusion. exit_code ( )
2625}
2726
27+ fn find_tests ( args : & Arguments , requirements : & [ Requirements ] ) -> Vec < Trial > {
28+ let tests: Vec < _ > = if let Some ( exact_filter) = exact_filter ( args) {
29+ let exact_tests: Vec < _ > = requirements
30+ . iter ( )
31+ . flat_map ( |req| req. exact ( exact_filter) )
32+ . collect ( ) ;
33+
34+ if is_nextest ( ) {
35+ if exact_tests. is_empty ( ) {
36+ panic ! ( "Failed to find exact match for filter {exact_filter}" ) ;
37+ } else if exact_tests. len ( ) > 1 {
38+ panic ! (
39+ "Only expected one but found {} exact matches for filter {exact_filter}" ,
40+ exact_tests. len( )
41+ ) ;
42+ }
43+ }
44+ exact_tests
45+ } else if is_full_scan_forbidden ( ) {
46+ panic ! ( "Exact filter was expected to be used" ) ;
47+ } else {
48+ let mut tests: Vec < _ > = requirements. iter ( ) . flat_map ( |req| req. expand ( ) ) . collect ( ) ;
49+ tests. sort_unstable_by ( |a, b| a. name ( ) . cmp ( b. name ( ) ) ) ;
50+ tests
51+ } ;
52+ tests
53+ }
54+
55+ fn is_nextest ( ) -> bool {
56+ std:: env:: var_os ( "NEXTEST" )
57+ . filter ( |var| var == "1" )
58+ . is_some ( )
59+ }
60+
61+ fn is_full_scan_forbidden ( ) -> bool {
62+ #[ cfg( test) ]
63+ {
64+ std:: env:: var_os ( "DATATEST_FULL_SCAN_FORBIDDEN" )
65+ . filter ( |var| var == "1" )
66+ . is_some ( )
67+ }
68+ #[ cfg( not( test) ) ]
69+ false
70+ }
71+
72+ fn exact_filter ( args : & Arguments ) -> Option < & str > {
73+ if args. exact && args. skip . is_empty ( ) {
74+ args. filter . as_deref ( )
75+ } else {
76+ None
77+ }
78+ }
79+
2880#[ doc( hidden) ]
2981pub struct Requirements {
3082 test : TestFn ,
@@ -49,6 +101,25 @@ impl Requirements {
49101 }
50102 }
51103
104+ fn trial ( & self , path : Utf8PathBuf ) -> Trial {
105+ let testfn = self . test ;
106+ let name = utils:: derive_test_name ( & self . root , & path, & self . test_name ) ;
107+ Trial :: test ( name, move || {
108+ testfn
109+ . call ( & path)
110+ . map_err ( |err| format ! ( "{:?}" , err) . into ( ) )
111+ } )
112+ }
113+
114+ fn exact ( & self , filter : & str ) -> Option < Trial > {
115+ let path = utils:: derive_test_path ( & self . root , filter, & self . test_name ) ?;
116+ if path. exists ( ) {
117+ Some ( self . trial ( path) )
118+ } else {
119+ None
120+ }
121+ }
122+
52123 /// Scans all files in a given directory, finds matching ones and generates a test descriptor
53124 /// for each of them.
54125 fn expand ( & self ) -> Vec < Trial > {
@@ -66,13 +137,7 @@ impl Requirements {
66137 error
67138 )
68139 } ) {
69- let testfn = self . test ;
70- let name = utils:: derive_test_name ( & self . root , & path, & self . test_name ) ;
71- Some ( Trial :: test ( name, move || {
72- testfn
73- . call ( & path)
74- . map_err ( |err| format ! ( "{:?}" , err) . into ( ) )
75- } ) )
140+ Some ( self . trial ( path) )
76141 } else {
77142 None
78143 }
0 commit comments