@@ -6,7 +6,6 @@ use std::io::prelude::Write;
6
6
use std:: time:: Instant ;
7
7
8
8
use super :: {
9
- bench:: fmt_bench_samples,
10
9
cli:: TestOpts ,
11
10
event:: { CompletedTest , TestEvent } ,
12
11
filter_tests,
@@ -15,7 +14,7 @@ use super::{
15
14
options:: { Options , OutputFormat } ,
16
15
run_tests, term,
17
16
test_result:: TestResult ,
18
- time:: { TestExecTime , TestSuiteExecTime } ,
17
+ time:: TestSuiteExecTime ,
19
18
types:: { NamePadding , TestDesc , TestDescAndFn } ,
20
19
} ;
21
20
@@ -29,20 +28,19 @@ impl<T: Write> Write for OutputLocation<T> {
29
28
fn write ( & mut self , buf : & [ u8 ] ) -> io:: Result < usize > {
30
29
match * self {
31
30
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) ,
33
32
}
34
33
}
35
34
36
35
fn flush ( & mut self ) -> io:: Result < ( ) > {
37
36
match * self {
38
37
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 ( ) ,
40
39
}
41
40
}
42
41
}
43
42
44
43
pub struct ConsoleTestState {
45
- pub log_out : Option < File > ,
46
44
pub total : usize ,
47
45
pub passed : usize ,
48
46
pub failed : usize ,
@@ -59,13 +57,7 @@ pub struct ConsoleTestState {
59
57
60
58
impl ConsoleTestState {
61
59
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
-
67
60
Ok ( ConsoleTestState {
68
- log_out,
69
61
total : 0 ,
70
62
passed : 0 ,
71
63
failed : 0 ,
@@ -81,54 +73,6 @@ impl ConsoleTestState {
81
73
} )
82
74
}
83
75
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
-
132
76
fn current_test_count ( & self ) -> usize {
133
77
self . passed + self . failed + self . ignored + self . measured
134
78
}
@@ -142,7 +86,11 @@ pub fn list_tests_console(opts: &TestOpts, tests: Vec<TestDescAndFn>) -> io::Res
142
86
} ;
143
87
144
88
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
+ } ;
146
94
147
95
let mut ntest = 0 ;
148
96
let mut nbench = 0 ;
@@ -164,7 +112,9 @@ pub fn list_tests_console(opts: &TestOpts, tests: Vec<TestDescAndFn>) -> io::Res
164
112
} ;
165
113
166
114
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
+ }
168
118
}
169
119
170
120
fn plural ( count : u32 , s : & str ) -> String {
@@ -177,9 +127,15 @@ pub fn list_tests_console(opts: &TestOpts, tests: Vec<TestDescAndFn>) -> io::Res
177
127
if !quiet {
178
128
if ntest != 0 || nbench != 0 {
179
129
writeln ! ( output) ?;
130
+ if let Some ( ref mut log_output) = log_out {
131
+ writeln ! ( log_output) ?;
132
+ }
180
133
}
181
134
182
135
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
+ }
183
139
}
184
140
185
141
Ok ( ( ) )
@@ -226,25 +182,41 @@ fn on_test_event(
226
182
event : & TestEvent ,
227
183
st : & mut ConsoleTestState ,
228
184
out : & mut dyn OutputFormatter ,
185
+ log_out : Option < & mut dyn OutputFormatter > ,
229
186
) -> io:: Result < ( ) > {
230
187
match ( * event) . clone ( ) {
231
188
TestEvent :: TeFiltered ( filtered_tests, shuffle_seed) => {
232
189
st. total = filtered_tests;
233
190
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
+ }
234
194
}
235
195
TestEvent :: TeFilteredOut ( filtered_out) => {
236
196
st. filtered_out = filtered_out;
237
197
}
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
+ }
240
210
TestEvent :: TeResult ( completed_test) => {
241
211
let test = & completed_test. desc ;
242
212
let result = & completed_test. result ;
243
213
let exec_time = & completed_test. exec_time ;
244
214
let stdout = & completed_test. stdout ;
245
215
246
- st. write_log_result ( test, result, exec_time. as_ref ( ) ) ?;
247
216
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
+ }
248
220
handle_test_result ( st, completed_test) ;
249
221
}
250
222
}
@@ -282,6 +254,30 @@ pub fn run_tests_console(opts: &TestOpts, tests: Vec<TestDescAndFn>) -> io::Resu
282
254
OutputFormat :: Json => Box :: new ( JsonFormatter :: new ( output) ) ,
283
255
OutputFormat :: Junit => Box :: new ( JunitFormatter :: new ( output) ) ,
284
256
} ;
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
+ } ;
285
281
let mut st = ConsoleTestState :: new ( opts) ?;
286
282
287
283
// Prevent the usage of `Instant` in some cases:
@@ -290,12 +286,27 @@ pub fn run_tests_console(opts: &TestOpts, tests: Vec<TestDescAndFn>) -> io::Resu
290
286
let is_instant_supported = !cfg ! ( target_family = "wasm" ) && !cfg ! ( miri) ;
291
287
292
288
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
+ } ) ?;
294
300
st. exec_time = start_time. map ( |t| TestSuiteExecTime ( t. elapsed ( ) ) ) ;
295
301
296
302
assert ! ( opts. fail_fast || st. current_test_count( ) == st. total) ;
297
303
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)
299
310
}
300
311
301
312
// Calculates padding for given test description.
0 commit comments