99c720fd8eaf95e396c7b28ac18626b9750e3927
[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                 try
151                 {
152                     socket_server ss("./socket");
153                     command_server cs(ss);
154
155                     // max 10 sec
156                     for (int i=0; i < 10; i++)
157                         cs.handle(1000000);
158                 } catch(...)
159                 {
160                     std::cerr << "exception in child. ignoring\n";
161                 }
162
163                 // don't call atexit and stuff
164                 _exit(0);
165             }
166
167             default:
168             // parent
169             {
170                 // wait till server is up
171                 sleep(1);
172                 socket_client_connection sc("./socket");
173                 sc.set_logging(&cerr,debug);
174                 command_client cc(&sc);
175
176                 result_container rc;
177                 cc.send_command(new testfunc_cmd("hello"),rc);
178
179                 string ret=dynamic_cast<testfunc_res*>(rc.get_result())->get_data();
180
181                 CPPUNIT_ASSERT_EQUAL(string("hello, testfunc() was here"),ret);
182             }
183         }
184     }
185
186     void SimpleException()
187     {
188         switch(child_pid=fork())
189         {
190             case -1:
191             {
192                 CPPUNIT_FAIL("fork error");
193                 break;
194             }
195             case 0:
196             // child
197             {
198                 try
199                 {
200                     socket_server ss("./socket");
201                     command_server cs(ss);
202
203                     // max 10 sec
204                     for (int i=0; i < 10; i++)
205                         cs.handle(1000000);
206                 } catch(...)
207                 {
208                     std::cerr << "exception in child. ignoring\n";
209                 }
210
211                 // don't call atexit and stuff
212                 _exit(0);
213             }
214
215             default:
216             // parent
217             {
218                 // wait till server is up
219                 sleep(1);
220                 socket_client_connection sc("./socket");
221                 sc.set_logging(&cerr,debug);
222                 command_client cc(&sc);
223
224                 result_container rc;
225                 cc.send_command(new testfunc_cmd("throw"),rc);
226
227                 string ret;
228
229                 try
230                 {
231                     ret=dynamic_cast<testfunc_res*>(rc.get_result())->get_data();
232                 }
233                 catch(t2n_runtime_error &e)
234                     { ret=e.what(); }
235                 catch(...)
236                     { throw; }
237
238                 CPPUNIT_ASSERT_EQUAL(string("throw me around"),ret);
239             }
240         }
241     }
242
243     void BigReturn()
244     {
245         switch(child_pid=fork())
246         {
247             case -1:
248             {
249                 CPPUNIT_FAIL("fork error");
250                 break;
251             }
252             case 0:
253             // child
254             {
255                 try
256                 {
257                     socket_server ss("./socket");
258                     command_server cs(ss);
259
260                     // max 10 sec
261                     for (int i=0; i < 10; i++)
262                         cs.handle(1000000);
263                 } catch(...)
264                 {
265                     std::cerr << "exception in child. ignoring\n";
266                 }
267
268                 // don't call atexit and stuff
269                 _exit(0);
270             }
271
272             default:
273             // parent
274             {
275                 // wait till server is up
276                 sleep(1);
277                 socket_client_connection sc("./socket");
278                 command_client cc(&sc);
279
280                 result_container rc;
281                 cc.send_command(new testfunc_cmd("big"),rc);
282
283                 string ret=dynamic_cast<testfunc_res*>(rc.get_result())->get_data();
284
285                 CPPUNIT_ASSERT_EQUAL(string().insert(0,100*1024,'x'),ret);
286             }
287         }
288     }
289
290     void BigParameter()
291     {
292         switch(child_pid=fork())
293         {
294             case -1:
295             {
296                 CPPUNIT_FAIL("fork error");
297                 break;
298             }
299             case 0:
300             // child
301             {
302                 try
303                 {
304                     socket_server ss("./socket");
305                     command_server cs(ss);
306
307                     // max 60 sec - we need atleast 28 handle calls to transfer the buffer
308                     for (int i=0; i < 60; i++) {
309                         cs.handle(1000000);
310                 }
311                 } catch(...)
312                 {
313                     std::cerr << "exception in child. ignoring\n";
314                 }
315
316                 // don't call atexit and stuff
317                 _exit(0);
318             }
319
320             default:
321             // parent
322             {
323                 // wait till server is up
324                 sleep(1);
325                 socket_client_connection sc("./socket");
326                 command_client cc(&sc);
327
328                 result_container rc;
329                 cc.send_command(new testfunc_cmd(string().insert(0,100*1024,'y')),rc);
330
331                 string ret=dynamic_cast<testfunc_res*>(rc.get_result())->get_data();
332
333                 CPPUNIT_ASSERT_EQUAL(string().insert(0,100*1024,'y')+", testfunc() was here",ret);
334             }
335         }
336     }
337
338 };
339
340 CPPUNIT_TEST_SUITE_REGISTRATION(test_simplecmd);