#include <string>
#include <RCF/test/TestMinimal.hpp>
#include <RCF/Idl.hpp>
#include <RCF/RcfServer.hpp>
#include <RCF/ObjectFactoryService.hpp>
#include <RCF/TcpClientTransport.hpp>
#include <RCF/TcpEndpoint.hpp>
#include <RCF/test/PrintTestHeader.hpp>
#include <RCF/test/TransportFactories.hpp>
#include <RCF/util/CommandLine.hpp>
#include <RCF/util/PortNumbers.hpp>
#include <RCF/util/Platform/OS/Sleep.hpp>
#include <RCF/util/TraceCommandLineOption.hpp>
namespace Test_ObjectFactoryService {
class Echo
{
public:
Echo() : mNVal(RCF_DEFAULT_INIT), mBVal(RCF_DEFAULT_INIT), mDVal(RCF_DEFAULT_INIT), mSVal()
{}
// I_Echo
std::string echo(const std::string &s)
{
sLog = s;
return s;
}
static std::string sLog;
void setVal(int val)
{
mNVal = val;
}
int getVal()
{
return mNVal;
}
// I_X1
void setVal(bool val)
{
mBVal = val;
}
bool getVal(bool)
{
return mBVal;
}
// I_X2
void setVal(double val)
{
mDVal = val;
}
double getVal(double)
{
return mDVal;
}
// I_X3
void setVal(std::string val)
{
mSVal = val;
}
std::string getVal(std::string)
{
return mSVal;
}
private:
int mNVal;
bool mBVal;
double mDVal;
std::string mSVal;
};
std::string Echo::sLog;
RCF_BEGIN(I_Echo, "I_Echo")
RCF_METHOD_R1(std::string, echo, const std::string &)
RCF_METHOD_V1(void, setVal, int)
RCF_METHOD_R0(int, getVal)
RCF_END(I_Echo)
RCF_BEGIN(I_X1, "I_X1")
RCF_METHOD_V1(void, setVal, bool)
RCF_METHOD_R1(bool, getVal, bool)
RCF_END(I_X1)
RCF_BEGIN(I_X2, "I_X2")
RCF_METHOD_V1(void, setVal, double)
RCF_METHOD_R1(double, getVal, double)
RCF_END(I_X2)
RCF_BEGIN(I_X3, "I_X3")
RCF_METHOD_V1(void, setVal, std::string)
RCF_METHOD_R1(std::string, getVal, std::string)
RCF_END(I_X3)
void exhaustTokenSpace(int numberOfTokens, RCF::I_RcfClient &client)
{
int count = 0;
for (int j=0; j<numberOfTokens+1;++j)
{
//if (RCF::createRemoteObject<I_Echo>(client,"Echo"))
if (tryCreateRemoteObject<I_Echo>(client,"Echo"))
{
++count;
}
std::cout << client.getClientStub().getTargetToken() << std::endl;
}
BOOST_CHECK(count == numberOfTokens);
}
} // namespace Test_ObjectFactoryService
int RCF_TEST_MAIN(int argc, char **argv)
{
printTestHeader(__FILE__);
using namespace Test_ObjectFactoryService;
util::CommandLineOption<int> clNumberOfTokens("tokens", 5, "number of tokens in object factory");
util::CommandLineOption<int> clClientStubTimeoutS("timeout", 2, "server object timeout in seconds");
util::CommandLineOption<int> clWaitIntervalS("wait", 5, "how long to wait for object factory to run cleanup");
util::CommandLineOption<int> clCleanupIntervalS("cleanup", 2, "object factory cleanup interval in seconds");
util::CommandLine::getSingleton().parse(argc, argv);
std::string ip = "localhost";
unsigned int numberOfTokens = clNumberOfTokens;
unsigned int clientStubTimeoutS = clClientStubTimeoutS;
unsigned int waitIntervalS = clWaitIntervalS;
unsigned int cleanupIntervalS = clCleanupIntervalS;
std::string s0 = "something special";
{
int port = util::PortNumbers::getSingleton().getNext();
RCF::TcpEndpoint serverEndpoint(port);
RCF::TcpEndpoint clientEndpoint(ip, port);
RCF::RcfServer server( serverEndpoint );
RCF::ObjectFactoryServicePtr objectFactoryServicePtr(
new RCF::ObjectFactoryService(
numberOfTokens, clientStubTimeoutS, cleanupIntervalS) );
//objectFactoryServicePtr->bind<I_Echo, Echo>("Echo");
objectFactoryServicePtr->bind( (I_Echo*) 0, (Echo**) 0, "Echo");
server.addService( objectFactoryServicePtr );
server.start();
RcfClient<I_Echo> client( clientEndpoint );
//bool ok = RCF::createRemoteObject<I_Echo>(client, "Echo");
bool ok = tryCreateRemoteObject<I_Echo>(client, "Echo");
BOOST_CHECK(ok);
std::string s = client.echo(s0);
RCF::Token token = client.getClientStub().getTargetToken();
BOOST_CHECK( s == s0 );
BOOST_CHECK(token != RCF::Token());
// check that we're ok w.r.t. server restarting
s = client.echo(s0);
server.stop();
server.start();
s = client.echo(s0);
// check that the object isn't deleted before the timeout
client.getClientStub().disconnect();
s == client.echo(s0);
// check that the object isn't deleted while the connection is alive
Platform::OS::SleepMs(waitIntervalS*1000);
s = client.echo(s0);
for (int j=0; j<numberOfTokens-1; ++j)
{
//ok = RCF::createRemoteObject<I_Echo>(client, "Echo");
ok = tryCreateRemoteObject<I_Echo>(client, "Echo");
BOOST_CHECK(ok);
}
//ok = RCF::createRemoteObject<I_Echo>(client, "Echo");
ok = tryCreateRemoteObject<I_Echo>(client, "Echo");
BOOST_CHECK(!ok);
std::cout << "Waiting for " << waitIntervalS << " seconds...\n";
Platform::OS::Sleep(waitIntervalS);
exhaustTokenSpace(numberOfTokens, client);
server.removeService(objectFactoryServicePtr);
server.addService(objectFactoryServicePtr);
std::cout << "Waiting for " << waitIntervalS << " seconds...\n";
Platform::OS::Sleep(waitIntervalS);
exhaustTokenSpace(numberOfTokens, client);
server.removeService(objectFactoryServicePtr);
objectFactoryServicePtr.reset( new RCF::ObjectFactoryService(
numberOfTokens, clientStubTimeoutS, cleanupIntervalS) );
objectFactoryServicePtr->bind( (I_Echo*) 0, (Echo**) 0, "Echo");
server.addService(objectFactoryServicePtr);
std::cout << "Waiting for " << waitIntervalS << " seconds...\n";
Platform::OS::Sleep(waitIntervalS);
exhaustTokenSpace(numberOfTokens, client);
}
{
// try moving an object factory service from one server to another
RCF::ObjectFactoryServicePtr objectFactoryServicePtr(
new RCF::ObjectFactoryService(
numberOfTokens, clientStubTimeoutS, cleanupIntervalS));
objectFactoryServicePtr->bind( (I_Echo*) 0, (Echo**) 0, "Echo");
std::string ip = "localhost";
int port1 = util::PortNumbers::getSingleton().getNext();
int port2 = util::PortNumbers::getSingleton().getNext();
int val = 17;
RCF::Token token;
{
RCF::TcpEndpoint endpoint(port1);
RCF::RcfServer server(endpoint);
server.start();
server.addService(objectFactoryServicePtr);
RcfClient<I_Echo> client( RCF::ClientTransportAutoPtr( new RCF::TcpClientTransport("127.0.0.1", port1)));
bool ok = tryCreateRemoteObject<I_Echo>(client, "Echo");
BOOST_CHECK(ok);
token = client.getClientStub().getTargetToken();
client.setVal(val);
exhaustTokenSpace(numberOfTokens-1, client);
}
{
RCF::TcpEndpoint endpoint(port2);
RCF::RcfServer server(endpoint);
server.start();
server.addService(objectFactoryServicePtr);
{
RcfClient<I_Echo> client( RCF::ClientTransportAutoPtr( new RCF::TcpClientTransport("127.0.0.1", port2)));
client.getClientStub().setTargetToken(token);
int myVal = client.getVal();
BOOST_CHECK(val == myVal);
}
Platform::OS::Sleep(waitIntervalS);
try
{
// the server object should have been cleaned up by now, so the next call
// should result in an exception
RcfClient<I_Echo> client( RCF::ClientTransportAutoPtr( new RCF::TcpClientTransport("127.0.0.1", port2)));
client.getClientStub().setTargetToken(token);
int myVal = client.getVal();
BOOST_CHECK(1==0);
}
catch(const RCF::Exception &e)
{
std::string strErr = RCF::getErrorString(e.getError());
std::string what = e.what();
std::string context = e.getContext();
BOOST_CHECK(1==1);
}
}
}
// faceted objects
// TODO: testing of
// 1) heavy concurrent access to different interfaces
// 2) user friendly reporting of interface-not-found errors
{
RCF::ObjectFactoryServicePtr objectFactoryServicePtr(
new RCF::ObjectFactoryService(
numberOfTokens, 60, cleanupIntervalS));
objectFactoryServicePtr->bind( (I_Echo*) 0, (Echo**) 0, "Echo");
objectFactoryServicePtr->bind( (I_Echo*) 0, (I_X1*) 0, (Echo**) 0, "Echo");
objectFactoryServicePtr->bind( (I_Echo*) 0, (I_X1*) 0, (I_X2*) 0, (Echo**) 0, "Echo");
objectFactoryServicePtr->bind( (I_Echo*) 0, (I_X1*) 0, (I_X2*) 0, (I_X3*) 0, (Echo**) 0, "Echo");
std::string ip = "localhost";
int port1 = util::PortNumbers::getSingleton().getNext();
int nVal = 17;
bool bVal = true;
double dVal = 3.14;
std::string sVal = "seventeen";
RCF::Token token;
RCF::TcpEndpoint endpoint(port1);
RCF::RcfServer server(endpoint);
server.start();
server.addService(objectFactoryServicePtr);
{
RcfClient<I_Echo> client(
RCF::ClientTransportAutoPtr(
new RCF::TcpClientTransport("127.0.0.1", port1)));
bool ok = tryCreateRemoteObject<I_Echo>(client, "Echo");
BOOST_CHECK(ok);
token = client.getClientStub().getTargetToken();
}
{
RcfClient<I_Echo> client(
RCF::ClientTransportAutoPtr(
new RCF::TcpClientTransport("127.0.0.1", port1)));
client.getClientStub().setTargetToken(token);
client.setVal(nVal);
BOOST_CHECK(client.getVal() == nVal);
}
{
RcfClient<I_X1> client(
RCF::ClientTransportAutoPtr(
new RCF::TcpClientTransport("127.0.0.1", port1)));
client.getClientStub().setTargetToken(token);
client.setVal(bVal);
BOOST_CHECK(client.getVal(bool()) == bVal);
}
{
RcfClient<I_X2> client(
RCF::ClientTransportAutoPtr(
new RCF::TcpClientTransport("127.0.0.1", port1)));
client.getClientStub().setTargetToken(token);
client.setVal(dVal);
BOOST_CHECK(client.getVal(double()) == dVal);
}
{
RcfClient<I_X3> client(
RCF::ClientTransportAutoPtr(
new RCF::TcpClientTransport("127.0.0.1", port1)));
client.getClientStub().setTargetToken(token);
client.setVal(sVal);
BOOST_CHECK(client.getVal(std::string()) == sVal);
}
{
// test deletion of remote objects
RcfClient<I_X3> client(
RCF::ClientTransportAutoPtr(
new RCF::TcpClientTransport("127.0.0.1", port1)));
client.getClientStub().setTargetToken(token);
client.setVal(sVal);
BOOST_CHECK(client.getVal(std::string()) == sVal);
//RCF::deleteRemoteObject(client);
client.getClientStub().deleteRemoteObject();
try
{
client.getVal(std::string());
BOOST_CHECK(1==0);
}
catch(const RCF::Exception &)
{
BOOST_CHECK(1==1);
}
//RCF::createRemoteSessionObject<I_X3>(client, "Echo");
client.getClientStub().createRemoteSessionObject("Echo");
client.setVal(sVal);
BOOST_CHECK(client.getVal(std::string()) == sVal);
//RCF::deleteRemoteSessionObject(client);
client.getClientStub().deleteRemoteSessionObject();
try
{
client.getVal(std::string());
BOOST_CHECK(1==0);
}
catch(const RCF::Exception &)
{
BOOST_CHECK(1==1);
}
}
}
return boost::exit_success;
}