2 #include <epicsAtomic.h>
3 #include <epicsGuard.h>
4 #include <epicsUnitTest.h>
7 #include <pv/epicsException.h>
8 #include <pv/monitor.h>
10 #include <pv/serverContext.h>
14 #include "utilities.h"
16 namespace pvd = epics::pvData;
17 namespace pva = epics::pvAccess;
19 typedef epicsGuard<epicsMutex> Guard;
23 pvd::PVStructurePtr makeRequest(
size_t bsize)
25 pvd::StructureConstPtr dtype(pvd::getFieldCreate()->createFieldBuilder()
26 ->addNestedStructure(
"record")
27 ->addNestedStructure(
"_options")
28 ->add(
"queueSize", pvd::pvString)
33 pvd::PVStructurePtr ret(pvd::getPVDataCreate()->createPVStructure(dtype));
34 ret->getSubFieldT<pvd::PVScalar>(
"record._options.queueSize")->putFrom<pvd::int32>(bsize);
40 TestProvider::shared_pointer upstream;
41 TestPV::shared_pointer test1;
44 GWServerChannelProvider::shared_pointer gateway;
46 TestChannelRequester::shared_pointer client_req;
47 pva::Channel::shared_pointer client;
52 ,test1(upstream->addPV(
"test1", pvd::getFieldCreate()->createFieldBuilder()
53 ->add(
"x", pvd::pvInt)
54 ->add(
"y", pvd::pvInt)
56 ,test1_x(test1->value,
"x")
57 ,test1_y(test1->value,
"y")
60 ,client(gateway->createChannel(
"test1", client_req))
62 testDiag(
"pre-test setup");
64 testAbort(
"channel \"test1\" not connected");
77 testDiag(
"Push the initial event through from upstream to downstream");
80 pvd::Monitor::shared_pointer mon(client->createMonitor(mreq, makeRequest(2)));
81 if(!mon) testAbort(
"Failed to create monitor");
83 testEqual(mreq->eventCnt, 0u);
84 testOk1(mon->start().isSuccess());
87 testEqual(mreq->eventCnt, 1u);
88 pva::MonitorElementPtr elem(mon->poll());
89 testOk1(!!elem.get());
90 if(!!elem.get()) testEqual(toString(*elem->changedBitSet),
"{0}");
91 else testFail(
"oops");
92 testOk1(elem && elem->pvStructurePtr->getSubFieldT<pvd::PVInt>(
"x")->get()==1);
94 if(elem) mon->release(elem);
96 testOk1(!mon->poll());
106 testDiag(
"Test two downstream monitors sharing the same upstream");
109 pvd::Monitor::shared_pointer mon(client->createMonitor(mreq, makeRequest(2)));
110 if(!mon) testAbort(
"Failed to create monitor");
114 pvd::Monitor::shared_pointer mon2(client->createMonitor(mreq2, makeRequest(2)));
115 if(!mon2) testAbort(
"Failed to create monitor2");
117 testOk1(mreq->eventCnt==0);
118 testOk1(mreq2->eventCnt==0);
119 testOk1(mon->start().isSuccess());
120 testOk1(mon2->start().isSuccess());
121 upstream->dispatch();
123 testOk1(mreq->eventCnt==1);
124 testOk1(mreq2->eventCnt==1);
126 pva::MonitorElementPtr elem(mon->poll());
127 pva::MonitorElementPtr elem2(mon2->poll());
128 testOk1(!!elem.get());
129 testOk1(!!elem2.get());
130 testOk1(elem!=elem2);
131 testOk1(elem && elem->pvStructurePtr->getSubFieldT<pvd::PVInt>(
"x")->get()==1);
132 testOk1(elem && elem->pvStructurePtr->getSubFieldT<pvd::PVInt>(
"y")->get()==2);
133 testOk1(elem2 && elem2->pvStructurePtr->getSubFieldT<pvd::PVInt>(
"x")->get()==1);
134 testOk1(elem2 && elem2->pvStructurePtr->getSubFieldT<pvd::PVInt>(
"y")->get()==2);
136 if(elem) mon->release(elem);
137 if(elem2) mon2->release(elem2);
139 testOk1(!mon->poll());
140 testOk1(!mon2->poll());
142 testDiag(
"explicitly push an update");
147 test1->post(changed);
150 elem2 = mon2->poll();
151 testOk1(!!elem.get());
152 testOk1(!!elem2.get());
153 testOk1(elem!=elem2);
154 if(elem) testDiag(
"elem changed '%s' overflow '%s'", toString(*elem->changedBitSet).c_str(), toString(*elem->overrunBitSet).c_str());
155 testOk1(elem && elem->pvStructurePtr->getSubFieldT<pvd::PVInt>(
"x")->get()==42);
156 testOk1(elem && elem->pvStructurePtr->getSubFieldT<pvd::PVInt>(
"y")->get()==2);
157 if(elem2) testDiag(
"elem2 changed '%s' overflow '%s'", toString(*elem2->changedBitSet).c_str(), toString(*elem2->overrunBitSet).c_str());
158 testOk1(elem2 && elem2->pvStructurePtr->getSubFieldT<pvd::PVInt>(
"x")->get()==42);
159 testOk1(elem2 && elem2->pvStructurePtr->getSubFieldT<pvd::PVInt>(
"y")->get()==2);
161 if(elem) mon->release(elem);
162 if(elem2) mon2->release(elem2);
164 testOk1(!mon->poll());
165 testOk1(!mon2->poll());
171 void test_ds_no_start()
173 testDiag(
"Test downstream monitor never start()s");
176 pvd::Monitor::shared_pointer mon(client->createMonitor(mreq, makeRequest(2)));
177 if(!mon) testAbort(
"Failed to create monitor");
179 upstream->dispatch();
181 testOk1(mreq->eventCnt==0);
182 testOk1(!mon->poll());
187 test1->post(changed,
false);
189 test1->post(changed,
false);
191 test1->post(changed,
false);
193 test1->post(changed);
195 testOk1(!mon->poll());
200 void test_overflow_upstream()
202 testDiag(
"Check behavour when upstream monitor overflows (mostly transparent)");
205 pvd::Monitor::shared_pointer mon(client->createMonitor(mreq, makeRequest(2)));
206 if(!mon) testAbort(
"Failed to create monitor");
208 testOk1(mreq->eventCnt==0);
209 testOk1(mon->start().isSuccess());
210 upstream->dispatch();
211 testOk1(mreq->eventCnt==1);
213 testDiag(
"poll initial update");
214 pva::MonitorElementPtr elem(mon->poll());
215 testOk1(!!elem.get());
216 if(elem) mon->release(elem);
218 testOk1(!mon->poll());
226 test1->post(changed,
false);
229 test1->post(changed,
false);
232 test1->post(changed,
false);
235 test1->post(changed);
238 testOk1(!!elem.get());
240 testDiag(
"XX %d", elem ? elem->pvStructurePtr->getSubFieldT<pvd::PVInt>(
"x")->get() : -42);
241 testOk1(elem && elem->pvStructurePtr->getSubFieldT<pvd::PVInt>(
"x")->get()==50);
242 testOk1(elem && elem->changedBitSet->nextSetBit(0)==1);
243 testOk1(elem && elem->changedBitSet->nextSetBit(2)==-1);
244 testOk1(elem && elem->overrunBitSet->nextSetBit(0)==-1);
246 if(elem) mon->release(elem);
249 testOk1(!!elem.get());
251 testOk1(elem && elem->pvStructurePtr->getSubFieldT<pvd::PVInt>(
"x")->get()==51);
252 testOk1(elem && elem->changedBitSet->nextSetBit(0)==1);
253 testOk1(elem && elem->changedBitSet->nextSetBit(2)==-1);
254 testOk1(elem && elem->overrunBitSet->nextSetBit(0)==-1);
256 if(elem) mon->release(elem);
259 testOk1(!!elem.get());
261 testOk1(elem && elem->pvStructurePtr->getSubFieldT<pvd::PVInt>(
"x")->get()==53);
262 testOk1(elem && elem->changedBitSet->nextSetBit(0)==1);
263 testOk1(elem && elem->changedBitSet->nextSetBit(2)==-1);
264 testOk1(elem && elem->overrunBitSet->nextSetBit(0)==1);
265 testOk1(elem && elem->overrunBitSet->nextSetBit(2)==-1);
267 if(elem) mon->release(elem);
269 testOk1(!mon->poll());
274 void test_overflow_downstream()
276 testDiag(
"Check behavour when downstream monitor overflows");
279 pvd::Monitor::shared_pointer mon(client->createMonitor(mreq, makeRequest(2)));
280 if(!mon) testAbort(
"Failed to create monitor");
282 testOk1(mreq->eventCnt==0);
283 testOk1(mon->start().isSuccess());
284 upstream->dispatch();
285 testOk1(mreq->eventCnt==1);
287 testDiag(
"poll initial update");
288 pva::MonitorElementPtr elem(mon->poll());
289 testOk1(!!elem.get());
290 if(elem) mon->release(elem);
298 test1->post(changed);
300 test1->post(changed);
302 test1->post(changed);
304 test1->post(changed);
307 testOk1(!!elem.get());
309 testOk1(elem && elem->pvStructurePtr->getSubFieldT<pvd::PVInt>(
"x")->get()==50);
310 testOk1(elem && elem->changedBitSet->nextSetBit(0)==1);
311 testOk1(elem && elem->changedBitSet->nextSetBit(2)==-1);
312 testOk1(elem && elem->overrunBitSet->nextSetBit(0)==-1);
314 if(elem) mon->release(elem);
317 testOk1(!!elem.get());
319 testOk1(elem && elem->pvStructurePtr->getSubFieldT<pvd::PVInt>(
"x")->get()==51);
320 testOk1(elem && elem->changedBitSet->nextSetBit(0)==1);
321 testOk1(elem && elem->changedBitSet->nextSetBit(2)==-1);
322 testOk1(elem && elem->overrunBitSet->nextSetBit(0)==-1);
324 if(elem) mon->release(elem);
327 testOk1(!!elem.get());
329 testOk1(elem && elem->pvStructurePtr->getSubFieldT<pvd::PVInt>(
"x")->get()==53);
330 testOk1(elem && elem->changedBitSet->nextSetBit(0)==1);
331 testOk1(elem && elem->changedBitSet->nextSetBit(2)==-1);
332 testOk1(elem && elem->overrunBitSet->nextSetBit(0)==1);
333 testOk1(elem && elem->overrunBitSet->nextSetBit(2)==-1);
335 if(elem) mon->release(elem);
337 testOk1(!mon->poll());
348 TEST_METHOD(TestMonitor, test_event);
349 TEST_METHOD(TestMonitor, test_share);
350 TEST_METHOD(TestMonitor, test_ds_no_start);
351 TEST_METHOD(TestMonitor, test_overflow_upstream);
352 TEST_METHOD(TestMonitor, test_overflow_downstream);
353 TestProvider::testCounts();
356 #define TESTC(name) temp=epicsAtomicGetSizeT(&name::num_instances); ok &= temp==0; testDiag("num. live " #name " %u", (unsigned)temp)
363 testOk(ok,
"All instances free'd");