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