This commit is contained in:
Michael Davidsaver
2016-03-17 17:00:43 -04:00
parent 3749d98c45
commit 302d2ec0a3
7 changed files with 92 additions and 52 deletions

View File

@@ -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--;
}

View File

@@ -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);

View File

@@ -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

View File

@@ -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")

View File

@@ -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);

View File

@@ -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")

View File

@@ -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 {