diff --git a/src/libCom/test/epicsMessageQueueTest.cpp b/src/libCom/test/epicsMessageQueueTest.cpp index 3bd47ae27..e4216c291 100644 --- a/src/libCom/test/epicsMessageQueueTest.cpp +++ b/src/libCom/test/epicsMessageQueueTest.cpp @@ -25,8 +25,10 @@ #include "testMain.h" static const char *msg1 = "1234567890This is a very long message."; -static volatile int testExit = 0; +static volatile int sendExit = 0; +static volatile int recvExit = 0; static epicsEventId finished; +static unsigned int mediumStack; /* * In Numerical Recipes in C: The Art of Scientific Computing (William H. @@ -77,6 +79,7 @@ extern "C" void receiver(void *arg) { epicsMessageQueue *q = (epicsMessageQueue *)arg; + const char *myName = epicsThreadGetNameSelf(); char cbuf[80]; int expectmsg[4]; int len; @@ -85,10 +88,10 @@ receiver(void *arg) for (sender = 1 ; sender <= 4 ; sender++) expectmsg[sender-1] = 1; - while (!testExit) { + while (!recvExit) { cbuf[0] = '\0'; len = q->receive(cbuf, sizeof cbuf, 5.0); - if (len < 0 && !testExit) { + if (len < 0 && !recvExit) { testDiag("receiver() received unexpected timeout"); ++errors; } @@ -96,7 +99,8 @@ receiver(void *arg) sender >= 1 && sender <= 4) { if (expectmsg[sender-1] != msgNum) { ++errors; - testDiag("%s received %d '%.*s' -- expected %d", epicsThreadGetNameSelf(), len, len, cbuf, expectmsg[sender-1]); + testDiag("%s received %d '%.*s' -- expected %d", + myName, len, len, cbuf, expectmsg[sender-1]); } expectmsg[sender-1] = msgNum + 1; epicsThreadSleep(0.001 * (randBelow(20))); @@ -104,10 +108,12 @@ receiver(void *arg) } for (sender = 1 ; sender <= 4 ; sender++) { if (expectmsg[sender-1] > 1) - testDiag("Sender %d -- %d messages", sender, expectmsg[sender-1]-1); + testDiag("Received %d messages from Sender %d", + expectmsg[sender-1]-1, sender); } if (!testOk1(errors == 0)) - testDiag("Receiver finished, error count was %d", errors); + testDiag("Error count was %d", errors); + testDiag("%s exiting", myName); epicsEventSignal(finished); } @@ -119,17 +125,18 @@ sender(void *arg) int len; int i = 0; - while (!testExit) { + while (!sendExit) { len = sprintf(cbuf, "%s -- %d.", epicsThreadGetNameSelf(), ++i); while (q->trySend((void *)cbuf, len) < 0) epicsThreadSleep(0.005 * (randBelow(5))); epicsThreadSleep(0.005 * (randBelow(20))); } - testDiag("%s exiting, sent %d messages", epicsThreadGetNameSelf(), i-1); + testDiag("%s exiting, sent %d messages", epicsThreadGetNameSelf(), i); } extern "C" void messageQueueTest(void *parm) { + epicsThreadId myThreadId = epicsThreadGetIdSelf(); unsigned int i; char cbuf[80]; int len; @@ -151,20 +158,23 @@ extern "C" void messageQueueTest(void *parm) len = q1->receive(cbuf, sizeof 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); + testDiag("wanted:%d '%.*s' got:%d '%.*s'", + want, want, msg1, len, len, cbuf); want++; len = q1->receive(cbuf, sizeof 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); + 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); 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); + testDiag("wanted:%d '%.*s' got:%d '%.*s'", + want, want, msg1, len, len, cbuf); q1->trySend((void *)msg1, i++); testOk1(q1->pending() == 3); @@ -174,7 +184,8 @@ extern "C" void messageQueueTest(void *parm) testOk(q1->pending() == i, "q1->pending() == %d", i); want++; if (!testOk1((len == want) & (strncmp(msg1, cbuf, len) == 0))) - testDiag("wanted:%d '%.*s' got:%d '%.*s'", want, want, msg1, len, len, cbuf); + testDiag("wanted:%d '%.*s' got:%d '%.*s'", + want, want, msg1, len, len, cbuf); } testOk1(q1->pending() == 0); @@ -191,20 +202,23 @@ extern "C" void messageQueueTest(void *parm) len = q1->receive(cbuf, sizeof 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); + testDiag("wanted:%d '%.*s' got:%d '%.*s'", + want, want, msg1, len, len, cbuf); want++; len = q1->receive(cbuf, sizeof 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); + 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); 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); + testDiag("wanted:%d '%.*s' got:%d '%.*s'", + want, want, msg1, len, len, cbuf); q1->send((void *)msg1, i++, 1.0); testOk1(q1->pending() == 3); @@ -214,7 +228,8 @@ extern "C" void messageQueueTest(void *parm) testOk(q1->pending() == i, "q1->pending() == %d", i); want++; if (!testOk1((len == want) && (strncmp(msg1, cbuf, len) == 0))) - testDiag("wanted:%d '%.*s' got:%d '%.*s'", want, want, msg1, len, len, cbuf); + testDiag("wanted:%d '%.*s' got:%d '%.*s'", + want, want, msg1, len, len, cbuf); } testOk1(q1->pending() == 0); @@ -230,7 +245,8 @@ extern "C" void messageQueueTest(void *parm) testOk1(q1->pending() == 0); testDiag("Single receiver with invalid size, single sender tests:"); - epicsThreadCreate("Bad Receiver", epicsThreadPriorityMedium, epicsThreadGetStackSize(epicsThreadStackMedium), badReceiver, q1); + epicsThreadCreate("Bad Receiver", epicsThreadPriorityMedium, + mediumStack, badReceiver, q1); epicsThreadSleep(1.0); testOk(q1->send((void *)msg1, 10) == 0, "Send with waiting receiver"); epicsThreadSleep(2.0); @@ -238,8 +254,9 @@ extern "C" void messageQueueTest(void *parm) epicsThreadSleep(2.0); testDiag("Single receiver, single sender tests:"); - epicsThreadSetPriority(epicsThreadGetIdSelf(), epicsThreadPriorityHigh); - epicsThreadCreate("Receiver one", epicsThreadPriorityMedium, epicsThreadGetStackSize(epicsThreadStackMedium), receiver, q1); + epicsThreadSetPriority(myThreadId, epicsThreadPriorityHigh); + epicsThreadCreate("Receiver one", epicsThreadPriorityMedium, + mediumStack, receiver, q1); for (pass = 1 ; pass <= 3 ; pass++) { for (i = 0 ; i < 10 ; i++) { if (q1->trySend((void *)msg1, i) < 0) @@ -251,7 +268,7 @@ extern "C" void messageQueueTest(void *parm) case 1: if (i<6) testDiag(" priority-based scheduler, sent %d messages", i); - epicsThreadSetPriority(epicsThreadGetIdSelf(), epicsThreadPriorityLow); + epicsThreadSetPriority(myThreadId, epicsThreadPriorityLow); break; case 2: if (i<10) @@ -271,27 +288,42 @@ extern "C" void messageQueueTest(void *parm) */ testDiag("Single receiver, multiple sender tests:"); testDiag("This test lasts 60 seconds..."); - epicsThreadCreate("Sender 1", epicsThreadPriorityLow, epicsThreadGetStackSize(epicsThreadStackMedium), sender, q1); - epicsThreadCreate("Sender 2", epicsThreadPriorityMedium, epicsThreadGetStackSize(epicsThreadStackMedium), sender, q1); - epicsThreadCreate("Sender 3", epicsThreadPriorityHigh, epicsThreadGetStackSize(epicsThreadStackMedium), sender, q1); - epicsThreadCreate("Sender 4", epicsThreadPriorityHigh, epicsThreadGetStackSize(epicsThreadStackMedium), sender, q1); + testOk(!!epicsThreadCreate("Sender 1", epicsThreadPriorityLow, + mediumStack, sender, q1), + "Created Sender 1"); + testOk(!!epicsThreadCreate("Sender 2", epicsThreadPriorityMedium, + mediumStack, sender, q1), + "Created Sender 2"); + testOk(!!epicsThreadCreate("Sender 3", epicsThreadPriorityHigh, + mediumStack, sender, q1), + "Created Sender 3"); + testOk(!!epicsThreadCreate("Sender 4", epicsThreadPriorityHigh, + mediumStack, sender, q1), + "Created Sender 4"); - epicsThreadSleep(60.0); + for (i = 0; i < 10; i++) { + testDiag("... %2d", 10 - i); + epicsThreadSleep(6.0); + } - testExit = 1; + sendExit = 1; + epicsThreadSleep(1.0); + recvExit = 1; + testDiag("Scheduler exiting"); } MAIN(epicsMessageQueueTest) { - testPlan(58); + testPlan(62); finished = epicsEventMustCreate(epicsEventEmpty); + mediumStack = epicsThreadGetStackSize(epicsThreadStackMedium); epicsThreadCreate("messageQueueTest", epicsThreadPriorityMedium, - epicsThreadGetStackSize(epicsThreadStackMedium), - messageQueueTest, NULL); + mediumStack, messageQueueTest, NULL); - (void) epicsEventWait(finished); + epicsEventMustWait(finished); + testDiag("Main thread signalled"); epicsThreadSleep(1.0); return testDone(); diff --git a/src/tools/makeTestfile.pl b/src/tools/makeTestfile.pl index 3766573a6..4ac5162db 100644 --- a/src/tools/makeTestfile.pl +++ b/src/tools/makeTestfile.pl @@ -10,7 +10,7 @@ # The makeTestfile.pl script generates a file $target.t which is needed # because some versions of the Perl test harness can only run test scripts -# that are actually written in Perl. The script we generate execs the +# that are actually written in Perl. The script we generate runs the # real test program which must be in the same directory as the .t file. # If the script is given an argument -tap it sets HARNESS_ACTIVE in the # environment to make the epicsUnitTest code generate strict TAP output. @@ -23,6 +23,10 @@ use strict; my ($target, $exe) = @ARGV; +# Use system on Windows, exec doesn't work the same there and +# GNUmake thinks the test has finished as soon as Perl exits. +my $exec = $^O eq 'MSWin32' ? "system('./$exe') == 0" : "exec './$exe'"; + open(my $OUT, '>', $target) or die "Can't create $target: $!\n"; print $OUT <