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"
56 using namespace libt2n;
60 stringstream logstream;
61 bool close_server=false;
62 bool kill_server=false;
75 std::string getserverlog(void)
77 return logstream.str();
80 class serverfunc_res : public libt2n::result
85 friend class boost::serialization::access;
86 template<class Archive>
87 void serialize(Archive & ar, const unsigned int version)
89 ar & BOOST_SERIALIZATION_BASE_OBJECT_NVP(libt2n::result);
90 ar & BOOST_SERIALIZATION_NVP(res);
108 class getserverlog_res : public libt2n::result
113 friend class boost::serialization::access;
114 template<class Archive>
115 void serialize(Archive & ar, const unsigned int version)
117 ar & BOOST_SERIALIZATION_BASE_OBJECT_NVP(libt2n::result);
118 ar & BOOST_SERIALIZATION_NVP(res);
125 getserverlog_res(std::string s)
130 std::string get_data()
136 class cmd_group_x : public command
139 friend class boost::serialization::access;
140 template<class Archive>
141 void serialize(Archive & ar, const unsigned int version)
143 ar & BOOST_SERIALIZATION_BASE_OBJECT_NVP(libt2n::command);
147 class serverfunc_cmd : public cmd_group_x
152 friend class boost::serialization::access;
153 template<class Archive>
154 void serialize(Archive & ar, const unsigned int version)
156 ar & BOOST_SERIALIZATION_BASE_OBJECT_NVP(cmd_group_x);
157 ar & BOOST_SERIALIZATION_NVP(param);
164 serverfunc_cmd(int i)
169 libt2n::result* operator()()
171 return new serverfunc_res(serverfunc(param));
175 class getserverlog_cmd : public cmd_group_x
178 friend class boost::serialization::access;
179 template<class Archive>
180 void serialize(Archive & ar, const unsigned int version)
182 ar & BOOST_SERIALIZATION_BASE_OBJECT_NVP(cmd_group_x);
189 libt2n::result* operator()()
191 return new getserverlog_res(getserverlog());
195 BOOST_CLASS_EXPORT(serverfunc_res)
196 BOOST_CLASS_EXPORT(getserverlog_res)
197 BOOST_CLASS_EXPORT(cmd_group_x)
198 BOOST_CLASS_EXPORT(serverfunc_cmd)
199 BOOST_CLASS_EXPORT(getserverlog_cmd)
201 class cmd_group_x_client : public command_client
204 cmd_group_x_client(libt2n::client_connection *_c,
205 long long _command_timeout_usec=command_timeout_usec_default,
206 long long _hello_timeout_usec=hello_timeout_usec_default)
207 : libt2n::command_client(_c,_command_timeout_usec,_hello_timeout_usec)
210 int serverfunc(int i)
212 libt2n::result_container rc;
214 send_command(new serverfunc_cmd(i), rc);
215 serverfunc_res* res=dynamic_cast<serverfunc_res*>(rc.get_result());
216 if (!res) throw libt2n::t2n_communication_error("result object of wrong type");
217 return res->get_data();
220 std::string getserverlog(void)
222 libt2n::result_container rc;
224 send_command(new getserverlog_cmd(), rc);
225 getserverlog_res* res=dynamic_cast<getserverlog_res*>(rc.get_result());
226 if (!res) throw libt2n::t2n_communication_error("result object of wrong type");
227 return res->get_data();
231 typedef T2nSingletonWrapper<cmd_group_x_client> wraptype;
234 std::auto_ptr<wraptype> wraptype::SingletonObject = std::auto_ptr<wraptype>();
237 std::auto_ptr<ConnectionWrapper> wraptype::WrappedConnection = std::auto_ptr<ConnectionWrapper>();
240 class test_wrapperFixture : public KillChildOnShutdownFixture
243 test_wrapperFixture()
248 switch(child_pid=fork())
252 BOOST_FAIL("fork error");
261 while(i < 10 && !kill_server)
265 socket_server ss("./socket");
266 group_command_server<cmd_group_x> cs(ss);
267 ss.set_logging(&logstream,debug);
270 for (; !close_server && !kill_server && i < 10; i++)
275 std::cerr << "exception in child. ignoring\n";
278 // don't call atexit and stuff
285 // don't kill us on broken pipe
286 signal(SIGPIPE, SIG_IGN);
288 // wait till server is up
294 ~test_wrapperFixture()
299 BOOST_FIXTURE_TEST_SUITE(test_wrapper, test_wrapperFixture)
301 BOOST_AUTO_TEST_CASE(no_init_exception) // must be called first!
303 BOOST_REQUIRE_THROW(t2n_exec(&cmd_group_x_client::serverfunc)(1),std::logic_error);
306 BOOST_AUTO_TEST_CASE(simple_wrap)
308 wraptype::set_connection(auto_ptr<ConnectionWrapper>
309 (new BasicSocketWrapper("./socket")));
311 int i=t2n_exec(&cmd_group_x_client::serverfunc)(1);
313 BOOST_CHECK_EQUAL(2,i);
316 BOOST_AUTO_TEST_CASE(double_use)
318 // only one connection used?
319 wraptype::set_connection(auto_ptr<ConnectionWrapper>
320 (new BasicSocketWrapper("./socket")));
322 t2n_exec(&cmd_group_x_client::serverfunc)(17);
323 string out=t2n_exec(&cmd_group_x_client::getserverlog)();
325 // count the number of times that "new connection accepted" appears in the server log
326 string::size_type p=0;
328 while ((p=out.find("new connection accepted",p))++ != string::npos)
331 BOOST_CHECK_EQUAL(1,cnt);
334 BOOST_AUTO_TEST_CASE(double_use_with_close)
336 wraptype::set_connection(auto_ptr<ConnectionWrapper>
337 (new BasicSocketWrapper("./socket")));
339 t2n_exec(&cmd_group_x_client::serverfunc)(17);
341 // closes the connection from the client side
342 wraptype::set_connection(auto_ptr<ConnectionWrapper>
343 (new BasicSocketWrapper("./socket")));
345 string out=t2n_exec(&cmd_group_x_client::getserverlog)();
347 // count the number of times that "new connection accepted" appears in the server log
348 string::size_type p=0;
350 while ((p=out.find("new connection accepted",p))++ != string::npos)
353 BOOST_CHECK_EQUAL(2,cnt);
356 BOOST_AUTO_TEST_CASE(reconnect_after_close)
358 wraptype::set_connection(auto_ptr<ConnectionWrapper>
359 (new ReconnectSocketWrapper("./socket")));
361 wraptype::get_connection_wrapper()->set_command_timeout_usec(3000000);
362 wraptype::get_connection_wrapper()->set_hello_timeout_usec(3000000);
364 // 42 closes connection on the server side
365 t2n_exec(&cmd_group_x_client::serverfunc)(42);
367 string out=t2n_exec(&cmd_group_x_client::getserverlog)();
369 // count the number of times that "new connection accepted" appears in the server log
370 string::size_type p=0;
372 while ((p=out.find("new connection accepted",p))++ != string::npos)
375 BOOST_CHECK_EQUAL(2,cnt);
378 BOOST_AUTO_TEST_CASE(reconnect_not_possible)
380 wraptype::set_connection(auto_ptr<ConnectionWrapper>
381 (new ReconnectSocketWrapper("./socket")));
383 // the server doens't like the beast
384 t2n_exec(&cmd_group_x_client::serverfunc)(666);
386 BOOST_REQUIRE_THROW(t2n_exec(&cmd_group_x_client::serverfunc)(1),t2n_communication_error);
389 BOOST_AUTO_TEST_CASE(ignore_server_disconnect)
391 wraptype::set_connection(auto_ptr<ConnectionWrapper>
392 (new ReconnectIgnoreFailureSocketWrapper("./socket")));
394 // the server doens't like the beast
395 t2n_exec(&cmd_group_x_client::serverfunc)(666);
397 int i=t2n_exec(&cmd_group_x_client::serverfunc)(1);
399 // result is constructed with default constructor on error-and-ignore -> i=0
401 BOOST_CHECK_EQUAL(0,i);
404 BOOST_AUTO_TEST_CASE(ignore_handler_reconnects)
406 wraptype::set_connection(auto_ptr<ConnectionWrapper>
407 (new ReconnectIgnoreFailureSocketWrapper("./socket")));
409 wraptype::get_connection_wrapper()->set_command_timeout_usec(3000000);
410 wraptype::get_connection_wrapper()->set_hello_timeout_usec(3000000);
412 // 42 closes connection on the server side
413 t2n_exec(&cmd_group_x_client::serverfunc)(42);
415 string out=t2n_exec(&cmd_group_x_client::getserverlog)();
417 // count the number of times that "new connection accepted" appears in the server log
418 string::size_type p=0;
420 while ((p=out.find("new connection accepted",p))++ != string::npos)
423 BOOST_CHECK_EQUAL(2,cnt);
426 BOOST_AUTO_TEST_SUITE_END()
428 BOOST_FIXTURE_TEST_SUITE(test_wrapper_noserver, KillChildOnShutdownFixture)
430 BOOST_AUTO_TEST_CASE(ignore_noserver)
432 wraptype::set_connection(auto_ptr<ConnectionWrapper>
433 (new ReconnectIgnoreFailureSocketWrapper("./socket")));
435 // wraptype::get_connection_wrapper()->set_logging(&cerr,debug);
437 // there is no server
439 int i=t2n_exec(&cmd_group_x_client::serverfunc)(1);
441 // result is constructed with default constructor on error-and-ignore -> i=0
443 BOOST_CHECK_EQUAL(0,i);
446 BOOST_AUTO_TEST_CASE(ignore_finds_lateserver)
448 wraptype::set_connection(auto_ptr<ConnectionWrapper>
449 (new ReconnectIgnoreFailureSocketWrapper("./socket")));
451 // there is no server
452 t2n_exec(&cmd_group_x_client::serverfunc)(1);
458 switch(child_pid=fork())
462 BOOST_FAIL("fork error");
471 while(i < 10 && !kill_server)
475 socket_server ss("./socket");
476 group_command_server<cmd_group_x> cs(ss);
477 ss.set_logging(&logstream,debug);
480 for (; !close_server && !kill_server && i < 10; i++)
485 std::cerr << "exception in child. ignoring\n";
488 // don't call atexit and stuff
495 // wait till server is up
500 // server should be active
501 int i=t2n_exec(&cmd_group_x_client::serverfunc)(1);
503 BOOST_CHECK_EQUAL(2,i);
506 BOOST_AUTO_TEST_CASE(ignore_wrongserver)
508 wraptype::set_connection(auto_ptr<ConnectionWrapper>
509 (new ReconnectIgnoreFailureSocketWrapper("./socket")));
513 switch(child_pid=fork())
517 BOOST_FAIL("fork error");
525 socket_server ss("./socket");
527 // server sends garbage
532 ss.add_callback(new_connection,bind(&test_wrapper_noserver::ignore_wrongserver::send_hello, boost::ref(*this), hello.str(),&ss, _1));
535 for (int i=0; i < 10; i++)
536 ss.fill_buffer(1000000);
539 std::cerr << "exception in child. ignoring\n";
542 // don't call atexit and stuff
549 // wait till server is up
554 // there is no valid server
556 int i=t2n_exec(&cmd_group_x_client::serverfunc)(1);
558 // result is constructed with default constructor on error-and-ignore -> i=0
560 BOOST_CHECK_EQUAL(0,i);
563 BOOST_AUTO_TEST_SUITE_END()