more
This commit is contained in:
@@ -45,7 +45,7 @@ void pdb_group_event(void *user_arg, struct dbChannel *chan,
|
||||
self->members[i].pvif->put(self->scratch, evt->dbe_mask, FL.pfl);
|
||||
}
|
||||
|
||||
if(info.had_initial_VALUE) {
|
||||
if(!info.had_initial_VALUE) {
|
||||
info.had_initial_VALUE = true;
|
||||
self->initial_waits--;
|
||||
}
|
||||
|
||||
@@ -315,19 +315,19 @@ void putMeta(const pvCommon& pv, unsigned dbe, db_field_log *pfl)
|
||||
}
|
||||
if(dbe&DBE_PROPERTY) {
|
||||
#undef FMAP
|
||||
#define FMAP(MNAME, FNAME) if(pv.MNAME) pv.MNAME->put(meta.FNAME)
|
||||
FMAP(displayHigh, upper_disp_limit);
|
||||
FMAP(displayLow, lower_disp_limit);
|
||||
FMAP(controlHigh, upper_ctrl_limit);
|
||||
FMAP(controlLow, lower_ctrl_limit);
|
||||
FMAP(egu, units);
|
||||
#define FMAP(MASK, MNAME, FNAME) if(META::mask&(MASK) && pv.MNAME) pv.MNAME->put(meta.FNAME)
|
||||
FMAP(DBR_GR_DOUBLE|DBR_GR_LONG, displayHigh, upper_disp_limit);
|
||||
FMAP(DBR_GR_DOUBLE|DBR_GR_LONG, displayLow, lower_disp_limit);
|
||||
FMAP(DBR_CTRL_DOUBLE|DBR_CTRL_DOUBLE, controlHigh, upper_ctrl_limit);
|
||||
FMAP(DBR_CTRL_DOUBLE|DBR_CTRL_DOUBLE, controlLow, lower_ctrl_limit);
|
||||
FMAP(DBR_GR_DOUBLE|DBR_GR_LONG, egu, units);
|
||||
#undef FMAP
|
||||
#define FMAP(MNAME, FNAME) if(pv.MNAME) pv.MNAME->putFrom(meta.FNAME)
|
||||
FMAP(prec, precision.dp);
|
||||
FMAP(warnHigh, upper_warning_limit);
|
||||
FMAP(warnLow, lower_warning_limit);
|
||||
FMAP(alarmHigh, upper_alarm_limit);
|
||||
FMAP(alarmLow, lower_alarm_limit);
|
||||
#define FMAP(MASK, MNAME, FNAME) if(META::mask&(MASK) && pv.MNAME) pv.MNAME->putFrom(meta.FNAME)
|
||||
FMAP(DBR_GR_DOUBLE, prec, precision.dp);
|
||||
FMAP(DBR_AL_DOUBLE|DBR_AL_DOUBLE, warnHigh, upper_warning_limit);
|
||||
FMAP(DBR_AL_DOUBLE|DBR_AL_DOUBLE, warnLow, lower_warning_limit);
|
||||
FMAP(DBR_AL_DOUBLE|DBR_AL_DOUBLE, alarmHigh, upper_alarm_limit);
|
||||
FMAP(DBR_AL_DOUBLE|DBR_AL_DOUBLE, alarmLow, lower_alarm_limit);
|
||||
#undef FMAP
|
||||
if(pv.enumopts) {
|
||||
pvd::shared_vector<std::string> strs(meta.no_str);
|
||||
|
||||
@@ -16,22 +16,6 @@ namespace pva = epics::pvAccess;
|
||||
|
||||
namespace {
|
||||
|
||||
template<typename PVD>
|
||||
void testFieldEqual(const pvd::PVStructurePtr& val, const char *name, typename PVD::value_type expect)
|
||||
{
|
||||
if(!val) {
|
||||
testFail("empty structure");
|
||||
return;
|
||||
}
|
||||
typename PVD::shared_pointer fval(val->getSubField<PVD>(name));
|
||||
if(!fval) {
|
||||
testFail("field '%s' with type %s does not exist", name, typeid(PVD).name());
|
||||
} else {
|
||||
typename PVD::value_type actual(fval->get());
|
||||
testEqualx(name, "expect", actual, expect);
|
||||
}
|
||||
}
|
||||
|
||||
pvd::PVStructurePtr makeRequest(bool atomic)
|
||||
{ pvd::StructureConstPtr def(pvd::getFieldCreate()->createFieldBuilder()
|
||||
->addNestedStructure("record")
|
||||
@@ -351,7 +335,25 @@ void testGroupMonitor(const PDBProvider::shared_pointer& prov)
|
||||
|
||||
testDiag("subscribe to grp1");
|
||||
PVMonitor mon(prov, "grp1");
|
||||
mon.mon->start();
|
||||
PVMonitor::Element e(mon);
|
||||
|
||||
testOk1(mon.mon->start().isOK());
|
||||
|
||||
testDiag("Wait for initial event");
|
||||
testOk1(mon.monreq->waitForEvent());
|
||||
testDiag("Initial event");
|
||||
|
||||
e = mon.poll();
|
||||
testOk1(!!e);
|
||||
|
||||
testFieldEqual<pvd::PVDouble>(e, "fld1.value", 3.0);
|
||||
testFieldEqual<pvd::PVInt>(e, "fld2.value", 30);
|
||||
testFieldEqual<pvd::PVDouble>(e, "fld3.value", 4.0);
|
||||
testFieldEqual<pvd::PVInt>(e, "fld4.value", 40);
|
||||
testFieldEqual<pvd::PVDouble>(e, "fld1.display.limitHigh", 200.0);
|
||||
testFieldEqual<pvd::PVDouble>(e, "fld1.display.limitLow", -200.0);
|
||||
testFieldEqual<pvd::PVDouble>(e, "fld2.display.limitHigh", 2147483647.0);
|
||||
testFieldEqual<pvd::PVDouble>(e, "fld2.display.limitLow", -2147483648.0);
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
@@ -12,6 +12,8 @@ record(ai, "rec3") {
|
||||
field(VAL, "3.0")
|
||||
field(RVAL, "30")
|
||||
info(pdbGroup, "grp1|fld1=VAL|fld2=RVAL")
|
||||
field(HOPR, "200")
|
||||
field(LOPR, "-200")
|
||||
}
|
||||
record(ai, "rec4") {
|
||||
field(VAL, "4.0")
|
||||
|
||||
@@ -37,18 +37,26 @@ void testScalar()
|
||||
|
||||
DBCH chan_li("test:li");
|
||||
DBCH chan_ai("test:ai");
|
||||
DBCH chan_ai_rval("test:ai.RVAL");
|
||||
DBCH chan_mbbi("test:mbbi");
|
||||
testOk1(dbChannelFieldType(chan_li)==DBR_LONG);
|
||||
testOk1(dbChannelFieldType(chan_ai)==DBR_DOUBLE);
|
||||
testOk1(dbChannelFieldType(chan_mbbi)==DBR_ENUM);
|
||||
testEqual(dbChannelFieldType(chan_li), DBR_LONG);
|
||||
testEqual(dbChannelFieldType(chan_ai), DBR_DOUBLE);
|
||||
testEqual(dbChannelFieldType(chan_ai_rval), DBR_LONG);
|
||||
testEqual(dbChannelFieldType(chan_mbbi), DBR_ENUM);
|
||||
testEqual(dbChannelFinalFieldType(chan_li), DBR_LONG);
|
||||
testEqual(dbChannelFinalFieldType(chan_ai), DBR_DOUBLE);
|
||||
testEqual(dbChannelFinalFieldType(chan_ai_rval), DBR_LONG);
|
||||
testEqual(dbChannelFinalFieldType(chan_mbbi), DBR_ENUM);
|
||||
|
||||
pvd::StructureConstPtr dtype_li(PVIF::dtype(chan_li));
|
||||
pvd::StructureConstPtr dtype_ai(PVIF::dtype(chan_ai));
|
||||
pvd::StructureConstPtr dtype_ai_rval(PVIF::dtype(chan_ai_rval));
|
||||
pvd::StructureConstPtr dtype_mbbi(PVIF::dtype(chan_mbbi));
|
||||
|
||||
pvd::StructureConstPtr dtype_root(pvd::getFieldCreate()->createFieldBuilder()
|
||||
->add("li", dtype_li)
|
||||
->add("ai", dtype_ai)
|
||||
->add("ai_rval", dtype_ai_rval)
|
||||
->add("mbbi", dtype_mbbi)
|
||||
->createStructure());
|
||||
|
||||
@@ -56,6 +64,7 @@ void testScalar()
|
||||
|
||||
std::auto_ptr<PVIF> pvif_li(PVIF::attach(chan_li, root->getSubField<pvd::PVStructure>("li")));
|
||||
std::auto_ptr<PVIF> pvif_ai(PVIF::attach(chan_ai, root->getSubField<pvd::PVStructure>("ai")));
|
||||
std::auto_ptr<PVIF> pvif_ai_rval(PVIF::attach(chan_ai_rval, root->getSubField<pvd::PVStructure>("ai_rval")));
|
||||
std::auto_ptr<PVIF> pvif_mbbi(PVIF::attach(chan_mbbi, root->getSubField<pvd::PVStructure>("mbbi")));
|
||||
|
||||
pvd::BitSet mask;
|
||||
@@ -70,6 +79,7 @@ void testScalar()
|
||||
prec_ai->time.secPastEpoch = 0x12345678;
|
||||
prec_ai->time.nsec = 12345678;
|
||||
pvif_ai->put(mask, DBE_VALUE|DBE_ALARM|DBE_PROPERTY, NULL);
|
||||
pvif_ai_rval->put(mask, DBE_VALUE|DBE_ALARM|DBE_PROPERTY, NULL);
|
||||
dbScanUnlock((dbCommon*)prec_ai);
|
||||
|
||||
dbScanLock((dbCommon*)prec_mbbi);
|
||||
@@ -78,27 +88,36 @@ void testScalar()
|
||||
pvif_mbbi->put(mask, DBE_VALUE|DBE_ALARM|DBE_PROPERTY, NULL);
|
||||
dbScanUnlock((dbCommon*)prec_mbbi);
|
||||
|
||||
testOk1(root->getSubFieldT<pvd::PVInt>("li.value")->get()==102042);
|
||||
testOk1(root->getSubFieldT<pvd::PVInt>("li.alarm.severity")->get()==1);
|
||||
testOk1(root->getSubFieldT<pvd::PVLong>("li.timeStamp.secondsPastEpoch")->get()==0x12345678);
|
||||
testOk1(root->getSubFieldT<pvd::PVInt>("li.timeStamp.nanoseconds")->get()==12345678);
|
||||
testOk1(root->getSubFieldT<pvd::PVDouble>("li.display.limitHigh")->get()==100.0);
|
||||
testOk1(root->getSubFieldT<pvd::PVDouble>("li.display.limitLow")->get()==10.0);
|
||||
testOk1(root->getSubFieldT<pvd::PVString>("li.display.units")->get()=="arb");
|
||||
testFieldEqual<pvd::PVInt>(root, "li.value", 102042);
|
||||
testFieldEqual<pvd::PVInt>(root, "li.alarm.severity", 1);
|
||||
testFieldEqual<pvd::PVLong>(root, "li.timeStamp.secondsPastEpoch", 0x12345678);
|
||||
testFieldEqual<pvd::PVInt>(root, "li.timeStamp.nanoseconds", 12345678);
|
||||
testFieldEqual<pvd::PVDouble>(root, "li.display.limitHigh", 100.0);
|
||||
testFieldEqual<pvd::PVDouble>(root, "li.display.limitLow", 10.0);
|
||||
testFieldEqual<pvd::PVString>(root, "li.display.units", "arb");
|
||||
|
||||
testOk1(root->getSubFieldT<pvd::PVDouble>("ai.value")->get()==42.2);
|
||||
testOk1(root->getSubFieldT<pvd::PVInt>("ai.alarm.severity")->get()==2);
|
||||
testOk1(root->getSubFieldT<pvd::PVLong>("ai.timeStamp.secondsPastEpoch")->get()==0x12345678);
|
||||
testOk1(root->getSubFieldT<pvd::PVInt>("ai.timeStamp.nanoseconds")->get()==12345678);
|
||||
testOk1(root->getSubFieldT<pvd::PVDouble>("ai.display.limitHigh")->get()==200.0);
|
||||
testOk1(root->getSubFieldT<pvd::PVDouble>("ai.display.limitLow")->get()==20.0);
|
||||
testOk1(root->getSubFieldT<pvd::PVString>("ai.display.format")->get()=="2");
|
||||
testOk1(root->getSubFieldT<pvd::PVString>("ai.display.units")->get()=="foo");
|
||||
testFieldEqual<pvd::PVDouble>(root, "ai.value", 42.2);
|
||||
testFieldEqual<pvd::PVInt>(root, "ai.alarm.severity", 2);
|
||||
testFieldEqual<pvd::PVLong>(root, "ai.timeStamp.secondsPastEpoch", 0x12345678);
|
||||
testFieldEqual<pvd::PVInt>(root, "ai.timeStamp.nanoseconds", 12345678);
|
||||
testFieldEqual<pvd::PVDouble>(root, "ai.display.limitHigh", 200.0);
|
||||
testFieldEqual<pvd::PVDouble>(root, "ai.display.limitLow", 20.0);
|
||||
testFieldEqual<pvd::PVString>(root, "ai.display.format", "2");
|
||||
testFieldEqual<pvd::PVString>(root, "ai.display.units", "foo");
|
||||
|
||||
testOk1(root->getSubFieldT<pvd::PVInt>("mbbi.value.index")->get()==1);
|
||||
testOk1(root->getSubFieldT<pvd::PVInt>("mbbi.alarm.severity")->get()==0);
|
||||
testOk1(root->getSubFieldT<pvd::PVLong>("mbbi.timeStamp.secondsPastEpoch")->get()==0x12345678);
|
||||
testOk1(root->getSubFieldT<pvd::PVInt>("mbbi.timeStamp.nanoseconds")->get()==12345678);
|
||||
testFieldEqual<pvd::PVInt>(root, "ai_rval.value", 1234);
|
||||
testFieldEqual<pvd::PVInt>(root, "ai_rval.alarm.severity", 2);
|
||||
testFieldEqual<pvd::PVLong>(root, "ai_rval.timeStamp.secondsPastEpoch", 0x12345678);
|
||||
testFieldEqual<pvd::PVInt>(root, "ai_rval.timeStamp.nanoseconds", 12345678);
|
||||
testFieldEqual<pvd::PVDouble>(root, "ai_rval.display.limitHigh", 2147483647.0);
|
||||
testFieldEqual<pvd::PVDouble>(root, "ai_rval.display.limitLow", -2147483648.0);
|
||||
testFieldEqual<pvd::PVString>(root, "ai_rval.display.format", "");
|
||||
testFieldEqual<pvd::PVString>(root, "ai_rval.display.units", "");
|
||||
|
||||
testFieldEqual<pvd::PVInt>(root, "mbbi.value.index", 1);
|
||||
testFieldEqual<pvd::PVInt>(root, "mbbi.alarm.severity", 0);
|
||||
testFieldEqual<pvd::PVLong>(root, "mbbi.timeStamp.secondsPastEpoch", 0x12345678);
|
||||
testFieldEqual<pvd::PVInt>(root, "mbbi.timeStamp.nanoseconds", 12345678);
|
||||
{
|
||||
pvd::PVStringArray::const_svector choices(root->getSubFieldT<pvd::PVStringArray>("mbbi.value.choices")->view());
|
||||
testOk1(choices.size()==3);
|
||||
|
||||
@@ -8,6 +8,7 @@ record(longin, "test:li") {
|
||||
}
|
||||
record(ai, "test:ai") {
|
||||
field(VAL, "42.2")
|
||||
field(RVAL, "1234")
|
||||
field(SEVR, "2")
|
||||
field(STAT, "0")
|
||||
field(EGU, "foo")
|
||||
|
||||
@@ -60,6 +60,22 @@ void testEqualx(const char *nLHS, const char *nRHS, LHS l, RHS r)
|
||||
}
|
||||
#define testEqual(LHS, RHS) testEqualx(#LHS, #RHS, LHS, RHS)
|
||||
|
||||
template<typename PVD>
|
||||
void testFieldEqual(const epics::pvData::PVStructurePtr& val, const char *name, typename PVD::value_type expect)
|
||||
{
|
||||
if(!val) {
|
||||
testFail("empty structure");
|
||||
return;
|
||||
}
|
||||
typename PVD::shared_pointer fval(val->getSubField<PVD>(name));
|
||||
if(!fval) {
|
||||
testFail("field '%s' with type %s does not exist", name, typeid(PVD).name());
|
||||
} else {
|
||||
typename PVD::value_type actual(fval->get());
|
||||
testEqualx(name, "expect", actual, expect);
|
||||
}
|
||||
}
|
||||
|
||||
// Boilerplate reduction for accessing a scalar field
|
||||
template<typename T>
|
||||
struct ScalarAccessor {
|
||||
|
||||
Reference in New Issue
Block a user