X-Git-Url: http://developer.intra2net.com/git/?p=libt2n;a=blobdiff_plain;f=test%2Ftimeout.cpp;fp=test%2Ftimeout.cpp;h=0493d627a38bdbe6a01ce44bac90ce879586ece3;hp=0000000000000000000000000000000000000000;hb=45a2ebc9695c4d7be6548b7e0f800d117ae56a0b;hpb=04d86ba4ad4f14ab08f38804e772ec46a8ac92b0 diff --git a/test/timeout.cpp b/test/timeout.cpp new file mode 100644 index 0000000..0493d62 --- /dev/null +++ b/test/timeout.cpp @@ -0,0 +1,411 @@ +/*************************************************************************** + * Copyright (C) 2004 by Intra2net AG * + * info@intra2net.com * + * * + ***************************************************************************/ + +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include + +#include +#include +#include + +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +#ifdef HAVE_CONFIG_H +#include +#endif + +using namespace std; +using namespace libt2n; +using namespace CppUnit; + +string testfunc2(const string& str) +{ + if (str=="throw") + throw libt2n::t2n_runtime_error("throw me around"); + string ret(str); + ret+=", testfunc() was here"; + return ret; +} + +class testfunc2_res : public libt2n::result +{ + private: + string res; + + friend class boost::serialization::access; + template + void serialize(Archive & ar, const unsigned int version) + { + ar & BOOST_SERIALIZATION_BASE_OBJECT_NVP(libt2n::result); + ar & BOOST_SERIALIZATION_NVP(res); + } + + public: + testfunc2_res() + { } + + testfunc2_res(const string& str) + { + res=str; + } + + string get_data() + { + return res; + } +}; + + +class testfunc2_cmd : public libt2n::command +{ + private: + string param; + + friend class boost::serialization::access; + template + void serialize(Archive & ar, const unsigned int version) + { + ar & BOOST_SERIALIZATION_BASE_OBJECT_NVP(libt2n::command); + ar & BOOST_SERIALIZATION_NVP(param); + } + + public: + testfunc2_cmd() + { } + + testfunc2_cmd(const string& str) + { + param=str; + } + + libt2n::result* operator()() + { + return new testfunc2_res(testfunc2(param)); + } +}; + +#include + +BOOST_CLASS_EXPORT(testfunc2_cmd) +BOOST_CLASS_EXPORT(testfunc2_res) + +// this is an evil hack to get access to real_write, don't ever do this in an app!!! +class real_write_connection: public socket_server_connection +{ + public: + void real_write(const std::string& data) + { socket_write(data); } +}; + +class test_timeout : public TestFixture +{ + CPPUNIT_TEST_SUITE(test_timeout); + + CPPUNIT_TEST(HelloTimeoutNothing); + CPPUNIT_TEST(HelloTimeoutSlowData); + CPPUNIT_TEST(CommandTimeout); + CPPUNIT_TEST(CommandSlowResponse); + + CPPUNIT_TEST_SUITE_END(); + + public: + + typedef uint32_t packet_size_indicator; + + void setUp() + { } + + void tearDown() + { } + + void send_hello(string hello_string, socket_server* ss, unsigned int conn_id) + { + server_connection *sc=ss->get_connection(conn_id); + sc->write(hello_string); + } + + void send_slow_raw_socket(string data, socket_server* ss, unsigned int conn_id) + { + socket_server_connection *ssc=dynamic_cast(ss->get_connection(conn_id)); + + // this is an evil hack to get access to real_write, don't ever do this in an app!!! + real_write_connection *rwc=(real_write_connection*)ssc; + + // we write one char each 0.2 sec + for (int pos=0; pos < data.size(); pos++) + { + string onebyte; + onebyte+=data[pos]; + rwc->real_write(onebyte); + usleep(200000); + } + } + + void HelloTimeoutNothing() + { + pid_t pid; + + switch(pid=fork()) + { + case -1: + { + CPPUNIT_FAIL("fork error"); + break; + } + case 0: + // child + { + socket_server ss("./socket"); + + // max 10 sec + for (int i=0; i < 10; i++) + ss.fill_buffer(1000000); + // don't call atexit and stuff + _exit(0); + } + + default: + // parent + { + string data; + + // wait till server is up + sleep(1); + socket_client_connection sc("./socket"); + + string errormsg; + + try + { + command_client cc(sc,1000000,1000000); + } + catch(t2n_transfer_error &e) + { errormsg=e.what(); } + catch(...) + { throw; } + + CPPUNIT_ASSERT_EQUAL(string("timeout exceeded"),errormsg); + } + } + } + + void HelloTimeoutSlowData() + { + pid_t pid; + + switch(pid=fork()) + { + case -1: + { + CPPUNIT_FAIL("fork error"); + break; + } + case 0: + // child + { + socket_server ss("./socket"); + + // create a valid packet + ostringstream hello; + hello << "T2Nv" << PROTOCOL_VERSION << ';'; + int byteordercheck=1; + hello.write((char*)&byteordercheck,sizeof(byteordercheck)); + hello << ';'; + + packet_size_indicator psize=htonl(hello.str().size()); + std::string send_data(hello.str()); + send_data.insert(0,(char*)&psize,sizeof(packet_size_indicator)); + + ss.add_callback(new_connection,bind(&test_timeout::send_slow_raw_socket, boost::ref(*this), send_data,&ss, _1)); + + // max 10 sec + for (int i=0; i < 10; i++) + ss.fill_buffer(1000000); + // don't call atexit and stuff + _exit(0); + } + + default: + // parent + { + string data; + + // wait till server is up + sleep(1); + socket_client_connection sc("./socket"); + + string errormsg; + + try + { + command_client cc(sc,1000000,1000000); + } + catch(t2n_transfer_error &e) + { errormsg=e.what(); } + catch(...) + { throw; } + + CPPUNIT_ASSERT_EQUAL(string("timeout exceeded"),errormsg); + } + } + } + + void CommandTimeout() + { + pid_t pid; + + switch(pid=fork()) + { + case -1: + { + CPPUNIT_FAIL("fork error"); + break; + } + case 0: + // child + { + socket_server ss("./socket"); + + ostringstream hello; + hello << "T2Nv" << PROTOCOL_VERSION << ';'; + int byteordercheck=1; + hello.write((char*)&byteordercheck,sizeof(byteordercheck)); + hello << ';'; + + ss.add_callback(new_connection,bind(&test_timeout::send_hello, boost::ref(*this), hello.str(),&ss, _1)); + + // max 10 sec + for (int i=0; i < 10; i++) + ss.fill_buffer(1000000); + // don't call atexit and stuff + _exit(0); + } + + default: + // parent + { + string data; + + // wait till server is up + sleep(1); + socket_client_connection sc("./socket"); + + command_client cc(sc,1000000,1000000); + result_container rc; + + string errormsg; + + try + { + cc.send_command(new testfunc2_cmd("hello"),rc); + } + catch(t2n_transfer_error &e) + { errormsg=e.what(); } + catch(...) + { throw; } + + CPPUNIT_ASSERT_EQUAL(string("timeout exceeded"),errormsg); + } + } + } + + void CommandSlowResponse() + { + pid_t pid; + + switch(pid=fork()) + { + case -1: + { + CPPUNIT_FAIL("fork error"); + break; + } + case 0: + // child + { + socket_server ss("./socket"); + + ostringstream hello; + hello << "T2Nv" << PROTOCOL_VERSION << ';'; + int byteordercheck=1; + hello.write((char*)&byteordercheck,sizeof(byteordercheck)); + hello << ';'; + + ss.add_callback(new_connection,bind(&test_timeout::send_hello, boost::ref(*this), hello.str(),&ss, _1)); + + // max 10 sec + for (int i=0; i < 10; i++) + { + ss.fill_buffer(1000000); + + string data; + unsigned int cid; + + if(ss.get_packet(data,cid)) + { + // create a valid packet & send + string response="abcdefghijklmnopqrstuvwxyz"; + packet_size_indicator psize=htonl(response.size()); + std::string send_data(response); + send_data.insert(0,(char*)&psize,sizeof(packet_size_indicator)); + send_slow_raw_socket(send_data,&ss,cid); + } + } + // don't call atexit and stuff + _exit(0); + } + + default: + // parent + { + string data; + + // wait till server is up + sleep(1); + socket_client_connection sc("./socket"); + + command_client cc(sc,1000000,1000000); + result_container rc; + + string errormsg; + + try + { + cc.send_command(new testfunc2_cmd("hello"),rc); + } + catch(t2n_transfer_error &e) + { errormsg=e.what(); } + catch(...) + { throw; } + + CPPUNIT_ASSERT_EQUAL(string("timeout exceeded"),errormsg); + } + } + } + +}; + +CPPUNIT_TEST_SUITE_REGISTRATION(test_timeout);