Merge 3.16 (after 3.16.2-rc1) into 7.0
This commit is contained in:
@@ -63,6 +63,8 @@ testHarness_SRCS += epicsRunFilterTests.c
|
||||
filterTestHarness_SRCS += $(testHarness_SRCS)
|
||||
filterTestHarness_SRCS_RTEMS += rtemsTestHarness.c
|
||||
|
||||
PROD_SRCS_RTEMS += rtemsTestData.c
|
||||
|
||||
PROD_vxWorks = filterTestHarness
|
||||
PROD_RTEMS = filterTestHarness
|
||||
|
||||
@@ -70,6 +72,10 @@ TESTSPEC_vxWorks = filterTestHarness.munch; epicsRunFilterTests
|
||||
TESTSPEC_RTEMS = filterTestHarness.boot; epicsRunFilterTests
|
||||
|
||||
TESTSCRIPTS_HOST += $(TESTS:%=%.t)
|
||||
ifneq ($(filter $(T_A),$(CROSS_COMPILER_RUNTEST_ARCHS)),)
|
||||
TESTPROD_RTEMS = $(TESTPROD_HOST)
|
||||
TESTSCRIPTS_RTEMS += $(TESTS:%=%.t)
|
||||
endif
|
||||
|
||||
include $(TOP)/configure/RULES
|
||||
|
||||
@@ -79,3 +85,6 @@ dbndTest$(DEP): $(COMMON_DIR)/xRecord.h
|
||||
syncTest$(DEP): $(COMMON_DIR)/xRecord.h
|
||||
arrRecord$(DEP): $(COMMON_DIR)/arrRecord.h
|
||||
arrTest$(DEP): $(COMMON_DIR)/arrRecord.h
|
||||
|
||||
rtemsTestData.c : $(TESTFILES) $(TOOLS)/epicsMakeMemFs.pl
|
||||
$(PERL) $(TOOLS)/epicsMakeMemFs.pl $@ epicsRtemsFSImage $(TESTFILES)
|
||||
|
||||
@@ -0,0 +1,60 @@
|
||||
#*************************************************************************
|
||||
# Copyright (c) 2018 UChicago Argonne LLC, as Operator of Argonne
|
||||
# National Laboratory.
|
||||
# EPICS BASE is distributed subject to a Software License Agreement found
|
||||
# in the file LICENSE that is included with this distribution.
|
||||
#*************************************************************************
|
||||
TOP=../../..
|
||||
|
||||
include $(TOP)/configure/CONFIG
|
||||
|
||||
TESTLIBRARY = Recs
|
||||
|
||||
Recs_SRCS += ioRecord.c
|
||||
Recs_LIBS += dbCore ca Com
|
||||
|
||||
PROD_LIBS = Recs dbRecStd dbCore ca Com
|
||||
|
||||
DBDDEPENDS_FILES += linkTest.dbd$(DEP)
|
||||
TARGETS += $(COMMON_DIR)/linkTest.dbd
|
||||
linkTest_DBD += menuGlobal.dbd
|
||||
linkTest_DBD += menuConvert.dbd
|
||||
linkTest_DBD += menuScan.dbd
|
||||
linkTest_DBD += links.dbd
|
||||
linkTest_DBD += ioRecord.dbd
|
||||
TESTFILES += $(COMMON_DIR)/linkTest.dbd
|
||||
TESTFILES += ../ioRecord.db
|
||||
|
||||
testHarness_SRCS += linkTest_registerRecordDeviceDriver.cpp
|
||||
|
||||
TESTPROD_HOST += lnkStateTest
|
||||
lnkStateTest_SRCS += lnkStateTest.c
|
||||
lnkStateTest_SRCS += linkTest_registerRecordDeviceDriver.cpp
|
||||
testHarness_SRCS += lnkStateTest.c
|
||||
TESTS += lnkStateTest
|
||||
|
||||
TESTPROD_HOST += lnkCalcTest
|
||||
lnkCalcTest_SRCS += lnkCalcTest.c
|
||||
lnkCalcTest_SRCS += linkTest_registerRecordDeviceDriver.cpp
|
||||
testHarness_SRCS += lnkCalcTest.c
|
||||
TESTS += lnkCalcTest
|
||||
|
||||
# epicsRunLinkTests runs all the test programs in a known working order.
|
||||
testHarness_SRCS += epicsRunLinkTests.c
|
||||
|
||||
linkTestHarness_SRCS += $(testHarness_SRCS)
|
||||
linkTestHarness_SRCS_RTEMS += rtemsTestHarness.c
|
||||
|
||||
PROD_vxWorks = linkTestHarness
|
||||
PROD_RTEMS = linkTestHarness
|
||||
|
||||
TESTSPEC_vxWorks = linkTestHarness.munch; epicsRunLinkTests
|
||||
TESTSPEC_RTEMS = linkTestHarness.boot; epicsRunLinkTests
|
||||
|
||||
TESTSCRIPTS_HOST += $(TESTS:%=%.t)
|
||||
|
||||
include $(TOP)/configure/RULES
|
||||
|
||||
ioRecord$(DEP): $(COMMON_DIR)/ioRecord.h
|
||||
lnkStateTest$(DEP): $(COMMON_DIR)/ioRecord.h
|
||||
lnkCalcTest$(DEP): $(COMMON_DIR)/ioRecord.h
|
||||
@@ -0,0 +1,29 @@
|
||||
/*************************************************************************\
|
||||
* Copyright (c) 2018 UChicago Argonne LLC, as Operator of Argonne
|
||||
* National Laboratory.
|
||||
* EPICS BASE is distributed subject to a Software License Agreement found
|
||||
* in the file LICENSE that is included with this distribution.
|
||||
\*************************************************************************/
|
||||
|
||||
/*
|
||||
* Run filter tests as a batch.
|
||||
*/
|
||||
|
||||
#include "epicsUnitTest.h"
|
||||
#include "epicsExit.h"
|
||||
#include "dbmf.h"
|
||||
|
||||
int lnkStateTest(void);
|
||||
int lnkCalcTest(void);
|
||||
|
||||
void epicsRunLinkTests(void)
|
||||
{
|
||||
testHarness();
|
||||
|
||||
runTest(lnkStateTest);
|
||||
runTest(lnkCalcTest);
|
||||
|
||||
dbmfFreeChunks();
|
||||
|
||||
epicsExit(0); /* Trigger test harness */
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
/*************************************************************************\
|
||||
* Copyright (c) 2018 UChicago Argonne LLC, as Operator of Argonne
|
||||
* National Laboratory.
|
||||
* EPICS BASE is distributed subject to a Software License Agreement found
|
||||
* in the file LICENSE that is included with this distribution.
|
||||
\*************************************************************************/
|
||||
|
||||
/*
|
||||
* Author: Andrew Johnson <anj@aps.anl.gov>
|
||||
*/
|
||||
|
||||
#include <dbAccessDefs.h>
|
||||
#include <recSup.h>
|
||||
|
||||
#define GEN_SIZE_OFFSET
|
||||
#include "ioRecord.h"
|
||||
#undef GEN_SIZE_OFFSET
|
||||
|
||||
#include <epicsExport.h>
|
||||
|
||||
static rset ioRSET;
|
||||
epicsExportAddress(rset,ioRSET);
|
||||
@@ -0,0 +1 @@
|
||||
record(io, io) {}
|
||||
@@ -0,0 +1,14 @@
|
||||
# This is a soft record type with both input and output links
|
||||
|
||||
recordtype(io) {
|
||||
include "dbCommon.dbd"
|
||||
field(VAL, DBF_LONG) {
|
||||
prompt("Value")
|
||||
}
|
||||
field(INPUT, DBF_INLINK) {
|
||||
prompt("Input Link")
|
||||
}
|
||||
field(OUTPUT, DBF_OUTLINK) {
|
||||
prompt("Output Link")
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,164 @@
|
||||
/*************************************************************************\
|
||||
* Copyright (c) 2018 Andrew Johnson
|
||||
* EPICS BASE is distributed subject to a Software License Agreement found
|
||||
* in the file LICENSE that is included with this distribution.
|
||||
\*************************************************************************/
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#include "dbAccess.h"
|
||||
#include "alarm.h"
|
||||
#include "dbUnitTest.h"
|
||||
#include "errlog.h"
|
||||
#include "epicsThread.h"
|
||||
#include "dbLink.h"
|
||||
#include "dbState.h"
|
||||
#include "recGbl.h"
|
||||
#include "testMain.h"
|
||||
#include "ioRecord.h"
|
||||
|
||||
#define testPutLongStr(PV, VAL) \
|
||||
testdbPutArrFieldOk(PV, DBF_CHAR, sizeof(VAL), VAL);
|
||||
|
||||
void linkTest_registerRecordDeviceDriver(struct dbBase *);
|
||||
|
||||
static void startTestIoc(const char *dbfile)
|
||||
{
|
||||
testdbPrepare();
|
||||
testdbReadDatabase("linkTest.dbd", NULL, NULL);
|
||||
linkTest_registerRecordDeviceDriver(pdbbase);
|
||||
testdbReadDatabase(dbfile, NULL, NULL);
|
||||
|
||||
eltc(0);
|
||||
testIocInitOk();
|
||||
eltc(1);
|
||||
}
|
||||
|
||||
static void testCalc()
|
||||
{
|
||||
ioRecord *pio;
|
||||
DBLINK *pinp, *pout;
|
||||
long status;
|
||||
epicsFloat64 f64;
|
||||
|
||||
startTestIoc("ioRecord.db");
|
||||
|
||||
pio = (ioRecord *) testdbRecordPtr("io");
|
||||
pinp = &pio->input;
|
||||
pout = &pio->output;
|
||||
|
||||
testDiag("testing lnkCalc input");
|
||||
|
||||
{
|
||||
dbStateId red;
|
||||
|
||||
testPutLongStr("io.INPUT", "{\"calc\":{"
|
||||
"\"expr\":\"a\","
|
||||
"\"args\":[{\"state\":\"red\"}]"
|
||||
"}}");
|
||||
if (testOk1(pinp->type == JSON_LINK))
|
||||
testDiag("Link was set to '%s'", pinp->value.json.string);
|
||||
red = dbStateFind("red");
|
||||
testOk(!!red, "State red was created");
|
||||
|
||||
dbStateSet(red);
|
||||
status = dbGetLink(pinp, DBF_DOUBLE, &f64, NULL, NULL);
|
||||
testOk(!status, "dbGetLink succeeded (status = %ld)", status);
|
||||
testOk(f64, "Got TRUE (%g)", f64);
|
||||
|
||||
dbStateClear(red);
|
||||
status = dbGetLink(pinp, DBF_DOUBLE, &f64, NULL, NULL);
|
||||
testOk(!status, "dbGetLink succeeded (status = %ld)", status);
|
||||
testOk(!f64, "Got FALSE (%g)", f64);
|
||||
}
|
||||
|
||||
{
|
||||
dbStateId major = dbStateCreate("major");
|
||||
dbStateId minor = dbStateCreate("minor");
|
||||
epicsEnum16 stat, sevr;
|
||||
|
||||
testPutLongStr("io.INPUT", "{\"calc\":{"
|
||||
"\"expr\":\"0\","
|
||||
"\"major\":\"A\","
|
||||
"\"minor\":\"B\","
|
||||
"\"args\":[{\"state\":\"major\"},{\"state\":\"minor\"}]"
|
||||
"}}");
|
||||
if (testOk1(pinp->type == JSON_LINK))
|
||||
testDiag("Link was set to '%s'", pinp->value.json.string);
|
||||
|
||||
dbStateSet(major);
|
||||
dbStateSet(minor);
|
||||
status = dbGetLink(pinp, DBF_DOUBLE, &f64, NULL, NULL);
|
||||
testOk(!status, "dbGetLink succeeded (status = %ld)", status);
|
||||
testOk(f64 == 0.0, "Got zero (%g)", f64);
|
||||
testOk(recGblResetAlarms(pio) & DBE_ALARM, "Record alarm was raised");
|
||||
status = dbGetAlarm(pinp, &stat, &sevr);
|
||||
testOk(!status, "dbGetAlarm succeeded (status = %ld)", status);
|
||||
testOk(stat == LINK_ALARM, "Alarm status = LINK (%d)", stat);
|
||||
testOk(sevr == MAJOR_ALARM, "Alarm severity = MAJOR (%d)", sevr);
|
||||
|
||||
dbStateClear(major);
|
||||
status = dbGetLink(pinp, DBF_DOUBLE, &f64, NULL, NULL);
|
||||
testOk(!status, "dbGetLink succeeded (status = %ld)", status);
|
||||
testOk(recGblResetAlarms(pio) & DBE_ALARM, "Record alarm was raised");
|
||||
status = dbGetAlarm(pinp, &stat, &sevr);
|
||||
testOk(!status, "dbGetAlarm succeeded (status = %ld)", status);
|
||||
testOk(stat == LINK_ALARM, "Alarm status = LINK (%d)", stat);
|
||||
testOk(sevr == MINOR_ALARM, "Alarm severity = MINOR (%d)", sevr);
|
||||
}
|
||||
|
||||
testDiag("testing lnkCalc output");
|
||||
|
||||
{
|
||||
dbStateId red = dbStateFind("red");
|
||||
dbStateId out = dbStateCreate("out");
|
||||
|
||||
testPutLongStr("io.OUTPUT", "{\"calc\":{"
|
||||
"\"expr\":\"!a\","
|
||||
"\"out\":{\"state\":\"out\"},"
|
||||
"\"args\":[{\"state\":\"red\"}],"
|
||||
"\"units\":\"things\","
|
||||
"\"prec\":3"
|
||||
"}}");
|
||||
if (testOk1(pout->type == JSON_LINK))
|
||||
testDiag("Link was set to '%s'", pout->value.json.string);
|
||||
|
||||
dbStateSet(red);
|
||||
f64 = 1.0;
|
||||
status = dbPutLink(pout, DBF_DOUBLE, &f64, 1);
|
||||
testOk(!status, "dbPutLink succeeded (status = %ld)", status);
|
||||
testOk(!dbStateGet(out), "output was cleared");
|
||||
|
||||
dbStateClear(red);
|
||||
status = dbPutLink(pout, DBF_DOUBLE, &f64, 1);
|
||||
testOk(!status, "dbGetLink succeeded (status = %ld)", status);
|
||||
testOk(dbStateGet(out), "output was set");
|
||||
}
|
||||
|
||||
{
|
||||
char units[20] = {0};
|
||||
short prec = 0;
|
||||
|
||||
status = dbGetUnits(pout, units, sizeof(units));
|
||||
testOk(!status, "dbGetUnits succeeded (status = %ld)", status);
|
||||
testOk(!strcmp(units, "things"), "Units string correct (%s)", units);
|
||||
|
||||
status = dbGetPrecision(pout, &prec);
|
||||
testOk(!status, "dbGetPrecision succeeded (status = %ld)", status);
|
||||
testOk(prec == 3, "Precision correct (%d)", prec);
|
||||
}
|
||||
|
||||
testIocShutdownOk();
|
||||
|
||||
testdbCleanup();
|
||||
}
|
||||
|
||||
|
||||
MAIN(lnkCalcTest)
|
||||
{
|
||||
testPlan(0);
|
||||
|
||||
testCalc();
|
||||
|
||||
return testDone();
|
||||
}
|
||||
@@ -0,0 +1,130 @@
|
||||
/*************************************************************************\
|
||||
* Copyright (c) 2018 Andrew Johnson
|
||||
* EPICS BASE is distributed subject to a Software License Agreement found
|
||||
* in the file LICENSE that is included with this distribution.
|
||||
\*************************************************************************/
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#include "dbAccess.h"
|
||||
#include "alarm.h"
|
||||
#include "dbUnitTest.h"
|
||||
#include "errlog.h"
|
||||
#include "epicsThread.h"
|
||||
#include "dbLink.h"
|
||||
#include "dbState.h"
|
||||
#include "ioRecord.h"
|
||||
|
||||
#include "testMain.h"
|
||||
|
||||
void linkTest_registerRecordDeviceDriver(struct dbBase *);
|
||||
|
||||
static void startTestIoc(const char *dbfile)
|
||||
{
|
||||
testdbPrepare();
|
||||
testdbReadDatabase("linkTest.dbd", NULL, NULL);
|
||||
linkTest_registerRecordDeviceDriver(pdbbase);
|
||||
testdbReadDatabase(dbfile, NULL, NULL);
|
||||
|
||||
eltc(0);
|
||||
testIocInitOk();
|
||||
eltc(1);
|
||||
}
|
||||
|
||||
static void testState()
|
||||
{
|
||||
dbStateId red;
|
||||
ioRecord *pio;
|
||||
DBLINK *pinp, *pout;
|
||||
long status;
|
||||
|
||||
testDiag("testing lnkState");
|
||||
|
||||
startTestIoc("ioRecord.db");
|
||||
|
||||
pio = (ioRecord *) testdbRecordPtr("io");
|
||||
pinp = &pio->input;
|
||||
pout = &pio->output;
|
||||
|
||||
red = dbStateFind("red");
|
||||
testOk(!red, "No state red exists");
|
||||
|
||||
testdbPutFieldOk("io.INPUT", DBF_STRING, "{\"state\":\"red\"}");
|
||||
if (testOk1(pinp->type == JSON_LINK))
|
||||
testDiag("Link was set to '%s'", pinp->value.json.string);
|
||||
red = dbStateFind("red");
|
||||
testOk(!!red, "state red exists");
|
||||
|
||||
{
|
||||
epicsInt16 i16;
|
||||
|
||||
dbStateSet(red);
|
||||
status = dbGetLink(pinp, DBF_SHORT, &i16, NULL, NULL);
|
||||
testOk(!status, "dbGetLink succeeded (status = %ld)", status);
|
||||
testOk(i16, "Got TRUE");
|
||||
|
||||
testdbPutFieldOk("io.INPUT", DBF_STRING, "{\"state\":\"!red\"}");
|
||||
if (testOk1(pinp->type == JSON_LINK))
|
||||
testDiag("Link was set to '%s'", pinp->value.json.string);
|
||||
|
||||
status = dbGetLink(pinp, DBF_SHORT, &i16, NULL, NULL);
|
||||
testOk(!status, "dbGetLink succeeded (status = %ld)", status);
|
||||
testOk(!i16, "Got FALSE");
|
||||
|
||||
testdbPutFieldOk("io.OUTPUT", DBF_STRING, "{\"state\":\"red\"}");
|
||||
if (testOk1(pout->type == JSON_LINK))
|
||||
testDiag("Link was set to '%s'", pout->value.json.string);
|
||||
|
||||
i16 = 0;
|
||||
status = dbPutLink(pout, DBF_SHORT, &i16, 1);
|
||||
testOk(!status, "dbPutLink %d succeeded (status = %ld)", i16, status);
|
||||
testOk(!dbStateGet(red), "state was cleared");
|
||||
|
||||
i16 = 0x8000;
|
||||
status = dbPutLink(pout, DBF_SHORT, &i16, 1);
|
||||
testOk(!status, "dbPutLink 0x%hx succeeded (status = %ld)", i16, status);
|
||||
testOk(dbStateGet(red), "state was set");
|
||||
}
|
||||
|
||||
status = dbPutLink(pout, DBF_STRING, "", 1);
|
||||
testOk(!status, "dbPutLink '' succeeded (status = %ld)", status);
|
||||
testOk(!dbStateGet(red), "state was cleared");
|
||||
|
||||
status = dbPutLink(pout, DBF_STRING, "FALSE", 1); /* Not really... */
|
||||
testOk(!status, "dbPutLink 'FALSE' succeeded (status = %ld)", status);
|
||||
testOk(dbStateGet(red), "state was set");
|
||||
|
||||
status = dbPutLink(pout, DBF_STRING, "0", 1);
|
||||
testOk(!status, "dbPutLink '0' succeeded (status = %ld)", status);
|
||||
testOk(!dbStateGet(red), "state was cleared");
|
||||
|
||||
{
|
||||
epicsFloat64 f64 = 0.1;
|
||||
|
||||
status = dbPutLink(pout, DBF_DOUBLE, &f64, 1);
|
||||
testOk(!status, "dbPutLink %g succeeded (status = %ld)", f64, status);
|
||||
testOk(dbStateGet(red), "state was set");
|
||||
|
||||
testdbPutFieldOk("io.OUTPUT", DBF_STRING, "{\"state\":\"!red\"}");
|
||||
if (testOk1(pout->type == JSON_LINK))
|
||||
testDiag("Link was set to '%s'", pout->value.json.string);
|
||||
|
||||
status = dbPutLink(pout, DBF_DOUBLE, &f64, 1);
|
||||
testOk(!status, "dbPutLink %g succeeded (status = %ld)", f64, status);
|
||||
testOk(!dbStateGet(red), "state was cleared");
|
||||
}
|
||||
|
||||
testIocShutdownOk();
|
||||
|
||||
testdbCleanup();
|
||||
}
|
||||
|
||||
|
||||
MAIN(lnkStateTest)
|
||||
{
|
||||
testPlan(28);
|
||||
|
||||
testState();
|
||||
|
||||
return testDone();
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
/*************************************************************************\
|
||||
* Copyright (c) 2018 UChicago Argonne LLC, as Operator of Argonne
|
||||
* National Laboratory.
|
||||
* EPICS BASE is distributed subject to a Software License Agreement found
|
||||
* in the file LICENSE that is included with this distribution.
|
||||
\*************************************************************************/
|
||||
|
||||
extern void epicsRunLinkTests(void);
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
epicsRunLinkTests(); /* calls epicsExit(0) */
|
||||
return 0;
|
||||
}
|
||||
@@ -136,12 +136,23 @@ testHarness_SRCS += mbbioDirectTest.c
|
||||
TESTFILES += ../mbbioDirectTest.db
|
||||
TESTS += mbbioDirectTest
|
||||
|
||||
TARGETS += $(COMMON_DIR)/asyncproctest.dbd
|
||||
DBDDEPENDS_FILES += asyncproctest.dbd$(DEP)
|
||||
asyncproctest_DBD += base.dbd
|
||||
TESTPROD_HOST += asyncproctest
|
||||
asyncproctest_SRCS += asyncproctest.c
|
||||
asyncproctest_SRCS += asyncproctest_registerRecordDeviceDriver.cpp
|
||||
TESTFILES += $(COMMON_DIR)/asyncproctest.dbd ../asyncproctest.db
|
||||
TESTS += asyncproctest
|
||||
|
||||
# epicsRunRecordTests runs all the test programs in a known working order.
|
||||
testHarness_SRCS += epicsRunRecordTests.c
|
||||
|
||||
recordTestHarness_SRCS += $(testHarness_SRCS)
|
||||
recordTestHarness_SRCS_RTEMS += rtemsTestHarness.c
|
||||
|
||||
PROD_SRCS_RTEMS += rtemsTestData.c
|
||||
|
||||
PROD_vxWorks = recordTestHarness
|
||||
PROD_RTEMS = recordTestHarness
|
||||
|
||||
@@ -149,5 +160,12 @@ TESTSPEC_vxWorks = recordTestHarness.munch; epicsRunRecordTests
|
||||
TESTSPEC_RTEMS = recordTestHarness.boot; epicsRunRecordTests
|
||||
|
||||
TESTSCRIPTS_HOST += $(TESTS:%=%.t)
|
||||
ifneq ($(filter $(T_A),$(CROSS_COMPILER_RUNTEST_ARCHS)),)
|
||||
TESTPROD_RTEMS = $(TESTPROD_HOST)
|
||||
TESTSCRIPTS_RTEMS += $(TESTS:%=%.t)
|
||||
endif
|
||||
|
||||
include $(TOP)/configure/RULES
|
||||
|
||||
rtemsTestData.c : $(TESTFILES) $(TOOLS)/epicsMakeMemFs.pl
|
||||
$(PERL) $(TOOLS)/epicsMakeMemFs.pl $@ epicsRtemsFSImage $(TESTFILES)
|
||||
|
||||
@@ -0,0 +1,107 @@
|
||||
/*************************************************************************\
|
||||
* Copyright (c) 2018 Michael Davidsaver
|
||||
* EPICS BASE is distributed subject to a Software License Agreement found
|
||||
* in file LICENSE that is included with this distribution.
|
||||
\*************************************************************************/
|
||||
/* This test covers some situations where asynchronous records are
|
||||
* dbProcess()'d while busy (PACT==1).
|
||||
*/
|
||||
|
||||
#include <testMain.h>
|
||||
#include <dbUnitTest.h>
|
||||
#include <dbCommon.h>
|
||||
#include <dbAccess.h>
|
||||
#include <epicsEvent.h>
|
||||
#include <epicsThread.h>
|
||||
#include <iocsh.h>
|
||||
#include "registryFunction.h"
|
||||
#include <subRecord.h>
|
||||
|
||||
epicsEventId done;
|
||||
static int waitFor;
|
||||
|
||||
static
|
||||
long doneSubr(subRecord *prec)
|
||||
{
|
||||
if (--waitFor <= 0)
|
||||
epicsEventMustTrigger(done);
|
||||
return 0;
|
||||
}
|
||||
|
||||
void asyncproctest_registerRecordDeviceDriver(struct dbBase *);
|
||||
|
||||
MAIN(asyncproctest)
|
||||
{
|
||||
testPlan(21);
|
||||
|
||||
done = epicsEventMustCreate(epicsEventEmpty);
|
||||
|
||||
testdbPrepare();
|
||||
|
||||
testdbReadDatabase("asyncproctest.dbd", NULL, NULL);
|
||||
asyncproctest_registerRecordDeviceDriver(pdbbase);
|
||||
registryFunctionAdd("doneSubr", (REGISTRYFUNCTION) doneSubr);
|
||||
testdbReadDatabase("asyncproctest.db", NULL, "TPRO=0");
|
||||
|
||||
dbAccessDebugPUTF = 1;
|
||||
|
||||
testIocInitOk();
|
||||
testDiag("===== Chain 1 ======");
|
||||
|
||||
waitFor = 2;
|
||||
testdbPutFieldOk("chain1.B", DBF_LONG, 6);
|
||||
testdbPutFieldOk("chain1.B", DBF_LONG, 7);
|
||||
|
||||
if (epicsEventWaitWithTimeout(done, 10.0) != epicsEventOK)
|
||||
testAbort("Processing timed out");
|
||||
|
||||
testdbGetFieldEqual("chain1", DBF_LONG, 7);
|
||||
testdbGetFieldEqual("chain1.A", DBF_LONG, 2);
|
||||
|
||||
testDiag("===== Chain 2 ======");
|
||||
|
||||
waitFor = 2;
|
||||
testdbPutFieldOk("chain2:1.B", DBF_LONG, 6);
|
||||
testdbPutFieldOk("chain2:1.B", DBF_LONG, 7);
|
||||
|
||||
if (epicsEventWaitWithTimeout(done, 10.0) != epicsEventOK)
|
||||
testAbort("Processing timed out");
|
||||
|
||||
testdbGetFieldEqual("chain2:1", DBF_LONG, 7);
|
||||
testdbGetFieldEqual("chain2:2", DBF_LONG, 7);
|
||||
testdbGetFieldEqual("chain2:1.A", DBF_LONG, 2);
|
||||
testdbGetFieldEqual("chain2:2.A", DBF_LONG, 2);
|
||||
|
||||
testDiag("===== Chain 2 again ======");
|
||||
|
||||
waitFor = 2;
|
||||
testdbPutFieldOk("chain2:1.B", DBF_LONG, 6);
|
||||
testdbPutFieldOk("chain2:1.B", DBF_LONG, 7);
|
||||
testdbPutFieldOk("chain2:1.B", DBF_LONG, 8);
|
||||
|
||||
if (epicsEventWaitWithTimeout(done, 10.0) != epicsEventOK)
|
||||
testAbort("Processing timed out");
|
||||
|
||||
testdbGetFieldEqual("chain2:1", DBF_LONG, 8);
|
||||
testdbGetFieldEqual("chain2:2", DBF_LONG, 8);
|
||||
testdbGetFieldEqual("chain2:1.A", DBF_LONG, 5);
|
||||
testdbGetFieldEqual("chain2:2.A", DBF_LONG, 4);
|
||||
|
||||
testDiag("===== Chain 3 ======");
|
||||
|
||||
waitFor = 2;
|
||||
testdbPutFieldOk("chain3.B", DBF_LONG, 6);
|
||||
testdbPutFieldOk("chain3.B", DBF_LONG, 7);
|
||||
|
||||
if (epicsEventWaitWithTimeout(done, 10.0) != epicsEventOK)
|
||||
testAbort("Processing timed out");
|
||||
|
||||
testdbGetFieldEqual("chain3", DBF_LONG, 7);
|
||||
testdbGetFieldEqual("chain3.A", DBF_LONG, 2);
|
||||
|
||||
testIocShutdownOk();
|
||||
|
||||
testdbCleanup();
|
||||
|
||||
return testDone();
|
||||
}
|
||||
@@ -0,0 +1,55 @@
|
||||
|
||||
# simple case
|
||||
# stand alone async record
|
||||
record(calcout, "chain1") {
|
||||
field(CALC, "A:=A+1;B")
|
||||
field(ODLY, "0.1")
|
||||
field(TPRO, "$(TPRO=)")
|
||||
field(FLNK, "done1")
|
||||
}
|
||||
record(sub, "done1") {
|
||||
field(SNAM, "doneSubr")
|
||||
field(TPRO, "$(TPRO=)")
|
||||
}
|
||||
|
||||
|
||||
# original problem case
|
||||
# async record chained after syncronous record
|
||||
record(calcout, "chain2:1") {
|
||||
field(CALC, "A:=A+1;B")
|
||||
# ODLY=0 synchronous
|
||||
field(OUT , "chain2:2.B PP")
|
||||
field(TPRO, "$(TPRO=)")
|
||||
}
|
||||
|
||||
record(ai, "chain2:3") {
|
||||
field(INP, "chain2:1 CPP")
|
||||
field(FLNK, "chain2:2")
|
||||
field(TPRO, "$(TPRO=)")
|
||||
}
|
||||
|
||||
record(calcout, "chain2:2") {
|
||||
field(CALC, "A:=A+1;B")
|
||||
field(ODLY, "0.5")
|
||||
field(TPRO, "$(TPRO=)")
|
||||
field(FLNK, "done2")
|
||||
}
|
||||
record(sub, "done2") {
|
||||
field(SNAM, "doneSubr")
|
||||
field(TPRO, "$(TPRO=)")
|
||||
}
|
||||
|
||||
|
||||
# ANJ's error case
|
||||
# async record FLNK's to itself (via done3)
|
||||
record(calcout, "chain3") {
|
||||
field(CALC, "A:=A+1;B")
|
||||
field(ODLY, "0.1")
|
||||
field(FLNK, "done3")
|
||||
field(TPRO, "$(TPRO=)")
|
||||
}
|
||||
record(sub, "done3") {
|
||||
field(SNAM, "doneSubr")
|
||||
field(FLNK, "chain3")
|
||||
field(TPRO, "$(TPRO=)")
|
||||
}
|
||||
@@ -7,11 +7,14 @@
|
||||
#include <string.h>
|
||||
|
||||
#include "dbAccess.h"
|
||||
#include "devSup.h"
|
||||
#include "alarm.h"
|
||||
#include "dbUnitTest.h"
|
||||
#include "errlog.h"
|
||||
#include "epicsThread.h"
|
||||
|
||||
#include "longinRecord.h"
|
||||
|
||||
#include "testMain.h"
|
||||
|
||||
void recTestIoc_registerRecordDeviceDriver(struct dbBase *);
|
||||
@@ -28,12 +31,21 @@ static void startTestIoc(const char *dbfile)
|
||||
eltc(1);
|
||||
}
|
||||
|
||||
/* testing here instead of ioc/db/test as xRecord has no INP/OUT */
|
||||
static void testdbGetDevLink(void)
|
||||
{
|
||||
longinRecord *rec = (longinRecord*)testdbRecordPtr("li1");
|
||||
testOk1(dbGetDevLink((dbCommon*)rec) == &rec->inp);
|
||||
}
|
||||
|
||||
static void testLongStringInit()
|
||||
{
|
||||
testDiag("testLongStringInit");
|
||||
|
||||
startTestIoc("linkInitTest.db");
|
||||
|
||||
testdbGetDevLink();
|
||||
|
||||
{
|
||||
const char buf[] = "!----------------------------------------------!";
|
||||
testdbGetArrFieldEqual("longstr1.VAL$", DBF_CHAR, NELEMENTS(buf)+2, NELEMENTS(buf), buf);
|
||||
@@ -230,7 +242,7 @@ void testInt64Inputs(void)
|
||||
|
||||
MAIN(linkInitTest)
|
||||
{
|
||||
testPlan(77);
|
||||
testPlan(78);
|
||||
|
||||
testLongStringInit();
|
||||
testCalcInit();
|
||||
|
||||
Reference in New Issue
Block a user