libt2n: (tomj) made reentrant unit-test more robust. Gave the guard_handle a lot...
[libt2n] / test / reentrant.cpp
... / ...
CommitLineData
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
34using namespace std;
35using namespace CppUnit;
36using namespace libt2n;
37
38namespace
39{
40
41command_server *global_server = NULL;
42
43string testfunc(const string& str)
44{
45 string ret;
46 ret=str+", testfunc() was here";
47
48 // call handle, eventually reentrant
49 if (global_server)
50 global_server->handle(1000);
51
52 return ret;
53}
54
55class testfunc_res : public libt2n::result
56{
57 private:
58 string res;
59
60 friend class boost::serialization::access;
61 template<class Archive>
62 void serialize(Archive & ar, const unsigned int version)
63 {
64 ar & BOOST_SERIALIZATION_BASE_OBJECT_NVP(libt2n::result);
65 ar & BOOST_SERIALIZATION_NVP(res);
66 }
67
68 public:
69 testfunc_res()
70 { }
71
72 testfunc_res(const string& str)
73 {
74 res=str;
75 }
76
77 string get_data()
78 {
79 return res;
80 }
81};
82
83
84class testfunc_cmd : public libt2n::command
85{
86 private:
87 string param;
88
89 friend class boost::serialization::access;
90 template<class Archive>
91 void serialize(Archive & ar, const unsigned int version)
92 {
93 ar & BOOST_SERIALIZATION_BASE_OBJECT_NVP(libt2n::command);
94 ar & BOOST_SERIALIZATION_NVP(param);
95 }
96
97 public:
98 testfunc_cmd()
99 { }
100
101 testfunc_cmd(const string& str)
102 {
103 param=str;
104 }
105
106 libt2n::result* operator()()
107 {
108 return new testfunc_res(testfunc(param));
109 }
110};
111
112}
113
114#include <boost/serialization/export.hpp>
115
116BOOST_CLASS_EXPORT(testfunc_cmd)
117BOOST_CLASS_EXPORT(testfunc_res)
118
119class test_reentrant : public TestFixture
120{
121 CPPUNIT_TEST_SUITE(test_reentrant);
122
123 CPPUNIT_TEST(ReentrantServer);
124
125 CPPUNIT_TEST_SUITE_END();
126
127 pid_t child_pid;
128
129 public:
130
131 void setUp()
132 { }
133
134 void tearDown()
135 { }
136
137 void ReentrantServer()
138 {
139 switch(child_pid=fork())
140 {
141 case -1:
142 {
143 CPPUNIT_FAIL("fork error");
144 break;
145 }
146 case 0:
147 // child
148 {
149 // wait till server is up
150 sleep(3);
151
152 // we want 8 identical childs hammering the server
153 fork();
154 fork();
155 fork();
156
157 for (int i=0; i < 100; i++)
158 {
159 socket_client_connection sc("./socket");
160 command_client cc(&sc);
161
162 result_container rc;
163 cc.send_command(new testfunc_cmd("hello"),rc);
164
165 string ret=dynamic_cast<testfunc_res*>(rc.get_result())->get_data();
166
167 CPPUNIT_ASSERT_EQUAL(string("hello, testfunc() was here"),ret);
168 }
169
170 // don't call atexit and stuff
171 _exit(0);
172 }
173
174 default:
175 // parent
176 {
177 socket_server ss("./socket");
178 command_server cs(ss);
179
180 global_server=&cs;
181
182 // max 10 sec
183 long long maxtime=5000000;
184 while(maxtime > 0)
185 cs.handle(maxtime,&maxtime);
186
187 global_server = NULL;
188 }
189
190 // we are still alive, everything is ok
191 CPPUNIT_ASSERT_EQUAL(1,1);
192 }
193 }
194
195};
196
197
198CPPUNIT_TEST_SUITE_REGISTRATION(test_reentrant);