pva2pva  1.4.1
 All Classes Functions Variables Pages
utilities.h
1 #ifndef UTILITIES_H
2 #define UTILITIES_H
3 
4 #include <deque>
5 #include <sstream>
6 
7 #include <errlog.h>
8 #include <epicsEvent.h>
9 #include <epicsUnitTest.h>
10 #include <dbUnitTest.h>
11 
12 #include <pv/pvUnitTest.h>
13 #include <pv/pvAccess.h>
14 
15 #include "pvahelper.h"
16 #include "weakmap.h"
17 #include "weakset.h"
18 
19 struct TestPV;
20 struct TestPVChannel;
21 struct TestPVMonitor;
22 struct TestProvider;
23 
24 // minimally useful boilerplate which must appear *everywhere*
25 #define DUMBREQUESTER(NAME) \
26  virtual std::string getRequesterName() OVERRIDE { return #NAME; }
27 
28 template<typename T>
29 inline std::string toString(const T& tbs)
30 {
31  std::ostringstream oss;
32  oss << tbs;
33  return oss.str();
34 }
35 
36 // Boilerplate reduction for accessing a scalar field
37 template<typename T>
39  epics::pvData::PVScalar::shared_pointer field;
40  typedef T value_type;
41  ScalarAccessor(const epics::pvData::PVStructurePtr& s, const char *name)
42  :field(s->getSubFieldT<epics::pvData::PVScalar>(name))
43  {}
44  operator value_type() {
45  return field->getAs<T>();
46  }
47  ScalarAccessor& operator=(T v) {
48  field->putFrom<T>(v);
49  return *this;
50  }
51  ScalarAccessor& operator+=(T v) {
52  field->putFrom<T>(field->getAs<T>()+v);
53  return *this;
54  }
55 };
56 
57 struct TestChannelRequester : public epics::pvAccess::ChannelRequester
58 {
59  POINTER_DEFINITIONS(TestChannelRequester);
60  DUMBREQUESTER(TestChannelRequester)
61 
62  epicsMutex lock;
63  epicsEvent wait;
64  epics::pvAccess::Channel::shared_pointer chan;
65  epics::pvData::Status status;
66  epics::pvAccess::Channel::ConnectionState laststate;
68  virtual ~TestChannelRequester();
69  virtual void channelCreated(const epics::pvData::Status& status, epics::pvAccess::Channel::shared_pointer const & channel);
70  virtual void channelStateChange(epics::pvAccess::Channel::shared_pointer const & channel, epics::pvAccess::Channel::ConnectionState connectionState);
71 
72  bool waitForConnect();
73 };
74 
75 struct TestChannelFieldRequester : public epics::pvAccess::GetFieldRequester
76 {
77  POINTER_DEFINITIONS(TestChannelFieldRequester);
78  DUMBREQUESTER(TestChannelFieldRequester)
79 
80  bool done;
81  epics::pvData::Status status;
82  epics::pvData::FieldConstPtr fielddesc;
83 
84  TestChannelFieldRequester() :done(false) {}
85  virtual ~TestChannelFieldRequester() {}
86 
87  virtual void getDone(
88  const epics::pvData::Status& status,
89  epics::pvData::FieldConstPtr const & field)
90  {
91  this->status = status;
92  fielddesc = field;
93  done = true;
94  }
95 };
96 
97 struct TestChannelGetRequester : public epics::pvAccess::ChannelGetRequester
98 {
99  POINTER_DEFINITIONS(TestChannelGetRequester);
100  DUMBREQUESTER(TestChannelGetRequester)
101 
102  bool connected, done;
103  epics::pvData::Status statusConnect, statusDone;
104  epics::pvAccess::ChannelGet::shared_pointer channelGet;
105  epics::pvData::Structure::const_shared_pointer fielddesc;
106  epics::pvData::PVStructure::shared_pointer value;
107  epics::pvData::BitSet::shared_pointer changed;
108 
110  virtual ~TestChannelGetRequester();
111 
112  virtual void channelGetConnect(
113  const epics::pvData::Status& status,
114  epics::pvAccess::ChannelGet::shared_pointer const & channelGet,
115  epics::pvData::Structure::const_shared_pointer const & structure);
116 
117  virtual void getDone(
118  const epics::pvData::Status& status,
119  epics::pvAccess::ChannelGet::shared_pointer const & channelGet,
120  epics::pvData::PVStructure::shared_pointer const & pvStructure,
121  epics::pvData::BitSet::shared_pointer const & bitSet);
122 };
123 
124 struct TestChannelPutRequester : public epics::pvAccess::ChannelPutRequester
125 {
126  POINTER_DEFINITIONS(TestChannelPutRequester);
127  DUMBREQUESTER(TestChannelPutRequester)
128 
129  bool connected, doneGet, donePut;
130  epics::pvData::Status statusConnect, statusPut, statusGet;
131  epics::pvAccess::ChannelPut::shared_pointer put;
132  epics::pvData::Structure::const_shared_pointer fielddesc;
133  epics::pvData::PVStructure::shared_pointer value;
134  epics::pvData::BitSet::shared_pointer changed;
135 
137  virtual ~TestChannelPutRequester();
138 
139  virtual void channelPutConnect(
140  const epics::pvData::Status& status,
141  epics::pvAccess::ChannelPut::shared_pointer const & channelPut,
142  epics::pvData::Structure::const_shared_pointer const & structure);
143 
144  virtual void putDone(
145  const epics::pvData::Status& status,
146  epics::pvAccess::ChannelPut::shared_pointer const & channelPut);
147 
148  virtual void getDone(
149  const epics::pvData::Status& status,
150  epics::pvAccess::ChannelPut::shared_pointer const & channelPut,
151  epics::pvData::PVStructure::shared_pointer const & pvStructure,
152  epics::pvData::BitSet::shared_pointer const & bitSet);
153 };
154 
155 struct TestChannelMonitorRequester : public epics::pvData::MonitorRequester
156 {
157  POINTER_DEFINITIONS(TestChannelMonitorRequester);
158  DUMBREQUESTER(TestChannelMonitorRequester)
159 
160  epicsMutex lock;
161  epicsEvent wait;
162  bool connected;
163  bool unlistend;
164  size_t eventCnt;
165  epics::pvData::Status connectStatus;
166  epics::pvData::MonitorPtr mon;
167  epics::pvData::StructureConstPtr dtype;
168 
170  virtual ~TestChannelMonitorRequester();
171 
172  virtual void monitorConnect(epics::pvData::Status const & status,
173  epics::pvData::MonitorPtr const & monitor,
174  epics::pvData::StructureConstPtr const & structure);
175  virtual void monitorEvent(epics::pvData::MonitorPtr const & monitor);
176  virtual void unlisten(epics::pvData::MonitorPtr const & monitor);
177 
178  bool waitForConnect();
179  bool waitForEvent();
180 };
181 
182 struct TestPVChannel : public BaseChannel
183 {
184  POINTER_DEFINITIONS(TestPVChannel);
185  DUMBREQUESTER(TestPVChannel)
186  std::tr1::weak_ptr<TestPVChannel> weakself;
187 
188  const std::tr1::shared_ptr<TestPV> pv;
189  ConnectionState state;
190 
192  monitors_t monitors;
193 
194  TestPVChannel(const std::tr1::shared_ptr<TestPV>& pv,
195  const std::tr1::shared_ptr<epics::pvAccess::ChannelRequester>& req);
196  virtual ~TestPVChannel();
197 
198  virtual std::string getRemoteAddress() { return "localhost:1234"; }
199  virtual ConnectionState getConnectionState();
200 
201  virtual void getField(epics::pvAccess::GetFieldRequester::shared_pointer const & requester,std::string const & subField);
202 
203  virtual epics::pvData::Monitor::shared_pointer createMonitor(
204  epics::pvData::MonitorRequester::shared_pointer const & monitorRequester,
205  epics::pvData::PVStructure::shared_pointer const & pvRequest);
206 };
207 
208 struct TestPVMonitor : public epics::pvData::Monitor
209 {
210  POINTER_DEFINITIONS(TestPVMonitor);
211  std::tr1::weak_ptr<TestPVMonitor> weakself;
212 
213  const TestPVChannel::shared_pointer channel;
214  const epics::pvData::MonitorRequester::weak_pointer requester;
215 
216  bool running;
217  bool finalize;
218  bool inoverflow;
219  bool needWakeup;
220 
221  TestPVMonitor(const TestPVChannel::shared_pointer& ch,
222  const epics::pvData::MonitorRequester::shared_pointer& req,
223  size_t bsize);
224  virtual ~TestPVMonitor();
225 
226  virtual void destroy();
227 
228  virtual epics::pvData::Status start();
229  virtual epics::pvData::Status stop();
230  virtual epics::pvData::MonitorElementPtr poll();
231  virtual void release(epics::pvData::MonitorElementPtr const & monitorElement);
232 
233  std::deque<epics::pvData::MonitorElementPtr> buffer, free;
234  epics::pvData::MonitorElementPtr overflow;
235 };
236 
237 struct TestPV
238 {
239  POINTER_DEFINITIONS(TestPV);
240  std::tr1::weak_ptr<TestPV> weakself;
241 
242  const std::string name;
243  std::tr1::weak_ptr<TestProvider> const provider;
244 
245  epics::pvData::PVDataCreatePtr factory;
246 
247  const epics::pvData::StructureConstPtr dtype;
248  epics::pvData::PVStructurePtr value;
249 
250  TestPV(const std::string& name,
251  const std::tr1::shared_ptr<TestProvider>& provider,
252  const epics::pvData::StructureConstPtr& dtype);
253  ~TestPV();
254 
255  void post(bool notify = true);
256  void post(const epics::pvData::BitSet& changed, bool notify = true);
257 
258  void disconnect();
259 
260  mutable epicsMutex lock;
261 
263  channels_t channels;
264  friend struct TestProvider;
265 };
266 
267 struct TestProvider : public epics::pvAccess::ChannelProvider, std::tr1::enable_shared_from_this<TestProvider>
268 {
269  POINTER_DEFINITIONS(TestProvider);
270 
271  virtual std::string getProviderName() { return "TestProvider"; }
272 
273  virtual void destroy();
274 
275  virtual epics::pvAccess::ChannelFind::shared_pointer channelFind(std::string const & channelName,
276  epics::pvAccess::ChannelFindRequester::shared_pointer const & channelFindRequester);
277  virtual epics::pvAccess::ChannelFind::shared_pointer channelList(epics::pvAccess::ChannelListRequester::shared_pointer const & channelListRequester);
278  virtual epics::pvAccess::Channel::shared_pointer createChannel(std::string const & channelName,epics::pvAccess::ChannelRequester::shared_pointer const & channelRequester,
279  short priority = PRIORITY_DEFAULT);
280  virtual epics::pvAccess::Channel::shared_pointer createChannel(std::string const & channelName, epics::pvAccess::ChannelRequester::shared_pointer const & channelRequester,
281  short priority, std::string const & address);
282 
283  TestProvider();
284  virtual ~TestProvider();
285 
286  TestPV::shared_pointer addPV(const std::string& name, const epics::pvData::StructureConstPtr& tdef);
287 
288  void dispatch();
289 
290  mutable epicsMutex lock;
292  pvs_t pvs;
293 
294  static void testCounts();
295 };
296 
297 struct TestIOC {
298  bool hasInit;
299  TestIOC() : hasInit(false) {
300  testdbPrepare();
301  }
302  ~TestIOC() {
303  this->shutdown();
304  testdbCleanup();
305  }
306  void init() {
307  if(!hasInit) {
308  eltc(0);
309  testIocInitOk();
310  eltc(1);
311  hasInit = true;
312  }
313  }
314  void shutdown() {
315  if(hasInit) {
316  testIocShutdownOk();
317  hasInit = false;
318  }
319  }
320 };
321 
322 #endif // UTILITIES_H