Change license from LGPL to GPL version 2 + linking exception. This fixes C++ templat...
[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 #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 #include <boost/serialization/export.hpp>
43
44 #include <container.hxx>
45 #include <socket_client.hxx>
46 #include <socket_server.hxx>
47 #include <command_client.hxx>
48 #include <command_server.hxx>
49
50 using namespace std;
51 using namespace CppUnit;
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 class test_cmdgroup : public TestFixture
177 {
178     CPPUNIT_TEST_SUITE(test_cmdgroup);
179
180     CPPUNIT_TEST(GroupOk);
181     CPPUNIT_TEST(WrongGroup);
182
183     CPPUNIT_TEST_SUITE_END();
184
185     pid_t child_pid;
186
187     public:
188
189     void setUp()
190     { }
191
192     void tearDown()
193     {
194         // make sure the server-child is dead before the next test runs
195         kill(child_pid,SIGKILL);
196         sleep(1);
197     }
198
199     void GroupOk()
200     {
201         switch(child_pid=fork())
202         {
203             case -1:
204             {
205                 CPPUNIT_FAIL("fork error");
206                 break;
207             }
208             case 0:
209             // child
210             {
211                 try
212                 {
213                     socket_server ss("./socket");
214                     group_command_server<cmd_group_a> cs(ss);
215
216                     // max 10 sec
217                     for (int i=0; i < 10; i++)
218                         cs.handle(1000000);
219                 } catch(...)
220                 {
221                     std::cerr << "exception in child. ignoring\n";
222                 }
223
224                 // don't call atexit and stuff
225                 _exit(0);
226             }
227
228             default:
229             // parent
230             {
231                 // wait till server is up
232                 sleep(1);
233                 socket_client_connection sc("./socket");
234                 command_client cc(&sc);
235
236                 result_container rc;
237                 cc.send_command(new testfunc4a_cmd("hello"),rc);
238
239                 string ret=dynamic_cast<testfunc4_res*>(rc.get_result())->get_data();
240
241                 CPPUNIT_ASSERT_EQUAL(string("hello, testfunc() was here"),ret);
242             }
243         }
244     }
245
246     void WrongGroup()
247     {
248         switch(child_pid=fork())
249         {
250             case -1:
251             {
252                 CPPUNIT_FAIL("fork error");
253                 break;
254             }
255             case 0:
256             // child
257             {
258                 try
259                 {
260                     socket_server ss("./socket");
261                     group_command_server<cmd_group_b> cs(ss);
262
263                     // max 10 sec
264                     for (int i=0; i < 10; i++)
265                         cs.handle(1000000);
266                 } catch(...)
267                 {
268                     std::cerr << "exception in child. ignoring\n";
269                 }
270
271                 // don't call atexit and stuff
272                 _exit(0);
273             }
274
275             default:
276             // parent
277             {
278                 // wait till server is up
279                 sleep(1);
280                 socket_client_connection sc("./socket");
281                 command_client cc(&sc);
282
283                 result_container rc;
284                 cc.send_command(new testfunc4a_cmd("hello"),rc);
285
286                 string ret;
287
288                 try
289                 {
290                     ret=dynamic_cast<testfunc4_res*>(rc.get_result())->get_data();
291                 }
292                 catch(t2n_command_error &e)
293                     { ret=e.what(); }
294                 catch(...)
295                     { throw; }
296
297                 string expected_what="illegal command of type ";
298
299                 CPPUNIT_ASSERT_EQUAL(expected_what,ret.substr(0,expected_what.size()));
300             }
301         }
302     }
303
304 };
305
306 CPPUNIT_TEST_SUITE_REGISTRATION(test_cmdgroup);