manual merge
This commit is contained in:
@@ -3,7 +3,7 @@
|
||||
SRC_DIRS += $(PVACCESS_TEST)/remote
|
||||
|
||||
TESTPROD_HOST += testChannelAccess
|
||||
testChannelAccess_SRCS = testChannelAccess channelAccessIFTest
|
||||
testChannelAccess_SRCS = channelAccessIFTest.cpp
|
||||
testHarness_SRCS += testChannelAccess.cpp channelAccessIFTest.cpp
|
||||
TESTS += testChannelAccess
|
||||
|
||||
@@ -48,3 +48,5 @@ rpcClientExample_SRCS += rpcClientExample.cpp
|
||||
PROD_HOST += pipelineServiceExample
|
||||
pipelineServiceExample_SRCS += pipelineServiceExample.cpp
|
||||
|
||||
TESTPROD_HOST += testClientFactory
|
||||
testClientFactory_SRCS += testClientFactory.cpp
|
||||
|
||||
@@ -21,6 +21,9 @@
|
||||
#include "channelAccessIFTest.h"
|
||||
|
||||
//#define ENABLE_STRESS_TESTS
|
||||
#define TESTSERVERNOMAIN
|
||||
|
||||
#include "testServer.cpp"
|
||||
|
||||
using namespace std::tr1;
|
||||
|
||||
@@ -38,14 +41,45 @@ std::string ChannelAccessIFTest::TEST_SUMRPC_CHANNEL_NAME = "testSum";
|
||||
// double[] value
|
||||
std::string ChannelAccessIFTest::TEST_ARRAY_CHANNEL_NAME = "testArray1";
|
||||
|
||||
#ifdef ENABLE_STRESS_TESTS
|
||||
#define EXTRA_STRESS_TESTS 5
|
||||
#else
|
||||
#define EXTRA_STRESS_TESTS 0
|
||||
#endif
|
||||
|
||||
namespace {
|
||||
struct ScopedClientFactory {
|
||||
ScopedClientFactory() { ClientFactory::start(); }
|
||||
~ScopedClientFactory() { ClientFactory::stop(); }
|
||||
};
|
||||
}
|
||||
|
||||
int ChannelAccessIFTest::runAllTest() {
|
||||
|
||||
#ifdef ENABLE_STRESS_TESTS
|
||||
testPlan(158);
|
||||
#else
|
||||
testPlan(153);
|
||||
#endif
|
||||
testPlan(153+EXTRA_STRESS_TESTS);
|
||||
|
||||
Configuration::shared_pointer base_config(ConfigurationBuilder()
|
||||
//.add("EPICS_PVA_DEBUG", "3")
|
||||
.add("EPICS_PVAS_INTF_ADDR_LIST", "127.0.0.1")
|
||||
.add("EPICS_PVA_ADDR_LIST", "127.0.0.1")
|
||||
.add("EPICS_PVA_AUTO_ADDR_LIST","0")
|
||||
.add("EPICS_PVA_SERVER_PORT", "0")
|
||||
.add("EPICS_PVA_BROADCAST_PORT", "0")
|
||||
.push_map()
|
||||
.build());
|
||||
|
||||
TestServer::shared_pointer tstserv(new TestServer(base_config));
|
||||
tstserv->start();
|
||||
testDiag("TestServer on ports TCP=%u UDP=%u\n",
|
||||
tstserv->getServerPort(),
|
||||
tstserv->getBroadcastPort());
|
||||
ConfigurationFactory::registerConfiguration("pvAccess-client",
|
||||
ConfigurationBuilder()
|
||||
.push_config(base_config)
|
||||
.add("EPICS_PVA_BROADCAST_PORT", tstserv->getBroadcastPort())
|
||||
.push_map()
|
||||
.build());
|
||||
ScopedClientFactory SCF;
|
||||
|
||||
test_implementation();
|
||||
test_providerName();
|
||||
@@ -2348,3 +2382,30 @@ PVStructure::shared_pointer ChannelAccessIFTest::createArrayPvRequest() {
|
||||
pvFieldName->put("value");
|
||||
return pvRequest;
|
||||
}
|
||||
|
||||
|
||||
class ChannelAccessIFRemoteTest: public ChannelAccessIFTest {
|
||||
|
||||
public:
|
||||
|
||||
virtual ChannelProvider::shared_pointer getChannelProvider() {
|
||||
return getChannelProviderRegistry()->getProvider(
|
||||
"pva");
|
||||
}
|
||||
|
||||
|
||||
virtual long getTimeoutSec() {
|
||||
return 3;
|
||||
}
|
||||
|
||||
|
||||
virtual bool isLocal() { return false;}
|
||||
|
||||
};
|
||||
|
||||
MAIN(testChannelAccess)
|
||||
{
|
||||
SET_LOG_LEVEL(logLevelError);
|
||||
ChannelAccessIFRemoteTest caRemoteTest;
|
||||
return caRemoteTest.runAllTest();
|
||||
}
|
||||
|
||||
@@ -1,104 +0,0 @@
|
||||
/*
|
||||
* testChannelAccess.cpp
|
||||
*/
|
||||
|
||||
#ifdef _WIN32
|
||||
#define NOMINMAX
|
||||
#endif
|
||||
|
||||
// TODO not nice
|
||||
// disable buggy boost enable_shared_from_this assert code
|
||||
#define BOOST_DISABLE_ASSERTS
|
||||
|
||||
#define TESTSERVERNOMAIN
|
||||
|
||||
#include <envDefs.h>
|
||||
#include <epicsExit.h>
|
||||
#include <epicsUnitTest.h>
|
||||
#include <testMain.h>
|
||||
|
||||
#include <pv/serverContext.h>
|
||||
#include <pv/clientFactory.h>
|
||||
|
||||
#include "channelAccessIFTest.h"
|
||||
|
||||
#include "testServer.cpp"
|
||||
|
||||
|
||||
class ServerContextAction : public Runnable {
|
||||
|
||||
public:
|
||||
|
||||
ServerContextAction():
|
||||
m_serverThread(){}
|
||||
|
||||
|
||||
virtual void run()
|
||||
{
|
||||
testServer(0);
|
||||
}
|
||||
|
||||
|
||||
void stop() {
|
||||
testServerShutdown();
|
||||
}
|
||||
|
||||
|
||||
void start() {
|
||||
m_serverThread.reset(new epics::pvData::Thread("pvAccess", highPriority, this));
|
||||
}
|
||||
|
||||
|
||||
private:
|
||||
auto_ptr<epics::pvData::Thread> m_serverThread;
|
||||
};
|
||||
|
||||
|
||||
class ChannelAccessIFRemoteTest: public ChannelAccessIFTest {
|
||||
|
||||
public:
|
||||
|
||||
ChannelAccessIFRemoteTest(): m_serverContextAction()
|
||||
{
|
||||
m_serverContextAction.start();
|
||||
ClientFactory::start();
|
||||
}
|
||||
|
||||
|
||||
virtual ChannelProvider::shared_pointer getChannelProvider() {
|
||||
return getChannelProviderRegistry()->getProvider(
|
||||
"pva");
|
||||
}
|
||||
|
||||
|
||||
virtual long getTimeoutSec() {
|
||||
return 3;
|
||||
}
|
||||
|
||||
|
||||
virtual bool isLocal() { return false;}
|
||||
|
||||
|
||||
~ChannelAccessIFRemoteTest() {
|
||||
m_serverContextAction.stop();
|
||||
ClientFactory::stop();
|
||||
|
||||
// shutdown SIGSEG problems
|
||||
epicsThreadSleep(2.0);
|
||||
}
|
||||
|
||||
private:
|
||||
ServerContextAction m_serverContextAction;
|
||||
};
|
||||
|
||||
|
||||
MAIN(testChannelAccess)
|
||||
{
|
||||
// note: this leaks memory (uses putenv)
|
||||
epicsEnvSet("EPICS_PVA_ADDR_LIST", "127.0.0.1");
|
||||
epicsEnvSet("EPICS_PVA_AUTO_ADDR_LIST", "0");
|
||||
|
||||
SET_LOG_LEVEL(logLevelError);
|
||||
ChannelAccessIFRemoteTest caRemoteTest;
|
||||
return caRemoteTest.runAllTest();
|
||||
}
|
||||
15
testApp/remote/testClientFactory.cpp
Normal file
15
testApp/remote/testClientFactory.cpp
Normal file
@@ -0,0 +1,15 @@
|
||||
#include <epicsExit.h>
|
||||
#include <pv/clientFactory.h>
|
||||
#include <pv/pvAccess.h>
|
||||
|
||||
int main()
|
||||
{
|
||||
epics::pvAccess::ClientFactory::start();
|
||||
epics::pvAccess::getChannelProviderRegistry()->getProvider("pva");
|
||||
epics::pvAccess::ClientFactory::stop();
|
||||
|
||||
//epicsThreadSleep ( 3.0 );
|
||||
//epicsExitCallAtExits();
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -22,6 +22,33 @@ namespace epics {
|
||||
|
||||
namespace pvAccess {
|
||||
|
||||
struct sender_break : public connection_closed_exception
|
||||
{
|
||||
sender_break() : connection_closed_exception("break") {}
|
||||
};
|
||||
|
||||
struct TransportSenderDisconnect: public TransportSender {
|
||||
void unlock() {}
|
||||
void lock() {}
|
||||
void send(ByteBuffer *buffer, TransportSendControl *control)
|
||||
{
|
||||
control->flush(true);
|
||||
throw sender_break();
|
||||
}
|
||||
};
|
||||
|
||||
struct TransportSenderSignal: public TransportSender {
|
||||
Event *evt;
|
||||
TransportSenderSignal(Event& evt) :evt(&evt) {}
|
||||
void unlock() {}
|
||||
void lock() {}
|
||||
void send(ByteBuffer *buffer, TransportSendControl *control)
|
||||
{
|
||||
evt->signal();
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
class PVAMessage {
|
||||
|
||||
public:
|
||||
@@ -257,13 +284,6 @@ namespace epics {
|
||||
}
|
||||
|
||||
|
||||
void endBlockedProcessSendQueue() {
|
||||
//TODO not thread safe
|
||||
_blockingProcessQueue = false;
|
||||
_sendQueue.wakeup();
|
||||
}
|
||||
|
||||
|
||||
void close() { _closedCount++; }
|
||||
|
||||
bool isOpen() { return _closedCount == 0; }
|
||||
@@ -288,6 +308,10 @@ namespace epics {
|
||||
|
||||
void sendCompleted() { _sendCompletedCount++; }
|
||||
|
||||
void breakSender() {
|
||||
enqueueSendRequest(std::tr1::shared_ptr<TransportSender>(new TransportSenderDisconnect()));
|
||||
}
|
||||
|
||||
bool terminated() { return false; }
|
||||
|
||||
void cachedSerialize(
|
||||
@@ -326,6 +350,8 @@ namespace epics {
|
||||
}
|
||||
|
||||
const osiSockAddr* getRemoteAddress() const { return 0; }
|
||||
std::string dummyRemoteName;
|
||||
const std::string& getRemoteName() const {return dummyRemoteName;}
|
||||
|
||||
epics::pvData::int8 getRevision() const
|
||||
{
|
||||
@@ -412,7 +438,7 @@ namespace epics {
|
||||
public:
|
||||
|
||||
int runAllTest() {
|
||||
testPlan(5882);
|
||||
testPlan(5883);
|
||||
testHeaderProcess();
|
||||
testInvalidHeaderMagic();
|
||||
testInvalidHeaderSegmentedInNormal();
|
||||
@@ -438,7 +464,6 @@ namespace epics {
|
||||
testSendException();
|
||||
testSendHugeMessagePartes();
|
||||
testRecipient();
|
||||
testClearSendQueue();
|
||||
testInvalidArguments();
|
||||
testDefaultModes();
|
||||
testEnqueueSendRequestExceptionThrown();
|
||||
@@ -2223,7 +2248,6 @@ namespace epics {
|
||||
"%s: codec._closedCount == 1", CURRENT_FUNCTION);
|
||||
}
|
||||
|
||||
|
||||
class TransportSenderForTestEnqueueSendRequest:
|
||||
public TransportSender {
|
||||
public:
|
||||
@@ -2290,7 +2314,10 @@ namespace epics {
|
||||
// process
|
||||
codec.enqueueSendRequest(sender);
|
||||
codec.enqueueSendRequest(sender2);
|
||||
codec.processSendQueue();
|
||||
codec.breakSender();
|
||||
try{
|
||||
codec.processSendQueue();
|
||||
}catch(sender_break&) {}
|
||||
|
||||
codec.transferToReadBuffer();
|
||||
|
||||
@@ -2430,11 +2457,16 @@ namespace epics {
|
||||
//was processed
|
||||
testOk(0 == codec._sendCompletedCount,
|
||||
"%s: 0 == codec._sendCompletedCount", CURRENT_FUNCTION);
|
||||
testOk1(!codec.sendQueueEmpty());
|
||||
|
||||
codec.processSendQueue();
|
||||
codec.breakSender();
|
||||
try{
|
||||
codec.processSendQueue();
|
||||
}catch(sender_break&) {}
|
||||
|
||||
testOk(1 == codec._sendCompletedCount,
|
||||
"%s: 1 == codec._sendCompletedCount", CURRENT_FUNCTION);
|
||||
testOk1(codec.sendQueueEmpty());
|
||||
|
||||
codec.transferToReadBuffer();
|
||||
|
||||
@@ -2483,6 +2515,13 @@ namespace epics {
|
||||
"%s: 0 == codec.getSendBuffer()->getPosition()",
|
||||
CURRENT_FUNCTION);
|
||||
|
||||
testOk1(codec.sendQueueEmpty());
|
||||
|
||||
testDiag("%u %u", (unsigned)codec._scheduleSendCount,
|
||||
(unsigned)codec._sendCompletedCount);
|
||||
testOk1(3 == codec._scheduleSendCount);
|
||||
testOk1(1 == codec._sendCompletedCount);
|
||||
|
||||
// now queue is empty and thread is right
|
||||
codec.enqueueSendRequest(sender2, PVA_MESSAGE_HEADER_SIZE);
|
||||
|
||||
@@ -2491,12 +2530,17 @@ namespace epics {
|
||||
"%s: PVA_MESSAGE_HEADER_SIZE == "
|
||||
"codec.getSendBuffer()->getPosition()",
|
||||
CURRENT_FUNCTION);
|
||||
testOk(3 == codec._scheduleSendCount,
|
||||
"%s: 3 == codec._scheduleSendCount", CURRENT_FUNCTION);
|
||||
testOk(1 == codec._sendCompletedCount,
|
||||
"%s: 1 == codec._sendCompletedCount", CURRENT_FUNCTION);
|
||||
|
||||
codec.processWrite();
|
||||
testDiag("%u %u", (unsigned)codec._scheduleSendCount,
|
||||
(unsigned)codec._sendCompletedCount);
|
||||
testOk1(4 == codec._scheduleSendCount);
|
||||
testOk1(1 == codec._sendCompletedCount);
|
||||
|
||||
codec.breakSender();
|
||||
|
||||
try{
|
||||
codec.processWrite();
|
||||
}catch(sender_break&) {}
|
||||
|
||||
testOk(2 == codec._sendCompletedCount,
|
||||
"%s: 2 == codec._sendCompletedCount", CURRENT_FUNCTION);
|
||||
@@ -2575,7 +2619,10 @@ namespace epics {
|
||||
|
||||
// process
|
||||
codec.enqueueSendRequest(sender);
|
||||
codec.processSendQueue();
|
||||
codec.breakSender();
|
||||
try{
|
||||
codec.processSendQueue();
|
||||
}catch(sender_break&) {}
|
||||
|
||||
codec.transferToReadBuffer();
|
||||
|
||||
@@ -2664,7 +2711,7 @@ namespace epics {
|
||||
|
||||
// process
|
||||
codec.enqueueSendRequest(sender);
|
||||
|
||||
codec.breakSender();
|
||||
try
|
||||
{
|
||||
codec.processSendQueue();
|
||||
@@ -2781,7 +2828,10 @@ namespace epics {
|
||||
|
||||
// process
|
||||
codec.enqueueSendRequest(sender);
|
||||
codec.processSendQueue();
|
||||
codec.breakSender();
|
||||
try{
|
||||
codec.processSendQueue();
|
||||
}catch(sender_break&) {}
|
||||
|
||||
codec.addToReadBuffer();
|
||||
|
||||
@@ -2886,37 +2936,6 @@ namespace epics {
|
||||
TestCodec &_codec;
|
||||
};
|
||||
|
||||
|
||||
void testClearSendQueue()
|
||||
{
|
||||
testDiag("BEGIN TEST %s:", CURRENT_FUNCTION);
|
||||
TestCodec codec(DEFAULT_BUFFER_SIZE,DEFAULT_BUFFER_SIZE);
|
||||
|
||||
std::tr1::shared_ptr<TransportSender> sender =
|
||||
std::tr1::shared_ptr<TransportSender>(
|
||||
new TransportSenderForTestClearSendQueue(codec));
|
||||
|
||||
std::tr1::shared_ptr<TransportSender> sender2 =
|
||||
std::tr1::shared_ptr<TransportSender>(
|
||||
new TransportSender2ForTestClearSendQueue(codec));
|
||||
|
||||
|
||||
codec.enqueueSendRequest(sender);
|
||||
codec.enqueueSendRequest(sender2);
|
||||
|
||||
codec.clearSendQueue();
|
||||
|
||||
codec.processSendQueue();
|
||||
|
||||
testOk(0 == codec.getSendBuffer()->getPosition(),
|
||||
"%s: 0 == codec.getSendBuffer()->getPosition()",
|
||||
CURRENT_FUNCTION);
|
||||
testOk(0 == codec._writeBuffer.getPosition(),
|
||||
"%s: 0 == codec._writeBuffer.getPosition()",
|
||||
CURRENT_FUNCTION);
|
||||
}
|
||||
|
||||
|
||||
void testInvalidArguments()
|
||||
{
|
||||
testDiag("BEGIN TEST %s:", CURRENT_FUNCTION);
|
||||
@@ -3128,6 +3147,7 @@ namespace epics {
|
||||
TransportSendControl* control)
|
||||
{
|
||||
_codec.putControlMessage((int8_t)0x01, 0x00112233);
|
||||
_codec.flush(true);
|
||||
}
|
||||
|
||||
private:
|
||||
@@ -3135,16 +3155,20 @@ namespace epics {
|
||||
};
|
||||
|
||||
|
||||
class ValueHolder {
|
||||
class ValueHolder : public Runnable {
|
||||
public:
|
||||
ValueHolder(
|
||||
TestCodec &testCodec,
|
||||
AtomicValue<bool> &processTreadExited):
|
||||
_testCodec(testCodec),
|
||||
_processTreadExited(processTreadExited) {}
|
||||
ValueHolder(TestCodec &testCodec):
|
||||
_testCodec(testCodec) {}
|
||||
|
||||
TestCodec &_testCodec;
|
||||
AtomicValue<bool> & _processTreadExited;
|
||||
Event waiter;
|
||||
|
||||
virtual void run() {
|
||||
waiter.signal();
|
||||
try{
|
||||
_testCodec.processSendQueue();
|
||||
}catch(sender_break&) {}
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -3155,56 +3179,40 @@ namespace epics {
|
||||
TestCodec codec(DEFAULT_BUFFER_SIZE,
|
||||
DEFAULT_BUFFER_SIZE, true);
|
||||
|
||||
_processTreadExited.getAndSet(false);
|
||||
std::tr1::shared_ptr<TransportSender> sender =
|
||||
std::tr1::shared_ptr<TransportSender>(
|
||||
new TransportSenderForTestBlockingProcessQueueTest(codec));
|
||||
|
||||
ValueHolder valueHolder(codec, _processTreadExited);
|
||||
ValueHolder valueHolder(codec);
|
||||
Event done;
|
||||
|
||||
epicsThreadCreate(
|
||||
"testBlockingProcessQueueTest-processThread",
|
||||
epicsThreadPriorityMedium,
|
||||
epicsThreadGetStackSize(
|
||||
epicsThreadStackMedium),
|
||||
CodecTest::blockingProcessQueueThread,
|
||||
&valueHolder);
|
||||
Thread thr(Thread::Config(&valueHolder)
|
||||
.name("testBlockingProcessQueueTest-processThread"));
|
||||
|
||||
epicsThreadSleep(3);
|
||||
|
||||
testOk(_processTreadExited.get() == false,
|
||||
"%s: _processTreadExited.get() == false",
|
||||
CURRENT_FUNCTION);
|
||||
valueHolder.waiter.wait();
|
||||
|
||||
// let's put something into it
|
||||
|
||||
codec.enqueueSendRequest(sender);
|
||||
codec.enqueueSendRequest(std::tr1::shared_ptr<TransportSender>(new TransportSenderSignal(done)));
|
||||
|
||||
epicsThreadSleep(1);
|
||||
testDiag("Waiting for work");
|
||||
done.wait();
|
||||
|
||||
testOk((std::size_t)PVA_MESSAGE_HEADER_SIZE ==
|
||||
codec._writeBuffer.getPosition(),
|
||||
"%s: PVA_MESSAGE_HEADER_SIZE == "
|
||||
"codec._writeBuffer.getPosition()",
|
||||
CURRENT_FUNCTION);
|
||||
"codec._writeBuffer.getPosition() (%u)",
|
||||
CURRENT_FUNCTION,
|
||||
(unsigned)codec._writeBuffer.getPosition());
|
||||
|
||||
codec.endBlockedProcessSendQueue();
|
||||
codec.breakSender();
|
||||
|
||||
epicsThreadSleep(1);
|
||||
|
||||
testOk(_processTreadExited.get() == true,
|
||||
"%s: _processTreadExited.get() == true", CURRENT_FUNCTION);
|
||||
thr.exitWait();
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
void static blockingProcessQueueThread(void *param) {
|
||||
ValueHolder *valueHolder = static_cast<ValueHolder *>(param);
|
||||
// this should block
|
||||
valueHolder->_testCodec.processSendQueue();
|
||||
valueHolder->_processTreadExited.getAndSet(true);
|
||||
}
|
||||
|
||||
AtomicValue<bool> _processTreadExited;
|
||||
};
|
||||
}
|
||||
|
||||
@@ -371,17 +371,6 @@ int main()
|
||||
{
|
||||
for (int i = 0; i < 10; i++) {
|
||||
{
|
||||
/*
|
||||
ClientContextImpl::shared_pointer context = createClientContextImpl();
|
||||
context->printInfo();
|
||||
|
||||
context->initialize();
|
||||
context->printInfo();
|
||||
|
||||
epicsThreadSleep ( SLEEP_TIME );
|
||||
|
||||
ChannelProvider::shared_pointer provider = context->getProvider();
|
||||
*/
|
||||
|
||||
ClientFactory::start();
|
||||
ChannelProvider::shared_pointer provider = getChannelProviderRegistry()->getProvider("pva");
|
||||
|
||||
@@ -1554,12 +1554,14 @@ public:
|
||||
m_channelRPCRequester->requestDone(Status::Ok, shared_from_this(), result);
|
||||
|
||||
}
|
||||
#ifndef TESTSERVERNOMAIN
|
||||
else if (channelName.find("testServerShutdown") == 0)
|
||||
{
|
||||
PVStructure::shared_pointer nullPtr;
|
||||
m_channelRPCRequester->requestDone(Status::Ok, shared_from_this(), nullPtr);
|
||||
testServerShutdown();
|
||||
}
|
||||
#endif
|
||||
else
|
||||
{
|
||||
/*
|
||||
@@ -2649,6 +2651,7 @@ public:
|
||||
{
|
||||
if (address == "local")
|
||||
{
|
||||
// this is a server instance provider, address holds remote socket IP
|
||||
if (channelName == "testCounter")
|
||||
{
|
||||
channelRequester->channelCreated(Status::Ok, m_counterChannel);
|
||||
@@ -2727,44 +2730,89 @@ public:
|
||||
|
||||
};
|
||||
|
||||
|
||||
static ServerContextImpl::shared_pointer ctx;
|
||||
|
||||
void testServer(int timeToRun)
|
||||
struct TestServer : public Runnable
|
||||
{
|
||||
POINTER_DEFINITIONS(TestServer);
|
||||
|
||||
MockChannelProviderFactory::shared_pointer factory(new MockChannelProviderFactory());
|
||||
registerChannelProviderFactory(factory);
|
||||
static TestServer::shared_pointer ctx;
|
||||
|
||||
//ServerContextImpl::shared_pointer ctx = ServerContextImpl::create();
|
||||
ctx = ServerContextImpl::create();
|
||||
ctx->initialize(getChannelProviderRegistry());
|
||||
Configuration::shared_pointer conf;
|
||||
ServerContextImpl::shared_pointer context;
|
||||
Event startup;
|
||||
Thread runner;
|
||||
MockChannelProviderFactory::shared_pointer factory;
|
||||
|
||||
ctx->printInfo();
|
||||
|
||||
ctx->run(timeToRun);
|
||||
|
||||
ctx->destroy();
|
||||
|
||||
unregisterChannelProviderFactory(factory);
|
||||
|
||||
structureChangedListeners.clear();
|
||||
TestServer(const Configuration::shared_pointer& conf)
|
||||
:conf(conf)
|
||||
,runner(Thread::Config(this).name("TestServer").autostart(false))
|
||||
,factory(new MockChannelProviderFactory())
|
||||
{
|
||||
Lock guard(structureStoreMutex);
|
||||
structureStore.clear();
|
||||
registerChannelProviderFactory(factory);
|
||||
|
||||
context = ServerContextImpl::create(conf);
|
||||
context->initialize(getChannelProviderRegistry());
|
||||
}
|
||||
void start(bool inSameThread = false)
|
||||
{
|
||||
if (inSameThread)
|
||||
{
|
||||
context->run(conf->getPropertyAsInteger("timeToRun", 0)); // default is no timeout
|
||||
}
|
||||
else
|
||||
{
|
||||
runner.start();
|
||||
startup.wait(); // wait for thread to start
|
||||
}
|
||||
}
|
||||
ctx.reset();
|
||||
|
||||
unregisterChannelProviderFactory(factory);
|
||||
~TestServer()
|
||||
{
|
||||
context->shutdown();
|
||||
runner.exitWait();
|
||||
context->destroy();
|
||||
|
||||
unregisterChannelProviderFactory(factory);
|
||||
|
||||
structureChangedListeners.clear();
|
||||
{
|
||||
Lock guard(structureStoreMutex);
|
||||
structureStore.clear();
|
||||
}
|
||||
ctx.reset();
|
||||
|
||||
unregisterChannelProviderFactory(factory);
|
||||
|
||||
|
||||
shutdownSimADCs();
|
||||
}
|
||||
shutdownSimADCs();
|
||||
}
|
||||
// Use with EPICS_PVA_SERVER_PORT==0 for dynamic port (unit-tests)
|
||||
unsigned short getServerPort()
|
||||
{
|
||||
return context->getServerPort();
|
||||
}
|
||||
unsigned short getBroadcastPort()
|
||||
{
|
||||
return context->getBroadcastPort();
|
||||
}
|
||||
virtual void run()
|
||||
{
|
||||
startup.signal();
|
||||
context->run(conf->getPropertyAsInteger("timeToRun", 0)); // default is no timeout
|
||||
}
|
||||
void waitForShutdown() {
|
||||
context->shutdown();
|
||||
}
|
||||
void shutdown() {
|
||||
context->shutdown();
|
||||
}
|
||||
};
|
||||
|
||||
TestServer::shared_pointer TestServer::ctx;
|
||||
|
||||
|
||||
void testServerShutdown()
|
||||
{
|
||||
// NOTE: this is not thread-safe TODO
|
||||
ctx->shutdown();
|
||||
TestServer::ctx->shutdown();
|
||||
}
|
||||
|
||||
#include <epicsGetopt.h>
|
||||
@@ -2789,7 +2837,7 @@ int main(int argc, char *argv[])
|
||||
int opt; /* getopt() current option */
|
||||
bool debug = false;
|
||||
bool cleanupAndReport = false;
|
||||
int timeToRun = 0;
|
||||
std::string timeToRun("0");
|
||||
|
||||
setvbuf(stdout,NULL,_IOLBF,BUFSIZ); /* Set stdout to line buffering */
|
||||
|
||||
@@ -2799,7 +2847,7 @@ int main(int argc, char *argv[])
|
||||
usage(argv);
|
||||
return 0;
|
||||
case 't': /* Print usage */
|
||||
timeToRun = atoi(optarg);
|
||||
timeToRun = optarg;
|
||||
break;
|
||||
case 'd': /* Debug log level */
|
||||
debug = true;
|
||||
@@ -2827,7 +2875,14 @@ int main(int argc, char *argv[])
|
||||
|
||||
srand ( time(NULL) );
|
||||
|
||||
testServer(timeToRun);
|
||||
TestServer::shared_pointer srv(new TestServer(ConfigurationBuilder()
|
||||
.push_env()
|
||||
.add("timeToRun", timeToRun)
|
||||
.push_map()
|
||||
.build()));
|
||||
TestServer::ctx = srv;
|
||||
srv->context->printInfo();
|
||||
srv->start(true);
|
||||
|
||||
cout << "Done" << endl;
|
||||
|
||||
|
||||
@@ -22,8 +22,6 @@ testInetAddressUtils_SYS_LIBS_WIN32 += ws2_32
|
||||
testHarness_SRCS += testInetAddressUtils.cpp
|
||||
TESTS += testInetAddressUtils
|
||||
|
||||
TESTSCRIPTS_HOST += $(TESTS:%=%.t)
|
||||
|
||||
#TESTPROD_HOST += loggerTest
|
||||
#loggerTest_SRCS += loggerTest.cpp
|
||||
#testHarness_SRCS += loggerTest.cpp
|
||||
@@ -49,3 +47,7 @@ configurationTest_SRCS += configurationTest.cpp
|
||||
configurationTest_SYS_LIBS_WIN32 += ws2_32
|
||||
#testHarness_SRCS += configurationTest.cpp
|
||||
TESTS += configurationTest
|
||||
|
||||
TESTPROD_HOST += testFairQueue
|
||||
testFairQueue_SRCS += testFairQueue
|
||||
TESTS += testFairQueue
|
||||
|
||||
@@ -14,6 +14,7 @@
|
||||
#include <epicsAssert.h>
|
||||
#include <epicsExit.h>
|
||||
#include <envDefs.h>
|
||||
#include <epicsString.h>
|
||||
#include <osiSock.h>
|
||||
|
||||
#include <epicsUnitTest.h>
|
||||
@@ -30,7 +31,58 @@ void setenv(char * a, char * b, int c)
|
||||
|
||||
using namespace epics::pvAccess;
|
||||
using namespace epics::pvData;
|
||||
using namespace std;
|
||||
|
||||
static const char indata[] =
|
||||
"hello = world \n"
|
||||
" # oops\n"
|
||||
" #dd=da\n"
|
||||
" empty = \n"
|
||||
" this = is a test\n\n"
|
||||
;
|
||||
|
||||
static const char expectdata[] =
|
||||
"empty = \n"
|
||||
"hello = world\n"
|
||||
"this = is a test\n"
|
||||
;
|
||||
|
||||
static
|
||||
void showEscaped(const char *msg, const std::string& s)
|
||||
{
|
||||
std::vector<char> chars(epicsStrnEscapedFromRawSize(s.c_str(), s.size())+1);
|
||||
epicsStrnEscapedFromRaw(&chars[0], chars.size(), s.c_str(), s.size());
|
||||
testDiag("%s: '%s", msg, &chars[0]);
|
||||
}
|
||||
|
||||
static
|
||||
void testProp()
|
||||
{
|
||||
Properties plist;
|
||||
|
||||
{
|
||||
std::istringstream input(indata);
|
||||
plist.load(input);
|
||||
testOk1(!input.bad());
|
||||
testOk1(input.eof());
|
||||
}
|
||||
|
||||
testOk1(plist.size()==3);
|
||||
testOk1(plist.getProperty("hello")=="world");
|
||||
testOk1(plist.getProperty("this")=="is a test");
|
||||
testOk1(!plist.hasProperty("foobar"));
|
||||
|
||||
{
|
||||
std::ostringstream output;
|
||||
plist.store(output);
|
||||
std::string expect(expectdata), actual(output.str());
|
||||
|
||||
testOk1(!output.bad());
|
||||
testOk(expect.size()==actual.size(), "%u == %u", (unsigned)expect.size(), (unsigned)actual.size());
|
||||
testOk1(actual==expectdata);
|
||||
showEscaped("actual", actual);
|
||||
showEscaped("expect", expect);
|
||||
}
|
||||
}
|
||||
|
||||
static void showEnv(const char *name)
|
||||
{
|
||||
@@ -43,6 +95,25 @@ static void setEnv(const char *name, const char *val)
|
||||
testDiag("%s = \"%s\"", name, getenv(name));
|
||||
}
|
||||
|
||||
static void testBuilder()
|
||||
{
|
||||
Configuration::shared_pointer C(ConfigurationBuilder()
|
||||
.add("TESTKEY","value1")
|
||||
.push_map()
|
||||
.push_env()
|
||||
.add("OTHERKEY","value3")
|
||||
.push_map()
|
||||
.build());
|
||||
|
||||
testOk1(C->getPropertyAsString("key", "X")=="X");
|
||||
testOk1(C->getPropertyAsString("TESTKEY", "X")=="value1");
|
||||
testOk1(C->getPropertyAsString("OTHERKEY", "X")=="value3");
|
||||
setEnv("TESTKEY", "value2");
|
||||
setEnv("OTHERKEY","value2");
|
||||
testOk1(C->getPropertyAsString("TESTKEY", "X")=="value2");
|
||||
testOk1(C->getPropertyAsString("OTHERKEY", "X")=="value3");
|
||||
}
|
||||
|
||||
static void showAddr(const osiSockAddr& addr)
|
||||
{
|
||||
char buf[40];
|
||||
@@ -60,9 +131,9 @@ static void showAddr(const osiSockAddr& addr)
|
||||
} while(0)
|
||||
|
||||
|
||||
MAIN(configurationTest)
|
||||
static
|
||||
void testConfig()
|
||||
{
|
||||
testPlan(35);
|
||||
testDiag("Default configuration");
|
||||
Configuration::shared_pointer configuration(new SystemConfigurationImpl());
|
||||
|
||||
@@ -126,7 +197,14 @@ MAIN(configurationTest)
|
||||
|
||||
Configuration::shared_pointer configurationOut(configProvider->getConfiguration("conf1"));
|
||||
testOk1(configurationOut.get() == configuration.get());
|
||||
}
|
||||
|
||||
MAIN(configurationTest)
|
||||
{
|
||||
testPlan(49);
|
||||
testProp();
|
||||
testBuilder();
|
||||
testConfig();
|
||||
return testDone();
|
||||
}
|
||||
|
||||
|
||||
75
testApp/utils/testFairQueue.cpp
Normal file
75
testApp/utils/testFairQueue.cpp
Normal file
@@ -0,0 +1,75 @@
|
||||
/**
|
||||
* Copyright - See the COPYRIGHT that is included with this distribution.
|
||||
* pvAccessCPP is distributed subject to a Software License Agreement found
|
||||
* in file LICENSE that is included with this distribution.
|
||||
*/
|
||||
|
||||
#include <vector>
|
||||
|
||||
#include <pv/fairQueue.h>
|
||||
|
||||
#include <epicsUnitTest.h>
|
||||
#include <testMain.h>
|
||||
|
||||
namespace {
|
||||
|
||||
struct Qnode : public epics::pvAccess::fair_queue<Qnode>::entry {
|
||||
unsigned i;
|
||||
Qnode(unsigned i):i(i) {}
|
||||
};
|
||||
|
||||
} // namespace
|
||||
|
||||
static unsigned Ninput[] = {0,0,0,1,0,2,1,0,1,0,0};
|
||||
static unsigned Nexpect[] = {0,1,2,0,1,0,1,0,0,0,0};
|
||||
|
||||
static
|
||||
void testOrder()
|
||||
{
|
||||
epics::pvAccess::fair_queue<Qnode> Q;
|
||||
typedef epics::pvAccess::fair_queue<Qnode>::value_type value_type;
|
||||
|
||||
std::vector<value_type> unique, inputs, outputs;
|
||||
unique.resize(3);
|
||||
unique[0].reset(new Qnode(0));
|
||||
unique[1].reset(new Qnode(1));
|
||||
unique[2].reset(new Qnode(2));
|
||||
|
||||
testDiag("Queueing");
|
||||
|
||||
for(unsigned i=0; i<NELEMENTS(Ninput); i++) {
|
||||
testDiag("[%u] = %u", i, Ninput[i]);
|
||||
Q.push_back(unique[Ninput[i]]);
|
||||
}
|
||||
|
||||
testDiag("De-queue");
|
||||
|
||||
{
|
||||
for(unsigned i=0; i<=NELEMENTS(Nexpect); i++) {
|
||||
value_type E;
|
||||
Q.pop_front_try(E);
|
||||
if(!E) break;
|
||||
outputs.push_back(E);
|
||||
testDiag("Dequeue %u", E->i);
|
||||
}
|
||||
}
|
||||
|
||||
testOk(outputs.size()==NELEMENTS(Nexpect), "sizes match actual %u expected %u",
|
||||
(unsigned)outputs.size(), (unsigned)NELEMENTS(Nexpect));
|
||||
|
||||
for(unsigned i=0; i<NELEMENTS(Nexpect); i++) {
|
||||
if(i>=outputs.size()) {
|
||||
testFail("output truncated");
|
||||
continue;
|
||||
}
|
||||
testOk(outputs[i]->i==Nexpect[i], "[%u] %u == %u",
|
||||
i, (unsigned)outputs[i]->i, Nexpect[i]);
|
||||
}
|
||||
}
|
||||
|
||||
MAIN(testFairQueue)
|
||||
{
|
||||
testPlan(12);
|
||||
testOrder();
|
||||
return testDone();
|
||||
}
|
||||
@@ -180,8 +180,9 @@ void test_getBroadcastAddresses()
|
||||
|
||||
SOCKET socket = epicsSocketCreate(AF_INET, SOCK_STREAM, IPPROTO_TCP);
|
||||
auto_ptr<InetAddrVector> broadcasts(getBroadcastAddresses(socket, 6678));
|
||||
// at least one is expected
|
||||
// at least one is expected, in case of no network connection a fallback address is returned
|
||||
testOk1(static_cast<size_t>(0) < broadcasts->size());
|
||||
//testDiag("getBroadcastAddresses() returned %zu entry/-ies.", broadcasts->size());
|
||||
epicsSocketDestroy(socket);
|
||||
|
||||
// debug
|
||||
|
||||
Reference in New Issue
Block a user