Converted some of the test routines to use the new epicsUnitTest facility.
This commit is contained in:
@@ -14,40 +14,13 @@
|
||||
#include <time.h>
|
||||
#include <math.h>
|
||||
#include <limits.h>
|
||||
#include <cstring>
|
||||
#include <string.h>
|
||||
|
||||
#include "epicsTime.h"
|
||||
#include "epicsThread.h"
|
||||
#include "errlog.h"
|
||||
#include "epicsUnitTest.h"
|
||||
|
||||
extern "C" {
|
||||
int epicsTimeTest (void);
|
||||
}
|
||||
|
||||
void invalidFormatTest ()
|
||||
{
|
||||
epicsTime ts ( epicsTime::getCurrent () );
|
||||
char bigBuf [512];
|
||||
char buf [32];
|
||||
memset ( bigBuf, '\a', sizeof ( bigBuf ) );
|
||||
bigBuf [ sizeof ( bigBuf ) - 1 ] = '\0';
|
||||
ts.strftime ( buf, sizeof ( buf ), bigBuf );
|
||||
printf ("A huge strftime format produces this result \"%s\"\n", buf );
|
||||
}
|
||||
|
||||
void badNanosecTest ()
|
||||
{
|
||||
static const char * pFormat = "%a %b %d %Y %H:%M:%S.%4f";
|
||||
try {
|
||||
const epicsTimeStamp ets = { 1, 1000000000 };
|
||||
epicsTime ts ( ets );
|
||||
char buf [32];
|
||||
ts.strftime ( buf, sizeof ( buf ), pFormat );
|
||||
printf ("A nano-sec overflow produces this result \"%s\"\n", buf );
|
||||
}
|
||||
catch ( ... ) {
|
||||
}
|
||||
}
|
||||
|
||||
struct l_fp { /* NTP time stamp */
|
||||
epicsUInt32 l_ui; /* sec past NTP epoch */
|
||||
@@ -60,44 +33,17 @@ static const unsigned mSecPerSec = 1000u;
|
||||
static const unsigned uSecPerSec = 1000u * mSecPerSec;
|
||||
static const unsigned nSecPerSec = 1000u * uSecPerSec;
|
||||
|
||||
void testStringConversion()
|
||||
{
|
||||
char buf[64];
|
||||
epicsTime uninit;
|
||||
|
||||
const char * pFormat = "%a %b %d %Y %H:%M:%S.%f";
|
||||
uninit.strftime ( buf, sizeof ( buf ), pFormat );
|
||||
printf ("Uninitialized using \"%s\" %s\n", pFormat, buf );
|
||||
|
||||
epicsTime current = epicsTime::getCurrent();
|
||||
|
||||
pFormat = "%a %b %d %Y %H:%M:%S.%f";
|
||||
current.strftime ( buf, sizeof ( buf ), pFormat );
|
||||
printf ("using \"%s\" %s\n", pFormat, buf );
|
||||
|
||||
pFormat = "%a %b %d %Y %H:%M:%S.%4f";
|
||||
current.strftime ( buf, sizeof ( buf ), pFormat );
|
||||
printf ("using \"%s\" %s\n", pFormat, buf );
|
||||
|
||||
pFormat = "%a %b %d %Y %H:%M:%S.%05f";
|
||||
current.strftime ( buf, sizeof ( buf ), pFormat );
|
||||
printf ("using \"%s\" %s\n", pFormat, buf );
|
||||
|
||||
}
|
||||
|
||||
extern "C"
|
||||
int epicsTimeTest (void)
|
||||
{
|
||||
unsigned errors, sum_errors=0, sum_errloops=0;
|
||||
const epicsTime begin = epicsTime::getCurrent();
|
||||
const unsigned wasteTime = 100000u;
|
||||
const int nTimes = 100;
|
||||
epicsTimeStamp stamp;
|
||||
struct timespec ts;
|
||||
struct tm tmAnsi;
|
||||
local_tm_nano_sec ansiDate;
|
||||
gm_tm_nano_sec ansiDateGMT;
|
||||
unsigned long nanoSec;
|
||||
const int nTimes = 10;
|
||||
const double precisionEPICS = 1.0 / nSecPerSec;
|
||||
|
||||
testPlan(7 + nTimes * 18);
|
||||
|
||||
const epicsTime begin = epicsTime::getCurrent();
|
||||
{
|
||||
epicsTime tsi = epicsTime::getCurrent ();
|
||||
l_fp ntp = tsi;
|
||||
@@ -105,14 +51,63 @@ int epicsTimeTest (void)
|
||||
const double diff = fabs ( tsf - tsi );
|
||||
// the difference in the precision of the two time formats
|
||||
static const double precisionNTP = 1.0 / ( 1.0 + 0xffffffff );
|
||||
static const double precisionEPICS = 1.0 / nSecPerSec;
|
||||
assert ( diff <= precisionEPICS + precisionNTP );
|
||||
testOk1(diff <= precisionEPICS + precisionNTP);
|
||||
}
|
||||
|
||||
invalidFormatTest ();
|
||||
badNanosecTest ();
|
||||
|
||||
printf ("epicsTime Test (%3d loops)\n========================\n\n", nTimes);
|
||||
{
|
||||
static const char * pFormat = "%a %b %d %Y %H:%M:%S.%4f";
|
||||
try {
|
||||
const epicsTimeStamp badTS = {1, 1000000000};
|
||||
epicsTime ts(badTS);
|
||||
char buf [32];
|
||||
ts.strftime(buf, sizeof(buf), pFormat);
|
||||
testFail("nanosecond overflow throws");
|
||||
testDiag("nanosecond overflow result is \"%s\"", buf);
|
||||
}
|
||||
catch ( ... ) {
|
||||
testPass("nanosecond overflow throws");
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
char buf[64];
|
||||
epicsTime et;
|
||||
|
||||
const char * pFormat = "%Y-%m-%d %H:%M:%S.%f";
|
||||
et.strftime(buf, sizeof(buf), pFormat);
|
||||
testOk(strcmp(buf, "<undefined>") == 0, "undefined strftime") ||
|
||||
testDiag("undefined.strftime(\"%s\") = \"%s\"", pFormat, buf);
|
||||
|
||||
// This is Noon GMT, when all timezones have the same date
|
||||
const epicsTimeStamp tTS = {12*60*60, 98765432};
|
||||
et = tTS;
|
||||
pFormat = "%Y-%m-%d %S.%09f"; // %H and %M change with timezone
|
||||
et.strftime(buf, sizeof(buf), pFormat);
|
||||
testOk(strcmp(buf, "1990-01-01 00.098765432") == 0, pFormat) ||
|
||||
testDiag("t.strftime(\"%s\") = \"%s\"", pFormat, buf);
|
||||
|
||||
pFormat = "%S.%04f";
|
||||
et.strftime(buf, sizeof(buf), pFormat);
|
||||
testOk(strcmp(buf, "00.0988") == 0, pFormat) ||
|
||||
testDiag("t.strftime(\"%s\") = \"%s\"", pFormat, buf);
|
||||
|
||||
pFormat = "%S.%05f";
|
||||
et.strftime(buf, sizeof(buf), pFormat);
|
||||
testOk(strcmp(buf, "00.09877") == 0, pFormat) ||
|
||||
testDiag("t.strftime(\"%s\") = \"%s\"", pFormat, buf);
|
||||
}
|
||||
|
||||
{
|
||||
char bigBuf [512];
|
||||
char buf [32];
|
||||
memset(bigBuf, '\a', sizeof(bigBuf ));
|
||||
bigBuf[ sizeof(bigBuf) - 1] = '\0';
|
||||
begin.strftime(buf, sizeof(buf), bigBuf);
|
||||
testOk(strcmp(buf, "<invalid format>") == 0, "strftime(huge)") ||
|
||||
testDiag("strftime(huge) = \"%s\"", buf);
|
||||
}
|
||||
|
||||
testDiag("Running %d loops", nTimes);
|
||||
|
||||
for (int iTimes=0; iTimes < nTimes; ++iTimes) {
|
||||
for (unsigned i=0; i<wasteTime; i++) {
|
||||
@@ -120,135 +115,52 @@ int epicsTimeTest (void)
|
||||
}
|
||||
|
||||
const epicsTime end = epicsTime::getCurrent();
|
||||
|
||||
const double diff = end - begin;
|
||||
|
||||
if (iTimes == 0) {
|
||||
printf ("Time per call to epicsTime::getCurrent() "
|
||||
"(%d calls) = %6.3f usec\n\n", wasteTime,
|
||||
testDiag ("%d calls to epicsTime::getCurrent() "
|
||||
"averaged %6.3f usec each", wasteTime,
|
||||
diff*1e6/wasteTime);
|
||||
stamp = begin;
|
||||
ansiDate = begin;
|
||||
ansiDateGMT = begin;
|
||||
ts = begin;
|
||||
printf ("The following should be your local time\ndisplayed using "
|
||||
"four different internal representations:\n\n");
|
||||
epicsTimeToTM (&tmAnsi, &nanoSec, &stamp);
|
||||
|
||||
printf ("epicsTimeStamp = %s %lu nSec \n", asctime(&tmAnsi), nanoSec);
|
||||
printf ("local time zone struct tm = %s %f\n", asctime(&ansiDate.ansi_tm),
|
||||
ansiDate.nSec/(double)nSecPerSec);
|
||||
printf ("struct timespec = %s %f\n", asctime(&ansiDate.ansi_tm),
|
||||
ts.tv_nsec/(double)nSecPerSec);
|
||||
printf ("UTC struct tm = %s %f\n", asctime(&ansiDateGMT.ansi_tm),
|
||||
ansiDateGMT.nSec/(double)nSecPerSec);
|
||||
begin.show (100);
|
||||
printf ("\n");
|
||||
} else {
|
||||
if (iTimes % 10 == 0)
|
||||
printf (" ... now at loop %3d\n", iTimes);
|
||||
}
|
||||
}
|
||||
|
||||
epicsTime copy = end;
|
||||
errors = 0;
|
||||
testOk1(copy == end);
|
||||
testOk1(copy <= end);
|
||||
testOk1(copy >= end);
|
||||
|
||||
if (!(copy==end)) {
|
||||
printf ("#%3d: Failed copy==end by %12.9f\n",
|
||||
iTimes, fabs(copy-end));
|
||||
errors += 1;
|
||||
}
|
||||
if (!(copy<=end)) {
|
||||
printf ("#%3d: Failed copy<=end by %12.9f\n",
|
||||
iTimes, (copy-end));
|
||||
errors += 1;
|
||||
}
|
||||
if (!(copy>=end)) {
|
||||
printf ("#%3d: Failed copy>=end by %12.9f\n",
|
||||
iTimes, (end-copy));
|
||||
errors += 1;
|
||||
}
|
||||
if (!(end>begin)) {
|
||||
printf ("#%3d: Failed end>begin by %12.9f\n",
|
||||
iTimes, (begin-end));
|
||||
errors += 1;
|
||||
}
|
||||
if (!(end>=begin)) {
|
||||
printf ("#%3d: Failed end>=begin by %12.9f\n",
|
||||
iTimes, (begin-end));
|
||||
errors += 1;
|
||||
}
|
||||
if (!(begin<end)) {
|
||||
printf ("#%3d: Failed begin<end by %12.9f\n",
|
||||
iTimes, (begin-end));
|
||||
errors += 1;
|
||||
}
|
||||
if (!(begin<=end)) {
|
||||
printf ("#%3d: Failed begin<=end by %12.9f\n",
|
||||
iTimes, (begin-end));
|
||||
errors += 1;
|
||||
}
|
||||
if (!(begin!=end)) {
|
||||
printf ("#%3d: Failed begin!=end\n",iTimes);
|
||||
errors += 1;
|
||||
}
|
||||
const double diff2 = end - begin;
|
||||
if (!(diff2==diff)) {
|
||||
printf ("#%3d: Failed end-begin==diff by %g\n",
|
||||
iTimes, fabs(diff2-diff));
|
||||
errors += 1;
|
||||
}
|
||||
testOk1(end > begin);
|
||||
testOk1(end >= begin);
|
||||
testOk1(begin != end);
|
||||
testOk1(begin < end);
|
||||
testOk1(begin <= end);
|
||||
|
||||
testOk1(end - end == 0);
|
||||
testOk(fabs((end - begin) - diff) < precisionEPICS * 0.01,
|
||||
"end - begin ~= diff");
|
||||
|
||||
testOk1(begin + 0 == begin);
|
||||
testOk1(begin + diff == end);
|
||||
testOk1(end - 0 == end);
|
||||
testOk1(end - diff == begin);
|
||||
|
||||
epicsTime end2 = begin;
|
||||
end2 += diff;
|
||||
if (!(end2==end)) {
|
||||
printf ("#%3d: Failed (begin+=diff)==end by %12.9f\n",
|
||||
iTimes, fabs(begin-end));
|
||||
errors += 1;
|
||||
}
|
||||
end2 += diff;
|
||||
testOk(end2 == end, "(begin += diff) == end");
|
||||
|
||||
end2 = end;
|
||||
end2 -= diff;
|
||||
if (!(end2+diff==end)) {
|
||||
printf ("#%3d: Failed begin+diff==end by %12.9f\n",
|
||||
iTimes, fabs(begin+diff-end));
|
||||
errors += 1;
|
||||
}
|
||||
testOk(end2 == begin, "(end -= diff) == begin");
|
||||
|
||||
//
|
||||
// test struct tm conversions
|
||||
//
|
||||
ansiDate = begin;
|
||||
epicsTime beginANSI = ansiDate;
|
||||
if (!(beginANSI+diff==end)) {
|
||||
printf ("#%3d: Failed begin+diff==end "
|
||||
"after tm conversions by %12.9f\n",
|
||||
iTimes, fabs(begin+diff-end));
|
||||
errors += 1;
|
||||
}
|
||||
// test struct tm round-trip conversion
|
||||
local_tm_nano_sec ansiDate = begin;
|
||||
epicsTime beginANSI = ansiDate;
|
||||
testOk1(beginANSI + diff == end);
|
||||
|
||||
//
|
||||
// test struct timespec conversion
|
||||
//
|
||||
ts = begin;
|
||||
// test struct timespec round-trip conversion
|
||||
struct timespec ts = begin;
|
||||
epicsTime beginTS = ts;
|
||||
if (!(beginTS+diff==end)) {
|
||||
printf ("#%3d: Failed begin+diff==end "
|
||||
"after timespec conversions by %12.9f\n",
|
||||
iTimes, fabs(begin+diff-end));
|
||||
errors += 1;
|
||||
}
|
||||
|
||||
if (errors) {
|
||||
printf ("#%3d: begin ", iTimes); begin.show(0);
|
||||
printf ("#%3d: end ", iTimes); end.show(0);
|
||||
printf ("#%3d: diff %12.9f\n\n", iTimes, diff);
|
||||
sum_errors += errors;
|
||||
sum_errloops += 1;
|
||||
}
|
||||
testOk1(beginTS + diff == end);
|
||||
}
|
||||
|
||||
printf ("epicsTime test complete. Summary: %d errors found "
|
||||
"in %d out of %d loops.\n",
|
||||
sum_errors, sum_errloops, nTimes);
|
||||
|
||||
return (sum_errors?1:0);
|
||||
return testDone();
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user