From 4d67f3596aa69814c3024f0e41e7bc20fffd6908 Mon Sep 17 00:00:00 2001 From: Andrew Johnson Date: Thu, 30 Mar 2006 20:13:25 +0000 Subject: [PATCH] Converted some of the test routines to use the new epicsUnitTest facility. --- src/libCom/test/Makefile | 36 +++ src/libCom/test/buckTest.c | 2 +- src/libCom/test/epicsAlgorithmTest.cpp | 58 +++-- src/libCom/test/epicsExceptionTest.cpp | 26 +- src/libCom/test/epicsExceptionTestMain.cpp | 5 +- src/libCom/test/epicsMathTest.c | 72 ++++-- src/libCom/test/epicsStdioTest.c | 128 +++++----- src/libCom/test/epicsStringTest.c | 56 ++--- src/libCom/test/epicsTimeTest.cpp | 278 +++++++-------------- src/libCom/test/macEnvExpandTest.c | 92 ++++--- 10 files changed, 357 insertions(+), 396 deletions(-) diff --git a/src/libCom/test/Makefile b/src/libCom/test/Makefile index d73bb8065..a84fc0590 100644 --- a/src/libCom/test/Makefile +++ b/src/libCom/test/Makefile @@ -13,25 +13,39 @@ include $(TOP)/configure/CONFIG PROD_LIBS += Com +epicsUnitTestTest_SRCS += epicsUnitTestTest.c +PROD_HOST += epicsUnitTestTest +TESTS += epicsUnitTestTest + +epicsCalcTest_SRCS += epicsCalcTest.cpp +PROD_HOST += epicsCalcTest +OBJS_IOC_vxWorks += epicsCalcTest +TESTS += epicsCalcTest + epicsAlgorithmTest_SRCS += epicsAlgorithmTest.cpp PROD_HOST += epicsAlgorithmTest OBJS_IOC_vxWorks += epicsAlgorithmTest +TESTS += epicsAlgorithmTest epicsMathTestHost_SRCS += epicsMathTestMain.cpp epicsMathTest.c PROD_HOST += epicsMathTestHost OBJS_IOC_vxWorks += epicsMathTest +TESTS += epicsMathTestHost epicsStdioTestHost_SRCS += epicsStdioTestMain.cpp epicsStdioTest.c PROD_HOST += epicsStdioTestHost OBJS_IOC_vxWorks += epicsStdioTest +TESTS += epicsStdioTestHost epicsStringTestHost_SRCS += epicsStringTestMain.cpp epicsStringTest.c PROD_HOST += epicsStringTestHost OBJS_IOC_vxWorks += epicsStringTest +TESTS += epicsStringTestHost epicsTimeTestHost_SRCS += epicsTimeTestMain.cpp epicsTimeTest.cpp PROD_HOST += epicsTimeTestHost OBJS_IOC_vxWorks += epicsTimeTest +TESTS += epicsTimeTestHost epicsThreadTestHost_SRCS += epicsThreadTestMain.cpp epicsThreadTest.cpp PROD_HOST += epicsThreadTestHost @@ -81,6 +95,7 @@ OBJS_IOC_vxWorks += epicsMutexTest epicsExceptionTestHost_SRCS += epicsExceptionTestMain.cpp epicsExceptionTest.cpp PROD_HOST += epicsExceptionTestHost OBJS_IOC_vxWorks += epicsExceptionTest +TESTS += epicsExceptionTestHost epicsMessageQueueTestHost_SRCS += epicsMessageQueueTestMain.cpp epicsMessageQueueTest.cpp PROD_HOST += epicsMessageQueueTestHost @@ -89,6 +104,7 @@ OBJS_IOC_vxWorks += epicsMessageQueueTest macEnvExpandTestHost_SRCS += macEnvExpandTestMain.cpp macEnvExpandTest.c PROD_HOST += macEnvExpandTestHost OBJS_IOC_vxWorks += macEnvExpandTest +TESTS += macEnvExpandTestHost blockingSockTestHost_SRCS += blockingSockTestMain.cpp blockingSockTest.cpp PROD_HOST += blockingSockTestHost @@ -98,10 +114,30 @@ blockingSockTestHost_SYS_LIBS_WIN32 = ws2_32 advapi32 user32 blockingSockTestHost_SYS_LIBS_solaris = socket +#buckTest_SRCS += buckTest.c +#PROD_HOST += buckTest + #fdmgrTest_SRCS += fdmgrTest.c #PROD_HOST += fdmgrTest + OBJS_IOC_RTEMS += $(OBJS_IOC_vxWorks) +TEST_SCRIPTS += $(TESTS:%=%.t) + + include $(TOP)/configure/RULES +test: $(TEST_SCRIPTS) + @perl -e 'use Test::Harness; runtests @ARGV;' $(TEST_SCRIPTS) + +# If there's a perl test script (.plt) available, use it +%.t: ../%.plt + @$(RM) $@ + @$(CP) $< $@ + +# Early versions of Test::Harness expect test programs in perl only. +# Generate a 1-line test program to run the real test binary +%.t: %$(EXE) + @$(RM) $@ + @echo 'exec "$<";' >$@ diff --git a/src/libCom/test/buckTest.c b/src/libCom/test/buckTest.c index fcc81015e..3230e42cf 100644 --- a/src/libCom/test/buckTest.c +++ b/src/libCom/test/buckTest.c @@ -14,7 +14,7 @@ #include "epicsAssert.h" #include "bucketLib.h" -main() +int main() { unsigned id1; unsigned id2; diff --git a/src/libCom/test/epicsAlgorithmTest.cpp b/src/libCom/test/epicsAlgorithmTest.cpp index 2d3957dd8..a05de7fe5 100644 --- a/src/libCom/test/epicsAlgorithmTest.cpp +++ b/src/libCom/test/epicsAlgorithmTest.cpp @@ -10,50 +10,60 @@ // epicsAlgorithmTest.cpp // Authors: Jeff Hill & Andrew Johnson -#include -#include - +#include "epicsUnitTest.h" #include "epicsAlgorithm.h" #if defined(vxWorks) || defined(__rtems__) - #define MAIN epicsAlgorithm - extern "C" int MAIN(int /*argc*/, char* /*argv[]*/); + #define MAIN(prog) extern "C" int prog #else - #define MAIN main + #define MAIN(prog) int main #endif - -int MAIN(int /*argc*/, char* /*argv[]*/) +MAIN(epicsAlgorithm) (int /*argc*/, char* /*argv[]*/) { + testPlan(22); + + float f0 = 0.0; float f1 = 3.3f; float f2 = 3.4f; - float f3; + float Inf = 1.0 / f0; + float NaN = 0.0 / f0; - f3 = epicsMin(f1,f2); - assert(f3==f1); + testOk(epicsMin(f1, f2) == f1, "epicsMin(f1, f2)"); + testOk(epicsMin(f1, -Inf) == -Inf, "epicsMin(f1, -Inf)"); + testOk(isnan(epicsMin(f1, NaN)), "epicsMin(f1, NaN)"); + testOk(epicsMin(f1, Inf) == f1, "epicsMin(f1, Inf)"); - f3 = epicsMax(f1,f2); - assert(f3==f2); + testOk(epicsMin(f2, f1) == f1, "epicsMin(f2, f1)"); + testOk(epicsMin(-Inf, f1) == -Inf, "epicsMin(-Inf, f1)"); + testOk(isnan(epicsMin(NaN, f1)), "epicsMin(NaN, f1)"); + testOk(epicsMin(Inf, f1) == f1, "epicsMin(Inf, f1)"); + + testOk(epicsMax(f2, f1) == f2, "epicsMax(f2, f1)"); + testOk(epicsMax(-Inf, f1) == f1, "epicsMax(-Inf, f1)"); + testOk(isnan(epicsMax(NaN, f1)), "epicsMax(NaN, f1)"); + testOk(epicsMax(Inf, f1) == Inf, "epicsMax(Inf, f1)"); + + testOk(epicsMax(f1, f2) == f2, "epicsMax(f1, f2)"); + testOk(epicsMax(f1, -Inf) == f1, "epicsMax(f1, -Inf)"); + testOk(isnan(epicsMax(f1, NaN)), "epicsMax(f1, NaN)"); + testOk(epicsMax(f1, Inf) == Inf, "epicsMax(f1, Inf)"); epicsSwap(f1,f2); - assert(f1==3.4f); - assert(f2==3.3f); + testOk(f1==3.4f && f2==3.3f, "epicsSwap(f1, f2)"); int i1 = 3; int i2 = 4; - int i3; - i3 = epicsMin(i1,i2); - assert(i3==i1); + testOk(epicsMin(i1,i2)==i1, "epicsMin(i1,i2)"); + testOk(epicsMin(i2,i1)==i1, "epicsMin(i2,i1)"); - i3 = epicsMax(i1,i2); - assert(i3==i2); + testOk(epicsMax(i1,i2)==i2, "epicsMax(i1,i2)"); + testOk(epicsMax(i2,i1)==i2, "epicsMax(i2,i1)"); epicsSwap(i1,i2); - assert(i1==4); - assert(i2==3); + testOk(i1==4 && i2==3, "epicsSwap(i1,i2)"); - puts("epicsMin, epicsMax and epicsSwap tested OK."); - return 0; + return testDone(); } diff --git a/src/libCom/test/epicsExceptionTest.cpp b/src/libCom/test/epicsExceptionTest.cpp index f87e792f8..c97350e45 100644 --- a/src/libCom/test/epicsExceptionTest.cpp +++ b/src/libCom/test/epicsExceptionTest.cpp @@ -9,7 +9,7 @@ \*************************************************************************/ // -// Verify that the local c++ exception mechanism maches the ANSI/ISO standard. +// Verify that the local c++ exception mechanism matches the ANSI/ISO standard. // Author: Jeff Hill // @@ -21,9 +21,9 @@ #include #endif -#include #include +#include "epicsUnitTest.h" #include "epicsThread.h" using namespace std; @@ -60,24 +60,23 @@ private: static void epicsExceptionTestPrivate () { - int excep = false; try { new char [unsuccessfulNewSize]; - assert ( 0 ); + testFail("new: didn't throw at all"); } catch ( const bad_alloc & ) { - excep = true; + testPass("new"); } catch ( ... ) { - assert ( 0 ); + testFail("new: threw wrong type"); } try { char * p = new ( nothrow ) char [unsuccessfulNewSize]; - assert ( p == 0); + testOk(p == 0, "new (nothrow)"); } catch( ... ) { - assert ( 0 ); + testFail("new (nothrow): threw"); } } @@ -101,13 +100,12 @@ void exThread::waitForCompletion () } } -extern "C" void epicsExceptionTest () +extern "C" int epicsExceptionTest () { - exThread athread; - + testPlan(4); epicsExceptionTestPrivate (); - + + exThread athread; athread.waitForCompletion (); - - printf ( "Test Complete.\n" ); + return testDone(); } diff --git a/src/libCom/test/epicsExceptionTestMain.cpp b/src/libCom/test/epicsExceptionTestMain.cpp index 3d2e15a0e..8eee729d4 100644 --- a/src/libCom/test/epicsExceptionTestMain.cpp +++ b/src/libCom/test/epicsExceptionTestMain.cpp @@ -8,10 +8,9 @@ * in file LICENSE that is included with this distribution. \*************************************************************************/ -extern "C" void epicsExceptionTest (); +extern "C" int epicsExceptionTest (); int main () { - epicsExceptionTest (); - return 0; + return epicsExceptionTest (); } diff --git a/src/libCom/test/epicsMathTest.c b/src/libCom/test/epicsMathTest.c index 60ad94740..4872ec0b2 100644 --- a/src/libCom/test/epicsMathTest.c +++ b/src/libCom/test/epicsMathTest.c @@ -12,34 +12,56 @@ * Author Marty Kraimer */ -#include -#include -#include -#include -#include - +#include "epicsUnitTest.h" #include "epicsMath.h" -static char *truth[2] = {"false","true"}; - int epicsMathTest () { double a,b,c; - - a=0.0; b=0.0; c=a/b; - printf("a %e b %e c %e isnan %s isinf %s\n", - a,b,c,truth[isnan(c) ? 1 : 0],truth[isinf(c) ? 1 : 0]); - a=1e300; b=1e-300; c=a/b; - printf("a %e b %e c %e isnan %s isinf %s\n", - a,b,c,truth[isnan(c) ? 1 : 0],truth[isinf(c) ? 1 : 0]); - a=-1e300; b=1e-300; c=a/b; - printf("a %e b %e c %e isnan %s isinf %s\n", - a,b,c,truth[isnan(c) ? 1 : 0],truth[isinf(c) ? 1 : 0]); - a=0.0; b=1.0; c=a/b; - printf("a %e b %e c %e isnan %s isinf %s\n", - a,b,c,truth[isnan(c) ? 1 : 0],truth[isinf(c) ? 1 : 0]); - a=1e300; b=1e300; c=a/b; - printf("a %e b %e c %e isnan %s isinf %s\n", - a,b,c,truth[isnan(c) ? 1 : 0],truth[isinf(c) ? 1 : 0]); - return(0); + + testPlan(18); + + a = 0.0; + b = 1.0; + c = a / b; + testOk(!isnan(c), "!isnan(0.0 / 1.0)"); + testOk(!isinf(c), "!isinf(0.0 / 1.0)"); + testOk(c == 0.0, "0.0 / 1.0 == 0.0"); + + a = 1.0; + b = 0.0; + c = a / b; + testOk(!isnan(c), "!isnan(1.0 / 0.0)"); + testOk(isinf(c), "isinf(1.0 / 0.0)"); + testOk(c == c, "1.0 / 0.0 == 1.0 / 0.0"); + + a = 0.0; + b = 0.0; + c = a / b; + testOk(isnan(c), "isnan(0.0 / 0.0)"); + testOk(!isinf(c), "!isinf(0.0 / 0.0)"); + testOk(c != c, "0.0 / 0.0 != 0.0 / 0.0"); + + a = 1e300; + b = 1e-300; + c = a / b; + testOk(!isnan(c), "!isnan(1e300 / 1e-300)"); + testOk(isinf(c), "isinf(1e300 / 1e-300)"); + testOk(c > 0.0, "1e300 / 1e-300 > 0.0"); + + a = -1e300; + b = 1e-300; + c = a / b; + testOk(!isnan(c), "!isnan(-1e300 / 1e-300)"); + testOk(isinf(c), "isinf(-1e300 / 1e-300)"); + testOk(c < 0.0, "-1e300 / 1e-300 < 0.0"); + + a = 1e300; + b = 1e300; + c = a / b; + testOk(!isnan(c), "!isnan(1e300 / 1e300)"); + testOk(!isinf(c), "!isinf(1e300 / 1e300)"); + testOk(c == 1.0, "1e300 / 1e300 == 1.0"); + + return testDone(); } diff --git a/src/libCom/test/epicsStdioTest.c b/src/libCom/test/epicsStdioTest.c index 1bf0d434a..250c801fd 100644 --- a/src/libCom/test/epicsStdioTest.c +++ b/src/libCom/test/epicsStdioTest.c @@ -22,83 +22,77 @@ #include #include "epicsStdio.h" +#include "epicsStdioRedirect.h" +#include "epicsUnitTest.h" -static int xsnprintf(char *str, size_t size, const char *format, ...) -{ - int nchar; - va_list pvar; - - va_start(pvar,format); - nchar = epicsVsnprintf(str,size,format,pvar); - va_end (pvar); - return(nchar); +static void testEpicsSnprintf() { + const int ivalue = 1234; + const float fvalue = 1.23e4; + const char *svalue = "OneTwoThreeFour"; + const char *format = "int %d float %8.2e string %s"; + const char *result = "int 1234 float 1.23e+04 string OneTwoThreeFour"; + char buffer[80]; + int size, rtn; + int rlen = strlen(result)+1; + + strcpy(buffer, "AAAA"); + + for (size = 0; size < strlen(result) + 5; ++size) { + rtn = epicsSnprintf(buffer, size, format, ivalue, fvalue, svalue); + testOk1(rtn == rlen-1); + if (size) { + testOk(strncmp(buffer, result, size-1) == 0, buffer); + testOk(strlen(buffer) == (size < rlen ? size : rlen) -1, "length"); + } else { + testOk(strcmp(buffer, "AAAA") == 0, "Buffer unmodified, size=0"); + } + } } - -int epicsStdioTest (const char *report) +void testStdoutRedir (const char *report) { - char buffer[20]; - int rtn; - int value = 10; - int size = 10; + FILE *realStdout = stdout; FILE *stream = 0; - - memset(buffer,'*',sizeof(buffer)-1); - buffer[sizeof(buffer)-1] = 0; - printf("at start buffer |%s|\n",buffer); - rtn = xsnprintf(buffer,size,"value is %d",value); - printf("size %d rtn %d value %d buffer |%s|\n",size,rtn,value,buffer); - memset(buffer,'*',sizeof(buffer)-1); - rtn = xsnprintf(buffer,size,"value: %d",value); - printf("size %d rtn %d value %d buffer |%s|\n",size,rtn,value,buffer); - memset(buffer,'*',sizeof(buffer)-1); - rtn = xsnprintf(buffer,size,"%d",value); - printf("size %d rtn %d value %d buffer |%s|\n",size,rtn,value,buffer); - - memset(buffer,'*',sizeof(buffer)-1); - buffer[sizeof(buffer)-1] = 0; - printf("at start buffer |%s|\n",buffer); - rtn = epicsSnprintf(buffer,size,"value is %d",value); - printf("size %d rtn %d value %d buffer |%s|\n",size,rtn,value,buffer); - memset(buffer,'*',sizeof(buffer)-1); - rtn = epicsSnprintf(buffer,size,"value: %d",value); - printf("size %d rtn %d value %d buffer |%s|\n",size,rtn,value,buffer); - memset(buffer,'*',sizeof(buffer)-1); - rtn = epicsSnprintf(buffer,size,"%d",value); - printf("size %d rtn %d value %d buffer |%s|\n",size,rtn,value,buffer); - printf("\nTest epicsSetThreadStdout/epicsGetStdout stdout %p epicsGetStdout %p\n", - stdout,epicsGetStdout()); + + testOk1(epicsGetStdout() == stdout); if(report && strlen(report)>0) { - int fd; + int fd; - errno = 0; - fd = open(report, O_CREAT | O_WRONLY | O_TRUNC, 0644 ); - if(fd<0) { - fprintf(stderr,"%s could not be created %s\n", - report,strerror(errno)); - } else { - stream = fdopen(fd,"w"); - if(!stream) { - fprintf(stderr,"%s could not be opened for output %s\n", - report,strerror(errno)); - } else { - epicsSetThreadStdout(stream); - printf("After epicsSetThreadStdout stream %p epicsGetStdout %p\n", - stream,epicsGetStdout()); - } - } + errno = 0; + fd = open(report, O_CREAT | O_WRONLY | O_TRUNC, 0644 ); + if(fd<0) { + fprintf(stderr,"%s could not be created %s\n", + report,strerror(errno)); + } else { + stream = fdopen(fd,"w"); + if(!stream) { + fprintf(stderr,"%s could not be opened for output %s\n", + report,strerror(errno)); + } else { + epicsSetThreadStdout(stream); + testOk1(stdout == stream); + } + } } - printf("This is first line of sample report"); - printf("\nThis is second and last line of sample report\n"); + printf("# This is first line of sample report\n"); + printf("# This is second and last line of sample report\n"); errno = 0; if(stream) { - epicsSetThreadStdout(0); - if(fclose(stream)) { - fprintf(stderr,"fclose failed %s\n",strerror(errno)); - } + epicsSetThreadStdout(0); + if(fclose(stream)) { + fprintf(stderr,"fclose failed %s\n",strerror(errno)); + } } else { - fflush(stdout); + fflush(stdout); } - printf("at end stdout %p epicsGetStdout %p\n",stdout,epicsGetStdout()); - return(0); + testOk1(epicsGetStdout() == realStdout); + testOk1(stdout == realStdout); +} + +int epicsStdioTest (const char *report) +{ + testPlan(0); + testEpicsSnprintf(); + testStdoutRedir("report"); + return testDone(); } diff --git a/src/libCom/test/epicsStringTest.c b/src/libCom/test/epicsStringTest.c index 0af98190c..6d900a0af 100644 --- a/src/libCom/test/epicsStringTest.c +++ b/src/libCom/test/epicsStringTest.c @@ -7,46 +7,42 @@ * and higher are distributed subject to a Software License Agreement found * in file LICENSE that is included with this distribution. \*************************************************************************/ -/* epicsStdioTest.c +/* $Id$ * * Author Marty Kraimer */ -#include -#include -#include -#include #include -#include +#include "epicsUnitTest.h" #include "epicsString.h" int epicsStringTest() { - if(epicsStrnCaseCmp("","",0)!=0) printf("case 1 failed\n"); - if(epicsStrnCaseCmp("","",1)!=0) printf("case 2 failed\n"); - if(epicsStrnCaseCmp(" ","",1)!=-1) printf("case 3 failed\n"); - if(epicsStrnCaseCmp(""," ",1)!=1) printf("case 4 failed\n"); - if(epicsStrnCaseCmp("a","A",1)!=0) printf("case 5 failed\n"); - if(epicsStrnCaseCmp("a","A",2)!=0) printf("case 6 failed\n"); - if(epicsStrnCaseCmp("abcd","ABCD",2)!=0) printf("case 7 failed\n"); - if(epicsStrnCaseCmp("abcd","ABCD",4)!=0) printf("case 8 failed\n"); - if(epicsStrnCaseCmp("abcd","ABCD",1000)!=0) printf("case 9 failed\n"); - if(epicsStrnCaseCmp("abcd","ABCDE",2)!=0) printf("case 10 failed\n"); - if(epicsStrnCaseCmp("abcd","ABCDE",4)!=0) printf("case 11 failed\n"); - if(epicsStrnCaseCmp("abcd","ABCDE",1000)!=1) printf("case 12 failed\n"); - if(epicsStrnCaseCmp("abcde","ABCD",2)!=0) printf("case 13 failed\n"); - if(epicsStrnCaseCmp("abcde","ABCD",4)!=0) printf("case 14 failed\n"); - if(epicsStrnCaseCmp("abcde","ABCD",1000)!=-1) printf("case 15 failed\n"); + testPlan(21); + + testOk1(epicsStrnCaseCmp("","",0)==0); + testOk1(epicsStrnCaseCmp("","",1)==0); + testOk1(epicsStrnCaseCmp(" ","",1)<0); + testOk1(epicsStrnCaseCmp(""," ",1)>0); + testOk1(epicsStrnCaseCmp("a","A",1)==0); + testOk1(epicsStrnCaseCmp("a","A",2)==0); + testOk1(epicsStrnCaseCmp("abcd","ABCD",2)==0); + testOk1(epicsStrnCaseCmp("abcd","ABCD",4)==0); + testOk1(epicsStrnCaseCmp("abcd","ABCD",1000)==0); + testOk1(epicsStrnCaseCmp("abcd","ABCDE",2)==0); + testOk1(epicsStrnCaseCmp("abcd","ABCDE",4)==0); + testOk1(epicsStrnCaseCmp("abcd","ABCDE",1000)>0); + testOk1(epicsStrnCaseCmp("abcde","ABCD",2)==0); + testOk1(epicsStrnCaseCmp("abcde","ABCD",4)==0); + testOk1(epicsStrnCaseCmp("abcde","ABCD",1000)<0); - if(epicsStrCaseCmp("","")!=0) printf("case 16 failed\n"); - if(epicsStrCaseCmp("a","A")!=0) printf("case 17 failed\n"); - if(epicsStrCaseCmp("abcd","ABCD")!=0) printf("case 18 failed\n"); - if(epicsStrCaseCmp("abcd","ABCDE")==0) printf("case 19 failed\n"); - if(epicsStrCaseCmp("abcde","ABCD")==0) printf("case 20 failed\n"); - if(epicsStrCaseCmp("abcde","ABCDF")==0) printf("case 21 failed\n"); + testOk1(epicsStrCaseCmp("","")==0); + testOk1(epicsStrCaseCmp("a","A")==0); + testOk1(epicsStrCaseCmp("abcd","ABCD")==0); + testOk1(epicsStrCaseCmp("abcd","ABCDE")!=0); + testOk1(epicsStrCaseCmp("abcde","ABCD")!=0); + testOk1(epicsStrCaseCmp("abcde","ABCDF")!=0); - printf("String comparison tests completed.\n"); - - return(0); + return testDone(); } diff --git a/src/libCom/test/epicsTimeTest.cpp b/src/libCom/test/epicsTimeTest.cpp index c66718735..f0587f54e 100644 --- a/src/libCom/test/epicsTimeTest.cpp +++ b/src/libCom/test/epicsTimeTest.cpp @@ -14,40 +14,13 @@ #include #include #include -#include +#include #include "epicsTime.h" #include "epicsThread.h" #include "errlog.h" +#include "epicsUnitTest.h" -extern "C" { -int epicsTimeTest (void); -} - -void invalidFormatTest () -{ - epicsTime ts ( epicsTime::getCurrent () ); - char bigBuf [512]; - char buf [32]; - memset ( bigBuf, '\a', sizeof ( bigBuf ) ); - bigBuf [ sizeof ( bigBuf ) - 1 ] = '\0'; - ts.strftime ( buf, sizeof ( buf ), bigBuf ); - printf ("A huge strftime format produces this result \"%s\"\n", buf ); -} - -void badNanosecTest () -{ - static const char * pFormat = "%a %b %d %Y %H:%M:%S.%4f"; - try { - const epicsTimeStamp ets = { 1, 1000000000 }; - epicsTime ts ( ets ); - char buf [32]; - ts.strftime ( buf, sizeof ( buf ), pFormat ); - printf ("A nano-sec overflow produces this result \"%s\"\n", buf ); - } - catch ( ... ) { - } -} struct l_fp { /* NTP time stamp */ epicsUInt32 l_ui; /* sec past NTP epoch */ @@ -60,44 +33,17 @@ static const unsigned mSecPerSec = 1000u; static const unsigned uSecPerSec = 1000u * mSecPerSec; static const unsigned nSecPerSec = 1000u * uSecPerSec; -void testStringConversion() -{ - char buf[64]; - epicsTime uninit; - - const char * pFormat = "%a %b %d %Y %H:%M:%S.%f"; - uninit.strftime ( buf, sizeof ( buf ), pFormat ); - printf ("Uninitialized using \"%s\" %s\n", pFormat, buf ); - - epicsTime current = epicsTime::getCurrent(); - - pFormat = "%a %b %d %Y %H:%M:%S.%f"; - current.strftime ( buf, sizeof ( buf ), pFormat ); - printf ("using \"%s\" %s\n", pFormat, buf ); - - pFormat = "%a %b %d %Y %H:%M:%S.%4f"; - current.strftime ( buf, sizeof ( buf ), pFormat ); - printf ("using \"%s\" %s\n", pFormat, buf ); - - pFormat = "%a %b %d %Y %H:%M:%S.%05f"; - current.strftime ( buf, sizeof ( buf ), pFormat ); - printf ("using \"%s\" %s\n", pFormat, buf ); - -} +extern "C" int epicsTimeTest (void) { - unsigned errors, sum_errors=0, sum_errloops=0; - const epicsTime begin = epicsTime::getCurrent(); const unsigned wasteTime = 100000u; - const int nTimes = 100; - epicsTimeStamp stamp; - struct timespec ts; - struct tm tmAnsi; - local_tm_nano_sec ansiDate; - gm_tm_nano_sec ansiDateGMT; - unsigned long nanoSec; + const int nTimes = 10; + const double precisionEPICS = 1.0 / nSecPerSec; + testPlan(7 + nTimes * 18); + + const epicsTime begin = epicsTime::getCurrent(); { epicsTime tsi = epicsTime::getCurrent (); l_fp ntp = tsi; @@ -105,14 +51,63 @@ int epicsTimeTest (void) const double diff = fabs ( tsf - tsi ); // the difference in the precision of the two time formats static const double precisionNTP = 1.0 / ( 1.0 + 0xffffffff ); - static const double precisionEPICS = 1.0 / nSecPerSec; - assert ( diff <= precisionEPICS + precisionNTP ); + testOk1(diff <= precisionEPICS + precisionNTP); } - - invalidFormatTest (); - badNanosecTest (); - printf ("epicsTime Test (%3d loops)\n========================\n\n", nTimes); + { + static const char * pFormat = "%a %b %d %Y %H:%M:%S.%4f"; + try { + const epicsTimeStamp badTS = {1, 1000000000}; + epicsTime ts(badTS); + char buf [32]; + ts.strftime(buf, sizeof(buf), pFormat); + testFail("nanosecond overflow throws"); + testDiag("nanosecond overflow result is \"%s\"", buf); + } + catch ( ... ) { + testPass("nanosecond overflow throws"); + } + } + + { + char buf[64]; + epicsTime et; + + const char * pFormat = "%Y-%m-%d %H:%M:%S.%f"; + et.strftime(buf, sizeof(buf), pFormat); + testOk(strcmp(buf, "") == 0, "undefined strftime") || + testDiag("undefined.strftime(\"%s\") = \"%s\"", pFormat, buf); + + // This is Noon GMT, when all timezones have the same date + const epicsTimeStamp tTS = {12*60*60, 98765432}; + et = tTS; + pFormat = "%Y-%m-%d %S.%09f"; // %H and %M change with timezone + et.strftime(buf, sizeof(buf), pFormat); + testOk(strcmp(buf, "1990-01-01 00.098765432") == 0, pFormat) || + testDiag("t.strftime(\"%s\") = \"%s\"", pFormat, buf); + + pFormat = "%S.%04f"; + et.strftime(buf, sizeof(buf), pFormat); + testOk(strcmp(buf, "00.0988") == 0, pFormat) || + testDiag("t.strftime(\"%s\") = \"%s\"", pFormat, buf); + + pFormat = "%S.%05f"; + et.strftime(buf, sizeof(buf), pFormat); + testOk(strcmp(buf, "00.09877") == 0, pFormat) || + testDiag("t.strftime(\"%s\") = \"%s\"", pFormat, buf); + } + + { + char bigBuf [512]; + char buf [32]; + memset(bigBuf, '\a', sizeof(bigBuf )); + bigBuf[ sizeof(bigBuf) - 1] = '\0'; + begin.strftime(buf, sizeof(buf), bigBuf); + testOk(strcmp(buf, "") == 0, "strftime(huge)") || + testDiag("strftime(huge) = \"%s\"", buf); + } + + testDiag("Running %d loops", nTimes); for (int iTimes=0; iTimes < nTimes; ++iTimes) { for (unsigned i=0; i= end); - if (!(copy==end)) { - printf ("#%3d: Failed copy==end by %12.9f\n", - iTimes, fabs(copy-end)); - errors += 1; - } - if (!(copy<=end)) { - printf ("#%3d: Failed copy<=end by %12.9f\n", - iTimes, (copy-end)); - errors += 1; - } - if (!(copy>=end)) { - printf ("#%3d: Failed copy>=end by %12.9f\n", - iTimes, (end-copy)); - errors += 1; - } - if (!(end>begin)) { - printf ("#%3d: Failed end>begin by %12.9f\n", - iTimes, (begin-end)); - errors += 1; - } - if (!(end>=begin)) { - printf ("#%3d: Failed end>=begin by %12.9f\n", - iTimes, (begin-end)); - errors += 1; - } - if (!(begin begin); + testOk1(end >= begin); + testOk1(begin != end); + testOk1(begin < end); + testOk1(begin <= end); + + testOk1(end - end == 0); + testOk(fabs((end - begin) - diff) < precisionEPICS * 0.01, + "end - begin ~= diff"); + + testOk1(begin + 0 == begin); + testOk1(begin + diff == end); + testOk1(end - 0 == end); + testOk1(end - diff == begin); epicsTime end2 = begin; - end2 += diff; - if (!(end2==end)) { - printf ("#%3d: Failed (begin+=diff)==end by %12.9f\n", - iTimes, fabs(begin-end)); - errors += 1; - } + end2 += diff; + testOk(end2 == end, "(begin += diff) == end"); + end2 = end; end2 -= diff; - if (!(end2+diff==end)) { - printf ("#%3d: Failed begin+diff==end by %12.9f\n", - iTimes, fabs(begin+diff-end)); - errors += 1; - } + testOk(end2 == begin, "(end -= diff) == begin"); - // - // test struct tm conversions - // - ansiDate = begin; - epicsTime beginANSI = ansiDate; - if (!(beginANSI+diff==end)) { - printf ("#%3d: Failed begin+diff==end " - "after tm conversions by %12.9f\n", - iTimes, fabs(begin+diff-end)); - errors += 1; - } + // test struct tm round-trip conversion + local_tm_nano_sec ansiDate = begin; + epicsTime beginANSI = ansiDate; + testOk1(beginANSI + diff == end); - // - // test struct timespec conversion - // - ts = begin; + // test struct timespec round-trip conversion + struct timespec ts = begin; epicsTime beginTS = ts; - if (!(beginTS+diff==end)) { - printf ("#%3d: Failed begin+diff==end " - "after timespec conversions by %12.9f\n", - iTimes, fabs(begin+diff-end)); - errors += 1; - } - - if (errors) { - printf ("#%3d: begin ", iTimes); begin.show(0); - printf ("#%3d: end ", iTimes); end.show(0); - printf ("#%3d: diff %12.9f\n\n", iTimes, diff); - sum_errors += errors; - sum_errloops += 1; - } + testOk1(beginTS + diff == end); } - - printf ("epicsTime test complete. Summary: %d errors found " - "in %d out of %d loops.\n", - sum_errors, sum_errloops, nTimes); - return (sum_errors?1:0); + return testDone(); } diff --git a/src/libCom/test/macEnvExpandTest.c b/src/libCom/test/macEnvExpandTest.c index b77d50a2d..46c84752a 100644 --- a/src/libCom/test/macEnvExpandTest.c +++ b/src/libCom/test/macEnvExpandTest.c @@ -19,93 +19,87 @@ #include "macLib.h" #include "envDefs.h" #include "errlog.h" +#include "epicsUnitTest.h" -int -check(const char *str, const char *expect) +void check(const char *str, const char *expect) { char *got = macEnvExpand(str); - int bad = 0; - static int count = 0; + int pass = -1; if (expect && !got) { - printf("\t#Got NULL, expected \"%s\".\n", expect); - bad = 1; + testDiag("Got NULL, expected \"%s\".\n", expect); + pass = 0; } else if (!expect && got) { - printf("\t#Got \"%s\", expected NULL.\n", got); - bad = 1; + testDiag("Got \"%s\", expected NULL.\n", got); + pass = 0; } else if (expect && got && strcmp(got, expect)) { - printf("\t#Got \"%s\", expected \"%s\".\n", got, expect); - bad = 1; + testDiag("Got \"%s\", expected \"%s\".\n", got, expect); + pass = 0; } - /* This output format follows the perl standard: */ - printf("%sok %d - \"%s\".\n", (bad ? "not " : ""), ++count, str); - return bad; + testOk(pass, str); } int macEnvExpandTest(void) { - int bad = 0; int warn = 0; + testPlan(30); - /* Announce the number of calls to check() present in the code below: */ - printf("1..%d\n", 30); + check("FOO", "FOO"); - bad |= check ("FOO", "FOO"); - - bad |= check ("${FOO}", NULL); warn++; - bad |= check ("${FOO=}", ""); - bad |= check ("x${FOO=}y", "xy"); - bad |= check ("${FOO=BAR}", "BAR"); - bad |= check ("x${FOO=BAR}y", "xBARy"); + check("${FOO}", NULL); warn++; + check("${FOO=}", ""); + check("x${FOO=}y", "xy"); + check("${FOO=BAR}", "BAR"); + check("x${FOO=BAR}y", "xBARy"); epicsEnvSet("FOO","BLETCH"); - bad |= check ("${FOO}", "BLETCH"); - bad |= check ("x${FOO}y", "xBLETCHy"); - bad |= check ("x${FOO}y${FOO}z", "xBLETCHyBLETCHz"); - bad |= check ("${FOO=BAR}", "BLETCH"); - bad |= check ("x${FOO=BAR}y", "xBLETCHy"); - bad |= check ("${FOO=${BAZ}}", "BLETCH"); - bad |= check ("x${FOO=${BAZ}}y", "xBLETCHy"); - bad |= check ("${BAR=${FOO}}", "BLETCH"); - bad |= check ("x${BAR=${FOO}}y", "xBLETCHy"); - bad |= check ("w${BAR=x${FOO}y}z", "wxBLETCHyz"); + check("${FOO}", "BLETCH"); + check("x${FOO}y", "xBLETCHy"); + check("x${FOO}y${FOO}z", "xBLETCHyBLETCHz"); + check("${FOO=BAR}", "BLETCH"); + check("x${FOO=BAR}y", "xBLETCHy"); + check("${FOO=${BAZ}}", "BLETCH"); + check("x${FOO=${BAZ}}y", "xBLETCHy"); + check("${BAR=${FOO}}", "BLETCH"); + check("x${BAR=${FOO}}y", "xBLETCHy"); + check("w${BAR=x${FOO}y}z", "wxBLETCHyz"); epicsEnvSet("BAR","GLEEP"); - bad |= check ("${FOO}/${BAR}", "BLETCH/GLEEP"); - bad |= check ("x${FOO}/${BAR}y", "xBLETCH/GLEEPy"); - bad |= check ("${BAR=${FOO}}", "GLEEP"); + check("${FOO}/${BAR}", "BLETCH/GLEEP"); + check("x${FOO}/${BAR}y", "xBLETCH/GLEEPy"); + check("${BAR=${FOO}}", "GLEEP"); epicsEnvSet("BLETCH","BAR"); - bad |= check ("${${FOO}}", "BAR"); - bad |= check ("x${${FOO}}y", "xBARy"); - bad |= check ("${${FOO}=GRIBBLE}", "BAR"); - bad |= check ("x${${FOO}=GRIBBLE}y", "xBARy"); + check("${${FOO}}", "BAR"); + check("x${${FOO}}y", "xBARy"); + check("${${FOO}=GRIBBLE}", "BAR"); + check("x${${FOO}=GRIBBLE}y", "xBARy"); epicsEnvSet("BLETCH","${BAR}"); - bad |= check ("${${FOO}}", "GLEEP"); + check("${${FOO}}", "GLEEP"); epicsEnvSet("FOO","${BAR}"); - bad |= check ("${FOO}","GLEEP"); + check("${FOO}","GLEEP"); epicsEnvSet("BAR","${BAZ}"); - bad |= check ("${FOO}", NULL); warn++; + check("${FOO}", NULL); warn++; epicsEnvSet("BAR","${BAZ=GRIBBLE}"); - bad |= check ("${FOO}", "GRIBBLE"); + check("${FOO}", "GRIBBLE"); epicsEnvSet("BAR","${STR1}"); epicsEnvSet("STR1","VAL1"); epicsEnvSet("STR2","VAL2"); - bad |= check ("${FOO}", "VAL1"); + check("${FOO}", "VAL1"); epicsEnvSet("BAR","${STR2}"); - bad |= check ("${FOO}", "VAL2"); + check("${FOO}", "VAL2"); epicsEnvSet("BAR","${FOO}"); - bad |= check ("${FOO}", NULL); warn++; + check("${FOO}", NULL); warn++; - printf("# Expect %d warning messages here:\n", warn); + testDiag("Expect %d warning messages here:\n", warn); errlogFlush(); - return bad; + return testDone(); }