Files
pva2pva/testApp/utilities.h
Michael Davidsaver 3cd09efa0a more test
2016-01-29 15:01:37 -05:00

244 lines
9.2 KiB
C++

#ifndef UTILITIES_H
#define UTILITIES_H
#include <deque>
#include <epicsEvent.h>
#include <epicsUnitTest.h>
#include <pv/pvAccess.h>
#include "weakmap.h"
#include "weakset.h"
struct TestPV;
struct TestPVChannel;
struct TestPVMonitor;
struct TestProvider;
// minimally useful boilerplate which must appear *everywhere*
#define DUMBREQUESTER(NAME) \
virtual std::string getRequesterName() { return #NAME; } \
virtual void message(std::string const & message,epics::pvData::MessageType messageType) { \
testDiag("%s : " #NAME "(%p) : %s", epics::pvData::getMessageTypeName(messageType).c_str(), this, message.c_str()); \
}
template<class C, void (C::*M)()>
void test_method(const char *kname, const char *mname)
{
try {
testDiag("------- %s::%s --------", kname, mname);
C inst;
(inst.*M)();
} catch(std::exception& e) {
PRINT_EXCEPTION(e);
testAbort("unexpected exception: %s", e.what());
}
}
// Construct an instance and run one method
#define TEST_METHOD(klass, method) test_method<klass, &klass::method>(#klass, #method)
// Boilerplate reduction for accessing a scalar field
template<typename T>
struct ScalarAccessor {
epics::pvData::PVScalar::shared_pointer field;
typedef T value_type;
ScalarAccessor(const epics::pvData::PVStructurePtr& s, const char *name)
:field(s->getSubFieldT<epics::pvData::PVScalar>(name))
{}
operator value_type() {
return field->getAs<T>();
}
ScalarAccessor& operator=(T v) {
field->putFrom<T>(v);
return *this;
}
};
struct TestChannelRequester : public epics::pvAccess::ChannelRequester
{
POINTER_DEFINITIONS(TestChannelRequester);
DUMBREQUESTER(TestChannelRequester)
epicsMutex lock;
epicsEvent wait;
epics::pvAccess::Channel::shared_pointer chan;
epics::pvData::Status status;
epics::pvAccess::Channel::ConnectionState laststate;
TestChannelRequester();
virtual ~TestChannelRequester();
virtual void channelCreated(const epics::pvData::Status& status, epics::pvAccess::Channel::shared_pointer const & channel);
virtual void channelStateChange(epics::pvAccess::Channel::shared_pointer const & channel, epics::pvAccess::Channel::ConnectionState connectionState);
bool waitForConnect();
};
struct TestChannelMonitorRequester : public epics::pvData::MonitorRequester
{
POINTER_DEFINITIONS(TestChannelMonitorRequester);
DUMBREQUESTER(TestChannelMonitorRequester)
epicsMutex lock;
epicsEvent wait;
bool connected;
bool unlistend;
size_t eventCnt;
epics::pvData::Status connectStatus;
epics::pvData::MonitorPtr mon;
epics::pvData::StructureConstPtr dtype;
TestChannelMonitorRequester();
virtual ~TestChannelMonitorRequester();
virtual void monitorConnect(epics::pvData::Status const & status,
epics::pvData::MonitorPtr const & monitor,
epics::pvData::StructureConstPtr const & structure);
virtual void monitorEvent(epics::pvData::MonitorPtr const & monitor);
virtual void unlisten(epics::pvData::MonitorPtr const & monitor);
bool waitForEvent();
};
struct TestPVChannel : public epics::pvAccess::Channel
{
POINTER_DEFINITIONS(TestPVChannel);
DUMBREQUESTER(TestPVChannel)
std::tr1::weak_ptr<TestPVChannel> weakself;
const std::tr1::shared_ptr<TestPV> pv;
std::tr1::shared_ptr<epics::pvAccess::ChannelRequester> requester;
ConnectionState state;
typedef weak_set<TestPVMonitor> monitors_t;
monitors_t monitors;
TestPVChannel(const std::tr1::shared_ptr<TestPV>& pv,
const std::tr1::shared_ptr<epics::pvAccess::ChannelRequester>& req);
virtual ~TestPVChannel();
virtual void destroy();
virtual std::tr1::shared_ptr<epics::pvAccess::ChannelProvider> getProvider();
virtual std::string getRemoteAddress() { return "localhost:1234"; }
virtual ConnectionState getConnectionState();
virtual std::string getChannelName();
virtual std::tr1::shared_ptr<epics::pvAccess::ChannelRequester> getChannelRequester()
{ return std::tr1::shared_ptr<epics::pvAccess::ChannelRequester>(requester); }
virtual bool isConnected();
virtual void getField(epics::pvAccess::GetFieldRequester::shared_pointer const & requester,std::string const & subField);
virtual epics::pvAccess::AccessRights getAccessRights(epics::pvData::PVField::shared_pointer const & pvField)
{ return epics::pvAccess::readWrite; }
virtual epics::pvAccess::ChannelProcess::shared_pointer createChannelProcess(
epics::pvAccess::ChannelProcessRequester::shared_pointer const & channelProcessRequester,
epics::pvData::PVStructure::shared_pointer const & pvRequest);
virtual epics::pvAccess::ChannelGet::shared_pointer createChannelGet(
epics::pvAccess::ChannelGetRequester::shared_pointer const & channelGetRequester,
epics::pvData::PVStructure::shared_pointer const & pvRequest);
virtual epics::pvAccess::ChannelPut::shared_pointer createChannelPut(
epics::pvAccess::ChannelPutRequester::shared_pointer const & channelPutRequester,
epics::pvData::PVStructure::shared_pointer const & pvRequest);
virtual epics::pvAccess::ChannelPutGet::shared_pointer createChannelPutGet(
epics::pvAccess::ChannelPutGetRequester::shared_pointer const & channelPutGetRequester,
epics::pvData::PVStructure::shared_pointer const & pvRequest);
virtual epics::pvAccess::ChannelRPC::shared_pointer createChannelRPC(
epics::pvAccess::ChannelRPCRequester::shared_pointer const & channelRPCRequester,
epics::pvData::PVStructure::shared_pointer const & pvRequest);
virtual epics::pvData::Monitor::shared_pointer createMonitor(
epics::pvData::MonitorRequester::shared_pointer const & monitorRequester,
epics::pvData::PVStructure::shared_pointer const & pvRequest);
virtual epics::pvAccess::ChannelArray::shared_pointer createChannelArray(
epics::pvAccess::ChannelArrayRequester::shared_pointer const & channelArrayRequester,
epics::pvData::PVStructure::shared_pointer const & pvRequest);
virtual void printInfo() {}
virtual void printInfo(std::ostream& out) {}
};
struct TestPVMonitor : public epics::pvData::Monitor
{
POINTER_DEFINITIONS(TestPVMonitor);
std::tr1::weak_ptr<TestPVMonitor> weakself;
TestPVChannel::shared_pointer channel;
epics::pvData::MonitorRequester::shared_pointer requester;
bool running;
bool finalize;
bool inoverflow;
bool needWakeup;
TestPVMonitor(const TestPVChannel::shared_pointer& ch,
const epics::pvData::MonitorRequester::shared_pointer& req,
size_t bsize);
virtual ~TestPVMonitor();
virtual void destroy();
virtual epics::pvData::Status start();
virtual epics::pvData::Status stop();
virtual epics::pvData::MonitorElementPtr poll();
virtual void release(epics::pvData::MonitorElementPtr const & monitorElement);
std::deque<epics::pvData::MonitorElementPtr> buffer, free;
epics::pvData::BitSet changedMask, overflowMask;
};
struct TestPV
{
POINTER_DEFINITIONS(TestPV);
std::tr1::weak_ptr<TestPV> weakself;
const std::string name;
std::tr1::shared_ptr<TestProvider> const provider;
epics::pvData::PVDataCreatePtr factory;
const epics::pvData::StructureConstPtr dtype;
epics::pvData::PVStructurePtr value;
TestPV(const std::string& name,
const std::tr1::shared_ptr<TestProvider>& provider,
const epics::pvData::StructureConstPtr& dtype);
~TestPV();
void post(const epics::pvData::BitSet& changed, bool notify = true);
void disconnect();
typedef weak_set<TestPVChannel> channels_t;
channels_t channels;
friend struct TestProvider;
};
struct TestProvider : public epics::pvAccess::ChannelProvider, std::tr1::enable_shared_from_this<TestProvider>
{
POINTER_DEFINITIONS(TestProvider);
virtual std::string getProviderName() { return "TestProvider"; }
virtual void destroy();
virtual epics::pvAccess::ChannelFind::shared_pointer channelFind(std::string const & channelName,
epics::pvAccess::ChannelFindRequester::shared_pointer const & channelFindRequester);
virtual epics::pvAccess::ChannelFind::shared_pointer channelList(epics::pvAccess::ChannelListRequester::shared_pointer const & channelListRequester);
virtual epics::pvAccess::Channel::shared_pointer createChannel(std::string const & channelName,epics::pvAccess::ChannelRequester::shared_pointer const & channelRequester,
short priority = PRIORITY_DEFAULT);
virtual epics::pvAccess::Channel::shared_pointer createChannel(std::string const & channelName, epics::pvAccess::ChannelRequester::shared_pointer const & channelRequester,
short priority, std::string const & address);
TestProvider();
virtual ~TestProvider();
TestPV::shared_pointer addPV(const std::string& name, const epics::pvData::StructureConstPtr& tdef);
void dispatch();
epicsMutex lock;
typedef weak_value_map<std::string, TestPV> pvs_t;
pvs_t pvs;
static void testCounts();
};
#endif // UTILITIES_H