2 #include <epicsAtomic.h>
4 #include <epicsEvent.h>
5 #include <epicsUnitTest.h>
6 #include <dbUnitTest.h>
8 #include <pv/pvUnitTest.h>
9 #include <pv/pvAccess.h>
11 #define epicsExportSharedSymbols
12 #include <utilities.h>
15 typedef epicsGuard<epicsMutex> Guard;
16 typedef epicsGuardRelease<epicsMutex> UnGuard;
18 namespace pvd = epics::pvData;
19 namespace pva = epics::pvAccess;
21 static size_t countTestChannelRequester;
23 TestChannelRequester::TestChannelRequester()
24 :laststate(pva::Channel::NEVER_CONNECTED)
26 epicsAtomicIncrSizeT(&countTestChannelRequester);
30 TestChannelRequester::~TestChannelRequester()
32 epicsAtomicDecrSizeT(&countTestChannelRequester);
35 void TestChannelRequester::channelCreated(
const pvd::Status& status, pva::Channel::shared_pointer
const & channel)
37 testDiag(
"channelCreated %s", channel ? channel->getChannelName().c_str() :
"<fails>");
39 laststate = pva::Channel::CONNECTED;
40 this->status = status;
45 void TestChannelRequester::channelStateChange(pva::Channel::shared_pointer
const & channel,
46 pva::Channel::ConnectionState connectionState)
48 testDiag(
"channelStateChange %s %d", channel->getChannelName().c_str(), (int)connectionState);
50 laststate = connectionState;
54 bool TestChannelRequester::waitForConnect()
59 pva::Channel::ConnectionState cur = chan->getConnectionState();
61 case pva::Channel::NEVER_CONNECTED:
63 case pva::Channel::CONNECTED:
65 case pva::Channel::DISCONNECTED:
66 case pva::Channel::DESTROYED:
75 static size_t countTestChannelGetRequester;
77 TestChannelGetRequester::TestChannelGetRequester()
81 epicsAtomicIncrSizeT(&countTestChannelGetRequester);
84 TestChannelGetRequester::~TestChannelGetRequester()
86 epicsAtomicDecrSizeT(&countTestChannelGetRequester);
89 void TestChannelGetRequester::channelGetConnect(
const epics::pvData::Status &status,
90 const epics::pvAccess::ChannelGet::shared_pointer &
get,
91 const epics::pvData::Structure::const_shared_pointer &structure)
94 testFail(
"channelGetConnect() called twice");
95 statusConnect = status;
97 fielddesc = structure;
101 void TestChannelGetRequester::getDone(
const epics::pvData::Status &status,
102 const epics::pvAccess::ChannelGet::shared_pointer &
get,
103 const epics::pvData::PVStructure::shared_pointer &pvStructure,
104 const epics::pvData::BitSet::shared_pointer &bitSet)
113 TestChannelPutRequester::TestChannelPutRequester()
118 TestChannelPutRequester::~TestChannelPutRequester() {}
120 void TestChannelPutRequester::channelPutConnect(
121 const epics::pvData::Status& status,
122 epics::pvAccess::ChannelPut::shared_pointer
const & channelPut,
123 epics::pvData::Structure::const_shared_pointer
const & structure)
125 statusConnect = status;
127 fielddesc = structure;
131 void TestChannelPutRequester::putDone(
132 const epics::pvData::Status& status,
133 epics::pvAccess::ChannelPut::shared_pointer
const & channelPut)
140 void TestChannelPutRequester::getDone(
141 const epics::pvData::Status& status,
142 epics::pvAccess::ChannelPut::shared_pointer
const & channelPut,
143 epics::pvData::PVStructure::shared_pointer
const & pvStructure,
144 epics::pvData::BitSet::shared_pointer
const & bitSet)
154 static size_t countTestChannelMonitorRequester;
156 TestChannelMonitorRequester::TestChannelMonitorRequester()
161 epicsAtomicIncrSizeT(&countTestChannelMonitorRequester);
164 TestChannelMonitorRequester::~TestChannelMonitorRequester()
166 epicsAtomicDecrSizeT(&countTestChannelMonitorRequester);
169 void TestChannelMonitorRequester::monitorConnect(pvd::Status
const & status,
170 pvd::MonitorPtr
const & monitor,
171 pvd::StructureConstPtr
const & structure)
173 testDiag(
"monitorConnect %p %d", monitor.get(), (int)status.isSuccess());
175 connectStatus = status;
181 void TestChannelMonitorRequester::monitorEvent(pvd::MonitorPtr
const & monitor)
183 testDiag(
"monitorEvent %p", monitor.get());
189 void TestChannelMonitorRequester::unlisten(pvd::MonitorPtr
const & monitor)
191 testDiag(
"unlisten %p", monitor.get());
197 bool TestChannelMonitorRequester::waitForConnect()
207 bool TestChannelMonitorRequester::waitForEvent()
210 size_t icnt = eventCnt;
211 while(!unlistend && eventCnt==icnt) {
218 static size_t countTestPVChannel;
220 TestPVChannel::TestPVChannel(
const std::tr1::shared_ptr<TestPV> &pv,
221 const std::tr1::shared_ptr<pva::ChannelRequester> &req)
222 :
BaseChannel(pv->name, pv->provider, req, pv->dtype)
226 epicsAtomicIncrSizeT(&countTestPVChannel);
229 TestPVChannel::~TestPVChannel()
231 epicsAtomicDecrSizeT(&countTestPVChannel);
234 TestPVChannel::ConnectionState TestPVChannel::getConnectionState()
240 void TestPVChannel::getField(pva::GetFieldRequester::shared_pointer
const & requester,std::string
const & subField)
245 requester->getDone(pvd::Status(), pv->dtype);
248 pvd::Monitor::shared_pointer
249 TestPVChannel::createMonitor(
250 pvd::MonitorRequester::shared_pointer
const & requester,
251 pvd::PVStructure::shared_pointer
const & pvRequest)
253 shared_pointer
self(weakself);
254 TestPVMonitor::shared_pointer ret(
new TestPVMonitor(
self, requester, 2));
260 testDiag(
"TestPVChannel::createMonitor %s %p", pv->name.c_str(), ret.get());
261 requester->monitorConnect(pvd::Status(), ret, pv->dtype);
265 static size_t countTestPVMonitor;
267 TestPVMonitor::TestPVMonitor(
const TestPVChannel::shared_pointer& ch,
268 const pvd::MonitorRequester::shared_pointer& req,
277 pvd::PVDataCreatePtr fact(pvd::PVDataCreate::getPVDataCreate());
278 for(
size_t i=0; i<bsize; i++) {
279 pva::MonitorElementPtr elem(
new pvd::MonitorElement(fact->createPVStructure(channel->pv->dtype)));
280 free.push_back(elem);
282 overflow.reset(
new pvd::MonitorElement(fact->createPVStructure(channel->pv->dtype)));
283 overflow->changedBitSet->set(0);
284 epicsAtomicIncrSizeT(&countTestPVMonitor);
287 TestPVMonitor::~TestPVMonitor()
289 epicsAtomicDecrSizeT(&countTestPVMonitor);
292 void TestPVMonitor::destroy()
294 Guard G(channel->pv->lock);
296 shared_pointer
self(weakself);
297 channel->monitors.erase(
self);
300 pvd::Status TestPVMonitor::start()
302 testDiag(
"TestPVMonitor::start %p",
this);
304 Guard G(channel->pv->lock);
305 if(finalize && buffer.empty())
306 return pvd::Status();
309 return pvd::Status();
313 overflow->pvStructurePtr->copyUnchecked(*channel->pv->value);
315 if(this->buffer.empty()) {
317 testDiag(
" need wakeup");
320 if(!this->free.empty()) {
321 pva::MonitorElementPtr monitorElement(this->free.front());
323 if(overflow->changedBitSet->isEmpty()) {
324 overflow->changedBitSet->set(0);
325 overflow->overrunBitSet->clear();
328 monitorElement->pvStructurePtr->copyUnchecked(*overflow->pvStructurePtr);
329 *monitorElement->changedBitSet = *overflow->changedBitSet;
330 *monitorElement->overrunBitSet = *overflow->overrunBitSet;
331 overflow->changedBitSet->clear();
332 overflow->overrunBitSet->clear();
334 buffer.push_back(monitorElement);
335 this->free.pop_front();
336 testDiag(
" push current");
340 overflow->changedBitSet->clear();
341 overflow->changedBitSet->set(0);
342 testDiag(
" push overflow");
345 return pvd::Status();
348 pvd::Status TestPVMonitor::stop()
350 testDiag(
"TestPVMonitor::stop %p",
this);
351 Guard G(channel->pv->lock);
353 return pvd::Status();
356 pva::MonitorElementPtr TestPVMonitor::poll()
358 pva::MonitorElementPtr ret;
359 Guard G(channel->pv->lock);
360 if(!buffer.empty()) {
361 ret = buffer.front();
364 testDiag(
"TestPVMonitor::poll %p %p",
this, ret.get());
368 void TestPVMonitor::release(pva::MonitorElementPtr
const & monitorElement)
370 Guard G(channel->pv->lock);
371 testDiag(
"TestPVMonitor::release %p %p",
this, monitorElement.get());
375 assert(this->free.empty());
377 monitorElement->pvStructurePtr->copyUnchecked(*overflow->pvStructurePtr);
378 *monitorElement->changedBitSet = *overflow->changedBitSet;
379 *monitorElement->overrunBitSet = *overflow->overrunBitSet;
381 overflow->changedBitSet->clear();
382 overflow->overrunBitSet->clear();
384 buffer.push_back(monitorElement);
385 testDiag(
"TestPVMonitor::release overflow resume %p %p",
this, monitorElement.get());
388 this->free.push_back(monitorElement);
392 static size_t countTestPV;
394 TestPV::TestPV(
const std::string& name,
395 const std::tr1::shared_ptr<TestProvider>& provider,
396 const pvd::StructureConstPtr& dtype)
399 ,factory(pvd::PVDataCreate::getPVDataCreate())
401 ,value(factory->createPVStructure(dtype))
403 epicsAtomicIncrSizeT(&countTestPV);
408 epicsAtomicDecrSizeT(&countTestPV);
411 void TestPV::post(
bool notify)
415 post(changed, notify);
418 void TestPV::post(
const pvd::BitSet& changed,
bool notify)
420 testDiag(
"post %s %d changed '%s'", name.c_str(), (int)notify, toString(changed).c_str());
423 channels_t::vector_type toupdate(channels.
lock_vector());
425 FOREACH(channels_t::vector_type::const_iterator, it, end, toupdate)
429 TestPVChannel::monitors_t::vector_type tomon(chan->monitors.
lock_vector());
430 FOREACH(TestPVChannel::monitors_t::vector_type::const_iterator, it2, end2, tomon)
437 mon->overflow->pvStructurePtr->copyUnchecked(*value, changed);
439 if(mon->free.empty()) {
440 mon->inoverflow =
true;
441 mon->overflow->overrunBitSet->or_and(*mon->overflow->changedBitSet, changed);
442 *mon->overflow->changedBitSet |= changed;
443 testDiag(
"overflow changed '%s' overrun '%s'",
444 toString(*mon->overflow->changedBitSet).c_str(),
445 toString(*mon->overflow->overrunBitSet).c_str());
448 assert(!mon->inoverflow);
450 if(mon->buffer.empty())
451 mon->needWakeup =
true;
453 pvd::MonitorElementPtr& elem(mon->free.front());
456 elem->pvStructurePtr->copyUnchecked(*mon->overflow->pvStructurePtr);
457 *elem->changedBitSet = changed;
458 elem->overrunBitSet->clear();
460 mon->buffer.push_back(elem);
461 mon->free.pop_front();
462 testDiag(
"push %p changed '%s' overflow '%s'", elem.get(),
463 toString(*elem->changedBitSet).c_str(),
464 toString(*elem->overrunBitSet).c_str());
467 if(mon->needWakeup && notify) {
469 mon->needWakeup =
false;
470 pva::MonitorRequester::shared_pointer req(mon->requester.lock());
473 req->monitorEvent(*it2);
479 void TestPV::disconnect()
482 channels_t::vector_type toupdate(channels.
lock_vector());
484 FOREACH(channels_t::vector_type::const_iterator, it, end, toupdate)
488 chan->state = TestPVChannel::DISCONNECTED;
490 pva::ChannelRequester::shared_pointer req(chan->requester.lock());
493 req->channelStateChange(*it, TestPVChannel::DISCONNECTED);
498 static size_t countTestProvider;
500 TestProvider::TestProvider()
502 epicsAtomicIncrSizeT(&countTestProvider);
505 TestProvider::~TestProvider()
507 epicsAtomicDecrSizeT(&countTestProvider);
510 void TestProvider::destroy()
515 pva::ChannelFind::shared_pointer
516 TestProvider::channelList(pva::ChannelListRequester::shared_pointer
const & requester)
518 pva::ChannelFind::shared_pointer ret;
519 pvd::PVStringArray::const_svector names;
520 requester->channelListResult(pvd::Status(pvd::Status::STATUSTYPE_FATAL,
"Not implemented"),
527 pva::ChannelFind::shared_pointer
528 TestProvider::channelFind(std::string
const & channelName,
529 pva::ChannelFindRequester::shared_pointer
const & requester)
531 pva::ChannelFind::shared_pointer ret;
532 requester->channelFindResult(pvd::Status(pvd::Status::STATUSTYPE_FATAL,
"Not implemented"),
537 pva::Channel::shared_pointer
538 TestProvider::createChannel(std::string
const & channelName,pva::ChannelRequester::shared_pointer
const & requester,
541 return createChannel(channelName, requester, priority,
"<unused>");
544 pva::Channel::shared_pointer
545 TestProvider::createChannel(std::string
const & channelName,
546 pva::ChannelRequester::shared_pointer
const & requester,
547 short priority, std::string
const & address)
549 pva::Channel::shared_pointer ret;
554 TestPV::shared_pointer pv(pvs.
find(channelName));
556 TestPVChannel::shared_pointer chan(
new TestPVChannel(pv, requester));
557 pv->channels.insert(chan);
558 chan->weakself = chan;
564 requester->channelCreated(pvd::Status(), ret);
566 requester->channelCreated(pvd::Status(pvd::Status::STATUSTYPE_ERROR,
"PV not found"), ret);
568 testDiag(
"createChannel %s %p", channelName.c_str(), ret.get());
572 TestPV::shared_pointer
573 TestProvider::addPV(
const std::string& name,
const pvd::StructureConstPtr& tdef)
576 TestPV::shared_pointer ret(
new TestPV(name, shared_from_this(), tdef));
581 void TestProvider::dispatch()
584 testDiag(
"TestProvider::dispatch");
587 FOREACH(pvs_t::lock_vector_type::const_iterator, pvit, pvend, allpvs)
589 TestPV *pv = pvit->second.get();
590 TestPV::channels_t::vector_type channels(pv->channels.
lock_vector());
592 FOREACH(TestPV::channels_t::vector_type::const_iterator, chit, chend, channels)
595 TestPVChannel::monitors_t::vector_type monitors(chan->monitors.
lock_vector());
597 if(!chan->isConnected())
600 FOREACH(TestPVChannel::monitors_t::vector_type::const_iterator, monit, monend, monitors)
604 if(mon->finalize || !mon->running)
607 if(mon->needWakeup) {
608 testDiag(
" wakeup monitor %p", mon);
609 mon->needWakeup =
false;
610 pva::MonitorRequester::shared_pointer req(mon->requester.lock());
613 req->monitorEvent(*monit);
620 void TestProvider::testCounts()
624 #define TESTC(name) temp=epicsAtomicGetSizeT(&count##name); ok &= temp==0; testDiag("num. live " #name " %u", (unsigned)temp)
632 testOk(ok,
"All instances free'd");
lock_vector_type lock_vector() const
value_pointer find(const K &k) const
vector_type lock_vector() const
value_pointer insert(const K &k, value_pointer &v)
void insert(value_pointer &)