libt2n: (gerd) make sure no exception is thrown in command_client constructor, fix...
[libt2n] / test / simplecmd.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 testfunc(const string& str)
38 {
39     string ret;
40     if (str=="throw")
41         throw libt2n::t2n_runtime_error("throw me around");
42     if (str=="big")
43         ret.insert(0,100*1024,'x');
44     else
45         ret=str+", testfunc() was here";
46     return ret;
47 }
48
49 class testfunc_res : public libt2n::result
50 {
51     private:
52         string res;
53
54         friend class boost::serialization::access;
55         template<class Archive>
56         void serialize(Archive & ar, const unsigned int version)
57         {
58             ar & BOOST_SERIALIZATION_BASE_OBJECT_NVP(libt2n::result);
59             ar & BOOST_SERIALIZATION_NVP(res);
60         }
61
62     public:
63         testfunc_res()
64             { }
65
66         testfunc_res(const string& str)
67         {
68             res=str;
69         }
70
71         string get_data()
72         {
73             return res;
74         }
75 };
76
77
78 class testfunc_cmd : public libt2n::command
79 {
80     private:
81         string param;
82
83         friend class boost::serialization::access;
84         template<class Archive>
85         void serialize(Archive & ar, const unsigned int version)
86         {
87             ar & BOOST_SERIALIZATION_BASE_OBJECT_NVP(libt2n::command);
88             ar & BOOST_SERIALIZATION_NVP(param);
89         }
90
91     public:
92         testfunc_cmd()
93             { }
94
95         testfunc_cmd(const string& str)
96         {
97             param=str;
98         }
99
100         libt2n::result* operator()()
101         {
102             return new testfunc_res(testfunc(param));
103         }
104 };
105
106 #include <boost/serialization/export.hpp>
107
108 BOOST_CLASS_EXPORT(testfunc_cmd)
109 BOOST_CLASS_EXPORT(testfunc_res)
110
111 using namespace libt2n;
112
113 class test_simplecmd : public TestFixture
114 {
115     CPPUNIT_TEST_SUITE(test_simplecmd);
116
117     CPPUNIT_TEST(SimpleCmd);
118     CPPUNIT_TEST(SimpleException);
119     CPPUNIT_TEST(BigReturn);
120     CPPUNIT_TEST(BigParameter);
121
122     CPPUNIT_TEST_SUITE_END();
123
124     pid_t child_pid;
125
126     public:
127
128     void setUp()
129     { }
130
131     void tearDown()
132     {
133         // make sure the server-child is dead before the next test runs
134         kill(child_pid,SIGKILL);
135         sleep(1);
136     }
137
138     void SimpleCmd()
139     {
140         switch(child_pid=fork())
141         {
142             case -1:
143             {
144                 CPPUNIT_FAIL("fork error");
145                 break;
146             }
147             case 0:
148             // child
149             {
150                 socket_server ss("./socket");
151                 command_server cs(ss);
152
153                 // max 10 sec
154                 for (int i=0; i < 10; i++)
155                     cs.handle(1000000);
156
157                 // don't call atexit and stuff
158                 _exit(0);
159             }
160
161             default:
162             // parent
163             {
164                 // wait till server is up
165                 sleep(1);
166                 socket_client_connection sc("./socket");
167                 sc.set_logging(&cerr,debug);
168                 command_client cc(&sc);
169
170                 result_container rc;
171                 cc.send_command(new testfunc_cmd("hello"),rc);
172
173                 string ret=dynamic_cast<testfunc_res*>(rc.get_result())->get_data();
174
175                 CPPUNIT_ASSERT_EQUAL(string("hello, testfunc() was here"),ret);
176             }
177         }
178     }
179
180     void SimpleException()
181     {
182         switch(child_pid=fork())
183         {
184             case -1:
185             {
186                 CPPUNIT_FAIL("fork error");
187                 break;
188             }
189             case 0:
190             // child
191             {
192                 socket_server ss("./socket");
193                 command_server cs(ss);
194
195                 // max 10 sec
196                 for (int i=0; i < 10; i++)
197                     cs.handle(1000000);
198
199                 // don't call atexit and stuff
200                 _exit(0);
201             }
202
203             default:
204             // parent
205             {
206                 // wait till server is up
207                 sleep(1);
208                 socket_client_connection sc("./socket");
209                 sc.set_logging(&cerr,debug);
210                 command_client cc(&sc);
211
212                 result_container rc;
213                 cc.send_command(new testfunc_cmd("throw"),rc);
214
215                 string ret;
216
217                 try
218                 {
219                     ret=dynamic_cast<testfunc_res*>(rc.get_result())->get_data();
220                 }
221                 catch(t2n_runtime_error &e)
222                     { ret=e.what(); }
223                 catch(...)
224                     { throw; }
225
226                 CPPUNIT_ASSERT_EQUAL(string("throw me around"),ret);
227             }
228         }
229     }
230
231     void BigReturn()
232     {
233         switch(child_pid=fork())
234         {
235             case -1:
236             {
237                 CPPUNIT_FAIL("fork error");
238                 break;
239             }
240             case 0:
241             // child
242             {
243                 socket_server ss("./socket");
244                 command_server cs(ss);
245
246                 // max 10 sec
247                 for (int i=0; i < 10; i++)
248                     cs.handle(1000000);
249
250                 // don't call atexit and stuff
251                 _exit(0);
252             }
253
254             default:
255             // parent
256             {
257                 // wait till server is up
258                 sleep(1);
259                 socket_client_connection sc("./socket");
260                 command_client cc(&sc);
261
262                 result_container rc;
263                 cc.send_command(new testfunc_cmd("big"),rc);
264
265                 string ret=dynamic_cast<testfunc_res*>(rc.get_result())->get_data();
266
267                 CPPUNIT_ASSERT_EQUAL(string().insert(0,100*1024,'x'),ret);
268             }
269         }
270     }
271
272     void BigParameter()
273     {
274         switch(child_pid=fork())
275         {
276             case -1:
277             {
278                 CPPUNIT_FAIL("fork error");
279                 break;
280             }
281             case 0:
282             // child
283             {
284                 socket_server ss("./socket");
285                 command_server cs(ss);
286
287                 // max 10 sec
288                 for (int i=0; i < 10; i++)
289                     cs.handle(1000000);
290
291                 // don't call atexit and stuff
292                 _exit(0);
293             }
294
295             default:
296             // parent
297             {
298                 // wait till server is up
299                 sleep(1);
300                 socket_client_connection sc("./socket");
301                 command_client cc(&sc);
302
303                 result_container rc;
304                 cc.send_command(new testfunc_cmd(string().insert(0,100*1024,'y')),rc);
305
306                 string ret=dynamic_cast<testfunc_res*>(rc.get_result())->get_data();
307
308                 CPPUNIT_ASSERT_EQUAL(string().insert(0,100*1024,'y')+", testfunc() was here",ret);
309             }
310         }
311     }
312
313 };
314
315 CPPUNIT_TEST_SUITE_REGISTRATION(test_simplecmd);