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:
parent
f9df76f8b3
commit
7ed8fc8f7d
@ -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" );
|
||||||
|
Loading…
Reference in New Issue
Block a user