|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#include "xmlrpc_config.h" |
|
|
|
|
|
#if MSVCRT |
|
|
#include <winsock2.h> |
|
|
#include <io.h> |
|
|
#else |
|
|
#include <unistd.h> |
|
|
#include <sys/socket.h> |
|
|
#include <arpa/inet.h> |
|
|
#include <netinet/in.h> |
|
|
#endif |
|
|
|
|
|
#include <errno.h> |
|
|
#include <string> |
|
|
#include <cstring> |
|
|
#include <fcntl.h> |
|
|
|
|
|
#include "xmlrpc-c/config.h" |
|
|
|
|
|
#if MSVCRT |
|
|
int |
|
|
xmlrpc_win32_socketpair(int const domain, |
|
|
int const type, |
|
|
int const protocol, |
|
|
SOCKET socks[2]); |
|
|
#endif |
|
|
|
|
|
#include "xmlrpc-c/girerr.hpp" |
|
|
using girerr::error; |
|
|
using girerr::throwf; |
|
|
#include "xmlrpc-c/sleep_int.h" |
|
|
#include "xmlrpc-c/base.hpp" |
|
|
#include "xmlrpc-c/registry.hpp" |
|
|
#include "xmlrpc-c/server_pstream.hpp" |
|
|
|
|
|
#include "tools.hpp" |
|
|
#include "server_pstream.hpp" |
|
|
|
|
|
using namespace xmlrpc_c; |
|
|
using namespace std; |
|
|
|
|
|
|
|
|
namespace { |
|
|
|
|
|
static void |
|
|
setNonBlocking(XMLRPC_SOCKET const socket) { |
|
|
|
|
|
#if MSVCRT |
|
|
u_long iMode = 1; |
|
|
ioctlsocket(socket, FIONBIO, &iMode); |
|
|
#else |
|
|
fcntl(socket, F_SETFL, O_NONBLOCK); |
|
|
#endif |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
#define ESC_STR "\x1B" |
|
|
|
|
|
|
|
|
static string const |
|
|
xmlPrologue("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\r\n"); |
|
|
|
|
|
static string const |
|
|
packetStart(ESC_STR "PKT"); |
|
|
|
|
|
static string const |
|
|
packetEnd(ESC_STR "END"); |
|
|
|
|
|
|
|
|
class callInfo_test : public callInfo { |
|
|
public: |
|
|
callInfo_test() : info("this is a test") {} |
|
|
string const info; |
|
|
}; |
|
|
|
|
|
|
|
|
|
|
|
class sampleAddMethod : public method { |
|
|
public: |
|
|
sampleAddMethod() { |
|
|
this->_signature = "i:ii"; |
|
|
this->_help = "This method adds two integers together"; |
|
|
} |
|
|
void |
|
|
execute(xmlrpc_c::paramList const& paramList, |
|
|
value * const retvalP) { |
|
|
|
|
|
int const addend(paramList.getInt(0)); |
|
|
int const adder(paramList.getInt(1)); |
|
|
|
|
|
paramList.verifyEnd(2); |
|
|
|
|
|
*retvalP = value_int(addend + adder); |
|
|
} |
|
|
}; |
|
|
|
|
|
string const sampleAddCallXml( |
|
|
xmlPrologue + |
|
|
"<methodCall>\r\n" |
|
|
"<methodName>sample.add</methodName>\r\n" |
|
|
"<params>\r\n" |
|
|
"<param><value><i4>5</i4></value></param>\r\n" |
|
|
"<param><value><i4>7</i4></value></param>\r\n" |
|
|
"</params>\r\n" |
|
|
"</methodCall>\r\n" |
|
|
); |
|
|
|
|
|
string const sampleAddResponseXml( |
|
|
xmlPrologue + |
|
|
"<methodResponse>\r\n" |
|
|
"<params>\r\n" |
|
|
"<param><value><i4>12</i4></value></param>\r\n" |
|
|
"</params>\r\n" |
|
|
"</methodResponse>\r\n" |
|
|
); |
|
|
|
|
|
|
|
|
class testCallInfoMethod : public method2 { |
|
|
|
|
|
public: |
|
|
virtual void |
|
|
execute(paramList const& paramList, |
|
|
const callInfo * const callInfoPtr, |
|
|
value * const retvalP) { |
|
|
|
|
|
const callInfo_test * const callInfoP( |
|
|
dynamic_cast<const callInfo_test *>(callInfoPtr)); |
|
|
|
|
|
TEST(callInfoP != NULL); |
|
|
|
|
|
paramList.verifyEnd(0); |
|
|
|
|
|
TEST(callInfoP->info == string("this is a test")); |
|
|
|
|
|
*retvalP = value_nil(); |
|
|
} |
|
|
}; |
|
|
|
|
|
string const testCallInfoCallXml( |
|
|
xmlPrologue + |
|
|
"<methodCall>\r\n" |
|
|
"<methodName>test.callinfo</methodName>\r\n" |
|
|
"<params>\r\n" |
|
|
"</params>\r\n" |
|
|
"</methodCall>\r\n" |
|
|
); |
|
|
|
|
|
string const testCallInfoResponseXml( |
|
|
xmlPrologue + |
|
|
"<methodResponse>\r\n" |
|
|
"<params>\r\n" |
|
|
"<param><value><nil/></value>" |
|
|
"</param>\r\n" |
|
|
"</params>\r\n" |
|
|
"</methodResponse>\r\n" |
|
|
); |
|
|
|
|
|
|
|
|
|
|
|
static void |
|
|
waitForNetworkTransport() { |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
xmlrpc_millisecond_sleep(50); |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
class client { |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
public: |
|
|
|
|
|
client(); |
|
|
|
|
|
~client(); |
|
|
|
|
|
void |
|
|
sendCall(string const& callBytes) const; |
|
|
|
|
|
void |
|
|
hangup(); |
|
|
|
|
|
void |
|
|
recvResp(string * const respBytesP) const; |
|
|
|
|
|
int serverFd; |
|
|
|
|
|
private: |
|
|
|
|
|
int clientFd; |
|
|
}; |
|
|
|
|
|
|
|
|
|
|
|
client::client() { |
|
|
|
|
|
enum { |
|
|
SERVER = 0, |
|
|
CLIENT = 1, |
|
|
}; |
|
|
XMLRPC_SOCKET sockets[2]; |
|
|
int rc; |
|
|
|
|
|
rc = XMLRPC_SOCKETPAIR(AF_UNIX, SOCK_STREAM, 0, sockets); |
|
|
|
|
|
if (rc < 0) |
|
|
throwf("Failed to create UNIX domain stream socket pair " |
|
|
"as test tool. errno=%d (%s)", |
|
|
errno, strerror(errno)); |
|
|
else { |
|
|
setNonBlocking(sockets[CLIENT]); |
|
|
|
|
|
this->serverFd = sockets[SERVER]; |
|
|
this->clientFd = sockets[CLIENT]; |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
client::~client() { |
|
|
|
|
|
XMLRPC_CLOSESOCKET(this->clientFd); |
|
|
XMLRPC_CLOSESOCKET(this->serverFd); |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
void |
|
|
client::sendCall(string const& packetBytes) const { |
|
|
|
|
|
int rc; |
|
|
|
|
|
rc = send(this->clientFd, packetBytes.c_str(), packetBytes.length(), 0); |
|
|
|
|
|
waitForNetworkTransport(); |
|
|
|
|
|
if (rc < 0) |
|
|
throwf("send() of test data to socket failed, errno=%d (%s)", |
|
|
errno, strerror(errno)); |
|
|
else { |
|
|
unsigned int bytesWritten(rc); |
|
|
|
|
|
if (bytesWritten != packetBytes.length()) |
|
|
throwf("Short write to socket"); |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
void |
|
|
client::hangup() { |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
shutdown(this->clientFd, 1); |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
void |
|
|
client::recvResp(string * const packetBytesP) const { |
|
|
|
|
|
char buffer[4096]; |
|
|
int rc; |
|
|
|
|
|
waitForNetworkTransport(); |
|
|
|
|
|
rc = recv(this->clientFd, buffer, sizeof(buffer), 0); |
|
|
|
|
|
if (rc < 0) |
|
|
throwf("recv() from socket failed, errno=%d (%s)", |
|
|
errno, strerror(errno)); |
|
|
else { |
|
|
unsigned int bytesReceived(rc); |
|
|
|
|
|
*packetBytesP = string(buffer, bytesReceived); |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
static void |
|
|
testEmptyStream(registry const& myRegistry) { |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
client client; |
|
|
|
|
|
serverPstreamConn server(serverPstreamConn::constrOpt() |
|
|
.registryP(&myRegistry) |
|
|
.socketFd(client.serverFd)); |
|
|
|
|
|
client.hangup(); |
|
|
|
|
|
bool eof; |
|
|
server.runOnce(&eof); |
|
|
|
|
|
TEST(eof); |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
static void |
|
|
testBrokenPacket(registry const& myRegistry) { |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
client client; |
|
|
|
|
|
serverPstreamConn server(serverPstreamConn::constrOpt() |
|
|
.registryP(&myRegistry) |
|
|
.socketFd(client.serverFd)); |
|
|
|
|
|
client.sendCall("junk"); |
|
|
client.hangup(); |
|
|
|
|
|
bool eof; |
|
|
|
|
|
EXPECT_ERROR( |
|
|
server.runOnce(&eof); |
|
|
); |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
static void |
|
|
testEmptyPacket(registry const& myRegistry) { |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
client client; |
|
|
|
|
|
serverPstreamConn server(serverPstreamConn::constrOpt() |
|
|
.registryP(&myRegistry) |
|
|
.socketFd(client.serverFd)); |
|
|
|
|
|
client.sendCall(packetStart + packetEnd); |
|
|
|
|
|
bool eof; |
|
|
server.runOnce(&eof); |
|
|
|
|
|
TEST(!eof); |
|
|
|
|
|
string response; |
|
|
client.recvResp(&response); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
client.hangup(); |
|
|
|
|
|
server.runOnce(&eof); |
|
|
|
|
|
TEST(eof); |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
static void |
|
|
testCallInfo(client * const clientP, |
|
|
serverPstreamConn * const serverP) { |
|
|
|
|
|
string const testCallInfoCallStream( |
|
|
packetStart + testCallInfoCallXml + packetEnd |
|
|
); |
|
|
|
|
|
string const testCallInfoResponseStream( |
|
|
packetStart + testCallInfoResponseXml + packetEnd |
|
|
); |
|
|
|
|
|
clientP->sendCall(testCallInfoCallStream); |
|
|
|
|
|
callInfo_test callInfo; |
|
|
int nointerrupt(0); |
|
|
bool eof; |
|
|
serverP->runOnce(&callInfo, &nointerrupt, &eof); |
|
|
|
|
|
TEST(!eof); |
|
|
|
|
|
string response; |
|
|
clientP->recvResp(&response); |
|
|
|
|
|
TEST(response == testCallInfoResponseStream); |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
static void |
|
|
testNormalCall(registry const& myRegistry) { |
|
|
|
|
|
string const sampleAddGoodCallStream( |
|
|
packetStart + sampleAddCallXml + packetEnd |
|
|
); |
|
|
|
|
|
string const sampleAddGoodResponseStream( |
|
|
packetStart + sampleAddResponseXml + packetEnd |
|
|
); |
|
|
|
|
|
client client; |
|
|
|
|
|
serverPstreamConn server(serverPstreamConn::constrOpt() |
|
|
.registryP(&myRegistry) |
|
|
.socketFd(client.serverFd)); |
|
|
|
|
|
client.sendCall(sampleAddGoodCallStream); |
|
|
|
|
|
bool eof; |
|
|
|
|
|
int interrupt(1); |
|
|
server.runOnce(&interrupt, &eof); |
|
|
TEST(!eof); |
|
|
|
|
|
server.runOnce(&eof); |
|
|
|
|
|
TEST(!eof); |
|
|
|
|
|
string response; |
|
|
client.recvResp(&response); |
|
|
|
|
|
TEST(response == sampleAddGoodResponseStream); |
|
|
|
|
|
testCallInfo(&client, &server); |
|
|
|
|
|
client.hangup(); |
|
|
|
|
|
server.runOnce(&eof); |
|
|
|
|
|
TEST(eof); |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
static void |
|
|
testNoWaitCall(registry const& myRegistry) { |
|
|
|
|
|
string const sampleAddGoodCallStream( |
|
|
packetStart + |
|
|
xmlPrologue + |
|
|
"<methodCall>\r\n" |
|
|
"<methodName>sample.add</methodName>\r\n" |
|
|
"<params>\r\n" |
|
|
"<param><value><i4>5</i4></value></param>\r\n" |
|
|
"<param><value><i4>7</i4></value></param>\r\n" |
|
|
"</params>\r\n" |
|
|
"</methodCall>\r\n" + |
|
|
packetEnd |
|
|
); |
|
|
|
|
|
|
|
|
string const sampleAddGoodResponseStream( |
|
|
packetStart + |
|
|
xmlPrologue + |
|
|
"<methodResponse>\r\n" |
|
|
"<params>\r\n" |
|
|
"<param><value><i4>12</i4></value></param>\r\n" |
|
|
"</params>\r\n" |
|
|
"</methodResponse>\r\n" + |
|
|
packetEnd |
|
|
); |
|
|
|
|
|
client client; |
|
|
|
|
|
serverPstreamConn server(serverPstreamConn::constrOpt() |
|
|
.registryP(&myRegistry) |
|
|
.socketFd(client.serverFd)); |
|
|
|
|
|
bool eof; |
|
|
bool gotOne; |
|
|
string response; |
|
|
|
|
|
server.runOnceNoWait(&eof, &gotOne); |
|
|
|
|
|
TEST(!eof); |
|
|
TEST(!gotOne); |
|
|
|
|
|
server.runOnceNoWait(&eof); |
|
|
|
|
|
TEST(!eof); |
|
|
|
|
|
client.sendCall(sampleAddGoodCallStream); |
|
|
|
|
|
server.runOnceNoWait(&eof, &gotOne); |
|
|
|
|
|
TEST(!eof); |
|
|
TEST(gotOne); |
|
|
|
|
|
client.recvResp(&response); |
|
|
|
|
|
TEST(response == sampleAddGoodResponseStream); |
|
|
|
|
|
client.sendCall(sampleAddGoodCallStream); |
|
|
|
|
|
server.runOnce(&eof); |
|
|
|
|
|
TEST(!eof); |
|
|
client.recvResp(&response); |
|
|
TEST(response == sampleAddGoodResponseStream); |
|
|
|
|
|
client.hangup(); |
|
|
|
|
|
server.runOnce(&eof); |
|
|
|
|
|
TEST(eof); |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
static void |
|
|
testMultiRpcRunNoRpc(registry const& myRegistry) { |
|
|
|
|
|
client client; |
|
|
|
|
|
serverPstreamConn server(serverPstreamConn::constrOpt() |
|
|
.registryP(&myRegistry) |
|
|
.socketFd(client.serverFd)); |
|
|
|
|
|
client.hangup(); |
|
|
|
|
|
server.run(); |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
static void |
|
|
testMultiRpcRunOneRpc(registry const& myRegistry) { |
|
|
|
|
|
string const sampleAddGoodCallStream( |
|
|
packetStart + |
|
|
xmlPrologue + |
|
|
"<methodCall>\r\n" |
|
|
"<methodName>sample.add</methodName>\r\n" |
|
|
"<params>\r\n" |
|
|
"<param><value><i4>5</i4></value></param>\r\n" |
|
|
"<param><value><i4>7</i4></value></param>\r\n" |
|
|
"</params>\r\n" |
|
|
"</methodCall>\r\n" + |
|
|
packetEnd |
|
|
); |
|
|
|
|
|
|
|
|
string const sampleAddGoodResponseStream( |
|
|
packetStart + |
|
|
xmlPrologue + |
|
|
"<methodResponse>\r\n" |
|
|
"<params>\r\n" |
|
|
"<param><value><i4>12</i4></value></param>\r\n" |
|
|
"</params>\r\n" |
|
|
"</methodResponse>\r\n" + |
|
|
packetEnd |
|
|
); |
|
|
|
|
|
client client; |
|
|
|
|
|
serverPstreamConn server(serverPstreamConn::constrOpt() |
|
|
.registryP(&myRegistry) |
|
|
.socketFd(client.serverFd)); |
|
|
|
|
|
|
|
|
client.sendCall(sampleAddGoodCallStream); |
|
|
client.hangup(); |
|
|
|
|
|
int interrupt; |
|
|
|
|
|
interrupt = 1; |
|
|
server.run(&interrupt); |
|
|
|
|
|
interrupt = 0; |
|
|
server.run(&interrupt); |
|
|
|
|
|
string response; |
|
|
client.recvResp(&response); |
|
|
|
|
|
TEST(response == sampleAddGoodResponseStream); |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
class serverPstreamConnTestSuite : public testSuite { |
|
|
|
|
|
public: |
|
|
virtual string suiteName() { |
|
|
return "serverPstreamConnTestSuite"; |
|
|
} |
|
|
virtual void runtests(unsigned int const) { |
|
|
registry myRegistry; |
|
|
|
|
|
myRegistry.addMethod("sample.add", |
|
|
methodPtr(new sampleAddMethod)); |
|
|
myRegistry.addMethod("test.callinfo", |
|
|
methodPtr(new testCallInfoMethod)); |
|
|
|
|
|
registryPtr myRegistryP(new registry); |
|
|
|
|
|
myRegistryP->addMethod("sample.add", methodPtr(new sampleAddMethod)); |
|
|
|
|
|
EXPECT_ERROR( |
|
|
serverPstreamConn::constrOpt opt; |
|
|
serverPstreamConn server(opt); |
|
|
); |
|
|
|
|
|
EXPECT_ERROR( |
|
|
serverPstreamConn server(serverPstreamConn::constrOpt() |
|
|
.socketFd(3)); |
|
|
); |
|
|
|
|
|
EXPECT_ERROR( |
|
|
serverPstreamConn server(serverPstreamConn::constrOpt() |
|
|
.registryP(&myRegistry)); |
|
|
); |
|
|
|
|
|
testEmptyStream(myRegistry); |
|
|
|
|
|
testBrokenPacket(myRegistry); |
|
|
|
|
|
testEmptyPacket(myRegistry); |
|
|
|
|
|
testNormalCall(myRegistry); |
|
|
|
|
|
testNoWaitCall(myRegistry); |
|
|
|
|
|
testMultiRpcRunNoRpc(myRegistry); |
|
|
|
|
|
testMultiRpcRunOneRpc(myRegistry); |
|
|
} |
|
|
}; |
|
|
|
|
|
|
|
|
|
|
|
static void |
|
|
testMultiConnInterrupt(registry const& myRegistry) { |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
serverPstream server(serverPstream::constrOpt() |
|
|
.registryP(&myRegistry) |
|
|
.socketFd(37)); |
|
|
|
|
|
int interrupt(1); |
|
|
|
|
|
server.runSerial(&interrupt); |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
class derivedServer : public xmlrpc_c::serverPstream { |
|
|
public: |
|
|
derivedServer(serverPstream::constrOpt const& constrOpt) : |
|
|
serverPstream(constrOpt), |
|
|
info("this is my derived server") {} |
|
|
|
|
|
string const info; |
|
|
}; |
|
|
|
|
|
|
|
|
|
|
|
class multiTestCallInfoMethod : public method2 { |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
public: |
|
|
virtual void |
|
|
execute(paramList const& paramList, |
|
|
const callInfo * const callInfoPtr, |
|
|
value * const retvalP) { |
|
|
|
|
|
const callInfo_serverPstream * const callInfoP( |
|
|
dynamic_cast<const callInfo_serverPstream *>(callInfoPtr)); |
|
|
|
|
|
TEST(callInfoP != NULL); |
|
|
|
|
|
paramList.verifyEnd(0); |
|
|
|
|
|
derivedServer * const derivedServerP( |
|
|
dynamic_cast<derivedServer *>(callInfoP->serverP)); |
|
|
|
|
|
TEST(derivedServerP->info == string("this is my derived server")); |
|
|
|
|
|
TEST(callInfoP->clientAddr.sa_family == AF_INET); |
|
|
TEST(callInfoP->clientAddrSize >= sizeof(struct sockaddr_in)); |
|
|
|
|
|
*retvalP = value_nil(); |
|
|
} |
|
|
}; |
|
|
|
|
|
static void |
|
|
testMultiConnCallInfo() { |
|
|
|
|
|
registry myRegistry; |
|
|
|
|
|
myRegistry.addMethod("testCallInfo", |
|
|
methodPtr(new multiTestCallInfoMethod)); |
|
|
|
|
|
derivedServer server(serverPstream::constrOpt() |
|
|
.registryP(&myRegistry) |
|
|
.socketFd(37)); |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
class multiConnServerTestSuite : public testSuite { |
|
|
|
|
|
public: |
|
|
virtual string suiteName() { |
|
|
return "multiConnServerTestSuite"; |
|
|
} |
|
|
virtual void runtests(unsigned int const) { |
|
|
registry myRegistry; |
|
|
|
|
|
myRegistry.addMethod("sample.add", |
|
|
methodPtr(new sampleAddMethod)); |
|
|
|
|
|
registryPtr myRegistryP(new registry); |
|
|
|
|
|
myRegistryP->addMethod("sample.add", methodPtr(new sampleAddMethod)); |
|
|
|
|
|
EXPECT_ERROR( |
|
|
serverPstream::constrOpt opt; |
|
|
serverPstream server(opt); |
|
|
); |
|
|
|
|
|
EXPECT_ERROR( |
|
|
serverPstream server(serverPstream::constrOpt() |
|
|
.socketFd(3)); |
|
|
); |
|
|
|
|
|
EXPECT_ERROR( |
|
|
serverPstream server(serverPstream::constrOpt() |
|
|
.registryP(&myRegistry)); |
|
|
); |
|
|
|
|
|
testMultiConnInterrupt(myRegistry); |
|
|
|
|
|
testMultiConnCallInfo(); |
|
|
} |
|
|
}; |
|
|
|
|
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
string |
|
|
serverPstreamTestSuite::suiteName() { |
|
|
return "serverPstreamTestSuite"; |
|
|
} |
|
|
|
|
|
|
|
|
void |
|
|
serverPstreamTestSuite::runtests(unsigned int const indentation) { |
|
|
|
|
|
serverPstreamConnTestSuite().run(indentation + 1); |
|
|
|
|
|
multiConnServerTestSuite().run(indentation + 1); |
|
|
} |
|
|
|
|
|
|