From 539b09c0c1819f9394e5a0ae8b3df3687715fa7c Mon Sep 17 00:00:00 2001 From: Gerd v. Egidy Date: Mon, 30 Oct 2006 18:43:58 +0000 Subject: [PATCH] libt2n: (gerd) add command groups --- src/command_server.cpp | 24 +++-- src/command_server.hxx | 24 ++++- test/Makefile.am | 2 +- test/cmdgroup.cpp | 277 ++++++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 316 insertions(+), 11 deletions(-) create mode 100644 test/cmdgroup.cpp diff --git a/src/command_server.cpp b/src/command_server.cpp index 55c4cc1..cc66de4 100644 --- a/src/command_server.cpp +++ b/src/command_server.cpp @@ -54,7 +54,7 @@ void command_server::send_hello(unsigned int conn_id) { server_connection* sc=s.get_connection(conn_id); - ostringstream hello; + std::ostringstream hello; hello << "T2Nv" << PROTOCOL_VERSION << ';'; @@ -72,7 +72,7 @@ void command_server::handle_packet(const std::string& packet, server_connection* OBJLOGSTREAM(s,debug,"handling packet from connection " << conn->get_id()); // deserialize packet - istringstream ifs(packet); + std::istringstream ifs(packet); boost::archive::binary_iarchive ia(ifs); command_container ccont; result_container res; @@ -83,7 +83,7 @@ void command_server::handle_packet(const std::string& packet, server_connection* } catch(boost::archive::archive_exception &e) { - ostringstream msg; + std::ostringstream msg; msg << "archive_exception while deserializing on server-side, " "code " << e.code << " (" << e.what() << ")"; res.set_exception(new t2n_serialization_error(msg.str())); @@ -101,8 +101,7 @@ void command_server::handle_packet(const std::string& packet, server_connection* xo << BOOST_SERIALIZATION_NVP(ccont); } - // TODO: cast to command subclass (template) - command *cmd=ccont.get_command(); + command* cmd=cast_command(ccont.get_command()); if (cmd) { @@ -116,10 +115,17 @@ void command_server::handle_packet(const std::string& packet, server_connection* { throw; } } else - throw logic_error("uninitialized command called"); + { + std::ostringstream msg; + if (ccont.get_command()!=NULL) + msg << "illegal command of type " << typeid(ccont.get_command()).name() << " called"; + else + msg << "NULL command called"; + res.set_exception(new t2n_command_error(msg.str())); + } } - ostringstream ofs; + std::ostringstream ofs; boost::archive::binary_oarchive oa(ofs); try @@ -128,7 +134,7 @@ void command_server::handle_packet(const std::string& packet, server_connection* } catch(boost::archive::archive_exception &e) { - ostringstream msg; + std::ostringstream msg; msg << "archive_exception while serializing on server-side, " "code " << e.code << " (" << e.what() << ")"; res.set_exception(new t2n_serialization_error(msg.str())); @@ -156,7 +162,7 @@ void command_server::handle(long long usec_timeout, long long* usec_timeout_rema { if (s.fill_buffer(usec_timeout,usec_timeout_remaining)) { - string packet; + std::string packet; unsigned int conn_id; while (s.get_packet(packet,conn_id)) diff --git a/src/command_server.hxx b/src/command_server.hxx index 1926733..3c00262 100644 --- a/src/command_server.hxx +++ b/src/command_server.hxx @@ -19,6 +19,7 @@ #ifndef __LIBT2N_COMMAND_SERVER #define __LIBT2N_COMMAND_SERVER +#include "command.hxx" #include "server.hxx" namespace libt2n @@ -32,6 +33,10 @@ class command_server void handle_packet(const std::string& packet, server_connection* conn); + protected: + virtual command* cast_command(command* input) + { return input; } + public: command_server(server& _s); @@ -40,7 +45,24 @@ class command_server void send_hello(unsigned int conn_id); }; -} +template struct Derived_from { + static void constraints(T* p) { B* pb = p; } + Derived_from() { void(*p)(T*) = constraints; } +}; + +template +class group_command_server : public command_server +{ + private: + virtual command* cast_command(command* input) + { return dynamic_cast(input); } + public: + group_command_server(server& _s) + : command_server(_s) + { Derived_from(); } +}; + +} #endif diff --git a/test/Makefile.am b/test/Makefile.am index bc1f77b..d41e6e4 100644 --- a/test/Makefile.am +++ b/test/Makefile.am @@ -5,6 +5,6 @@ check_PROGRAMS = test test_LDADD = $(top_builddir)/src/libt2n.la @BOOST_SERIALIZATION_LIB@ \ @BOOST_LDFLAGS@ @CPPUNIT_LIBS@ test_SOURCES = test.cpp comm.cpp simplecmd.cpp callback.cpp hello.cpp \ - timeout.cpp serialize.cpp + timeout.cpp serialize.cpp cmdgroup.cpp TESTS = test diff --git a/test/cmdgroup.cpp b/test/cmdgroup.cpp new file mode 100644 index 0000000..fc5952b --- /dev/null +++ b/test/cmdgroup.cpp @@ -0,0 +1,277 @@ +/*************************************************************************** + * 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 + +using namespace std; +using namespace CppUnit; +using namespace libt2n; + +string testfunc4(const string& str) +{ + if (str=="throw") + throw libt2n::t2n_runtime_error("throw me around"); + string ret(str); + ret+=", testfunc() was here"; + return ret; +} + +class testfunc4_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: + testfunc4_res() + { } + + testfunc4_res(const string& str) + { + res=str; + } + + string get_data() + { + return res; + } +}; + +class cmd_group_a : public command +{ + private: + friend class boost::serialization::access; + template + void serialize(Archive & ar, const unsigned int version) + { + ar & BOOST_SERIALIZATION_BASE_OBJECT_NVP(libt2n::command); + } +}; + +class cmd_group_b : public command +{ + private: + friend class boost::serialization::access; + template + void serialize(Archive & ar, const unsigned int version) + { + ar & BOOST_SERIALIZATION_BASE_OBJECT_NVP(libt2n::command); + } +}; + +class testfunc4a_cmd : public cmd_group_a +{ + private: + string param; + + friend class boost::serialization::access; + template + void serialize(Archive & ar, const unsigned int version) + { + ar & BOOST_SERIALIZATION_BASE_OBJECT_NVP(cmd_group_a); + ar & BOOST_SERIALIZATION_NVP(param); + } + + public: + testfunc4a_cmd() + { } + + testfunc4a_cmd(const string& str) + { + param=str; + } + + libt2n::result* operator()() + { + return new testfunc4_res(testfunc4(param)); + } +}; + +class testfunc4b_cmd : public cmd_group_b +{ + private: + string param; + + friend class boost::serialization::access; + template + void serialize(Archive & ar, const unsigned int version) + { + ar & BOOST_SERIALIZATION_BASE_OBJECT_NVP(cmd_group_b); + ar & BOOST_SERIALIZATION_NVP(param); + } + + public: + testfunc4b_cmd() + { } + + testfunc4b_cmd(const string& str) + { + param=str; + } + + libt2n::result* operator()() + { + return new testfunc4_res(testfunc4(param)); + } +}; + + +BOOST_CLASS_EXPORT(testfunc4_res) +BOOST_CLASS_EXPORT(cmd_group_a) +BOOST_CLASS_EXPORT(cmd_group_b) +BOOST_CLASS_EXPORT(testfunc4a_cmd) +BOOST_CLASS_EXPORT(testfunc4b_cmd) + +class test_cmdgroup : public TestFixture +{ + CPPUNIT_TEST_SUITE(test_cmdgroup); + + CPPUNIT_TEST(GroupOk); + CPPUNIT_TEST(WrongGroup); + + CPPUNIT_TEST_SUITE_END(); + + public: + + void setUp() + { } + + void tearDown() + { } + + void GroupOk() + { + pid_t pid; + + switch(pid=fork()) + { + case -1: + { + CPPUNIT_FAIL("fork error"); + break; + } + case 0: + // child + { + socket_server ss("./socket"); + group_command_server cs(ss); + + // max 10 sec + for (int i=0; i < 10; 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"); + command_client cc(sc); + + result_container rc; + cc.send_command(new testfunc4a_cmd("hello"),rc); + + string ret=dynamic_cast(rc.get_result())->get_data(); + + CPPUNIT_ASSERT_EQUAL(string("hello, testfunc() was here"),ret); + } + } + } + + void WrongGroup() + { + pid_t pid; + + switch(pid=fork()) + { + case -1: + { + CPPUNIT_FAIL("fork error"); + break; + } + case 0: + // child + { + socket_server ss("./socket"); + group_command_server cs(ss); + + // max 10 sec + for (int i=0; i < 10; 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"); + command_client cc(sc); + + result_container rc; + cc.send_command(new testfunc4a_cmd("hello"),rc); + + string ret; + + try + { + ret=dynamic_cast(rc.get_result())->get_data(); + } + catch(t2n_command_error &e) + { ret=e.what(); } + catch(...) + { throw; } + + string expected_what="illegal command of type "; + + CPPUNIT_ASSERT_EQUAL(expected_what,ret.substr(0,expected_what.size())); + } + } + } + +}; + +CPPUNIT_TEST_SUITE_REGISTRATION(test_cmdgroup); -- 1.7.1