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