diff --git a/src/libCom/test/Makefile b/src/libCom/test/Makefile index 24e1c40d8..84279a890 100644 --- a/src/libCom/test/Makefile +++ b/src/libCom/test/Makefile @@ -1,152 +1,153 @@ #************************************************************************* -# Copyright (c) 2002 The University of Chicago, as Operator of Argonne +# Copyright (c) 2006 The University of Chicago, as Operator of Argonne # National Laboratory. # Copyright (c) 2002 The Regents of the University of California, as # Operator of Los Alamos National Laboratory. -# EPICS BASE Versions 3.13.7 -# and higher are distributed subject to a Software License Agreement found -# in file LICENSE that is included with this distribution. +# EPICS BASE is distributed subject to a Software License Agreement found +# in file LICENSE that is included with this distribution. #************************************************************************* TOP=../../.. include $(TOP)/configure/CONFIG +INC += testMain.h + PROD_LIBS += Com +TESTPROD_HOST += epicsUnitTestTest epicsUnitTestTest_SRCS += epicsUnitTestTest.c -PROD_HOST += epicsUnitTestTest +# Not much point running this on vxWorks or RTEMS... TESTS += epicsUnitTestTest +TESTPROD_HOST += epicsCalcTest epicsCalcTest_SRCS += epicsCalcTest.cpp -PROD_HOST += epicsCalcTest -OBJS_IOC_vxWorks += epicsCalcTest +testHarness_SRCS += epicsCalcTest.cpp TESTS += epicsCalcTest +TESTPROD_HOST += epicsAlgorithmTest epicsAlgorithmTest_SRCS += epicsAlgorithmTest.cpp -PROD_HOST += epicsAlgorithmTest -OBJS_IOC_vxWorks += epicsAlgorithmTest +testHarness_SRCS += epicsAlgorithmTest.cpp TESTS += epicsAlgorithmTest -epicsMathTestHost_SRCS += epicsMathTestMain.cpp epicsMathTest.c -PROD_HOST += epicsMathTestHost -OBJS_IOC_vxWorks += epicsMathTest -TESTS += epicsMathTestHost +TESTPROD_HOST += epicsMathTest +epicsMathTest_SRCS += epicsMathTest.c +testHarness_SRCS += epicsMathTest.c +TESTS += epicsMathTest -epicsStdioTestHost_SRCS += epicsStdioTestMain.cpp epicsStdioTest.c -PROD_HOST += epicsStdioTestHost -OBJS_IOC_vxWorks += epicsStdioTest -TESTS += epicsStdioTestHost +TESTPROD_HOST += epicsStdioTest +epicsStdioTest_SRCS += epicsStdioTest.c +testHarness_SRCS += epicsStdioTest.c +TESTS += epicsStdioTest -epicsStringTestHost_SRCS += epicsStringTestMain.cpp epicsStringTest.c -PROD_HOST += epicsStringTestHost -OBJS_IOC_vxWorks += epicsStringTest -TESTS += epicsStringTestHost +TESTPROD_HOST += epicsStringTest +epicsStringTest_SRCS += epicsStringTest.c +testHarness_SRCS += epicsStringTest.c +TESTS += epicsStringTest -epicsTimeTestHost_SRCS += epicsTimeTestMain.cpp epicsTimeTest.cpp -PROD_HOST += epicsTimeTestHost -OBJS_IOC_vxWorks += epicsTimeTest -TESTS += epicsTimeTestHost +TESTPROD_HOST += epicsTimeTest +epicsTimeTest_SRCS += epicsTimeTest.cpp +testHarness_SRCS += epicsTimeTest.cpp +TESTS += epicsTimeTest -epicsThreadTestHost_SRCS += epicsThreadTestMain.cpp epicsThreadTest.cpp -PROD_HOST += epicsThreadTestHost -OBJS_IOC_vxWorks += epicsThreadTest +TESTPROD_HOST += epicsThreadTest +epicsThreadTest_SRCS += epicsThreadTest.cpp +testHarness_SRCS += epicsThreadTest.cpp +TESTS += epicsThreadTest -epicsThreadPriorityTestHost_SRCS += epicsThreadPriorityTestMain.cpp epicsThreadPriorityTest.cpp -PROD_HOST += epicsThreadPriorityTestHost -OBJS_IOC_vxWorks += epicsThreadPriorityTest +TESTPROD_HOST += epicsThreadPriorityTest +epicsThreadPriorityTest_SRCS += epicsThreadPriorityTest.cpp +testHarness_SRCS += epicsThreadPriorityTest.cpp +TESTS += epicsThreadPriorityTest -epicsThreadPrivateTestHost_SRCS += epicsThreadPrivateTestMain.cpp epicsThreadPrivateTest.cpp -PROD_HOST += epicsThreadPrivateTestHost -OBJS_IOC_vxWorks += epicsThreadPrivateTest +TESTPROD_HOST += epicsThreadPrivateTest +epicsThreadPrivateTest_SRCS += epicsThreadPrivateTest.cpp +testHarness_SRCS += epicsThreadPrivateTest.cpp +TESTS += epicsThreadPrivateTest -epicsMaxThreadsHost_SRCS += epicsMaxThreadsMain.cpp epicsMaxThreads.c -PROD_HOST += epicsMaxThreadsHost -OBJS_IOC_vxWorks += epicsMaxThreads +TESTPROD_HOST += epicsExitTest +epicsExitTest_SRCS += epicsExitTest.c +testHarness_SRCS += epicsExitTest.c +TESTS += epicsExitTest -epicsOkToBlockTestHost_SRCS += epicsOkToBlockTestMain.cpp epicsOkToBlockTest.cpp -PROD_HOST += epicsOkToBlockTestHost -OBJS_IOC_vxWorks += epicsOkToBlockTest +TESTPROD_HOST += epicsTimerTest +epicsTimerTest_SRCS += epicsTimerTest.cpp +testHarness_SRCS += epicsTimerTest.cpp +# Some of this is doing measurement, tests fail... +TESTS += epicsTimerTest -epicsExitTestHost_SRCS += epicsExitTestMain.c epicsExitTest.c -PROD_HOST += epicsExitTestHost -OBJS_IOC_vxWorks += epicsExitTest +TESTPROD_HOST += ringPointerTest +ringPointerTest_SRCS += ringPointerTest.c +testHarness_SRCS += ringPointerTest.c +TESTS += ringPointerTest + +TESTPROD_HOST += epicsEventTest +epicsEventTest_SRCS += epicsEventTest.cpp +testHarness_SRCS += epicsEventTest.cpp +TESTS += epicsEventTest + +TESTPROD_HOST += epicsMutexTest +epicsMutexTest_SRCS += epicsMutexTest.cpp +testHarness_SRCS += epicsMutexTest.cpp +TESTS += epicsMutexTest + +TESTPROD_HOST += epicsExceptionTest +epicsExceptionTest_SRCS += epicsExceptionTest.cpp +testHarness_SRCS += epicsExceptionTest.cpp +TESTS += epicsExceptionTest + +TESTPROD_HOST += epicsMessageQueueTest +epicsMessageQueueTest_SRCS += epicsMessageQueueTest.cpp +testHarness_SRCS += epicsMessageQueueTest.cpp +TESTS += epicsMessageQueueTest + +TESTPROD_HOST += macEnvExpandTest +macEnvExpandTest_SRCS += macEnvExpandTest.c +testHarness_SRCS += macEnvExpandTest.c +TESTS += macEnvExpandTest -epicsTimerTestHost_SRCS += epicsTimerTestMain.cpp epicsTimerTest.cpp -PROD_HOST += epicsTimerTestHost -OBJS_IOC_vxWorks += epicsTimerTest +# The testHarness runs all the test programs in a known working order. +testHarness_SRCS += epicsRunLibComTests.c -epicsTimerExampleHost_SRCS += epicsTimerExampleMain.cpp epicsTimerExample.cpp -PROD_HOST += epicsTimerExampleHost -OBJS_IOC_vxWorks += epicsTimerExample - -ringPointerTestHost_SRCS += ringPointerTestMain.cpp ringPointerTest.c -PROD_HOST += ringPointerTestHost -OBJS_IOC_vxWorks += ringPointerTest - -epicsEventTestHost_SRCS += epicsEventTestMain.cpp epicsEventTest.cpp -PROD_HOST += epicsEventTestHost -OBJS_IOC_vxWorks += epicsEventTest - -epicsMutexTestHost_SRCS += epicsMutexTestMain.cpp epicsMutexTest.cpp -PROD_HOST += epicsMutexTestHost -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 -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 -OBJS_IOC_vxWorks += blockingSockTest -# needed when its an object library build -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 +PROD_vxWorks = vxTestHarness +vxTestHarness_SRCS += $(testHarness_SRCS) +vxTestHarness_OBJS += $(INSTALL_BIN)/vxComLibrary PROD_RTEMS += rtemsTestHarness rtemsTestHarness_SRCS += rtemsTestHarness.c -rtemsTestHarness_SRCS += epicsRunLibComTests.c -rtemsTestHarness_SRCS += blockingSockTest.cpp -rtemsTestHarness_SRCS += epicsAlgorithmTest.cpp -rtemsTestHarness_SRCS += epicsCalcTest.cpp -rtemsTestHarness_SRCS += epicsEventTest.cpp -rtemsTestHarness_SRCS += epicsExceptionTest.cpp -rtemsTestHarness_SRCS += epicsExitTest.cpp -rtemsTestHarness_SRCS += epicsMathTest.c -rtemsTestHarness_SRCS += epicsMessageQueueTest.cpp -rtemsTestHarness_SRCS += epicsMutexTest.cpp -rtemsTestHarness_SRCS += epicsOkToBlockTest.cpp -rtemsTestHarness_SRCS += epicsStdioTest.c -rtemsTestHarness_SRCS += epicsStringTest.c -rtemsTestHarness_SRCS += epicsThreadPriorityTest.cpp -rtemsTestHarness_SRCS += epicsThreadPrivateTest.cpp -rtemsTestHarness_SRCS += epicsThreadTest.cpp -rtemsTestHarness_SRCS += epicsTimeTest.cpp -rtemsTestHarness_SRCS += epicsTimerTest.cpp -rtemsTestHarness_SRCS += macEnvExpandTest.c -rtemsTestHarness_SRCS += ringPointerTest.c +rtemsTestHarness_SRCS += $(testHarness_SRCS) TEST_SCRIPTS += $(TESTS:%=%.t) +# The following are not test programs, they measure performance + +TESTPROD_HOST += epicsThreadPerform +epicsThreadPerform_SRCS += epicsThreadPerform.cpp +testHarness_SRCS += epicsThreadPerform.cpp + +TESTPROD_HOST += epicsMaxThreads +epicsMaxThreads_SRCS += epicsMaxThreads.c +testHarness_SRCS += epicsMaxThreads.c + +TESTPROD_HOST += blockingSockTest +blockingSockTest_SRCS += blockingSockTest.cpp +testHarness_SRCS += blockingSockTest.cpp +# needed when its an object library build +blockingSockTest_SYS_LIBS_WIN32 = ws2_32 advapi32 user32 +blockingSockTest_SYS_LIBS_solaris = socket + +TESTPROD_HOST += buckTest +buckTest_SRCS += buckTest.c +testHarness_SRCS += buckTest.c + +#TESTPROD_HOST += fdmgrTest +fdmgrTest_SRCS += fdmgrTest.c +fdmgrTest_LIBS += ca +# FIXME: program never exits. + + include $(TOP)/configure/RULES test: $(TEST_SCRIPTS) @@ -157,7 +158,7 @@ test: $(TEST_SCRIPTS) @$(RM) $@ @$(CP) $< $@ -# Early versions of Test::Harness expect test programs in perl only. +# Some 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) $@ diff --git a/src/libCom/test/blockingSockTest.cpp b/src/libCom/test/blockingSockTest.cpp index 6646cb190..14b20cbff 100644 --- a/src/libCom/test/blockingSockTest.cpp +++ b/src/libCom/test/blockingSockTest.cpp @@ -1,3 +1,11 @@ +/*************************************************************************\ +* Copyright (c) 2006 UChicago Argonne LLC, as Operator of Argonne +* National Laboratory. +* Copyright (c) 2002 The Regents of the University of California, as +* Operator of Los Alamos National Laboratory. +* EPICS BASE is distributed subject to a Software License Agreement found +* in file LICENSE that is included with this distribution. +\*************************************************************************/ #include #include @@ -7,6 +15,7 @@ #include "osiWireFormat.h" #include "epicsThread.h" #include "epicsSignal.h" +#include "testMain.h" union address { struct sockaddr_in ia; @@ -47,6 +56,7 @@ private: class server { public: server ( const address & ); + void start (); void daemon (); protected: SOCKET sock; @@ -164,7 +174,10 @@ server::server ( const address & addrIn ) : assert ( status == 0 ); status = listen ( this->sock, 10 ); assert ( status == 0 ); +} +void server::start () +{ this->id = epicsThreadCreate ( "server daemon", epicsThreadPriorityMedium, epicsThreadGetStackSize(epicsThreadStackMedium), @@ -181,7 +194,8 @@ void server::daemon () SOCKET ns = accept ( this->sock, & addr.sa, & addressSize ); assert ( ns != INVALID_SOCKET ); - new serverCircuit ( ns ); + circuit * pCir = new serverCircuit ( ns ); + assert ( pCir ); } } @@ -201,7 +215,7 @@ const char * serverCircuit::pName () return "server circuit"; } -extern "C" void blockingSockTest (void) +MAIN(blockingSockTest) { address addr; memset ( (char *) & addr, 0, sizeof ( addr ) ); @@ -210,6 +224,7 @@ extern "C" void blockingSockTest (void) addr.ia.sin_port = epicsHTON16 ( 5064 ); // CA server srv ( addr ); + srv.start (); clientCircuit client ( addr ); epicsThreadSleep ( 1.0 ); @@ -254,5 +269,6 @@ extern "C" void blockingSockTest (void) } printf ( "The epicsSocketSystemCallInterruptMechanismQuery() function returns\n\"%s\".\n", pStr ); + return 0; } diff --git a/src/libCom/test/blockingSockTestMain.cpp b/src/libCom/test/blockingSockTestMain.cpp deleted file mode 100644 index 01f5b9b31..000000000 --- a/src/libCom/test/blockingSockTestMain.cpp +++ /dev/null @@ -1,7 +0,0 @@ -extern "C" void blockingSockTest (void); - -int main () -{ - blockingSockTest (); - return 0; -} diff --git a/src/libCom/test/buckTest.c b/src/libCom/test/buckTest.c index 3230e42cf..6290a5b8a 100644 --- a/src/libCom/test/buckTest.c +++ b/src/libCom/test/buckTest.c @@ -1,11 +1,10 @@ /*************************************************************************\ -* Copyright (c) 2002 The University of Chicago, as Operator of Argonne +* Copyright (c) 2006 UChicago Argonne LLC, as Operator of Argonne * National Laboratory. * Copyright (c) 2002 The Regents of the University of California, as * Operator of Los Alamos National Laboratory. -* EPICS BASE Versions 3.13.7 -* and higher are distributed subject to a Software License Agreement found -* in file LICENSE that is included with this distribution. +* EPICS BASE is distributed subject to a Software License Agreement found +* in file LICENSE that is included with this distribution. \*************************************************************************/ #include @@ -13,8 +12,9 @@ #include "epicsAssert.h" #include "bucketLib.h" +#include "testMain.h" -int main() +MAIN(buckTest) { unsigned id1; unsigned id2; diff --git a/src/libCom/test/epicsAlgorithmTest.cpp b/src/libCom/test/epicsAlgorithmTest.cpp index a05de7fe5..7f186af23 100644 --- a/src/libCom/test/epicsAlgorithmTest.cpp +++ b/src/libCom/test/epicsAlgorithmTest.cpp @@ -1,25 +1,19 @@ /*************************************************************************\ -* Copyright (c) 2002 The University of Chicago, as Operator of Argonne +* Copyright (c) 2006 UChicago Argonne LLC, as Operator of Argonne * National Laboratory. * Copyright (c) 2002 The Regents of the University of California, as * Operator of Los Alamos National Laboratory. -* EPICS BASE Versions 3.13.7 -* and higher are distributed subject to a Software License Agreement found -* in file LICENSE that is included with this distribution. +* EPICS BASE is distributed subject to a Software License Agreement found +* in file LICENSE that is included with this distribution. \*************************************************************************/ // epicsAlgorithmTest.cpp // Authors: Jeff Hill & Andrew Johnson #include "epicsUnitTest.h" #include "epicsAlgorithm.h" +#include "testMain.h" -#if defined(vxWorks) || defined(__rtems__) - #define MAIN(prog) extern "C" int prog -#else - #define MAIN(prog) int main -#endif - -MAIN(epicsAlgorithm) (int /*argc*/, char* /*argv[]*/) +MAIN(epicsAlgorithm) { testPlan(22); diff --git a/src/libCom/test/epicsCalcTest.cpp b/src/libCom/test/epicsCalcTest.cpp index b8e90b7d9..6d33dfa23 100644 --- a/src/libCom/test/epicsCalcTest.cpp +++ b/src/libCom/test/epicsCalcTest.cpp @@ -1,11 +1,8 @@ /*************************************************************************\ -* Copyright (c) 2002 The University of Chicago, as Operator of Argonne +* Copyright (c) 2006 UChicago Argonne LLC, as Operator of Argonne * National Laboratory. -* Copyright (c) 2002 The Regents of the University of California, as -* Operator of Los Alamos National Laboratory. -* EPICS BASE Versions 3.13.7 -* and higher are distributed subject to a Software License Agreement found -* in file LICENSE that is included with this distribution. +* EPICS BASE is distributed subject to a Software License Agreement found +* in file LICENSE that is included with this distribution. \*************************************************************************/ // $Id$ // Author: Andrew Johnson @@ -14,13 +11,7 @@ #include "epicsMath.h" #include "epicsAlgorithm.h" #include "postfix.h" - -#if defined(vxWorks) || defined(__rtems__) - #define MAIN(prog) extern "C" int prog -#else - #define MAIN(prog) int main -#endif - +#include "testMain.h" /* Infrastructure for running tests */ @@ -100,7 +91,7 @@ void testCalc(const char *expr, double expected) { #define XOR ^ -MAIN(epicsCalcTest) (int /*argc*/, char* /*argv[]*/) +MAIN(epicsCalcTest) { int repeat; const double a=1.0, b=2.0, c=3.0, d=4.0, e=5.0, f=6.0, @@ -110,7 +101,7 @@ MAIN(epicsCalcTest) (int /*argc*/, char* /*argv[]*/) Inf /= NaN; NaN /= NaN; - testPlan(240); + testPlan(392); /* LITERAL_OPERAND elements */ testExpr(0); @@ -193,13 +184,13 @@ MAIN(epicsCalcTest) (int /*argc*/, char* /*argv[]*/) testExpr(MAX(1,2)); testExpr(MAX(1.,Inf)); testExpr(MAX(1.,-Inf)); - testCalc("MAX(1,NaN)", NaN); - testCalc("MAX(NaN,1)", NaN); + testExpr(MAX(1.,NaN)); + testExpr(MAX(NaN,1.)); testExpr(MIN(1,2)); testExpr(MIN(1.,Inf)); testExpr(MIN(1.,-Inf)); - testCalc("MIN(1,NaN)", NaN); - testCalc("MIN(NaN,1)", NaN); + testExpr(MIN(1.,NaN)); + testExpr(MIN(NaN,1.)); testExpr(NINT(0.6)); testExpr(NINT(-0.6)); testExpr(sin(0.5)); @@ -216,6 +207,21 @@ MAIN(epicsCalcTest) (int /*argc*/, char* /*argv[]*/) testExpr(0 != 0); testExpr(1 != 0); testExpr(1 != 0 != 2); + testExpr(0.0 != Inf); + testExpr(0.0 != -Inf); + testExpr(0.0 != NaN); + testExpr(Inf != 0.0); + testExpr(Inf != Inf); + testExpr(Inf != -Inf); + testExpr(Inf != NaN); + testExpr(-Inf != 0.0); + testExpr(-Inf != Inf); + testExpr(-Inf != -Inf); + testExpr(-Inf != NaN); + testExpr(NaN != 0.0); + testExpr(NaN != Inf); + testExpr(NaN != -Inf); + testExpr(NaN != NaN); testCalc("0 # 1", 0 != 1); testCalc("0 # 0", 0 != 0); @@ -234,6 +240,21 @@ MAIN(epicsCalcTest) (int /*argc*/, char* /*argv[]*/) testExpr(1 && 1); testExpr(2 * 2); + testExpr(0.0 * Inf); + testExpr(0.0 * -Inf); + testExpr(0.0 * NaN); + testExpr(Inf * 0.0); + testExpr(Inf * Inf); + testExpr(Inf * -Inf); + testExpr(Inf * NaN); + testExpr(-Inf * 0.0); + testExpr(-Inf * Inf); + testExpr(-Inf * -Inf); + testExpr(-Inf * NaN); + testExpr(NaN * 0.0); + testExpr(NaN * Inf); + testExpr(NaN * -Inf); + testExpr(NaN * NaN); testCalc("2 ** 0.2", pow(2., 0.2)); testCalc("2 ** -0.2", pow(2., -0.2)); @@ -242,17 +263,77 @@ MAIN(epicsCalcTest) (int /*argc*/, char* /*argv[]*/) testCalc("2 ** 2 ** 3", pow(pow(2., 2.), 3.)); testExpr(0 + 1); + testExpr(0.0 + Inf); + testExpr(0.0 + -Inf); + testExpr(0.0 + NaN); + testExpr(Inf + 0.0); + testExpr(Inf + Inf); + testExpr(Inf + -Inf); + testExpr(Inf + NaN); + testExpr(-Inf + 0.0); + testExpr(-Inf + Inf); + testExpr(-Inf + -Inf); + testExpr(-Inf + NaN); + testExpr(NaN + 0.0); + testExpr(NaN + Inf); + testExpr(NaN + -Inf); + testExpr(NaN + NaN); testExpr(0 - 1); testExpr(0 - 1 - 2); + testExpr(0.0 - Inf); + testExpr(0.0 - -Inf); + testExpr(0.0 - NaN); + testExpr(Inf - 0.0); + testExpr(Inf - Inf); + testExpr(Inf - -Inf); + testExpr(Inf - NaN); + testExpr(-Inf - 0.0); + testExpr(-Inf - Inf); + testExpr(-Inf - -Inf); + testExpr(-Inf - NaN); + testExpr(NaN - 0.0); + testExpr(NaN - Inf); + testExpr(NaN - -Inf); + testExpr(NaN - NaN); testExpr(2.0 / 3.0); testExpr(1.0 / 2.0 / 3.0); + testExpr(0.0 / Inf); + testExpr(0.0 / -Inf); + testExpr(0.0 / NaN); + testExpr(Inf / 1.0); + testExpr(Inf / Inf); + testExpr(Inf / -Inf); + testExpr(Inf / NaN); + testExpr(-Inf / 1.0); + testExpr(-Inf / Inf); + testExpr(-Inf / -Inf); + testExpr(-Inf / NaN); + testExpr(NaN / 1.0); + testExpr(NaN / Inf); + testExpr(NaN / -Inf); + testExpr(NaN / NaN); testExpr(0 < 1); testExpr(0 < 0); testExpr(1 < 0); testExpr(2 < 0 < 2) + testExpr(0.0 < Inf); + testExpr(0.0 < -Inf); + testExpr(0.0 < NaN); + testExpr(Inf < 0.0); + testExpr(Inf < Inf); + testExpr(Inf < -Inf); + testExpr(Inf < NaN); + testExpr(-Inf < 0.0); + testExpr(-Inf < Inf); + testExpr(-Inf < -Inf); + testExpr(-Inf < NaN); + testExpr(NaN < 0.0); + testExpr(NaN < Inf); + testExpr(NaN < -Inf); + testExpr(NaN < NaN); testExpr(1 << 2); testExpr(1 << 3 << 2) @@ -261,6 +342,21 @@ MAIN(epicsCalcTest) (int /*argc*/, char* /*argv[]*/) testExpr(0 <= 0); testExpr(1 <= 0); testExpr(3 <= 2 <= 3) + testExpr(0.0 <= Inf); + testExpr(0.0 <= -Inf); + testExpr(0.0 <= NaN); + testExpr(Inf <= 0.0); + testExpr(Inf <= Inf); + testExpr(Inf <= -Inf); + testExpr(Inf <= NaN); + testExpr(-Inf <= 0.0); + testExpr(-Inf <= Inf); + testExpr(-Inf <= -Inf); + testExpr(-Inf <= NaN); + testExpr(NaN <= 0.0); + testExpr(NaN <= Inf); + testExpr(NaN <= -Inf); + testExpr(NaN <= NaN); testCalc("0 = 1", 0 == 1); testCalc("0 = 0", 0 == 0); @@ -271,16 +367,61 @@ MAIN(epicsCalcTest) (int /*argc*/, char* /*argv[]*/) testExpr(0 == 0); testExpr(1 == 0); testExpr(2 == 2 == 1); + testExpr(0.0 == Inf); + testExpr(0.0 == -Inf); + testExpr(0.0 == NaN); + testExpr(Inf == 0.0); + testExpr(Inf == Inf); + testExpr(Inf == -Inf); + testExpr(Inf == NaN); + testExpr(-Inf == 0.0); + testExpr(-Inf == Inf); + testExpr(-Inf == -Inf); + testExpr(-Inf == NaN); + testExpr(NaN == 0.0); + testExpr(NaN == Inf); + testExpr(NaN == -Inf); + testExpr(NaN == NaN); testExpr(0 > 1); testExpr(0 > 0); testExpr(1 > 0); testExpr(2 > 0 > 2); + testExpr(0.0 > Inf); + testExpr(0.0 > -Inf); + testExpr(0.0 > NaN); + testExpr(Inf > 0.0); + testExpr(Inf > Inf); + testExpr(Inf > -Inf); + testExpr(Inf > NaN); + testExpr(-Inf > 0.0); + testExpr(-Inf > Inf); + testExpr(-Inf > -Inf); + testExpr(-Inf > NaN); + testExpr(NaN > 0.0); + testExpr(NaN > Inf); + testExpr(NaN > -Inf); + testExpr(NaN > NaN); testExpr(0 >= 1); testExpr(0 >= 0); testExpr(1 >= 0); testExpr(3 >= 2 >= 3); + testExpr(0.0 >= Inf); + testExpr(0.0 >= -Inf); + testExpr(0.0 >= NaN); + testExpr(Inf >= 0.0); + testExpr(Inf >= Inf); + testExpr(Inf >= -Inf); + testExpr(Inf >= NaN); + testExpr(-Inf >= 0.0); + testExpr(-Inf >= Inf); + testExpr(-Inf >= -Inf); + testExpr(-Inf >= NaN); + testExpr(NaN >= 0.0); + testExpr(NaN >= Inf); + testExpr(NaN >= -Inf); + testExpr(NaN >= NaN); testExpr(8 >> 1); testExpr(64 >> 2 >> 1); @@ -307,6 +448,8 @@ MAIN(epicsCalcTest) (int /*argc*/, char* /*argv[]*/) /* CONDITIONAL elements */ testExpr(0 ? 1 : 2); testExpr(1 ? 1 : 2); + testExpr(Inf ? 1 : 2); + testExpr(NaN ? 1 : 2); testExpr(0 ? 0 ? 2 : 3 : 4); testExpr(0 ? 1 ? 2 : 3 : 4); testExpr(1 ? 0 ? 2 : 3 : 4); diff --git a/src/libCom/test/epicsEventTest.cpp b/src/libCom/test/epicsEventTest.cpp index f91ada6a1..58aa47e28 100644 --- a/src/libCom/test/epicsEventTest.cpp +++ b/src/libCom/test/epicsEventTest.cpp @@ -1,11 +1,10 @@ /*************************************************************************\ -* Copyright (c) 2002 The University of Chicago, as Operator of Argonne +* Copyright (c) 2006 UChicago Argonne LLC, as Operator of Argonne * National Laboratory. * Copyright (c) 2002 The Regents of the University of California, as * Operator of Los Alamos National Laboratory. -* EPICS BASE Versions 3.13.7 -* and higher are distributed subject to a Software License Agreement found -* in file LICENSE that is included with this distribution. +* EPICS BASE is distributed subject to a Software License Agreement found +* in file LICENSE that is included with this distribution. \*************************************************************************/ /* epicsEventTest.cpp */ @@ -27,6 +26,8 @@ #include "epicsRingPointer.h" #include "epicsTime.h" #include "errlog.h" +#include "epicsUnitTest.h" +#include "testMain.h" typedef struct info { @@ -34,84 +35,74 @@ typedef struct info { epicsMutexId lockRing; int quit; epicsRingPointerId ring; -}info; - +} info; + extern "C" { static void consumer(void *arg) { info *pinfo = (info *)arg; - time_t tp; - epicsThreadId idSelf = epicsThreadGetIdSelf(); + int errors = 0; - printf("consumer %p starting time %ld\n",idSelf,time(&tp)); - while(1) { - epicsEventWaitStatus status; - if(pinfo->quit) { - printf("consumer %p returning time %ld\n", - idSelf,time(&tp)); - return; + testDiag("consumer: starting"); + while (!pinfo->quit) { + epicsEventWaitStatus status = epicsEventWait(pinfo->event); + if (status != epicsEventWaitOK) { + testDiag("consumer: epicsEventWait returned %d", status); + errors++; } - status = epicsEventWait(pinfo->event); - if(status!=epicsEventWaitOK) { - printf("task %p epicsEventWait returned %d time %ld\n", - idSelf,(int)status,time(&tp)); - } - while(epicsRingPointerGetUsed(pinfo->ring)>=2) { + while (epicsRingPointerGetUsed(pinfo->ring) >= 2) { epicsRingPointerId message[2]; - int i; - - for(i=0; i<2; i++) { - if(!(message[i]=epicsRingPointerPop(pinfo->ring))) - printf("consumer error\n"); + for (int i = 0; i < 2; i++) { + message[i] = epicsRingPointerPop(pinfo->ring); + if (message[i] == 0) { + testDiag("consumer: epicsRingPointerPop returned 0"); + errors++; + } } - if(message[0]!=message[1]) { - printf("consumer error message %p %p\n",message[0],message[1]); - } else { - printf("consumer message from %p\n",message[0]); + if (message[0] != message[1]) { + testDiag("consumer: message %p %p\n", message[0], message[1]); + errors++; } } } + testOk(errors == 0, "consumer: errors = %d", errors); } - + static void producer(void *arg) { info *pinfo = (info *)arg; - time_t tp; - epicsThreadId idSelf = epicsThreadGetIdSelf(); - int ntimes=0; - - printf("producer %p starting time %ld\n",idSelf,time(&tp)); - while(1) { - epicsMutexLockStatus status; + const char *name = epicsThreadGetNameSelf(); + epicsThreadId myId = epicsThreadGetIdSelf(); + int errors = 0; + int ntimes = 0; + testDiag("%s: starting", name); + while(!pinfo->quit) { ++ntimes; - if(pinfo->quit) { - printf("producer %p returning time %ld\n", - idSelf,time(&tp)); - return; + epicsMutexLockStatus status = epicsMutexLock(pinfo->lockRing); + if (status != epicsMutexLockOK) { + testDiag("%s: epicsMutexLock returned %d", name, status); + errors++; } - status = epicsMutexLock(pinfo->lockRing); - if(status!=epicsMutexLockOK) { - printf("producer %p epicsMutexLock returned %d time %ld\n", - idSelf,(int)status,time(&tp)); - } - if(epicsRingPointerGetFree(pinfo->ring)>=2) { - int i; - - for(i=0; i<2; i++) { - if(!epicsRingPointerPush(pinfo->ring,idSelf)) - printf("producer %p error\n",idSelf); - if(i==0 && (ntimes%4==0)) epicsThreadSleep(.1); + if (epicsRingPointerGetFree(pinfo->ring) >= 2) { + for (int i = 0; i < 2; i++) { + if (!epicsRingPointerPush(pinfo->ring, myId)) { + testDiag("%s: epicsRingPointerPush fail", name); + errors++; + } + if (i == 0 && (ntimes % 4 == 0)) + epicsThreadSleep(0.1); } - printf("producer %p sending\n",idSelf); } else { - printf("producer %p ring buffer is full\n",idSelf); + testFail("%s: ring buffer full", name); + errors++; } epicsMutexUnlock(pinfo->lockRing); epicsThreadSleep(1.0); epicsEventSignal(pinfo->event); } + testOk(errors == 0, "%s: errors = %d", name, errors); } } // extern "C" @@ -123,7 +114,7 @@ static double eventWaitMeasureDelayError( const epicsEventId &id, const double & epicsTime end = epicsTime::getCurrent(); double meas = end - beg; double error = fabs ( delay - meas ); - printf ( "epicsEventWaitWithTimeout ( %10f ) tmo delay err %10f sec\n", + testDiag("epicsEventWaitWithTimeout(%.6f) delay error %.6f sec", delay, error ); return error; } @@ -139,68 +130,66 @@ static void eventWaitTest() } errorSum += eventWaitMeasureDelayError ( event, 0.0 ); epicsEventDestroy ( event ); - printf ( "Average error %f sec\n", errorSum / ( i + 1 ) ); + double meanError = errorSum / ( i + 1 ); + testOk(meanError < 0.05, "Average error %.6f sec", meanError); } - -extern "C" void epicsEventTest(int nthreads,int verbose) + +MAIN(epicsEventTest) { - unsigned int stackSize; + const int nthreads = 3; epicsThreadId *id; char **name; - int i; - info *pinfo; epicsEventId event; int status; - time_t tp; - int errVerboseSave = errVerbose; - eventWaitTest(); + testPlan(9); - errVerbose = verbose; event = epicsEventMustCreate(epicsEventEmpty); - printf("calling epicsEventWaitWithTimeout(event,2.0) time %ld\n",time(&tp)); - status = epicsEventWaitWithTimeout(event,2.0); - if(status!=epicsEventWaitTimeout) printf("status %d\n",status); - printf("calling epicsEventTryWait(event) time %ld\n",time(&tp)); - status = epicsEventTryWait(event); - if(status!=epicsEventWaitTimeout) printf("status %d\n",status); - printf("calling epicsEventSignal() time %ld\n",time(&tp)); - epicsEventSignal(event); - printf("calling epicsEventWaitWithTimeout(event,2.0) time %ld\n",time(&tp)); - status = epicsEventWaitWithTimeout(event,2.0); - if(status) printf("status %d\n",status); - printf("calling epicsEventSignal() time %ld\n",time(&tp)); - epicsEventSignal(event); - printf("calling epicsEventTryWait(event) time %ld\n",time(&tp)); - status = epicsEventTryWait(event); - if(status) printf("status %d\n",status); - if(nthreads<=0) { - errVerbose = errVerboseSave; - return; - } - pinfo = (info *)calloc(1,sizeof(info)); + status = epicsEventWaitWithTimeout(event, 2.0); + testOk(status == epicsEventWaitTimeout, + "epicsEventWaitWithTimeout(event, 2.0) = %d", status); + + status = epicsEventTryWait(event); + testOk(status == epicsEventWaitTimeout, + "epicsEventTryWait(event) = %d", status); + + epicsEventSignal(event); + status = epicsEventWaitWithTimeout(event,2.0); + testOk(status == 0, + "epicsEventWaitWithTimeout(event, 2.0) = %d", status); + + epicsEventSignal(event); + status = epicsEventTryWait(event); + testOk(status == 0, + "epicsEventTryWait(event) = %d", status); + + info *pinfo = (info *)calloc(1,sizeof(info)); pinfo->event = event; pinfo->lockRing = epicsMutexCreate(); pinfo->ring = epicsRingPointerCreate(1024*2); - stackSize = epicsThreadGetStackSize(epicsThreadStackSmall); - epicsThreadCreate("consumer",50,stackSize,consumer,pinfo); - id = (epicsThreadId *)calloc(nthreads,sizeof(epicsThreadId)); - name = (char **)calloc(nthreads,sizeof(char *)); - for(i=0; iquit = 1; epicsThreadSleep(2.0); + epicsEventSignal(pinfo->event); epicsThreadSleep(1.0); - printf("semTest returning time %ld\n",time(&tp)); - errVerbose = errVerboseSave; + + eventWaitTest(); + + return testDone(); } diff --git a/src/libCom/test/epicsEventTestMain.cpp b/src/libCom/test/epicsEventTestMain.cpp deleted file mode 100644 index fd7c0cfec..000000000 --- a/src/libCom/test/epicsEventTestMain.cpp +++ /dev/null @@ -1,49 +0,0 @@ -/*************************************************************************\ -* Copyright (c) 2002 The University of Chicago, as Operator of Argonne -* National Laboratory. -* Copyright (c) 2002 The Regents of the University of California, as -* Operator of Los Alamos National Laboratory. -* EPICS BASE Versions 3.13.7 -* and higher are distributed subject to a Software License Agreement found -* in file LICENSE that is included with this distribution. -\*************************************************************************/ -/* epicsEventTestMain.cpp */ - -/* Author: Marty Kraimer Date: 26JAN2000 */ - -#include -#include -#include -#include -#include -#include - -#include "epicsThread.h" -extern "C" void epicsEventTest(int nthreads,int errVerbose); - - -int main(int argc,char *argv[]) -{ - int nthreads = 2; - int errVerboseIn = 0; - - if(argc>1) { - if(isdigit(*argv[1])) { - sscanf(argv[1],"%d",&nthreads); - printf("nthreads %d\n",nthreads); - } else { - printf("Illegal argument %s\n",argv[1]); - } - } - if(argc>2) { - if(isdigit(*argv[2])) { - sscanf(argv[2],"%d",&errVerboseIn); - printf("errVerbose %d\n",errVerboseIn); - } else { - printf("Illegal argument %s\n",argv[1]); - } - } - epicsEventTest(nthreads,errVerboseIn); - printf("main terminating\n"); - return(0); -} diff --git a/src/libCom/test/epicsExceptionTest.cpp b/src/libCom/test/epicsExceptionTest.cpp index c97350e45..af8a1d2fe 100644 --- a/src/libCom/test/epicsExceptionTest.cpp +++ b/src/libCom/test/epicsExceptionTest.cpp @@ -1,11 +1,10 @@ /*************************************************************************\ -* Copyright (c) 2002 The University of Chicago, as Operator of Argonne +* Copyright (c) 2006 UChicago Argonne LLC, as Operator of Argonne * National Laboratory. * Copyright (c) 2002 The Regents of the University of California, as * Operator of Los Alamos National Laboratory. -* EPICS BASE Versions 3.13.7 -* and higher are distributed subject to a Software License Agreement found -* in file LICENSE that is included with this distribution. +* EPICS BASE is distributed subject to a Software License Agreement found +* in file LICENSE that is included with this distribution. \*************************************************************************/ // @@ -25,6 +24,7 @@ #include "epicsUnitTest.h" #include "epicsThread.h" +#include "testMain.h" using namespace std; @@ -42,8 +42,8 @@ const nothrow_t nothrow ; static const size_t unsuccessfulNewSize = numeric_limits::max()-100; # endif #elif defined(__GNUC__) && (__GNUC__<2 || (__GNUC__==2 && __GNUC_MINOR__<=96)) - // tornado does not supply ansi c++ - static const size_t unsuccessfulNewSize = UINT_MAX; + // tornado does not supply ansi c++, and malloc(-15) succeeds... + static const size_t unsuccessfulNewSize = UINT_MAX - 15u; #else static const size_t unsuccessfulNewSize = numeric_limits::max(); #endif @@ -61,11 +61,11 @@ private: static void epicsExceptionTestPrivate () { try { - new char [unsuccessfulNewSize]; - testFail("new: didn't throw at all"); + char * p = new char [unsuccessfulNewSize]; + testFail("new char[%u] returned %p", unsuccessfulNewSize, p); } catch ( const bad_alloc & ) { - testPass("new"); + testPass("new char[%u] threw", unsuccessfulNewSize); } catch ( ... ) { testFail("new: threw wrong type"); @@ -100,7 +100,7 @@ void exThread::waitForCompletion () } } -extern "C" int epicsExceptionTest () +MAIN(epicsExceptionTest) { testPlan(4); epicsExceptionTestPrivate (); diff --git a/src/libCom/test/epicsExceptionTestMain.cpp b/src/libCom/test/epicsExceptionTestMain.cpp deleted file mode 100644 index 8eee729d4..000000000 --- a/src/libCom/test/epicsExceptionTestMain.cpp +++ /dev/null @@ -1,16 +0,0 @@ -/*************************************************************************\ -* Copyright (c) 2002 The University of Chicago, as Operator of Argonne -* National Laboratory. -* Copyright (c) 2002 The Regents of the University of California, as -* Operator of Los Alamos National Laboratory. -* EPICS BASE Versions 3.13.7 -* and higher are distributed subject to a Software License Agreement found -* in file LICENSE that is included with this distribution. -\*************************************************************************/ - -extern "C" int epicsExceptionTest (); - -int main () -{ - return epicsExceptionTest (); -} diff --git a/src/libCom/test/epicsExitTest.c b/src/libCom/test/epicsExitTest.c index 06dcc5388..c628208c4 100644 --- a/src/libCom/test/epicsExitTest.c +++ b/src/libCom/test/epicsExitTest.c @@ -1,11 +1,10 @@ /*************************************************************************\ -* Copyright (c) 2002 The University of Chicago, as Operator of Argonne +* Copyright (c) 2006 UChicago Argonne LLC, as Operator of Argonne * National Laboratory. * Copyright (c) 2002 The Regents of the University of California, as * Operator of Los Alamos National Laboratory. -* EPICS BASE Versions 3.13.7 -* and higher are distributed subject to a Software License Agreement found -* in file LICENSE that is included with this distribution. +* EPICS BASE is distributed subject to a Software License Agreement found +* in file LICENSE that is included with this distribution. \*************************************************************************/ /* epicsExitTest.cpp */ @@ -22,9 +21,12 @@ #include "epicsAssert.h" #include "epicsEvent.h" #include "epicsExit.h" +#include "epicsUnitTest.h" +#include "testMain.h" typedef struct info { + const char *name; epicsEventId terminate; epicsEventId terminated; }info; @@ -32,9 +34,11 @@ typedef struct info { static void atExit(void *pvt) { info *pinfo = (info *)pvt; + testPass("%s reached atExit", pinfo->name); epicsEventSignal(pinfo->terminate); /*Now wait for thread to terminate*/ epicsEventMustWait(pinfo->terminated); + testPass("%s destroying pinfo", pinfo->name); epicsEventDestroy(pinfo->terminate); epicsEventDestroy(pinfo->terminated); free(pinfo); @@ -44,25 +48,39 @@ static void thread(void *arg) { info *pinfo = (info *)arg; - printf("thread %s starting\n", epicsThreadGetNameSelf()); + pinfo->name = epicsThreadGetNameSelf(); + testDiag("%s starting", pinfo->name); pinfo->terminate = epicsEventMustCreate(epicsEventEmpty); pinfo->terminated = epicsEventMustCreate(epicsEventEmpty); - epicsAtExit(atExit,pinfo); - printf("thread %s waiting for atExit\n", epicsThreadGetNameSelf()); + epicsAtExit(atExit, pinfo); + testDiag("%s waiting for atExit", pinfo->name); epicsEventMustWait(pinfo->terminate); - printf("thread %s terminating\n", epicsThreadGetNameSelf()); + testPass("%s terminating", pinfo->name); epicsEventSignal(pinfo->terminated); } -void epicsExitTest(void) -{ - unsigned int stackSize; - info *pinfoA; - info *pinfoB; - stackSize = epicsThreadGetStackSize(epicsThreadStackSmall); - pinfoA = (info *)calloc(1,sizeof(info)); - epicsThreadCreate("threadA",50,stackSize,thread,pinfoA); - pinfoB = (info *)calloc(1,sizeof(info)); - epicsThreadCreate("threadB",50,stackSize,thread,pinfoB); - epicsThreadSleep(1.0); +static void mainExit(void *pvt) +{ + testPass("Reached mainExit"); + testDone(); +} + +MAIN(epicsExitTest) +{ + unsigned int stackSize = epicsThreadGetStackSize(epicsThreadStackSmall); + info *pinfoA = (info *)calloc(1, sizeof(info)); + info *pinfoB = (info *)calloc(1, sizeof(info)); + + testPlan(7); + + epicsAtExit(mainExit, NULL); + + epicsThreadCreate("threadA", 50, stackSize, thread, pinfoA); + epicsThreadSleep(0.1); + epicsThreadCreate("threadB", 50, stackSize, thread, pinfoB); + epicsThreadSleep(1.0); + + testDiag("Calling epicsExit\n"); + epicsExit(0); + return 0; } diff --git a/src/libCom/test/epicsExitTestMain.c b/src/libCom/test/epicsExitTestMain.c deleted file mode 100644 index 423c8db77..000000000 --- a/src/libCom/test/epicsExitTestMain.c +++ /dev/null @@ -1,34 +0,0 @@ -/*************************************************************************\ -* Copyright (c) 2002 The University of Chicago, as Operator of Argonne -* National Laboratory. -* Copyright (c) 2002 The Regents of the University of California, as -* Operator of Los Alamos National Laboratory. -* EPICS BASE Versions 3.13.7 -* and higher are distributed subject to a Software License Agreement found -* in file LICENSE that is included with this distribution. -\*************************************************************************/ -/* epicsExitTestMain.c */ - -/* Author: Marty Kraimer Date: 24AUG2004 */ - -#include -#include -#include -#include -#include -#include - -#include "epicsExit.h" -#include "epicsThread.h" - -void epicsExitTest(void); - - -int main(int argc,char *argv[]) -{ - epicsExitTest(); - epicsThreadSleep(1.0); - printf("main calling epicsExit\n"); - epicsExit(0); - return(0); -} diff --git a/src/libCom/test/epicsMathTest.c b/src/libCom/test/epicsMathTest.c index 4872ec0b2..e4d878580 100644 --- a/src/libCom/test/epicsMathTest.c +++ b/src/libCom/test/epicsMathTest.c @@ -1,11 +1,10 @@ /*************************************************************************\ -* Copyright (c) 2002 The University of Chicago, as Operator of Argonne +* Copyright (c) 2006 UChicago Argonne LLC, as Operator of Argonne * National Laboratory. * Copyright (c) 2002 The Regents of the University of California, as * Operator of Los Alamos National Laboratory. -* EPICS BASE Versions 3.13.7 -* and higher are distributed subject to a Software License Agreement found -* in file LICENSE that is included with this distribution. +* EPICS BASE is distributed subject to a Software License Agreement found +* in file LICENSE that is included with this distribution. \*************************************************************************/ /* epicsMathTest.c * @@ -14,8 +13,9 @@ #include "epicsUnitTest.h" #include "epicsMath.h" +#include "testMain.h" -int epicsMathTest () +MAIN(epicsMathTest) { double a,b,c; diff --git a/src/libCom/test/epicsMathTestMain.cpp b/src/libCom/test/epicsMathTestMain.cpp deleted file mode 100644 index 457e98808..000000000 --- a/src/libCom/test/epicsMathTestMain.cpp +++ /dev/null @@ -1,23 +0,0 @@ -/*************************************************************************\ -* Copyright (c) 2002 The University of Chicago, as Operator of Argonne -* National Laboratory. -* Copyright (c) 2002 The Regents of the University of California, as -* Operator of Los Alamos National Laboratory. -* EPICS BASE Versions 3.13.7 -* and higher are distributed subject to a Software License Agreement found -* in file LICENSE that is included with this distribution. -\*************************************************************************/ -/* epicsMathTestMain.cpp - * - * Author Marty Kraimer - */ - -extern "C" { -int epicsMathTest ( void ); -} - -int main ( int , char *[] ) -{ - epicsMathTest (); - return 0; -} diff --git a/src/libCom/test/epicsMaxThreads.c b/src/libCom/test/epicsMaxThreads.c index 44b103179..8d0d06da5 100644 --- a/src/libCom/test/epicsMaxThreads.c +++ b/src/libCom/test/epicsMaxThreads.c @@ -1,11 +1,10 @@ /*************************************************************************\ -* Copyright (c) 2002 The University of Chicago, as Operator of Argonne +* Copyright (c) 2006 UChicago Argonne LLC, as Operator of Argonne * National Laboratory. * Copyright (c) 2002 The Regents of the University of California, as * Operator of Los Alamos National Laboratory. -* EPICS BASE Versions 3.13.7 -* and higher are distributed subject to a Software License Agreement found -* in file LICENSE that is included with this distribution. +* EPICS BASE is distributed subject to a Software License Agreement found +* in file LICENSE that is included with this distribution. \*************************************************************************/ /* epicsMaxThreads.cpp */ @@ -22,6 +21,7 @@ #include "epicsEvent.h" #include "epicsExit.h" #include "errlog.h" +#include "testMain.h" static epicsEventId started; @@ -31,15 +31,15 @@ static void thread(void *arg) epicsThreadSuspendSelf(); } -void epicsMaxThreads(void) +MAIN(epicsMaxThreads) { unsigned int stackSize; epicsThreadId id; int i = 0; stackSize = epicsThreadGetStackSize(epicsThreadStackSmall); - errlogPrintf("stackSize %d\n",stackSize); - errlogFlush(); + printf("stackSize %d\n",stackSize); + started = epicsEventMustCreate(epicsEventEmpty); while(1) { @@ -47,9 +47,10 @@ void epicsMaxThreads(void) if(!id) break; i++; if ((i % 100) == 0) - printf ("%d\n", i); + printf ("Reached %d...\n", i); epicsEventMustWait(started); } - fprintf(stdout,"number threads %d\n",i); - epicsExitCallAtExits(); + + printf("Max number of \"Small\" threads on this OS is %d\n", i); + return 0; } diff --git a/src/libCom/test/epicsMaxThreadsMain.cpp b/src/libCom/test/epicsMaxThreadsMain.cpp deleted file mode 100644 index 89fd0d202..000000000 --- a/src/libCom/test/epicsMaxThreadsMain.cpp +++ /dev/null @@ -1,29 +0,0 @@ -/*************************************************************************\ -* Copyright (c) 2002 The University of Chicago, as Operator of Argonne -* National Laboratory. -* Copyright (c) 2002 The Regents of the University of California, as -* Operator of Los Alamos National Laboratory. -* EPICS BASE Versions 3.13.7 -* and higher are distributed subject to a Software License Agreement found -* in file LICENSE that is included with this distribution. -\*************************************************************************/ -/* epicsMaxThreadsMain.cpp */ - -/* Author: Marty Kraimer Date: 26JAN2000 */ - -#include -#include -#include -#include -#include -#include - -extern "C" void epicsMaxThreads(void); - - -int main(int /*argc*/, char * /*argv[]*/ ) -{ - epicsMaxThreads(); - printf("main terminating\n"); - return(0); -} diff --git a/src/libCom/test/epicsMessageQueueTest.cpp b/src/libCom/test/epicsMessageQueueTest.cpp index b10050bcb..a63cb2772 100644 --- a/src/libCom/test/epicsMessageQueueTest.cpp +++ b/src/libCom/test/epicsMessageQueueTest.cpp @@ -1,11 +1,10 @@ /*************************************************************************\ -* Copyright (c) 2002 The University of Chicago, as Operator of Argonne +* Copyright (c) 2006 UChicago Argonne LLC, as Operator of Argonne * National Laboratory. * Copyright (c) 2002 The Regents of the University of California, as * Operator of Los Alamos National Laboratory. -* EPICS BASE Versions 3.13.7 -* and higher are distributed subject to a Software License Agreement found -* in file LICENSE that is included with this distribution. +* EPICS BASE is distributed subject to a Software License Agreement found +* in file LICENSE that is included with this distribution. \*************************************************************************/ /* * $Id$ @@ -18,12 +17,17 @@ #include #include #include -#include -#include -#include -#include -const char *msg1 = "1234567890This is a very long message."; +#include "epicsMessageQueue.h" +#include "epicsThread.h" +#include "epicsExit.h" +#include "epicsEvent.h" +#include "epicsAssert.h" +#include "epicsUnitTest.h" +#include "testMain.h" + +static const char *msg1 = "1234567890This is a very long message."; +static int testExit = 0; /* * In Numerical Recipes in C: The Art of Scientific Computing (William H. @@ -47,11 +51,27 @@ badReceiver(void *arg) { epicsMessageQueue *q = (epicsMessageQueue *)arg; char cbuf[80]; + int len; cbuf[0] = '\0'; - assert((q->receive(cbuf, 1) == -1) && (cbuf[0] == '\0')); - epicsThreadSleep(5.0); - assert((q->receive(cbuf, 1) == -1) && (cbuf[0] == '\0')); + len = q->receive(cbuf, 1); + if (len < 0 && cbuf[0] == '\0') + testPass("receive into undersized buffer returned error (%d)", len); + else if (len == 1 && cbuf[0] == *msg1) + testPass("receive into undersized buffer truncated message"); + else + testFail("receive into undersized buffer returned %d", len); + + epicsThreadSleep(3.0); + + cbuf[0] = '\0'; + len = q->receive(cbuf, 1); + if (len < 0 && cbuf[0] == '\0') + testPass("receive into undersized buffer returned error (%d)", len); + else if (len == 1 && cbuf[0] == *msg1) + testPass("receive into undersized buffer truncated message"); + else + testFail("receive into undersized buffer returned %d", len); } extern "C" void @@ -62,27 +82,29 @@ receiver(void *arg) int expectmsg[4]; int len; int sender, msgNum; + int errors = 0; for (sender = 1 ; sender <= 4 ; sender++) expectmsg[sender-1] = 1; - for (;;) { + while (!testExit) { cbuf[0] = '\0'; len = q->receive(cbuf, sizeof cbuf); if ((sscanf(cbuf, "Sender %d -- %d", &sender, &msgNum) == 2) && (sender >= 1) && (sender <= 4)) { - if (expectmsg[sender-1] != msgNum) - printf("%s received %d '%.*s' -- expected %d\n", epicsThreadGetNameSelf(), len, len, cbuf, expectmsg[sender-1]); + if (expectmsg[sender-1] != msgNum) { + ++errors; + testDiag("%s received %d '%.*s' -- expected %d", epicsThreadGetNameSelf(), len, len, cbuf, expectmsg[sender-1]); + } expectmsg[sender-1] = msgNum + 1; epicsThreadSleep(0.001 * (randBelow(20))); } - else { - for (sender = 1 ; sender <= 4 ; sender++) { - if (expectmsg[sender-1] > 1) - printf("Sender %d -- %d messages\n", sender, expectmsg[sender-1]-1); - } - } } + for (sender = 1 ; sender <= 4 ; sender++) { + if (expectmsg[sender-1] > 1) + testDiag("Sender %d -- %d messages", sender, expectmsg[sender-1]-1); + } + testOk1(errors == 0); } extern "C" void @@ -93,7 +115,7 @@ sender(void *arg) int len; int i = 0; - for (;;) { + while (!testExit) { len = sprintf(cbuf, "%s -- %d.", epicsThreadGetNameSelf(), ++i); while (q->trySend((void *)cbuf, len) < 0) epicsThreadSleep(0.005 * (randBelow(5))); @@ -101,8 +123,9 @@ sender(void *arg) } } -extern "C" void epicsMessageQueueTest(void *parm) +extern "C" void messageQueueTest(void *parm) { + epicsEventId *pfinished = (epicsEventId *) parm; unsigned int i; char cbuf[80]; int len; @@ -112,143 +135,141 @@ extern "C" void epicsMessageQueueTest(void *parm) epicsMessageQueue *q1 = new epicsMessageQueue(4, 20); - printf ("Simple single-thread tests.\n"); + testDiag("Simple single-thread tests:"); i = 0; used = 0; - assert(q1->pending() == 0); + testOk1(q1->pending() == 0); while (q1->trySend((void *)msg1, i ) == 0) { i++; - assert(q1->pending() == i); - printf("Should have %d pending -- ", ++used); - q1->show(); + testOk(q1->pending() == i, "q1->pending() == %d", i); } - assert(q1->pending() == 4); + testOk1(q1->pending() == 4); want = 0; len = q1->receive(cbuf, sizeof cbuf); - assert(q1->pending() == 3); - if ((len != want) || (strncmp(msg1, cbuf, len) != 0)) - printf("wanted:%d '%.*s' got:%d '%.*s'\n", want, want, msg1, len, len, cbuf); + testOk1(q1->pending() == 3); + if (!testOk1((len == want) && (strncmp(msg1, cbuf, len) == 0))) + testDiag("wanted:%d '%.*s' got:%d '%.*s'", want, want, msg1, len, len, cbuf); want++; len = q1->receive(cbuf, sizeof cbuf); - assert(q1->pending() == 2); - if ((len != want) || (strncmp(msg1, cbuf, len) != 0)) - printf("wanted:%d '%.*s' got:%d '%.*s'\n", want, want, msg1, len, len, cbuf); + testOk1(q1->pending() == 2); + if (!testOk1((len == want) && (strncmp(msg1, cbuf, len) == 0))) + testDiag("wanted:%d '%.*s' got:%d '%.*s'", want, want, msg1, len, len, cbuf); q1->trySend((void *)msg1, i++); want++; len = q1->receive(cbuf, sizeof cbuf); - assert(q1->pending() == 2); - if ((len != want) || (strncmp(msg1, cbuf, len) != 0)) - printf("wanted:%d '%.*s' got:%d '%.*s'\n", want, want, msg1, len, len, cbuf); + testOk1(q1->pending() == 2); + if (!testOk1((len == want) && (strncmp(msg1, cbuf, len) == 0))) + testDiag("wanted:%d '%.*s' got:%d '%.*s'", want, want, msg1, len, len, cbuf); q1->trySend((void *)msg1, i++); - assert(q1->pending() == 3); + testOk1(q1->pending() == 3); i = 3; while ((len = q1->receive(cbuf, sizeof cbuf, 1.0)) >= 0) { - assert(q1->pending() == --i); + --i; + testOk(q1->pending() == i, "q1->pending() == %d", i); want++; - if ((len != want) || (strncmp(msg1, cbuf, len) != 0)) - printf("wanted:%d '%.*s' got:%d '%.*s'\n", want, want, msg1, len, len, cbuf); + if (!testOk1((len == want) & (strncmp(msg1, cbuf, len) == 0))) + testDiag("wanted:%d '%.*s' got:%d '%.*s'", want, want, msg1, len, len, cbuf); } - assert(q1->pending() == 0); + testOk1(q1->pending() == 0); - printf ("Test sender timeout.\n"); + testDiag("Test sender timeout:"); i = 0; used = 0; - assert(q1->pending() == 0); + testOk1(q1->pending() == 0); while (q1->send((void *)msg1, i, 1.0 ) == 0) { i++; - assert(q1->pending() == i); - printf("Should have %d pending -- ", ++used); - q1->show(); + testOk(q1->pending() == i, "q1->pending() == %d", i); } - assert(q1->pending() == 4); + testOk1(q1->pending() == 4); want = 0; len = q1->receive(cbuf, sizeof cbuf); - assert(q1->pending() == 3); - if ((len != want) || (strncmp(msg1, cbuf, len) != 0)) - printf("wanted:%d '%.*s' got:%d '%.*s'\n", want, want, msg1, len, len, cbuf); + testOk1(q1->pending() == 3); + if (!testOk1((len == want) && (strncmp(msg1, cbuf, len) == 0))) + testDiag("wanted:%d '%.*s' got:%d '%.*s'", want, want, msg1, len, len, cbuf); want++; len = q1->receive(cbuf, sizeof cbuf); - assert(q1->pending() == 2); - if ((len != want) || (strncmp(msg1, cbuf, len) != 0)) - printf("wanted:%d '%.*s' got:%d '%.*s'\n", want, want, msg1, len, len, cbuf); + testOk1(q1->pending() == 2); + if (!testOk1((len == want) && (strncmp(msg1, cbuf, len) == 0))) + testDiag("wanted:%d '%.*s' got:%d '%.*s'", want, want, msg1, len, len, cbuf); q1->send((void *)msg1, i++, 1.0); want++; len = q1->receive(cbuf, sizeof cbuf); - assert(q1->pending() == 2); - if ((len != want) || (strncmp(msg1, cbuf, len) != 0)) - printf("wanted:%d '%.*s' got:%d '%.*s'\n", want, want, msg1, len, len, cbuf); + testOk1(q1->pending() == 2); + if (!testOk1((len == want) && (strncmp(msg1, cbuf, len) == 0))) + testDiag("wanted:%d '%.*s' got:%d '%.*s'", want, want, msg1, len, len, cbuf); q1->send((void *)msg1, i++, 1.0); - assert(q1->pending() == 3); + testOk1(q1->pending() == 3); i = 3; while ((len = q1->receive(cbuf, sizeof cbuf, 1.0)) >= 0) { - assert(q1->pending() == --i); + --i; + testOk(q1->pending() == i, "q1->pending() == %d", i); want++; - if ((len != want) || (strncmp(msg1, cbuf, len) != 0)) - printf("wanted:%d '%.*s' got:%d '%.*s'\n", want, want, msg1, len, len, cbuf); + if (!testOk1((len == want) && (strncmp(msg1, cbuf, len) == 0))) + testDiag("wanted:%d '%.*s' got:%d '%.*s'", want, want, msg1, len, len, cbuf); } - assert(q1->pending() == 0); + testOk1(q1->pending() == 0); - printf ("Test receiver with timeout.\n"); + testDiag("Test receiver with timeout:"); for (i = 0 ; i < 4 ; i++) - assert (q1->send((void *)msg1, i, 1.0) == 0); - assert(q1->pending() == 4); + testOk1 (q1->send((void *)msg1, i, 1.0) == 0); + testOk1(q1->pending() == 4); for (i = 0 ; i < 4 ; i++) - assert (q1->receive((void *)cbuf, sizeof cbuf, 1.0) == (int)i); - assert(q1->pending() == 0); - assert (q1->receive((void *)cbuf, sizeof cbuf, 1.0) < 0); - assert(q1->pending() == 0); + testOk(q1->receive((void *)cbuf, sizeof cbuf, 1.0) == (int)i, + "q1->receive(...) == %d", i); + testOk1(q1->pending() == 0); + testOk1(q1->receive((void *)cbuf, sizeof cbuf, 1.0) < 0); + testOk1(q1->pending() == 0); - printf("Single receiver with invalid size, single sender tests.\n"); + testDiag("Single receiver with invalid size, single sender tests:"); epicsThreadCreate("Bad Receiver", epicsThreadPriorityMedium, epicsThreadGetStackSize(epicsThreadStackMedium), badReceiver, q1); - epicsThreadSleep(5.0); - assert (q1->send((void *)msg1, 10) == 0); /* Send with waiting receiver */ + epicsThreadSleep(1.0); + testOk(q1->send((void *)msg1, 10) == 0, "Send with waiting receiver"); + epicsThreadSleep(2.0); + testOk(q1->send((void *)msg1, 10) == 0, "Send with no receiver"); epicsThreadSleep(2.0); - assert (q1->send((void *)msg1, 10) == 0); /* Send with no receiver */ - epicsThreadSleep(10.0); - printf("Single receiver, single sender tests.\n"); + testDiag("Single receiver, single sender tests:"); epicsThreadSetPriority(epicsThreadGetIdSelf(), epicsThreadPriorityHigh); epicsThreadCreate("Receiver one", epicsThreadPriorityMedium, epicsThreadGetStackSize(epicsThreadStackMedium), receiver, q1); for (pass = 1 ; pass <= 3 ; pass++) { - switch (pass) { - case 1: - printf ("Systems with priority-based scheduler should send only\n" - "4 or 5 messages (sender priority > receiver priority).\n"); - break; - case 2: - printf ("Systems with strict priority-based scheduler should send\n" - "10 messages (sender priority < receiver priority).\n"); - break; - case 3: - printf ("All systems should send 10 messages (sender pauses\n" - "after sending each message).\n"); - break; - } - epicsThreadSleep(1.0); for (i = 0 ; i < 10 ; i++) { if (q1->trySend((void *)msg1, i) < 0) break; if (pass >= 3) epicsThreadSleep(0.5); } - printf ("Sent %d messages.\n", i); - epicsThreadSetPriority(epicsThreadGetIdSelf(), epicsThreadPriorityLow); + switch (pass) { + case 1: + if (i<6) + testDiag(" priority-based scheduler, sent %d messages", i); + epicsThreadSetPriority(epicsThreadGetIdSelf(), epicsThreadPriorityLow); + break; + case 2: + if (i<10) + testDiag(" scheduler not strict priority, sent %d messages", i); + else + testDiag(" strict priority scheduler, sent 10 messages"); + break; + case 3: + testOk(i == 10, "%d of 10 messages sent with sender pauses", i); + break; + } epicsThreadSleep(1.0); } /* * Single receiver, multiple sender tests */ - printf("Single receiver, multiple sender tests.\n"); - printf("The following test takes 5 minutes to run and has succeeded\nif nothing appears between here....\n"); + testDiag("Single receiver, multiple sender tests:"); + testDiag("This test takes 5 minutes..."); epicsThreadCreate("Sender 1", epicsThreadPriorityLow, epicsThreadGetStackSize(epicsThreadStackMedium), sender, q1); epicsThreadCreate("Sender 2", epicsThreadPriorityMedium, epicsThreadGetStackSize(epicsThreadStackMedium), sender, q1); epicsThreadCreate("Sender 3", epicsThreadPriorityHigh, epicsThreadGetStackSize(epicsThreadStackMedium), sender, q1); @@ -256,10 +277,22 @@ extern "C" void epicsMessageQueueTest(void *parm) epicsThreadSleep(300.0); - /* - * Force out summaries - */ - printf("......and here.\n"); - q1->trySend((void *)msg1, 0); + testExit = 1; epicsThreadSleep(1.0); + epicsEventSignal(*pfinished); +} + +MAIN(epicsMessageQueueTest) +{ + testPlan(58); + + epicsEventId finished = epicsEventMustCreate(epicsEventEmpty); + + epicsThreadCreate("messageQueueTest", epicsThreadPriorityMedium, + epicsThreadGetStackSize(epicsThreadStackMedium), + messageQueueTest, (void *) &finished); + + epicsEventWait(finished); + + return testDone(); } diff --git a/src/libCom/test/epicsMessageQueueTestMain.cpp b/src/libCom/test/epicsMessageQueueTestMain.cpp deleted file mode 100644 index fcaa9917f..000000000 --- a/src/libCom/test/epicsMessageQueueTestMain.cpp +++ /dev/null @@ -1,29 +0,0 @@ -/*************************************************************************\ -* Copyright (c) 2002 The University of Chicago, as Operator of Argonne -* National Laboratory. -* Copyright (c) 2002 The Regents of the University of California, as -* Operator of Los Alamos National Laboratory. -* EPICS BASE Versions 3.13.7 -* and higher are distributed subject to a Software License Agreement found -* in file LICENSE that is included with this distribution. -\*************************************************************************/ -/* - * $Id$ - * - * Author W. Eric Norum - * norume@aps.anl.gov - * 630 252 4793 - */ - -#include "epicsThread.h" - -extern "C" void epicsMessageQueueTest ( void *); - -int main ( int /* argc */, char /* *argv[] */ ) -{ - epicsThreadCreate("messageQueueTest",epicsThreadPriorityMedium, - epicsThreadGetStackSize(epicsThreadStackMedium), - epicsMessageQueueTest,0); - epicsThreadExitMain(); - return 0; -} diff --git a/src/libCom/test/epicsMutexTest.cpp b/src/libCom/test/epicsMutexTest.cpp index 9a29b34d1..76e4c81a9 100644 --- a/src/libCom/test/epicsMutexTest.cpp +++ b/src/libCom/test/epicsMutexTest.cpp @@ -1,11 +1,10 @@ /*************************************************************************\ -* Copyright (c) 2002 The University of Chicago, as Operator of Argonne +* Copyright (c) 2006 UChicago Argonne LLC, as Operator of Argonne * National Laboratory. * Copyright (c) 2002 The Regents of the University of California, as * Operator of Los Alamos National Laboratory. -* EPICS BASE Versions 3.13.7 -* and higher are distributed subject to a Software License Agreement found -* in file LICENSE that is included with this distribution. +* EPICS BASE is distributed subject to a Software License Agreement found +* in file LICENSE that is included with this distribution. \*************************************************************************/ /* epicsMutexTest.c */ @@ -27,6 +26,8 @@ #include "epicsMutex.h" #include "epicsEvent.h" #include "errlog.h" +#include "epicsUnitTest.h" +#include "testMain.h" typedef struct info { int threadnum; @@ -34,29 +35,21 @@ typedef struct info { int quit; }info; -extern "C" void mutexThread ( void * arg ) +extern "C" void mutexThread(void * arg) { info *pinfo = (info *)arg; - time_t tp; - printf("mutexThread %d starting time %ld\n",pinfo->threadnum,time(&tp)); - while(1) { - epicsMutexLockStatus status; - if(pinfo->quit) { - printf("mutexThread %d returning time %ld\n", - pinfo->threadnum,time(&tp)); - return; - } - status = epicsMutexLock(pinfo->mutex); - if(status!=epicsMutexLockOK) { - printf("task %d epicsMutexLock returned %d time %ld\n", - pinfo->threadnum,(int)status,time(&tp)); - } - printf("mutexThread %d epicsMutexLock time %ld\n", - pinfo->threadnum,time(&tp)); + testDiag("mutexThread %d starting", pinfo->threadnum); + while (!pinfo->quit) { + epicsMutexLockStatus status = epicsMutexLock(pinfo->mutex); + testOk(status == epicsMutexLockOK, + "mutexThread %d epicsMutexLock returned %d", + pinfo->threadnum, (int)status); epicsThreadSleep(.1); epicsMutexUnlock(pinfo->mutex); epicsThreadSleep(.9); } + testDiag("mutexThread %d exiting", pinfo->threadnum); + return; } inline void lockPair ( epicsMutex & mutex ) @@ -183,7 +176,7 @@ void epicsMutexPerformance () double delay = epicsTime::getCurrent () - begin; delay /= N * 100u; // convert to delay per lock pair delay *= 1e6; // convert to micro seconds - printf ( "One lock pair completes in %f micro sec\n", delay ); + testDiag("lock()*1/unlock()*1 takes %f microseconds", delay); // test a two times recursive lock pair begin = epicsTime::getCurrent (); @@ -193,7 +186,7 @@ void epicsMutexPerformance () delay = epicsTime::getCurrent () - begin; delay /= N * 100u; // convert to delay per lock pair delay *= 1e6; // convert to micro seconds - printf ( "One double recursive lock pair completes in %f micro sec\n", delay ); + testDiag("lock()*2/unlock()*2 takes %f microseconds", delay); // test a four times recursive lock pair begin = epicsTime::getCurrent (); @@ -203,7 +196,7 @@ void epicsMutexPerformance () delay = epicsTime::getCurrent () - begin; delay /= N * 100u; // convert to delay per lock pair delay *= 1e6; // convert to micro seconds - printf ( "One quad recursive lock pair completes in %f micro sec\n", delay ); + testDiag("lock()*4/unlock()*4 takes %f microseconds", delay); } struct verifyTryLock { @@ -215,23 +208,19 @@ extern "C" void verifyTryLockThread ( void *pArg ) { struct verifyTryLock *pVerify = ( struct verifyTryLock * ) pArg; - epicsMutexLockStatus status; - status = epicsMutexTryLock ( pVerify->mutex ); - assert ( status == epicsMutexLockTimeout ); + testOk1(epicsMutexTryLock(pVerify->mutex) == epicsMutexLockTimeout); epicsEventSignal ( pVerify->done ); } void verifyTryLock () { struct verifyTryLock verify; - epicsMutexLockStatus status; verify.mutex = epicsMutexMustCreate (); verify.done = epicsEventMustCreate ( epicsEventEmpty ); - status = epicsMutexTryLock ( verify.mutex ); - assert ( status == epicsMutexLockOK ); + testOk1(epicsMutexTryLock(verify.mutex) == epicsMutexLockOK); epicsThreadCreate ( "verifyTryLockThread", 40, epicsThreadGetStackSize(epicsThreadStackSmall), @@ -244,8 +233,9 @@ void verifyTryLock () epicsEventDestroy ( verify.done ); } -extern "C" void epicsMutexTest(int nthreads,int verbose) +MAIN(epicsMutexTest) { + const int nthreads = 3; unsigned int stackSize; epicsThreadId *id; int i; @@ -254,31 +244,19 @@ extern "C" void epicsMutexTest(int nthreads,int verbose) info **pinfo; epicsMutexId mutex; int status; - time_t tp; - int errVerboseSave = errVerbose; - epicsMutexPerformance (); + testPlan(19); + verifyTryLock (); - errVerbose = verbose; mutex = epicsMutexMustCreate(); - printf("calling epicsMutexLock(mutex) time %ld\n",time(&tp)); status = epicsMutexLock(mutex); - if(status) printf("status %d\n",status); - printf("calling epicsMutexTryLock(mutex) time %ld\n",time(&tp)); + testOk(status == 0, "epicsMutexLock returned %d", status); status = epicsMutexTryLock(mutex); - if(status) printf("status %d\n",status); - epicsMutexShow(mutex,1); - printf("calling epicsMutexUnlock() time %ld\n",time(&tp)); + testOk(status == 0, "epicsMutexTryLock returned %d", status); epicsMutexUnlock(mutex); - printf("calling epicsMutexUnlock() time %ld\n",time(&tp)); epicsMutexUnlock(mutex); - epicsMutexShow(mutex,1); - if(nthreads<=0) { - errVerbose = errVerboseSave; - return; - } id = (epicsThreadId *)calloc(nthreads,sizeof(epicsThreadId)); name = (char **)calloc(nthreads,sizeof(char *)); arg = (void **)calloc(nthreads,sizeof(void *)); @@ -294,14 +272,14 @@ extern "C" void epicsMutexTest(int nthreads,int verbose) id[i] = epicsThreadCreate(name[i],40,stackSize, mutexThread, arg[i]); - printf("semTest created mutexThread %d id %p time %ld\n", - i, id[i],time(&tp)); } epicsThreadSleep(5.0); - printf("semTest setting quit time %ld\n",time(&tp)); for(i=0; iquit = 1; } epicsThreadSleep(2.0); - errVerbose = errVerboseSave; + + epicsMutexPerformance (); + + return testDone(); } diff --git a/src/libCom/test/epicsMutexTestMain.cpp b/src/libCom/test/epicsMutexTestMain.cpp deleted file mode 100644 index f68a995da..000000000 --- a/src/libCom/test/epicsMutexTestMain.cpp +++ /dev/null @@ -1,49 +0,0 @@ -/*************************************************************************\ -* Copyright (c) 2002 The University of Chicago, as Operator of Argonne -* National Laboratory. -* Copyright (c) 2002 The Regents of the University of California, as -* Operator of Los Alamos National Laboratory. -* EPICS BASE Versions 3.13.7 -* and higher are distributed subject to a Software License Agreement found -* in file LICENSE that is included with this distribution. -\*************************************************************************/ -/* epicsMutexTestMain.c */ - -/* Author: Marty Kraimer Date: 26JAN2000 */ - -#include -#include -#include -#include -#include -#include - -#include "epicsThread.h" -extern "C" void epicsMutexTest(int nthreads,int errVerbose); - - -int main(int argc,char *argv[]) -{ - int nthreads = 2; - int errVerboseIn = 0; - - if(argc>1) { - if(isdigit(*argv[1])) { - sscanf(argv[1],"%d",&nthreads); - printf("nthreads %d\n",nthreads); - } else { - printf("Illegal argument %s\n",argv[1]); - } - } - if(argc>2) { - if(isdigit(*argv[2])) { - sscanf(argv[2],"%d",&errVerboseIn); - printf("errVerbose %d\n",errVerboseIn); - } else { - printf("Illegal argument %s\n",argv[1]); - } - } - epicsMutexTest(nthreads,errVerboseIn); - printf("main terminating\n"); - return(0); -} diff --git a/src/libCom/test/epicsOkToBlockTest.cpp b/src/libCom/test/epicsOkToBlockTest.cpp deleted file mode 100644 index bae09dcc4..000000000 --- a/src/libCom/test/epicsOkToBlockTest.cpp +++ /dev/null @@ -1,60 +0,0 @@ -/*************************************************************************\ -* Copyright (c) 2002 The University of Chicago, as Operator of Argonne -* National Laboratory. -* Copyright (c) 2002 The Regents of the University of California, as -* Operator of Los Alamos National Laboratory. -* EPICS BASE Versions 3.13.7 -* and higher are distributed subject to a Software License Agreement found -* in file LICENSE that is included with this distribution. -\*************************************************************************/ -/* epicsOkToBlockTest.cpp */ - -/* Author: Marty Kraimer Date: 09JUL2004*/ - -#include -#include -#include -#include -#include -#include - -#include "epicsThread.h" - - -typedef struct info { - int isOkToBlock; -}info; - -extern "C" { - -static void thread(void *arg) -{ - info *pinfo = (info *)arg; - int isOkToBlock; - - printf("thread %s isOkToBlock %d\n", - epicsThreadGetNameSelf(),pinfo->isOkToBlock); - epicsThreadSetOkToBlock(pinfo->isOkToBlock); - epicsThreadSleep(1.0); - isOkToBlock = epicsThreadIsOkToBlock(); - printf("thread %s epicsThreadIsOkToBlock %d\n", - epicsThreadGetNameSelf(),isOkToBlock); - epicsThreadSleep(.1); - free(pinfo); -} -void epicsOkToBlockTest(void) -{ - unsigned int stackSize; - info *pinfoA; - info *pinfoB; - - stackSize = epicsThreadGetStackSize(epicsThreadStackSmall); - pinfoA = (info *)calloc(1,sizeof(info)); - pinfoA->isOkToBlock = 0; - epicsThreadCreate("threadA",50,stackSize,thread,pinfoA); - pinfoB = (info *)calloc(1,sizeof(info)); - pinfoB->isOkToBlock = 1; - epicsThreadCreate("threadB",50,stackSize,thread,pinfoB); - epicsThreadSleep(2.0); -} -} diff --git a/src/libCom/test/epicsOkToBlockTestMain.cpp b/src/libCom/test/epicsOkToBlockTestMain.cpp deleted file mode 100644 index c9105f8c5..000000000 --- a/src/libCom/test/epicsOkToBlockTestMain.cpp +++ /dev/null @@ -1,29 +0,0 @@ -/*************************************************************************\ -* Copyright (c) 2002 The University of Chicago, as Operator of Argonne -* National Laboratory. -* Copyright (c) 2002 The Regents of the University of California, as -* Operator of Los Alamos National Laboratory. -* EPICS BASE Versions 3.13.7 -* and higher are distributed subject to a Software License Agreement found -* in file LICENSE that is included with this distribution. -\*************************************************************************/ -/* epicsOkToBlockTestMain.cpp */ - -/* Author: Marty Kraimer Date: 26JAN2000 */ - -#include -#include -#include -#include -#include -#include - -extern "C" void epicsOkToBlockTest(void); - - -int main(int /*argc*/, char * /*argv[]*/ ) -{ - epicsOkToBlockTest(); - printf("main terminating\n"); - return(0); -} diff --git a/src/libCom/test/epicsRunLibComTests.c b/src/libCom/test/epicsRunLibComTests.c index 4362944cc..7fa0391aa 100644 --- a/src/libCom/test/epicsRunLibComTests.c +++ b/src/libCom/test/epicsRunLibComTests.c @@ -15,110 +15,105 @@ #include #include -void threadTest(int ntasks,int verbose); -void epicsTimerTest(); -int epicsAlgorithm(int /*argc*/, char* /*argv[]*/); -int epicsCalcTest(int /*argc*/, char* /*argv[]*/); -void epicsEventTest(int nthreads,int verbose); -int epicsExceptionTest(); -int epicsMathTest(); -void epicsMessageQueueTest(void *parm); -void epicsMutexTest(int nthreads,int verbose); -void epicsOkToBlockTest(void); -int epicsStdioTest (const char *report); -int epicsStringTest(); -void epicsThreadPriorityTest(void *); -void epicsThreadPrivateTest(); +int epicsThreadTest(void); +int epicsTimerTest(void); +int epicsAlgorithm(void); +int epicsCalcTest(void); +int epicsEventTest(void); +int epicsExceptionTest(void); +int epicsMathTest(void); +int epicsMessageQueueTest(void); +int epicsMutexTest(void); +int epicsStdioTest(void); +int epicsStringTest(void); +int epicsThreadPriorityTest(void); +int epicsThreadPrivateTest(void); int epicsTimeTest(void); int macEnvExpandTest(void); -void ringPointerTest(); -void blockingSockTest (void); -void epicsExitTest(void); +int ringPointerTest(void); +int blockingSockTest(void); +int epicsExitTest(void); void epicsRunLibComTests(void) { - /* - * Thread startup sets some internal variables so do it first - */ + /* + * Thread startup sets some internal variables so do it first + */ printf("\n****** Thread Test *****\n"); - threadTest (2, 0); - epicsThreadSleep (1.0); + epicsThreadTest (); + epicsThreadSleep (1.0); - /* - * Timer tests get confused if run after some of the other tests - */ + /* + * Timer tests get confused if run after some of the other tests + */ printf("\n****** Timer Test *****\n"); epicsTimerTest (); - epicsThreadSleep (1.0); + epicsThreadSleep (1.0); printf("\n****** Algorithm Test *****\n"); - epicsAlgorithm (0, NULL); - epicsThreadSleep (1.0); + epicsAlgorithm (); + epicsThreadSleep (1.0); printf("\n****** Calculation Test *****\n"); - epicsCalcTest(0, NULL); - epicsThreadSleep (1.0); + epicsCalcTest(); + epicsThreadSleep (1.0); printf("\n****** Event Test *****\n"); - epicsEventTest (2,0); - epicsThreadSleep (1.0); + epicsEventTest (); + epicsThreadSleep (1.0); printf("\n****** Exception Test *****\n"); - epicsExceptionTest (); - epicsThreadSleep (1.0); + epicsExceptionTest (); + epicsThreadSleep (1.0); printf("\n****** Math Test *****\n"); epicsMathTest (); - epicsThreadSleep (1.0); + epicsThreadSleep (1.0); printf("\n****** Message Queue Test *****\n"); - epicsMessageQueueTest (NULL); - epicsThreadSleep (1.0); + epicsMessageQueueTest (); + epicsThreadSleep (1.0); printf("\n****** Mutex Test *****\n"); - epicsMutexTest (2, 0); - epicsThreadSleep (1.0); - - printf("\n****** OK to Block Test *****\n"); - epicsOkToBlockTest (); - epicsThreadSleep (1.0); + epicsMutexTest (); + epicsThreadSleep (1.0); printf("\n****** Stdio Test *****\n"); - epicsStdioTest ("report"); - epicsThreadSleep (1.0); + epicsStdioTest (); + epicsThreadSleep (1.0); printf("\n****** String Test *****\n"); epicsStringTest (); - epicsThreadSleep (1.0); + epicsThreadSleep (1.0); printf("\n****** Thread Priority Test *****\n"); - epicsThreadPriorityTest (NULL); - epicsThreadSleep (1.0); + epicsThreadPriorityTest (); + epicsThreadSleep (1.0); printf("\n****** Thread Private Test *****\n"); - epicsThreadPrivateTest (NULL); - epicsThreadSleep (1.0); + epicsThreadPrivateTest (); + epicsThreadSleep (1.0); printf("\n****** Time Test *****\n"); epicsTimeTest (); - epicsThreadSleep (1.0); + epicsThreadSleep (1.0); printf("\n****** Macro Environment Variable Expansion Test *****\n"); macEnvExpandTest (); - epicsThreadSleep (1.0); + epicsThreadSleep (1.0); printf("\n****** Ring Pointer Test *****\n"); ringPointerTest (); - epicsThreadSleep (1.0); + epicsThreadSleep (1.0); printf("\n****** Check socket behaviour *****\n"); - blockingSockTest(); - epicsThreadSleep (1.0); + blockingSockTest(); + epicsThreadSleep (1.0); - /* - * Must come last - */ + /* + * Must come last + */ printf("\n****** EpicsExit Test *****\n"); - epicsExitTest(); + epicsExitTest(); /* Never returns */ } diff --git a/src/libCom/test/epicsStdioTest.c b/src/libCom/test/epicsStdioTest.c index 0fda2526c..2ed810c5b 100644 --- a/src/libCom/test/epicsStdioTest.c +++ b/src/libCom/test/epicsStdioTest.c @@ -1,11 +1,10 @@ /*************************************************************************\ -* Copyright (c) 2002 The University of Chicago, as Operator of Argonne +* Copyright (c) 2006 UChicago Argonne LLC, as Operator of Argonne * National Laboratory. * Copyright (c) 2002 The Regents of the University of California, as * Operator of Los Alamos National Laboratory. -* EPICS BASE Versions 3.13.7 -* and higher are distributed subject to a Software License Agreement found -* in file LICENSE that is included with this distribution. +* EPICS BASE is distributed subject to a Software License Agreement found +* in file LICENSE that is included with this distribution. \*************************************************************************/ /* epicsStdioTest.c * @@ -24,6 +23,8 @@ #include "epicsStdio.h" #include "epicsStdioRedirect.h" #include "epicsUnitTest.h" +#include "testMain.h" + #define LINE_1 "# This is first line of sample report\n" #define LINE_2 "# This is second and last line of sample report\n" @@ -33,20 +34,21 @@ static void testEpicsSnprintf() { 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"; + const char *expected = "int 1234 float 1.23e+04 string OneTwoThreeFour"; char buffer[80]; int size, rtn; - int rlen = strlen(result)+1; + int rlen = strlen(expected)+1; strcpy(buffer, "AAAA"); - for (size = 1; size < strlen(result) + 5; ++size) { + for (size = 1; size < strlen(expected) + 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"); - } + testOk(rtn == rlen-1, "epicsSnprintf(size=%d) = %d", size, rtn); + testOk(strncmp(buffer, expected, size - 1) == 0, + "buffer = '%s'", buffer); + rtn = strlen(buffer); + testOk(rtn == (size < rlen ? size : rlen) - 1, + "length = %d", rtn); } } @@ -54,67 +56,63 @@ void testStdoutRedir (const char *report) { FILE *realStdout = stdout; FILE *stream = 0; + char linebuf[80]; + size_t buflen = sizeof linebuf; testOk1(epicsGetStdout() == stdout); - if(report && strlen(report)>0) { - 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); - testOk1(stdout == stream); - } - } + errno = 0; + if (!testOk1((stream = fopen(report, "w")) != NULL)) { + testDiag("'%s' could not be opened for writing: %s", + report, strerror(errno)); + testSkip(11, "Can't create stream file"); + return; } + + epicsSetThreadStdout(stream); + testOk1(stdout == stream); + printf(LINE_1); printf(LINE_2); - errno = 0; - if(stream) { - epicsSetThreadStdout(0); - if(fclose(stream)) { - fprintf(stderr,"fclose failed %s\n",strerror(errno)); - } - } else { - fflush(stdout); - } + + epicsSetThreadStdout(0); testOk1(epicsGetStdout() == realStdout); testOk1(stdout == realStdout); - if ((stream = fopen(report, "r")) == NULL) { - fprintf(stderr, "Can't reopen report file: %s\n", strerror(errno)); + + errno = 0; + if (!testOk1(!fclose(stream))) + testDiag("fclose error: %s\n", strerror(errno)); + + if (!testOk1((stream = fopen(report, "r")) != NULL)) { + testDiag("'%s' could not be opened for reading: %s", + report, strerror(errno)); + testSkip(6, "Can't reopen stream file."); + return; } - else { - char linebuf[80]; - if (fgets(linebuf, sizeof linebuf, stream) == NULL) { - fprintf(stderr, "Can't read first line of report file: %s\n", strerror(errno)); - } - else if (!testOk(strcmp(linebuf, LINE_1) == 0, "First line")) { } - else if (fgets(linebuf, sizeof linebuf, stream) == NULL) { - fprintf(stderr, "Can't read second line of report file: %s\n", strerror(errno)); - } - else if (!testOk(strcmp(linebuf, LINE_2) == 0, "Second line")) { } - else if (fgets(linebuf, sizeof linebuf, stream) != NULL) { - fprintf(stderr, "Read too much from report file.\n"); - } - else { - } - if(fclose(stream)) { - fprintf(stderr,"fclose failed %s\n",strerror(errno)); - } + + if (!testOk1(fgets(linebuf, buflen, stream) != NULL)) { + testDiag("File read error: %s", strerror(errno)); + testSkip(5, "Read failed."); + fclose(stream); + return; } + testOk(strcmp(linebuf, LINE_1) == 0, "First line correct"); + + if (!testOk1(fgets(linebuf, buflen, stream) != NULL)) { + testDiag("File read error: %s", strerror(errno)); + testSkip(1, "No line to compare."); + } else + testOk(strcmp(linebuf, LINE_2) == 0, "Second line"); + + testOk(!fgets(linebuf, buflen, stream), "File ends"); + + if (!testOk1(!fclose(stream))) + testDiag("fclose error: %s\n", strerror(errno)); } -int epicsStdioTest (const char *report) +MAIN(epicsStdioTest) { - testPlan(0); + testPlan(163); testEpicsSnprintf(); testStdoutRedir("report"); return testDone(); diff --git a/src/libCom/test/epicsStdioTestMain.cpp b/src/libCom/test/epicsStdioTestMain.cpp deleted file mode 100644 index 0e816207a..000000000 --- a/src/libCom/test/epicsStdioTestMain.cpp +++ /dev/null @@ -1,26 +0,0 @@ -/*************************************************************************\ -* Copyright (c) 2002 The University of Chicago, as Operator of Argonne -* National Laboratory. -* Copyright (c) 2002 The Regents of the University of California, as -* Operator of Los Alamos National Laboratory. -* EPICS BASE Versions 3.13.7 -* and higher are distributed subject to a Software License Agreement found -* in file LICENSE that is included with this distribution. -\*************************************************************************/ -/* epicsStdioTestMain.cpp - * - * Author Marty Kraimer - */ - -extern "C" { -int epicsStdioTest (const char *report); -} - -int main ( int argc, char *argv[] ) -{ - const char *report = ""; - if(argc>1) report = argv[1]; - - epicsStdioTest (report); - return 0; -} diff --git a/src/libCom/test/epicsStringTest.c b/src/libCom/test/epicsStringTest.c index 6d900a0af..e75ab33de 100644 --- a/src/libCom/test/epicsStringTest.c +++ b/src/libCom/test/epicsStringTest.c @@ -1,11 +1,10 @@ /*************************************************************************\ -* Copyright (c) 2002 The University of Chicago, as Operator of Argonne +* Copyright (c) 2006 UChicago Argonne LLC, as Operator of Argonne * National Laboratory. * Copyright (c) 2002 The Regents of the University of California, as * Operator of Los Alamos National Laboratory. -* EPICS BASE Versions 3.13.7 -* and higher are distributed subject to a Software License Agreement found -* in file LICENSE that is included with this distribution. +* EPICS BASE is distributed subject to a Software License Agreement found +* in file LICENSE that is included with this distribution. \*************************************************************************/ /* $Id$ * @@ -16,8 +15,9 @@ #include "epicsUnitTest.h" #include "epicsString.h" +#include "testMain.h" -int epicsStringTest() +MAIN(epicsStringTest) { testPlan(21); diff --git a/src/libCom/test/epicsStringTestMain.cpp b/src/libCom/test/epicsStringTestMain.cpp deleted file mode 100644 index e783e6c89..000000000 --- a/src/libCom/test/epicsStringTestMain.cpp +++ /dev/null @@ -1,23 +0,0 @@ -/*************************************************************************\ -* Copyright (c) 2002 The University of Chicago, as Operator of Argonne -* National Laboratory. -* Copyright (c) 2002 The Regents of the University of California, as -* Operator of Los Alamos National Laboratory. -* EPICS BASE Versions 3.13.7 -* and higher are distributed subject to a Software License Agreement found -* in file LICENSE that is included with this distribution. -\*************************************************************************/ -/* epicsStringTestMain.cpp - * - * Author Marty Kraimer - */ - -extern "C" { -int epicsStringTest ( void ); -} - -int main ( int , char *[] ) -{ - epicsStringTest (); - return 0; -} diff --git a/src/libCom/test/epicsThreadPerform.cpp b/src/libCom/test/epicsThreadPerform.cpp new file mode 100644 index 000000000..43fc12f8c --- /dev/null +++ b/src/libCom/test/epicsThreadPerform.cpp @@ -0,0 +1,180 @@ +/*************************************************************************\ +* Copyright (c) 2006 UChicago Argonne LLC, as Operator of Argonne +* National Laboratory. +* Copyright (c) 2002 The Regents of the University of California, as +* Operator of Los Alamos National Laboratory. +* EPICS BASE is distributed subject to a Software License Agreement found +* in file LICENSE that is included with this distribution. +\*************************************************************************/ +/* epicsThreadPerform.cpp */ + +/* sleep accuracy and sleep quantum tests by Jeff Hill */ +/* epicsThreadGetIdSelf performance by Jeff Hill */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "epicsThread.h" +#include "epicsTime.h" +#include "errlog.h" +#include "testMain.h" + +static void testPriority(const char *who) +{ + epicsThreadId id; + unsigned int oldPriority,newPriority; + + id = epicsThreadGetIdSelf(); + oldPriority = epicsThreadGetPriority(id); + epicsThreadSetPriority(id,epicsThreadPriorityMax); + newPriority = epicsThreadGetPriority(id); + epicsThreadSetPriority(id,oldPriority); + printf("testPriority %s\n id %p old %u new %u\n", + who,id,oldPriority,newPriority); +} + +extern "C" void testPriorityThread(void *arg) +{ + testPriority("thread"); +} + +static void epicsThreadPriorityTest() +{ + testPriority("main error expected from epicsThreadSetPriority"); + epicsThreadCreate("testPriorityThread",epicsThreadPriorityMedium, + epicsThreadGetStackSize(epicsThreadStackMedium),testPriorityThread,0); + epicsThreadSleep(0.5); +} + + +static double threadSleepMeasureDelayError ( const double & delay ) +{ + epicsTime beg = epicsTime::getCurrent(); + epicsThreadSleep ( delay ); + epicsTime end = epicsTime::getCurrent(); + double meas = end - beg; + double error = fabs ( delay - meas ); + return error; +} + +static double measureSleepQuantum ( + const unsigned iterations, const double testInterval ) +{ + double errorSum = 0.0; + printf ( "Estimating sleep quantum" ); + fflush ( stdout ); + for ( unsigned i = 0u; i < iterations; i++ ) { + // try to guarantee a uniform probability density function + // by intentionally burning some CPU until we are less + // likely to be aligned with the schedualing clock + double interval = rand (); + interval /= RAND_MAX; + interval *= testInterval; + epicsTime start = epicsTime::getCurrent (); + epicsTime current = start; + while ( current - start < interval ) { + current = epicsTime::getCurrent (); + } + errorSum += threadSleepMeasureDelayError ( testInterval ); + if ( i % ( iterations / 10 ) == 0 ) { + printf ( "." ); + fflush ( stdout ); + } + } + printf ( "done\n" ); + + // with a uniform probability density function the + // sleep delay error mean is one half of the quantum + double quantumEstimate = 2 * errorSum / iterations; + return quantumEstimate; +} + +static void threadSleepQuantumTest () +{ + const double quantum = epicsThreadSleepQuantum (); + + double quantumEstimate = measureSleepQuantum ( 10, 10 * quantum ); + quantumEstimate = measureSleepQuantum ( 100, 2 * quantumEstimate ); + + double quantumError = fabs ( quantumEstimate - quantum ) / quantum; + const char * pTol = 0; + if ( quantumError > 0.1 ) { + pTol = "10%"; + } + else if ( quantumError > 0.01 ) { + pTol = "1%"; + } + else if ( quantumError > 0.001 ) { + pTol = "0.1%"; + } + if ( pTol ) { + printf ( + "The epicsThreadSleepQuantum() call returns %f sec.\n", + quantum ); + printf ( + "This doesnt match the quantum estimate " + "of %f sec within %s.\n", + quantumEstimate, pTol ); + } +} + + +static void threadSleepTest () +{ + static const int iterations = 20; + const double quantum = epicsThreadSleepQuantum (); + double errorSum = threadSleepMeasureDelayError ( 0.0 ); + for ( int i = 0u; i < iterations; i++ ) { + double delay = ldexp ( 1.0 , -i ); + double error = + threadSleepMeasureDelayError ( delay ); + errorSum += error; + if ( error > quantum + quantum / 8.0 ) { + printf ( "epicsThreadSleep ( %10f ) delay err %10f sec\n", + delay, error ); + } + } + double averageError = errorSum / ( iterations + 1 ); + if ( averageError > quantum ) { + printf ( "Average sleep delay error was %f sec\n", averageError ); + } +} + +static void epicsThreadGetIdSelfPerfTest () +{ + static const unsigned N = 10000; + static const double microSecPerSec = 1e6; + epicsTime begin = epicsTime::getCurrent (); + for ( unsigned i = 0u; i < N; i++ ) { + epicsThreadGetIdSelf (); + epicsThreadGetIdSelf (); + epicsThreadGetIdSelf (); + epicsThreadGetIdSelf (); + epicsThreadGetIdSelf (); + + epicsThreadGetIdSelf (); + epicsThreadGetIdSelf (); + epicsThreadGetIdSelf (); + epicsThreadGetIdSelf (); + epicsThreadGetIdSelf (); + }; + epicsTime end = epicsTime::getCurrent (); + printf ( "It takes %f micro sec to call epicsThreadGetIdSelf ()\n", + microSecPerSec * ( end - begin ) / (10 * N) ); +} + + +MAIN(epicsThreadPerform) +{ + epicsThreadPriorityTest (); + threadSleepQuantumTest (); + threadSleepTest (); + epicsThreadGetIdSelfPerfTest (); + return 0; +} diff --git a/src/libCom/test/epicsThreadPriorityTest.cpp b/src/libCom/test/epicsThreadPriorityTest.cpp index 5cfae819f..4f5a82d9e 100644 --- a/src/libCom/test/epicsThreadPriorityTest.cpp +++ b/src/libCom/test/epicsThreadPriorityTest.cpp @@ -1,11 +1,10 @@ /*************************************************************************\ -* Copyright (c) 2002 The University of Chicago, as Operator of Argonne +* Copyright (c) 2006 UChicago Argonne LLC, as Operator of Argonne * National Laboratory. * Copyright (c) 2002 The Regents of the University of California, as * Operator of Los Alamos National Laboratory. -* EPICS BASE Versions 3.13.7 -* and higher are distributed subject to a Software License Agreement found -* in file LICENSE that is included with this distribution. +* EPICS BASE is distributed subject to a Software License Agreement found +* in file LICENSE that is included with this distribution. \*************************************************************************/ /* epicsdThreadPriorityTest.cpp */ @@ -22,6 +21,8 @@ #include "epicsThread.h" #include "epicsEvent.h" #include "epicsExit.h" +#include "epicsUnitTest.h" +#include "testMain.h" typedef struct info { @@ -37,65 +38,84 @@ static void client(void *arg) epicsThreadId idSelf = epicsThreadGetIdSelf(); int pass; - for(pass = 0 ; pass < 3 ; pass++) { + for (pass = 0 ; pass < 3 ; pass++) { epicsEventWaitStatus status; status = epicsEventWait(pinfo->waitForMaster); - if(status!=epicsEventWaitOK) { - printf("task %p epicsEventWait returned %d\n", idSelf,(int)status); - } + testOk(status == epicsEventWaitOK, + "task %p epicsEventWait returned %d", idSelf, status); + epicsThreadSleep(0.01); epicsEventSignal(pinfo->waitForClient); } } -extern "C" void epicsThreadPriorityTest(void *) +static void runThreadPriorityTest(void *arg) { - unsigned int stackSize; - info *pinfo; - epicsThreadId clientId; - epicsThreadId myId; - epicsEventWaitStatus status; + epicsEventId testComplete = (epicsEventId) arg; + unsigned int stackSize = epicsThreadGetStackSize(epicsThreadStackSmall); - myId = epicsThreadGetIdSelf(); - epicsThreadSetPriority(myId,50); - pinfo = (info *)calloc(1,sizeof(info)); + epicsThreadId myId = epicsThreadGetIdSelf(); + epicsThreadSetPriority(myId, 50); + + info *pinfo = (info *)calloc(1, sizeof(info)); pinfo->waitForMaster = epicsEventMustCreate(epicsEventEmpty); pinfo->waitForClient = epicsEventMustCreate(epicsEventEmpty); - stackSize = epicsThreadGetStackSize(epicsThreadStackSmall); - clientId = epicsThreadCreate("client",50,stackSize,client,pinfo); + + epicsThreadId clientId = epicsThreadCreate("client", + 50, stackSize, client, pinfo); epicsEventSignal(pinfo->waitForMaster); - status = epicsEventWaitWithTimeout(pinfo->waitForClient,.1); - if(status!=epicsEventWaitOK) { - printf("epicsEventWaitWithTimeout failed. Why????\n"); + + epicsEventWaitStatus status; + status = epicsEventWaitWithTimeout(pinfo->waitForClient, 0.1); + if (!testOk(status == epicsEventWaitOK, + "epicsEventWaitWithTimeout returned %d", status)) { + testSkip(2, "epicsEventWaitWithTimeout failed"); goto done; } - epicsThreadSetPriority(clientId,20); + + epicsThreadSetPriority(clientId, 20); /* expect that client will not be able to run */ epicsEventSignal(pinfo->waitForMaster); + status = epicsEventTryWait(pinfo->waitForClient); - if(status!=epicsEventWaitTimeout) { - printf("epicsEventTryWait did not return epicsEventWaitTimeout\n"); + if (status != epicsEventWaitTimeout) { + testFail("epicsEventTryWait returned %d", status); } else { - status = epicsEventWaitWithTimeout(pinfo->waitForClient,.1); - if(status!=epicsEventWaitOK) { - printf("epicsEventWaitWithTimeout failed. Why????\n"); + status = epicsEventWaitWithTimeout(pinfo->waitForClient, 0.1); + if (!testOk(status == epicsEventWaitOK, + "epicsEventWaitWithTimeout returned %d", status)) { + testSkip(1, "epicsEventWaitWithTimeout failed"); goto done; } } - epicsThreadSetPriority(clientId,80); + epicsThreadSetPriority(clientId, 80); /* expect that client will be able to run */ epicsEventSignal(pinfo->waitForMaster); status = epicsEventTryWait(pinfo->waitForClient); - if(status==epicsEventWaitOK) { - printf("Seems to support strict priority scheduling\n"); + if (status==epicsEventWaitOK) { + testPass("Strict priority scheduler"); } else { - printf("Does not appear to support strict priority scheduling\n"); + testDiag("No strict priority scheduler"); status = epicsEventWaitWithTimeout(pinfo->waitForClient,.1); - if(status!=epicsEventWaitOK) { - printf("epicsEventWaitWithTimeout failed. Why????\n"); - goto done; - } + testOk(status == epicsEventWaitOK, + "epicsEventWaitWithTimeout returned %d", status); } done: epicsThreadSleep(1.0); + epicsEventSignal(testComplete); } + } /* extern "C" */ + + +MAIN(epicsThreadPriorityTest) +{ + testPlan(7); + epicsEventId testComplete = epicsEventMustCreate(epicsEventEmpty); + epicsThreadMustCreate("threadPriorityTest", epicsThreadPriorityMedium, + epicsThreadGetStackSize(epicsThreadStackMedium), + runThreadPriorityTest, testComplete); + epicsEventWaitStatus status = epicsEventWait(testComplete); + testOk(status == epicsEventWaitOK, + "epicsEventWait returned %d", status); + return testDone(); +} diff --git a/src/libCom/test/epicsThreadPriorityTestMain.cpp b/src/libCom/test/epicsThreadPriorityTestMain.cpp deleted file mode 100644 index 23f2dd8b7..000000000 --- a/src/libCom/test/epicsThreadPriorityTestMain.cpp +++ /dev/null @@ -1,27 +0,0 @@ -/*************************************************************************\ -* Copyright (c) 2002 The University of Chicago, as Operator of Argonne -* National Laboratory. -* Copyright (c) 2002 The Regents of the University of California, as -* Operator of Los Alamos National Laboratory. -* EPICS BASE Versions 3.13.7 -* and higher are distributed subject to a Software License Agreement found -* in file LICENSE that is included with this distribution. -\*************************************************************************/ -/* - * $Id$ - * - * Author Marty Kraimer - */ - -#include "epicsThread.h" - -extern "C" void epicsThreadPriorityTest(void *arg); - -int main ( int argc , char *argv[] ) -{ - epicsThreadMustCreate("threadPriorityTest",epicsThreadPriorityMedium, - epicsThreadGetStackSize(epicsThreadStackMedium), - epicsThreadPriorityTest,0); - epicsThreadExitMain(); - return 0; -} diff --git a/src/libCom/test/epicsThreadPrivateTest.cpp b/src/libCom/test/epicsThreadPrivateTest.cpp index cf1f43c1b..1bef0c047 100644 --- a/src/libCom/test/epicsThreadPrivateTest.cpp +++ b/src/libCom/test/epicsThreadPrivateTest.cpp @@ -1,11 +1,10 @@ /*************************************************************************\ -* Copyright (c) 2002 The University of Chicago, as Operator of Argonne +* Copyright (c) 2006 UChicago Argonne LLC, as Operator of Argonne * National Laboratory. * Copyright (c) 2002 The Regents of the University of California, as * Operator of Los Alamos National Laboratory. -* EPICS BASE Versions 3.13.7 -* and higher are distributed subject to a Software License Agreement found -* in file LICENSE that is included with this distribution. +* EPICS BASE is distributed subject to a Software License Agreement found +* in file LICENSE that is included with this distribution. \*************************************************************************/ /* $Id$ */ @@ -15,7 +14,8 @@ #include "epicsTime.h" #include "epicsThread.h" -#include "epicsAssert.h" +#include "epicsUnitTest.h" +#include "testMain.h" static epicsThreadPrivate < bool > priv; @@ -23,10 +23,10 @@ static bool doneFlag = false; extern "C" void epicsThreadPrivateTestThread ( void * ) { - assert ( 0 == priv.get () ); + testOk1 ( 0 == priv.get () ); static bool var; priv.set ( &var ); - assert ( &var == priv.get () ); + testOk1 ( &var == priv.get () ); doneFlag = true; } @@ -59,20 +59,24 @@ inline void callItTenTimesSquared () callItTenTimes (); } -extern "C" void epicsThreadPrivateTest () +MAIN(epicsThreadPrivateTest) { + testPlan(5); + static bool var; priv.set ( &var ); - assert ( &var == priv.get() ); + testOk1 ( &var == priv.get() ); + epicsThreadCreate ( "epicsThreadPrivateTest", epicsThreadPriorityMax, epicsThreadGetStackSize ( epicsThreadStackSmall ), epicsThreadPrivateTestThread, 0 ); while ( ! doneFlag ) { epicsThreadSleep ( 0.1 ); } - assert ( &var == priv.get() ); + testOk1 ( &var == priv.get() ); + priv.set ( 0 ); - assert ( 0 == priv.get() ); + testOk1 ( 0 == priv.get() ); epicsTime begin = epicsTime::getCurrent (); static const unsigned N = 1000u; @@ -82,6 +86,8 @@ extern "C" void epicsThreadPrivateTest () double delay = epicsTime::getCurrent() - begin; delay /= N * 100u; // convert to sec per call delay *= 1e6; // convert to micro sec - printf ( "It takes %f micro sec to call epicsThreadPrivateGet()\n", delay ); + testDiag("epicsThreadPrivateGet() takes %f microseconds", delay); + + return testDone(); } diff --git a/src/libCom/test/epicsThreadPrivateTestMain.cpp b/src/libCom/test/epicsThreadPrivateTestMain.cpp deleted file mode 100644 index 1d04f70f6..000000000 --- a/src/libCom/test/epicsThreadPrivateTestMain.cpp +++ /dev/null @@ -1,22 +0,0 @@ -/*************************************************************************\ -* Copyright (c) 2002 The University of Chicago, as Operator of Argonne -* National Laboratory. -* Copyright (c) 2002 The Regents of the University of California, as -* Operator of Los Alamos National Laboratory. -* EPICS BASE Versions 3.13.7 -* and higher are distributed subject to a Software License Agreement found -* in file LICENSE that is included with this distribution. -\*************************************************************************/ - -/* $Id$ */ - -/* Author: Jeff Hill Date: March 28 2001 */ - -extern "C" void epicsThreadPrivateTest (); - -int main () -{ - epicsThreadPrivateTest (); - return 0; -} - diff --git a/src/libCom/test/epicsThreadTest.cpp b/src/libCom/test/epicsThreadTest.cpp index bbe59eaf2..b1e28bb8c 100644 --- a/src/libCom/test/epicsThreadTest.cpp +++ b/src/libCom/test/epicsThreadTest.cpp @@ -1,18 +1,13 @@ /*************************************************************************\ -* Copyright (c) 2002 The University of Chicago, as Operator of Argonne +* Copyright (c) 2006 UChicago Argonne LLC, as Operator of Argonne * National Laboratory. * Copyright (c) 2002 The Regents of the University of California, as * Operator of Los Alamos National Laboratory. -* EPICS BASE Versions 3.13.7 -* and higher are distributed subject to a Software License Agreement found -* in file LICENSE that is included with this distribution. +* EPICS BASE is distributed subject to a Software License Agreement found +* in file LICENSE that is included with this distribution. \*************************************************************************/ /* epicsThreadTest.cpp */ -/* Author: Marty Kraimer Date: 26JAN2000 */ -/* sleep accuracy and sleep quantum tests by Jeff Hill */ -/* epicsThreadGetIdSelf performance by Jeff Hill */ - #include #include #include @@ -25,33 +20,8 @@ #include "epicsThread.h" #include "epicsTime.h" #include "errlog.h" - -static void testPriority(const char *who) -{ - epicsThreadId id; - unsigned int oldPriority,newPriority; - - id = epicsThreadGetIdSelf(); - oldPriority = epicsThreadGetPriority(id); - epicsThreadSetPriority(id,epicsThreadPriorityMax); - newPriority = epicsThreadGetPriority(id); - epicsThreadSetPriority(id,oldPriority); - printf("testPriority %s\n id %p old %u new %u\n", - who,id,oldPriority,newPriority); -} - -extern "C" void testPriorityThread(void *arg) -{ - testPriority("thread"); -} - -static void epicsThreadPriorityTest() -{ - testPriority("main error expected from epicsThreadSetPriority"); - epicsThreadCreate("testPriorityThread",epicsThreadPriorityMedium, - epicsThreadGetStackSize(epicsThreadStackMedium),testPriorityThread,0); - epicsThreadSleep(0.5); -} +#include "epicsUnitTest.h" +#include "testMain.h" static epicsThreadPrivate privateKey; @@ -78,166 +48,64 @@ myThread::~myThread() {delete argvalue;} void myThread::run() { - int myPrivate = *argvalue; + int *pset = argvalue; privateKey.set(argvalue); - errlogPrintf("threadFunc %d starting argvalue %p\n",myPrivate,argvalue); epicsThreadSleep(2.0); - argvalue = privateKey.get(); - errlogPrintf("threadFunc %d stopping argvalue %p\n",myPrivate,argvalue); + int *pget = privateKey.get(); + testOk1(pget == pset); + + epicsThreadId self = epicsThreadGetIdSelf(); + testOk1(thread.getPriority() == epicsThreadGetPriority(self)); } -static double threadSleepMeasureDelayError ( const double & delay ) + +typedef struct info { + int isOkToBlock; +} info; + +extern "C" { +static void thread(void *arg) { - epicsTime beg = epicsTime::getCurrent(); - epicsThreadSleep ( delay ); - epicsTime end = epicsTime::getCurrent(); - double meas = end - beg; - double error = fabs ( delay - meas ); - return error; + info *pinfo = (info *)arg; + + epicsThreadSetOkToBlock(pinfo->isOkToBlock); + epicsThreadSleep(1.0); + + testOk(epicsThreadIsOkToBlock() == pinfo->isOkToBlock, + "%s epicsThreadIsOkToBlock() = %d", + epicsThreadGetNameSelf(), pinfo->isOkToBlock); + epicsThreadSleep(0.1); +} } -static double measureSleepQuantum ( - const unsigned iterations, const double testInterval ) + +MAIN(epicsThreadTest) { - double errorSum = 0.0; - printf ( "Estimating sleep quantum" ); - fflush ( stdout ); - for ( unsigned i = 0u; i < iterations; i++ ) { - // try to guarantee a uniform probability density function - // by intentionally burning some CPU until we are less - // likely to be aligned with the schedualing clock - double interval = rand (); - interval /= RAND_MAX; - interval *= testInterval; - epicsTime start = epicsTime::getCurrent (); - epicsTime current = start; - while ( current - start < interval ) { - current = epicsTime::getCurrent (); - } - errorSum += threadSleepMeasureDelayError ( testInterval ); - if ( i % ( iterations / 10 ) == 0 ) { - printf ( "." ); - fflush ( stdout ); - } - } - printf ( "done\n" ); + testPlan(8); - // with a uniform probability density function the - // sleep delay error mean is one half of the quantum - double quantumEstimate = 2 * errorSum / iterations; - return quantumEstimate; -} - -static void threadSleepQuantumTest () -{ - const double quantum = epicsThreadSleepQuantum (); - - double quantumEstimate = measureSleepQuantum ( 10, 10 * quantum ); - quantumEstimate = measureSleepQuantum ( 100, 2 * quantumEstimate ); - - double quantumError = fabs ( quantumEstimate - quantum ) / quantum; - const char * pTol = 0; - if ( quantumError > 0.1 ) { - pTol = "10%"; - } - else if ( quantumError > 0.01 ) { - pTol = "1%"; - } - else if ( quantumError > 0.001 ) { - pTol = "0.1%"; - } - if ( pTol ) { - printf ( - "The epicsThreadSleepQuantum() call returns %f sec.\n", - quantum ); - printf ( - "This doesnt match the quantum estimate " - "of %f sec within %s.\n", - quantumEstimate, pTol ); - } -} - -static void threadSleepTest () -{ - static const int iterations = 20; - const double quantum = epicsThreadSleepQuantum (); - double errorSum = threadSleepMeasureDelayError ( 0.0 ); - for ( int i = 0u; i < iterations; i++ ) { - double delay = ldexp ( 1.0 , -i ); - double error = - threadSleepMeasureDelayError ( delay ); - errorSum += error; - if ( error > quantum + quantum / 8.0 ) { - printf ( "epicsThreadSleep ( %10f ) delay err %10f sec\n", - delay, error ); - } - } - double averageError = errorSum / ( iterations + 1 ); - if ( averageError > quantum ) { - printf ( "Average sleep delay error was %f sec\n", averageError ); - } -} - -static void epicsThreadGetIdSelfPerfTest () -{ - static const unsigned N = 10000; - static const double microSecPerSec = 1e6; - epicsTime begin = epicsTime::getCurrent (); - for ( unsigned i = 0u; i < N; i++ ) { - epicsThreadGetIdSelf (); - epicsThreadGetIdSelf (); - epicsThreadGetIdSelf (); - epicsThreadGetIdSelf (); - epicsThreadGetIdSelf (); - - epicsThreadGetIdSelf (); - epicsThreadGetIdSelf (); - epicsThreadGetIdSelf (); - epicsThreadGetIdSelf (); - epicsThreadGetIdSelf (); - }; - epicsTime end = epicsTime::getCurrent (); - printf ( "It takes %f micro sec to call epicsThreadGetIdSelf ()\n", - microSecPerSec * ( end - begin ) / (10 * N) ); -} - -extern "C" void threadTest(int ntasks,int verbose) -{ - myThread **papmyThread; - int i; - char **name; - int startPriority,minPriority,maxPriority; - int errVerboseSave = errVerbose; - - epicsThreadPriorityTest(); - epicsThreadGetIdSelfPerfTest (); - - threadSleepTest(); - threadSleepQuantumTest(); - - errVerbose = verbose; - errlogInit(4096); - papmyThread = (myThread **)calloc(ntasks,sizeof(myThread *)); - name = (char **)calloc(ntasks,sizeof(char **)); - errlogPrintf("threadTest starting\n"); - for(i=0; ithread.getPriority(); - papmyThread[i]->thread.setPriority(epicsThreadPriorityMin); - minPriority = papmyThread[i]->thread.getPriority(); - papmyThread[i]->thread.setPriority(epicsThreadPriorityMax); - maxPriority = papmyThread[i]->thread.getPriority(); - papmyThread[i]->thread.setPriority(50+i); - if(i==0)errlogPrintf("startPriority %d minPriority %d maxPriority %d\n", - startPriority,minPriority,maxPriority); - } - epicsThreadSleep(.1); - epicsThreadShowAll(0); - epicsThreadSleep(5.0); - errlogPrintf("epicsThreadTest returning\n"); - epicsThreadSleep(.5); - errVerbose = errVerboseSave; + const int ntasks = 3; + myThread *myThreads[ntasks]; + + int startPriority = 0; + for (int i = 0; i < ntasks; i++) { + char name[10]; + sprintf(name, "t%d", i); + myThreads[i] = new myThread(i, name); + if (i == 0) + startPriority = myThreads[i]->thread.getPriority(); + myThreads[i]->thread.setPriority(startPriority + i); + } + epicsThreadSleep(3.0); + + unsigned int stackSize = epicsThreadGetStackSize(epicsThreadStackSmall); + + info infoA = {0}; + epicsThreadCreate("threadA", 50, stackSize, thread, &infoA); + + info infoB = {1}; + epicsThreadCreate("threadB", 50, stackSize, thread, &infoB); + + epicsThreadSleep(2.0); + + return testDone(); } diff --git a/src/libCom/test/epicsThreadTestMain.cpp b/src/libCom/test/epicsThreadTestMain.cpp deleted file mode 100644 index 122d81684..000000000 --- a/src/libCom/test/epicsThreadTestMain.cpp +++ /dev/null @@ -1,48 +0,0 @@ -/*************************************************************************\ -* Copyright (c) 2002 The University of Chicago, as Operator of Argonne -* National Laboratory. -* Copyright (c) 2002 The Regents of the University of California, as -* Operator of Los Alamos National Laboratory. -* EPICS BASE Versions 3.13.7 -* and higher are distributed subject to a Software License Agreement found -* in file LICENSE that is included with this distribution. -\*************************************************************************/ -/* threadTestMain.c */ - -/* Author: Marty Kraimer Date: 26JAN2000 */ - -#include -#include -#include -#include -#include -#include - -#include "epicsThread.h" -extern "C" void threadTest(int nthreads,int errVerbose); - -int main(int argc,char *argv[]) -{ - int nthreads = 2; - int errVerboseIn = 0; - - if(argc>1) { - if(isdigit(*argv[1])) { - sscanf(argv[1],"%d",&nthreads); - printf("nthreads %d\n",nthreads); - } else { - printf("Illegal argument %s\n",argv[1]); - } - } - if(argc>2) { - if(isdigit(*argv[2])) { - sscanf(argv[2],"%d",&errVerboseIn); - printf("errVerbose %d\n",errVerboseIn); - } else { - printf("Illegal argument %s\n",argv[1]); - } - } - if(nthreads>0) threadTest(nthreads,errVerboseIn); - printf("main terminating\n"); - return(0); -} diff --git a/src/libCom/test/epicsTimeTest.cpp b/src/libCom/test/epicsTimeTest.cpp index c633cd5a6..644c6d7d6 100644 --- a/src/libCom/test/epicsTimeTest.cpp +++ b/src/libCom/test/epicsTimeTest.cpp @@ -1,11 +1,10 @@ /*************************************************************************\ -* Copyright (c) 2002 The University of Chicago, as Operator of Argonne +* Copyright (c) 2006 UChicago Argonne LLC, as Operator of Argonne * National Laboratory. * Copyright (c) 2002 The Regents of the University of California, as * Operator of Los Alamos National Laboratory. -* EPICS BASE Versions 3.13.7 -* and higher are distributed subject to a Software License Agreement found -* in file LICENSE that is included with this distribution. +* EPICS BASE is distributed subject to a Software License Agreement found +* in file LICENSE that is included with this distribution. \*************************************************************************/ /* * Authors: Jeff HIll and Marty Kraimer @@ -20,6 +19,7 @@ #include "epicsThread.h" #include "errlog.h" #include "epicsUnitTest.h" +#include "testMain.h" using namespace std; @@ -39,8 +39,7 @@ static const unsigned uSecPerSec = 1000u * mSecPerSec; static const unsigned nSecPerSec = 1000u * uSecPerSec; -extern "C" -int epicsTimeTest (void) +MAIN(epicsTimeTest) { const unsigned wasteTime = 100000u; const int nTimes = 10; @@ -66,8 +65,7 @@ int epicsTimeTest (void) epicsTime ts(badTS); char buf [32]; ts.strftime(buf, sizeof(buf), pFormat); - testFail("nanosecond overflow throws"); - testDiag("nanosecond overflow result is \"%s\"", buf); + testFail("nanosecond overflow returned \"%s\"", buf); } catch ( ... ) { testPass("nanosecond overflow throws"); @@ -75,31 +73,27 @@ int epicsTimeTest (void) } { - char buf[64]; + char buf[80]; epicsTime et; const char * pFormat = "%Y-%m-%d %H:%M:%S.%f"; et.strftime(buf, sizeof(buf), pFormat); - if (!testOk(strcmp(buf, "") == 0, "undefined strftime")) - testDiag("undefined.strftime(\"%s\") = \"%s\"", pFormat, buf); + testOk(strcmp(buf, "") == 0, "undefined => '%s'", 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); - if (!testOk(strcmp(buf, "1990-01-01 00.098765432") == 0, pFormat)) - testDiag("t.strftime(\"%s\") = \"%s\"", pFormat, buf); + testOk(strcmp(buf, "1990-01-01 00.098765432") == 0, "'%s' => '%s'", pFormat, buf); pFormat = "%S.%04f"; et.strftime(buf, sizeof(buf), pFormat); - if (!testOk(strcmp(buf, "00.0988") == 0, pFormat)) - testDiag("t.strftime(\"%s\") = \"%s\"", pFormat, buf); + testOk(strcmp(buf, "00.0988") == 0, "'%s' => '%s'", pFormat, buf); pFormat = "%S.%05f"; et.strftime(buf, sizeof(buf), pFormat); - if (!testOk(strcmp(buf, "00.09877") == 0, pFormat)) - testDiag("t.strftime(\"%s\") = \"%s\"", pFormat, buf); + testOk(strcmp(buf, "00.09877") == 0, "'%s' => '%s'", pFormat, buf); } { // invalidFormatTest @@ -108,8 +102,7 @@ int epicsTimeTest (void) memset(bigBuf, '\a', sizeof(bigBuf )); bigBuf[ sizeof(bigBuf) - 1] = '\0'; begin.strftime(buf, sizeof(buf), bigBuf); - if (!testOk(strcmp(buf, "") == 0, "strftime(huge)")) - testDiag("strftime(huge) = \"%s\"", buf); + testOk(strcmp(buf, "") == 0, "bad format => '%s'", buf); } testDiag("Running %d loops", nTimes); diff --git a/src/libCom/test/epicsTimeTestMain.cpp b/src/libCom/test/epicsTimeTestMain.cpp deleted file mode 100644 index 4bd126896..000000000 --- a/src/libCom/test/epicsTimeTestMain.cpp +++ /dev/null @@ -1,17 +0,0 @@ -/*************************************************************************\ -* Copyright (c) 2002 The University of Chicago, as Operator of Argonne -* National Laboratory. -* Copyright (c) 2002 The Regents of the University of California, as -* Operator of Los Alamos National Laboratory. -* EPICS BASE Versions 3.13.7 -* and higher are distributed subject to a Software License Agreement found -* in file LICENSE that is included with this distribution. -\*************************************************************************/ -#include - -extern "C" int epicsTimeTest (void); - -int main (int , char **) -{ - return epicsTimeTest (); -} diff --git a/src/libCom/test/epicsTimerExample.cpp b/src/libCom/test/epicsTimerExample.cpp deleted file mode 100644 index 6c58ec5cf..000000000 --- a/src/libCom/test/epicsTimerExample.cpp +++ /dev/null @@ -1,42 +0,0 @@ -/*************************************************************************\ -* Copyright (c) 2002 The University of Chicago, as Operator of Argonne -* National Laboratory. -* Copyright (c) 2002 The Regents of the University of California, as -* Operator of Los Alamos National Laboratory. -* EPICS BASE Versions 3.13.7 -* and higher are distributed subject to a Software License Agreement found -* in file LICENSE that is included with this distribution. -\*************************************************************************/ -#include - -#include "epicsTimer.h" - -class something : public epicsTimerNotify { -public: - something(const char* nm,epicsTimerQueueActive &queue) - : name(nm), timer(queue.createTimer()) {} - virtual ~something() { timer.destroy();} - void start(double delay) {timer.start(*this,delay);} - virtual expireStatus expire(const epicsTime & currentTime) { - printf("%s\n",name); - currentTime.show(1); - return(noRestart); - } -private: - const char* name; - epicsTimer &timer; -}; - -void epicsTimerExample() -{ - epicsTimerQueueActive &queue = epicsTimerQueueActive::allocate(true); - { - something first("first",queue); - something second("second",queue); - - first.start(1.0); - second.start(1.5); - epicsThreadSleep(2.0); - } - queue.release(); -} diff --git a/src/libCom/test/epicsTimerExampleMain.cpp b/src/libCom/test/epicsTimerExampleMain.cpp deleted file mode 100644 index 06956792a..000000000 --- a/src/libCom/test/epicsTimerExampleMain.cpp +++ /dev/null @@ -1,25 +0,0 @@ -/*************************************************************************\ -* Copyright (c) 2002 The University of Chicago, as Operator of Argonne -* National Laboratory. -* Copyright (c) 2002 The Regents of the University of California, as -* Operator of Los Alamos National Laboratory. -* EPICS BASE Versions 3.13.7 -* and higher are distributed subject to a Software License Agreement found -* in file LICENSE that is included with this distribution. -\*************************************************************************/ - -/* - * $Id$ - * - * Author Jeffrey O. Hill - * johill@lanl.gov - * 505 665 1831 - */ - -void epicsTimerExample ( void ); - -int main ( int /* argc */, char /* *argv[] */ ) -{ - epicsTimerExample (); - return 0; -} diff --git a/src/libCom/test/epicsTimerTest.cpp b/src/libCom/test/epicsTimerTest.cpp index a626940cf..a2132243b 100644 --- a/src/libCom/test/epicsTimerTest.cpp +++ b/src/libCom/test/epicsTimerTest.cpp @@ -1,11 +1,10 @@ /*************************************************************************\ -* Copyright (c) 2002 The University of Chicago, as Operator of Argonne +* Copyright (c) 2006 UChicago Argonne LLC, as Operator of Argonne * National Laboratory. * Copyright (c) 2002 The Regents of the University of California, as * Operator of Los Alamos National Laboratory. -* EPICS BASE Versions 3.13.7 -* and higher are distributed subject to a Software License Agreement found -* in file LICENSE that is included with this distribution. +* EPICS BASE is distributed subject to a Software License Agreement found +* in file LICENSE that is included with this distribution. \*************************************************************************/ /* * $Id$ @@ -25,6 +24,9 @@ #include "epicsGuard.h" #include "tsFreeList.h" #include "epicsSingleton.h" +#include "epicsUnitTest.h" +#include "testMain.h" + static const double delayVerifyOffset = 1.0; // sec @@ -66,19 +68,18 @@ inline void delayVerify::setBegin ( const epicsTime &beginIn ) inline double delayVerify::delay () const { - return delayVerifyOffset + this->expectedDelay; + return this->expectedDelay; } double delayVerify::checkError () const { const double messageThresh = 0.5; // percent double actualDelay = this->expireStamp - this->beginStamp; - double measuredError = actualDelay - delayVerifyOffset - this->expectedDelay; - double percentError = fabs ( measuredError ) / this->expectedDelay; - percentError *= 100.0; - if ( percentError > messageThresh ) { - printf ( "delay error > %g %%, delay = %g s, error = %g ms (%f %%)\n", - messageThresh, this->expectedDelay, measuredError * 1000.0, percentError ); + double measuredError = actualDelay - this->expectedDelay; + double percentError = 100.0 * fabs ( measuredError ) / this->expectedDelay; + if ( ! testOk1 ( percentError < messageThresh ) ) { + testDiag ( "delay = %f s, error = %f s (%.1f %%)", + this->expectedDelay, measuredError, percentError ); } return measuredError; } @@ -106,13 +107,16 @@ void testAccuracy () delayVerify *pTimers[nTimers]; unsigned i; + testDiag ( "Testing timer accuracy" ); + epicsTimerQueueActive &queue = epicsTimerQueueActive::allocate ( true, epicsThreadPriorityMax ); for ( i = 0u; i < nTimers; i++ ) { - pTimers[i] = new delayVerify ( ( nTimers - i ) * 0.1, queue ); + pTimers[i] = new delayVerify ( i * 0.1 + delayVerifyOffset, queue ); assert ( pTimers[i] ); } + expireCount = nTimers; for ( i = 0u; i < nTimers; i++ ) { epicsTime cur = epicsTime::getCurrent (); @@ -127,27 +131,29 @@ void testAccuracy () averageMeasuredError += pTimers[i]->checkError (); } averageMeasuredError /= nTimers; - printf ("average timer delay error %f ms\n", + testDiag ("average timer delay error %f ms", averageMeasuredError * 1000 ); queue.release (); } + class cancelVerify : public epicsTimerNotify { public: cancelVerify ( epicsTimerQueue & ); void start ( const epicsTime &expireTime ); void cancel (); + static unsigned cancellCount; + static unsigned expireCount; protected: virtual ~cancelVerify (); private: epicsTimer &timer; - bool failOutIfExpireIsCalled; expireStatus expire ( const epicsTime & ); static epicsSingleton < tsFreeList < class cancelVerify, 0x20 > > pFreeList; }; cancelVerify::cancelVerify ( epicsTimerQueue &queueIn ) : - timer ( queueIn.createTimer () ), failOutIfExpireIsCalled ( false ) + timer ( queueIn.createTimer () ) { } @@ -164,21 +170,24 @@ inline void cancelVerify::start ( const epicsTime &expireTime ) inline void cancelVerify::cancel () { this->timer.cancel (); - this->failOutIfExpireIsCalled = true; + ++cancelVerify::cancellCount; } epicsTimerNotify::expireStatus cancelVerify::expire ( const epicsTime & ) { + ++cancelVerify::expireCount; double root = 3.14159; for ( unsigned i = 0u; i < 1000; i++ ) { root = sqrt ( root ); } - assert ( ! this->failOutIfExpireIsCalled ); return noRestart; } +unsigned cancelVerify::cancellCount = 0; +unsigned cancelVerify::expireCount = 0; + // -// verify that when cancel() is calle dthe timer never runs again +// verify that expire() won't be called after the timer is cancelled // void testCancel () { @@ -186,6 +195,8 @@ void testCancel () cancelVerify *pTimers[nTimers]; unsigned i; + testDiag ( "Testing timer cancellation" ); + epicsTimerQueueActive &queue = epicsTimerQueueActive::allocate ( true, epicsThreadPriorityMin ); @@ -193,22 +204,39 @@ void testCancel () pTimers[i] = new cancelVerify ( queue ); assert ( pTimers[i] ); } - epicsTime cur = epicsTime::getCurrent (); + assert ( cancelVerify::expireCount == 0 ); + assert ( cancelVerify::cancellCount == 0 ); + + testDiag ( "starting %d timers", nTimers ); + epicsTime exp = epicsTime::getCurrent () + 4.0; for ( i = 0u; i < nTimers; i++ ) { - pTimers[i]->start ( cur + 4.0 ); + pTimers[i]->start ( exp ); } - epicsThreadSleep ( 5.0 ); + testOk1 ( cancelVerify::expireCount == 0 ); + testOk1 ( cancelVerify::cancellCount == 0 ); + + testDiag ( "cancelling timers" ); for ( i = 0u; i < nTimers; i++ ) { pTimers[i]->cancel (); } + testOk1 ( cancelVerify::expireCount == 0 ); + testOk1 ( cancelVerify::cancellCount == nTimers ); + + testDiag ( "waiting until after timers should have expired" ); + epicsThreadSleep ( 5.0 ); + testOk1 ( cancelVerify::expireCount == 0 ); + testOk1 ( cancelVerify::cancellCount == nTimers ); + epicsThreadSleep ( 1.0 ); queue.release (); } + class expireDestroVerify : public epicsTimerNotify { public: expireDestroVerify ( epicsTimerQueue & ); void start ( const epicsTime &expireTime ); + static unsigned destroyCount; protected: virtual ~expireDestroVerify (); private: @@ -225,6 +253,7 @@ expireDestroVerify::expireDestroVerify ( epicsTimerQueue & queueIn ) : expireDestroVerify::~expireDestroVerify () { this->timer.destroy (); + ++expireDestroVerify::destroyCount; } inline void expireDestroVerify::start ( const epicsTime & expireTime ) @@ -238,6 +267,8 @@ epicsTimerNotify::expireStatus expireDestroVerify::expire ( const epicsTime & ) return noRestart; } +unsigned expireDestroVerify::destroyCount = 0; + // // verify that a timer can be destroyed in expire // @@ -247,6 +278,8 @@ void testExpireDestroy () expireDestroVerify *pTimers[nTimers]; unsigned i; + testDiag ( "Testing timer destruction in expire()" ); + epicsTimerQueueActive &queue = epicsTimerQueueActive::allocate ( true, epicsThreadPriorityMin ); @@ -254,11 +287,18 @@ void testExpireDestroy () pTimers[i] = new expireDestroVerify ( queue ); assert ( pTimers[i] ); } + assert ( expireDestroVerify::destroyCount == 0 ); + + testDiag ( "starting %d timers", nTimers ); epicsTime cur = epicsTime::getCurrent (); for ( i = 0u; i < nTimers; i++ ) { pTimers[i]->start ( cur ); } + + testDiag ( "waiting until all timers should have expired" ); epicsThreadSleep ( 5.0 ); + + testOk1 ( expireDestroVerify::destroyCount == nTimers ); queue.release (); } @@ -268,20 +308,20 @@ public: periodicVerify ( epicsTimerQueue & ); void start ( const epicsTime &expireTime ); void cancel (); - void verifyCount (); + bool verifyCount (); protected: virtual ~periodicVerify (); private: epicsTimer &timer; unsigned nExpire; - bool failOutIfExpireIsCalled; + bool cancelCalled; expireStatus expire ( const epicsTime & ); static epicsSingleton < tsFreeList < class periodicVerify, 0x20 > > pFreeList; }; periodicVerify::periodicVerify ( epicsTimerQueue & queueIn ) : timer ( queueIn.createTimer () ), nExpire ( 0u ), - failOutIfExpireIsCalled ( false ) + cancelCalled ( false ) { } @@ -298,12 +338,12 @@ inline void periodicVerify::start ( const epicsTime &expireTime ) inline void periodicVerify::cancel () { this->timer.cancel (); - this->failOutIfExpireIsCalled = true; + this->cancelCalled = true; } -inline void periodicVerify::verifyCount () +inline bool periodicVerify::verifyCount () { - assert ( this->nExpire > 1u ); + return ( this->nExpire > 1u ); } epicsTimerNotify::expireStatus periodicVerify::expire ( const epicsTime & ) @@ -313,7 +353,7 @@ epicsTimerNotify::expireStatus periodicVerify::expire ( const epicsTime & ) for ( unsigned i = 0u; i < 1000; i++ ) { root = sqrt ( root ); } - assert ( ! this->failOutIfExpireIsCalled ); + assert ( ! this->cancelCalled ); double delay = rand (); delay = delay / RAND_MAX; delay /= 10.0; @@ -329,6 +369,8 @@ void testPeriodic () periodicVerify *pTimers[nTimers]; unsigned i; + testDiag ( "Testing periodic timers" ); + epicsTimerQueueActive &queue = epicsTimerQueueActive::allocate ( true, epicsThreadPriorityMin ); @@ -336,24 +378,32 @@ void testPeriodic () pTimers[i] = new periodicVerify ( queue ); assert ( pTimers[i] ); } + + testDiag ( "starting %d timers", nTimers ); epicsTime cur = epicsTime::getCurrent (); for ( i = 0u; i < nTimers; i++ ) { pTimers[i]->start ( cur ); } + + testDiag ( "waiting until all timers should have expired" ); epicsThreadSleep ( 5.0 ); + + bool notWorking = false; for ( i = 0u; i < nTimers; i++ ) { - pTimers[i]->verifyCount (); + notWorking |= ! pTimers[i]->verifyCount (); pTimers[i]->cancel (); } + testOk( ! notWorking, "All timers expiring" ); epicsThreadSleep ( 1.0 ); queue.release (); } -extern "C" void epicsTimerTest () +MAIN(epicsTimerTest) { - testExpireDestroy (); + testPlan(33); testAccuracy (); testCancel (); + testExpireDestroy (); testPeriodic (); - printf ( "test complete\n" ); + return testDone(); } diff --git a/src/libCom/test/epicsTimerTestMain.cpp b/src/libCom/test/epicsTimerTestMain.cpp deleted file mode 100644 index b9265cd56..000000000 --- a/src/libCom/test/epicsTimerTestMain.cpp +++ /dev/null @@ -1,26 +0,0 @@ -/*************************************************************************\ -* Copyright (c) 2002 The University of Chicago, as Operator of Argonne -* National Laboratory. -* Copyright (c) 2002 The Regents of the University of California, as -* Operator of Los Alamos National Laboratory. -* EPICS BASE Versions 3.13.7 -* and higher are distributed subject to a Software License Agreement found -* in file LICENSE that is included with this distribution. -\*************************************************************************/ - -/* - * $Id$ - * - * Author Jeffrey O. Hill - * johill@lanl.gov - * 505 665 1831 - * - */ - -extern "C" void epicsTimerTest ( void ); - -int main ( int /* argc */, char /* *argv[] */ ) -{ - epicsTimerTest (); - return 0; -} diff --git a/src/libCom/test/fdmgrTest.c b/src/libCom/test/fdmgrTest.c index 00fc8832d..07153796b 100644 --- a/src/libCom/test/fdmgrTest.c +++ b/src/libCom/test/fdmgrTest.c @@ -1,11 +1,10 @@ /*************************************************************************\ -* Copyright (c) 2002 The University of Chicago, as Operator of Argonne +* Copyright (c) 2006 UChicago Argonne LLC, as Operator of Argonne * National Laboratory. * Copyright (c) 2002 The Regents of the University of California, as * Operator of Los Alamos National Laboratory. -* EPICS BASE Versions 3.13.7 -* and higher are distributed subject to a Software License Agreement found -* in file LICENSE that is included with this distribution. +* EPICS BASE is distributed subject to a Software License Agreement found +* in file LICENSE that is included with this distribution. \*************************************************************************/ #include diff --git a/src/libCom/test/macEnvExpandTest.c b/src/libCom/test/macEnvExpandTest.c index 7ec1c53ae..5bd3a3845 100644 --- a/src/libCom/test/macEnvExpandTest.c +++ b/src/libCom/test/macEnvExpandTest.c @@ -1,11 +1,10 @@ /*************************************************************************\ -* Copyright (c) 2002 The University of Chicago, as Operator of Argonne +* Copyright (c) 2006 UChicago Argonne LLC, as Operator of Argonne * National Laboratory. * Copyright (c) 2002 The Regents of the University of California, as * Operator of Los Alamos National Laboratory. -* EPICS BASE Versions 3.13.7 -* and higher are distributed subject to a Software License Agreement found -* in file LICENSE that is included with this distribution. +* EPICS BASE is distributed subject to a Software License Agreement found +* in file LICENSE that is included with this distribution. \*************************************************************************/ /* * $Id$ @@ -20,6 +19,7 @@ #include "envDefs.h" #include "errlog.h" #include "epicsUnitTest.h" +#include "testMain.h" void check(const char *str, const char *expect) { @@ -40,7 +40,7 @@ void check(const char *str, const char *expect) testOk(pass, str); } -int macEnvExpandTest(void) +MAIN(macEnvExpandTest) { int warn = 0; testPlan(30); diff --git a/src/libCom/test/macEnvExpandTestMain.cpp b/src/libCom/test/macEnvExpandTestMain.cpp deleted file mode 100644 index c321fce2b..000000000 --- a/src/libCom/test/macEnvExpandTestMain.cpp +++ /dev/null @@ -1,20 +0,0 @@ -/*************************************************************************\ -* Copyright (c) 2002 The University of Chicago, as Operator of Argonne -* National Laboratory. -* Copyright (c) 2002 The Regents of the University of California, as -* Operator of Los Alamos National Laboratory. -* EPICS BASE Versions 3.13.7 -* and higher are distributed subject to a Software License Agreement found -* in file LICENSE that is included with this distribution. -\*************************************************************************/ -/* $Id$ - */ - -extern "C" { -int macEnvExpandTest ( void ); -} - -int main ( int , char *[] ) -{ - return macEnvExpandTest (); -} diff --git a/src/libCom/test/ringPointerTest.c b/src/libCom/test/ringPointerTest.c index 1b86c3eca..e176e9057 100644 --- a/src/libCom/test/ringPointerTest.c +++ b/src/libCom/test/ringPointerTest.c @@ -1,11 +1,10 @@ /*************************************************************************\ -* Copyright (c) 2002 The University of Chicago, as Operator of Argonne +* Copyright (c) 2006 UChicago Argonne LLC, as Operator of Argonne * National Laboratory. * Copyright (c) 2002 The Regents of the University of California, as * Operator of Los Alamos National Laboratory. -* EPICS BASE Versions 3.13.7 -* and higher are distributed subject to a Software License Agreement found -* in file LICENSE that is included with this distribution. +* EPICS BASE is distributed subject to a Software License Agreement found +* in file LICENSE that is included with this distribution. \*************************************************************************/ /* ringPointerTest.c */ @@ -23,34 +22,37 @@ #include "epicsRingPointer.h" #include "errlog.h" #include "epicsEvent.h" +#include "epicsUnitTest.h" +#include "testMain.h" #define ringSize 10 +static int testExit = 0; + typedef struct info { epicsEventId consumerEvent; epicsRingPointerId ring; }info; - + static void consumer(void *arg) { info *pinfo = (info *)arg; static int expectedValue=0; int *newvalue; - printf("consumer starting\n"); + testDiag("Consumer starting"); while(1) { epicsEventMustWait(pinfo->consumerEvent); + if (testExit) return; while((newvalue = (int *)epicsRingPointerPop(pinfo->ring))) { - if(expectedValue != *newvalue) { - printf("consumer expected %d got %d\n", - expectedValue,*newvalue); - } + testOk(expectedValue == *newvalue, + "Consumer: %d == %d", expectedValue, *newvalue); expectedValue = *newvalue + 1; } } } - -void ringPointerTest() + +MAIN(ringPointerTest) { int i; info *pinfo; @@ -59,38 +61,47 @@ void ringPointerTest() int *pgetValue; epicsRingPointerId ring; - for(i=0; iconsumerEvent = consumerEvent = epicsEventMustCreate(epicsEventEmpty); - if(!consumerEvent) {printf("epicsEventMustCreate failed\n");exit(1);} + if (!consumerEvent) { + testAbort("epicsEventMustCreate failed"); + } + pinfo->ring = ring = epicsRingPointerCreate(ringSize); - if(!ring) {printf("epicsRingPointerCreate failed\n");exit(1);} - epicsThreadCreate("consumer",50,epicsThreadGetStackSize(epicsThreadStackSmall), - consumer,pinfo); - if(!epicsRingPointerIsEmpty(ring)) printf("epicsRingPointerIsEmpty failed\n"); - printf("fill ring\n"); - i=0; - while(1) { - if(!epicsRingPointerPush(ring,(void *)&value[i])) break; - ++i; + if (!ring) { + testAbort("epicsRingPointerCreate failed"); } - if(i!=ringSize) printf("fill ring failed i %d ringSize %d\n",i,ringSize); - printf("empty ring\n"); - i=0; - while(1) { - if(!(pgetValue = (int *)epicsRingPointerPop(ring))) break; - if(i!=*pgetValue) printf("main expected %d got %d\n",i,*pgetValue); - ++i; + testOk(epicsRingPointerIsEmpty(ring), "Ring empty"); + + for (i=0; epicsRingPointerPush(ring,(void *)&value[i]); ++i) {} + testOk(i==ringSize, "ring filled, %d values", i); + + for (i=0; (pgetValue = (int *)epicsRingPointerPop(ring)); ++i) { + testOk(i==*pgetValue, "Pop test: %d == %d", i, *pgetValue); } - if(!epicsRingPointerIsEmpty(ring)) printf("epicsRingPointerIsEmpty failed\n"); - for(i=0; i -#include -#include -#include -#include -#include - -#include "epicsThread.h" -extern "C" { -void ringPointerTest(void); -} - - -int main() -{ - ringPointerTest(); - printf("main terminating\n"); - return(0); -} diff --git a/src/libCom/test/testMain.h b/src/libCom/test/testMain.h new file mode 100644 index 000000000..a5fd1893d --- /dev/null +++ b/src/libCom/test/testMain.h @@ -0,0 +1,46 @@ +/*************************************************************************\ +* Copyright (c) 2006 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. +\*************************************************************************/ +/* $Id$ */ + +#ifndef INC_testMain_H +#define INC_testMain_H + +/* This header defines a convenience macro for use by pure test programs. + * A pure test program cannot take any arguments since it must be fully + * automatable. If your program needs to use argv/argc, it may be doing + * measurements not unit and/or regression testing. On Host architectures + * these programs needs to be named main and take dummy argc/argv args, + * but on vxWorks and RTEMS they must be named as the test program. + * + * Use this macro as follows: + * + * #include "testMain.h" + * #include "epicsUnitTest.h" + * + * MAIN(myProgTest) { + * testPlan(...); + * testOk(...) + * return testDone(); + * } + */ + +#if defined(vxWorks) || defined(__rtems__) + #ifdef __cplusplus + #define MAIN(prog) extern "C" int prog(void) + #else + #define MAIN(prog) int prog() + #endif +#else + #ifdef __cplusplus + #define MAIN(prog) int main(int /*argc*/, char * /*argv*/ [] ) + #else + #define MAIN(prog) int main(int argc, char *argv[] ) + #endif +#endif + + +#endif /* INC_testMain_H */