1
We have implemented a number of applications to test the qsastime library.
2
In general, if you want to build any of these test applications you specify
3
the cmake option -DTEST_QSASTIME=ON (but an additional option has to be
4
set for the qsastime_testlib case discussed below in III).
6
(I) lib/qsastime/qsastime_test is automatically built in the build tree if
7
-DTEST_QSASTIME=ON. This test routine does some minimal tests of the
8
qsastime library using the C library. Because the date range is so small, I
9
believe this test builds and runs on every platform without running into C
10
library limitations. Note some of the results of this test depend on C
11
library routines whose results depend on the local time zone.
13
Run this test as follows from the top of the build tree
15
lib/qsastime/qsastime_test >qsastime_test.out
17
Then compare these output results with those at
18
lib/qsastime/qsastime_test.out_standard in the source tree. Your results
19
will differ in some respects if you have a different time zone than the PST
20
(7 hours west of Greenwich) time zone where the
21
lib/qsastime/qsastime_test.out_standard result was produced.
23
(II) lib/qsastime/bhunt_search_test is automatically built in the build tree
24
if -DTEST_QSASTIME=ON. Depending on input, this test routine is capable of
25
severe testing of the bhunt_search routine in the qsastime library.
27
The point of bhunt_search is to avoid scanning through the whole leap second
28
table every time you are dealing with a broken-down or continuous time. So
29
this algorithm follows the general idea in Numerical Recipes of first having
30
a hunt phase where the increment (or decrement) in index is doubled until
31
the value is bracketed, and then bisection is used to find the index such
34
x[index] <= value < x[index+1], (1)
36
This has been implemented as a completely generalized routine so "<=" and
37
"<" stand for a generalized comparison of anything that can be stuffed into
38
a struct, with the comparisons provided by a callback routine.
40
bhunt_search_test tests bhunt_search as follows:
42
ntable, offset, and multiplier values are provided via stdin.
43
bhunt_search_test then creates a table of ntable double values (of 0.
44
through (double) ntable-1) and searches that table at a set of
46
ntest = (ntable-1)*multiplier +1 (2)
48
points which are offset from the table range by offset. (Thus, large
49
positive or negative offset values allow you to test repeated searches for
50
data beyond the ends of the table.) An offset of zero and a multiplier of 1
51
mean you search the table for the exact table values rather than something
52
in between the table values. For each of the ntest values, bhunt_search
53
returns an index which the test routine then tests to make sure it
54
satisfies condition 1 above.
56
Here are some typical results for a table with 64 values (somewhat larger
57
than the current TAI-UTC offset table which has 38 values.)
59
software@raven> echo '64 0 1000'| lib/qsastime/bhunt_search_test
60
ntable, offset, multiplier, ntest = 64, 0, 1000, 63001
61
Average number of gedouble calls per bhunt_search call = 6.015889 for
62
ifhunt, ifrandom = 0,0
63
Average number of gedouble calls per bhunt_search call = 6.016444 for
64
ifhunt, ifrandom = 0,1
65
Average number of gedouble calls per bhunt_search call = 2.002016 for
66
ifhunt, ifrandom = 1,0
67
Average number of gedouble calls per bhunt_search call = 8.502754 for
68
ifhunt, ifrandom = 1,1
69
Successful completion of bhunt_search test
70
software@raven> echo '64 -64 1000'| lib/qsastime/bhunt_search_test
71
ntable, offset, multiplier, ntest = 64, -64, 1000, 63001
72
Average number of gedouble calls per bhunt_search call = 6.000000 for
73
ifhunt, ifrandom = 0,0
74
Average number of gedouble calls per bhunt_search call = 6.000000 for
75
ifhunt, ifrandom = 0,1
76
Average number of gedouble calls per bhunt_search call = 1.000079 for
77
ifhunt, ifrandom = 1,0
78
Average number of gedouble calls per bhunt_search call = 1.000079 for
79
ifhunt, ifrandom = 1,1
80
Successful completion of bhunt_search test
81
software@raven> echo '64 64 1000'| lib/qsastime/bhunt_search_test
82
ntable, offset, multiplier, ntest = 64, 64, 1000, 63001
83
Average number of gedouble calls per bhunt_search call = 7.000000 for
84
ifhunt, ifrandom = 0,0
85
Average number of gedouble calls per bhunt_search call = 7.000000 for
86
ifhunt, ifrandom = 0,1
87
Average number of gedouble calls per bhunt_search call = 1.000095 for
88
ifhunt, ifrandom = 1,0
89
Average number of gedouble calls per bhunt_search call = 1.000095 for
90
ifhunt, ifrandom = 1,1
91
Successful completion of bhunt_search test
93
Here are results for a table with one million values.
95
software@raven> echo '1000000 0 10'| lib/qsastime/bhunt_search_test
96
ntable, offset, multiplier, ntest = 1000000, 0, 10, 9999991
97
Average number of gedouble calls per bhunt_search call = 19.951426 for ifhunt, ifrandom = 0,0
98
Average number of gedouble calls per bhunt_search call = 19.951496 for ifhunt, ifrandom = 0,1
99
Average number of gedouble calls per bhunt_search call = 2.200001 for ifhunt, ifrandom = 1,0
100
Average number of gedouble calls per bhunt_search call = 35.978823 for ifhunt, ifrandom = 1,1
101
Successful completion of bhunt_search test
103
As expected for a table with 2^6 = 64 entries, bhunt_search requires only an
104
average of 6 calls to gedouble (my simple callback test code inside
105
bhunt_search_test.c which compares two floating point numbers) to search per
106
bhunt_search call if you turn off the hunt phase part of the routine. That
107
number drops down close to 2 if the hunt phase is turned on and the
108
successive numbers tend to be correlated (as happens quite often with time
109
variables, for example). The number drops close to unity if you are beyond
110
the end of the table (which also happens often for time variables). The
111
hunt phase actually slows down the search for completely uncorrelated (i.e.,
112
random) variables, but that is a rare case for time variables so within the
113
qsastime library, the the hunt phase is always turned on when using
114
bhunt_search to determine the offset between TAI and UTC.
116
For fun, I also showed a test above for a large table of one million values
117
(near 2^20). As expected bhunt_search scales well for this case requiring
118
an average of only 20 calls to gedouble if the hunt phase is turned off and
119
only 2 calls to geodouble if the hunt phase is turned on for correlated
122
(III) lib/qsastime/qsastime_testlib is automatically built in the build tree
123
if _both_ -DTEST_QSASTIME=ON and -DBUILD_QSASTIME_TESTLIB=ON. This test
124
routine tests the qsastime library over essentially the complete range of
125
possible dates that can be represented internally without integer overflow
126
by the qsastime library continuous time variable which stores the integer
127
part of the MJD as a signed int. This works out to a range of +/-5.9
128
million years from the (Gregorian and Julian) calendar epoch. The actual
129
tests in lib/qsastime/qsastime_testlib range over +/- 5 million years from
132
Internally our build system forces BUILD_QSASTIME_TESTLIB to OFF for the
133
Windows (WIN32) case because we have found in practice that the Windows C
134
library time function limitations are so severe (e.g., dates prior to 1970
135
give incorrect results) that this test of a large date range is worthless on
136
Windows. Also, once we acknowledged that Windows was never going to give
137
good results for this test because of limitations in the Windows C library,
138
it greatly simplified the programming of qsastime_testlib to ignore the
139
Windows case completely. N.B. This is just an issue with the
140
qsastime_testlib routine. The qsastime library itself works fine on Windows
141
because it specifically avoids using any C library time routines.
143
For 32-bit Linux platforms qsastime_testlib is also worthless because of
144
limitations in the 32-bit C Linux library (e.g., the date range is limited
145
to just 1902 through 2038). However, qsastime_testlib gives excellent
146
results for the 64-bit Linux C library. To avoid wasting time on a
147
32-bit test, we have installed a check in qsastime_testlib which refuses to
148
run the test if (sizeof(time_t) < 8). N.B. The sizeof(time_t) issue is only
149
relevant for the qsastime_testlib routine. The qsastime library itself
150
works fine on 32-bit platforms because it specifically avoids using any C
151
library time routines.
153
On 64-bit Linux (and possibly Mac OS X) platforms run this test as follows:
155
echo 0xffff |lib/qsastime/qsastime_testlib > qsastime_testlib.out
157
Then compare these output results with those at
158
lib/qsastime/qsastime_testlib.out_standard in the source tree. They should
159
be identical in all cases because the C library time routines that
160
qsastime_testlib calls are made independent of time zone issues by forcing a
161
zero time zone. (The qsastime library itself is, of course, independent of
164
N.B. this comprehensive test of the qsastime library takes 12
165
minutes to run on a 2.4GHz PC.