client_wrapper.hxx, socket_wrapper.hxx: reorder member initialization order
[libt2n] / test / reconnect.cpp
CommitLineData
19facd85
TJ
1/*
2Copyright (C) 2004 by Intra2net AG
af84dfb5 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*/
af84dfb5
GE
22#include <sys/types.h>
23#include <unistd.h>
24#include <errno.h>
25#include <signal.h>
26#include <stdio.h>
4c3662a0 27#include <time.h>
af84dfb5
GE
28
29#include <iostream>
30#include <string>
31#include <sstream>
32#include <stdexcept>
33
307b5e74
TJ
34#define BOOST_TEST_DYN_LINK
35#include <boost/test/unit_test.hpp>
af84dfb5
GE
36
37#include <socket_client.hxx>
38#include <socket_server.hxx>
39
307b5e74
TJ
40#include "test_fixtures.hxx"
41
af84dfb5 42#include <config.h>
af84dfb5
GE
43
44using namespace std;
45using namespace libt2n;
af84dfb5 46
df94ded3 47BOOST_FIXTURE_TEST_SUITE(test_reconnect, KillChildOnShutdownFixture)
307b5e74
TJ
48
49BOOST_AUTO_TEST_CASE(simple_reconnect)
50{
51 switch(child_pid=fork())
52 {
53 case -1:
af84dfb5 54 {
307b5e74
TJ
55 BOOST_FAIL("fork error");
56 break;
57 }
58 case 0:
59 // child
60 {
61 try
af84dfb5 62 {
307b5e74 63 socket_server ss("./socket");
af84dfb5 64
307b5e74 65 time_t t0 = time(NULL);
af84dfb5 66
307b5e74
TJ
67 // max 10 sec
68 while (time(NULL) < t0 + 10 )
69 {
70 ss.fill_buffer(1000000);
441d41fe 71
307b5e74
TJ
72 string data;
73 unsigned int cid;
441d41fe 74
307b5e74
TJ
75 if(ss.get_packet(data,cid))
76 {
77 server_connection* con=ss.get_connection(cid);
af84dfb5 78
307b5e74
TJ
79 if (data=="QUIT")
80 break;
af84dfb5 81
307b5e74
TJ
82 if (data=="x")
83 con->write(string().insert(0,100,'X'));
84 else
85 con->write(string().insert(0,100,'Y'));
af84dfb5
GE
86 }
87 }
307b5e74
TJ
88 } catch(...)
89 {
90 std::cerr << "exception in child. ignoring\n";
af84dfb5
GE
91 }
92
307b5e74
TJ
93 // don't call atexit and stuff
94 _exit(0);
95 }
af84dfb5 96
307b5e74
TJ
97 default:
98 // parent
99 {
100 // don't kill us on broken pipe
101 signal(SIGPIPE, SIG_IGN);
af84dfb5 102
307b5e74
TJ
103 // wait till server is up
104 sleep(1);
105 socket_client_connection sc("./socket");
af84dfb5 106
307b5e74 107 sc.write("abc");
af84dfb5 108
307b5e74 109 string data;
af84dfb5 110
307b5e74
TJ
111 while (!sc.get_packet(data))
112 sc.fill_buffer(1000000);
af84dfb5 113
307b5e74 114 sc.reconnect();
af84dfb5 115
307b5e74 116 sc.write("x");
af84dfb5 117
307b5e74
TJ
118 while (!sc.get_packet(data))
119 sc.fill_buffer(1000000);
120
121 BOOST_CHECK_EQUAL(string().insert(0,100,'X'),data);
af84dfb5
GE
122 }
123 }
307b5e74 124}
af84dfb5 125
307b5e74
TJ
126BOOST_AUTO_TEST_CASE(reconnect_with_close)
127{
128 switch(child_pid=fork())
af84dfb5 129 {
307b5e74 130 case -1:
af84dfb5 131 {
307b5e74
TJ
132 BOOST_FAIL("fork error");
133 break;
134 }
135 case 0:
136 // child
137 {
138 try
af84dfb5 139 {
307b5e74 140 socket_server ss("./socket");
af84dfb5 141
307b5e74 142 time_t t0 = time(NULL);
af84dfb5 143
307b5e74
TJ
144 // max 10 sec
145 while (time(NULL) < t0 + 10 )
146 {
147 ss.fill_buffer(1000000);
af84dfb5 148
307b5e74
TJ
149 string data;
150 unsigned int cid;
af84dfb5 151
307b5e74
TJ
152 if(ss.get_packet(data,cid))
153 {
154 server_connection* con=ss.get_connection(cid);
441d41fe 155
307b5e74
TJ
156 if (data=="QUIT")
157 break;
441d41fe 158
307b5e74
TJ
159 if (data=="x")
160 con->write(string().insert(0,100,'X'));
161 else
162 con->write(string().insert(0,100,'Y'));
af84dfb5
GE
163 }
164 }
307b5e74
TJ
165 } catch(...)
166 {
167 std::cerr << "exception in child. ignoring\n";
af84dfb5
GE
168 }
169
307b5e74
TJ
170 // don't call atexit and stuff
171 _exit(0);
172 }
af84dfb5 173
307b5e74
TJ
174 default:
175 // parent
176 {
177 // don't kill us on broken pipe
178 signal(SIGPIPE, SIG_IGN);
af84dfb5 179
307b5e74
TJ
180 // wait till server is up
181 sleep(1);
182 socket_client_connection sc("./socket");
af84dfb5 183
307b5e74 184 sc.write("abc");
af84dfb5 185
307b5e74 186 string data;
af84dfb5 187
307b5e74
TJ
188 while (!sc.get_packet(data))
189 sc.fill_buffer(1000000);
af84dfb5 190
307b5e74 191 sc.close();
af84dfb5 192
307b5e74
TJ
193 // empty buffer
194 sc.get_packet(data);
af84dfb5 195
307b5e74 196 sc.reconnect();
af84dfb5 197
307b5e74 198 sc.write("x");
af84dfb5 199
307b5e74
TJ
200 while (!sc.get_packet(data))
201 sc.fill_buffer(1000000);
202
203 BOOST_CHECK_EQUAL(string().insert(0,100,'X'),data);
af84dfb5
GE
204 }
205 }
307b5e74 206}
af84dfb5 207
307b5e74
TJ
208BOOST_AUTO_TEST_CASE(reconnect_buffer_complete)
209{
210 switch(child_pid=fork())
af84dfb5 211 {
307b5e74 212 case -1:
af84dfb5 213 {
307b5e74
TJ
214 BOOST_FAIL("fork error");
215 break;
216 }
217 case 0:
218 // child
219 {
220 try
af84dfb5 221 {
307b5e74 222 socket_server ss("./socket");
af84dfb5 223
307b5e74 224 time_t t0 = time(NULL);
af84dfb5 225
307b5e74
TJ
226 // max 10 sec
227 while (time(NULL) < t0 + 10 )
228 {
229 ss.fill_buffer(1000000);
441d41fe 230
307b5e74
TJ
231 string data;
232 unsigned int cid;
441d41fe 233
307b5e74
TJ
234 if(ss.get_packet(data,cid))
235 {
236 server_connection* con=ss.get_connection(cid);
af84dfb5 237
307b5e74
TJ
238 if (data=="QUIT")
239 break;
af84dfb5 240
307b5e74
TJ
241 if (data=="x")
242 con->write(string().insert(0,100,'X'));
af84dfb5
GE
243 }
244 }
307b5e74
TJ
245 } catch(...)
246 {
247 std::cerr << "exception in child. ignoring\n";
af84dfb5
GE
248 }
249
307b5e74
TJ
250 // don't call atexit and stuff
251 _exit(0);
252 }
af84dfb5 253
307b5e74
TJ
254 default:
255 // parent
256 {
257 // don't kill us on broken pipe
258 signal(SIGPIPE, SIG_IGN);
af84dfb5 259
307b5e74
TJ
260 // wait till server is up
261 sleep(1);
262 socket_client_connection sc("./socket");
af84dfb5 263
307b5e74 264 sc.write("x");
af84dfb5 265
307b5e74 266 string data;
af84dfb5 267
307b5e74
TJ
268 while (!sc.packet_available())
269 sc.fill_buffer(1000000);
af84dfb5 270
307b5e74 271 sc.reconnect();
af84dfb5 272
307b5e74
TJ
273 BOOST_CHECK_MESSAGE(sc.get_packet(data) == true, "packet not there");
274
275 BOOST_CHECK_MESSAGE(data == string().insert(0,100,'X'), "data incorrect");
af84dfb5
GE
276 }
277 }
307b5e74 278}
af84dfb5 279
307b5e74
TJ
280BOOST_AUTO_TEST_CASE(reconnect_buffer_several_complete)
281{
282 const int packets=3;
af84dfb5 283
307b5e74
TJ
284 switch(child_pid=fork())
285 {
286 case -1:
af84dfb5 287 {
307b5e74
TJ
288 BOOST_FAIL("fork error");
289 break;
290 }
291 case 0:
292 // child
293 {
294 try
af84dfb5 295 {
307b5e74
TJ
296 socket_server ss("./socket");
297
298 time_t t0 = time(NULL);
299
300 // max 10 sec
301 while (time(NULL) < t0 + 10 )
af84dfb5 302 {
307b5e74 303 ss.fill_buffer(1000000);
af84dfb5 304
307b5e74
TJ
305 string data;
306 unsigned int cid;
af84dfb5 307
307b5e74 308 if(ss.get_packet(data,cid))
af84dfb5 309 {
307b5e74 310 server_connection* con=ss.get_connection(cid);
af84dfb5 311
307b5e74
TJ
312 if (data=="QUIT")
313 break;
af84dfb5 314
307b5e74 315 if (data=="x")
af84dfb5 316 {
307b5e74
TJ
317 for (int i=0; i<packets; i++)
318 con->write(string().insert(0,100,'X'));
af84dfb5
GE
319 }
320 }
321 }
307b5e74
TJ
322 } catch(...)
323 {
324 std::cerr << "exception in child. ignoring\n";
af84dfb5
GE
325 }
326
307b5e74
TJ
327 // don't call atexit and stuff
328 _exit(0);
329 }
af84dfb5 330
307b5e74
TJ
331 default:
332 // parent
333 {
334 // don't kill us on broken pipe
335 signal(SIGPIPE, SIG_IGN);
af84dfb5 336
307b5e74
TJ
337 // wait till server is up
338 sleep(1);
339 socket_client_connection sc("./socket");
af84dfb5 340
307b5e74 341 sc.write("x");
af84dfb5 342
307b5e74
TJ
343 // retrieve packets for 3 seconds
344 time_t t0 = time(NULL);
af84dfb5 345
307b5e74
TJ
346 // max 3 sec
347 while (time(NULL) < t0 + 3 )
348 sc.fill_buffer(1000000);
af84dfb5 349
307b5e74 350 // we now should have packets complete packets in the buffer
af84dfb5 351
307b5e74 352 sc.reconnect();
af84dfb5 353
307b5e74 354 // are these packets still there?
af84dfb5 355
307b5e74
TJ
356 for (int i=0; i < packets; i++)
357 {
358 string data;
af84dfb5 359
307b5e74
TJ
360 ostringstream os;
361 os << "packet " << i << " not there";
af84dfb5 362
307b5e74 363 BOOST_CHECK_MESSAGE(sc.get_packet(data) == true, os.str());
af84dfb5 364
307b5e74
TJ
365 os.str("");
366 os << "packet " << i << " incorrect";
367
368 BOOST_CHECK_MESSAGE(string().insert(0,100,'X') == data, os.str());
af84dfb5
GE
369 }
370 }
371 }
307b5e74 372}
af84dfb5 373
307b5e74
TJ
374BOOST_AUTO_TEST_CASE(reconnect_buffer_no_incomplete1)
375{
376 switch(child_pid=fork())
af84dfb5 377 {
307b5e74 378 case -1:
af84dfb5 379 {
307b5e74
TJ
380 BOOST_FAIL("fork error");
381 break;
382 }
383 case 0:
384 // child
385 {
386 try
af84dfb5 387 {
307b5e74
TJ
388 socket_server ss("./socket");
389
390 time_t t0 = time(NULL);
391
392 // max 10 sec
393 while (time(NULL) < t0 + 10 )
af84dfb5 394 {
307b5e74 395 ss.fill_buffer(1000000);
af84dfb5 396
307b5e74
TJ
397 string data;
398 unsigned int cid;
af84dfb5 399
307b5e74 400 if(ss.get_packet(data,cid))
af84dfb5 401 {
307b5e74 402 server_connection* con=ss.get_connection(cid);
af84dfb5 403
307b5e74
TJ
404 if (data=="QUIT")
405 break;
af84dfb5 406
307b5e74 407 if (data=="x")
af84dfb5 408 {
307b5e74
TJ
409 con->write(string().insert(0,100,'X'));
410 send_raw_socket("aaaab",&ss,cid);
af84dfb5
GE
411 }
412 }
413 }
307b5e74
TJ
414 } catch(...)
415 {
416 std::cerr << "exception in child. ignoring\n";
af84dfb5
GE
417 }
418
307b5e74
TJ
419 // don't call atexit and stuff
420 _exit(0);
421 }
af84dfb5 422
307b5e74
TJ
423 default:
424 // parent
425 {
426 // don't kill us on broken pipe
427 signal(SIGPIPE, SIG_IGN);
af84dfb5 428
307b5e74
TJ
429 // wait till server is up
430 sleep(1);
431 socket_client_connection sc("./socket");
af84dfb5 432
307b5e74 433 sc.write("x");
af84dfb5 434
307b5e74
TJ
435 // retrieve packets for 3 seconds
436 time_t t0 = time(NULL);
af84dfb5 437
307b5e74
TJ
438 // max 3 sec
439 while (time(NULL) < t0 + 3 )
440 sc.fill_buffer(1000000);
af84dfb5 441
307b5e74 442 // we now should have one complete packet and some stuff in the buffer
af84dfb5 443
307b5e74
TJ
444 string data;
445 sc.get_packet(data);
af84dfb5 446
307b5e74 447 BOOST_CHECK_MESSAGE((sc.peek_packet(data))>0, "no incomplete packet");
af84dfb5 448
307b5e74
TJ
449 sc.reconnect();
450
451 BOOST_CHECK_MESSAGE((int)sc.peek_packet(data) == 0, "incomplete packet not removed");
af84dfb5
GE
452 }
453 }
307b5e74 454}
af84dfb5 455
307b5e74
TJ
456BOOST_AUTO_TEST_CASE(reconnect_buffer_no_incomplete2)
457{
458 switch(child_pid=fork())
af84dfb5 459 {
307b5e74 460 case -1:
af84dfb5 461 {
307b5e74
TJ
462 BOOST_FAIL("fork error");
463 break;
464 }
465 case 0:
466 // child
467 {
468 try
af84dfb5 469 {
307b5e74
TJ
470 socket_server ss("./socket");
471
472 time_t t0 = time(NULL);
473
474 // max 10 sec
475 while (time(NULL) < t0 + 10 )
af84dfb5 476 {
307b5e74 477 ss.fill_buffer(1000000);
af84dfb5 478
307b5e74
TJ
479 string data;
480 unsigned int cid;
af84dfb5 481
307b5e74 482 if(ss.get_packet(data,cid))
af84dfb5 483 {
307b5e74 484 server_connection* con=ss.get_connection(cid);
af84dfb5 485
307b5e74
TJ
486 if (data=="QUIT")
487 break;
af84dfb5 488
307b5e74 489 if (data=="x")
af84dfb5 490 {
307b5e74 491 con->write(string().insert(0,100,'X'));
441d41fe 492
307b5e74 493 string blob=string().insert(0,100,'Y');
af84dfb5 494
307b5e74
TJ
495 // one byte will be missing...
496 int size=blob.size()+1;
497 char sizetransfer[sizeof(int)+1];
498 memcpy(sizetransfer,(void*)&size,sizeof(int));
499 sizetransfer[sizeof(int)+1]=0;
af84dfb5 500
307b5e74 501 string packet=string(sizetransfer)+blob;
af84dfb5 502
307b5e74 503 send_raw_socket(packet,&ss,cid);
af84dfb5
GE
504 }
505 }
506 }
307b5e74
TJ
507 } catch(...)
508 {
509 std::cerr << "exception in child. ignoring\n";
af84dfb5
GE
510 }
511
307b5e74
TJ
512 // don't call atexit and stuff
513 _exit(0);
514 }
af84dfb5 515
307b5e74
TJ
516 default:
517 // parent
518 {
519 // don't kill us on broken pipe
520 signal(SIGPIPE, SIG_IGN);
af84dfb5 521
307b5e74
TJ
522 // wait till server is up
523 sleep(1);
524 socket_client_connection sc("./socket");
af84dfb5 525
307b5e74 526 sc.write("x");
af84dfb5 527
307b5e74
TJ
528 // retrieve packets for 3 seconds
529 time_t t0 = time(NULL);
af84dfb5 530
307b5e74
TJ
531 // max 3 sec
532 while (time(NULL) < t0 + 3 )
533 sc.fill_buffer(1000000);
af84dfb5 534
307b5e74 535 // we now should have one complete packet and some stuff in the buffer
af84dfb5 536
307b5e74 537 sc.reconnect();
af84dfb5 538
307b5e74 539 string data;
af84dfb5 540
307b5e74
TJ
541 BOOST_CHECK_MESSAGE(sc.get_packet(data) == true, "packet not there");
542 BOOST_CHECK_MESSAGE(string().insert(0,100,'X') == data, "data incorrect");
543
544 BOOST_CHECK_MESSAGE((int)sc.peek_packet(data) == 0, "incomplete packet not removed");
af84dfb5
GE
545 }
546 }
307b5e74 547}
af84dfb5 548
307b5e74 549BOOST_AUTO_TEST_SUITE_END()