@@ -6,7 +6,6 @@ use std::io::prelude::Write;
66use std:: time:: Instant ;
77
88use super :: {
9- bench:: fmt_bench_samples,
109 cli:: TestOpts ,
1110 event:: { CompletedTest , TestEvent } ,
1211 filter_tests,
@@ -15,7 +14,7 @@ use super::{
1514 options:: { Options , OutputFormat } ,
1615 run_tests, term,
1716 test_result:: TestResult ,
18- time:: { TestExecTime , TestSuiteExecTime } ,
17+ time:: TestSuiteExecTime ,
1918 types:: { NamePadding , TestDesc , TestDescAndFn } ,
2019} ;
2120
@@ -29,20 +28,19 @@ impl<T: Write> Write for OutputLocation<T> {
2928 fn write ( & mut self , buf : & [ u8 ] ) -> io:: Result < usize > {
3029 match * self {
3130 OutputLocation :: Pretty ( ref mut term) => term. write ( buf) ,
32- OutputLocation :: Raw ( ref mut stdout ) => stdout . write ( buf) ,
31+ OutputLocation :: Raw ( ref mut stdout_or_file ) => stdout_or_file . write ( buf) ,
3332 }
3433 }
3534
3635 fn flush ( & mut self ) -> io:: Result < ( ) > {
3736 match * self {
3837 OutputLocation :: Pretty ( ref mut term) => term. flush ( ) ,
39- OutputLocation :: Raw ( ref mut stdout ) => stdout . flush ( ) ,
38+ OutputLocation :: Raw ( ref mut stdout_or_file ) => stdout_or_file . flush ( ) ,
4039 }
4140 }
4241}
4342
4443pub struct ConsoleTestState {
45- pub log_out : Option < File > ,
4644 pub total : usize ,
4745 pub passed : usize ,
4846 pub failed : usize ,
@@ -59,13 +57,7 @@ pub struct ConsoleTestState {
5957
6058impl ConsoleTestState {
6159 pub fn new ( opts : & TestOpts ) -> io:: Result < ConsoleTestState > {
62- let log_out = match opts. logfile {
63- Some ( ref path) => Some ( File :: create ( path) ?) ,
64- None => None ,
65- } ;
66-
6760 Ok ( ConsoleTestState {
68- log_out,
6961 total : 0 ,
7062 passed : 0 ,
7163 failed : 0 ,
@@ -81,54 +73,6 @@ impl ConsoleTestState {
8173 } )
8274 }
8375
84- pub fn write_log < F , S > ( & mut self , msg : F ) -> io:: Result < ( ) >
85- where
86- S : AsRef < str > ,
87- F : FnOnce ( ) -> S ,
88- {
89- match self . log_out {
90- None => Ok ( ( ) ) ,
91- Some ( ref mut o) => {
92- let msg = msg ( ) ;
93- let msg = msg. as_ref ( ) ;
94- o. write_all ( msg. as_bytes ( ) )
95- }
96- }
97- }
98-
99- pub fn write_log_result (
100- & mut self ,
101- test : & TestDesc ,
102- result : & TestResult ,
103- exec_time : Option < & TestExecTime > ,
104- ) -> io:: Result < ( ) > {
105- self . write_log ( || {
106- let TestDesc { name, ignore_message, .. } = test;
107- format ! (
108- "{} {}" ,
109- match * result {
110- TestResult :: TrOk => "ok" . to_owned( ) ,
111- TestResult :: TrFailed => "failed" . to_owned( ) ,
112- TestResult :: TrFailedMsg ( ref msg) => format!( "failed: {msg}" ) ,
113- TestResult :: TrIgnored => {
114- if let Some ( msg) = ignore_message {
115- format!( "ignored: {msg}" )
116- } else {
117- "ignored" . to_owned( )
118- }
119- }
120- TestResult :: TrBench ( ref bs) => fmt_bench_samples( bs) ,
121- TestResult :: TrTimedFail => "failed (time limit exceeded)" . to_owned( ) ,
122- } ,
123- name,
124- )
125- } ) ?;
126- if let Some ( exec_time) = exec_time {
127- self . write_log ( || format ! ( " <{exec_time}>" ) ) ?;
128- }
129- self . write_log ( || "\n " )
130- }
131-
13276 fn current_test_count ( & self ) -> usize {
13377 self . passed + self . failed + self . ignored + self . measured
13478 }
@@ -142,7 +86,11 @@ pub fn list_tests_console(opts: &TestOpts, tests: Vec<TestDescAndFn>) -> io::Res
14286 } ;
14387
14488 let quiet = opts. format == OutputFormat :: Terse ;
145- let mut st = ConsoleTestState :: new ( opts) ?;
89+
90+ let mut log_out = match & opts. logfile {
91+ None => None ,
92+ Some ( path) => Some ( OutputLocation :: Raw ( File :: create ( path) ?) ) ,
93+ } ;
14694
14795 let mut ntest = 0 ;
14896 let mut nbench = 0 ;
@@ -164,7 +112,9 @@ pub fn list_tests_console(opts: &TestOpts, tests: Vec<TestDescAndFn>) -> io::Res
164112 } ;
165113
166114 writeln ! ( output, "{name}: {fntype}" ) ?;
167- st. write_log ( || format ! ( "{fntype} {name}\n " ) ) ?;
115+ if let Some ( ref mut log_output) = log_out {
116+ writeln ! ( log_output, "{name}: {fntype}" ) ?;
117+ }
168118 }
169119
170120 fn plural ( count : u32 , s : & str ) -> String {
@@ -177,9 +127,15 @@ pub fn list_tests_console(opts: &TestOpts, tests: Vec<TestDescAndFn>) -> io::Res
177127 if !quiet {
178128 if ntest != 0 || nbench != 0 {
179129 writeln ! ( output) ?;
130+ if let Some ( ref mut log_output) = log_out {
131+ writeln ! ( log_output) ?;
132+ }
180133 }
181134
182135 writeln ! ( output, "{}, {}" , plural( ntest, "test" ) , plural( nbench, "benchmark" ) ) ?;
136+ if let Some ( ref mut log_output) = log_out {
137+ writeln ! ( log_output, "{}, {}" , plural( ntest, "test" ) , plural( nbench, "benchmark" ) ) ?;
138+ }
183139 }
184140
185141 Ok ( ( ) )
@@ -226,25 +182,41 @@ fn on_test_event(
226182 event : & TestEvent ,
227183 st : & mut ConsoleTestState ,
228184 out : & mut dyn OutputFormatter ,
185+ log_out : Option < & mut dyn OutputFormatter > ,
229186) -> io:: Result < ( ) > {
230187 match ( * event) . clone ( ) {
231188 TestEvent :: TeFiltered ( filtered_tests, shuffle_seed) => {
232189 st. total = filtered_tests;
233190 out. write_run_start ( filtered_tests, shuffle_seed) ?;
191+ if let Some ( log_output) = log_out {
192+ log_output. write_run_start ( filtered_tests, shuffle_seed) ?;
193+ }
234194 }
235195 TestEvent :: TeFilteredOut ( filtered_out) => {
236196 st. filtered_out = filtered_out;
237197 }
238- TestEvent :: TeWait ( ref test) => out. write_test_start ( test) ?,
239- TestEvent :: TeTimeout ( ref test) => out. write_timeout ( test) ?,
198+ TestEvent :: TeWait ( ref test) => {
199+ out. write_test_start ( test) ?;
200+ if let Some ( log_output) = log_out {
201+ log_output. write_test_start ( test) ?;
202+ }
203+ }
204+ TestEvent :: TeTimeout ( ref test) => {
205+ out. write_timeout ( test) ?;
206+ if let Some ( log_output) = log_out {
207+ log_output. write_timeout ( test) ?;
208+ }
209+ }
240210 TestEvent :: TeResult ( completed_test) => {
241211 let test = & completed_test. desc ;
242212 let result = & completed_test. result ;
243213 let exec_time = & completed_test. exec_time ;
244214 let stdout = & completed_test. stdout ;
245215
246- st. write_log_result ( test, result, exec_time. as_ref ( ) ) ?;
247216 out. write_result ( test, result, exec_time. as_ref ( ) , stdout, st) ?;
217+ if let Some ( log_output) = log_out {
218+ log_output. write_result ( test, result, exec_time. as_ref ( ) , stdout, st) ?;
219+ }
248220 handle_test_result ( st, completed_test) ;
249221 }
250222 }
@@ -282,6 +254,30 @@ pub fn run_tests_console(opts: &TestOpts, tests: Vec<TestDescAndFn>) -> io::Resu
282254 OutputFormat :: Json => Box :: new ( JsonFormatter :: new ( output) ) ,
283255 OutputFormat :: Junit => Box :: new ( JunitFormatter :: new ( output) ) ,
284256 } ;
257+
258+ let mut log_out: Option < Box < dyn OutputFormatter > > = match & opts. logfile {
259+ None => None ,
260+ Some ( path) => {
261+ let log_output_location = OutputLocation :: Raw ( File :: create ( path) ?) ;
262+ match opts. format {
263+ OutputFormat :: Pretty => Some ( Box :: new ( PrettyFormatter :: new (
264+ log_output_location,
265+ opts. use_color ( ) ,
266+ max_name_len,
267+ is_multithreaded,
268+ opts. time_options ,
269+ ) ) ) ,
270+ OutputFormat :: Terse => Some ( Box :: new ( TerseFormatter :: new (
271+ log_output_location,
272+ opts. use_color ( ) ,
273+ max_name_len,
274+ is_multithreaded,
275+ ) ) ) ,
276+ OutputFormat :: Json => Some ( Box :: new ( JsonFormatter :: new ( log_output_location) ) ) ,
277+ OutputFormat :: Junit => Some ( Box :: new ( JunitFormatter :: new ( log_output_location) ) ) ,
278+ }
279+ }
280+ } ;
285281 let mut st = ConsoleTestState :: new ( opts) ?;
286282
287283 // Prevent the usage of `Instant` in some cases:
@@ -290,12 +286,27 @@ pub fn run_tests_console(opts: &TestOpts, tests: Vec<TestDescAndFn>) -> io::Resu
290286 let is_instant_supported = !cfg ! ( target_family = "wasm" ) && !cfg ! ( miri) ;
291287
292288 let start_time = is_instant_supported. then ( Instant :: now) ;
293- run_tests ( opts, tests, |x| on_test_event ( & x, & mut st, & mut * out) ) ?;
289+ run_tests ( opts, tests, |x| {
290+ on_test_event (
291+ & x,
292+ & mut st,
293+ & mut * out,
294+ match & mut log_out {
295+ None => None ,
296+ Some ( ref mut log_output) => Some ( & mut * * log_output) ,
297+ } ,
298+ )
299+ } ) ?;
294300 st. exec_time = start_time. map ( |t| TestSuiteExecTime ( t. elapsed ( ) ) ) ;
295301
296302 assert ! ( opts. fail_fast || st. current_test_count( ) == st. total) ;
297303
298- out. write_run_finish ( & st)
304+ let out_result = out. write_run_finish ( & st) ;
305+ let log_out_result = match & mut log_out {
306+ None => Ok ( true ) ,
307+ Some ( ref mut log_output) => log_output. write_run_finish ( & st) ,
308+ } ;
309+ log_out_result. and ( out_result)
299310}
300311
301312// Calculates padding for given test description.
0 commit comments