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);
37 void test_Helpers1(void);
38 void test_Normalise(void);
39 void test_SignNoFrac(void);
40 void test_SignWithFrac(void);
41 void test_CmpFracEQ(void);
42 void test_CmpFracGT(void);
43 void test_CmpFracLT(void);
44 void test_AddFullNorm(void);
45 void test_AddFullOflow1(void);
46 void test_AddNsecNorm(void);
47 void test_AddNsecOflow1(void);
48 void test_SubFullNorm(void);
49 void test_SubFullOflow(void);
50 void test_SubNsecNorm(void);
51 void test_SubNsecOflow(void);
53 void test_AbsNoFrac(void);
54 void test_AbsWithFrac(void);
55 void test_Helpers2(void);
56 void test_ToLFPbittest(void);
57 void test_ToLFPrelPos(void);
58 void test_ToLFPrelNeg(void);
59 void test_ToLFPabs(void);
60 void test_FromLFPbittest(void);
61 void test_FromLFPrelPos(void);
62 void test_FromLFPrelNeg(void);
63 void test_LFProundtrip(void);
64 void test_ToString(void);
66 const bool timespec_isValid(struct timespec V);
67 struct timespec timespec_init(time_t hi, long lo);
68 l_fp l_fp_init(int32 i, u_int32 f);
69 bool AssertFpClose(const l_fp m, const l_fp n, const l_fp limit);
70 bool AssertTimespecClose(const struct timespec m,
71 const struct timespec n,
72 const struct timespec limit);
75 //***************************MY CUSTOM FUNCTIONS***************************
88 timespec_isValid(struct timespec V)
91 return V.tv_nsec >= 0 && V.tv_nsec < 1000000000;
96 timespec_init(time_t hi, long lo)
108 l_fp_init(int32 i, u_int32 f)
120 AssertFpClose(const l_fp m, const l_fp n, const l_fp limit)
124 if (L_ISGEQ(&m, &n)) {
131 if (L_ISGEQ(&limit, &diff)) {
135 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));
142 AssertTimespecClose(const struct timespec m, const struct timespec n,
143 const struct timespec limit)
145 struct timespec diff;
147 diff = abs_tspec(sub_tspec(m, n));
148 if (cmp_tspec(limit, diff) >= 0)
152 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);
157 //-----------------------------------------------
159 static const struct lfpfracdata fdata[] = {
160 { 0, 0x00000000 }, { 2218896, 0x00916ae6 },
161 { 16408100, 0x0433523d }, { 125000000, 0x20000000 },
162 { 250000000, 0x40000000 }, { 287455871, 0x4996b53d },
163 { 375000000, 0x60000000 }, { 500000000, 0x80000000 },
164 { 518978897, 0x84dbcd0e }, { 563730222, 0x90509fb3 },
165 { 563788007, 0x9054692c }, { 583289882, 0x95527c57 },
166 { 607074509, 0x9b693c2a }, { 625000000, 0xa0000000 },
167 { 645184059, 0xa52ac851 }, { 676497788, 0xad2ef583 },
168 { 678910895, 0xadcd1abb }, { 679569625, 0xadf84663 },
169 { 690926741, 0xb0e0932d }, { 705656483, 0xb4a5e73d },
170 { 723553854, 0xb93ad34c }, { 750000000, 0xc0000000 },
171 { 763550253, 0xc3780785 }, { 775284917, 0xc6791284 },
172 { 826190764, 0xd3813ce8 }, { 875000000, 0xe0000000 },
173 { 956805507, 0xf4f134a9 }, { 982570733, 0xfb89c16c }
178 my_tick_to_tsf(u_int32 ticks)
180 // convert nanoseconds to l_fp fractional units, using double
181 // precision float calculations or, if available, 64bit integer
182 // arithmetic. This should give the precise fraction, rounded to
183 // the nearest representation.
186 return (u_int32)((( ((u_int64)(ticks)) << 32) + 500000000) / 1000000000);
188 return (u_int32)((double(ticks)) * 4.294967296 + 0.5);
190 // And before you ask: if ticks >= 1000000000, the result is
191 // truncated nonsense, so don't use it out-of-bounds.
196 my_tsf_to_tick(u_int32 tsf)
199 // Inverse operation: converts fraction to microseconds.
201 return (u_int32)(( ((u_int64)(tsf)) * 1000000000 + 0x80000000) >> 32);
203 return (u_int32)(double(tsf) / 4.294967296 + 0.5);
205 // Beware: The result might be 10^9 due to rounding!
210 // ---------------------------------------------------------------------
211 // test support stuff -- part 1
212 // ---------------------------------------------------------------------
219 for (x.tv_sec = -2; x.tv_sec < 3; x.tv_sec++) {
221 TEST_ASSERT_FALSE(timespec_isValid(x));
223 TEST_ASSERT_TRUE(timespec_isValid(x));
224 x.tv_nsec = 999999999;
225 TEST_ASSERT_TRUE(timespec_isValid(x));
226 x.tv_nsec = 1000000000;
227 TEST_ASSERT_FALSE(timespec_isValid(x));
234 //----------------------------------------------------------------------
235 // test normalisation
236 //----------------------------------------------------------------------
243 for ( ns = -2000000000; ns <= 2000000000; ns += 10000000) {
244 struct timespec x = timespec_init(0, ns);
246 x = normalize_tspec(x);
247 TEST_ASSERT_TRUE(timespec_isValid(x));
253 //----------------------------------------------------------------------
254 // test classification
255 //----------------------------------------------------------------------
258 test_SignNoFrac(void)
260 // sign test, no fraction
263 for (i = -4; i <= 4; ++i) {
264 struct timespec a = timespec_init(i, 0);
265 int E = (i > 0) - (i < 0);
266 int r = test_tspec(a);
268 TEST_ASSERT_EQUAL(E, r);
276 test_SignWithFrac(void)
278 // sign test, with fraction
281 for (i = -4; i <= 4; ++i) {
282 struct timespec a = timespec_init(i, 10);
283 int E = (i >= 0) - (i < 0);
284 int r = test_tspec(a);
286 TEST_ASSERT_EQUAL(E, r);
292 //----------------------------------------------------------------------
294 //----------------------------------------------------------------------
298 // fractions are equal
300 for (i = -4; i <= 4; ++i)
301 for (j = -4; j <= 4; ++j) {
302 struct timespec a = timespec_init( i , 200);
303 struct timespec b = timespec_init( j , 200);
304 int E = (i > j) - (i < j);
305 int r = cmp_tspec_denorm(a, b);
307 TEST_ASSERT_EQUAL(E, r);
317 // fraction a bigger fraction b
320 for (i = -4; i <= 4; ++i)
321 for (j = -4; j <= 4; ++j) {
322 struct timespec a = timespec_init(i, 999999800);
323 struct timespec b = timespec_init(j, 200);
324 int E = (i >= j) - (i < j);
325 int r = cmp_tspec_denorm(a, b);
327 TEST_ASSERT_EQUAL(E, r);
337 // fraction a less fraction b
340 for (i = -4; i <= 4; ++i)
341 for (j = -4; j <= 4; ++j) {
342 struct timespec a = timespec_init(i, 200);
343 struct timespec b = timespec_init(j, 999999800);
344 int E = (i > j) - (i <= j);
345 int r = cmp_tspec_denorm(a, b);
347 TEST_ASSERT_EQUAL(E, r);
353 //----------------------------------------------------------------------
354 // Test addition (sum)
355 //----------------------------------------------------------------------
358 test_AddFullNorm(void)
362 for (i = -4; i <= 4; ++i)
363 for (j = -4; j <= 4; ++j) {
364 struct timespec a = timespec_init(i, 200);
365 struct timespec b = timespec_init(j, 400);
366 struct timespec E = timespec_init(i + j, 200 + 400);
370 TEST_ASSERT_EQUAL_timespec(E, c);
378 test_AddFullOflow1(void)
382 for (i = -4; i <= 4; ++i)
383 for (j = -4; j <= 4; ++j) {
384 struct timespec a = timespec_init(i, 200);
385 struct timespec b = timespec_init(j, 999999900);
386 struct timespec E = timespec_init(i + j + 1, 100);
390 TEST_ASSERT_EQUAL_timespec(E, c);
398 test_AddNsecNorm(void) {
401 for (i = -4; i <= 4; ++i) {
402 struct timespec a = timespec_init(i, 200);
403 struct timespec E = timespec_init(i, 600);
406 c = add_tspec_ns(a, 600 - 200);
407 TEST_ASSERT_EQUAL_timespec(E, c);
415 test_AddNsecOflow1(void)
419 for (i = -4; i <= 4; ++i) {
420 struct timespec a = timespec_init(i, 200);
421 struct timespec E = timespec_init(i + 1, 100);
424 c = add_tspec_ns(a, NANOSECONDS - 100);
425 TEST_ASSERT_EQUAL_timespec(E, c);
431 //----------------------------------------------------------------------
432 // test subtraction (difference)
433 //----------------------------------------------------------------------
436 test_SubFullNorm(void)
440 for (i = -4; i <= 4; ++i)
441 for (j = -4; j <= 4; ++j) {
442 struct timespec a = timespec_init( i , 600);
443 struct timespec b = timespec_init( j , 400);
444 struct timespec E = timespec_init(i-j, 200);
448 TEST_ASSERT_EQUAL_timespec(E, c);
456 test_SubFullOflow(void)
460 for (i = -4; i <= 4; ++i)
461 for (j = -4; j <= 4; ++j) {
462 struct timespec a = timespec_init(i, 100);
463 struct timespec b = timespec_init(j, 999999900);
464 struct timespec E = timespec_init(i - j - 1, 200);
468 TEST_ASSERT_EQUAL_timespec(E, c);
476 test_SubNsecNorm(void)
480 for (i = -4; i <= 4; ++i) {
481 struct timespec a = timespec_init(i, 600);
482 struct timespec E = timespec_init(i, 200);
485 c = sub_tspec_ns(a, 600 - 200);
486 TEST_ASSERT_EQUAL_timespec(E, c);
494 test_SubNsecOflow(void)
498 for (i = -4; i <= 4; ++i) {
499 struct timespec a = timespec_init( i , 100);
500 struct timespec E = timespec_init(i-1, 200);
503 c = sub_tspec_ns(a, NANOSECONDS - 100);
504 TEST_ASSERT_EQUAL_timespec(E, c);
510 //----------------------------------------------------------------------
512 //----------------------------------------------------------------------
520 for (i = -4; i <= 4; ++i) {
521 struct timespec a = timespec_init(i, 100);
527 TEST_ASSERT_EQUAL(0, test_tspec(c));
533 //----------------------------------------------------------------------
535 //----------------------------------------------------------------------
542 for (i = -4; i <= 4; ++i) {
543 struct timespec a = timespec_init(i , 0);
547 TEST_ASSERT_EQUAL((i != 0), test_tspec(b));
555 test_AbsWithFrac(void)
559 for (i = -4; i <= 4; ++i) {
560 struct timespec a = timespec_init(i, 100);
564 TEST_ASSERT_EQUAL(1, test_tspec(b));
570 // ---------------------------------------------------------------------
571 // test support stuff -- part 2
572 // ---------------------------------------------------------------------
577 struct timespec limit = timespec_init(0, 2);
578 struct timespec x, y;
581 for (x.tv_sec = -2; x.tv_sec < 3; x.tv_sec++)
583 x.tv_nsec < 1000000000;
584 x.tv_nsec += 499999999) {
585 for (i = -4; i < 5; ++i) {
588 if (i >= -2 && i <= 2) {
589 TEST_ASSERT_TRUE(AssertTimespecClose(x, y, limit));
593 TEST_ASSERT_FALSE(AssertTimespecClose(x, y, limit));
601 //----------------------------------------------------------------------
602 // conversion to l_fp
603 //----------------------------------------------------------------------
606 test_ToLFPbittest(void)
608 l_fp lfpClose = l_fp_init(0, 1);
611 for (i = 0; i < 1000000000; i+=1000) {
612 struct timespec a = timespec_init(1, i);
613 l_fp E= l_fp_init(1, my_tick_to_tsf(i));
616 r = tspec_intv_to_lfp(a);
617 TEST_ASSERT_TRUE(AssertFpClose(E, r, lfpClose));
625 test_ToLFPrelPos(void)
629 for (i = 0; i < COUNTOF(fdata); ++i) {
630 struct timespec a = timespec_init(1, fdata[i].nsec);
631 l_fp E = l_fp_init(1, fdata[i].frac);
634 r = tspec_intv_to_lfp(a);
635 TEST_ASSERT_EQUAL_l_fp(E, r);
643 test_ToLFPrelNeg(void)
647 for (i = 0; i < COUNTOF(fdata); ++i) {
648 struct timespec a = timespec_init(-1, fdata[i].nsec);
649 l_fp E = l_fp_init(~0, fdata[i].frac);
652 r = tspec_intv_to_lfp(a);
653 TEST_ASSERT_EQUAL_l_fp(E, r);
665 for (i = 0; i < COUNTOF(fdata); ++i) {
666 struct timespec a = timespec_init(1, fdata[i].nsec);
667 l_fp E = l_fp_init(1 + JAN_1970, fdata[i].frac);
670 r = tspec_stamp_to_lfp(a);
671 TEST_ASSERT_EQUAL_l_fp(E, r);
677 //----------------------------------------------------------------------
678 // conversion from l_fp
679 //----------------------------------------------------------------------
682 test_FromLFPbittest(void)
684 struct timespec limit = timespec_init(0, 2);
686 // Not *exactly* a bittest, because 2**32 tests would take a
687 // really long time even on very fast machines! So we do test
688 // every 1000 fractional units.
690 for (tsf = 0; tsf < ~((u_int32)(1000)); tsf += 1000) {
691 struct timespec E = timespec_init(1, my_tsf_to_tick(tsf));
692 l_fp a = l_fp_init(1, tsf);
695 r = lfp_intv_to_tspec(a);
696 // The conversion might be off by one nanosecond when
697 // comparing to calculated value.
698 TEST_ASSERT_TRUE(AssertTimespecClose(E, r, limit));
706 test_FromLFPrelPos(void)
708 struct timespec limit = timespec_init(0, 2);
711 for (i = 0; i < COUNTOF(fdata); ++i) {
712 l_fp a = l_fp_init(1, fdata[i].frac);
713 struct timespec E = timespec_init(1, fdata[i].nsec);
716 r = lfp_intv_to_tspec(a);
717 TEST_ASSERT_TRUE(AssertTimespecClose(E, r, limit));
725 test_FromLFPrelNeg(void)
727 struct timespec limit = timespec_init(0, 2);
730 for (i = 0; i < COUNTOF(fdata); ++i) {
731 l_fp a = l_fp_init(~0, fdata[i].frac);
732 struct timespec E = timespec_init(-1, fdata[i].nsec);
735 r = lfp_intv_to_tspec(a);
736 TEST_ASSERT_TRUE(AssertTimespecClose(E, r, limit));
743 // nsec -> frac -> nsec roundtrip, using a prime start and increment
745 test_LFProundtrip(void)
750 for (t = -1; t < 2; ++t)
751 for (i = 4999; i < 1000000000; i += 10007) {
752 struct timespec E = timespec_init(t, i);
756 a = tspec_intv_to_lfp(E);
757 r = lfp_intv_to_tspec(a);
758 TEST_ASSERT_EQUAL_timespec(E, r);
764 //----------------------------------------------------------------------
766 //----------------------------------------------------------------------
771 static const struct {
776 { 0, 0, "0.000000000" },
777 { 2, 0, "2.000000000" },
778 {-2, 0, "-2.000000000" },
779 { 0, 1, "0.000000001" },
780 { 0,-1, "-0.000000001" },
781 { 1,-1, "0.999999999" },
782 {-1, 1, "-0.999999999" },
783 {-1,-1, "-1.000000001" },
787 for (i = 0; i < COUNTOF(data); ++i) {
788 struct timespec a = timespec_init(data[i].sec, data[i].nsec);
789 const char * E = data[i].repr;
790 const char * r = tspectoa(a);
791 TEST_ASSERT_EQUAL_STRING(E, r);