diff --git a/src/ioc/db/dbConstLink.c b/src/ioc/db/dbConstLink.c index ffedce43f..928dae983 100644 --- a/src/ioc/db/dbConstLink.c +++ b/src/ioc/db/dbConstLink.c @@ -211,6 +211,12 @@ static long dbConstGetValue(struct link *plink, short dbrType, void *pbuffer, return 0; } +static long dbConstPutValue(struct link *plink, short dbrType, + const void *pbuffer, long nRequest) +{ + return 0; +} + static lset dbConst_lset = { 1, 0, /* Constant, not Volatile */ NULL, NULL, @@ -223,6 +229,6 @@ static lset dbConst_lset = { NULL, NULL, NULL, NULL, NULL, NULL, NULL, - NULL, NULL, + dbConstPutValue, NULL, NULL, NULL }; diff --git a/src/std/link/lnkConst.c b/src/std/link/lnkConst.c index db824abbc..6a3dc5d6c 100644 --- a/src/std/link/lnkConst.c +++ b/src/std/link/lnkConst.c @@ -558,6 +558,12 @@ static long lnkConst_getValue(struct link *plink, short dbrType, void *pbuffer, return 0; } +static long lnkConst_putValue(struct link *plink, short dbrType, + const void *pbuffer, long nRequest) +{ + return 0; +} + /************************* Interface Tables *************************/ @@ -569,7 +575,7 @@ static lset lnkConst_lset = { NULL, NULL, NULL, NULL, NULL, NULL, NULL, - NULL, NULL, + lnkConst_putValue, NULL, NULL, NULL }; diff --git a/src/std/rec/test/Makefile b/src/std/rec/test/Makefile index f200e54e6..23e18adcb 100644 --- a/src/std/rec/test/Makefile +++ b/src/std/rec/test/Makefile @@ -67,6 +67,13 @@ testHarness_SRCS += asyncSoftTest.c TESTFILES += ../asyncSoftTest.db TESTS += asyncSoftTest +TESTPROD_HOST += softTest +softTest_SRCS += softTest.c +softTest_SRCS += recTestIoc_registerRecordDeviceDriver.cpp +testHarness_SRCS += softTest.c +TESTFILES += ../softTest.db +TESTS += softTest + TARGETS += $(COMMON_DIR)/asTestIoc.dbd DBDDEPENDS_FILES += asTestIoc.dbd$(DEP) asTestIoc_DBD += base.dbd diff --git a/src/std/rec/test/softTest.c b/src/std/rec/test/softTest.c new file mode 100644 index 000000000..d92bf64dd --- /dev/null +++ b/src/std/rec/test/softTest.c @@ -0,0 +1,169 @@ +/*************************************************************************\ +* Copyright (c) 2017 UChicago Argonne LLC, as operator of Argonne +* National Laboratory. +* EPICS BASE is distributed subject to a Software License Agreement found +* in file LICENSE that is included with this distribution. +\*************************************************************************/ + +#include + +#include "dbAccess.h" +#include "dbStaticLib.h" +#include "dbTest.h" +#include "dbUnitTest.h" +#include "errlog.h" +#include "registryFunction.h" +#include "subRecord.h" +#include "testMain.h" + +static +void checkDtyp(const char *rec) +{ + char dtyp[16]; + + strcpy(dtyp, rec); + strcat(dtyp, ".DTYP"); + + testdbGetFieldEqual(dtyp, DBF_LONG, 0); /* Soft Channel = 0 */ +} + +static +void checkInput(const char *rec, int value) +{ + char proc[16]; + + testDiag("Checking record '%s'", rec); + + strcpy(proc, rec); + strcat(proc, ".PROC"); + + testdbPutFieldOk(proc, DBF_CHAR, 1); + + testdbGetFieldEqual(rec, DBF_LONG, value); +} + +static +void testGroup0(void) +{ + const char ** rec; + const char * records[] = { + "ai0", "bi0", "di0", "ii0", "li0", "lsi0", "mi0", "si0", NULL + }; + + testDiag("============ Starting %s ============", EPICS_FUNCTION); + + testdbPutFieldOk("source", DBF_LONG, 1); + for (rec = records; *rec; rec++) { + checkInput(*rec, 1); + checkDtyp(*rec); + } + + testdbPutFieldOk("source", DBF_LONG, 0); + for (rec = records; *rec; rec++) { + checkInput(*rec, 0); + } +} + +static +void testGroup1(void) +{ + const char ** rec; + const char * records[] = { + "bi1", + "ai1", "di1", "ii1", "li1", "lsi1", "mi1", "si1", NULL + }; + int init = 1; /* bi1 initializes to 1 */ + + testDiag("============ Starting %s ============", EPICS_FUNCTION); + + for (rec = records; *rec; rec++) { + checkInput(*rec, init); + init = 9; /* remainder initialize to 9 */ + } +} + +int dest; + +static +long destSubr(subRecord *prec) +{ + dest = prec->val; + return 0; +} + +static +void checkOutput(const char *rec, int value) +{ + testDiag("Checking record '%s'", rec); + + testdbPutFieldOk(rec, DBF_LONG, value); + + testOk(dest == value, "value %d output -> %d", value, dest); +} + +static +void testGroup2(void) +{ + const char ** rec; + const char * records[] = { + "ao0", "bo0", "io0", "lo0", "lso0", "mo0", "so0", NULL, + }; + + testDiag("============ Starting %s ============", EPICS_FUNCTION); + + for (rec = records; *rec; rec++) { + checkOutput(*rec, 1); + checkDtyp(*rec); + } + checkOutput("do0.B0", 1); + checkDtyp("do0"); + + for (rec = records; *rec; rec++) { + checkOutput(*rec, 0); + } + checkOutput("do0.B0", 0); +} + +static +void testGroup3(void) +{ + const char ** rec; + const char * records[] = { + "ao1", "bo1", "do1.B0", "io1", "lo1", "lso1", "mo1", "so1", NULL, + }; + + testDiag("============ Starting %s ============", EPICS_FUNCTION); + + for (rec = records; *rec; rec++) { + checkOutput(*rec, 0); + } +} + +void recTestIoc_registerRecordDeviceDriver(struct dbBase *); + +MAIN(softTest) +{ + testPlan(114); + + testdbPrepare(); + testdbReadDatabase("recTestIoc.dbd", NULL, NULL); + + recTestIoc_registerRecordDeviceDriver(pdbbase); + registryFunctionAdd("destSubr", (REGISTRYFUNCTION) destSubr); + + testdbReadDatabase("softTest.db", NULL, NULL); + + eltc(0); + testIocInitOk(); + eltc(1); + + testGroup0(); + testGroup1(); + testGroup2(); + testGroup3(); + + testIocShutdownOk(); + testdbCleanup(); + + return testDone(); +} diff --git a/src/std/rec/test/softTest.db b/src/std/rec/test/softTest.db new file mode 100644 index 000000000..010a47a5c --- /dev/null +++ b/src/std/rec/test/softTest.db @@ -0,0 +1,227 @@ +# Group 0 are input records with INP being a DB link to 'source'. +# Processing them reads that value. + +record(longin, "source") {} + +record(ai, "ai0") { + field(DTYP, "Soft Channel") + field(INP, "source") +} +record(bi, "bi0") { + field(DTYP, "Soft Channel") + field(INP, "source") + field(ZNAM, "Zero") + field(ONAM, "One") +} +record(int64in, "ii0") { + field(DTYP, "Soft Channel") + field(INP, "source") +} +record(longin, "li0") { + field(DTYP, "Soft Channel") + field(INP, "source") +} +record(mbbiDirect, "di0") { + field(DTYP, "Soft Channel") + field(NOBT, 4) + field(INP, "source") +} +record(mbbi, "mi0") { + field(DTYP, "Soft Channel") + field(NOBT, 4) + field(INP, "source") + field(ZRST, "Zero") + field(ONST, "One") + field(TWST, "Two") + field(THST, "Three") + field(FRST, "Four") + field(FVST, "Five") + field(SXST, "Six") + field(SVST, "Seven") + field(EIST, "Eight") + field(NIST, "Nine") + field(TEST, "Ten") + field(ELST, "Eleven") + field(TWST, "Twelve") + field(TTST, "Thirteen") + field(FTST, "Fourteen") + field(FFST, "Fifteen") +} +record(lsi, "lsi0") { + field(DTYP, "Soft Channel") + field(SIZV, 40) + field(INP, "source") +} +record(stringin, "si0") { + field(DTYP, "Soft Channel") + field(INP, "source") +} + +# Group 1 are input records with INP being a non-zero constant. +# Processing them succeeds but does not change VAL. + +record(ai, "ai1") { + field(DTYP, "Soft Channel") + field(INP, {const:9}) +} +record(bi, "bi1") { + field(DTYP, "Soft Channel") + field(INP, {const:1}) + field(ZNAM, "Zero") + field(ONAM, "One") +} +record(int64in, "ii1") { + field(DTYP, "Soft Channel") + field(INP, {const:9}) +} +record(longin, "li1") { + field(DTYP, "Soft Channel") + field(INP, {const:9}) +} +record(mbbiDirect, "di1") { + field(DTYP, "Soft Channel") + field(NOBT, 4) + field(INP, {const:9}) +} +record(mbbi, "mi1") { + field(DTYP, "Soft Channel") + field(NOBT, 4) + field(INP, {const:9}) + field(ZRST, "Zero") + field(ONST, "One") + field(TWST, "Two") + field(THST, "Three") + field(FRST, "Four") + field(FVST, "Five") + field(SXST, "Six") + field(SVST, "Seven") + field(EIST, "Eight") + field(NIST, "Nine") + field(TEST, "Ten") + field(ELST, "Eleven") + field(TWST, "Twelve") + field(TTST, "Thirteen") + field(FTST, "Fourteen") + field(FFST, "Fifteen") +} +record(lsi, "lsi1") { + field(DTYP, "Soft Channel") + field(SIZV, 40) + field(INP, {const:"9"}) +} +record(stringin, "si1") { + field(DTYP, "Soft Channel") + field(INP, {const:"9"}) +} + + +# Group 2 are output records with OUT being a DB link to 'dest' with PP. +# Putting a value to them writes that value to 'dest'. + +record(sub, "dest") { + field(SNAM, "destSubr") +} + +record(ao, "ao0") { + field(DTYP, "Soft Channel") + field(OUT, "dest PP") +} +record(bo, "bo0") { + field(DTYP, "Soft Channel") + field(OUT, "dest PP") + field(ZNAM, "Zero") + field(ONAM, "One") +} +record(int64out, "io0") { + field(DTYP, "Soft Channel") + field(OUT, "dest PP") +} +record(longout, "lo0") { + field(DTYP, "Soft Channel") + field(OUT, "dest PP") +} +record(mbboDirect, "do0") { + field(DTYP, "Soft Channel") + field(NOBT, 4) + field(OUT, "dest PP") +} +record(mbbo, "mo0") { + field(DTYP, "Soft Channel") + field(NOBT, 4) + field(OUT, "dest PP") + field(ZRST, "Zero") + field(ONST, "One") + field(TWST, "Two") + field(THST, "Three") + field(FRST, "Four") + field(FVST, "Five") + field(SXST, "Six") + field(SVST, "Seven") + field(EIST, "Eight") + field(NIST, "Nine") + field(TEST, "Ten") + field(ELST, "Eleven") + field(TWST, "Twelve") + field(TTST, "Thirteen") + field(FTST, "Fourteen") + field(FFST, "Fifteen") +} +record(lso, "lso0") { + field(DTYP, "Soft Channel") + field(OUT, "dest PP") + field(SIZV, 40) +} +record(stringout, "so0") { + field(DTYP, "Soft Channel") + field(OUT, "dest PP") +} + + +# Group 3 are output records with OUT being empty (a constant link). +# Putting a value to them must succeed. + +record(ao, "ao1") { + field(DTYP, "Soft Channel") +} +record(bo, "bo1") { + field(DTYP, "Soft Channel") + field(ZNAM, "Zero") + field(ONAM, "One") +} +record(int64out, "io1") { + field(DTYP, "Soft Channel") +} +record(longout, "lo1") { + field(DTYP, "Soft Channel") +} +record(mbboDirect, "do1") { + field(DTYP, "Soft Channel") + field(NOBT, 4) +} +record(mbbo, "mo1") { + field(DTYP, "Soft Channel") + field(NOBT, 4) + field(ZRST, "Zero") + field(ONST, "One") + field(TWST, "Two") + field(THST, "Three") + field(FRST, "Four") + field(FVST, "Five") + field(SXST, "Six") + field(SVST, "Seven") + field(EIST, "Eight") + field(NIST, "Nine") + field(TEST, "Ten") + field(ELST, "Eleven") + field(TWST, "Twelve") + field(TTST, "Thirteen") + field(FTST, "Fourteen") + field(FFST, "Fifteen") +} +record(lso, "lso1") { + field(DTYP, "Soft Channel") + field(SIZV, 40) +} +record(stringout, "so1") { + field(DTYP, "Soft Channel") +}