Merge remote-tracking branch 'origin' into PSI-7.0

Conflicts:
	configure/os/CONFIG_SITE.Common.linuxCommon
	modules/libcom/src/log/iocLog.c
	modules/libcom/src/log/logClient.c
	modules/pvAccess
	modules/pvData
	modules/pvDatabase
This commit is contained in:
2020-02-06 17:28:40 +01:00
374 changed files with 16167 additions and 9000 deletions
+9 -1
View File
@@ -7,10 +7,12 @@
# in the file LICENSE that is included with this distribution.
#*************************************************************************
TOP = ../../..
TOP = ../../../../..
include $(TOP)/configure/CONFIG
USR_CPPFLAGS += -DUSE_TYPED_RSET
TESTLIBRARY = Recs
Recs_SRCS += xRecord.c
@@ -57,6 +59,12 @@ syncTest_SRCS += filterTest_registerRecordDeviceDriver.cpp
testHarness_SRCS += syncTest.c
TESTS += syncTest
TESTPROD_HOST += decTest
decTest_SRCS += decTest.c
decTest_SRCS += filterTest_registerRecordDeviceDriver.cpp
testHarness_SRCS += decTest.c
TESTS += decTest
# epicsRunFilterTests runs all the test programs in a known working order.
testHarness_SRCS += epicsRunFilterTests.c
+30 -1
View File
@@ -39,12 +39,14 @@ static int fl_equal(const db_field_log *pfl1, const db_field_log *pfl2) {
static void fl_setup(dbChannel *chan, db_field_log *pfl) {
struct dbCommon *prec = dbChannelRecord(chan);
memset(pfl, 0, sizeof(db_field_log));
pfl->ctx = dbfl_context_read;
pfl->type = dbfl_type_val;
pfl->stat = prec->stat;
pfl->sevr = prec->sevr;
pfl->time = prec->time;
pfl->field_type = dbChannelFieldType(chan);
pfl->field_size = dbChannelFieldSize(chan);
pfl->no_elements = dbChannelElements(chan);
/*
* use memcpy to avoid a bus error on
@@ -62,6 +64,7 @@ static void changeValue(db_field_log *pfl2, long val) {
}
static void mustPassOnce(dbChannel *pch, db_field_log *pfl2, char* m, double d, long val) {
int oldFree = db_available_logs(), newFree;
db_field_log *pfl;
changeValue(pfl2, val);
@@ -71,18 +74,26 @@ static void mustPassOnce(dbChannel *pch, db_field_log *pfl2, char* m, double d,
testOk(fl_equal(pfl, pfl2), "call 1 does not change field_log data");
pfl = dbChannelRunPreChain(pch, pfl2);
testOk(NULL == pfl, "call 2 drops field_log");
newFree = db_available_logs();
testOk(newFree == oldFree + 1, "field_log was freed - %d+1 => %d",
oldFree, newFree);
}
static void mustDrop(dbChannel *pch, db_field_log *pfl2, char* m, double d, long val) {
int oldFree = db_available_logs(), newFree;
db_field_log *pfl;
changeValue(pfl2, val);
testDiag("mode=%s delta=%g filter must drop", m, d);
pfl = dbChannelRunPreChain(pch, pfl2);
testOk(NULL == pfl, "call 1 drops field_log");
newFree = db_available_logs();
testOk(newFree == oldFree + 1, "field_log was freed - %d+1 => %d",
oldFree, newFree);
}
static void mustPassTwice(dbChannel *pch, db_field_log *pfl2, char* m, double d, long val) {
int oldFree = db_available_logs(), newFree;
db_field_log *pfl;
changeValue(pfl2, val);
@@ -93,6 +104,9 @@ static void mustPassTwice(dbChannel *pch, db_field_log *pfl2, char* m, double d,
pfl = dbChannelRunPreChain(pch, pfl2);
testOk(pfl2 == pfl, "call 2 does not drop or replace field_log");
testOk(fl_equal(pfl, pfl2), "call 2 does not change field_log data");
newFree = db_available_logs();
testOk(newFree == oldFree, "field_log was not freed - %d => %d",
oldFree, newFree);
}
static void testHead (char* title) {
@@ -113,8 +127,9 @@ MAIN(dbndTest)
db_field_log *pfl2;
db_field_log fl1;
dbEventCtx evtctx;
int logsFree, logsFinal;
testPlan(59);
testPlan(77);
testdbPrepare();
@@ -135,6 +150,11 @@ MAIN(dbndTest)
testOk(!!(pch = dbChannelCreate("x.VAL{\"dbnd\":{}}")), "dbChannel with plugin dbnd (delta=0) created");
testOk((ellCount(&pch->filters) == 1), "channel has one plugin");
/* Start the free-list */
db_delete_field_log(db_create_read_log(pch));
logsFree = db_available_logs();
testDiag("%d field_logs on free-list", logsFree);
memset(&fl, PATTERN, sizeof(fl));
fl1 = fl;
node = ellFirst(&pch->filters);
@@ -176,6 +196,8 @@ MAIN(dbndTest)
dbChannelDelete(pch);
testDiag("%d field_logs on free-list", db_available_logs());
/* Delta = -1: pass any update */
testHead("Delta = -1: pass any update");
@@ -192,6 +214,8 @@ MAIN(dbndTest)
db_delete_field_log(pfl2);
dbChannelDelete(pch);
testDiag("%d field_logs on free-list", db_available_logs());
/* Delta = absolute */
testHead("Delta = absolute");
@@ -224,6 +248,8 @@ MAIN(dbndTest)
dbChannelDelete(pch);
testDiag("%d field_logs on free-list", db_available_logs());
/* Delta = relative */
testHead("Delta = relative");
@@ -275,6 +301,9 @@ MAIN(dbndTest)
dbChannelDelete(pch);
logsFinal = db_available_logs();
testOk(logsFree == logsFinal, "%d field_logs on free-list", logsFinal);
db_close_events(evtctx);
testIocShutdownOk();
+289
View File
@@ -0,0 +1,289 @@
/*************************************************************************\
* Copyright (c) 2019 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.
\*************************************************************************/
/*
* Authors: Ralph Lange <Ralph.Lange@bessy.de>,
* Andrew Johnson <anj@anl.gov>
*/
#include <string.h>
#include "dbStaticLib.h"
#include "dbAccessDefs.h"
#include "db_field_log.h"
#include "dbCommon.h"
#include "dbChannel.h"
#include "registry.h"
#include "chfPlugin.h"
#include "errlog.h"
#include "dbmf.h"
#include "epicsUnitTest.h"
#include "dbUnitTest.h"
#include "epicsTime.h"
#include "testMain.h"
#include "osiFileName.h"
void filterTest_registerRecordDeviceDriver(struct dbBase *);
static int fl_equal(const db_field_log *pfl1, const db_field_log *pfl2) {
return !(memcmp(pfl1, pfl2, sizeof(db_field_log)));
}
static void fl_setup(dbChannel *chan, db_field_log *pfl, long val) {
struct dbCommon *prec = dbChannelRecord(chan);
memset(pfl, 0, sizeof(db_field_log));
pfl->ctx = dbfl_context_event;
pfl->type = dbfl_type_val;
pfl->stat = prec->stat;
pfl->sevr = prec->sevr;
pfl->time = prec->time;
pfl->field_type = DBF_LONG;
pfl->field_size = sizeof(epicsInt32);
pfl->no_elements = 1;
/*
* use memcpy to avoid a bus error on
* union copy of char in the db at an odd
* address
*/
memcpy(&pfl->u.v.field,
dbChannelField(chan),
dbChannelFieldSize(chan));
pfl->u.v.field.dbf_long = val;
}
static void testHead (char* title) {
testDiag("--------------------------------------------------------");
testDiag("%s", title);
testDiag("--------------------------------------------------------");
}
static void mustDrop(dbChannel *pch, db_field_log *pfl, char* m) {
int oldFree = db_available_logs();
db_field_log *pfl2 = dbChannelRunPreChain(pch, pfl);
int newFree = db_available_logs();
testOk(NULL == pfl2, "filter drops field_log (%s)", m);
testOk(newFree == oldFree + 1, "field_log was freed - %d+1 => %d",
oldFree, newFree);
db_delete_field_log(pfl2);
}
static void mustPass(dbChannel *pch, db_field_log *pfl, char* m) {
int oldFree = db_available_logs();
db_field_log *pfl2 = dbChannelRunPreChain(pch, pfl);
int newFree = db_available_logs();
testOk(pfl == pfl2, "filter passes field_log (%s)", m);
testOk(newFree == oldFree, "field_log was not freed - %d => %d",
oldFree, newFree);
db_delete_field_log(pfl2);
}
static void checkAndOpenChannel(dbChannel *pch, const chFilterPlugin *plug) {
ELLNODE *node;
chFilter *filter;
chPostEventFunc *cb_out = NULL;
void *arg_out = NULL;
db_field_log fl, fl1;
testDiag("Test filter structure and open channel");
testOk((ellCount(&pch->filters) == 1), "channel has one plugin");
fl_setup(pch, &fl, 1);
fl1 = fl;
node = ellFirst(&pch->filters);
filter = CONTAINER(node, chFilter, list_node);
plug->fif->channel_register_pre(filter, &cb_out, &arg_out, &fl1);
testOk(cb_out && arg_out,
"register_pre registers one filter with argument");
testOk(fl_equal(&fl1, &fl),
"register_pre does not change field_log data type");
testOk(!(dbChannelOpen(pch)), "dbChannel with plugin dec opened");
node = ellFirst(&pch->pre_chain);
filter = CONTAINER(node, chFilter, pre_node);
testOk((ellCount(&pch->pre_chain) == 1 && filter->pre_arg != NULL),
"dec has one filter with argument in pre chain");
testOk((ellCount(&pch->post_chain) == 0),
"sync has no filter in post chain");
}
MAIN(decTest)
{
dbChannel *pch;
const chFilterPlugin *plug;
char myname[] = "dec";
db_field_log *pfl[10];
int i, logsFree, logsFinal;
dbEventCtx evtctx;
testPlan(104);
testdbPrepare();
testdbReadDatabase("filterTest.dbd", NULL, NULL);
filterTest_registerRecordDeviceDriver(pdbbase);
testdbReadDatabase("xRecord.db", NULL, NULL);
eltc(0);
testIocInitOk();
eltc(1);
evtctx = db_init_events();
testOk(!!(plug = dbFindFilter(myname, strlen(myname))),
"plugin '%s' registered correctly", myname);
/* N < 1 */
testOk(!(pch = dbChannelCreate("x.VAL{\"dec\":{\"n\":-1}}")),
"dbChannel with dec (n=-1) failed");
testOk(!(pch = dbChannelCreate("x.VAL{\"dec\":{\"n\":0}}")),
"dbChannel with dec (n=0) failed");
/* Bad parms */
testOk(!(pch = dbChannelCreate("x.VAL{\"dec\":{}}")),
"dbChannel with dec (no parm) failed");
testOk(!(pch = dbChannelCreate("x.VAL{\"dec\":{\"x\":true}}")),
"dbChannel with dec (x=true) failed");
/* No Decimation (N=1) */
testHead("No Decimation (n=1)");
testOk(!!(pch = dbChannelCreate("x.VAL{\"dec\":{\"n\":1}}")),
"dbChannel with plugin dec (n=1) created");
/* Start the free-list */
db_delete_field_log(db_create_read_log(pch));
logsFree = db_available_logs();
testDiag("%d field_logs on free-list", logsFree);
checkAndOpenChannel(pch, plug);
for (i = 0; i < 5; i++) {
pfl[i] = db_create_read_log(pch);
fl_setup(pch, pfl[i], 10 + i);
}
testDiag("Test event stream");
mustPass(pch, pfl[0], "i=0");
mustPass(pch, pfl[1], "i=1");
mustPass(pch, pfl[2], "i=2");
mustPass(pch, pfl[3], "i=3");
mustPass(pch, pfl[4], "i=4");
dbChannelDelete(pch);
testDiag("%d field_logs on free-list", db_available_logs());
/* Decimation (N=2) */
testHead("Decimation (n=2)");
testOk(!!(pch = dbChannelCreate("x.VAL{\"dec\":{\"n\":2}}")),
"dbChannel with plugin dec (n=2) created");
checkAndOpenChannel(pch, plug);
for (i = 0; i < 10; i++) {
pfl[i] = db_create_read_log(pch);
fl_setup(pch, pfl[i], 20 + i);
}
testDiag("Test event stream");
mustPass(pch, pfl[0], "i=0");
mustDrop(pch, pfl[1], "i=1");
mustPass(pch, pfl[2], "i=2");
mustDrop(pch, pfl[3], "i=3");
mustPass(pch, pfl[4], "i=4");
mustDrop(pch, pfl[5], "i=5");
mustPass(pch, pfl[6], "i=6");
mustDrop(pch, pfl[7], "i=7");
mustPass(pch, pfl[8], "i=8");
mustDrop(pch, pfl[9], "i=9");
dbChannelDelete(pch);
testDiag("%d field_logs on free-list", db_available_logs());
/* Decimation (N=3) */
testHead("Decimation (n=3)");
testOk(!!(pch = dbChannelCreate("x.VAL{\"dec\":{\"n\":3}}")),
"dbChannel with plugin dec (n=3) created");
checkAndOpenChannel(pch, plug);
for (i = 0; i < 10; i++) {
pfl[i] = db_create_read_log(pch);
fl_setup(pch, pfl[i], 30 + i);
}
testDiag("Test event stream");
mustPass(pch, pfl[0], "i=0");
mustDrop(pch, pfl[1], "i=1");
mustDrop(pch, pfl[2], "i=2");
mustPass(pch, pfl[3], "i=3");
mustDrop(pch, pfl[4], "i=4");
mustDrop(pch, pfl[5], "i=5");
mustPass(pch, pfl[6], "i=6");
mustDrop(pch, pfl[7], "i=7");
mustDrop(pch, pfl[8], "i=8");
mustPass(pch, pfl[9], "i=9");
dbChannelDelete(pch);
testDiag("%d field_logs on free-list", db_available_logs());
/* Decimation (N=4) */
testHead("Decimation (n=4)");
testOk(!!(pch = dbChannelCreate("x.VAL{\"dec\":{\"n\":4}}")),
"dbChannel with plugin dec (n=4) created");
checkAndOpenChannel(pch, plug);
for (i = 0; i < 10; i++) {
pfl[i] = db_create_read_log(pch);
fl_setup(pch, pfl[i], 40 + i);
}
testDiag("Test event stream");
mustPass(pch, pfl[0], "i=0");
mustDrop(pch, pfl[1], "i=1");
mustDrop(pch, pfl[2], "i=2");
mustDrop(pch, pfl[3], "i=3");
mustPass(pch, pfl[4], "i=4");
mustDrop(pch, pfl[5], "i=5");
mustDrop(pch, pfl[6], "i=6");
mustDrop(pch, pfl[7], "i=7");
mustPass(pch, pfl[8], "i=8");
mustDrop(pch, pfl[9], "i=9");
dbChannelDelete(pch);
logsFinal = db_available_logs();
testOk(logsFree == logsFinal, "%d field_logs on free-list", logsFinal);
db_close_events(evtctx);
testIocShutdownOk();
testdbCleanup();
return testDone();
}
@@ -17,6 +17,7 @@ int tsTest(void);
int dbndTest(void);
int syncTest(void);
int arrTest(void);
int decTest(void);
void epicsRunFilterTests(void)
{
@@ -26,6 +27,7 @@ void epicsRunFilterTests(void)
runTest(dbndTest);
runTest(syncTest);
runTest(arrTest);
runTest(decTest);
dbmfFreeChunks();
+130 -61
View File
@@ -42,12 +42,14 @@ static int fl_equal(const db_field_log *pfl1, const db_field_log *pfl2) {
static void fl_setup(dbChannel *chan, db_field_log *pfl, long val) {
struct dbCommon *prec = dbChannelRecord(chan);
memset(pfl, 0, sizeof(db_field_log));
pfl->ctx = dbfl_context_event;
pfl->type = dbfl_type_val;
pfl->stat = prec->stat;
pfl->sevr = prec->sevr;
pfl->time = prec->time;
pfl->field_type = DBF_LONG;
pfl->field_size = sizeof(epicsInt32);
pfl->no_elements = 1;
/*
* use memcpy to avoid a bus error on
@@ -66,31 +68,92 @@ static void testHead (char* title) {
testDiag("--------------------------------------------------------");
}
static void mustDrop(dbChannel *pch, db_field_log *pfl2, char* m) {
db_field_log *pfl = dbChannelRunPreChain(pch, pfl2);
testOk(NULL == pfl, "filter drops field_log (%s)", m);
/*
* Use mustDrop() and mustPass() to test filters with no memory
* of previous field_log pointers.
*/
static void mustDrop(dbChannel *pch, db_field_log *pfl, char* m) {
int oldFree = db_available_logs();
db_field_log *pfl2 = dbChannelRunPreChain(pch, pfl);
int newFree = db_available_logs();
testOk(NULL == pfl2, "filter drops field_log (%s)", m);
testOk(newFree == oldFree + 1, "a field_log was freed - %d+1 => %d",
oldFree, newFree);
db_delete_field_log(pfl2);
}
static void mustPassTwice(dbChannel *pch, db_field_log *pfl2, char* m) {
db_field_log *pfl;
static void mustPass(dbChannel *pch, db_field_log *pfl, char* m) {
int oldFree = db_available_logs();
db_field_log *pfl2 = dbChannelRunPreChain(pch, pfl);
int newFree = db_available_logs();
testOk(pfl == pfl2, "filter passes field_log (%s)", m);
testOk(newFree == oldFree, "no field_logs were freed - %d => %d",
oldFree, newFree);
db_delete_field_log(pfl2);
}
/*
* Use mustStash() and mustSwap() to test filters that save
* field_log pointers and return them later.
*
* mustStash() expects the filter to save the current pointer
* (freeing any previously saved pointer) and return NULL.
* mustSwap() expects the filter to return the previously
* saved pointer and save the current pointer.
*/
static db_field_log *stashed;
static void streamReset(void) {
stashed = NULL;
}
static void mustStash(dbChannel *pch, db_field_log *pfl, char* m) {
int oldFree = db_available_logs();
db_field_log *pfl2 = dbChannelRunPreChain(pch, pfl);
int newFree = db_available_logs();
testOk(NULL == pfl2, "filter stashes field_log (%s)", m);
if (stashed) {
testOk(newFree == oldFree + 1, "a field_log was freed - %d+1 => %d",
oldFree, newFree);
}
else {
testOk(newFree == oldFree, "no field_logs were freed - %d => %d",
oldFree, newFree);
}
stashed = pfl;
db_delete_field_log(pfl2);
}
static void mustSwap(dbChannel *pch, db_field_log *pfl, char* m) {
int oldFree = db_available_logs();
db_field_log *pfl2 = dbChannelRunPreChain(pch, pfl);
int newFree = db_available_logs();
testOk(stashed == pfl2, "filter returns stashed field log (%s)", m);
testOk(newFree == oldFree, "no field_logs were freed - %d => %d",
oldFree, newFree);
stashed = pfl;
db_delete_field_log(pfl2);
}
static void mustPassTwice(dbChannel *pch, db_field_log *pfl, char* m) {
int oldFree = db_available_logs(), newFree;
db_field_log *pfl2;
testDiag("%s: filter must pass twice", m);
pfl = dbChannelRunPreChain(pch, pfl2);
pfl2 = dbChannelRunPreChain(pch, pfl);
testOk(pfl2 == pfl, "call 1 does not drop or replace field_log");
pfl = dbChannelRunPreChain(pch, pfl2);
pfl2 = dbChannelRunPreChain(pch, pfl);
testOk(pfl2 == pfl, "call 2 does not drop or replace field_log");
}
static void mustPassOld(dbChannel *pch, db_field_log *old, db_field_log *cur, char* m) {
db_field_log *pfl = dbChannelRunPreChain(pch, cur);
testOk(old == pfl, "filter passes previous field log (%s)", m);
}
static void mustPass(dbChannel *pch, db_field_log *cur, char* m) {
db_field_log *pfl = dbChannelRunPreChain(pch, cur);
testOk(cur == pfl, "filter passes field_log (%s)", m);
newFree = db_available_logs();
testOk(newFree == oldFree, "no field_logs were freed - %d => %d",
oldFree, newFree);
}
static void checkCtxRead(dbChannel *pch, dbStateId id) {
@@ -138,10 +201,10 @@ MAIN(syncTest)
const chFilterPlugin *plug;
char myname[] = "sync";
db_field_log *pfl[10];
int i;
int i, logsFree, logsFinal;
dbEventCtx evtctx;
testPlan(139);
testPlan(214);
testdbPrepare();
@@ -176,9 +239,14 @@ MAIN(syncTest)
testOk(!!(pch = dbChannelCreate("x.VAL{\"sync\":{\"m\":\"while\",\"s\":\"red\"}}")),
"dbChannel with plugin sync (m='while' s='red') created");
/* Start the free-list */
db_delete_field_log(db_create_read_log(pch));
logsFree = db_available_logs();
testDiag("%d field_logs on free-list", logsFree);
checkAndOpenChannel(pch, plug);
for (i = 0; i < 10; i++) {
for (i = 0; i < 9; i++) {
pfl[i] = db_create_read_log(pch);
fl_setup(pch, pfl[i], 120 + i);
}
@@ -198,11 +266,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]);
dbChannelDelete(pch);
testDiag("%d field_logs on free-list", db_available_logs());
/* mode UNLESS */
testHead("Mode UNLESS (m='unless', s='red')");
@@ -211,7 +278,7 @@ MAIN(syncTest)
checkAndOpenChannel(pch, plug);
for (i = 0; i < 10; i++) {
for (i = 0; i < 9; i++) {
pfl[i] = db_create_read_log(pch);
fl_setup(pch, pfl[i], 120 + i);
}
@@ -231,11 +298,10 @@ MAIN(syncTest)
mustPass(pch, pfl[7], "state=FALSE, log7");
mustPass(pch, pfl[8], "state=FALSE, log8");
for (i = 0; i < 10; i++)
db_delete_field_log(pfl[i]);
dbChannelDelete(pch);
testDiag("%d field_logs on free-list", db_available_logs());
/* mode BEFORE */
testHead("Mode BEFORE (m='before', s='red')");
@@ -251,24 +317,25 @@ MAIN(syncTest)
testDiag("Test event stream");
streamReset();
dbStateClear(red);
mustDrop(pch, pfl[0], "state=FALSE, log0");
mustDrop(pch, pfl[1], "state=FALSE, log1");
mustDrop(pch, pfl[2], "state=FALSE, log2");
mustStash(pch, pfl[0], "state=FALSE, log0");
mustStash(pch, pfl[1], "state=FALSE, log1");
mustStash(pch, pfl[2], "state=FALSE, log2");
dbStateSet(red);
mustPassOld(pch, pfl[2], pfl[3], "state=TRUE, log3, pass=log2");
mustDrop(pch, pfl[4], "state=TRUE, log4");
mustDrop(pch, pfl[5], "state=TRUE, log5");
mustDrop(pch, pfl[6], "state=TRUE, log6");
mustSwap(pch, pfl[3], "state=TRUE, log3");
mustStash(pch, pfl[4], "state=TRUE, log4");
mustStash(pch, pfl[5], "state=TRUE, log5");
mustStash(pch, pfl[6], "state=TRUE, log6");
dbStateClear(red);
mustDrop(pch, pfl[7], "state=FALSE, log7");
mustDrop(pch, pfl[8], "state=FALSE, log8");
mustDrop(pch, pfl[9], "state=FALSE, log9");
db_delete_field_log(pfl[2]);
mustStash(pch, pfl[7], "state=FALSE, log7");
mustStash(pch, pfl[8], "state=FALSE, log8");
mustStash(pch, pfl[9], "state=FALSE, log9");
dbChannelDelete(pch);
testDiag("%d field_logs on free-list", db_available_logs());
/* mode FIRST */
testHead("Mode FIRST (m='first', s='red')");
@@ -277,13 +344,14 @@ MAIN(syncTest)
checkAndOpenChannel(pch, plug);
for (i = 0; i < 10; i++) {
for (i = 0; i < 9; i++) {
pfl[i] = db_create_read_log(pch);
fl_setup(pch, pfl[i], 120 + i);
}
testDiag("Test event stream");
streamReset();
dbStateClear(red);
mustDrop(pch, pfl[0], "state=FALSE, log0");
mustDrop(pch, pfl[1], "state=FALSE, log1");
@@ -297,11 +365,10 @@ MAIN(syncTest)
mustDrop(pch, pfl[7], "state=FALSE, log7");
mustDrop(pch, pfl[8], "state=FALSE, log8");
db_delete_field_log(pfl[3]);
db_delete_field_log(pfl[9]);
dbChannelDelete(pch);
testDiag("%d field_logs on free-list", db_available_logs());
/* mode LAST */
testHead("Mode LAST (m='last', s='red')");
@@ -317,24 +384,25 @@ MAIN(syncTest)
testDiag("Test event stream");
streamReset();
dbStateClear(red);
mustDrop(pch, pfl[0], "state=FALSE, log0");
mustDrop(pch, pfl[1], "state=FALSE, log1");
mustDrop(pch, pfl[2], "state=FALSE, log2");
mustStash(pch, pfl[0], "state=FALSE, log0");
mustStash(pch, pfl[1], "state=FALSE, log1");
mustStash(pch, pfl[2], "state=FALSE, log2");
dbStateSet(red);
mustDrop(pch, pfl[3], "state=TRUE, log3");
mustDrop(pch, pfl[4], "state=TRUE, log4");
mustDrop(pch, pfl[5], "state=TRUE, log5");
mustStash(pch, pfl[3], "state=TRUE, log3");
mustStash(pch, pfl[4], "state=TRUE, log4");
mustStash(pch, pfl[5], "state=TRUE, log5");
dbStateClear(red);
mustPassOld(pch, pfl[5], pfl[6], "state=TRUE, log6, pass=log5");
mustDrop(pch, pfl[7], "state=FALSE, log7");
mustDrop(pch, pfl[8], "state=FALSE, log8");
mustDrop(pch, pfl[9], "state=FALSE, log9");
db_delete_field_log(pfl[5]);
mustSwap(pch, pfl[6], "state=TRUE, log6");
mustStash(pch, pfl[7], "state=FALSE, log7");
mustStash(pch, pfl[8], "state=FALSE, log8");
mustStash(pch, pfl[9], "state=FALSE, log9");
dbChannelDelete(pch);
testDiag("%d field_logs on free-list", db_available_logs());
/* mode AFTER */
testHead("Mode AFTER (m='after', s='red')");
@@ -343,13 +411,14 @@ MAIN(syncTest)
checkAndOpenChannel(pch, plug);
for (i = 0; i < 10; i++) {
for (i = 0; i < 9; i++) {
pfl[i] = db_create_read_log(pch);
fl_setup(pch, pfl[i], 120 + i);
}
testDiag("Test event stream");
streamReset();
dbStateClear(red);
mustDrop(pch, pfl[0], "state=FALSE, log0");
mustDrop(pch, pfl[1], "state=FALSE, log1");
@@ -363,11 +432,11 @@ MAIN(syncTest)
mustDrop(pch, pfl[7], "state=FALSE, log7");
mustDrop(pch, pfl[8], "state=FALSE, log8");
db_delete_field_log(pfl[6]);
db_delete_field_log(pfl[9]);
dbChannelDelete(pch);
logsFinal = db_available_logs();
testOk(logsFree == logsFinal, "%d field_logs on free-list", logsFinal);
db_close_events(evtctx);
testIocShutdownOk();
+3 -1
View File
@@ -4,10 +4,12 @@
# EPICS BASE is distributed subject to a Software License Agreement found
# in the file LICENSE that is included with this distribution.
#*************************************************************************
TOP=../../..
TOP=../../../../..
include $(TOP)/configure/CONFIG
USR_CPPFLAGS += -DUSE_TYPED_RSET
TESTLIBRARY = Recs
Recs_SRCS += ioRecord.c
+11 -1
View File
@@ -7,9 +7,12 @@
# in the file LICENSE that is included with this distribution.
#*************************************************************************
TOP = ../../..
TOP = ../../../../..
include $(TOP)/configure/CONFIG
USR_CPPFLAGS += -DUSE_TYPED_RSET
USR_CPPFLAGS += -DUSE_TYPED_DSET
TESTLIBRARY = dbRecStdTest
dbRecStdTest_SRCS += asTestLib.c
@@ -146,6 +149,13 @@ asyncproctest_SRCS += asyncproctest_registerRecordDeviceDriver.cpp
TESTFILES += $(COMMON_DIR)/asyncproctest.dbd ../asyncproctest.db
TESTS += asyncproctest
# dbHeader* is only a compile test
# no need to actually run
TESTPROD += dbHeaderTest
dbHeaderTest_SRCS += dbHeaderTest.cpp
TESTPROD += dbHeaderTestxx
dbHeaderTestxx_SRCS += dbHeaderTestxx.cpp
ifeq ($(T_A),$(EPICS_HOST_ARCH))
# Host-only tests of softIoc/softIocPVA, caget and pvget (if present)
TESTS += netget
@@ -0,0 +1,244 @@
/*************************************************************************\
* Copyright (c) 2019 Michael Davidsaver
* EPICS BASE is distributed subject to a Software License Agreement found
* in file LICENSE that is included with this distribution.
\*************************************************************************/
/* This test includes all public headers from libCom and database modules
* to ensure they are all syntaxtically correct in C and C++
*/
#include <aaiRecord.h>
#include <aaoRecord.h>
#include <addrList.h>
#include <adjustment.h>
#include <aiRecord.h>
#include <alarm.h>
#include <alarmString.h>
#include <aoRecord.h>
#include <asCa.h>
#include <asDbLib.h>
#include <asIocRegister.h>
#include <asLib.h>
#include <asTrapWrite.h>
#include <aSubRecord.h>
#include <biRecord.h>
#include <boRecord.h>
#include <bucketLib.h>
#include <calcoutRecord.h>
#include <calcRecord.h>
#include <callback.h>
#include <cantProceed.h>
#include <caProto.h>
#include <caVersion.h>
#include <caVersionNum.h>
#include <chfPlugin.h>
#include <compilerDependencies.h>
#include <compressRecord.h>
#include <cvtFast.h>
#include <cvtTable.h>
#include <databaseVersion.h>
#include <databaseVersionNum.h>
#include <dbAccessDefs.h>
#include <dbAccess.h>
#include <dbAddr.h>
#include <dbBase.h>
#include <dbBkpt.h>
#include <dbCa.h>
#include <dbCaTest.h>
#include <dbChannel.h>
#include <dbCommon.h>
#include <dbConstLink.h>
#include <dbConvertFast.h>
#include <dbConvert.h>
#include <dbConvertJSON.h>
#include <dbDbLink.h>
#include <dbDefs.h>
#include <dbEvent.h>
#include <dbExtractArray.h>
#include <db_field_log.h>
#include <dbFldTypes.h>
#include <dbIocRegister.h>
#include <dbJLink.h>
#include <dbLink.h>
#include <dbLoadTemplate.h>
#include <dbLock.h>
#include <dbmf.h>
#include <dbNotify.h>
#include <dbScan.h>
#include <dbServer.h>
#include <dbState.h>
#include <dbStaticIocRegister.h>
#include <dbStaticLib.h>
#include <dbStaticPvt.h>
#include <db_test.h>
#include <dbTest.h>
#include <dbtoolsIocRegister.h>
#include <dbUnitTest.h>
#include <devLib.h>
#include <devLibVME.h>
#include <devLibVMEImpl.h>
#include <devSup.h>
#include <dfanoutRecord.h>
#include <drvSup.h>
#include <ellLib.h>
#include <envDefs.h>
#ifdef __cplusplus
# include <epicsAlgorithm.h>
#endif
#include <epicsAssert.h>
#include <epicsAtomic.h>
#include <epicsConvert.h>
#include <epicsEndian.h>
#include <epicsEvent.h>
#include <epicsExit.h>
#include <epicsFindSymbol.h>
#include <epicsGeneralTime.h>
#ifdef __cplusplus
# include <epicsGuard.h>
#endif
#include <epicsInterrupt.h>
#include <epicsMemFs.h>
#include <epicsMessageQueue.h>
#include <epicsMutex.h>
#include <epicsPrint.h>
#include <epicsReadline.h>
#include <epicsRelease.h>
#include <epicsRingBytes.h>
#include <epicsRingPointer.h>
#ifdef __rtems__
# include <epicsRtemsInitHooks.h>
#endif
#include <epicsSignal.h>
#ifdef __cplusplus
# include <epicsSingleton.h>
#endif
#include <epicsSpin.h>
#include <epicsStackTrace.h>
#include <epicsStdio.h>
#include <epicsStdioRedirect.h>
#include <epicsStdlib.h>
#include <epicsString.h>
#include <epicsTempFile.h>
#include <epicsThread.h>
#include <epicsThreadPool.h>
#include <epicsTime.h>
#include <epicsTimer.h>
#include <epicsTypes.h>
#include <epicsUnitTest.h>
#include <epicsVersion.h>
#include <errlog.h>
#include <errMdef.h>
#include <errSymTbl.h>
#include <eventRecord.h>
#include <fanoutRecord.h>
#ifdef __cplusplus
# include <fdManager.h>
#endif
#include <fdmgr.h>
#include <freeList.h>
#include <generalTimeSup.h>
#include <gpHash.h>
#include <histogramRecord.h>
#include <initHooks.h>
#include <int64inRecord.h>
#include <int64outRecord.h>
#include <iocInit.h>
#include <iocLog.h>
#include <iocsh.h>
#include <iocshRegisterCommon.h>
#ifdef __cplusplus
# include <ipAddrToAsciiAsynchronous.h>
#endif
#include <libComRegister.h>
#include <libComVersion.h>
#include <libComVersionNum.h>
#include <link.h>
#ifdef __cplusplus
# include <locationException.h>
#endif
#include <logClient.h>
#include <longinRecord.h>
#include <longoutRecord.h>
#include <lsiRecord.h>
#include <lsoRecord.h>
#include <macLib.h>
#include <mbbiDirectRecord.h>
#include <mbbiRecord.h>
#include <mbboDirectRecord.h>
#include <mbboRecord.h>
#include <menuAlarmSevr.h>
#include <menuAlarmStat.h>
#include <menuConvert.h>
#include <menuFtype.h>
#include <menuIvoa.h>
#include <menuOmsl.h>
#include <menuPini.h>
#include <menuPost.h>
#include <menuPriority.h>
#include <menuScan.h>
#include <menuSimm.h>
#include <menuYesNo.h>
#include <miscIocRegister.h>
#include <osiClockTime.h>
#include <osiPoolStatus.h>
#include <osiProcess.h>
#include <osiSock.h>
#ifdef __cplusplus
# include <osiWireFormat.h>
#endif
#include <epicsGetopt.h>
#include <epicsMath.h>
#include <epicsMMIO.h>
#include <osiFileName.h>
#include <osiUnistd.h>
#include <permissiveRecord.h>
#include <postfix.h>
#include <printfRecord.h>
#include <recGbl.h>
#include <recSup.h>
#include <registryCommon.h>
#include <registryDeviceSupport.h>
#include <registryDriverSupport.h>
#include <registryFunction.h>
#include <registry.h>
#include <registryIocRegister.h>
#include <registryJLinks.h>
#include <registryRecordType.h>
#ifdef __cplusplus
# include <resourceLib.h>
#endif
#include <rsrv.h>
#include <selRecord.h>
#include <seqRecord.h>
#include <shareLib.h>
#include <special.h>
#include <stateRecord.h>
#include <stringinRecord.h>
#include <stringoutRecord.h>
#include <subArrayRecord.h>
#include <subRecord.h>
#include <taskwd.h>
#include <testMain.h>
#ifdef __cplusplus
# include <tsDLList.h>
# include <tsFreeList.h>
# include <tsMinMax.h>
# include <tsSLList.h>
#endif
#include <valgrind/valgrind.h>
#include <waveformRecord.h>
#include <yajl_alloc.h>
#include <yajl_common.h>
#include <yajl_gen.h>
#include <yajl_parse.h>
/* must be last */
#include <epicsExport.h>
MAIN(dbHeaderTest)
{
testPlan(1);
testPass("Compiled successfully");
return testDone();
}
@@ -0,0 +1,2 @@
// just compile as c++
#include "dbHeaderTest.c"
+37 -9
View File
@@ -8,6 +8,9 @@ use lib '@TOP@/lib/perl';
use Test::More tests => 3;
use EPICS::IOC;
# Set to 1 to echo all IOC and client communications
my $debug = 1;
$ENV{HARNESS_ACTIVE} = 1 if scalar @ARGV && shift eq '-tap';
# Keep traffic local and avoid duplicates over multiple interfaces
@@ -23,15 +26,15 @@ $ENV{EPICS_PVAS_SERVER_PORT} = 55075;
$ENV{EPICS_PVA_BROADCAST_PORT} = 55076;
$ENV{EPICS_PVAS_INTF_ADDR_LIST} = 'localhost';
my $bin = "@TOP@/bin/@ARCH@";
my $bin = '@TOP@/bin/@ARCH@';
my $exe = ($^O =~ m/^(MSWin32|cygwin)$/x) ? '.exe' : '';
my $prefix = "test-$$";
my $ioc = EPICS::IOC->new();
#$ioc->debug(1);
$ioc->debug($debug);
$SIG{__DIE__} = $SIG{INT} = $SIG{QUIT} = sub {
$ioc->kill;
$ioc->exit;
BAIL_OUT('Caught signal');
};
@@ -41,7 +44,7 @@ $SIG{__DIE__} = $SIG{INT} = $SIG{QUIT} = sub {
sub kill_bail {
my $doing = shift;
return sub {
$ioc->kill;
$ioc->exit;
BAIL_OUT("Timeout $doing");
}
}
@@ -87,6 +90,19 @@ like($version, qr/^ \d+ \. \d+ \. \d+ /x,
"Got BaseVersion '$version' from iocsh");
# Client Tests
my $client = EPICS::IOC->new;
$client->debug($debug);
sub close_client {
my $doing = shift;
return sub {
diag("Timeout $doing");
$client->close;
}
}
# Channel Access
SKIP: {
@@ -104,10 +120,16 @@ SKIP: {
# CA Client test
watchdog {
my $caVersion = `$caget -w5 $pv`;
$client->start($caget, '-w5', $pv);
my $caVersion = $client->_getline;
like($caVersion, qr/^ $pv \s+ \Q$version\E $/x,
'Got same BaseVersion from caget');
} 10, kill_bail('doing caget');
my @errors = $client->_geterrors;
note("Errors from caget:\n",
map(" $_\n", @errors))
if scalar @errors;
$client->close;
} 15, close_client('doing caget');
}
@@ -131,10 +153,16 @@ SKIP: {
# PVA Client test
watchdog {
my $pvaVersion = `$pvget -w5 $pv`;
$client->start($pvget, '-w5', $pv);
my $pvaVersion = $client->_getline;
like($pvaVersion, qr/^ $pv \s .* \Q$version\E \s* $/x,
'Got same BaseVersion from pvget');
} 10, kill_bail('doing pvget');
my @errors = $client->_geterrors;
note("Errors from pvget:\n",
map(" $_\n", @errors))
if scalar @errors;
$client->close;
} 10, close_client('doing pvget');
}
$ioc->kill;
$ioc->exit;