From 026307c06d9fc629ffdf8331e0861d59788f9ec8 Mon Sep 17 00:00:00 2001 From: Michael Davidsaver Date: Thu, 28 Jun 2012 10:55:44 -0400 Subject: [PATCH 01/21] db cleanup cleanup to allow database re-load --- src/ioc/db/dbChannel.c | 2 +- src/ioc/db/test/epicsRunDbTests.c | 3 +++ src/ioc/dbStatic/dbStaticLib.c | 1 + src/ioc/registry/registerRecordDeviceDriver.pl | 3 +-- src/libCom/dbmf/dbmf.h | 1 + src/libCom/iocsh/registry.c | 1 + 6 files changed, 8 insertions(+), 3 deletions(-) diff --git a/src/ioc/db/dbChannel.c b/src/ioc/db/dbChannel.c index 9305f7da4..4d5a3e968 100644 --- a/src/ioc/db/dbChannel.c +++ b/src/ioc/db/dbChannel.c @@ -838,7 +838,7 @@ void dbRegisterFilter(const char *name, const chFilterIf *fif, void *puser) if (pgph) return; - pfilt = dbCalloc(1, sizeof(chFilterPlugin)); + pfilt = dbCalloc(1, sizeof(chFilterPlugin)); /* leaked */ pfilt->name = epicsStrDup(name); pfilt->fif = fif; pfilt->puser = puser; diff --git a/src/ioc/db/test/epicsRunDbTests.c b/src/ioc/db/test/epicsRunDbTests.c index 0a3e00cd0..0b747abc2 100644 --- a/src/ioc/db/test/epicsRunDbTests.c +++ b/src/ioc/db/test/epicsRunDbTests.c @@ -14,6 +14,7 @@ #include "epicsUnitTest.h" #include "epicsExit.h" +#include "dbmf.h" int callbackTest(void); @@ -23,5 +24,7 @@ void epicsRunDbTests(void) runTest(callbackTest); + dbmfFreeChunks(); + epicsExit(0); /* Trigger test harness */ } diff --git a/src/ioc/dbStatic/dbStaticLib.c b/src/ioc/dbStatic/dbStaticLib.c index ce27803a5..2ef3c0585 100644 --- a/src/ioc/dbStatic/dbStaticLib.c +++ b/src/ioc/dbStatic/dbStaticLib.c @@ -651,6 +651,7 @@ void epicsShareAPI dbFreeBase(dbBase *pdbbase) ellDelete(&pdbRecordType->attributeList,&pAttribute->node); free((void *)pAttribute->name); free((void *)pAttribute->pdbFldDes); + free(pAttribute); pAttribute = pAttributeNext; } pdbRecordTypeNext = (dbRecordType *)ellNext(&pdbRecordType->node); diff --git a/src/ioc/registry/registerRecordDeviceDriver.pl b/src/ioc/registry/registerRecordDeviceDriver.pl index 5ab5c14d3..e914473e7 100755 --- a/src/ioc/registry/registerRecordDeviceDriver.pl +++ b/src/ioc/registry/registerRecordDeviceDriver.pl @@ -186,8 +186,7 @@ print << 'END'; } if (executed) { - printf("Registration already done.\n"); - return 0; + printf("Warning: Registration already done.\n"); } executed = 1; diff --git a/src/libCom/dbmf/dbmf.h b/src/libCom/dbmf/dbmf.h index 44395ade3..3740e532e 100644 --- a/src/libCom/dbmf/dbmf.h +++ b/src/libCom/dbmf/dbmf.h @@ -16,6 +16,7 @@ #ifndef DBMF_H #define DBMF_H +#include #include "shareLib.h" #ifdef __cplusplus diff --git a/src/libCom/iocsh/registry.c b/src/libCom/iocsh/registry.c index 89b50ccca..0b2e312e3 100644 --- a/src/libCom/iocsh/registry.c +++ b/src/libCom/iocsh/registry.c @@ -81,6 +81,7 @@ epicsShareFunc void epicsShareAPI registryFree(void) { if(!gphPvt) return; gphFreeMem(gphPvt); + gphPvt = 0; } epicsShareFunc int epicsShareAPI registryDump(void) From 39ccbeeb11363a1ba4e9291ac0367300a72cfde5 Mon Sep 17 00:00:00 2001 From: Michael Davidsaver Date: Thu, 28 Jun 2012 10:55:46 -0400 Subject: [PATCH 02/21] Make db unit tests self contained --- src/ioc/db/test/Makefile | 17 ++-- src/ioc/db/test/arrShorthandTest.c | 28 +++--- src/ioc/db/test/chfPluginTest.c | 26 ++---- src/ioc/db/test/dbChannelTest.c | 24 ++---- src/ioc/db/test/dbChannelTest.db | 2 - src/ioc/db/test/epicsRunDbTests.c | 8 ++ src/ioc/db/test/xRecord.c | 132 +++++++++++++++++++++++++++++ src/ioc/db/test/xRecord.dbd | 12 --- 8 files changed, 176 insertions(+), 73 deletions(-) delete mode 100644 src/ioc/db/test/dbChannelTest.db create mode 100644 src/ioc/db/test/xRecord.c delete mode 100644 src/ioc/db/test/xRecord.dbd diff --git a/src/ioc/db/test/Makefile b/src/ioc/db/test/Makefile index 86f4853a1..c44226b04 100644 --- a/src/ioc/db/test/Makefile +++ b/src/ioc/db/test/Makefile @@ -28,30 +28,31 @@ TESTSPEC_vxWorks = dbTestHarness.munch; epicsRunDbTests TESTSPEC_RTEMS = dbTestHarness.boot; epicsRunDbTests TESTPROD_HOST += dbChannelTest -dbChannelTest_SRCS += dbChannelTest.c xRecord_registerRecordDeviceDriver.cpp +dbChannelTest_SRCS += dbChannelTest.c xRecord.c +dbTestHarness_SRCS += dbChannelTest.c OBJS_IOC_vxWorks += dbChannelTest TESTS += dbChannelTest TESTPROD_HOST += chfPluginTest -chfPluginTest_SRCS += chfPluginTest.c xRecord_registerRecordDeviceDriver.cpp +chfPluginTest_SRCS += chfPluginTest.c xRecord.c +dbTestHarness_SRCS += chfPluginTest.c OBJS_IOC_vxWorks += chfPluginTest TESTS += chfPluginTest TESTPROD_HOST += arrShorthandTest -arrShorthandTest_SRCS += arrShorthandTest.c xRecord_registerRecordDeviceDriver.cpp +arrShorthandTest_SRCS += arrShorthandTest.c xRecord.c +dbTestHarness_SRCS += arrShorthandTest.c OBJS_IOC_vxWorks += arrShorthandTest TESTS += arrShorthandTest TESTPROD_HOST += dbStateTest dbStateTest_SRCS += dbStateTest.c +dbTestHarness_SRCS += dbStateTest.c OBJS_IOC_vxWorks += dbStateTest TESTS += dbStateTest +dbTestHarness_SRCS += xRecord.c + TESTSCRIPTS_HOST += $(TESTS:%=%.t) include $(TOP)/configure/RULES - -dbChannelTest$(DEP): $(COMMON_DIR)/xRecord.h -chfPluginTest$(DEP): $(COMMON_DIR)/xRecord.h -arrShorthandTest$(DEP): $(COMMON_DIR)/xRecord.h -dbStateTest$(DEP): $(COMMON_DIR)/xRecord.h diff --git a/src/ioc/db/test/arrShorthandTest.c b/src/ioc/db/test/arrShorthandTest.c index 669eab9ca..9957ff897 100644 --- a/src/ioc/db/test/arrShorthandTest.c +++ b/src/ioc/db/test/arrShorthandTest.c @@ -21,6 +21,7 @@ #include "chfPlugin.h" #include "dbStaticLib.h" #include "dbAccessDefs.h" +#include "registry.h" #include "epicsUnitTest.h" #include "testMain.h" @@ -75,22 +76,21 @@ static void testHead (char* title) { testDiag("--------------------------------------------------------"); } -void xRecord_registerRecordDeviceDriver(struct dbBase *); +int loadTestDB(DBBASE **ppbase); -MAIN(chfPluginTest) +MAIN(arrShorthandTest) { dbChannel *pch; - testPlan(26); + testPlan(28); db_init_events(); - if (dbReadDatabase(&pdbbase, "xRecord.dbd", "..", NULL)) - testAbort("Database description not loaded"); + testHead("Set up database"); + if(loadTestDB(&pdbbase)) + return testDone(); - xRecord_registerRecordDeviceDriver(pdbbase); - if (dbReadDatabase(&pdbbase, "dbChannelTest.db", "..", NULL)) - testAbort("Test database not loaded"); + testOk(!!pdbbase, "pdbbase was set"); testHead("Register plugin"); testOk(!chfPluginRegister("arr", &myPif, opts), "register fake arr plugin"); @@ -124,16 +124,8 @@ MAIN(chfPluginTest) TESTGOOD("range with incr [s:i:e]", "[2:3:4]", 2, 3, 4); dbFreeBase(pdbbase); + registryFree(); + pdbbase=0; return testDone(); } - - -#define GEN_SIZE_OFFSET -#include "xRecord.h" - -#include -#include - -static rset xRSET; -epicsExportAddress(rset,xRSET); diff --git a/src/ioc/db/test/chfPluginTest.c b/src/ioc/db/test/chfPluginTest.c index 20db71830..89d39f8c9 100644 --- a/src/ioc/db/test/chfPluginTest.c +++ b/src/ioc/db/test/chfPluginTest.c @@ -15,6 +15,7 @@ #include "chfPlugin.h" #include "dbStaticLib.h" #include "dbAccessDefs.h" +#include "registry.h" #include "epicsUnitTest.h" #include "testMain.h" @@ -462,14 +463,14 @@ static void testHead (char* title) { testDiag("--------------------------------------------------------"); } -void xRecord_registerRecordDeviceDriver(struct dbBase *); +int loadTestDB(DBBASE **ppbase); MAIN(chfPluginTest) { dbChannel *pch; db_field_log *pfl; - testPlan(1351); + testPlan(1353); db_init_events(); @@ -484,12 +485,10 @@ MAIN(chfPluginTest) testOk(strcmp(chfPluginEnumString(colorEnum, 3, "-"), "-") == 0, "Enum to string: invalid index"); - if (dbReadDatabase(&pdbbase, "xRecord.dbd", "..", NULL)) - testAbort("Database description not loaded"); - - xRecord_registerRecordDeviceDriver(pdbbase); - if (dbReadDatabase(&pdbbase, "dbChannelTest.db", "..", NULL)) - testAbort("Test database not loaded"); + testHead("Set up database"); + if(loadTestDB(&pdbbase)) + return testDone(); + testOk(!!pdbbase, "pdbbase was set"); testHead("Try to register buggy plugins"); testOk(!!chfPluginRegister("buggy", &myPif, brokenOpts1), @@ -818,15 +817,8 @@ MAIN(chfPluginTest) drop = -1; dbFreeBase(pdbbase); + registryFree(); + pdbbase=0; return testDone(); } - -#define GEN_SIZE_OFFSET -#include "xRecord.h" - -#include -#include - -static rset xRSET; -epicsExportAddress(rset,xRSET); diff --git a/src/ioc/db/test/dbChannelTest.c b/src/ioc/db/test/dbChannelTest.c index 94de616f7..dab486b9d 100644 --- a/src/ioc/db/test/dbChannelTest.c +++ b/src/ioc/db/test/dbChannelTest.c @@ -16,6 +16,7 @@ #include "dbChannel.h" #include "dbStaticLib.h" #include "dbAccessDefs.h" +#include "registry.h" #include "recSup.h" #include "epicsUnitTest.h" #include "testMain.h" @@ -147,20 +148,18 @@ chFilterIf testIf = p_string, p_start_map, p_map_key, p_end_map, p_start_array, p_end_array, c_open, c_reg_pre, c_reg_post, c_report, c_close }; -void xRecord_registerRecordDeviceDriver(struct dbBase *); +int loadTestDB(DBBASE **ppbase); MAIN(testDbChannel) /* dbChannelTest is an API routine... */ { dbChannel *pch; - testPlan(66); + testPlan(68); - if (dbReadDatabase(&pdbbase, "xRecord.dbd", "..", NULL)) - testAbort("Database description not loaded"); + if(loadTestDB(&pdbbase)) + return testDone(); - xRecord_registerRecordDeviceDriver(pdbbase); - if (dbReadDatabase(&pdbbase, "dbChannelTest.db", "..", NULL)) - testAbort("Test database not loaded"); + testOk(!!pdbbase, "pdbbase was set"); r = e = 0; /* dbChannelTest() checks record and field names */ @@ -247,15 +246,8 @@ MAIN(testDbChannel) /* dbChannelTest is an API routine... */ testOk1(!dbChannelCreate("x.{\"scalar\":{}}")); dbFreeBase(pdbbase); + registryFree(); + pdbbase=0; return testDone(); } - -#define GEN_SIZE_OFFSET -#include "xRecord.h" - -#include -#include - -static rset xRSET; -epicsExportAddress(rset,xRSET); diff --git a/src/ioc/db/test/dbChannelTest.db b/src/ioc/db/test/dbChannelTest.db deleted file mode 100644 index a6fa08e40..000000000 --- a/src/ioc/db/test/dbChannelTest.db +++ /dev/null @@ -1,2 +0,0 @@ -record(x, x) {} - diff --git a/src/ioc/db/test/epicsRunDbTests.c b/src/ioc/db/test/epicsRunDbTests.c index 0b747abc2..d8633702e 100644 --- a/src/ioc/db/test/epicsRunDbTests.c +++ b/src/ioc/db/test/epicsRunDbTests.c @@ -17,12 +17,20 @@ #include "dbmf.h" int callbackTest(void); +int dbStateTest(void); +int testDbChannel(void); +int chfPluginTest(void); +int arrShorthandTest(void); void epicsRunDbTests(void) { testHarness(); runTest(callbackTest); + runTest(dbStateTest); + runTest(testDbChannel); + runTest(chfPluginTest); + runTest(arrShorthandTest); dbmfFreeChunks(); diff --git a/src/ioc/db/test/xRecord.c b/src/ioc/db/test/xRecord.c new file mode 100644 index 000000000..a8dc1ef0d --- /dev/null +++ b/src/ioc/db/test/xRecord.c @@ -0,0 +1,132 @@ + +#include +#include + +#include "epicsTypes.h" +#include "dbBase.h" +#include "devSup.h" +#include "registryCommon.h" +#include "registryRecordType.h" +#include "dbStaticLib.h" + +#include "epicsUnitTest.h" + +/* + * Test database initialization + */ + +/* No actual record support code is provided */ +static rset xRSET; + +/* the following would normally be found in xRecord.h */ + +typedef struct xRecord { + char name[61]; /* Record Name */ + epicsInt32 val; /* Value */ +} xRecord; + +typedef enum { + xRecordNAME = 0, + xRecordVAL = 1 +} xFieldIndex; + +static int xRecordSizeOffset(dbRecordType *prt) +{ + xRecord *prec = 0; + prt->papFldDes[xRecordNAME]->size = sizeof(prec->name); + prt->papFldDes[xRecordVAL]->size = sizeof(prec->val); + prt->papFldDes[xRecordNAME]->offset = (char *)&prec->name - (char *)prec; + prt->papFldDes[xRecordVAL]->offset = (char *)&prec->val - (char *)prec; + prt->rec_size = sizeof(*prec); + return 0; +} + +/* the following would normally be found in xRecord_registerRecordDeviceDriver.cpp */ + +static const char * const recordTypeNames[] = { + "x" +}; + +static const recordTypeLocation rtl[] = { + {&xRSET, &xRecordSizeOffset} +}; + +/* the following wpuld normally be the contents of xRecord.dbd */ + +static const char xRecord_dbd[] = +"# This is a combined minimal DBD and DB file\n" +"\n" +"recordtype(x) {\n" +" field(NAME, DBF_STRING) {\n" +" prompt(\"Record Name\")\n" +" special(SPC_NOMOD)\n" +" size(61)\n" +" }\n" +" field(VAL, DBF_LONG) {\n" +" prompt(\"Value\")\n" +" }\n" +"}\n"; + +/* the following is a db file which loads a single record instance */ + +static const char recinst_db[] = "record(x, x) {}\n"; + +/* The remainder of this file is specific to the test database initialization */ + +static FILE* makefile(const char* contents) +{ + size_t len=strlen(contents); + FILE *fp=epicsTempFile(); + if(!fp) { + perror("epicsTempFile fails"); + return NULL; + } + + if(fwrite(contents, 1, len, fp)!=len){ + perror("makefile fwrite failed"); + goto fail; + } + + if(fseek(fp, 0, SEEK_SET)!=0) + goto fail; + + return fp; +fail: + fclose(fp); + return NULL; +} + +int loadTestDB(DBBASE **ppbase) +{ + FILE *fp=makefile(xRecord_dbd); + if(!fp) { + testFail("Failed to create temp xRecord.dbd"); + return -1; + } + + if(dbReadDatabaseFP(ppbase, fp, 0, 0)) { + testFail("Failed to load temp xRecord.dbd"); + goto fail; + } + /* fp closed by dbReadDatabaseFP */ + + registerRecordTypes(*ppbase, NELEMENTS(rtl), recordTypeNames, rtl); + + fp=makefile(recinst_db); + if(!fp) { + testFail("Failed to create temp xinst.db"); + return -1; + } + + if(dbReadDatabaseFP(ppbase, fp, 0, 0)) { + testFail("Failed to load temp xinst.db"); + goto fail; + } + /* fp closed by dbReadDatabaseFP */ + + testPass("Loaded test database"); + return 0; +fail: + fclose(fp); + return -1; +} diff --git a/src/ioc/db/test/xRecord.dbd b/src/ioc/db/test/xRecord.dbd deleted file mode 100644 index 4837871a4..000000000 --- a/src/ioc/db/test/xRecord.dbd +++ /dev/null @@ -1,12 +0,0 @@ -# This is a combined minimal DBD and DB file - -recordtype(x) { - field(NAME, DBF_STRING) { - prompt("Record Name") - special(SPC_NOMOD) - size(61) - } - field(VAL, DBF_LONG) { - prompt("Value") - } -} From 4a6216534ca8344de988ae1644e339b9c76276fa Mon Sep 17 00:00:00 2001 From: Michael Davidsaver Date: Thu, 28 Jun 2012 10:55:46 -0400 Subject: [PATCH 03/21] rtems test harness setup to create temp files Apparently the default location for tmp files doesn't exist in the default IMFS tree. --- src/ioc/db/test/rtemsTestHarness.c | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/src/ioc/db/test/rtemsTestHarness.c b/src/ioc/db/test/rtemsTestHarness.c index c9ab2a68c..c72122b67 100644 --- a/src/ioc/db/test/rtemsTestHarness.c +++ b/src/ioc/db/test/rtemsTestHarness.c @@ -5,10 +5,32 @@ * in file LICENSE that is included with this distribution. \*************************************************************************/ + +#ifdef __rtems__ + +#include +#include +#include +#include + +#endif /* __rtems__ */ + extern void epicsRunDbTests(void); int main(int argc, char **argv) { +#ifdef __rtems__ + struct stat s; + printf("Try to create /tmp\n"); + umask(0); + if(mkdir("/tmp", 0777)!=0) + perror("Can't create /tmp"); + if(stat("/tmp", &s)==0) { + printf("Stat /tmp: %o %u,%u\n", s.st_mode, s.st_uid, s.st_gid); + } + epicsEnvSet("TMPDIR","/tmp"); +#endif + epicsRunDbTests(); /* calls epicsExit(0) */ return 0; } From 8eedb093952ff31dfba75ba53fb194f630663412 Mon Sep 17 00:00:00 2001 From: Michael Davidsaver Date: Thu, 28 Jun 2012 10:55:47 -0400 Subject: [PATCH 04/21] chfPluginTest: more verbose error messages --- src/ioc/db/test/chfPluginTest.c | 23 +++++++++++++++-------- 1 file changed, 15 insertions(+), 8 deletions(-) diff --git a/src/ioc/db/test/chfPluginTest.c b/src/ioc/db/test/chfPluginTest.c index 89d39f8c9..aaffc0b7b 100644 --- a/src/ioc/db/test/chfPluginTest.c +++ b/src/ioc/db/test/chfPluginTest.c @@ -446,15 +446,22 @@ static chfPluginIf postPif = { static int checkValues(myStruct *my, epicsUInt32 i, int f, double d, char *s, int c) { + int ret = 1; if (!my) return 0; - if (my->sent1 == PATTERN && my->sent2 == PATTERN && my->sent3 == PATTERN - && my->sent4 == PATTERN && my->sent5 == PATTERN && my->sent6 == PATTERN - && my->ival == i && my->flag == f && my->dval == d && my->enumval == c - && (strcmp(s, my->str) == 0)) { - return 1; - } else { - return 0; - } +#define CHK(A,B,FMT) if((A)!=(B)) {testDiag("Fail: " #A " (" FMT ") != " #B " (" FMT")", A, B); ret=0;} + CHK(my->sent1, PATTERN, "%08x") + CHK(my->sent2, PATTERN, "%08x") + CHK(my->sent3, PATTERN, "%08x") + CHK(my->sent4, PATTERN, "%08x") + CHK(my->sent5, PATTERN, "%08x") + CHK(my->sent6, PATTERN, "%08x") + CHK(my->ival, i, "%08x") + CHK(my->flag, f, "%02x") + CHK(my->dval, d, "%f") + CHK(my->enumval, c, "%d") +#undef CHK + if(strcmp(s, my->str) != 0) {testDiag("Fail: my->str (%s) != s (%s)", my->str, s); ret=0;} + return ret; } static void testHead (char* title) { From 4a393a428dde681b4558e7ce256cf8647a4ed0fd Mon Sep 17 00:00:00 2001 From: Michael Davidsaver Date: Thu, 28 Jun 2012 10:55:47 -0400 Subject: [PATCH 05/21] fix examples in chfPlugin.h --- src/ioc/db/chfPlugin.h | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/ioc/db/chfPlugin.h b/src/ioc/db/chfPlugin.h index 7d9745d10..99739aab8 100644 --- a/src/ioc/db/chfPlugin.h +++ b/src/ioc/db/chfPlugin.h @@ -44,11 +44,12 @@ struct db_field_log; * * typedef struct myStruct { * ... other stuff - * epicsUInt32 ival; + * epicsInt32 ival; * double dval; - * epicsUInt32 ival2; + * epicsInt32 ival2; * int enumval; * char strval[20]; + * char boolval; * } myStruct; * * static const @@ -61,6 +62,7 @@ struct db_field_log; * chfDouble(myStruct, dval, "Double" , 1, 0), * chfString(myStruct, strval , "String" , 1, 0), * chfEnum (myStruct, enumval, "Color" , 1, 0, colorEnum), + * chfBoolean(myStruct, boolval, "Bool" , 1, 0), * chfPluginEnd * }; * From 61b285a5e39ab60e49095c41c8921333362ca413 Mon Sep 17 00:00:00 2001 From: Michael Davidsaver Date: Thu, 28 Jun 2012 10:55:48 -0400 Subject: [PATCH 06/21] booleans are stored as char not int --- src/ioc/db/chfPlugin.c | 22 ++++++++++------------ 1 file changed, 10 insertions(+), 12 deletions(-) diff --git a/src/ioc/db/chfPlugin.c b/src/ioc/db/chfPlugin.c index 4516950e0..81ef33509 100644 --- a/src/ioc/db/chfPlugin.c +++ b/src/ioc/db/chfPlugin.c @@ -89,8 +89,8 @@ static int store_integer_value(const chfPluginArgDef *opt, void *user, long val) *ival = val; break; case chfPluginArgBoolean: - eval = (int*) ((char*)user + opt->offset); - *eval = !!val; + sval = (char*) ((char*)user + opt->offset); + *sval = !!val; break; case chfPluginArgDouble: dval = (double*) ((char*)user + opt->offset); @@ -130,7 +130,6 @@ static int store_integer_value(const chfPluginArgDef *opt, void *user, long val) static int store_boolean_value(const chfPluginArgDef *opt, void *user, int val) { epicsInt32 *ival; - int *eval; double *dval; char *sval; @@ -146,8 +145,8 @@ static int store_boolean_value(const chfPluginArgDef *opt, void *user, int val) *ival = val; break; case chfPluginArgBoolean: - eval = (int*) ((char*)user + opt->offset); - *eval = val; + sval = (char*) ((char*)user + opt->offset); + *sval = val; break; case chfPluginArgDouble: dval = (double*) ((char*)user + opt->offset); @@ -175,7 +174,6 @@ static int store_boolean_value(const chfPluginArgDef *opt, void *user, int val) static int store_double_value(const chfPluginArgDef *opt, void *user, double val) { epicsInt32 *ival; - int *eval; double *dval; char *sval; int i; @@ -199,8 +197,8 @@ static int store_double_value(const chfPluginArgDef *opt, void *user, double val *ival = val; break; case chfPluginArgBoolean: - eval = (int*) ((char*)user + opt->offset); - *eval = (val != 0.) ? 1 : 0; + sval = (char*) ((char*)user + opt->offset); + *sval = (val != 0.) ? 1 : 0; break; case chfPluginArgDouble: dval = (double*) ((char*)user + opt->offset); @@ -259,17 +257,17 @@ static int store_string_value(const chfPluginArgDef *opt, void *user, const char *ival = lval; break; case chfPluginArgBoolean: - eval = (int*) ((char*)user + opt->offset); + sval = (char*) ((char*)user + opt->offset); if (epicsStrnCaseCmp(val, "true", len) == 0) { - *eval = 1; + *sval = 1; } else if (epicsStrnCaseCmp(val, "false", len) == 0) { - *eval = 0; + *sval = 0; } else { i = strtol(val, &end, 0); if (i > INT_MAX || i < INT_MIN || end == val) { return -1; } - *eval = !!i; + *sval = !!i; } break; case chfPluginArgDouble: From 683093222ae438901bc9349c922e00299629e54e Mon Sep 17 00:00:00 2001 From: Michael Davidsaver Date: Thu, 28 Jun 2012 10:55:49 -0400 Subject: [PATCH 07/21] integer type should be epicsInt32 Can't use long for this on 64-bit systems --- src/ioc/db/chfPlugin.c | 34 +++++++++++++++++----------------- 1 file changed, 17 insertions(+), 17 deletions(-) diff --git a/src/ioc/db/chfPlugin.c b/src/ioc/db/chfPlugin.c index 81ef33509..c4e5c150f 100644 --- a/src/ioc/db/chfPlugin.c +++ b/src/ioc/db/chfPlugin.c @@ -65,10 +65,10 @@ typedef enum chfPluginType { } chfPluginType; /* - * Convert the (long) integer value 'val' to the type named in 'opt->optType' + * Convert the (epicsInt32) integer value 'val' to the type named in 'opt->optType' * and store the result at 'user + opt->offset'. */ -static int store_integer_value(const chfPluginArgDef *opt, void *user, long val) +static int store_integer_value(const chfPluginArgDef *opt, void *user, epicsInt32 val) { epicsInt32 *ival; int *eval; @@ -98,7 +98,7 @@ static int store_integer_value(const chfPluginArgDef *opt, void *user, long val) break; case chfPluginArgString: sval = ((char*)user + opt->offset); - sprintf(buff, "%ld", val); + sprintf(buff, "%ld", (long)val); if (strlen(buff) > opt->size-1) { return -1; } @@ -188,13 +188,11 @@ static int store_double_value(const chfPluginArgDef *opt, void *user, double val switch (opt->optType) { case chfPluginArgInt32: -#if (LONG_MAX > 0x7fffffff) - if (val < -0x80000000L || val > 0x7fffffff) { + if (val < INT_MIN || val > INT_MAX) { return -1; } -#endif ival = (epicsInt32 *) ((char*)user + opt->offset); - *ival = val; + *ival = (epicsInt32) val; break; case chfPluginArgBoolean: sval = (char*) ((char*)user + opt->offset); @@ -244,17 +242,14 @@ static int store_string_value(const chfPluginArgDef *opt, void *user, const char switch (opt->optType) { case chfPluginArgInt32: - lval = strtol(val, &end, 0); - /* test for the myriad error conditions which strtol may use */ - if (lval == LONG_MAX || lval == LONG_MIN -#if (LONG_MAX > 0x7fffffff) - || lval < -0x80000000L || lval > 0x7fffffff -#endif - || end == val) { - return -1; - } ival = (epicsInt32 *) ((char*)user + opt->offset); + lval = strtol(val, &end, 0); *ival = lval; + /* test for the myriad error conditions which strtol may use */ + if (lval == LONG_MAX || lval == LONG_MIN || end == val) { + return -1; + } else if(*ival != lval) + return -1; break; case chfPluginArgBoolean: sval = (char*) ((char*)user + opt->offset); @@ -273,7 +268,7 @@ static int store_string_value(const chfPluginArgDef *opt, void *user, const char case chfPluginArgDouble: dval = (double*) ((char*)user + opt->offset); *dval = strtod(val, &end); - /* Indicates errors in the same manner as strtol */ + /* Indicates errors in the same manner as strtod */ if (*dval==HUGE_VALF||*dval==HUGE_VALL||end==val ) { return -1; @@ -411,6 +406,11 @@ static parse_result parse_integer(chFilter *filter, long integerVal) const chfPluginArgDef *opts = ((chfPlugin*)filter->plug->puser)->opts; chfFilter *f = (chfFilter*)filter->puser; + if(sizeof(long)>sizeof(epicsInt32)) { + epicsInt32 temp=integerVal; + if(integerVal !=temp) + return parse_stop; + } if (f->nextParam < 0 || store_integer_value(&opts[f->nextParam], f->puser, integerVal)) { return parse_stop; } else { From 4986c184c7e172aefb82f481944941c7172eb781 Mon Sep 17 00:00:00 2001 From: Michael Davidsaver Date: Thu, 28 Jun 2012 13:44:33 -0400 Subject: [PATCH 08/21] cleanup for dbRegisterFilter() --- src/ioc/db/chfPlugin.c | 9 +++++++++ src/ioc/db/dbChannel.h | 4 ++++ src/ioc/dbStatic/dbStaticLib.c | 12 ++++++++++++ 3 files changed, 25 insertions(+) diff --git a/src/ioc/db/chfPlugin.c b/src/ioc/db/chfPlugin.c index c4e5c150f..23bfdc6f9 100644 --- a/src/ioc/db/chfPlugin.c +++ b/src/ioc/db/chfPlugin.c @@ -523,11 +523,20 @@ static void channel_close(chFilter *filter) free(f); /* FIXME: Use a free-list */ } +static void plugin_free(void* puser) +{ + chfPlugin *p=puser; + free(p->required); + free(p); +} + /* * chFilterIf for the wrapper * we just support a simple one-level map, and no arrays */ static chFilterIf wrapper_fif = { + plugin_free, + parse_start, parse_abort, parse_end, diff --git a/src/ioc/db/dbChannel.h b/src/ioc/db/dbChannel.h index 2e50185aa..f646cac9d 100644 --- a/src/ioc/db/dbChannel.h +++ b/src/ioc/db/dbChannel.h @@ -72,6 +72,10 @@ typedef enum { /* These routines must be implemented by each filter plug-in */ typedef struct chFilterIf { + /* cleanup pointer passed to dbRegisterFilter(). + * Called during DB shutdown + */ + void (* priv_free)(void *puser); /* Parsing event handlers: */ parse_result (* parse_start)(chFilter *filter); /* If parse_start() returns parse_continue for a filter, one of diff --git a/src/ioc/dbStatic/dbStaticLib.c b/src/ioc/dbStatic/dbStaticLib.c index 2ef3c0585..f845c73e2 100644 --- a/src/ioc/dbStatic/dbStaticLib.c +++ b/src/ioc/dbStatic/dbStaticLib.c @@ -31,6 +31,7 @@ #include "epicsStdlib.h" #include "epicsString.h" #include "epicsStdio.h" +#include "dbChannel.h" #define epicsExportSharedSymbols #include "link.h" @@ -592,6 +593,8 @@ void epicsShareAPI dbFreeBase(dbBase *pdbbase) drvSup *pdrvSupNext; brkTable *pbrkTable; brkTable *pbrkTableNext; + chFilterPlugin *pfilt; + chFilterPlugin *pfiltNext; int i; DBENTRY dbentry; @@ -723,6 +726,15 @@ void epicsShareAPI dbFreeBase(dbBase *pdbbase) free((void *)pbrkTable); pbrkTable = pbrkTableNext; } + pfilt = (chFilterPlugin *)ellFirst(&pdbbase->filterList); + while(pfilt) { + pfiltNext = (chFilterPlugin *)ellNext(&pfilt->node); + free((char*)pfilt->name); + if(pfilt->fif->priv_free) + (*pfilt->fif->priv_free)(pfilt->puser); + free(pfilt); + pfilt = pfiltNext; + } gphFreeMem(pdbbase->pgpHash); dbPvdFreeMem(pdbbase); dbFreePath(pdbbase); From 2fd6004827a3a5baea7d05699d947990485fe772 Mon Sep 17 00:00:00 2001 From: Michael Davidsaver Date: Thu, 28 Jun 2012 13:57:24 -0400 Subject: [PATCH 09/21] forgot to remove TODO --- src/ioc/db/dbChannel.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ioc/db/dbChannel.c b/src/ioc/db/dbChannel.c index 4d5a3e968..9305f7da4 100644 --- a/src/ioc/db/dbChannel.c +++ b/src/ioc/db/dbChannel.c @@ -838,7 +838,7 @@ void dbRegisterFilter(const char *name, const chFilterIf *fif, void *puser) if (pgph) return; - pfilt = dbCalloc(1, sizeof(chFilterPlugin)); /* leaked */ + pfilt = dbCalloc(1, sizeof(chFilterPlugin)); pfilt->name = epicsStrDup(name); pfilt->fif = fif; pfilt->puser = puser; From bde52418b9ee80d25971671a6a9d04ca4d11e019 Mon Sep 17 00:00:00 2001 From: Andrew Johnson Date: Fri, 29 Jun 2012 10:09:56 -0500 Subject: [PATCH 10/21] Various fixes for vxWorks Provide a separate dbd file for each test. Don't require a writable filesystem. Simplfy xRecord.c again. --- src/ioc/db/test/Makefile | 63 +++++++----- src/ioc/db/test/arrShorthandTest.c | 18 ++-- src/ioc/db/test/arrShorthandTest.dbd | 1 + src/ioc/db/test/chfPluginTest.c | 19 ++-- src/ioc/db/test/chfPluginTest.dbd | 1 + src/ioc/db/test/dbChannelTest.c | 19 ++-- src/ioc/db/test/dbChannelTest.dbd | 1 + src/ioc/db/test/xRecord.c | 147 ++++----------------------- src/ioc/db/test/xRecord.db | 2 + src/ioc/db/test/xRecord.dbd | 12 +++ 10 files changed, 107 insertions(+), 176 deletions(-) create mode 100644 src/ioc/db/test/arrShorthandTest.dbd create mode 100644 src/ioc/db/test/chfPluginTest.dbd create mode 100644 src/ioc/db/test/dbChannelTest.dbd create mode 100644 src/ioc/db/test/xRecord.db create mode 100644 src/ioc/db/test/xRecord.dbd diff --git a/src/ioc/db/test/Makefile b/src/ioc/db/test/Makefile index c44226b04..2ba82c344 100644 --- a/src/ioc/db/test/Makefile +++ b/src/ioc/db/test/Makefile @@ -10,8 +10,8 @@ TOP=../../../.. include $(TOP)/configure/CONFIG -PROD_vxWorks += dbTestHarness -PROD_RTEMS += dbTestHarness +PROD_vxWorks += dbTestHarness chfPluginTest +PROD_RTEMS += dbTestHarness chfPluginTest PROD_LIBS = dbCore ca Com @@ -20,6 +20,36 @@ callbackTest_SRCS += callbackTest.c dbTestHarness_SRCS += callbackTest.c TESTS += callbackTest +TESTPROD_HOST += dbStateTest +dbStateTest_SRCS += dbStateTest.c +dbTestHarness_SRCS += dbStateTest.c +TESTS += dbStateTest + +TESTPROD_HOST += dbChannelTest +dbChannelTest_SRCS += xRecord.c +dbChannelTest_SRCS += dbChannelTest.c +dbChannelTest_SRCS += dbChannelTest_registerRecordDeviceDriver.cpp +dbTestHarness_SRCS += xRecord.c +dbTestHarness_SRCS += dbChannelTest.c +dbTestHarness_SRCS += dbChannelTest_registerRecordDeviceDriver.cpp +TESTS += dbChannelTest + +TESTPROD_HOST += chfPluginTest +chfPluginTest_SRCS += xRecord.c +chfPluginTest_SRCS += chfPluginTest.c +chfPluginTest_SRCS += chfPluginTest_registerRecordDeviceDriver.cpp +dbTestHarness_SRCS += chfPluginTest.c +dbTestHarness_SRCS += chfPluginTest_registerRecordDeviceDriver.cpp +TESTS += chfPluginTest + +TESTPROD_HOST += arrShorthandTest +arrShorthandTest_SRCS += xRecord.c +arrShorthandTest_SRCS += arrShorthandTest.c +arrShorthandTest_SRCS += arrShorthandTest_registerRecordDeviceDriver.cpp +dbTestHarness_SRCS += arrShorthandTest.c +dbTestHarness_SRCS += arrShorthandTest_registerRecordDeviceDriver.cpp +TESTS += arrShorthandTest + dbTestHarness_SRCS += epicsRunDbTests.c dbTestHarness_SRCS_RTEMS = rtemsTestHarness.c @@ -27,32 +57,9 @@ dbTestHarness_SRCS_RTEMS = rtemsTestHarness.c TESTSPEC_vxWorks = dbTestHarness.munch; epicsRunDbTests TESTSPEC_RTEMS = dbTestHarness.boot; epicsRunDbTests -TESTPROD_HOST += dbChannelTest -dbChannelTest_SRCS += dbChannelTest.c xRecord.c -dbTestHarness_SRCS += dbChannelTest.c -OBJS_IOC_vxWorks += dbChannelTest -TESTS += dbChannelTest - -TESTPROD_HOST += chfPluginTest -chfPluginTest_SRCS += chfPluginTest.c xRecord.c -dbTestHarness_SRCS += chfPluginTest.c -OBJS_IOC_vxWorks += chfPluginTest -TESTS += chfPluginTest - -TESTPROD_HOST += arrShorthandTest -arrShorthandTest_SRCS += arrShorthandTest.c xRecord.c -dbTestHarness_SRCS += arrShorthandTest.c -OBJS_IOC_vxWorks += arrShorthandTest -TESTS += arrShorthandTest - -TESTPROD_HOST += dbStateTest -dbStateTest_SRCS += dbStateTest.c -dbTestHarness_SRCS += dbStateTest.c -OBJS_IOC_vxWorks += dbStateTest -TESTS += dbStateTest - -dbTestHarness_SRCS += xRecord.c - TESTSCRIPTS_HOST += $(TESTS:%=%.t) include $(TOP)/configure/RULES + +# xRecord$(OBJ): $(COMMON_DIR)/xRecord.h +xRecord$(DEP): $(COMMON_DIR)/xRecord.h diff --git a/src/ioc/db/test/arrShorthandTest.c b/src/ioc/db/test/arrShorthandTest.c index 9957ff897..8eecb0dc3 100644 --- a/src/ioc/db/test/arrShorthandTest.c +++ b/src/ioc/db/test/arrShorthandTest.c @@ -24,6 +24,7 @@ #include "registry.h" #include "epicsUnitTest.h" #include "testMain.h" +#include "osiFileName.h" typedef struct myStruct { epicsInt32 start; @@ -76,21 +77,24 @@ static void testHead (char* title) { testDiag("--------------------------------------------------------"); } -int loadTestDB(DBBASE **ppbase); +void arrShorthandTest_registerRecordDeviceDriver(struct dbBase *); MAIN(arrShorthandTest) { dbChannel *pch; - testPlan(28); + testPlan(26); db_init_events(); - testHead("Set up database"); - if(loadTestDB(&pdbbase)) - return testDone(); + if (dbReadDatabase(&pdbbase, "arrShorthandTest.dbd", + "." OSI_PATH_LIST_SEPARATOR "..", NULL)) + testAbort("Database description not loaded"); - testOk(!!pdbbase, "pdbbase was set"); + arrShorthandTest_registerRecordDeviceDriver(pdbbase); + if (dbReadDatabase(&pdbbase, "xRecord.db", + "." OSI_PATH_LIST_SEPARATOR "..", NULL)) + testAbort("Test database not loaded"); testHead("Register plugin"); testOk(!chfPluginRegister("arr", &myPif, opts), "register fake arr plugin"); @@ -125,7 +129,7 @@ MAIN(arrShorthandTest) dbFreeBase(pdbbase); registryFree(); - pdbbase=0; + pdbbase = NULL; return testDone(); } diff --git a/src/ioc/db/test/arrShorthandTest.dbd b/src/ioc/db/test/arrShorthandTest.dbd new file mode 100644 index 000000000..7411d88b5 --- /dev/null +++ b/src/ioc/db/test/arrShorthandTest.dbd @@ -0,0 +1 @@ +include "xRecord.dbd" diff --git a/src/ioc/db/test/chfPluginTest.c b/src/ioc/db/test/chfPluginTest.c index aaffc0b7b..f8b87c81f 100644 --- a/src/ioc/db/test/chfPluginTest.c +++ b/src/ioc/db/test/chfPluginTest.c @@ -18,6 +18,7 @@ #include "registry.h" #include "epicsUnitTest.h" #include "testMain.h" +#include "osiFileName.h" #define PATTERN 0x55555555 #define TYPE_START 0xAAA @@ -470,14 +471,14 @@ static void testHead (char* title) { testDiag("--------------------------------------------------------"); } -int loadTestDB(DBBASE **ppbase); +void chfPluginTest_registerRecordDeviceDriver(struct dbBase *); MAIN(chfPluginTest) { dbChannel *pch; db_field_log *pfl; - testPlan(1353); + testPlan(1351); db_init_events(); @@ -492,10 +493,14 @@ MAIN(chfPluginTest) testOk(strcmp(chfPluginEnumString(colorEnum, 3, "-"), "-") == 0, "Enum to string: invalid index"); - testHead("Set up database"); - if(loadTestDB(&pdbbase)) - return testDone(); - testOk(!!pdbbase, "pdbbase was set"); + if (dbReadDatabase(&pdbbase, "chfPluginTest.dbd", + "." OSI_PATH_LIST_SEPARATOR "..", NULL)) + testAbort("Database description not loaded"); + + chfPluginTest_registerRecordDeviceDriver(pdbbase); + if (dbReadDatabase(&pdbbase, "xRecord.db", + "." OSI_PATH_LIST_SEPARATOR "..", NULL)) + testAbort("Test database not loaded"); testHead("Try to register buggy plugins"); testOk(!!chfPluginRegister("buggy", &myPif, brokenOpts1), @@ -825,7 +830,7 @@ MAIN(chfPluginTest) dbFreeBase(pdbbase); registryFree(); - pdbbase=0; + pdbbase = NULL; return testDone(); } diff --git a/src/ioc/db/test/chfPluginTest.dbd b/src/ioc/db/test/chfPluginTest.dbd new file mode 100644 index 000000000..7411d88b5 --- /dev/null +++ b/src/ioc/db/test/chfPluginTest.dbd @@ -0,0 +1 @@ +include "xRecord.dbd" diff --git a/src/ioc/db/test/dbChannelTest.c b/src/ioc/db/test/dbChannelTest.c index dab486b9d..6a5779f7b 100644 --- a/src/ioc/db/test/dbChannelTest.c +++ b/src/ioc/db/test/dbChannelTest.c @@ -20,6 +20,7 @@ #include "recSup.h" #include "epicsUnitTest.h" #include "testMain.h" +#include "osiFileName.h" /* Expected call bit definitions */ #define e_start 0x00000001 @@ -144,22 +145,26 @@ void c_close(chFilter *filter) } chFilterIf testIf = - { p_start, p_abort, p_end, p_null, p_boolean, p_integer, p_double, + { NULL, p_start, p_abort, p_end, p_null, p_boolean, p_integer, p_double, p_string, p_start_map, p_map_key, p_end_map, p_start_array, p_end_array, c_open, c_reg_pre, c_reg_post, c_report, c_close }; -int loadTestDB(DBBASE **ppbase); +void dbChannelTest_registerRecordDeviceDriver(struct dbBase *); MAIN(testDbChannel) /* dbChannelTest is an API routine... */ { dbChannel *pch; - testPlan(68); + testPlan(66); - if(loadTestDB(&pdbbase)) - return testDone(); + if (dbReadDatabase(&pdbbase, "dbChannelTest.dbd", + "." OSI_PATH_LIST_SEPARATOR "..", NULL)) + testAbort("Database description not loaded"); - testOk(!!pdbbase, "pdbbase was set"); + dbChannelTest_registerRecordDeviceDriver(pdbbase); + if (dbReadDatabase(&pdbbase, "xRecord.db", + "." OSI_PATH_LIST_SEPARATOR "..", NULL)) + testAbort("Test database not loaded"); r = e = 0; /* dbChannelTest() checks record and field names */ @@ -247,7 +252,7 @@ MAIN(testDbChannel) /* dbChannelTest is an API routine... */ dbFreeBase(pdbbase); registryFree(); - pdbbase=0; + pdbbase = NULL; return testDone(); } diff --git a/src/ioc/db/test/dbChannelTest.dbd b/src/ioc/db/test/dbChannelTest.dbd new file mode 100644 index 000000000..7411d88b5 --- /dev/null +++ b/src/ioc/db/test/dbChannelTest.dbd @@ -0,0 +1 @@ +include "xRecord.dbd" diff --git a/src/ioc/db/test/xRecord.c b/src/ioc/db/test/xRecord.c index a8dc1ef0d..568fbb838 100644 --- a/src/ioc/db/test/xRecord.c +++ b/src/ioc/db/test/xRecord.c @@ -1,132 +1,25 @@ - -#include -#include - -#include "epicsTypes.h" -#include "dbBase.h" -#include "devSup.h" -#include "registryCommon.h" -#include "registryRecordType.h" -#include "dbStaticLib.h" - -#include "epicsUnitTest.h" +/*************************************************************************\ +* Copyright (c) 2010 UChicago Argonne LLC, as Operator of Argonne +* National Laboratory. +* Copyright (c) 2010 Brookhaven National Laboratory. +* Copyright (c) 2010 Helmholtz-Zentrum Berlin +* fuer Materialien und Energie GmbH. +* EPICS BASE is distributed subject to a Software License Agreement found +* in file LICENSE that is included with this distribution. + \*************************************************************************/ /* - * Test database initialization + * Author: Andrew Johnson + * Ralph Lange */ -/* No actual record support code is provided */ +#include "dbAccessDefs.h" +#include + +#define GEN_SIZE_OFFSET +#include "xRecord.h" + +#include + static rset xRSET; - -/* the following would normally be found in xRecord.h */ - -typedef struct xRecord { - char name[61]; /* Record Name */ - epicsInt32 val; /* Value */ -} xRecord; - -typedef enum { - xRecordNAME = 0, - xRecordVAL = 1 -} xFieldIndex; - -static int xRecordSizeOffset(dbRecordType *prt) -{ - xRecord *prec = 0; - prt->papFldDes[xRecordNAME]->size = sizeof(prec->name); - prt->papFldDes[xRecordVAL]->size = sizeof(prec->val); - prt->papFldDes[xRecordNAME]->offset = (char *)&prec->name - (char *)prec; - prt->papFldDes[xRecordVAL]->offset = (char *)&prec->val - (char *)prec; - prt->rec_size = sizeof(*prec); - return 0; -} - -/* the following would normally be found in xRecord_registerRecordDeviceDriver.cpp */ - -static const char * const recordTypeNames[] = { - "x" -}; - -static const recordTypeLocation rtl[] = { - {&xRSET, &xRecordSizeOffset} -}; - -/* the following wpuld normally be the contents of xRecord.dbd */ - -static const char xRecord_dbd[] = -"# This is a combined minimal DBD and DB file\n" -"\n" -"recordtype(x) {\n" -" field(NAME, DBF_STRING) {\n" -" prompt(\"Record Name\")\n" -" special(SPC_NOMOD)\n" -" size(61)\n" -" }\n" -" field(VAL, DBF_LONG) {\n" -" prompt(\"Value\")\n" -" }\n" -"}\n"; - -/* the following is a db file which loads a single record instance */ - -static const char recinst_db[] = "record(x, x) {}\n"; - -/* The remainder of this file is specific to the test database initialization */ - -static FILE* makefile(const char* contents) -{ - size_t len=strlen(contents); - FILE *fp=epicsTempFile(); - if(!fp) { - perror("epicsTempFile fails"); - return NULL; - } - - if(fwrite(contents, 1, len, fp)!=len){ - perror("makefile fwrite failed"); - goto fail; - } - - if(fseek(fp, 0, SEEK_SET)!=0) - goto fail; - - return fp; -fail: - fclose(fp); - return NULL; -} - -int loadTestDB(DBBASE **ppbase) -{ - FILE *fp=makefile(xRecord_dbd); - if(!fp) { - testFail("Failed to create temp xRecord.dbd"); - return -1; - } - - if(dbReadDatabaseFP(ppbase, fp, 0, 0)) { - testFail("Failed to load temp xRecord.dbd"); - goto fail; - } - /* fp closed by dbReadDatabaseFP */ - - registerRecordTypes(*ppbase, NELEMENTS(rtl), recordTypeNames, rtl); - - fp=makefile(recinst_db); - if(!fp) { - testFail("Failed to create temp xinst.db"); - return -1; - } - - if(dbReadDatabaseFP(ppbase, fp, 0, 0)) { - testFail("Failed to load temp xinst.db"); - goto fail; - } - /* fp closed by dbReadDatabaseFP */ - - testPass("Loaded test database"); - return 0; -fail: - fclose(fp); - return -1; -} +epicsExportAddress(rset,xRSET); diff --git a/src/ioc/db/test/xRecord.db b/src/ioc/db/test/xRecord.db new file mode 100644 index 000000000..a6fa08e40 --- /dev/null +++ b/src/ioc/db/test/xRecord.db @@ -0,0 +1,2 @@ +record(x, x) {} + diff --git a/src/ioc/db/test/xRecord.dbd b/src/ioc/db/test/xRecord.dbd new file mode 100644 index 000000000..4837871a4 --- /dev/null +++ b/src/ioc/db/test/xRecord.dbd @@ -0,0 +1,12 @@ +# This is a combined minimal DBD and DB file + +recordtype(x) { + field(NAME, DBF_STRING) { + prompt("Record Name") + special(SPC_NOMOD) + size(61) + } + field(VAL, DBF_LONG) { + prompt("Value") + } +} From aa17f317f86db420f95ef892401320a119bc113c Mon Sep 17 00:00:00 2001 From: Michael Davidsaver Date: Fri, 29 Jun 2012 17:02:20 -0400 Subject: [PATCH 11/21] define more of probe field log plugins don't need to inspect more than field_type, field_size, and no_elements. In case they do define type=val to prevent accidental use of uninitialized pointer. --- src/ioc/db/dbChannel.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/ioc/db/dbChannel.c b/src/ioc/db/dbChannel.c index 9305f7da4..d27527b37 100644 --- a/src/ioc/db/dbChannel.c +++ b/src/ioc/db/dbChannel.c @@ -584,6 +584,8 @@ long dbChannelOpen(dbChannel *chan) } /* Set up type probe */ + probe.type = dbfl_type_val; + probe.ctx = dbfl_context_read; probe.field_type = dbChannelFieldType(chan); probe.no_elements = dbChannelElements(chan); probe.field_size = dbChannelFieldSize(chan); From e6ae903f2c16977eaf9a209fc4ceee724e05d8fc Mon Sep 17 00:00:00 2001 From: Michael Davidsaver Date: Fri, 29 Jun 2012 17:02:22 -0400 Subject: [PATCH 12/21] notes on db_field_log usage --- src/ioc/db/db_field_log.h | 32 ++++++++++++++++++++++++++++++++ 1 file changed, 32 insertions(+) diff --git a/src/ioc/db/db_field_log.h b/src/ioc/db/db_field_log.h index 1f1d212d0..0a503744f 100644 --- a/src/ioc/db/db_field_log.h +++ b/src/ioc/db/db_field_log.h @@ -73,6 +73,13 @@ struct dbfl_val { union native_value field; /* Field value */ }; +/* External data reference. + * If dtor is provided then it should be called when the referenced + * data is no longer needed. This is done automatically by + * db_delete_field_log(). Any code which changes a dbfl_type_ref + * field log to another type, or to reference different data, + * must explicitly call the dtor function. + */ struct dbfl_ref { dbfl_freeFunc *dtor; /* Callback to free filter-allocated resources */ void *pvt; /* Private pointer */ @@ -81,7 +88,9 @@ struct dbfl_ref { typedef struct db_field_log { enum dbfl_type type:2; /* type (union) selector */ + /* ctx is used for all types */ enum dbfl_context ctx:1; /* context (operation type) */ + /* the following are used for value and reference types */ epicsTimeStamp time; /* Time stamp */ unsigned short stat; /* Alarm Status */ unsigned short sevr; /* Alarm Severity */ @@ -94,6 +103,29 @@ typedef struct db_field_log { } u; } db_field_log; +/* + * A db_field_log will in one of three types: + * + * dbfl_type_rec - Reference to record + * The field log stores no data itself. Data must instead be taken + * via the dbChannel* which must always be provided when along + * with the field log. + * For this type only the 'type' and 'ctx' members are used. + * + * dbfl_type_ref - Reference to outside value + * Used for variable size (array) data types. Meta-data + * is stored in the field log, but value data is stored externally + * (see struct dbfl_ref). + * For this type all meta-data members are used. The dbfl_ref side of the + * data union is used. + * + * dbfl_type_val - Internal value + * Used to store small scalar data. Meta-data and value are + * present in this structure and no external references are used. + * For this type all meta-data members are used. The dbfl_val side of the + * data union is used. + */ + #ifdef __cplusplus } #endif From a103a2434a33f138ee379f7e245d785c4fb6fb13 Mon Sep 17 00:00:00 2001 From: Michael Davidsaver Date: Fri, 29 Jun 2012 17:02:22 -0400 Subject: [PATCH 13/21] dbEvent don't queue dropped events --- src/ioc/db/dbEvent.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ioc/db/dbEvent.c b/src/ioc/db/dbEvent.c index 6fbb9a03a..8b6cb06c3 100644 --- a/src/ioc/db/dbEvent.c +++ b/src/ioc/db/dbEvent.c @@ -824,7 +824,7 @@ void epicsShareAPI db_post_single_event (dbEventSubscription event) pLog = db_create_event_log(pevent); pLog = dbChannelRunPreChain(pevent->chan, pLog); - db_queue_event_log(pevent, pLog); + if(pLog) db_queue_event_log(pevent, pLog); dbScanUnlock (prec); } From 46fb21c88036283cecd3caffed8ad98ac3921dcf Mon Sep 17 00:00:00 2001 From: Michael Davidsaver Date: Fri, 29 Jun 2012 17:02:22 -0400 Subject: [PATCH 14/21] dbnd must free dropped events --- src/std/filters/dbnd.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/std/filters/dbnd.c b/src/std/filters/dbnd.c index 33e79198d..5056185ee 100644 --- a/src/std/filters/dbnd.c +++ b/src/std/filters/dbnd.c @@ -93,8 +93,10 @@ static db_field_log* filter(void* pvt, dbChannel *chan, db_field_log *pfl) { } } } - if (drop) return NULL; - else return pfl; + if (drop) { + db_delete_field_log(pfl); + return NULL; + } else return pfl; } static void channelRegisterPre(dbChannel *chan, void *pvt, From d2b0e920012d4c9bc0eaecc0e092cedd776db578 Mon Sep 17 00:00:00 2001 From: Michael Davidsaver Date: Fri, 29 Jun 2012 17:02:23 -0400 Subject: [PATCH 15/21] db_close_events cleanup Move cleanup from event thread to caller. This handles cases (unit tests) where the task is never started. The pexitsem flag serves as the indicatior that the event task was started. --- src/ioc/db/dbEvent.c | 78 ++++++++++++++++++++++++++++---------------- 1 file changed, 50 insertions(+), 28 deletions(-) diff --git a/src/ioc/db/dbEvent.c b/src/ioc/db/dbEvent.c index 8b6cb06c3..24d81a04a 100644 --- a/src/ioc/db/dbEvent.c +++ b/src/ioc/db/dbEvent.c @@ -74,6 +74,7 @@ struct event_user { epicsMutexId lock; epicsEventId ppendsem; /* Wait while empty */ epicsEventId pflush_sem; /* wait for flush */ + epicsEventId pexitsem; /* wait for event task to join */ EXTRALABORFUNC *extralabor_sub;/* off load to event task */ void *extralabor_arg;/* parameter to above */ @@ -276,35 +277,44 @@ dbEventCtx epicsShareAPI db_init_events (void) return NULL; } + /* Flag will be cleared when event task starts */ + evUser->pendexit = TRUE; + evUser->firstque.evUser = evUser; evUser->firstque.writelock = epicsMutexCreate(); - if (!evUser->firstque.writelock) { - return NULL; - } + if (!evUser->firstque.writelock) + goto fail; evUser->ppendsem = epicsEventCreate(epicsEventEmpty); - if (!evUser->ppendsem) { - epicsMutexDestroy (evUser->firstque.writelock); - return NULL; - } + if (!evUser->ppendsem) + goto fail; evUser->pflush_sem = epicsEventCreate(epicsEventEmpty); - if (!evUser->pflush_sem) { - epicsMutexDestroy (evUser->firstque.writelock); - epicsEventDestroy (evUser->ppendsem); - return NULL; - } + if (!evUser->pflush_sem) + goto fail; evUser->lock = epicsMutexCreate(); - if (!evUser->lock) { - epicsMutexDestroy (evUser->firstque.writelock); - epicsEventDestroy (evUser->pflush_sem); - epicsEventDestroy (evUser->ppendsem); - return NULL; - } + if (!evUser->lock) + goto fail; + evUser->pexitsem = epicsEventCreate(epicsEventEmpty); + if (!evUser->pexitsem) + goto fail; evUser->flowCtrlMode = FALSE; evUser->extraLaborBusy = FALSE; evUser->pSuicideEvent = NULL; return (dbEventCtx) evUser; +fail: + if(evUser->lock) + epicsMutexDestroy (evUser->lock); + if(evUser->firstque.writelock) + epicsMutexDestroy (evUser->firstque.writelock); + if(evUser->ppendsem) + epicsEventDestroy (evUser->ppendsem); + if(evUser->pflush_sem) + epicsEventDestroy (evUser->pflush_sem); + if(evUser->pexitsem) + epicsEventDestroy (evUser->pexitsem); + freeListFree(dbevEventUserFreeList,evUser); + return NULL; } /* @@ -328,10 +338,26 @@ void epicsShareAPI db_close_events (dbEventCtx ctx) * hazardous to the system's health. */ epicsMutexMustLock ( evUser->lock ); - evUser->pendexit = TRUE; + if(!evUser->pendexit) { /* event task running */ + evUser->pendexit = TRUE; + epicsMutexUnlock ( evUser->lock ); + + /* notify the waiting task */ + epicsEventSignal(evUser->ppendsem); + /* wait for task to exit */ + epicsEventMustWait(evUser->pexitsem); + + epicsMutexMustLock ( evUser->lock ); + } + epicsMutexUnlock ( evUser->lock ); - /* notify the waiting task */ - epicsEventSignal(evUser->ppendsem); + + epicsEventDestroy(evUser->pexitsem); + epicsEventDestroy(evUser->ppendsem); + epicsEventDestroy(evUser->pflush_sem); + epicsMutexDestroy(evUser->lock); + + freeListFree(dbevEventUserFreeList, evUser); } /* @@ -1006,14 +1032,10 @@ static void event_task (void *pParm) } } - epicsEventDestroy(evUser->ppendsem); - epicsEventDestroy(evUser->pflush_sem); - epicsMutexDestroy(evUser->lock); - - freeListFree(dbevEventUserFreeList, evUser); - taskwdRemove(epicsThreadGetIdSelf()); + epicsEventSignal(evUser->pexitsem); + return; } @@ -1037,7 +1059,6 @@ int epicsShareAPI db_start_events ( return DB_EVENT_OK; } - evUser->pendexit = FALSE; evUser->init_func = init_func; evUser->init_func_arg = init_func_arg; if (!taskname) { @@ -1051,6 +1072,7 @@ int epicsShareAPI db_start_events ( epicsMutexUnlock ( evUser->lock ); return DB_EVENT_ERROR; } + evUser->pendexit = FALSE; epicsMutexUnlock ( evUser->lock ); return DB_EVENT_OK; } From 60b684a4dc8a36d35ecb931960f1df650265f0bd Mon Sep 17 00:00:00 2001 From: Michael Davidsaver Date: Fri, 29 Jun 2012 17:02:24 -0400 Subject: [PATCH 16/21] update dbndTest --- src/std/filters/test/dbndTest.c | 64 ++++++++++++++++++++++++++++++--- 1 file changed, 60 insertions(+), 4 deletions(-) diff --git a/src/std/filters/test/dbndTest.c b/src/std/filters/test/dbndTest.c index 18cccc361..c4becd18d 100644 --- a/src/std/filters/test/dbndTest.c +++ b/src/std/filters/test/dbndTest.c @@ -16,9 +16,11 @@ #include "dbAccessDefs.h" #include "db_field_log.h" #include "dbCommon.h" +#include "registry.h" #include "chfPlugin.h" #include "epicsUnitTest.h" #include "epicsTime.h" +#include "dbmf.h" #include "testMain.h" #define PATTERN 0x55 @@ -109,10 +111,11 @@ MAIN(dbndTest) void *arg_out = NULL; db_field_log *pfl2; db_field_log fl1; + dbEventCtx evtctx; testPlan(59); - db_init_events(); + evtctx = db_init_events(); if (dbReadDatabase(&pdbbase, "xRecord.dbd", "..", NULL)) testAbort("Database description not loaded"); @@ -160,9 +163,13 @@ MAIN(dbndTest) fl_setup(pch, pfl2); mustPassOnce(pch, pfl2, "abs", 0., 0); + + pfl2 = db_create_read_log(pch); + testDiag("new field_log from record"); + fl_setup(pch, pfl2); + mustPassOnce(pch, pfl2, "abs", 0., 1); - db_delete_field_log(pfl2); dbChannelDelete(pch); /* Delta = -1: pass any update */ @@ -192,11 +199,25 @@ MAIN(dbndTest) fl_setup(pch, pfl2); mustPassOnce(pch, pfl2, "abs", 3., 1); + + pfl2 = db_create_read_log(pch); + testDiag("new field_log from record"); + fl_setup(pch, pfl2); + mustDrop(pch, pfl2, "abs", 3., 3); + + pfl2 = db_create_read_log(pch); + testDiag("new field_log from record"); + fl_setup(pch, pfl2); + mustDrop(pch, pfl2, "abs", 3., 4); + + pfl2 = db_create_read_log(pch); + testDiag("new field_log from record"); + fl_setup(pch, pfl2); + mustPassOnce(pch, pfl2, "abs", 3., 5); - db_delete_field_log(pfl2); dbChannelDelete(pch); /* Delta = relative */ @@ -211,16 +232,51 @@ MAIN(dbndTest) fl_setup(pch, pfl2); mustPassOnce(pch, pfl2, "rel", 50., 1); + + pfl2 = db_create_read_log(pch); + testDiag("new field_log from record"); + fl_setup(pch, pfl2); + mustPassOnce(pch, pfl2, "rel", 50., 2); + + pfl2 = db_create_read_log(pch); + testDiag("new field_log from record"); + fl_setup(pch, pfl2); + mustDrop(pch, pfl2, "rel", 50., 3); + + pfl2 = db_create_read_log(pch); + testDiag("new field_log from record"); + fl_setup(pch, pfl2); + mustPassOnce(pch, pfl2, "rel", 50., 4); + + pfl2 = db_create_read_log(pch); + testDiag("new field_log from record"); + fl_setup(pch, pfl2); + mustDrop(pch, pfl2, "rel", 50., 5); + + pfl2 = db_create_read_log(pch); + testDiag("new field_log from record"); + fl_setup(pch, pfl2); + mustDrop(pch, pfl2, "rel", 50., 6); + + pfl2 = db_create_read_log(pch); + testDiag("new field_log from record"); + fl_setup(pch, pfl2); + mustPassOnce(pch, pfl2, "rel", 50., 7); - db_delete_field_log(pfl2); dbChannelDelete(pch); dbFreeBase(pdbbase); + registryFree(); + pdbbase=0; + + db_close_events(evtctx); + + dbmfFreeChunks(); return testDone(); } From f5bad40474606b9f0ff8afc4869bfdca14ffee09 Mon Sep 17 00:00:00 2001 From: Michael Davidsaver Date: Fri, 29 Jun 2012 17:02:24 -0400 Subject: [PATCH 17/21] sync needs to free held events The sync plugin may hold an update internally. If this is done then it must be free'd when the dbChannel is closed. --- src/std/filters/sync.c | 2 ++ src/std/filters/test/syncTest.c | 35 ++++++++++++++++++++++++--------- 2 files changed, 28 insertions(+), 9 deletions(-) diff --git a/src/std/filters/sync.c b/src/std/filters/sync.c index 15c27b267..55ff9303a 100644 --- a/src/std/filters/sync.c +++ b/src/std/filters/sync.c @@ -59,6 +59,8 @@ static void * allocPvt(void) static void freePvt(void *pvt) { + myStruct *my = (myStruct*) pvt; + db_delete_field_log(my->lastfl); freeListFree(myStructFreeList, pvt); } diff --git a/src/std/filters/test/syncTest.c b/src/std/filters/test/syncTest.c index 11c772491..1f2d8b2ed 100644 --- a/src/std/filters/test/syncTest.c +++ b/src/std/filters/test/syncTest.c @@ -17,7 +17,9 @@ #include "db_field_log.h" #include "dbCommon.h" #include "dbChannel.h" +#include "registry.h" #include "chfPlugin.h" +#include "dbmf.h" #include "epicsUnitTest.h" #include "epicsTime.h" #include "dbState.h" @@ -136,10 +138,11 @@ MAIN(syncTest) char myname[] = "sync"; db_field_log *pfl[10]; int i; + dbEventCtx evtctx; testPlan(0); - db_init_events(); + evtctx = db_init_events(); if (dbReadDatabase(&pdbbase, "xRecord.dbd", "..", NULL)) testAbort("Database description not loaded"); @@ -194,6 +197,8 @@ MAIN(syncTest) for (i = 0; i < 10; i++) db_delete_field_log(pfl[i]); + dbChannelDelete(pch); + /* mode UNLESS */ testHead("Mode UNLESS (m='unless', s='red')"); @@ -225,6 +230,8 @@ MAIN(syncTest) for (i = 0; i < 10; i++) db_delete_field_log(pfl[i]); + dbChannelDelete(pch); + /* mode BEFORE */ testHead("Mode BEFORE (m='before', s='red')"); @@ -254,8 +261,9 @@ MAIN(syncTest) mustDrop(pch, pfl[8], "state=FALSE, log8"); mustDrop(pch, pfl[9], "state=FALSE, log9"); - for (i = 0; i < 10; i++) - db_delete_field_log(pfl[i]); + db_delete_field_log(pfl[2]); + + dbChannelDelete(pch); /* mode FIRST */ @@ -285,8 +293,10 @@ MAIN(syncTest) mustDrop(pch, pfl[7], "state=FALSE, log7"); mustDrop(pch, pfl[8], "state=FALSE, log8"); - for (i = 0; i < 10; i++) - db_delete_field_log(pfl[i]); + db_delete_field_log(pfl[3]); + db_delete_field_log(pfl[9]); + + dbChannelDelete(pch); /* mode LAST */ @@ -317,8 +327,9 @@ MAIN(syncTest) mustDrop(pch, pfl[8], "state=FALSE, log8"); mustDrop(pch, pfl[9], "state=FALSE, log9"); - for (i = 0; i < 10; i++) - db_delete_field_log(pfl[i]); + db_delete_field_log(pfl[5]); + + dbChannelDelete(pch); /* mode AFTER */ @@ -348,11 +359,17 @@ MAIN(syncTest) mustDrop(pch, pfl[7], "state=FALSE, log7"); mustDrop(pch, pfl[8], "state=FALSE, log8"); - for (i = 0; i < 10; i++) - db_delete_field_log(pfl[i]); + db_delete_field_log(pfl[6]); + db_delete_field_log(pfl[9]); dbChannelDelete(pch); dbFreeBase(pdbbase); + registryFree(); + pdbbase=0; + + db_close_events(evtctx); + + dbmfFreeChunks(); return testDone(); } From b5c223f462c6f8ae23c2789ee28097297275cb11 Mon Sep 17 00:00:00 2001 From: Michael Davidsaver Date: Fri, 29 Jun 2012 17:02:24 -0400 Subject: [PATCH 18/21] fix tsTest --- src/std/filters/test/tsTest.c | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/src/std/filters/test/tsTest.c b/src/std/filters/test/tsTest.c index 9c54063ce..708f1c2a7 100644 --- a/src/std/filters/test/tsTest.c +++ b/src/std/filters/test/tsTest.c @@ -16,6 +16,8 @@ #include "dbAccessDefs.h" #include "chfPlugin.h" #include "epicsUnitTest.h" +#include "registry.h" +#include "dbmf.h" #include "epicsTime.h" #include "testMain.h" @@ -50,10 +52,11 @@ MAIN(tsTest) db_field_log fl1; db_field_log *pfl2; epicsTimeStamp stamp, now; + dbEventCtx evtctx; testPlan(12); - db_init_events(); + evtctx = db_init_events(); if (dbReadDatabase(&pdbbase, "xRecord.dbd", "..", NULL)) testAbort("Database description not loaded"); @@ -92,6 +95,8 @@ MAIN(tsTest) testOk(!!(pfl2 = db_create_read_log(pch)), "create field log from channel"); stamp = pfl2->time; + db_delete_field_log(pfl2); + pfl2 = dbChannelRunPreChain(pch, &fl1); epicsTimeGetCurrent(&now); testOk(epicsTimeDiffInSeconds(&pfl2->time, &stamp) > 0. && @@ -99,6 +104,12 @@ MAIN(tsTest) dbChannelDelete(pch); dbFreeBase(pdbbase); + registryFree(); + pdbbase=0; + + db_close_events(evtctx); + + dbmfFreeChunks(); return testDone(); } From d6bda6fb3a894ae0d674f4e242d0d9c76e778bcb Mon Sep 17 00:00:00 2001 From: Michael Davidsaver Date: Fri, 29 Jun 2012 17:02:25 -0400 Subject: [PATCH 19/21] arrTest cleanup on exit Do test db cleanup after hooks registered by iocInit --- src/std/filters/test/arrTest.cpp | 25 ++++++++++++++++++------- 1 file changed, 18 insertions(+), 7 deletions(-) diff --git a/src/std/filters/test/arrTest.cpp b/src/std/filters/test/arrTest.cpp index 389b1fc9a..87c1a9602 100644 --- a/src/std/filters/test/arrTest.cpp +++ b/src/std/filters/test/arrTest.cpp @@ -28,6 +28,8 @@ #include "epicsStdio.h" #include "envDefs.h" #include "dbStaticLib.h" +#include "dbmf.h" +#include "registry.h" #include "subRecord.h" #include "dbAddr.h" #include "dbAccess.h" @@ -293,6 +295,19 @@ static void check(short dbr_type) { TEST5B(3, -8, -4, "both sides from-end"); } +static dbEventCtx evtctx; + +static void arrTestCleanup(void* junk) +{ + dbFreeBase(pdbbase); + registryFree(); + pdbbase=0; + + db_close_events(evtctx); + + dbmfFreeChunks(); +} + MAIN(arrTest) { const chFilterPlugin *plug; @@ -315,10 +330,12 @@ MAIN(arrTest) if (dbReadDatabase(&pdbbase, "arrTest.db", "..", NULL)) testAbort("Test database not loaded"); + epicsAtExit(&arrTestCleanup,NULL); + /* Start the IOC */ iocInit(); - db_init_events(); + evtctx = db_init_events(); epicsThreadSleep(0.2); testOk(!!(plug = dbFindFilter(arr, strlen(arr))), "plugin arr registered correctly"); @@ -327,11 +344,5 @@ MAIN(arrTest) check(DBR_DOUBLE); check(DBR_STRING); - dbFreeBase(pdbbase); - return testDone(); - - epicsExit(EXIT_SUCCESS); - /*Note that the following statement will never be executed*/ - return 0; } From 788d5a1ca1a44abff7b4191c34a162d3651cfbe9 Mon Sep 17 00:00:00 2001 From: Michael Davidsaver Date: Fri, 29 Jun 2012 17:02:25 -0400 Subject: [PATCH 20/21] minor --- src/ioc/db/test/Makefile | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/ioc/db/test/Makefile b/src/ioc/db/test/Makefile index 2ba82c344..55610f825 100644 --- a/src/ioc/db/test/Makefile +++ b/src/ioc/db/test/Makefile @@ -11,7 +11,7 @@ TOP=../../../.. include $(TOP)/configure/CONFIG PROD_vxWorks += dbTestHarness chfPluginTest -PROD_RTEMS += dbTestHarness chfPluginTest +PROD_RTEMS += dbTestHarness PROD_LIBS = dbCore ca Com @@ -52,7 +52,7 @@ TESTS += arrShorthandTest dbTestHarness_SRCS += epicsRunDbTests.c -dbTestHarness_SRCS_RTEMS = rtemsTestHarness.c +dbTestHarness_SRCS_RTEMS += rtemsTestHarness.c TESTSPEC_vxWorks = dbTestHarness.munch; epicsRunDbTests TESTSPEC_RTEMS = dbTestHarness.boot; epicsRunDbTests From 7d51031d60b74d1e6b33c228e27c5d2312a1d758 Mon Sep 17 00:00:00 2001 From: Michael Davidsaver Date: Fri, 29 Jun 2012 17:02:25 -0400 Subject: [PATCH 21/21] RTEMS test harness show run directory --- src/ioc/db/test/rtemsTestHarness.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/ioc/db/test/rtemsTestHarness.c b/src/ioc/db/test/rtemsTestHarness.c index c72122b67..0aacbe573 100644 --- a/src/ioc/db/test/rtemsTestHarness.c +++ b/src/ioc/db/test/rtemsTestHarness.c @@ -12,6 +12,7 @@ #include #include #include +#include #endif /* __rtems__ */ @@ -29,6 +30,13 @@ int main(int argc, char **argv) printf("Stat /tmp: %o %u,%u\n", s.st_mode, s.st_uid, s.st_gid); } epicsEnvSet("TMPDIR","/tmp"); + { + char name[40]; + if(getcwd(name,40)) + printf("Running from %s\n", name); + else + printf("Can't determine PWD"); + } #endif epicsRunDbTests(); /* calls epicsExit(0) */