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