From 802136176813cb851e5c9fa56b76dd0259fd75ae Mon Sep 17 00:00:00 2001 From: Matej Sekoranja Date: Tue, 3 Dec 2013 12:41:48 +0100 Subject: [PATCH] added testChannelAccess tests --- testApp/remote/Makefile | 7 + testApp/remote/channelAccessIFTest.cpp | 2027 ++++++++++++++++++++++++ testApp/remote/channelAccessIFTest.h | 151 ++ testApp/remote/syncTestRequesters.h | 1323 ++++++++++++++++ testApp/remote/testChannelAccess.cpp | 89 ++ testApp/remote/testServer.cpp | 49 +- 6 files changed, 3636 insertions(+), 10 deletions(-) create mode 100755 testApp/remote/channelAccessIFTest.cpp create mode 100755 testApp/remote/channelAccessIFTest.h create mode 100755 testApp/remote/syncTestRequesters.h create mode 100755 testApp/remote/testChannelAccess.cpp diff --git a/testApp/remote/Makefile b/testApp/remote/Makefile index 702d485..9846542 100644 --- a/testApp/remote/Makefile +++ b/testApp/remote/Makefile @@ -46,6 +46,11 @@ PROD_HOST += testServer testServer_SRCS += testServer.cpp testServer_LIBS += pvData pvAccess pvMB Com +TESTPROD_HOST += testChannelAccess +testChannelAccess_SRCS = testChannelAccess channelAccessIFTest +testChannelAccess_LIBS += pvData pvAccess pvMB Com +#TESTS += testChannelAccess + PROD_HOST += pvget pvget_SRCS += pvget.cpp pvget_LIBS += pvData pvAccess pvMB Com @@ -70,6 +75,8 @@ PROD_HOST += rpcServiceExample rpcServiceExample_SRCS += rpcServiceExample.cpp rpcServiceExample_LIBS += pvData pvAccess pvMB Com +TESTSCRIPTS_HOST += $(TESTS:%=%.t) + include $(TOP)/configure/RULES #---------------------------------------- # ADD RULES AFTER THIS LINE diff --git a/testApp/remote/channelAccessIFTest.cpp b/testApp/remote/channelAccessIFTest.cpp new file mode 100755 index 0000000..2f1135d --- /dev/null +++ b/testApp/remote/channelAccessIFTest.cpp @@ -0,0 +1,2027 @@ +#include +#include +#include +#include +#include + +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include "channelAccessIFTest.h" + + +using namespace std::tr1; + + +std::string ChannelAccessIFTest::TEST_COUNTER_CHANNEL_NAME = "testCounter"; +std::string ChannelAccessIFTest::TEST_CHANNEL_NAME = "testValue"; +std::string ChannelAccessIFTest::TEST_VALUEONLY_CHANNEL_NAME = "testValueOnly"; +std::string ChannelAccessIFTest::TEST_SUMRPC_CHANNEL_NAME = "testSum"; +std::string ChannelAccessIFTest::TEST_ARRAY_CHANNEL_NAME = "testArray"; + + +int ChannelAccessIFTest::runAllTest() { + + testPlan(142); + + test_implementation(); + test_providerName(); + + test_createEmptyChannel(); + test_createChannelWithInvalidPriority(); + test_createChannel(); + test_recreateChannelOnDestroyedProvider(); + test_findEmptyChannel(); + test_findChannel(); + test_channel(); + + test_channelGetWithInvalidChannelAndRequester(); + test_channelGetNoProcess(); + test_channelGetIntProcess(); + test_channelGetTestNoConnection(); + test_channelGetNotYetConnected(); + + test_channelPutWithInvalidChannelAndRequester(); + test_channelPutNoProcess(); + test_channelPutIntProcess(); + test_channelPutTestNoConnection(); + test_channelPutNotYetConnected(); + + test_channelGetFieldAll(); + test_channelGetFieldValue(); + test_channelGetFieldInvalid(); + + test_channelProcesstWithInvalidRequesterAndRequest(); + test_channelProcess(); + test_channelProcessNoConnection(); + + test_channelPutGetWithInvalidRequesterAndRequest(); + test_channelPutGetNoProcess_putGet(); + test_channelPutGetNoProcess_getPut(); + test_channelPutGetNoProcess_getGet(); + test_channelPutGetNoProcess_destroy(); + test_channelPutGetIntProcess(); + + test_channelRPC(); + test_channelRPC_destroy(); + test_channelRPCWithInvalidRequesterAndRequest(); + + test_channelMonitorWithInvalidRequesterAndRequest(); + test_channelMonitor(1); + + test_channelArray(); + test_channelArray_destroy(); + + test_stressConnectDisconnect(); + test_stressConnectGetDisconnect(); + test_stressMonitorAndProcess(); + + return testDone(); +} + + +Channel::shared_pointer ChannelAccessIFTest::createChannel(string channelName, bool debug ) +{ + + std::tr1::shared_ptr channelReq(new SyncChannelRequesterImpl(debug)); + Channel::shared_pointer channel = getChannelProvider()->createChannel(channelName, channelReq); + return channel; +} + + +Channel::shared_pointer ChannelAccessIFTest::syncCreateChannel(string channelName, bool debug ) +{ + + std::tr1::shared_ptr channelReq(new SyncChannelRequesterImpl(debug)); + Channel::shared_pointer channel = getChannelProvider()->createChannel(channelName, channelReq); + bool isConnected = channelReq->waitUntilStateChange(getTimeoutSec()); + if (!isConnected) { + std::cerr << "[" << channelName << "] failed to connect to the channel. " << std::endl; + return shared_ptr(); + } + + return channel; +} + + +SyncChannelGetRequesterImpl::shared_pointer ChannelAccessIFTest::syncCreateChannelGet( + Channel::shared_pointer const & channel, string const & request, bool debug ) +{ + + shared_ptr + channelGetReq(new SyncChannelGetRequesterImpl(channel->getChannelName(), debug)); + + PVStructure::shared_pointer pvRequest = CreateRequest::create()->createRequest(request); + + channel->createChannelGet(channelGetReq,pvRequest); + bool succStatus = channelGetReq->waitUntilGetDone(getTimeoutSec()); + if (!succStatus) { + std::cerr << "[" << channel->getChannelName() << "] failed to get. " << std::endl; + return shared_ptr(); + } + return channelGetReq; +} + + +SyncChannelPutRequesterImpl::shared_pointer ChannelAccessIFTest::syncCreateChannelPut( + Channel::shared_pointer const & channel, string const & request, bool debug ) +{ + + shared_ptr + channelPutReq(new SyncChannelPutRequesterImpl(channel->getChannelName(), debug)); + + + PVStructure::shared_pointer pvRequest = CreateRequest::create()->createRequest(request); + + channel->createChannelPut(channelPutReq,pvRequest); + bool succStatus = channelPutReq->waitUntilConnected(getTimeoutSec()); + + if (!succStatus) { + std::cerr << "[" << channel->getChannelName() << "] failed to create a put channel. " << std::endl; + return shared_ptr(); + } + return channelPutReq; +} + + +SyncChannelPutGetRequesterImpl::shared_pointer ChannelAccessIFTest::syncCreateChannelPutGet( + Channel::shared_pointer const & channel, string const & request, bool debug ) +{ + + shared_ptr + channelPutGetReq(new SyncChannelPutGetRequesterImpl(debug)); + + PVStructure::shared_pointer pvRequest = CreateRequest::create()->createRequest(request); + + channel->createChannelPutGet(channelPutGetReq,pvRequest); + bool succStatus = channelPutGetReq->waitUntilConnected(getTimeoutSec()); + + if (!succStatus) { + std::cerr << "[" << channel->getChannelName() << "] failed to create a put get channel. " << std::endl; + return shared_ptr(); + } + return channelPutGetReq; +} + + +SyncChannelRPCRequesterImpl::shared_pointer ChannelAccessIFTest::syncCreateChannelRPC( + Channel::shared_pointer const & channel, bool debug ) +{ + + shared_ptr + channelRPCReq(new SyncChannelRPCRequesterImpl(debug)); + + PVStructure::shared_pointer pvRequest = CreateRequest::create()->createRequest(string()); + + channel->createChannelRPC(channelRPCReq, pvRequest); + bool succStatus = channelRPCReq->waitUntilConnected(getTimeoutSec()); + + if (!succStatus) { + std::cerr << "[" << channel->getChannelName() << "] failed to create a RPC channel. " << std::endl; + return shared_ptr(); + } + return channelRPCReq; +} + + +SyncMonitorRequesterImpl::shared_pointer ChannelAccessIFTest::syncCreateChannelMonitor( + Channel::shared_pointer const & channel, string const & request, bool debug ) +{ + shared_ptr monitorReq(new SyncMonitorRequesterImpl(debug)); + + PVStructure::shared_pointer pvRequest = CreateRequest::create()->createRequest(request); + + channel->createMonitor(monitorReq, pvRequest); + bool succStatus = monitorReq->waitUntilConnected(getTimeoutSec()); + + if (!succStatus) { + std::cerr << "[" << channel->getChannelName() << "] failed to create a monitor channel. " << std::endl; + return shared_ptr(); + } + return monitorReq; +} + + +SyncChannelArrayRequesterImpl::shared_pointer ChannelAccessIFTest::syncCreateChannelArray( + Channel::shared_pointer const & channel, PVStructure::shared_pointer pvRequest, bool debug ) +{ + shared_ptr arrayReq(new SyncChannelArrayRequesterImpl(debug)); + + channel->createChannelArray(arrayReq, pvRequest); + bool succStatus = arrayReq->waitUntilConnected(getTimeoutSec()); + + if (!succStatus) { + std::cerr << "[" << channel->getChannelName() << "] failed to create an array channel. " << std::endl; + return shared_ptr(); + } + return arrayReq; +} + + +void ChannelAccessIFTest::test_implementation() { + + testDiag("BEGIN TEST %s:", CURRENT_FUNCTION); + + testOk(getChannelProvider().get() != 0, "%s: channel provider is provided", CURRENT_FUNCTION ); + ChannelProvider::shared_pointer cp1 = getChannelProvider(); + ChannelProvider::shared_pointer cp2 = getChannelProvider(); + testOk(cp1 == cp2, "%s: calling getChannelProvider twice", CURRENT_FUNCTION); + testOk(getTimeoutSec() > 0, "%s: timeout is set", CURRENT_FUNCTION); +} + + +void ChannelAccessIFTest::test_providerName() { + + testDiag("BEGIN TEST %s:", CURRENT_FUNCTION); + + testOk(!getChannelProvider()->getProviderName().empty(), "%s: provider name is set", CURRENT_FUNCTION); + testOk(getChannelProvider()->getProviderName()== getChannelProvider()->getProviderName(), + "%s: calling getProviderName twice should return the same provider", CURRENT_FUNCTION); +} + + +void ChannelAccessIFTest::test_createEmptyChannel() { + + testDiag("BEGIN TEST %s:", CURRENT_FUNCTION); + + std::tr1::shared_ptr channelReq(new SyncChannelRequesterImpl()); + + try { + Channel::shared_pointer channel = getChannelProvider()->createChannel(String(), channelReq); + testFail("%s: empty channel name should not be allowed", CURRENT_FUNCTION); + return; + } catch(std::runtime_error &) { + } + + testOk(channelReq->getCreatedCount() == 0, + "%s: checking for empty channel name", CURRENT_FUNCTION); +} + + +void ChannelAccessIFTest::test_createChannelWithInvalidPriority() { + + testDiag("BEGIN TEST %s:", CURRENT_FUNCTION); + + std::tr1::shared_ptr channelReq(new SyncChannelRequesterImpl()); + + try { + Channel::shared_pointer channel = getChannelProvider()->createChannel(String(), channelReq, + ChannelProvider::PRIORITY_MIN - 1 ); + testFail("%s: invalid priority should not be allowed when creating a channel",CURRENT_FUNCTION); + return; + } catch(std::runtime_error &) { + } + + testOk(channelReq->getCreatedCount() == 0, + "%s: checking for invalid priority when creating a new channel",CURRENT_FUNCTION); +} + + +void ChannelAccessIFTest::test_createChannel() { + + testDiag("BEGIN TEST %s:", CURRENT_FUNCTION); + + std::tr1::shared_ptr channelReq(new SyncChannelRequesterImpl()); + Channel::shared_pointer channel = getChannelProvider()->createChannel(TEST_COUNTER_CHANNEL_NAME, channelReq); + bool succStatus = channelReq->waitUntilStateChange(getTimeoutSec()); + if (!succStatus) { + std::cerr << "[" << TEST_COUNTER_CHANNEL_NAME << "] failed to connect. " << std::endl; + testFail("%s: could not create a channel", CURRENT_FUNCTION); + return; + } + + channel->destroy(); + testOk(channelReq->getStatus().isSuccess(), "%s: create a channel", CURRENT_FUNCTION); +} + + +void ChannelAccessIFTest::test_recreateChannelOnDestroyedProvider() { + + testDiag("BEGIN TEST %s:", CURRENT_FUNCTION); + + if (isLocal()){ + testOk(true, "%s: recreating channel on destroyed provider", CURRENT_FUNCTION); + return; + } + + ChannelProvider::shared_pointer provider = getChannelProvider(); + provider->destroy(); + test_createChannel(); +} + + +void ChannelAccessIFTest::test_findEmptyChannel() { + + testDiag("BEGIN TEST %s:", CURRENT_FUNCTION); + + try { + std::tr1::shared_ptr channelFindReq(new SyncChannelFindRequesterImpl()); + getChannelProvider()->channelFind(String(), channelFindReq); + testFail("%s: empty channel name shoud never be allowed when searching for channels", CURRENT_FUNCTION); + return; + + } catch(std::runtime_error &) { + } + + testOk(true, "%s: finding an empty channel", CURRENT_FUNCTION); +} + + +void ChannelAccessIFTest::test_findChannel() { + + testDiag("BEGIN TEST %s:", CURRENT_FUNCTION); + + std::tr1::shared_ptr channelFindReq(new SyncChannelFindRequesterImpl()); + getChannelProvider()->channelFind(TEST_COUNTER_CHANNEL_NAME, channelFindReq); + bool isFindResult = channelFindReq->waitUntilFindResult(getTimeoutSec()); + if (!isFindResult) { + std::cerr << "[" << TEST_COUNTER_CHANNEL_NAME << "] failed to connect. " << std::endl; + testFail("%s: could not find a channel", CURRENT_FUNCTION); + return; + } + testSkip(1, "finding a channel not implemented"); +} + + +void ChannelAccessIFTest::test_channel() { + + testDiag("BEGIN TEST %s:", CURRENT_FUNCTION); + + std::tr1::shared_ptr channelReq(new SyncChannelRequesterImpl()); + Channel::shared_pointer channel = getChannelProvider()->createChannel(TEST_COUNTER_CHANNEL_NAME, channelReq); + bool succStatus = channelReq->waitUntilStateChange(getTimeoutSec()); + if (!succStatus) { + std::cerr << "[" << channel->getChannelName() << "] failed to connect. " << std::endl; + testFail("%s: could not create a channel", CURRENT_FUNCTION); + return; + } + + testOk(channelReq->getCreatedCount() == 1, "%s: channel created count", CURRENT_FUNCTION); + testOk(channelReq->getStatus().isSuccess(), "%s: succ created a channel", CURRENT_FUNCTION); + testOk(channelReq->getStateChangeCount() == 1, "%s: channel state change count", CURRENT_FUNCTION); + testOk(channel->getChannelName() == TEST_COUNTER_CHANNEL_NAME, "%s: channel name match", CURRENT_FUNCTION); + testOk(channel->getChannelRequester() == channelReq, "%s: channel requesters match", CURRENT_FUNCTION); + //testOk(channel->getRequesterName() == channelRequesterPtr->getRequesterName(), + // " channel requester's name match"); + testSkip(1, "channel requester's name mismatch"); + testOk(channel->getProvider() == getChannelProvider(), "%s: channel provider match", CURRENT_FUNCTION); + testOk(!channel->getRemoteAddress().empty(), "%s: channel remote address set", CURRENT_FUNCTION); + testOk(channel->isConnected(), "%s: channel connected ", CURRENT_FUNCTION); + testOk(channel->getConnectionState() == Channel::CONNECTED , + "%s: channel connection state connected ", CURRENT_FUNCTION); + + testDiag("%s: destroying the channel", CURRENT_FUNCTION); + channel->destroy(); + + succStatus = channelReq->waitUntilStateChange(getTimeoutSec()); + if (!succStatus) { + std::cerr << "[" << channel->getChannelName() << "] failed to registered a destroy event " << std::endl; + testFail("%s: a destroy event was not caught for the testing channel ", CURRENT_FUNCTION); + return; + } + + testOk(channelReq->getCreatedCount() == 1, + "%s: channel created count should be the same on the destroyed channel", CURRENT_FUNCTION); + testOk(channelReq->getStateChangeCount() == 3, + "%s: channel state change count should increase on the destroyed channel", CURRENT_FUNCTION); + testOk(!channel->isConnected(), "%s: channel should not be connected ", CURRENT_FUNCTION); + testOk(channel->getConnectionState() == Channel::DESTROYED , + "%s: channel connection state DESTROYED ", CURRENT_FUNCTION); + + testDiag("%s: destroying the channel yet again", CURRENT_FUNCTION); + channel->destroy(); + + succStatus = channelReq->waitUntilStateChange(getTimeoutSec()); + if (!succStatus) { + std::cerr << "[" << channel->getChannelName() << "] failed to registered a destroy event " << std::endl; + testFail("%s: a destroy event was not caught for the testing channel that was destroyed twice ", + CURRENT_FUNCTION); + return; + } + + testOk(channelReq->getCreatedCount() == 1, + "%s: channel created count should be the same on the yet again destroyed channel", CURRENT_FUNCTION); + + testOk(!channel->isConnected(), "%s: yet again destroyed channel should not be connected ", CURRENT_FUNCTION); + testOk(channel->getConnectionState() == Channel::DESTROYED , + "%s: yet again destroyed channel connection state DESTROYED ", CURRENT_FUNCTION); + +} + + +void ChannelAccessIFTest::test_channelGetWithInvalidChannelAndRequester() { + + testDiag("BEGIN TEST %s:", CURRENT_FUNCTION); + + Channel::shared_pointer channel = syncCreateChannel(TEST_CHANNEL_NAME); + if (!channel.get()) { + testFail("%s: channel not created ", CURRENT_FUNCTION); + return; + } + + testSkip(1, " creating a channel get with a null channel"); + //SyncChannelGetRequesterImpl::shared_pointer channelGetReq = synCreateChannelGet(Channel::shared_pointer(), + // string("field(timeStamp,value)")); + + + testSkip(1, " creating a channel get with an empty request"); + //SyncChannelGetRequesterImpl::shared_pointer channelGetReq = syncCreateChannelGet(Channel::shared_pointer(), + // string()); + + channel->destroy(); +} + + +void ChannelAccessIFTest::test_channelGetNoProcess() { + + testDiag("BEGIN TEST %s:", CURRENT_FUNCTION); + + string request = "field(timeStamp,value)"; + + Channel::shared_pointer channel = syncCreateChannel(TEST_CHANNEL_NAME); + if (!channel.get()) { + testFail("%s: channel not created ", CURRENT_FUNCTION); + return; + } + + SyncChannelGetRequesterImpl::shared_pointer channelGetReq = syncCreateChannelGet(channel,request); + + if (!channelGetReq.get()) { + testFail("%s: channel get not created ", CURRENT_FUNCTION); + return; + } + + testOk(channelGetReq->getBitSet()->cardinality() == 1, "%s: bitset cardinality", CURRENT_FUNCTION); + testOk(channelGetReq->getBitSet()->get(0) == true, "%s: bitset get(0)", CURRENT_FUNCTION); + + bool succStatus = channelGetReq->syncGet(false, getTimeoutSec()); + if (!succStatus) { + testFail("%s: sync get failed ", CURRENT_FUNCTION); + return; + } + + testOk(channelGetReq->getBitSet()->cardinality() == 0, + "%s: bitset cardinality after first sync get", CURRENT_FUNCTION); + + succStatus = channelGetReq->syncGet(false, getTimeoutSec()); + if (!succStatus) { + testFail("%s: sync get failed ", CURRENT_FUNCTION); + return; + } + + testOk(channelGetReq->getBitSet()->cardinality() == 0, + "%s: bitset cardinality after second sync get", CURRENT_FUNCTION); + + channelGetReq->getChannelGet()->destroy(); + testOk(channelGetReq->syncGet(false, getTimeoutSec()) == false, + "%s: after the channel get destroy, sync get must fail", CURRENT_FUNCTION); + + channel->destroy(); +} + + +void ChannelAccessIFTest::test_channelGetIntProcess() { + + testDiag("BEGIN TEST %s:", CURRENT_FUNCTION); + + Channel::shared_pointer channel = syncCreateChannel(TEST_COUNTER_CHANNEL_NAME); + if (!channel.get()) { + testFail("%s: channel not created ", CURRENT_FUNCTION); + return; + } + + test_channelGetIntProcessInternal(channel, CURRENT_FUNCTION); + + channel->destroy(); +} + + +void ChannelAccessIFTest::test_channelGetNotYetConnected() { + + testDiag("BEGIN TEST %s:", CURRENT_FUNCTION); + + Channel::shared_pointer channel = createChannel(TEST_COUNTER_CHANNEL_NAME); + if (!channel.get()) { + testFail("%s: channel not created ", CURRENT_FUNCTION); + return; + } + + test_channelGetIntProcessInternal(channel, CURRENT_FUNCTION); + + channel->destroy(); +} + + +void ChannelAccessIFTest::test_channelGetIntProcessInternal(Channel::shared_pointer channel, + string const & testMethodName) { + + string request = "record[process=true]field(timeStamp,value)"; + + SyncChannelGetRequesterImpl::shared_pointer channelGetReq = syncCreateChannelGet(channel, request); + if (!channelGetReq.get()) { + testFail("%s: channel get not created ", testMethodName.c_str()); + return; + } + + std::tr1::shared_ptr value = channelGetReq->getPVStructure()->getIntField("value"); + + PVTimeStamp pvTimeStamp; + + testOk(pvTimeStamp.attach(channelGetReq->getPVStructure()->getStructureField("timeStamp")), + "%s: attaching a timestamp", testMethodName.c_str()); + + TimeStamp timeStamp; + + bool succStatus = channelGetReq->syncGet(false, getTimeoutSec()); + if (!succStatus) { + testFail("%s: sync get failed ", testMethodName.c_str()); + return; + } + + pvTimeStamp.get(timeStamp); + + testOk(channelGetReq->getBitSet()->cardinality() == 1, "%s: bitset cardinality", testMethodName.c_str()); + testOk(channelGetReq->getBitSet()->get(0) == true, "%s: bitset get(0)", testMethodName.c_str()); + + int numOfTimes = 3; + + for (int i = 0; i < numOfTimes; i++) { + + int previousValue = value->get(); + long previousTimestampSec = timeStamp.getSecondsPastEpoch(); + + epicsThreadSleep(1.0); + + bool succStatus = channelGetReq->syncGet(false, getTimeoutSec()); + if (!succStatus) { + testFail("%s: sync get failed ", testMethodName.c_str()); + return; + } + + pvTimeStamp.get(timeStamp); + + testOk((previousValue +1)%11 == value->get(), "%s: testing the counter value change", + testMethodName.c_str()); + testOk(timeStamp.getSecondsPastEpoch() > previousTimestampSec, + "%s: testing the timestamp change", testMethodName.c_str()); + } + + channelGetReq->getChannelGet()->destroy(); + testOk(channelGetReq->syncGet(false, getTimeoutSec()) == false, + "%s: after the channel get destroy, sync get must fail", testMethodName.c_str()); + + channel->destroy(); +} + + +void ChannelAccessIFTest::test_channelGetTestNoConnection() { + + testDiag("BEGIN TEST %s:", CURRENT_FUNCTION); + + string request = "field(timeStamp,value)"; + + Channel::shared_pointer channel = syncCreateChannel(TEST_COUNTER_CHANNEL_NAME); + if (!channel.get()) { + testFail("%s: channel not created ", CURRENT_FUNCTION); + return; + } + + SyncChannelGetRequesterImpl::shared_pointer channelGetReq = syncCreateChannelGet(channel, request); + if (!channelGetReq.get()) { + testFail("%s: channel get not created ", CURRENT_FUNCTION); + return; + } + + channel->destroy(); + + bool succStatus = channelGetReq->syncGet(false, getTimeoutSec()); + if (!succStatus) { + testOk(true, "%s: get failed on destroy channel ", CURRENT_FUNCTION); + } + else { + testFail("%s: get should fail on destroy channel ", CURRENT_FUNCTION); + } +} + + +void ChannelAccessIFTest::test_channelPutWithInvalidChannelAndRequester() { + + testDiag("BEGIN TEST %s:", CURRENT_FUNCTION); + + Channel::shared_pointer channel = syncCreateChannel(TEST_CHANNEL_NAME); + if (!channel.get()) { + testFail("%s: channel not created ", CURRENT_FUNCTION); + return; + } + + testSkip(1, " creating a channel put with a null channel: seg fault"); + //SyncChannelPutRequesterImpl::shared_pointer channelPutReq = syncCreateChannelPut(Channel::shared_pointer(), + // string("field(timeStamp,value)")); + + + testSkip(1, " creating a channel put with an empty request: seg fault"); + //SyncChannelPutRequesterImpl::shared_pointer channelPutReq1 = syncCreateChannelPut(channel, + // string()); + + channel->destroy(); +} + + +void ChannelAccessIFTest::test_channelPutNoProcess() { + + testDiag("BEGIN TEST %s:", CURRENT_FUNCTION); + + string request = "field(value)"; + + Channel::shared_pointer channel = syncCreateChannel(TEST_CHANNEL_NAME); + if (!channel.get()) { + testFail("%s: channel not created ", CURRENT_FUNCTION); + return; + } + + SyncChannelPutRequesterImpl::shared_pointer channelPutReq = syncCreateChannelPut(channel,request); + + if (!channelPutReq.get()) { + testFail("%s: channel put not created ", CURRENT_FUNCTION); + return; + } + + std::tr1::shared_ptr value = channelPutReq->getPVStructure()->getDoubleField("value"); + if (!value.get()) { + testFail("%s: getting double value field failed ", CURRENT_FUNCTION); + return; + } + + double initVal = 123.0; + + value->put(initVal); + channelPutReq->getBitSet()->set(value->getFieldOffset()); + + bool succStatus = channelPutReq->syncPut(false, getTimeoutSec()); + if (!succStatus) { + testFail("%s: sync put failed ", CURRENT_FUNCTION); + return; + } + + succStatus = channelPutReq->syncGet(getTimeoutSec()); + if (!succStatus) { + testFail("%s: sync get failed ", CURRENT_FUNCTION); + return; + } + + + testOk(initVal == value->get(), "%s: initial value matches the get value ", CURRENT_FUNCTION); + + value->put(initVal + 2); + channelPutReq->getBitSet()->clear(); + + succStatus = channelPutReq->syncPut(false, getTimeoutSec()); + if (!succStatus) { + testFail("%s: second sync put failed ", CURRENT_FUNCTION); + return; + } + + succStatus = channelPutReq->syncGet(getTimeoutSec()); + if (!succStatus) { + testFail("%s: second sync get failed ", CURRENT_FUNCTION); + return; + } + + if (isLocal()) { + testOk(initVal+2 == value->get(), + "%s: value should not change since bitset is not set unless is local ", CURRENT_FUNCTION); + } + else { + testOk(initVal == value->get(), "%s: value should not change since bitset is not set ", CURRENT_FUNCTION); + } + + value->put(initVal + 1); + channelPutReq->getBitSet()->set(value->getFieldOffset()); + + succStatus = channelPutReq->syncPut(false, getTimeoutSec()); + if (!succStatus) { + testFail("%s: third sync put failed ", CURRENT_FUNCTION); + return; + } + + succStatus = channelPutReq->syncGet(getTimeoutSec()); + if (!succStatus) { + testFail("%s: third sync get failed ", CURRENT_FUNCTION); + return; + } + + testOk(initVal+1 == value->get(), "%s: changed value matches the get value ", CURRENT_FUNCTION); + + testDiag("%s: Ok, let's destroy the put channel", CURRENT_FUNCTION); + + succStatus = channelPutReq->syncPut(true, getTimeoutSec()); + if (!succStatus) { + testFail("%s: destroying sync put failed ", CURRENT_FUNCTION); + return; + } + + channelPutReq->getChannelPut()->destroy(); + + succStatus = channelPutReq->syncPut(true, getTimeoutSec()); + if (!succStatus) { + testOk(true, "%s: put on destroyed put channel should not succeed ", CURRENT_FUNCTION); + } + else { + testFail("%s: put on destroyed put channel did succeed ", CURRENT_FUNCTION); + } + + channel->destroy(); +} + + +void ChannelAccessIFTest::test_channelPutIntProcess() { + + testDiag("BEGIN TEST %s:", CURRENT_FUNCTION); + + Channel::shared_pointer channel = syncCreateChannel(TEST_COUNTER_CHANNEL_NAME); + if (!channel.get()) { + testFail("%s: channel not created ", CURRENT_FUNCTION); + return; + } + + test_channelPutIntProcessInternal(channel, CURRENT_FUNCTION); + + channel->destroy(); +} + + +void ChannelAccessIFTest::test_channelPutNotYetConnected() { + + testDiag("BEGIN TEST %s:", CURRENT_FUNCTION); + + Channel::shared_pointer channel = createChannel(TEST_COUNTER_CHANNEL_NAME); + if (!channel.get()) { + testFail("%s: channel not created ", CURRENT_FUNCTION); + return; + } + + test_channelPutIntProcessInternal(channel, CURRENT_FUNCTION); + + channel->destroy(); +} + + +void ChannelAccessIFTest::test_channelPutIntProcessInternal(Channel::shared_pointer channel, + string const & testMethodName) { + + string request = "record[process=true]field(value)"; + + SyncChannelPutRequesterImpl::shared_pointer channelPutReq = syncCreateChannelPut(channel,request); + + if (!channelPutReq.get()) { + testFail("%s: channel put not created ", testMethodName.c_str()); + return; + } + + std::tr1::shared_ptr value = channelPutReq->getPVStructure()->getIntField("value"); + if (!value.get()) { + testFail("%s: getting int value field failed ", testMethodName.c_str()); + return; + } + + int initVal = 3; + + value->put(initVal); + channelPutReq->getBitSet()->set(value->getFieldOffset()); + + bool succStatus = channelPutReq->syncPut(false, getTimeoutSec()); + if (!succStatus) { + testFail("%s: sync put failed ", testMethodName.c_str()); + return; + } + + succStatus = channelPutReq->syncGet(getTimeoutSec()); + if (!succStatus) { + testFail("%s: sync get failed ", testMethodName.c_str()); + return; + } + + testOk(initVal + 1 == value->get(), "%s: value changed +1 due to processing ", testMethodName.c_str()); + + value->put(initVal + 3); + channelPutReq->getBitSet()->clear(); + + succStatus = channelPutReq->syncPut(false, getTimeoutSec()); + if (!succStatus) { + testFail("%s: second sync put failed ", testMethodName.c_str()); + return; + } + + succStatus = channelPutReq->syncGet(getTimeoutSec()); + if (!succStatus) { + testFail("%s: second sync get failed ", testMethodName.c_str()); + return; + } + + if (isLocal()) { + testOk(initVal+4 == value->get(), + "%s: value changed due to processing unless is local ", testMethodName.c_str()); + } + else { + testOk(initVal+2 == value->get(), "%s: value not changed ", testMethodName.c_str()); + } + + + testDiag("%s: Ok, let's destroy the put channel", testMethodName.c_str()); + + succStatus = channelPutReq->syncPut(true, getTimeoutSec()); + if (!succStatus) { + testFail("%s: destroying sync put failed ", testMethodName.c_str()); + return; + } + + channelPutReq->getChannelPut()->destroy(); + + succStatus = channelPutReq->syncPut(true, getTimeoutSec()); + if (!succStatus) { + testOk(true, "%s: put on destroyed put channel should not succeed ", testMethodName.c_str()); + } + else { + testFail("%s: put on destroyed put channel did succeed ", testMethodName.c_str()); + } + + channel->destroy(); +} + + +void ChannelAccessIFTest::test_channelPutTestNoConnection() { + + testDiag("BEGIN TEST %s:", CURRENT_FUNCTION); + + string request = "field(timeStamp,value)"; + + Channel::shared_pointer channel = syncCreateChannel(TEST_COUNTER_CHANNEL_NAME); + if (!channel.get()) { + testFail("%s: channel not created ", CURRENT_FUNCTION); + return; + } + + SyncChannelPutRequesterImpl::shared_pointer channelPutReq = syncCreateChannelPut(channel, request); + if (!channelPutReq.get()) { + testFail("%s: channel put not created ", CURRENT_FUNCTION); + return; + } + + channel->destroy(); + + bool succStatus = channelPutReq->syncPut(false, getTimeoutSec()); + if (!succStatus) { + testOk(true, "%s: put failed on destroy channel ", CURRENT_FUNCTION); + } + else { + testFail("%s: put should fail on destroy channel ", CURRENT_FUNCTION); + } + + channel->destroy(); +} + + +void ChannelAccessIFTest::test_channelGetFieldAll() { + + testDiag("BEGIN TEST %s:", CURRENT_FUNCTION); + + Channel::shared_pointer channel = syncCreateChannel(TEST_COUNTER_CHANNEL_NAME); + if (!channel.get()) { + testFail("%s: channel not created ", CURRENT_FUNCTION); + return; + } + + shared_ptr + channelGetFieldReq(new SyncGetFieldRequesterImpl()); + + channel->getField(channelGetFieldReq, String()); + + bool succStatus = channelGetFieldReq->waitUntilGetDone(getTimeoutSec()); + if (!succStatus) { + testFail("%s: get all fields failed ", CURRENT_FUNCTION); + } + else { + testOk(true, "%s: get all fields succeeded ", CURRENT_FUNCTION); + testOk(channelGetFieldReq->getField()->getType() == structure, + "%s: field type is structure ", CURRENT_FUNCTION); + } + + channel->destroy(); + +} + + +void ChannelAccessIFTest::test_channelGetFieldValue() { + + testDiag("BEGIN TEST %s:", CURRENT_FUNCTION); + + Channel::shared_pointer channel = syncCreateChannel(TEST_COUNTER_CHANNEL_NAME); + if (!channel.get()) { + testFail("%s: channel not created ", CURRENT_FUNCTION); + return; + } + + shared_ptr + channelGetFieldReq(new SyncGetFieldRequesterImpl()); + + channel->getField(channelGetFieldReq, "value"); + + bool succStatus = channelGetFieldReq->waitUntilGetDone(getTimeoutSec()); + if (!succStatus) { + testFail("%s: get field value failed ", CURRENT_FUNCTION); + } + else { + testOk(true, "%s: get field value succeeded ", CURRENT_FUNCTION); + testOk(channelGetFieldReq->getField()->getType() == scalar, + "%s: field type is scalar", CURRENT_FUNCTION); + } + + channel->destroy(); + +} + + +void ChannelAccessIFTest::test_channelGetFieldInvalid() { + + testDiag("BEGIN TEST %s:", CURRENT_FUNCTION); + + Channel::shared_pointer channel = syncCreateChannel(TEST_COUNTER_CHANNEL_NAME); + if (!channel.get()) { + testFail("%s: channel not created ", CURRENT_FUNCTION); + return; + } + + shared_ptr + channelGetFieldReq(new SyncGetFieldRequesterImpl()); + + channel->getField(channelGetFieldReq, "invalid"); + + bool succStatus = channelGetFieldReq->waitUntilGetDone(getTimeoutSec()); + if (!succStatus) { + testOk(true, "%s: get invalid field should not succeed ", CURRENT_FUNCTION); + } + else { + testFail("%s: get invalid field succeded ", CURRENT_FUNCTION); + } + + channel->destroy(); + +} + + +void ChannelAccessIFTest::test_channelProcesstWithInvalidRequesterAndRequest() { + + testDiag("BEGIN TEST %s:", CURRENT_FUNCTION); + + Channel::shared_pointer channel = syncCreateChannel(TEST_CHANNEL_NAME); + if (!channel.get()) { + testFail("%s: channel not created ", CURRENT_FUNCTION); + return; + } + + ChannelProcess::shared_pointer channelProcess = + channel->createChannelProcess(ChannelProcessRequester::shared_pointer(), + epics::pvData::PVStructure::shared_pointer()); + + if (!channelProcess.get()) { + testOk(true, "%s: creating channel process with empty requester/request should not succeed ", CURRENT_FUNCTION); + } + else { + testFail("%s: creating channel process with empty requester/request succeded ", CURRENT_FUNCTION); + } + + channel->destroy(); +} + + +void ChannelAccessIFTest::test_channelProcess() { + + testDiag("BEGIN TEST %s:", CURRENT_FUNCTION); + + string request = "field(value)"; + + Channel::shared_pointer channel = syncCreateChannel(TEST_COUNTER_CHANNEL_NAME); + if (!channel.get()) { + testFail("%s: channel not created ", CURRENT_FUNCTION); + return; + } + + SyncChannelGetRequesterImpl::shared_pointer channelGetReq = syncCreateChannelGet(channel, request); + if (!channelGetReq.get()) { + testFail("%s: channel get not created ", CURRENT_FUNCTION); + return; + } + + bool succStatus = channelGetReq->syncGet(false, getTimeoutSec()); + if (!succStatus) { + testFail("%s: sync get failed ", CURRENT_FUNCTION); + return; + } + else { + testOk(true, "%s: syncGet the initial state", CURRENT_FUNCTION); + } + + shared_ptr + channelProcessReq(new SyncChannelProcessRequesterImpl()); + + + ChannelProcess::shared_pointer channelProcess = + channel->createChannelProcess(channelProcessReq, + epics::pvData::PVStructure::shared_pointer()); + + succStatus = channelProcessReq->waitUntilConnected(getTimeoutSec()); + if (!succStatus) { + testFail("%s: a channel process is not connected ", CURRENT_FUNCTION); + return; + } + else { + testOk(true,"%s: a process channel with an empty request connected", CURRENT_FUNCTION); + } + + + succStatus = channelGetReq->syncGet(false, getTimeoutSec()); + if (!succStatus) { + testFail("%s: second sync get failed ", CURRENT_FUNCTION); + return; + } + + testOk(channelGetReq->getBitSet()->cardinality() == 0, "%s: bitset cardinality is 0", CURRENT_FUNCTION); + + succStatus = channelProcessReq->syncProcess(false, getTimeoutSec()); + if (!succStatus) { + testFail("%s: syncProcess failed ", CURRENT_FUNCTION); + return; + } + else { + testOk(true, "%s: a sync process succeeded", CURRENT_FUNCTION); + } + + succStatus = channelGetReq->syncGet(false, getTimeoutSec()); + if (!succStatus) { + testFail("%s: third sync get failed ", CURRENT_FUNCTION); + return; + } + + + testOk(channelGetReq->getBitSet()->cardinality() == 1, + "%s: bitset cardinality should change after process", CURRENT_FUNCTION); + + testDiag("%s: destroying the process channel", CURRENT_FUNCTION); + channelProcessReq->getChannelProcess()->destroy(); + + succStatus = channelProcessReq->syncProcess(false, getTimeoutSec()); + if (!succStatus) { + testOk(true, "%s: processing on a destroyed process channel should not succeed", CURRENT_FUNCTION); + } + else { + testFail("%s: processing on a destroyed process channel succeed ", CURRENT_FUNCTION); + } + + channel->destroy(); +} + + +void ChannelAccessIFTest::test_channelProcessNoConnection() { + + testDiag("BEGIN TEST %s:", CURRENT_FUNCTION); + + string request = "field(value)"; + + Channel::shared_pointer channel = syncCreateChannel(TEST_COUNTER_CHANNEL_NAME); + if (!channel.get()) { + testFail("%s: channel not created ", CURRENT_FUNCTION); + return; + } + + SyncChannelGetRequesterImpl::shared_pointer channelGetReq = syncCreateChannelGet(channel, request); + if (!channelGetReq.get()) { + testFail("%s: channel get not created ", CURRENT_FUNCTION); + return; + } + + testDiag("%s: destroying the channel", CURRENT_FUNCTION); + channel->destroy(); + + bool succStatus = channelGetReq->syncGet(false, getTimeoutSec()); + if (!succStatus) { + testOk(true, "%s: processing on a destroyed channel should not succeed", CURRENT_FUNCTION); + } + else { + testFail("%s: processing on a destroyed channel succeed ", CURRENT_FUNCTION); + } +} + + +void ChannelAccessIFTest::test_channelPutGetWithInvalidRequesterAndRequest() { + + testDiag("BEGIN TEST %s:", CURRENT_FUNCTION); + + string request = "putField(value)getField(timeStamp,value)"; + + Channel::shared_pointer channel = syncCreateChannel(TEST_VALUEONLY_CHANNEL_NAME); + if (!channel.get()) { + testFail("%s: channel not created ", CURRENT_FUNCTION); + return; + } + + testSkip(1, " creating a channel put get with a null channel"); + //SyncChannelPutGetRequesterImpl::shared_pointer channelPutGetReq = + // syncCreateChannelPutGet(Channel::shared_pointer(),request); + + testSkip(1, " creating a channel put get with an empty request"); + //SyncChannelPutGetRequesterImpl::shared_pointer channelPutGetReq1 = + //syncCreateChannelPutGet(channel,String()); + + channel->destroy(); +} + + +void ChannelAccessIFTest::test_channelPutGetNoProcess_putGet() { + + testDiag("BEGIN TEST %s:", CURRENT_FUNCTION); + + string request = "putField(value)getField(timeStamp,value)"; + + Channel::shared_pointer channel = syncCreateChannel(TEST_VALUEONLY_CHANNEL_NAME); + if (!channel.get()) { + testFail("%s: channel not created ", CURRENT_FUNCTION); + return; + } + + SyncChannelPutGetRequesterImpl::shared_pointer channelPutGetReq = + syncCreateChannelPutGet(channel,request); + if (!channelPutGetReq.get()) { + testFail("%s: creating a channel putget failed ", CURRENT_FUNCTION); + return; + } + + + std::tr1::shared_ptr putValue = channelPutGetReq->getPVPutStructure()->getDoubleField("value"); + if (!putValue.get()) { + testFail("%s: getting put double value field failed ", CURRENT_FUNCTION); + return; + } + + double initVal = 321.0; + putValue->put(initVal); + + std::tr1::shared_ptr getValuePtr = channelPutGetReq->getPVGetStructure()->getDoubleField("value"); + if (!getValuePtr.get()) { + testFail("%s: getting get double value field failed ", CURRENT_FUNCTION); + return; + } + + bool succStatus = channelPutGetReq->syncPutGet(false, getTimeoutSec()); + if (!succStatus) { + testFail("%s: syncPutGet failed ", CURRENT_FUNCTION); + return; + } + else { + testOk(true, "%s: a syncPutGet succeeded", CURRENT_FUNCTION); + } + + testOk(getValuePtr->get() == initVal, "value after syncPutGet should be initVal"); + + testDiag("%s: testing putGet", CURRENT_FUNCTION); + + putValue->put(initVal + 1.0); + + succStatus = channelPutGetReq->syncPutGet(false, getTimeoutSec()); + if (!succStatus) { + testFail("%s: second syncPutGet failed ", CURRENT_FUNCTION); + return; + } + else { + testOk(true, "%s: a syncPutGet succeeded", CURRENT_FUNCTION); + } + + testOk(getValuePtr->get() == initVal + 1.0, "value after syncPutGet should be initVal + 1"); + + channel->destroy(); +} + + +void ChannelAccessIFTest::test_channelPutGetNoProcess_getPut() { + + testDiag("BEGIN TEST %s:", CURRENT_FUNCTION); + + string request = "putField(value)getField(timeStamp,value)"; + + Channel::shared_pointer channel = syncCreateChannel(TEST_VALUEONLY_CHANNEL_NAME); + if (!channel.get()) { + testFail("%s: channel not created ", CURRENT_FUNCTION); + return; + } + + SyncChannelPutGetRequesterImpl::shared_pointer channelPutGetReq = + syncCreateChannelPutGet(channel,request); + if (!channelPutGetReq.get()) { + testFail("%s: creating a channel putget failed ", CURRENT_FUNCTION); + return; + } + + + std::tr1::shared_ptr putValue = channelPutGetReq->getPVPutStructure()->getDoubleField("value"); + if (!putValue.get()) { + testFail("%s: getting put double value field failed ", CURRENT_FUNCTION); + return; + } + + double initVal = 321.0; + putValue->put(initVal); + + std::tr1::shared_ptr getValuePtr = channelPutGetReq->getPVGetStructure()->getDoubleField("value"); + if (!getValuePtr.get()) { + testFail("%s: getting get double value field failed ", CURRENT_FUNCTION); + return; + } + + testDiag("%s: first put the initial pvPutStructure into the record", CURRENT_FUNCTION); + + bool succStatus = channelPutGetReq->syncPutGet(false, getTimeoutSec()); + if (!succStatus) { + testFail("%s: syncPutGet failed ", CURRENT_FUNCTION); + return; + } + else { + testOk(true, "%s: a syncPutGet succeeded", CURRENT_FUNCTION); + } + + testDiag("%s: get the current data from the record and put it into pvPutStructure", CURRENT_FUNCTION); + + succStatus = channelPutGetReq->syncGetPut(getTimeoutSec()); + if (!succStatus) { + testFail("%s: syncGetPut failed ", CURRENT_FUNCTION); + return; + } + else { + testOk(true, "%s: a syncGetPut succeeded", CURRENT_FUNCTION); + } + + testOk(putValue->get() == initVal, "value after syncGetPut should be initVal"); + + channel->destroy(); +} + + +void ChannelAccessIFTest::test_channelPutGetNoProcess_getGet() { + + testDiag("BEGIN TEST %s:", CURRENT_FUNCTION); + + string request = "putField(value)getField(timeStamp,value)"; + + Channel::shared_pointer channel = syncCreateChannel(TEST_VALUEONLY_CHANNEL_NAME); + if (!channel.get()) { + testFail("%s: channel not created ", CURRENT_FUNCTION); + return; + } + + SyncChannelPutGetRequesterImpl::shared_pointer channelPutGetReq = + syncCreateChannelPutGet(channel,request); + if (!channelPutGetReq.get()) { + testFail("%s: creating a channel putget failed ", CURRENT_FUNCTION); + return; + } + + + std::tr1::shared_ptr putValue = channelPutGetReq->getPVPutStructure()->getDoubleField("value"); + if (!putValue.get()) { + testFail("%s: getting put double value field failed ", CURRENT_FUNCTION); + return; + } + + double initVal = 432.0; + putValue->put(initVal); + + std::tr1::shared_ptr getValuePtr = channelPutGetReq->getPVGetStructure()->getDoubleField("value"); + if (!getValuePtr.get()) { + testFail("%s: getting get double value field failed ", CURRENT_FUNCTION); + return; + } + + testDiag("%s: first put the initial pvPutStructure into the record", CURRENT_FUNCTION); + + bool succStatus = channelPutGetReq->syncPutGet(false, getTimeoutSec()); + if (!succStatus) { + testFail("%s: syncPutGet failed ", CURRENT_FUNCTION); + return; + } + else { + testOk(true, "%s: a syncPutGet succeeded", CURRENT_FUNCTION); + } + + testDiag("%s: get the current data from the record and put it into pvGetStructure", CURRENT_FUNCTION); + + succStatus = channelPutGetReq->syncGetGet(getTimeoutSec()); + if (!succStatus) { + testFail("%s: syncGetGet failed ", CURRENT_FUNCTION); + return; + } + else { + testOk(true, "%s: a syncGetGet succeeded", CURRENT_FUNCTION); + } + + testOk(getValuePtr->get() == initVal, "value after syncGetGet should be initVal"); + + channel->destroy(); +} + + +void ChannelAccessIFTest::test_channelPutGetNoProcess_destroy() { + + testDiag("BEGIN TEST %s:", CURRENT_FUNCTION); + + string request = "putField(value)getField(timeStamp,value)"; + + Channel::shared_pointer channel = syncCreateChannel(TEST_VALUEONLY_CHANNEL_NAME); + if (!channel.get()) { + testFail("%s: channel not created ", CURRENT_FUNCTION); + return; + } + + SyncChannelPutGetRequesterImpl::shared_pointer channelPutGetReq = + syncCreateChannelPutGet(channel,request); + if (!channelPutGetReq.get()) { + testFail("%s: creating a channel putget failed ", CURRENT_FUNCTION); + return; + } + + bool succStatus = channelPutGetReq->syncPutGet(true, getTimeoutSec()); + if (!succStatus) { + testFail("%s: syncPutGet failed ", CURRENT_FUNCTION); + return; + } + else { + testOk(true, "%s: syncPutGet succeeded", CURRENT_FUNCTION); + } + + testDiag("%s: destroying a channel putget", CURRENT_FUNCTION); + channelPutGetReq->getChannelPutGet()->destroy(); + + + succStatus = channelPutGetReq->syncPutGet(true, getTimeoutSec()); + if (!succStatus) { + testOk(true, "%s: syncPutGet on a destroyed channel should not succeed", CURRENT_FUNCTION); + } + else { + testFail("%s: syncPutGet on a destroyed channel succeeded ", CURRENT_FUNCTION); + } + + channel->destroy(); +} + + +void ChannelAccessIFTest::test_channelPutGetIntProcess() { + + testDiag("BEGIN TEST %s:", CURRENT_FUNCTION); + + string request = "record[process=true]putField(value)getField(timeStamp,value)"; + + Channel::shared_pointer channel = syncCreateChannel(TEST_COUNTER_CHANNEL_NAME); + if (!channel.get()) { + testFail("%s: channel not created ", CURRENT_FUNCTION); + return; + } + + SyncChannelPutGetRequesterImpl::shared_pointer channelPutGetReq = + syncCreateChannelPutGet(channel,request); + if (!channelPutGetReq.get()) { + testFail("%s: creating a channel putget failed ", CURRENT_FUNCTION); + return; + } + + + std::tr1::shared_ptr putValue = channelPutGetReq->getPVPutStructure()->getIntField("value"); + if (!putValue.get()) { + testFail("%s: getting put int value field failed ", CURRENT_FUNCTION); + return; + } + + int initVal = 3; + putValue->put(initVal); + + std::tr1::shared_ptr getValuePtr = channelPutGetReq->getPVGetStructure()->getIntField("value"); + if (!getValuePtr.get()) { + testFail("%s: getting get int value field failed ", CURRENT_FUNCTION); + return; + } + + PVTimeStamp pvTimeStamp; + + testOk(pvTimeStamp.attach(channelPutGetReq->getPVGetStructure()->getStructureField("timeStamp")), + "%s: attaching a timestamp", CURRENT_FUNCTION); + + TimeStamp timeStamp; + + bool succStatus = channelPutGetReq->syncGetGet(getTimeoutSec()); + if (!succStatus) { + testFail("%s: syncGetGet failed ", CURRENT_FUNCTION); + return; + } + else { + testOk(true, "%s: a syncGetGet succeeded", CURRENT_FUNCTION); + } + + pvTimeStamp.get(timeStamp); + + int numOfTimes = 3; + + for (int i = 0; i < numOfTimes; i++) { + + int previousValue = getValuePtr->get(); + long previousTimestampSec = timeStamp.getSecondsPastEpoch(); + + cout << "previousValue:" << previousValue << " previousTimestampSec:" << previousTimestampSec << endl; + cout << "next val:" << ((previousValue +1) % 11) << endl; + + + putValue->put((previousValue + 1) % 11); + + succStatus = channelPutGetReq->syncPutGet(i == numOfTimes, getTimeoutSec()); + if (!succStatus) { + testFail("%s: syncPutGet failed ", CURRENT_FUNCTION); + return; + } + + epicsThreadSleep(1.0); + + pvTimeStamp.get(timeStamp); + + int testValue = (previousValue +1 + 1) % 11; //+1 (new value) +1 (process) + + cout << "Testing1:" << testValue << " == " << getValuePtr->get() << endl; + cout << "Testing2:" << timeStamp.getSecondsPastEpoch() << ">" << previousTimestampSec << endl; + testOk( testValue == getValuePtr->get(), "%s: testing the counter value change", + CURRENT_FUNCTION); + testOk(timeStamp.getSecondsPastEpoch() > previousTimestampSec, + "%s: testing the timestamp change", CURRENT_FUNCTION); + } + + channel->destroy(); +} + + +void ChannelAccessIFTest::test_channelRPC() { + + testDiag("BEGIN TEST %s:", CURRENT_FUNCTION); + + string request = "record[process=true]putField(value)getField(timeStamp,value)"; + + Channel::shared_pointer channel = syncCreateChannel(TEST_SUMRPC_CHANNEL_NAME); + if (!channel.get()) { + testFail("%s: channel not created ", CURRENT_FUNCTION); + return; + } + + SyncChannelRPCRequesterImpl::shared_pointer channelRPCReq = syncCreateChannelRPC(channel); + if (!channelRPCReq.get()) { + testFail("%s: creating a channel rpc failed ", CURRENT_FUNCTION); + return; + } + + bool succStatus = channelRPCReq->syncRPC( + createSumArgumentStructure(1,2),false, getTimeoutSec()); + if (succStatus) { + testOk(true, "%s: calling sum rpc service successfull", CURRENT_FUNCTION); + testOk(channelRPCReq->getLastResponse()->getIntField("c")->get() == 3, + "%s: rpc service returned correct sum", CURRENT_FUNCTION); + } + else { + testFail("%s: error calling syncRPC ", CURRENT_FUNCTION); + } + + channel->destroy(); +} + + +void ChannelAccessIFTest::test_channelRPC_destroy() { + + testDiag("BEGIN TEST %s:", CURRENT_FUNCTION); + + string request = "record[process=true]putField(value)getField(timeStamp,value)"; + + Channel::shared_pointer channel = syncCreateChannel(TEST_SUMRPC_CHANNEL_NAME); + if (!channel.get()) { + testFail("%s: channel not created ", CURRENT_FUNCTION); + return; + } + + SyncChannelRPCRequesterImpl::shared_pointer channelRPCReq = syncCreateChannelRPC(channel); + if (!channelRPCReq.get()) { + testFail("%s: creating a channel rpc failed ", CURRENT_FUNCTION); + return; + } + + testDiag("%s: destroying the channel rpc", CURRENT_FUNCTION); + channelRPCReq->getChannelRPC()->destroy(); + + bool succStatus = channelRPCReq->syncRPC( + createSumArgumentStructure(1,2),false, getTimeoutSec()); + if (succStatus) { + testFail("%s: rpc call succeded on a destroyed channel ", CURRENT_FUNCTION); + } + else { + testOk(true, "%s: rpc call should not succeed on a destroyed channel ", CURRENT_FUNCTION); + } + + channel->destroy(); +} + + +void ChannelAccessIFTest::test_channelRPCWithInvalidRequesterAndRequest() { + + testDiag("BEGIN TEST %s:", CURRENT_FUNCTION); + + string request = "record[process=true]putField(value)getField(timeStamp,value)"; + + Channel::shared_pointer channel = syncCreateChannel(TEST_SUMRPC_CHANNEL_NAME); + if (!channel.get()) { + testFail("%s: channel not created ", CURRENT_FUNCTION); + return; + } + + testSkip(1, " creating a channel rpc with a null channel"); + //SyncChannelRPCRequesterImpl::shared_pointer channelRPCReq = + //syncCreateChannelRPC(Channel::shared_pointer()); + + SyncChannelRPCRequesterImpl::shared_pointer channelRPCReq = syncCreateChannelRPC(channel); + if (!channelRPCReq.get()) { + testFail("%s: creating a channel rpc failed ", CURRENT_FUNCTION); + return; + } + + + testSkip(1, " skiping a rpc request with an empty pvArguments"); + //bool succStatus = channelRPCReq->syncRPC( + // PVStructure::shared_pointer(), false, getTimeoutSec()); + // if (!succStatus) { + // testOk(true, "%s: calling sum rpc service with an empty pvArguments should not succeed", CURRENT_FUNCTION); + // } + // else { + // testFail("%s: rpc request with an empty pvArguments succeeded ", CURRENT_FUNCTION); + // } + + channel->destroy(); +} + + +void ChannelAccessIFTest::test_channelMonitorWithInvalidRequesterAndRequest() { + + testDiag("BEGIN TEST %s:", CURRENT_FUNCTION); + + string request = "record[queueSize=3]field(timeStamp)"; + + Channel::shared_pointer channel = syncCreateChannel(TEST_COUNTER_CHANNEL_NAME); + if (!channel.get()) { + testFail("%s: channel not created ", CURRENT_FUNCTION); + return; + } + + testSkip(true, " creating a monitoring channel with a null channel"); + + //SyncMonitorRequesterImpl::shared_pointer monitorReq = + // syncCreateChannelMonitor(Channel::shared_pointer(), request); + + + SyncMonitorRequesterImpl::shared_pointer monitorReq1 = + syncCreateChannelMonitor(channel, string()); + if (monitorReq1.get()) { + testOk(true, "%s: a monitor requester with an empty request created ", CURRENT_FUNCTION); + } + else { + testFail("%s: a monitor requester with an empty request not created ", CURRENT_FUNCTION); + } + + channel->destroy(); +} + + +void ChannelAccessIFTest::test_channelMonitor(int queueSize) { + + testDiag("BEGIN TEST %s:", CURRENT_FUNCTION); + ostringstream ostream; + ostream << queueSize; + string request = "record[queueSize="; + request.append(ostream.str()); + request.append("]field(timeStamp,value)"); + + Channel::shared_pointer channel = syncCreateChannel(TEST_COUNTER_CHANNEL_NAME); + if (!channel.get()) { + testFail("%s: channel not created ", CURRENT_FUNCTION); + return; + } + + SyncMonitorRequesterImpl::shared_pointer monitorReq = + syncCreateChannelMonitor(channel,request); + if (!monitorReq.get()) { + testFail("%s: creating a channel monitor failed ", CURRENT_FUNCTION); + return; + } + + testOk(monitorReq->getMonitorCounter() == 0, "%s: monitoring counter before calling start should be zero", + CURRENT_FUNCTION); + + monitorReq->getChannelMonitor()->start(); + + bool succStatus = monitorReq->waitUntilMonitor(getTimeoutSec()); + if (!succStatus) { + testFail("%s: no monitoring event happened ", CURRENT_FUNCTION); + return; + } + else { + testOk(monitorReq->getMonitorCounter() == 1, "%s: monitor event happened", CURRENT_FUNCTION); + testOk(monitorReq->getChangedBitSet()->cardinality() == 1, "%s: monitor cardinality is 1", CURRENT_FUNCTION); + testOk(monitorReq->getChangedBitSet()->get(0) == true, "%s: changeBitSet get(0) is true ", CURRENT_FUNCTION); + } + + std::tr1::shared_ptr valueField = monitorReq->getPVStructure()->getSubField("value"); + std::tr1::shared_ptr previousValue = getPVDataCreate()->createPVField(valueField->getField()); + + ConvertPtr convert = getConvert(); + convert->copy(valueField, previousValue); + + testOk(valueField->equals(*previousValue.get()) == true , "%s: value field equals to a previous value", + CURRENT_FUNCTION); + + for (int i = 2; i < 5; i++ ) { + + succStatus = monitorReq->waitUntilMonitor(getTimeoutSec()); + if (!succStatus) { + testFail("%s: no further monitoring event happened ", CURRENT_FUNCTION); + return; + } + + testOk(monitorReq->getMonitorCounter() == i, "%s: monitor event happened for i=%d", CURRENT_FUNCTION, i); + + if (queueSize == 1 ) { + testOk(monitorReq->getChangedBitSet()->cardinality() == 1, "%s: monitor cardinality is 1 (queue size = 1)", + CURRENT_FUNCTION); + testOk(monitorReq->getChangedBitSet()->get(0) == true, "%s: changeBitSet get(0) is true (queue size = 1)", + CURRENT_FUNCTION); + } + else { + testOk(monitorReq->getChangedBitSet()->cardinality() == 2, "%s: monitor cardinality is 1 (queue size != 1)", + CURRENT_FUNCTION); + testOk(monitorReq->getChangedBitSet()->get(1) == true, "%s: changeBitSet get(1) is true (queue size != 1)", + CURRENT_FUNCTION); + testOk(monitorReq->getChangedBitSet()->get(4) == true, "%s: changeBitSet get(4) is true (queue size != 1)", + CURRENT_FUNCTION); + + } + + + valueField = monitorReq->getPVStructure()->getSubField("value"); + + testOk(valueField->equals(*previousValue.get()) == false , "%s: value field not equals to a previous value", + CURRENT_FUNCTION); + + convert->copy(valueField, previousValue); + } + + + monitorReq->getChannelMonitor()->stop(); + epicsThreadSleep(1.0); + int mc = monitorReq->getMonitorCounter(); + epicsThreadSleep(2.0); + testOk(mc == monitorReq->getMonitorCounter(), "%s: after monitor stop the counter should not increase", + CURRENT_FUNCTION); + channel->destroy(); +} + + +void ChannelAccessIFTest::test_channelArray() { + + testDiag("BEGIN TEST %s:", CURRENT_FUNCTION); + + bool debug = false; + + Channel::shared_pointer channel = syncCreateChannel(TEST_ARRAY_CHANNEL_NAME, debug); + if (!channel.get()) { + testFail("%s: channel not created ", CURRENT_FUNCTION); + return; + } + + StringArray fieldNames; fieldNames.push_back("field"); + FieldConstPtrArray fields; fields.push_back(getFieldCreate()->createScalar(pvString)); + PVStructure::shared_pointer pvRequest(getPVDataCreate()->createPVStructure( + getFieldCreate()->createStructure(fieldNames, fields))); + + PVString::shared_pointer pvFieldName = pvRequest->getStringField("field"); + pvFieldName->put("value"); + + SyncChannelArrayRequesterImpl::shared_pointer arrayReq = + syncCreateChannelArray(channel, pvRequest); + if (!arrayReq.get()) { + testFail("%s: creating a channel array failed ", CURRENT_FUNCTION); + return; + } + + PVDoubleArrayPtr array = static_pointer_cast(arrayReq->getArray()); + + bool succStatus = arrayReq->syncGet(false, 0, 2, getTimeoutSec()); + if (!succStatus) { + testFail("%s: an array syncGet failed (1) ", CURRENT_FUNCTION); + return; + } + + unsigned numOfElements = 5; + PVDoubleArray::svector newdata; + + //inserting 1.1 2.2 3.3 4.4 5.5 + for (unsigned i = 1 ; i <= numOfElements; i++) { + double val = i+i*0.1; + newdata.push_back(val); + } + + array->replace(freeze(newdata)); + + succStatus = arrayReq->syncPut(false, 0, -1, getTimeoutSec()); + if (!succStatus) { + testFail("%s: an array syncPut failed (2) ", CURRENT_FUNCTION); + return; + } + + succStatus = arrayReq->syncGet(false, 0, -1, getTimeoutSec()); + if (!succStatus) { + testFail("%s: an array syncGet failed (3) ", CURRENT_FUNCTION); + return; + } + + PVDoubleArray::const_svector data(array->view()); + testOk(data.size() == numOfElements, "%s: data array size should be %d", + CURRENT_FUNCTION, numOfElements); + + + //checking 1.1 2.2 3.3 4.4 5.5 + for (unsigned i = 0; i < numOfElements; i++) { + int ii = i + 1; + testOk(data[i] == (ii+ii*0.1), "%s: data slot %d should be %f", CURRENT_FUNCTION, i, (ii+ii*0.1)); + } + + + succStatus = arrayReq->syncPut(false, 4, data.size(), getTimeoutSec()); + if (!succStatus) { + testFail("%s: an array syncPut failed (5)", CURRENT_FUNCTION); + return; + } + + succStatus = arrayReq->syncGet(false, 3, 3, getTimeoutSec()); + if (!succStatus) { + testFail("%s: an array syncGet failed (6) ", CURRENT_FUNCTION); + return; + } + + + PVDoubleArrayPtr array1 = static_pointer_cast(arrayReq->getArray()); + PVDoubleArray::const_svector data1(array1->view()); + testOk(data1[0] == 4.4 , "%s: check 0: %f", CURRENT_FUNCTION, data1[0]); + testOk(data1[1] == 1.1 , "%s: check 1: %f", CURRENT_FUNCTION, data1[1]); + testOk(data1[2] == 2.2 , "%s: check 2: %f", CURRENT_FUNCTION, data1[2]); + + + succStatus = arrayReq->syncSetLength(false, 4, 3, -1); + if (!succStatus) { + testFail("%s: an array setLength failed ", CURRENT_FUNCTION); + return; + } + + succStatus = arrayReq->syncGet(false, 0, -1, getTimeoutSec()); + if (!succStatus) { + testFail("%s: an array syncGet failed (7) ", CURRENT_FUNCTION); + return; + } + + PVDoubleArrayPtr array2 = static_pointer_cast(arrayReq->getArray()); + PVDoubleArray::const_svector data2(array2->view()); + testOk(data2.size() == 3, "%s: data size after calling setLength should be 3", CURRENT_FUNCTION); + testOk(data2[0] == 1.1 , "%s: check 0: %f", CURRENT_FUNCTION, data2[0]); + testOk(data2[1] == 2.2 , "%s: check 1: %f", CURRENT_FUNCTION, data2[1]); + testOk(data2[2] == 3.3, "%s: check 2: %f", CURRENT_FUNCTION, data2[2]); + + + + + channel->destroy(); +} + + +void ChannelAccessIFTest::test_channelArray_destroy() { + + testDiag("BEGIN TEST %s:", CURRENT_FUNCTION); + + bool debug = false; + + Channel::shared_pointer channel = syncCreateChannel(TEST_ARRAY_CHANNEL_NAME, debug); + if (!channel.get()) { + testFail("%s: channel not created ", CURRENT_FUNCTION); + return; + } + + StringArray fieldNames; fieldNames.push_back("field"); + FieldConstPtrArray fields; fields.push_back(getFieldCreate()->createScalar(pvString)); + PVStructure::shared_pointer pvRequest(getPVDataCreate()->createPVStructure( + getFieldCreate()->createStructure(fieldNames, fields))); + + PVString::shared_pointer pvFieldName = pvRequest->getStringField("field"); + pvFieldName->put("value"); + + SyncChannelArrayRequesterImpl::shared_pointer arrayReq = + syncCreateChannelArray(channel, pvRequest); + if (!arrayReq.get()) { + testFail("%s: creating a channel array failed ", CURRENT_FUNCTION); + return; + } + + bool succStatus = arrayReq->syncGet(false, 0, 2, getTimeoutSec()); + if (!succStatus) { + testFail("%s: an array syncGet failed ", CURRENT_FUNCTION); + return; + } + + testDiag("%s: Destroying the channels", CURRENT_FUNCTION); + + channel->destroy(); + + arrayReq->getChannelArray()->destroy(); + + succStatus = arrayReq->syncGet(false, 0, 2, getTimeoutSec()); + if (!succStatus) { + testOk(true,"%s: an array sync get should not succeed on a destroyed channel", CURRENT_FUNCTION); + } + else { + testFail("%s: an array syncGet failed ", CURRENT_FUNCTION); + } + +} + + +void ChannelAccessIFTest::test_stressConnectDisconnect() { + + testDiag("BEGIN TEST %s:", CURRENT_FUNCTION); + + int count = 300; + bool debug = false; + + testDiag("%s: stress test connect-disconnect %d times", CURRENT_FUNCTION, count); + + for (int i = 0; i < count; i++) { + Channel::shared_pointer channel = syncCreateChannel(TEST_VALUEONLY_CHANNEL_NAME, debug); + if (!channel.get()) { + testFail("%s: channel not created ", CURRENT_FUNCTION); + return; + } + channel->destroy(); + } + + testOk(true, "%s: stress test connect-disconnect successfull", CURRENT_FUNCTION); +} + + +void ChannelAccessIFTest::test_stressConnectGetDisconnect() { + + testDiag("BEGIN TEST %s:", CURRENT_FUNCTION); + + string request = "field(value)"; + int count = 300; + bool debug = false; + + + testDiag("%s: stress testing connect-get-disconnect %d times", CURRENT_FUNCTION, count); + + for (int i = 0; i < count; i++) { + + Channel::shared_pointer channel = syncCreateChannel(TEST_VALUEONLY_CHANNEL_NAME, debug); + if (!channel.get()) { + testFail("%s: channel not created ", CURRENT_FUNCTION); + return; + } + + + SyncChannelGetRequesterImpl::shared_pointer channelGetReq = syncCreateChannelGet(channel, request, debug); + if (!channelGetReq.get()) { + testFail("%s: channel get not created ", CURRENT_FUNCTION); + return; + } + + bool succStatus = channelGetReq->syncGet(true, getTimeoutSec()); + if (!succStatus) { + testFail("%s: sync get failed ", CURRENT_FUNCTION); + return; + } + + channel->destroy(); + } + + testOk(true, "%s: stress test connect-disconnect successfull", CURRENT_FUNCTION); +} + + +void ChannelAccessIFTest::test_stressMonitorAndProcess() { + + testDiag("BEGIN TEST %s:", CURRENT_FUNCTION); + + string request = "record[queueSize=3]field(timeStamp,value,alarm.severity.choices)"; + bool debug = false; + + Channel::shared_pointer channel = syncCreateChannel(TEST_COUNTER_CHANNEL_NAME, debug); + if (!channel.get()) { + testFail("%s: channel not created ", CURRENT_FUNCTION); + return; + } + + SyncMonitorRequesterImpl::shared_pointer monitorReq = + syncCreateChannelMonitor(channel, request, debug); + if (!monitorReq.get()) { + testFail("%s: creating a channel monitor failed ", CURRENT_FUNCTION); + return; + } + + testOk(monitorReq->getMonitorCounter() == 0, "%s: monitoring counter before calling start should be zero", + CURRENT_FUNCTION); + + + shared_ptr + channelProcessReq(new SyncChannelProcessRequesterImpl(debug)); + + ChannelProcess::shared_pointer channelProcess = + channel->createChannelProcess(channelProcessReq, + epics::pvData::PVStructure::shared_pointer()); + + bool succStatus = channelProcessReq->waitUntilConnected(getTimeoutSec()); + if (!succStatus) { + testFail("%s: a channel process is not connected ", CURRENT_FUNCTION); + return; + } + + + monitorReq->getChannelMonitor()->start(); + + succStatus = monitorReq->waitUntilMonitor(getTimeoutSec()); + if (!succStatus) { + testFail("%s: no monitoring event happened ", CURRENT_FUNCTION); + return; + } + else { + testOk(monitorReq->getMonitorCounter() == 1, "%s: monitor event happened", CURRENT_FUNCTION); + } + + int count = 50000; + + testDiag("%s: stress testing monitor-process %d times", CURRENT_FUNCTION, count); + + for (int i = 2; i < count; i++ ) { + + succStatus = channelProcessReq->syncProcess(false, getTimeoutSec()); + if (!succStatus) { + testFail("%s: syncProcess failed ", CURRENT_FUNCTION); + return; + } + + while(monitorReq->getMonitorCounter() < i) { + monitorReq->waitUntilMonitor(getTimeoutSec()); + } + + int counter = monitorReq->getMonitorCounter(); + + if (counter != i ) { + testFail("%s: monitor counter != i. monitorCounter: %d, i:%d", CURRENT_FUNCTION, counter, i); + return; + } + } + + testOk(true, "%s: stress testing monitor-process successfull", CURRENT_FUNCTION); +} + + +PVStructure::shared_pointer ChannelAccessIFTest::createSumArgumentStructure(int a, int b) { + + int i = 0; + StringArray fieldNames(2); + FieldConstPtrArray fields(2); + fieldNames[i] = "a"; + fields[i++] = getFieldCreate()->createScalar(pvInt); + fieldNames[i] = "b"; + fields[i++] = getFieldCreate()->createScalar(pvInt); + + PVStructure::shared_pointer pvArguments( + getPVDataCreate()->createPVStructure( + getFieldCreate()->createStructure(fieldNames, fields))); + + pvArguments->getIntField("a")->put(a); + pvArguments->getIntField("b")->put(b); + + return pvArguments; + +} + diff --git a/testApp/remote/channelAccessIFTest.h b/testApp/remote/channelAccessIFTest.h new file mode 100755 index 0000000..1e7ab16 --- /dev/null +++ b/testApp/remote/channelAccessIFTest.h @@ -0,0 +1,151 @@ +#ifndef CHANNELACCESSIFTEST_HPP +#define CHANNELACCESSIFTEST_HPP + +#include +#include "syncTestRequesters.h" + + +class ChannelAccessIFTest { + + public: + + int runAllTest(); + + ~ChannelAccessIFTest() {} + + protected: + + static std::string TEST_COUNTER_CHANNEL_NAME; + static std::string TEST_CHANNEL_NAME; + static std::string TEST_VALUEONLY_CHANNEL_NAME; + static std::string TEST_SUMRPC_CHANNEL_NAME; + static std::string TEST_ARRAY_CHANNEL_NAME; + + + virtual ChannelProvider::shared_pointer getChannelProvider() = 0; + virtual long getTimeoutSec() = 0; + virtual bool isLocal() = 0; + + + Channel::shared_pointer createChannel(std::string channelName, bool debug = true ); + + + Channel::shared_pointer syncCreateChannel(std::string channelName, bool debug = true ); + + + SyncChannelGetRequesterImpl::shared_pointer syncCreateChannelGet( + Channel::shared_pointer const & channel, std::string const & request, bool debug = true ); + + + SyncChannelPutRequesterImpl::shared_pointer syncCreateChannelPut( + Channel::shared_pointer const & channel, std::string const & request, bool debug = true ); + + + SyncChannelPutGetRequesterImpl::shared_pointer syncCreateChannelPutGet( + Channel::shared_pointer const & channel, std::string const & request, bool debug = true ); + + + SyncChannelRPCRequesterImpl::shared_pointer syncCreateChannelRPC( + Channel::shared_pointer const & channel, bool debug = true); + + + SyncMonitorRequesterImpl::shared_pointer syncCreateChannelMonitor( + Channel::shared_pointer const & channel, std::string const & request, bool debug = true); + + SyncChannelArrayRequesterImpl::shared_pointer syncCreateChannelArray( + Channel::shared_pointer const & channel, PVStructure::shared_pointer pvRequest, bool debug = true); + + + private: + + void test_implementation(); + + void test_providerName(); + + void test_createEmptyChannel(); + + void test_createChannelWithInvalidPriority(); + + void test_createChannel(); + + void test_recreateChannelOnDestroyedProvider(); + + void test_findEmptyChannel(); + + void test_findChannel(); + + void test_channel(); + + void test_channelGetWithInvalidChannelAndRequester(); + + void test_channelGetNoProcess(); + + void test_channelGetIntProcess(); + + void test_channelGetNotYetConnected(); + + void test_channelGetIntProcessInternal(Channel::shared_pointer channel, std::string const & testMethodName); + + void test_channelGetTestNoConnection(); + + void test_channelPutWithInvalidChannelAndRequester(); + + void test_channelPutNoProcess(); + + void test_channelPutIntProcess(); + + void test_channelPutNotYetConnected(); + + void test_channelPutIntProcessInternal(Channel::shared_pointer channel, std::string const & testMethodName); + + void test_channelPutTestNoConnection(); + + void test_channelGetFieldAll(); + + void test_channelGetFieldValue(); + + void test_channelGetFieldInvalid(); + + void test_channelProcess(); + + void test_channelProcesstWithInvalidRequesterAndRequest(); + + void test_channelProcessNoConnection(); + + void test_channelPutGetWithInvalidRequesterAndRequest(); + + void test_channelPutGetNoProcess_putGet(); + + void test_channelPutGetNoProcess_getPut(); + + void test_channelPutGetNoProcess_getGet(); + + void test_channelPutGetNoProcess_destroy(); + + void test_channelPutGetIntProcess(); + + void test_channelRPC(); + + void test_channelRPC_destroy(); + + void test_channelRPCWithInvalidRequesterAndRequest(); + + void test_channelMonitorWithInvalidRequesterAndRequest(); + + void test_channelMonitor(int queueSize); + + void test_channelArray(); + + void test_channelArray_destroy(); + + void test_stressConnectDisconnect(); + + void test_stressConnectGetDisconnect(); + + void test_stressMonitorAndProcess(); + + PVStructure::shared_pointer createSumArgumentStructure(int a, int b); + +}; + +#endif diff --git a/testApp/remote/syncTestRequesters.h b/testApp/remote/syncTestRequesters.h new file mode 100755 index 0000000..9df24b8 --- /dev/null +++ b/testApp/remote/syncTestRequesters.h @@ -0,0 +1,1323 @@ +#ifndef SYNCTESTREQUESTERS_HPP +#define SYNCTESTREQUESTERS_HPP + + +#include +#include + +using namespace epics::pvAccess; +using namespace epics::pvData; +using namespace std; +using std::tr1::static_pointer_cast; +using std::tr1::dynamic_pointer_cast; + + +class SyncBaseRequester { + + public: + + bool waitUntilGetDone(double timeOut) + { + + bool signaled = waitUntilEvent(timeOut); + if (!signaled) + return false; + + Lock lock(m_getStatusMutex); + return m_getStatus; + } + + + bool waitUntilConnected(double timeOut) + { + + bool signaled = waitUntilEvent(timeOut); + if (!signaled) + return false; + + Lock lock(m_connectedStatusMutex); + return m_connectedStatus; + } + + virtual ~SyncBaseRequester() {} ; + + + protected: + + const bool m_debug; + + SyncBaseRequester(bool debug = true): + m_debug(debug), + m_connectedStatus(false), + m_getStatus(false), + m_putStatus(false) {} + + + bool waitUntilPutDone(double timeOut) + { + + bool signaled = waitUntilEvent(timeOut); + if (!signaled) + return false; + + Lock lock(m_putStatusMutex); + return m_putStatus; + } + + + bool waitUntilProcessDone(double timeOut) + { + + bool signaled = waitUntilEvent(timeOut); + if (!signaled) + return false; + + Lock lock(m_processStatusMutex); + return m_processStatus; + } + + + void setConnectedStatus(bool status) { + Lock lock(m_connectedStatusMutex); + m_connectedStatus = status; + } + + + bool getConnectedStatus() { + Lock lock(m_connectedStatusMutex); + return m_connectedStatus; + } + + + void setGetStatus(bool status) { + Lock lock(m_getStatusMutex); + m_getStatus = status; + } + + + bool getGetStatus() { + Lock lock(m_getStatusMutex); + return m_getStatus; + } + + + void setPutStatus(bool status) { + Lock lock(m_putStatusMutex); + m_putStatus = status; + } + + + bool getPutStatus() { + Lock lock(m_putStatusMutex); + return m_putStatus; + } + + + void setProcessStatus(bool status) { + Lock lock(m_processStatusMutex); + m_processStatus = status; + } + + + bool getProcessStatus() { + Lock lock(m_processStatusMutex); + return m_processStatus; + } + + + void signalEvent() { + m_event.signal(); + } + + + bool waitUntilEvent(double timeOut) + { + bool signaled = m_event.wait(timeOut); + if (!signaled) + { + if (m_debug) + std::cerr << "wait until event timeout" << std::endl; + + return false; + } + + return true; + } + + private: + + epics::pvData::Event m_event; + bool m_connectedStatus; + bool m_getStatus; + bool m_putStatus; + bool m_processStatus; + Mutex m_connectedStatusMutex; + Mutex m_getStatusMutex; + Mutex m_putStatusMutex; + Mutex m_processStatusMutex; +}; + + +class SyncChannelRequesterImpl : public epics::pvAccess::ChannelRequester, public SyncBaseRequester +{ + public: + + SyncChannelRequesterImpl(bool debug = true): SyncBaseRequester(debug), + m_createdCount(0), m_stateChangeCount(0) {} + + + bool waitUntilStateChange(double timeOut) + { + return waitUntilEvent(timeOut); + } + + + int getCreatedCount() { + Lock lock(m_pointerMutex); + return m_createdCount; + } + + + int getStateChangeCount() { + Lock lock(m_pointerMutex); + return m_stateChangeCount; + } + + + Status getStatus() { + Lock lock(m_pointerMutex); + return m_status; + } + + + virtual string getRequesterName() + { + return "SyncChannelRequesterImpl"; + } + + + virtual void message(string const &, epics::pvData::MessageType ) + { + } + + + virtual void channelCreated( + const epics::pvData::Status& status, + epics::pvAccess::Channel::shared_pointer const & channel) + { + if (m_debug) + std::cout << getRequesterName() << "." << "channelCreated(" << status.toString() << ")" << std::endl; + + Lock lock(m_pointerMutex); + m_status = status; + + if (status.isSuccess()) + { + m_createdCount++; + } + else + { + if (m_debug) + std::cerr << "[" << channel->getChannelName() << "] failed to create a channel: " << std::endl; + } + } + + + virtual void channelStateChange( + epics::pvAccess::Channel::shared_pointer const & , + epics::pvAccess::Channel::ConnectionState connectionState) + { + + if (m_debug) + std::cout << getRequesterName() << "." << "channelStateChange:" << connectionState << std::endl; + + { + Lock lock(m_pointerMutex); + m_stateChangeCount++; + } + + signalEvent(); + } + + private: + Mutex m_pointerMutex; + int m_createdCount; + int m_stateChangeCount; + Status m_status; +}; + + +class SyncChannelFindRequesterImpl : public ChannelFindRequester, public SyncBaseRequester +{ + public: + + SyncChannelFindRequesterImpl(bool debug = true): SyncBaseRequester(debug), m_isFound(false) {} + + + bool waitUntilFindResult(double timeOut) + { + return waitUntilEvent(timeOut); + } + + + Status getStatus() { + Lock lock(m_pointerMutex); + return m_status; + } + + + bool isChannelFound() { + Lock lock(m_pointerMutex); + return m_isFound; + } + + + virtual void channelFindResult(const epics::pvData::Status& status, + const epics::pvAccess::ChannelFind::shared_pointer&, bool wasFound) + { + if (m_debug) + std::cout << "channelFindResult(" << status.toString() << ")" << std::endl; + + { + Lock lock(m_pointerMutex); + m_status = status; + m_isFound = wasFound; + } + + signalEvent(); + } + + private: + Mutex m_pointerMutex; + Status m_status; + bool m_isFound; +}; + + +class SyncChannelGetRequesterImpl : public ChannelGetRequester, public SyncBaseRequester +{ + public: + + typedef std::tr1::shared_ptr shared_pointer; + + + SyncChannelGetRequesterImpl(string channelName, bool debug = true): + SyncBaseRequester(debug), + m_channelName(channelName) {} + + + bool syncGet(bool lastRequest, long timeOut) { + m_channelGet->get(lastRequest); + return waitUntilGetDone(timeOut); + } + + + PVStructure::shared_pointer getPVStructure() + { + Lock lock(m_pointerMutex); + return m_pvStructure; + } + + + BitSet::shared_pointer getBitSet() { + Lock lock(m_pointerMutex); + return m_bitSet; + } + + + ChannelGet::shared_pointer getChannelGet() { + Lock lock(m_pointerMutex); + return m_channelGet; + } + + + virtual string getRequesterName() + { + return "SyncChannelGetRequesterImpl"; + } + + + virtual void message(string const & message, MessageType messageType) + { + if (m_debug) + std::cerr << "[" + << getRequesterName() + << "] message(" + << message << ", " + << getMessageTypeName(messageType) + << ")" + << std::endl; + } + + + virtual void channelGetConnect( + const epics::pvData::Status& status,ChannelGet::shared_pointer const & channelGet, + epics::pvData::PVStructure::shared_pointer const & pvStructure, + epics::pvData::BitSet::shared_pointer const & bitSet) + { + if (m_debug) + std::cout << getRequesterName() << "." << "channelGetConnect(" << status.toString() << ")" << std::endl; + + if (status.isSuccess()) + { + { + Lock lock(m_pointerMutex); + m_channelGet = channelGet; + m_pvStructure = pvStructure; + m_bitSet = bitSet; + } + channelGet->get(false); + } + else + { + signalEvent(); + } + } + + + virtual void getDone(const epics::pvData::Status& status) + { + if (m_debug) + std::cout << getRequesterName() << "." << "getDone(" << status.toString() << ")" << std::endl; + + setGetStatus(status.isSuccess()); + signalEvent(); + } + + + private: + Mutex m_pointerMutex; + ChannelGet::shared_pointer m_channelGet; + PVStructure::shared_pointer m_pvStructure; + BitSet::shared_pointer m_bitSet; + string m_channelName; +}; + + + +class SyncChannelPutRequesterImpl : public ChannelPutRequester, public SyncBaseRequester +{ + public: + + typedef std::tr1::shared_ptr shared_pointer; + + SyncChannelPutRequesterImpl(string const & channelName, bool debug = true): + SyncBaseRequester(debug), m_channelName(channelName) {} + + + bool syncPut(bool lastRequest, long timeOut) + { + + if (!getConnectedStatus()) { + return false; + } + + m_channelPut->put(lastRequest); + return waitUntilPutDone(timeOut); + } + + + bool syncGet(long timeOut) + { + + if (!getConnectedStatus()) { + return false; + } + + m_channelPut->get(); + return waitUntilGetDone(timeOut); + } + + + PVStructure::shared_pointer getPVStructure() + { + Lock lock(m_pointerMutex); + return m_pvStructure; + } + + + BitSet::shared_pointer getBitSet() { + Lock lock(m_pointerMutex); + return m_bitSet; + } + + + ChannelPut::shared_pointer getChannelPut() { + Lock lock(m_pointerMutex); + return m_channelPut; + } + + + virtual string getRequesterName() + { + return "SyncChannelPutRequesterImpl"; + } + + + virtual void message(string const & message,MessageType messageType) + { + if (m_debug) + std::cout << "[" << getRequesterName() << "] message(" << message << ", " + << getMessageTypeName(messageType) << ")" << std::endl; + } + + + virtual void channelPutConnect(const epics::pvData::Status& status, + ChannelPut::shared_pointer const & channelPut, + epics::pvData::PVStructure::shared_pointer const & pvStructure, + epics::pvData::BitSet::shared_pointer const & bitSet) + { + + if (m_debug) + std::cout << getRequesterName() << "." << "channelPutConnect(" << status.toString() << ")" << std::endl; + + if (status.isSuccess()) + { + + { + Lock lock(m_pointerMutex); + m_channelPut = channelPut; + m_pvStructure = pvStructure; + m_bitSet = bitSet; + } + setConnectedStatus(true); + } + else + { + setConnectedStatus(false); + } + + signalEvent(); + } + + + virtual void getDone(const epics::pvData::Status& status) + { + if (m_debug) + std::cout << getRequesterName() << "." << "getDone(" << status.toString() << ")" << std::endl; + + setGetStatus(status.isSuccess()); + signalEvent(); + } + + + virtual void putDone(const epics::pvData::Status& status) + { + if (m_debug) + std::cout << getRequesterName() << "." << "putDone(" << status.toString() << ")" << std::endl; + + setPutStatus(status.isSuccess()); + signalEvent(); + } + + + private: + + Mutex m_pointerMutex; + ChannelPut::shared_pointer m_channelPut; + epics::pvData::PVStructure::shared_pointer m_pvStructure; + epics::pvData::BitSet::shared_pointer m_bitSet; + string m_channelName; +}; + + +class SyncGetFieldRequesterImpl : public GetFieldRequester, public SyncBaseRequester +{ + public: + + typedef std::tr1::shared_ptr shared_pointer; + + + SyncGetFieldRequesterImpl(bool debug = true): SyncBaseRequester(debug) {} + + + FieldConstPtr getField() { + Lock lock(m_pointerMutex); + return m_field; + } + + + virtual string getRequesterName() + { + return "SyncGetFieldRequesterImpl"; + }; + + + virtual void message(string const & message,MessageType /*messageType*/) + { + if (m_debug) + std::cout << "[" << getRequesterName() << "] message(" << message << endl; + } + + + virtual void getDone(const epics::pvData::Status& status,epics::pvData::FieldConstPtr const & field) + { + + if (m_debug) + std::cout << getRequesterName() << "." << "getDone(" << status.toString() << endl; + + if (status.isSuccess() && field) + { + { + Lock lock(m_pointerMutex); + m_field = field; + } + setGetStatus(true); + } + else { + setGetStatus(false); + } + + signalEvent(); + } + + private: + Mutex m_pointerMutex; + FieldConstPtr m_field; +}; + + +class SyncChannelProcessRequesterImpl : public ChannelProcessRequester, public SyncBaseRequester +{ + public: + + typedef std::tr1::shared_ptr shared_pointer; + + + SyncChannelProcessRequesterImpl(bool debug = true): SyncBaseRequester(debug) {} + + + bool syncProcess(bool lastRequest, double timeOut) { + if(!getConnectedStatus()) { + return false; + } + + m_channelProcess->process(lastRequest); + return waitUntilProcessDone(timeOut); + } + + + ChannelProcess::shared_pointer getChannelProcess() { + Lock lock(m_pointerMutex); + return m_channelProcess; + } + + + virtual string getRequesterName() + { + return "ProcessRequesterImpl"; + }; + + + virtual void message(string const & message,MessageType /*messageType*/) + { + if (m_debug) + std::cout << "[" << getRequesterName() << "] message(" << message << std::endl; + } + + + virtual void channelProcessConnect(const epics::pvData::Status& status, + ChannelProcess::shared_pointer const & channelProcess) + { + + if (m_debug) + std::cout << getRequesterName() << "." << "channelProcessConnect(" << status.toString() << ")" << std::endl; + + if (status.isSuccess()) + { + { + Lock lock(m_pointerMutex); + m_channelProcess = channelProcess; + } + setConnectedStatus(true); + } + else + { + setConnectedStatus(false); + } + + signalEvent(); + } + + + virtual void processDone(const epics::pvData::Status& status) + { + if (m_debug) + std::cout << getRequesterName() << "." << "processDone(" << status.toString() << ")" << std::endl; + + setProcessStatus(status.isSuccess()); + signalEvent(); + } + + + private: + Mutex m_pointerMutex; + ChannelProcess::shared_pointer m_channelProcess; +}; + + +class SyncChannelPutGetRequesterImpl : public ChannelPutGetRequester, public SyncBaseRequester +{ + public: + + typedef std::tr1::shared_ptr shared_pointer; + + + SyncChannelPutGetRequesterImpl(bool debug = true): + SyncBaseRequester(debug), + m_putGetStatus(false), + m_getPutStatus(false), + m_getGetStatus(false) {} + + + bool syncGetPut(double timeOut) { + + if(!getConnectedStatus()) { + return false; + } + + m_channelPutGet->getPut(); + return waitUntilGetPutDone(timeOut); + } + + + bool syncPutGet(bool lastRequest, double timeOut) { + + if(!getConnectedStatus()) { + return false; + } + + m_channelPutGet->putGet(lastRequest); + return waitUntilPutGetDone(timeOut); + } + + + bool syncGetGet(double timeOut) { + + if(!getConnectedStatus()) { + return false; + } + + m_channelPutGet->getGet(); + return waitUntilGetGetDone(timeOut); + } + + + PVStructure::shared_pointer getPVPutStructure() + { + Lock lock(m_pointerMutex); + return m_putData; + } + + + PVStructure::shared_pointer getPVGetStructure() + { + Lock lock(m_pointerMutex); + return m_getData; + } + + + ChannelPutGet::shared_pointer getChannelPutGet() + { + Lock lock(m_pointerMutex); + return m_channelPutGet; + } + + + virtual string getRequesterName() + { + return "SyncChannelGetPutRequesterImpl"; + }; + + + virtual void message(string const & message,MessageType messageType) + { + if (m_debug) + std::cout << "[" << getRequesterName() << "] message(" << + message << ", " << getMessageTypeName(messageType) << ")" << std::endl; + } + + + virtual void channelPutGetConnect(const epics::pvData::Status& status, + ChannelPutGet::shared_pointer const & channelPutGet, + epics::pvData::PVStructure::shared_pointer const & putData, + epics::pvData::PVStructure::shared_pointer const & getData) + { + if (m_debug) + std::cout << getRequesterName() << "." << "channelGetPutConnect(" + << status.toString() << ")" << std::endl; + + if (status.isSuccess()) + { + { + Lock lock(m_pointerMutex); + m_channelPutGet = channelPutGet; + m_putData = putData; + m_getData = getData; + } + setConnectedStatus(true); + } + else + { + setConnectedStatus(false); + } + + signalEvent(); + } + + + virtual void getGetDone(const epics::pvData::Status& status) + { + if (m_debug) + std::cout << getRequesterName() << "." << "getGetDone(" << status.toString() << ")" << std::endl; + + { + Lock lock(m_pointerMutex); + m_getGetStatus = status.isSuccess(); + } + + signalEvent(); + } + + + virtual void getPutDone(const epics::pvData::Status& status) + { + if (m_debug) + std::cout << getRequesterName() << "." << "getPutDone(" << status.toString() << ")" << std::endl; + + { + Lock lock(m_pointerMutex); + m_getPutStatus = status.isSuccess(); + } + + signalEvent(); + } + + + virtual void putGetDone(const epics::pvData::Status& status) + { + if (m_debug) + std::cout << getRequesterName() << "." << "putGetDone(" << status.toString() << ")" << std::endl; + + { + Lock lock(m_pointerMutex); + m_putGetStatus = status.isSuccess(); + } + + signalEvent(); + } + + + private: + + bool waitUntilPutGetDone(double timeOut) + { + + bool signaled = waitUntilEvent(timeOut); + if (!signaled) + return false; + + Lock lock(m_pointerMutex); + return m_putGetStatus; + } + + + bool waitUntilGetPutDone(double timeOut) + { + + bool signaled = waitUntilEvent(timeOut); + if (!signaled) + return false; + + Lock lock(m_pointerMutex); + return m_getPutStatus; + } + + + bool waitUntilGetGetDone(double timeOut) + { + + bool signaled = waitUntilEvent(timeOut); + if (!signaled) + return false; + + Lock lock(m_pointerMutex); + return m_getGetStatus; + } + + + bool m_putGetStatus; + bool m_getPutStatus; + bool m_getGetStatus; + + Mutex m_pointerMutex; + ChannelPutGet::shared_pointer m_channelPutGet; + epics::pvData::PVStructure::shared_pointer m_putData; + epics::pvData::PVStructure::shared_pointer m_getData; +}; + + +class SyncChannelRPCRequesterImpl : public ChannelRPCRequester, public SyncBaseRequester +{ + + public: + + typedef std::tr1::shared_ptr shared_pointer; + + + SyncChannelRPCRequesterImpl(bool debug = true) : SyncBaseRequester(debug), m_done(false) {} + + + bool syncRPC( epics::pvData::PVStructure::shared_pointer const & pvArguments, + boolean lastRequest, long timeOut) { + + if(!getConnectedStatus()) { + return false; + } + + m_channelRPC->request(pvArguments, lastRequest); + return waitUntilRPC(timeOut); + } + + + PVStructure::shared_pointer getLastResponse() + { + Lock lock(m_pointerMutex); + return m_lastResponse; + } + + + ChannelRPC::shared_pointer getChannelRPC() { + Lock lock(m_pointerMutex); + return m_channelRPC; + } + + + virtual string getRequesterName() + { + return "SyncChannelRPCRequesterImpl"; + } + + + virtual void message(string const & message, MessageType messageType) + { + if (m_debug) + std::cerr << "[" << getRequesterName() << "] message(" << message << ", " + << getMessageTypeName(messageType) << ")" << std::endl; + } + + + virtual void channelRPCConnect(const epics::pvData::Status& status, + ChannelRPC::shared_pointer const & channelRPC) + { + + if (m_debug) + std::cout << getRequesterName() << "." << "channelRPCConnect(" + << status.toString() << ")" << std::endl; + + if (status.isSuccess()) + { + { + Lock lock(m_pointerMutex); + m_channelRPC = channelRPC; + } + + setConnectedStatus(true); + } + else + { + setConnectedStatus(false); + } + + signalEvent(); + } + + + virtual void requestDone (const epics::pvData::Status &status, + epics::pvData::PVStructure::shared_pointer const &pvResponse) + { + + if (m_debug) + std::cout << getRequesterName() << "." << "requestDone(" + << status.toString() << ")" << std::endl; + + if (status.isSuccess()) + { + Lock lock(m_pointerMutex); + m_lastResponse = pvResponse; + } + + { + Lock lock(m_pointerMutex); + m_done = status.isSuccess(); + } + + signalEvent(); + } + + + private: + + bool waitUntilRPC(double timeOut) + { + bool signaled = waitUntilEvent(timeOut); + if (!signaled) + { + return false; + } + + Lock lock(m_pointerMutex); + return m_done; + } + + bool m_done; + ChannelRPC::shared_pointer m_channelRPC; + Mutex m_pointerMutex; + PVStructure::shared_pointer m_lastResponse; +}; + + +class SyncMonitorRequesterImpl: public MonitorRequester, public SyncBaseRequester +{ + public: + + typedef std::tr1::shared_ptr shared_pointer; + + + SyncMonitorRequesterImpl(bool debug = true): + SyncBaseRequester(debug), + m_monitorCounter(0), + m_monitorStatus(false) {} + + + int getMonitorCounter() { + Lock lock(m_pointerMutex); + return m_monitorCounter; + } + + + PVStructure::shared_pointer getPVStructure() { + Lock lock(m_pointerMutex); + return m_pvStructure; + } + + + + std::tr1::shared_ptr getChannelMonitor() { + Lock lock(m_pointerMutex); + return m_monitor; + } + + + BitSet::shared_pointer getChangedBitSet() { + Lock lock(m_pointerMutex); + return m_changedBitSet; + } + + + BitSet::shared_pointer getOverrunBitSet() { + Lock lock(m_pointerMutex); + return m_overrunBitSet; + } + + + bool waitUntilMonitor(double timeOut) + { + { + Lock lock(m_pointerMutex); + m_monitorStatus = false; + } + + + bool signaled = waitUntilEvent(timeOut); + if (!signaled) { + + if (m_debug) + std::cerr << getRequesterName() << ".waitUntilMonitor:" << " timeout occurred" << endl; + + return false; + } + + Lock lock(m_pointerMutex); + return m_monitorStatus; + } + + + virtual string getRequesterName() + { + return "SyncMonitorRequesterImpl"; + } + + + virtual void message(string const & message, MessageType messageType) + { + if (m_debug) + std::cerr << "[" << getRequesterName() << "] message(" << message << ", " + << getMessageTypeName(messageType) << ")" << std::endl; + } + + + virtual void monitorConnect(const epics::pvData::Status& status, Monitor::shared_pointer const & monitor, + StructureConstPtr const & /*structure*/) + { + if (m_debug) + std::cout << getRequesterName() << "." << "monitorConnect(" << status.toString() << ")" << std::endl; + + if (status.isSuccess()) + { + { + Lock lock(m_pointerMutex); + m_monitor = monitor; + } + + setConnectedStatus(true); + } + else + { + setConnectedStatus(false); + } + + signalEvent(); + } + + + virtual void monitorEvent(MonitorPtr const & monitor) + { + if (m_debug) + std::cout << getRequesterName() << "." << "monitorEvent" << std::endl; + + MonitorElement::shared_pointer element = monitor->poll(); + + { + Lock lock(m_pointerMutex); + m_monitorStatus = true; + m_pvStructure = element->pvStructurePtr; + m_changedBitSet = element->changedBitSet; + m_overrunBitSet = element->overrunBitSet; + m_monitorCounter++; + } + + monitor->release(element); + signalEvent(); + } + + + virtual void unlisten(MonitorPtr const & /*monitor*/) + { + if (m_debug) + std::cout << getRequesterName() << "." << "unlisten" << std::endl; + } + + + private: + int m_monitorCounter; + bool m_monitorStatus; + MonitorPtr m_monitor; + Mutex m_pointerMutex; + PVStructure::shared_pointer m_pvStructure; + BitSet::shared_pointer m_changedBitSet; + BitSet::shared_pointer m_overrunBitSet; +}; + + +class SyncChannelArrayRequesterImpl : public ChannelArrayRequester, public SyncBaseRequester +{ + + public: + + typedef std::tr1::shared_ptr shared_pointer; + + SyncChannelArrayRequesterImpl(bool debug = true) : + SyncBaseRequester(debug), + m_getArrayStatus(false), + m_putArrayStatus(false), + m_lengthArrayStatus(false) {} + + + bool syncPut(bool lastRequest, int offset, int count, long timeOut) + { + + if (!getConnectedStatus()) { + return false; + } + + m_channelArray->putArray(lastRequest, offset, count); + return waitUntilPutArrayDone(timeOut); + } + + + bool syncGet(bool lastRequest, int offset, int count, long timeOut) + { + + if (!getConnectedStatus()) { + return false; + } + + m_channelArray->getArray(lastRequest, offset, count); + return waitUntilGetArrayDone(timeOut); + } + + + bool syncSetLength(bool lastRequest, int length, int capacity, long timeOut) + { + + if (!getConnectedStatus()) { + return false; + } + + m_channelArray->setLength(lastRequest, length, capacity); + return waitUntilSetLengthDone(timeOut); + } + + + ChannelArray::shared_pointer getChannelArray() + { + Lock lock(m_pointerMutex); + return m_channelArray; + } + + + epics::pvData::PVArray::shared_pointer getArray() + { + Lock lock(m_pointerMutex); + return m_pvArray; + } + + + virtual String getRequesterName() + { + return "SynChannelArrayRequesterImpl"; + } + + + virtual void message(String const & message,MessageType messageType) + { + if (m_debug) + std::cout << "[" << getRequesterName() << "] message(" << message << ", " + << getMessageTypeName(messageType) << ")" << std::endl; + } + + + virtual void channelArrayConnect(const epics::pvData::Status& status, + ChannelArray::shared_pointer const & channelArray, + epics::pvData::PVArray::shared_pointer const & pvArray) + { + if (m_debug) + std::cout << getRequesterName() << ".channelArrayConnect(" << status.toString() << ")" << std::endl; + if (status.isSuccess()) + { + { + Lock lock(m_pointerMutex); + m_channelArray = channelArray; + m_pvArray = pvArray; + } + + setConnectedStatus(true); + } + else + { + setConnectedStatus(false); + } + + signalEvent(); + } + + + virtual void getArrayDone(const epics::pvData::Status& status) + { + if (m_debug) + std::cout << getRequesterName() << ".getArrayDone(" << status.toString() << ")" << std::endl; + + Lock lock(m_pointerMutex); + m_getArrayStatus = status.isSuccess(); + signalEvent(); + } + + + virtual void putArrayDone(const epics::pvData::Status& status) + { + if (m_debug) + std::cout << getRequesterName() << ".putArrayDone(" << status.toString() << ")" << std::endl; + + Lock lock(m_pointerMutex); + m_putArrayStatus = status.isSuccess(); + signalEvent(); + } + + + virtual void setLengthDone(const epics::pvData::Status& status) + { + if (m_debug) + std::cout << getRequesterName() << ".setLengthDone(" << status.toString() << ")" << std::endl; + + Lock lock(m_pointerMutex); + m_lengthArrayStatus = status.isSuccess(); + signalEvent(); + } + + + private: + + bool waitUntilGetArrayDone(double timeOut) + { + { + Lock lock(m_pointerMutex); + m_getArrayStatus = false; + } + + + bool signaled = waitUntilEvent(timeOut); + if (!signaled) { + return false; + } + + Lock lock(m_pointerMutex); + return m_getArrayStatus; + } + + + bool waitUntilPutArrayDone(double timeOut) + { + { + Lock lock(m_pointerMutex); + m_putArrayStatus = false; + } + + + bool signaled = waitUntilEvent(timeOut); + if (!signaled) { + return false; + } + + Lock lock(m_pointerMutex); + return m_putArrayStatus; + } + + + bool waitUntilSetLengthDone(double timeOut) + { + { + Lock lock(m_pointerMutex); + m_lengthArrayStatus = false; + } + + + bool signaled = waitUntilEvent(timeOut); + if (!signaled) { + return false; + } + + Lock lock(m_pointerMutex); + return m_lengthArrayStatus; + } + + + bool m_getArrayStatus; + bool m_putArrayStatus; + bool m_lengthArrayStatus; + Mutex m_pointerMutex; + ChannelArray::shared_pointer m_channelArray; + epics::pvData::PVArray::shared_pointer m_pvArray; +}; + +#endif diff --git a/testApp/remote/testChannelAccess.cpp b/testApp/remote/testChannelAccess.cpp new file mode 100755 index 0000000..a2be71b --- /dev/null +++ b/testApp/remote/testChannelAccess.cpp @@ -0,0 +1,89 @@ +/* + * testChannelAccess.cpp + */ +#define TESTSERVERNOMAIN + +#include +#include +#include + +#include +#include +#include + +#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 m_serverThread; +}; + + +class ChannelAccessIFRemoteTest: public ChannelAccessIFTest { + + public: + + ChannelAccessIFRemoteTest(): m_serverContextAction() + { + m_serverContextAction.start(); + ClientFactory::start(); + } + + + virtual ChannelProvider::shared_pointer getChannelProvider() { + return getChannelAccess()->getProvider( + ClientContextImpl::PROVIDER_NAME); + } + + + virtual long getTimeoutSec() { + return 10; + } + + + virtual bool isLocal() { return false;} + + + ~ChannelAccessIFRemoteTest() { + m_serverContextAction.stop(); + ClientFactory::stop(); + structureChangedListeners.clear(); + structureStore.clear(); + } + + private: + ServerContextAction m_serverContextAction; +}; + + +MAIN(testChannelProvider) +{ + ChannelAccessIFRemoteTest caRemoteTest; + return caRemoteTest.runAllTest(); +} diff --git a/testApp/remote/testServer.cpp b/testApp/remote/testServer.cpp index 88534ce..0880822 100644 --- a/testApp/remote/testServer.cpp +++ b/testApp/remote/testServer.cpp @@ -1279,6 +1279,25 @@ public: m_channelRPCRequester->requestDone(Status::Ok, pvArgument); } } + else if (m_channelName == "testSum") { + + int a = pvArgument->getIntField("a")->get(); + int b = pvArgument->getIntField("b")->get(); + + FieldCreatePtr fieldCreate = getFieldCreate(); + + StringArray fieldNames; + fieldNames.push_back("c"); + FieldConstPtrArray fields; + fields.push_back(fieldCreate->createScalar(pvInt)); + StructureConstPtr resultStructure = fieldCreate->createStructure(fieldNames, fields); + + PVStructure::shared_pointer result = getPVDataCreate()->createPVStructure(resultStructure); + result->getIntField("c")->put(a+b); + + m_channelRPCRequester->requestDone(Status::Ok, result); + + } else if (m_channelName.find("testServerShutdown") == 0) { PVStructure::shared_pointer nullPtr; @@ -1475,9 +1494,17 @@ public: virtual void setLength(bool lastRequest, int length, int capacity) { - m_pvStructureArray->setCapacity(capacity); - m_pvStructureArray->setLength(length); + if (capacity > 0) { + m_pvArray->setCapacity(capacity); + } + + if (length > 0) { + m_pvArray->setLength(length); + } + m_channelArrayRequester->setLengthDone(Status::Ok); + + cout << "DDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDD" << endl; if (lastRequest) destroy(); } @@ -2049,19 +2076,19 @@ public: process = c->createChannelProcess(cpr, PVStructure::shared_pointer()); m_scan1Hz.toProcess.push_back(process); - m_scan1HzThread.reset(new Thread("process1hz", highPriority, &m_scan1Hz)); - m_scan10HzThread.reset(new Thread("process10hz", highPriority, &m_scan10Hz)); + m_scan1HzThread.reset(new epics::pvData::Thread("process1hz", highPriority, &m_scan1Hz)); + m_scan10HzThread.reset(new epics::pvData::Thread("process10hz", highPriority, &m_scan10Hz)); m_adcChannel = MockChannel::create(chProviderPtr, cr, "testADC", "local"); m_adcAction.name = "testADC"; m_adcAction.adcMatrix = static_pointer_cast(m_adcChannel)->m_pvStructure; m_adcAction.adcSim = createSimADC("testADC"); - m_adcThread.reset(new Thread("adcThread", highPriority, &m_adcAction)); + m_adcThread.reset(new epics::pvData::Thread("adcThread", highPriority, &m_adcAction)); m_mpChannel = MockChannel::create(chProviderPtr, cr, "testMP", "local"); m_imgAction.name = "testMP"; m_imgAction.pvImage = static_pointer_cast(m_mpChannel)->m_pvStructure; - m_imgThread.reset(new Thread("imgThread", highPriority, &m_imgAction)); + m_imgThread.reset(new epics::pvData::Thread("imgThread", highPriority, &m_imgAction)); } virtual epics::pvData::String getProviderName() @@ -2138,16 +2165,16 @@ private: Channel::shared_pointer m_mpChannel; ProcessAction m_scan1Hz; - auto_ptr m_scan1HzThread; + auto_ptr m_scan1HzThread; ProcessAction m_scan10Hz; - auto_ptr m_scan10HzThread; + auto_ptr m_scan10HzThread; ADCAction m_adcAction; - auto_ptr m_adcThread; + auto_ptr m_adcThread; NTImageAction m_imgAction; - auto_ptr m_imgThread; + auto_ptr m_imgThread; }; String MockServerChannelProvider::PROVIDER_NAME = "local"; @@ -2226,6 +2253,7 @@ void usage (char *argv[]) } +#ifndef TESTSERVERNOMAIN int main(int argc, char *argv[]) { @@ -2286,3 +2314,4 @@ int main(int argc, char *argv[]) return (0); } +#endif