libt2n: (reinhard) more compile fixes.
[libt2n] / test / reconnect.cpp
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>
12 #include <time.h>
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
30 using namespace std;
31 using namespace libt2n;
32 using namespace CppUnit;
33
34 // this is an evil hack to get access to real_write, don't ever do this in an app!!!
35 class real_write_connection: public socket_server_connection
36 {
37     public:
38         void real_write(const std::string& data)
39             { socket_write(data); }
40 };
41
42 class 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
55     public:
56
57     void setUp()
58     { }
59
60     void tearDown()
61     { }
62
63     void send_raw_socket(string hello_string, socket_server* ss, int conn_id)
64     {
65         socket_server_connection *ssc=dynamic_cast<socket_server_connection*>(ss->get_connection(conn_id));
66
67         // this is an evil hack to get access to real_write, don't ever do this in an app!!!
68         real_write_connection *rwc=(real_write_connection*)ssc;
69         rwc->real_write(hello_string);
70     }
71
72     void simple_reconnect()
73     {
74         pid_t pid;
75
76         switch(pid=fork())
77         {
78             case -1:
79             {
80                 CPPUNIT_FAIL("fork error");
81                 break;
82             }
83             case 0:
84             // child
85             {
86                 socket_server ss("./socket");
87
88                 time_t t0 = time(NULL);
89
90                 // max 10 sec
91                 while (time(NULL) < t0 + 10 )
92                 {
93                     ss.fill_buffer(1000000);
94
95                     string data;
96                     unsigned int cid;
97
98                     if(ss.get_packet(data,cid))
99                     {
100                         server_connection* con=ss.get_connection(cid);
101
102                         if (data=="QUIT")
103                             break;
104
105                         if (data=="x")
106                             con->write(string().insert(0,100,'X'));
107                         else
108                             con->write(string().insert(0,100,'Y'));
109                     }
110                 }
111
112                 // don't call atexit and stuff
113                 _exit(0);
114             }
115
116             default:
117             // parent
118             {
119                 // don't kill us on broken pipe
120                 signal(SIGPIPE, SIG_IGN);
121
122                 // wait till server is up
123                 sleep(1);
124                 socket_client_connection sc("./socket");
125
126                 sc.write("abc");
127
128                 string data;
129
130                 while (!sc.get_packet(data))
131                     sc.fill_buffer(1000000);
132
133                 sc.reconnect();
134
135                 sc.write("x");
136
137                 while (!sc.get_packet(data))
138                     sc.fill_buffer(1000000);
139
140                 CPPUNIT_ASSERT_EQUAL(string().insert(0,100,'X'),data);
141             }
142         }
143     }
144
145     void reconnect_with_close()
146     {
147         pid_t pid;
148
149         switch(pid=fork())
150         {
151             case -1:
152             {
153                 CPPUNIT_FAIL("fork error");
154                 break;
155             }
156             case 0:
157             // child
158             {
159                 socket_server ss("./socket");
160
161                 time_t t0 = time(NULL);
162
163                 // max 10 sec
164                 while (time(NULL) < t0 + 10 )
165                 {
166                     ss.fill_buffer(1000000);
167
168                     string data;
169                     unsigned int cid;
170
171                     if(ss.get_packet(data,cid))
172                     {
173                         server_connection* con=ss.get_connection(cid);
174
175                         if (data=="QUIT")
176                             break;
177
178                         if (data=="x")
179                             con->write(string().insert(0,100,'X'));
180                         else
181                             con->write(string().insert(0,100,'Y'));
182                     }
183                 }
184
185                 // don't call atexit and stuff
186                 _exit(0);
187             }
188
189             default:
190             // parent
191             {
192                 // don't kill us on broken pipe
193                 signal(SIGPIPE, SIG_IGN);
194
195                 // wait till server is up
196                 sleep(1);
197                 socket_client_connection sc("./socket");
198
199                 sc.write("abc");
200
201                 string data;
202
203                 while (!sc.get_packet(data))
204                     sc.fill_buffer(1000000);
205
206                 sc.close();
207
208                 // empty buffer
209                 sc.get_packet(data);
210
211                 sc.reconnect();
212
213                 sc.write("x");
214
215                 while (!sc.get_packet(data))
216                     sc.fill_buffer(1000000);
217
218                 CPPUNIT_ASSERT_EQUAL(string().insert(0,100,'X'),data);
219             }
220         }
221     }
222
223     void reconnect_buffer_complete()
224     {
225         pid_t pid;
226
227         switch(pid=fork())
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     {
293         pid_t pid;
294
295         const int packets=3;
296
297         switch(pid=fork())
298         {
299             case -1:
300             {
301                 CPPUNIT_FAIL("fork error");
302                 break;
303             }
304             case 0:
305             // child
306             {
307                 socket_server ss("./socket");
308
309                 time_t t0 = time(NULL);
310
311                 // max 10 sec
312                 while (time(NULL) < t0 + 10 )
313                 {
314                     ss.fill_buffer(1000000);
315
316                     string data;
317                     unsigned int cid;
318
319                     if(ss.get_packet(data,cid))
320                     {
321                         server_connection* con=ss.get_connection(cid);
322
323                         if (data=="QUIT")
324                             break;
325
326                         if (data=="x")
327                         {
328                             for (int i=0; i<packets; i++)
329                                 con->write(string().insert(0,100,'X'));
330                         }
331                     }
332                 }
333
334                 // don't call atexit and stuff
335                 _exit(0);
336             }
337
338             default:
339             // parent
340             {
341                 // don't kill us on broken pipe
342                 signal(SIGPIPE, SIG_IGN);
343
344                 // wait till server is up
345                 sleep(1);
346                 socket_client_connection sc("./socket");
347
348                 sc.write("x");
349
350                 // retrieve packets for 3 seconds
351                 time_t t0 = time(NULL);
352
353                 // max 3 sec
354                 while (time(NULL) < t0 + 3 )
355                     sc.fill_buffer(1000000);
356
357                 // we now should have packets complete packets in the buffer
358
359                 sc.reconnect();
360
361                 // are these packets still there?
362
363                 for (int i=0; i < packets; i++)
364                 {
365                     string data;
366
367                     ostringstream os;
368                     os << "packet " << i << " not there";
369
370                     CPPUNIT_ASSERT_EQUAL_MESSAGE(os.str(),true,sc.get_packet(data));
371
372                     os.str("");
373                     os << "packet " << i << " incorrect";
374
375                     CPPUNIT_ASSERT_EQUAL_MESSAGE(os.str(),string().insert(0,100,'X'),data);
376                 }
377             }
378         }
379     }
380
381     void reconnect_buffer_no_incomplete1()
382     {
383         pid_t pid;
384
385         switch(pid=fork())
386         {
387             case -1:
388             {
389                 CPPUNIT_FAIL("fork error");
390                 break;
391             }
392             case 0:
393             // child
394             {
395                 socket_server ss("./socket");
396
397                 time_t t0 = time(NULL);
398
399                 // max 10 sec
400                 while (time(NULL) < t0 + 10 )
401                 {
402                     ss.fill_buffer(1000000);
403
404                     string data;
405                     unsigned int cid;
406
407                     if(ss.get_packet(data,cid))
408                     {
409                         server_connection* con=ss.get_connection(cid);
410
411                         if (data=="QUIT")
412                             break;
413
414                         if (data=="x")
415                         {
416                             con->write(string().insert(0,100,'X'));
417                             send_raw_socket("aaaab",&ss,cid);
418                         }
419                     }
420                 }
421
422                 // don't call atexit and stuff
423                 _exit(0);
424             }
425
426             default:
427             // parent
428             {
429                 // don't kill us on broken pipe
430                 signal(SIGPIPE, SIG_IGN);
431
432                 // wait till server is up
433                 sleep(1);
434                 socket_client_connection sc("./socket");
435
436                 sc.write("x");
437
438                 // retrieve packets for 3 seconds
439                 time_t t0 = time(NULL);
440
441                 // max 3 sec
442                 while (time(NULL) < t0 + 3 )
443                     sc.fill_buffer(1000000);
444
445                 // we now should have one complete packet and some stuff in the buffer
446
447                 string data;
448                 sc.get_packet(data);
449
450                 CPPUNIT_ASSERT_EQUAL_MESSAGE("no incomplete packet",true,(sc.peek_packet(data))>0);
451
452                 sc.reconnect();
453
454                 CPPUNIT_ASSERT_EQUAL_MESSAGE("incomplete packet not removed",0,(int)sc.peek_packet(data));
455             }
456         }
457     }
458
459     void reconnect_buffer_no_incomplete2()
460     {
461         pid_t pid;
462
463         switch(pid=fork())
464         {
465             case -1:
466             {
467                 CPPUNIT_FAIL("fork error");
468                 break;
469             }
470             case 0:
471             // child
472             {
473                 socket_server ss("./socket");
474
475                 time_t t0 = time(NULL);
476
477                 // max 10 sec
478                 while (time(NULL) < t0 + 10 )
479                 {
480                     ss.fill_buffer(1000000);
481
482                     string data;
483                     unsigned int cid;
484
485                     if(ss.get_packet(data,cid))
486                     {
487                         server_connection* con=ss.get_connection(cid);
488
489                         if (data=="QUIT")
490                             break;
491
492                         if (data=="x")
493                         {
494                             con->write(string().insert(0,100,'X'));
495
496                             string blob=string().insert(0,100,'Y');
497
498                             // one byte will be missing...
499                             int size=blob.size()+1;
500                             char sizetransfer[sizeof(int)+1];
501                             memcpy(sizetransfer,(void*)&size,sizeof(int));
502                             sizetransfer[sizeof(int)+1]=0;
503
504                             string packet=string(sizetransfer)+blob;
505
506                             send_raw_socket(packet,&ss,cid);
507                         }
508                     }
509                 }
510
511                 // don't call atexit and stuff
512                 _exit(0);
513             }
514
515             default:
516             // parent
517             {
518                 // don't kill us on broken pipe
519                 signal(SIGPIPE, SIG_IGN);
520
521                 // wait till server is up
522                 sleep(1);
523                 socket_client_connection sc("./socket");
524
525                 sc.write("x");
526
527                 // retrieve packets for 3 seconds
528                 time_t t0 = time(NULL);
529
530                 // max 3 sec
531                 while (time(NULL) < t0 + 3 )
532                     sc.fill_buffer(1000000);
533
534                 // we now should have one complete packet and some stuff in the buffer
535
536                 sc.reconnect();
537
538                 string data;
539
540                 CPPUNIT_ASSERT_EQUAL_MESSAGE("packet not there",true,sc.get_packet(data));
541                 CPPUNIT_ASSERT_EQUAL_MESSAGE("data incorrect",string().insert(0,100,'X'),data);
542
543                 CPPUNIT_ASSERT_EQUAL_MESSAGE("incomplete packet not removed",0,(int)sc.peek_packet(data));
544             }
545         }
546     }
547
548 };
549
550 CPPUNIT_TEST_SUITE_REGISTRATION(test_reconnect);