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 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);
73 
74 
75 //***************************MY CUSTOM FUNCTIONS***************************
76 
77 
78 void
setUp(void)79 setUp(void)
80 {
81 	init_lib();
82 
83 	return;
84 }
85 
86 
87 const bool
timespec_isValid(struct timespec V)88 timespec_isValid(struct timespec V)
89 {
90 
91 	return V.tv_nsec >= 0 && V.tv_nsec < 1000000000;
92 }
93 
94 
95 struct timespec
timespec_init(time_t hi,long lo)96 timespec_init(time_t hi, long lo)
97 {
98 	struct timespec V;
99 
100 	V.tv_sec = hi;
101 	V.tv_nsec = lo;
102 
103 	return V;
104 }
105 
106 
107 l_fp
l_fp_init(int32 i,u_int32 f)108 l_fp_init(int32 i, u_int32 f)
109 {
110 	l_fp temp;
111 
112 	temp.l_i  = i;
113 	temp.l_uf = f;
114 
115 	return temp;
116 }
117 
118 
119 bool
AssertFpClose(const l_fp m,const l_fp n,const l_fp limit)120 AssertFpClose(const l_fp m, const l_fp n, const l_fp limit)
121 {
122 	l_fp diff;
123 
124 	if (L_ISGEQ(&m, &n)) {
125 		diff = m;
126 		L_SUB(&diff, &n);
127 	} else {
128 		diff = n;
129 		L_SUB(&diff, &m);
130 	}
131 	if (L_ISGEQ(&limit, &diff)) {
132 		return TRUE;
133 	}
134 	else {
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));
136 		return FALSE;
137 	}
138 }
139 
140 
141 bool
AssertTimespecClose(const struct timespec m,const struct timespec n,const struct timespec limit)142 AssertTimespecClose(const struct timespec m, const struct timespec n,
143 	const struct timespec limit)
144 {
145 	struct timespec diff;
146 
147 	diff = abs_tspec(sub_tspec(m, n));
148 	if (cmp_tspec(limit, diff) >= 0)
149 		return TRUE;
150 	else
151 	{
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);
153 		return FALSE;
154 	}
155 }
156 
157 //-----------------------------------------------
158 
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 }
174 	};
175 
176 
177 u_int32
my_tick_to_tsf(u_int32 ticks)178 my_tick_to_tsf(u_int32 ticks)
179 {
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.
184 
185 #ifdef HAVE_U_INT64
186 	return (u_int32)((( ((u_int64)(ticks)) << 32) + 500000000) / 1000000000);
187 #else
188 	return (u_int32)((double(ticks)) * 4.294967296 + 0.5);
189 #endif
190 	// And before you ask: if ticks >= 1000000000, the result is
191 	// truncated nonsense, so don't use it out-of-bounds.
192 }
193 
194 
195 u_int32
my_tsf_to_tick(u_int32 tsf)196 my_tsf_to_tick(u_int32 tsf)
197 {
198 
199 	// Inverse operation: converts fraction to microseconds.
200 #ifdef HAVE_U_INT64
201 	return (u_int32)(( ((u_int64)(tsf)) * 1000000000 + 0x80000000) >> 32);
202 #else
203 	return (u_int32)(double(tsf) / 4.294967296 + 0.5);
204 #endif
205 	// Beware: The result might be 10^9 due to rounding!
206 }
207 
208 
209 
210 // ---------------------------------------------------------------------
211 // test support stuff -- part 1
212 // ---------------------------------------------------------------------
213 
214 void
test_Helpers1(void)215 test_Helpers1(void)
216 {
217 	struct timespec x;
218 
219 	for (x.tv_sec = -2; x.tv_sec < 3; x.tv_sec++) {
220 		x.tv_nsec = -1;
221 		TEST_ASSERT_FALSE(timespec_isValid(x));
222 		x.tv_nsec = 0;
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));
228 	}
229 
230 	return;
231 }
232 
233 
234 //----------------------------------------------------------------------
235 // test normalisation
236 //----------------------------------------------------------------------
237 
238 void
test_Normalise(void)239 test_Normalise(void)
240 {
241 	long ns;
242 
243 	for ( ns = -2000000000; ns <= 2000000000; ns += 10000000) {
244 		struct timespec x = timespec_init(0, ns);
245 
246 		x = normalize_tspec(x);
247 		TEST_ASSERT_TRUE(timespec_isValid(x));
248 	}
249 
250 	return;
251 }
252 
253 //----------------------------------------------------------------------
254 // test classification
255 //----------------------------------------------------------------------
256 
257 void
test_SignNoFrac(void)258 test_SignNoFrac(void)
259 {
260 	// sign test, no fraction
261 	int i;
262 
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);
267 
268 		TEST_ASSERT_EQUAL(E, r);
269 	}
270 
271 	return;
272 }
273 
274 
275 void
test_SignWithFrac(void)276 test_SignWithFrac(void)
277 {
278 	// sign test, with fraction
279 	int i;
280 
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);
285 
286 		TEST_ASSERT_EQUAL(E, r);
287 	}
288 
289 	return;
290 }
291 
292 //----------------------------------------------------------------------
293 // test compare
294 //----------------------------------------------------------------------
295 void
test_CmpFracEQ(void)296 test_CmpFracEQ(void)
297 {
298 	// fractions are equal
299 	int i, j;
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);
306 
307 			TEST_ASSERT_EQUAL(E, r);
308 		}
309 
310 	return;
311 }
312 
313 
314 void
test_CmpFracGT(void)315 test_CmpFracGT(void)
316 {
317 	// fraction a bigger fraction b
318 	int i, j;
319 
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);
326 
327 			TEST_ASSERT_EQUAL(E, r);
328 		}
329 
330 	return;
331 }
332 
333 
334 void
test_CmpFracLT(void)335 test_CmpFracLT(void)
336 {
337 	// fraction a less fraction b
338 	int i, j;
339 
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);
346 
347 			TEST_ASSERT_EQUAL(E, r);
348 		}
349 
350 	return;
351 }
352 
353 //----------------------------------------------------------------------
354 // Test addition (sum)
355 //----------------------------------------------------------------------
356 
357 void
test_AddFullNorm(void)358 test_AddFullNorm(void)
359 {
360 	int i, j;
361 
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);
367 			struct timespec c;
368 
369 			c = add_tspec(a, b);
370 			TEST_ASSERT_EQUAL_timespec(E, c);
371 		}
372 
373 	return;
374 }
375 
376 
377 void
test_AddFullOflow1(void)378 test_AddFullOflow1(void)
379 {
380 	int i, j;
381 
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);
387 			struct timespec c;
388 
389 			c = add_tspec(a, b);
390 			TEST_ASSERT_EQUAL_timespec(E, c);
391 		}
392 
393 	return;
394 }
395 
396 
397 void
test_AddNsecNorm(void)398 test_AddNsecNorm(void) {
399 	int i;
400 
401 	for (i = -4; i <= 4; ++i) {
402 		struct timespec a = timespec_init(i, 200);
403 		struct timespec E = timespec_init(i, 600);
404 		struct timespec c;
405 
406 		c = add_tspec_ns(a, 600 - 200);
407 		TEST_ASSERT_EQUAL_timespec(E, c);
408 	}
409 
410 	return;
411 }
412 
413 
414 void
test_AddNsecOflow1(void)415 test_AddNsecOflow1(void)
416 {
417 	int i;
418 
419 	for (i = -4; i <= 4; ++i) {
420 		struct timespec a = timespec_init(i, 200);
421 		struct timespec E = timespec_init(i + 1, 100);
422 		struct timespec c;
423 
424 		c = add_tspec_ns(a, NANOSECONDS - 100);
425 		TEST_ASSERT_EQUAL_timespec(E, c);
426 	}
427 
428 	return;
429 }
430 
431 //----------------------------------------------------------------------
432 // test subtraction (difference)
433 //----------------------------------------------------------------------
434 
435 void
test_SubFullNorm(void)436 test_SubFullNorm(void)
437 {
438 	int i, j;
439 
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);
445 			struct timespec c;
446 
447 			c = sub_tspec(a, b);
448 			TEST_ASSERT_EQUAL_timespec(E, c);
449 		}
450 
451 	return;
452 }
453 
454 
455 void
test_SubFullOflow(void)456 test_SubFullOflow(void)
457 {
458 	int i, j;
459 
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);
465 			struct timespec c;
466 
467 			c = sub_tspec(a, b);
468 			TEST_ASSERT_EQUAL_timespec(E, c);
469 		}
470 
471 	return;
472 }
473 
474 
475 void
test_SubNsecNorm(void)476 test_SubNsecNorm(void)
477 {
478 	int i;
479 
480 	for (i = -4; i <= 4; ++i) {
481 		struct timespec a = timespec_init(i, 600);
482 		struct timespec E = timespec_init(i, 200);
483 		struct timespec c;
484 
485 		c = sub_tspec_ns(a, 600 - 200);
486 		TEST_ASSERT_EQUAL_timespec(E, c);
487 	}
488 
489 	return;
490 }
491 
492 
493 void
test_SubNsecOflow(void)494 test_SubNsecOflow(void)
495 {
496 	int i;
497 
498 	for (i = -4; i <= 4; ++i) {
499 		struct timespec a = timespec_init( i , 100);
500 		struct timespec E = timespec_init(i-1, 200);
501 		struct timespec c;
502 
503 		c = sub_tspec_ns(a, NANOSECONDS - 100);
504 		TEST_ASSERT_EQUAL_timespec(E, c);
505 	}
506 
507 	return;
508 }
509 
510 //----------------------------------------------------------------------
511 // test negation
512 //----------------------------------------------------------------------
513 
514 
515 void
test_Neg(void)516 test_Neg(void)
517 {
518 	int i;
519 
520 	for (i = -4; i <= 4; ++i) {
521 		struct timespec a = timespec_init(i, 100);
522 		struct timespec b;
523 		struct timespec c;
524 
525 		b = neg_tspec(a);
526 		c = add_tspec(a, b);
527 		TEST_ASSERT_EQUAL(0, test_tspec(c));
528 	}
529 
530 	return;
531 }
532 
533 //----------------------------------------------------------------------
534 // test abs value
535 //----------------------------------------------------------------------
536 
537 void
test_AbsNoFrac(void)538 test_AbsNoFrac(void)
539 {
540 	int i;
541 
542 	for (i = -4; i <= 4; ++i) {
543 		struct timespec a = timespec_init(i , 0);
544 		struct timespec b;
545 
546 		b = abs_tspec(a);
547 		TEST_ASSERT_EQUAL((i != 0), test_tspec(b));
548 	}
549 
550 	return;
551 }
552 
553 
554 void
test_AbsWithFrac(void)555 test_AbsWithFrac(void)
556 {
557 	int i;
558 
559 	for (i = -4; i <= 4; ++i) {
560 		struct timespec a = timespec_init(i, 100);
561 		struct timespec b;
562 
563 		b = abs_tspec(a);
564 		TEST_ASSERT_EQUAL(1, test_tspec(b));
565 	}
566 
567 	return;
568 }
569 
570 // ---------------------------------------------------------------------
571 // test support stuff -- part 2
572 // ---------------------------------------------------------------------
573 
574 void
test_Helpers2(void)575 test_Helpers2(void)
576 {
577 	struct timespec limit = timespec_init(0, 2);
578 	struct timespec x, y;
579 	long i;
580 
581 	for (x.tv_sec = -2; x.tv_sec < 3; x.tv_sec++)
582 		for (x.tv_nsec = 1;
583 		     x.tv_nsec < 1000000000;
584 		     x.tv_nsec += 499999999) {
585 			for (i = -4; i < 5; ++i) {
586 				y = x;
587 				y.tv_nsec += i;
588 				if (i >= -2 && i <= 2) {
589 					TEST_ASSERT_TRUE(AssertTimespecClose(x, y, limit));
590 				}
591 				else
592 				{
593 					TEST_ASSERT_FALSE(AssertTimespecClose(x, y, limit));
594 				}
595 			}
596 		}
597 
598 	return;
599 }
600 
601 //----------------------------------------------------------------------
602 // conversion to l_fp
603 //----------------------------------------------------------------------
604 
605 void
test_ToLFPbittest(void)606 test_ToLFPbittest(void)
607 {
608 	l_fp lfpClose =  l_fp_init(0, 1);
609 	u_int32 i;
610 
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));
614 		l_fp r;
615 
616 		r = tspec_intv_to_lfp(a);
617 		TEST_ASSERT_TRUE(AssertFpClose(E, r, lfpClose));
618 	}
619 
620 	return;
621 }
622 
623 
624 void
test_ToLFPrelPos(void)625 test_ToLFPrelPos(void)
626 {
627 	int i;
628 
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);
632 		l_fp r;
633 
634 		r = tspec_intv_to_lfp(a);
635 		TEST_ASSERT_EQUAL_l_fp(E, r);
636 	}
637 
638 	return;
639 }
640 
641 
642 void
test_ToLFPrelNeg(void)643 test_ToLFPrelNeg(void)
644 {
645 	int i;
646 
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);
650 		l_fp r;
651 
652 		r = tspec_intv_to_lfp(a);
653 		TEST_ASSERT_EQUAL_l_fp(E, r);
654 	}
655 
656 	return;
657 }
658 
659 
660 void
test_ToLFPabs(void)661 test_ToLFPabs(void)
662 {
663 	int i;
664 
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);
668 		l_fp r;
669 
670 		r = tspec_stamp_to_lfp(a);
671 		TEST_ASSERT_EQUAL_l_fp(E, r);
672 	}
673 
674 	return;
675 }
676 
677 //----------------------------------------------------------------------
678 // conversion from l_fp
679 //----------------------------------------------------------------------
680 
681 void
test_FromLFPbittest(void)682 test_FromLFPbittest(void)
683 {
684 	struct timespec limit = timespec_init(0, 2);
685 
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.
689 	u_int32 tsf;
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);
693 		struct timespec r;
694 
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));
699 	}
700 
701 	return;
702 }
703 
704 
705 void
test_FromLFPrelPos(void)706 test_FromLFPrelPos(void)
707 {
708 	struct timespec limit = timespec_init(0, 2);
709 	int i;
710 
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);
714 		struct timespec r;
715 
716 		r = lfp_intv_to_tspec(a);
717 		TEST_ASSERT_TRUE(AssertTimespecClose(E, r, limit));
718 	}
719 
720 	return;
721 }
722 
723 
724 void
test_FromLFPrelNeg(void)725 test_FromLFPrelNeg(void)
726 {
727 	struct timespec limit = timespec_init(0, 2);
728 	int i;
729 
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);
733 		struct timespec r;
734 
735 		r = lfp_intv_to_tspec(a);
736 		TEST_ASSERT_TRUE(AssertTimespecClose(E, r, limit));
737 	}
738 
739 	return;
740 }
741 
742 
743 // nsec -> frac -> nsec roundtrip, using a prime start and increment
744 void
test_LFProundtrip(void)745 test_LFProundtrip(void)
746 {
747 	int32_t t;
748 	u_int32 i;
749 
750 	for (t = -1; t < 2; ++t)
751 		for (i = 4999; i < 1000000000; i += 10007) {
752 			struct timespec E = timespec_init(t, i);
753 			l_fp a;
754 			struct timespec r;
755 
756 			a = tspec_intv_to_lfp(E);
757 			r = lfp_intv_to_tspec(a);
758 			TEST_ASSERT_EQUAL_timespec(E, r);
759 		}
760 
761 	return;
762 }
763 
764 //----------------------------------------------------------------------
765 // string formatting
766 //----------------------------------------------------------------------
767 
768 void
test_ToString(void)769 test_ToString(void)
770 {
771 	static const struct {
772 		time_t		sec;
773 		long		nsec;
774 		const char *	repr;
775 	} data [] = {
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" },
784 	};
785 	int i;
786 
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);
792 	}
793 
794 	return;
795 }
796 
797 // -*- EOF -*-
798