2 Copyright (C) 2004 by Intra2net AG
4 The software in this package is distributed under the GNU General
5 Public License version 2 (with a special exception described below).
7 A copy of GNU General Public License (GPL) is included in this distribution,
8 in the file COPYING.GPL.
10 As a special exception, if other files instantiate templates or use macros
11 or inline functions from this file, or you compile this file and link it
12 with other works to produce a work based on this file, this file
13 does not by itself cause the resulting work to be covered
14 by the GNU General Public License.
16 However the source code for this file must still be made available
17 in accordance with section (3) of the GNU General Public License.
19 This exception does not invalidate any other reasons why a work based
20 on this file might be covered by the GNU General Public License.
22 #include <sys/types.h>
33 #include <boost/bind.hpp>
35 #include <cppunit/extensions/TestFactoryRegistry.h>
36 #include <cppunit/ui/text/TestRunner.h>
37 #include <cppunit/extensions/HelperMacros.h>
39 #include <boost/archive/binary_oarchive.hpp>
40 #include <boost/archive/binary_iarchive.hpp>
41 #include <boost/archive/xml_oarchive.hpp>
42 #include <boost/archive/xml_iarchive.hpp>
43 #include <boost/serialization/serialization.hpp>
45 #include <container.hxx>
46 #include <socket_client.hxx>
47 #include <socket_server.hxx>
48 #include <command_client.hxx>
49 #include <command_server.hxx>
56 using namespace libt2n;
57 using namespace CppUnit;
59 string testfunc2(const string& str)
62 throw libt2n::t2n_runtime_error("throw me around");
64 ret+=", testfunc() was here";
68 class testfunc2_res : public libt2n::result
73 friend class boost::serialization::access;
74 template<class Archive>
75 void serialize(Archive & ar, const unsigned int version)
77 ar & BOOST_SERIALIZATION_BASE_OBJECT_NVP(libt2n::result);
78 ar & BOOST_SERIALIZATION_NVP(res);
85 testfunc2_res(const string& str)
97 class testfunc2_cmd : public libt2n::command
102 friend class boost::serialization::access;
103 template<class Archive>
104 void serialize(Archive & ar, const unsigned int version)
106 ar & BOOST_SERIALIZATION_BASE_OBJECT_NVP(libt2n::command);
107 ar & BOOST_SERIALIZATION_NVP(param);
114 testfunc2_cmd(const string& str)
119 libt2n::result* operator()()
121 return new testfunc2_res(testfunc2(param));
125 #include <boost/serialization/export.hpp>
127 BOOST_CLASS_EXPORT(testfunc2_cmd)
128 BOOST_CLASS_EXPORT(testfunc2_res)
130 // this is an evil hack to get access to real_write, don't ever do this in an app!!!
131 class real_write_connection: public socket_server_connection
134 void real_write(const std::string& data)
135 { socket_write(data); }
138 // this is an evil hack to get access to real_write, don't ever do this in an app!!!
139 class real_write_client_connection: public socket_client_connection
142 void real_write(const std::string& data)
143 { socket_write(data); }
146 class test_timeout : public TestFixture
148 CPPUNIT_TEST_SUITE(test_timeout);
150 CPPUNIT_TEST(ConnectTimeout);
151 CPPUNIT_TEST(HelloTimeoutNothing);
152 CPPUNIT_TEST(HelloTimeoutSlowData);
153 CPPUNIT_TEST(CommandTimeout);
154 CPPUNIT_TEST(CommandSlowResponse);
155 CPPUNIT_TEST(DisconnectOnWrite);
156 CPPUNIT_TEST(WriteTwice);
157 CPPUNIT_TEST(DisconnectOnRead);
158 CPPUNIT_TEST(BreakAccept);
160 CPPUNIT_TEST_SUITE_END();
166 typedef uint32_t packet_size_indicator;
173 // make sure the server-child is dead before the next test runs
174 kill(child_pid,SIGKILL);
178 void send_hello(string hello_string, socket_server* ss, unsigned int conn_id)
180 server_connection *sc=ss->get_connection(conn_id);
181 sc->write(hello_string);
184 void send_slow_raw_socket(string data, socket_server* ss, unsigned int conn_id)
186 socket_server_connection *ssc=dynamic_cast<socket_server_connection*>(ss->get_connection(conn_id));
188 // this is an evil hack to get access to real_write, don't ever do this in an app!!!
189 real_write_connection *rwc=(real_write_connection*)ssc;
191 // we write one char each 0.2 sec
192 for (int pos=0; pos < data.size(); pos++)
196 rwc->real_write(onebyte);
201 void ConnectTimeout()
203 switch(child_pid=fork())
207 CPPUNIT_FAIL("fork error");
215 socket_server ss("./socket");
218 std::cerr << "exception in child. ignoring\n";
221 // don't call atexit and stuff
230 // wait till server is up
235 socket_client_connection sc("./socket");
237 CPPUNIT_ASSERT_EQUAL_MESSAGE("connection not closed",true,sc.connection::is_closed());
239 CPPUNIT_ASSERT_EQUAL_MESSAGE("wrong errormessage",string("no more retries left after connect error"),sc.get_last_error_msg());
244 void HelloTimeoutNothing()
246 switch(child_pid=fork())
250 CPPUNIT_FAIL("fork error");
258 socket_server ss("./socket");
261 for (int i=0; i < 10; i++)
262 ss.fill_buffer(1000000);
265 std::cerr << "exception in child. ignoring\n";
268 // don't call atexit and stuff
277 // wait till server is up
279 socket_client_connection sc("./socket");
280 command_client cc(&sc,1000000,1000000);
282 t2n_exception* ep=cc.get_constuctor_exception();
288 CPPUNIT_ASSERT_EQUAL(string("timeout exceeded"),errormsg);
293 void HelloTimeoutSlowData()
295 switch(child_pid=fork())
299 CPPUNIT_FAIL("fork error");
307 socket_server ss("./socket");
309 // create a valid packet
311 hello << "T2Nv" << PROTOCOL_VERSION << ';';
312 int byteordercheck=1;
313 hello.write((char*)&byteordercheck,sizeof(byteordercheck));
316 packet_size_indicator psize=htonl(hello.str().size());
317 std::string send_data(hello.str());
318 send_data.insert(0,(char*)&psize,sizeof(packet_size_indicator));
320 ss.add_callback(new_connection,bind(&test_timeout::send_slow_raw_socket, boost::ref(*this), send_data,&ss, _1));
323 for (int i=0; i < 10; i++)
324 ss.fill_buffer(1000000);
327 std::cerr << "exception in child. ignoring\n";
330 // don't call atexit and stuff
339 // wait till server is up
341 socket_client_connection sc("./socket");
342 command_client cc(&sc,1000000,1000000);
344 t2n_exception* ep=cc.get_constuctor_exception();
350 CPPUNIT_ASSERT_EQUAL(string("timeout exceeded"),errormsg);
355 void CommandTimeout()
357 switch(child_pid=fork())
361 CPPUNIT_FAIL("fork error");
369 socket_server ss("./socket");
372 hello << "T2Nv" << PROTOCOL_VERSION << ';';
373 int byteordercheck=1;
374 hello.write((char*)&byteordercheck,sizeof(byteordercheck));
377 ss.add_callback(new_connection,bind(&test_timeout::send_hello, boost::ref(*this), hello.str(),&ss, _1));
380 for (int i=0; i < 10; i++)
381 ss.fill_buffer(1000000);
384 std::cerr << "exception in child. ignoring\n";
387 // don't call atexit and stuff
396 // wait till server is up
398 socket_client_connection sc("./socket");
400 command_client cc(&sc,1000000,1000000);
407 cc.send_command(new testfunc2_cmd("hello"),rc);
409 catch(t2n_transfer_error &e)
410 { errormsg=e.what(); }
414 CPPUNIT_ASSERT_EQUAL(string("timeout exceeded"),errormsg);
419 void CommandSlowResponse()
421 switch(child_pid=fork())
425 CPPUNIT_FAIL("fork error");
433 socket_server ss("./socket");
436 hello << "T2Nv" << PROTOCOL_VERSION << ';';
437 int byteordercheck=1;
438 hello.write((char*)&byteordercheck,sizeof(byteordercheck));
441 ss.add_callback(new_connection,bind(&test_timeout::send_hello, boost::ref(*this), hello.str(),&ss, _1));
444 for (int i=0; i < 10; i++)
446 ss.fill_buffer(1000000);
451 if(ss.get_packet(data,cid))
453 // create a valid packet & send
454 string response="abcdefghijklmnopqrstuvwxyz";
455 packet_size_indicator psize=htonl(response.size());
456 std::string send_data(response);
457 send_data.insert(0,(char*)&psize,sizeof(packet_size_indicator));
458 send_slow_raw_socket(send_data,&ss,cid);
463 std::cerr << "exception in child. ignoring\n";
466 // don't call atexit and stuff
475 // wait till server is up
477 socket_client_connection sc("./socket");
479 command_client cc(&sc,1000000,1000000);
486 cc.send_command(new testfunc2_cmd("hello"),rc);
488 catch(t2n_transfer_error &e)
489 { errormsg=e.what(); }
493 CPPUNIT_ASSERT_EQUAL(string("timeout exceeded"),errormsg);
498 void DisconnectOnWrite()
500 switch(child_pid=fork())
504 CPPUNIT_FAIL("fork error");
512 socket_server ss("./socket");
514 // bail out as soon as we get something
518 std::cerr << "exception in child. ignoring\n";
521 // don't call atexit and stuff
530 // don't kill us on broken pipe
531 signal(SIGPIPE, SIG_IGN);
533 // wait till server is up
535 socket_client_connection sc("./socket");
539 string huge(5000000,'x');
545 catch(t2n_transfer_error &e)
546 { errormsg=e.what(); }
550 CPPUNIT_ASSERT_EQUAL(string("write() returned Broken pipe"),errormsg);
557 switch(child_pid=fork())
561 CPPUNIT_FAIL("fork error");
569 socket_server ss("./socket");
571 // bail out as soon as we get something
576 std::cerr << "exception in child. ignoring\n";
579 // don't call atexit and stuff
588 // don't kill us on broken pipe
589 signal(SIGPIPE, SIG_IGN);
591 // wait till server is up
593 socket_client_connection sc("./socket");
597 sc.write("somedata");
601 // server should disconnect now
604 sc.write("other data");
606 catch(t2n_transfer_error &e)
607 { errormsg=e.what(); }
611 CPPUNIT_ASSERT_EQUAL(string("write() returned Broken pipe"),errormsg);
616 void DisconnectOnRead()
620 switch(child_pid=fork())
624 CPPUNIT_FAIL("fork error");
632 // wait till server is up
635 socket_client_connection sc("./socket");
637 // this is an evil hack to get access to real_write, don't ever do this in an app!!!
638 real_write_client_connection *rwc=(real_write_client_connection*)≻
639 rwc->real_write(string(10000,'x'));
642 std::cerr << "exception in child. ignoring\n";
645 // don't call atexit and stuff
652 // don't kill us on broken pipe
653 signal(SIGPIPE, SIG_IGN);
655 socket_server ss("./socket");
657 time_t t0 = time(NULL);
660 while (time(NULL) < t0 + 5 )
662 ss.fill_buffer(1000000);
668 // are we still alive and able to process data?
674 CPPUNIT_FAIL("fork error");
682 socket_client_connection *sc=new socket_client_connection("./socket");
683 sc->write(string(10000,'x'));
684 // socket is closed regularly
688 std::cerr << "exception in child. ignoring\n";
691 // don't run regular cleanup, otherwise cppunit stuff gets called
703 while (time(NULL) < t0 + 10 )
705 ss.fill_buffer(1000000);
707 if (ss.get_packet(received))
711 CPPUNIT_ASSERT_EQUAL(string(10000,'x'),received);
723 switch(child_pid=fork())
727 CPPUNIT_FAIL("fork error");
735 // wait till server is really up and waiting
738 // connect with very tight timeout and only 1 retry
739 socket_client_connection sc("./socket",50,1);
742 std::cerr << "exception in child. ignoring\n";
745 // don't call atexit and stuff
752 // don't kill us on broken pipe
753 signal(SIGPIPE, SIG_IGN);
755 socket_server ss("./socket");
757 // server is "working" while client wants to connect
760 time_t t0 = time(NULL);
763 while (time(NULL) < t0 + 5 )
765 ss.fill_buffer(1000000);
771 // are we still alive and able to process data?
777 CPPUNIT_FAIL("fork error");
785 socket_client_connection *sc=new socket_client_connection("./socket");
786 sc->write(string(10000,'x'));
788 // socket is closed regularly
791 std::cerr << "exception in child. ignoring\n";
794 // don't run regular cleanup, otherwise cppunit stuff gets called
806 while (time(NULL) < t0 + 10 )
808 ss.fill_buffer(1000000);
810 if (ss.get_packet(received))
814 CPPUNIT_ASSERT_EQUAL(string(10000,'x'),received);
823 CPPUNIT_TEST_SUITE_REGISTRATION(test_timeout);