libept
test-main.h
Go to the documentation of this file.
1 // -*- C++ -*-
2 #include <unistd.h>
3 #include <sys/wait.h>
4 
5 struct Main {
6 
7  int suite, test;
8  int status[2];
9  int confirm[2];
11  pid_t pid;
12  int argc;
13  char **argv;
14  pid_t finished;
16  int test_ok;
17 
20 
22  std::string current;
23 
25 
26  Main() : suite(0), test(0) {
27  suite_ok = suite_failed = 0;
28  total_ok = total_failed = 0;
29  test_ok = 0;
30  announced_suite = -1;
31  }
32 
33  void child() {
34  close( status[0] );
35  close( confirm[1] );
36  all.status = fdopen( status[1], "w" );
37  all.confirm = fdopen( confirm[0], "r" );
38  if ( argc > 1 ) {
39  RunSuite *s = all.findSuite( argv[1] );
40  if (!s) {
41  std::cerr << "No such suite " << argv[1] << std::endl;
42  // todo dump possible suites?
43  exit(250);
44  }
45  all.runSuite( *s, test, 0, 1 );
46  }
47  if ( argc == 1 ) {
48  all.runFrom( suite, test );
49  }
50  fprintf( all.status, "done\n" );
51  exit( 0 );
52  }
53 
54  void testDied()
55  {
56  /* std::cerr << "test died: " << test << "/"
57  << suites[suite].testCount << std::endl; */
58  if ( WIFEXITED( status_code ) ) {
59  if ( WEXITSTATUS( status_code ) == 250 )
60  exit( 3 );
61  if ( WEXITSTATUS( status_code ) == 0 )
62  return;
63  }
64  std::cout << "failed test: "<< current;
65  if ( WIFEXITED( status_code ) )
66  std::cout << " (exit status " << WEXITSTATUS( status_code ) << ")";
67  if ( WIFSIGNALED( status_code ) )
68  std::cout << " (caught signal " << WTERMSIG( status_code ) << ")";
69  std::cout << std::endl;
70  // re-announce the suite
71  announced_suite --;
72  ++ test; // continue with next test
73  test_ok = 0;
74  suite_failed ++;
75  }
76 
77  void processStatus( const char *line ) {
78  if ( std::string("done") == line ) { // finished
79  finished = waitpid( pid, &status_code, 0 );
80  assert_eq( pid, finished );
81  assert( WIFEXITED( status_code ) );
82  assert_eq( WEXITSTATUS( status_code ), 0 );
83  std::cout << "overall " << total_ok << "/"
85  << " ok" << std::endl;
86  exit( total_failed == 0 ? 0 : 1 );
87  }
88 
89  if ( test_ok ) {
90  /* std::cerr << "test ok: " << test << "/"
91  << suites[suite].testCount << std::endl; */
92  std::cout << "." << std::flush;
93  suite_ok ++;
94  ++ test;
95  test_ok = 0;
96  }
97 
98  if ( line[0] == 's' ) {
99  if ( line[2] == 'd' ) {
100  std::cout << " " << suite_ok << "/" << suite_ok + suite_failed
101  << " ok" << std::endl;
102  ++ suite; test = 0;
103  assert( !test_ok );
104  total_ok += suite_ok;
106  suite_ok = suite_failed = 0;
107  }
108  if ( line[2] == 's' ) {
109  if ( announced_suite < suite ) {
110  std::cout << line + 5 << ": " << std::flush;
112  }
113  }
114  }
115  if ( line[0] == 't' ) {
116  if ( line[2] == 'd' ) {
117  fprintf( f_confirm, "ack\n" );
118  fflush( f_confirm );
119  test_ok = 1;
120  }
121  if ( line[2] == 's' ) {
122  fprintf( f_confirm, "ack\n" );
123  fflush( f_confirm );
124  current = line + 5;
125  }
126  }
127  }
128 
129  void parent() {
130  close( status[1] );
131  close( confirm[0] );
132  f_status = fdopen( status[0], "r" );
133  f_confirm = fdopen( confirm[1], "w" );
134  char *line = 0;
135  size_t n;
136 
137  while ( true ) {
138  if ( getline( &line, &n, f_status ) < 0 ) {
139  finished = waitpid( pid, &status_code, 0 );
140  if ( finished < 0 ) {
141  perror( "waitpid failed" );
142  exit( 5 );
143  }
144  assert_eq( pid, finished );
145  testDied();
146  /* std::cerr << "child will be reforked at: "
147  << suite << " " << test << std::endl; */
148  return;
149  } else {
150  // std::cerr << "reading pipe: " << line;
151  line[ strlen( line ) - 1 ] = 0;
152  processStatus( line );
153  free( line );
154  }
155  line = 0;
156  }
157  }
158 
159  int main( int _argc, char **_argv )
160  {
161  argc = _argc;
162  argv = _argv;
163 
164  all.suiteCount = sizeof(suites)/sizeof(RunSuite);
165  all.suites = suites;
166 
167  while (true) {
168  if ( pipe( status ) )
169  return 1;
170  if ( pipe( confirm ) )
171  return 1;
172  pid = fork();
173  if ( pid < 0 )
174  return 2;
175  if ( pid == 0 ) { // child
176  child();
177  } else {
178  parent();
179  }
180  }
181  }
182 };
183 
184 int main( int argc, char **argv ) {
185  return Main().main( argc, argv );
186 }