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