From 80dd66a58da109d1b8cdb0a48df882c2fd6c1be1 Mon Sep 17 00:00:00 2001 From: Michael Davidsaver Date: Mon, 23 Jun 2014 16:28:25 -0400 Subject: [PATCH] add dbUnitTest.h hide boilerplate of tests using the PDB --- src/ioc/db/Makefile | 3 +- src/ioc/db/dbUnitTest.c | 123 +++++++++++++++++++++++++++++++ src/ioc/db/dbUnitTest.h | 54 ++++++++++++++ src/ioc/db/test/dbShutdownTest.c | 24 +++--- 4 files changed, 189 insertions(+), 15 deletions(-) create mode 100644 src/ioc/db/dbUnitTest.c create mode 100644 src/ioc/db/dbUnitTest.h diff --git a/src/ioc/db/Makefile b/src/ioc/db/Makefile index c957842cb..8788207fe 100644 --- a/src/ioc/db/Makefile +++ b/src/ioc/db/Makefile @@ -37,6 +37,7 @@ INC += chfPlugin.h INC += dbState.h INC += db_access_routines.h INC += db_convert.h +INC += dbUnitTest.h # Generate menuGlobal.dbd automatically DBD += menuGlobal.dbd @@ -86,4 +87,4 @@ dbCore_SRCS += templateInstances.cpp dbCore_SRCS += dbIocRegister.c dbCore_SRCS += chfPlugin.c dbCore_SRCS += dbState.c - +dbCore_SRCS += dbUnitTest.c diff --git a/src/ioc/db/dbUnitTest.c b/src/ioc/db/dbUnitTest.c new file mode 100644 index 000000000..1a7f74dde --- /dev/null +++ b/src/ioc/db/dbUnitTest.c @@ -0,0 +1,123 @@ +/*************************************************************************\ +* Copyright (c) 2013 Brookhaven National Laboratory. +* Copyright (c) 2013 ITER Organization. +* EPICS BASE is distributed subject to a Software License Agreement found +* in file LICENSE that is included with this distribution. + \*************************************************************************/ + +/* + * Author: Michael Davidsaver + * Ralph Lange + */ + +#include + +#include "epicsUnitTest.h" +#include "osiFileName.h" +#include "dbmf.h" +#include "registry.h" +#define epicsExportSharedSymbols +#include "iocInit.h" +#include "initHooks.h" +#include "dbBase.h" +#include "dbAccess.h" +#include "dbStaticLib.h" + +#include "dbUnitTest.h" + +void testdbPrepare(void) +{ + /* No-op at the moment */ +} + +void testdbReadDatabase(const char* file, + const char* path, + const char* substitutions) +{ + if(!path) + path = "." OSI_PATH_LIST_SEPARATOR ".." OSI_PATH_LIST_SEPARATOR + "../O.Common" OSI_PATH_LIST_SEPARATOR "O.Common"; + if(dbReadDatabase(&pdbbase, file, path, substitutions)) + testAbort("Failed to load test database\ndbReadDatabase(%s,%s,%s)", + file, path, substitutions); +} + +int testiocInit(void) +{ + return iocBuildNoCA() || iocRun(); +} + +int testiocShutdown(void) +{ + return iocShutdown(); +} + +void testdbCleanup(void) +{ + dbFreeBase(pdbbase); + initHookFree(); + registryFree(); + pdbbase = NULL; + dbmfFreeChunks(); +} + +long testdbPutField(const char* pv, short dbrType, ...) +{ + long ret; + va_list ap; + va_start(ap, dbrType); + ret = testVdbPutField(pv, dbrType, ap); + va_end(ap); + return ret; +} + +union anybuf { + epicsAny val; + char bytes[sizeof(epicsAny)]; +}; + +long testVdbPutField(const char* pv, short dbrType, va_list ap) +{ + DBADDR addr; + union anybuf pod; + + if(dbNameToAddr(pv, &addr)) + testAbort("Missing PV %s", pv); + + switch(dbrType) { + case DBR_STRING: { + const char *uarg = va_arg(ap,char*); + epicsOldString buffer; + strncpy(buffer, uarg, sizeof(buffer)); + buffer[sizeof(buffer)-1] = '\0'; + return dbPutField(&addr, dbrType, buffer, 1); + } + +#define OP(DBR,Type,mem) case DBR: {pod.val.mem = va_arg(ap,Type); break;} + OP(DBR_CHAR, int, int8); + OP(DBR_UCHAR, int, uInt8); + OP(DBR_SHORT, int, int16); + OP(DBR_USHORT, int, uInt16); + OP(DBR_LONG, int, int32); + OP(DBR_ULONG, unsigned int, uInt32); + OP(DBR_FLOAT, double, float32); + OP(DBR_DOUBLE, double, float64); + OP(DBR_ENUM, int, enum16); +#undef OP + default: + testAbort("invalid DBR: dbPutField(%s, %d, ...)", + addr.precord->name, dbrType); + } + + return dbPutField(&addr, dbrType, pod.bytes, 1); +} + +dbCommon* testGetRecord(const char* pv) +{ + DBADDR addr; + + if(dbNameToAddr(pv, &addr)) + testAbort("Missing PV %s", pv); + + return addr.precord; +} diff --git a/src/ioc/db/dbUnitTest.h b/src/ioc/db/dbUnitTest.h new file mode 100644 index 000000000..9b58673ed --- /dev/null +++ b/src/ioc/db/dbUnitTest.h @@ -0,0 +1,54 @@ +/*************************************************************************\ +* Copyright (c) 2013 Brookhaven National Laboratory. +* Copyright (c) 2013 ITER Organization. +* EPICS BASE is distributed subject to a Software License Agreement found +* in file LICENSE that is included with this distribution. + \*************************************************************************/ + +/* + * Author: Michael Davidsaver + * Ralph Lange + */ + +#ifndef EPICSUNITTESTDB_H +#define EPICSUNITTESTDB_H + +#include + +#include "epicsUnitTest.h" +#include "dbAddr.h" +#include "dbCommon.h" + +#include "shareLib.h" + +#ifdef __cplusplus +extern "C" { +#endif + +epicsShareFunc void testdbPrepare(void); +epicsShareFunc void testdbReadDatabase(const char* file, + const char* path, + const char* substitutions); +epicsShareFunc int testiocInit(void); +epicsShareFunc int testiocShutdown(void); +epicsShareFunc void testdbCleanup(void); + +/* Scalar only version. + * + * Remember to use the correct argument type!s + * + * int for DBR_UCHAR, DBR_CHAR, DBR_USHORT, DBR_SHORT, DBR_LONG + * unsigned int for DBR_ULONG + * double for DBR_FLOAT and DBR_DOUBLE + * const char* for DBR_STRING + */ +epicsShareFunc long testdbPutField(const char* pv, short dbrType, ...); +epicsShareFunc long testVdbPutField(const char* pv, short dbrType, va_list ap); + +epicsShareFunc dbCommon* testGetRecord(const char* pv); + +#ifdef __cplusplus +} +#endif + +#endif // EPICSUNITTESTDB_H diff --git a/src/ioc/db/test/dbShutdownTest.c b/src/ioc/db/test/dbShutdownTest.c index 7d9b3862a..d3a993b6e 100644 --- a/src/ioc/db/test/dbShutdownTest.c +++ b/src/ioc/db/test/dbShutdownTest.c @@ -12,7 +12,7 @@ #include -#include "epicsUnitTest.h" +#include "dbUnitTest.h" #include "epicsThread.h" #include "iocInit.h" #include "dbBase.h" @@ -64,27 +64,23 @@ void checkCommonThreads (void) { static void cycle(void) { - if (dbReadDatabase(&pdbbase, "dbShutdownTest.dbd", - "." OSI_PATH_LIST_SEPARATOR ".." OSI_PATH_LIST_SEPARATOR - "../O.Common" OSI_PATH_LIST_SEPARATOR "O.Common", NULL)) - testAbort("Database description 'dbShutdownTest.dbd' not found"); + + testdbPrepare(); + + testdbReadDatabase("dbShutdownTest.dbd", NULL, NULL); dbShutdownTest_registerRecordDeviceDriver(pdbbase); - if (dbReadDatabase(&pdbbase, "sRecord.db", - "." OSI_PATH_LIST_SEPARATOR "..", NULL)) - testAbort("Test database 'sRecord.db' not found"); - testOk1(!(iocBuildNoCA() || iocRun())); + testdbReadDatabase("sRecord.db", NULL, NULL); + + testOk1(!testiocInit()); epicsThreadMap(findCommonThread); checkCommonThreads(); - testOk1(iocShutdown()==0); + testOk1(testiocShutdown()==0); - dbFreeBase(pdbbase); - registryFree(); - pdbbase = NULL; - dbmfFreeChunks(); + testdbCleanup(); } MAIN(dbShutdownTest)