1 //#include "ntpdtest.h"
6 #include "ntp_calendar.h"
7 #include "ntp_stdlib.h"
8 #include "ntp_leapsec.h"
14 #include "test-libntp.h"
16 static const char leap1 [] =
20 "2272060800 10 # 1 Jan 1972\n"
21 "2287785600 11 # 1 Jul 1972\n"
22 "2303683200 12 # 1 Jan 1973\n"
23 "2335219200 13 # 1 Jan 1974\n"
24 "2366755200 14 # 1 Jan 1975\n"
25 "2398291200 15 # 1 Jan 1976\n"
26 "2429913600 16 # 1 Jan 1977\n"
27 "2461449600 17 # 1 Jan 1978\n"
28 "2492985600 18 # 1 Jan 1979\n"
29 "2524521600 19 # 1 Jan 1980\n"
31 "2571782400 20 # 1 Jul 1981\n"
32 "2603318400 21 # 1 Jul 1982\n"
33 "2634854400 22 # 1 Jul 1983\n"
34 "2698012800 23 # 1 Jul 1985\n"
35 "2776982400 24 # 1 Jan 1988\n"
36 "2840140800 25 # 1 Jan 1990\n"
37 "2871676800 26 # 1 Jan 1991\n"
38 "2918937600 27 # 1 Jul 1992\n"
39 "2950473600 28 # 1 Jul 1993\n"
40 "2982009600 29 # 1 Jul 1994\n"
41 "3029443200 30 # 1 Jan 1996\n"
42 "3076704000 31 # 1 Jul 1997\n"
43 "3124137600 32 # 1 Jan 1999\n"
44 "3345062400 33 # 1 Jan 2006\n"
45 "3439756800 34 # 1 Jan 2009\n"
46 "3550089600 35 # 1 Jul 2012\n"
48 "#h dc2e6b0b 5aade95d a0587abd 4e0dacb4 e4d5049e\n"
51 static const char leap2 [] =
55 "2272060800 10 # 1 Jan 1972\n"
56 "2287785600 11 # 1 Jul 1972\n"
57 "2303683200 12 # 1 Jan 1973\n"
58 "2335219200 13 # 1 Jan 1974\n"
59 "2366755200 14 # 1 Jan 1975\n"
60 "2398291200 15 # 1 Jan 1976\n"
61 "2429913600 16 # 1 Jan 1977\n"
62 "2461449600 17 # 1 Jan 1978\n"
63 "2492985600 18 # 1 Jan 1979\n"
64 "2524521600 19 # 1 Jan 1980\n"
65 "2571782400 20 # 1 Jul 1981\n"
66 "2603318400 21 # 1 Jul 1982\n"
67 "2634854400 22 # 1 Jul 1983\n"
68 "2698012800 23 # 1 Jul 1985\n"
69 "2776982400 24 # 1 Jan 1988\n"
70 "2840140800 25 # 1 Jan 1990\n"
71 "2871676800 26 # 1 Jan 1991\n"
72 "2918937600 27 # 1 Jul 1992\n"
73 "2950473600 28 # 1 Jul 1993\n"
76 // Faked table with a leap second removal at 2009
77 static const char leap3 [] =
81 "2272060800 10 # 1 Jan 1972\n"
82 "2287785600 11 # 1 Jul 1972\n"
83 "2303683200 12 # 1 Jan 1973\n"
84 "2335219200 13 # 1 Jan 1974\n"
85 "2366755200 14 # 1 Jan 1975\n"
86 "2398291200 15 # 1 Jan 1976\n"
87 "2429913600 16 # 1 Jan 1977\n"
88 "2461449600 17 # 1 Jan 1978\n"
89 "2492985600 18 # 1 Jan 1979\n"
90 "2524521600 19 # 1 Jan 1980\n"
91 "2571782400 20 # 1 Jul 1981\n"
92 "2603318400 21 # 1 Jul 1982\n"
93 "2634854400 22 # 1 Jul 1983\n"
94 "2698012800 23 # 1 Jul 1985\n"
95 "2776982400 24 # 1 Jan 1988\n"
96 "2840140800 25 # 1 Jan 1990\n"
97 "2871676800 26 # 1 Jan 1991\n"
98 "2918937600 27 # 1 Jul 1992\n"
99 "2950473600 28 # 1 Jul 1993\n"
100 "2982009600 29 # 1 Jul 1994\n"
101 "3029443200 30 # 1 Jan 1996\n"
102 "3076704000 31 # 1 Jul 1997\n"
103 "3124137600 32 # 1 Jan 1999\n"
104 "3345062400 33 # 1 Jan 2006\n"
105 "3439756800 32 # 1 Jan 2009\n"
106 "3550089600 33 # 1 Jul 2012\n"
109 // short table with good hash
110 static const char leap_ghash [] =
115 "2272060800 10 # 1 Jan 1972\n"
116 "2287785600 11 # 1 Jul 1972\n"
117 "2303683200 12 # 1 Jan 1973\n"
118 "2335219200 13 # 1 Jan 1974\n"
119 "2366755200 14 # 1 Jan 1975\n"
120 "2398291200 15 # 1 Jan 1976\n"
121 "2429913600 16 # 1 Jan 1977\n"
122 "2461449600 17 # 1 Jan 1978\n"
123 "2492985600 18 # 1 Jan 1979\n"
124 "2524521600 19 # 1 Jan 1980\n"
126 "#h 4b304e10 95642b3f c10b91f9 90791725 25f280d0\n"
129 // short table with bad hash
130 static const char leap_bhash [] =
135 "2272060800 10 # 1 Jan 1972\n"
136 "2287785600 11 # 1 Jul 1972\n"
137 "2303683200 12 # 1 Jan 1973\n"
138 "2335219200 13 # 1 Jan 1974\n"
139 "2366755200 14 # 1 Jan 1975\n"
140 "2398291200 15 # 1 Jan 1976\n"
141 "2429913600 16 # 1 Jan 1977\n"
142 "2461449600 17 # 1 Jan 1978\n"
143 "2492985600 18 # 1 Jan 1979\n"
144 "2524521600 19 # 1 Jan 1980\n"
146 "#h dc2e6b0b 5aade95d a0587abd 4e0dacb4 e4d5049e\n"
149 // short table with malformed hash
150 static const char leap_mhash [] =
155 "2272060800 10 # 1 Jan 1972\n"
156 "2287785600 11 # 1 Jul 1972\n"
157 "2303683200 12 # 1 Jan 1973\n"
158 "2335219200 13 # 1 Jan 1974\n"
159 "2366755200 14 # 1 Jan 1975\n"
160 "2398291200 15 # 1 Jan 1976\n"
161 "2429913600 16 # 1 Jan 1977\n"
162 "2461449600 17 # 1 Jan 1978\n"
163 "2492985600 18 # 1 Jan 1979\n"
164 "2524521600 19 # 1 Jan 1980\n"
166 "#h f2349a02 788b9534 a8f2e141 f2029Q6d 4064a7ee\n"
169 // short table with only 4 hash groups
170 static const char leap_shash [] =
175 "2272060800 10 # 1 Jan 1972\n"
176 "2287785600 11 # 1 Jul 1972\n"
177 "2303683200 12 # 1 Jan 1973\n"
178 "2335219200 13 # 1 Jan 1974\n"
179 "2366755200 14 # 1 Jan 1975\n"
180 "2398291200 15 # 1 Jan 1976\n"
181 "2429913600 16 # 1 Jan 1977\n"
182 "2461449600 17 # 1 Jan 1978\n"
183 "2492985600 18 # 1 Jan 1979\n"
184 "2524521600 19 # 1 Jan 1980\n"
186 "#h f2349a02 788b9534 a8f2e141 f2029Q6d\n"
189 // table with good hash and truncated/missing leading zeros
190 static const char leap_gthash [] = {
194 "# Updated through IERS Bulletin C46\n"
195 "# File expires on: 28 June 2014\n"
199 "2272060800 10 # 1 Jan 1972\n"
200 "2287785600 11 # 1 Jul 1972\n"
201 "2303683200 12 # 1 Jan 1973\n"
202 "2335219200 13 # 1 Jan 1974\n"
203 "2366755200 14 # 1 Jan 1975\n"
204 "2398291200 15 # 1 Jan 1976\n"
205 "2429913600 16 # 1 Jan 1977\n"
206 "2461449600 17 # 1 Jan 1978\n"
207 "2492985600 18 # 1 Jan 1979\n"
208 "2524521600 19 # 1 Jan 1980\n"
209 "2571782400 20 # 1 Jul 1981\n"
210 "2603318400 21 # 1 Jul 1982\n"
211 "2634854400 22 # 1 Jul 1983\n"
212 "2698012800 23 # 1 Jul 1985\n"
213 "2776982400 24 # 1 Jan 1988\n"
214 "2840140800 25 # 1 Jan 1990\n"
215 "2871676800 26 # 1 Jan 1991\n"
216 "2918937600 27 # 1 Jul 1992\n"
217 "2950473600 28 # 1 Jul 1993\n"
218 "2982009600 29 # 1 Jul 1994\n"
219 "3029443200 30 # 1 Jan 1996\n"
220 "3076704000 31 # 1 Jul 1997\n"
221 "3124137600 32 # 1 Jan 1999\n"
222 "3345062400 33 # 1 Jan 2006\n"
223 "3439756800 34 # 1 Jan 2009\n"
224 "3550089600 35 # 1 Jul 2012\n"
226 "#h 1151a8f e85a5069 9000fcdb 3d5e5365 1d505b37"
229 static const uint32_t lsec2006 = 3345062400u; // +33, 1 Jan 2006, 00:00:00 utc
230 static const uint32_t lsec2009 = 3439756800u; // +34, 1 Jan 2009, 00:00:00 utc
231 static const uint32_t lsec2012 = 3550089600u; // +35, 1 Jul 2012, 00:00:00 utc
232 static const uint32_t lsec2015 = 3644697600u; // +36, 1 Jul 2015, 00:00:00 utc
234 int stringreader(void* farg)
236 const char ** cpp = (const char**)farg;
249 leap_table_t * pt = leapsec_get_table(0);
250 rc = (pt != NULL) && leapsec_load(pt, stringreader, &cp, blim);
251 rc = rc && leapsec_set_table(pt);
256 setup_clear_table(void)
259 leap_table_t * pt = leapsec_get_table(0);
262 rc = leapsec_set_table(pt);
267 char * CalendarToString(const struct calendar cal) {
268 char * ss = malloc (sizeof (char) * 100);
270 char buffer[100] ="";
271 sprintf(buffer, "%u", cal.year);
274 sprintf(buffer, "%u", (u_int)cal.month);
277 sprintf(buffer, "%u", (u_int)cal.monthday);
280 sprintf(buffer, "%u", (u_int) cal.yearday);
283 sprintf(buffer, "%u", (u_int)cal.hour);
286 sprintf(buffer, "%u", (u_int)cal.minute);
289 sprintf(buffer, "%u", (u_int)cal.second);
291 //ss << cal.year << "-" << (u_int)cal.month << "-" << (u_int)cal.monthday << " (" << cal.yearday << ") " << (u_int)cal.hour << ":" << (u_int)cal.minute << ":" << (u_int)cal.second;
296 int IsEqual(const struct calendar expected, const struct calendar actual) {
297 if (expected.year == actual.year &&
298 (expected.yearday == actual.yearday ||
299 (expected.month == actual.month &&
300 expected.monthday == actual.monthday)) &&
301 expected.hour == actual.hour &&
302 expected.minute == actual.minute &&
303 expected.second == actual.second) {
306 printf("expected: %s but was %s", CalendarToString(expected) ,CalendarToString(actual));
312 //-------------------------
316 ntpcal_set_timefunc(timefunc);
317 settime(1970, 1, 1, 0, 0, 0);
318 leapsec_ut_pristine();
323 ntpcal_set_timefunc(NULL);
326 // =====================================================================
328 // =====================================================================
330 // ----------------------------------------------------------------------
331 void test_ValidateGood(void) {
332 const char *cp = leap_ghash;
333 int rc = leapsec_validate(stringreader, &cp);
334 TEST_ASSERT_EQUAL(LSVALID_GOODHASH, rc);
337 // ----------------------------------------------------------------------
338 void test_ValidateNoHash(void) {
339 const char *cp = leap2;
340 int rc = leapsec_validate(stringreader, &cp);
341 TEST_ASSERT_EQUAL(LSVALID_NOHASH, rc);
344 // ----------------------------------------------------------------------
345 void test_ValidateBad(void) {
346 const char *cp = leap_bhash;
347 int rc = leapsec_validate(stringreader, &cp);
348 TEST_ASSERT_EQUAL(LSVALID_BADHASH, rc);
351 // ----------------------------------------------------------------------
352 void test_ValidateMalformed(void) {
353 const char *cp = leap_mhash;
354 int rc = leapsec_validate(stringreader, &cp);
355 TEST_ASSERT_EQUAL(LSVALID_BADFORMAT, rc);
358 // ----------------------------------------------------------------------
359 void test_ValidateMalformedShort(void) {
360 const char *cp = leap_shash;
361 int rc = leapsec_validate(stringreader, &cp);
362 TEST_ASSERT_EQUAL(LSVALID_BADFORMAT, rc);
365 // ----------------------------------------------------------------------
366 void test_ValidateNoLeadZero(void) {
367 const char *cp = leap_gthash;
368 int rc = leapsec_validate(stringreader, &cp);
369 TEST_ASSERT_EQUAL(LSVALID_GOODHASH, rc);
372 // =====================================================================
374 // =====================================================================
376 // ----------------------------------------------------------------------
377 // test table selection
378 void test_tableSelect(void) {
379 leap_table_t *pt1, *pt2, *pt3, *pt4;
381 pt1 = leapsec_get_table(0);
382 pt2 = leapsec_get_table(0);
383 TEST_ASSERT_EQUAL_MESSAGE(pt1, pt2,"first");
385 pt1 = leapsec_get_table(1);
386 pt2 = leapsec_get_table(1);
387 TEST_ASSERT_EQUAL_MESSAGE(pt1, pt2,"second");
389 pt1 = leapsec_get_table(1);
390 pt2 = leapsec_get_table(0);
391 TEST_ASSERT_NOT_EQUAL(pt1, pt2);
393 pt1 = leapsec_get_table(0);
394 pt2 = leapsec_get_table(1);
395 TEST_ASSERT_NOT_EQUAL(pt1, pt2);
397 leapsec_set_table(pt1);
398 pt2 = leapsec_get_table(0);
399 pt3 = leapsec_get_table(1);
400 TEST_ASSERT_EQUAL(pt1, pt2);
401 TEST_ASSERT_NOT_EQUAL(pt2, pt3);
404 leapsec_set_table(pt1);
405 pt2 = leapsec_get_table(0);
406 pt3 = leapsec_get_table(1);
407 TEST_ASSERT_EQUAL(pt1, pt2);
408 TEST_ASSERT_NOT_EQUAL(pt2, pt3);
411 // ----------------------------------------------------------------------
412 // load file & check expiration
414 void test_loadFileExpire(void) {
415 const char *cp = leap1;
417 leap_table_t * pt = leapsec_get_table(0);
419 rc = leapsec_load(pt, stringreader, &cp, FALSE)
420 && leapsec_set_table(pt);
421 TEST_ASSERT_EQUAL_MESSAGE(1, rc,"first");
422 rc = leapsec_expired(3439756800u, NULL);
423 TEST_ASSERT_EQUAL(0, rc);
424 rc = leapsec_expired(3610569601u, NULL);
425 TEST_ASSERT_EQUAL(1, rc);
428 // ----------------------------------------------------------------------
429 // load file & check time-to-live
431 void test_loadFileTTL(void) {
432 const char *cp = leap1;
434 leap_table_t * pt = leapsec_get_table(0);
435 time_t pivot = 0x70000000u;
437 const uint32_t limit = 3610569600u;
439 rc = leapsec_load(pt, stringreader, &cp, FALSE)
440 && leapsec_set_table(pt);
441 TEST_ASSERT_EQUAL(1, rc); //
443 // exactly 1 day to live
444 rc = leapsec_daystolive(limit - 86400, &pivot);
445 TEST_ASSERT_EQUAL( 1, rc);
446 // less than 1 day to live
447 rc = leapsec_daystolive(limit - 86399, &pivot);
448 TEST_ASSERT_EQUAL( 0, rc);
449 // hit expiration exactly
450 rc = leapsec_daystolive(limit, &pivot);
451 TEST_ASSERT_EQUAL( 0, rc);
452 // expired since 1 sec
453 rc = leapsec_daystolive(limit + 1, &pivot);
454 TEST_ASSERT_EQUAL(-1, rc);
457 // =====================================================================
458 // RANDOM QUERY TESTS
459 // =====================================================================
461 // ----------------------------------------------------------------------
462 // test query in pristine state (bug#2745 misbehaviour)
463 void test_lsQueryPristineState(void) {
467 rc = leapsec_query(&qr, lsec2012, NULL);
468 TEST_ASSERT_EQUAL(FALSE, rc);
469 TEST_ASSERT_EQUAL(0, qr.warped );
470 TEST_ASSERT_EQUAL(LSPROX_NOWARN, qr.proximity);
473 // ----------------------------------------------------------------------
474 // ad-hoc jump: leap second at 2009.01.01 -60days
475 void test_ls2009faraway(void) {
479 rc = setup_load_table(leap1,FALSE);
480 TEST_ASSERT_EQUAL(1, rc);
482 // test 60 days before leap. Nothing scheduled or indicated.
483 rc = leapsec_query(&qr, lsec2009 - 60*SECSPERDAY, NULL);
484 TEST_ASSERT_EQUAL(FALSE, rc);
485 TEST_ASSERT_EQUAL(33, qr.tai_offs);
486 TEST_ASSERT_EQUAL(0, qr.tai_diff);
487 TEST_ASSERT_EQUAL(LSPROX_NOWARN, qr.proximity);
490 // ----------------------------------------------------------------------
491 // ad-hoc jump: leap second at 2009.01.01 -1week
492 void test_ls2009weekaway(void) {
496 rc = setup_load_table(leap1,FALSE);
497 TEST_ASSERT_EQUAL(1, rc);
499 // test 7 days before leap. Leap scheduled, but not yet indicated.
500 rc = leapsec_query(&qr, lsec2009 - 7*SECSPERDAY, NULL);
501 TEST_ASSERT_EQUAL(FALSE, rc);
502 TEST_ASSERT_EQUAL(33, qr.tai_offs);
503 TEST_ASSERT_EQUAL(1, qr.tai_diff);
504 TEST_ASSERT_EQUAL(LSPROX_SCHEDULE, qr.proximity);
507 // ----------------------------------------------------------------------
508 // ad-hoc jump: leap second at 2009.01.01 -1hr
509 void test_ls2009houraway(void) {
513 rc = setup_load_table(leap1,FALSE);
514 TEST_ASSERT_EQUAL(1, rc);
516 // test 1 hour before leap. 61 true seconds to go.
517 rc = leapsec_query(&qr, lsec2009 - SECSPERHR, NULL);
518 TEST_ASSERT_EQUAL(FALSE, rc);
519 TEST_ASSERT_EQUAL(33, qr.tai_offs);
520 TEST_ASSERT_EQUAL(1, qr.tai_diff);
521 TEST_ASSERT_EQUAL(LSPROX_ANNOUNCE, qr.proximity);
524 // ----------------------------------------------------------------------
525 // ad-hoc jump: leap second at 2009.01.01 -1sec
526 void test_ls2009secaway(void) {
530 rc = setup_load_table(leap1,FALSE);
531 TEST_ASSERT_EQUAL(1, rc);
533 // test 1 second before leap (last boundary...) 2 true seconds to go.
534 rc = leapsec_query(&qr, lsec2009 - 1, NULL);
535 TEST_ASSERT_EQUAL(FALSE, rc);
536 TEST_ASSERT_EQUAL(33, qr.tai_offs);
537 TEST_ASSERT_EQUAL(1, qr.tai_diff);
538 TEST_ASSERT_EQUAL(LSPROX_ALERT, qr.proximity);
541 // ----------------------------------------------------------------------
542 // ad-hoc jump to leap second at 2009.01.01
543 void test_ls2009onspot(void) {
547 rc = setup_load_table(leap1,FALSE);
548 TEST_ASSERT_EQUAL(1, rc);
550 // test on-spot: treat leap second as already gone.
551 rc = leapsec_query(&qr, lsec2009, NULL);
552 TEST_ASSERT_EQUAL(FALSE, rc);
553 TEST_ASSERT_EQUAL(34, qr.tai_offs);
554 TEST_ASSERT_EQUAL(0, qr.tai_diff);
555 TEST_ASSERT_EQUAL(LSPROX_NOWARN, qr.proximity);
558 // ----------------------------------------------------------------------
559 // test handling of the leap second at 2009.01.01 without table
560 void test_ls2009nodata(void) {
564 rc = setup_clear_table();
565 TEST_ASSERT_EQUAL(1, rc);
567 // test on-spot with empty table
568 rc = leapsec_query(&qr, lsec2009, NULL);
569 TEST_ASSERT_EQUAL(FALSE, rc);
570 TEST_ASSERT_EQUAL(0, qr.tai_offs);
571 TEST_ASSERT_EQUAL(0, qr.tai_diff);
572 TEST_ASSERT_EQUAL(LSPROX_NOWARN, qr.proximity);
575 // ----------------------------------------------------------------------
576 // test handling of the leap second at 2009.01.01 with culled data
577 void test_ls2009limdata(void) {
581 rc = setup_load_table(leap1, TRUE);
582 TEST_ASSERT_EQUAL(1, rc);
584 // test on-spot with limited table - this is tricky.
585 // The table used ends 2012; depending on the build date, the 2009 entry
586 // might be included or culled. The resulting TAI offset must be either
587 // 34 or 35 seconds, depending on the build date of the test.
588 rc = leapsec_query(&qr, lsec2009, NULL);
589 TEST_ASSERT_EQUAL(FALSE, rc);
590 TEST_ASSERT_TRUE(34 <= qr.tai_offs);
591 TEST_ASSERT_TRUE(35 >= qr.tai_offs);
592 TEST_ASSERT_EQUAL(0, qr.tai_diff);
593 TEST_ASSERT_EQUAL(LSPROX_NOWARN, qr.proximity);
596 // ----------------------------------------------------------------------
597 // Far-distance forward jump into a transiton window.
598 void test_qryJumpFarAhead(void) {
604 for (mode=0; mode < 2; ++mode) {
605 leapsec_ut_pristine();
606 rc = setup_load_table(leap1, FALSE);
607 TEST_ASSERT_EQUAL(1, rc);
608 leapsec_electric(mode);
610 rc = leapsec_query(&qr, lsec2006, NULL);
611 TEST_ASSERT_EQUAL(FALSE, rc);
613 rc = leapsec_query(&qr, lsec2012, NULL);
614 TEST_ASSERT_EQUAL(FALSE, rc);
618 // ----------------------------------------------------------------------
619 // Forward jump into the next transition window
620 void test_qryJumpAheadToTransition(void) {
626 for (mode=0; mode < 2; ++mode) {
627 leapsec_ut_pristine();
628 rc = setup_load_table(leap1, FALSE);
629 TEST_ASSERT_EQUAL(1, rc);
630 leapsec_electric(mode);
632 rc = leapsec_query(&qr, lsec2009-SECSPERDAY, NULL);
633 TEST_ASSERT_EQUAL(FALSE, rc);
635 rc = leapsec_query(&qr, lsec2009+1, NULL);
636 TEST_ASSERT_EQUAL(TRUE, rc);
640 // ----------------------------------------------------------------------
641 // Forward jump over the next transition window
642 void test_qryJumpAheadOverTransition(void) {
648 for (mode=0; mode < 2; ++mode) {
649 leapsec_ut_pristine();
650 rc = setup_load_table(leap1, FALSE);
651 TEST_ASSERT_EQUAL(1, rc);
652 leapsec_electric(mode);
654 rc = leapsec_query(&qr, lsec2009-SECSPERDAY, NULL);
655 TEST_ASSERT_EQUAL(FALSE, rc);
657 rc = leapsec_query(&qr, lsec2009+5, NULL);
658 TEST_ASSERT_EQUAL(FALSE, rc);
662 // =====================================================================
663 // TABLE MODIFICATION AT RUNTIME
664 // =====================================================================
666 // ----------------------------------------------------------------------
667 // add dynamic leap second (like from peer/clock)
668 void test_addDynamic(void) {
672 static const uint32_t insns[] = {
673 2982009600u, // 29 # 1 Jul 1994
674 3029443200u, // 30 # 1 Jan 1996
675 3076704000u, // 31 # 1 Jul 1997
676 3124137600u, // 32 # 1 Jan 1999
677 3345062400u, // 33 # 1 Jan 2006
678 3439756800u, // 34 # 1 Jan 2009
679 3550089600u, // 35 # 1 Jul 2012
683 rc = setup_load_table(leap2, FALSE);
684 TEST_ASSERT_EQUAL(1, rc);
686 leap_table_t * pt = leapsec_get_table(0);
689 for (idx=1; insns[idx]; ++idx) {
690 rc = leapsec_add_dyn(TRUE, insns[idx] - 20*SECSPERDAY - 100, NULL);
691 TEST_ASSERT_EQUAL(TRUE, rc);
693 // try to slip in a previous entry
694 rc = leapsec_add_dyn(TRUE, insns[0] - 20*SECSPERDAY - 100, NULL);
695 TEST_ASSERT_EQUAL(FALSE, rc);
696 //leapsec_dump(pt, (leapsec_dumper)fprintf, stdout);
699 // ----------------------------------------------------------------------
700 // add fixed leap seconds (like from network packet)
701 #if 0 /* currently unused -- possibly revived later */
702 void FAILtest_addFixed(void) {
706 static const struct { uint32_t tt; int of; } insns[] = {
707 {2982009600u, 29},// # 1 Jul 1994
708 {3029443200u, 30},// # 1 Jan 1996
709 {3076704000u, 31},// # 1 Jul 1997
710 {3124137600u, 32},// # 1 Jan 1999
711 {3345062400u, 33},// # 1 Jan 2006
712 {3439756800u, 34},// # 1 Jan 2009
713 {3550089600u, 35},// # 1 Jul 2012
717 rc = setup_load_table(leap2, FALSE);
718 TEST_ASSERT_EQUAL(1, rc);
720 leap_table_t * pt = leapsec_get_table(0);
721 // try to get in BAD time stamps...
722 for (idx=0; insns[idx].tt; ++idx) {
723 rc = leapsec_add_fix(
725 insns[idx].tt - 20*SECSPERDAY - 100,
726 insns[idx].tt + SECSPERDAY,
728 TEST_ASSERT_EQUAL(FALSE, rc);
731 for (idx=0; insns[idx].tt; ++idx) {
732 rc = leapsec_add_fix(
735 insns[idx].tt + SECSPERDAY,
737 TEST_ASSERT_EQUAL(TRUE, rc);
739 // try to slip in a previous entry
740 rc = leapsec_add_fix(
743 insns[0].tt + SECSPERDAY,
745 TEST_ASSERT_EQUAL(FALSE, rc);
746 //leapsec_dump(pt, (leapsec_dumper)fprintf, stdout);
750 // ----------------------------------------------------------------------
751 // add fixed leap seconds (like from network packet)
752 #if 0 /* currently unused -- possibly revived later */
753 void FAILtest_addFixedExtend(void) {
758 static const struct { uint32_t tt; int of; } insns[] = {
759 {2982009600u, 29},// # 1 Jul 1994
760 {3029443200u, 30},// # 1 Jan 1996
764 rc = setup_load_table(leap2, FALSE);
765 TEST_ASSERT_EQUAL(1, rc);
767 leap_table_t * pt = leapsec_get_table(FALSE);
768 for (last=idx=0; insns[idx].tt; ++idx) {
770 rc = leapsec_add_fix(
773 insns[idx].tt + SECSPERDAY,
775 TEST_ASSERT_EQUAL(TRUE, rc);
778 // try to extend the expiration of the last entry
779 rc = leapsec_add_fix(
782 insns[last].tt + 128*SECSPERDAY,
784 TEST_ASSERT_EQUAL(TRUE, rc);
786 // try to extend the expiration of the last entry with wrong offset
787 rc = leapsec_add_fix(
790 insns[last].tt + 129*SECSPERDAY,
792 TEST_ASSERT_EQUAL(FALSE, rc);
793 //leapsec_dump(pt, (leapsec_dumper)fprintf, stdout);
797 // ----------------------------------------------------------------------
798 // add fixed leap seconds (like from network packet) in an otherwise
799 // empty table and test queries before / between /after the tabulated
801 #if 0 /* currently unused -- possibly revived later */
802 void FAILtest_setFixedExtend(void) {
807 static const struct { uint32_t tt; int of; } insns[] = {
808 {2982009600u, 29},// # 1 Jul 1994
809 {3029443200u, 30},// # 1 Jan 1996
813 leap_table_t * pt = leapsec_get_table(0);
814 for (last=idx=0; insns[idx].tt; ++idx) {
816 rc = leapsec_add_fix(
819 insns[idx].tt + 128*SECSPERDAY,
821 TEST_ASSERT_EQUAL(TRUE, rc);
824 rc = leapsec_query(&qr, insns[0].tt - 86400, NULL);
825 TEST_ASSERT_EQUAL(28, qr.tai_offs);
827 rc = leapsec_query(&qr, insns[0].tt + 86400, NULL);
828 TEST_ASSERT_EQUAL(29, qr.tai_offs);
830 rc = leapsec_query(&qr, insns[1].tt - 86400, NULL);
831 TEST_ASSERT_EQUAL(29, qr.tai_offs);
833 rc = leapsec_query(&qr, insns[1].tt + 86400, NULL);
834 TEST_ASSERT_EQUAL(30, qr.tai_offs);
836 //leapsec_dump(pt, (leapsec_dumper)fprintf, stdout);
840 // =====================================================================
841 // AUTOKEY LEAP TRANSFER TESTS
842 // =====================================================================
844 // ----------------------------------------------------------------------
845 // Check if the offset can be applied to an empty table ONCE
846 void test_taiEmptyTable(void) {
849 rc = leapsec_autokey_tai(35, lsec2015-30*86400, NULL);
850 TEST_ASSERT_EQUAL(TRUE, rc);
852 rc = leapsec_autokey_tai(35, lsec2015-29*86400, NULL);
853 TEST_ASSERT_EQUAL(FALSE, rc);
856 // ----------------------------------------------------------------------
857 // Check that with fixed entries the operation fails
858 void test_taiTableFixed(void) {
861 rc = setup_load_table(leap1, FALSE);
862 TEST_ASSERT_EQUAL(1, rc);
864 rc = leapsec_autokey_tai(35, lsec2015-30*86400, NULL);
865 TEST_ASSERT_EQUAL(FALSE, rc);
868 // ----------------------------------------------------------------------
869 // test adjustment with a dynamic entry already there
870 void test_taiTableDynamic(void) {
874 rc = leapsec_add_dyn(TRUE, lsec2015-20*SECSPERDAY, NULL);
875 TEST_ASSERT_EQUAL(TRUE, rc);
877 leapsec_query_era(&era, lsec2015-10, NULL);
878 TEST_ASSERT_EQUAL(0, era.taiof);
879 leapsec_query_era(&era, lsec2015+10, NULL);
880 TEST_ASSERT_EQUAL(1, era.taiof);
882 rc = leapsec_autokey_tai(35, lsec2015-19*86400, NULL);
883 TEST_ASSERT_EQUAL(TRUE, rc);
885 rc = leapsec_autokey_tai(35, lsec2015-19*86400, NULL);
886 TEST_ASSERT_EQUAL(FALSE, rc);
888 leapsec_query_era(&era, lsec2015-10, NULL);
889 TEST_ASSERT_EQUAL(35, era.taiof);
890 leapsec_query_era(&era, lsec2015+10, NULL);
891 TEST_ASSERT_EQUAL(36, era.taiof);
894 // ----------------------------------------------------------------------
895 // test adjustment with a dynamic entry already there in dead zone
896 void test_taiTableDynamicDeadZone(void) {
899 rc = leapsec_add_dyn(TRUE, lsec2015-20*SECSPERDAY, NULL);
900 TEST_ASSERT_EQUAL(TRUE, rc);
902 rc = leapsec_autokey_tai(35, lsec2015-5, NULL);
903 TEST_ASSERT_EQUAL(FALSE, rc);
905 rc = leapsec_autokey_tai(35, lsec2015+5, NULL);
906 TEST_ASSERT_EQUAL(FALSE, rc);
910 // =====================================================================
912 // =====================================================================
914 // ----------------------------------------------------------------------
915 // leap second insert at 2009.01.01, electric mode
916 void test_ls2009seqInsElectric(void) {
920 rc = setup_load_table(leap1,FALSE);
921 TEST_ASSERT_EQUAL(1, rc);
923 TEST_ASSERT_EQUAL(1, leapsec_electric(-1));
925 rc = leapsec_query(&qr, lsec2009 - 60*SECSPERDAY, NULL);
926 TEST_ASSERT_EQUAL(FALSE, rc);
927 TEST_ASSERT_EQUAL(0, qr.warped );
928 TEST_ASSERT_EQUAL(LSPROX_NOWARN, qr.proximity);
930 rc = leapsec_query(&qr, lsec2009 - 7*SECSPERDAY, NULL);
931 TEST_ASSERT_EQUAL(FALSE, rc);
932 TEST_ASSERT_EQUAL(0, qr.warped );
933 TEST_ASSERT_EQUAL(LSPROX_SCHEDULE, qr.proximity);
935 rc = leapsec_query(&qr, lsec2009 - SECSPERHR, NULL);
936 TEST_ASSERT_EQUAL(FALSE, rc);
937 TEST_ASSERT_EQUAL(0, qr.warped );
938 TEST_ASSERT_EQUAL(LSPROX_ANNOUNCE, qr.proximity);
940 rc = leapsec_query(&qr, lsec2009 - 1, NULL);
941 TEST_ASSERT_EQUAL(FALSE, rc);
942 TEST_ASSERT_EQUAL(0, qr.warped );
943 TEST_ASSERT_EQUAL(LSPROX_ALERT, qr.proximity);
945 rc = leapsec_query(&qr, lsec2009, NULL);
946 TEST_ASSERT_EQUAL(TRUE, rc);
947 TEST_ASSERT_EQUAL(0, qr.warped );
948 TEST_ASSERT_EQUAL(LSPROX_NOWARN, qr.proximity);
950 // second call, same time frame: no trigger!
951 rc = leapsec_query(&qr, lsec2009, NULL);
952 TEST_ASSERT_EQUAL(FALSE, rc);
953 TEST_ASSERT_EQUAL(0, qr.warped );
954 TEST_ASSERT_EQUAL(LSPROX_NOWARN, qr.proximity);
957 // ----------------------------------------------------------------------
958 // leap second insert at 2009.01.01, dumb mode
959 void test_ls2009seqInsDumb(void) {
963 rc = setup_load_table(leap1,FALSE);
964 TEST_ASSERT_EQUAL(1, rc);
965 TEST_ASSERT_EQUAL(0, leapsec_electric(-1));
967 rc = leapsec_query(&qr, lsec2009 - 60*SECSPERDAY, NULL);
968 TEST_ASSERT_EQUAL(FALSE, rc);
969 TEST_ASSERT_EQUAL(0, qr.warped );
970 TEST_ASSERT_EQUAL(LSPROX_NOWARN, qr.proximity);
972 rc = leapsec_query(&qr, lsec2009 - 7*SECSPERDAY, NULL);
973 TEST_ASSERT_EQUAL(FALSE, rc);
974 TEST_ASSERT_EQUAL(0, qr.warped );
975 TEST_ASSERT_EQUAL(LSPROX_SCHEDULE, qr.proximity);
977 rc = leapsec_query(&qr, lsec2009 - SECSPERHR, NULL);
978 TEST_ASSERT_EQUAL(FALSE, rc);
979 TEST_ASSERT_EQUAL(0, qr.warped );
980 TEST_ASSERT_EQUAL(LSPROX_ANNOUNCE, qr.proximity);
982 rc = leapsec_query(&qr, lsec2009 - 1, NULL);
983 TEST_ASSERT_EQUAL(FALSE, rc);
984 TEST_ASSERT_EQUAL(0, qr.warped );
985 TEST_ASSERT_EQUAL(LSPROX_ALERT, qr.proximity);
987 rc = leapsec_query(&qr, lsec2009, NULL);
988 TEST_ASSERT_EQUAL(FALSE, rc);
989 TEST_ASSERT_EQUAL(0, qr.warped );
990 TEST_ASSERT_EQUAL(LSPROX_ALERT, qr.proximity);
992 rc = leapsec_query(&qr, lsec2009+1, NULL);
993 TEST_ASSERT_EQUAL(TRUE, rc);
994 TEST_ASSERT_EQUAL(-1, qr.warped );
995 TEST_ASSERT_EQUAL(LSPROX_NOWARN, qr.proximity);
997 // second call, same time frame: no trigger!
998 rc = leapsec_query(&qr, lsec2009, NULL);
999 TEST_ASSERT_EQUAL(FALSE, rc);
1000 TEST_ASSERT_EQUAL(0, qr.warped );
1001 TEST_ASSERT_EQUAL(LSPROX_NOWARN, qr.proximity);
1005 // ----------------------------------------------------------------------
1006 // fake leap second remove at 2009.01.01, electric mode
1007 void test_ls2009seqDelElectric(void) {
1011 rc = setup_load_table(leap3,FALSE);
1012 TEST_ASSERT_EQUAL(1, rc);
1013 leapsec_electric(1);
1014 TEST_ASSERT_EQUAL(1, leapsec_electric(-1));
1016 rc = leapsec_query(&qr, lsec2009 - 60*SECSPERDAY, NULL);
1017 TEST_ASSERT_EQUAL(FALSE, rc);
1018 TEST_ASSERT_EQUAL(0, qr.warped );
1019 TEST_ASSERT_EQUAL(LSPROX_NOWARN, qr.proximity);
1021 rc = leapsec_query(&qr, lsec2009 - 7*SECSPERDAY, NULL);
1022 TEST_ASSERT_EQUAL(FALSE, rc);
1023 TEST_ASSERT_EQUAL(0, qr.warped );
1024 TEST_ASSERT_EQUAL(LSPROX_SCHEDULE, qr.proximity);
1026 rc = leapsec_query(&qr, lsec2009 - SECSPERHR, NULL);
1027 TEST_ASSERT_EQUAL(FALSE, rc);
1028 TEST_ASSERT_EQUAL(0, qr.warped );
1029 TEST_ASSERT_EQUAL(LSPROX_ANNOUNCE, qr.proximity);
1031 rc = leapsec_query(&qr, lsec2009 - 1, NULL);
1032 TEST_ASSERT_EQUAL(FALSE, rc);
1033 TEST_ASSERT_EQUAL(0, qr.warped );
1034 TEST_ASSERT_EQUAL(LSPROX_ALERT, qr.proximity);
1036 rc = leapsec_query(&qr, lsec2009, NULL);
1037 TEST_ASSERT_EQUAL(TRUE, rc);
1038 TEST_ASSERT_EQUAL(0, qr.warped );
1039 TEST_ASSERT_EQUAL(LSPROX_NOWARN, qr.proximity);
1041 // second call, same time frame: no trigger!
1042 rc = leapsec_query(&qr, lsec2009, NULL);
1043 TEST_ASSERT_EQUAL(FALSE, rc);
1044 TEST_ASSERT_EQUAL(0, qr.warped );
1045 TEST_ASSERT_EQUAL(LSPROX_NOWARN, qr.proximity);
1048 // ----------------------------------------------------------------------
1049 // fake leap second remove at 2009.01.01. dumb mode
1050 void test_ls2009seqDelDumb(void) {
1054 rc = setup_load_table(leap3,FALSE);
1055 TEST_ASSERT_EQUAL(1, rc);
1056 TEST_ASSERT_EQUAL(0, leapsec_electric(-1));
1058 rc = leapsec_query(&qr, lsec2009 - 60*SECSPERDAY, NULL);
1059 TEST_ASSERT_EQUAL(FALSE, rc);
1060 TEST_ASSERT_EQUAL(0, qr.warped );
1061 TEST_ASSERT_EQUAL(LSPROX_NOWARN, qr.proximity);
1063 rc = leapsec_query(&qr, lsec2009 - 7*SECSPERDAY, NULL);
1064 TEST_ASSERT_EQUAL(FALSE, rc);
1065 TEST_ASSERT_EQUAL(0, qr.warped );
1066 TEST_ASSERT_EQUAL(LSPROX_SCHEDULE, qr.proximity);
1068 rc = leapsec_query(&qr, lsec2009 - SECSPERHR, NULL);
1069 TEST_ASSERT_EQUAL(FALSE, rc);
1070 TEST_ASSERT_EQUAL(0, qr.warped );
1071 TEST_ASSERT_EQUAL(LSPROX_ANNOUNCE, qr.proximity);
1073 rc = leapsec_query(&qr, lsec2009 - 2, NULL);
1074 TEST_ASSERT_EQUAL(FALSE, rc);
1075 TEST_ASSERT_EQUAL(0, qr.warped );
1076 TEST_ASSERT_EQUAL(LSPROX_ALERT, qr.proximity);
1078 rc = leapsec_query(&qr, lsec2009 - 1, NULL);
1079 TEST_ASSERT_EQUAL(TRUE, rc);
1080 TEST_ASSERT_EQUAL(1, qr.warped );
1081 TEST_ASSERT_EQUAL(LSPROX_NOWARN, qr.proximity);
1083 // second call, same time frame: no trigger!
1084 rc = leapsec_query(&qr, lsec2009, NULL);
1085 TEST_ASSERT_EQUAL(FALSE, rc);
1086 TEST_ASSERT_EQUAL(0, qr.warped );
1087 TEST_ASSERT_EQUAL(LSPROX_NOWARN, qr.proximity);
1090 // ----------------------------------------------------------------------
1091 // leap second insert at 2012.07.01, electric mode
1092 void test_ls2012seqInsElectric(void) {
1096 rc = setup_load_table(leap1,FALSE);
1097 TEST_ASSERT_EQUAL(1, rc);
1098 leapsec_electric(1);
1099 TEST_ASSERT_EQUAL(1, leapsec_electric(-1));
1101 rc = leapsec_query(&qr, lsec2012 - 60*SECSPERDAY, NULL);
1102 TEST_ASSERT_EQUAL(FALSE, rc);
1103 TEST_ASSERT_EQUAL(0, qr.warped );
1104 TEST_ASSERT_EQUAL(LSPROX_NOWARN, qr.proximity);
1106 rc = leapsec_query(&qr, lsec2012 - 7*SECSPERDAY, NULL);
1107 TEST_ASSERT_EQUAL(FALSE, rc);
1108 TEST_ASSERT_EQUAL(0, qr.warped );
1109 TEST_ASSERT_EQUAL(LSPROX_SCHEDULE, qr.proximity);
1111 rc = leapsec_query(&qr, lsec2012 - SECSPERHR, NULL);
1112 TEST_ASSERT_EQUAL(FALSE, rc);
1113 TEST_ASSERT_EQUAL(0, qr.warped );
1114 TEST_ASSERT_EQUAL(LSPROX_ANNOUNCE, qr.proximity);
1116 rc = leapsec_query(&qr, lsec2012 - 1, NULL);
1117 TEST_ASSERT_EQUAL(FALSE, rc);
1118 TEST_ASSERT_EQUAL(0, qr.warped );
1119 TEST_ASSERT_EQUAL(LSPROX_ALERT, qr.proximity);
1121 rc = leapsec_query(&qr, lsec2012, NULL);
1122 TEST_ASSERT_EQUAL(TRUE, rc);
1123 TEST_ASSERT_EQUAL(0, qr.warped );
1124 TEST_ASSERT_EQUAL(LSPROX_NOWARN, qr.proximity);
1126 // second call, same time frame: no trigger!
1127 rc = leapsec_query(&qr, lsec2012, NULL);
1128 TEST_ASSERT_EQUAL(FALSE, rc);
1129 TEST_ASSERT_EQUAL(0, qr.warped );
1130 TEST_ASSERT_EQUAL(LSPROX_NOWARN, qr.proximity);
1133 // ----------------------------------------------------------------------
1134 // leap second insert at 2012.07.01, dumb mode
1135 void test_ls2012seqInsDumb(void) {
1139 rc = setup_load_table(leap1,FALSE);
1140 TEST_ASSERT_EQUAL(1, rc);
1141 TEST_ASSERT_EQUAL(0, leapsec_electric(-1));
1143 rc = leapsec_query(&qr, lsec2012 - 60*SECSPERDAY, NULL);
1144 TEST_ASSERT_EQUAL(FALSE, rc);
1145 TEST_ASSERT_EQUAL(0, qr.warped );
1146 TEST_ASSERT_EQUAL(LSPROX_NOWARN, qr.proximity);
1148 rc = leapsec_query(&qr, lsec2012 - 7*SECSPERDAY, NULL);
1149 TEST_ASSERT_EQUAL(FALSE, rc);
1150 TEST_ASSERT_EQUAL(0, qr.warped );
1151 TEST_ASSERT_EQUAL(LSPROX_SCHEDULE, qr.proximity);
1153 rc = leapsec_query(&qr, lsec2012 - SECSPERHR, NULL);
1154 TEST_ASSERT_EQUAL(FALSE, rc);
1155 TEST_ASSERT_EQUAL(0, qr.warped );
1156 TEST_ASSERT_EQUAL(LSPROX_ANNOUNCE, qr.proximity);
1158 rc = leapsec_query(&qr, lsec2012 - 1, NULL);
1159 TEST_ASSERT_EQUAL(FALSE, rc);
1160 TEST_ASSERT_EQUAL(0, qr.warped );
1161 TEST_ASSERT_EQUAL(LSPROX_ALERT, qr.proximity);
1163 // This is just 1 sec before transition!
1164 rc = leapsec_query(&qr, lsec2012, NULL);
1165 TEST_ASSERT_EQUAL(FALSE, rc);
1166 TEST_ASSERT_EQUAL(0, qr.warped );
1167 TEST_ASSERT_EQUAL(LSPROX_ALERT, qr.proximity);
1169 // NOW the insert/backwarp must happen
1170 rc = leapsec_query(&qr, lsec2012+1, NULL);
1171 TEST_ASSERT_EQUAL(TRUE, rc);
1172 TEST_ASSERT_EQUAL(-1, qr.warped );
1173 TEST_ASSERT_EQUAL(LSPROX_NOWARN, qr.proximity);
1175 // second call with transition time: no trigger!
1176 rc = leapsec_query(&qr, lsec2012, NULL);
1177 TEST_ASSERT_EQUAL(FALSE, rc);
1178 TEST_ASSERT_EQUAL(0, qr.warped );
1179 TEST_ASSERT_EQUAL(LSPROX_NOWARN, qr.proximity);
1182 // ----------------------------------------------------------------------
1183 // test repeated query on empty table in dumb mode
1184 void test_lsEmptyTableDumb(void) {
1192 //time_t pivot(lsec2012);
1193 const uint32_t t0 = lsec2012 - 10;
1194 const uint32_t tE = lsec2012 + 10;
1196 TEST_ASSERT_EQUAL(0, leapsec_electric(-1));
1199 for (t = t0; t != tE; ++t) {
1200 rc = leapsec_query(&qr, t, &pivot);
1201 TEST_ASSERT_EQUAL(FALSE, rc);
1202 TEST_ASSERT_EQUAL(0, qr.warped );
1203 TEST_ASSERT_EQUAL(LSPROX_NOWARN, qr.proximity);
1207 // ----------------------------------------------------------------------
1208 // test repeated query on empty table in electric mode
1209 void test_lsEmptyTableElectric(void) {
1213 leapsec_electric(1);
1214 TEST_ASSERT_EQUAL(1, leapsec_electric(-1));
1217 time_t pivot;//(lsec2012);
1219 const uint32_t t0 = lsec2012 - 10;
1220 const uint32_t tE = lsec2012 + 10;
1223 for (t = t0; t != tE; ++t) {
1224 rc = leapsec_query(&qr, t, &pivot);
1225 TEST_ASSERT_EQUAL(FALSE, rc);
1226 TEST_ASSERT_EQUAL(0, qr.warped );
1227 TEST_ASSERT_EQUAL(LSPROX_NOWARN, qr.proximity);