diff --git a/modules/database/test/std/rec/Makefile b/modules/database/test/std/rec/Makefile index 816164ebe..a717b769e 100644 --- a/modules/database/test/std/rec/Makefile +++ b/modules/database/test/std/rec/Makefile @@ -23,6 +23,11 @@ PROD_LIBS = dbRecStdTest dbRecStd dbCore ca Com TARGETS += $(COMMON_DIR)/recTestIoc.dbd DBDDEPENDS_FILES += recTestIoc.dbd$(DEP) recTestIoc_DBD = base.dbd +recTestIoc_DBD += bptTypeKdegC.dbd +recTestIoc_DBD += bptTypeKdegF.dbd +recTestIoc_DBD += bptTypeJdegF.dbd +recTestIoc_DBD += bptTypeJdegC.dbd + TESTFILES += $(COMMON_DIR)/recTestIoc.dbd testHarness_SRCS += recTestIoc_registerRecordDeviceDriver.cpp @@ -93,6 +98,34 @@ testHarness_SRCS += longoutTest.c TESTFILES += ../longoutTest.db TESTS += longoutTest +TESTPROD_HOST += boTest +boTest_SRCS += boTest.c +boTest_SRCS += recTestIoc_registerRecordDeviceDriver.cpp +testHarness_SRCS += boTest.c +TESTFILES += ../boTest.db +TESTS += boTest + +TESTPROD_HOST += biTest +biTest_SRCS += biTest.c +biTest_SRCS += recTestIoc_registerRecordDeviceDriver.cpp +testHarness_SRCS += biTest.c +TESTFILES += ../biTest.db +TESTS += biTest + +TESTPROD_HOST += printfTest +printfTest_SRCS += printfTest.c +printfTest_SRCS += recTestIoc_registerRecordDeviceDriver.cpp +testHarness_SRCS += printfTest.c +TESTFILES += ../printfTest.db +TESTS += printfTest + +TESTPROD_HOST += aiTest +aiTest_SRCS += aiTest.c +aiTest_SRCS += recTestIoc_registerRecordDeviceDriver.cpp +testHarness_SRCS += aiTest.c +TESTFILES += ../aiTest.db +TESTS += aiTest + TARGETS += $(COMMON_DIR)/asTestIoc.dbd DBDDEPENDS_FILES += asTestIoc.dbd$(DEP) asTestIoc_DBD += base.dbd diff --git a/modules/database/test/std/rec/aiTest.c b/modules/database/test/std/rec/aiTest.c new file mode 100644 index 000000000..887f56582 --- /dev/null +++ b/modules/database/test/std/rec/aiTest.c @@ -0,0 +1,445 @@ +/*************************************************************************\ +* Copyright (c) 2023 Karl Vestin +* EPICS BASE is distributed subject to a Software License Agreement found +* in file LICENSE that is included with this distribution. +\*************************************************************************/ + +#include "dbUnitTest.h" +#include "testMain.h" +#include "errlog.h" +#include "dbAccess.h" +#include "menuAlarmSevr.h" +#include "menuConvert.h" +#include "epicsMath.h" +#include "menuScan.h" +#include "caeventmask.h" + +void recTestIoc_registerRecordDeviceDriver(struct dbBase *); + +static void test_soft_input(void){ + double value = 543.123; + + /* set soft channel */ + testdbPutFieldOk("test_ai_rec.DTYP", DBF_STRING, "Soft Channel"); + testdbPutFieldOk("test_ai_rec.INP", DBF_STRING, "test_ai_link_rec.VAL"); + testdbPutFieldOk("test_ai_link_rec.FLNK", DBF_STRING, "test_ai_rec"); + + /* set VAL to on linked record */ + testdbPutFieldOk("test_ai_link_rec.VAL", DBF_DOUBLE, value); + + /* verify that this record VAL is updated but RVAL is not */ + testdbGetFieldEqual("test_ai_rec.VAL", DBF_DOUBLE, value); + testdbGetFieldEqual("test_ai_rec.RVAL", DBF_DOUBLE, 0.0); + + // number of tests = 6 +} + +static void test_raw_soft_input(void){ + double value = -255; + + /* set soft channel */ + testdbPutFieldOk("test_ai_rec.DTYP", DBF_STRING, "Raw Soft Channel"); + testdbPutFieldOk("test_ai_rec.INP", DBF_STRING, "test_ai_link_rec.VAL"); + testdbPutFieldOk("test_ai_link_rec.FLNK", DBF_STRING, "test_ai_rec"); + + /* set VAL to on linked record */ + testdbPutFieldOk("test_ai_link_rec.VAL", DBF_DOUBLE, value); + + /* verify that this record RVAL and VAL are updated */ + testdbGetFieldEqual("test_ai_rec.VAL", DBF_DOUBLE, value); + testdbGetFieldEqual("test_ai_rec.RVAL", DBF_DOUBLE, value); + + // number of tests = 6 +} + +static void test_operator_display(void){ + const short hopr = 199; + const short lopr = 50; + const short prec = 2; + const char egu[] = "mm"; + const char desc[] = "hmm?"; + + /* set operator display parameters */ + testdbPutFieldOk("test_ai_rec.EGU", DBF_STRING, egu); + testdbPutFieldOk("test_ai_rec.DESC", DBF_STRING, desc); + testdbPutFieldOk("test_ai_rec.HOPR", DBF_SHORT, hopr); + testdbPutFieldOk("test_ai_rec.LOPR", DBF_SHORT, lopr); + testdbPutFieldOk("test_ai_rec.PREC", DBF_SHORT, prec); + + /* verify operator display parameters read back */ + testdbGetFieldEqual("test_ai_rec.NAME", DBF_STRING, "test_ai_rec"); + testdbGetFieldEqual("test_ai_rec.EGU", DBF_STRING, egu); + testdbGetFieldEqual("test_ai_rec.DESC", DBF_STRING, desc); + testdbGetFieldEqual("test_ai_rec.HOPR", DBF_SHORT, hopr); + testdbGetFieldEqual("test_ai_rec.LOPR", DBF_SHORT, lopr); + testdbGetFieldEqual("test_ai_rec.PREC", DBF_SHORT, prec); + + // number of tests = 7 +} + +static void test_no_linr_unit_conversion(void){ + const short roff = 10; + const short aslo = 2; + const short aoff = 4; + + const short rval = 9; + const short val = (((rval + roff) * aslo) + aoff); + + + /* set soft channel */ + testdbPutFieldOk("test_ai_rec.DTYP", DBF_STRING, "Raw Soft Channel"); + testdbPutFieldOk("test_ai_rec.INP", DBF_STRING, "test_ai_link_rec.VAL"); + testdbPutFieldOk("test_ai_link_rec.FLNK", DBF_STRING, "test_ai_rec"); + + /* set unit conversion parameters */ + testdbPutFieldOk("test_ai_rec.ROFF", DBF_SHORT, roff); + testdbPutFieldOk("test_ai_rec.ASLO", DBF_SHORT, aslo); + testdbPutFieldOk("test_ai_rec.AOFF", DBF_SHORT, aoff); + testdbPutFieldOk("test_ai_rec.LINR", DBF_LONG, menuConvertNO_CONVERSION); + + /* verify conversion */ + testdbPutFieldOk("test_ai_link_rec.VAL", DBF_SHORT, rval); + testdbGetFieldEqual("test_ai_rec.VAL", DBF_SHORT, val); + testdbGetFieldEqual("test_ai_rec.RVAL", DBF_SHORT, rval); + + // number of tests = 10 +} + +static void test_slope_linr_unit_conversion(void){ + const short roff = 1; + const short aslo = 3; + const short aoff = 99; + const short eslo = 3; + const short eoff = 2; + + const short rval = 7; + const short val = ((((rval + roff) * aslo) + aoff) * eslo) + eoff; + + + /* set soft channel */ + testdbPutFieldOk("test_ai_rec.DTYP", DBF_STRING, "Raw Soft Channel"); + testdbPutFieldOk("test_ai_rec.INP", DBF_STRING, "test_ai_link_rec.VAL"); + testdbPutFieldOk("test_ai_link_rec.FLNK", DBF_STRING, "test_ai_rec"); + + /* set unit conversion parameters */ + testdbPutFieldOk("test_ai_rec.ROFF", DBF_LONG, roff); + testdbPutFieldOk("test_ai_rec.ASLO", DBF_LONG, aslo); + testdbPutFieldOk("test_ai_rec.AOFF", DBF_LONG, aoff); + testdbPutFieldOk("test_ai_rec.ESLO", DBF_LONG, eslo); + testdbPutFieldOk("test_ai_rec.EOFF", DBF_LONG, eoff); + testdbPutFieldOk("test_ai_rec.LINR", DBF_LONG, menuConvertSLOPE); + + /* verify conversion */ + testdbPutFieldOk("test_ai_link_rec.VAL", DBF_LONG, rval); + testdbGetFieldEqual("test_ai_rec.VAL", DBF_LONG, val); + testdbGetFieldEqual("test_ai_rec.RVAL", DBF_LONG, rval); + + // number of tests = 12 +} + +static void test_linear_linr_unit_conversion(void){ + const long roff = 6; + const long aslo = 2; + const long aoff = 19; + const long eslo = 4; + const long eoff = 1; + const long egul = 9999; + const long eguf = -1000; + + const long rval = 2; + /* Since our raw soft input does not support EGUL and EGUF conversion LINEAR should work like SLOPE */ + const long val = ((((rval + roff) * aslo) + aoff) * eslo) + eoff; + + + /* set soft channel */ + testdbPutFieldOk("test_ai_rec.DTYP", DBF_STRING, "Raw Soft Channel"); + testdbPutFieldOk("test_ai_rec.INP", DBF_STRING, "test_ai_link_rec.VAL"); + testdbPutFieldOk("test_ai_link_rec.FLNK", DBF_STRING, "test_ai_rec"); + + /* set unit conversion parameters */ + testdbPutFieldOk("test_ai_rec.ROFF", DBF_LONG, roff); + testdbPutFieldOk("test_ai_rec.ASLO", DBF_LONG, aslo); + testdbPutFieldOk("test_ai_rec.AOFF", DBF_LONG, aoff); + testdbPutFieldOk("test_ai_rec.ESLO", DBF_LONG, eslo); + testdbPutFieldOk("test_ai_rec.EOFF", DBF_LONG, eoff); + /* Since our raw soft input does not support EGUL and EGUF conversion we set them to lagre values here just to check they dont break anything */ + testdbPutFieldOk("test_ai_rec.EGUL", DBF_LONG, egul); + testdbPutFieldOk("test_ai_rec.EGUF", DBF_LONG, eguf); + testdbPutFieldOk("test_ai_rec.LINR", DBF_LONG, menuConvertLINEAR); + + /* verify conversion */ + testdbPutFieldOk("test_ai_link_rec.VAL", DBF_LONG, rval); + testdbGetFieldEqual("test_ai_rec.VAL", DBF_LONG, val); + testdbGetFieldEqual("test_ai_rec.RVAL", DBF_LONG, rval); + + // number of tests = 14 +} + +static void test_bpt_conversion(void){ + const float typeKdegFin = 699.550510; + const float typeKdegF = 3.427551e+02; + const float typeKdegCin = 2902.787322; + const float typeKdegC = 7.028131e+02; + const float typeJdegFin = 1218.865107; + const float typeJdegF = 3.897504e+02; + const float typeJdegCin = 4042.988372; + const float typeJdegC = 6.918437e+02; + + /* set soft channel */ + testdbPutFieldOk("test_ai_rec.DTYP", DBF_STRING, "Raw Soft Channel"); + testdbPutFieldOk("test_ai_rec.INP", DBF_STRING, "test_ai_link_rec.VAL"); + testdbPutFieldOk("test_ai_link_rec.FLNK", DBF_STRING, "test_ai_rec"); + + /* set unit conversion parameters */ + testdbPutFieldOk("test_ai_rec.ROFF", DBF_LONG, 0); + testdbPutFieldOk("test_ai_rec.ASLO", DBF_LONG, 1); + testdbPutFieldOk("test_ai_rec.AOFF", DBF_LONG, 0); + + /* Set type K deg F break point table and verify */ + testdbPutFieldOk("test_ai_rec.LINR", DBF_SHORT, menuConverttypeKdegF); + testdbPutFieldOk("test_ai_link_rec.VAL", DBF_FLOAT, typeKdegFin); + testdbGetFieldEqual("test_ai_rec.VAL", DBF_FLOAT, typeKdegF); + + /* Set type K deg C break point table and verify */ + testdbPutFieldOk("test_ai_rec.LINR", DBF_SHORT, menuConverttypeKdegC); + testdbPutFieldOk("test_ai_link_rec.VAL", DBF_FLOAT, typeKdegCin); + testdbGetFieldEqual("test_ai_rec.VAL", DBF_FLOAT, typeKdegC); + + /* Set type J deg F break point table and verify */ + testdbPutFieldOk("test_ai_rec.LINR", DBF_SHORT, menuConverttypeJdegF); + testdbPutFieldOk("test_ai_link_rec.VAL", DBF_FLOAT, typeJdegFin); + testdbGetFieldEqual("test_ai_rec.VAL", DBF_FLOAT, typeJdegF); + + /* Set type J deg C break point table and verify */ + testdbPutFieldOk("test_ai_rec.LINR", DBF_SHORT, menuConverttypeJdegC); + testdbPutFieldOk("test_ai_link_rec.VAL", DBF_FLOAT, typeJdegCin); + testdbGetFieldEqual("test_ai_rec.VAL", DBF_FLOAT, typeJdegC); + + // number of tests = 18 +} + +static void test_smoothing_filter(void){ + const double smoo = 0.7; + const short roff = 1; + const short aslo = 3; + const short aoff = -2; + const short eslo = 2; + const short eoff = 6; + + const short rval1 = 7; + const short val1 = ((((rval1 + roff) * aslo) + aoff) * eslo) + eoff; + const short rval2 = 9; + const short val2_pre_smoo = ((((rval2 + roff) * aslo) + aoff) * eslo) + eoff; + const float val2 = val1 * smoo + (1 - smoo) * val2_pre_smoo; + + + /* set soft channel */ + testdbPutFieldOk("test_ai_rec.DTYP", DBF_STRING, "Raw Soft Channel"); + testdbPutFieldOk("test_ai_rec.INP", DBF_STRING, "test_ai_link_rec.VAL"); + testdbPutFieldOk("test_ai_link_rec.FLNK", DBF_STRING, "test_ai_rec"); + + /* set unit conversion parameters */ + testdbPutFieldOk("test_ai_rec.ROFF", DBF_LONG, roff); + testdbPutFieldOk("test_ai_rec.ASLO", DBF_LONG, aslo); + testdbPutFieldOk("test_ai_rec.AOFF", DBF_LONG, aoff); + testdbPutFieldOk("test_ai_rec.ESLO", DBF_LONG, eslo); + testdbPutFieldOk("test_ai_rec.EOFF", DBF_LONG, eoff); + testdbPutFieldOk("test_ai_rec.LINR", DBF_LONG, menuConvertSLOPE); + + /* set well known starting point (without smmothing) */ + testdbPutFieldOk("test_ai_link_rec.VAL", DBF_SHORT, rval1); + testdbGetFieldEqual("test_ai_rec.VAL", DBF_SHORT, val1); + + /* set SMOO */ + testdbPutFieldOk("test_ai_rec.SMOO", DBF_DOUBLE, smoo); + + /* update value again and verify smoothing */ + testdbPutFieldOk("test_ai_link_rec.VAL", DBF_SHORT, rval2); + testdbGetFieldEqual("test_ai_rec.VAL", DBF_FLOAT, val2); + + /* clear SMOO */ + testdbPutFieldOk("test_ai_rec.SMOO", DBF_DOUBLE, 0.0); + + // number of tests = 15 +} + +static void test_udf(void){ + /* set soft channel */ + testdbPutFieldOk("test_ai_rec2.DTYP", DBF_STRING, "Raw Soft Channel"); + testdbPutFieldOk("test_ai_rec2.INP", DBF_STRING, "test_ai_link_rec2.VAL"); + testdbPutFieldOk("test_ai_link_rec2.FLNK", DBF_STRING, "test_ai_rec2"); + + /* verify UDF */ + testdbGetFieldEqual("test_ai_rec2.UDF", DBF_CHAR, TRUE); + + /* set VAL and verify UDF is cleared */ + testdbPutFieldOk("test_ai_link_rec2.VAL", DBF_FLOAT, 7.0); + testdbGetFieldEqual("test_ai_rec2.UDF", DBF_CHAR, FALSE); + + // number of tests = 6 +} + +static void test_alarm(void){ + const double h = 5000; + const double hh = 7500; + const double l = 200; + const double ll = -20; + const double hyst = 5; + + /* set soft channel */ + testdbPutFieldOk("test_ai_rec.DTYP", DBF_STRING, "Soft Channel"); + testdbPutFieldOk("test_ai_rec.INP", DBF_STRING, "test_ai_link_rec.VAL"); + testdbPutFieldOk("test_ai_link_rec.FLNK", DBF_STRING, "test_ai_rec"); + + /* set alarm parameters */ + testdbPutFieldOk("test_ai_rec.HIGH", DBF_DOUBLE, h); + testdbPutFieldOk("test_ai_rec.HIHI", DBF_DOUBLE, hh); + testdbPutFieldOk("test_ai_rec.LOW", DBF_DOUBLE, l); + testdbPutFieldOk("test_ai_rec.LOLO", DBF_DOUBLE, ll); + testdbPutFieldOk("test_ai_rec.HHSV", DBF_SHORT, menuAlarmSevrMAJOR); + testdbPutFieldOk("test_ai_rec.HSV", DBF_SHORT, menuAlarmSevrMINOR); + testdbPutFieldOk("test_ai_rec.LSV", DBF_SHORT, menuAlarmSevrMINOR); + testdbPutFieldOk("test_ai_rec.LLSV", DBF_SHORT, menuAlarmSevrMAJOR); + + /* set non alarm VAL and verify */ + testdbPutFieldOk("test_ai_link_rec.VAL", DBF_DOUBLE, 400.0); + testdbGetFieldEqual("test_ai_rec.SEVR", DBF_SHORT, menuAlarmSevrNO_ALARM); + + /* set LOW alarm VAL and verify */ + testdbPutFieldOk("test_ai_link_rec.VAL", DBF_DOUBLE, 190.0); + testdbGetFieldEqual("test_ai_rec.VAL", DBF_DOUBLE, 190.0); + testdbGetFieldEqual("test_ai_rec.SEVR", DBF_SHORT, menuAlarmSevrMINOR); + + /* set LOLO alarm VAL and verify */ + testdbPutFieldOk("test_ai_link_rec.VAL", DBF_DOUBLE, -9998.0); + testdbGetFieldEqual("test_ai_rec.SEVR", DBF_SHORT, menuAlarmSevrMAJOR); + + /* set HIGH alarm VAL and verify */ + testdbPutFieldOk("test_ai_link_rec.VAL", DBF_DOUBLE, 6111.0); + testdbGetFieldEqual("test_ai_rec.SEVR", DBF_SHORT, menuAlarmSevrMINOR); + + /* set HIHI alarm VAL and verify */ + testdbPutFieldOk("test_ai_link_rec.VAL", DBF_DOUBLE, 19998.0); + testdbGetFieldEqual("test_ai_rec.SEVR", DBF_SHORT, menuAlarmSevrMAJOR); + + /* set HYST, verify and clear */ + testdbPutFieldOk("test_ai_rec.HYST", DBF_DOUBLE, hyst); + testdbPutFieldOk("test_ai_link_rec.VAL", DBF_DOUBLE, hh - 1.0); + testdbGetFieldEqual("test_ai_rec.SEVR", DBF_SHORT, menuAlarmSevrMAJOR); + testdbPutFieldOk("test_ai_rec.HYST", DBF_DOUBLE, 0.0); + testdbPutFieldOk("test_ai_link_rec.VAL", DBF_DOUBLE, hh - 2.0); + testdbGetFieldEqual("test_ai_rec.SEVR", DBF_SHORT, menuAlarmSevrMINOR); + + /* verify LALM */ + testdbGetFieldEqual("test_ai_rec.LALM", DBF_DOUBLE, h); + + // number of tests = 29 +} + +static void test_aftc(void){ + const double h = 5000; + const double hh = 7500; + const double l = 200; + const double ll = -20; + const double aftc = 3; + testMonitor* test_mon = NULL; + epicsTimeStamp startTime; + epicsTimeStamp endTime; + double diffTime = 0; + + /* set soft channel */ + testdbPutFieldOk("test_ai_rec3.DTYP", DBF_STRING, "Raw Soft Channel"); + testdbPutFieldOk("test_ai_rec3.INP", DBF_STRING, "test_ai_link_rec3.VAL"); + testdbPutFieldOk("test_ai_link_rec3.FLNK", DBF_STRING, "test_ai_rec3"); + + /* set alarm parameters */ + testdbPutFieldOk("test_ai_rec3.HIGH", DBF_DOUBLE, h); + testdbPutFieldOk("test_ai_rec3.HIHI", DBF_DOUBLE, hh); + testdbPutFieldOk("test_ai_rec3.LOW", DBF_DOUBLE, l); + testdbPutFieldOk("test_ai_rec3.LOLO", DBF_DOUBLE, ll); + testdbPutFieldOk("test_ai_rec3.HHSV", DBF_SHORT, menuAlarmSevrMAJOR); + testdbPutFieldOk("test_ai_rec3.HSV", DBF_SHORT, menuAlarmSevrMINOR); + testdbPutFieldOk("test_ai_rec3.LSV", DBF_SHORT, menuAlarmSevrMINOR); + testdbPutFieldOk("test_ai_rec3.LLSV", DBF_SHORT, menuAlarmSevrMAJOR); + + /* test AFTC using a monitor and time stamps */ + testdbPutFieldOk("test_ai_rec3.AFTC", DBF_DOUBLE, aftc); + testdbPutFieldOk("test_ai_rec3.SCAN", DBF_SHORT, menuScan_1_second); + + /* set HIHI alarm VAL */ + testdbPutFieldOk("test_ai_link_rec3.VAL", DBF_DOUBLE, 7550.0); + + /* Create test monitor for alarm SEVR */ + test_mon = testMonitorCreate("test_ai_rec3.VAL", DBE_ALARM, 0); + + /* Get start time */ + epicsTimeGetCurrent(&startTime); + + /* wait for monitor to trigger on the new alarm status*/ + testMonitorWait(test_mon); + epicsTimeGetCurrent(&endTime); + + /* Verify that alarm status is now MAJOR */ + testdbGetFieldEqual("test_ai_rec3.SEVR", DBF_SHORT, menuAlarmSevrMAJOR); + + /* set HI alarm VAL */ + testdbPutFieldOk("test_ai_link_rec3.VAL", DBF_DOUBLE, 5550.0); + + /* Create test monitor for alarm SEVR */ + test_mon = testMonitorCreate("test_ai_rec3.VAL", DBE_ALARM, 0); + + /* Get start time */ + epicsTimeGetCurrent(&startTime); + + /* wait for monitor to trigger on the new alarm status*/ + testMonitorWait(test_mon); + epicsTimeGetCurrent(&endTime); + + /* Verify that alarm status is now MINOR */ + testdbGetFieldEqual("test_ai_rec3.SEVR", DBF_SHORT, menuAlarmSevrMINOR); + + /* Verify that time is at least equal to configured aftc */ + diffTime = epicsTimeDiffInSeconds(&endTime, &startTime); + testOk(diffTime >= aftc, "ATFC time %lf", diffTime); + + // number of tests = 18 +} + +MAIN(aiTest) { + +#ifdef _WIN32 +#if (defined(_MSC_VER) && _MSC_VER < 1900) || \ + (defined(_MINGW) && defined(_TWO_DIGIT_EXPONENT)) + _set_output_format(_TWO_DIGIT_EXPONENT); +#endif +#endif + + testPlan(6+6+11+10+12+14+18+15+6+29+18); + + testdbPrepare(); + testdbReadDatabase("recTestIoc.dbd", NULL, NULL); + recTestIoc_registerRecordDeviceDriver(pdbbase); + + testdbReadDatabase("aiTest.db", NULL, NULL); + + eltc(0); + testIocInitOk(); + eltc(1); + + test_soft_input(); + test_raw_soft_input(); + test_operator_display(); + test_no_linr_unit_conversion(); + test_slope_linr_unit_conversion(); + test_linear_linr_unit_conversion(); + test_bpt_conversion(); + test_smoothing_filter(); + test_udf(); + test_alarm(); + test_aftc(); + + testIocShutdownOk(); + testdbCleanup(); + + return testDone(); +} diff --git a/modules/database/test/std/rec/aiTest.db b/modules/database/test/std/rec/aiTest.db new file mode 100644 index 000000000..ef05fb180 --- /dev/null +++ b/modules/database/test/std/rec/aiTest.db @@ -0,0 +1,20 @@ +record(ai, "test_ai_rec") { +} + +record(ao, "test_ai_link_rec") { + +} + +record(ai, "test_ai_rec2") { +} + +record(ao, "test_ai_link_rec2") { + +} + +record(ai, "test_ai_rec3") { +} + +record(ao, "test_ai_link_rec3") { + +} diff --git a/modules/database/test/std/rec/biTest.c b/modules/database/test/std/rec/biTest.c new file mode 100644 index 000000000..8e551e762 --- /dev/null +++ b/modules/database/test/std/rec/biTest.c @@ -0,0 +1,122 @@ +/*************************************************************************\ +* Copyright (c) 2023 Karl Vestin +* EPICS BASE is distributed subject to a Software License Agreement found +* in file LICENSE that is included with this distribution. +\*************************************************************************/ + +#include "dbUnitTest.h" +#include "testMain.h" +#include "errlog.h" +#include "dbAccess.h" +#include "menuAlarmSevr.h" + +void recTestIoc_registerRecordDeviceDriver(struct dbBase *); + +static void test_soft_input(void){ + /* set soft channel */ + testdbPutFieldOk("test_bi_rec.DTYP", DBF_STRING, "Soft Channel"); + testdbPutFieldOk("test_bi_rec.INP", DBF_STRING, "test_bi_link_rec.VAL"); + testdbPutFieldOk("test_bi_link_rec.FLNK", DBF_STRING, "test_bi_rec"); + + /* set VAL to on linked record */ + testdbPutFieldOk("test_bi_link_rec.VAL", DBF_SHORT, TRUE); + + /* verify that this record VAL is updated but RVAL is not */ + testdbGetFieldEqual("test_bi_rec.VAL", DBF_SHORT, TRUE); + testdbGetFieldEqual("test_bi_rec.RVAL", DBF_SHORT, FALSE); + + // number of tests = 6 +} + +static void test_raw_soft_input(void){ + /* set soft channel */ + testdbPutFieldOk("test_bi_rec.DTYP", DBF_STRING, "Raw Soft Channel"); + testdbPutFieldOk("test_bi_rec.INP", DBF_STRING, "test_bi_link_rec.VAL"); + testdbPutFieldOk("test_bi_link_rec.FLNK", DBF_STRING, "test_bi_rec"); + + /* set VAL to on linked record */ + testdbPutFieldOk("test_bi_link_rec.VAL", DBF_SHORT, TRUE); + + /* verify that this record RVAL and VAL are updated */ + testdbGetFieldEqual("test_bi_rec.VAL", DBF_SHORT, TRUE); + testdbGetFieldEqual("test_bi_rec.RVAL", DBF_SHORT, TRUE); + + // number of tests = 6 +} + +static void test_operator_display(void){ + /* set operator display parameters */ + testdbPutFieldOk("test_bi_rec.ZNAM", DBF_STRING, "ZNAM_TEST"); + testdbPutFieldOk("test_bi_rec.ONAM", DBF_STRING, "ONAM_TEST"); + testdbPutFieldOk("test_bi_rec.DESC", DBF_STRING, "DESC_TEST"); + + /* verify operator display parameters */ + testdbGetFieldEqual("test_bi_rec.ZNAM", DBF_STRING, "ZNAM_TEST"); + testdbGetFieldEqual("test_bi_rec.ONAM", DBF_STRING, "ONAM_TEST"); + testdbGetFieldEqual("test_bi_rec.NAME", DBF_STRING, "test_bi_rec"); + testdbGetFieldEqual("test_bi_rec.DESC", DBF_STRING, "DESC_TEST"); + + /* verify conversion */ + testdbPutFieldOk("test_bi_link_rec.VAL", DBF_SHORT, TRUE); + testdbGetFieldEqual("test_bi_rec.VAL", DBF_STRING, "ONAM_TEST"); + testdbPutFieldOk("test_bi_link_rec.VAL", DBF_SHORT, FALSE); + testdbGetFieldEqual("test_bi_rec.VAL", DBF_STRING, "ZNAM_TEST"); + + // number of tests = 11 +} + +static void test_alarm(void){ + /* set soft channel */ + testdbPutFieldOk("test_bi_rec.DTYP", DBF_STRING, "Soft Channel"); + testdbPutFieldOk("test_bi_rec.INP", DBF_STRING, "test_bi_link_rec.VAL"); + testdbPutFieldOk("test_bi_link_rec.FLNK", DBF_STRING, "test_bi_rec"); + + /* set start VAL to FALSE*/ + testdbPutFieldOk("test_bi_link_rec.VAL", DBF_SHORT, FALSE); + + /* set alarm parameters */ + testdbPutFieldOk("test_bi_rec.ZSV", DBF_SHORT, menuAlarmSevrNO_ALARM); + testdbPutFieldOk("test_bi_rec.OSV", DBF_SHORT, menuAlarmSevrMINOR); + testdbPutFieldOk("test_bi_rec.COSV", DBF_SHORT, menuAlarmSevrINVALID); + + /* verify alarm status is NO_ALARM*/ + testdbGetFieldEqual("test_bi_rec.SEVR", DBF_SHORT, menuAlarmSevrNO_ALARM); + + /* set ZSV to MAJOR and verify that SEVR is now MAJOR */ + testdbPutFieldOk("test_bi_rec.ZSV", DBF_SHORT, menuAlarmSevrMAJOR); + testdbGetFieldEqual("test_bi_rec.SEVR", DBF_SHORT, menuAlarmSevrMAJOR); + + /* set VAL to 1 on linked record and verify that COSV now sets the SEVR to INVALID */ + testdbPutFieldOk("test_bi_link_rec.VAL", DBF_SHORT, TRUE); + testdbGetFieldEqual("test_bi_rec.SEVR", DBF_SHORT, menuAlarmSevrINVALID); + + /* verify LAML */ + testdbGetFieldEqual("test_bi_rec.LALM", DBF_SHORT, TRUE); + + // number of tests = 13 +} + +MAIN(biTest) { + + testPlan(6+6+11+13); + + testdbPrepare(); + testdbReadDatabase("recTestIoc.dbd", NULL, NULL); + recTestIoc_registerRecordDeviceDriver(pdbbase); + + testdbReadDatabase("biTest.db", NULL, NULL); + + eltc(0); + testIocInitOk(); + eltc(1); + + test_soft_input(); + test_raw_soft_input(); + test_operator_display(); + test_alarm(); + + testIocShutdownOk(); + testdbCleanup(); + + return testDone(); +} diff --git a/modules/database/test/std/rec/biTest.db b/modules/database/test/std/rec/biTest.db new file mode 100644 index 000000000..4304cce91 --- /dev/null +++ b/modules/database/test/std/rec/biTest.db @@ -0,0 +1,6 @@ +record(bi, "test_bi_rec") { +} + +record(bo, "test_bi_link_rec") { + +} diff --git a/modules/database/test/std/rec/boTest.c b/modules/database/test/std/rec/boTest.c new file mode 100644 index 000000000..55865c79c --- /dev/null +++ b/modules/database/test/std/rec/boTest.c @@ -0,0 +1,158 @@ +/*************************************************************************\ +* Copyright (c) 2023 Karl Vestin +* EPICS BASE is distributed subject to a Software License Agreement found +* in file LICENSE that is included with this distribution. +\*************************************************************************/ + +#include "dbUnitTest.h" +#include "testMain.h" +#include "errlog.h" +#include "dbAccess.h" +#include "menuAlarmSevr.h" +#include "menuIvoa.h" + +#include "boRecord.h" + +void recTestIoc_registerRecordDeviceDriver(struct dbBase *); + +static void test_soft_output(void){ + /* set soft channel */ + testdbPutFieldOk("test_bo_rec.DTYP", DBF_STRING, "Soft Channel"); + testdbPutFieldOk("test_bo_rec.OUT", DBF_STRING, "test_bo_link_rec"); + + /* set VAL to process record */ + testdbPutFieldOk("test_bo_rec.VAL", DBF_SHORT, TRUE); + + /* verify that OUT record is updated */ + testdbGetFieldEqual("test_bo_link_rec.VAL", DBF_SHORT, TRUE); + + // number of tests = 4 +} + +static void test_high(void){ + const int high_time = 2; + testMonitor* test_mon = NULL; + epicsTimeStamp startTime; + epicsTimeStamp endTime; + double diffTime = 0; + double diffTimeTolerance = 0.1; + + /* set soft channel */ + testdbPutFieldOk("test_bo_rec.DTYP", DBF_STRING, "Soft Channel"); + testdbPutFieldOk("test_bo_rec.OUT", DBF_STRING, "test_bo_link_rec"); + + /* set HIGH to 2 seconds */ + testdbPutFieldOk("test_bo_rec.HIGH", DBF_SHORT, high_time); + + /* Create test monitor */ + test_mon = testMonitorCreate("test_bo_rec.VAL", DBR_SHORT, 0); + + /* Get start time */ + epicsTimeGetCurrent(&startTime); + + /* set VAL to process record */ + testdbPutFieldOk("test_bo_rec.VAL", DBF_SHORT, TRUE); + + /* wait and verfiy time */ + testMonitorWait(test_mon); + epicsTimeGetCurrent(&endTime); + + /* EPICS timers have a tendency to trip slightly early, hence the test tolerance is added here to avoid false positives in testing */ + diffTime = epicsTimeDiffInSeconds(&endTime, &startTime) + diffTimeTolerance; + testOk(diffTime >= high_time, "HIGH time %lf", diffTime); + + /* verify that both records are set back to 0 */ + testdbGetFieldEqual("test_bo_rec.VAL", DBF_SHORT, FALSE); + testdbGetFieldEqual("test_bo_link_rec.VAL", DBF_SHORT, FALSE); + + testMonitorDestroy(test_mon); + // number of tests = 7 +} + +static void test_operator_display(void){ + /* set operator display parameters */ + testdbPutFieldOk("test_bo_rec.ZNAM", DBF_STRING, "ZNAM_TEST"); + testdbPutFieldOk("test_bo_rec.ONAM", DBF_STRING, "ONAM_TEST"); + testdbPutFieldOk("test_bo_rec.DESC", DBF_STRING, "DESC_TEST"); + + /* verify operator display parameters */ + testdbGetFieldEqual("test_bo_rec.ZNAM", DBF_STRING, "ZNAM_TEST"); + testdbGetFieldEqual("test_bo_rec.ONAM", DBF_STRING, "ONAM_TEST"); + testdbGetFieldEqual("test_bo_rec.NAME", DBF_STRING, "test_bo_rec"); + testdbGetFieldEqual("test_bo_rec.DESC", DBF_STRING, "DESC_TEST"); + + /* verify conversion */ + testdbPutFieldOk("test_bo_rec.VAL", DBF_SHORT, TRUE); + testdbGetFieldEqual("test_bo_rec.VAL", DBF_STRING, "ONAM_TEST"); + testdbPutFieldOk("test_bo_rec.VAL", DBF_SHORT, FALSE); + testdbGetFieldEqual("test_bo_rec.VAL", DBF_STRING, "ZNAM_TEST"); + + // number of tests = 11 +} + +static void test_alarm(void){ + /* set soft channel */ + testdbPutFieldOk("test_bo_rec.DTYP", DBF_STRING, "Soft Channel"); + testdbPutFieldOk("test_bo_rec.OUT", DBF_STRING, "test_bo_link_rec"); + + /* Set start VAL to FALSE*/ + testdbPutFieldOk("test_bo_rec.VAL", DBF_SHORT, FALSE); + + /* set alarm parameters */ + testdbPutFieldOk("test_bo_rec.ZSV", DBF_SHORT, menuAlarmSevrNO_ALARM); + testdbPutFieldOk("test_bo_rec.OSV", DBF_SHORT, menuAlarmSevrMINOR); + testdbPutFieldOk("test_bo_rec.COSV", DBF_SHORT, menuAlarmSevrINVALID); + testdbPutFieldOk("test_bo_rec.IVOA", DBF_SHORT, menuIvoaSet_output_to_IVOV); + testdbPutFieldOk("test_bo_rec.IVOV", DBF_SHORT, FALSE); + + /* Verify alarm status is NO_ALARM*/ + testdbGetFieldEqual("test_bo_rec.SEVR", DBF_SHORT, menuAlarmSevrNO_ALARM); + + /* Set ZSV to MAJOR and verify that SEVR is now MAJOR */ + testdbPutFieldOk("test_bo_rec.ZSV", DBF_SHORT, menuAlarmSevrMAJOR); + testdbGetFieldEqual("test_bo_rec.SEVR", DBF_SHORT, menuAlarmSevrMAJOR); + + /* Set VAL to 1 and verify that COSV now sets the SEVR to INVALID and in turn triggers the IVOV on output */ + testdbPutFieldOk("test_bo_link_rec.VAL", DBF_SHORT, TRUE); + testdbPutFieldOk("test_bo_rec.VAL", DBF_SHORT, TRUE); + testdbGetFieldEqual("test_bo_rec.SEVR", DBF_SHORT, menuAlarmSevrINVALID); + testdbGetFieldEqual("test_bo_link_rec.VAL", DBF_SHORT, FALSE); + + /* verify IVOV continue normally action */ + testdbPutFieldOk("test_bo_rec.IVOA", DBF_SHORT, menuIvoaContinue_normally); + testdbPutFieldOk("test_bo_rec.VAL", DBF_SHORT, TRUE); + testdbGetFieldEqual("test_bo_link_rec.VAL", DBF_SHORT, TRUE); + + /* verify IVOV dont drive outputs action */ + testdbPutFieldOk("test_bo_rec.VAL", DBF_SHORT, FALSE); + testdbPutFieldOk("test_bo_rec.IVOA", DBF_SHORT, menuIvoaDon_t_drive_outputs); + testdbPutFieldOk("test_bo_rec.VAL", DBF_SHORT, TRUE); + testdbGetFieldEqual("test_bo_link_rec.VAL", DBF_SHORT, FALSE); + + // number of tests = 22 +} + +MAIN(boTest) { + + testPlan(4+7+11+22); + + testdbPrepare(); + testdbReadDatabase("recTestIoc.dbd", NULL, NULL); + recTestIoc_registerRecordDeviceDriver(pdbbase); + + testdbReadDatabase("boTest.db", NULL, NULL); + + eltc(0); + testIocInitOk(); + eltc(1); + + test_soft_output(); + test_high(); + test_operator_display(); + test_alarm(); + + testIocShutdownOk(); + testdbCleanup(); + + return testDone(); +} diff --git a/modules/database/test/std/rec/boTest.db b/modules/database/test/std/rec/boTest.db new file mode 100644 index 000000000..0e39cf5f0 --- /dev/null +++ b/modules/database/test/std/rec/boTest.db @@ -0,0 +1,6 @@ +record(bo, "test_bo_rec") { +} + +record(bi, "test_bo_link_rec") { + +} diff --git a/modules/database/test/std/rec/epicsRunRecordTests.c b/modules/database/test/std/rec/epicsRunRecordTests.c index 79db80e3f..60ddd0f32 100644 --- a/modules/database/test/std/rec/epicsRunRecordTests.c +++ b/modules/database/test/std/rec/epicsRunRecordTests.c @@ -24,6 +24,10 @@ int asyncSoftTest(void); int simmTest(void); int mbbioDirectTest(void); int scanEventTest(void); +int boTest(void); +int biTest(void); +int printfTest(void); +int aiTest(void); void epicsRunRecordTests(void) { @@ -51,5 +55,13 @@ void epicsRunRecordTests(void) runTest(scanEventTest); + runTest(boTest); + + runTest(biTest); + + runTest(printfTest); + + runTest(aiTest); + epicsExit(0); /* Trigger test harness */ } diff --git a/modules/database/test/std/rec/printfTest.c b/modules/database/test/std/rec/printfTest.c new file mode 100644 index 000000000..b62b1d9c0 --- /dev/null +++ b/modules/database/test/std/rec/printfTest.c @@ -0,0 +1,577 @@ +/*************************************************************************\ +* Copyright (c) 2023 Karl Vestin +* EPICS BASE is distributed subject to a Software License Agreement found +* in file LICENSE that is included with this distribution. +\*************************************************************************/ + +#include "dbUnitTest.h" +#include "testMain.h" +#include "errlog.h" +#include "dbAccess.h" + +void recTestIoc_registerRecordDeviceDriver(struct dbBase *); + +static void test_double_percentile(void){ + const char format_string[] = "Format test string %%d"; + const char result_string[] = "Format test string %d"; + + /* set format string */ + testdbPutFieldOk("test_printf_rec.FMT", DBF_STRING, format_string); + + /* set value on inp0 */ + testdbPutFieldOk("test_printf_inp0_rec.VAL", DBF_SHORT, 1); + + /* verify that string is formatted as expected */ + testdbGetFieldEqual("test_printf_rec.VAL", DBF_STRING, result_string); + + // number of tests = 3 +} + +static void test_d_format(void){ + const char format_string[] = "Format test string %d"; + const char result_string[] = "Format test string 7"; + + /* set format string */ + testdbPutFieldOk("test_printf_rec.FMT", DBF_STRING, format_string); + + /* set value on inp0 */ + testdbPutFieldOk("test_printf_inp0_rec.VAL", DBF_SHORT, 7); + + /* verify that string is formatted as expected */ + testdbGetFieldEqual("test_printf_rec.VAL", DBF_STRING, result_string); + + // number of tests = 3 +} + +static void test_c_format(void){ + const char format_string[] = "Format test string %c"; + const char result_string[] = "Format test string R"; + + /* set format string */ + testdbPutFieldOk("test_printf_rec.FMT", DBF_STRING, format_string); + + /* set value on inp0, 82 is ASCII for R */ + testdbPutFieldOk("test_printf_inp0_rec.VAL", DBF_SHORT, 82); + + /* verify that string is formatted as expected */ + testdbGetFieldEqual("test_printf_rec.VAL", DBF_STRING, result_string); + + // number of tests = 3 +} + +static void test_i_format(void){ + const char format_string[] = "Format test string %i"; + const char result_string[] = "Format test string -27"; + + /* set format string */ + testdbPutFieldOk("test_printf_rec.FMT", DBF_STRING, format_string); + + /* set value on inp0 */ + testdbPutFieldOk("test_printf_inp0_rec.VAL", DBF_SHORT, -27); + + /* verify that string is formatted as expected */ + testdbGetFieldEqual("test_printf_rec.VAL", DBF_STRING, result_string); + + // number of tests = 3 +} + +static void test_o_format(void){ + const char format_string[] = "Format test string %o"; + const char result_string[] = "Format test string 6777"; + + /* set format string */ + testdbPutFieldOk("test_printf_rec.FMT", DBF_STRING, format_string); + + /* set value on inp0 */ + testdbPutFieldOk("test_printf_inp0_rec.VAL", DBF_SHORT, 06777); + + /* verify that string is formatted as expected */ + testdbGetFieldEqual("test_printf_rec.VAL", DBF_STRING, result_string); + + // number of tests = 3 +} + +static void test_u_format(void){ + const char format_string[] = "Format test string %u"; + const char result_string[] = "Format test string 8009"; + + /* set format string */ + testdbPutFieldOk("test_printf_rec.FMT", DBF_STRING, format_string); + + /* set value on inp0 */ + testdbPutFieldOk("test_printf_inp0_rec.VAL", DBF_SHORT, 8009); + + /* verify that string is formatted as expected */ + testdbGetFieldEqual("test_printf_rec.VAL", DBF_STRING, result_string); + + // number of tests = 3 +} + +static void test_x_format(void){ + const char format_string[] = "Format test string %x"; + const char result_string[] = "Format test string fafa"; + + /* set format string */ + testdbPutFieldOk("test_printf_rec.FMT", DBF_STRING, format_string); + + /* set value on inp0 */ + testdbPutFieldOk("test_printf_inp0_rec.VAL", DBF_LONG, 0xfafa); + + /* verify that string is formatted as expected */ + testdbGetFieldEqual("test_printf_rec.VAL", DBF_STRING, result_string); + + // number of tests = 3 +} + +static void test_X_format(void){ + const char format_string[] = "Format test string %X"; + const char result_string[] = "Format test string BA"; + + /* set format string */ + testdbPutFieldOk("test_printf_rec.FMT", DBF_STRING, format_string); + + /* set value on inp0 */ + testdbPutFieldOk("test_printf_inp0_rec.VAL", DBF_SHORT, 0x00ba); + + /* verify that string is formatted as expected */ + testdbGetFieldEqual("test_printf_rec.VAL", DBF_STRING, result_string); + + // number of tests = 3 +} + +static void test_e_format(void){ + const char format_string[] = "Format test string %e"; + const char result_string[] = "Format test string -1.400000e+01"; + + /* set format string */ + testdbPutFieldOk("test_printf_rec.FMT", DBF_STRING, format_string); + + /* set value on inp0 */ + testdbPutFieldOk("test_printf_inp0_rec.VAL", DBF_SHORT, -14); + + /* verify that string is formatted as expected */ + testdbGetFieldEqual("test_printf_rec.VAL", DBF_STRING, result_string); + + // number of tests = 3 +} + +static void test_E_format(void){ + const char format_string[] = "Format test string %E"; + const char result_string[] = "Format test string 1.992000E+03"; + + /* set format string */ + testdbPutFieldOk("test_printf_rec.FMT", DBF_STRING, format_string); + + /* set value on inp0 */ + testdbPutFieldOk("test_printf_inp0_rec.VAL", DBF_SHORT, 1992); + + /* verify that string is formatted as expected */ + testdbGetFieldEqual("test_printf_rec.VAL", DBF_STRING, result_string); + + // number of tests = 3 +} + +static void test_f_format(void){ + const char format_string[] = "Format test string %f"; + const char result_string[] = "Format test string -0.062000"; + + /* set format string */ + testdbPutFieldOk("test_printf_rec.FMT", DBF_STRING, format_string); + + /* set value on inp0 */ + testdbPutFieldOk("test_printf_inp0_rec.VAL", DBF_DOUBLE, -0.062); + + /* verify that string is formatted as expected */ + testdbGetFieldEqual("test_printf_rec.VAL", DBF_STRING, result_string); + + // number of tests = 3 +} + +static void test_F_format(void){ + const char format_string[] = "Format test string %F"; + const char result_string[] = "Format test string 6729982.999000"; + + /* set format string */ + testdbPutFieldOk("test_printf_rec.FMT", DBF_STRING, format_string); + + /* set value on inp0 */ + testdbPutFieldOk("test_printf_inp0_rec.VAL", DBF_DOUBLE, 6729982.999); + + /* verify that string is formatted as expected */ + // visual studio less than 2015 does not support %F + // mingw/gcc also fails, suspect this may be gcc version + // related and checking __GNUC__ could resolve but + // initial attempts didn't work so excluding mingw entirely for now + #ifdef _WIN32 + #if (defined(_MSC_VER) && _MSC_VER < 1900) || defined(_MINGW) + testTodoBegin("Fails on windows with old visual studio versions and mingw"); + #endif + #endif + + testdbGetFieldEqual("test_printf_rec.VAL", DBF_STRING, result_string); + + #ifdef _WIN32 + #if (defined(_MSC_VER) && _MSC_VER < 1900) || defined(_MINGW) + testTodoEnd(); + #endif + #endif + // number of tests = 3 +} + +static void test_g_format(void){ + const char format_string[] = "Format test string %g"; + const char result_string[] = "Format test string -0.093"; + + /* set format string */ + testdbPutFieldOk("test_printf_rec.FMT", DBF_STRING, format_string); + + /* set value on inp0 */ + testdbPutFieldOk("test_printf_inp0_rec.VAL", DBF_DOUBLE, -93e-3); + + /* verify that string is formatted as expected */ + testdbGetFieldEqual("test_printf_rec.VAL", DBF_STRING, result_string); + + // number of tests = 3 +} + +static void test_G_format(void){ + const char format_string[] = "Format test string %G"; + const char result_string[] = "Format test string 7.2884E+08"; + + /* set format string */ + testdbPutFieldOk("test_printf_rec.FMT", DBF_STRING, format_string); + + /* set value on inp0 */ + testdbPutFieldOk("test_printf_inp0_rec.VAL", DBF_LONG, 728839938); + + /* verify that string is formatted as expected */ + testdbGetFieldEqual("test_printf_rec.VAL", DBF_STRING, result_string); + + // number of tests = 3 +} + +static void test_s_format(void){ + + const char format_string[] = "Format test string %d %s"; + const char result_string[] = "Format test string 7 Molly III"; + + /* set format string */ + testdbPutFieldOk("test_printf_rec.FMT", DBF_STRING, format_string); + + /* set value on inp0 */ + testdbPutFieldOk("test_printf_inp0_rec.VAL", DBF_SHORT, 7); + + /* set value on inp1 */ + testdbPutFieldOk("test_printf_inp1_rec.VAL", DBF_STRING, "Molly III"); + + /* verify that string is formatted as expected */ + testdbGetFieldEqual("test_printf_rec.VAL", DBF_STRING, result_string); + + // number of tests = 4 +} + +static void test_plus_flag(void){ + + const char format_string[] = "Format test string %+d"; + const char result_string[] = "Format test string +7"; + + /* set format string */ + testdbPutFieldOk("test_printf_rec.FMT", DBF_STRING, format_string); + + /* set value on inp0 */ + testdbPutFieldOk("test_printf_inp0_rec.VAL", DBF_SHORT, 7); + + /* verify that string is formatted as expected */ + testdbGetFieldEqual("test_printf_rec.VAL", DBF_STRING, result_string); + + // number of tests = 3 +} + +static void test_minus_flag(void){ + + const char format_string[] = "Format test string %-10d"; + const char result_string[] = "Format test string 18 "; + + /* set format string */ + testdbPutFieldOk("test_printf_rec.FMT", DBF_STRING, format_string); + + /* set value on inp0 */ + testdbPutFieldOk("test_printf_inp0_rec.VAL", DBF_SHORT, 18); + + /* verify that string is formatted as expected */ + testdbGetFieldEqual("test_printf_rec.VAL", DBF_STRING, result_string); + + // number of tests = 3 +} + +static void test_space_flag(void){ + + const char format_string[] = "Format test string % d"; + const char result_string[] = "Format test string 12"; + + /* set format string */ + testdbPutFieldOk("test_printf_rec.FMT", DBF_STRING, format_string); + + /* set value on inp0 */ + testdbPutFieldOk("test_printf_inp0_rec.VAL", DBF_SHORT, 12); + + /* verify that string is formatted as expected */ + testdbGetFieldEqual("test_printf_rec.VAL", DBF_STRING, result_string); + + // number of tests = 3 +} + +static void test_hash_flag(void){ + + const char format_string[] = "Format test string %#o"; + const char result_string[] = "Format test string 014"; + + /* set format string */ + testdbPutFieldOk("test_printf_rec.FMT", DBF_STRING, format_string); + + /* set value on inp0 */ + testdbPutFieldOk("test_printf_inp0_rec.VAL", DBF_SHORT, 014); + + /* verify that string is formatted as expected */ + testdbGetFieldEqual("test_printf_rec.VAL", DBF_STRING, result_string); + + // number of tests = 3 +} + +static void test_min_width_flag(void){ + + const char format_string[] = "Format test string %04i"; + const char result_string[] = "Format test string 0003"; + + /* set format string */ + testdbPutFieldOk("test_printf_rec.FMT", DBF_STRING, format_string); + + /* set value on inp0 */ + testdbPutFieldOk("test_printf_inp0_rec.VAL", DBF_SHORT, 3); + + /* verify that string is formatted as expected */ + testdbGetFieldEqual("test_printf_rec.VAL", DBF_STRING, result_string); + + // number of tests = 3 +} + +static void test_prec_flag(void){ + + const char format_string[] = "Format test string %.4f"; + const char result_string[] = "Format test string 71.2000"; + + /* set format string */ + testdbPutFieldOk("test_printf_rec.FMT", DBF_STRING, format_string); + + /* set value on inp0 */ + testdbPutFieldOk("test_printf_inp0_rec.VAL", DBF_DOUBLE, 71.2); + + /* verify that string is formatted as expected */ + testdbGetFieldEqual("test_printf_rec.VAL", DBF_STRING, result_string); + + // number of tests = 3 +} + +static void test_h_flag(void){ + + const char format_string[] = "Format test string %hx"; + const char result_string[] = "Format test string baba"; + + /* set format string */ + testdbPutFieldOk("test_printf_rec.FMT", DBF_STRING, format_string); + + /* set value on inp0 */ + testdbPutFieldOk("test_printf_inp0_rec.VAL", DBF_LONG, 0xffbaba); + + /* verify that string is formatted as expected */ + testdbGetFieldEqual("test_printf_rec.VAL", DBF_STRING, result_string); + + // number of tests = 3 +} + +static void test_hh_flag(void){ + + const char format_string[] = "Format test string %hhx"; + const char result_string[] = "Format test string c1"; + + /* set format string */ + testdbPutFieldOk("test_printf_rec.FMT", DBF_STRING, format_string); + + /* set value on inp0 */ + testdbPutFieldOk("test_printf_inp0_rec.VAL", DBF_LONG, 0xffc0c1); + + /* verify that string is formatted as expected */ + #ifdef __rtems__ + testTodoBegin("Fails on UB-20 gcc-9 on RTEMS"); + #endif + testdbGetFieldEqual("test_printf_rec.VAL", DBF_STRING, result_string); + #ifdef __rtems__ + testTodoEnd(); + #endif + + // number of tests = 3 +} + +static void test_l_flag(void){ + + const char format_string[] = "Format test string %lx"; + const char result_string[] = "Format test string 70a1c0c1"; + + /* set format string */ + testdbPutFieldOk("test_printf_rec.FMT", DBF_STRING, format_string); + + /* set value on inp0 */ + testdbPutFieldOk("test_printf_inp0_rec.VAL", DBF_LONG, 0x70a1c0c1); + + /* verify that string is formatted as expected */ + testdbGetFieldEqual("test_printf_rec.VAL", DBF_STRING, result_string); + // number of tests = 3 +} + +static void test_ll_flag(void){ + + const char format_string[] = "%d %s %llx"; + const char result_string[] = "2 Reperbahn ba0110baa0a1c0c1"; + const epicsInt64 value = 0xba0110baa0a1c0c1ull; + + /* set format string */ + testdbPutFieldOk("test_printf_rec.FMT", DBF_STRING, format_string); + + /* set value on inp0 */ + testdbPutFieldOk("test_printf_inp0_rec.VAL", DBF_SHORT, 2); + + /* set value on inp1 */ + testdbPutFieldOk("test_printf_inp1_rec.VAL", DBF_STRING, "Reperbahn"); + + /* set value on inp2 */ + testdbPutFieldOk("test_printf_inp2_rec.VAL", DBR_INT64, value); + testdbGetFieldEqual("test_printf_inp2_rec.VAL", DBR_INT64, value); + + /* verify that string is formatted as expected */ + testdbGetFieldEqual("test_printf_rec.VAL", DBF_STRING, result_string); + + // number of tests = 6 +} + +static void test_sizv(void){ + + const char format_string[] = "%d %s %llx"; + const char result_string[] = "99 123456789012345678901234567890 6640baa0a1"; + const epicsInt64 value = 0x06640baa0a1c0c1ull; + + /* set format string */ + testdbPutFieldOk("test_printf_rec.FMT", DBF_STRING, format_string); + + /* set value on inp0 */ + testdbPutFieldOk("test_printf_inp0_rec.VAL", DBF_SHORT, 99); + + /* set value on inp1 */ + testdbPutFieldOk("test_printf_inp1_rec.VAL", DBF_STRING, "123456789012345678901234567890"); + + /* set value on inp2 */ + testdbPutFieldOk("test_printf_inp2_rec.VAL", DBR_INT64, value); + testdbGetFieldEqual("test_printf_inp2_rec.VAL", DBR_INT64, value); + + /* verify that string is formatted as expected */ + testdbGetArrFieldEqual("test_printf_rec.VAL$", DBF_CHAR, 45, 45, result_string); + + // number of tests = 6 +} + +static void test_all_inputs(void){ + + const char format_string[] = "%d %s %i %i %i %i %i %i %i %i"; + const char result_string[] = "0 One 2 3 4 5 6 7 8 9"; + + /* set format string */ + testdbPutFieldOk("test_printf_rec.FMT", DBF_STRING, format_string); + + /* set value on inp0 */ + testdbPutFieldOk("test_printf_inp0_rec.VAL", DBF_SHORT, 0); + + /* set value on inp1 */ + testdbPutFieldOk("test_printf_inp1_rec.VAL", DBF_STRING, "One"); + + /* set value on inp2 */ + testdbPutFieldOk("test_printf_inp2_rec.VAL", DBF_SHORT, 2); + + /* set value on inp3 */ + testdbPutFieldOk("test_printf_inp3_rec.VAL", DBF_SHORT, 3); + + /* set value on inp4 */ + testdbPutFieldOk("test_printf_inp4_rec.VAL", DBF_SHORT, 4); + + /* set value on inp5 */ + testdbPutFieldOk("test_printf_inp5_rec.VAL", DBF_SHORT, 5); + + /* set value on inp6 */ + testdbPutFieldOk("test_printf_inp6_rec.VAL", DBF_SHORT, 6); + + /* set value on inp7 */ + testdbPutFieldOk("test_printf_inp7_rec.VAL", DBF_SHORT, 7); + + /* set value on inp8 */ + testdbPutFieldOk("test_printf_inp8_rec.VAL", DBF_SHORT, 8); + + /* set value on inp9 */ + testdbPutFieldOk("test_printf_inp9_rec.VAL", DBF_SHORT, 9); + + /* verify that string is formatted as expected */ + testdbGetFieldEqual("test_printf_rec.VAL", DBF_STRING, result_string); + + // number of tests = 12 +} + +MAIN(printfTest) { +#ifdef _WIN32 +#if (defined(_MSC_VER) && _MSC_VER < 1900) || \ + (defined(_MINGW) && defined(_TWO_DIGIT_EXPONENT)) + _set_output_format(_TWO_DIGIT_EXPONENT); +#endif +#endif + + testPlan(3+3+3+3+3+3+3+3+4+3+3+3+3+3+3+3+3+3+3+3+3+3+3+3+6+6+12); + + testdbPrepare(); + testdbReadDatabase("recTestIoc.dbd", NULL, NULL); + recTestIoc_registerRecordDeviceDriver(pdbbase); + + testdbReadDatabase("printfTest.db", NULL, NULL); + + eltc(0); + testIocInitOk(); + eltc(1); + + test_double_percentile(); + test_c_format(); + test_d_format(); + test_i_format(); + test_o_format(); + test_u_format(); + test_x_format(); + test_X_format(); + test_e_format(); + test_E_format(); + test_f_format(); + test_F_format(); + test_g_format(); + test_G_format(); + test_s_format(); + test_plus_flag(); + test_minus_flag(); + test_space_flag(); + test_hash_flag(); + test_min_width_flag(); + test_prec_flag(); + test_h_flag(); + test_hh_flag(); + test_l_flag(); + test_ll_flag(); + test_sizv(); + test_all_inputs(); + + testIocShutdownOk(); + testdbCleanup(); + + return testDone(); +} diff --git a/modules/database/test/std/rec/printfTest.db b/modules/database/test/std/rec/printfTest.db new file mode 100644 index 000000000..1f4de2e6e --- /dev/null +++ b/modules/database/test/std/rec/printfTest.db @@ -0,0 +1,53 @@ +record(printf, "test_printf_rec") { + field(SIZV, 45) + field(INP0, "test_printf_inp0_rec") + field(INP1, "test_printf_inp1_rec") + field(INP2, "test_printf_inp2_rec") + field(INP3, "test_printf_inp3_rec") + field(INP4, "test_printf_inp4_rec") + field(INP5, "test_printf_inp5_rec") + field(INP6, "test_printf_inp6_rec") + field(INP7, "test_printf_inp7_rec") + field(INP8, "test_printf_inp8_rec") + field(INP9, "test_printf_inp9_rec") +} + +record(ai, "test_printf_inp0_rec") { + field(FLNK, "test_printf_rec") +} + +record(stringin, "test_printf_inp1_rec") { + field(FLNK, "test_printf_rec") +} + +record(int64in, "test_printf_inp2_rec") { + field(FLNK, "test_printf_rec") +} + +record(ai, "test_printf_inp3_rec") { + field(FLNK, "test_printf_rec") +} + +record(ai, "test_printf_inp4_rec") { + field(FLNK, "test_printf_rec") +} + +record(ai, "test_printf_inp5_rec") { + field(FLNK, "test_printf_rec") +} + +record(ai, "test_printf_inp6_rec") { + field(FLNK, "test_printf_rec") +} + +record(ai, "test_printf_inp7_rec") { + field(FLNK, "test_printf_rec") +} + +record(ai, "test_printf_inp8_rec") { + field(FLNK, "test_printf_rec") +} + +record(ai, "test_printf_inp9_rec") { + field(FLNK, "test_printf_rec") +}