Change license from LGPL to GPL version 2 + linking exception. This fixes C++ templat...
[libt2n] / test / simplecmd.cpp
1 /*
2 Copyright (C) 2004 by Intra2net AG
3
4 The software in this package is distributed under the GNU General
5 Public License version 2 (with a special exception described below).
6
7 A copy of GNU General Public License (GPL) is included in this distribution,
8 in the file COPYING.GPL.
9
10 As a special exception, if other files instantiate templates or use macros
11 or inline functions from this file, or you compile this file and link it
12 with other works to produce a work based on this file, this file
13 does not by itself cause the resulting work to be covered
14 by the GNU General Public License.
15
16 However the source code for this file must still be made available
17 in accordance with section (3) of the GNU General Public License.
18
19 This exception does not invalidate any other reasons why a work based
20 on this file might be covered by the GNU General Public License.
21 */
22 #include <sys/types.h>
23 #include <unistd.h>
24 #include <errno.h>
25 #include <signal.h>
26 #include <stdio.h>
27
28 #include <iostream>
29 #include <string>
30 #include <sstream>
31 #include <stdexcept>
32
33 #include <cppunit/extensions/TestFactoryRegistry.h>
34 #include <cppunit/ui/text/TestRunner.h>
35 #include <cppunit/extensions/HelperMacros.h>
36
37 #include <boost/archive/binary_oarchive.hpp>
38 #include <boost/archive/binary_iarchive.hpp>
39 #include <boost/archive/xml_oarchive.hpp>
40 #include <boost/archive/xml_iarchive.hpp>
41 #include <boost/serialization/serialization.hpp>
42
43 #include <container.hxx>
44 #include <socket_client.hxx>
45 #include <socket_server.hxx>
46 #include <command_client.hxx>
47 #include <command_server.hxx>
48
49 using namespace std;
50 using namespace CppUnit;
51
52 string testfunc(const string& str)
53 {
54     string ret;
55     if (str=="throw")
56         throw libt2n::t2n_runtime_error("throw me around");
57     if (str=="big")
58         ret.insert(0,100*1024,'x');
59     else
60         ret=str+", testfunc() was here";
61     return ret;
62 }
63
64 class testfunc_res : public libt2n::result
65 {
66     private:
67         string res;
68
69         friend class boost::serialization::access;
70         template<class Archive>
71         void serialize(Archive & ar, const unsigned int version)
72         {
73             ar & BOOST_SERIALIZATION_BASE_OBJECT_NVP(libt2n::result);
74             ar & BOOST_SERIALIZATION_NVP(res);
75         }
76
77     public:
78         testfunc_res()
79             { }
80
81         testfunc_res(const string& str)
82         {
83             res=str;
84         }
85
86         string get_data()
87         {
88             return res;
89         }
90 };
91
92
93 class testfunc_cmd : public libt2n::command
94 {
95     private:
96         string param;
97
98         friend class boost::serialization::access;
99         template<class Archive>
100         void serialize(Archive & ar, const unsigned int version)
101         {
102             ar & BOOST_SERIALIZATION_BASE_OBJECT_NVP(libt2n::command);
103             ar & BOOST_SERIALIZATION_NVP(param);
104         }
105
106     public:
107         testfunc_cmd()
108             { }
109
110         testfunc_cmd(const string& str)
111         {
112             param=str;
113         }
114
115         libt2n::result* operator()()
116         {
117             return new testfunc_res(testfunc(param));
118         }
119 };
120
121 #include <boost/serialization/export.hpp>
122
123 BOOST_CLASS_EXPORT(testfunc_cmd)
124 BOOST_CLASS_EXPORT(testfunc_res)
125
126 using namespace libt2n;
127
128 class test_simplecmd : public TestFixture
129 {
130     CPPUNIT_TEST_SUITE(test_simplecmd);
131
132     CPPUNIT_TEST(SimpleCmd);
133     CPPUNIT_TEST(SimpleException);
134     CPPUNIT_TEST(BigReturn);
135     CPPUNIT_TEST(BigParameter);
136
137     CPPUNIT_TEST_SUITE_END();
138
139     pid_t child_pid;
140
141     public:
142
143     void setUp()
144     { }
145
146     void tearDown()
147     {
148         // make sure the server-child is dead before the next test runs
149         kill(child_pid,SIGKILL);
150         sleep(1);
151     }
152
153     void SimpleCmd()
154     {
155         switch(child_pid=fork())
156         {
157             case -1:
158             {
159                 CPPUNIT_FAIL("fork error");
160                 break;
161             }
162             case 0:
163             // child
164             {
165                 try
166                 {
167                     socket_server ss("./socket");
168                     command_server cs(ss);
169
170                     // max 10 sec
171                     for (int i=0; i < 10; i++)
172                         cs.handle(1000000);
173                 } catch(...)
174                 {
175                     std::cerr << "exception in child. ignoring\n";
176                 }
177
178                 // don't call atexit and stuff
179                 _exit(0);
180             }
181
182             default:
183             // parent
184             {
185                 // wait till server is up
186                 sleep(1);
187                 socket_client_connection sc("./socket");
188                 sc.set_logging(&cerr,debug);
189                 command_client cc(&sc);
190
191                 result_container rc;
192                 cc.send_command(new testfunc_cmd("hello"),rc);
193
194                 string ret=dynamic_cast<testfunc_res*>(rc.get_result())->get_data();
195
196                 CPPUNIT_ASSERT_EQUAL(string("hello, testfunc() was here"),ret);
197             }
198         }
199     }
200
201     void SimpleException()
202     {
203         switch(child_pid=fork())
204         {
205             case -1:
206             {
207                 CPPUNIT_FAIL("fork error");
208                 break;
209             }
210             case 0:
211             // child
212             {
213                 try
214                 {
215                     socket_server ss("./socket");
216                     command_server cs(ss);
217
218                     // max 10 sec
219                     for (int i=0; i < 10; i++)
220                         cs.handle(1000000);
221                 } catch(...)
222                 {
223                     std::cerr << "exception in child. ignoring\n";
224                 }
225
226                 // don't call atexit and stuff
227                 _exit(0);
228             }
229
230             default:
231             // parent
232             {
233                 // wait till server is up
234                 sleep(1);
235                 socket_client_connection sc("./socket");
236                 sc.set_logging(&cerr,debug);
237                 command_client cc(&sc);
238
239                 result_container rc;
240                 cc.send_command(new testfunc_cmd("throw"),rc);
241
242                 string ret;
243
244                 try
245                 {
246                     ret=dynamic_cast<testfunc_res*>(rc.get_result())->get_data();
247                 }
248                 catch(t2n_runtime_error &e)
249                     { ret=e.what(); }
250                 catch(...)
251                     { throw; }
252
253                 CPPUNIT_ASSERT_EQUAL(string("throw me around"),ret);
254             }
255         }
256     }
257
258     void BigReturn()
259     {
260         switch(child_pid=fork())
261         {
262             case -1:
263             {
264                 CPPUNIT_FAIL("fork error");
265                 break;
266             }
267             case 0:
268             // child
269             {
270                 try
271                 {
272                     socket_server ss("./socket");
273                     command_server cs(ss);
274
275                     // max 10 sec
276                     for (int i=0; i < 10; i++)
277                         cs.handle(1000000);
278                 } catch(...)
279                 {
280                     std::cerr << "exception in child. ignoring\n";
281                 }
282
283                 // don't call atexit and stuff
284                 _exit(0);
285             }
286
287             default:
288             // parent
289             {
290                 // wait till server is up
291                 sleep(1);
292                 socket_client_connection sc("./socket");
293                 command_client cc(&sc);
294
295                 result_container rc;
296                 cc.send_command(new testfunc_cmd("big"),rc);
297
298                 string ret=dynamic_cast<testfunc_res*>(rc.get_result())->get_data();
299
300                 CPPUNIT_ASSERT_EQUAL(string().insert(0,100*1024,'x'),ret);
301             }
302         }
303     }
304
305     void BigParameter()
306     {
307         switch(child_pid=fork())
308         {
309             case -1:
310             {
311                 CPPUNIT_FAIL("fork error");
312                 break;
313             }
314             case 0:
315             // child
316             {
317                 try
318                 {
319                     socket_server ss("./socket");
320                     command_server cs(ss);
321
322                     // max 60 sec - we need atleast 28 handle calls to transfer the buffer
323                     for (int i=0; i < 60; i++) {
324                         cs.handle(1000000);
325                 }
326                 } catch(...)
327                 {
328                     std::cerr << "exception in child. ignoring\n";
329                 }
330
331                 // don't call atexit and stuff
332                 _exit(0);
333             }
334
335             default:
336             // parent
337             {
338                 // wait till server is up
339                 sleep(1);
340                 socket_client_connection sc("./socket");
341                 command_client cc(&sc);
342
343                 result_container rc;
344                 cc.send_command(new testfunc_cmd(string().insert(0,100*1024,'y')),rc);
345
346                 string ret=dynamic_cast<testfunc_res*>(rc.get_result())->get_data();
347
348                 CPPUNIT_ASSERT_EQUAL(string().insert(0,100*1024,'y')+", testfunc() was here",ret);
349             }
350         }
351     }
352
353 };
354
355 CPPUNIT_TEST_SUITE_REGISTRATION(test_simplecmd);