class cmd_group_example_client : public libt2n::command_client
{
public:
- cmd_group_example_client(libt2n::client_connection &_c,
+ cmd_group_example_client(libt2n::client_connection *_c,
long long _command_timeout_usec=command_timeout_usec_default,
long long _hello_timeout_usec=hello_timeout_usec_default)
: libt2n::command_client(_c,_command_timeout_usec,_hello_timeout_usec)
extended_type_info_test();
libt2n::socket_client_connection sc("./socket");
- cmd_group_example_client cc(sc);
+ cmd_group_example_client cc(&sc);
return (cc.testfunc("hello")=="hello, testfunc() was here") ? EXIT_SUCCESS : EXIT_FAILURE;
}
virtual client_connection* get_connection()=0;
- virtual void handle(command_client* stubBase, boost::function< void() > f)
+ virtual bool handle(command_client* stubBase, boost::function< void() > f)
{
f();
+ return true;
}
long long get_command_timeout_usec(void)
if (WrappedConnection.get() == NULL)
throw std::logic_error(NotInitializedMessage);
- std::auto_ptr<Client> stub(new Client(*(WrappedConnection->get_connection()),
+ std::auto_ptr<Client> stub(new Client(WrappedConnection->get_connection(),
WrappedConnection->get_command_timeout_usec(),
WrappedConnection->get_hello_timeout_usec()));
ensure_singleton_there();
typename detail::TypeWrap<R>::type result;
+
+ // bind our Client-object and the local result
detail::Call<R> call( boost::bind( f, SingletonObject->Stub.get()), result );
- WrappedConnection->handle(SingletonObject->Stub.get(),call);
+
+ // let the wrapper-handler call the fully-bound function
+ if (!WrappedConnection->handle(SingletonObject->Stub.get(),call))
+ {
+ // create an result with default-constructor if the handler could not
+ // successfully do a call but no exception occured
+ result=typename detail::TypeWrap<R>::type();
+ }
return result;
}
namespace libt2n
{
-command_client::command_client(client_connection& _c, long long _command_timeout_usec, long long _hello_timeout_usec)
+command_client::command_client(client_connection* _c, long long _command_timeout_usec, long long _hello_timeout_usec)
: c(_c)
{
command_timeout_usec=_command_timeout_usec;
hello_timeout_usec=_hello_timeout_usec;
// for reconnects
- c.add_callback(new_connection,bind(&command_client::read_hello, boost::ref(*this)));
+ c->add_callback(new_connection,bind(&command_client::read_hello, boost::ref(*this)));
- read_hello();
+ // don't expect hello from an always closed connection (like dummy_client_connection)
+ if (!c->is_closed())
+ read_hello();
}
/** @brief replace the connection currently in use with a new one
- @param _c reference of the new connection
+ @param _c pointer to the new connection
@note the old connection must still be valid when this method is called,
it can safely be deleted after this method returned
@note all callbacks registered on the old connection will be copied over
to the new one
*/
-void command_client::replace_connection(client_connection& _c)
+void command_client::replace_connection(client_connection* _c)
{
// copy all callbacks registered on the old connection
for(callback_event_type e=static_cast<callback_event_type>(0);
e < __events_end;
e=static_cast<callback_event_type>(static_cast<int>(e)+1))
{
- list<boost::function<void ()> > evcb=c.get_callback_list(e);
+ list<boost::function<void ()> > evcb=c->get_callback_list(e);
for (list<boost::function<void ()> >::iterator i=evcb.begin(); i != evcb.end(); i++)
- _c.add_callback(e,*i);
+ _c->add_callback(e,*i);
}
// replace the connection
string resultpacket;
bool got_packet=false;
long long my_timeout=usec_timeout;
- while(!(got_packet=c.get_packet(resultpacket)) && my_timeout > 0 && !c.is_closed())
- c.fill_buffer(my_timeout,&my_timeout);
+ while(!(got_packet=c->get_packet(resultpacket)) && my_timeout > 0 && !c->is_closed())
+ c->fill_buffer(my_timeout,&my_timeout);
if (!got_packet)
throw t2n_transfer_error("timeout exceeded");
string resultpacket;
bool got_packet=false;
long long my_timeout=hello_timeout_usec;
- while(!(got_packet=c.get_packet(resultpacket)) && my_timeout > 0 && !c.is_closed())
+ while(!(got_packet=c->get_packet(resultpacket)) && my_timeout > 0 && !c->is_closed())
{
- c.fill_buffer(my_timeout,&my_timeout);
+ c->fill_buffer(my_timeout,&my_timeout);
- c.peek_packet(resultpacket);
+ c->peek_packet(resultpacket);
check_hello(resultpacket); // will throw before timeout if wrong data received
}
{ throw; }
std::ostream* ostr;
- if ((ostr=c.get_logstream(fulldebug))!=NULL)
+ if ((ostr=c->get_logstream(fulldebug))!=NULL)
{
(*ostr) << "sending command, decoded data: " << std::endl;
boost::archive::xml_oarchive xo(*ostr);
xo << BOOST_SERIALIZATION_NVP(cc);
}
- c.write(ofs.str());
+ c->write(ofs.str());
istringstream ifs(read_packet(command_timeout_usec));
boost::archive::binary_iarchive ia(ifs);
catch(...)
{ throw; }
- if ((ostr=c.get_logstream(fulldebug))!=NULL)
+ if ((ostr=c->get_logstream(fulldebug))!=NULL)
{
(*ostr) << "received result, decoded data: " << std::endl;
boost::archive::xml_oarchive xo(*ostr);
static const long long hello_timeout_usec_default=30000000;
private:
- client_connection &c;
+ client_connection *c;
long long hello_timeout_usec;
long long command_timeout_usec;
bool check_hello(const std::string& hellostr);
public:
- command_client(client_connection& _c,
+ command_client(client_connection* _c,
long long _command_timeout_usec=command_timeout_usec_default,
long long _hello_timeout_usec=hello_timeout_usec_default);
virtual ~command_client() {}
- void replace_connection(client_connection& _c);
+ void replace_connection(client_connection* _c);
void send_command(command* cmd, result_container &res);
namespace libt2n
{
+/// returns a closed connection if connection could not be established, call get_last_error_msg() for details
socket_client_connection::socket_client_connection(int _port, const std::string& _server,
long long _connect_timeout_usec, int _max_retries,
std::ostream *_logstream, log_level_values _log_level)
set_logging(_logstream,_log_level);
- tcp_connect(max_retries);
+ try
+ {
+ tcp_connect(max_retries);
+ }
+ catch (t2n_communication_error &e)
+ {
+ lastErrorMsg=e.what();
+ LOGSTREAM(debug,"tcp connect error: " << lastErrorMsg);
+ close();
+ }
- do_callbacks(new_connection);
+ if (!connection::is_closed())
+ do_callbacks(new_connection);
}
+/// returns a closed connection if connection could not be established, call get_last_error_msg() for details
socket_client_connection::socket_client_connection(const std::string& _path,
long long _connect_timeout_usec, int _max_retries,
std::ostream *_logstream, log_level_values _log_level)
set_logging(_logstream,_log_level);
- unix_connect(max_retries);
+ try
+ {
+ unix_connect(max_retries);
+ }
+ catch (t2n_communication_error &e)
+ {
+ lastErrorMsg=e.what();
+ LOGSTREAM(debug,"unix connect error: " << lastErrorMsg);
+ close();
+ }
- do_callbacks(new_connection);
+ if (!connection::is_closed())
+ do_callbacks(new_connection);
}
void socket_client_connection::tcp_connect(int max_retries)
tcp_connect(max_retries-1);
}
else
- LOGSTREAM(debug,"no more retries left after connect error");
+ throw t2n_connect_error("no more retries left after connect error");
}
}
unix_connect(max_retries-1);
}
else
- LOGSTREAM(debug,"no more retries left after connect error");
+ throw t2n_connect_error("no more retries left after connect error");
}
}
ret < 0 && errno==EINTR);
if (ret < 0)
- {
- LOGSTREAM(debug,"connect_with_timeout(): select error: " << strerror(errno));
throw t2n_connect_error(string("connect() error (select): ")+strerror(errno));
- }
socklen_t sopt=sizeof(int);
int valopt;
ret=getsockopt(sock, SOL_SOCKET, SO_ERROR, (void*)(&valopt), &sopt);
if (ret < 0 || valopt)
- {
- LOGSTREAM(debug,"connect_with_timeout(): getsockopt error: " << strerror(errno));
throw t2n_connect_error(string("connect() error (getsockopt): ")+strerror(errno));
- }
}
else
- {
- LOGSTREAM(debug,"connect_with_timeout(): error: " << strerror(errno));
throw t2n_connect_error(string("connect() error: ")+strerror(errno));
- }
}
LOGSTREAM(debug,"connect_with_timeout(): success");
}
/** @brief try to reconnect the current connection with the same connection credentials (host and port or path)
+
+ @note will throw an exeption if reconnecting not possible
*/
void socket_client_connection::reconnect()
{
else if (type == unix_s)
unix_connect(max_retries);
- LOGSTREAM(debug,"reconnect(): basic connection established");
-
+ // connection is open now, otherwise an execption would have been thrown
reopen();
LOGSTREAM(debug,"reconnect() done, client_connection::is_closed() now " << client_connection::is_closed());
-
}
}
std::string server;
int port;
+ std::string lastErrorMsg;
+
protected:
std::ostream* get_logstream(log_level_values level)
void close();
void reconnect();
+
+ std::string get_last_error_msg(void)
+ { return lastErrorMsg; }
};
}
char socket_buffer[recv_buffer_size];
int nbytes = read (sock, socket_buffer, recv_buffer_size);
+
if (nbytes < 0)
{
if (errno == EAGAIN)
return c.get();
}
-void ReconnectSocketWrapper::handle(command_client* stubBase, boost::function< void() > f)
+bool ReconnectSocketWrapper::handle(command_client* stubBase, boost::function< void() > f)
{
int tries=0;
f();
// we were successful
- return;
+ return true;
}
catch(t2n_connect_error &e)
{
tries++;
}
+
+ return false;
}
client_connection* ReconnectIgnoreFailureSocketWrapper::get_connection(void)
{
- client_connection* tmp;
+ client_connection* tmp=BasicSocketWrapper::get_connection();
- try
- {
- tmp=BasicSocketWrapper::get_connection();
- }
- catch(t2n_connect_error &e)
+ if (tmp->is_closed())
{
- // TODO: return some kind of dummy connection
- }
- catch(...)
- {
- throw;
+ // throw away the closed connection...
+ c.reset();
+ // ...return the dummy one instead
+ tmp=&dc;
}
return tmp;
}
-void ReconnectIgnoreFailureSocketWrapper::handle(command_client* stubBase, boost::function< void() > f)
+bool ReconnectIgnoreFailureSocketWrapper::handle(command_client* stubBase, boost::function< void() > f)
{
- // TODO: check for dummy connection and try to establish a real one
-
- try
+ if (!connection_established())
{
- ReconnectSocketWrapper::handle(stubBase,f);
- }
- catch(t2n_communication_error &e)
- {
- // ignore
+ // dummy connection is in place: try to establish a real one
+ client_connection* tmp=get_connection();
+
+ if (tmp != &dc)
+ {
+ // success! we've got a real connection
+ stubBase->replace_connection(tmp);
+ }
}
- catch(...)
+
+ // only try to handle the call if we've got a real connection
+ if (connection_established())
{
- throw;
+ try
+ {
+ ReconnectSocketWrapper::handle(stubBase,f);
+ return true;
+ }
+ catch(t2n_communication_error &e)
+ {
+ // ignore
+ }
+ catch(...)
+ {
+ throw;
+ }
}
+
+ return false;
}
}
{ }
client_connection* get_connection(void);
+
+ bool connection_established(void)
+ { return (c.get() != NULL); }
};
class ReconnectSocketWrapper : public BasicSocketWrapper
: BasicSocketWrapper(_path,_connect_timeout_usec,_max_retries)
{ }
- void handle(command_client* stubBase, boost::function< void() > f);
+ bool handle(command_client* stubBase, boost::function< void() > f);
};
+class dummy_client_connection : public client_connection
+{
+ private:
+ void real_write(const std::string& data)
+ { }
+
+ public:
+ dummy_client_connection()
+ : client_connection()
+ { close(); }
+
+ bool fill_buffer(long long usec_timeout=-1, long long *usec_timeout_remaining=NULL)
+ { return false; }
+};
class ReconnectIgnoreFailureSocketWrapper : public ReconnectSocketWrapper
{
+ private:
+ dummy_client_connection dc;
+
public:
ReconnectIgnoreFailureSocketWrapper(int _port, const std::string& _server="127.0.0.1",
long long _connect_timeout_usec=socket_client_connection::connect_timeout_usec_default,
{ }
client_connection* get_connection(void);
- void handle(command_client* stubBase, boost::function< void() > f);
+ bool handle(command_client* stubBase, boost::function< void() > f);
};
-
-
}
#endif
// wait till server is up
sleep(1);
socket_client_connection sc("./socket");
- command_client cc(sc);
+ command_client cc(&sc);
result_container rc;
cc.send_command(new testfunc4a_cmd("hello"),rc);
// wait till server is up
sleep(1);
socket_client_connection sc("./socket");
- command_client cc(sc);
+ command_client cc(&sc);
result_container rc;
cc.send_command(new testfunc4a_cmd("hello"),rc);
// wait till server is up
sleep(1);
socket_client_connection sc("./socket");
- command_client cc(sc);
+ command_client cc(&sc);
}
}
}
try
{
- command_client cc(sc);
+ command_client cc(&sc);
}
catch(t2n_version_mismatch &e)
{ errormsg=e.what(); }
try
{
- command_client cc(sc);
+ command_client cc(&sc);
}
catch(t2n_version_mismatch &e)
{ errormsg=e.what(); }
try
{
- command_client cc(sc);
+ command_client cc(&sc);
}
catch(t2n_version_mismatch &e)
{ errormsg=e.what(); }
try
{
- command_client cc(sc);
+ command_client cc(&sc);
}
catch(t2n_version_mismatch &e)
{ errormsg=e.what(); }
try
{
- command_client cc(sc);
+ command_client cc(&sc);
}
catch(t2n_version_mismatch &e)
{ errormsg=e.what(); }
try
{
- command_client cc(sc);
+ command_client cc(&sc);
}
catch(t2n_version_mismatch &e)
{ errormsg=e.what(); }
// wait till server is up
sleep(1);
socket_client_connection sc("./socket");
- command_client cc(sc);
+ command_client cc(&sc);
string errormsg;
sleep(1);
socket_client_connection sc("./socket");
sc.set_logging(&cerr,debug);
- command_client cc(sc);
+ command_client cc(&sc);
result_container rc;
cc.send_command(new testfunc_cmd("hello"),rc);
CPPUNIT_ASSERT_EQUAL(string("hello, testfunc() was here"),ret);
}
}
+ kill(pid,SIGKILL);
}
void SimpleException()
sleep(1);
socket_client_connection sc("./socket");
sc.set_logging(&cerr,debug);
- command_client cc(sc);
+ command_client cc(&sc);
result_container rc;
cc.send_command(new testfunc_cmd("throw"),rc);
{ throw; }
CPPUNIT_ASSERT_EQUAL(string("throw me around"),ret);
+
+ kill(pid,SIGKILL);
}
}
}
// wait till server is up
sleep(1);
socket_client_connection sc("./socket");
- command_client cc(sc);
+ command_client cc(&sc);
result_container rc;
cc.send_command(new testfunc_cmd("big"),rc);
string ret=dynamic_cast<testfunc_res*>(rc.get_result())->get_data();
CPPUNIT_ASSERT_EQUAL(string().insert(0,100*1024,'x'),ret);
+
+ kill(pid,SIGKILL);
}
}
}
// wait till server is up
sleep(1);
socket_client_connection sc("./socket");
- command_client cc(sc);
+ command_client cc(&sc);
result_container rc;
cc.send_command(new testfunc_cmd(string().insert(0,100*1024,'y')),rc);
string ret=dynamic_cast<testfunc_res*>(rc.get_result())->get_data();
CPPUNIT_ASSERT_EQUAL(string().insert(0,100*1024,'y')+", testfunc() was here",ret);
+
+ kill(pid,SIGKILL);
}
}
}
string errormsg;
- try
- {
- socket_client_connection sc("./socket");
- command_client cc(sc,1000000,1000000);
- }
- catch(t2n_transfer_error &e)
- { errormsg=e.what(); }
- catch(...)
- { throw; }
+ socket_client_connection sc("./socket");
- CPPUNIT_ASSERT_EQUAL(string("error reading from socket : Invalid argument"),errormsg);
+ CPPUNIT_ASSERT_EQUAL(true,sc.connection::is_closed());
}
}
}
try
{
- command_client cc(sc,1000000,1000000);
+ command_client cc(&sc,1000000,1000000);
}
catch(t2n_transfer_error &e)
{ errormsg=e.what(); }
{ throw; }
CPPUNIT_ASSERT_EQUAL(string("timeout exceeded"),errormsg);
+
+ kill(pid,SIGKILL);
}
}
}
try
{
- command_client cc(sc,1000000,1000000);
+ command_client cc(&sc,1000000,1000000);
}
catch(t2n_transfer_error &e)
{ errormsg=e.what(); }
{ throw; }
CPPUNIT_ASSERT_EQUAL(string("timeout exceeded"),errormsg);
+
+ kill(pid,SIGKILL);
}
}
}
sleep(1);
socket_client_connection sc("./socket");
- command_client cc(sc,1000000,1000000);
+ command_client cc(&sc,1000000,1000000);
result_container rc;
string errormsg;
{ throw; }
CPPUNIT_ASSERT_EQUAL(string("timeout exceeded"),errormsg);
+
+ kill(pid,SIGKILL);
}
}
}
sleep(1);
socket_client_connection sc("./socket");
- command_client cc(sc,1000000,1000000);
+ command_client cc(&sc,1000000,1000000);
result_container rc;
string errormsg;
{ throw; }
CPPUNIT_ASSERT_EQUAL(string("timeout exceeded"),errormsg);
+
+ kill(pid,SIGKILL);
}
}
}
{ throw; }
CPPUNIT_ASSERT_EQUAL(string("write() returned Broken pipe"),errormsg);
+
+ kill(pid,SIGKILL);
}
}
}
void DisconnectOnRead()
{
- pid_t pid;
+ pid_t pid1, pid2;
- switch(pid=fork())
+ switch(pid1=fork())
{
case -1:
{
// are we still alive and able to process data?
- switch(pid=fork())
+ switch(pid2=fork())
{
case -1:
{
}
}
}
+ kill(pid1,SIGKILL);
+ kill(pid2,SIGKILL);
}
void BreakAccept()
{
- pid_t pid;
+ pid_t pid1,pid2;
- switch(pid=fork())
+ switch(pid1=fork())
{
case -1:
{
// are we still alive and able to process data?
- switch(pid=fork())
+ switch(pid2=fork())
{
case -1:
{
}
}
}
+ kill(pid1,SIGKILL);
+ kill(pid2,SIGKILL);
}
};
class cmd_group_x_client : public command_client
{
public:
- cmd_group_x_client(libt2n::client_connection &_c,
+ cmd_group_x_client(libt2n::client_connection *_c,
long long _command_timeout_usec=command_timeout_usec_default,
long long _hello_timeout_usec=hello_timeout_usec_default)
: libt2n::command_client(_c,_command_timeout_usec,_hello_timeout_usec)
CPPUNIT_TEST(double_use_with_close);
CPPUNIT_TEST(reconnect_after_close);
CPPUNIT_TEST(reconnect_not_possible);
+ CPPUNIT_TEST(ignore_server_disconnect);
+ CPPUNIT_TEST(ignore_handler_reconnects);
// TODO: missing tests:
-// ignore: init, use, server die, ignore
// ignore: init, no server, ignore
// ignore: init, no server, ignore, server ok, connect?
public:
+ pid_t child_pid;
+
void setUp()
{
- pid_t pid;
+ close_server=false;
+ kill_server=false;
- switch(pid=fork())
+ switch(child_pid=fork())
{
case -1:
{
// child
{
int i=0;
- while(i < 15 && !kill_server)
+ while(i < 10 && !kill_server)
{
close_server=false;
ss.set_logging(&logstream,debug);
// max 10 sec
- for (; !close_server && !kill_server && i < 15; i++)
+ for (; !close_server && !kill_server && i < 10; i++)
cs.handle(1000000);
}
}
void tearDown()
- { }
+ {
+ // make sure the server-child is dead before the next test runs
+ kill(child_pid,SIGKILL);
+ sleep(1);
+ }
+
+ void no_init_exception()
+ {
+ CPPUNIT_ASSERT_THROW(t2n_exec(&cmd_group_x_client::serverfunc)(1),std::logic_error);
+ }
void simple_wrap()
{
CPPUNIT_ASSERT_EQUAL(2,i);
}
- void no_init_exception()
- {
- CPPUNIT_ASSERT_THROW(t2n_exec(&cmd_group_x_client::serverfunc)(1),std::logic_error);
- }
-
void double_use()
{
// only one connection used?
CPPUNIT_ASSERT_THROW(t2n_exec(&cmd_group_x_client::serverfunc)(1),t2n_communication_error);
}
+ void ignore_server_disconnect()
+ {
+ wraptype::set_connection(auto_ptr<ConnectionWrapper>
+ (new ReconnectIgnoreFailureSocketWrapper("./socket")));
+
+ // the server doens't like the beast
+ t2n_exec(&cmd_group_x_client::serverfunc)(666);
+
+ int i=t2n_exec(&cmd_group_x_client::serverfunc)(1);
+
+ // result is constructed with default constructor on error-and-ignore -> i=0
+
+ CPPUNIT_ASSERT_EQUAL(0,i);
+ }
+
+ void ignore_handler_reconnects()
+ {
+ wraptype::set_connection(auto_ptr<ConnectionWrapper>
+ (new ReconnectIgnoreFailureSocketWrapper("./socket")));
+
+ wraptype::get_connection_wrapper()->set_command_timeout_usec(3000000);
+ wraptype::get_connection_wrapper()->set_hello_timeout_usec(3000000);
+
+ // 42 closes connection on the server side
+ t2n_exec(&cmd_group_x_client::serverfunc)(42);
+
+ string out=t2n_exec(&cmd_group_x_client::getserverlog)();
+
+ // count the number of times that "new connection accepted" appears in the server log
+ string::size_type p=0;
+ int cnt=0;
+ while ((p=out.find("new connection accepted",p))++ != string::npos)
+ cnt++;
+
+ CPPUNIT_ASSERT_EQUAL(2,cnt);
+ }
+
+
};
CPPUNIT_TEST_SUITE_REGISTRATION(test_wrapper);
+
+
+class test_wrapper_noserver : public TestFixture
+{
+ CPPUNIT_TEST_SUITE(test_wrapper_noserver);
+
+ CPPUNIT_TEST(ignore_noserver);
+ CPPUNIT_TEST(ignore_finds_lateserver);
+
+ CPPUNIT_TEST_SUITE_END();
+
+ public:
+
+ pid_t child_pid;
+
+ void setUp()
+ { }
+
+ void tearDown()
+ { }
+
+ void ignore_noserver()
+ {
+ wraptype::set_connection(auto_ptr<ConnectionWrapper>
+ (new ReconnectIgnoreFailureSocketWrapper("./socket")));
+
+ // wraptype::get_connection_wrapper()->set_logging(&cerr,debug);
+
+ // there is no server
+
+ int i=t2n_exec(&cmd_group_x_client::serverfunc)(1);
+
+ // result is constructed with default constructor on error-and-ignore -> i=0
+
+ CPPUNIT_ASSERT_EQUAL(0,i);
+ }
+
+ void ignore_finds_lateserver()
+ {
+ wraptype::set_connection(auto_ptr<ConnectionWrapper>
+ (new ReconnectIgnoreFailureSocketWrapper("./socket")));
+
+ // there is no server
+ t2n_exec(&cmd_group_x_client::serverfunc)(1);
+
+ // launch a server
+
+ close_server=false;
+ kill_server=false;
+
+ switch(child_pid=fork())
+ {
+ case -1:
+ {
+ CPPUNIT_FAIL("fork error");
+ break;
+ }
+ case 0:
+ // child
+ {
+ int i=0;
+ while(i < 10 && !kill_server)
+ {
+ close_server=false;
+
+ socket_server ss("./socket");
+ group_command_server<cmd_group_x> cs(ss);
+ ss.set_logging(&logstream,debug);
+
+ // max 10 sec
+ for (; !close_server && !kill_server && i < 10; i++)
+ cs.handle(1000000);
+ }
+
+ // don't call atexit and stuff
+ _exit(0);
+ }
+
+ default:
+ // parent
+ {
+ // wait till server is up
+ sleep(1);
+ }
+ }
+
+ // server should be active
+ int i=t2n_exec(&cmd_group_x_client::serverfunc)(1);
+
+ CPPUNIT_ASSERT_EQUAL(2,i);
+
+ // make sure the server-child is dead before the next test runs
+ kill(child_pid,SIGKILL);
+ sleep(1);
+ }
+
+
+};
+
+CPPUNIT_TEST_SUITE_REGISTRATION(test_wrapper_noserver);