1
0
mirror of git://sourceware.org/git/lvm2.git synced 2025-01-03 05:18:29 +03:00

test: Update brick-shelltest.h.

This commit is contained in:
Petr Rockai 2014-07-22 18:44:32 +02:00
parent f9df76f8b3
commit 7ed8fc8f7d

View File

@ -386,8 +386,9 @@ struct BufSink : Sink {
} }
void dump( std::ostream &o ) { void dump( std::ostream &o ) {
o << std::endl;
while ( !data.empty( true ) ) while ( !data.empty( true ) )
o << "| " << fmt.format( data.shift( true ) ) << std::endl; o << "| " << fmt.format( data.shift( true ) );
} }
}; };
@ -432,6 +433,7 @@ struct FileSink : FdSink {
} }
FdSink::sync(); FdSink::sync();
} }
~FileSink() { ~FileSink() {
if ( fd >= 0 ) { if ( fd >= 0 ) {
fsync( fd ); fsync( fd );
@ -440,12 +442,60 @@ struct FileSink : FdSink {
} }
}; };
#define BRICK_SYSLOG_ACTION_READ 2
#define BRICK_SYSLOG_ACTION_READ_CLEAR 4 #define BRICK_SYSLOG_ACTION_READ_CLEAR 4
#define BRICK_SYSLOG_ACTION_CLEAR 5 #define BRICK_SYSLOG_ACTION_CLEAR 5
struct KMsg { struct Source {
int fd; int fd;
virtual void sync( Sink *sink ) {
ssize_t sz;
char buf[ 128 * 1024 ];
while ( (sz = read(fd, buf, sizeof(buf) - 1)) > 0 )
sink->push( std::string( buf, sz ) );
if ( sz < 0 && errno != EAGAIN )
throw syserr( "reading pipe" );
}
virtual void reset() {}
virtual int fd_set( fd_set *set ) {
if ( fd >= 0 ) {
FD_SET( fd, set );
return fd;
} else
return -1;
}
Source( int fd = -1 ) : fd( fd ) {}
virtual ~Source() {
if ( fd >= 0 )
::close( fd );
}
};
struct FileSource : Source {
std::string file;
FileSource( std::string n ) : Source( -1 ), file( n ) {}
int fd_set( ::fd_set * ) { return -1; } /* reading a file is always non-blocking */
void sync( Sink *s ) {
if ( fd < 0 ) {
fd = open( file.c_str(), O_RDONLY | O_CLOEXEC | O_NONBLOCK );
if ( fd >= 0 )
lseek( fd, 0, SEEK_END );
}
if ( fd >= 0 )
Source::sync( s );
}
};
struct KMsg : Source {
bool can_clear;
KMsg() : can_clear( true ) {}
bool dev_kmsg() { bool dev_kmsg() {
return fd >= 0; return fd >= 0;
} }
@ -461,14 +511,14 @@ struct KMsg {
} else if (lseek(fd, 0L, SEEK_END) == (off_t) -1) } else if (lseek(fd, 0L, SEEK_END) == (off_t) -1)
perror("lseek /dev/kmsg"); perror("lseek /dev/kmsg");
} else } else
klogctl( BRICK_SYSLOG_ACTION_CLEAR, 0, 0 ); if ( klogctl( BRICK_SYSLOG_ACTION_CLEAR, 0, 0 ) < 0 )
can_clear = false;
#endif #endif
} }
void read( Sink *s ) { void sync( Sink *s ) {
#ifdef __unix #ifdef __unix
int sz; int sz;
char buf[ 128 * 1024 ]; char buf[ 128 * 1024 ];
if ( dev_kmsg() ) { if ( dev_kmsg() ) {
@ -476,16 +526,17 @@ struct KMsg {
s->push( std::string( buf, sz ) ); s->push( std::string( buf, sz ) );
if ( sz < 0 ) { if ( sz < 0 ) {
fd = -1; fd = -1;
read( s ); sync( s );
} }
} else { } else if ( can_clear ) {
while ( (sz = klogctl( BRICK_SYSLOG_ACTION_READ_CLEAR, buf, sizeof(buf) - 1 )) > 0 ) while ( (sz = klogctl( BRICK_SYSLOG_ACTION_READ_CLEAR, buf,
sizeof(buf) - 1 )) > 0 )
s->push( std::string( buf, sz ) ); s->push( std::string( buf, sz ) );
if ( sz < 0 && errno == EPERM )
can_clear = false;
} }
#endif #endif
} }
KMsg() : fd( -1 ) {}
}; };
struct Observer : Sink { struct Observer : Sink {
@ -495,11 +546,12 @@ struct Observer : Sink {
struct IO : Sink { struct IO : Sink {
typedef std::vector< Sink* > Sinks; typedef std::vector< Sink* > Sinks;
mutable Sinks sinks; typedef std::vector< Source* > Sources;
Observer *_observer;
KMsg kmsg; mutable Sinks sinks;
int fd; mutable Sources sources;
Observer *_observer;
virtual void push( std::string x ) { virtual void push( std::string x ) {
for ( Sinks::iterator i = sinks.begin(); i != sinks.end(); ++i ) for ( Sinks::iterator i = sinks.begin(); i != sinks.end(); ++i )
@ -507,39 +559,43 @@ struct IO : Sink {
} }
void sync() { void sync() {
ssize_t sz; for ( Sources::iterator i = sources.begin(); i != sources.end(); ++i )
char buf[ 128 * 1024 ]; (*i)->sync( this );
while ( (sz = read(fd, buf, sizeof(buf) - 1)) > 0 )
push( std::string( buf, sz ) );
if ( sz < 0 && errno != EAGAIN )
throw syserr( "reading pipe" );
kmsg.read( this );
for ( Sinks::iterator i = sinks.begin(); i != sinks.end(); ++i ) for ( Sinks::iterator i = sinks.begin(); i != sinks.end(); ++i )
(*i)->sync(); (*i)->sync();
} }
void close() { ::close( fd ); } void close() {
for ( Sources::iterator i = sources.begin(); i != sources.end(); ++i )
delete *i;
sources.clear();
}
int fd_set( fd_set *set ) {
int max = -1;
for ( Sources::iterator i = sources.begin(); i != sources.end(); ++i )
max = std::max( (*i)->fd_set( set ), max );
return max + 1;
}
Observer &observer() { return *_observer; } Observer &observer() { return *_observer; }
IO() : fd( -1 ) { IO() {
sinks.push_back( _observer = new Observer ); sinks.push_back( _observer = new Observer );
} }
IO( const IO &io ) { /* a stealing copy constructor */
fd = io.fd; IO( const IO &io ) : sinks( io.sinks ), sources( io.sources )
sinks = io.sinks; {
io.sinks.clear(); io.sinks.clear();
io.sources.clear();
} }
IO &operator= ( const IO &io ) { IO &operator= ( const IO &io ) {
fd = io.fd; this->~IO();
sinks = io.sinks; return *new (this) IO( io );
io.sinks.clear();
return *this;
} }
void clear() { void clear() {
@ -548,7 +604,7 @@ struct IO : Sink {
sinks.clear(); sinks.clear();
} }
~IO() { clear(); } ~IO() { close(); clear(); }
}; };
@ -559,12 +615,12 @@ bool interrupt = false;
} }
struct Options { struct Options {
bool verbose, batch, interactive, cont, fatal_timeouts; bool verbose, batch, interactive, cont, fatal_timeouts, kmsg;
std::string testdir, outdir, workdir, heartbeat; std::string testdir, outdir, workdir, heartbeat;
std::vector< std::string > flavours, filter; std::vector< std::string > flavours, filter, watch;
std::string flavour_envvar; std::string flavour_envvar;
Options() : verbose( false ), batch( false ), interactive( false ), Options() : verbose( false ), batch( false ), interactive( false ),
cont( false ), fatal_timeouts( false ) {} cont( false ), fatal_timeouts( false ), kmsg( false ) {}
}; };
struct TestProcess struct TestProcess
@ -576,7 +632,12 @@ struct TestProcess
void exec() { void exec() {
assert( fd >= 0 ); assert( fd >= 0 );
if ( !interactive ) { if ( !interactive ) {
close( STDIN_FILENO ); int devnull = ::open( "/dev/null", O_RDONLY );
if ( devnull >= 0 ) { /* gcc really doesn't like to not have stdin */
dup2( devnull, STDIN_FILENO );
close( devnull );
} else
close( STDIN_FILENO );
dup2( fd, STDOUT_FILENO ); dup2( fd, STDOUT_FILENO );
dup2( fd, STDERR_FILENO ); dup2( fd, STDERR_FILENO );
close( fd ); close( fd );
@ -633,7 +694,7 @@ struct TestCase {
exit(202); exit(202);
} }
io.fd = fds[0]; io.sources.push_back( new Source( fds[0] ) );
child.fd = fds[1]; child.fd = fds[1];
child.interactive = options.interactive; child.interactive = options.interactive;
} }
@ -661,7 +722,7 @@ struct TestCase {
kill( pid, SIGINT ); kill( pid, SIGINT );
sleep( 5 ); /* wait a bit for a reaction */ sleep( 5 ); /* wait a bit for a reaction */
if ( waitpid( pid, &status, WNOHANG ) == 0 ) { if ( waitpid( pid, &status, WNOHANG ) == 0 ) {
system( "echo t > /proc/sysrq-trigger" ); system( "echo t > /proc/sysrq-trigger 2> /dev/null" );
kill( -pid, SIGKILL ); kill( -pid, SIGKILL );
waitpid( pid, &status, 0 ); waitpid( pid, &status, 0 );
} }
@ -674,7 +735,7 @@ struct TestCase {
fd_set set; fd_set set;
FD_ZERO( &set ); FD_ZERO( &set );
FD_SET( io.fd, &set ); int nfds = io.fd_set( &set );
wait.tv_sec = 0; wait.tv_sec = 0;
wait.tv_usec = 500000; /* timeout 0.5s */ wait.tv_usec = 500000; /* timeout 0.5s */
@ -686,7 +747,7 @@ struct TestCase {
} }
} }
if ( select( io.fd + 1, &set, NULL, NULL, &wait ) > 0 ) if ( select( nfds, &set, NULL, NULL, &wait ) > 0 )
silent_start = end; /* something happened */ silent_start = end; /* something happened */
io.sync(); io.sync();
@ -798,6 +859,7 @@ struct TestCase {
progress( First ) << " " << rusage() << std::endl; progress( First ) << " " << rusage() << std::endl;
} else } else
progress( Last ) << tag( r ) << pretty() << std::endl; progress( Last ) << tag( r ) << pretty() << std::endl;
io.clear(); io.clear();
} }
@ -829,6 +891,12 @@ struct TestCase {
std::replace( n.begin(), n.end(), '/', '_' ); std::replace( n.begin(), n.end(), '/', '_' );
std::string fn = options.outdir + "/" + n + ".txt"; std::string fn = options.outdir + "/" + n + ".txt";
io.sinks.push_back( new FileSink( fn ) ); io.sinks.push_back( new FileSink( fn ) );
for ( std::vector< std::string >::iterator i = options.watch.begin();
i != options.watch.end(); ++i )
io.sources.push_back( new FileSource( *i ) );
if ( options.kmsg )
io.sources.push_back( new KMsg );
} }
TestCase( Journal &j, Options opt, std::string path, std::string name, std::string flavour ) TestCase( Journal &j, Options opt, std::string path, std::string name, std::string flavour )
@ -941,13 +1009,6 @@ void setup_handlers() {
} }
} }
int64_t get_time_us(void)
{
struct timeval tv;
(void) gettimeofday(&tv, 0);
return (int64_t) tv.tv_sec * 1000000 + (int64_t) tv.tv_usec;
}
} }
/* TODO remove in favour of brick-commandline.h */ /* TODO remove in favour of brick-commandline.h */
@ -1035,6 +1096,12 @@ int run( int argc, const char **argv, std::string fl_envvar = "TEST_FLAVOUR" )
else else
opt.flavours.push_back( "vanilla" ); opt.flavours.push_back( "vanilla" );
if ( args.has( "--watch" ) )
split( args.opt( "--watch" ), opt.watch );
if ( args.has( "--kmsg" ) )
opt.kmsg = true;
opt.outdir = args.opt( "--outdir" ); opt.outdir = args.opt( "--outdir" );
opt.testdir = args.opt( "--testdir" ); opt.testdir = args.opt( "--testdir" );
opt.workdir = args.opt( "--workdir" ); opt.workdir = args.opt( "--workdir" );