From 039e52da9b40d0e729360ff0a953dfbddf975b8a Mon Sep 17 00:00:00 2001 From: Gerd v. Egidy Date: Fri, 21 Nov 2008 10:48:14 +0000 Subject: [PATCH] libt2n: (gerd) set additional non-blocking options, not really needed but a safety-measure, add unit-test --- src/socket_client.cpp | 11 +++ test/Makefile.am | 2 +- test/newserver.cpp | 197 +++++++++++++++++++++++++++++++++++++++++++++++++ test/timeout.cpp | 54 +++++++++++++ 4 files changed, 263 insertions(+), 1 deletions(-) create mode 100644 test/newserver.cpp diff --git a/src/socket_client.cpp b/src/socket_client.cpp index a26b004..360e5f0 100644 --- a/src/socket_client.cpp +++ b/src/socket_client.cpp @@ -175,6 +175,17 @@ void socket_client_connection::connect_with_timeout(struct sockaddr *sock_addr,u { set_socket_options(sock); + /* non-blocking mode */ + int flflags; + flflags=fcntl(sock,F_GETFL,0); + if (flflags < 0) + EXCEPTIONSTREAM(error,t2n_communication_error,"fcntl error on socket: " << strerror(errno)); + + flflags &= (O_NONBLOCK ^ 0xFFFF); + if (fcntl(sock,F_SETFL,flflags) < 0) + EXCEPTIONSTREAM(error,t2n_communication_error,"fcntl error on socket: " << strerror(errno)); + + LOGSTREAM(debug,"connect_with_timeout()"); int ret=::connect(sock,sock_addr, sockaddr_size); diff --git a/test/Makefile.am b/test/Makefile.am index cbe0440..5aad119 100644 --- a/test/Makefile.am +++ b/test/Makefile.am @@ -4,7 +4,7 @@ check_PROGRAMS = test test_LDADD = $(top_builddir)/src/libt2n.la @BOOST_SERIALIZATION_LIB@ \ @BOOST_LDFLAGS@ @CPPUNIT_LIBS@ -test_SOURCES = callback.cpp cmdgroup.cpp comm.cpp hello.cpp reconnect.cpp \ +test_SOURCES = newserver.cpp callback.cpp cmdgroup.cpp comm.cpp hello.cpp reconnect.cpp \ reentrant.cpp serialize.cpp simplecmd.cpp test.cpp timeout.cpp wrapper.cpp TESTS = test diff --git a/test/newserver.cpp b/test/newserver.cpp new file mode 100644 index 0000000..2631d0e --- /dev/null +++ b/test/newserver.cpp @@ -0,0 +1,197 @@ +/*************************************************************************** + * 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 + +using namespace std; +using namespace CppUnit; + +int newserver_func(int i) +{ + + return 1; +} + +class newserver_res : public libt2n::result +{ + private: + int 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: + newserver_res() + { } + + newserver_res(int i) + { + res=i; + } + + int get_data() + { + return res; + } +}; + + +class newserver_cmd : public libt2n::command +{ + private: + int 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: + newserver_cmd() + { } + + newserver_cmd(int i) + { + param=i; + } + + libt2n::result* operator()() + { + return new newserver_res(newserver_func(param)); + } +}; + +#include + +BOOST_CLASS_EXPORT(newserver_cmd) +BOOST_CLASS_EXPORT(newserver_res) + +using namespace libt2n; + +class test_newserver : public TestFixture +{ + CPPUNIT_TEST_SUITE(test_newserver); + + CPPUNIT_TEST(NewServerSocket); + + CPPUNIT_TEST_SUITE_END(); + + pid_t child_pid; + + public: + + void setUp() + { } + + void tearDown() + { + // make sure the server-child is dead before the next test runs + kill(child_pid,SIGKILL); + sleep(1); + } + + void NewServerSocket() + { + switch(child_pid=fork()) + { + case -1: + { + CPPUNIT_FAIL("fork error"); + break; + } + case 0: + // child + { + { + socket_server ss("./socket"); + command_server cs(ss); + + // handle new connection and just one command + cs.handle(10000000); + cs.handle(10000000); + } + // close socket, create new one + { + socket_server ss("./socket"); + ss.set_logging(&cerr,debug); + command_server cs(ss); + + // max 30 sec + for (int i=0; i < 30; i++) + cs.handle(1000000); + } + + // don't call atexit and stuff + _exit(0); + } + + default: + // parent + { + // wait till server is up + sleep(1); + socket_client_connection sc("./socket"); + sc.set_logging(&cerr,debug); + command_client cc(&sc); + + result_container rc; + cc.send_command(new newserver_cmd(1),rc); + + // very short sleep to make sure new server socket is up + usleep(10000); + + // still has connection to the old server-socket + string errormsg; + + try + { + sc.write("some stuff"); + } + catch(t2n_transfer_error &e) + { errormsg=e.what(); } + catch(...) + { throw; } + + CPPUNIT_ASSERT_EQUAL(string("error reading from socket : Connection reset by peer"),errormsg); + } + } + } +}; + +CPPUNIT_TEST_SUITE_REGISTRATION(test_newserver); diff --git a/test/timeout.cpp b/test/timeout.cpp index 7a4e9ed..e194b85 100644 --- a/test/timeout.cpp +++ b/test/timeout.cpp @@ -138,6 +138,7 @@ class test_timeout : public TestFixture CPPUNIT_TEST(CommandTimeout); CPPUNIT_TEST(CommandSlowResponse); CPPUNIT_TEST(DisconnectOnWrite); + CPPUNIT_TEST(WriteTwice); CPPUNIT_TEST(DisconnectOnRead); CPPUNIT_TEST(BreakAccept); @@ -495,6 +496,59 @@ class test_timeout : public TestFixture } } + void WriteTwice() + { + switch(child_pid=fork()) + { + case -1: + { + CPPUNIT_FAIL("fork error"); + break; + } + case 0: + // child + { + socket_server ss("./socket"); + + // bail out as soon as we get something + ss.fill_buffer(-1); + // don't call atexit and stuff + _exit(0); + } + + default: + // parent + { + string data; + + // don't kill us on broken pipe + signal(SIGPIPE, SIG_IGN); + + // wait till server is up + sleep(1); + socket_client_connection sc("./socket"); + + string errormsg; + + sc.write("somedata"); + + sleep(1); + + // server should disconnect now + try + { + sc.write("other data"); + } + catch(t2n_transfer_error &e) + { errormsg=e.what(); } + catch(...) + { throw; } + + CPPUNIT_ASSERT_EQUAL(string("write() returned Broken pipe"),errormsg); + } + } + } + void DisconnectOnRead() { pid_t pid2; -- 1.7.1