From 160d29e7b0fcb0fe1c260ddadbdb0938582ed1a7 Mon Sep 17 00:00:00 2001 From: Michael Davidsaver Date: Sun, 20 Mar 2016 13:31:38 -0400 Subject: [PATCH] add check_consist demo/test --- testApp/Makefile | 3 ++ testApp/check_consist.cpp | 101 ++++++++++++++++++++++++++++++++++++++ testApp/check_consist.db | 40 +++++++++++++++ testApp/utilities.cpp | 10 ++++ testApp/utilities.h | 1 + 5 files changed, 155 insertions(+) create mode 100644 testApp/check_consist.cpp create mode 100644 testApp/check_consist.db diff --git a/testApp/Makefile b/testApp/Makefile index cd0f3d3..3d26511 100644 --- a/testApp/Makefile +++ b/testApp/Makefile @@ -50,6 +50,9 @@ testpdb_SRCS += p2pTestIoc_registerRecordDeviceDriver.cpp testpdb_LIBS += testutils pdbcore pvAccess pvData $(EPICS_BASE_IOC_LIBS) TESTS += testpdb +PROD_HOST += check_consist +check_consist_SRCS += check_consist.cpp +check_consist_LIBS += testutils pvAccess pvData Com TESTSCRIPTS_HOST += $(TESTS:%=%.t) diff --git a/testApp/check_consist.cpp b/testApp/check_consist.cpp new file mode 100644 index 0000000..d1876a5 --- /dev/null +++ b/testApp/check_consist.cpp @@ -0,0 +1,101 @@ + +#include + +#include "utilities.h" + +namespace pvd = epics::pvData; +namespace pva = epics::pvAccess; + +namespace { +struct Destroyer { + pvd::Destroyable::shared_pointer D; + Destroyer(const pvd::Destroyable::shared_pointer& d) : D(d) {} + ~Destroyer() { if(D) D->destroy(); } +}; + +struct Releaser { + pva::Monitor::shared_pointer& mon; + pva::MonitorElementPtr& elem; + Releaser(pva::Monitor::shared_pointer& m, pva::MonitorElementPtr& e) + :mon(m), elem(e) + {} + ~Releaser() { mon->release(elem); } +}; +} // namespace + +int main(int argc, char *argv[]) +{ + testPlan(0); + try { + if(argc<4) { + std::cerr<<"Usage: "< ..."; + return 1; + } + + pvd::StructureConstPtr reqdesc(pvd::getFieldCreate()->createFieldBuilder() + ->add("unused", pvd::pvBoolean) + ->createStructure()); + + pvd::PVStructurePtr pvreq(pvd::getPVDataCreate()->createPVStructure(reqdesc)); + + pva::ClientFactory::start(); + + pva::ChannelProvider::shared_pointer prov(pva::getChannelProviderRegistry()->getProvider("pva")); + if(!prov) throw std::runtime_error("No pva provider?!?"); + Destroyer prov_d(prov); + + TestChannelRequester::shared_pointer chreq(new TestChannelRequester); + pva::Channel::shared_pointer chan(prov->createChannel(argv[1], chreq)); + Destroyer chan_d(chan); + if(!chan) throw std::runtime_error("Failed to create channel"); + + std::cout<<"Connecting...\n"; + if(!chreq->waitForConnect()) + throw std::runtime_error("Failed to connect channel"); + + TestChannelMonitorRequester::shared_pointer monreq(new TestChannelMonitorRequester); + pva::Monitor::shared_pointer mon(chan->createMonitor(monreq, pvreq)); + Destroyer mon_d(mon); + if(!mon) throw std::runtime_error("Failed to create monitor"); + + if(!monreq->waitForConnect()) + throw std::runtime_error("failed to connect monitor"); + + if(!mon->start().isSuccess()) + throw std::runtime_error("failed to start monitor"); + + std::cout<<"Wait for initial event...\n"; + while(monreq->waitForEvent()) { + pva::MonitorElementPtr elem; + while(!!(elem=mon->poll())) { + Releaser R(mon, elem); + + pvd::PVStructurePtr A, B; + A = elem->pvStructurePtr->getSubField("a"); + B = elem->pvStructurePtr->getSubField("b"); + if(!A || !B) + throw std::runtime_error("unexpected types"); + + epicsUInt32 vA = A->getSubFieldT("value")->getAs(), + vB = B->getSubFieldT("value")->getAs(); + epicsUInt64 tsA = A->getSubFieldT("timeStamp.secondsPastEpoch")->getAs(), + tsB = B->getSubFieldT("timeStamp.secondsPastEpoch")->getAs(); + epicsUInt32 tnA = A->getSubFieldT("timeStamp.nanoseconds")->getAs(), + tnB = B->getSubFieldT("timeStamp.nanoseconds")->getAs(); + + if(vA==vB && tsA==tsB && tnA==tnB) { + std::cout<<"."; + continue; + } + std::cout<<"\nMismatch:\nA:\n"<<*A<<"B:\n"<<*B<<"\n"; + } + } + std::cout<<"Done\n"; + + return 0; + }catch(std::exception&e){ + PRINT_EXCEPTION(e); + std::cerr<<"Error: "<*") +} + +record(calc, "cnt:rate") { + field(INPA, "cnt:x NPP") + field(CALC, "C:=A-B;B:=A;C/10") + field(SCAN, ".1 second") + field(EGU , "cnt/s") +} diff --git a/testApp/utilities.cpp b/testApp/utilities.cpp index 03c8eab..a8b2ec8 100644 --- a/testApp/utilities.cpp +++ b/testApp/utilities.cpp @@ -186,6 +186,16 @@ void TestChannelMonitorRequester::unlisten(pvd::MonitorPtr const & monitor) wait.trigger(); } +bool TestChannelMonitorRequester::waitForConnect() +{ + Guard G(lock); + while(!connected) { + UnGuard U(G); + wait.wait(); + } + return true; +} + bool TestChannelMonitorRequester::waitForEvent() { Guard G(lock); diff --git a/testApp/utilities.h b/testApp/utilities.h index c50b1bd..e656a97 100644 --- a/testApp/utilities.h +++ b/testApp/utilities.h @@ -218,6 +218,7 @@ struct TestChannelMonitorRequester : public epics::pvData::MonitorRequester virtual void monitorEvent(epics::pvData::MonitorPtr const & monitor); virtual void unlisten(epics::pvData::MonitorPtr const & monitor); + bool waitForConnect(); bool waitForEvent(); };