]> CyberLeo.Net >> Repos - FreeBSD/releng/10.2.git/blob - contrib/ntp/tests/libntp/timespecops.c
Upgrade NTP to 4.2.8p4.
[FreeBSD/releng/10.2.git] / contrib / ntp / tests / libntp / timespecops.c
1 #include "config.h"
2
3 #include "ntp_types.h"
4 #include "ntp_fp.h"
5 #include "timespecops.h"
6
7 #include "unity.h"
8
9 #include <math.h>
10 #include <string.h>
11
12
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");   \
16 }
17
18
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");       \
22 }
23
24
25 static u_int32 my_tick_to_tsf(u_int32 ticks);
26 static u_int32 my_tsf_to_tick(u_int32 tsf);
27
28
29 // that's it...
30 struct lfpfracdata {
31         long    nsec;
32         u_int32 frac;
33 };
34
35
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);
51 void test_Neg(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);
64
65 typedef int bool;
66
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);
72
73
74 //******************************************MY CUSTOM FUNCTIONS*******************************
75
76
77
78 const bool
79 timespec_isValid(struct timespec V) {
80         return V.tv_nsec >= 0 && V.tv_nsec < 1000000000;
81 }
82
83
84 struct timespec
85 timespec_init(time_t hi, long lo) {
86         struct timespec V;      
87         V.tv_sec = hi;
88         V.tv_nsec = lo;
89         return V;
90 }
91
92
93 l_fp
94 l_fp_init(int32 i, u_int32 f) {
95         l_fp temp;
96         temp.l_i  = i;
97         temp.l_uf = f;
98
99         return temp;
100 }
101
102
103 bool
104 AssertFpClose(const l_fp m, const l_fp n, const l_fp limit) {
105         l_fp diff;
106
107         if (L_ISGEQ(&m, &n)) {
108                 diff = m;
109                 L_SUB(&diff, &n);
110         } else {
111                 diff = n;
112                 L_SUB(&diff, &m);
113         }
114         if (L_ISGEQ(&limit, &diff)){
115                 return TRUE;
116         }
117         else {
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)); 
119                 return FALSE;
120         }
121 }
122
123
124 bool
125 AssertTimespecClose(const struct timespec m, const struct timespec n, const struct timespec limit) {
126         struct timespec diff;
127
128         diff = abs_tspec(sub_tspec(m, n));
129         if (cmp_tspec(limit, diff) >= 0)
130                 return TRUE;
131         else
132         {
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); 
134                 return FALSE;
135         }
136 }
137
138 //-----------------------------------------------
139
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 }
155         };
156
157
158 u_int32
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.
164 #ifdef HAVE_U_INT64
165         return (u_int32)((( ((u_int64)(ticks)) << 32) + 500000000) / 1000000000);
166 #else
167         return (u_int32)((double(ticks)) * 4.294967296 + 0.5);
168 #endif
169         // And before you ask: if ticks >= 1000000000, the result is
170         // truncated nonsense, so don't use it out-of-bounds.
171 }
172
173
174 u_int32
175 my_tsf_to_tick(u_int32 tsf) {
176         // Inverse operation: converts fraction to microseconds.
177 #ifdef HAVE_U_INT64
178         return (u_int32)(( ((u_int64)(tsf)) * 1000000000 + 0x80000000) >> 32);
179 #else
180         return (u_int32)(double(tsf) / 4.294967296 + 0.5);
181 #endif
182         // Beware: The result might be 10^9 due to rounding!
183 }
184
185
186
187 // ---------------------------------------------------------------------
188 // test support stuff -- part 1
189 // ---------------------------------------------------------------------
190
191 void
192 test_Helpers1(void) {
193         struct timespec x;
194
195         for (x.tv_sec = -2; x.tv_sec < 3; x.tv_sec++) {
196                 x.tv_nsec = -1;
197                 TEST_ASSERT_FALSE(timespec_isValid(x));
198                 x.tv_nsec = 0;
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));
204         }
205 }
206
207
208 //----------------------------------------------------------------------
209 // test normalisation
210 //----------------------------------------------------------------------
211
212 void
213 test_Normalise(void) {
214         long ns;
215         for ( ns = -2000000000; ns <= 2000000000; ns += 10000000) {
216                 struct timespec x = timespec_init(0, ns);
217
218                 x = normalize_tspec(x);
219                 TEST_ASSERT_TRUE(timespec_isValid(x));
220         }
221 }
222
223 //----------------------------------------------------------------------
224 // test classification
225 //----------------------------------------------------------------------
226
227 void
228 test_SignNoFrac(void) {
229         // sign test, no fraction
230         int i;
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);
235
236                 TEST_ASSERT_EQUAL(E, r);
237         }
238 }
239
240
241 void
242 test_SignWithFrac(void) {
243         // sign test, with fraction
244         int i;
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);
250         }
251 }
252
253 //----------------------------------------------------------------------
254 // test compare
255 //----------------------------------------------------------------------
256 void
257 test_CmpFracEQ(void) {
258         // fractions are equal
259         int i, j;
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);
267                 }
268 }
269
270
271 void
272 test_CmpFracGT(void) {
273         // fraction a bigger fraction b
274         int i, j;
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);
282                 }
283 }
284
285
286 void
287 test_CmpFracLT(void) {
288         // fraction a less fraction b
289         int i, j;
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);
297                 }
298 }
299
300 //----------------------------------------------------------------------
301 // Test addition (sum)
302 //----------------------------------------------------------------------
303
304 void
305 test_AddFullNorm(void) {
306         int i, j;
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);
312                         struct timespec c;
313
314                         c = add_tspec(a, b);
315                         TEST_ASSERT_EQUAL_timespec(E, c);
316                 }
317 }
318
319
320 void
321 test_AddFullOflow1(void) {
322         int i, j;
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);
328                         struct timespec c;
329
330                         c = add_tspec(a, b);
331                         TEST_ASSERT_EQUAL_timespec(E, c);
332                 }
333 }
334
335
336 void
337 test_AddNsecNorm(void) {
338         int i;
339         for (i = -4; i <= 4; ++i) {
340                 struct timespec a = timespec_init(i, 200);
341                 struct timespec E = timespec_init(i, 600);
342                 struct timespec c;
343
344                 c = add_tspec_ns(a, 600 - 200);
345                 TEST_ASSERT_EQUAL_timespec(E, c);
346         }
347 }
348
349
350 void
351 test_AddNsecOflow1(void) {
352         int i;
353         for (i = -4; i <= 4; ++i) {
354                 struct timespec a = timespec_init(i, 200);
355                 struct timespec E = timespec_init(i + 1, 100);
356                 struct timespec c;
357
358                 c = add_tspec_ns(a, NANOSECONDS - 100);
359                 TEST_ASSERT_EQUAL_timespec(E, c);
360         }
361 }
362
363 //----------------------------------------------------------------------
364 // test subtraction (difference)
365 //----------------------------------------------------------------------
366
367 void
368 test_SubFullNorm(void) {
369         int i, j;
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);
375                         struct timespec c;
376
377                         c = sub_tspec(a, b);
378                         TEST_ASSERT_EQUAL_timespec(E, c);
379                 }
380 }
381
382
383 void
384 test_SubFullOflow(void) {
385         int i, j;
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);
391                         struct timespec c;
392
393                         c = sub_tspec(a, b);
394                         TEST_ASSERT_EQUAL_timespec(E, c);
395                 }
396 }
397
398
399 void
400 test_SubNsecNorm(void) {
401         int i;
402         for (i = -4; i <= 4; ++i) {
403                 struct timespec a = timespec_init(i, 600);
404                 struct timespec E = timespec_init(i, 200);
405                 struct timespec c;
406
407                 c = sub_tspec_ns(a, 600 - 200);
408                 TEST_ASSERT_EQUAL_timespec(E, c);
409         }
410 }
411
412
413 void
414 test_SubNsecOflow(void) {
415         int i;
416         for (i = -4; i <= 4; ++i) {
417                 struct timespec a = timespec_init( i , 100);
418                 struct timespec E = timespec_init(i-1, 200);
419                 struct timespec c;
420
421                 c = sub_tspec_ns(a, NANOSECONDS - 100);
422                 TEST_ASSERT_EQUAL_timespec(E, c);
423         }
424 }
425
426 //----------------------------------------------------------------------
427 // test negation
428 //----------------------------------------------------------------------
429
430
431 void
432 test_Neg(void) {
433         int i;
434         for (i = -4; i <= 4; ++i) {
435                 struct timespec a = timespec_init(i, 100);
436                 struct timespec b;
437                 struct timespec c;
438
439                 b = neg_tspec(a);
440                 c = add_tspec(a, b);
441                 TEST_ASSERT_EQUAL(0, test_tspec(c));
442         }
443 }
444
445 //----------------------------------------------------------------------
446 // test abs value
447 //----------------------------------------------------------------------
448
449 void
450 test_AbsNoFrac(void) {
451         int i;
452         for (i = -4; i <= 4; ++i) {
453                 struct timespec a = timespec_init(i , 0);
454                 struct timespec b;
455
456                 b = abs_tspec(a);
457                 TEST_ASSERT_EQUAL((i != 0), test_tspec(b));
458         }
459 }
460
461
462 void
463 test_AbsWithFrac(void) {
464         int i;
465         for (i = -4; i <= 4; ++i) {
466                 struct timespec a = timespec_init(i, 100);
467                 struct timespec b;
468
469                 b = abs_tspec(a);
470                 TEST_ASSERT_EQUAL(1, test_tspec(b));
471         }
472 }
473
474 // ---------------------------------------------------------------------
475 // test support stuff -- part 2
476 // ---------------------------------------------------------------------
477
478 void
479 test_Helpers2(void) {
480         struct timespec limit = timespec_init(0, 2);
481         
482         struct timespec x, y;
483         long i;
484
485         for (x.tv_sec = -2; x.tv_sec < 3; x.tv_sec++)
486                 for (x.tv_nsec = 1;
487                      x.tv_nsec < 1000000000;
488                      x.tv_nsec += 499999999) {
489                         for (i = -4; i < 5; ++i) {
490                                 y = x;
491                                 y.tv_nsec += i;
492                                 if (i >= -2 && i <= 2){
493                                         TEST_ASSERT_TRUE(AssertTimespecClose(x, y, limit));
494                                 }
495                                 else
496                                 {
497                                         TEST_ASSERT_FALSE(AssertTimespecClose(x, y, limit));
498                                 }
499                         }
500                 }
501 }
502
503 //----------------------------------------------------------------------
504 // conversion to l_fp
505 //----------------------------------------------------------------------
506
507 void
508 test_ToLFPbittest(void) {
509         l_fp lfpClose =  l_fp_init(0, 1);
510         u_int32 i;
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));
514                 l_fp r;
515
516                 r = tspec_intv_to_lfp(a);
517                 TEST_ASSERT_TRUE(AssertFpClose(E, r, lfpClose));
518         }
519 }
520
521
522 void
523 test_ToLFPrelPos(void) {
524         int i;
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);
528                 l_fp r;
529
530                 r = tspec_intv_to_lfp(a);
531                 TEST_ASSERT_EQUAL_l_fp(E, r);
532         }
533 }
534
535
536 void
537 test_ToLFPrelNeg(void) {
538         int i;
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);
542                 l_fp r;
543
544                 r = tspec_intv_to_lfp(a);
545                 TEST_ASSERT_EQUAL_l_fp(E, r);
546         }
547 }
548
549
550 void
551 test_ToLFPabs(void) {
552         int i;
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);
556                 l_fp r;
557
558                 r = tspec_stamp_to_lfp(a);
559                 TEST_ASSERT_EQUAL_l_fp(E, r);
560         }
561 }
562
563 //----------------------------------------------------------------------
564 // conversion from l_fp
565 //----------------------------------------------------------------------
566
567 void
568 test_FromLFPbittest(void) {
569         struct timespec limit = timespec_init(0, 2);
570
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.
574         u_int32 tsf;
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);
578                 struct timespec r;
579
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));
584         }
585 }
586
587
588 void
589 test_FromLFPrelPos(void) {
590         struct timespec limit = timespec_init(0, 2);
591         int i;
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);
595                 struct timespec r;
596
597                 r = lfp_intv_to_tspec(a);
598                 TEST_ASSERT_TRUE(AssertTimespecClose(E, r, limit));
599         }
600 }
601
602
603 void
604 test_FromLFPrelNeg(void) {
605         struct timespec limit = timespec_init(0, 2);
606         int i;
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);
610                 struct timespec r;
611
612                 r = lfp_intv_to_tspec(a);
613                 TEST_ASSERT_TRUE(AssertTimespecClose(E, r, limit));
614         }
615 }
616
617
618 // nsec -> frac -> nsec roundtrip, using a prime start and increment
619 void
620 test_LFProundtrip(void) {
621         int32_t t;
622         u_int32 i;
623         for (t = -1; t < 2; ++t)
624                 for (i = 4999; i < 1000000000; i += 10007) {
625                         struct timespec E = timespec_init(t, i);
626                         l_fp a;
627                         struct timespec r;
628
629                         a = tspec_intv_to_lfp(E);
630                         r = lfp_intv_to_tspec(a);
631                         TEST_ASSERT_EQUAL_timespec(E, r);
632                 }
633 }
634
635 //----------------------------------------------------------------------
636 // string formatting
637 //----------------------------------------------------------------------
638
639 void
640 test_ToString(void) {
641         static const struct {
642                 time_t          sec;
643                 long            nsec;
644                 const char *    repr;
645         } data [] = {
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" },
654         };
655         int i;
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);
661         }
662 }
663
664 // -*- EOF -*-