libt2n: (gerd) add server serialization exceptions
authorGerd v. Egidy <gerd.von.egidy@intra2net.com>
Mon, 30 Oct 2006 17:27:53 +0000 (17:27 +0000)
committerGerd v. Egidy <gerd.von.egidy@intra2net.com>
Mon, 30 Oct 2006 17:27:53 +0000 (17:27 +0000)
src/command_server.cpp
src/container.hxx
test/Makefile.am
test/serialize.cpp [new file with mode: 0644]

index 4f386ec..55c4cc1 100644 (file)
@@ -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;
index 2bf576b..710a07e 100644 (file)
@@ -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
index ff0e4a6..bc1f77b 100644 (file)
@@ -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 (file)
index 0000000..02f8a6e
--- /dev/null
@@ -0,0 +1,180 @@
+/***************************************************************************
+ *   Copyright (C) 2004 by Intra2net AG                                    *
+ *   info@intra2net.com                                                    *
+ *                                                                         *
+ ***************************************************************************/
+
+#include <sys/types.h>
+#include <unistd.h>
+#include <errno.h>
+#include <signal.h>
+#include <stdio.h>
+
+#include <iostream>
+#include <string>
+#include <sstream>
+#include <stdexcept>
+
+#include <cppunit/extensions/TestFactoryRegistry.h>
+#include <cppunit/ui/text/TestRunner.h>
+#include <cppunit/extensions/HelperMacros.h>
+
+#include <boost/archive/binary_oarchive.hpp>
+#include <boost/archive/binary_iarchive.hpp>
+#include <boost/archive/xml_oarchive.hpp>
+#include <boost/archive/xml_iarchive.hpp>
+#include <boost/serialization/serialization.hpp>
+
+#include <container.hxx>
+#include <socket_client.hxx>
+#include <socket_server.hxx>
+#include <command_client.hxx>
+#include <command_server.hxx>
+
+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<class Archive>
+        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<class Archive>
+        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 <boost/serialization/export.hpp>
+
+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);