diff --git a/testCa/Makefile b/testCa/Makefile index 4300613..da17a17 100644 --- a/testCa/Makefile +++ b/testCa/Makefile @@ -3,34 +3,45 @@ TOP = .. include $(TOP)/configure/CONFIG +# Need access to caProviderPvt.h USR_CPPFLAGS += -I$(TOP)/src/ca -CAPROVIDER_TEST = $(TOP)/testCa - -PROD_LIBS += pvAccess pvAccessCA pvData ca Com +PROD_LIBS += pvAccess pvAccessCA pvData $(EPICS_BASE_IOC_LIBS) TESTPROD_HOST += testCaProvider testCaProvider_SRCS += testCaProvider.cpp -testHarness_SRCS += testCaProvider.cpp +caTestHarness_SRCS += testCaProvider.cpp TESTS += testCaProvider -testHarness_SRCS += pvCaAllTests.c +ifdef BASE_3_15 + testCaProvider_SRCS += testIoc_registerRecordDeviceDriver.cpp + REGRDDFLAGS = -l +else + # testCaProvider needs EPICS_HOST_ARCH set in the environment + export EPICS_HOST_ARCH +endif -# testCaProvider needs EPICS_HOST_ARCH set in the environment -export EPICS_HOST_ARCH +ifdef BASE_3_15 + # Embedded OSes need dbUnitTest, Base-3.15 and higher only -# Name the application caTestHarness -caTestHarness_SRCS = $(testHarness_SRCS) + # The test collection is caTestHarness + caTestHarness_SRCS += pvCaAllTests.c -# Build for vxWorks -PROD_vxWorks = caTestHarness -TESTSPEC_vxWorks = caTestHarness.$(MUNCH_SUFFIX); pvCaAllTests + # Build for vxWorks + PROD_vxWorks = caTestHarness + TESTSPEC_vxWorks = caTestHarness.$(MUNCH_SUFFIX); pvCaAllTests -# Build for RTEMS, with harness code & configuration -PROD_RTEMS += caTestHarness -caTestHarness_SRCS_RTEMS += rtemsTestHarness.c -TESTSPEC_RTEMS = caTestHarness.$(MUNCH_SUFFIX); pvCaAllTests + # Build for RTEMS, with harness code & configuration + PROD_RTEMS += caTestHarness + caTestHarness_SRCS_RTEMS += rtemsTestHarness.c + TESTSPEC_RTEMS = caTestHarness.$(MUNCH_SUFFIX); pvCaAllTests +endif # Build test scripts for hosts TESTSCRIPTS_HOST += $(TESTS:%=%.t) include $(TOP)/configure/RULES + +ifdef BASE_3_15 + $(COMMON_DIR)/testIoc.dbd: $(EPICS_BASE)/dbd/softIoc.dbd + $(CP) $< $@ +endif diff --git a/testCa/testCaProvider.cpp b/testCa/testCaProvider.cpp index 4f623aa..15dfc16 100644 --- a/testCa/testCaProvider.cpp +++ b/testCa/testCaProvider.cpp @@ -13,7 +13,21 @@ #include #include +#include +#if defined(VERSION_INT) && EPICS_VERSION_INT >= VERSION_INT(3,15,0,1) + #define USE_DBUNITTEST + // USE_TYPED_RSET prevents deprecation warnings + #define USE_TYPED_RSET + #define EXIT_TESTS 0 + #include + #include + #include + + extern "C" int testIoc_registerRecordDeviceDriver(struct dbBase *pbase); +#else + #define EXIT_TESTS 1 +#endif #include #include @@ -26,6 +40,9 @@ #include #include +// DEBUG must be 0 to run under the automated test harness +#define DEBUG 0 + using namespace epics::pvData; using namespace epics::pvAccess; using namespace epics::pvAccess::ca; @@ -584,7 +601,7 @@ void TestClient::getDone( testOk(pvStructure->getSubField("value")!=NULL,"value not null"); testOk(pvStructure->getSubField("timeStamp")!=NULL,"timeStamp not null"); testOk(pvStructure->getSubField("alarm")!=NULL,"alarm not null"); - std::cout << testChannel->getChannelName() + " TestClient::getDone" + if (DEBUG) std::cout << testChannel->getChannelName() + " TestClient::getDone" << " bitSet " << *bitSet << " pvStructure\n" << pvStructure << "\n"; waitForGet.signal(); @@ -599,35 +616,38 @@ void TestClient::monitorEvent( PVStructure::shared_pointer const & pvStructure, BitSet::shared_pointer const & bitSet) { - std::cout << testChannel->getChannelName() + " TestClient::monitorEvent" + if (DEBUG) std::cout << testChannel->getChannelName() + " TestClient::monitorEvent" << " bitSet " << *bitSet << " pvStructure\n" << pvStructure << "\n"; } void TestClient::get() { -cout << "TestClient::get() calling get\n"; + testDiag("TestClient::get %s", + testChannel->getChannelName().c_str()); testChannelGet->get(); -cout << "TestClient::get() calling waitGet\n"; + if (DEBUG) cout << "TestClient::get() calling waitGet\n"; waitGet(5.0); } void TestClient::waitGet(double timeout) { - if(waitForGet.wait(timeout)) return; - throw std::runtime_error(testChannel->getChannelName() + " TestClient::waitGet failed "); + testOk(waitForGet.wait(timeout), + "waitGet(%s) succeeded", testChannel->getChannelName().c_str()); } void TestClient::put(string const & value) { + testDiag("TestClient::put %s := %s", + testChannel->getChannelName().c_str(), value.c_str()); testChannelPut->put(value); waitPut(5.0); } void TestClient::waitPut(double timeout) { - if(waitForPut.wait(timeout)) return; - throw std::runtime_error(testChannel->getChannelName() + " TestClient::waitPut failed "); + testOk(waitForPut.wait(timeout), + "waitPut(%s) succeeded", testChannel->getChannelName().c_str()); } void TestClient::stopEvents() @@ -645,8 +665,11 @@ public: virtual void run(); static TestIocPtr create(); void start(); + void shutdown(); private: +#ifndef USE_DBUNITTEST std::auto_ptr thread; +#endif }; TestIocPtr TestIoc::create() @@ -656,141 +679,116 @@ TestIocPtr TestIoc::create() void TestIoc::start() { +#ifdef USE_DBUNITTEST + testdbPrepare(); + testdbReadDatabase("testIoc.dbd", NULL, NULL); + testIoc_registerRecordDeviceDriver(pdbbase); + testdbReadDatabase("testCaProvider.db", NULL, NULL); + eltc(0); + testIocInitOk(); + eltc(1); +#else thread = std::auto_ptr(new epicsThread( *this, "testIoc", epicsThreadGetStackSize(epicsThreadStackSmall), epicsThreadPriorityLow)); thread->start(); +#endif } void TestIoc::run() { +#ifndef USE_DBUNITTEST + // Base-3.14 doesn't provide the dbUnitTest APIs. + // This code only works on workstation targets, it runs the + // softIoc from Base as a separate process, using system(). char * base; base = getenv("EPICS_BASE"); if(base==NULL) throw std::runtime_error("TestIoc::run $EPICS_BASE not defined"); char * arch; arch = getenv("EPICS_HOST_ARCH"); if(arch==NULL) throw std::runtime_error("TestIoc::run $$EPICS_HOST_ARCH not defined"); - if(system("$EPICS_BASE/bin/$EPICS_HOST_ARCH/softIoc -d ../testCaProvider.db")!=0) { + setenv("EPICS_CA_ADDR_LIST", "localhost", 1); + setenv("EPICS_CA_AUTO_ADDR_LIST", "NO", 1); + if(system("$EPICS_BASE/bin/$EPICS_HOST_ARCH/softIoc -x test -d ../testCaProvider.db")!=0) { string message(base); message += "/bin/"; message += arch; message += "/softIoc -d ../testCaProvider.db not started"; throw std::runtime_error(message); } +#endif +} + +void TestIoc::shutdown() +{ +#ifdef USE_DBUNITTEST + testIocShutdownOk(); + testdbCleanup(); +#endif +} + +void checkClient(const string &channelName, const string &putValue) +{ + string request("value,alarm,timeStamp"); + PVStructurePtr pvRequest(createRequest(request)); + TestClientPtr client = TestClient::create(channelName,pvRequest); + if (!client) + testAbort("NULL client for %s", channelName.c_str()); + client->put(putValue); + client->get(); + client->stopEvents(); } MAIN(testCaProvider) { + testPlan(84 + EXIT_TESTS); TestIocPtr testIoc(new TestIoc()); testIoc->start(); - testPlan(56); + testDiag("===Test caProvider==="); CAClientFactory::start(); ChannelProviderRegistry::shared_pointer reg(ChannelProviderRegistry::clients()); - ChannelProvider::shared_pointer channelProvider(reg->getProvider("ca")); - try{ - if(!channelProvider) { - throw std::runtime_error(" provider ca not registered"); - } - string channelName; - string request("value,alarm,timeStamp"); - PVStructurePtr pvRequest(createRequest(request)); - TestClientPtr client; + try { + ChannelProvider::shared_pointer channelProvider(reg->getProvider("ca")); + if (!channelProvider) + testAbort("Channel provider 'ca' not registered"); - channelName = "DBRlongout"; - client = TestClient::create(channelName,pvRequest); - if(!client) throw std::runtime_error(channelName + " client null"); - client->put("5"); - client->get(); - client->stopEvents(); - channelName = "DBRdoubleout"; - client = TestClient::create(channelName,pvRequest); - if(!client) throw std::runtime_error(channelName + " client null"); - client->put("1.5"); - client->get(); - client->stopEvents(); - channelName = "DBRstringout"; - client = TestClient::create(channelName,pvRequest); - if(!client) throw std::runtime_error(channelName + " client null"); - client->put("test"); - client->get(); - client->stopEvents(); - channelName = "DBRbyteArray"; - client = TestClient::create(channelName,pvRequest); - if(!client) throw std::runtime_error(channelName + " client null"); - client->put("1 2 3"); - client->get(); - client->stopEvents(); - channelName = "DBRshortArray"; - client = TestClient::create(channelName,pvRequest); - if(!client) throw std::runtime_error(channelName + " client null"); - client->put("1 2 3"); - client->get(); - client->stopEvents(); - channelName = "DBRintArray"; - client = TestClient::create(channelName,pvRequest); - if(!client) throw std::runtime_error(channelName + " client null"); - client->put("1 2 3"); - client->get(); - channelName = "DBRubyteArray"; - client = TestClient::create(channelName,pvRequest); - if(!client) throw std::runtime_error(channelName + " client null"); - client->put("1 2 3"); - client->get(); - client->stopEvents(); - channelName = "DBRushortArray"; - client = TestClient::create(channelName,pvRequest); - if(!client) throw std::runtime_error(channelName + " client null"); - client->put("1 2 3"); - client->get(); - client->stopEvents(); - channelName = "DBRuintArray"; - client = TestClient::create(channelName,pvRequest); - if(!client) throw std::runtime_error(channelName + " client null"); - client->put("1 2 3"); - client->get(); - channelName = "DBRfloatArray"; - client = TestClient::create(channelName,pvRequest); - if(!client) throw std::runtime_error(channelName + " client null"); - client->put("1 2 3"); - client->get(); - client->stopEvents(); - channelName = "DBRdoubleArray"; - client = TestClient::create(channelName,pvRequest); - if(!client) throw std::runtime_error(channelName + " client null"); - client->put("1 2 3"); - client->get(); - client->stopEvents(); - channelName = "DBRstringArray"; - client = TestClient::create(channelName,pvRequest); - if(!client) throw std::runtime_error(channelName + " client null"); - client->put("aa bb cc"); - client->get(); - client->stopEvents(); - channelName = "DBRmbbout"; - client = TestClient::create(channelName,pvRequest); - if(!client) throw std::runtime_error(channelName + " client null"); - client->put("2"); - client->get(); - client->stopEvents(); - channelName = "DBRbinaryout"; - client = TestClient::create(channelName,pvRequest); - if(!client) throw std::runtime_error(channelName + " client null"); - client->put("1"); - client->get(); - client->stopEvents(); + checkClient("DBRlongout", "5"); + checkClient("DBRdoubleout", "1.5"); + checkClient("DBRstringout", "test"); + checkClient("DBRbyteArray", "1 2 3"); + checkClient("DBRshortArray", "1 2 3"); + checkClient("DBRintArray", "1 2 3"); + checkClient("DBRubyteArray", "1 2 3"); + checkClient("DBRushortArray", "1 2 3"); + checkClient("DBRuintArray", "1 2 3"); + checkClient("DBRfloatArray", "1 2 3"); + checkClient("DBRdoubleArray", "1 2 3"); + checkClient("DBRstringArray", "aa bb cc"); + checkClient("DBRmbbout", "2"); + checkClient("DBRbinaryout", "1"); + +#ifndef USE_DBUNITTEST // put to record that makes IOC exit - channelName = "DBRexit"; - client = TestClient::create(channelName,pvRequest); - if(!client) throw std::runtime_error(channelName + " client null"); + string channelName = "test:exit"; + string request("value"); + PVStructurePtr pvRequest(createRequest(request)); + TestClientPtr client = TestClient::create(channelName,pvRequest); + if (!client) + testAbort("NULL client for %s", channelName.c_str()); client->put("1"); client->stopEvents(); - }catch(std::exception& e){ - testFail("caught un-expected exception: %s", e.what()); +#endif } + catch (std::exception& e) { + testAbort("caught un-expected exception: %s", e.what()); + } + + testIoc->shutdown(); + return testDone();; } diff --git a/testCa/testCaProvider.db b/testCa/testCaProvider.db index d66e322..04cdcf7 100644 --- a/testCa/testCaProvider.db +++ b/testCa/testCaProvider.db @@ -39,12 +39,6 @@ record(calc, "DBRcalcin") field(LLSV, "MAJOR") } -record(sub, "DBRexit") -{ - field(DESC, "exit") - field(SNAM, "exit") -} - record(longin,"DBRlongin") { field(DESC, "longin") field(EGU, "volts") @@ -131,12 +125,6 @@ record(stringin,"DBRstringin") { record(bo,"DBRbinaryout") { field(DESC, "bo") - field(OUT, "DBRbi.VAL PP NMS") - field(ZNAM,"zero") - field(ONAM,"one") -} -record(bi,"DBRbinaryin") { - field(DESC, "bi") field(ZNAM,"zero") field(ONAM,"one") }