libt2n: (tomj) disable recently added unit test: it won't work as is
[libt2n] / test / timeout.cpp
CommitLineData
45a2ebc9
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>
12
13#include <iostream>
14#include <string>
15#include <sstream>
16#include <stdexcept>
17
18#include <boost/bind.hpp>
19
20#include <cppunit/extensions/TestFactoryRegistry.h>
21#include <cppunit/ui/text/TestRunner.h>
22#include <cppunit/extensions/HelperMacros.h>
23
24#include <boost/archive/binary_oarchive.hpp>
25#include <boost/archive/binary_iarchive.hpp>
26#include <boost/archive/xml_oarchive.hpp>
27#include <boost/archive/xml_iarchive.hpp>
28#include <boost/serialization/serialization.hpp>
29
30#include <container.hxx>
31#include <socket_client.hxx>
32#include <socket_server.hxx>
33#include <command_client.hxx>
34#include <command_server.hxx>
35
36#ifdef HAVE_CONFIG_H
37#include <config.h>
38#endif
39
40using namespace std;
41using namespace libt2n;
42using namespace CppUnit;
43
44string testfunc2(const string& str)
45{
46 if (str=="throw")
47 throw libt2n::t2n_runtime_error("throw me around");
48 string ret(str);
49 ret+=", testfunc() was here";
50 return ret;
51}
52
53class testfunc2_res : public libt2n::result
54{
55 private:
56 string res;
57
58 friend class boost::serialization::access;
59 template<class Archive>
60 void serialize(Archive & ar, const unsigned int version)
61 {
62 ar & BOOST_SERIALIZATION_BASE_OBJECT_NVP(libt2n::result);
63 ar & BOOST_SERIALIZATION_NVP(res);
64 }
65
66 public:
67 testfunc2_res()
68 { }
69
70 testfunc2_res(const string& str)
71 {
72 res=str;
73 }
74
75 string get_data()
76 {
77 return res;
78 }
79};
80
81
82class testfunc2_cmd : public libt2n::command
83{
84 private:
85 string param;
86
87 friend class boost::serialization::access;
88 template<class Archive>
89 void serialize(Archive & ar, const unsigned int version)
90 {
91 ar & BOOST_SERIALIZATION_BASE_OBJECT_NVP(libt2n::command);
92 ar & BOOST_SERIALIZATION_NVP(param);
93 }
94
95 public:
96 testfunc2_cmd()
97 { }
98
99 testfunc2_cmd(const string& str)
100 {
101 param=str;
102 }
103
104 libt2n::result* operator()()
105 {
106 return new testfunc2_res(testfunc2(param));
107 }
108};
109
110#include <boost/serialization/export.hpp>
111
112BOOST_CLASS_EXPORT(testfunc2_cmd)
113BOOST_CLASS_EXPORT(testfunc2_res)
114
115// this is an evil hack to get access to real_write, don't ever do this in an app!!!
116class real_write_connection: public socket_server_connection
117{
118 public:
119 void real_write(const std::string& data)
120 { socket_write(data); }
121};
122
c7857475
GE
123// this is an evil hack to get access to real_write, don't ever do this in an app!!!
124class real_write_client_connection: public socket_client_connection
125{
126 public:
127 void real_write(const std::string& data)
128 { socket_write(data); }
129};
130
45a2ebc9
GE
131class test_timeout : public TestFixture
132{
133 CPPUNIT_TEST_SUITE(test_timeout);
134
c7857475 135 CPPUNIT_TEST(ConnectTimeout);
45a2ebc9
GE
136 CPPUNIT_TEST(HelloTimeoutNothing);
137 CPPUNIT_TEST(HelloTimeoutSlowData);
138 CPPUNIT_TEST(CommandTimeout);
139 CPPUNIT_TEST(CommandSlowResponse);
c7857475 140 CPPUNIT_TEST(DisconnectOnWrite);
039e52da 141 CPPUNIT_TEST(WriteTwice);
c7857475
GE
142 CPPUNIT_TEST(DisconnectOnRead);
143 CPPUNIT_TEST(BreakAccept);
45a2ebc9
GE
144
145 CPPUNIT_TEST_SUITE_END();
146
b5922184
GE
147 pid_t child_pid;
148
45a2ebc9
GE
149 public:
150
151 typedef uint32_t packet_size_indicator;
152
153 void setUp()
154 { }
155
156 void tearDown()
b5922184
GE
157 {
158 // make sure the server-child is dead before the next test runs
159 kill(child_pid,SIGKILL);
160 sleep(1);
161 }
45a2ebc9
GE
162
163 void send_hello(string hello_string, socket_server* ss, unsigned int conn_id)
164 {
165 server_connection *sc=ss->get_connection(conn_id);
166 sc->write(hello_string);
167 }
168
169 void send_slow_raw_socket(string data, socket_server* ss, unsigned int conn_id)
170 {
171 socket_server_connection *ssc=dynamic_cast<socket_server_connection*>(ss->get_connection(conn_id));
172
173 // this is an evil hack to get access to real_write, don't ever do this in an app!!!
174 real_write_connection *rwc=(real_write_connection*)ssc;
175
176 // we write one char each 0.2 sec
177 for (int pos=0; pos < data.size(); pos++)
178 {
179 string onebyte;
180 onebyte+=data[pos];
181 rwc->real_write(onebyte);
182 usleep(200000);
183 }
184 }
185
c7857475
GE
186 void ConnectTimeout()
187 {
b5922184 188 switch(child_pid=fork())
c7857475
GE
189 {
190 case -1:
191 {
192 CPPUNIT_FAIL("fork error");
193 break;
194 }
195 case 0:
196 // child
197 {
198 socket_server ss("./socket");
199
200 // don't call atexit and stuff
201 _exit(0);
202 }
203
204 default:
205 // parent
206 {
207 string data;
208
209 // wait till server is up
210 sleep(1);
211
212 string errormsg;
213
fb3345ad 214 socket_client_connection sc("./socket");
c7857475 215
b5922184
GE
216 CPPUNIT_ASSERT_EQUAL_MESSAGE("connection not closed",true,sc.connection::is_closed());
217
218 CPPUNIT_ASSERT_EQUAL_MESSAGE("wrong errormessage",string("no more retries left after connect error"),sc.get_last_error_msg());
c7857475
GE
219 }
220 }
221 }
222
45a2ebc9
GE
223 void HelloTimeoutNothing()
224 {
b5922184 225 switch(child_pid=fork())
45a2ebc9
GE
226 {
227 case -1:
228 {
229 CPPUNIT_FAIL("fork error");
230 break;
231 }
232 case 0:
233 // child
234 {
235 socket_server ss("./socket");
236
237 // max 10 sec
238 for (int i=0; i < 10; i++)
239 ss.fill_buffer(1000000);
240 // don't call atexit and stuff
241 _exit(0);
242 }
243
244 default:
245 // parent
246 {
247 string data;
248
249 // wait till server is up
250 sleep(1);
251 socket_client_connection sc("./socket");
b5922184 252 command_client cc(&sc,1000000,1000000);
45a2ebc9 253
b5922184 254 t2n_exception* ep=cc.get_constuctor_exception();
45a2ebc9 255
b5922184
GE
256 string errormsg;
257 if (ep)
258 errormsg=ep->what();
45a2ebc9
GE
259
260 CPPUNIT_ASSERT_EQUAL(string("timeout exceeded"),errormsg);
261 }
262 }
263 }
264
265 void HelloTimeoutSlowData()
266 {
b5922184 267 switch(child_pid=fork())
45a2ebc9
GE
268 {
269 case -1:
270 {
271 CPPUNIT_FAIL("fork error");
272 break;
273 }
274 case 0:
275 // child
276 {
277 socket_server ss("./socket");
278
279 // create a valid packet
280 ostringstream hello;
281 hello << "T2Nv" << PROTOCOL_VERSION << ';';
282 int byteordercheck=1;
283 hello.write((char*)&byteordercheck,sizeof(byteordercheck));
284 hello << ';';
285
286 packet_size_indicator psize=htonl(hello.str().size());
287 std::string send_data(hello.str());
288 send_data.insert(0,(char*)&psize,sizeof(packet_size_indicator));
289
290 ss.add_callback(new_connection,bind(&test_timeout::send_slow_raw_socket, boost::ref(*this), send_data,&ss, _1));
291
292 // max 10 sec
293 for (int i=0; i < 10; i++)
294 ss.fill_buffer(1000000);
295 // don't call atexit and stuff
296 _exit(0);
297 }
298
299 default:
300 // parent
301 {
302 string data;
303
304 // wait till server is up
305 sleep(1);
306 socket_client_connection sc("./socket");
b5922184 307 command_client cc(&sc,1000000,1000000);
45a2ebc9 308
b5922184 309 t2n_exception* ep=cc.get_constuctor_exception();
45a2ebc9 310
b5922184
GE
311 string errormsg;
312 if (ep)
313 errormsg=ep->what();
45a2ebc9
GE
314
315 CPPUNIT_ASSERT_EQUAL(string("timeout exceeded"),errormsg);
316 }
317 }
318 }
319
320 void CommandTimeout()
321 {
b5922184 322 switch(child_pid=fork())
45a2ebc9
GE
323 {
324 case -1:
325 {
326 CPPUNIT_FAIL("fork error");
327 break;
328 }
329 case 0:
330 // child
331 {
332 socket_server ss("./socket");
333
334 ostringstream hello;
335 hello << "T2Nv" << PROTOCOL_VERSION << ';';
336 int byteordercheck=1;
337 hello.write((char*)&byteordercheck,sizeof(byteordercheck));
338 hello << ';';
339
340 ss.add_callback(new_connection,bind(&test_timeout::send_hello, boost::ref(*this), hello.str(),&ss, _1));
341
342 // max 10 sec
343 for (int i=0; i < 10; i++)
344 ss.fill_buffer(1000000);
345 // don't call atexit and stuff
346 _exit(0);
347 }
348
349 default:
350 // parent
351 {
352 string data;
353
354 // wait till server is up
355 sleep(1);
356 socket_client_connection sc("./socket");
357
fb3345ad 358 command_client cc(&sc,1000000,1000000);
45a2ebc9
GE
359 result_container rc;
360
361 string errormsg;
362
363 try
364 {
365 cc.send_command(new testfunc2_cmd("hello"),rc);
366 }
367 catch(t2n_transfer_error &e)
368 { errormsg=e.what(); }
369 catch(...)
370 { throw; }
371
372 CPPUNIT_ASSERT_EQUAL(string("timeout exceeded"),errormsg);
373 }
374 }
375 }
376
377 void CommandSlowResponse()
378 {
b5922184 379 switch(child_pid=fork())
45a2ebc9
GE
380 {
381 case -1:
382 {
383 CPPUNIT_FAIL("fork error");
384 break;
385 }
386 case 0:
387 // child
388 {
389 socket_server ss("./socket");
390
391 ostringstream hello;
392 hello << "T2Nv" << PROTOCOL_VERSION << ';';
393 int byteordercheck=1;
394 hello.write((char*)&byteordercheck,sizeof(byteordercheck));
395 hello << ';';
396
397 ss.add_callback(new_connection,bind(&test_timeout::send_hello, boost::ref(*this), hello.str(),&ss, _1));
398
399 // max 10 sec
400 for (int i=0; i < 10; i++)
401 {
402 ss.fill_buffer(1000000);
403
404 string data;
405 unsigned int cid;
406
407 if(ss.get_packet(data,cid))
408 {
409 // create a valid packet & send
410 string response="abcdefghijklmnopqrstuvwxyz";
411 packet_size_indicator psize=htonl(response.size());
412 std::string send_data(response);
413 send_data.insert(0,(char*)&psize,sizeof(packet_size_indicator));
414 send_slow_raw_socket(send_data,&ss,cid);
415 }
416 }
417 // don't call atexit and stuff
418 _exit(0);
419 }
420
421 default:
422 // parent
423 {
424 string data;
425
426 // wait till server is up
427 sleep(1);
428 socket_client_connection sc("./socket");
429
fb3345ad 430 command_client cc(&sc,1000000,1000000);
45a2ebc9
GE
431 result_container rc;
432
433 string errormsg;
434
435 try
436 {
437 cc.send_command(new testfunc2_cmd("hello"),rc);
438 }
439 catch(t2n_transfer_error &e)
440 { errormsg=e.what(); }
441 catch(...)
442 { throw; }
443
444 CPPUNIT_ASSERT_EQUAL(string("timeout exceeded"),errormsg);
445 }
446 }
447 }
448
c7857475
GE
449 void DisconnectOnWrite()
450 {
b5922184 451 switch(child_pid=fork())
c7857475
GE
452 {
453 case -1:
454 {
455 CPPUNIT_FAIL("fork error");
456 break;
457 }
458 case 0:
459 // child
460 {
461 socket_server ss("./socket");
462
463 // bail out as soon as we get something
464 ss.fill_buffer(-1);
465 // don't call atexit and stuff
466 _exit(0);
467 }
468
469 default:
470 // parent
471 {
472 string data;
473
474 // don't kill us on broken pipe
475 signal(SIGPIPE, SIG_IGN);
476
477 // wait till server is up
478 sleep(1);
479 socket_client_connection sc("./socket");
480
481 string errormsg;
482
e72e07f3 483 string huge(5000000,'x');
c7857475
GE
484
485 try
486 {
487 sc.write(huge);
488 }
489 catch(t2n_transfer_error &e)
490 { errormsg=e.what(); }
491 catch(...)
492 { throw; }
493
494 CPPUNIT_ASSERT_EQUAL(string("write() returned Broken pipe"),errormsg);
495 }
496 }
497 }
498
039e52da
GE
499 void WriteTwice()
500 {
501 switch(child_pid=fork())
502 {
503 case -1:
504 {
505 CPPUNIT_FAIL("fork error");
506 break;
507 }
508 case 0:
509 // child
510 {
511 socket_server ss("./socket");
512
513 // bail out as soon as we get something
514 ss.fill_buffer(-1);
515 // don't call atexit and stuff
516 _exit(0);
517 }
518
519 default:
520 // parent
521 {
522 string data;
523
524 // don't kill us on broken pipe
525 signal(SIGPIPE, SIG_IGN);
526
527 // wait till server is up
528 sleep(1);
529 socket_client_connection sc("./socket");
530
531 string errormsg;
532
533 sc.write("somedata");
534
535 sleep(1);
536
537 // server should disconnect now
538 try
539 {
540 sc.write("other data");
541 }
542 catch(t2n_transfer_error &e)
543 { errormsg=e.what(); }
544 catch(...)
545 { throw; }
546
547 CPPUNIT_ASSERT_EQUAL(string("write() returned Broken pipe"),errormsg);
548 }
549 }
550 }
551
c7857475
GE
552 void DisconnectOnRead()
553 {
b5922184 554 pid_t pid2;
c7857475 555
b5922184 556 switch(child_pid=fork())
c7857475
GE
557 {
558 case -1:
559 {
560 CPPUNIT_FAIL("fork error");
561 break;
562 }
563 case 0:
564 // child
565 {
566 // wait till server is up
567 sleep(1);
568
569 socket_client_connection sc("./socket");
570
571 // this is an evil hack to get access to real_write, don't ever do this in an app!!!
572 real_write_client_connection *rwc=(real_write_client_connection*)&sc;
573 rwc->real_write(string(10000,'x'));
574
575 // don't call atexit and stuff
576 _exit(0);
577 }
578
579 default:
580 // parent
581 {
582 // don't kill us on broken pipe
583 signal(SIGPIPE, SIG_IGN);
584
585 socket_server ss("./socket");
586
587 time_t t0 = time(NULL);
588
589 // max 5 sec
590 while (time(NULL) < t0 + 5 )
591 {
592 ss.fill_buffer(1000000);
593
594 string data;
595 ss.get_packet(data);
596 }
597
598 // are we still alive and able to process data?
599
fb3345ad 600 switch(pid2=fork())
c7857475
GE
601 {
602 case -1:
603 {
604 CPPUNIT_FAIL("fork error");
605 break;
606 }
607 case 0:
608 // child
609 {
610 socket_client_connection *sc=new socket_client_connection("./socket");
611 sc->write(string(10000,'x'));
612 delete sc;
613 // socket is closed regularly
614
615 // don't run regular cleanup, otherwise cppunit stuff gets called
616 _exit(0);
617 }
618
619 default:
620 // parent
621 {
622 string received;
623
624 t0 = time(NULL);
625
626 // max 10 sec
627 while (time(NULL) < t0 + 10 )
628 {
629 ss.fill_buffer(1000000);
630
631 if (ss.get_packet(received))
632 break;
633 }
634
635 CPPUNIT_ASSERT_EQUAL(string(10000,'x'),received);
636 }
637 }
638 }
639 }
fb3345ad 640 kill(pid2,SIGKILL);
c7857475
GE
641 }
642
643 void BreakAccept()
644 {
b5922184 645 pid_t pid2;
c7857475 646
b5922184 647 switch(child_pid=fork())
c7857475
GE
648 {
649 case -1:
650 {
651 CPPUNIT_FAIL("fork error");
652 break;
653 }
654 case 0:
655 // child
656 {
657 // wait till server is really up and waiting
658 sleep(2);
659
660 // connect with very tight timeout and only 1 retry
661 socket_client_connection sc("./socket",50,1);
662
663 // don't call atexit and stuff
664 _exit(0);
665 }
666
667 default:
668 // parent
669 {
670 // don't kill us on broken pipe
671 signal(SIGPIPE, SIG_IGN);
672
673 socket_server ss("./socket");
674
675 // server is "working" while client wants to connect
676 sleep(5);
677
678 time_t t0 = time(NULL);
679
680 // max 5 sec
681 while (time(NULL) < t0 + 5 )
682 {
683 ss.fill_buffer(1000000);
684
685 string data;
686 ss.get_packet(data);
687 }
688
689 // are we still alive and able to process data?
690
fb3345ad 691 switch(pid2=fork())
c7857475
GE
692 {
693 case -1:
694 {
695 CPPUNIT_FAIL("fork error");
696 break;
697 }
698 case 0:
699 // child
700 {
701 socket_client_connection *sc=new socket_client_connection("./socket");
702 sc->write(string(10000,'x'));
703 delete sc;
704 // socket is closed regularly
705
706 // don't run regular cleanup, otherwise cppunit stuff gets called
707 _exit(0);
708 }
709
710 default:
711 // parent
712 {
713 string received;
714
715 t0 = time(NULL);
716
717 // max 10 sec
718 while (time(NULL) < t0 + 10 )
719 {
720 ss.fill_buffer(1000000);
721
722 if (ss.get_packet(received))
723 break;
724 }
725
726 CPPUNIT_ASSERT_EQUAL(string(10000,'x'),received);
727 }
728 }
729 }
730 }
fb3345ad 731 kill(pid2,SIGKILL);
c7857475 732 }
45a2ebc9
GE
733};
734
735CPPUNIT_TEST_SUITE_REGISTRATION(test_timeout);