libt2n: (gerd) adapt codegen to new command_client interface, fix codegen-examples
[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     pid_t child_pid;
56
57     public:
58
59     void setUp()
60     { }
61
62     void tearDown()
63     {
64         // make sure the server-child is dead before the next test runs
65         kill(child_pid,SIGKILL);
66         sleep(1);
67     }
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     {
80         switch(child_pid=fork())
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     {
151         switch(child_pid=fork())
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     {
227         switch(child_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         const int packets=3;
294
295         switch(child_pid=fork())
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     {
381         switch(child_pid=fork())
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     {
457         switch(child_pid=fork())
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
544 CPPUNIT_TEST_SUITE_REGISTRATION(test_reconnect);