libept
|
00001 // -*- C++ -*- 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 // todo dump possible suites? 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 /* std::cerr << "test died: " << test << "/" 00057 << suites[suite].testCount << std::endl; */ 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 // re-announce the suite 00071 announced_suite --; 00072 ++ test; // continue with next test 00073 test_ok = 0; 00074 suite_failed ++; 00075 } 00076 00077 void processStatus( const char *line ) { 00078 if ( std::string("done") == line ) { // finished 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 /* std::cerr << "test ok: " << test << "/" 00091 << suites[suite].testCount << std::endl; */ 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 /* std::cerr << "child will be reforked at: " 00147 << suite << " " << test << std::endl; */ 00148 return; 00149 } else { 00150 // std::cerr << "reading pipe: " << line; 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 ) { // child 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 }