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(DisconnectOnRead);
142 CPPUNIT_TEST(BreakAccept);
144 CPPUNIT_TEST_SUITE_END();
148 typedef uint32_t packet_size_indicator;
156 void send_hello(string hello_string, socket_server* ss, unsigned int conn_id)
158 server_connection *sc=ss->get_connection(conn_id);
159 sc->write(hello_string);
162 void send_slow_raw_socket(string data, socket_server* ss, unsigned int conn_id)
164 socket_server_connection *ssc=dynamic_cast<socket_server_connection*>(ss->get_connection(conn_id));
166 // this is an evil hack to get access to real_write, don't ever do this in an app!!!
167 real_write_connection *rwc=(real_write_connection*)ssc;
169 // we write one char each 0.2 sec
170 for (int pos=0; pos < data.size(); pos++)
174 rwc->real_write(onebyte);
179 void ConnectTimeout()
187 CPPUNIT_FAIL("fork error");
193 socket_server ss("./socket");
195 // don't call atexit and stuff
204 // wait till server is up
211 socket_client_connection sc("./socket");
212 command_client cc(sc,1000000,1000000);
214 catch(t2n_transfer_error &e)
215 { errormsg=e.what(); }
219 CPPUNIT_ASSERT_EQUAL(string("error reading from socket : Invalid argument"),errormsg);
224 void HelloTimeoutNothing()
232 CPPUNIT_FAIL("fork error");
238 socket_server ss("./socket");
241 for (int i=0; i < 10; i++)
242 ss.fill_buffer(1000000);
243 // don't call atexit and stuff
252 // wait till server is up
254 socket_client_connection sc("./socket");
260 command_client cc(sc,1000000,1000000);
262 catch(t2n_transfer_error &e)
263 { errormsg=e.what(); }
267 CPPUNIT_ASSERT_EQUAL(string("timeout exceeded"),errormsg);
272 void HelloTimeoutSlowData()
280 CPPUNIT_FAIL("fork error");
286 socket_server ss("./socket");
288 // create a valid packet
290 hello << "T2Nv" << PROTOCOL_VERSION << ';';
291 int byteordercheck=1;
292 hello.write((char*)&byteordercheck,sizeof(byteordercheck));
295 packet_size_indicator psize=htonl(hello.str().size());
296 std::string send_data(hello.str());
297 send_data.insert(0,(char*)&psize,sizeof(packet_size_indicator));
299 ss.add_callback(new_connection,bind(&test_timeout::send_slow_raw_socket, boost::ref(*this), send_data,&ss, _1));
302 for (int i=0; i < 10; i++)
303 ss.fill_buffer(1000000);
304 // don't call atexit and stuff
313 // wait till server is up
315 socket_client_connection sc("./socket");
321 command_client cc(sc,1000000,1000000);
323 catch(t2n_transfer_error &e)
324 { errormsg=e.what(); }
328 CPPUNIT_ASSERT_EQUAL(string("timeout exceeded"),errormsg);
333 void CommandTimeout()
341 CPPUNIT_FAIL("fork error");
347 socket_server ss("./socket");
350 hello << "T2Nv" << PROTOCOL_VERSION << ';';
351 int byteordercheck=1;
352 hello.write((char*)&byteordercheck,sizeof(byteordercheck));
355 ss.add_callback(new_connection,bind(&test_timeout::send_hello, boost::ref(*this), hello.str(),&ss, _1));
358 for (int i=0; i < 10; i++)
359 ss.fill_buffer(1000000);
360 // don't call atexit and stuff
369 // wait till server is up
371 socket_client_connection sc("./socket");
373 command_client cc(sc,1000000,1000000);
380 cc.send_command(new testfunc2_cmd("hello"),rc);
382 catch(t2n_transfer_error &e)
383 { errormsg=e.what(); }
387 CPPUNIT_ASSERT_EQUAL(string("timeout exceeded"),errormsg);
392 void CommandSlowResponse()
400 CPPUNIT_FAIL("fork error");
406 socket_server ss("./socket");
409 hello << "T2Nv" << PROTOCOL_VERSION << ';';
410 int byteordercheck=1;
411 hello.write((char*)&byteordercheck,sizeof(byteordercheck));
414 ss.add_callback(new_connection,bind(&test_timeout::send_hello, boost::ref(*this), hello.str(),&ss, _1));
417 for (int i=0; i < 10; i++)
419 ss.fill_buffer(1000000);
424 if(ss.get_packet(data,cid))
426 // create a valid packet & send
427 string response="abcdefghijklmnopqrstuvwxyz";
428 packet_size_indicator psize=htonl(response.size());
429 std::string send_data(response);
430 send_data.insert(0,(char*)&psize,sizeof(packet_size_indicator));
431 send_slow_raw_socket(send_data,&ss,cid);
434 // don't call atexit and stuff
443 // wait till server is up
445 socket_client_connection sc("./socket");
447 command_client cc(sc,1000000,1000000);
454 cc.send_command(new testfunc2_cmd("hello"),rc);
456 catch(t2n_transfer_error &e)
457 { errormsg=e.what(); }
461 CPPUNIT_ASSERT_EQUAL(string("timeout exceeded"),errormsg);
466 void DisconnectOnWrite()
474 CPPUNIT_FAIL("fork error");
480 socket_server ss("./socket");
482 // bail out as soon as we get something
484 // don't call atexit and stuff
493 // don't kill us on broken pipe
494 signal(SIGPIPE, SIG_IGN);
496 // wait till server is up
498 socket_client_connection sc("./socket");
502 string huge(1000000,'x');
508 catch(t2n_transfer_error &e)
509 { errormsg=e.what(); }
513 CPPUNIT_ASSERT_EQUAL(string("write() returned Broken pipe"),errormsg);
518 void DisconnectOnRead()
526 CPPUNIT_FAIL("fork error");
532 // wait till server is up
535 socket_client_connection sc("./socket");
537 // this is an evil hack to get access to real_write, don't ever do this in an app!!!
538 real_write_client_connection *rwc=(real_write_client_connection*)≻
539 rwc->real_write(string(10000,'x'));
541 // don't call atexit and stuff
548 // don't kill us on broken pipe
549 signal(SIGPIPE, SIG_IGN);
551 socket_server ss("./socket");
553 time_t t0 = time(NULL);
556 while (time(NULL) < t0 + 5 )
558 ss.fill_buffer(1000000);
564 // are we still alive and able to process data?
570 CPPUNIT_FAIL("fork error");
576 socket_client_connection *sc=new socket_client_connection("./socket");
577 sc->write(string(10000,'x'));
579 // socket is closed regularly
581 // don't run regular cleanup, otherwise cppunit stuff gets called
593 while (time(NULL) < t0 + 10 )
595 ss.fill_buffer(1000000);
597 if (ss.get_packet(received))
601 CPPUNIT_ASSERT_EQUAL(string(10000,'x'),received);
616 CPPUNIT_FAIL("fork error");
622 // wait till server is really up and waiting
625 // connect with very tight timeout and only 1 retry
626 socket_client_connection sc("./socket",50,1);
628 // don't call atexit and stuff
635 // don't kill us on broken pipe
636 signal(SIGPIPE, SIG_IGN);
638 socket_server ss("./socket");
640 // server is "working" while client wants to connect
643 time_t t0 = time(NULL);
646 while (time(NULL) < t0 + 5 )
648 ss.fill_buffer(1000000);
654 // are we still alive and able to process data?
660 CPPUNIT_FAIL("fork error");
666 socket_client_connection *sc=new socket_client_connection("./socket");
667 sc->write(string(10000,'x'));
669 // socket is closed regularly
671 // don't run regular cleanup, otherwise cppunit stuff gets called
683 while (time(NULL) < t0 + 10 )
685 ss.fill_buffer(1000000);
687 if (ss.get_packet(received))
691 CPPUNIT_ASSERT_EQUAL(string(10000,'x'),received);
699 CPPUNIT_TEST_SUITE_REGISTRATION(test_timeout);