2 Copyright (C) 2004 by Intra2net AG
4 The software in this package is distributed under the GNU General
5 Public License version 2 (with a special exception described below).
7 A copy of GNU General Public License (GPL) is included in this distribution,
8 in the file COPYING.GPL.
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.
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.
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.
22 #include <sys/types.h>
33 #define BOOST_TEST_DYN_LINK
34 #include <boost/test/unit_test.hpp>
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>
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 #include <client_wrapper.hxx>
49 #include <socket_wrapper.hxx>
51 #include "test_fixtures.hxx"
58 using namespace libt2n;
62 stringstream logstream;
63 bool close_server=false;
64 bool kill_server=false;
77 std::string getserverlog(void)
79 return logstream.str();
82 class serverfunc_res : public libt2n::result
87 friend class boost::serialization::access;
88 template<class Archive>
89 void serialize(Archive & ar, const unsigned int version)
91 ar & BOOST_SERIALIZATION_BASE_OBJECT_NVP(libt2n::result);
92 ar & BOOST_SERIALIZATION_NVP(res);
110 class getserverlog_res : public libt2n::result
115 friend class boost::serialization::access;
116 template<class Archive>
117 void serialize(Archive & ar, const unsigned int version)
119 ar & BOOST_SERIALIZATION_BASE_OBJECT_NVP(libt2n::result);
120 ar & BOOST_SERIALIZATION_NVP(res);
127 getserverlog_res(std::string s)
132 std::string get_data()
138 class cmd_group_x : public command
141 friend class boost::serialization::access;
142 template<class Archive>
143 void serialize(Archive & ar, const unsigned int version)
145 ar & BOOST_SERIALIZATION_BASE_OBJECT_NVP(libt2n::command);
149 class serverfunc_cmd : public cmd_group_x
154 friend class boost::serialization::access;
155 template<class Archive>
156 void serialize(Archive & ar, const unsigned int version)
158 ar & BOOST_SERIALIZATION_BASE_OBJECT_NVP(cmd_group_x);
159 ar & BOOST_SERIALIZATION_NVP(param);
166 serverfunc_cmd(int i)
171 libt2n::result* operator()()
173 return new serverfunc_res(serverfunc(param));
177 class getserverlog_cmd : public cmd_group_x
180 friend class boost::serialization::access;
181 template<class Archive>
182 void serialize(Archive & ar, const unsigned int version)
184 ar & BOOST_SERIALIZATION_BASE_OBJECT_NVP(cmd_group_x);
191 libt2n::result* operator()()
193 return new getserverlog_res(getserverlog());
197 BOOST_CLASS_EXPORT(serverfunc_res)
198 BOOST_CLASS_EXPORT(getserverlog_res)
199 BOOST_CLASS_EXPORT(cmd_group_x)
200 BOOST_CLASS_EXPORT(serverfunc_cmd)
201 BOOST_CLASS_EXPORT(getserverlog_cmd)
203 class cmd_group_x_client : public command_client
206 cmd_group_x_client(libt2n::client_connection *_c,
207 long long _command_timeout_usec=command_timeout_usec_default,
208 long long _hello_timeout_usec=hello_timeout_usec_default)
209 : libt2n::command_client(_c,_command_timeout_usec,_hello_timeout_usec)
212 int serverfunc(int i)
214 libt2n::result_container rc;
216 send_command(new serverfunc_cmd(i), rc);
217 serverfunc_res* res=dynamic_cast<serverfunc_res*>(rc.get_result());
218 if (!res) throw libt2n::t2n_communication_error("result object of wrong type");
219 return res->get_data();
222 std::string getserverlog(void)
224 libt2n::result_container rc;
226 send_command(new getserverlog_cmd(), rc);
227 getserverlog_res* res=dynamic_cast<getserverlog_res*>(rc.get_result());
228 if (!res) throw libt2n::t2n_communication_error("result object of wrong type");
229 return res->get_data();
233 typedef T2nSingletonWrapper<cmd_group_x_client> wraptype;
236 std::auto_ptr<wraptype> wraptype::SingletonObject = std::auto_ptr<wraptype>();
239 std::auto_ptr<ConnectionWrapper> wraptype::WrappedConnection = std::auto_ptr<ConnectionWrapper>();
242 class test_wrapperFixture : public KillChildOnShutdownFixture
245 test_wrapperFixture()
250 switch(child_pid=fork())
254 BOOST_FAIL("fork error");
263 while(i < 10 && !kill_server)
267 socket_server ss("./socket");
268 group_command_server<cmd_group_x> cs(ss);
269 ss.set_logging(&logstream,debug);
272 for (; !close_server && !kill_server && i < 10; i++)
277 std::cerr << "exception in child. ignoring\n";
280 // don't call atexit and stuff
287 // don't kill us on broken pipe
288 signal(SIGPIPE, SIG_IGN);
290 // wait till server is up
296 ~test_wrapperFixture()
301 BOOST_FIXTURE_TEST_SUITE(test_wrapper, test_wrapperFixture)
303 BOOST_AUTO_TEST_CASE(no_init_exception) // must be called first!
305 BOOST_REQUIRE_THROW(t2n_exec(&cmd_group_x_client::serverfunc)(1),std::logic_error);
308 BOOST_AUTO_TEST_CASE(simple_wrap)
310 wraptype::set_connection(auto_ptr<ConnectionWrapper>
311 (new BasicSocketWrapper("./socket")));
313 int i=t2n_exec(&cmd_group_x_client::serverfunc)(1);
315 BOOST_CHECK_EQUAL(2,i);
318 BOOST_AUTO_TEST_CASE(double_use)
320 // only one connection used?
321 wraptype::set_connection(auto_ptr<ConnectionWrapper>
322 (new BasicSocketWrapper("./socket")));
324 t2n_exec(&cmd_group_x_client::serverfunc)(17);
325 string out=t2n_exec(&cmd_group_x_client::getserverlog)();
327 // count the number of times that "new connection accepted" appears in the server log
328 string::size_type p=0;
330 while ((p=out.find("new connection accepted",p))++ != string::npos)
333 BOOST_CHECK_EQUAL(1,cnt);
336 BOOST_AUTO_TEST_CASE(double_use_with_close)
338 wraptype::set_connection(auto_ptr<ConnectionWrapper>
339 (new BasicSocketWrapper("./socket")));
341 t2n_exec(&cmd_group_x_client::serverfunc)(17);
343 // closes the connection from the client side
344 wraptype::set_connection(auto_ptr<ConnectionWrapper>
345 (new BasicSocketWrapper("./socket")));
347 string out=t2n_exec(&cmd_group_x_client::getserverlog)();
349 // count the number of times that "new connection accepted" appears in the server log
350 string::size_type p=0;
352 while ((p=out.find("new connection accepted",p))++ != string::npos)
355 BOOST_CHECK_EQUAL(2,cnt);
358 BOOST_AUTO_TEST_CASE(reconnect_after_close)
360 wraptype::set_connection(auto_ptr<ConnectionWrapper>
361 (new ReconnectSocketWrapper("./socket")));
363 wraptype::get_connection_wrapper()->set_command_timeout_usec(3000000);
364 wraptype::get_connection_wrapper()->set_hello_timeout_usec(3000000);
366 // 42 closes connection on the server side
367 t2n_exec(&cmd_group_x_client::serverfunc)(42);
369 string out=t2n_exec(&cmd_group_x_client::getserverlog)();
371 // count the number of times that "new connection accepted" appears in the server log
372 string::size_type p=0;
374 while ((p=out.find("new connection accepted",p))++ != string::npos)
377 BOOST_CHECK_EQUAL(2,cnt);
380 BOOST_AUTO_TEST_CASE(reconnect_not_possible)
382 wraptype::set_connection(auto_ptr<ConnectionWrapper>
383 (new ReconnectSocketWrapper("./socket")));
385 // the server doens't like the beast
386 t2n_exec(&cmd_group_x_client::serverfunc)(666);
388 BOOST_REQUIRE_THROW(t2n_exec(&cmd_group_x_client::serverfunc)(1),t2n_communication_error);
391 BOOST_AUTO_TEST_CASE(ignore_server_disconnect)
393 wraptype::set_connection(auto_ptr<ConnectionWrapper>
394 (new ReconnectIgnoreFailureSocketWrapper("./socket")));
396 // the server doens't like the beast
397 t2n_exec(&cmd_group_x_client::serverfunc)(666);
399 int i=t2n_exec(&cmd_group_x_client::serverfunc)(1);
401 // result is constructed with default constructor on error-and-ignore -> i=0
403 BOOST_CHECK_EQUAL(0,i);
406 BOOST_AUTO_TEST_CASE(ignore_handler_reconnects)
408 wraptype::set_connection(auto_ptr<ConnectionWrapper>
409 (new ReconnectIgnoreFailureSocketWrapper("./socket")));
411 wraptype::get_connection_wrapper()->set_command_timeout_usec(3000000);
412 wraptype::get_connection_wrapper()->set_hello_timeout_usec(3000000);
414 // 42 closes connection on the server side
415 t2n_exec(&cmd_group_x_client::serverfunc)(42);
417 string out=t2n_exec(&cmd_group_x_client::getserverlog)();
419 // count the number of times that "new connection accepted" appears in the server log
420 string::size_type p=0;
422 while ((p=out.find("new connection accepted",p))++ != string::npos)
425 BOOST_CHECK_EQUAL(2,cnt);
428 BOOST_AUTO_TEST_SUITE_END()
430 BOOST_FIXTURE_TEST_SUITE(test_wrapper_noserver, KillChildOnShutdownFixture)
432 BOOST_AUTO_TEST_CASE(ignore_noserver)
434 wraptype::set_connection(auto_ptr<ConnectionWrapper>
435 (new ReconnectIgnoreFailureSocketWrapper("./socket")));
437 // wraptype::get_connection_wrapper()->set_logging(&cerr,debug);
439 // there is no server
441 int i=t2n_exec(&cmd_group_x_client::serverfunc)(1);
443 // result is constructed with default constructor on error-and-ignore -> i=0
445 BOOST_CHECK_EQUAL(0,i);
448 BOOST_AUTO_TEST_CASE(ignore_finds_lateserver)
450 wraptype::set_connection(auto_ptr<ConnectionWrapper>
451 (new ReconnectIgnoreFailureSocketWrapper("./socket")));
453 // there is no server
454 t2n_exec(&cmd_group_x_client::serverfunc)(1);
460 switch(child_pid=fork())
464 BOOST_FAIL("fork error");
473 while(i < 10 && !kill_server)
477 socket_server ss("./socket");
478 group_command_server<cmd_group_x> cs(ss);
479 ss.set_logging(&logstream,debug);
482 for (; !close_server && !kill_server && i < 10; i++)
487 std::cerr << "exception in child. ignoring\n";
490 // don't call atexit and stuff
497 // wait till server is up
502 // server should be active
503 int i=t2n_exec(&cmd_group_x_client::serverfunc)(1);
505 BOOST_CHECK_EQUAL(2,i);
508 BOOST_AUTO_TEST_CASE(ignore_wrongserver)
510 wraptype::set_connection(auto_ptr<ConnectionWrapper>
511 (new ReconnectIgnoreFailureSocketWrapper("./socket")));
515 switch(child_pid=fork())
519 BOOST_FAIL("fork error");
527 socket_server ss("./socket");
529 // server sends garbage
534 ss.add_callback(new_connection,bind(&test_wrapper_noserver::ignore_wrongserver::send_hello, boost::ref(*this), hello.str(),&ss, _1));
537 for (int i=0; i < 10; i++)
538 ss.fill_buffer(1000000);
541 std::cerr << "exception in child. ignoring\n";
544 // don't call atexit and stuff
551 // wait till server is up
556 // there is no valid server
558 int i=t2n_exec(&cmd_group_x_client::serverfunc)(1);
560 // result is constructed with default constructor on error-and-ignore -> i=0
562 BOOST_CHECK_EQUAL(0,i);
565 BOOST_AUTO_TEST_SUITE_END()