@@ -2,82 +2,153 @@ use libtest_lexarg::OutputFormat;
22
33use crate :: { cli, notify, Case , RunError , RunMode , TestContext } ;
44
5- pub struct Harness {
6- raw : std:: io:: Result < Vec < std:: ffi:: OsString > > ,
7- cases : Vec < Box < dyn Case > > ,
5+ pub trait HarnessState : sealed:: _HarnessState_is_Sealed { }
6+
7+ pub struct Harness < State : HarnessState > {
8+ state : State ,
89}
910
10- impl Harness {
11- pub fn with_env ( ) -> Self {
12- let raw = std:: env:: args_os ( ) ;
13- Self :: with_args ( raw)
11+ pub struct StateInitial {
12+ start : std:: time:: Instant ,
13+ }
14+ impl HarnessState for StateInitial { }
15+ impl sealed:: _HarnessState_is_Sealed for StateInitial { }
16+
17+ impl Harness < StateInitial > {
18+ pub fn new ( ) -> Self {
19+ Self {
20+ state : StateInitial {
21+ start : std:: time:: Instant :: now ( ) ,
22+ } ,
23+ }
1424 }
1525
16- pub fn with_args ( args : impl IntoIterator < Item = impl Into < std:: ffi :: OsString > > ) -> Self {
17- let raw = expand_args ( args ) ;
18- Self { raw, cases : vec ! [ ] }
26+ pub fn with_env ( self ) -> std:: io :: Result < Harness < StateArgs > > {
27+ let raw = std :: env :: args_os ( ) ;
28+ self . with_args ( raw)
1929 }
2030
21- pub fn discover ( & mut self , cases : impl IntoIterator < Item = impl Case + ' static > ) {
22- for case in cases {
23- self . cases . push ( Box :: new ( case) ) ;
24- }
31+ pub fn with_args (
32+ self ,
33+ args : impl IntoIterator < Item = impl Into < std:: ffi:: OsString > > ,
34+ ) -> std:: io:: Result < Harness < StateArgs > > {
35+ let raw = expand_args ( args) ?;
36+ Ok ( Harness {
37+ state : StateArgs {
38+ start : self . state . start ,
39+ raw,
40+ } ,
41+ } )
2542 }
43+ }
2644
27- pub fn main ( self ) -> ! {
28- main ( self . raw , self . cases )
45+ impl Default for Harness < StateInitial > {
46+ fn default ( ) -> Self {
47+ Self :: new ( )
2948 }
3049}
3150
32- const ERROR_EXIT_CODE : i32 = 101 ;
33-
34- fn main ( raw : std:: io:: Result < Vec < std:: ffi:: OsString > > , mut cases : Vec < Box < dyn Case > > ) -> ! {
35- let start = std:: time:: Instant :: now ( ) ;
51+ pub struct StateArgs {
52+ start : std:: time:: Instant ,
53+ raw : Vec < std:: ffi:: OsString > ,
54+ }
55+ impl HarnessState for StateArgs { }
56+ impl sealed:: _HarnessState_is_Sealed for StateArgs { }
57+
58+ impl Harness < StateArgs > {
59+ pub fn parse ( & self ) -> Result < Harness < StateParsed > , cli:: LexError < ' _ > > {
60+ let mut parser = cli:: Parser :: new ( & self . state . raw ) ;
61+ let opts = parse ( & mut parser) ?;
62+
63+ #[ cfg( feature = "color" ) ]
64+ match opts. color {
65+ libtest_lexarg:: ColorConfig :: AutoColor => anstream:: ColorChoice :: Auto ,
66+ libtest_lexarg:: ColorConfig :: AlwaysColor => anstream:: ColorChoice :: Always ,
67+ libtest_lexarg:: ColorConfig :: NeverColor => anstream:: ColorChoice :: Never ,
68+ }
69+ . write_global ( ) ;
3670
37- let raw = match raw {
38- Ok ( raw) => raw,
39- Err ( err) => {
71+ let notifier = notifier ( & opts) . unwrap_or_else ( |err| {
4072 eprintln ! ( "{err}" ) ;
4173 std:: process:: exit ( 1 )
42- }
43- } ;
44- let mut parser = cli:: Parser :: new ( & raw ) ;
45- let opts = parse ( & mut parser) . unwrap_or_else ( |err| {
46- eprintln ! ( "{err}" ) ;
47- std:: process:: exit ( 1 )
48- } ) ;
74+ } ) ;
75+
76+ Ok ( Harness {
77+ state : StateParsed {
78+ start : self . state . start ,
79+ opts,
80+ notifier,
81+ } ,
82+ } )
83+ }
84+ }
4985
50- #[ cfg( feature = "color" ) ]
51- match opts. color {
52- libtest_lexarg:: ColorConfig :: AutoColor => anstream:: ColorChoice :: Auto ,
53- libtest_lexarg:: ColorConfig :: AlwaysColor => anstream:: ColorChoice :: Always ,
54- libtest_lexarg:: ColorConfig :: NeverColor => anstream:: ColorChoice :: Never ,
86+ pub struct StateParsed {
87+ start : std:: time:: Instant ,
88+ opts : libtest_lexarg:: TestOpts ,
89+ notifier : Box < dyn notify:: Notifier > ,
90+ }
91+ impl HarnessState for StateParsed { }
92+ impl sealed:: _HarnessState_is_Sealed for StateParsed { }
93+
94+ impl Harness < StateParsed > {
95+ pub fn discover (
96+ mut self ,
97+ cases : impl IntoIterator < Item = impl Case + ' static > ,
98+ ) -> std:: io:: Result < Harness < StateDiscovered > > {
99+ let mut cases = cases
100+ . into_iter ( )
101+ . map ( |c| Box :: new ( c) as Box < dyn Case > )
102+ . collect ( ) ;
103+ discover (
104+ & self . state . start ,
105+ & self . state . opts ,
106+ & mut cases,
107+ self . state . notifier . as_mut ( ) ,
108+ ) ?;
109+ Ok ( Harness {
110+ state : StateDiscovered {
111+ start : self . state . start ,
112+ opts : self . state . opts ,
113+ notifier : self . state . notifier ,
114+ cases,
115+ } ,
116+ } )
55117 }
56- . write_global ( ) ;
118+ }
57119
58- let mut notifier = notifier ( & opts ) . unwrap_or_else ( |err| {
59- eprintln ! ( "{err}" ) ;
60- std :: process :: exit ( 1 )
61- } ) ;
62- discover ( & start , & opts , & mut cases, notifier . as_mut ( ) ) . unwrap_or_else ( |err| {
63- eprintln ! ( "{err}" ) ;
64- std :: process :: exit ( 1 )
65- } ) ;
120+ pub struct StateDiscovered {
121+ start : std :: time :: Instant ,
122+ opts : libtest_lexarg :: TestOpts ,
123+ notifier : Box < dyn notify :: Notifier > ,
124+ cases : Vec < Box < dyn Case > > ,
125+ }
126+ impl HarnessState for StateDiscovered { }
127+ impl sealed :: _HarnessState_is_Sealed for StateDiscovered { }
66128
67- if !opts. list {
68- match run ( & start, & opts, cases, notifier. as_mut ( ) ) {
69- Ok ( true ) => { }
70- Ok ( false ) => std:: process:: exit ( ERROR_EXIT_CODE ) ,
71- Err ( e) => {
72- eprintln ! ( "error: io error when listing tests: {e:?}" ) ;
73- std:: process:: exit ( ERROR_EXIT_CODE )
74- }
129+ impl Harness < StateDiscovered > {
130+ pub fn run ( mut self ) -> std:: io:: Result < bool > {
131+ if self . state . opts . list {
132+ Ok ( true )
133+ } else {
134+ run (
135+ & self . state . start ,
136+ & self . state . opts ,
137+ self . state . cases ,
138+ self . state . notifier . as_mut ( ) ,
139+ )
75140 }
76141 }
142+ }
77143
78- std:: process:: exit ( 0 )
144+ mod sealed {
145+ #[ allow( unnameable_types) ]
146+ #[ allow( non_camel_case_types) ]
147+ pub trait _HarnessState_is_Sealed { }
79148}
80149
150+ pub const ERROR_EXIT_CODE : i32 = 101 ;
151+
81152fn parse < ' p > ( parser : & mut cli:: Parser < ' p > ) -> Result < libtest_lexarg:: TestOpts , cli:: LexError < ' p > > {
82153 let mut test_opts = libtest_lexarg:: TestOptsBuilder :: new ( ) ;
83154
0 commit comments