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