From 0bddd7dc8c18baa6ef2731c7865db167d15e7fc0 Mon Sep 17 00:00:00 2001 From: Andrew Johnson Date: Wed, 3 Sep 2008 16:48:03 +0000 Subject: [PATCH] Added Unit Test Harness to summarize results on vxWorks/RTEMS. Added taskwdTest to tests run. --- src/libCom/misc/epicsUnitTest.c | 96 +++++++++++++++++++++-- src/libCom/misc/epicsUnitTest.h | 9 ++- src/libCom/test/epicsRunLibComTests.c | 105 +++++++++----------------- 3 files changed, 135 insertions(+), 75 deletions(-) diff --git a/src/libCom/misc/epicsUnitTest.c b/src/libCom/misc/epicsUnitTest.c index a28212500..b3687aefa 100644 --- a/src/libCom/misc/epicsUnitTest.c +++ b/src/libCom/misc/epicsUnitTest.c @@ -16,12 +16,23 @@ #include #include -#define epicsExportSharedSymbols #include "epicsThread.h" #include "epicsMutex.h" #include "epicsUnitTest.h" +#include "epicsExit.h" +#include "epicsTime.h" +#include "ellLib.h" + +typedef struct { + ELLNODE node; + const char *name; + int tests; + int failures; + int skips; +} testFailure; static epicsMutexId testLock = 0; +static int perlHarness; static int planned; static int tested; static int passed; @@ -30,10 +41,19 @@ static int skipped; static int bonus; static const char *todo; +epicsTimeStamp started; +static int Harness; +static int Programs; +static int Tests; + +ELLLIST faults; +const char *testing = NULL; + static epicsThreadOnceId onceFlag = EPICS_THREAD_ONCE_INIT; static void testOnce(void *dummy) { testLock = epicsMutexMustCreate(); + perlHarness = (getenv("HARNESS_ACTIVE") != NULL); } void testPlan(int plan) { @@ -136,15 +156,14 @@ void testAbort(const char *fmt, ...) { } static void testResult(const char *result, int count) { - printf("%12.12s: %2d = %d%%\n", result, count, 100 * count / tested); + printf("%12.12s: %3d = %5.2f%%\n", result, count, 100.0 * count / tested); } int testDone(void) { int status = 0; - char *harness = getenv("HARNESS_ACTIVE"); epicsMutexMustLock(testLock); - if (harness) { + if (perlHarness) { if (!planned) printf("1..%d\n", tested); } else { if (planned && tested > planned) { @@ -154,7 +173,7 @@ int testDone(void) { printf("\nPlanned %d tests but only ran %d\n", planned, tested); status = 2; } - printf("\n Results\n =======\n Tests: %d\n", tested); + printf("\n Results\n =======\n Tests: %-3d\n", tested); if (tested) { testResult("Passed", passed); if (bonus) testResult("Todo Passes", bonus); @@ -165,6 +184,73 @@ int testDone(void) { if (skipped) testResult("Skipped", skipped); } } + if (Harness) { + if (failed) { + testFailure *fault = calloc(1, sizeof(testFailure)); + fault->name = testing; + fault->tests = tested; + fault->failures = failed; + fault->skips = skipped; + ellAdd(&faults, &fault->node); + } + Programs++; + Tests += tested; + } epicsMutexUnlock(testLock); return (status); } + + +/* Our test harness, for RTEMS and vxWorks */ + +static void harnessExit(void *dummy) { + epicsTimeStamp ended; + int Faulty; + + if (!Harness) return; + + epicsTimeGetCurrent(&ended); + + printf("\n\n EPICS Test Harness Results" + "\n ==========================\n\n"); + + Faulty = ellCount(&faults); + if (!Faulty) + printf("All tests successful.\n"); + else { + int Failures = 0; + testFailure *f; + + printf("Failing Program Tests Faults\n" + "---------------------------------------\n"); + while ((f = (testFailure *)ellGet(&faults))) { + Failures += f->failures; + printf("%-25s %5d %5d\n", f->name, f->tests, f->failures); + if (f->skips) + printf("%d subtests skipped\n", f->skips); + free(f); + } + printf("\nFailed %d/%d test programs. %d/%d subtests failed.\n", + Faulty, Programs, Failures, Tests); + } + + printf("Programs=%d, Tests=%d, %.0f wallclock secs\n\n", + Programs, Tests, epicsTimeDiffInSeconds(&ended, &started)); +} + +void testHarness(void) { + epicsThreadOnce(&onceFlag, testOnce, NULL); + epicsAtExit(harnessExit, NULL); + Harness = 1; + Programs = 0; + Tests = 0; + ellInit(&faults); + epicsTimeGetCurrent(&started); +} + +void runTestFunc(const char *name, TESTFUNC func) { + printf("\n***** %s *****\n", name); + testing = name; + func(); /* May not return */ + epicsThreadSleep(1.0); +} diff --git a/src/libCom/misc/epicsUnitTest.h b/src/libCom/misc/epicsUnitTest.h index 195611130..b6fb6d23d 100644 --- a/src/libCom/misc/epicsUnitTest.h +++ b/src/libCom/misc/epicsUnitTest.h @@ -1,5 +1,5 @@ /*************************************************************************\ -* Copyright (c) 2006 The University of Chicago, as Operator of Argonne +* Copyright (c) 2008 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. @@ -37,6 +37,13 @@ epicsShareFunc int testDone(void); #define testOk1(cond) testOk(cond, "%s", #cond) + +typedef int (*TESTFUNC)(void); +epicsShareFunc void testHarness(void); +epicsShareFunc void runTestFunc(const char *name, TESTFUNC func); + +#define runTest(func) runTestFunc(#func, func) + #ifdef __cplusplus } #endif diff --git a/src/libCom/test/epicsRunLibComTests.c b/src/libCom/test/epicsRunLibComTests.c index 8b74c24bc..e5e7058e0 100644 --- a/src/libCom/test/epicsRunLibComTests.c +++ b/src/libCom/test/epicsRunLibComTests.c @@ -6,14 +6,14 @@ \*************************************************************************/ /* - * Run tests as a batch + * Run libCom tests as a batch * * This is part of the work being done to provide a unified set of automated * tests for EPICS. Many more changes will be forthcoming. */ #include #include -#include +#include int epicsThreadTest(void); int epicsTimerTest(void); @@ -33,92 +33,59 @@ int macLibTest(void); int macEnvExpandTest(void); int ringPointerTest(void); int blockingSockTest(void); +int taskwdTest(void); int epicsExitTest(void); -void -epicsRunLibComTests(void) +void epicsRunLibComTests(void) { - /* - * Thread startup sets some internal variables so do it first - */ - printf("\n****** Thread Test *****\n"); - epicsThreadTest (); - epicsThreadSleep (1.0); + testHarness(); - /* - * Timer tests get confused if run after some of the other tests - */ - printf("\n****** Timer Test *****\n"); - epicsTimerTest (); - epicsThreadSleep (1.0); + /* + * Thread startup sets some internal variables so do it first + */ + runTest(epicsThreadTest); - printf("\n****** Algorithm Test *****\n"); - epicsAlgorithm (); - epicsThreadSleep (1.0); + /* + * Timer tests get confused if run after some of the other tests + */ + runTest(epicsTimerTest); - printf("\n****** Calculation Test *****\n"); - epicsCalcTest(); - epicsThreadSleep (1.0); + runTest(epicsAlgorithm); - printf("\n****** Event Test *****\n"); - epicsEventTest (); - epicsThreadSleep (1.0); + runTest(epicsCalcTest); - printf("\n****** Exception Test *****\n"); - epicsExceptionTest (); - epicsThreadSleep (1.0); + runTest(epicsEventTest); - printf("\n****** Math Test *****\n"); - epicsMathTest (); - epicsThreadSleep (1.0); + runTest(epicsExceptionTest); - printf("\n****** Message Queue Test *****\n"); - epicsMessageQueueTest (); - epicsThreadSleep (1.0); + runTest(epicsMathTest); - printf("\n****** Mutex Test *****\n"); - epicsMutexTest (); - epicsThreadSleep (1.0); + runTest(epicsMessageQueueTest); - printf("\n****** Stdio Test *****\n"); - epicsStdioTest (); - epicsThreadSleep (1.0); + runTest(epicsMutexTest); - printf("\n****** String Test *****\n"); - epicsStringTest (); - epicsThreadSleep (1.0); + runTest(epicsStdioTest); - printf("\n****** Thread Priority Test *****\n"); - epicsThreadPriorityTest (); - epicsThreadSleep (1.0); + runTest(epicsStringTest); - printf("\n****** Thread Private Test *****\n"); - epicsThreadPrivateTest (); - epicsThreadSleep (1.0); + runTest(epicsThreadPriorityTest); - printf("\n****** Time Test *****\n"); - epicsTimeTest (); - epicsThreadSleep (1.0); + runTest(epicsThreadPrivateTest); - printf("\n****** Macro Library Test *****\n"); - macLibTest (); - epicsThreadSleep (1.0); + runTest(epicsTimeTest); - printf("\n****** Macro Environment Variable Expansion Test *****\n"); - macEnvExpandTest (); - epicsThreadSleep (1.0); + runTest(macLibTest); - printf("\n****** Ring Pointer Test *****\n"); - ringPointerTest (); - epicsThreadSleep (1.0); + runTest(macEnvExpandTest); - printf("\n****** Check socket behaviour *****\n"); - blockingSockTest(); - epicsThreadSleep (1.0); + runTest(ringPointerTest); - /* - * Must come last - */ - printf("\n****** EpicsExit Test *****\n"); - epicsExitTest(); /* Never returns */ + runTest(blockingSockTest); + + runTest(taskwdTest); + + /* + * Exit must come last as it never returns + */ + runTest(epicsExitTest); }