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