@@ -46,6 +46,8 @@ pub struct Config {
4646 /// Can be used to override what command to run instead of `cargo` to build the
4747 /// dependencies in `manifest_path`
4848 pub dependency_builder : Option < DependencyBuilder > ,
49+ /// Print one character per test instead of one line
50+ pub quiet : bool ,
4951}
5052
5153#[ derive( Debug ) ]
@@ -123,11 +125,50 @@ pub fn run_tests(mut config: Config) -> Result<()> {
123125 drop ( submit) ;
124126 } ) ;
125127
128+ // A channel for the messages emitted by the individual test threads.
129+ let ( finished_files_sender, finished_files_recv) = crossbeam:: channel:: unbounded ( ) ;
130+ enum TestResult {
131+ Ok ,
132+ Failed ,
133+ Ignored ,
134+ }
135+
136+ s. spawn ( |_| {
137+ if config. quiet {
138+ for ( i, ( _, result) ) in finished_files_recv. into_iter ( ) . enumerate ( ) {
139+ // Humans start counting at 1
140+ let i = i + 1 ;
141+ match result {
142+ TestResult :: Ok => eprint ! ( "{}" , "." . green( ) ) ,
143+ TestResult :: Failed => eprint ! ( "{}" , "F" . red( ) . bold( ) ) ,
144+ TestResult :: Ignored => eprint ! ( "{}" , "i" . yellow( ) ) ,
145+ }
146+ if i % 100 == 0 {
147+ eprintln ! ( " {i}" ) ;
148+ }
149+ }
150+ } else {
151+ for ( msg, result) in finished_files_recv {
152+ eprint ! ( "{msg} ... " ) ;
153+ eprintln ! (
154+ "{}" ,
155+ match result {
156+ TestResult :: Ok => "ok" . green( ) ,
157+ TestResult :: Failed => "FAILED" . red( ) . bold( ) ,
158+ TestResult :: Ignored => "ignored (in-test comment)" . yellow( ) ,
159+ }
160+ ) ;
161+ }
162+ }
163+ } ) ;
164+
126165 let mut threads = vec ! [ ] ;
127166
128167 // Create N worker threads that receive files to test.
129168 for _ in 0 ..std:: thread:: available_parallelism ( ) . unwrap ( ) . get ( ) {
169+ let finished_files_sender = finished_files_sender. clone ( ) ;
130170 threads. push ( s. spawn ( |_| -> Result < ( ) > {
171+ let finished_files_sender = finished_files_sender;
131172 for path in & receive {
132173 if !config. path_filter . is_empty ( ) {
133174 let path_display = path. display ( ) . to_string ( ) ;
@@ -140,11 +181,8 @@ pub fn run_tests(mut config: Config) -> Result<()> {
140181 // Ignore file if only/ignore rules do (not) apply
141182 if !test_file_conditions ( & comments, & target, & config) {
142183 ignored. fetch_add ( 1 , Ordering :: Relaxed ) ;
143- eprintln ! (
144- "{} ... {}" ,
145- path. display( ) ,
146- "ignored (in-test comment)" . yellow( )
147- ) ;
184+ finished_files_sender
185+ . send ( ( path. display ( ) . to_string ( ) , TestResult :: Ignored ) ) ?;
148186 continue ;
149187 }
150188 // Run the test for all revisions
@@ -159,12 +197,11 @@ pub fn run_tests(mut config: Config) -> Result<()> {
159197 if !revision. is_empty ( ) {
160198 write ! ( msg, "(revision `{revision}`) " ) . unwrap ( ) ;
161199 }
162- write ! ( msg, "... " ) . unwrap ( ) ;
163200 if errors. is_empty ( ) {
164- eprintln ! ( "{ msg}{}" , "ok" . green ( ) ) ;
201+ finished_files_sender . send ( ( msg, TestResult :: Ok ) ) ? ;
165202 succeeded. fetch_add ( 1 , Ordering :: Relaxed ) ;
166203 } else {
167- eprintln ! ( "{ msg}{}" , "FAILED" . red ( ) . bold ( ) ) ;
204+ finished_files_sender . send ( ( msg, TestResult :: Failed ) ) ? ;
168205 failures. lock ( ) . unwrap ( ) . push ( (
169206 path. clone ( ) ,
170207 m,
@@ -178,6 +215,7 @@ pub fn run_tests(mut config: Config) -> Result<()> {
178215 Ok ( ( ) )
179216 } ) ) ;
180217 }
218+
181219 for thread in threads {
182220 thread. join ( ) . unwrap ( ) ?;
183221 }
0 commit comments