@@ -14,9 +14,10 @@ use chrono::Local;
1414use log:: { debug, error, warn} ;
1515use std:: {
1616 collections:: HashSet ,
17+ env,
1718 fs:: { self , OpenOptions } ,
1819 io:: { ErrorKind , stdout, Write } ,
19- process:: { Command , Output } ,
20+ process:: Command ,
2021 result,
2122 sync:: {
2223 Arc ,
@@ -82,6 +83,15 @@ struct State {
8283 total : usize ,
8384}
8485
86+ /// Result of a test run.
87+ struct TestResult {
88+ /// Was this run successful.
89+ success : bool ,
90+
91+ /// The captured output.
92+ output : Vec < u8 > ,
93+ }
94+
8595impl State {
8696 fn new ( total : usize ) -> Arc < Mutex < State > > {
8797 Arc :: new ( Mutex :: new ( State {
@@ -101,46 +111,41 @@ impl State {
101111 self . status ( ) ;
102112 }
103113
104- fn done ( & mut self , fs : & FeatureSet , output : Result < Option < Output > > ) {
114+ fn done ( & mut self , fs : & FeatureSet , output : Result < TestResult > ) {
105115 let key = fs. textual ( ) ;
106116 self . running . remove ( & key) ;
107117 self . done . insert ( key. clone ( ) ) ;
108118 match output {
109- Ok ( None ) => {
110- // println!("Success {} ({} running)", key, self.running.len());
111- }
112- Ok ( Some ( output ) ) => {
113- // Write the output into a file.
114- let mut count = 1 ;
115- let ( mut fd , logname ) = loop {
116- let name = format ! ( "./failure-{:04}.log" , count) ;
117- count += 1 ;
118- match OpenOptions :: new ( )
119- . create_new ( true )
120- . write ( true )
121- . open ( & name )
122- {
123- Ok ( file ) => break ( file , name ) ,
124- Err ( ref err ) if err . kind ( ) == ErrorKind :: AlreadyExists => continue ,
125- Err ( err ) => {
126- error ! ( "Unable to write log file to current directory: {:?}" , err ) ;
127- return ;
119+ Ok ( output ) => {
120+ if !output . success || log_all ( ) {
121+ // Write the output into a file.
122+ let mut count = 1 ;
123+ let ( mut fd , logname ) = loop {
124+ let base = if output . success { "success" } else { "failure" } ;
125+ let name = format ! ( "./{}-{:04}.log" , base , count ) ;
126+ count += 1 ;
127+ match OpenOptions :: new ( )
128+ . create_new ( true )
129+ . write ( true )
130+ . open ( & name )
131+ {
132+ Ok ( file ) => break ( file , name ) ,
133+ Err ( ref err ) if err . kind ( ) == ErrorKind :: AlreadyExists => continue ,
134+ Err ( err ) => {
135+ error ! ( "Unable to write log file to current directory: {:?}" , err ) ;
136+ return ;
137+ }
128138 }
139+ } ;
140+ fd. write_all ( & output. output ) . unwrap ( ) ;
141+ if !output. success {
142+ error ! ( "Failure {} log:{:?} ({} running)" , key, logname,
143+ self . running. len( ) ) ;
129144 }
130- } ;
131- writeln ! ( & mut fd, "Test failure {}" , key) . unwrap ( ) ;
132- writeln ! ( & mut fd, "time: {}" , Local :: now( ) . to_rfc3339( ) ) . unwrap ( ) ;
133- writeln ! ( & mut fd, "----------------------------------------" ) . unwrap ( ) ;
134- writeln ! ( & mut fd, "stdout:" ) . unwrap ( ) ;
135- fd. write_all ( & output. stdout ) . unwrap ( ) ;
136- writeln ! ( & mut fd, "----------------------------------------" ) . unwrap ( ) ;
137- writeln ! ( & mut fd, "\n stderr:" ) . unwrap ( ) ;
138- fd. write_all ( & output. stderr ) . unwrap ( ) ;
139- error ! ( "Failure {} log:{:?} ({} running)" , key, logname,
140- self . running. len( ) ) ;
145+ }
141146 }
142147 Err ( err) => {
143- error ! ( "Unable to run test {:?} ({:?}) " , key, err) ;
148+ error ! ( "Unable to run test {:?} ({:?}" , key, err) ;
144149 }
145150 }
146151 self . status ( ) ;
@@ -239,18 +244,31 @@ impl FeatureSet {
239244 /// Run a test for this given feature set. Output is captured and will be returned if there is
240245 /// an error. Each will be run successively, and the first failure will be returned.
241246 /// Otherwise, it returns None, which means everything worked.
242- fn run ( & self ) -> Result < Option < Output > > {
247+ fn run ( & self ) -> Result < TestResult > {
248+ let mut output = vec ! [ ] ;
249+ let mut success = true ;
243250 for v in & self . values {
244- let output = Command :: new ( "bash" )
251+ let cmdout = Command :: new ( "bash" )
245252 . arg ( "./ci/sim_run.sh" )
246253 . current_dir ( ".." )
247254 . env ( & self . env , v)
248255 . output ( ) ?;
249- if !output. status . success ( ) {
250- return Ok ( Some ( output) ) ;
256+ // Grab the output for logging, etc.
257+ writeln ! ( & mut output, "Test {} {}" ,
258+ if cmdout. status. success( ) { "success" } else { "FAILURE" } ,
259+ self . textual( ) ) ?;
260+ writeln ! ( & mut output, "time: {}" , Local :: now( ) . to_rfc3339( ) ) ?;
261+ writeln ! ( & mut output, "----------------------------------------" ) ?;
262+ writeln ! ( & mut output, "stdout:" ) ?;
263+ output. extend ( & cmdout. stdout ) ;
264+ writeln ! ( & mut output, "----------------------------------------" ) ?;
265+ writeln ! ( & mut output, "stderr:" ) ?;
266+ output. extend ( & cmdout. stderr ) ;
267+ if !cmdout. status . success ( ) {
268+ success = false ;
251269 }
252270 }
253- return Ok ( None ) ;
271+ Ok ( TestResult { success , output } )
254272 }
255273
256274 /// Convert this feature set into a textual representation
@@ -282,3 +300,8 @@ fn lookup_matrix(y: &Yaml) -> Option<&Vec<Yaml>> {
282300 . as_hash ( ) ?. get ( & features) ?
283301 . as_vec ( )
284302}
303+
304+ /// Query if we should be logging all tests and not only failures.
305+ fn log_all ( ) -> bool {
306+ env:: var ( "PTEST_LOG_ALL" ) . is_ok ( )
307+ }
0 commit comments