Merge up changes from below

This commit is contained in:
Andrew Johnson
2018-01-20 19:17:35 -06:00
15 changed files with 303 additions and 83 deletions
+1 -1
View File
@@ -652,7 +652,7 @@ not follow this pattern, but are still printable strings.
=item [1] R3.15 Channel Access Reference Manual by Jeffrey O. Hill
L<http://www.aps.anl.gov/epics/base/R3-15/2-docs/CAref.html>
L<https://epics.anl.gov/base/R3-15/5-docs/CAref.html>
=back
+7 -3
View File
@@ -34,6 +34,8 @@
*
* Two time intervals are measured. The time to queue and run each of
* the immediate callbacks, and the actual delay of the delayed callback.
*
* Slow callbacks no longer fail the test, they just emit a diagnostic.
*/
#define NCALLBACKS 169
@@ -108,7 +110,7 @@ MAIN(callbackParallelTest)
for (j = 0; j < 5; j++)
setupError[i][j] = timeError[i][j] = defaultError[j];
testPlan(4);
testPlan(2);
testDiag("Starting %d parallel callback threads", noCpus);
@@ -165,7 +167,8 @@ MAIN(callbackParallelTest)
}
}
testOk(faults == 0, "%d faults during callback setup", faults);
testOk(slowups <= 1, "%d slowups during callback setup", slowups);
if (slowups)
testDiag("%d slowups during callback setup", slowups);
slowups = 0;
for (i = 0; i < NCALLBACKS ; i++) {
@@ -182,7 +185,8 @@ MAIN(callbackParallelTest)
}
updateStats(timeError[i%NUM_CALLBACK_PRIORITIES], error);
}
testOk(slowups < 5, "%d slowups during callbacks", slowups);
if (slowups)
testDiag("%d slowups during callback setup", slowups);
testDiag("Setup time statistics");
printStats(setupError[0], "LOW");
+7 -3
View File
@@ -34,6 +34,8 @@
*
* Two time intervals are measured. The time to queue and run each of
* the immediate callbacks, and the actual delay of the delayed callback.
*
* Slow callbacks no longer fail the test, they just emit a diagnostic.
*/
#define NCALLBACKS 169
@@ -108,7 +110,7 @@ MAIN(callbackTest)
for (j = 0; j < 5; j++)
setupError[i][j] = timeError[i][j] = defaultError[j];
testPlan(4);
testPlan(2);
callbackInit();
epicsThreadSleep(1.0);
@@ -162,7 +164,8 @@ MAIN(callbackTest)
}
}
testOk(faults == 0, "%d faults during callback setup", faults);
testOk(slowups <= 1, "%d slowups during callback setup", slowups);
if (slowups)
testDiag("%d slowups during callback setup", slowups);
slowups = 0;
for (i = 0; i < NCALLBACKS ; i++) {
@@ -179,7 +182,8 @@ MAIN(callbackTest)
}
updateStats(timeError[i%NUM_CALLBACK_PRIORITIES], error);
}
testOk(slowups < 5, "%d slowups during callbacks", slowups);
if (slowups)
testDiag("%d slowups during callback setup", slowups);
testDiag("Setup time statistics");
printStats(setupError[0], "LOW");
+37 -31
View File
@@ -1,11 +1,11 @@
/*************************************************************************\
* Copyright (c) 2002 The University of Saskatchewan
* Copyright (c) 2014 UChicago Argonne LLC, as Operator of Argonne
* Copyright (c) 2015 UChicago Argonne LLC, as Operator of Argonne
* National Laboratory.
* EPICS BASE is distributed subject to a Software License Agreement found
* in file LICENSE that is included with this distribution.
\*************************************************************************/
/* Author: Eric Norum Date: 12DEC2001 */
/* Author: Eric Norum */
#include <stdio.h>
#include <stdlib.h>
@@ -15,8 +15,15 @@
#include "envDefs.h"
#include "epicsReadline.h"
/* Basic command-line input, no editing or history: */
#define EPICS_COMMANDLINE_LIBRARY_EPICS 0
/* OS-specific command-line editing and/or history: */
#define EPICS_COMMANDLINE_LIBRARY_LIBTECLA 1
#define EPICS_COMMANDLINE_LIBRARY_LEDLIB 1
#define EPICS_COMMANDLINE_LIBRARY_OTHER 1
/* GNU readline, or Apple's libedit wrapper: */
#define EPICS_COMMANDLINE_LIBRARY_READLINE 2
#define EPICS_COMMANDLINE_LIBRARY_READLINE_CURSES 2
#define EPICS_COMMANDLINE_LIBRARY_READLINE_NCURSES 2
@@ -38,18 +45,17 @@ static void osdReadlineEnd(struct readlineContext *);
#if EPICS_COMMANDLINE_LIBRARY == EPICS_COMMANDLINE_LIBRARY_EPICS
static void osdReadlineBegin(struct readlineContext * c) {}
static char * osdReadline(const char *prompt, struct readlineContext * c) { return NULL; }
static void osdReadlineEnd(struct readlineContext * c) {}
static void osdReadlineBegin(struct readlineContext *rc) {}
static char * osdReadline(const char *prompt, struct readlineContext *rc)
{
return NULL;
}
static void osdReadlineEnd(struct readlineContext *rc) {}
#elif EPICS_COMMANDLINE_LIBRARY == EPICS_COMMANDLINE_LIBRARY_READLINE
# include "gnuReadline.c"
#else
# if EPICS_COMMANDLINE_LIBRARY == EPICS_COMMANDLINE_LIBRARY_READLINE
# include "gnuReadline.c"
# else
# include "osdReadline.c"
# endif
# include "osdReadline.c"
#endif
/*
@@ -58,15 +64,15 @@ static void osdReadlineEnd(struct readlineContext * c) {}
void * epicsShareAPI
epicsReadlineBegin(FILE *in)
{
struct readlineContext *readlineContext = calloc(1, sizeof(*readlineContext));
struct readlineContext *rc = calloc(1, sizeof(*rc));
if (readlineContext) {
readlineContext->in = in;
readlineContext->line = NULL;
if (rc) {
rc->in = in;
rc->line = NULL;
if (!envGetConfigParamPtr(&IOCSH_HISTEDIT_DISABLE))
osdReadlineBegin(readlineContext);
osdReadlineBegin(rc);
}
return readlineContext;
return rc;
}
/*
@@ -75,19 +81,19 @@ epicsReadlineBegin(FILE *in)
char * epicsShareAPI
epicsReadline (const char *prompt, void *context)
{
struct readlineContext *readlineContext = context;
struct readlineContext *rc = context;
FILE *in;
char *line;
int c; /* char is unsigned on some archs, EOF is -ve */
int linelen = 0;
int linesize = 50;
if (readlineContext->osd)
return osdReadline(prompt, readlineContext);
if (rc->osd)
return osdReadline(prompt, rc);
free(readlineContext->line);
readlineContext->line = NULL;
if ((in = readlineContext->in) == NULL) {
free(rc->line);
rc->line = NULL;
if ((in = rc->in) == NULL) {
in = stdin;
if (prompt) {
fputs(prompt, stdout);
@@ -125,7 +131,7 @@ epicsReadline (const char *prompt, void *context)
line[linelen++] = c;
}
line[linelen] = '\0';
readlineContext->line = line;
rc->line = line;
return line;
}
@@ -136,13 +142,13 @@ void epicsShareAPI
epicsReadlineEnd (void *context)
{
if (context) {
struct readlineContext *readlineContext = context;
struct readlineContext *rc = context;
if (readlineContext->osd)
osdReadlineEnd(readlineContext);
else
free(readlineContext->line);
free(readlineContext);
if (rc->osd)
osdReadlineEnd(rc);
else
free(rc->line);
free(rc);
}
}
+1 -1
View File
@@ -33,7 +33,7 @@ struct osdContext {
static void
osdReadlineBegin(struct readlineContext *context)
{
struct osdContext osd = malloc(sizeof *osd);
struct osdContext *osd = malloc(sizeof *osd);
if (osd != NULL) {
osd->ledId = (LED_ID) ERROR;
+34 -14
View File
@@ -11,6 +11,7 @@
#include "dbStaticLib.h"
#include "dbTest.h"
#include "dbUnitTest.h"
#include "epicsThread.h"
#include "errlog.h"
#include "registryFunction.h"
#include "subRecord.h"
@@ -39,10 +40,10 @@ void doProcess(const char *rec)
testdbPutFieldOk(proc, DBR_CHAR, 1);
}
/* Group 0 are all soft-channel input records with INP being a DB link
/* Group 0 are soft-channel input records with INP being a DB or CA link
* to the PV 'source'. Their VAL fields all start out with the default
* value for the type, i.e. 0 or an empty string. Triggering record
* processing should read the integer value from the 'source' PV.
* processing reads the value from the 'source' PV.
*/
static
@@ -50,14 +51,22 @@ void testGroup0(void)
{
const char ** rec;
const char * records[] = {
"ai0", "bi0", "di0", "ii0", "li0", "lsi0", "mi0", "si0", NULL
"ai0", "bi0", "di0", "ii0", "li0", "lsi0", "mi0", "si0",
"ai0c", "bi0c", "di0c", "ii0c", "li0c", "lsi0c", "mi0c", "si0c",
NULL
};
testDiag("============ Starting %s ============", EPICS_FUNCTION);
testdbPutFieldOk("source", DBR_LONG, 1);
/* The above put sends CA monitors to all of the CA links, but
* doesn't trigger record processing (the links are not CP/CPP).
* How could we wait until all of those monitors have arrived,
* instead of just waiting for an arbitrary time period?
*/
epicsThreadSleep(1.0); /* FIXME: Wait here? */
for (rec = records; *rec; rec++) {
if (strcmp(*rec, "lsi0") != 0)
if (strncmp(*rec, "lsi0", 4) != 0)
testdbGetFieldEqual(*rec, DBR_LONG, 0);
checkDtyp(*rec);
doProcess(*rec);
@@ -65,6 +74,7 @@ void testGroup0(void)
}
testdbPutFieldOk("source", DBR_LONG, 0);
epicsThreadSleep(1.0); /* FIXME: Wait here as above */
for (rec = records; *rec; rec++) {
doProcess(*rec);
testdbGetFieldEqual(*rec, DBR_LONG, 0);
@@ -129,6 +139,7 @@ static
long destSubr(subRecord *prec)
{
dest = prec->val;
prec->val = -1;
return 0;
}
@@ -138,20 +149,25 @@ void checkOutput(const char *rec, int value)
testDiag("Checking record '%s'", rec);
testdbPutFieldOk(rec, DBR_LONG, value);
/* Even with a local CA link, the dest record gets processed in
* the context of this thread (i.e. immediately). TPRO confirms.
*/
testOk(dest == value, "value %d output -> %d", value, dest);
}
/* Group 3 are all soft-channel output records with OUT being a DB link
* to the PV 'dest' with PP. Putting a value to the record writes that
* value to 'dest' and processes it.
/* Group 3 are all soft-channel output records with OUT being a DB or
* local CA link to the subRecord 'dest'; DB links have the PP flag,
* for CA links the VAL field is marked PP. Putting a value to the
* output record writes that value to 'dest'.
*/
static
void testGroup3(void)
{
const char ** rec;
const char * records[] = {
"ao0", "bo0", "io0", "lo0", "lso0", "mo0", "so0", NULL,
"ao3", "bo3", "io3", "lo3", "lso3", "mo3", "so3",
"ao3c", "bo3c", "io3c", "lo3c", "lso3c", "mo3c", "so3c",
NULL,
};
testDiag("============ Starting %s ============", EPICS_FUNCTION);
@@ -160,13 +176,16 @@ void testGroup3(void)
checkOutput(*rec, 1);
checkDtyp(*rec);
}
checkOutput("do0.B0", 1);
checkDtyp("do0");
checkOutput("do3.B0", 1);
checkDtyp("do3");
checkOutput("do3c.B0", 1);
checkDtyp("do3c");
for (rec = records; *rec; rec++) {
checkOutput(*rec, 0);
}
checkOutput("do0.B0", 0);
checkOutput("do3.B0", 0);
checkOutput("do3c.B0", 0);
}
/* Group 4 are all soft-channel output records with OUT being empty
@@ -177,7 +196,7 @@ void testGroup4(void)
{
const char ** rec;
const char * records[] = {
"ao1", "bo1", "do1.B0", "io1", "lo1", "lso1", "mo1", "so1", NULL,
"ao4", "bo4", "do4.B0", "io4", "lo4", "lso4", "mo4", "so4", NULL,
};
testDiag("============ Starting %s ============", EPICS_FUNCTION);
@@ -189,9 +208,10 @@ void testGroup4(void)
void recTestIoc_registerRecordDeviceDriver(struct dbBase *);
MAIN(softTest)
{
testPlan(163);
testPlan(266);
testdbPrepare();
testdbReadDatabase("recTestIoc.dbd", NULL, NULL);
+128 -19
View File
@@ -59,6 +59,60 @@ record(stringin, "si0") {
field(INP, "source")
}
record(ai, "ai0c") {
field(DTYP, "Soft Channel")
field(INP, "source CA")
}
record(bi, "bi0c") {
field(DTYP, "Soft Channel")
field(INP, "source CA")
field(ZNAM, "Zero")
field(ONAM, "One")
}
record(int64in, "ii0c") {
field(DTYP, "Soft Channel")
field(INP, "source CA")
}
record(longin, "li0c") {
field(DTYP, "Soft Channel")
field(INP, "source CA")
}
record(mbbiDirect, "di0c") {
field(DTYP, "Soft Channel")
field(NOBT, 4)
field(INP, "source CA")
}
record(mbbi, "mi0c") {
field(DTYP, "Soft Channel")
field(NOBT, 4)
field(INP, "source CA")
field(ZRST, "Zero")
field(ONST, "One")
field(TWST, "Two")
field(THST, "Three")
field(FRST, "Four")
field(FVST, "Five")
field(SXST, "Six")
field(SVST, "Seven")
field(EIST, "Eight")
field(NIST, "Nine")
field(TEST, "Ten")
field(ELST, "Eleven")
field(TWST, "Twelve")
field(TTST, "Thirteen")
field(FTST, "Fourteen")
field(FFST, "Fifteen")
}
record(lsi, "lsi0c") {
field(DTYP, "Soft Channel")
field(SIZV, 40)
field(INP, "source CA")
}
record(stringin, "si0c") {
field(DTYP, "Soft Channel")
field(INP, "source CA")
}
# Group 1 are all soft-channel input records with INP being a non-zero
# "const" JSON-link, 9 for most records, 1 for the binary. Their VAL
@@ -171,38 +225,39 @@ record(mbbi, "mi2") {
}
# Group 3 are all soft-channel output records with OUT being a DB link
# to the PV 'dest' with PP. Putting a value to the record writes that
# value to 'dest' and processes it.
# Group 3 are all soft-channel output records with OUT being a DB or
# CA link to the PV 'dest' with PP. Putting a value to the record
# under test writes the value to 'dest' and processes it.
record(sub, "dest") {
field(SNAM, "destSubr")
field(VAL, -1)
}
record(ao, "ao0") {
record(ao, "ao3") {
field(DTYP, "Soft Channel")
field(OUT, "dest PP")
}
record(bo, "bo0") {
record(bo, "bo3") {
field(DTYP, "Soft Channel")
field(OUT, "dest PP")
field(ZNAM, "Zero")
field(ONAM, "One")
}
record(int64out, "io0") {
record(int64out, "io3") {
field(DTYP, "Soft Channel")
field(OUT, "dest PP")
}
record(longout, "lo0") {
record(longout, "lo3") {
field(DTYP, "Soft Channel")
field(OUT, "dest PP")
}
record(mbboDirect, "do0") {
record(mbboDirect, "do3") {
field(DTYP, "Soft Channel")
field(NOBT, 4)
field(OUT, "dest PP")
}
record(mbbo, "mo0") {
record(mbbo, "mo3") {
field(DTYP, "Soft Channel")
field(NOBT, 4)
field(OUT, "dest PP")
@@ -223,39 +278,93 @@ record(mbbo, "mo0") {
field(FTST, "Fourteen")
field(FFST, "Fifteen")
}
record(lso, "lso0") {
record(lso, "lso3") {
field(DTYP, "Soft Channel")
field(OUT, "dest PP")
field(SIZV, 40)
}
record(stringout, "so0") {
record(stringout, "so3") {
field(DTYP, "Soft Channel")
field(OUT, "dest PP")
}
record(ao, "ao3c") {
field(DTYP, "Soft Channel")
field(OUT, "dest CA")
}
record(bo, "bo3c") {
field(DTYP, "Soft Channel")
field(OUT, "dest CA")
field(ZNAM, "Zero")
field(ONAM, "One")
}
record(int64out, "io3c") {
field(DTYP, "Soft Channel")
field(OUT, "dest CA")
}
record(longout, "lo3c") {
field(DTYP, "Soft Channel")
field(OUT, "dest CA")
}
record(mbboDirect, "do3c") {
field(DTYP, "Soft Channel")
field(NOBT, 4)
field(OUT, "dest CA")
}
record(mbbo, "mo3c") {
field(DTYP, "Soft Channel")
field(NOBT, 4)
field(OUT, "dest CA")
field(ZRST, "Zero")
field(ONST, "One")
field(TWST, "Two")
field(THST, "Three")
field(FRST, "Four")
field(FVST, "Five")
field(SXST, "Six")
field(SVST, "Seven")
field(EIST, "Eight")
field(NIST, "Nine")
field(TEST, "Ten")
field(ELST, "Eleven")
field(TWST, "Twelve")
field(TTST, "Thirteen")
field(FTST, "Fourteen")
field(FFST, "Fifteen")
}
record(lso, "lso3c") {
field(DTYP, "Soft Channel")
field(OUT, "dest CA")
field(SIZV, 40)
}
record(stringout, "so3c") {
field(DTYP, "Soft Channel")
field(OUT, "dest CA")
}
# Group 4 are all soft-channel output records with OUT being empty
# (i.e. a CONSTANT link). Putting a value to the record must succeed.
record(ao, "ao1") {
record(ao, "ao4") {
field(DTYP, "Soft Channel")
}
record(bo, "bo1") {
record(bo, "bo4") {
field(DTYP, "Soft Channel")
field(ZNAM, "Zero")
field(ONAM, "One")
}
record(int64out, "io1") {
record(int64out, "io4") {
field(DTYP, "Soft Channel")
}
record(longout, "lo1") {
record(longout, "lo4") {
field(DTYP, "Soft Channel")
}
record(mbboDirect, "do1") {
record(mbboDirect, "do4") {
field(DTYP, "Soft Channel")
field(NOBT, 4)
}
record(mbbo, "mo1") {
record(mbbo, "mo4") {
field(DTYP, "Soft Channel")
field(NOBT, 4)
field(ZRST, "Zero")
@@ -275,10 +384,10 @@ record(mbbo, "mo1") {
field(FTST, "Fourteen")
field(FFST, "Fifteen")
}
record(lso, "lso1") {
record(lso, "lso4") {
field(DTYP, "Soft Channel")
field(SIZV, 40)
}
record(stringout, "so1") {
record(stringout, "so4") {
field(DTYP, "Soft Channel")
}
+2 -2
View File
@@ -18,8 +18,8 @@ use POSIX qw(strftime);
use strict;
# RFC 8601 date+time w/ zone (eg "2014-08-29T09:42:47-0700")
my $tfmt = '%Y-%m-%dT%H:%M:%S';
# RFC 8601 date+time w/ zone (eg "2014-08-29T09:42-0700")
my $tfmt = '%Y-%m-%dT%H:%M';
$tfmt .= '%z' unless $^O eq 'MSWin32'; # %z returns zone name on Windows
my $now = strftime($tfmt, localtime);