5 #include "ntp_calendar.h"
6 #include "ntp_leapsec.h"
12 static const char leap1 [] =
16 "2272060800 10 # 1 Jan 1972\n"
17 "2287785600 11 # 1 Jul 1972\n"
18 "2303683200 12 # 1 Jan 1973\n"
19 "2335219200 13 # 1 Jan 1974\n"
20 "2366755200 14 # 1 Jan 1975\n"
21 "2398291200 15 # 1 Jan 1976\n"
22 "2429913600 16 # 1 Jan 1977\n"
23 "2461449600 17 # 1 Jan 1978\n"
24 "2492985600 18 # 1 Jan 1979\n"
25 "2524521600 19 # 1 Jan 1980\n"
27 "2571782400 20 # 1 Jul 1981\n"
28 "2603318400 21 # 1 Jul 1982\n"
29 "2634854400 22 # 1 Jul 1983\n"
30 "2698012800 23 # 1 Jul 1985\n"
31 "2776982400 24 # 1 Jan 1988\n"
32 "2840140800 25 # 1 Jan 1990\n"
33 "2871676800 26 # 1 Jan 1991\n"
34 "2918937600 27 # 1 Jul 1992\n"
35 "2950473600 28 # 1 Jul 1993\n"
36 "2982009600 29 # 1 Jul 1994\n"
37 "3029443200 30 # 1 Jan 1996\n"
38 "3076704000 31 # 1 Jul 1997\n"
39 "3124137600 32 # 1 Jan 1999\n"
40 "3345062400 33 # 1 Jan 2006\n"
41 "3439756800 34 # 1 Jan 2009\n"
42 "3550089600 35 # 1 Jul 2012\n"
44 "#h dc2e6b0b 5aade95d a0587abd 4e0dacb4 e4d5049e\n"
47 static const char leap2 [] =
51 "2272060800 10 # 1 Jan 1972\n"
52 "2287785600 11 # 1 Jul 1972\n"
53 "2303683200 12 # 1 Jan 1973\n"
54 "2335219200 13 # 1 Jan 1974\n"
55 "2366755200 14 # 1 Jan 1975\n"
56 "2398291200 15 # 1 Jan 1976\n"
57 "2429913600 16 # 1 Jan 1977\n"
58 "2461449600 17 # 1 Jan 1978\n"
59 "2492985600 18 # 1 Jan 1979\n"
60 "2524521600 19 # 1 Jan 1980\n"
61 "2571782400 20 # 1 Jul 1981\n"
62 "2603318400 21 # 1 Jul 1982\n"
63 "2634854400 22 # 1 Jul 1983\n"
64 "2698012800 23 # 1 Jul 1985\n"
65 "2776982400 24 # 1 Jan 1988\n"
66 "2840140800 25 # 1 Jan 1990\n"
67 "2871676800 26 # 1 Jan 1991\n"
68 "2918937600 27 # 1 Jul 1992\n"
69 "2950473600 28 # 1 Jul 1993\n"
72 // Faked table with a leap second removal at 2009
73 static const char leap3 [] =
77 "2272060800 10 # 1 Jan 1972\n"
78 "2287785600 11 # 1 Jul 1972\n"
79 "2303683200 12 # 1 Jan 1973\n"
80 "2335219200 13 # 1 Jan 1974\n"
81 "2366755200 14 # 1 Jan 1975\n"
82 "2398291200 15 # 1 Jan 1976\n"
83 "2429913600 16 # 1 Jan 1977\n"
84 "2461449600 17 # 1 Jan 1978\n"
85 "2492985600 18 # 1 Jan 1979\n"
86 "2524521600 19 # 1 Jan 1980\n"
87 "2571782400 20 # 1 Jul 1981\n"
88 "2603318400 21 # 1 Jul 1982\n"
89 "2634854400 22 # 1 Jul 1983\n"
90 "2698012800 23 # 1 Jul 1985\n"
91 "2776982400 24 # 1 Jan 1988\n"
92 "2840140800 25 # 1 Jan 1990\n"
93 "2871676800 26 # 1 Jan 1991\n"
94 "2918937600 27 # 1 Jul 1992\n"
95 "2950473600 28 # 1 Jul 1993\n"
96 "2982009600 29 # 1 Jul 1994\n"
97 "3029443200 30 # 1 Jan 1996\n"
98 "3076704000 31 # 1 Jul 1997\n"
99 "3124137600 32 # 1 Jan 1999\n"
100 "3345062400 33 # 1 Jan 2006\n"
101 "3439756800 32 # 1 Jan 2009\n"
102 "3550089600 33 # 1 Jul 2012\n"
105 // short table with good hash
106 static const char leap_ghash [] =
111 "2272060800 10 # 1 Jan 1972\n"
112 "2287785600 11 # 1 Jul 1972\n"
113 "2303683200 12 # 1 Jan 1973\n"
114 "2335219200 13 # 1 Jan 1974\n"
115 "2366755200 14 # 1 Jan 1975\n"
116 "2398291200 15 # 1 Jan 1976\n"
117 "2429913600 16 # 1 Jan 1977\n"
118 "2461449600 17 # 1 Jan 1978\n"
119 "2492985600 18 # 1 Jan 1979\n"
120 "2524521600 19 # 1 Jan 1980\n"
122 "#h 4b304e10 95642b3f c10b91f9 90791725 25f280d0\n"
125 // short table with bad hash
126 static const char leap_bhash [] =
131 "2272060800 10 # 1 Jan 1972\n"
132 "2287785600 11 # 1 Jul 1972\n"
133 "2303683200 12 # 1 Jan 1973\n"
134 "2335219200 13 # 1 Jan 1974\n"
135 "2366755200 14 # 1 Jan 1975\n"
136 "2398291200 15 # 1 Jan 1976\n"
137 "2429913600 16 # 1 Jan 1977\n"
138 "2461449600 17 # 1 Jan 1978\n"
139 "2492985600 18 # 1 Jan 1979\n"
140 "2524521600 19 # 1 Jan 1980\n"
142 "#h dc2e6b0b 5aade95d a0587abd 4e0dacb4 e4d5049e\n"
145 // short table with malformed hash
146 static const char leap_mhash [] =
151 "2272060800 10 # 1 Jan 1972\n"
152 "2287785600 11 # 1 Jul 1972\n"
153 "2303683200 12 # 1 Jan 1973\n"
154 "2335219200 13 # 1 Jan 1974\n"
155 "2366755200 14 # 1 Jan 1975\n"
156 "2398291200 15 # 1 Jan 1976\n"
157 "2429913600 16 # 1 Jan 1977\n"
158 "2461449600 17 # 1 Jan 1978\n"
159 "2492985600 18 # 1 Jan 1979\n"
160 "2524521600 19 # 1 Jan 1980\n"
162 "#h f2349a02 788b9534 a8f2e141 f2029Q6d 4064a7ee\n"
165 // short table with only 4 hash groups
166 static const char leap_shash [] =
171 "2272060800 10 # 1 Jan 1972\n"
172 "2287785600 11 # 1 Jul 1972\n"
173 "2303683200 12 # 1 Jan 1973\n"
174 "2335219200 13 # 1 Jan 1974\n"
175 "2366755200 14 # 1 Jan 1975\n"
176 "2398291200 15 # 1 Jan 1976\n"
177 "2429913600 16 # 1 Jan 1977\n"
178 "2461449600 17 # 1 Jan 1978\n"
179 "2492985600 18 # 1 Jan 1979\n"
180 "2524521600 19 # 1 Jan 1980\n"
182 "#h f2349a02 788b9534 a8f2e141 f2029Q6d\n"
185 // table with good hash and truncated/missing leading zeros
186 static const char leap_gthash [] = {
190 "# Updated through IERS Bulletin C46\n"
191 "# File expires on: 28 June 2014\n"
195 "2272060800 10 # 1 Jan 1972\n"
196 "2287785600 11 # 1 Jul 1972\n"
197 "2303683200 12 # 1 Jan 1973\n"
198 "2335219200 13 # 1 Jan 1974\n"
199 "2366755200 14 # 1 Jan 1975\n"
200 "2398291200 15 # 1 Jan 1976\n"
201 "2429913600 16 # 1 Jan 1977\n"
202 "2461449600 17 # 1 Jan 1978\n"
203 "2492985600 18 # 1 Jan 1979\n"
204 "2524521600 19 # 1 Jan 1980\n"
205 "2571782400 20 # 1 Jul 1981\n"
206 "2603318400 21 # 1 Jul 1982\n"
207 "2634854400 22 # 1 Jul 1983\n"
208 "2698012800 23 # 1 Jul 1985\n"
209 "2776982400 24 # 1 Jan 1988\n"
210 "2840140800 25 # 1 Jan 1990\n"
211 "2871676800 26 # 1 Jan 1991\n"
212 "2918937600 27 # 1 Jul 1992\n"
213 "2950473600 28 # 1 Jul 1993\n"
214 "2982009600 29 # 1 Jul 1994\n"
215 "3029443200 30 # 1 Jan 1996\n"
216 "3076704000 31 # 1 Jul 1997\n"
217 "3124137600 32 # 1 Jan 1999\n"
218 "3345062400 33 # 1 Jan 2006\n"
219 "3439756800 34 # 1 Jan 2009\n"
220 "3550089600 35 # 1 Jul 2012\n"
222 "#h 1151a8f e85a5069 9000fcdb 3d5e5365 1d505b37"
225 static const uint32_t lsec2006 = 3345062400u; // +33, 1 Jan 2006, 00:00:00 utc
226 static const uint32_t lsec2009 = 3439756800u; // +34, 1 Jan 2009, 00:00:00 utc
227 static const uint32_t lsec2012 = 3550089600u; // +35, 1 Jul 2012, 00:00:00 utc
228 static const uint32_t lsec2015 = 3644697600u; // +36, 1 Jul 2015, 00:00:00 utc
230 int stringreader(void* farg)
232 const char ** cpp = (const char**)farg;
245 leap_table_t * pt = leapsec_get_table(0);
246 rc = (pt != NULL) && leapsec_load(pt, stringreader, &cp, blim);
247 rc = rc && leapsec_set_table(pt);
255 leap_table_t * pt = leapsec_get_table(0);
258 rc = leapsec_set_table(pt);
263 class leapsecTest : public ntpdtest {
265 virtual void SetUp();
266 virtual void TearDown();
268 std::string CalendarToString(const calendar &cal) {
269 std::ostringstream ss;
270 ss << cal.year << "-" << (u_int)cal.month << "-" << (u_int)cal.monthday
271 << " (" << cal.yearday << ") " << (u_int)cal.hour << ":"
272 << (u_int)cal.minute << ":" << (u_int)cal.second;
276 ::testing::AssertionResult IsEqual(const calendar &expected, const calendar &actual) {
277 if (expected.year == actual.year &&
278 (expected.yearday == actual.yearday ||
279 (expected.month == actual.month &&
280 expected.monthday == actual.monthday)) &&
281 expected.hour == actual.hour &&
282 expected.minute == actual.minute &&
283 expected.second == actual.second) {
284 return ::testing::AssertionSuccess();
286 return ::testing::AssertionFailure()
287 << "expected: " << CalendarToString(expected) << " but was "
288 << CalendarToString(actual);
293 void leapsecTest::SetUp()
295 ntpcal_set_timefunc(timefunc);
296 settime(1970, 1, 1, 0, 0, 0);
297 leapsec_ut_pristine();
300 void leapsecTest::TearDown()
302 ntpcal_set_timefunc(NULL);
305 // =====================================================================
307 // =====================================================================
309 // ----------------------------------------------------------------------
310 TEST_F(leapsecTest, ValidateGood) {
311 const char *cp = leap_ghash;
312 int rc = leapsec_validate(stringreader, &cp);
313 EXPECT_EQ(LSVALID_GOODHASH, rc);
316 // ----------------------------------------------------------------------
317 TEST_F(leapsecTest, ValidateNoHash) {
318 const char *cp = leap2;
319 int rc = leapsec_validate(stringreader, &cp);
320 EXPECT_EQ(LSVALID_NOHASH, rc);
323 // ----------------------------------------------------------------------
324 TEST_F(leapsecTest, ValidateBad) {
325 const char *cp = leap_bhash;
326 int rc = leapsec_validate(stringreader, &cp);
327 EXPECT_EQ(LSVALID_BADHASH, rc);
330 // ----------------------------------------------------------------------
331 TEST_F(leapsecTest, ValidateMalformed) {
332 const char *cp = leap_mhash;
333 int rc = leapsec_validate(stringreader, &cp);
334 EXPECT_EQ(LSVALID_BADFORMAT, rc);
337 // ----------------------------------------------------------------------
338 TEST_F(leapsecTest, ValidateMalformedShort) {
339 const char *cp = leap_shash;
340 int rc = leapsec_validate(stringreader, &cp);
341 EXPECT_EQ(LSVALID_BADFORMAT, rc);
344 // ----------------------------------------------------------------------
345 TEST_F(leapsecTest, ValidateNoLeadZero) {
346 const char *cp = leap_gthash;
347 int rc = leapsec_validate(stringreader, &cp);
348 EXPECT_EQ(LSVALID_GOODHASH, rc);
351 // =====================================================================
353 // =====================================================================
355 // ----------------------------------------------------------------------
356 // test table selection
357 TEST_F(leapsecTest, tableSelect) {
358 leap_table_t *pt1, *pt2, *pt3, *pt4;
360 pt1 = leapsec_get_table(0);
361 pt2 = leapsec_get_table(0);
364 pt1 = leapsec_get_table(1);
365 pt2 = leapsec_get_table(1);
368 pt1 = leapsec_get_table(1);
369 pt2 = leapsec_get_table(0);
372 pt1 = leapsec_get_table(0);
373 pt2 = leapsec_get_table(1);
376 leapsec_set_table(pt1);
377 pt2 = leapsec_get_table(0);
378 pt3 = leapsec_get_table(1);
383 leapsec_set_table(pt1);
384 pt2 = leapsec_get_table(0);
385 pt3 = leapsec_get_table(1);
390 // ----------------------------------------------------------------------
391 // load file & check expiration
392 TEST_F(leapsecTest, loadFileExpire) {
393 const char *cp = leap1;
395 leap_table_t * pt = leapsec_get_table(0);
397 rc = leapsec_load(pt, stringreader, &cp, FALSE)
398 && leapsec_set_table(pt);
400 rc = leapsec_expired(3439756800u, NULL);
402 rc = leapsec_expired(3610569601u, NULL);
406 // ----------------------------------------------------------------------
407 // load file & check time-to-live
408 TEST_F(leapsecTest, loadFileTTL) {
409 const char *cp = leap1;
411 leap_table_t * pt = leapsec_get_table(0);
412 time_t pivot = 0x70000000u;
414 const uint32_t limit = 3610569600u;
416 rc = leapsec_load(pt, stringreader, &cp, FALSE)
417 && leapsec_set_table(pt);
420 // exactly 1 day to live
421 rc = leapsec_daystolive(limit - 86400, &pivot);
423 // less than 1 day to live
424 rc = leapsec_daystolive(limit - 86399, &pivot);
426 // hit expiration exactly
427 rc = leapsec_daystolive(limit, &pivot);
429 // expired since 1 sec
430 rc = leapsec_daystolive(limit + 1, &pivot);
434 // =====================================================================
435 // RANDOM QUERY TESTS
436 // =====================================================================
438 // ----------------------------------------------------------------------
439 // test query in pristine state (bug#2745 misbehaviour)
440 TEST_F(leapsecTest, lsQueryPristineState) {
444 rc = leapsec_query(&qr, lsec2012, NULL);
445 EXPECT_EQ(FALSE, rc);
446 EXPECT_EQ(0, qr.warped );
447 EXPECT_EQ(LSPROX_NOWARN, qr.proximity);
450 // ----------------------------------------------------------------------
451 // ad-hoc jump: leap second at 2009.01.01 -60days
452 TEST_F(leapsecTest, ls2009faraway) {
456 rc = setup_load_table(leap1);
459 // test 60 days before leap. Nothing scheduled or indicated.
460 rc = leapsec_query(&qr, lsec2009 - 60*SECSPERDAY, NULL);
461 EXPECT_EQ(FALSE, rc);
462 EXPECT_EQ(33, qr.tai_offs);
463 EXPECT_EQ(0, qr.tai_diff);
464 EXPECT_EQ(LSPROX_NOWARN, qr.proximity);
467 // ----------------------------------------------------------------------
468 // ad-hoc jump: leap second at 2009.01.01 -1week
469 TEST_F(leapsecTest, ls2009weekaway) {
473 rc = setup_load_table(leap1);
476 // test 7 days before leap. Leap scheduled, but not yet indicated.
477 rc = leapsec_query(&qr, lsec2009 - 7*SECSPERDAY, NULL);
478 EXPECT_EQ(FALSE, rc);
479 EXPECT_EQ(33, qr.tai_offs);
480 EXPECT_EQ(1, qr.tai_diff);
481 EXPECT_EQ(LSPROX_SCHEDULE, qr.proximity);
484 // ----------------------------------------------------------------------
485 // ad-hoc jump: leap second at 2009.01.01 -1hr
486 TEST_F(leapsecTest, ls2009houraway) {
490 rc = setup_load_table(leap1);
493 // test 1 hour before leap. 61 true seconds to go.
494 rc = leapsec_query(&qr, lsec2009 - SECSPERHR, NULL);
495 EXPECT_EQ(FALSE, rc);
496 EXPECT_EQ(33, qr.tai_offs);
497 EXPECT_EQ(1, qr.tai_diff);
498 EXPECT_EQ(LSPROX_ANNOUNCE, qr.proximity);
501 // ----------------------------------------------------------------------
502 // ad-hoc jump: leap second at 2009.01.01 -1sec
503 TEST_F(leapsecTest, ls2009secaway) {
507 rc = setup_load_table(leap1);
510 // test 1 second before leap (last boundary...) 2 true seconds to go.
511 rc = leapsec_query(&qr, lsec2009 - 1, NULL);
512 EXPECT_EQ(FALSE, rc);
513 EXPECT_EQ(33, qr.tai_offs);
514 EXPECT_EQ(1, qr.tai_diff);
515 EXPECT_EQ(LSPROX_ALERT, qr.proximity);
518 // ----------------------------------------------------------------------
519 // ad-hoc jump to leap second at 2009.01.01
520 TEST_F(leapsecTest, ls2009onspot) {
524 rc = setup_load_table(leap1);
527 // test on-spot: treat leap second as already gone.
528 rc = leapsec_query(&qr, lsec2009, NULL);
529 EXPECT_EQ(FALSE, rc);
530 EXPECT_EQ(34, qr.tai_offs);
531 EXPECT_EQ(0, qr.tai_diff);
532 EXPECT_EQ(LSPROX_NOWARN, qr.proximity);
535 // ----------------------------------------------------------------------
536 // test handling of the leap second at 2009.01.01 without table
537 TEST_F(leapsecTest, ls2009nodata) {
541 rc = setup_clear_table();
544 // test on-spot with empty table
545 rc = leapsec_query(&qr, lsec2009, NULL);
546 EXPECT_EQ(FALSE, rc);
547 EXPECT_EQ(0, qr.tai_offs);
548 EXPECT_EQ(0, qr.tai_diff);
549 EXPECT_EQ(LSPROX_NOWARN, qr.proximity);
552 // ----------------------------------------------------------------------
553 // test handling of the leap second at 2009.01.01 with culled data
554 TEST_F(leapsecTest, ls2009limdata) {
558 rc = setup_load_table(leap1, TRUE);
561 // test on-spot with limited table - this is tricky.
562 // The table used ends 2012; depending on the build date, the 2009 entry
563 // might be included or culled. The resulting TAI offset must be either
564 // 34 or 35 seconds, depending on the build date of the test.
565 rc = leapsec_query(&qr, lsec2009, NULL);
566 EXPECT_EQ(FALSE, rc);
567 EXPECT_LE(34, qr.tai_offs);
568 EXPECT_GE(35, qr.tai_offs);
569 EXPECT_EQ(0, qr.tai_diff);
570 EXPECT_EQ(LSPROX_NOWARN, qr.proximity);
573 // ----------------------------------------------------------------------
574 // Far-distance forward jump into a transiton window.
575 TEST_F(leapsecTest, qryJumpFarAhead) {
580 for (int mode=0; mode < 2; ++mode) {
581 leapsec_ut_pristine();
582 rc = setup_load_table(leap1, FALSE);
584 leapsec_electric(mode);
586 rc = leapsec_query(&qr, lsec2006, NULL);
587 EXPECT_EQ(FALSE, rc);
589 rc = leapsec_query(&qr, lsec2012, NULL);
590 EXPECT_EQ(FALSE, rc);
594 // ----------------------------------------------------------------------
595 // Forward jump into the next transition window
596 TEST_F(leapsecTest, qryJumpAheadToTransition) {
601 for (int mode=0; mode < 2; ++mode) {
602 leapsec_ut_pristine();
603 rc = setup_load_table(leap1, FALSE);
605 leapsec_electric(mode);
607 rc = leapsec_query(&qr, lsec2009-SECSPERDAY, NULL);
608 EXPECT_EQ(FALSE, rc);
610 rc = leapsec_query(&qr, lsec2009+1, NULL);
615 // ----------------------------------------------------------------------
616 // Forward jump over the next transition window
617 TEST_F(leapsecTest, qryJumpAheadOverTransition) {
622 for (int mode=0; mode < 2; ++mode) {
623 leapsec_ut_pristine();
624 rc = setup_load_table(leap1, FALSE);
626 leapsec_electric(mode);
628 rc = leapsec_query(&qr, lsec2009-SECSPERDAY, NULL);
629 EXPECT_EQ(FALSE, rc);
631 rc = leapsec_query(&qr, lsec2009+5, NULL);
632 EXPECT_EQ(FALSE, rc);
636 // =====================================================================
637 // TABLE MODIFICATION AT RUNTIME
638 // =====================================================================
640 // ----------------------------------------------------------------------
641 // add dynamic leap second (like from peer/clock)
642 TEST_F(leapsecTest, addDynamic) {
646 static const uint32_t insns[] = {
647 2982009600u, // 29 # 1 Jul 1994
648 3029443200u, // 30 # 1 Jan 1996
649 3076704000u, // 31 # 1 Jul 1997
650 3124137600u, // 32 # 1 Jan 1999
651 3345062400u, // 33 # 1 Jan 2006
652 3439756800u, // 34 # 1 Jan 2009
653 3550089600u, // 35 # 1 Jul 2012
657 rc = setup_load_table(leap2, FALSE);
660 leap_table_t * pt = leapsec_get_table(0);
661 for (int idx=1; insns[idx]; ++idx) {
662 rc = leapsec_add_dyn(TRUE, insns[idx] - 20*SECSPERDAY - 100, NULL);
665 // try to slip in a previous entry
666 rc = leapsec_add_dyn(TRUE, insns[0] - 20*SECSPERDAY - 100, NULL);
667 EXPECT_EQ(FALSE, rc);
668 //leapsec_dump(pt, (leapsec_dumper)fprintf, stdout);
671 // ----------------------------------------------------------------------
672 // add fixed leap seconds (like from network packet)
673 #if 0 /* currently unused -- possibly revived later */
674 TEST_F(leapsecTest, addFixed) {
678 static const struct { uint32_t tt; int of; } insns[] = {
679 {2982009600u, 29},// # 1 Jul 1994
680 {3029443200u, 30},// # 1 Jan 1996
681 {3076704000u, 31},// # 1 Jul 1997
682 {3124137600u, 32},// # 1 Jan 1999
683 {3345062400u, 33},// # 1 Jan 2006
684 {3439756800u, 34},// # 1 Jan 2009
685 {3550089600u, 35},// # 1 Jul 2012
689 rc = setup_load_table(leap2, FALSE);
692 leap_table_t * pt = leapsec_get_table(0);
693 // try to get in BAD time stamps...
694 for (int idx=0; insns[idx].tt; ++idx) {
695 rc = leapsec_add_fix(
697 insns[idx].tt - 20*SECSPERDAY - 100,
698 insns[idx].tt + SECSPERDAY,
700 EXPECT_EQ(FALSE, rc);
703 for (int idx=0; insns[idx].tt; ++idx) {
704 rc = leapsec_add_fix(
707 insns[idx].tt + SECSPERDAY,
711 // try to slip in a previous entry
712 rc = leapsec_add_fix(
715 insns[0].tt + SECSPERDAY,
717 EXPECT_EQ(FALSE, rc);
718 //leapsec_dump(pt, (leapsec_dumper)fprintf, stdout);
722 // ----------------------------------------------------------------------
723 // add fixed leap seconds (like from network packet)
724 #if 0 /* currently unused -- possibly revived later */
725 TEST_F(leapsecTest, addFixedExtend) {
730 static const struct { uint32_t tt; int of; } insns[] = {
731 {2982009600u, 29},// # 1 Jul 1994
732 {3029443200u, 30},// # 1 Jan 1996
736 rc = setup_load_table(leap2, FALSE);
739 leap_table_t * pt = leapsec_get_table(FALSE);
740 for (last=idx=0; insns[idx].tt; ++idx) {
742 rc = leapsec_add_fix(
745 insns[idx].tt + SECSPERDAY,
750 // try to extend the expiration of the last entry
751 rc = leapsec_add_fix(
754 insns[last].tt + 128*SECSPERDAY,
758 // try to extend the expiration of the last entry with wrong offset
759 rc = leapsec_add_fix(
762 insns[last].tt + 129*SECSPERDAY,
764 EXPECT_EQ(FALSE, rc);
765 //leapsec_dump(pt, (leapsec_dumper)fprintf, stdout);
769 // ----------------------------------------------------------------------
770 // add fixed leap seconds (like from network packet) in an otherwise
771 // empty table and test queries before / between /after the tabulated
773 #if 0 /* currently unused -- possibly revived later */
774 TEST_F(leapsecTest, setFixedExtend) {
779 static const struct { uint32_t tt; int of; } insns[] = {
780 {2982009600u, 29},// # 1 Jul 1994
781 {3029443200u, 30},// # 1 Jan 1996
785 leap_table_t * pt = leapsec_get_table(0);
786 for (last=idx=0; insns[idx].tt; ++idx) {
788 rc = leapsec_add_fix(
791 insns[idx].tt + 128*SECSPERDAY,
796 rc = leapsec_query(&qr, insns[0].tt - 86400, NULL);
797 EXPECT_EQ(28, qr.tai_offs);
799 rc = leapsec_query(&qr, insns[0].tt + 86400, NULL);
800 EXPECT_EQ(29, qr.tai_offs);
802 rc = leapsec_query(&qr, insns[1].tt - 86400, NULL);
803 EXPECT_EQ(29, qr.tai_offs);
805 rc = leapsec_query(&qr, insns[1].tt + 86400, NULL);
806 EXPECT_EQ(30, qr.tai_offs);
808 //leapsec_dump(pt, (leapsec_dumper)fprintf, stdout);
812 // =====================================================================
813 // AUTOKEY LEAP TRANSFER TESTS
814 // =====================================================================
816 // ----------------------------------------------------------------------
817 // Check if the offset can be applied to an empty table ONCE
818 TEST_F(leapsecTest, taiEmptyTable) {
821 rc = leapsec_autokey_tai(35, lsec2015-30*86400, NULL);
824 rc = leapsec_autokey_tai(35, lsec2015-29*86400, NULL);
825 EXPECT_EQ(FALSE, rc);
828 // ----------------------------------------------------------------------
829 // Check that with fixed entries the operation fails
830 TEST_F(leapsecTest, taiTableFixed) {
833 rc = setup_load_table(leap1, FALSE);
836 rc = leapsec_autokey_tai(35, lsec2015-30*86400, NULL);
837 EXPECT_EQ(FALSE, rc);
840 // ----------------------------------------------------------------------
841 // test adjustment with a dynamic entry already there
842 TEST_F(leapsecTest, taiTableDynamic) {
846 rc = leapsec_add_dyn(TRUE, lsec2015-20*SECSPERDAY, NULL);
849 leapsec_query_era(&era, lsec2015-10, NULL);
850 EXPECT_EQ(0, era.taiof);
851 leapsec_query_era(&era, lsec2015+10, NULL);
852 EXPECT_EQ(1, era.taiof);
854 rc = leapsec_autokey_tai(35, lsec2015-19*86400, NULL);
857 rc = leapsec_autokey_tai(35, lsec2015-19*86400, NULL);
858 EXPECT_EQ(FALSE, rc);
860 leapsec_query_era(&era, lsec2015-10, NULL);
861 EXPECT_EQ(35, era.taiof);
862 leapsec_query_era(&era, lsec2015+10, NULL);
863 EXPECT_EQ(36, era.taiof);
866 // ----------------------------------------------------------------------
867 // test adjustment with a dynamic entry already there in dead zone
868 TEST_F(leapsecTest, taiTableDynamicDeadZone) {
871 rc = leapsec_add_dyn(TRUE, lsec2015-20*SECSPERDAY, NULL);
874 rc = leapsec_autokey_tai(35, lsec2015-5, NULL);
875 EXPECT_EQ(FALSE, rc);
877 rc = leapsec_autokey_tai(35, lsec2015+5, NULL);
878 EXPECT_EQ(FALSE, rc);
882 // =====================================================================
884 // =====================================================================
886 // ----------------------------------------------------------------------
887 // leap second insert at 2009.01.01, electric mode
888 TEST_F(leapsecTest, ls2009seqInsElectric) {
892 rc = setup_load_table(leap1);
895 EXPECT_EQ(1, leapsec_electric(-1));
897 rc = leapsec_query(&qr, lsec2009 - 60*SECSPERDAY, NULL);
898 EXPECT_EQ(FALSE, rc);
899 EXPECT_EQ(0, qr.warped );
900 EXPECT_EQ(LSPROX_NOWARN, qr.proximity);
902 rc = leapsec_query(&qr, lsec2009 - 7*SECSPERDAY, NULL);
903 EXPECT_EQ(FALSE, rc);
904 EXPECT_EQ(0, qr.warped );
905 EXPECT_EQ(LSPROX_SCHEDULE, qr.proximity);
907 rc = leapsec_query(&qr, lsec2009 - SECSPERHR, NULL);
908 EXPECT_EQ(FALSE, rc);
909 EXPECT_EQ(0, qr.warped );
910 EXPECT_EQ(LSPROX_ANNOUNCE, qr.proximity);
912 rc = leapsec_query(&qr, lsec2009 - 1, NULL);
913 EXPECT_EQ(FALSE, rc);
914 EXPECT_EQ(0, qr.warped );
915 EXPECT_EQ(LSPROX_ALERT, qr.proximity);
917 rc = leapsec_query(&qr, lsec2009, NULL);
919 EXPECT_EQ(0, qr.warped );
920 EXPECT_EQ(LSPROX_NOWARN, qr.proximity);
922 // second call, same time frame: no trigger!
923 rc = leapsec_query(&qr, lsec2009, NULL);
924 EXPECT_EQ(FALSE, rc);
925 EXPECT_EQ(0, qr.warped );
926 EXPECT_EQ(LSPROX_NOWARN, qr.proximity);
929 // ----------------------------------------------------------------------
930 // leap second insert at 2009.01.01, dumb mode
931 TEST_F(leapsecTest, ls2009seqInsDumb) {
935 rc = setup_load_table(leap1);
937 EXPECT_EQ(0, leapsec_electric(-1));
939 rc = leapsec_query(&qr, lsec2009 - 60*SECSPERDAY, NULL);
940 EXPECT_EQ(FALSE, rc);
941 EXPECT_EQ(0, qr.warped );
942 EXPECT_EQ(LSPROX_NOWARN, qr.proximity);
944 rc = leapsec_query(&qr, lsec2009 - 7*SECSPERDAY, NULL);
945 EXPECT_EQ(FALSE, rc);
946 EXPECT_EQ(0, qr.warped );
947 EXPECT_EQ(LSPROX_SCHEDULE, qr.proximity);
949 rc = leapsec_query(&qr, lsec2009 - SECSPERHR, NULL);
950 EXPECT_EQ(FALSE, rc);
951 EXPECT_EQ(0, qr.warped );
952 EXPECT_EQ(LSPROX_ANNOUNCE, qr.proximity);
954 rc = leapsec_query(&qr, lsec2009 - 1, NULL);
955 EXPECT_EQ(FALSE, rc);
956 EXPECT_EQ(0, qr.warped );
957 EXPECT_EQ(LSPROX_ALERT, qr.proximity);
959 rc = leapsec_query(&qr, lsec2009, NULL);
960 EXPECT_EQ(FALSE, rc);
961 EXPECT_EQ(0, qr.warped );
962 EXPECT_EQ(LSPROX_ALERT, qr.proximity);
964 rc = leapsec_query(&qr, lsec2009+1, NULL);
966 EXPECT_EQ(-1, qr.warped );
967 EXPECT_EQ(LSPROX_NOWARN, qr.proximity);
969 // second call, same time frame: no trigger!
970 rc = leapsec_query(&qr, lsec2009, NULL);
971 EXPECT_EQ(FALSE, rc);
972 EXPECT_EQ(0, qr.warped );
973 EXPECT_EQ(LSPROX_NOWARN, qr.proximity);
977 // ----------------------------------------------------------------------
978 // fake leap second remove at 2009.01.01, electric mode
979 TEST_F(leapsecTest, ls2009seqDelElectric) {
983 rc = setup_load_table(leap3);
986 EXPECT_EQ(1, leapsec_electric(-1));
988 rc = leapsec_query(&qr, lsec2009 - 60*SECSPERDAY, NULL);
989 EXPECT_EQ(FALSE, rc);
990 EXPECT_EQ(0, qr.warped );
991 EXPECT_EQ(LSPROX_NOWARN, qr.proximity);
993 rc = leapsec_query(&qr, lsec2009 - 7*SECSPERDAY, NULL);
994 EXPECT_EQ(FALSE, rc);
995 EXPECT_EQ(0, qr.warped );
996 EXPECT_EQ(LSPROX_SCHEDULE, qr.proximity);
998 rc = leapsec_query(&qr, lsec2009 - SECSPERHR, NULL);
999 EXPECT_EQ(FALSE, rc);
1000 EXPECT_EQ(0, qr.warped );
1001 EXPECT_EQ(LSPROX_ANNOUNCE, qr.proximity);
1003 rc = leapsec_query(&qr, lsec2009 - 1, NULL);
1004 EXPECT_EQ(FALSE, rc);
1005 EXPECT_EQ(0, qr.warped );
1006 EXPECT_EQ(LSPROX_ALERT, qr.proximity);
1008 rc = leapsec_query(&qr, lsec2009, NULL);
1009 EXPECT_EQ(TRUE, rc);
1010 EXPECT_EQ(0, qr.warped );
1011 EXPECT_EQ(LSPROX_NOWARN, qr.proximity);
1013 // second call, same time frame: no trigger!
1014 rc = leapsec_query(&qr, lsec2009, NULL);
1015 EXPECT_EQ(FALSE, rc);
1016 EXPECT_EQ(0, qr.warped );
1017 EXPECT_EQ(LSPROX_NOWARN, qr.proximity);
1020 // ----------------------------------------------------------------------
1021 // fake leap second remove at 2009.01.01. dumb mode
1022 TEST_F(leapsecTest, ls2009seqDelDumb) {
1026 rc = setup_load_table(leap3);
1028 EXPECT_EQ(0, leapsec_electric(-1));
1030 rc = leapsec_query(&qr, lsec2009 - 60*SECSPERDAY, NULL);
1031 EXPECT_EQ(FALSE, rc);
1032 EXPECT_EQ(0, qr.warped );
1033 EXPECT_EQ(LSPROX_NOWARN, qr.proximity);
1035 rc = leapsec_query(&qr, lsec2009 - 7*SECSPERDAY, NULL);
1036 EXPECT_EQ(FALSE, rc);
1037 EXPECT_EQ(0, qr.warped );
1038 EXPECT_EQ(LSPROX_SCHEDULE, qr.proximity);
1040 rc = leapsec_query(&qr, lsec2009 - SECSPERHR, NULL);
1041 EXPECT_EQ(FALSE, rc);
1042 EXPECT_EQ(0, qr.warped );
1043 EXPECT_EQ(LSPROX_ANNOUNCE, qr.proximity);
1045 rc = leapsec_query(&qr, lsec2009 - 2, NULL);
1046 EXPECT_EQ(FALSE, rc);
1047 EXPECT_EQ(0, qr.warped );
1048 EXPECT_EQ(LSPROX_ALERT, qr.proximity);
1050 rc = leapsec_query(&qr, lsec2009 - 1, NULL);
1051 EXPECT_EQ(TRUE, rc);
1052 EXPECT_EQ(1, qr.warped );
1053 EXPECT_EQ(LSPROX_NOWARN, qr.proximity);
1055 // second call, same time frame: no trigger!
1056 rc = leapsec_query(&qr, lsec2009, NULL);
1057 EXPECT_EQ(FALSE, rc);
1058 EXPECT_EQ(0, qr.warped );
1059 EXPECT_EQ(LSPROX_NOWARN, qr.proximity);
1062 // ----------------------------------------------------------------------
1063 // leap second insert at 2012.07.01, electric mode
1064 TEST_F(leapsecTest, ls2012seqInsElectric) {
1068 rc = setup_load_table(leap1);
1070 leapsec_electric(1);
1071 EXPECT_EQ(1, leapsec_electric(-1));
1073 rc = leapsec_query(&qr, lsec2012 - 60*SECSPERDAY, NULL);
1074 EXPECT_EQ(FALSE, rc);
1075 EXPECT_EQ(0, qr.warped );
1076 EXPECT_EQ(LSPROX_NOWARN, qr.proximity);
1078 rc = leapsec_query(&qr, lsec2012 - 7*SECSPERDAY, NULL);
1079 EXPECT_EQ(FALSE, rc);
1080 EXPECT_EQ(0, qr.warped );
1081 EXPECT_EQ(LSPROX_SCHEDULE, qr.proximity);
1083 rc = leapsec_query(&qr, lsec2012 - SECSPERHR, NULL);
1084 EXPECT_EQ(FALSE, rc);
1085 EXPECT_EQ(0, qr.warped );
1086 EXPECT_EQ(LSPROX_ANNOUNCE, qr.proximity);
1088 rc = leapsec_query(&qr, lsec2012 - 1, NULL);
1089 EXPECT_EQ(FALSE, rc);
1090 EXPECT_EQ(0, qr.warped );
1091 EXPECT_EQ(LSPROX_ALERT, qr.proximity);
1093 rc = leapsec_query(&qr, lsec2012, NULL);
1094 EXPECT_EQ(TRUE, rc);
1095 EXPECT_EQ(0, qr.warped );
1096 EXPECT_EQ(LSPROX_NOWARN, qr.proximity);
1098 // second call, same time frame: no trigger!
1099 rc = leapsec_query(&qr, lsec2012, NULL);
1100 EXPECT_EQ(FALSE, rc);
1101 EXPECT_EQ(0, qr.warped );
1102 EXPECT_EQ(LSPROX_NOWARN, qr.proximity);
1105 // ----------------------------------------------------------------------
1106 // leap second insert at 2012.07.01, dumb mode
1107 TEST_F(leapsecTest, ls2012seqInsDumb) {
1111 rc = setup_load_table(leap1);
1113 EXPECT_EQ(0, leapsec_electric(-1));
1115 rc = leapsec_query(&qr, lsec2012 - 60*SECSPERDAY, NULL);
1116 EXPECT_EQ(FALSE, rc);
1117 EXPECT_EQ(0, qr.warped );
1118 EXPECT_EQ(LSPROX_NOWARN, qr.proximity);
1120 rc = leapsec_query(&qr, lsec2012 - 7*SECSPERDAY, NULL);
1121 EXPECT_EQ(FALSE, rc);
1122 EXPECT_EQ(0, qr.warped );
1123 EXPECT_EQ(LSPROX_SCHEDULE, qr.proximity);
1125 rc = leapsec_query(&qr, lsec2012 - SECSPERHR, NULL);
1126 EXPECT_EQ(FALSE, rc);
1127 EXPECT_EQ(0, qr.warped );
1128 EXPECT_EQ(LSPROX_ANNOUNCE, qr.proximity);
1130 rc = leapsec_query(&qr, lsec2012 - 1, NULL);
1131 EXPECT_EQ(FALSE, rc);
1132 EXPECT_EQ(0, qr.warped );
1133 EXPECT_EQ(LSPROX_ALERT, qr.proximity);
1135 // This is just 1 sec before transition!
1136 rc = leapsec_query(&qr, lsec2012, NULL);
1137 EXPECT_EQ(FALSE, rc);
1138 EXPECT_EQ(0, qr.warped );
1139 EXPECT_EQ(LSPROX_ALERT, qr.proximity);
1141 // NOW the insert/backwarp must happen
1142 rc = leapsec_query(&qr, lsec2012+1, NULL);
1143 EXPECT_EQ(TRUE, rc);
1144 EXPECT_EQ(-1, qr.warped );
1145 EXPECT_EQ(LSPROX_NOWARN, qr.proximity);
1147 // second call with transition time: no trigger!
1148 rc = leapsec_query(&qr, lsec2012, NULL);
1149 EXPECT_EQ(FALSE, rc);
1150 EXPECT_EQ(0, qr.warped );
1151 EXPECT_EQ(LSPROX_NOWARN, qr.proximity);
1154 // ----------------------------------------------------------------------
1155 // test repeated query on empty table in dumb mode
1156 TEST_F(leapsecTest, lsEmptyTableDumb) {
1160 const time_t pivot(lsec2012);
1161 const uint32_t t0 (lsec2012 - 10);
1162 const uint32_t tE (lsec2012 + 10);
1164 EXPECT_EQ(0, leapsec_electric(-1));
1166 for (uint32_t t = t0; t != tE; ++t) {
1167 rc = leapsec_query(&qr, t, &pivot);
1168 EXPECT_EQ(FALSE, rc);
1169 EXPECT_EQ(0, qr.warped );
1170 EXPECT_EQ(LSPROX_NOWARN, qr.proximity);
1174 // ----------------------------------------------------------------------
1175 // test repeated query on empty table in electric mode
1176 TEST_F(leapsecTest, lsEmptyTableElectric) {
1180 leapsec_electric(1);
1181 EXPECT_EQ(1, leapsec_electric(-1));
1183 const time_t pivot(lsec2012);
1184 const uint32_t t0 (lsec2012 - 10);
1185 const uint32_t tE (lsec2012 + 10);
1187 for (time_t t = t0; t != tE; ++t) {
1188 rc = leapsec_query(&qr, t, &pivot);
1189 EXPECT_EQ(FALSE, rc);
1190 EXPECT_EQ(0, qr.warped );
1191 EXPECT_EQ(LSPROX_NOWARN, qr.proximity);