timevalops.c revision 293896
1#include "config.h"
2
3//some unused features are still in the wrapper, unconverted
4
5#include "ntp_types.h"
6#include "ntp_fp.h"
7
8#include "timevalops.h"
9
10#include <math.h>
11#include "unity.h"
12
13
14#define TEST_ASSERT_EQUAL_timeval(a, b) {				\
15    TEST_ASSERT_EQUAL_MESSAGE(a.tv_sec, b.tv_sec, "Field tv_sec");	\
16    TEST_ASSERT_EQUAL_MESSAGE(a.tv_usec, b.tv_usec, "Field tv_usec");	\
17}
18
19
20static u_int32 my_tick_to_tsf(u_int32 ticks);
21static u_int32 my_tsf_to_tick(u_int32 tsf);
22
23
24// that's it...
25typedef struct {
26	long	usec;
27	u_int32	frac;
28} lfpfracdata ;
29
30typedef int bool;
31
32struct timeval timeval_init( time_t hi, long lo);
33const bool timeval_isValid(struct timeval V);
34l_fp l_fp_init(int32 i, u_int32 f);
35bool AssertTimevalClose(const struct timeval m, const struct timeval n, const struct timeval limit);
36bool AssertFpClose(const l_fp m, const l_fp n, const l_fp limit);
37
38void setUp(void);
39void test_Helpers1(void);
40void test_Normalise(void);
41void test_SignNoFrac(void);
42void test_SignWithFrac(void);
43void test_CmpFracEQ(void);
44void test_CmpFracGT(void);
45void test_CmpFracLT(void);
46void test_AddFullNorm(void);
47void test_AddFullOflow1(void);
48void test_AddUsecNorm(void);
49void test_AddUsecOflow1(void);
50void test_SubFullNorm(void);
51void test_SubFullOflow(void);
52void test_SubUsecNorm(void);
53void test_SubUsecOflow(void);
54void test_Neg(void);
55void test_AbsNoFrac(void);
56void test_AbsWithFrac(void);
57void test_Helpers2(void);
58void test_ToLFPbittest(void);
59void test_ToLFPrelPos(void);
60void test_ToLFPrelNeg(void);
61void test_ToLFPabs(void);
62void test_FromLFPbittest(void);
63void test_FromLFPrelPos(void);
64void test_FromLFPrelNeg(void);
65void test_LFProundtrip(void);
66void test_ToString(void);
67
68
69//**********************************MY CUSTOM FUNCTIONS***********************
70
71
72void
73setUp(void)
74{
75	init_lib();
76
77	return;
78}
79
80
81struct timeval
82timeval_init(time_t hi, long lo)
83{
84	struct timeval V;
85
86	V.tv_sec = hi;
87	V.tv_usec = lo;
88
89	return V;
90}
91
92
93const bool
94timeval_isValid(struct timeval V)
95{
96
97	return V.tv_usec >= 0 && V.tv_usec < 1000000;
98}
99
100
101l_fp
102l_fp_init(int32 i, u_int32 f)
103{
104	l_fp temp;
105
106	temp.l_i  = i;
107	temp.l_uf = f;
108
109	return temp;
110}
111
112
113bool
114AssertTimevalClose(const struct timeval m, const struct timeval n, const struct timeval limit)
115{
116	struct timeval diff;
117
118	diff = abs_tval(sub_tval(m, n));
119	if (cmp_tval(limit, diff) >= 0)
120		return TRUE;
121	else
122	{
123		printf("m_expr which is %ld.%lu \nand\nn_expr which is %ld.%lu\nare not close; diff=%ld.%luusec\n", m.tv_sec, m.tv_usec, n.tv_sec, n.tv_usec, diff.tv_sec, diff.tv_usec);
124		//I don't have variables m_expr and n_expr in unity, those are command line arguments which only getst has!!!
125
126		return FALSE;
127	}
128}
129
130
131bool
132AssertFpClose(const l_fp m, const l_fp n, const l_fp limit)
133{
134	l_fp diff;
135
136	if (L_ISGEQ(&m, &n)) {
137		diff = m;
138		L_SUB(&diff, &n);
139	} else {
140		diff = n;
141		L_SUB(&diff, &m);
142	}
143	if (L_ISGEQ(&limit, &diff)) {
144		return TRUE;
145	}
146	else {
147		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));
148		//printf("m_expr which is %d.%d \nand\nn_expr which is %d.%d\nare not close; diff=%d.%dusec\n", m.l_uf, m.Ul_i, n.l_uf, n.Ul_i, diff.l_uf, diff.Ul_i);
149		return FALSE;
150	}
151}
152
153
154//---------------------------------------------------
155
156static const lfpfracdata fdata[] = {
157	{      0, 0x00000000 }, {   7478, 0x01ea1405 },
158	{  22077, 0x05a6d699 }, { 125000, 0x20000000 },
159	{ 180326, 0x2e29d841 }, { 207979, 0x353e1c9b },
160	{ 250000, 0x40000000 }, { 269509, 0x44fe8ab5 },
161	{ 330441, 0x5497c808 }, { 333038, 0x5541fa76 },
162	{ 375000, 0x60000000 }, { 394734, 0x650d4995 },
163	{ 446327, 0x72427c7c }, { 500000, 0x80000000 },
164	{ 517139, 0x846338b4 }, { 571953, 0x926b8306 },
165	{ 587353, 0x965cc426 }, { 625000, 0xa0000000 },
166	{ 692136, 0xb12fd32c }, { 750000, 0xc0000000 },
167	{ 834068, 0xd5857aff }, { 848454, 0xd9344806 },
168	{ 854222, 0xdaae4b02 }, { 861465, 0xdc88f862 },
169	{ 875000, 0xe0000000 }, { 910661, 0xe921144d },
170	{ 922162, 0xec12cf10 }, { 942190, 0xf1335d25 }
171};
172
173
174u_int32
175my_tick_to_tsf(u_int32 ticks)
176{
177	// convert microseconds to l_fp fractional units, using double
178	// precision float calculations or, if available, 64bit integer
179	// arithmetic. This should give the precise fraction, rounded to
180	// the nearest representation.
181
182#ifdef HAVE_U_INT64
183	return (u_int32)((( ((u_int64)(ticks)) << 32) + 500000) / 1000000); //I put too much () when casting just to be safe
184#else
185	return (u_int32)( ((double)(ticks)) * 4294.967296 + 0.5);
186#endif
187	// And before you ask: if ticks >= 1000000, the result is
188	// truncated nonsense, so don't use it out-of-bounds.
189}
190
191
192u_int32
193my_tsf_to_tick(u_int32 tsf)
194{
195	// Inverse operation: converts fraction to microseconds.
196#ifdef HAVE_U_INT64
197	return (u_int32)( ((u_int64)(tsf) * 1000000 + 0x80000000) >> 32); //CHECK ME!!!
198#else
199	return (u_int32)(double(tsf) / 4294.967296 + 0.5);
200#endif
201	// Beware: The result might be 10^6 due to rounding!
202}
203
204
205//*******************************END OF CUSTOM FUNCTIONS*********************
206
207
208// ---------------------------------------------------------------------
209// test support stuff - part1
210// ---------------------------------------------------------------------
211
212void
213test_Helpers1(void)
214{
215	struct timeval x;
216
217	for (x.tv_sec = -2; x.tv_sec < 3; x.tv_sec++) {
218		x.tv_usec = -1;
219		TEST_ASSERT_FALSE(timeval_isValid(x));
220		x.tv_usec = 0;
221		TEST_ASSERT_TRUE(timeval_isValid(x));
222		x.tv_usec = 999999;
223		TEST_ASSERT_TRUE(timeval_isValid(x));
224		x.tv_usec = 1000000;
225		TEST_ASSERT_FALSE(timeval_isValid(x));
226	}
227
228	return;
229}
230
231
232//----------------------------------------------------------------------
233// test normalisation
234//----------------------------------------------------------------------
235
236void
237test_Normalise(void)
238{
239	long ns;
240
241	for (ns = -2000000000; ns <= 2000000000; ns += 10000000) {
242		struct timeval x = timeval_init(0, ns);
243
244		x = normalize_tval(x);
245		TEST_ASSERT_TRUE(timeval_isValid(x));
246	}
247
248	return;
249}
250
251//----------------------------------------------------------------------
252// test classification
253//----------------------------------------------------------------------
254
255void
256test_SignNoFrac(void)
257{
258	int i;
259
260	// sign test, no fraction
261	for (i = -4; i <= 4; ++i) {
262		struct timeval a = timeval_init(i, 0);
263		int	     E = (i > 0) - (i < 0);
264		int	     r = test_tval(a);
265
266		TEST_ASSERT_EQUAL(E, r);
267	}
268
269	return;
270}
271
272
273void
274test_SignWithFrac(void)
275{
276	// sign test, with fraction
277	int i;
278
279	for (i = -4; i <= 4; ++i) {
280		struct timeval a = timeval_init(i, 10);
281		int	     E = (i >= 0) - (i < 0);
282		int	     r = test_tval(a);
283
284		TEST_ASSERT_EQUAL(E, r);
285	}
286
287	return;
288}
289
290//----------------------------------------------------------------------
291// test compare
292//----------------------------------------------------------------------
293void
294test_CmpFracEQ(void)
295{
296	int i, j;
297
298	// fractions are equal
299	for (i = -4; i <= 4; ++i)
300		for (j = -4; j <= 4; ++j) {
301			struct timeval a = timeval_init(i, 200);
302			struct timeval b = timeval_init(j, 200);
303			int	     E = (i > j) - (i < j);
304			int	     r = cmp_tval_denorm(a, b);
305
306			TEST_ASSERT_EQUAL(E, r);
307		}
308
309	return;
310}
311
312
313void
314test_CmpFracGT(void)
315{
316	// fraction a bigger fraction b
317	int i, j;
318
319	for (i = -4; i <= 4; ++i)
320		for (j = -4; j <= 4; ++j) {
321			struct timeval a = timeval_init( i , 999800);
322			struct timeval b = timeval_init( j , 200);
323			int	     E = (i >= j) - (i < j);
324			int	     r = cmp_tval_denorm(a, b);
325
326			TEST_ASSERT_EQUAL(E, r);
327		}
328
329	return;
330}
331
332
333void
334test_CmpFracLT(void)
335{
336	// fraction a less fraction b
337	int i, j;
338
339	for (i = -4; i <= 4; ++i)
340		for (j = -4; j <= 4; ++j) {
341			struct timeval a = timeval_init(i, 200);
342			struct timeval b = timeval_init(j, 999800);
343			int	     E = (i > j) - (i <= j);
344			int	     r = cmp_tval_denorm(a, b);
345
346			TEST_ASSERT_EQUAL(E, r);
347		}
348
349	return;
350}
351
352//----------------------------------------------------------------------
353// Test addition (sum)
354//----------------------------------------------------------------------
355
356void
357test_AddFullNorm(void)
358{
359	int i, j;
360
361	for (i = -4; i <= 4; ++i)
362		for (j = -4; j <= 4; ++j) {
363			struct timeval a = timeval_init(i, 200);
364			struct timeval b = timeval_init(j, 400);
365			struct timeval E = timeval_init(i + j, 200 + 400);
366			struct timeval c;
367
368			c = add_tval(a, b);
369			TEST_ASSERT_EQUAL_timeval(E, c);
370		}
371
372	return;
373}
374
375
376void
377test_AddFullOflow1(void)
378{
379	int i, j;
380
381	for (i = -4; i <= 4; ++i)
382		for (j = -4; j <= 4; ++j) {
383			struct timeval a = timeval_init(i, 200);
384			struct timeval b = timeval_init(j, 999900);
385			struct timeval E = timeval_init(i + j + 1, 100);
386			struct timeval c;
387
388			c = add_tval(a, b);
389			TEST_ASSERT_EQUAL_timeval(E, c);
390		}
391
392	return;
393}
394
395
396void
397test_AddUsecNorm(void)
398{
399	int i;
400
401	for (i = -4; i <= 4; ++i) {
402		struct timeval a = timeval_init(i, 200);
403		struct timeval E = timeval_init(i, 600);
404		struct timeval c;
405
406		c = add_tval_us(a, 600 - 200);
407		TEST_ASSERT_EQUAL_timeval(E, c);
408	}
409
410	return;
411}
412
413
414void
415test_AddUsecOflow1(void)
416{
417	int i;
418
419	for (i = -4; i <= 4; ++i) {
420		struct timeval a = timeval_init(i, 200);
421		struct timeval E = timeval_init(i + 1, 100);
422		struct timeval c;
423
424		c = add_tval_us(a, MICROSECONDS - 100);
425		TEST_ASSERT_EQUAL_timeval(E, c);
426	}
427
428	return;
429}
430
431//----------------------------------------------------------------------
432// test subtraction (difference)
433//----------------------------------------------------------------------
434
435void
436test_SubFullNorm(void)
437{
438	int i, j;
439
440	for (i = -4; i <= 4; ++i)
441		for (j = -4; j <= 4; ++j) {
442			struct timeval a = timeval_init(i, 600);
443			struct timeval b = timeval_init(j, 400);
444			struct timeval E = timeval_init(i - j, 600 - 400);
445			struct timeval c;
446
447			c = sub_tval(a, b);
448			TEST_ASSERT_EQUAL_timeval(E, c);
449		}
450
451	return;
452}
453
454
455void
456test_SubFullOflow(void)
457{
458	int i, j;
459
460	for (i = -4; i <= 4; ++i)
461		for (j = -4; j <= 4; ++j) {
462			struct timeval a = timeval_init(i, 100);
463			struct timeval b = timeval_init(j, 999900);
464			struct timeval E = timeval_init(i - j - 1, 200);
465			struct timeval c;
466
467			c = sub_tval(a, b);
468			TEST_ASSERT_EQUAL_timeval(E, c);
469		}
470
471	return;
472}
473
474
475void
476test_SubUsecNorm(void)
477{
478	int i = -4;
479
480	for (i = -4; i <= 4; ++i) {
481		struct timeval a = timeval_init(i, 600);
482		struct timeval E = timeval_init(i, 200);
483		struct timeval c;
484
485		c = sub_tval_us(a, 600 - 200);
486		TEST_ASSERT_EQUAL_timeval(E, c);
487	}
488
489	return;
490}
491
492
493void
494test_SubUsecOflow(void)
495{
496	int i = -4;
497
498	for (i = -4; i <= 4; ++i) {
499		struct timeval a = timeval_init(i, 100);
500		struct timeval E = timeval_init(i - 1, 200);
501		struct timeval c;
502
503		c = sub_tval_us(a, MICROSECONDS - 100);
504		TEST_ASSERT_EQUAL_timeval(E, c);
505	}
506
507	return;
508}
509
510//----------------------------------------------------------------------
511// test negation
512//----------------------------------------------------------------------
513
514void
515test_Neg(void)
516{
517	int i = -4;
518
519	for (i = -4; i <= 4; ++i) {
520		struct timeval a = timeval_init(i, 100);
521		struct timeval b;
522		struct timeval c;
523
524		b = neg_tval(a);
525		c = add_tval(a, b);
526		TEST_ASSERT_EQUAL(0, test_tval(c));
527	}
528
529	return;
530}
531
532//----------------------------------------------------------------------
533// test abs value
534//----------------------------------------------------------------------
535
536void
537test_AbsNoFrac(void)
538{
539	int i = -4;
540
541	for (i = -4; i <= 4; ++i) {
542		struct timeval a = timeval_init(i, 0);
543		struct timeval b;
544
545		b = abs_tval(a);
546		TEST_ASSERT_EQUAL((i != 0), test_tval(b));
547	}
548
549	return;
550}
551
552
553void
554test_AbsWithFrac(void)
555{
556	int i = -4;
557
558	for (i = -4; i <= 4; ++i) {
559		struct timeval a = timeval_init(i, 100);
560		struct timeval b;
561
562		b = abs_tval(a);
563		TEST_ASSERT_EQUAL(1, test_tval(b));
564	}
565
566	return;
567}
568
569// ---------------------------------------------------------------------
570// test support stuff -- part 2
571// ---------------------------------------------------------------------
572
573
574void
575test_Helpers2(void)
576{
577	struct timeval limit = timeval_init(0, 2);
578	struct timeval x, y;
579	long i;
580
581	for (x.tv_sec = -2; x.tv_sec < 3; x.tv_sec++) {
582		for (x.tv_usec = 1;
583		     x.tv_usec < 1000000;
584		     x.tv_usec += 499999) {
585			for (i = -4; i < 5; ++i) {
586				y = x;
587				y.tv_usec += i;
588				if (i >= -2 && i <= 2) {
589					TEST_ASSERT_TRUE(AssertTimevalClose(x, y, limit));//ASSERT_PRED_FORMAT2(isClose, x, y);
590				}
591				else {
592					TEST_ASSERT_FALSE(AssertTimevalClose(x, y, limit));
593				}
594			}
595		}
596	}
597
598	return;
599}
600
601// and the global predicate instances we're using here
602
603//static l_fp lfpClose =  l_fp_init(0, 1); //static AssertFpClose FpClose(0, 1);
604//static struct timeval timevalClose = timeval_init(0, 1); //static AssertTimevalClose TimevalClose(0, 1);
605
606//----------------------------------------------------------------------
607// conversion to l_fp
608//----------------------------------------------------------------------
609
610void
611test_ToLFPbittest(void)
612{
613	l_fp lfpClose =  l_fp_init(0, 1);
614
615	u_int32 i = 0;
616	for (i = 0; i < 1000000; ++i) {
617		struct timeval a = timeval_init(1, i);
618		l_fp E = l_fp_init(1, my_tick_to_tsf(i));
619		l_fp r;
620
621		r = tval_intv_to_lfp(a);
622		TEST_ASSERT_TRUE(AssertFpClose(E, r, lfpClose));	//ASSERT_PRED_FORMAT2(FpClose, E, r);
623	}
624
625	return;
626}
627
628
629void
630test_ToLFPrelPos(void)
631{
632	l_fp lfpClose =  l_fp_init(0, 1);
633	int i = 0;
634
635	for (i = 0; i < COUNTOF(fdata); ++i) {
636		struct timeval a = timeval_init(1, fdata[i].usec);
637		l_fp E = l_fp_init(1, fdata[i].frac);
638		l_fp r;
639
640		r = tval_intv_to_lfp(a);
641		TEST_ASSERT_TRUE(AssertFpClose(E, r, lfpClose));
642	}
643
644	return;
645}
646
647
648void
649test_ToLFPrelNeg(void)
650{
651	l_fp lfpClose =  l_fp_init(0, 1);
652	int i = 0;
653
654	for (i = 0; i < COUNTOF(fdata); ++i) {
655		struct timeval a = timeval_init(-1, fdata[i].usec);
656		l_fp E = l_fp_init(~0, fdata[i].frac);
657		l_fp    r;
658
659		r = tval_intv_to_lfp(a);
660		TEST_ASSERT_TRUE(AssertFpClose(E, r, lfpClose));
661	}
662
663	return;
664}
665
666
667void
668test_ToLFPabs(void)
669{
670	l_fp lfpClose =  l_fp_init(0, 1);
671	int i = 0;
672
673	for (i = 0; i < COUNTOF(fdata); ++i) {
674		struct timeval a = timeval_init(1, fdata[i].usec);
675		l_fp E = l_fp_init(1 + JAN_1970, fdata[i].frac);
676		l_fp    r;
677
678		r = tval_stamp_to_lfp(a);
679		TEST_ASSERT_TRUE(AssertFpClose(E, r, lfpClose));
680	}
681
682	return;
683}
684
685//----------------------------------------------------------------------
686// conversion from l_fp
687//----------------------------------------------------------------------
688
689void
690test_FromLFPbittest(void)
691{
692	struct timeval timevalClose = timeval_init(0, 1);
693	// Not *exactly* a bittest, because 2**32 tests would take a
694	// really long time even on very fast machines! So we do test
695	// every 1000 fractional units.
696	u_int32 tsf = 0;
697
698	for (tsf = 0; tsf < ~((u_int32)(1000)); tsf += 1000) {
699		struct timeval E = timeval_init(1, my_tsf_to_tick(tsf));
700		l_fp a = l_fp_init(1, tsf);
701		struct timeval r;
702
703		r = lfp_intv_to_tval(a);
704		// The conversion might be off by one microsecond when
705		// comparing to calculated value.
706		TEST_ASSERT_TRUE(AssertTimevalClose(E, r, timevalClose));
707	}
708
709	return;
710}
711
712
713void
714test_FromLFPrelPos(void)
715{
716	struct timeval timevalClose = timeval_init(0, 1);
717	int i = 0;
718
719	for (i = 0; i < COUNTOF(fdata); ++i) {
720		l_fp a = l_fp_init(1, fdata[i].frac);
721		struct timeval E = timeval_init(1, fdata[i].usec);
722		struct timeval r;
723
724		r = lfp_intv_to_tval(a);
725		TEST_ASSERT_TRUE(AssertTimevalClose(E, r, timevalClose));
726	}
727
728	return;
729}
730
731
732void
733test_FromLFPrelNeg(void)
734{
735	struct timeval timevalClose = timeval_init(0, 1);
736	int i = 0;
737
738	for (i = 0; i < COUNTOF(fdata); ++i) {
739		l_fp a = l_fp_init(~0, fdata[i].frac);
740		struct timeval E = timeval_init(-1, fdata[i].usec);
741		struct timeval r;
742
743		r = lfp_intv_to_tval(a);
744		TEST_ASSERT_TRUE(AssertTimevalClose(E, r, timevalClose));
745	}
746
747	return;
748}
749
750
751// usec -> frac -> usec roundtrip, using a prime start and increment
752void
753test_LFProundtrip(void)
754{
755	int32_t t = -1;
756	u_int32 i = 5;
757
758	for (t = -1; t < 2; ++t)
759		for (i = 5; i < 1000000; i += 11) {
760			struct timeval E = timeval_init(t, i);
761			l_fp a;
762			struct timeval r;
763
764			a = tval_intv_to_lfp(E);
765			r = lfp_intv_to_tval(a);
766			TEST_ASSERT_EQUAL_timeval(E, r);
767		}
768
769	return;
770}
771
772//----------------------------------------------------------------------
773// string formatting
774//----------------------------------------------------------------------
775
776void
777test_ToString(void)
778{
779	static const struct {
780		time_t	     sec;
781		long	     usec;
782		const char * repr;
783	} data [] = {
784		{ 0, 0,	 "0.000000" },
785		{ 2, 0,	 "2.000000" },
786		{-2, 0, "-2.000000" },
787		{ 0, 1,	 "0.000001" },
788		{ 0,-1,	"-0.000001" },
789		{ 1,-1,	 "0.999999" },
790		{-1, 1, "-0.999999" },
791		{-1,-1, "-1.000001" },
792	};
793	int i;
794
795	for (i = 0; i < COUNTOF(data); ++i) {
796		struct timeval a = timeval_init(data[i].sec, data[i].usec);
797		const char *  E = data[i].repr;
798		const char *  r = tvaltoa(a);
799
800		TEST_ASSERT_EQUAL_STRING(E, r);
801	}
802
803	return;
804}
805
806// -*- EOF -*-
807