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