add testing lset

This commit is contained in:
Michael Davidsaver
2017-02-28 18:00:51 -06:00
committed by Andrew Johnson
parent 00549c832a
commit 428dfe7a5c
4 changed files with 335 additions and 87 deletions

View File

@@ -20,6 +20,7 @@ dbTestIoc_SRCS += xRecord.c
dbTestIoc_SRCS += dbLinkdset.c
dbTestIoc_SRCS += xLink.c
dbTestIoc_SRCS += devx.c
dbTestIoc_SRCS += jlinkz.c
dbTestIoc_LIBS = dbCore ca Com
TARGETS += $(COMMON_DIR)/dbTestIoc.dbd
@@ -31,6 +32,7 @@ dbTestIoc_DBD += xRecord.dbd
dbTestIoc_DBD += arrRecord.dbd
dbTestIoc_DBD += xLink.dbd
dbTestIoc_DBD += devx.dbd
dbTestIoc_DBD += jlinkz.dbd
dbTestIoc_DBD += dbLinkdset.dbd
TESTFILES += $(COMMON_DIR)/dbTestIoc.dbd ../xRecord.db

View File

@@ -68,7 +68,7 @@ static void testLinkParse(void)
{
const struct testParseDataT *td = testParseData;
dbLinkInfo info;
testDiag("link parsing");
testDiag("\n# Checking link parsing\n#");
testdbPrepare();
testdbReadDatabase("dbTestIoc.dbd", NULL, NULL);
@@ -81,22 +81,27 @@ static void testLinkParse(void)
testIocInitOk();
eltc(1);
for(;td->str; td++) {
for (;td->str; td++) {
int i, N;
testDiag("Parse \"%s\"", td->str);
testOk1(dbParseLink(td->str, DBF_INLINK, &info)==0);
testOk1(info.ltype==td->info.ltype);
if(td->info.target)
testDiag("Parsing \"%s\"", td->str);
testOk(dbParseLink(td->str, DBF_INLINK, &info) == 0, "Parser returned OK");
if (!testOk(info.ltype == td->info.ltype, "Link type value"))
testDiag("Expected %d, got %d", td->info.ltype, info.ltype);
if (td->info.target)
testStrcmp(0, info.target, td->info.target);
if(info.ltype==td->info.ltype) {
switch(info.ltype) {
if (info.ltype == td->info.ltype) {
switch (info.ltype) {
case PV_LINK:
testOk1(info.modifiers==td->info.modifiers);
if (!testOk(info.modifiers == td->info.modifiers,
"PV Link modifier flags"))
testDiag("Expected %d, got %d", td->info.modifiers,
info.modifiers);
break;
case VME_IO:
case CAMAC_IO:
testStrcmp(0, info.hwid, td->info.hwid);
N = strlen(td->info.hwid);
for(i=0; i<N; i++)
for (i=0; i<N; i++)
testOk(info.hwnums[i]==td->info.hwnums[i], "%d == %d",
info.hwnums[i], td->info.hwnums[i]);
}
@@ -125,7 +130,7 @@ static void testLinkFailParse(void)
{
const char * const *td = testParseFailData;
dbLinkInfo info;
testDiag("link parsing of invalid input");
testDiag("\n# Check parsing of invalid inputs\n#");
testdbPrepare();
testdbReadDatabase("dbTestIoc.dbd", NULL, NULL);
@@ -139,8 +144,8 @@ static void testLinkFailParse(void)
eltc(1);
for(;*td; td++) {
testDiag("Expect failure \"%s\"", *td);
testOk1(dbParseLink(*td, DBF_INLINK, &info)==S_dbLib_badField);
testOk(dbParseLink(*td, DBF_INLINK, &info) == S_dbLib_badField,
"dbParseLink correctly rejected \"%s\"", *td);
}
testIocShutdownOk();
@@ -180,7 +185,7 @@ static void testCADBSet(void)
const struct testDataT *td = testSetData;
xRecord *prec;
DBLINK *plink;
testDiag("DB/CA link retargeting");
testDiag("\n# Checking DB/CA link retargeting\n#");
testdbPrepare();
testdbReadDatabase("dbTestIoc.dbd", NULL, NULL);
@@ -197,21 +202,22 @@ static void testCADBSet(void)
plink = &prec->lnk;
for (;td->linkstring;td++) {
testDiag("x1.LNK <- \"%s\"", td->linkstring);
testDiag("Trying field value \"%s\"", td->linkstring);
testdbPutFieldOk("x1.LNK", DBF_STRING, td->linkstring);
if (td->linkback)
testdbGetFieldEqual("x1.LNK", DBF_STRING, td->linkback);
else
testdbGetFieldEqual("x1.LNK", DBF_STRING, td->linkstring);
testOk1(plink->type==td->linkType);
if (!testOk(plink->type == td->linkType, "Link type"))
testDiag("Expected %d, got %d", td->linkType, plink->type);
if (plink->type==td->linkType) {
switch(td->linkType) {
if (plink->type == td->linkType) {
switch (td->linkType) {
case CONSTANT:
if(plink->value.constantStr)
testOk1(strcmp(plink->value.constantStr,td->linkstring)==0);
else if(td->linkstring[0]=='\0')
if (plink->value.constantStr)
testOk1(strcmp(plink->value.constantStr, td->linkstring) == 0);
else if (td->linkstring[0]=='\0')
testPass("Empty String");
else
testFail("oops");
@@ -219,7 +225,7 @@ static void testCADBSet(void)
case DB_LINK:
case CA_LINK:
testOk(plink->value.pv_link.pvlMask==td->pvlMask,
testOk(plink->value.pv_link.pvlMask == td->pvlMask,
"pvlMask %x == %x", plink->value.pv_link.pvlMask, td->pvlMask);
break;
}
@@ -258,65 +264,65 @@ static void testLink(DBLINK *plink, const testHWDataT *td)
{
switch(td->ltype) {
case JSON_LINK:
testOk1(strcmp(plink->value.json.string, td->parm)==0);
testOk1(strcmp(plink->value.json.string, td->parm) == 0);
break;
case VME_IO:
testOk1(plink->value.vmeio.card==td->vals[0]);
testOk1(plink->value.vmeio.signal==td->vals[1]);
testOk1(strcmp(plink->value.vmeio.parm, td->parm)==0);
testOk1(plink->value.vmeio.card == td->vals[0]);
testOk1(plink->value.vmeio.signal == td->vals[1]);
testOk1(strcmp(plink->value.vmeio.parm, td->parm) == 0);
break;
case CAMAC_IO:
testOk1(plink->value.camacio.b==td->vals[0]);
testOk1(plink->value.camacio.c==td->vals[1]);
testOk1(plink->value.camacio.n==td->vals[2]);
testOk1(plink->value.camacio.a==td->vals[3]);
testOk1(plink->value.camacio.f==td->vals[4]);
testOk1(strcmp(plink->value.camacio.parm, td->parm)==0);
testOk1(plink->value.camacio.b == td->vals[0]);
testOk1(plink->value.camacio.c == td->vals[1]);
testOk1(plink->value.camacio.n == td->vals[2]);
testOk1(plink->value.camacio.a == td->vals[3]);
testOk1(plink->value.camacio.f == td->vals[4]);
testOk1(strcmp(plink->value.camacio.parm, td->parm) == 0);
break;
case AB_IO:
testOk1(plink->value.abio.link==td->vals[0]);
testOk1(plink->value.abio.adapter==td->vals[1]);
testOk1(plink->value.abio.card==td->vals[2]);
testOk1(plink->value.abio.signal==td->vals[3]);
testOk1(strcmp(plink->value.abio.parm, td->parm)==0);
testOk1(plink->value.abio.link == td->vals[0]);
testOk1(plink->value.abio.adapter == td->vals[1]);
testOk1(plink->value.abio.card == td->vals[2]);
testOk1(plink->value.abio.signal == td->vals[3]);
testOk1(strcmp(plink->value.abio.parm, td->parm) == 0);
break;
case GPIB_IO:
testOk1(plink->value.gpibio.link==td->vals[0]);
testOk1(plink->value.gpibio.addr==td->vals[1]);
testOk1(strcmp(plink->value.gpibio.parm, td->parm)==0);
testOk1(plink->value.gpibio.link == td->vals[0]);
testOk1(plink->value.gpibio.addr == td->vals[1]);
testOk1(strcmp(plink->value.gpibio.parm, td->parm) == 0);
break;
case BITBUS_IO:
testOk1(plink->value.bitbusio.link==td->vals[0]);
testOk1(plink->value.bitbusio.node==td->vals[1]);
testOk1(plink->value.bitbusio.port==td->vals[2]);
testOk1(plink->value.bitbusio.signal==td->vals[3]);
testOk1(strcmp(plink->value.bitbusio.parm, td->parm)==0);
testOk1(plink->value.bitbusio.link == td->vals[0]);
testOk1(plink->value.bitbusio.node == td->vals[1]);
testOk1(plink->value.bitbusio.port == td->vals[2]);
testOk1(plink->value.bitbusio.signal == td->vals[3]);
testOk1(strcmp(plink->value.bitbusio.parm, td->parm) == 0);
break;
case INST_IO:
testOk1(strcmp(plink->value.instio.string, td->parm)==0);
testOk1(strcmp(plink->value.instio.string, td->parm) == 0);
break;
case BBGPIB_IO:
testOk1(plink->value.bbgpibio.link==td->vals[0]);
testOk1(plink->value.bbgpibio.bbaddr==td->vals[1]);
testOk1(plink->value.bbgpibio.gpibaddr==td->vals[2]);
testOk1(strcmp(plink->value.bbgpibio.parm, td->parm)==0);
testOk1(plink->value.bbgpibio.link == td->vals[0]);
testOk1(plink->value.bbgpibio.bbaddr == td->vals[1]);
testOk1(plink->value.bbgpibio.gpibaddr == td->vals[2]);
testOk1(strcmp(plink->value.bbgpibio.parm, td->parm) == 0);
break;
case RF_IO:
testOk1(plink->value.rfio.cryo==td->vals[0]);
testOk1(plink->value.rfio.micro==td->vals[1]);
testOk1(plink->value.rfio.dataset==td->vals[2]);
testOk1(plink->value.rfio.element==td->vals[3]);
testOk1(plink->value.rfio.cryo == td->vals[0]);
testOk1(plink->value.rfio.micro == td->vals[1]);
testOk1(plink->value.rfio.dataset == td->vals[2]);
testOk1(plink->value.rfio.element == td->vals[3]);
break;
case VXI_IO:
if(plink->value.vxiio.flag==VXIDYNAMIC) {
testOk1(plink->value.vxiio.frame==td->vals[0]);
testOk1(plink->value.vxiio.slot==td->vals[1]);
testOk1(plink->value.vxiio.signal==td->vals[2]);
if(plink->value.vxiio.flag == VXIDYNAMIC) {
testOk1(plink->value.vxiio.frame == td->vals[0]);
testOk1(plink->value.vxiio.slot == td->vals[1]);
testOk1(plink->value.vxiio.signal == td->vals[2]);
} else {
testOk1(plink->value.vxiio.la==td->vals[0]);
testOk1(plink->value.vxiio.signal==td->vals[1]);
testOk1(plink->value.vxiio.la == td->vals[0]);
testOk1(plink->value.vxiio.signal == td->vals[1]);
}
testOk1(strcmp(plink->value.vxiio.parm, td->parm)==0);
testOk1(strcmp(plink->value.vxiio.parm, td->parm) == 0);
break;
}
}
@@ -324,7 +330,7 @@ static void testLink(DBLINK *plink, const testHWDataT *td)
static void testHWInitSet(void)
{
const testHWDataT *td = testHWData;
testDiag("HW link parsing during initialization");
testDiag("\n# Checking HW link parsing during initialization\n#");
testdbPrepare();
testdbReadDatabase("dbTestIoc.dbd", NULL, NULL);
@@ -337,13 +343,14 @@ static void testHWInitSet(void)
testIocInitOk();
eltc(1);
for(;td->recname;td++) {
for (;td->recname; td++) {
char buf[MAX_STRING_SIZE];
xRecord *prec;
DBLINK *plink;
testDiag("%s == \"%s\"", td->recname, td->wval);
prec = (xRecord*)testdbRecordPtr(td->recname);
prec = (xRecord *) testdbRecordPtr(td->recname);
plink = &prec->inp;
strcpy(buf, td->recname);
@@ -351,9 +358,11 @@ static void testHWInitSet(void)
testdbGetFieldEqual(buf, DBR_STRING, td->wval);
testOk(plink->type==td->ltype, "link type %d == %d",
plink->type, td->ltype);
if(plink->type==td->ltype) {
if (!testOk(plink->type == td->ltype, "Link type")) {
testDiag("Expected %d, got %d",
td->ltype, plink->type);
}
else {
testLink(plink, td);
}
@@ -382,7 +391,8 @@ static const testHWDataT testHWData2[] = {
static void testHWMod(void)
{
const testHWDataT *td = testHWData2;
testDiag("HW link parsing during retarget");
testDiag("\n# Checking HW link parsing during retarget\n#");
testdbPrepare();
testdbReadDatabase("dbTestIoc.dbd", NULL, NULL);
@@ -411,9 +421,11 @@ static void testHWMod(void)
testdbGetFieldEqual(buf, DBR_STRING, td->wval);
testOk(plink->type==td->ltype, "link type %d == %d",
plink->type, td->ltype);
if(plink->type==td->ltype) {
if (!testOk(plink->type == td->ltype, "Link type")) {
testDiag("Expected %d, got %d",
td->ltype, plink->type);
}
else {
testLink(plink, td);
}
@@ -428,42 +440,42 @@ static void testLinkInitFail(void)
{
xRecord *prec;
DBLINK *plink;
testDiag("Link parsing failures during initialization");
testDiag("\n# Checking link parse failures at iocInit\n#");
testdbPrepare();
testdbReadDatabase("dbTestIoc.dbd", NULL, NULL);
dbTestIoc_registerRecordDeviceDriver(pdbbase);
/* this load will fail */
eltc(0);
testOk1(dbReadDatabase(&pdbbase, "dbBadLink.db", "." OSI_PATH_LIST_SEPARATOR ".." OSI_PATH_LIST_SEPARATOR
"../O.Common" OSI_PATH_LIST_SEPARATOR "O.Common", NULL)!=0);
testOk(dbReadDatabase(&pdbbase, "dbBadLink.db", "." OSI_PATH_LIST_SEPARATOR
".." OSI_PATH_LIST_SEPARATOR "../O.Common" OSI_PATH_LIST_SEPARATOR
"O.Common", NULL) != 0, "dbReadDatabase returned error (expected)");
testIocInitOk();
eltc(1);
testdbGetFieldEqual("eVME_IO1.INP", DBR_STRING, "#C0 S0 @");
prec = (xRecord*)testdbRecordPtr("eVME_IO1");
prec = (xRecord *) testdbRecordPtr("eVME_IO1");
plink = &prec->inp;
testOk1(plink->type==VME_IO);
testOk1(plink->value.vmeio.parm!=NULL);
testOk1(plink->type == VME_IO);
testOk1(plink->value.vmeio.parm != NULL);
testdbGetFieldEqual("eVME_IO2.INP", DBR_STRING, "#C0 S0 @");
prec = (xRecord*)testdbRecordPtr("eVME_IO2");
prec = (xRecord *) testdbRecordPtr("eVME_IO2");
plink = &prec->inp;
testOk1(plink->type==VME_IO);
testOk1(plink->value.vmeio.parm!=NULL);
testOk1(plink->type == VME_IO);
testOk1(plink->value.vmeio.parm != NULL);
testdbGetFieldEqual("eINST_IO.INP", DBR_STRING, "@");
prec = (xRecord*)testdbRecordPtr("eINST_IO");
prec = (xRecord *) testdbRecordPtr("eINST_IO");
plink = &prec->inp;
testOk1(plink->type==INST_IO);
testOk1(plink->value.instio.string!=NULL);
testOk1(plink->type == INST_IO);
testOk1(plink->value.instio.string != NULL);
testIocShutdownOk();
@@ -472,7 +484,7 @@ static void testLinkInitFail(void)
static void testLinkFail(void)
{
testDiag("Link parsing failures");
testDiag("\n# Checking runtime link parse failures\n#");
testdbPrepare();
testdbReadDatabase("dbTestIoc.dbd", NULL, NULL);
@@ -491,7 +503,8 @@ static void testLinkFail(void)
/* INST_IO doesn't accept string without @ */
testdbPutFieldFail(S_dbLib_badField, "rINST_IO.INP", DBR_STRING, "abc");
/* JSON_LINK dies properly */
/* JSON_LINK dies when expected */
testdbPutFieldOk("rJSON_LINK.INP", DBR_STRING, "{\"x\":true}");
testdbPutFieldFail(S_dbLib_badField, "rJSON_LINK.INP", DBR_STRING, "{\"x\":false}");
testdbPutFieldFail(S_dbLib_badField, "rJSON_LINK.INP", DBR_STRING, "{\"x\":null}");
testdbPutFieldFail(S_dbLib_badField, "rJSON_LINK.INP", DBR_STRING, "{\"x\":1}");
@@ -522,7 +535,7 @@ static void testLinkFail(void)
MAIN(dbPutLinkTest)
{
testPlan(269);
testPlan(280);
testLinkParse();
testLinkFailParse();
testCADBSet();

232
src/ioc/db/test/jlinkz.c Normal file
View File

@@ -0,0 +1,232 @@
/*************************************************************************\
* Copyright (c) 2016 Michael Davidsaver
* EPICS BASE is distributed subject to a Software License Agreement found
* in file LICENSE that is included with this distribution.
\*************************************************************************/
#include <stdlib.h>
#include <string.h>
#include <epicsExport.h>
#include <dbAccess.h>
#include <link.h>
#include <alarm.h>
#include <dbJLink.h>
#include <dbDefs.h>
#include <dbConvertFast.h>
#include <epicsAtomic.h>
#include <epicsMutex.h>
#include <epicsUnitTest.h>
int numzalloc;
typedef struct {
jlink base;
epicsMutexId lock;
unsigned isset:1;
unsigned isopen:1;
epicsInt32 value;
} zpriv;
static
void z_open(struct link *plink)
{
zpriv *priv = CONTAINER(plink->value.json.jlink, zpriv, base);
if(priv->isopen)
testDiag("lsetZ re-open");
priv->isopen = 1;
}
static
void z_remove(struct dbLocker *locker, struct link *plink)
{
zpriv *priv = CONTAINER(plink->value.json.jlink, zpriv, base);
epicsMutexLock(priv->lock);
if(!priv->isopen)
testDiag("lsetZ remove without open");
epicsMutexUnlock(priv->lock);
epicsAtomicDecrIntT(&numzalloc);
free(priv);
plink->value.json.jlink = NULL; /* paranoia */
}
static
int z_connected(const struct link *plink)
{
return 1; /* TODO: not provided should be connected */
}
static
int z_dbftype(const struct link *plink)
{
return DBF_LONG;
}
static
long z_elements(const struct link *plink, long *nelements)
{
*nelements = 1;
return 0;
}
static
long z_getval(struct link *plink, short dbrType, void *pbuffer,
long *pnRequest)
{
long ret;
long (*pconv)(const epicsInt32 *, void *, const dbAddr *) = dbFastGetConvertRoutine[DBF_LONG][dbrType];
zpriv *priv = CONTAINER(plink->value.json.jlink, zpriv, base);
if(pnRequest && *pnRequest==0) return 0;
epicsMutexLock(priv->lock);
ret = (*pconv)(&priv->value, pbuffer, NULL);
epicsMutexUnlock(priv->lock);
if(ret==0 && pnRequest) *pnRequest = 1;
return ret;
}
/* TODO: atomicly get value and alarm */
static
long z_getalarm(const struct link *plink, epicsEnum16 *status,
epicsEnum16 *severity)
{
zpriv *priv = CONTAINER(plink->value.json.jlink, zpriv, base);
epicsEnum16 sevr, stat;
epicsMutexLock(priv->lock);
sevr = priv->isset ? 0 : INVALID_ALARM;
stat = priv->isset ? 0 : LINK_ALARM;
epicsMutexUnlock(priv->lock);
if(status) *status = stat;
if(severity) *severity = sevr;
return 0;
}
static
long z_putval(struct link *plink, short dbrType,
const void *pbuffer, long nRequest)
{
long ret;
long (*pconv)(epicsInt32 *, const void *, const dbAddr *) = dbFastPutConvertRoutine[DBF_LONG][dbrType];
zpriv *priv = CONTAINER(plink->value.json.jlink, zpriv, base);
if(nRequest==0) return 0;
epicsMutexLock(priv->lock);
ret = (*pconv)(&priv->value, pbuffer, NULL);
epicsMutexUnlock(priv->lock);
return ret;
}
static lset lsetZ = {
0, 0, /* non-const, non-volatile */
&z_open,
&z_remove,
NULL, NULL, NULL, /* load */
&z_connected,
&z_dbftype,
&z_elements,
&z_getval,
NULL, /* control limits */
NULL, /* display limits */
NULL, /* alarm limits */
NULL, /* prec */
NULL, /* units */
&z_getalarm,
NULL, /* time */
&z_putval,
NULL, /* putasync */
NULL, /* forward */
};
static
jlink* z_alloc(short dbfType)
{
zpriv *priv;
priv = calloc(1, sizeof(*priv));
if(!priv) return NULL;
epicsAtomicIncrIntT(&numzalloc);
return &priv->base;
}
static
void z_free(jlink *pj)
{
zpriv *priv = CONTAINER(pj, zpriv, base);
if(priv->isopen)
testDiag("lsetZ jlink free after open()\n");
epicsAtomicDecrIntT(&numzalloc);
free(priv);
}
static
jlif_result z_int(jlink *pj, long num)
{
zpriv *priv = CONTAINER(pj, zpriv, base);
priv->value = num;
priv->isset = 1;
return jlif_continue;
}
static
jlif_key_result z_start(jlink *pj)
{
return jlif_continue;
}
static
jlif_result z_key(jlink *pj, const char *key, size_t len)
{
if(strcmp(key,"fail")==0) return jlif_stop;
else return jlif_continue;
}
static
jlif_result z_end(jlink *pj)
{
return jlif_continue;
}
static
struct lset* z_lset(const jlink *pj)
{
return &lsetZ;
}
static jlif jlifZ = {
"z",
&z_alloc,
&z_free,
NULL, /* null */
NULL, /* bool */
&z_int,
NULL, /* double */
NULL, /* string */
&z_start,
&z_key,
&z_end,
NULL, /* start array */
NULL, /* end array */
NULL, /* end child */
&z_lset,
NULL, /* report */
NULL /* map child */
};
epicsExportAddress(jlif, jlifZ);

View File

@@ -0,0 +1 @@
link("z", "jlifZ")