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