Go to the documentation of this file.00001
00002 #include <unistd.h>
00003 #include <sys/wait.h>
00004
00005 struct Main {
00006
00007 int suite, test;
00008 int status[2];
00009 int confirm[2];
00010 FILE *f_confirm, *f_status;
00011 pid_t pid;
00012 int argc;
00013 char **argv;
00014 pid_t finished;
00015 int status_code;
00016 int test_ok;
00017
00018 int suite_ok, suite_failed;
00019 int total_ok, total_failed;
00020
00021 int announced_suite;
00022 std::string current;
00023
00024 RunAll all;
00025
00026 Main() : suite(0), test(0) {
00027 suite_ok = suite_failed = 0;
00028 total_ok = total_failed = 0;
00029 test_ok = 0;
00030 announced_suite = -1;
00031 }
00032
00033 void child() {
00034 close( status[0] );
00035 close( confirm[1] );
00036 all.status = fdopen( status[1], "w" );
00037 all.confirm = fdopen( confirm[0], "r" );
00038 if ( argc > 1 ) {
00039 RunSuite *s = all.findSuite( argv[1] );
00040 if (!s) {
00041 std::cerr << "No such suite " << argv[1] << std::endl;
00042
00043 exit(250);
00044 }
00045 all.runSuite( *s, test, 0, 1 );
00046 }
00047 if ( argc == 1 ) {
00048 all.runFrom( suite, test );
00049 }
00050 fprintf( all.status, "done\n" );
00051 exit( 0 );
00052 }
00053
00054 void testDied()
00055 {
00056
00057
00058 if ( WIFEXITED( status_code ) ) {
00059 if ( WEXITSTATUS( status_code ) == 250 )
00060 exit( 3 );
00061 if ( WEXITSTATUS( status_code ) == 0 )
00062 return;
00063 }
00064 std::cout << "failed test: "<< current;
00065 if ( WIFEXITED( status_code ) )
00066 std::cout << " (exit status " << WEXITSTATUS( status_code ) << ")";
00067 if ( WIFSIGNALED( status_code ) )
00068 std::cout << " (caught signal " << WTERMSIG( status_code ) << ")";
00069 std::cout << std::endl;
00070
00071 announced_suite --;
00072 ++ test;
00073 test_ok = 0;
00074 suite_failed ++;
00075 }
00076
00077 void processStatus( const char *line ) {
00078 if ( std::string("done") == line ) {
00079 finished = waitpid( pid, &status_code, 0 );
00080 assert_eq( pid, finished );
00081 assert( WIFEXITED( status_code ) );
00082 assert_eq( WEXITSTATUS( status_code ), 0 );
00083 std::cout << "overall " << total_ok << "/"
00084 << total_ok + total_failed
00085 << " ok" << std::endl;
00086 exit( total_failed == 0 ? 0 : 1 );
00087 }
00088
00089 if ( test_ok ) {
00090
00091
00092 std::cout << "." << std::flush;
00093 suite_ok ++;
00094 ++ test;
00095 test_ok = 0;
00096 }
00097
00098 if ( line[0] == 's' ) {
00099 if ( line[2] == 'd' ) {
00100 std::cout << " " << suite_ok << "/" << suite_ok + suite_failed
00101 << " ok" << std::endl;
00102 ++ suite; test = 0;
00103 assert( !test_ok );
00104 total_ok += suite_ok;
00105 total_failed += suite_failed;
00106 suite_ok = suite_failed = 0;
00107 }
00108 if ( line[2] == 's' ) {
00109 if ( announced_suite < suite ) {
00110 std::cout << line + 5 << ": " << std::flush;
00111 announced_suite = suite;
00112 }
00113 }
00114 }
00115 if ( line[0] == 't' ) {
00116 if ( line[2] == 'd' ) {
00117 fprintf( f_confirm, "ack\n" );
00118 fflush( f_confirm );
00119 test_ok = 1;
00120 }
00121 if ( line[2] == 's' ) {
00122 fprintf( f_confirm, "ack\n" );
00123 fflush( f_confirm );
00124 current = line + 5;
00125 }
00126 }
00127 }
00128
00129 void parent() {
00130 close( status[1] );
00131 close( confirm[0] );
00132 f_status = fdopen( status[0], "r" );
00133 f_confirm = fdopen( confirm[1], "w" );
00134 char *line = 0;
00135 size_t n;
00136
00137 while ( true ) {
00138 if ( getline( &line, &n, f_status ) < 0 ) {
00139 finished = waitpid( pid, &status_code, 0 );
00140 if ( finished < 0 ) {
00141 perror( "waitpid failed" );
00142 exit( 5 );
00143 }
00144 assert_eq( pid, finished );
00145 testDied();
00146
00147
00148 return;
00149 } else {
00150
00151 line[ strlen( line ) - 1 ] = 0;
00152 processStatus( line );
00153 free( line );
00154 }
00155 line = 0;
00156 }
00157 }
00158
00159 int main( int _argc, char **_argv )
00160 {
00161 argc = _argc;
00162 argv = _argv;
00163
00164 all.suiteCount = sizeof(suites)/sizeof(RunSuite);
00165 all.suites = suites;
00166
00167 while (true) {
00168 if ( pipe( status ) )
00169 return 1;
00170 if ( pipe( confirm ) )
00171 return 1;
00172 pid = fork();
00173 if ( pid < 0 )
00174 return 2;
00175 if ( pid == 0 ) {
00176 child();
00177 } else {
00178 parent();
00179 }
00180 }
00181 }
00182 };
00183
00184 int main( int argc, char **argv ) {
00185 return Main().main( argc, argv );
00186 }