libt2n: (tomj) added exception handling to every child after fork(). This is needed...
[libt2n] / test / serialize.cpp
1 /***************************************************************************
2  *   Copyright (C) 2004 by Intra2net AG                                    *
3  *   info@intra2net.com                                                    *
4  *                                                                         *
5  ***************************************************************************/
6
7 #include <sys/types.h>
8 #include <unistd.h>
9 #include <errno.h>
10 #include <signal.h>
11 #include <stdio.h>
12
13 #include <iostream>
14 #include <string>
15 #include <sstream>
16 #include <stdexcept>
17
18 #include <cppunit/extensions/TestFactoryRegistry.h>
19 #include <cppunit/ui/text/TestRunner.h>
20 #include <cppunit/extensions/HelperMacros.h>
21
22 #include <boost/archive/binary_oarchive.hpp>
23 #include <boost/archive/binary_iarchive.hpp>
24 #include <boost/archive/xml_oarchive.hpp>
25 #include <boost/archive/xml_iarchive.hpp>
26 #include <boost/serialization/serialization.hpp>
27
28 #include <container.hxx>
29 #include <socket_client.hxx>
30 #include <socket_server.hxx>
31 #include <command_client.hxx>
32 #include <command_server.hxx>
33
34 using namespace std;
35 using namespace CppUnit;
36
37 string testfunc3(const string& str)
38 {
39     if (str=="throw")
40         throw libt2n::t2n_runtime_error("throw me around");
41     string ret(str);
42     ret+=", testfunc() was here";
43     return ret;
44 }
45
46 class testfunc3_res : public libt2n::result
47 {
48     private:
49         string res;
50
51         friend class boost::serialization::access;
52         template<class Archive>
53         void serialize(Archive & ar, const unsigned int version)
54         {
55             ar & BOOST_SERIALIZATION_BASE_OBJECT_NVP(libt2n::result);
56             ar & BOOST_SERIALIZATION_NVP(res);
57         }
58
59     public:
60         testfunc3_res()
61             { }
62
63         testfunc3_res(const string& str)
64         {
65             res=str;
66         }
67
68         string get_data()
69         {
70             return res;
71         }
72 };
73
74
75 class testfunc3_cmd : public libt2n::command
76 {
77     private:
78         string param;
79
80         friend class boost::serialization::access;
81         template<class Archive>
82         void serialize(Archive & ar, const unsigned int version)
83         {
84             ar & BOOST_SERIALIZATION_BASE_OBJECT_NVP(libt2n::command);
85             ar & BOOST_SERIALIZATION_NVP(param);
86         }
87
88     public:
89         testfunc3_cmd()
90             { }
91
92         testfunc3_cmd(const string& str)
93         {
94             param=str;
95         }
96
97         libt2n::result* operator()()
98         {
99             return new testfunc3_res(testfunc3(param));
100         }
101 };
102
103 #include <boost/serialization/export.hpp>
104
105 using namespace libt2n;
106
107 class test_serialize : public TestFixture
108 {
109     CPPUNIT_TEST_SUITE(test_serialize);
110
111     CPPUNIT_TEST(ClientSerializeErr);
112
113     // TODO: Server Deserialization Error
114     // TODO: Server Serialization Error
115     // TODO: Client Deserialization Error
116     // but those probably need separate client/server binaries
117
118     CPPUNIT_TEST_SUITE_END();
119
120     pid_t child_pid;
121
122     public:
123
124     void setUp()
125     {
126     }
127
128     void tearDown()
129     {
130         // make sure the server-child is dead before the next test runs
131         kill(child_pid,SIGKILL);
132         sleep(1);
133     }
134
135     void ClientSerializeErr()
136     {
137         switch(child_pid=fork())
138         {
139             case -1:
140             {
141                 CPPUNIT_FAIL("fork error");
142                 break;
143             }
144             case 0:
145             // child
146             {
147                 try
148                 {
149                     socket_server ss("./socket");
150                     command_server cs(ss);
151
152                     // max 10 sec
153                     for (int i=0; i < 10; i++)
154                         cs.handle(1000000);
155                 } catch(...)
156                 {
157                     std::cerr << "exception in child. ignoring\n";
158                 }
159
160                 // don't call atexit and stuff
161                 _exit(0);
162             }
163
164             default:
165             // parent
166             {
167                 // wait till server is up
168                 sleep(1);
169                 socket_client_connection sc("./socket");
170                 command_client cc(&sc);
171
172                 string errormsg;
173
174                 result_container rc;
175                 try
176                 {
177                     cc.send_command(new testfunc3_cmd("xyz"),rc);
178                 }
179                 catch(t2n_serialization_error &e)
180                     { errormsg=e.what(); }
181                 catch(...)
182                     { throw; }
183
184                 CPPUNIT_ASSERT_EQUAL(string("archive_exception while serializing on client-side, code 2 (unregistered class)"),errormsg);
185             }
186         }
187     }
188
189 };
190
191 CPPUNIT_TEST_SUITE_REGISTRATION(test_serialize);