libt2n: (tomj) added exception handling to every child after fork(). This is needed...
[libt2n] / test / callback.cpp
CommitLineData
6cda58a6
GE
1/***************************************************************************
2 * Copyright (C) 2004 by Intra2net AG *
3 * info@intra2net.com *
4 * *
5 ***************************************************************************/
6
7#include <sys/types.h>
8#include <unistd.h>
9#include <errno.h>
10#include <signal.h>
11#include <stdio.h>
12
13#include <iostream>
14#include <string>
15#include <sstream>
16#include <stdexcept>
17#include <vector>
18
19#include <boost/bind.hpp>
20
21#include <cppunit/extensions/TestFactoryRegistry.h>
22#include <cppunit/ui/text/TestRunner.h>
23#include <cppunit/extensions/HelperMacros.h>
24
25#include <socket_client.hxx>
26#include <socket_server.hxx>
27
28using namespace std;
29using namespace libt2n;
30using namespace CppUnit;
31
32class test_callback : public TestFixture
33{
34 CPPUNIT_TEST_SUITE(test_callback);
35
91730468
GE
36 CPPUNIT_TEST(ServerNewConnCallback);
37 CPPUNIT_TEST(ServerConnClosedCallback);
38 CPPUNIT_TEST(ServerConnDeletedCallback);
39 CPPUNIT_TEST(ServerCallbackOrder);
40 CPPUNIT_TEST(ClientConnClosedCallback);
41 CPPUNIT_TEST(ClientConnDeletedCallback);
6cda58a6
GE
42
43 CPPUNIT_TEST_SUITE_END();
44
45 std::vector<bool> callback_done;
46
b5922184
GE
47 pid_t child_pid;
48
6cda58a6
GE
49 public:
50
51 void setUp()
52 {
53 callback_done.resize(__events_end);
54 }
55
56 void tearDown()
57 {
58 callback_done.clear();
b5922184
GE
59
60 // make sure the server-child is dead before the next test runs
61 kill(child_pid,SIGKILL);
62 sleep(1);
6cda58a6
GE
63 }
64
65 void callback_func(callback_event_type ev, int conn_id)
66 {
67 // we don't care for the conn_id, we just mark the callback as done
68 if (callback_done[ev])
69 throw runtime_error("callback already done for this event");
70
71 callback_done[ev]=true;
72 }
73
91730468 74 void ServerNewConnCallback()
6cda58a6 75 {
b5922184 76 switch(child_pid=fork())
6cda58a6
GE
77 {
78 case -1:
79 {
80 CPPUNIT_FAIL("fork error");
81 break;
82 }
83 case 0:
84 // child
85 {
441d41fe 86 try
6cda58a6 87 {
441d41fe
TJ
88 string data;
89 // wait till server is up
90 sleep(1);
6cda58a6 91
441d41fe
TJ
92 {
93 socket_client_connection sc("./socket");
6cda58a6 94
441d41fe 95 sc.write("ABC");
6cda58a6 96
441d41fe
TJ
97 // wait half a sec
98 sc.fill_buffer(500000);
99 sc.get_packet(data);
100
101 // close the connection
102 }
103 } catch(...)
104 {
105 std::cerr << "exception in child. ignoring\n";
6cda58a6
GE
106 }
107
108 // don't call atexit and stuff
109 _exit(0);
110 }
111
112 default:
113 // parent
114 {
115 socket_server ss("./socket");
116
117 ss.add_callback(new_connection,bind(&test_callback::callback_func, boost::ref(*this), new_connection, _1));
118
119 // max 3 sec
120 for (int i=0; i < 3; i++)
121 {
122 ss.fill_buffer(1000000);
123
124 string data;
125 unsigned int cid;
126 if(ss.get_packet(data,cid))
127 {
128 server_connection* con=ss.get_connection(cid);
129 con->write("XYZ");
130 }
131 }
132 CPPUNIT_ASSERT_EQUAL(true,static_cast<bool>(callback_done[new_connection]));
133 CPPUNIT_ASSERT_EQUAL(false,static_cast<bool>(callback_done[connection_closed]));
134 CPPUNIT_ASSERT_EQUAL(false,static_cast<bool>(callback_done[connection_deleted]));
135 }
136 }
137 }
138
91730468 139 void ServerConnClosedCallback()
6cda58a6 140 {
b5922184 141 switch(child_pid=fork())
6cda58a6
GE
142 {
143 case -1:
144 {
145 CPPUNIT_FAIL("fork error");
146 break;
147 }
148 case 0:
149 // child
150 {
441d41fe 151 try
6cda58a6 152 {
441d41fe
TJ
153 string data;
154 // wait till server is up
155 sleep(1);
6cda58a6 156
441d41fe
TJ
157 {
158 socket_client_connection sc("./socket");
6cda58a6 159
441d41fe
TJ
160 sc.write("ABC");
161
162 // wait half a sec
163 sc.fill_buffer(500000);
164 sc.get_packet(data);
6cda58a6 165
441d41fe
TJ
166 // close the connection
167 }
168 } catch(...)
169 {
170 std::cerr << "exception in child. ignoring\n";
6cda58a6
GE
171 }
172
173 // don't call atexit and stuff
174 _exit(0);
175 }
176
177 default:
178 // parent
179 {
180 socket_server ss("./socket");
181
182 ss.add_callback(connection_closed,bind(&test_callback::callback_func, boost::ref(*this), connection_closed, _1));
183
184 // max 3 sec
185 for (int i=0; i < 3; i++)
186 {
187 ss.fill_buffer(1000000);
188
189 string data;
190 unsigned int cid;
191 if(ss.get_packet(data,cid))
192 {
193 server_connection* con=ss.get_connection(cid);
194 con->write("XYZ");
195 }
196 }
197 CPPUNIT_ASSERT_EQUAL(false,static_cast<bool>(callback_done[new_connection]));
198 CPPUNIT_ASSERT_EQUAL(true,static_cast<bool>(callback_done[connection_closed]));
199 CPPUNIT_ASSERT_EQUAL(false,static_cast<bool>(callback_done[connection_deleted]));
200 }
201 }
202 }
203
91730468 204 void ServerConnDeletedCallback()
6cda58a6 205 {
b5922184 206 switch(child_pid=fork())
6cda58a6
GE
207 {
208 case -1:
209 {
210 CPPUNIT_FAIL("fork error");
211 break;
212 }
213 case 0:
214 // child
215 {
441d41fe 216 try
6cda58a6 217 {
441d41fe
TJ
218 string data;
219 // wait till server is up
220 sleep(1);
6cda58a6 221
441d41fe
TJ
222 {
223 socket_client_connection sc("./socket");
6cda58a6 224
441d41fe 225 sc.write("ABC");
6cda58a6 226
441d41fe
TJ
227 // wait half a sec
228 sc.fill_buffer(500000);
229 sc.get_packet(data);
230
231 // close the connection
232 }
233 } catch(...)
234 {
235 std::cerr << "exception in child. ignoring\n";
6cda58a6
GE
236 }
237
238 // don't call atexit and stuff
239 _exit(0);
240 }
241
242 default:
243 // parent
244 {
245 socket_server ss("./socket");
246
247 ss.add_callback(connection_deleted,bind(&test_callback::callback_func, boost::ref(*this), connection_deleted, _1));
248
249 // max 3 sec
250 for (int i=0; i < 3; i++)
251 {
252 ss.fill_buffer(1000000);
253
254 string data;
255 unsigned int cid;
256 if(ss.get_packet(data,cid))
257 {
258 server_connection* con=ss.get_connection(cid);
259 con->write("XYZ");
260 }
261 ss.cleanup();
262 }
263 ss.cleanup();
264
265 CPPUNIT_ASSERT_EQUAL(false,static_cast<bool>(callback_done[new_connection]));
266 CPPUNIT_ASSERT_EQUAL(false,static_cast<bool>(callback_done[connection_closed]));
267 CPPUNIT_ASSERT_EQUAL(true,static_cast<bool>(callback_done[connection_deleted]));
268 }
269 }
270 }
271
91730468 272 void ServerCallbackOrder()
6cda58a6 273 {
b5922184 274 switch(child_pid=fork())
6cda58a6
GE
275 {
276 case -1:
277 {
278 CPPUNIT_FAIL("fork error");
279 break;
280 }
281 case 0:
282 // child
283 {
441d41fe 284 try
6cda58a6 285 {
441d41fe
TJ
286 string data;
287 // wait till server is up
288 sleep(1);
6cda58a6 289
441d41fe
TJ
290 {
291 socket_client_connection sc("./socket");
6cda58a6 292
441d41fe
TJ
293 sc.write("1");
294
295 // wait half a sec
296 sc.fill_buffer(500000);
297 sc.get_packet(data);
6cda58a6 298
441d41fe 299 sc.write("2");
6cda58a6 300
441d41fe
TJ
301 // close the connection
302 }
303 } catch(...)
304 {
305 std::cerr << "exception in child. ignoring\n";
6cda58a6
GE
306 }
307
308 // don't call atexit and stuff
309 _exit(0);
310 }
311
312 default:
313 // parent
314 {
315 socket_server ss("./socket");
316
317 ss.add_callback(connection_closed,bind(&test_callback::callback_func, boost::ref(*this), connection_closed, _1));
318 ss.add_callback(connection_deleted,bind(&test_callback::callback_func, boost::ref(*this), connection_deleted, _1));
319
320 bool got_1=false;
321
af84dfb5 322 for (int i=0; i < 5; i++)
6cda58a6
GE
323 {
324 ss.fill_buffer(500000);
325
326 string data;
327 unsigned int cid;
328 if(!got_1 && ss.get_packet(data,cid))
329 {
330 server_connection* con=ss.get_connection(cid);
331 con->write("XYZ");
332 got_1=true;
333 // don't call get_packet anymore
334 }
335 ss.cleanup();
336 }
337 ss.cleanup();
338
af84dfb5
GE
339 CPPUNIT_ASSERT_EQUAL_MESSAGE("closed done",true,static_cast<bool>(callback_done[connection_closed]));
340 CPPUNIT_ASSERT_EQUAL_MESSAGE("not deleted yet",false,static_cast<bool>(callback_done[connection_deleted]));
6cda58a6
GE
341
342 for (int i=0; i < 4; i++)
343 {
344 ss.fill_buffer(500000);
345
346 string data;
347 unsigned int cid;
348 ss.get_packet(data,cid);
349 ss.cleanup();
350 }
351 ss.cleanup();
352
af84dfb5
GE
353 CPPUNIT_ASSERT_EQUAL_MESSAGE("closed done (2)",true,static_cast<bool>(callback_done[connection_closed]));
354 CPPUNIT_ASSERT_EQUAL_MESSAGE("deleted done",true,static_cast<bool>(callback_done[connection_deleted]));
6cda58a6
GE
355 }
356 }
357 }
358
91730468
GE
359 void ClientConnClosedCallback()
360 {
b5922184 361 switch(child_pid=fork())
91730468
GE
362 {
363 case -1:
364 {
365 CPPUNIT_FAIL("fork error");
366 break;
367 }
368 case 0:
369 // child
370 {
441d41fe 371 try
91730468 372 {
441d41fe 373 socket_server ss("./socket");
91730468 374
441d41fe
TJ
375 // max 3 sec
376 for (int i=0; i < 3; i++)
377 {
378 ss.fill_buffer(1000000);
379
380 string data;
381 unsigned int cid;
382 if(ss.get_packet(data,cid))
383 break;
384 }
385 } catch(...)
386 {
387 std::cerr << "exception in child. ignoring\n";
91730468 388 }
441d41fe 389
91730468
GE
390 // don't call atexit and stuff
391 _exit(0);
392 }
393
394 default:
395 // parent
396 {
397 string data;
398 // wait till server is up
399 sleep(1);
400
401 socket_client_connection sc("./socket");
402
403 sc.add_callback(connection_closed,bind(&test_callback::callback_func, boost::ref(*this), connection_closed, 0));
404
405 sc.write("ABC");
406
407 // wait half a sec
408 sc.fill_buffer(500000);
409 sc.get_packet(data);
410
411 CPPUNIT_ASSERT_EQUAL(false,static_cast<bool>(callback_done[new_connection]));
412 CPPUNIT_ASSERT_EQUAL(true,static_cast<bool>(callback_done[connection_closed]));
413 CPPUNIT_ASSERT_EQUAL(false,static_cast<bool>(callback_done[connection_deleted]));
414 }
415 }
416 }
417
418 void ClientConnDeletedCallback()
419 {
b5922184 420 switch(child_pid=fork())
91730468
GE
421 {
422 case -1:
423 {
424 CPPUNIT_FAIL("fork error");
425 break;
426 }
427 case 0:
428 // child
429 {
441d41fe 430 try
91730468 431 {
441d41fe 432 socket_server ss("./socket");
91730468 433
441d41fe
TJ
434 // max 3 sec
435 for (int i=0; i < 3; i++)
436 {
437 ss.fill_buffer(1000000);
438
439 string data;
440 unsigned int cid;
441 if(ss.get_packet(data,cid))
442 break;
443 }
444 } catch(...)
445 {
446 std::cerr << "exception in child. ignoring\n";
91730468 447 }
441d41fe 448
91730468
GE
449 // don't call atexit and stuff
450 _exit(0);
451 }
452
453 default:
454 // parent
455 {
456 string data;
457 // wait till server is up
458 sleep(1);
459
460 {
461 socket_client_connection sc("./socket");
462
463 sc.add_callback(connection_deleted,bind(&test_callback::callback_func, boost::ref(*this), connection_deleted, 0));
464
465 sc.write("ABC");
466
467 // wait half a sec
468 sc.fill_buffer(500000);
469 sc.get_packet(data);
470 }
471
472 CPPUNIT_ASSERT_EQUAL(false,static_cast<bool>(callback_done[new_connection]));
473 CPPUNIT_ASSERT_EQUAL(false,static_cast<bool>(callback_done[connection_closed]));
474 CPPUNIT_ASSERT_EQUAL(true,static_cast<bool>(callback_done[connection_deleted]));
475 }
476 }
477 }
6cda58a6
GE
478};
479
480CPPUNIT_TEST_SUITE_REGISTRATION(test_callback);