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"
55 using namespace libt2n;
57 string testfunc2(const string& str)
60 throw libt2n::t2n_runtime_error("throw me around");
62 ret+=", testfunc() was here";
66 class testfunc2_res : public libt2n::result
71 friend class boost::serialization::access;
72 template<class Archive>
73 void serialize(Archive & ar, const unsigned int version)
75 ar & BOOST_SERIALIZATION_BASE_OBJECT_NVP(libt2n::result);
76 ar & BOOST_SERIALIZATION_NVP(res);
83 testfunc2_res(const string& str)
95 class testfunc2_cmd : public libt2n::command
100 friend class boost::serialization::access;
101 template<class Archive>
102 void serialize(Archive & ar, const unsigned int version)
104 ar & BOOST_SERIALIZATION_BASE_OBJECT_NVP(libt2n::command);
105 ar & BOOST_SERIALIZATION_NVP(param);
112 testfunc2_cmd(const string& str)
117 libt2n::result* operator()()
119 return new testfunc2_res(testfunc2(param));
123 #include <boost/serialization/export.hpp>
125 BOOST_CLASS_EXPORT(testfunc2_cmd)
126 BOOST_CLASS_EXPORT(testfunc2_res)
128 class test_timeoutFixture : public KillChildOnShutdownFixture
131 typedef uint32_t packet_size_indicator;
133 // this is an evil hack to get access to real_write, don't ever do this in an app!!!
134 class real_write_client_connection: public socket_client_connection
137 void real_write(const std::string& data)
138 { socket_write(data); }
141 void send_slow_raw_socket(string data, socket_server* ss, unsigned int conn_id)
143 socket_server_connection *ssc=dynamic_cast<socket_server_connection*>(ss->get_connection(conn_id));
145 // this is an evil hack to get access to real_write, don't ever do this in an app!!!
146 real_write_connection *rwc=(real_write_connection*)ssc;
148 // we write one char each 0.2 sec
149 for (int pos=0; pos < data.size(); pos++)
153 rwc->real_write(onebyte);
159 BOOST_FIXTURE_TEST_SUITE(test_timeout, test_timeoutFixture)
161 BOOST_AUTO_TEST_CASE(ConnectTimeout)
163 switch(child_pid=fork())
167 BOOST_FAIL("fork error");
175 socket_server ss("./socket");
178 std::cerr << "exception in child. ignoring\n";
181 // don't call atexit and stuff
190 // wait till server is up
195 socket_client_connection sc("./socket");
197 BOOST_CHECK_MESSAGE(sc.connection::is_closed() == true, "connection not closed");
199 BOOST_CHECK_MESSAGE(sc.get_last_error_msg() == string("no more retries left after connect error"), "wrong errormessage");
204 BOOST_AUTO_TEST_CASE(HelloTimeoutNothing)
206 switch(child_pid=fork())
210 BOOST_FAIL("fork error");
218 socket_server ss("./socket");
221 for (int i=0; i < 10; i++)
222 ss.fill_buffer(1000000);
225 std::cerr << "exception in child. ignoring\n";
228 // don't call atexit and stuff
237 // wait till server is up
239 socket_client_connection sc("./socket");
240 command_client cc(&sc,1000000,1000000);
242 t2n_exception* ep=cc.get_constuctor_exception();
248 BOOST_CHECK_EQUAL(string("timeout exceeded"),errormsg);
253 BOOST_AUTO_TEST_CASE(HelloTimeoutSlowData)
255 switch(child_pid=fork())
259 BOOST_FAIL("fork error");
267 socket_server ss("./socket");
269 // create a valid packet
271 hello << "T2Nv" << PROTOCOL_VERSION << ';';
272 int byteordercheck=1;
273 hello.write((char*)&byteordercheck,sizeof(byteordercheck));
276 packet_size_indicator psize=htonl(hello.str().size());
277 std::string send_data(hello.str());
278 send_data.insert(0,(char*)&psize,sizeof(packet_size_indicator));
280 ss.add_callback(new_connection,bind(&test_timeout::HelloTimeoutSlowData::send_slow_raw_socket, boost::ref(*this), send_data,&ss, _1));
283 for (int i=0; i < 10; i++)
284 ss.fill_buffer(1000000);
287 std::cerr << "exception in child. ignoring\n";
290 // don't call atexit and stuff
299 // wait till server is up
301 socket_client_connection sc("./socket");
302 command_client cc(&sc,1000000,1000000);
304 t2n_exception* ep=cc.get_constuctor_exception();
310 BOOST_CHECK_EQUAL(string("timeout exceeded"),errormsg);
315 BOOST_AUTO_TEST_CASE(CommandTimeout)
317 switch(child_pid=fork())
321 BOOST_FAIL("fork error");
329 socket_server ss("./socket");
332 hello << "T2Nv" << PROTOCOL_VERSION << ';';
333 int byteordercheck=1;
334 hello.write((char*)&byteordercheck,sizeof(byteordercheck));
337 ss.add_callback(new_connection,bind(&test_timeout::CommandTimeout::send_hello, boost::ref(*this), hello.str(),&ss, _1));
340 for (int i=0; i < 10; i++)
341 ss.fill_buffer(1000000);
344 std::cerr << "exception in child. ignoring\n";
347 // don't call atexit and stuff
356 // wait till server is up
358 socket_client_connection sc("./socket");
360 command_client cc(&sc,1000000,1000000);
367 cc.send_command(new testfunc2_cmd("hello"),rc);
369 catch(t2n_transfer_error &e)
370 { errormsg=e.what(); }
372 BOOST_CHECK_EQUAL(string("timeout exceeded"),errormsg);
377 BOOST_AUTO_TEST_CASE(CommandSlowResponse)
379 switch(child_pid=fork())
383 BOOST_FAIL("fork error");
391 socket_server ss("./socket");
394 hello << "T2Nv" << PROTOCOL_VERSION << ';';
395 int byteordercheck=1;
396 hello.write((char*)&byteordercheck,sizeof(byteordercheck));
399 ss.add_callback(new_connection,bind(&test_timeout::CommandSlowResponse::send_hello, boost::ref(*this), hello.str(),&ss, _1));
402 for (int i=0; i < 10; i++)
404 ss.fill_buffer(1000000);
409 if(ss.get_packet(data,cid))
411 // create a valid packet & send
412 string response="abcdefghijklmnopqrstuvwxyz";
413 packet_size_indicator psize=htonl(response.size());
414 std::string send_data(response);
415 send_data.insert(0,(char*)&psize,sizeof(packet_size_indicator));
416 send_slow_raw_socket(send_data,&ss,cid);
421 std::cerr << "exception in child. ignoring\n";
424 // don't call atexit and stuff
433 // wait till server is up
435 socket_client_connection sc("./socket");
437 command_client cc(&sc,1000000,1000000);
444 cc.send_command(new testfunc2_cmd("hello"),rc);
446 catch(t2n_transfer_error &e)
447 { errormsg=e.what(); }
449 BOOST_CHECK_EQUAL(string("timeout exceeded"),errormsg);
454 BOOST_AUTO_TEST_CASE(DisconnectOnWrite)
456 switch(child_pid=fork())
460 BOOST_FAIL("fork error");
468 socket_server ss("./socket");
470 // bail out as soon as we get something
474 std::cerr << "exception in child. ignoring\n";
477 // don't call atexit and stuff
486 // don't kill us on broken pipe
487 signal(SIGPIPE, SIG_IGN);
489 // wait till server is up
491 socket_client_connection sc("./socket");
495 string huge(5000000,'x');
501 catch(t2n_transfer_error &e)
502 { errormsg=e.what(); }
504 BOOST_CHECK_EQUAL(string("write() returned Broken pipe"),errormsg);
509 BOOST_AUTO_TEST_CASE(WriteTwice)
511 switch(child_pid=fork())
515 BOOST_FAIL("fork error");
523 socket_server ss("./socket");
525 // bail out as soon as we get something
530 std::cerr << "exception in child. ignoring\n";
533 // don't call atexit and stuff
542 // don't kill us on broken pipe
543 signal(SIGPIPE, SIG_IGN);
545 // wait till server is up
547 socket_client_connection sc("./socket");
551 sc.write("somedata");
555 // server should disconnect now
558 sc.write("other data(2)");
560 sc.write("other data(3)");
562 catch(t2n_transfer_error &e)
563 { errormsg=e.what(); }
565 BOOST_CHECK_EQUAL(string("write() returned Broken pipe"),errormsg);
570 BOOST_AUTO_TEST_CASE(DisconnectOnRead)
574 switch(child_pid=fork())
578 BOOST_FAIL("fork error");
586 // wait till server is up
589 socket_client_connection sc("./socket");
591 // this is an evil hack to get access to real_write, don't ever do this in an app!!!
592 real_write_client_connection *rwc=(real_write_client_connection*)≻
593 rwc->real_write(string(10000,'x'));
596 std::cerr << "exception in child. ignoring\n";
599 // don't call atexit and stuff
606 // don't kill us on broken pipe
607 signal(SIGPIPE, SIG_IGN);
609 socket_server ss("./socket");
611 time_t t0 = time(NULL);
614 while (time(NULL) < t0 + 5 )
616 ss.fill_buffer(1000000);
622 // are we still alive and able to process data?
628 BOOST_FAIL("fork error");
636 socket_client_connection *sc=new socket_client_connection("./socket");
637 sc->write(string(10000,'x'));
638 // socket is closed regularly
642 std::cerr << "exception in child. ignoring\n";
645 // don't run regular cleanup, otherwise cppunit stuff gets called
657 while (time(NULL) < t0 + 10 )
659 ss.fill_buffer(1000000);
661 if (ss.get_packet(received))
665 BOOST_CHECK_EQUAL(string(10000,'x'),received);
673 BOOST_AUTO_TEST_CASE(BreakAccept)
677 switch(child_pid=fork())
681 BOOST_FAIL("fork error");
689 // wait till server is really up and waiting
692 // connect with very tight timeout and only 1 retry
693 socket_client_connection sc("./socket",50,1);
696 std::cerr << "exception in child. ignoring\n";
699 // don't call atexit and stuff
706 // don't kill us on broken pipe
707 signal(SIGPIPE, SIG_IGN);
709 socket_server ss("./socket");
711 // server is "working" while client wants to connect
714 time_t t0 = time(NULL);
717 while (time(NULL) < t0 + 5 )
719 ss.fill_buffer(1000000);
725 // are we still alive and able to process data?
731 BOOST_FAIL("fork error");
739 socket_client_connection *sc=new socket_client_connection("./socket");
740 sc->write(string(10000,'x'));
742 // socket is closed regularly
745 std::cerr << "exception in child. ignoring\n";
748 // don't run regular cleanup, otherwise cppunit stuff gets called
760 while (time(NULL) < t0 + 10 )
762 ss.fill_buffer(1000000);
764 if (ss.get_packet(received))
768 BOOST_CHECK_EQUAL(string(10000,'x'),received);
776 BOOST_AUTO_TEST_SUITE_END()