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