2006-05-09 19:35:46 +04:00
/*
2007-01-19 23:30:05 +03:00
* testutils . c : basic test utils
2006-05-09 19:35:46 +04:00
*
2007-01-19 23:30:05 +03:00
* Copyright ( C ) 2005 - 2007 Red Hat , Inc .
2006-05-09 19:35:46 +04:00
*
* See COPYING . LIB for the License of this software
*
* Karel Zak < kzak @ redhat . com >
*
* $ Id $
*/
2007-12-07 13:08:06 +03:00
# include "config.h"
2006-05-09 19:35:46 +04:00
# include <stdio.h>
# include <stdlib.h>
# include <sys/time.h>
2006-08-24 19:05:19 +04:00
# include <sys/types.h>
# include <sys/stat.h>
2006-08-25 01:46:28 +04:00
# include <sys/wait.h>
2006-08-24 19:05:19 +04:00
# include <unistd.h>
2006-08-25 01:46:28 +04:00
# include <fcntl.h>
# include <limits.h>
2006-05-09 19:35:46 +04:00
# include "testutils.h"
2007-06-15 19:24:20 +04:00
# ifdef HAVE_PATHS_H
# include <paths.h>
# endif
# ifndef _PATH_DEVNULL
# define _PATH_DEVNULL " / dev / null"
# endif
2006-05-09 19:35:46 +04:00
# define GETTIMEOFDAY(T) gettimeofday(T, NULL)
2007-01-19 23:30:05 +03:00
# define DIFF_MSEC(T, U) \
( ( ( ( int ) ( ( T ) - > tv_sec - ( U ) - > tv_sec ) ) * 1000000.0 + \
( ( int ) ( ( T ) - > tv_usec - ( U ) - > tv_usec ) ) ) / 1000.0 )
2006-05-09 19:35:46 +04:00
double
virtTestCountAverage ( double * items , int nitems )
{
2007-01-19 23:30:05 +03:00
long double sum = 0 ;
int i ;
2006-05-09 19:35:46 +04:00
2007-01-19 23:30:05 +03:00
for ( i = 1 ; i < nitems ; i + + )
sum + = items [ i ] ;
2006-05-09 19:35:46 +04:00
2007-01-19 23:30:05 +03:00
return ( double ) ( sum / nitems ) ;
2006-05-09 19:35:46 +04:00
}
2007-01-19 23:30:05 +03:00
/*
2006-05-22 18:38:33 +04:00
* Runs test and count average time ( if the nloops is grater than 1 )
2007-01-19 23:30:05 +03:00
*
* returns : - 1 = error , 0 = success
2006-05-09 19:35:46 +04:00
*/
int
2007-07-19 01:08:22 +04:00
virtTestRun ( const char * title , int nloops , int ( * body ) ( const void * data ) , const void * data )
2006-05-09 19:35:46 +04:00
{
2007-01-19 23:30:05 +03:00
int i , ret = 0 ;
double * ts = NULL ;
if ( nloops > 1 & & ( ts = calloc ( nloops ,
sizeof ( double ) ) ) = = NULL )
return - 1 ;
for ( i = 0 ; i < nloops ; i + + ) {
struct timeval before , after ;
if ( ts )
GETTIMEOFDAY ( & before ) ;
if ( ( ret = body ( data ) ) ! = 0 )
break ;
if ( ts ) {
GETTIMEOFDAY ( & after ) ;
ts [ i ] = DIFF_MSEC ( & after , & before ) ;
}
}
if ( ret = = 0 & & ts )
fprintf ( stderr , " %-50s ... OK [%.5f ms] \n " , title ,
virtTestCountAverage ( ts , nloops ) ) ;
else if ( ret = = 0 )
fprintf ( stderr , " %-50s ... OK \n " , title ) ;
else
fprintf ( stderr , " %-50s ... FAILED \n " , title ) ;
if ( ts )
free ( ts ) ;
return ret ;
2006-05-09 19:35:46 +04:00
}
2006-08-24 19:05:19 +04:00
int virtTestLoadFile ( const char * name ,
2007-01-19 23:30:05 +03:00
char * * buf ,
int buflen ) {
2006-08-24 19:05:19 +04:00
FILE * fp = fopen ( name , " r " ) ;
struct stat st ;
2007-01-19 23:30:05 +03:00
2006-08-24 19:05:19 +04:00
if ( ! fp )
return - 1 ;
if ( fstat ( fileno ( fp ) , & st ) < 0 ) {
fclose ( fp ) ;
return - 1 ;
}
if ( st . st_size > ( buflen - 1 ) ) {
fclose ( fp ) ;
return - 1 ;
}
2007-01-19 23:30:05 +03:00
if ( st . st_size ) {
if ( fread ( * buf , st . st_size , 1 , fp ) ! = 1 ) {
fclose ( fp ) ;
return - 1 ;
}
2006-08-24 19:05:19 +04:00
}
( * buf ) [ st . st_size ] = ' \0 ' ;
fclose ( fp ) ;
return st . st_size ;
}
2006-08-25 01:46:28 +04:00
static
void virtTestCaptureProgramExecChild ( const char * const argv [ ] ,
2007-01-19 23:30:05 +03:00
int pipefd ) {
int i ;
int open_max ;
int stdinfd = - 1 ;
int stderrfd = - 1 ;
const char * const env [ ] = {
" LANG=C " ,
NULL
} ;
if ( ( stdinfd = open ( _PATH_DEVNULL , O_RDONLY ) ) < 0 )
goto cleanup ;
if ( ( stderrfd = open ( _PATH_DEVNULL , O_WRONLY ) ) < 0 )
goto cleanup ;
open_max = sysconf ( _SC_OPEN_MAX ) ;
for ( i = 0 ; i < open_max ; i + + ) {
if ( i ! = stdinfd & &
i ! = stderrfd & &
i ! = pipefd )
close ( i ) ;
}
if ( dup2 ( stdinfd , STDIN_FILENO ) ! = STDIN_FILENO )
goto cleanup ;
if ( dup2 ( pipefd , STDOUT_FILENO ) ! = STDOUT_FILENO )
goto cleanup ;
if ( dup2 ( stderrfd , STDERR_FILENO ) ! = STDERR_FILENO )
goto cleanup ;
/* SUS is crazy here, hence the cast */
execve ( argv [ 0 ] , ( char * const * ) argv , ( char * const * ) env ) ;
2006-08-25 01:46:28 +04:00
cleanup :
2007-01-19 23:30:05 +03:00
if ( stdinfd ! = - 1 )
close ( stdinfd ) ;
if ( stderrfd ! = - 1 )
close ( stderrfd ) ;
2006-08-25 01:46:28 +04:00
}
int virtTestCaptureProgramOutput ( const char * const argv [ ] ,
2007-01-19 23:30:05 +03:00
char * * buf ,
int buflen ) {
int pipefd [ 2 ] ;
if ( pipe ( pipefd ) < 0 )
return - 1 ;
int pid = fork ( ) ;
switch ( pid ) {
2006-08-25 01:46:28 +04:00
case 0 :
close ( pipefd [ 0 ] ) ;
2007-01-19 23:30:05 +03:00
virtTestCaptureProgramExecChild ( argv , pipefd [ 1 ] ) ;
close ( pipefd [ 1 ] ) ;
_exit ( 1 ) ;
2006-08-25 01:46:28 +04:00
case - 1 :
return - 1 ;
2007-01-19 23:30:05 +03:00
2006-08-25 01:46:28 +04:00
default :
2007-01-19 23:30:05 +03:00
{
int got = 0 ;
int ret = - 1 ;
int want = buflen - 1 ;
2006-08-25 01:46:28 +04:00
2007-01-19 23:30:05 +03:00
close ( pipefd [ 1 ] ) ;
2006-08-25 01:46:28 +04:00
2007-01-19 23:30:05 +03:00
while ( want ) {
if ( ( ret = read ( pipefd [ 0 ] , ( * buf ) + got , want ) ) < = 0 )
break ;
got + = ret ;
want - = ret ;
}
close ( pipefd [ 0 ] ) ;
2006-08-25 01:46:28 +04:00
2007-01-19 23:30:05 +03:00
if ( ! ret )
( * buf ) [ got ] = ' \0 ' ;
2006-08-25 01:46:28 +04:00
2007-01-19 23:30:05 +03:00
waitpid ( pid , NULL , 0 ) ;
2006-08-25 01:46:28 +04:00
2007-01-19 23:30:05 +03:00
return ret ;
}
}
2006-08-25 01:46:28 +04:00
}
2007-01-19 23:30:05 +03:00
/*
* Local variables :
* indent - tabs - mode : nil
* c - indent - level : 4
* c - basic - offset : 4
* tab - width : 4
* End :
*/