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 #define BOOST_TEST_DYN_LINK
36 #include <boost/test/unit_test.hpp>
38 #include <boost/archive/binary_oarchive.hpp>
39 #include <boost/archive/binary_iarchive.hpp>
40 #include <boost/archive/xml_oarchive.hpp>
41 #include <boost/archive/xml_iarchive.hpp>
42 #include <boost/serialization/serialization.hpp>
44 #include <container.hxx>
45 #include <socket_client.hxx>
46 #include <socket_server.hxx>
47 #include <command_client.hxx>
48 #include <command_server.hxx>
50 #include "test_fixtures.hxx"
57 using namespace libt2n;
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); }
147 class test_timeoutFixture : public KillChildOnShutdownFixture
150 typedef uint32_t packet_size_indicator;
152 void send_hello(string hello_string, socket_server* ss, unsigned int conn_id)
154 server_connection *sc=ss->get_connection(conn_id);
155 sc->write(hello_string);
158 void send_slow_raw_socket(string data, socket_server* ss, unsigned int conn_id)
160 socket_server_connection *ssc=dynamic_cast<socket_server_connection*>(ss->get_connection(conn_id));
162 // this is an evil hack to get access to real_write, don't ever do this in an app!!!
163 real_write_connection *rwc=(real_write_connection*)ssc;
165 // we write one char each 0.2 sec
166 for (int pos=0; pos < data.size(); pos++)
170 rwc->real_write(onebyte);
176 test_timeoutFixture()
180 ~test_timeoutFixture()
185 BOOST_FIXTURE_TEST_SUITE(test_timeout, test_timeoutFixture)
187 BOOST_AUTO_TEST_CASE(ConnectTimeout)
189 switch(child_pid=fork())
193 BOOST_FAIL("fork error");
201 socket_server ss("./socket");
204 std::cerr << "exception in child. ignoring\n";
207 // don't call atexit and stuff
216 // wait till server is up
221 socket_client_connection sc("./socket");
223 BOOST_CHECK_MESSAGE(sc.connection::is_closed() == true, "connection not closed");
225 BOOST_CHECK_MESSAGE(sc.get_last_error_msg() == string("no more retries left after connect error"), "wrong errormessage");
230 BOOST_AUTO_TEST_CASE(HelloTimeoutNothing)
232 switch(child_pid=fork())
236 BOOST_FAIL("fork error");
244 socket_server ss("./socket");
247 for (int i=0; i < 10; i++)
248 ss.fill_buffer(1000000);
251 std::cerr << "exception in child. ignoring\n";
254 // don't call atexit and stuff
263 // wait till server is up
265 socket_client_connection sc("./socket");
266 command_client cc(&sc,1000000,1000000);
268 t2n_exception* ep=cc.get_constuctor_exception();
274 BOOST_CHECK_EQUAL(string("timeout exceeded"),errormsg);
279 BOOST_AUTO_TEST_CASE(HelloTimeoutSlowData)
281 switch(child_pid=fork())
285 BOOST_FAIL("fork error");
293 socket_server ss("./socket");
295 // create a valid packet
297 hello << "T2Nv" << PROTOCOL_VERSION << ';';
298 int byteordercheck=1;
299 hello.write((char*)&byteordercheck,sizeof(byteordercheck));
302 packet_size_indicator psize=htonl(hello.str().size());
303 std::string send_data(hello.str());
304 send_data.insert(0,(char*)&psize,sizeof(packet_size_indicator));
306 ss.add_callback(new_connection,bind(&test_timeout::HelloTimeoutSlowData::send_slow_raw_socket, boost::ref(*this), send_data,&ss, _1));
309 for (int i=0; i < 10; i++)
310 ss.fill_buffer(1000000);
313 std::cerr << "exception in child. ignoring\n";
316 // don't call atexit and stuff
325 // wait till server is up
327 socket_client_connection sc("./socket");
328 command_client cc(&sc,1000000,1000000);
330 t2n_exception* ep=cc.get_constuctor_exception();
336 BOOST_CHECK_EQUAL(string("timeout exceeded"),errormsg);
341 BOOST_AUTO_TEST_CASE(CommandTimeout)
343 switch(child_pid=fork())
347 BOOST_FAIL("fork error");
355 socket_server ss("./socket");
358 hello << "T2Nv" << PROTOCOL_VERSION << ';';
359 int byteordercheck=1;
360 hello.write((char*)&byteordercheck,sizeof(byteordercheck));
363 ss.add_callback(new_connection,bind(&test_timeout::CommandTimeout::send_hello, boost::ref(*this), hello.str(),&ss, _1));
366 for (int i=0; i < 10; i++)
367 ss.fill_buffer(1000000);
370 std::cerr << "exception in child. ignoring\n";
373 // don't call atexit and stuff
382 // wait till server is up
384 socket_client_connection sc("./socket");
386 command_client cc(&sc,1000000,1000000);
393 cc.send_command(new testfunc2_cmd("hello"),rc);
395 catch(t2n_transfer_error &e)
396 { errormsg=e.what(); }
400 BOOST_CHECK_EQUAL(string("timeout exceeded"),errormsg);
405 BOOST_AUTO_TEST_CASE(CommandSlowResponse)
407 switch(child_pid=fork())
411 BOOST_FAIL("fork error");
419 socket_server ss("./socket");
422 hello << "T2Nv" << PROTOCOL_VERSION << ';';
423 int byteordercheck=1;
424 hello.write((char*)&byteordercheck,sizeof(byteordercheck));
427 ss.add_callback(new_connection,bind(&test_timeout::CommandSlowResponse::send_hello, boost::ref(*this), hello.str(),&ss, _1));
430 for (int i=0; i < 10; i++)
432 ss.fill_buffer(1000000);
437 if(ss.get_packet(data,cid))
439 // create a valid packet & send
440 string response="abcdefghijklmnopqrstuvwxyz";
441 packet_size_indicator psize=htonl(response.size());
442 std::string send_data(response);
443 send_data.insert(0,(char*)&psize,sizeof(packet_size_indicator));
444 send_slow_raw_socket(send_data,&ss,cid);
449 std::cerr << "exception in child. ignoring\n";
452 // don't call atexit and stuff
461 // wait till server is up
463 socket_client_connection sc("./socket");
465 command_client cc(&sc,1000000,1000000);
472 cc.send_command(new testfunc2_cmd("hello"),rc);
474 catch(t2n_transfer_error &e)
475 { errormsg=e.what(); }
479 BOOST_CHECK_EQUAL(string("timeout exceeded"),errormsg);
484 BOOST_AUTO_TEST_CASE(DisconnectOnWrite)
486 switch(child_pid=fork())
490 BOOST_FAIL("fork error");
498 socket_server ss("./socket");
500 // bail out as soon as we get something
504 std::cerr << "exception in child. ignoring\n";
507 // don't call atexit and stuff
516 // don't kill us on broken pipe
517 signal(SIGPIPE, SIG_IGN);
519 // wait till server is up
521 socket_client_connection sc("./socket");
525 string huge(5000000,'x');
531 catch(t2n_transfer_error &e)
532 { errormsg=e.what(); }
536 BOOST_CHECK_EQUAL(string("write() returned Broken pipe"),errormsg);
541 BOOST_AUTO_TEST_CASE(WriteTwice)
543 switch(child_pid=fork())
547 BOOST_FAIL("fork error");
555 socket_server ss("./socket");
557 // bail out as soon as we get something
562 std::cerr << "exception in child. ignoring\n";
565 // don't call atexit and stuff
574 // don't kill us on broken pipe
575 signal(SIGPIPE, SIG_IGN);
577 // wait till server is up
579 socket_client_connection sc("./socket");
583 sc.write("somedata");
587 // server should disconnect now
590 sc.write("other data(2)");
592 sc.write("other data(3)");
594 catch(t2n_transfer_error &e)
595 { errormsg=e.what(); }
599 BOOST_CHECK_EQUAL(string("write() returned Broken pipe"),errormsg);
604 BOOST_AUTO_TEST_CASE(DisconnectOnRead)
608 switch(child_pid=fork())
612 BOOST_FAIL("fork error");
620 // wait till server is up
623 socket_client_connection sc("./socket");
625 // this is an evil hack to get access to real_write, don't ever do this in an app!!!
626 real_write_client_connection *rwc=(real_write_client_connection*)≻
627 rwc->real_write(string(10000,'x'));
630 std::cerr << "exception in child. ignoring\n";
633 // don't call atexit and stuff
640 // don't kill us on broken pipe
641 signal(SIGPIPE, SIG_IGN);
643 socket_server ss("./socket");
645 time_t t0 = time(NULL);
648 while (time(NULL) < t0 + 5 )
650 ss.fill_buffer(1000000);
656 // are we still alive and able to process data?
662 BOOST_FAIL("fork error");
670 socket_client_connection *sc=new socket_client_connection("./socket");
671 sc->write(string(10000,'x'));
672 // socket is closed regularly
676 std::cerr << "exception in child. ignoring\n";
679 // don't run regular cleanup, otherwise cppunit stuff gets called
691 while (time(NULL) < t0 + 10 )
693 ss.fill_buffer(1000000);
695 if (ss.get_packet(received))
699 BOOST_CHECK_EQUAL(string(10000,'x'),received);
707 BOOST_AUTO_TEST_CASE(BreakAccept)
711 switch(child_pid=fork())
715 BOOST_FAIL("fork error");
723 // wait till server is really up and waiting
726 // connect with very tight timeout and only 1 retry
727 socket_client_connection sc("./socket",50,1);
730 std::cerr << "exception in child. ignoring\n";
733 // don't call atexit and stuff
740 // don't kill us on broken pipe
741 signal(SIGPIPE, SIG_IGN);
743 socket_server ss("./socket");
745 // server is "working" while client wants to connect
748 time_t t0 = time(NULL);
751 while (time(NULL) < t0 + 5 )
753 ss.fill_buffer(1000000);
759 // are we still alive and able to process data?
765 BOOST_FAIL("fork error");
773 socket_client_connection *sc=new socket_client_connection("./socket");
774 sc->write(string(10000,'x'));
776 // socket is closed regularly
779 std::cerr << "exception in child. ignoring\n";
782 // don't run regular cleanup, otherwise cppunit stuff gets called
794 while (time(NULL) < t0 + 10 )
796 ss.fill_buffer(1000000);
798 if (ss.get_packet(received))
802 BOOST_CHECK_EQUAL(string(10000,'x'),received);
810 BOOST_AUTO_TEST_SUITE_END()