2010-07-28 16:20:38 +04:00
/*
2013-06-09 00:23:39 +04:00
* Copyright ( C ) 2010 - 2013 Red Hat , Inc . All rights reserved .
2010-07-28 16:20:38 +04:00
*
* This file is part of LVM2 .
*
* This copyrighted material is made available to anyone wishing to use ,
* modify , copy , or redistribute it subject to the terms and conditions
* of the GNU General Public License v .2 .
*
* You should have received a copy of the GNU General Public License
* along with this program ; if not , write to the Free Software Foundation ,
* Inc . , 59 Temple Place , Suite 330 , Boston , MA 02111 - 1307 USA
*/
2011-01-10 16:25:22 +03:00
# define _GNU_SOURCE
2009-02-12 22:54:45 +03:00
# include <fcntl.h>
2013-06-09 00:23:39 +04:00
# include <limits.h>
2009-02-12 22:54:45 +03:00
# include <stdio.h>
2013-06-09 00:23:39 +04:00
# include <stdlib.h>
# include <string.h>
# include <sys/resource.h> /* rusage */
# include <sys/select.h>
2009-02-12 22:54:45 +03:00
# include <sys/socket.h>
2013-06-09 00:23:39 +04:00
# include <sys/time.h>
# include <sys/types.h>
2009-02-12 22:54:45 +03:00
# include <sys/wait.h>
2011-01-28 19:05:38 +03:00
# include <time.h>
2013-06-09 00:23:39 +04:00
# include <unistd.h>
2009-02-12 22:54:45 +03:00
2011-01-05 18:03:43 +03:00
static pid_t pid ;
static int fds [ 2 ] ;
2010-04-07 13:41:33 +04:00
# define MAX 1024
2013-06-09 00:23:39 +04:00
# define MAX_LOG_SIZE (32*1024*1024) /* Default max size of test log */
2010-04-07 13:41:33 +04:00
struct stats {
int nfailed ;
int nskipped ;
int npassed ;
2012-05-16 14:43:41 +04:00
int nknownfail ;
2010-04-30 18:33:39 +04:00
int nwarned ;
2013-06-09 00:23:39 +04:00
int ninterrupted ;
2010-04-07 13:41:33 +04:00
int status [ MAX ] ;
} ;
2011-01-05 18:03:43 +03:00
static struct stats s ;
2009-02-12 22:54:45 +03:00
2011-01-05 18:03:43 +03:00
static char * readbuf = NULL ;
2013-06-03 14:09:21 +04:00
static size_t readbuf_sz = 0 , readbuf_used = 0 ;
2009-02-12 22:54:45 +03:00
2011-01-05 18:03:43 +03:00
static int die = 0 ;
2012-03-12 18:24:15 +04:00
static int verbose = 0 ; /* >1 with timestamps */
2012-10-08 22:15:55 +04:00
static int interactive = 0 ; /* disable all redirections */
2013-06-03 14:07:31 +04:00
static const char * results ;
2013-06-09 00:23:39 +04:00
static unsigned fullbuffer = 0 ;
2011-01-05 03:16:18 +03:00
2013-05-27 06:26:33 +04:00
static FILE * outfile = NULL ;
2011-01-05 03:16:18 +03:00
struct subst {
2011-03-10 17:47:22 +03:00
const char * key ;
char * value ;
2011-01-05 03:16:18 +03:00
} ;
2011-01-05 18:03:43 +03:00
static struct subst subst [ 2 ] ;
2009-02-12 22:54:45 +03:00
2013-06-03 14:09:21 +04:00
enum {
UNKNOWN ,
PASSED ,
SKIPPED ,
FAILED ,
WARNED ,
KNOWNFAIL ,
2013-06-09 00:23:39 +04:00
INTERRUPTED ,
2013-07-23 13:42:34 +04:00
TIMEOUT ,
2013-06-03 14:09:21 +04:00
} ;
2009-02-12 22:54:45 +03:00
2011-01-13 14:02:55 +03:00
static void handler ( int sig ) {
signal ( sig , SIG_DFL ) ;
2013-07-23 13:42:34 +04:00
kill ( - pid , sig ) ;
2011-01-13 14:02:55 +03:00
die = sig ;
2009-02-12 22:54:45 +03:00
}
2013-05-27 06:26:33 +04:00
static int outline ( FILE * out , char * buf , int start , int force ) {
2011-03-10 17:47:22 +03:00
char * from = buf + start ;
char * next = strchr ( buf + start , ' \n ' ) ;
if ( ! next & & ! force ) /* not a complete line yet... */
return start ;
if ( ! next )
next = from + strlen ( from ) ;
else
+ + next ;
if ( ! strncmp ( from , " @TESTDIR= " , 9 ) ) {
subst [ 0 ] . key = " @TESTDIR@ " ;
2013-06-12 16:16:25 +04:00
free ( subst [ 0 ] . value ) ;
2011-03-10 17:47:22 +03:00
subst [ 0 ] . value = strndup ( from + 9 , next - from - 9 - 1 ) ;
} else if ( ! strncmp ( from , " @PREFIX= " , 8 ) ) {
subst [ 1 ] . key = " @PREFIX@ " ;
2013-06-12 16:16:25 +04:00
free ( subst [ 1 ] . value ) ;
2011-03-10 17:47:22 +03:00
subst [ 1 ] . value = strndup ( from + 8 , next - from - 8 - 1 ) ;
} else {
char * line = strndup ( from , next - from ) ;
char * a = line , * b ;
do {
int idx = - 1 ;
int i ;
b = line + strlen ( line ) ;
for ( i = 0 ; i < 2 ; + + i ) {
if ( subst [ i ] . key ) {
// printf("trying: %s -> %s\n", subst[i].value, subst[i].key);
char * stop = strstr ( a , subst [ i ] . value ) ;
if ( stop & & stop < b ) {
idx = i ;
b = stop ;
}
}
}
2013-05-27 06:26:33 +04:00
fwrite ( a , 1 , b - a , out ) ;
2011-03-10 17:47:22 +03:00
a = b ;
if ( idx > = 0 ) {
2013-05-27 06:26:33 +04:00
fprintf ( out , " %s " , subst [ idx ] . key ) ;
2011-03-10 17:47:22 +03:00
a + = strlen ( subst [ idx ] . value ) ;
}
} while ( b < line + strlen ( line ) ) ;
free ( line ) ;
}
return next - buf + ( force ? 0 : 1 ) ;
2011-01-05 03:16:18 +03:00
}
2011-01-05 18:03:43 +03:00
static void dump ( void ) {
2011-01-13 18:03:28 +03:00
int counter_last = - 1 , counter = 0 ;
2011-01-05 03:16:18 +03:00
2013-06-03 14:09:21 +04:00
while ( ( counter < ( int ) readbuf_used ) & & ( counter ! = counter_last ) ) {
2011-01-13 14:02:55 +03:00
counter_last = counter ;
2013-05-27 06:26:33 +04:00
counter = outline ( stdout , readbuf , counter , 1 ) ;
2011-01-13 14:02:55 +03:00
}
2009-02-12 22:54:45 +03:00
}
2013-05-27 06:26:33 +04:00
static void trickle ( FILE * out , int * last , int * counter ) {
2013-06-03 14:09:21 +04:00
if ( * last > ( int ) readbuf_used ) {
2013-05-27 06:26:33 +04:00
* last = - 1 ;
* counter = 0 ;
2012-03-12 18:24:15 +04:00
}
2013-06-03 14:09:21 +04:00
while ( ( * counter < ( int ) readbuf_used ) & & ( * counter ! = * last ) ) {
2013-05-27 06:26:33 +04:00
* last = * counter ;
* counter = outline ( out , readbuf , * counter , 1 ) ;
2012-02-15 05:31:10 +04:00
}
}
2011-01-05 18:03:43 +03:00
static void clear ( void ) {
2009-02-12 22:54:45 +03:00
readbuf_used = 0 ;
2013-06-12 16:16:25 +04:00
fullbuffer = 0 ;
2009-02-12 22:54:45 +03:00
}
2012-03-12 18:24:15 +04:00
static 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 ;
}
static void _append_buf ( const char * buf , size_t len )
{
if ( ( readbuf_used + len ) > = readbuf_sz ) {
2013-06-09 00:23:39 +04:00
if ( ( readbuf_sz > = MAX_LOG_SIZE ) & &
! getenv ( " LVM_TEST_UNLIMITED " ) ) {
if ( fullbuffer + + = = 0 )
2013-07-23 13:42:34 +04:00
kill ( - pid , SIGINT ) ;
2013-06-09 00:23:39 +04:00
return ;
}
2013-10-12 00:31:57 +04:00
readbuf_sz = readbuf_sz ? 2 * readbuf_sz : 16384 ;
2012-03-12 18:24:15 +04:00
readbuf = realloc ( readbuf , readbuf_sz ) ;
}
if ( ! readbuf )
exit ( 205 ) ;
memcpy ( readbuf + readbuf_used , buf , len ) ;
readbuf_used + = len ;
}
static const char * _append_with_stamp ( const char * buf , int stamp )
{
static const char spaces [ ] = " " ;
static int64_t t_last ;
static int64_t t_start = 0 ;
int64_t t_now ;
char stamp_buf [ 32 ] ; /* Bigger to always fit both numbers */
const char * be ;
const char * bb = buf ;
size_t len ;
while ( ( be = strchr ( bb , ' \n ' ) ) ) {
if ( stamp + + = = 0 ) {
t_now = _get_time_us ( ) ;
if ( ! t_start )
t_start = t_last = t_now ;
len = snprintf ( stamp_buf , sizeof ( stamp_buf ) ,
" %8.3f%8.4f " ,
( t_now - t_start ) / 1000000.f ,
( t_now - t_last ) / 1000000.f ) ;
_append_buf ( stamp_buf , ( len < ( sizeof ( spaces ) - 1 ) ) ?
len : ( sizeof ( spaces ) - 1 ) ) ;
t_last = t_now ;
}
_append_buf ( bb , be + 1 - bb ) ;
bb = be + 1 ;
if ( stamp > 0 & & bb [ 0 ] )
_append_buf ( spaces , sizeof ( spaces ) - 1 ) ;
}
return bb ;
}
2013-09-12 15:30:12 +04:00
static void drain ( int fd )
{
2013-10-12 00:31:57 +04:00
char buf [ 4096 + 1 ] ;
2012-03-12 18:24:15 +04:00
const char * bp ;
int stamp = 0 ;
2009-02-12 22:54:45 +03:00
int sz ;
2012-03-12 18:24:15 +04:00
2013-05-27 06:26:33 +04:00
static int stdout_last = - 1 , stdout_counter = 0 ;
static int outfile_last = - 1 , outfile_counter = 0 ;
2013-09-12 15:30:12 +04:00
while ( ( sz = read ( fd , buf , sizeof ( buf ) - 1 ) ) > 0 ) {
2013-06-09 00:23:39 +04:00
if ( fullbuffer )
continue ;
2012-03-12 18:24:15 +04:00
buf [ sz ] = ' \0 ' ;
bp = ( verbose < 2 ) ? buf : _append_with_stamp ( buf , stamp ) ;
if ( sz > ( bp - buf ) ) {
_append_buf ( bp , sz - ( bp - buf ) ) ;
stamp = - 1 ; /* unfinished line */
} else
stamp = 0 ;
readbuf [ readbuf_used ] = 0 ;
2012-02-15 05:31:10 +04:00
if ( verbose )
2013-05-27 06:26:33 +04:00
trickle ( stdout , & stdout_last , & stdout_counter ) ;
if ( outfile )
trickle ( outfile , & outfile_last , & outfile_counter ) ;
2009-02-12 22:54:45 +03:00
}
}
2013-06-09 00:23:39 +04:00
static const char * duration ( time_t start , const struct rusage * usage )
2011-01-28 19:05:38 +03:00
{
2013-06-09 00:23:39 +04:00
static char buf [ 100 ] ;
2011-01-28 19:05:38 +03:00
int t = ( int ) ( time ( NULL ) - start ) ;
2013-06-09 00:23:39 +04:00
int p = sprintf ( buf , " %2d:%02d " , t / 60 , t % 60 ) ;
if ( usage )
sprintf ( buf + p , " %2ld:%02ld.%03ld/%ld:%02ld.%03ld%5ld%8ld/%ld " ,
usage - > ru_utime . tv_sec / 60 , usage - > ru_utime . tv_sec % 60 ,
usage - > ru_utime . tv_usec / 1000 ,
usage - > ru_stime . tv_sec / 60 , usage - > ru_stime . tv_sec % 60 ,
usage - > ru_stime . tv_usec / 1000 ,
usage - > ru_maxrss / 1024 ,
usage - > ru_inblock , usage - > ru_oublock ) ;
2011-01-28 19:05:38 +03:00
return buf ;
}
2013-06-09 00:23:39 +04:00
static void passed ( int i , char * f , time_t t , const struct rusage * usage ) {
2012-05-16 14:43:41 +04:00
if ( readbuf & & strstr ( readbuf , " TEST EXPECT FAIL " ) ) {
+ + s . npassed ;
s . status [ i ] = PASSED ;
2013-06-09 00:23:39 +04:00
printf ( " passed (UNEXPECTED). %s \n " , duration ( t , usage ) ) ;
2012-05-16 14:43:41 +04:00
} else if ( readbuf & & strstr ( readbuf , " TEST WARNING " ) ) {
2010-04-30 18:33:39 +04:00
+ + s . nwarned ;
s . status [ i ] = WARNED ;
2013-06-09 00:23:39 +04:00
printf ( " warnings %s \n " , duration ( t , usage ) ) ;
2010-04-30 18:33:39 +04:00
} else {
+ + s . npassed ;
s . status [ i ] = PASSED ;
2013-06-09 00:23:39 +04:00
printf ( " passed. %s \n " , duration ( t , usage ) ) ;
}
}
static void interrupted ( int i , char * f ) {
+ + s . ninterrupted ;
s . status [ i ] = INTERRUPTED ;
printf ( " \n interrupted. \n " ) ;
if ( ! verbose & & fullbuffer ) {
printf ( " -- Interrupted %s ------------------------------------ \n " , f ) ;
dump ( ) ;
printf ( " \n -- Interrupted %s (end) ------------------------------ \n " , f ) ;
2010-04-30 18:33:39 +04:00
}
2009-02-12 22:54:45 +03:00
}
2013-07-23 13:42:34 +04:00
static void timeout ( int i , char * f ) {
+ + s . ninterrupted ;
s . status [ i ] = TIMEOUT ;
printf ( " timeout. \n " ) ;
if ( ! verbose & & readbuf ) {
printf ( " -- Timed out %s ------------------------------------ \n " , f ) ;
dump ( ) ;
printf ( " \n -- Timed out %s (end) ------------------------------ \n " , f ) ;
}
}
2011-01-05 18:03:43 +03:00
static void skipped ( int i , char * f ) {
2010-04-07 13:41:33 +04:00
+ + s . nskipped ;
s . status [ i ] = SKIPPED ;
2009-02-12 22:54:45 +03:00
printf ( " skipped. \n " ) ;
}
2011-01-05 18:03:43 +03:00
static void failed ( int i , char * f , int st ) {
2012-05-16 14:43:41 +04:00
if ( readbuf & & strstr ( readbuf , " TEST EXPECT FAIL " ) ) {
printf ( " FAILED (expected). \n " ) ;
s . status [ i ] = KNOWNFAIL ;
+ + s . nknownfail ;
return ;
}
2010-04-07 13:41:33 +04:00
+ + s . nfailed ;
s . status [ i ] = FAILED ;
2013-10-12 00:31:57 +04:00
printf ( " FAILED (status %d). \n " , WEXITSTATUS ( st ) ) ;
2013-06-09 00:23:39 +04:00
if ( ! verbose & & readbuf ) {
2011-11-07 21:02:56 +04:00
printf ( " -- FAILED %s ------------------------------------ \n " , f ) ;
dump ( ) ;
printf ( " -- FAILED %s (end) ------------------------------ \n " , f ) ;
}
2009-02-12 22:54:45 +03:00
}
2011-01-05 18:03:43 +03:00
static void run ( int i , char * f ) {
2013-06-09 00:23:39 +04:00
struct rusage usage ;
2013-06-03 14:09:21 +04:00
char flavour [ 512 ] , script [ 512 ] ;
2009-02-12 22:54:45 +03:00
pid = fork ( ) ;
if ( pid < 0 ) {
perror ( " Fork failed. " ) ;
exit ( 201 ) ;
} else if ( pid = = 0 ) {
2012-10-08 22:15:55 +04:00
if ( ! interactive ) {
2013-10-12 00:31:57 +04:00
close ( STDIN_FILENO ) ;
dup2 ( fds [ 1 ] , STDOUT_FILENO ) ;
dup2 ( fds [ 1 ] , STDERR_FILENO ) ;
2012-10-08 22:15:55 +04:00
close ( fds [ 1 ] ) ;
}
2013-10-12 00:31:57 +04:00
close ( fds [ 0 ] ) ;
2013-05-27 05:12:03 +04:00
if ( strchr ( f , ' : ' ) ) {
strcpy ( flavour , f ) ;
* strchr ( flavour , ' : ' ) = 0 ;
setenv ( " LVM_TEST_FLAVOUR " , flavour , 1 ) ;
strcpy ( script , strchr ( f , ' : ' ) + 1 ) ;
} else {
strcpy ( script , f ) ;
}
2013-07-23 13:42:34 +04:00
setpgid ( 0 , 0 ) ;
2013-06-09 00:23:39 +04:00
execlp ( " bash " , " bash " , " -noprofile " , " -norc " , script , NULL ) ;
2009-02-12 22:54:45 +03:00
perror ( " execlp " ) ;
2009-07-14 01:26:41 +04:00
fflush ( stderr ) ;
_exit ( 202 ) ;
2009-02-12 22:54:45 +03:00
} else {
2013-06-09 00:23:39 +04:00
int st = - 1 , w ;
2011-01-28 19:05:38 +03:00
time_t start = time ( NULL ) ;
2009-02-12 22:54:45 +03:00
char buf [ 128 ] ;
2013-06-03 14:07:31 +04:00
char outpath [ PATH_MAX ] ;
char * c = outpath + strlen ( results ) + 1 ;
2013-07-23 13:42:34 +04:00
struct timeval selectwait ;
2013-09-09 14:14:00 +04:00
fd_set set ;
2013-07-23 13:42:34 +04:00
int runaway = 0 ;
2013-09-09 14:14:00 +04:00
int no_write = 0 ;
2013-09-12 15:30:12 +04:00
FILE * varlogmsg ;
int fd_vlm = - 1 ;
2013-06-09 00:23:39 +04:00
2013-10-12 00:31:57 +04:00
//close(fds[1]);
2013-06-03 14:07:31 +04:00
snprintf ( buf , sizeof ( buf ) , " %s ... " , f ) ;
2013-06-03 01:57:53 +04:00
printf ( " Running %-60s " , buf ) ;
2009-02-12 22:54:45 +03:00
fflush ( stdout ) ;
2013-06-03 14:07:31 +04:00
snprintf ( outpath , sizeof ( outpath ) , " %s/%s.txt " , results , f ) ;
while ( ( c = strchr ( c , ' / ' ) ) )
* c = ' _ ' ;
2013-06-09 00:23:39 +04:00
if ( ! ( outfile = fopen ( outpath , " w " ) ) )
perror ( " fopen " ) ;
2013-09-12 15:30:12 +04:00
/* Mix in kernel log message */
if ( ! ( varlogmsg = fopen ( " /var/log/messages " , " r " ) ) )
perror ( " fopen " ) ;
else if ( ( ( fd_vlm = fileno ( varlogmsg ) ) > = 0 ) & &
fseek ( varlogmsg , 0L , SEEK_END ) )
perror ( " fseek " ) ;
2013-06-09 00:23:39 +04:00
while ( ( w = wait4 ( pid , & st , WNOHANG , & usage ) ) = = 0 ) {
2013-07-23 13:42:34 +04:00
if ( ( fullbuffer & & fullbuffer + + = = 8000 ) | |
2013-09-09 14:14:00 +04:00
( no_write > 180 * 2 ) ) /* a 3 minute timeout */
2013-07-23 13:42:34 +04:00
{
2013-08-05 23:11:49 +04:00
system ( " echo t > /proc/sysrq-trigger " ) ;
kill ( pid , SIGINT ) ;
2013-07-23 13:42:34 +04:00
sleep ( 5 ) ; /* wait a bit for a reaction */
if ( ( w = waitpid ( pid , & st , WNOHANG ) ) = = 0 ) {
kill ( - pid , SIGKILL ) ;
2013-08-05 23:11:49 +04:00
w = pid ; // waitpid(pid, &st, NULL);
2013-07-23 13:42:34 +04:00
}
runaway = 1 ;
break ;
}
2013-09-09 14:14:00 +04:00
FD_ZERO ( & set ) ;
2013-10-12 00:31:57 +04:00
FD_SET ( fds [ 0 ] , & set ) ;
2013-07-23 13:42:34 +04:00
selectwait . tv_sec = 0 ;
2013-09-09 14:14:00 +04:00
selectwait . tv_usec = 500000 ; /* timeout 0.5s */
2013-10-12 00:31:57 +04:00
if ( select ( fds [ 0 ] + 1 , & set , NULL , NULL , & selectwait ) < = 0 ) {
2013-09-09 14:14:00 +04:00
no_write + + ;
2013-06-09 00:23:39 +04:00
continue ;
2013-09-09 14:14:00 +04:00
}
2013-10-12 00:31:57 +04:00
drain ( fds [ 0 ] ) ;
2013-09-09 14:14:00 +04:00
no_write = 0 ;
2013-09-12 15:30:12 +04:00
if ( fd_vlm > = 0 )
drain ( fd_vlm ) ;
2013-06-09 00:23:39 +04:00
}
if ( w ! = pid ) {
perror ( " waitpid " ) ;
exit ( 206 ) ;
}
2013-10-12 00:31:57 +04:00
drain ( fds [ 0 ] ) ;
2013-09-12 15:30:12 +04:00
if ( fd_vlm > = 0 )
drain ( fd_vlm ) ;
2013-07-23 13:42:34 +04:00
if ( die = = 2 )
2013-06-09 00:23:39 +04:00
interrupted ( i , f ) ;
2013-07-23 13:42:34 +04:00
else if ( runaway ) {
timeout ( i , f ) ;
} else if ( WIFEXITED ( st ) ) {
2013-06-09 00:23:39 +04:00
if ( WEXITSTATUS ( st ) = = 0 )
passed ( i , f , start , & usage ) ;
else if ( WEXITSTATUS ( st ) = = 200 )
skipped ( i , f ) ;
else
2009-02-12 22:54:45 +03:00
failed ( i , f , st ) ;
2013-06-09 00:23:39 +04:00
} else
failed ( i , f , st ) ;
2013-06-12 16:16:25 +04:00
2013-09-12 15:30:12 +04:00
if ( varlogmsg )
fclose ( varlogmsg ) ;
2013-06-09 00:23:39 +04:00
if ( outfile )
2013-06-03 14:07:31 +04:00
fclose ( outfile ) ;
2013-06-09 00:23:39 +04:00
if ( fullbuffer )
printf ( " \n Test was interrupted, output has got too large (>%u) (loop:%u) \n "
" Set LVM_TEST_UNLIMITED=1 for unlimited log. \n " ,
( unsigned ) readbuf_sz , fullbuffer ) ;
2013-06-12 16:16:25 +04:00
clear ( ) ;
2009-02-12 22:54:45 +03:00
}
}
int main ( int argc , char * * argv ) {
2013-06-03 14:07:31 +04:00
char results_list [ PATH_MAX ] ;
const char * result ;
2012-10-08 22:15:55 +04:00
const char * be_verbose = getenv ( " VERBOSE " ) ,
* be_interactive = getenv ( " INTERACTIVE " ) ;
2011-01-28 19:05:38 +03:00
time_t start = time ( NULL ) ;
2009-02-12 22:54:45 +03:00
int i ;
2013-06-03 14:07:31 +04:00
FILE * list ;
2010-04-07 13:41:33 +04:00
if ( argc > = MAX ) {
fprintf ( stderr , " Sorry, my head exploded. Please increase MAX. \n " ) ;
exit ( 1 ) ;
}
2012-03-12 18:24:15 +04:00
if ( be_verbose )
verbose = atoi ( be_verbose ) ;
2009-02-12 22:54:45 +03:00
2012-10-08 22:15:55 +04:00
if ( be_interactive )
interactive = atoi ( be_interactive ) ;
2013-06-09 00:23:39 +04:00
results = getenv ( " LVM_TEST_RESULTS " ) ? : " results " ;
( void ) snprintf ( results_list , sizeof ( results_list ) , " %s/list " , results ) ;
2013-06-03 14:07:31 +04:00
2013-10-12 00:31:57 +04:00
//if (pipe(fds)) {
2009-02-12 22:54:45 +03:00
if ( socketpair ( PF_UNIX , SOCK_STREAM , 0 , fds ) ) {
perror ( " socketpair " ) ;
return 201 ;
}
2013-10-12 00:31:57 +04:00
if ( fcntl ( fds [ 0 ] , F_SETFL , O_NONBLOCK ) = = - 1 ) {
2009-02-12 22:54:45 +03:00
perror ( " fcntl on socket " ) ;
return 202 ;
}
/* set up signal handlers */
2013-06-12 16:16:25 +04:00
for ( i = 0 ; i < = 32 ; + + i )
switch ( i ) {
case SIGCHLD : case SIGWINCH : case SIGURG :
case SIGKILL : case SIGSTOP : break ;
default : signal ( i , handler ) ;
}
2009-02-12 22:54:45 +03:00
/* run the tests */
2013-06-09 00:23:39 +04:00
for ( i = 1 ; ! die & & i < argc ; + + i )
2009-02-12 22:54:45 +03:00
run ( i , argv [ i ] ) ;
2013-06-12 16:16:25 +04:00
free ( subst [ 0 ] . value ) ;
free ( subst [ 1 ] . value ) ;
free ( readbuf ) ;
2013-06-09 00:23:39 +04:00
printf ( " \n ## %d tests %s : %d OK, %d warnings, %d failures, %d known failures; "
" %d skipped, %d interrupted \n " ,
s . nwarned + s . npassed + s . nfailed + s . nskipped + s . ninterrupted ,
duration ( start , NULL ) ,
s . npassed , s . nwarned , s . nfailed , s . nknownfail ,
s . nskipped , s . ninterrupted ) ;
2009-02-12 22:54:45 +03:00
2013-05-27 06:26:33 +04:00
/* dump a list to results */
2013-06-03 14:07:31 +04:00
if ( ( list = fopen ( results_list , " w " ) ) ) {
for ( i = 1 ; i < argc ; + + i ) {
switch ( s . status [ i ] ) {
case PASSED : result = " passed " ; break ;
case FAILED : result = " failed " ; break ;
case SKIPPED : result = " skipped " ; break ;
case WARNED : result = " warnings " ; break ;
2013-07-23 13:42:34 +04:00
case TIMEOUT : result = " timeout " ; break ;
2013-06-09 00:23:39 +04:00
case INTERRUPTED : result = " interrupted " ; break ;
2013-06-03 14:07:31 +04:00
default : result = " unknown " ; break ;
}
fprintf ( list , " %s %s \n " , argv [ i ] , result ) ;
2013-05-27 06:26:33 +04:00
}
2013-06-03 14:07:31 +04:00
fclose ( list ) ;
} else
perror ( " fopen result " ) ;
2013-05-27 06:26:33 +04:00
2009-02-12 22:54:45 +03:00
/* print out a summary */
2013-06-09 00:23:39 +04:00
if ( s . nfailed | | s . nskipped | | s . nknownfail | | s . ninterrupted ) {
2009-02-12 22:54:45 +03:00
for ( i = 1 ; i < argc ; + + i ) {
2010-04-07 13:41:33 +04:00
switch ( s . status [ i ] ) {
2009-02-12 22:54:45 +03:00
case FAILED :
printf ( " FAILED: %s \n " , argv [ i ] ) ;
break ;
2012-05-16 14:43:41 +04:00
case KNOWNFAIL :
printf ( " FAILED (expected): %s \n " , argv [ i ] ) ;
break ;
2009-02-12 22:54:45 +03:00
case SKIPPED :
printf ( " skipped: %s \n " , argv [ i ] ) ;
break ;
2013-06-09 00:23:39 +04:00
case INTERRUPTED :
2013-10-12 00:31:57 +04:00
printf ( " INTERRUPTED: %s \n " , argv [ i ] ) ;
2013-06-09 00:23:39 +04:00
break ;
2013-09-04 18:20:35 +04:00
case TIMEOUT :
2013-10-12 00:31:57 +04:00
printf ( " TIMEOUT: %s \n " , argv [ i ] ) ;
2013-09-04 18:20:35 +04:00
break ;
2013-06-03 14:09:21 +04:00
default : /* do nothing */ ;
2009-02-12 22:54:45 +03:00
}
}
printf ( " \n " ) ;
2013-06-09 00:23:39 +04:00
return ( s . nfailed > 0 ) | | ( s . ninterrupted > 0 ) | | die ;
2009-02-12 22:54:45 +03:00
}
2011-01-28 19:05:38 +03:00
2010-04-13 11:34:19 +04:00
return die ;
2009-02-12 22:54:45 +03:00
}