2
2
3
3
use crate :: testcase:: collect_test_dirs;
4
4
use anyhow:: Result ;
5
+ use libtest_mimic:: { Arguments , Trial } ;
5
6
use runner:: Runner ;
7
+ use std:: process:: ExitCode ;
8
+ use std:: sync:: Arc ;
6
9
use std:: {
7
10
env, fs,
8
- process:: { self , Command } ,
9
- } ;
10
- use tester:: {
11
- ColorConfig , DynTestName , OutputFormat , RunIgnored , ShouldPanic , TestDesc , TestDescAndFn ,
12
- TestFn , TestType , run_tests_console,
13
- test:: { TestOpts , parse_opts} ,
11
+ process:: { self } ,
14
12
} ;
15
13
use tracing_subscriber:: FmtSubscriber ;
16
14
17
15
mod differ;
18
16
mod runner;
19
17
mod testcase;
20
18
21
- fn run ( ) -> Result < ( ) > {
19
+ pub fn run ( ) -> Result < ExitCode > {
22
20
let subscriber = FmtSubscriber :: builder ( )
23
21
. with_env_filter ( tracing_subscriber:: EnvFilter :: from_default_env ( ) )
24
22
. finish ( ) ;
25
23
tracing:: subscriber:: set_global_default ( subscriber) . expect ( "Failed to set global subscriber" ) ;
26
24
27
- let args: Vec < String > = env:: args ( ) . collect ( ) ;
28
- let opts: TestOpts = match parse_opts ( & args) {
29
- Some ( Ok ( o) ) => TestOpts {
30
- test_threads : Some ( 1 ) ,
31
- ..o
32
- } ,
33
- Some ( Err ( e) ) => {
34
- eprintln ! ( "Error parsing test options: {e}" ) ;
35
- process:: exit ( 1 ) ;
36
- }
37
- None => TestOpts {
38
- list : false ,
39
- filters : vec ! [ ] ,
40
- filter_exact : false ,
41
- force_run_in_process : false ,
42
- exclude_should_panic : false ,
43
- run_ignored : RunIgnored :: No ,
44
- run_tests : true ,
45
- bench_benchmarks : false ,
46
- logfile : None ,
47
- nocapture : false ,
48
- color : ColorConfig :: AutoColor ,
49
- format : OutputFormat :: Pretty ,
50
- test_threads : Some ( 1 ) ,
51
- skip : vec ! [ ] ,
52
- time_options : None ,
53
- options : tester:: Options {
54
- display_output : true ,
55
- panic_abort : true ,
56
- } ,
57
- } ,
58
- } ;
25
+ let mut args = Arguments :: from_args ( ) ;
26
+
27
+ // If filters are provided that look like paths (contain '/'), convert them to test names
28
+ if let Some ( filter) = & mut args. filter {
29
+ * filter = filter. replace ( '/' , "::" ) ;
30
+ }
59
31
32
+ let tests = collect_tests ( ) ?;
33
+ Ok ( libtest_mimic:: run ( & args, tests) . exit_code ( ) )
34
+ }
35
+
36
+ fn collect_tests ( ) -> Result < Vec < Trial > > {
60
37
// Find the manifest directory at compile time and locate tests in ../tests.
61
38
let manifest_dir = env ! ( "CARGO_MANIFEST_DIR" ) ;
62
39
let base = std:: path:: Path :: new ( manifest_dir)
@@ -72,77 +49,23 @@ fn run() -> Result<()> {
72
49
. expect ( "Failed to canonicalize tests directory" ) ;
73
50
tracing:: debug!( "Using output directory: {}" , output_dir. display( ) ) ;
74
51
75
- let runner = Runner {
52
+ let runner = Arc :: new ( Runner {
76
53
base_dir : base. clone ( ) ,
77
54
output_dir,
78
- } ;
55
+ } ) ;
79
56
80
57
let test_cases = collect_test_dirs ( & base) . expect ( "Failed to collect test case directories" ) ;
81
58
if test_cases. is_empty ( ) {
82
59
eprintln ! ( "No valid tests found in {}" , base. display( ) ) ;
83
60
process:: exit ( 1 ) ;
84
61
}
85
62
86
- // We build first to ensure that the tests are compiled before running them and to
87
- // passthrough stdout and stderr from cargo to help debugging.
88
- let mut cmd = Command :: new ( "cargo" ) ;
89
- let cmd = cmd. arg ( "build" ) . arg ( "--release" ) ;
90
- runner:: forward_features ( cmd) ;
91
- cmd. current_dir ( & base)
92
- . stderr ( process:: Stdio :: inherit ( ) )
93
- . stdout ( process:: Stdio :: inherit ( ) ) ;
94
- tracing:: debug!( "Running cargo command: {:?}" , cmd) ;
95
-
96
- let output = cmd. output ( ) . expect ( "build output" ) ;
97
- let exit_code = output. status . code ( ) . unwrap_or ( -1 ) ;
98
- tracing:: debug!( "Cargo build exited with code {}" , exit_code) ;
99
- if !output. status . success ( ) {
100
- tracing:: error!( "Cargo build failed" ) ;
101
- process:: exit ( exit_code) ;
102
- }
103
-
104
- let tests: Vec < TestDescAndFn > = test_cases
63
+ let trails = test_cases
105
64
. into_iter ( )
106
- . map ( |case| TestDescAndFn {
107
- desc : TestDesc {
108
- name : DynTestName ( case. to_string ( ) ) ,
109
- ignore : false ,
110
- should_panic : ShouldPanic :: No ,
111
- allow_fail : false ,
112
- test_type : TestType :: IntegrationTest ,
113
- } ,
114
- testfn : TestFn :: DynTestFn ( Box :: new ( {
115
- let runner = runner. clone ( ) ;
116
- move || {
117
- runner
118
- . run_test_case ( & case)
119
- . unwrap_or_else ( |e| panic ! ( "{}" , e) ) ;
120
- }
121
- } ) ) ,
65
+ . map ( |case| {
66
+ let runner = runner. clone ( ) ;
67
+ Trial :: test ( case. to_string ( ) , move || Ok ( runner. run_test_case ( & case) ?) )
122
68
} )
123
69
. collect ( ) ;
124
-
125
- // If filters are provided that look like paths (contain '/'), convert them to test names
126
- let opts = if opts. filters . iter ( ) . any ( |f| f. contains ( '/' ) ) {
127
- let mut new_opts = opts;
128
- new_opts. filters = new_opts
129
- . filters
130
- . into_iter ( )
131
- . map ( |filter| {
132
- if filter. contains ( '/' ) {
133
- // Convert path-like filter to test name format
134
- filter. replace ( '/' , "::" )
135
- } else {
136
- filter
137
- }
138
- } )
139
- . collect ( ) ;
140
- new_opts
141
- } else {
142
- opts
143
- } ;
144
-
145
- let passed = run_tests_console ( & opts, tests) . expect ( "Failed to run tests" ) ;
146
-
147
- process:: exit ( if passed { 0 } else { 1 } ) ;
70
+ Ok ( trails)
148
71
}
0 commit comments