1 /***************************************************************************
2 * Copyright (C) 2004 by Intra2net AG *
5 ***************************************************************************/
18 #include <boost/bind.hpp>
20 #include <cppunit/extensions/TestFactoryRegistry.h>
21 #include <cppunit/ui/text/TestRunner.h>
22 #include <cppunit/extensions/HelperMacros.h>
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>
30 #include <container.hxx>
31 #include <socket_client.hxx>
32 #include <socket_server.hxx>
33 #include <command_client.hxx>
34 #include <command_server.hxx>
41 using namespace libt2n;
42 using namespace CppUnit;
44 string testfunc2(const string& str)
47 throw libt2n::t2n_runtime_error("throw me around");
49 ret+=", testfunc() was here";
53 class testfunc2_res : public libt2n::result
58 friend class boost::serialization::access;
59 template<class Archive>
60 void serialize(Archive & ar, const unsigned int version)
62 ar & BOOST_SERIALIZATION_BASE_OBJECT_NVP(libt2n::result);
63 ar & BOOST_SERIALIZATION_NVP(res);
70 testfunc2_res(const string& str)
82 class testfunc2_cmd : public libt2n::command
87 friend class boost::serialization::access;
88 template<class Archive>
89 void serialize(Archive & ar, const unsigned int version)
91 ar & BOOST_SERIALIZATION_BASE_OBJECT_NVP(libt2n::command);
92 ar & BOOST_SERIALIZATION_NVP(param);
99 testfunc2_cmd(const string& str)
104 libt2n::result* operator()()
106 return new testfunc2_res(testfunc2(param));
110 #include <boost/serialization/export.hpp>
112 BOOST_CLASS_EXPORT(testfunc2_cmd)
113 BOOST_CLASS_EXPORT(testfunc2_res)
115 // this is an evil hack to get access to real_write, don't ever do this in an app!!!
116 class real_write_connection: public socket_server_connection
119 void real_write(const std::string& data)
120 { socket_write(data); }
123 // this is an evil hack to get access to real_write, don't ever do this in an app!!!
124 class real_write_client_connection: public socket_client_connection
127 void real_write(const std::string& data)
128 { socket_write(data); }
131 class test_timeout : public TestFixture
133 CPPUNIT_TEST_SUITE(test_timeout);
135 CPPUNIT_TEST(ConnectTimeout);
136 CPPUNIT_TEST(HelloTimeoutNothing);
137 CPPUNIT_TEST(HelloTimeoutSlowData);
138 CPPUNIT_TEST(CommandTimeout);
139 CPPUNIT_TEST(CommandSlowResponse);
140 CPPUNIT_TEST(DisconnectOnWrite);
141 CPPUNIT_TEST(WriteTwice);
142 CPPUNIT_TEST(DisconnectOnRead);
143 CPPUNIT_TEST(BreakAccept);
145 CPPUNIT_TEST_SUITE_END();
151 typedef uint32_t packet_size_indicator;
158 // make sure the server-child is dead before the next test runs
159 kill(child_pid,SIGKILL);
163 void send_hello(string hello_string, socket_server* ss, unsigned int conn_id)
165 server_connection *sc=ss->get_connection(conn_id);
166 sc->write(hello_string);
169 void send_slow_raw_socket(string data, socket_server* ss, unsigned int conn_id)
171 socket_server_connection *ssc=dynamic_cast<socket_server_connection*>(ss->get_connection(conn_id));
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;
176 // we write one char each 0.2 sec
177 for (int pos=0; pos < data.size(); pos++)
181 rwc->real_write(onebyte);
186 void ConnectTimeout()
188 switch(child_pid=fork())
192 CPPUNIT_FAIL("fork error");
200 socket_server ss("./socket");
203 std::cerr << "exception in child. ignoring\n";
206 // don't call atexit and stuff
215 // wait till server is up
220 socket_client_connection sc("./socket");
222 CPPUNIT_ASSERT_EQUAL_MESSAGE("connection not closed",true,sc.connection::is_closed());
224 CPPUNIT_ASSERT_EQUAL_MESSAGE("wrong errormessage",string("no more retries left after connect error"),sc.get_last_error_msg());
229 void HelloTimeoutNothing()
231 switch(child_pid=fork())
235 CPPUNIT_FAIL("fork error");
243 socket_server ss("./socket");
246 for (int i=0; i < 10; i++)
247 ss.fill_buffer(1000000);
250 std::cerr << "exception in child. ignoring\n";
253 // don't call atexit and stuff
262 // wait till server is up
264 socket_client_connection sc("./socket");
265 command_client cc(&sc,1000000,1000000);
267 t2n_exception* ep=cc.get_constuctor_exception();
273 CPPUNIT_ASSERT_EQUAL(string("timeout exceeded"),errormsg);
278 void HelloTimeoutSlowData()
280 switch(child_pid=fork())
284 CPPUNIT_FAIL("fork error");
292 socket_server ss("./socket");
294 // create a valid packet
296 hello << "T2Nv" << PROTOCOL_VERSION << ';';
297 int byteordercheck=1;
298 hello.write((char*)&byteordercheck,sizeof(byteordercheck));
301 packet_size_indicator psize=htonl(hello.str().size());
302 std::string send_data(hello.str());
303 send_data.insert(0,(char*)&psize,sizeof(packet_size_indicator));
305 ss.add_callback(new_connection,bind(&test_timeout::send_slow_raw_socket, boost::ref(*this), send_data,&ss, _1));
308 for (int i=0; i < 10; i++)
309 ss.fill_buffer(1000000);
312 std::cerr << "exception in child. ignoring\n";
315 // don't call atexit and stuff
324 // wait till server is up
326 socket_client_connection sc("./socket");
327 command_client cc(&sc,1000000,1000000);
329 t2n_exception* ep=cc.get_constuctor_exception();
335 CPPUNIT_ASSERT_EQUAL(string("timeout exceeded"),errormsg);
340 void CommandTimeout()
342 switch(child_pid=fork())
346 CPPUNIT_FAIL("fork error");
354 socket_server ss("./socket");
357 hello << "T2Nv" << PROTOCOL_VERSION << ';';
358 int byteordercheck=1;
359 hello.write((char*)&byteordercheck,sizeof(byteordercheck));
362 ss.add_callback(new_connection,bind(&test_timeout::send_hello, boost::ref(*this), hello.str(),&ss, _1));
365 for (int i=0; i < 10; i++)
366 ss.fill_buffer(1000000);
369 std::cerr << "exception in child. ignoring\n";
372 // don't call atexit and stuff
381 // wait till server is up
383 socket_client_connection sc("./socket");
385 command_client cc(&sc,1000000,1000000);
392 cc.send_command(new testfunc2_cmd("hello"),rc);
394 catch(t2n_transfer_error &e)
395 { errormsg=e.what(); }
399 CPPUNIT_ASSERT_EQUAL(string("timeout exceeded"),errormsg);
404 void CommandSlowResponse()
406 switch(child_pid=fork())
410 CPPUNIT_FAIL("fork error");
418 socket_server ss("./socket");
421 hello << "T2Nv" << PROTOCOL_VERSION << ';';
422 int byteordercheck=1;
423 hello.write((char*)&byteordercheck,sizeof(byteordercheck));
426 ss.add_callback(new_connection,bind(&test_timeout::send_hello, boost::ref(*this), hello.str(),&ss, _1));
429 for (int i=0; i < 10; i++)
431 ss.fill_buffer(1000000);
436 if(ss.get_packet(data,cid))
438 // create a valid packet & send
439 string response="abcdefghijklmnopqrstuvwxyz";
440 packet_size_indicator psize=htonl(response.size());
441 std::string send_data(response);
442 send_data.insert(0,(char*)&psize,sizeof(packet_size_indicator));
443 send_slow_raw_socket(send_data,&ss,cid);
448 std::cerr << "exception in child. ignoring\n";
451 // don't call atexit and stuff
460 // wait till server is up
462 socket_client_connection sc("./socket");
464 command_client cc(&sc,1000000,1000000);
471 cc.send_command(new testfunc2_cmd("hello"),rc);
473 catch(t2n_transfer_error &e)
474 { errormsg=e.what(); }
478 CPPUNIT_ASSERT_EQUAL(string("timeout exceeded"),errormsg);
483 void DisconnectOnWrite()
485 switch(child_pid=fork())
489 CPPUNIT_FAIL("fork error");
497 socket_server ss("./socket");
499 // bail out as soon as we get something
503 std::cerr << "exception in child. ignoring\n";
506 // don't call atexit and stuff
515 // don't kill us on broken pipe
516 signal(SIGPIPE, SIG_IGN);
518 // wait till server is up
520 socket_client_connection sc("./socket");
524 string huge(5000000,'x');
530 catch(t2n_transfer_error &e)
531 { errormsg=e.what(); }
535 CPPUNIT_ASSERT_EQUAL(string("write() returned Broken pipe"),errormsg);
542 switch(child_pid=fork())
546 CPPUNIT_FAIL("fork error");
554 socket_server ss("./socket");
556 // bail out as soon as we get something
561 std::cerr << "exception in child. ignoring\n";
564 // don't call atexit and stuff
573 // don't kill us on broken pipe
574 signal(SIGPIPE, SIG_IGN);
576 // wait till server is up
578 socket_client_connection sc("./socket");
582 sc.write("somedata");
586 // server should disconnect now
589 sc.write("other data");
591 catch(t2n_transfer_error &e)
592 { errormsg=e.what(); }
596 CPPUNIT_ASSERT_EQUAL(string("write() returned Broken pipe"),errormsg);
601 void DisconnectOnRead()
605 switch(child_pid=fork())
609 CPPUNIT_FAIL("fork error");
617 // wait till server is up
620 socket_client_connection sc("./socket");
622 // this is an evil hack to get access to real_write, don't ever do this in an app!!!
623 real_write_client_connection *rwc=(real_write_client_connection*)≻
624 rwc->real_write(string(10000,'x'));
627 std::cerr << "exception in child. ignoring\n";
630 // don't call atexit and stuff
637 // don't kill us on broken pipe
638 signal(SIGPIPE, SIG_IGN);
640 socket_server ss("./socket");
642 time_t t0 = time(NULL);
645 while (time(NULL) < t0 + 5 )
647 ss.fill_buffer(1000000);
653 // are we still alive and able to process data?
659 CPPUNIT_FAIL("fork error");
667 socket_client_connection *sc=new socket_client_connection("./socket");
668 sc->write(string(10000,'x'));
669 // socket is closed regularly
673 std::cerr << "exception in child. ignoring\n";
676 // don't run regular cleanup, otherwise cppunit stuff gets called
688 while (time(NULL) < t0 + 10 )
690 ss.fill_buffer(1000000);
692 if (ss.get_packet(received))
696 CPPUNIT_ASSERT_EQUAL(string(10000,'x'),received);
708 switch(child_pid=fork())
712 CPPUNIT_FAIL("fork error");
720 // wait till server is really up and waiting
723 // connect with very tight timeout and only 1 retry
724 socket_client_connection sc("./socket",50,1);
727 std::cerr << "exception in child. ignoring\n";
730 // don't call atexit and stuff
737 // don't kill us on broken pipe
738 signal(SIGPIPE, SIG_IGN);
740 socket_server ss("./socket");
742 // server is "working" while client wants to connect
745 time_t t0 = time(NULL);
748 while (time(NULL) < t0 + 5 )
750 ss.fill_buffer(1000000);
756 // are we still alive and able to process data?
762 CPPUNIT_FAIL("fork error");
770 socket_client_connection *sc=new socket_client_connection("./socket");
771 sc->write(string(10000,'x'));
773 // socket is closed regularly
776 std::cerr << "exception in child. ignoring\n";
779 // don't run regular cleanup, otherwise cppunit stuff gets called
791 while (time(NULL) < t0 + 10 )
793 ss.fill_buffer(1000000);
795 if (ss.get_packet(received))
799 CPPUNIT_ASSERT_EQUAL(string(10000,'x'),received);
808 CPPUNIT_TEST_SUITE_REGISTRATION(test_timeout);