From: Gerd v. Egidy Date: Mon, 30 Oct 2006 17:27:53 +0000 (+0000) Subject: libt2n: (gerd) add server serialization exceptions X-Git-Tag: v0.2~130 X-Git-Url: http://developer.intra2net.com/git/?p=libt2n;a=commitdiff_plain;h=01a464637ed95b0aacd58eb74bdd17df4a7851ab;hp=b604df5f671b5e7abfd37570d76927a6ebd45f98 libt2n: (gerd) add server serialization exceptions --- diff --git a/src/command_server.cpp b/src/command_server.cpp index 4f386ec..55c4cc1 100644 --- a/src/command_server.cpp +++ b/src/command_server.cpp @@ -75,43 +75,69 @@ void command_server::handle_packet(const std::string& packet, server_connection* istringstream ifs(packet); boost::archive::binary_iarchive ia(ifs); command_container ccont; + result_container res; - // TODO: catch - ia >> ccont; - - std::ostream* ostr; - if ((ostr=s.get_logstream(fulldebug))!=NULL) + try { - (*ostr) << "decoded packet data: " << std::endl; - boost::archive::xml_oarchive xo(*ostr); - xo << BOOST_SERIALIZATION_NVP(ccont); + ia >> ccont; } + catch(boost::archive::archive_exception &e) + { + ostringstream msg; + msg << "archive_exception while deserializing on server-side, " + "code " << e.code << " (" << e.what() << ")"; + res.set_exception(new t2n_serialization_error(msg.str())); + } + catch(...) + { throw; } - // TODO: cast to command subclass (template) - command *cmd=ccont.get_command(); + if (!res.has_exception()) + { + std::ostream* ostr; + if ((ostr=s.get_logstream(fulldebug))!=NULL) + { + (*ostr) << "decoded packet data: " << std::endl; + boost::archive::xml_oarchive xo(*ostr); + xo << BOOST_SERIALIZATION_NVP(ccont); + } - result_container res; + // TODO: cast to command subclass (template) + command *cmd=ccont.get_command(); - if (cmd) - { - try + if (cmd) { - res.set_result((*cmd)()); + try + { + res.set_result((*cmd)()); + } + catch (t2n_exception &e) + { res.set_exception(e.clone()); } + catch (...) + { throw; } } - catch (t2n_exception &e) - { res.set_exception(e.clone()); } - catch (...) - { throw; } + else + throw logic_error("uninitialized command called"); } - else - throw logic_error("uninitialized command called"); ostringstream ofs; boost::archive::binary_oarchive oa(ofs); - // TODO: catch - oa << res; + try + { + oa << res; + } + catch(boost::archive::archive_exception &e) + { + ostringstream msg; + msg << "archive_exception while serializing on server-side, " + "code " << e.code << " (" << e.what() << ")"; + res.set_exception(new t2n_serialization_error(msg.str())); + oa << res; + } + catch(...) + { throw; } + std::ostream* ostr; if ((ostr=s.get_logstream(fulldebug))!=NULL) { (*ostr) << "returning result, decoded data: " << std::endl; diff --git a/src/container.hxx b/src/container.hxx index 2bf576b..710a07e 100644 --- a/src/container.hxx +++ b/src/container.hxx @@ -64,6 +64,11 @@ class result_container { res=0; ex=_ex; result_type=exception; } result* get_result(void); + + bool has_exception() + { return (result_type==exception); } + bool has_result() + { return (result_type==regular); } }; /** @brief contains a command diff --git a/test/Makefile.am b/test/Makefile.am index ff0e4a6..bc1f77b 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 + timeout.cpp serialize.cpp TESTS = test diff --git a/test/serialize.cpp b/test/serialize.cpp new file mode 100644 index 0000000..02f8a6e --- /dev/null +++ b/test/serialize.cpp @@ -0,0 +1,180 @@ +/*************************************************************************** + * 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; + +string testfunc3(const string& str) +{ + if (str=="throw") + throw libt2n::t2n_runtime_error("throw me around"); + string ret(str); + ret+=", testfunc() was here"; + return ret; +} + +class testfunc3_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: + testfunc3_res() + { } + + testfunc3_res(const string& str) + { + res=str; + } + + string get_data() + { + return res; + } +}; + + +class testfunc3_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: + testfunc3_cmd() + { } + + testfunc3_cmd(const string& str) + { + param=str; + } + + libt2n::result* operator()() + { + return new testfunc3_res(testfunc3(param)); + } +}; + +#include + +using namespace libt2n; + +class test_serialize : public TestFixture +{ + CPPUNIT_TEST_SUITE(test_serialize); + + CPPUNIT_TEST(ClientSerializeErr); + + // TODO: Server Deserialization Error + // TODO: Server Serialization Error + // TODO: Client Deserialization Error + // but those probably need separate client/server binaries + + CPPUNIT_TEST_SUITE_END(); + + public: + + void setUp() + { } + + void tearDown() + { } + + void ClientSerializeErr() + { + pid_t pid; + + switch(pid=fork()) + { + case -1: + { + CPPUNIT_FAIL("fork error"); + break; + } + case 0: + // child + { + socket_server ss("./socket"); + 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); + + string errormsg; + + result_container rc; + try + { + cc.send_command(new testfunc3_cmd("xyz"),rc); + } + catch(t2n_serialization_error &e) + { errormsg=e.what(); } + catch(...) + { throw; } + + CPPUNIT_ASSERT_EQUAL(string("archive_exception while serializing on client-side, code 2 (unregistered class)"),errormsg); + } + } + } + +}; + +CPPUNIT_TEST_SUITE_REGISTRATION(test_serialize);