• Main Page
  • Namespaces
  • Classes
  • Files
  • File List
  • File Members

test-main.h

Go to the documentation of this file.
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 }

Generated on Wed Oct 27 2010 12:43:31 for libept by  doxygen 1.7.1