97edcfc289
On some systems the wall clock may tick slowly, so we must allow the time to not change at all between checks. Show the time differences.
516 lines
17 KiB
C
516 lines
17 KiB
C
/*************************************************************************\
|
|
* Copyright (c) 2017 ITER Organization
|
|
* SPDX-License-Identifier: EPICS
|
|
* EPICS BASE is distributed subject to a Software License Agreement found
|
|
* in file LICENSE that is included with this distribution.
|
|
\*************************************************************************/
|
|
|
|
#include <limits.h>
|
|
#include <string.h>
|
|
|
|
#include <dbUnitTest.h>
|
|
#include <testMain.h>
|
|
#include <dbAccess.h>
|
|
#include <epicsTime.h>
|
|
#include <epicsThread.h>
|
|
#include <errlog.h>
|
|
#include <alarm.h>
|
|
|
|
#include "recSup.h"
|
|
#include "aiRecord.h"
|
|
#include "aoRecord.h"
|
|
#include "aaiRecord.h"
|
|
#include "aaoRecord.h"
|
|
#include "biRecord.h"
|
|
#include "boRecord.h"
|
|
#include "mbbiRecord.h"
|
|
#include "mbboRecord.h"
|
|
#include "mbbiDirectRecord.h"
|
|
#include "mbboDirectRecord.h"
|
|
#include "longinRecord.h"
|
|
#include "longoutRecord.h"
|
|
#include "int64inRecord.h"
|
|
#include "int64outRecord.h"
|
|
#include "stringinRecord.h"
|
|
#include "stringoutRecord.h"
|
|
#include "lsiRecord.h"
|
|
#include "lsoRecord.h"
|
|
#include "eventRecord.h"
|
|
#include "histogramRecord.h"
|
|
#include "waveformRecord.h"
|
|
|
|
/*
|
|
* Tests for simulation mode
|
|
*/
|
|
|
|
void simmTest_registerRecordDeviceDriver(struct dbBase *);
|
|
|
|
static
|
|
void startSimmTestIoc(const char *dbfile)
|
|
{
|
|
testdbPrepare();
|
|
testdbReadDatabase("simmTest.dbd", NULL, NULL);
|
|
simmTest_registerRecordDeviceDriver(pdbbase);
|
|
testdbReadDatabase(dbfile, NULL, NULL);
|
|
|
|
eltc(0);
|
|
testIocInitOk();
|
|
eltc(1);
|
|
}
|
|
|
|
static char *rawSupp[] = {
|
|
"ai",
|
|
"bi",
|
|
"mbbi",
|
|
"mbbiDirect",
|
|
};
|
|
|
|
static
|
|
int hasRawSimmSupport(const char *rectype) {
|
|
int i;
|
|
for (i = 0; i < (sizeof(rawSupp)/sizeof(rawSupp[0])); i++)
|
|
if (strcmp(rectype, rawSupp[i]) == 0) return 1;
|
|
return 0;
|
|
}
|
|
|
|
#define PVNAMELENGTH 60
|
|
static char nameVAL[PVNAMELENGTH];
|
|
static char nameB0[PVNAMELENGTH];
|
|
static char nameRVAL[PVNAMELENGTH];
|
|
static char nameSGNL[PVNAMELENGTH];
|
|
static char nameSIMM[PVNAMELENGTH];
|
|
static char nameSIML[PVNAMELENGTH];
|
|
static char nameSVAL[PVNAMELENGTH];
|
|
static char nameSIOL[PVNAMELENGTH];
|
|
static char nameSCAN[PVNAMELENGTH];
|
|
static char namePROC[PVNAMELENGTH];
|
|
static char namePACT[PVNAMELENGTH];
|
|
static char nameSTAT[PVNAMELENGTH];
|
|
static char nameSEVR[PVNAMELENGTH];
|
|
static char nameSIMS[PVNAMELENGTH];
|
|
static char nameTSE[PVNAMELENGTH];
|
|
static char nameSimmode[PVNAMELENGTH];
|
|
static char nameSimval[PVNAMELENGTH];
|
|
static char nameSimvalNORD[PVNAMELENGTH];
|
|
static char nameSimvalLEN[PVNAMELENGTH];
|
|
|
|
#define SETNAME(field) strcpy(name ## field, name); strcat(name ## field, "." #field)
|
|
static
|
|
void setNames(const char *name)
|
|
{
|
|
SETNAME(VAL); SETNAME(B0); SETNAME(RVAL); SETNAME(SGNL);
|
|
SETNAME(SVAL); SETNAME(SIMM); SETNAME(SIML); SETNAME(SIOL); SETNAME(SIMS);
|
|
SETNAME(SCAN); SETNAME(PROC); SETNAME(PACT);
|
|
SETNAME(STAT); SETNAME(SEVR); SETNAME(TSE);
|
|
strcpy(nameSimmode, name); strcat(nameSimmode, ":simmode");
|
|
strcpy(nameSimval, name); strcat(nameSimval, ":simval");
|
|
strcpy(nameSimvalNORD, name); strcat(nameSimvalNORD, ":simval.NORD");
|
|
strcpy(nameSimvalLEN, name); strcat(nameSimvalLEN, ":simval.LEN");
|
|
}
|
|
|
|
/*
|
|
* Parsing of info items and xsimm structure setting
|
|
*/
|
|
static
|
|
void testSimmSetup(void)
|
|
{
|
|
aiRecord *precai;
|
|
|
|
testDiag("##### Simm initialization #####");
|
|
|
|
/* no config */
|
|
precai = (aiRecord*)testdbRecordPtr("ai-0");
|
|
testOk(precai->simpvt == NULL, "ai-0.SIMPVT = %p == NULL [no callback]", precai->simpvt);
|
|
testOk(precai->sscn == USHRT_MAX, "ai-0.SSCN = %u == USHRT_MAX (not set)", precai->sscn);
|
|
testOk(precai->sdly < 0., "ai-0.SDLY = %g < 0.0 (not set)", precai->sdly);
|
|
|
|
/* with SCAN */
|
|
precai = (aiRecord*)testdbRecordPtr("ai-1");
|
|
testOk(precai->sscn == 5, "ai-1.SSCN = %u == 5 (2 second)", precai->sscn);
|
|
testOk(precai->sdly < 0., "ai-1.SDLY = %g < 0.0 (not set)", precai->sdly);
|
|
|
|
/* with DELAY */
|
|
precai = (aiRecord*)testdbRecordPtr("ai-2");
|
|
testOk(precai->sscn == USHRT_MAX, "ai-2.SSCN = %u == USHRT_MAX (not set)", precai->sscn);
|
|
testOk(precai->sdly == 0.234, "ai-2.SDLY = %g == 0.234", precai->sdly);
|
|
|
|
/* with SCAN and DELAY */
|
|
precai = (aiRecord*)testdbRecordPtr("ai-3");
|
|
testOk(precai->sscn == 4, "ai-3.SSCN = %u == 4 (5 second)", precai->sscn);
|
|
testOk(precai->sdly == 0.345, "ai-3.SDLY = %g == 0.345", precai->sdly);
|
|
}
|
|
|
|
/*
|
|
* Invalid SIML link sets LINK/NO_ALARM if in NO_ALARM
|
|
*/
|
|
static
|
|
void testSimlFail(void)
|
|
{
|
|
aoRecord *precao;
|
|
|
|
testDiag("##### Behavior for failing SIML #####");
|
|
|
|
precao = (aoRecord*)testdbRecordPtr("ao-0");
|
|
/* before anything: UDF INVALID */
|
|
testOk(precao->stat == UDF_ALARM, "ao-0.STAT = %u [%s] == %u [UDF]",
|
|
precao->stat, epicsAlarmConditionStrings[precao->stat], UDF_ALARM);
|
|
testOk(precao->sevr == INVALID_ALARM, "ao-0.SEVR = %u [%s] == %u [INVALID]",
|
|
precao->sevr, epicsAlarmSeverityStrings[precao->sevr], INVALID_ALARM);
|
|
|
|
/* legal value: LINK NO_ALARM */
|
|
testdbPutFieldOk("ao-0.VAL", DBR_DOUBLE, 1.0);
|
|
testOk(precao->stat == LINK_ALARM, "ao-0.STAT = %u [%s] == %u [LINK]",
|
|
precao->stat, epicsAlarmConditionStrings[precao->stat], LINK_ALARM);
|
|
testOk(precao->sevr == NO_ALARM, "ao-0.SEVR = %u [%s] == %u [NO_ALARM]",
|
|
precao->sevr, epicsAlarmSeverityStrings[precao->sevr], NO_ALARM);
|
|
|
|
/* HIGH/MINOR overrides */
|
|
testdbPutFieldOk("ao-0.VAL", DBR_DOUBLE, 2.0);
|
|
testOk(precao->stat == HIGH_ALARM, "ao-0.STAT = %u [%s] == %u [HIGH]",
|
|
precao->stat, epicsAlarmConditionStrings[precao->stat], HIGH_ALARM);
|
|
testOk(precao->sevr == MINOR_ALARM, "ao-0.SEVR = %u [%s] == %u [MINOR]",
|
|
precao->sevr, epicsAlarmSeverityStrings[precao->sevr], MINOR_ALARM);
|
|
}
|
|
|
|
/*
|
|
* SIMM triggered SCAN swapping, by writing to SIMM and through SIML
|
|
*/
|
|
|
|
static
|
|
void testSimmToggle(const char *name, epicsEnum16 *psscn)
|
|
{
|
|
testDiag("## SIMM toggle and SCAN swapping ##");
|
|
|
|
/* SIMM mode by setting the field */
|
|
|
|
testdbGetFieldEqual(nameSCAN, DBR_USHORT, 0);
|
|
testOk(*psscn == 1, "SSCN = %u == 1 (Event)", *psscn);
|
|
|
|
testDiag("set SIMM to YES");
|
|
testdbPutFieldOk(nameSIMM, DBR_STRING, "YES");
|
|
testdbGetFieldEqual(nameSCAN, DBR_USHORT, 1);
|
|
testOk(*psscn == 0, "SSCN = %u == 0 (Passive)", *psscn);
|
|
|
|
/* Change simm:SCAN when simmYES */
|
|
testdbPutFieldOk(nameSCAN, DBR_USHORT, 3);
|
|
|
|
testDiag("set SIMM to NO");
|
|
testdbPutFieldOk(nameSIMM, DBR_STRING, "NO");
|
|
testdbGetFieldEqual(nameSCAN, DBR_USHORT, 0);
|
|
testOk(*psscn == 3, "SSCN = %u == 3 (10 second)", *psscn);
|
|
*psscn = 1;
|
|
|
|
if (hasRawSimmSupport(name)) {
|
|
testDiag("set SIMM to RAW");
|
|
testdbPutFieldOk(nameSIMM, DBR_STRING, "RAW");
|
|
testdbGetFieldEqual(nameSCAN, DBR_USHORT, 1);
|
|
testOk(*psscn == 0, "SSCN = %u == 0 (Passive)", *psscn);
|
|
|
|
testDiag("set SIMM to NO");
|
|
testdbPutFieldOk(nameSIMM, DBR_STRING, "NO");
|
|
testdbGetFieldEqual(nameSCAN, DBR_USHORT, 0);
|
|
testOk(*psscn == 1, "SSCN = %u == 1 (Event)", *psscn);
|
|
} else {
|
|
testDiag("Record type %s has no support for simmRAW", name);
|
|
}
|
|
|
|
/* SIMM mode through SIML */
|
|
|
|
testdbPutFieldOk(nameSIML, DBR_STRING, nameSimmode);
|
|
|
|
testDiag("set SIMM (via SIML -> simmode) to YES");
|
|
testdbPutFieldOk(nameSimmode, DBR_USHORT, 1);
|
|
testdbPutFieldOk(namePROC, DBR_LONG, 0);
|
|
|
|
testdbGetFieldEqual(nameSIMM, DBR_USHORT, 1);
|
|
testdbGetFieldEqual(nameSCAN, DBR_USHORT, 1);
|
|
testOk(*psscn == 0, "SSCN = %u == 0 (Passive)", *psscn);
|
|
|
|
testDiag("set SIMM (via SIML -> simmode) to NO");
|
|
testdbPutFieldOk(nameSimmode, DBR_USHORT, 0);
|
|
testdbPutFieldOk(namePROC, DBR_LONG, 0);
|
|
|
|
testdbGetFieldEqual(nameSIMM, DBR_USHORT, 0);
|
|
testdbGetFieldEqual(nameSCAN, DBR_USHORT, 0);
|
|
testOk(*psscn == 1, "SSCN = %u == 1 (Event)", *psscn);
|
|
|
|
if (hasRawSimmSupport(name)) {
|
|
testDiag("set SIMM (via SIML -> simmode) to RAW");
|
|
testdbPutFieldOk(nameSimmode, DBR_USHORT, 2);
|
|
testdbPutFieldOk(namePROC, DBR_LONG, 0);
|
|
|
|
testdbGetFieldEqual(nameSIMM, DBR_USHORT, 2);
|
|
testdbGetFieldEqual(nameSCAN, DBR_USHORT, 1);
|
|
testOk(*psscn == 0, "SSCN = %u == 0 (Passive)", *psscn);
|
|
|
|
testDiag("set SIMM (via SIML -> simmode) to NO");
|
|
testdbPutFieldOk(nameSimmode, DBR_USHORT, 0);
|
|
testdbPutFieldOk(namePROC, DBR_LONG, 0);
|
|
|
|
testdbGetFieldEqual(nameSIMM, DBR_USHORT, 0);
|
|
testdbGetFieldEqual(nameSCAN, DBR_USHORT, 0);
|
|
testOk(*psscn == 1, "SSCN = %u == 1 (Event)", *psscn);
|
|
} else {
|
|
testDiag("Record type %s has no support for simmRAW", name);
|
|
}
|
|
}
|
|
|
|
/*
|
|
* Reading from SVAL (direct write or through SIOL link)
|
|
*/
|
|
|
|
static
|
|
void testSvalRead(const char *name,
|
|
const epicsTimeStamp *mytime,
|
|
const epicsTimeStamp *svtime)
|
|
{
|
|
epicsTimeStamp last;
|
|
double diff;
|
|
|
|
if (strcmp(name, "histogram") == 0)
|
|
strcpy(nameVAL, nameSGNL);
|
|
|
|
if (strcmp(name, "aai") != 0 &&
|
|
strcmp(name, "waveform") != 0 &&
|
|
strcmp(name, "lsi") != 0) {
|
|
|
|
testDiag("## Reading from SVAL ##");
|
|
|
|
testDiag("in simmNO, SVAL must be ignored");
|
|
testdbPutFieldOk(nameSimmode, DBR_USHORT, 0);
|
|
testdbPutFieldOk(nameVAL, DBR_LONG, 0);
|
|
if (strcmp(name, "stringin") == 0)
|
|
testdbPutFieldOk(nameSVAL, DBR_STRING, "1");
|
|
else
|
|
testdbPutFieldOk(nameSVAL, DBR_USHORT, 1);
|
|
testdbPutFieldOk(namePROC, DBR_LONG, 0);
|
|
testdbGetFieldEqual(nameVAL, DBR_USHORT, 0);
|
|
|
|
testDiag("in simmYES, SVAL is used for VAL");
|
|
testdbPutFieldOk(nameSIMS, DBR_USHORT, 0);
|
|
testdbPutFieldOk(nameSimmode, DBR_USHORT, 1);
|
|
testdbPutFieldOk(namePROC, DBR_LONG, 0);
|
|
testdbGetFieldEqual(nameVAL, DBR_USHORT, 1);
|
|
testDiag("No SIMS setting: STAT/SEVR == NO_ALARM");
|
|
testdbGetFieldEqual(nameSTAT, DBR_STRING, "NO_ALARM");
|
|
testdbGetFieldEqual(nameSEVR, DBR_USHORT, 0);
|
|
|
|
if (hasRawSimmSupport(name)) {
|
|
testDiag("in simmRAW, SVAL is used for RVAL");
|
|
testdbPutFieldOk(nameSimmode, DBR_USHORT, 2);
|
|
testdbPutFieldOk(namePROC, DBR_LONG, 0);
|
|
testdbGetFieldEqual(nameRVAL, DBR_USHORT, 1);
|
|
} else {
|
|
testDiag("Record type %s has no support for simmRAW", name);
|
|
}
|
|
}
|
|
|
|
testDiag("## Reading from SIOL->SVAL ##");
|
|
|
|
/* Set SIOL link to simval */
|
|
testdbPutFieldOk(nameSIOL, DBR_STRING, nameSimval);
|
|
|
|
testDiag("in simmNO, SIOL->SVAL must be ignored");
|
|
testdbPutFieldOk(nameSimmode, DBR_USHORT, 0);
|
|
testdbPutFieldOk(nameVAL, DBR_LONG, 0);
|
|
testdbPutFieldOk(nameSimval, DBR_LONG, 1);
|
|
testdbPutFieldOk(namePROC, DBR_LONG, 0);
|
|
testdbGetFieldEqual(nameVAL, DBR_USHORT, 0);
|
|
|
|
testDiag("in simmYES, SIOL->SVAL is used for VAL");
|
|
testdbPutFieldOk(nameSIMS, DBR_USHORT, 3);
|
|
testdbPutFieldOk(nameSimmode, DBR_USHORT, 1);
|
|
testdbPutFieldOk(namePROC, DBR_LONG, 0);
|
|
testdbGetFieldEqual(nameVAL, DBR_USHORT, 1);
|
|
testDiag("SIMS is INVALID: STAT/SEVR == SIMM/INVALID");
|
|
testdbGetFieldEqual(nameSTAT, DBR_STRING, "SIMM");
|
|
testdbGetFieldEqual(nameSEVR, DBR_USHORT, 3);
|
|
testdbPutFieldOk(nameSIMS, DBR_USHORT, 0);
|
|
|
|
if (hasRawSimmSupport(name)) {
|
|
testDiag("in simmRAW, SIOL->SVAL is used for RVAL");
|
|
testdbPutFieldOk(nameSimmode, DBR_USHORT, 2);
|
|
testdbPutFieldOk(namePROC, DBR_LONG, 0);
|
|
testdbGetFieldEqual(nameRVAL, DBR_USHORT, 1);
|
|
} else {
|
|
testDiag("Record type %s has no support for simmRAW", name);
|
|
}
|
|
|
|
/* My timestamp must be later than simval's */
|
|
diff = epicsTimeDiffInSeconds(mytime, svtime);
|
|
testOk(diff >= 0.0, "simval time <= my time [TSE = 0] (%.9f sec)", diff);
|
|
|
|
testDiag("for TSE=-2 (from device) and simmYES, take time stamp from IOC or input link");
|
|
|
|
/* Set simmYES */
|
|
testdbPutFieldOk(nameSimmode, DBR_USHORT, 1);
|
|
|
|
/* Set TSE to -2 (from device) and reprocess: timestamps is taken through SIOL from simval */
|
|
testdbPutFieldOk(nameTSE, DBR_SHORT, -2);
|
|
testdbPutFieldOk(namePROC, DBR_LONG, 0);
|
|
testOk(epicsTimeEqual(svtime, mytime), "simval time == my time [TSE = -2]");
|
|
last = *mytime;
|
|
|
|
/* With TSE=-2 and no SIOL, timestamp is taken from IOC */
|
|
testdbPutFieldOk(nameSIOL, DBR_STRING, "");
|
|
testdbPutFieldOk(namePROC, DBR_LONG, 0);
|
|
diff = epicsTimeDiffInSeconds(mytime, &last);
|
|
testOk(diff >= 0.0, "new time stamp from IOC [TSE = -2, no SIOL] (%.9f sec)", diff);
|
|
|
|
/* Reset TSE */
|
|
testdbPutFieldOk(nameTSE, DBR_SHORT, 0);
|
|
}
|
|
|
|
/*
|
|
* Writing through SIOL link
|
|
*/
|
|
|
|
static
|
|
void testSiolWrite(const char *name,
|
|
const epicsTimeStamp *mytime)
|
|
{
|
|
epicsTimeStamp now;
|
|
double diff;
|
|
|
|
testDiag("## Writing through SIOL ##");
|
|
|
|
/* Set SIOL link to simval */
|
|
testdbPutFieldOk(nameSIOL, DBR_STRING, nameSimval);
|
|
|
|
testDiag("in simmNO, SIOL must be ignored");
|
|
testdbPutFieldOk(nameSimmode, DBR_USHORT, 0);
|
|
if (strcmp(name, "mbboDirect") == 0)
|
|
testdbPutFieldOk(nameB0, DBR_LONG, 1);
|
|
else
|
|
testdbPutFieldOk(nameVAL, DBR_LONG, 1);
|
|
|
|
if (strcmp(name, "aao") == 0)
|
|
testdbGetFieldEqual(nameSimvalNORD, DBR_USHORT, 0);
|
|
else if (strcmp(name, "lso") == 0)
|
|
testdbGetFieldEqual(nameSimvalLEN, DBR_USHORT, 0);
|
|
else
|
|
testdbGetFieldEqual(nameSimval, DBR_USHORT, 0);
|
|
|
|
testDiag("in simmYES, SIOL is used to write VAL");
|
|
testdbPutFieldOk(nameSimmode, DBR_USHORT, 1);
|
|
if (strcmp(name, "mbboDirect") == 0)
|
|
testdbPutFieldOk(nameB0, DBR_LONG, 1);
|
|
else
|
|
testdbPutFieldOk(nameVAL, DBR_LONG, 1);
|
|
testdbGetFieldEqual(nameSimval, DBR_USHORT, 1);
|
|
|
|
/* Set TSE to -2 (from device) and reprocess: timestamp is taken from IOC */
|
|
epicsTimeGetCurrent(&now);
|
|
testdbPutFieldOk(nameTSE, DBR_SHORT, -2);
|
|
testdbPutFieldOk(namePROC, DBR_LONG, 0);
|
|
diff = epicsTimeDiffInSeconds(mytime, &now);
|
|
testOk(diff >= 0.0, "new time stamp from IOC [TSE = -2] (%.9f sec)", diff);
|
|
|
|
/* Reset TSE */
|
|
testdbPutFieldOk(nameTSE, DBR_SHORT, 0);
|
|
}
|
|
|
|
/*
|
|
* Asynchronous processing using simm:DELAY
|
|
*/
|
|
|
|
static
|
|
void testSimmDelay(const char *name,
|
|
epicsFloat64 *psdly,
|
|
const epicsTimeStamp *mytime)
|
|
{
|
|
epicsTimeStamp now;
|
|
const double delay = 0.01; /* 10 ms */
|
|
double diff;
|
|
|
|
testDiag("## Asynchronous processing with simm:DELAY ##");
|
|
|
|
/* Set delay to something just long enough */
|
|
*psdly = delay;
|
|
|
|
/* Process in simmNO: synchronous */
|
|
testDiag("simm:DELAY and simmNO processes synchronously");
|
|
testdbPutFieldOk(nameSimmode, DBR_USHORT, 0);
|
|
epicsTimeGetCurrent(&now);
|
|
testdbPutFieldOk(namePROC, DBR_LONG, 0);
|
|
testdbGetFieldEqual(namePACT, DBR_USHORT, 0);
|
|
diff = epicsTimeDiffInSeconds(mytime, &now);
|
|
testOk(diff >= 0.0, "time stamp is recent (%.9f sec)", diff);
|
|
|
|
/* Process in simmYES: asynchronous */
|
|
testDiag("simm:DELAY and simmYES processes asynchronously");
|
|
testdbPutFieldOk(nameSimmode, DBR_USHORT, 1);
|
|
testdbPutFieldOk(namePROC, DBR_LONG, 0);
|
|
testdbGetFieldEqual(namePACT, DBR_USHORT, 1);
|
|
epicsTimeGetCurrent(&now);
|
|
epicsThreadSleep(1.75*delay);
|
|
if(testImpreciseTiming())
|
|
testTodoBegin("imprecise");
|
|
testdbGetFieldEqual(namePACT, DBR_USHORT, 0);
|
|
diff = epicsTimeDiffInSeconds(mytime, &now);
|
|
testOk(diff >= 0.0, "time stamp is recent (%.9f sec)", diff);
|
|
if(testImpreciseTiming())
|
|
testTodoEnd();
|
|
|
|
/* Reset delay */
|
|
*psdly = -1.;
|
|
}
|
|
|
|
#define RUNALLTESTSREAD(type) \
|
|
testDiag("################################################### Record Type " #type); \
|
|
setNames(#type); \
|
|
testSimmToggle(#type, &((type ## Record*)testdbRecordPtr(#type))->sscn); \
|
|
testSvalRead(#type, &((type ## Record*)testdbRecordPtr(#type))->time, \
|
|
&((type ## Record*)testdbRecordPtr(#type ":simval"))->time); \
|
|
testSimmDelay(#type, &((type ## Record*)testdbRecordPtr(#type))->sdly, \
|
|
&((type ## Record*)testdbRecordPtr(#type))->time)
|
|
|
|
#define RUNALLTESTSWRITE(type) \
|
|
testDiag("################################################### Record Type " #type); \
|
|
setNames(#type); \
|
|
testSimmToggle(#type, &((type ## Record*)testdbRecordPtr(#type))->sscn); \
|
|
testSiolWrite(#type, &((type ## Record*)testdbRecordPtr(#type))->time); \
|
|
testSimmDelay(#type, &((type ## Record*)testdbRecordPtr(#type))->sdly, \
|
|
&((type ## Record*)testdbRecordPtr(#type))->time)
|
|
|
|
static
|
|
void testAllRecTypes(void)
|
|
{
|
|
RUNALLTESTSREAD(ai);
|
|
RUNALLTESTSWRITE(ao);
|
|
RUNALLTESTSREAD(aai);
|
|
RUNALLTESTSWRITE(aao);
|
|
RUNALLTESTSREAD(bi);
|
|
RUNALLTESTSWRITE(bo);
|
|
RUNALLTESTSREAD(mbbi);
|
|
RUNALLTESTSWRITE(mbbo);
|
|
RUNALLTESTSREAD(mbbiDirect);
|
|
RUNALLTESTSWRITE(mbboDirect);
|
|
RUNALLTESTSREAD(longin);
|
|
RUNALLTESTSWRITE(longout);
|
|
RUNALLTESTSREAD(int64in);
|
|
RUNALLTESTSWRITE(int64out);
|
|
RUNALLTESTSREAD(stringin);
|
|
RUNALLTESTSWRITE(stringout);
|
|
RUNALLTESTSREAD(lsi);
|
|
RUNALLTESTSWRITE(lso);
|
|
RUNALLTESTSREAD(event);
|
|
RUNALLTESTSREAD(waveform);
|
|
RUNALLTESTSREAD(histogram);
|
|
}
|
|
|
|
|
|
MAIN(simmTest)
|
|
{
|
|
testPlan(1176);
|
|
startSimmTestIoc("simmTest.db");
|
|
|
|
testSimmSetup();
|
|
testSimlFail();
|
|
testAllRecTypes();
|
|
|
|
testIocShutdownOk();
|
|
testdbCleanup();
|
|
return testDone();
|
|
}
|