diff --git a/testApp/remote/Makefile b/testApp/remote/Makefile index a161fab..ceea70e 100644 --- a/testApp/remote/Makefile +++ b/testApp/remote/Makefile @@ -3,7 +3,7 @@ SRC_DIRS += $(PVACCESS_TEST)/remote TESTPROD_HOST += testChannelAccess -testChannelAccess_SRCS = testChannelAccess channelAccessIFTest +testChannelAccess_SRCS = channelAccessIFTest.cpp testHarness_SRCS += testChannelAccess.cpp channelAccessIFTest.cpp TESTS += testChannelAccess diff --git a/testApp/remote/channelAccessIFTest.cpp b/testApp/remote/channelAccessIFTest.cpp index e137277..e31c037 100755 --- a/testApp/remote/channelAccessIFTest.cpp +++ b/testApp/remote/channelAccessIFTest.cpp @@ -21,6 +21,9 @@ #include "channelAccessIFTest.h" //#define ENABLE_STRESS_TESTS +#define TESTSERVERNOMAIN + +#include "testServer.cpp" using namespace std::tr1; @@ -38,14 +41,43 @@ std::string ChannelAccessIFTest::TEST_SUMRPC_CHANNEL_NAME = "testSum"; // double[] value std::string ChannelAccessIFTest::TEST_ARRAY_CHANNEL_NAME = "testArray1"; +#ifdef ENABLE_STRESS_TESTS +#define EXTRA_STRESS_TESTS 5 +#else +#define EXTRA_STRESS_TESTS 0 +#endif + +namespace { +struct ScopedClientFactory { + ScopedClientFactory() { ClientFactory::start(); } + ~ScopedClientFactory() { ClientFactory::stop(); } +}; +} int ChannelAccessIFTest::runAllTest() { -#ifdef ENABLE_STRESS_TESTS - testPlan(158); -#else - testPlan(153); -#endif + testPlan(153+EXTRA_STRESS_TESTS); + + Configuration::shared_pointer base_config(ConfigurationBuilder() + .add("EPICS_PVAS_INTF_ADDR_LIST", "127.0.0.1") + .add("EPICS_PVA_ADDR_LIST", "127.0.0.1") + .add("EPICS_PVA_AUTO_ADDR_LIST","0") + .add("EPICS_PVA_SERVER_PORT", "0") + .add("EPICS_PVA_BROADCAST_PORT", "0") + .push_map() + .build()); + + TestServer::shared_pointer tstserv(new TestServer(base_config)); + testDiag("TestServer on ports TCP=%u UDP=%u\n", + tstserv->getServerPort(), + tstserv->getBroadcastPort()); + ConfigurationFactory::registerConfiguration("pvAccess-client", + ConfigurationBuilder() + .push_config(base_config) + .add("EPICS_PVA_BROADCAST_PORT", tstserv->getBroadcastPort()) + .push_map() + .build()); + ScopedClientFactory SCF; test_implementation(); test_providerName(); @@ -2348,3 +2380,30 @@ PVStructure::shared_pointer ChannelAccessIFTest::createArrayPvRequest() { pvFieldName->put("value"); return pvRequest; } + + +class ChannelAccessIFRemoteTest: public ChannelAccessIFTest { + + public: + + virtual ChannelProvider::shared_pointer getChannelProvider() { + return getChannelProviderRegistry()->getProvider( + "pva"); + } + + + virtual long getTimeoutSec() { + return 3; + } + + + virtual bool isLocal() { return false;} + +}; + +MAIN(testChannelAccess) +{ + SET_LOG_LEVEL(logLevelError); + ChannelAccessIFRemoteTest caRemoteTest; + return caRemoteTest.runAllTest(); +} diff --git a/testApp/remote/testChannelAccess.cpp b/testApp/remote/testChannelAccess.cpp deleted file mode 100755 index 3e343ba..0000000 --- a/testApp/remote/testChannelAccess.cpp +++ /dev/null @@ -1,104 +0,0 @@ -/* - * testChannelAccess.cpp - */ - -#ifdef _WIN32 -#define NOMINMAX -#endif - -// TODO not nice -// disable buggy boost enable_shared_from_this assert code -#define BOOST_DISABLE_ASSERTS - -#define TESTSERVERNOMAIN - -#include -#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 getChannelProviderRegistry()->getProvider( - "pva"); - } - - - virtual long getTimeoutSec() { - return 3; - } - - - virtual bool isLocal() { return false;} - - - ~ChannelAccessIFRemoteTest() { - m_serverContextAction.stop(); - ClientFactory::stop(); - - // shutdown SIGSEG problems - epicsThreadSleep(2.0); - } - - private: - ServerContextAction m_serverContextAction; -}; - - -MAIN(testChannelAccess) -{ - // note: this leaks memory (uses putenv) - epicsEnvSet("EPICS_PVA_ADDR_LIST", "127.0.0.1"); - epicsEnvSet("EPICS_PVA_AUTO_ADDR_LIST", "0"); - - SET_LOG_LEVEL(logLevelError); - ChannelAccessIFRemoteTest caRemoteTest; - return caRemoteTest.runAllTest(); -} diff --git a/testApp/remote/testServer.cpp b/testApp/remote/testServer.cpp index cacbb26..b49fdc2 100644 --- a/testApp/remote/testServer.cpp +++ b/testApp/remote/testServer.cpp @@ -1554,12 +1554,14 @@ public: m_channelRPCRequester->requestDone(Status::Ok, shared_from_this(), result); } +#ifndef TESTSERVERNOMAIN else if (channelName.find("testServerShutdown") == 0) { PVStructure::shared_pointer nullPtr; m_channelRPCRequester->requestDone(Status::Ok, shared_from_this(), nullPtr); testServerShutdown(); } +#endif else { /* @@ -2727,44 +2729,76 @@ public: }; - -static ServerContextImpl::shared_pointer ctx; - -void testServer(int timeToRun) +struct TestServer : public Runnable { + POINTER_DEFINITIONS(TestServer); - MockChannelProviderFactory::shared_pointer factory(new MockChannelProviderFactory()); - registerChannelProviderFactory(factory); + static TestServer::shared_pointer ctx; - //ServerContextImpl::shared_pointer ctx = ServerContextImpl::create(); - ctx = ServerContextImpl::create(); - ctx->initialize(getChannelProviderRegistry()); + Configuration::shared_pointer conf; + ServerContextImpl::shared_pointer context; + Event startup; + Thread runner; + MockChannelProviderFactory::shared_pointer factory; - ctx->printInfo(); - - ctx->run(timeToRun); - - ctx->destroy(); - - unregisterChannelProviderFactory(factory); - - structureChangedListeners.clear(); + TestServer(const Configuration::shared_pointer& conf) + :conf(conf) + ,runner(Thread::Config(this).name("TestServer").autostart(false)) + ,factory(new MockChannelProviderFactory()) { - Lock guard(structureStoreMutex); - structureStore.clear(); + registerChannelProviderFactory(factory); + + context = ServerContextImpl::create(conf); + context->initialize(getChannelProviderRegistry()); + + runner.start(); + startup.wait(); // wait for thread to start } - ctx.reset(); + ~TestServer() + { + context->shutdown(); + runner.exitWait(); + context->destroy(); - unregisterChannelProviderFactory(factory); + unregisterChannelProviderFactory(factory); + + structureChangedListeners.clear(); + { + Lock guard(structureStoreMutex); + structureStore.clear(); + } + ctx.reset(); + + unregisterChannelProviderFactory(factory); - shutdownSimADCs(); -} + shutdownSimADCs(); + } + // Use with EPICS_PVA_SERVER_PORT==0 for dynamic port (unit-tests) + unsigned short getServerPort() + { + return context->getServerPort(); + } + unsigned short getBroadcastPort() + { + return context->getBroadcastPort(); + } + virtual void run() + { + startup.signal(); + context->run(conf->getPropertyAsInteger("timeToRun", 0)); // default is no timeout + } + void shutdown() { + context->shutdown(); + } +}; + +TestServer::shared_pointer TestServer::ctx; + void testServerShutdown() { - // NOTE: this is not thread-safe TODO - ctx->shutdown(); + TestServer::ctx->shutdown(); } #include @@ -2789,7 +2823,7 @@ int main(int argc, char *argv[]) int opt; /* getopt() current option */ bool debug = false; bool cleanupAndReport = false; - int timeToRun = 0; + std::string timeToRun("0"); setvbuf(stdout,NULL,_IOLBF,BUFSIZ); /* Set stdout to line buffering */ @@ -2799,7 +2833,7 @@ int main(int argc, char *argv[]) usage(argv); return 0; case 't': /* Print usage */ - timeToRun = atoi(optarg); + timeToRun = optarg; break; case 'd': /* Debug log level */ debug = true; @@ -2827,7 +2861,15 @@ int main(int argc, char *argv[]) srand ( time(NULL) ); - testServer(timeToRun); + { + TestServer::shared_pointer srv(new TestServer(ConfigurationBuilder() + .push_env() + .add("timeToRun", timeToRun) + .push_map() + .build())); + TestServer::ctx = srv; + } + TestServer::ctx.reset(); cout << "Done" << endl;