]> CyberLeo.Net >> Repos - FreeBSD/releng/9.3.git/blob - contrib/ntp/tests/libntp/timespecops.c
o Fix invalid TCP checksums with pf(4). [EN-16:02.pf]
[FreeBSD/releng/9.3.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 setUp(void);
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);
52 void test_Neg(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);
65
66 typedef int bool;
67
68 const bool      timespec_isValid(struct timespec V);
69 struct timespec timespec_init(time_t hi, long lo);
70 l_fp            l_fp_init(int32 i, u_int32 f);
71 bool            AssertFpClose(const l_fp m, const l_fp n, const l_fp limit);
72 bool            AssertTimespecClose(const struct timespec m,
73                                     const struct timespec n,
74                                     const struct timespec limit);
75
76
77 //***************************MY CUSTOM FUNCTIONS***************************
78
79
80 void
81 setUp(void)
82 {
83         init_lib();
84
85         return;
86 }
87
88
89 const bool
90 timespec_isValid(struct timespec V)
91 {
92
93         return V.tv_nsec >= 0 && V.tv_nsec < 1000000000;
94 }
95
96
97 struct timespec
98 timespec_init(time_t hi, long lo)
99 {
100         struct timespec V;
101
102         V.tv_sec = hi;
103         V.tv_nsec = lo;
104
105         return V;
106 }
107
108
109 l_fp
110 l_fp_init(int32 i, u_int32 f)
111 {
112         l_fp temp;
113
114         temp.l_i  = i;
115         temp.l_uf = f;
116
117         return temp;
118 }
119
120
121 bool
122 AssertFpClose(const l_fp m, const l_fp n, const l_fp limit)
123 {
124         l_fp diff;
125
126         if (L_ISGEQ(&m, &n)) {
127                 diff = m;
128                 L_SUB(&diff, &n);
129         } else {
130                 diff = n;
131                 L_SUB(&diff, &m);
132         }
133         if (L_ISGEQ(&limit, &diff)) {
134                 return TRUE;
135         }
136         else {
137                 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)); 
138                 return FALSE;
139         }
140 }
141
142
143 bool
144 AssertTimespecClose(const struct timespec m, const struct timespec n,
145         const struct timespec limit)
146 {
147         struct timespec diff;
148
149         diff = abs_tspec(sub_tspec(m, n));
150         if (cmp_tspec(limit, diff) >= 0)
151                 return TRUE;
152         else
153         {
154                 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); 
155                 return FALSE;
156         }
157 }
158
159 //-----------------------------------------------
160
161 static const struct lfpfracdata fdata[] = {
162         {         0, 0x00000000 }, {   2218896, 0x00916ae6 },
163         {  16408100, 0x0433523d }, { 125000000, 0x20000000 },
164         { 250000000, 0x40000000 }, { 287455871, 0x4996b53d },
165         { 375000000, 0x60000000 }, { 500000000, 0x80000000 },
166         { 518978897, 0x84dbcd0e }, { 563730222, 0x90509fb3 },
167         { 563788007, 0x9054692c }, { 583289882, 0x95527c57 },
168         { 607074509, 0x9b693c2a }, { 625000000, 0xa0000000 },
169         { 645184059, 0xa52ac851 }, { 676497788, 0xad2ef583 },
170         { 678910895, 0xadcd1abb }, { 679569625, 0xadf84663 },
171         { 690926741, 0xb0e0932d }, { 705656483, 0xb4a5e73d },
172         { 723553854, 0xb93ad34c }, { 750000000, 0xc0000000 },
173         { 763550253, 0xc3780785 }, { 775284917, 0xc6791284 },
174         { 826190764, 0xd3813ce8 }, { 875000000, 0xe0000000 },
175         { 956805507, 0xf4f134a9 }, { 982570733, 0xfb89c16c }
176         };
177
178
179 u_int32
180 my_tick_to_tsf(u_int32 ticks)
181 {
182         // convert nanoseconds to l_fp fractional units, using double
183         // precision float calculations or, if available, 64bit integer
184         // arithmetic. This should give the precise fraction, rounded to
185         // the nearest representation.
186
187 #ifdef HAVE_U_INT64
188         return (u_int32)((( ((u_int64)(ticks)) << 32) + 500000000) / 1000000000);
189 #else
190         return (u_int32)((double(ticks)) * 4.294967296 + 0.5);
191 #endif
192         // And before you ask: if ticks >= 1000000000, the result is
193         // truncated nonsense, so don't use it out-of-bounds.
194 }
195
196
197 u_int32
198 my_tsf_to_tick(u_int32 tsf)
199 {
200
201         // Inverse operation: converts fraction to microseconds.
202 #ifdef HAVE_U_INT64
203         return (u_int32)(( ((u_int64)(tsf)) * 1000000000 + 0x80000000) >> 32);
204 #else
205         return (u_int32)(double(tsf) / 4.294967296 + 0.5);
206 #endif
207         // Beware: The result might be 10^9 due to rounding!
208 }
209
210
211
212 // ---------------------------------------------------------------------
213 // test support stuff -- part 1
214 // ---------------------------------------------------------------------
215
216 void
217 test_Helpers1(void)
218 {
219         struct timespec x;
220
221         for (x.tv_sec = -2; x.tv_sec < 3; x.tv_sec++) {
222                 x.tv_nsec = -1;
223                 TEST_ASSERT_FALSE(timespec_isValid(x));
224                 x.tv_nsec = 0;
225                 TEST_ASSERT_TRUE(timespec_isValid(x));
226                 x.tv_nsec = 999999999;
227                 TEST_ASSERT_TRUE(timespec_isValid(x));
228                 x.tv_nsec = 1000000000;
229                 TEST_ASSERT_FALSE(timespec_isValid(x));
230         }
231
232         return;
233 }
234
235
236 //----------------------------------------------------------------------
237 // test normalisation
238 //----------------------------------------------------------------------
239
240 void
241 test_Normalise(void)
242 {
243         long ns;
244
245         for ( ns = -2000000000; ns <= 2000000000; ns += 10000000) {
246                 struct timespec x = timespec_init(0, ns);
247
248                 x = normalize_tspec(x);
249                 TEST_ASSERT_TRUE(timespec_isValid(x));
250         }
251
252         return;
253 }
254
255 //----------------------------------------------------------------------
256 // test classification
257 //----------------------------------------------------------------------
258
259 void
260 test_SignNoFrac(void)
261 {
262         // sign test, no fraction
263         int i;
264
265         for (i = -4; i <= 4; ++i) {
266                 struct timespec a = timespec_init(i, 0);
267                 int E = (i > 0) - (i < 0);
268                 int r = test_tspec(a);
269
270                 TEST_ASSERT_EQUAL(E, r);
271         }
272
273         return;
274 }
275
276
277 void
278 test_SignWithFrac(void)
279 {
280         // sign test, with fraction
281         int i;
282
283         for (i = -4; i <= 4; ++i) {
284                 struct timespec a = timespec_init(i, 10);
285                 int E = (i >= 0) - (i < 0);
286                 int r = test_tspec(a);
287
288                 TEST_ASSERT_EQUAL(E, r);
289         }
290
291         return;
292 }
293
294 //----------------------------------------------------------------------
295 // test compare
296 //----------------------------------------------------------------------
297 void
298 test_CmpFracEQ(void)
299 {
300         // fractions are equal
301         int i, j;
302         for (i = -4; i <= 4; ++i)
303                 for (j = -4; j <= 4; ++j) {
304                         struct timespec a = timespec_init( i , 200);
305                         struct timespec b = timespec_init( j , 200);
306                         int   E = (i > j) - (i < j);
307                         int   r = cmp_tspec_denorm(a, b);
308
309                         TEST_ASSERT_EQUAL(E, r);
310                 }
311
312         return;
313 }
314
315
316 void
317 test_CmpFracGT(void)
318 {
319         // fraction a bigger fraction b
320         int i, j;
321
322         for (i = -4; i <= 4; ++i)
323                 for (j = -4; j <= 4; ++j) {
324                         struct timespec a = timespec_init(i, 999999800);
325                         struct timespec b = timespec_init(j, 200);
326                         int   E = (i >= j) - (i < j);
327                         int   r = cmp_tspec_denorm(a, b);
328
329                         TEST_ASSERT_EQUAL(E, r);
330                 }
331
332         return;
333 }
334
335
336 void
337 test_CmpFracLT(void)
338 {
339         // fraction a less fraction b
340         int i, j;
341
342         for (i = -4; i <= 4; ++i)
343                 for (j = -4; j <= 4; ++j) {
344                         struct timespec a = timespec_init(i, 200);
345                         struct timespec b = timespec_init(j, 999999800);
346                         int   E = (i > j) - (i <= j);
347                         int   r = cmp_tspec_denorm(a, b);
348
349                         TEST_ASSERT_EQUAL(E, r);
350                 }
351
352         return;
353 }
354
355 //----------------------------------------------------------------------
356 // Test addition (sum)
357 //----------------------------------------------------------------------
358
359 void
360 test_AddFullNorm(void)
361 {
362         int i, j;
363
364         for (i = -4; i <= 4; ++i)
365                 for (j = -4; j <= 4; ++j) {
366                         struct timespec a = timespec_init(i, 200);
367                         struct timespec b = timespec_init(j, 400);
368                         struct timespec E = timespec_init(i + j, 200 + 400);
369                         struct timespec c;
370
371                         c = add_tspec(a, b);
372                         TEST_ASSERT_EQUAL_timespec(E, c);
373                 }
374
375         return;
376 }
377
378
379 void
380 test_AddFullOflow1(void)
381 {
382         int i, j;
383
384         for (i = -4; i <= 4; ++i)
385                 for (j = -4; j <= 4; ++j) {
386                         struct timespec a = timespec_init(i, 200);
387                         struct timespec b = timespec_init(j, 999999900);
388                         struct timespec E = timespec_init(i + j + 1, 100);
389                         struct timespec c;
390
391                         c = add_tspec(a, b);
392                         TEST_ASSERT_EQUAL_timespec(E, c);
393                 }
394
395         return;
396 }
397
398
399 void
400 test_AddNsecNorm(void) {
401         int i;
402
403         for (i = -4; i <= 4; ++i) {
404                 struct timespec a = timespec_init(i, 200);
405                 struct timespec E = timespec_init(i, 600);
406                 struct timespec c;
407
408                 c = add_tspec_ns(a, 600 - 200);
409                 TEST_ASSERT_EQUAL_timespec(E, c);
410         }
411
412         return;
413 }
414
415
416 void
417 test_AddNsecOflow1(void)
418 {
419         int i;
420
421         for (i = -4; i <= 4; ++i) {
422                 struct timespec a = timespec_init(i, 200);
423                 struct timespec E = timespec_init(i + 1, 100);
424                 struct timespec c;
425
426                 c = add_tspec_ns(a, NANOSECONDS - 100);
427                 TEST_ASSERT_EQUAL_timespec(E, c);
428         }
429
430         return;
431 }
432
433 //----------------------------------------------------------------------
434 // test subtraction (difference)
435 //----------------------------------------------------------------------
436
437 void
438 test_SubFullNorm(void)
439 {
440         int i, j;
441
442         for (i = -4; i <= 4; ++i)
443                 for (j = -4; j <= 4; ++j) {
444                         struct timespec a = timespec_init( i , 600);
445                         struct timespec b = timespec_init( j , 400);
446                         struct timespec E = timespec_init(i-j, 200);
447                         struct timespec c;
448
449                         c = sub_tspec(a, b);
450                         TEST_ASSERT_EQUAL_timespec(E, c);
451                 }
452
453         return;
454 }
455
456
457 void
458 test_SubFullOflow(void)
459 {
460         int i, j;
461
462         for (i = -4; i <= 4; ++i)
463                 for (j = -4; j <= 4; ++j) {
464                         struct timespec a = timespec_init(i, 100);
465                         struct timespec b = timespec_init(j, 999999900);
466                         struct timespec E = timespec_init(i - j - 1, 200);
467                         struct timespec c;
468
469                         c = sub_tspec(a, b);
470                         TEST_ASSERT_EQUAL_timespec(E, c);
471                 }
472
473         return;
474 }
475
476
477 void
478 test_SubNsecNorm(void)
479 {
480         int i;
481
482         for (i = -4; i <= 4; ++i) {
483                 struct timespec a = timespec_init(i, 600);
484                 struct timespec E = timespec_init(i, 200);
485                 struct timespec c;
486
487                 c = sub_tspec_ns(a, 600 - 200);
488                 TEST_ASSERT_EQUAL_timespec(E, c);
489         }
490
491         return;
492 }
493
494
495 void
496 test_SubNsecOflow(void)
497 {
498         int i;
499
500         for (i = -4; i <= 4; ++i) {
501                 struct timespec a = timespec_init( i , 100);
502                 struct timespec E = timespec_init(i-1, 200);
503                 struct timespec c;
504
505                 c = sub_tspec_ns(a, NANOSECONDS - 100);
506                 TEST_ASSERT_EQUAL_timespec(E, c);
507         }
508
509         return;
510 }
511
512 //----------------------------------------------------------------------
513 // test negation
514 //----------------------------------------------------------------------
515
516
517 void
518 test_Neg(void)
519 {
520         int i;
521
522         for (i = -4; i <= 4; ++i) {
523                 struct timespec a = timespec_init(i, 100);
524                 struct timespec b;
525                 struct timespec c;
526
527                 b = neg_tspec(a);
528                 c = add_tspec(a, b);
529                 TEST_ASSERT_EQUAL(0, test_tspec(c));
530         }
531
532         return;
533 }
534
535 //----------------------------------------------------------------------
536 // test abs value
537 //----------------------------------------------------------------------
538
539 void
540 test_AbsNoFrac(void)
541 {
542         int i;
543
544         for (i = -4; i <= 4; ++i) {
545                 struct timespec a = timespec_init(i , 0);
546                 struct timespec b;
547
548                 b = abs_tspec(a);
549                 TEST_ASSERT_EQUAL((i != 0), test_tspec(b));
550         }
551
552         return;
553 }
554
555
556 void
557 test_AbsWithFrac(void)
558 {
559         int i;
560
561         for (i = -4; i <= 4; ++i) {
562                 struct timespec a = timespec_init(i, 100);
563                 struct timespec b;
564
565                 b = abs_tspec(a);
566                 TEST_ASSERT_EQUAL(1, test_tspec(b));
567         }
568
569         return;
570 }
571
572 // ---------------------------------------------------------------------
573 // test support stuff -- part 2
574 // ---------------------------------------------------------------------
575
576 void
577 test_Helpers2(void)
578 {
579         struct timespec limit = timespec_init(0, 2);
580         struct timespec x, y;
581         long i;
582
583         for (x.tv_sec = -2; x.tv_sec < 3; x.tv_sec++)
584                 for (x.tv_nsec = 1;
585                      x.tv_nsec < 1000000000;
586                      x.tv_nsec += 499999999) {
587                         for (i = -4; i < 5; ++i) {
588                                 y = x;
589                                 y.tv_nsec += i;
590                                 if (i >= -2 && i <= 2) {
591                                         TEST_ASSERT_TRUE(AssertTimespecClose(x, y, limit));
592                                 }
593                                 else
594                                 {
595                                         TEST_ASSERT_FALSE(AssertTimespecClose(x, y, limit));
596                                 }
597                         }
598                 }
599
600         return;
601 }
602
603 //----------------------------------------------------------------------
604 // conversion to l_fp
605 //----------------------------------------------------------------------
606
607 void
608 test_ToLFPbittest(void)
609 {
610         l_fp lfpClose =  l_fp_init(0, 1);
611         u_int32 i;
612
613         for (i = 0; i < 1000000000; i+=1000) {
614                 struct timespec a = timespec_init(1, i);
615                 l_fp E= l_fp_init(1, my_tick_to_tsf(i));
616                 l_fp r;
617
618                 r = tspec_intv_to_lfp(a);
619                 TEST_ASSERT_TRUE(AssertFpClose(E, r, lfpClose));
620         }
621
622         return;
623 }
624
625
626 void
627 test_ToLFPrelPos(void)
628 {
629         int i;
630
631         for (i = 0; i < COUNTOF(fdata); ++i) {
632                 struct timespec a = timespec_init(1, fdata[i].nsec);
633                 l_fp E = l_fp_init(1, fdata[i].frac);
634                 l_fp r;
635
636                 r = tspec_intv_to_lfp(a);
637                 TEST_ASSERT_EQUAL_l_fp(E, r);
638         }
639
640         return;
641 }
642
643
644 void
645 test_ToLFPrelNeg(void)
646 {
647         int i;
648
649         for (i = 0; i < COUNTOF(fdata); ++i) {
650                 struct timespec a = timespec_init(-1, fdata[i].nsec);
651                 l_fp E = l_fp_init(~0, fdata[i].frac);
652                 l_fp r;
653
654                 r = tspec_intv_to_lfp(a);
655                 TEST_ASSERT_EQUAL_l_fp(E, r);
656         }
657
658         return;
659 }
660
661
662 void
663 test_ToLFPabs(void)
664 {
665         int i;
666
667         for (i = 0; i < COUNTOF(fdata); ++i) {
668                 struct timespec a = timespec_init(1, fdata[i].nsec);
669                 l_fp E = l_fp_init(1 + JAN_1970, fdata[i].frac);
670                 l_fp r;
671
672                 r = tspec_stamp_to_lfp(a);
673                 TEST_ASSERT_EQUAL_l_fp(E, r);
674         }
675
676         return;
677 }
678
679 //----------------------------------------------------------------------
680 // conversion from l_fp
681 //----------------------------------------------------------------------
682
683 void
684 test_FromLFPbittest(void)
685 {
686         struct timespec limit = timespec_init(0, 2);
687
688         // Not *exactly* a bittest, because 2**32 tests would take a
689         // really long time even on very fast machines! So we do test
690         // every 1000 fractional units.
691         u_int32 tsf;
692         for (tsf = 0; tsf < ~((u_int32)(1000)); tsf += 1000) {
693                 struct timespec E = timespec_init(1, my_tsf_to_tick(tsf));
694                 l_fp a = l_fp_init(1, tsf);
695                 struct timespec r;
696
697                 r = lfp_intv_to_tspec(a);
698                 // The conversion might be off by one nanosecond when
699                 // comparing to calculated value.
700                 TEST_ASSERT_TRUE(AssertTimespecClose(E, r, limit));
701         }
702
703         return;
704 }
705
706
707 void
708 test_FromLFPrelPos(void)
709 {
710         struct timespec limit = timespec_init(0, 2);
711         int i;
712
713         for (i = 0; i < COUNTOF(fdata); ++i) {
714                 l_fp a = l_fp_init(1, fdata[i].frac);
715                 struct timespec E = timespec_init(1, fdata[i].nsec);
716                 struct timespec r;
717
718                 r = lfp_intv_to_tspec(a);
719                 TEST_ASSERT_TRUE(AssertTimespecClose(E, r, limit));
720         }
721
722         return;
723 }
724
725
726 void
727 test_FromLFPrelNeg(void)
728 {
729         struct timespec limit = timespec_init(0, 2);
730         int i;
731
732         for (i = 0; i < COUNTOF(fdata); ++i) {
733                 l_fp a = l_fp_init(~0, fdata[i].frac);
734                 struct timespec E = timespec_init(-1, fdata[i].nsec);
735                 struct timespec r;
736
737                 r = lfp_intv_to_tspec(a);
738                 TEST_ASSERT_TRUE(AssertTimespecClose(E, r, limit));
739         }
740
741         return;
742 }
743
744
745 // nsec -> frac -> nsec roundtrip, using a prime start and increment
746 void
747 test_LFProundtrip(void)
748 {
749         int32_t t;
750         u_int32 i;
751
752         for (t = -1; t < 2; ++t)
753                 for (i = 4999; i < 1000000000; i += 10007) {
754                         struct timespec E = timespec_init(t, i);
755                         l_fp a;
756                         struct timespec r;
757
758                         a = tspec_intv_to_lfp(E);
759                         r = lfp_intv_to_tspec(a);
760                         TEST_ASSERT_EQUAL_timespec(E, r);
761                 }
762
763         return;
764 }
765
766 //----------------------------------------------------------------------
767 // string formatting
768 //----------------------------------------------------------------------
769
770 void
771 test_ToString(void)
772 {
773         static const struct {
774                 time_t          sec;
775                 long            nsec;
776                 const char *    repr;
777         } data [] = {
778                 { 0, 0,  "0.000000000" },
779                 { 2, 0,  "2.000000000" },
780                 {-2, 0, "-2.000000000" },
781                 { 0, 1,  "0.000000001" },
782                 { 0,-1, "-0.000000001" },
783                 { 1,-1,  "0.999999999" },
784                 {-1, 1, "-0.999999999" },
785                 {-1,-1, "-1.000000001" },
786         };
787         int i;
788
789         for (i = 0; i < COUNTOF(data); ++i) {
790                 struct timespec a = timespec_init(data[i].sec, data[i].nsec);
791                 const char * E = data[i].repr;
792                 const char * r = tspectoa(a);
793                 TEST_ASSERT_EQUAL_STRING(E, r);
794         }
795
796         return;
797 }
798
799 // -*- EOF -*-