1
0
mirror of git://sourceware.org/git/lvm2.git synced 2024-12-21 13:34:40 +03:00

test: Implement journalling and --continue.

This commit is contained in:
Petr Rockai 2014-06-26 01:02:13 +02:00
parent 9dfbce0aa7
commit d2dbc65f00
2 changed files with 92 additions and 9 deletions

View File

@ -1,7 +1,10 @@
// -*- C++ -*-
#include <map>
#include <string>
#include <iostream>
#include <fstream>
#include <iterator>
#ifndef RUNNER_JOURNAL_H
#define RUNNER_JOURNAL_H
@ -9,6 +12,7 @@
struct Journal {
enum R {
STARTED,
RETRIED,
UNKNOWN,
FAILED,
INTERRUPTED,
@ -32,9 +36,59 @@ struct Journal {
}
}
friend std::istream &operator>>( std::istream &i, R &r ) {
std::string x;
i >> x;
r = UNKNOWN;
if ( x == "started" ) r = STARTED;
if ( x == "retried" ) r = RETRIED;
if ( x == "failed" ) r = FAILED;
if ( x == "interrupted" ) r = INTERRUPTED;
if ( x == "passed" ) r = PASSED;
if ( x == "skipped" ) r = SKIPPED;
if ( x == "timeout" ) r = TIMEOUT;
if ( x == "warnings" ) r = WARNED;
return i;
}
template< typename S, typename T >
friend std::istream &operator>>( std::istream &i, std::pair< S, T > &r ) {
return i >> r.first >> r.second;
}
typedef std::map< std::string, R > Status;
Status status;
std::string location_tmp, location;
void sync() {
std::ofstream of( location_tmp.c_str() );
for ( Status::iterator i = status.begin(); i != status.end(); ++i )
of << i->first << " " << i->second << std::endl;
of.close();
rename( location_tmp.c_str(), location.c_str() );
}
void started( std::string n ) {
if ( status.count( n ) && status[ n ] == STARTED )
status[ n ] = RETRIED;
else
status[ n ] = STARTED;
sync();
}
void done( std::string n, R r ) {
status[ n ] = r;
sync();
}
bool done( std::string n ) {
if ( !status.count( n ) )
return false;
return status[ n ] != STARTED && status[ n ] != INTERRUPTED;
}
int count( R r ) {
int c = 0;
for ( Status::iterator i = status.begin(); i != status.end(); ++i )
@ -53,6 +107,17 @@ struct Journal {
if ( i->second != PASSED )
std::cout << i->second << ": " << i->first << std::endl;
}
void read() {
std::ifstream ifs( location.c_str() );
typedef std::istream_iterator< std::pair< std::string, R > > It;
std::copy( It( ifs ), It(), std::inserter( status, status.begin() ) );
}
Journal( std::string dir )
: location( dir + "/journal" ),
location_tmp( dir + "/journal.tmp" )
{}
};
#endif

View File

@ -55,11 +55,12 @@
pid_t kill_pid = 0;
bool fatal_signal = false;
bool interrupt = false;
struct Options {
bool verbose, quiet, interactive;
bool verbose, quiet, interactive, cont;
std::string testdir, outdir;
Options() : verbose( false ), quiet( false ), interactive( false ) {}
Options() : verbose( false ), quiet( false ), interactive( false ), cont( false ) {}
};
struct TestProcess
@ -115,6 +116,8 @@ struct TestCase {
time_t start, end;
Options options;
Journal *journal;
void pipe() {
int fds[2];
@ -175,7 +178,7 @@ struct TestCase {
}
std::string tag( std::string n ) {
int pad = (8 - n.length());
int pad = (12 - n.length());
return "### " + std::string( pad, ' ' ) + n + ": ";
}
@ -217,7 +220,9 @@ struct TestCase {
r = Journal::SKIPPED;
else
r = Journal::FAILED;
} else
} else if ( interrupt && WIFSIGNALED( status ) && WTERMSIG( status ) == SIGINT )
r = Journal::INTERRUPTED;
else
r = Journal::FAILED;
::close( io.fd );
@ -228,6 +233,7 @@ struct TestCase {
close(fd_debuglog);
} */
journal->done( name, r );
progress( Last ) << tag( r ) << name << std::endl;
}
@ -241,6 +247,7 @@ struct TestCase {
io.close();
child.exec();
} else {
journal->started( name );
progress( First ) << tag( "running" ) << name << std::flush;
if ( options.verbose || options.interactive )
progress() << std::endl;
@ -249,8 +256,8 @@ struct TestCase {
}
}
TestCase( Options opt, std::string path, std::string name )
: timeout( false ), silent_ctr( 0 ), child( path ), name( name ), options( opt )
TestCase( Journal &j, Options opt, std::string path, std::string name )
: timeout( false ), silent_ctr( 0 ), child( path ), name( name ), options( opt ), journal( &j )
{
if ( opt.verbose )
io.sinks.push_back( new FdSink( 1 ) );
@ -276,10 +283,12 @@ struct Main {
continue;
if ( i->substr( 0, 4 ) == "lib/" )
continue;
cases.push_back( TestCase( options, options.testdir + *i, *i ) );
cases.push_back( TestCase( journal, options, options.testdir + *i, *i ) );
cases.back().options = options;
}
if ( options.cont )
journal.read();
}
void run() {
@ -288,6 +297,10 @@ struct Main {
std::cerr << "running " << cases.size() << " tests" << std::endl;
for ( Cases::iterator i = cases.begin(); i != cases.end(); ++i ) {
if ( options.cont && journal.done( i->name ) )
continue;
i->run();
if ( time(0) - start > 3 * 3600 ) {
@ -304,14 +317,16 @@ struct Main {
exit( 1 );
}
Main( Options o ) : die( false ), options( o ) {}
Main( Options o ) : die( false ), options( o ), journal( o.outdir ) {}
};
static void handler( int sig ) {
signal( sig, SIG_DFL );
signal( sig, SIG_DFL ); /* die right away next time */
if ( kill_pid > 0 )
kill( -kill_pid, sig );
fatal_signal = true;
if ( sig == SIGINT )
interrupt = true;
}
void setup_handlers() {
@ -378,6 +393,9 @@ int main(int argc, char **argv)
Args args( argc, argv );
Options opt;
if ( args.has( "--continue" ) )
opt.cont = true;
if ( args.has( "--quiet" ) || getenv( "QUIET" ) ) {
opt.verbose = false;
opt.quiet = true;