commit changes to build
[libt2n] / test / timeout.cpp
CommitLineData
45a2ebc9
GE
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 <boost/bind.hpp>
19
20#include <cppunit/extensions/TestFactoryRegistry.h>
21#include <cppunit/ui/text/TestRunner.h>
22#include <cppunit/extensions/HelperMacros.h>
23
24#include <boost/archive/binary_oarchive.hpp>
25#include <boost/archive/binary_iarchive.hpp>
26#include <boost/archive/xml_oarchive.hpp>
27#include <boost/archive/xml_iarchive.hpp>
28#include <boost/serialization/serialization.hpp>
29
30#include <container.hxx>
31#include <socket_client.hxx>
32#include <socket_server.hxx>
33#include <command_client.hxx>
34#include <command_server.hxx>
35
36#ifdef HAVE_CONFIG_H
37#include <config.h>
38#endif
39
40using namespace std;
41using namespace libt2n;
42using namespace CppUnit;
43
44string testfunc2(const string& str)
45{
46 if (str=="throw")
47 throw libt2n::t2n_runtime_error("throw me around");
48 string ret(str);
49 ret+=", testfunc() was here";
50 return ret;
51}
52
53class testfunc2_res : public libt2n::result
54{
55 private:
56 string res;
57
58 friend class boost::serialization::access;
59 template<class Archive>
60 void serialize(Archive & ar, const unsigned int version)
61 {
62 ar & BOOST_SERIALIZATION_BASE_OBJECT_NVP(libt2n::result);
63 ar & BOOST_SERIALIZATION_NVP(res);
64 }
65
66 public:
67 testfunc2_res()
68 { }
69
70 testfunc2_res(const string& str)
71 {
72 res=str;
73 }
74
75 string get_data()
76 {
77 return res;
78 }
79};
80
81
82class testfunc2_cmd : public libt2n::command
83{
84 private:
85 string param;
86
87 friend class boost::serialization::access;
88 template<class Archive>
89 void serialize(Archive & ar, const unsigned int version)
90 {
91 ar & BOOST_SERIALIZATION_BASE_OBJECT_NVP(libt2n::command);
92 ar & BOOST_SERIALIZATION_NVP(param);
93 }
94
95 public:
96 testfunc2_cmd()
97 { }
98
99 testfunc2_cmd(const string& str)
100 {
101 param=str;
102 }
103
104 libt2n::result* operator()()
105 {
106 return new testfunc2_res(testfunc2(param));
107 }
108};
109
110#include <boost/serialization/export.hpp>
111
112BOOST_CLASS_EXPORT(testfunc2_cmd)
113BOOST_CLASS_EXPORT(testfunc2_res)
114
115// this is an evil hack to get access to real_write, don't ever do this in an app!!!
116class real_write_connection: public socket_server_connection
117{
118 public:
119 void real_write(const std::string& data)
120 { socket_write(data); }
121};
122
123class test_timeout : public TestFixture
124{
125 CPPUNIT_TEST_SUITE(test_timeout);
126
127 CPPUNIT_TEST(HelloTimeoutNothing);
128 CPPUNIT_TEST(HelloTimeoutSlowData);
129 CPPUNIT_TEST(CommandTimeout);
130 CPPUNIT_TEST(CommandSlowResponse);
131
132 CPPUNIT_TEST_SUITE_END();
133
134 public:
135
136 typedef uint32_t packet_size_indicator;
137
138 void setUp()
139 { }
140
141 void tearDown()
142 { }
143
144 void send_hello(string hello_string, socket_server* ss, unsigned int conn_id)
145 {
146 server_connection *sc=ss->get_connection(conn_id);
147 sc->write(hello_string);
148 }
149
150 void send_slow_raw_socket(string data, socket_server* ss, unsigned int conn_id)
151 {
152 socket_server_connection *ssc=dynamic_cast<socket_server_connection*>(ss->get_connection(conn_id));
153
154 // this is an evil hack to get access to real_write, don't ever do this in an app!!!
155 real_write_connection *rwc=(real_write_connection*)ssc;
156
157 // we write one char each 0.2 sec
158 for (int pos=0; pos < data.size(); pos++)
159 {
160 string onebyte;
161 onebyte+=data[pos];
162 rwc->real_write(onebyte);
163 usleep(200000);
164 }
165 }
166
167 void HelloTimeoutNothing()
168 {
169 pid_t pid;
170
171 switch(pid=fork())
172 {
173 case -1:
174 {
175 CPPUNIT_FAIL("fork error");
176 break;
177 }
178 case 0:
179 // child
180 {
181 socket_server ss("./socket");
182
183 // max 10 sec
184 for (int i=0; i < 10; i++)
185 ss.fill_buffer(1000000);
186 // don't call atexit and stuff
187 _exit(0);
188 }
189
190 default:
191 // parent
192 {
193 string data;
194
195 // wait till server is up
196 sleep(1);
197 socket_client_connection sc("./socket");
198
199 string errormsg;
200
201 try
202 {
203 command_client cc(sc,1000000,1000000);
204 }
205 catch(t2n_transfer_error &e)
206 { errormsg=e.what(); }
207 catch(...)
208 { throw; }
209
210 CPPUNIT_ASSERT_EQUAL(string("timeout exceeded"),errormsg);
211 }
212 }
213 }
214
215 void HelloTimeoutSlowData()
216 {
217 pid_t pid;
218
219 switch(pid=fork())
220 {
221 case -1:
222 {
223 CPPUNIT_FAIL("fork error");
224 break;
225 }
226 case 0:
227 // child
228 {
229 socket_server ss("./socket");
230
231 // create a valid packet
232 ostringstream hello;
233 hello << "T2Nv" << PROTOCOL_VERSION << ';';
234 int byteordercheck=1;
235 hello.write((char*)&byteordercheck,sizeof(byteordercheck));
236 hello << ';';
237
238 packet_size_indicator psize=htonl(hello.str().size());
239 std::string send_data(hello.str());
240 send_data.insert(0,(char*)&psize,sizeof(packet_size_indicator));
241
242 ss.add_callback(new_connection,bind(&test_timeout::send_slow_raw_socket, boost::ref(*this), send_data,&ss, _1));
243
244 // max 10 sec
245 for (int i=0; i < 10; i++)
246 ss.fill_buffer(1000000);
247 // don't call atexit and stuff
248 _exit(0);
249 }
250
251 default:
252 // parent
253 {
254 string data;
255
256 // wait till server is up
257 sleep(1);
258 socket_client_connection sc("./socket");
259
260 string errormsg;
261
262 try
263 {
264 command_client cc(sc,1000000,1000000);
265 }
266 catch(t2n_transfer_error &e)
267 { errormsg=e.what(); }
268 catch(...)
269 { throw; }
270
271 CPPUNIT_ASSERT_EQUAL(string("timeout exceeded"),errormsg);
272 }
273 }
274 }
275
276 void CommandTimeout()
277 {
278 pid_t pid;
279
280 switch(pid=fork())
281 {
282 case -1:
283 {
284 CPPUNIT_FAIL("fork error");
285 break;
286 }
287 case 0:
288 // child
289 {
290 socket_server ss("./socket");
291
292 ostringstream hello;
293 hello << "T2Nv" << PROTOCOL_VERSION << ';';
294 int byteordercheck=1;
295 hello.write((char*)&byteordercheck,sizeof(byteordercheck));
296 hello << ';';
297
298 ss.add_callback(new_connection,bind(&test_timeout::send_hello, boost::ref(*this), hello.str(),&ss, _1));
299
300 // max 10 sec
301 for (int i=0; i < 10; i++)
302 ss.fill_buffer(1000000);
303 // don't call atexit and stuff
304 _exit(0);
305 }
306
307 default:
308 // parent
309 {
310 string data;
311
312 // wait till server is up
313 sleep(1);
314 socket_client_connection sc("./socket");
315
316 command_client cc(sc,1000000,1000000);
317 result_container rc;
318
319 string errormsg;
320
321 try
322 {
323 cc.send_command(new testfunc2_cmd("hello"),rc);
324 }
325 catch(t2n_transfer_error &e)
326 { errormsg=e.what(); }
327 catch(...)
328 { throw; }
329
330 CPPUNIT_ASSERT_EQUAL(string("timeout exceeded"),errormsg);
331 }
332 }
333 }
334
335 void CommandSlowResponse()
336 {
337 pid_t pid;
338
339 switch(pid=fork())
340 {
341 case -1:
342 {
343 CPPUNIT_FAIL("fork error");
344 break;
345 }
346 case 0:
347 // child
348 {
349 socket_server ss("./socket");
350
351 ostringstream hello;
352 hello << "T2Nv" << PROTOCOL_VERSION << ';';
353 int byteordercheck=1;
354 hello.write((char*)&byteordercheck,sizeof(byteordercheck));
355 hello << ';';
356
357 ss.add_callback(new_connection,bind(&test_timeout::send_hello, boost::ref(*this), hello.str(),&ss, _1));
358
359 // max 10 sec
360 for (int i=0; i < 10; i++)
361 {
362 ss.fill_buffer(1000000);
363
364 string data;
365 unsigned int cid;
366
367 if(ss.get_packet(data,cid))
368 {
369 // create a valid packet & send
370 string response="abcdefghijklmnopqrstuvwxyz";
371 packet_size_indicator psize=htonl(response.size());
372 std::string send_data(response);
373 send_data.insert(0,(char*)&psize,sizeof(packet_size_indicator));
374 send_slow_raw_socket(send_data,&ss,cid);
375 }
376 }
377 // don't call atexit and stuff
378 _exit(0);
379 }
380
381 default:
382 // parent
383 {
384 string data;
385
386 // wait till server is up
387 sleep(1);
388 socket_client_connection sc("./socket");
389
390 command_client cc(sc,1000000,1000000);
391 result_container rc;
392
393 string errormsg;
394
395 try
396 {
397 cc.send_command(new testfunc2_cmd("hello"),rc);
398 }
399 catch(t2n_transfer_error &e)
400 { errormsg=e.what(); }
401 catch(...)
402 { throw; }
403
404 CPPUNIT_ASSERT_EQUAL(string("timeout exceeded"),errormsg);
405 }
406 }
407 }
408
409};
410
411CPPUNIT_TEST_SUITE_REGISTRATION(test_timeout);