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