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