wibble 1.1
test-main.h
Go to the documentation of this file.
1// -*- C++ -*-
2#include <wibble/sys/macros.h>
3
4#include <unistd.h>
5
6#ifdef POSIX
7#include <sys/wait.h>
8#include <sys/socket.h>
9#endif
10
11#include <cstring>
12#include <cstdio>
13
14#include <wibble/sys/pipe.h>
15
16struct Main : RunFeedback {
17
18 int suite, test;
21 int status_fds[2];
23 pid_t pid;
24 int argc;
25 char **argv;
26 pid_t finished;
29
32
34 std::string current;
36
38
39 Main() : suite(0), test(0) {
42 test_ok = 0;
43 announced_suite = -1;
44 }
45
46 void child() {
47#ifdef POSIX
48 close( status_fds[0] );
49 close( confirm_fds[1] );
50#endif
52 if ( argc > 1 ) {
53 RunSuite *s = all.findSuite( argv[1] );
54 if (!s) {
55 std::cerr << "No such suite " << argv[1] << std::endl;
56 // todo dump possible suites?
57 exit(250);
58 }
59 if ( argc > 2 ) {
60 if ( !test ) {
61 char *end;
62 int t = strtol( argv[2], &end, 0 );
63 if ( end == argv[2] && t == 0 ) {
64 t = s->findTest( argv[2] );
65 if ( t < 0 ) {
66 std::cerr << "No such test " << argv[2]
67 << " in suite " << argv[1] << std::endl;
68 // todo dump possible suites?
69 exit(250);
70 }
71 }
72 all.runTest( *s, t );
73 }
74 } else
75 all.runSuite( *s, test, 0, 1 );
76 }
77 if ( argc == 1 ) {
79 }
80 status( "done" );
81 exit( 0 );
82 }
83
84#ifdef POSIX
85 void testDied()
86 {
87#pragma GCC diagnostic push
88#pragma GCC diagnostic ignored "-Wold-style-cast"
89 /* std::cerr << "test died: " << test << "/"
90 << suites[suite].testCount << std::endl; */
91 if ( WIFEXITED( status_code ) ) {
92 if ( WEXITSTATUS( status_code ) == 250 )
93 exit( 3 );
94 if ( WEXITSTATUS( status_code ) == 0 )
95 return;
96 }
97 std::cout << "--> FAILED: "<< current;
98 if ( WIFEXITED( status_code ) )
99 std::cout << " (exit status " << WEXITSTATUS( status_code ) << ")";
100 if ( WIFSIGNALED( status_code ) )
101 std::cout << " (caught signal " << WTERMSIG( status_code ) << ")";
102 std::cout << std::endl;
103 // re-announce the suite
105 ++ test; // continue with next test
106 test_ok = 0;
107 suite_failed ++;
108#pragma GCC diagnostic pop
109 }
110#endif
111
112 void processStatus( std::string line ) {
113 // std::cerr << line << std::endl;
114 if ( line == "done" ) { // finished
115#ifdef POSIX
116#pragma GCC diagnostic push
117#pragma GCC diagnostic ignored "-Wold-style-cast"
118 if ( want_fork ) {
119 finished = waitpid( pid, &status_code, 0 );
121 assert( WIFEXITED( status_code ) );
122 assert_eq( WEXITSTATUS( status_code ), 0 );
123 }
124#pragma GCC diagnostic pop
125#endif
126 std::cout << "overall " << total_ok << "/"
128 << " ok" << std::endl;
129 exit( total_failed == 0 ? 0 : 1 );
130 }
131
132 if ( test_ok ) {
133 /* std::cerr << "test ok: " << test << "/"
134 << suites[suite].testCount << std::endl; */
135 std::cout << "." << std::flush;
136 suite_ok ++;
137 ++ test;
138 test_ok = 0;
139 }
140
141 if ( line[0] == 's' ) {
142 if ( line[2] == 'd' ) {
143 std::cout << " " << suite_ok << "/" << suite_ok + suite_failed
144 << " ok" << std::endl;
145 ++ suite; test = 0;
146 assert( !test_ok );
150 }
151 if ( line[2] == 's' ) {
152 if ( announced_suite < suite ) {
153 std::cout << std::string( line.begin() + 5, line.end() )
154 << ": " << std::flush;
156 }
157 }
158 }
159 if ( line[0] == 't' ) {
160 if ( line[2] == 'd' ) {
161 confirm();
162 test_ok = 1;
163 }
164 if ( line[2] == 's' ) {
165 confirm();
166 current = std::string( line.begin() + 5, line.end() );
167 }
168 }
169 }
170
171#ifdef POSIX
172 void parent() {
173 close( status_fds[1] );
174 close( confirm_fds[0] );
176 std::string line;
177
178 while ( true ) {
179 if ( p_status.eof() ) {
180 finished = waitpid( pid, &status_code, 0 );
181 if ( finished < 0 ) {
182 perror( "waitpid failed" );
183 exit( 5 );
184 }
186 testDied();
187 return;
188 }
189
190 line = p_status.nextLineBlocking();
191 processStatus( line );
192 }
193 }
194#endif
195
196 void status( std::string line ) {
197 // std::cerr << "status: " << line << std::endl;
198#ifdef POSIX
199 if ( want_fork ) {
200 line += "\n";
201 ::write( status_fds[ 1 ], line.c_str(), line.length() );
202 } else
203#endif
204 processStatus( line );
205 }
206
207 void confirm() {
208 std::string line( "ack\n" );
209 if ( want_fork )
210 ::write( confirm_fds[ 1 ], line.c_str(), line.length() );
211 }
212
213 void waitForAck() {
214 if ( want_fork ) {
215 std::string line = p_confirm.nextLineBlocking();
216 assert_eq( std::string( "ack" ), line );
217 }
218 }
219
220 int main( int _argc, char **_argv )
221 {
222 argc = _argc;
223 argv = _argv;
224
225 all.suiteCount = sizeof(suites)/sizeof(RunSuite);
226 all.suites = suites;
227 all.feedback = this;
228#ifdef POSIX
229 want_fork = argc <= 2;
230#else
231 want_fork = false;
232#endif
233
234 while (true) {
235#ifdef POSIX
236 if ( socketpair( PF_UNIX,SOCK_STREAM, 0, status_fds ) )
237 return 1;
238 if ( socketpair( PF_UNIX,SOCK_STREAM, 0, confirm_fds ) )
239 return 1;
240 if ( want_fork ) {
241 pid = fork();
242 if ( pid < 0 )
243 return 2;
244 if ( pid == 0 ) { // child
245 child();
246 } else {
247 parent();
248 }
249 } else
250#endif
251 child();
252 }
253 return 0;
254 }
255};
256
257int main( int argc, char **argv ) {
258 return Main().main( argc, argv );
259}
260
Definition test-main.h:16
void status(std::string line)
Definition test-main.h:196
int announced_suite
Definition test-main.h:33
int test
Definition test-main.h:18
int status_code
Definition test-main.h:27
int total_failed
Definition test-main.h:31
int test_ok
Definition test-main.h:28
void child()
Definition test-main.h:46
RunAll all
Definition test-main.h:37
std::string current
Definition test-main.h:34
Main()
Definition test-main.h:39
int argc
Definition test-main.h:24
int suite
Definition test-main.h:18
void confirm()
Definition test-main.h:207
void processStatus(std::string line)
Definition test-main.h:112
wibble::sys::Pipe p_status
Definition test-main.h:19
int main(int _argc, char **_argv)
Definition test-main.h:220
char ** argv
Definition test-main.h:25
void waitForAck()
Definition test-main.h:213
int total_ok
Definition test-main.h:31
int confirm_fds[2]
Definition test-main.h:22
wibble::sys::Pipe p_confirm
Definition test-main.h:20
int status_fds[2]
Definition test-main.h:21
pid_t finished
Definition test-main.h:26
pid_t pid
Definition test-main.h:23
bool want_fork
Definition test-main.h:35
int suite_ok
Definition test-main.h:30
int suite_failed
Definition test-main.h:30
Definition test-runner.h:36
void runFrom(int suite, int test)
Definition test-runner.h:76
void runSuite(RunSuite &s, int fromTest, int suite, int suiteCount)
Definition test-runner.h:48
int suiteCount
Definition test-runner.h:38
void runTest(RunSuite &s, int test)
Definition test-runner.h:65
RunFeedback * feedback
Definition test-runner.h:39
RunSuite * findSuite(std::string name)
Definition test-runner.h:41
RunSuite * suites
Definition test-runner.h:37
Definition test-runner.h:31
Definition test-runner.h:17
int findTest(std::string name)
Definition test-runner.h:22
Definition pipe.h:27
std::string nextLineBlocking()
Definition pipe.h:204
bool eof()
Definition pipe.h:130
int main(int argc, char **argv)
Definition test-main.h:257
#define assert_eq(x, y)
Definition test.h:33
#define assert(x)
Definition test.h:30