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