@@ -11,8 +11,7 @@ use libtest_mimic::{Arguments, Trial};
11
11
pub fn runner ( requirements : & [ Requirements ] ) -> ExitCode {
12
12
let args = Arguments :: from_args ( ) ;
13
13
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) ;
16
15
17
16
let conclusion = libtest_mimic:: run ( & args, tests) ;
18
17
@@ -25,6 +24,59 @@ pub fn runner(requirements: &[Requirements]) -> ExitCode {
25
24
conclusion. exit_code ( )
26
25
}
27
26
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
+
28
80
#[ doc( hidden) ]
29
81
pub struct Requirements {
30
82
test : TestFn ,
@@ -49,6 +101,25 @@ impl Requirements {
49
101
}
50
102
}
51
103
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
+
52
123
/// Scans all files in a given directory, finds matching ones and generates a test descriptor
53
124
/// for each of them.
54
125
fn expand ( & self ) -> Vec < Trial > {
@@ -66,13 +137,7 @@ impl Requirements {
66
137
error
67
138
)
68
139
} ) {
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) )
76
141
} else {
77
142
None
78
143
}
0 commit comments