5 #include "timespecops.h"
13 #define TEST_ASSERT_EQUAL_timespec(a, b) { \
14 TEST_ASSERT_EQUAL_MESSAGE(a.tv_sec, b.tv_sec, "Field tv_sec"); \
15 TEST_ASSERT_EQUAL_MESSAGE(a.tv_nsec, b.tv_nsec, "Field tv_nsec"); \
19 #define TEST_ASSERT_EQUAL_l_fp(a, b) { \
20 TEST_ASSERT_EQUAL_MESSAGE(a.l_i, b.l_i, "Field l_i"); \
21 TEST_ASSERT_EQUAL_UINT_MESSAGE(a.l_uf, b.l_uf, "Field l_uf"); \
25 static u_int32 my_tick_to_tsf(u_int32 ticks);
26 static u_int32 my_tsf_to_tick(u_int32 tsf);
36 void test_Helpers1(void);
37 void test_Normalise(void);
38 void test_SignNoFrac(void);
39 void test_SignWithFrac(void);
40 void test_CmpFracEQ(void);
41 void test_CmpFracGT(void);
42 void test_CmpFracLT(void);
43 void test_AddFullNorm(void);
44 void test_AddFullOflow1(void);
45 void test_AddNsecNorm(void);
46 void test_AddNsecOflow1(void);
47 void test_SubFullNorm(void);
48 void test_SubFullOflow(void);
49 void test_SubNsecNorm(void);
50 void test_SubNsecOflow(void);
52 void test_AbsNoFrac(void);
53 void test_AbsWithFrac(void);
54 void test_Helpers2(void);
55 void test_ToLFPbittest(void);
56 void test_ToLFPrelPos(void);
57 void test_ToLFPrelNeg(void);
58 void test_ToLFPabs(void);
59 void test_FromLFPbittest(void);
60 void test_FromLFPrelPos(void);
61 void test_FromLFPrelNeg(void);
62 void test_LFProundtrip(void);
63 void test_ToString(void);
67 const bool timespec_isValid(struct timespec V);
68 struct timespec timespec_init(time_t hi, long lo);
69 l_fp l_fp_init(int32 i, u_int32 f);
70 bool AssertFpClose(const l_fp m, const l_fp n, const l_fp limit);
71 bool AssertTimespecClose(const struct timespec m, const struct timespec n, const struct timespec limit);
74 //******************************************MY CUSTOM FUNCTIONS*******************************
79 timespec_isValid(struct timespec V) {
80 return V.tv_nsec >= 0 && V.tv_nsec < 1000000000;
85 timespec_init(time_t hi, long lo) {
94 l_fp_init(int32 i, u_int32 f) {
104 AssertFpClose(const l_fp m, const l_fp n, const l_fp limit) {
107 if (L_ISGEQ(&m, &n)) {
114 if (L_ISGEQ(&limit, &diff)){
118 printf("m_expr which is %s \nand\nn_expr which is %s\nare not close; diff=%susec\n", lfptoa(&m, 10), lfptoa(&n, 10), lfptoa(&diff, 10));
125 AssertTimespecClose(const struct timespec m, const struct timespec n, const struct timespec limit) {
126 struct timespec diff;
128 diff = abs_tspec(sub_tspec(m, n));
129 if (cmp_tspec(limit, diff) >= 0)
133 printf("m_expr which is %ld.%lu \nand\nn_expr which is %ld.%lu\nare not close; diff=%ld.%lunsec\n", m.tv_sec, m.tv_nsec, n.tv_sec, n.tv_nsec, diff.tv_sec, diff.tv_nsec);
138 //-----------------------------------------------
140 static const struct lfpfracdata fdata[] = {
141 { 0, 0x00000000 }, { 2218896, 0x00916ae6 },
142 { 16408100, 0x0433523d }, { 125000000, 0x20000000 },
143 { 250000000, 0x40000000 }, { 287455871, 0x4996b53d },
144 { 375000000, 0x60000000 }, { 500000000, 0x80000000 },
145 { 518978897, 0x84dbcd0e }, { 563730222, 0x90509fb3 },
146 { 563788007, 0x9054692c }, { 583289882, 0x95527c57 },
147 { 607074509, 0x9b693c2a }, { 625000000, 0xa0000000 },
148 { 645184059, 0xa52ac851 }, { 676497788, 0xad2ef583 },
149 { 678910895, 0xadcd1abb }, { 679569625, 0xadf84663 },
150 { 690926741, 0xb0e0932d }, { 705656483, 0xb4a5e73d },
151 { 723553854, 0xb93ad34c }, { 750000000, 0xc0000000 },
152 { 763550253, 0xc3780785 }, { 775284917, 0xc6791284 },
153 { 826190764, 0xd3813ce8 }, { 875000000, 0xe0000000 },
154 { 956805507, 0xf4f134a9 }, { 982570733, 0xfb89c16c }
159 my_tick_to_tsf(u_int32 ticks) {
160 // convert nanoseconds to l_fp fractional units, using double
161 // precision float calculations or, if available, 64bit integer
162 // arithmetic. This should give the precise fraction, rounded to
163 // the nearest representation.
165 return (u_int32)((( ((u_int64)(ticks)) << 32) + 500000000) / 1000000000);
167 return (u_int32)((double(ticks)) * 4.294967296 + 0.5);
169 // And before you ask: if ticks >= 1000000000, the result is
170 // truncated nonsense, so don't use it out-of-bounds.
175 my_tsf_to_tick(u_int32 tsf) {
176 // Inverse operation: converts fraction to microseconds.
178 return (u_int32)(( ((u_int64)(tsf)) * 1000000000 + 0x80000000) >> 32);
180 return (u_int32)(double(tsf) / 4.294967296 + 0.5);
182 // Beware: The result might be 10^9 due to rounding!
187 // ---------------------------------------------------------------------
188 // test support stuff -- part 1
189 // ---------------------------------------------------------------------
192 test_Helpers1(void) {
195 for (x.tv_sec = -2; x.tv_sec < 3; x.tv_sec++) {
197 TEST_ASSERT_FALSE(timespec_isValid(x));
199 TEST_ASSERT_TRUE(timespec_isValid(x));
200 x.tv_nsec = 999999999;
201 TEST_ASSERT_TRUE(timespec_isValid(x));
202 x.tv_nsec = 1000000000;
203 TEST_ASSERT_FALSE(timespec_isValid(x));
208 //----------------------------------------------------------------------
209 // test normalisation
210 //----------------------------------------------------------------------
213 test_Normalise(void) {
215 for ( ns = -2000000000; ns <= 2000000000; ns += 10000000) {
216 struct timespec x = timespec_init(0, ns);
218 x = normalize_tspec(x);
219 TEST_ASSERT_TRUE(timespec_isValid(x));
223 //----------------------------------------------------------------------
224 // test classification
225 //----------------------------------------------------------------------
228 test_SignNoFrac(void) {
229 // sign test, no fraction
231 for (i = -4; i <= 4; ++i) {
232 struct timespec a = timespec_init(i, 0);
233 int E = (i > 0) - (i < 0);
234 int r = test_tspec(a);
236 TEST_ASSERT_EQUAL(E, r);
242 test_SignWithFrac(void) {
243 // sign test, with fraction
245 for (i = -4; i <= 4; ++i) {
246 struct timespec a = timespec_init(i, 10);
247 int E = (i >= 0) - (i < 0);
248 int r = test_tspec(a);
249 TEST_ASSERT_EQUAL(E, r);
253 //----------------------------------------------------------------------
255 //----------------------------------------------------------------------
257 test_CmpFracEQ(void) {
258 // fractions are equal
260 for (i = -4; i <= 4; ++i)
261 for (j = -4; j <= 4; ++j) {
262 struct timespec a = timespec_init( i , 200);
263 struct timespec b = timespec_init( j , 200);
264 int E = (i > j) - (i < j);
265 int r = cmp_tspec_denorm(a, b);
266 TEST_ASSERT_EQUAL(E, r);
272 test_CmpFracGT(void) {
273 // fraction a bigger fraction b
275 for (i = -4; i <= 4; ++i)
276 for (j = -4; j <= 4; ++j) {
277 struct timespec a = timespec_init(i, 999999800);
278 struct timespec b = timespec_init(j, 200);
279 int E = (i >= j) - (i < j);
280 int r = cmp_tspec_denorm(a, b);
281 TEST_ASSERT_EQUAL(E, r);
287 test_CmpFracLT(void) {
288 // fraction a less fraction b
290 for (i = -4; i <= 4; ++i)
291 for (j = -4; j <= 4; ++j) {
292 struct timespec a = timespec_init(i, 200);
293 struct timespec b = timespec_init(j, 999999800);
294 int E = (i > j) - (i <= j);
295 int r = cmp_tspec_denorm(a, b);
296 TEST_ASSERT_EQUAL(E, r);
300 //----------------------------------------------------------------------
301 // Test addition (sum)
302 //----------------------------------------------------------------------
305 test_AddFullNorm(void) {
307 for (i = -4; i <= 4; ++i)
308 for (j = -4; j <= 4; ++j) {
309 struct timespec a = timespec_init(i, 200);
310 struct timespec b = timespec_init(j, 400);
311 struct timespec E = timespec_init(i + j, 200 + 400);
315 TEST_ASSERT_EQUAL_timespec(E, c);
321 test_AddFullOflow1(void) {
323 for (i = -4; i <= 4; ++i)
324 for (j = -4; j <= 4; ++j) {
325 struct timespec a = timespec_init(i, 200);
326 struct timespec b = timespec_init(j, 999999900);
327 struct timespec E = timespec_init(i + j + 1, 100);
331 TEST_ASSERT_EQUAL_timespec(E, c);
337 test_AddNsecNorm(void) {
339 for (i = -4; i <= 4; ++i) {
340 struct timespec a = timespec_init(i, 200);
341 struct timespec E = timespec_init(i, 600);
344 c = add_tspec_ns(a, 600 - 200);
345 TEST_ASSERT_EQUAL_timespec(E, c);
351 test_AddNsecOflow1(void) {
353 for (i = -4; i <= 4; ++i) {
354 struct timespec a = timespec_init(i, 200);
355 struct timespec E = timespec_init(i + 1, 100);
358 c = add_tspec_ns(a, NANOSECONDS - 100);
359 TEST_ASSERT_EQUAL_timespec(E, c);
363 //----------------------------------------------------------------------
364 // test subtraction (difference)
365 //----------------------------------------------------------------------
368 test_SubFullNorm(void) {
370 for (i = -4; i <= 4; ++i)
371 for (j = -4; j <= 4; ++j) {
372 struct timespec a = timespec_init( i , 600);
373 struct timespec b = timespec_init( j , 400);
374 struct timespec E = timespec_init(i-j, 200);
378 TEST_ASSERT_EQUAL_timespec(E, c);
384 test_SubFullOflow(void) {
386 for (i = -4; i <= 4; ++i)
387 for (j = -4; j <= 4; ++j) {
388 struct timespec a = timespec_init(i, 100);
389 struct timespec b = timespec_init(j, 999999900);
390 struct timespec E = timespec_init(i - j - 1, 200);
394 TEST_ASSERT_EQUAL_timespec(E, c);
400 test_SubNsecNorm(void) {
402 for (i = -4; i <= 4; ++i) {
403 struct timespec a = timespec_init(i, 600);
404 struct timespec E = timespec_init(i, 200);
407 c = sub_tspec_ns(a, 600 - 200);
408 TEST_ASSERT_EQUAL_timespec(E, c);
414 test_SubNsecOflow(void) {
416 for (i = -4; i <= 4; ++i) {
417 struct timespec a = timespec_init( i , 100);
418 struct timespec E = timespec_init(i-1, 200);
421 c = sub_tspec_ns(a, NANOSECONDS - 100);
422 TEST_ASSERT_EQUAL_timespec(E, c);
426 //----------------------------------------------------------------------
428 //----------------------------------------------------------------------
434 for (i = -4; i <= 4; ++i) {
435 struct timespec a = timespec_init(i, 100);
441 TEST_ASSERT_EQUAL(0, test_tspec(c));
445 //----------------------------------------------------------------------
447 //----------------------------------------------------------------------
450 test_AbsNoFrac(void) {
452 for (i = -4; i <= 4; ++i) {
453 struct timespec a = timespec_init(i , 0);
457 TEST_ASSERT_EQUAL((i != 0), test_tspec(b));
463 test_AbsWithFrac(void) {
465 for (i = -4; i <= 4; ++i) {
466 struct timespec a = timespec_init(i, 100);
470 TEST_ASSERT_EQUAL(1, test_tspec(b));
474 // ---------------------------------------------------------------------
475 // test support stuff -- part 2
476 // ---------------------------------------------------------------------
479 test_Helpers2(void) {
480 struct timespec limit = timespec_init(0, 2);
482 struct timespec x, y;
485 for (x.tv_sec = -2; x.tv_sec < 3; x.tv_sec++)
487 x.tv_nsec < 1000000000;
488 x.tv_nsec += 499999999) {
489 for (i = -4; i < 5; ++i) {
492 if (i >= -2 && i <= 2){
493 TEST_ASSERT_TRUE(AssertTimespecClose(x, y, limit));
497 TEST_ASSERT_FALSE(AssertTimespecClose(x, y, limit));
503 //----------------------------------------------------------------------
504 // conversion to l_fp
505 //----------------------------------------------------------------------
508 test_ToLFPbittest(void) {
509 l_fp lfpClose = l_fp_init(0, 1);
511 for (i = 0; i < 1000000000; i+=1000) {
512 struct timespec a = timespec_init(1, i);
513 l_fp E= l_fp_init(1, my_tick_to_tsf(i));
516 r = tspec_intv_to_lfp(a);
517 TEST_ASSERT_TRUE(AssertFpClose(E, r, lfpClose));
523 test_ToLFPrelPos(void) {
525 for (i = 0; i < COUNTOF(fdata); ++i) {
526 struct timespec a = timespec_init(1, fdata[i].nsec);
527 l_fp E = l_fp_init(1, fdata[i].frac);
530 r = tspec_intv_to_lfp(a);
531 TEST_ASSERT_EQUAL_l_fp(E, r);
537 test_ToLFPrelNeg(void) {
539 for (i = 0; i < COUNTOF(fdata); ++i) {
540 struct timespec a = timespec_init(-1, fdata[i].nsec);
541 l_fp E = l_fp_init(~0, fdata[i].frac);
544 r = tspec_intv_to_lfp(a);
545 TEST_ASSERT_EQUAL_l_fp(E, r);
551 test_ToLFPabs(void) {
553 for (i = 0; i < COUNTOF(fdata); ++i) {
554 struct timespec a = timespec_init(1, fdata[i].nsec);
555 l_fp E = l_fp_init(1 + JAN_1970, fdata[i].frac);
558 r = tspec_stamp_to_lfp(a);
559 TEST_ASSERT_EQUAL_l_fp(E, r);
563 //----------------------------------------------------------------------
564 // conversion from l_fp
565 //----------------------------------------------------------------------
568 test_FromLFPbittest(void) {
569 struct timespec limit = timespec_init(0, 2);
571 // Not *exactly* a bittest, because 2**32 tests would take a
572 // really long time even on very fast machines! So we do test
573 // every 1000 fractional units.
575 for (tsf = 0; tsf < ~((u_int32)(1000)); tsf += 1000) {
576 struct timespec E = timespec_init(1, my_tsf_to_tick(tsf));
577 l_fp a = l_fp_init(1, tsf);
580 r = lfp_intv_to_tspec(a);
581 // The conversion might be off by one nanosecond when
582 // comparing to calculated value.
583 TEST_ASSERT_TRUE(AssertTimespecClose(E, r, limit));
589 test_FromLFPrelPos(void) {
590 struct timespec limit = timespec_init(0, 2);
592 for (i = 0; i < COUNTOF(fdata); ++i) {
593 l_fp a = l_fp_init(1, fdata[i].frac);
594 struct timespec E = timespec_init(1, fdata[i].nsec);
597 r = lfp_intv_to_tspec(a);
598 TEST_ASSERT_TRUE(AssertTimespecClose(E, r, limit));
604 test_FromLFPrelNeg(void) {
605 struct timespec limit = timespec_init(0, 2);
607 for (i = 0; i < COUNTOF(fdata); ++i) {
608 l_fp a = l_fp_init(~0, fdata[i].frac);
609 struct timespec E = timespec_init(-1, fdata[i].nsec);
612 r = lfp_intv_to_tspec(a);
613 TEST_ASSERT_TRUE(AssertTimespecClose(E, r, limit));
618 // nsec -> frac -> nsec roundtrip, using a prime start and increment
620 test_LFProundtrip(void) {
623 for (t = -1; t < 2; ++t)
624 for (i = 4999; i < 1000000000; i += 10007) {
625 struct timespec E = timespec_init(t, i);
629 a = tspec_intv_to_lfp(E);
630 r = lfp_intv_to_tspec(a);
631 TEST_ASSERT_EQUAL_timespec(E, r);
635 //----------------------------------------------------------------------
637 //----------------------------------------------------------------------
640 test_ToString(void) {
641 static const struct {
646 { 0, 0, "0.000000000" },
647 { 2, 0, "2.000000000" },
648 {-2, 0, "-2.000000000" },
649 { 0, 1, "0.000000001" },
650 { 0,-1, "-0.000000001" },
651 { 1,-1, "0.999999999" },
652 {-1, 1, "-0.999999999" },
653 {-1,-1, "-1.000000001" },
656 for (i = 0; i < COUNTOF(data); ++i) {
657 struct timespec a = timespec_init(data[i].sec, data[i].nsec);
658 const char * E = data[i].repr;
659 const char * r = tspectoa(a);
660 TEST_ASSERT_EQUAL_STRING(E, r);