xref: /netbsd-src/external/bsd/ntp/dist/tests/ntpd/leapsec.c (revision eabc0478de71e4e011a5b4e0392741e01d491794)
1 /*	$NetBSD: leapsec.c,v 1.4 2024/08/18 20:47:27 christos Exp $	*/
2 
3 //#include "ntpdtest.h"
4 #include "config.h"
5 
6 
7 #include "ntp.h"
8 #include "ntp_calendar.h"
9 #include "ntp_stdlib.h"
10 #include "ntp_leapsec.h"
11 
12 #include "unity.h"
13 
14 #include <string.h>
15 
16 extern	void	setUp(void);
17 extern	void	tearDown(void);
18 
19 #include "test-libntp.h"
20 
21 static const char leap1 [] =
22     "#\n"
23     "#@ 	3610569600\n"
24     "#\n"
25     "2272060800 10	# 1 Jan 1972\n"
26     "2287785600	11	# 1 Jul 1972\n"
27     "2303683200	12	# 1 Jan 1973\n"
28     "2335219200	13	# 1 Jan 1974\n"
29     "2366755200	14	# 1 Jan 1975\n"
30     "2398291200	15	# 1 Jan 1976\n"
31     "2429913600	16	# 1 Jan 1977\n"
32     "2461449600	17	# 1 Jan 1978\n"
33     "2492985600	18	# 1 Jan 1979\n"
34     "2524521600	19	# 1 Jan 1980\n"
35     "   \t  \n"
36     "2571782400	20	# 1 Jul 1981\n"
37     "2603318400	21	# 1 Jul 1982\n"
38     "2634854400	22	# 1 Jul 1983\n"
39     "2698012800	23	# 1 Jul 1985\n"
40     "2776982400	24	# 1 Jan 1988\n"
41     "2840140800	25	# 1 Jan 1990\n"
42     "2871676800	26	# 1 Jan 1991\n"
43     "2918937600	27	# 1 Jul 1992\n"
44     "2950473600	28	# 1 Jul 1993\n"
45     "2982009600	29	# 1 Jul 1994\n"
46     "3029443200	30	# 1 Jan 1996\n"
47     "3076704000	31	# 1 Jul 1997\n"
48     "3124137600	32	# 1 Jan 1999\n"
49     "3345062400	33	# 1 Jan 2006\n"
50     "3439756800	34	# 1 Jan 2009\n"
51     "3550089600	35	# 1 Jul 2012\n"
52     "#\n"
53     "#h	dc2e6b0b 5aade95d a0587abd 4e0dacb4 e4d5049e\n"
54     "#\n";
55 
56 static const char leap2 [] =
57     "#\n"
58     "#@ 	2950473700\n"
59     "#\n"
60     "2272060800 10	# 1 Jan 1972\n"
61     "2287785600	11	# 1 Jul 1972\n"
62     "2303683200	12	# 1 Jan 1973\n"
63     "2335219200	13	# 1 Jan 1974\n"
64     "2366755200	14	# 1 Jan 1975\n"
65     "2398291200	15	# 1 Jan 1976\n"
66     "2429913600	16	# 1 Jan 1977\n"
67     "2461449600	17	# 1 Jan 1978\n"
68     "2492985600	18	# 1 Jan 1979\n"
69     "2524521600	19	# 1 Jan 1980\n"
70     "2571782400	20	# 1 Jul 1981\n"
71     "2603318400	21	# 1 Jul 1982\n"
72     "2634854400	22	# 1 Jul 1983\n"
73     "2698012800	23	# 1 Jul 1985\n"
74     "2776982400	24	# 1 Jan 1988\n"
75     "2840140800	25	# 1 Jan 1990\n"
76     "2871676800	26	# 1 Jan 1991\n"
77     "2918937600	27	# 1 Jul 1992\n"
78     "2950473600	28	# 1 Jul 1993\n"
79     "#\n";
80 
81 // Faked table with a leap second removal at 2009
82 static const char leap3 [] =
83     "#\n"
84     "#@ 	3610569600\n"
85     "#\n"
86     "2272060800 10	# 1 Jan 1972\n"
87     "2287785600	11	# 1 Jul 1972\n"
88     "2303683200	12	# 1 Jan 1973\n"
89     "2335219200	13	# 1 Jan 1974\n"
90     "2366755200	14	# 1 Jan 1975\n"
91     "2398291200	15	# 1 Jan 1976\n"
92     "2429913600	16	# 1 Jan 1977\n"
93     "2461449600	17	# 1 Jan 1978\n"
94     "2492985600	18	# 1 Jan 1979\n"
95     "2524521600	19	# 1 Jan 1980\n"
96     "2571782400	20	# 1 Jul 1981\n"
97     "2603318400	21	# 1 Jul 1982\n"
98     "2634854400	22	# 1 Jul 1983\n"
99     "2698012800	23	# 1 Jul 1985\n"
100     "2776982400	24	# 1 Jan 1988\n"
101     "2840140800	25	# 1 Jan 1990\n"
102     "2871676800	26	# 1 Jan 1991\n"
103     "2918937600	27	# 1 Jul 1992\n"
104     "2950473600	28	# 1 Jul 1993\n"
105     "2982009600	29	# 1 Jul 1994\n"
106     "3029443200	30	# 1 Jan 1996\n"
107     "3076704000	31	# 1 Jul 1997\n"
108     "3124137600	32	# 1 Jan 1999\n"
109     "3345062400	33	# 1 Jan 2006\n"
110     "3439756800	32	# 1 Jan 2009\n"
111     "3550089600	33	# 1 Jul 2012\n"
112     "#\n";
113 
114 // short table with good hash
115 static const char leap_ghash [] =
116     "#\n"
117     "#@ 	3610569600\n"
118     "#$ 	3610566000\n"
119     "#\n"
120     "2272060800 10	# 1 Jan 1972\n"
121     "2287785600	11	# 1 Jul 1972\n"
122     "2303683200	12	# 1 Jan 1973\n"
123     "2335219200	13	# 1 Jan 1974\n"
124     "2366755200	14	# 1 Jan 1975\n"
125     "2398291200	15	# 1 Jan 1976\n"
126     "2429913600	16	# 1 Jan 1977\n"
127     "2461449600	17	# 1 Jan 1978\n"
128     "2492985600	18	# 1 Jan 1979\n"
129     "2524521600	19	# 1 Jan 1980\n"
130     "#\n"
131     "#h 4b304e10 95642b3f c10b91f9 90791725 25f280d0\n"
132     "#\n";
133 
134 // short table with bad hash
135 static const char leap_bhash [] =
136     "#\n"
137     "#@ 	3610569600\n"
138     "#$ 	3610566000\n"
139     "#\n"
140     "2272060800 10	# 1 Jan 1972\n"
141     "2287785600	11	# 1 Jul 1972\n"
142     "2303683200	12	# 1 Jan 1973\n"
143     "2335219200	13	# 1 Jan 1974\n"
144     "2366755200	14	# 1 Jan 1975\n"
145     "2398291200	15	# 1 Jan 1976\n"
146     "2429913600	16	# 1 Jan 1977\n"
147     "2461449600	17	# 1 Jan 1978\n"
148     "2492985600	18	# 1 Jan 1979\n"
149     "2524521600	19	# 1 Jan 1980\n"
150     "#\n"
151     "#h	dc2e6b0b 5aade95d a0587abd 4e0dacb4 e4d5049e\n"
152     "#\n";
153 
154 // short table with malformed hash
155 static const char leap_mhash [] =
156     "#\n"
157     "#@ 	3610569600\n"
158     "#$ 	3610566000\n"
159     "#\n"
160     "2272060800 10	# 1 Jan 1972\n"
161     "2287785600	11	# 1 Jul 1972\n"
162     "2303683200	12	# 1 Jan 1973\n"
163     "2335219200	13	# 1 Jan 1974\n"
164     "2366755200	14	# 1 Jan 1975\n"
165     "2398291200	15	# 1 Jan 1976\n"
166     "2429913600	16	# 1 Jan 1977\n"
167     "2461449600	17	# 1 Jan 1978\n"
168     "2492985600	18	# 1 Jan 1979\n"
169     "2524521600	19	# 1 Jan 1980\n"
170     "#\n"
171     "#h f2349a02 788b9534 a8f2e141 f2029Q6d 4064a7ee\n"
172     "#\n";
173 
174 // short table with only 4 hash groups
175 static const char leap_shash [] =
176     "#\n"
177     "#@ 	3610569600\n"
178     "#$ 	3610566000\n"
179     "#\n"
180     "2272060800 10	# 1 Jan 1972\n"
181     "2287785600	11	# 1 Jul 1972\n"
182     "2303683200	12	# 1 Jan 1973\n"
183     "2335219200	13	# 1 Jan 1974\n"
184     "2366755200	14	# 1 Jan 1975\n"
185     "2398291200	15	# 1 Jan 1976\n"
186     "2429913600	16	# 1 Jan 1977\n"
187     "2461449600	17	# 1 Jan 1978\n"
188     "2492985600	18	# 1 Jan 1979\n"
189     "2524521600	19	# 1 Jan 1980\n"
190     "#\n"
191     "#h f2349a02 788b9534 a8f2e141 f2029Q6d\n"
192     "#\n";
193 
194 // table with good hash and truncated/missing leading zeros
195 static const char leap_gthash [] = {
196     "#\n"
197     "#$	 3535228800\n"
198     "#\n"
199     "#	Updated through IERS Bulletin C46\n"
200     "#	File expires on:  28 June 2014\n"
201     "#\n"
202     "#@	3612902400\n"
203     "#\n"
204     "2272060800	10	# 1 Jan 1972\n"
205     "2287785600	11	# 1 Jul 1972\n"
206     "2303683200	12	# 1 Jan 1973\n"
207     "2335219200	13	# 1 Jan 1974\n"
208     "2366755200	14	# 1 Jan 1975\n"
209     "2398291200	15	# 1 Jan 1976\n"
210     "2429913600	16	# 1 Jan 1977\n"
211     "2461449600	17	# 1 Jan 1978\n"
212     "2492985600	18	# 1 Jan 1979\n"
213     "2524521600	19	# 1 Jan 1980\n"
214     "2571782400	20	# 1 Jul 1981\n"
215     "2603318400	21	# 1 Jul 1982\n"
216     "2634854400	22	# 1 Jul 1983\n"
217     "2698012800	23	# 1 Jul 1985\n"
218     "2776982400	24	# 1 Jan 1988\n"
219     "2840140800	25	# 1 Jan 1990\n"
220     "2871676800	26	# 1 Jan 1991\n"
221     "2918937600	27	# 1 Jul 1992\n"
222     "2950473600	28	# 1 Jul 1993\n"
223     "2982009600	29	# 1 Jul 1994\n"
224     "3029443200	30	# 1 Jan 1996\n"
225     "3076704000	31	# 1 Jul 1997\n"
226     "3124137600	32	# 1 Jan 1999\n"
227     "3345062400	33	# 1 Jan 2006\n"
228     "3439756800	34	# 1 Jan 2009\n"
229     "3550089600	35	# 1 Jul 2012\n"
230     "#\n"
231     "#h	1151a8f e85a5069 9000fcdb 3d5e5365 1d505b37"
232 };
233 
234 static const uint32_t lsec2006 = 3345062400u; // +33, 1 Jan 2006, 00:00:00 utc
235 static const uint32_t lsec2009 = 3439756800u; // +34, 1 Jan 2009, 00:00:00 utc
236 static const uint32_t lsec2012 = 3550089600u; // +35, 1 Jul 2012, 00:00:00 utc
237 static const uint32_t lsec2015 = 3644697600u; // +36, 1 Jul 2015, 00:00:00 utc
238 
239 static int stringreader(void* farg)
240 {
241 	const char ** cpp = (const char**)farg;
242 
243 	if (**cpp)
244 		return *(*cpp)++;
245 	else
246 		return EOF;
247 }
248 
249 static int/*BOOL*/
250 setup_load_table(
251 	const char * cp,
252 	int          blim)
253 {
254 	int            rc;
255 	leap_table_t * pt = leapsec_get_table(0);
256 
257 	rc = (pt != NULL) && leapsec_load(pt, stringreader, &cp, blim);
258 	rc = rc && leapsec_set_table(pt);
259 	return rc;
260 }
261 
262 static int/*BOOL*/
263 setup_clear_table(void)
264 {
265 	int            rc;
266 	leap_table_t * pt = leapsec_get_table(0);
267 
268 	if (pt)
269 		leapsec_clear(pt);
270 	rc = leapsec_set_table(pt);
271 	return rc;
272 }
273 
274 #if 0 /* formatting & compare currently not used... */
275 static const char *
276 CalendarToString(const struct calendar cal)
277 {
278 	char * str;
279 
280 	LIB_GETBUF(str);
281 	snprintf(str, LIB_BUFLENGTH,
282 		 "%04hu-%02hhu-%02hhu (%hu) %02hhu:%02hhu:%02hhu",
283 		 cal.year, cal.month, cal.monthday, cal.yearday,
284 		 cal.hour, cal.minute, cal.second);
285 	return str;
286 }
287 
288 static int
289 IsEqual(const struct calendar expected, const struct calendar actual)
290 {
291 
292 	if (   expected.year == actual.year
293 	    && (   expected.yearday == actual.yearday
294 		|| (   expected.month == actual.month
295 		    && expected.monthday == actual.monthday))
296 	    && expected.hour == actual.hour
297 	    && expected.minute == actual.minute
298 	    && expected.second == actual.second) {
299 		return TRUE;
300 	} else {
301 		const char *p_exp = CalendarToString(expected);
302 		const char *p_act = CalendarToString(actual);
303 		printf("expected: %s but was %s", p_exp, p_act);
304 		return FALSE;
305 	}
306 }
307 #endif /*0*/
308 
309 //-------------------------
310 
311 void
312 setUp(void)
313 {
314     ntpcal_set_timefunc(timefunc);
315     settime(1970, 1, 1, 0, 0, 0);
316     leapsec_ut_pristine();
317 }
318 
319 void
320 tearDown(void)
321 {
322     ntpcal_set_timefunc(NULL);
323 }
324 
325 // =====================================================================
326 // VALIDATION TESTS
327 // =====================================================================
328 
329 // ----------------------------------------------------------------------
330 extern void test_ValidateGood(void);
331 void test_ValidateGood(void)
332 {
333 	const char *cp = leap_ghash;
334 	int         rc = leapsec_validate(stringreader, &cp);
335 
336 	TEST_ASSERT_EQUAL(LSVALID_GOODHASH, rc);
337 }
338 
339 // ----------------------------------------------------------------------
340 extern void test_ValidateNoHash(void);
341 void test_ValidateNoHash(void)
342 {
343 	const char *cp = leap2;
344 	int         rc = leapsec_validate(stringreader, &cp);
345 
346 	TEST_ASSERT_EQUAL(LSVALID_NOHASH, rc);
347 }
348 
349 // ----------------------------------------------------------------------
350 extern void test_ValidateBad(void);
351 void test_ValidateBad(void)
352 {
353 	const char *cp = leap_bhash;
354 	int         rc = leapsec_validate(stringreader, &cp);
355 
356 	TEST_ASSERT_EQUAL(LSVALID_BADHASH, rc);
357 }
358 
359 // ----------------------------------------------------------------------
360 extern void test_ValidateMalformed(void);
361 void test_ValidateMalformed(void)
362 {
363 	const char *cp = leap_mhash;
364 	int         rc = leapsec_validate(stringreader, &cp);
365 
366 	TEST_ASSERT_EQUAL(LSVALID_BADFORMAT, rc);
367 }
368 
369 // ----------------------------------------------------------------------
370 extern void test_ValidateMalformedShort(void);
371 void test_ValidateMalformedShort(void)
372 {
373 	const char *cp = leap_shash;
374 	int         rc = leapsec_validate(stringreader, &cp);
375 
376 	TEST_ASSERT_EQUAL(LSVALID_BADFORMAT, rc);
377 }
378 
379 // ----------------------------------------------------------------------
380 extern void test_ValidateNoLeadZero(void);
381 void test_ValidateNoLeadZero(void)
382 {
383 	const char *cp = leap_gthash;
384 	int         rc = leapsec_validate(stringreader, &cp);
385 
386 	TEST_ASSERT_EQUAL(LSVALID_GOODHASH, rc);
387 }
388 
389 // =====================================================================
390 // BASIC FUNCTIONS
391 // =====================================================================
392 
393 // ----------------------------------------------------------------------
394 // test table selection
395 extern void test_tableSelect(void);
396 void test_tableSelect(void)
397 {
398     leap_table_t *pt1, *pt2, *pt3;
399 
400 	pt1 = leapsec_get_table(0);
401 	pt2 = leapsec_get_table(0);
402 	TEST_ASSERT_EQUAL_MESSAGE(pt1, pt2,"first");
403 
404 	pt1 = leapsec_get_table(1);
405 	pt2 = leapsec_get_table(1);
406 	TEST_ASSERT_EQUAL_MESSAGE(pt1, pt2,"second");
407 
408 	pt1 = leapsec_get_table(1);
409 	pt2 = leapsec_get_table(0);
410 	TEST_ASSERT_NOT_EQUAL(pt1, pt2);
411 
412 	pt1 = leapsec_get_table(0);
413 	pt2 = leapsec_get_table(1);
414 	TEST_ASSERT_NOT_EQUAL(pt1, pt2);
415 
416 	leapsec_set_table(pt1);
417 	pt2 = leapsec_get_table(0);
418 	pt3 = leapsec_get_table(1);
419 	TEST_ASSERT_EQUAL(pt1, pt2);
420 	TEST_ASSERT_NOT_EQUAL(pt2, pt3);
421 
422 	pt1 = pt3;
423 	leapsec_set_table(pt1);
424 	pt2 = leapsec_get_table(0);
425 	pt3 = leapsec_get_table(1);
426 	TEST_ASSERT_EQUAL(pt1, pt2);
427 	TEST_ASSERT_NOT_EQUAL(pt2, pt3);
428 }
429 
430 // ----------------------------------------------------------------------
431 // load file & check expiration
432 extern void test_loadFileExpire(void);
433 void test_loadFileExpire(void)
434 {
435 	const char *cp = leap1;
436 	int rc;
437 	leap_table_t * pt = leapsec_get_table(0);
438 
439 	rc =   leapsec_load(pt, stringreader, &cp, FALSE)
440 	    && leapsec_set_table(pt);
441 	TEST_ASSERT_EQUAL_MESSAGE(1, rc,"first");
442 	rc = leapsec_expired(3439756800u, NULL);
443 	TEST_ASSERT_EQUAL(0, rc);
444 	rc = leapsec_expired(3610569601u, NULL);
445 	TEST_ASSERT_EQUAL(1, rc);
446 }
447 
448 // ----------------------------------------------------------------------
449 // load file & check time-to-live
450 extern void test_loadFileTTL(void);
451 void test_loadFileTTL(void)
452 {
453 	const char     *cp = leap1;
454 	int		rc;
455 	leap_table_t  * pt = leapsec_get_table(0);
456 	time_t		pivot = 0x70000000u;
457 	const uint32_t	limit = 3610569600u;
458 
459 	rc =   leapsec_load(pt, stringreader, &cp, FALSE)
460 	    && leapsec_set_table(pt);
461 	TEST_ASSERT_EQUAL(1, rc); //
462 
463 	// exactly 1 day to live
464 	rc = leapsec_daystolive(limit - 86400, &pivot);
465 	TEST_ASSERT_EQUAL( 1, rc);
466 	// less than 1 day to live
467 	rc = leapsec_daystolive(limit - 86399, &pivot);
468 	TEST_ASSERT_EQUAL( 0, rc);
469 	// hit expiration exactly
470 	rc = leapsec_daystolive(limit, &pivot);
471 	TEST_ASSERT_EQUAL( 0, rc);
472 	// expired since 1 sec
473 	rc = leapsec_daystolive(limit + 1, &pivot);
474 	TEST_ASSERT_EQUAL(-1, rc);
475 }
476 
477 // =====================================================================
478 // RANDOM QUERY TESTS
479 // =====================================================================
480 
481 // ----------------------------------------------------------------------
482 // test query in pristine state (bug#2745 misbehaviour)
483 extern void test_lsQueryPristineState(void);
484 void test_lsQueryPristineState(void)
485 {
486 	int            rc;
487 	leap_result_t  qr;
488 
489 	rc = leapsec_query(&qr, lsec2012, NULL);
490 	TEST_ASSERT_EQUAL(FALSE, rc);
491 	TEST_ASSERT_EQUAL(0,             qr.warped   );
492 	TEST_ASSERT_EQUAL(LSPROX_NOWARN, qr.proximity);
493 }
494 
495 // ----------------------------------------------------------------------
496 // ad-hoc jump: leap second at 2009.01.01 -60days
497 extern void test_ls2009faraway(void);
498 void test_ls2009faraway(void)
499 {
500 	int            rc;
501 	leap_result_t  qr;
502 
503 	rc = setup_load_table(leap1,FALSE);
504 	TEST_ASSERT_EQUAL(1, rc);
505 
506 	// test 60 days before leap. Nothing scheduled or indicated.
507 	rc = leapsec_query(&qr, lsec2009 - 60*SECSPERDAY, NULL);
508 	TEST_ASSERT_EQUAL(FALSE, rc);
509 	TEST_ASSERT_EQUAL(33, qr.tai_offs);
510 	TEST_ASSERT_EQUAL(0,  qr.tai_diff);
511 	TEST_ASSERT_EQUAL(LSPROX_NOWARN, qr.proximity);
512 }
513 
514 // ----------------------------------------------------------------------
515 // ad-hoc jump: leap second at 2009.01.01 -1week
516 extern void test_ls2009weekaway(void);
517 void test_ls2009weekaway(void)
518 {
519 	int            rc;
520 	leap_result_t  qr;
521 
522 	rc = setup_load_table(leap1,FALSE);
523 	TEST_ASSERT_EQUAL(1, rc);
524 
525 	// test 7 days before leap. Leap scheduled, but not yet indicated.
526 	rc = leapsec_query(&qr, lsec2009 - 7*SECSPERDAY, NULL);
527 	TEST_ASSERT_EQUAL(FALSE, rc);
528 	TEST_ASSERT_EQUAL(33, qr.tai_offs);
529 	TEST_ASSERT_EQUAL(1,  qr.tai_diff);
530 	TEST_ASSERT_EQUAL(LSPROX_SCHEDULE, qr.proximity);
531 }
532 
533 // ----------------------------------------------------------------------
534 // ad-hoc jump: leap second at 2009.01.01 -1hr
535 extern void test_ls2009houraway(void);
536 void test_ls2009houraway(void)
537 {
538 	int            rc;
539 	leap_result_t  qr;
540 
541 	rc = setup_load_table(leap1,FALSE);
542 	TEST_ASSERT_EQUAL(1, rc);
543 
544 	// test 1 hour before leap. 61 true seconds to go.
545 	rc = leapsec_query(&qr, lsec2009 - SECSPERHR, NULL);
546 	TEST_ASSERT_EQUAL(FALSE, rc);
547 	TEST_ASSERT_EQUAL(33, qr.tai_offs);
548 	TEST_ASSERT_EQUAL(1,  qr.tai_diff);
549 	TEST_ASSERT_EQUAL(LSPROX_ANNOUNCE, qr.proximity);
550 }
551 
552 // ----------------------------------------------------------------------
553 // ad-hoc jump: leap second at 2009.01.01 -1sec
554 extern void test_ls2009secaway(void);
555 void test_ls2009secaway(void)
556 {
557 	int            rc;
558 	leap_result_t  qr;
559 
560 	rc = setup_load_table(leap1,FALSE);
561 	TEST_ASSERT_EQUAL(1, rc);
562 
563 	// test 1 second before leap (last boundary...) 2 true seconds to go.
564 	rc = leapsec_query(&qr, lsec2009 - 1, NULL);
565 	TEST_ASSERT_EQUAL(FALSE, rc);
566 	TEST_ASSERT_EQUAL(33, qr.tai_offs);
567 	TEST_ASSERT_EQUAL(1,  qr.tai_diff);
568 	TEST_ASSERT_EQUAL(LSPROX_ALERT, qr.proximity);
569 }
570 
571 // ----------------------------------------------------------------------
572 // ad-hoc jump to leap second at 2009.01.01
573 extern void test_ls2009onspot(void);
574 void test_ls2009onspot(void)
575 {
576 	int            rc;
577 	leap_result_t  qr;
578 
579 	rc = setup_load_table(leap1,FALSE);
580 	TEST_ASSERT_EQUAL(1, rc);
581 
582 	// test on-spot: treat leap second as already gone.
583 	rc = leapsec_query(&qr, lsec2009, NULL);
584 	TEST_ASSERT_EQUAL(FALSE, rc);
585 	TEST_ASSERT_EQUAL(34, qr.tai_offs);
586 	TEST_ASSERT_EQUAL(0,  qr.tai_diff);
587 	TEST_ASSERT_EQUAL(LSPROX_NOWARN, qr.proximity);
588 }
589 
590 // ----------------------------------------------------------------------
591 // test handling of the leap second at 2009.01.01 without table
592 extern void test_ls2009nodata(void);
593 void test_ls2009nodata(void)
594 {
595 	int            rc;
596 	leap_result_t  qr;
597 
598 	rc = setup_clear_table();
599 	TEST_ASSERT_EQUAL(1, rc);
600 
601 	// test on-spot with empty table
602 	rc = leapsec_query(&qr, lsec2009, NULL);
603 	TEST_ASSERT_EQUAL(FALSE, rc);
604 	TEST_ASSERT_EQUAL(0,  qr.tai_offs);
605 	TEST_ASSERT_EQUAL(0,  qr.tai_diff);
606 	TEST_ASSERT_EQUAL(LSPROX_NOWARN, qr.proximity);
607 }
608 
609 // ----------------------------------------------------------------------
610 // test handling of the leap second at 2009.01.01 with culled data
611 extern void test_ls2009limdata(void);
612 void test_ls2009limdata(void)
613 {
614 	int            rc;
615 	leap_result_t  qr;
616 
617 	rc = setup_load_table(leap1, TRUE);
618 	TEST_ASSERT_EQUAL(1, rc);
619 
620 	// test on-spot with limited table - this is tricky.
621 	// The table used ends 2012; depending on the build date, the 2009 entry
622 	// might be included or culled. The resulting TAI offset must be either
623 	// 34 or 35 seconds, depending on the build date of the test.
624 	rc = leapsec_query(&qr, lsec2009, NULL);
625 	TEST_ASSERT_EQUAL(FALSE, rc);
626 	TEST_ASSERT_TRUE(34 <= qr.tai_offs);
627 	TEST_ASSERT_TRUE(35 >= qr.tai_offs);
628 	TEST_ASSERT_EQUAL(0,  qr.tai_diff);
629 	TEST_ASSERT_EQUAL(LSPROX_NOWARN, qr.proximity);
630 }
631 
632 // ----------------------------------------------------------------------
633 // Far-distance forward jump into a transiton window.
634 extern void test_qryJumpFarAhead(void);
635 void test_qryJumpFarAhead(void)
636 {
637 	int		rc;
638 	leap_result_t	qr;
639 	int		mode;
640 
641 	for (mode=0; mode < 2; ++mode) {
642 		leapsec_ut_pristine();
643 		rc = setup_load_table(leap1, FALSE);
644 		TEST_ASSERT_EQUAL(1, rc);
645 		leapsec_electric(mode);
646 
647 		rc = leapsec_query(&qr, lsec2006, NULL);
648 		TEST_ASSERT_EQUAL(FALSE, rc);
649 
650 		rc = leapsec_query(&qr, lsec2012, NULL);
651 		TEST_ASSERT_EQUAL(FALSE, rc);
652 	}
653 }
654 
655 // ----------------------------------------------------------------------
656 // Forward jump into the next transition window
657 extern void test_qryJumpAheadToTransition(void);
658 void test_qryJumpAheadToTransition(void)
659 {
660 	int		rc;
661 	leap_result_t	qr;
662 	int		mode;
663 
664 	for (mode=0; mode < 2; ++mode) {
665 		leapsec_ut_pristine();
666 		rc = setup_load_table(leap1, FALSE);
667 		TEST_ASSERT_EQUAL(1, rc);
668 		leapsec_electric(mode);
669 
670 		rc = leapsec_query(&qr, lsec2009-SECSPERDAY, NULL);
671 		TEST_ASSERT_EQUAL(FALSE, rc);
672 
673 		rc = leapsec_query(&qr, lsec2009+1, NULL);
674 		TEST_ASSERT_EQUAL(TRUE, rc);
675 	}
676 }
677 
678 // ----------------------------------------------------------------------
679 // Forward jump over the next transition window
680 extern void test_qryJumpAheadOverTransition(void);
681 void test_qryJumpAheadOverTransition(void)
682 {
683 	int		rc;
684 	leap_result_t	qr;
685 	int		mode;
686 
687 	for (mode=0; mode < 2; ++mode) {
688 		leapsec_ut_pristine();
689 		rc = setup_load_table(leap1, FALSE);
690 		TEST_ASSERT_EQUAL(1, rc);
691 		leapsec_electric(mode);
692 
693 		rc = leapsec_query(&qr, lsec2009-SECSPERDAY, NULL);
694 		TEST_ASSERT_EQUAL(FALSE, rc);
695 
696 		rc = leapsec_query(&qr, lsec2009+5, NULL);
697 		TEST_ASSERT_EQUAL(FALSE, rc);
698 	}
699 }
700 
701 // =====================================================================
702 // TABLE MODIFICATION AT RUNTIME
703 // =====================================================================
704 
705 // ----------------------------------------------------------------------
706 // add dynamic leap second (like from peer/clock)
707 extern void test_addDynamic(void);
708 void test_addDynamic(void)
709 {
710 	int            rc;
711 
712 	static const uint32_t insns[] = {
713 		2982009600u,	//	29	# 1 Jul 1994
714 		3029443200u,	//	30	# 1 Jan 1996
715 		3076704000u,	//	31	# 1 Jul 1997
716 		3124137600u,	//	32	# 1 Jan 1999
717 		3345062400u,	//	33	# 1 Jan 2006
718 		3439756800u,	//	34	# 1 Jan 2009
719 		3550089600u,	//	35	# 1 Jul 2012
720 		0 // sentinel
721 	};
722 
723 	rc = setup_load_table(leap2, FALSE);
724 	TEST_ASSERT_EQUAL(1, rc);
725 
726 	int		idx;
727 
728 	for (idx=1; insns[idx]; ++idx) {
729 		rc = leapsec_add_dyn(TRUE, insns[idx] - 20*SECSPERDAY - 100, NULL);
730 		TEST_ASSERT_EQUAL(TRUE, rc);
731 	}
732 	// try to slip in a previous entry
733 	rc = leapsec_add_dyn(TRUE, insns[0] - 20*SECSPERDAY - 100, NULL);
734 	TEST_ASSERT_EQUAL(FALSE, rc);
735 	//leap_table_t  * pt = leapsec_get_table(0);
736 	//leapsec_dump(pt, (leapsec_dumper)fprintf, stdout);
737 }
738 
739 // ----------------------------------------------------------------------
740 // add fixed leap seconds (like from network packet)
741 #if 0 /* currently unused -- possibly revived later */
742 extern void no_test_addFixed(void);
743 void no_test_addFixed(void)
744 {
745 	int            rc;
746 	leap_result_t  qr;
747 
748 	static const struct { uint32_t tt; int of; } insns[] = {
749 		{2982009600u, 29},//	# 1 Jul 1994
750 		{3029443200u, 30},//	# 1 Jan 1996
751 		{3076704000u, 31},//	# 1 Jul 1997
752 		{3124137600u, 32},//	# 1 Jan 1999
753 		{3345062400u, 33},//	# 1 Jan 2006
754 		{3439756800u, 34},//	# 1 Jan 2009
755 		{3550089600u, 35},//	# 1 Jul 2012
756 		{0,0} // sentinel
757 	};
758 
759 	rc = setup_load_table(leap2, FALSE);
760 	TEST_ASSERT_EQUAL(1, rc);
761 
762 	int idx;
763 	// try to get in BAD time stamps...
764 	for (idx=0; insns[idx].tt; ++idx) {
765 	    rc = leapsec_add_fix(
766 		insns[idx].of,
767 		insns[idx].tt - 20*SECSPERDAY - 100,
768 		insns[idx].tt + SECSPERDAY,
769 		NULL);
770 		TEST_ASSERT_EQUAL(FALSE, rc);
771 	}
772 	// now do it right
773 	for (idx=0; insns[idx].tt; ++idx) {
774 		rc = leapsec_add_fix(
775 		    insns[idx].of,
776 		    insns[idx].tt,
777 		    insns[idx].tt + SECSPERDAY,
778 		    NULL);
779 		TEST_ASSERT_EQUAL(TRUE, rc);
780 	}
781 	// try to slip in a previous entry
782 	rc = leapsec_add_fix(
783 	    insns[0].of,
784 	    insns[0].tt,
785 	    insns[0].tt + SECSPERDAY,
786 	    NULL);
787 	TEST_ASSERT_EQUAL(FALSE, rc);
788 	//leap_table_t * pt = leapsec_get_table(0);
789 	//leapsec_dump(pt, (leapsec_dumper)fprintf, stdout);
790 }
791 #endif
792 
793 // ----------------------------------------------------------------------
794 // add fixed leap seconds (like from network packet)
795 #if 0 /* currently unused -- possibly revived later */
796 extern void no_test_addFixedExtend(void);
797 void no_test_addFixedExtend(void)
798 {
799 	int            rc;
800 	leap_result_t  qr;
801 	int            last, idx;
802 
803 	static const struct { uint32_t tt; int of; } insns[] = {
804 		{2982009600u, 29},//	# 1 Jul 1994
805 		{3029443200u, 30},//	# 1 Jan 1996
806 		{0,0} // sentinel
807 	};
808 
809 	rc = setup_load_table(leap2, FALSE);
810 	TEST_ASSERT_EQUAL(1, rc);
811 
812 	for (last=idx=0; insns[idx].tt; ++idx) {
813 		last = idx;
814 		rc = leapsec_add_fix(
815 		    insns[idx].of,
816 		    insns[idx].tt,
817 		    insns[idx].tt + SECSPERDAY,
818 		    NULL);
819 		TEST_ASSERT_EQUAL(TRUE, rc);
820 	}
821 
822 	// try to extend the expiration of the last entry
823 	rc = leapsec_add_fix(
824 	    insns[last].of,
825 	    insns[last].tt,
826 	    insns[last].tt + 128*SECSPERDAY,
827 	    NULL);
828 	TEST_ASSERT_EQUAL(TRUE, rc);
829 
830 	// try to extend the expiration of the last entry with wrong offset
831 	rc = leapsec_add_fix(
832 	    insns[last].of+1,
833 	    insns[last].tt,
834 	    insns[last].tt + 129*SECSPERDAY,
835 	    NULL);
836 	TEST_ASSERT_EQUAL(FALSE, rc);
837 	//leap_table_t * pt = leapsec_get_table(FALSE);
838 	//leapsec_dump(pt, (leapsec_dumper)fprintf, stdout);
839 }
840 #endif
841 
842 // ----------------------------------------------------------------------
843 // add fixed leap seconds (like from network packet) in an otherwise
844 // empty table and test queries before / between /after the tabulated
845 // values.
846 #if 0 /* currently unused -- possibly revived later */
847 extern void no_test_setFixedExtend(void);
848 void no_test_setFixedExtend(void)
849 {
850 	int            rc;
851 	leap_result_t  qr;
852 	int            last, idx;
853 
854 	static const struct { uint32_t tt; int of; } insns[] = {
855 		{2982009600u, 29},//	# 1 Jul 1994
856 		{3029443200u, 30},//	# 1 Jan 1996
857 		{0,0} // sentinel
858 	};
859 
860 	for (last=idx=0; insns[idx].tt; ++idx) {
861 		last = idx;
862 		rc = leapsec_add_fix(
863 		    insns[idx].of,
864 		    insns[idx].tt,
865 		    insns[idx].tt + 128*SECSPERDAY,
866 		    NULL);
867 		TEST_ASSERT_EQUAL(TRUE, rc);
868 	}
869 
870 	rc = leapsec_query(&qr, insns[0].tt - 86400, NULL);
871 	TEST_ASSERT_EQUAL(28, qr.tai_offs);
872 
873 	rc = leapsec_query(&qr, insns[0].tt + 86400, NULL);
874 	TEST_ASSERT_EQUAL(29, qr.tai_offs);
875 
876 	rc = leapsec_query(&qr, insns[1].tt - 86400, NULL);
877 	TEST_ASSERT_EQUAL(29, qr.tai_offs);
878 
879 	rc = leapsec_query(&qr, insns[1].tt + 86400, NULL);
880 	TEST_ASSERT_EQUAL(30, qr.tai_offs);
881 
882 	//leap_table_t * pt = leapsec_get_table(0);
883 	//leapsec_dump(pt, (leapsec_dumper)fprintf, stdout);
884 }
885 #endif
886 
887 // =====================================================================
888 // AUTOKEY LEAP TRANSFER TESTS
889 // =====================================================================
890 
891 // ----------------------------------------------------------------------
892 // Check if the offset can be applied to an empty table ONCE
893 extern void test_taiEmptyTable(void);
894 void test_taiEmptyTable(void)
895 {
896 	int rc;
897 
898 	rc = leapsec_autokey_tai(35, lsec2015-30*86400, NULL);
899 	TEST_ASSERT_EQUAL(TRUE, rc);
900 
901 	rc = leapsec_autokey_tai(35, lsec2015-29*86400, NULL);
902 	TEST_ASSERT_EQUAL(FALSE, rc);
903 }
904 
905 // ----------------------------------------------------------------------
906 // Check that with fixed entries the operation fails
907 extern void test_taiTableFixed(void);
908 void test_taiTableFixed(void)
909 {
910 	int rc;
911 
912 	rc = setup_load_table(leap1, FALSE);
913 	TEST_ASSERT_EQUAL(1, rc);
914 
915 	rc = leapsec_autokey_tai(35, lsec2015-30*86400, NULL);
916 	TEST_ASSERT_EQUAL(FALSE, rc);
917 }
918 
919 // ----------------------------------------------------------------------
920 // test adjustment with a dynamic entry already there
921 extern void test_taiTableDynamic(void);
922 void test_taiTableDynamic(void)
923 {
924 	int        rc;
925 	leap_era_t era;
926 
927 	rc = leapsec_add_dyn(TRUE, lsec2015-20*SECSPERDAY, NULL);
928 	TEST_ASSERT_EQUAL(TRUE, rc);
929 
930 	leapsec_query_era(&era, lsec2015-10, NULL);
931 	TEST_ASSERT_EQUAL(0, era.taiof);
932 	leapsec_query_era(&era, lsec2015+10, NULL);
933 	TEST_ASSERT_EQUAL(1, era.taiof);
934 
935 	rc = leapsec_autokey_tai(35, lsec2015-19*86400, NULL);
936 	TEST_ASSERT_EQUAL(TRUE, rc);
937 
938 	rc = leapsec_autokey_tai(35, lsec2015-19*86400, NULL);
939 	TEST_ASSERT_EQUAL(FALSE, rc);
940 
941 	leapsec_query_era(&era, lsec2015-10, NULL);
942 	TEST_ASSERT_EQUAL(35, era.taiof);
943 	leapsec_query_era(&era, lsec2015+10, NULL);
944 	TEST_ASSERT_EQUAL(36, era.taiof);
945 }
946 
947 // ----------------------------------------------------------------------
948 // test adjustment with a dynamic entry already there in dead zone
949 extern void test_taiTableDynamicDeadZone(void);
950 void test_taiTableDynamicDeadZone(void)
951 {
952 	int rc;
953 
954 	rc = leapsec_add_dyn(TRUE, lsec2015-20*SECSPERDAY, NULL);
955 	TEST_ASSERT_EQUAL(TRUE, rc);
956 
957 	rc = leapsec_autokey_tai(35, lsec2015-5, NULL);
958 	TEST_ASSERT_EQUAL(FALSE, rc);
959 
960 	rc = leapsec_autokey_tai(35, lsec2015+5, NULL);
961 	TEST_ASSERT_EQUAL(FALSE, rc);
962 }
963 
964 
965 // =====================================================================
966 // SEQUENCE TESTS
967 // =====================================================================
968 
969 // ----------------------------------------------------------------------
970 // leap second insert at 2009.01.01, electric mode
971 extern void test_ls2009seqInsElectric(void);
972 void test_ls2009seqInsElectric(void)
973 {
974 	int            rc;
975 	leap_result_t  qr;
976 
977 	rc = setup_load_table(leap1,FALSE);
978 	TEST_ASSERT_EQUAL(1, rc);
979 	leapsec_electric(1);
980 	TEST_ASSERT_EQUAL(1, leapsec_electric(-1));
981 
982 	rc = leapsec_query(&qr, lsec2009 - 60*SECSPERDAY, NULL);
983 	TEST_ASSERT_EQUAL(FALSE, rc);
984 	TEST_ASSERT_EQUAL(0,             qr.warped   );
985 	TEST_ASSERT_EQUAL(LSPROX_NOWARN, qr.proximity);
986 
987 	rc = leapsec_query(&qr, lsec2009 - 7*SECSPERDAY, NULL);
988 	TEST_ASSERT_EQUAL(FALSE, rc);
989 	TEST_ASSERT_EQUAL(0,               qr.warped   );
990 	TEST_ASSERT_EQUAL(LSPROX_SCHEDULE, qr.proximity);
991 
992 	rc = leapsec_query(&qr, lsec2009 - SECSPERHR, NULL);
993 	TEST_ASSERT_EQUAL(FALSE, rc);
994 	TEST_ASSERT_EQUAL(0,               qr.warped   );
995 	TEST_ASSERT_EQUAL(LSPROX_ANNOUNCE, qr.proximity);
996 
997 	rc = leapsec_query(&qr, lsec2009 - 1, NULL);
998 	TEST_ASSERT_EQUAL(FALSE, rc);
999 	TEST_ASSERT_EQUAL(0,               qr.warped   );
1000 	TEST_ASSERT_EQUAL(LSPROX_ALERT,    qr.proximity);
1001 
1002 	rc = leapsec_query(&qr, lsec2009, NULL);
1003 	TEST_ASSERT_EQUAL(TRUE, rc);
1004 	TEST_ASSERT_EQUAL(0,             qr.warped   );
1005 	TEST_ASSERT_EQUAL(LSPROX_NOWARN, qr.proximity);
1006 
1007 	// second call, same time frame: no trigger!
1008 	rc = leapsec_query(&qr, lsec2009, NULL);
1009 	TEST_ASSERT_EQUAL(FALSE, rc);
1010 	TEST_ASSERT_EQUAL(0,             qr.warped   );
1011 	TEST_ASSERT_EQUAL(LSPROX_NOWARN, qr.proximity);
1012 }
1013 
1014 // ----------------------------------------------------------------------
1015 // leap second insert at 2009.01.01, dumb mode
1016 extern void test_ls2009seqInsDumb(void);
1017 void test_ls2009seqInsDumb(void)
1018 {
1019 	int            rc;
1020 	leap_result_t  qr;
1021 
1022 	rc = setup_load_table(leap1,FALSE);
1023 	TEST_ASSERT_EQUAL(1, rc);
1024 	TEST_ASSERT_EQUAL(0, leapsec_electric(-1));
1025 
1026 	rc = leapsec_query(&qr, lsec2009 - 60*SECSPERDAY, NULL);
1027 	TEST_ASSERT_EQUAL(FALSE, rc);
1028 	TEST_ASSERT_EQUAL(0,             qr.warped   );
1029 	TEST_ASSERT_EQUAL(LSPROX_NOWARN, qr.proximity);
1030 
1031 	rc = leapsec_query(&qr, lsec2009 - 7*SECSPERDAY, NULL);
1032 	TEST_ASSERT_EQUAL(FALSE, rc);
1033 	TEST_ASSERT_EQUAL(0,               qr.warped   );
1034 	TEST_ASSERT_EQUAL(LSPROX_SCHEDULE, qr.proximity);
1035 
1036 	rc = leapsec_query(&qr, lsec2009 - SECSPERHR, NULL);
1037 	TEST_ASSERT_EQUAL(FALSE, rc);
1038 	TEST_ASSERT_EQUAL(0,               qr.warped   );
1039 	TEST_ASSERT_EQUAL(LSPROX_ANNOUNCE, qr.proximity);
1040 
1041 	rc = leapsec_query(&qr, lsec2009 - 1, NULL);
1042 	TEST_ASSERT_EQUAL(FALSE, rc);
1043 	TEST_ASSERT_EQUAL(0,               qr.warped   );
1044 	TEST_ASSERT_EQUAL(LSPROX_ALERT,    qr.proximity);
1045 
1046 	rc = leapsec_query(&qr, lsec2009, NULL);
1047 	TEST_ASSERT_EQUAL(FALSE, rc);
1048 	TEST_ASSERT_EQUAL(0,               qr.warped   );
1049 	TEST_ASSERT_EQUAL(LSPROX_ALERT,    qr.proximity);
1050 
1051 	rc = leapsec_query(&qr, lsec2009+1, NULL);
1052 	TEST_ASSERT_EQUAL(TRUE, rc);
1053 	TEST_ASSERT_EQUAL(-1,             qr.warped   );
1054 	TEST_ASSERT_EQUAL(LSPROX_NOWARN, qr.proximity);
1055 
1056 	// second call, same time frame: no trigger!
1057 	rc = leapsec_query(&qr, lsec2009, NULL);
1058 	TEST_ASSERT_EQUAL(FALSE, rc);
1059 	TEST_ASSERT_EQUAL(0,             qr.warped   );
1060 	TEST_ASSERT_EQUAL(LSPROX_NOWARN, qr.proximity);
1061 }
1062 
1063 // ----------------------------------------------------------------------
1064 // fake leap second remove at 2009.01.01, electric mode
1065 extern void test_ls2009seqDelElectric(void);
1066 void test_ls2009seqDelElectric(void)
1067 {
1068 	int            rc;
1069 	leap_result_t  qr;
1070 
1071 	rc = setup_load_table(leap3,FALSE);
1072 	TEST_ASSERT_EQUAL(1, rc);
1073 	leapsec_electric(1);
1074 	TEST_ASSERT_EQUAL(1, leapsec_electric(-1));
1075 
1076 	rc = leapsec_query(&qr, lsec2009 - 60*SECSPERDAY, NULL);
1077 	TEST_ASSERT_EQUAL(FALSE, rc);
1078 	TEST_ASSERT_EQUAL(0,             qr.warped   );
1079 	TEST_ASSERT_EQUAL(LSPROX_NOWARN, qr.proximity);
1080 
1081 	rc = leapsec_query(&qr, lsec2009 - 7*SECSPERDAY, NULL);
1082 	TEST_ASSERT_EQUAL(FALSE, rc);
1083 	TEST_ASSERT_EQUAL(0,               qr.warped   );
1084 	TEST_ASSERT_EQUAL(LSPROX_SCHEDULE, qr.proximity);
1085 
1086 	rc = leapsec_query(&qr, lsec2009 - SECSPERHR, NULL);
1087 	TEST_ASSERT_EQUAL(FALSE, rc);
1088 	TEST_ASSERT_EQUAL(0,               qr.warped   );
1089 	TEST_ASSERT_EQUAL(LSPROX_ANNOUNCE, qr.proximity);
1090 
1091 	rc = leapsec_query(&qr, lsec2009 - 1, NULL);
1092 	TEST_ASSERT_EQUAL(FALSE, rc);
1093 	TEST_ASSERT_EQUAL(0,               qr.warped   );
1094 	TEST_ASSERT_EQUAL(LSPROX_ALERT,    qr.proximity);
1095 
1096 	rc = leapsec_query(&qr, lsec2009, NULL);
1097 	TEST_ASSERT_EQUAL(TRUE, rc);
1098 	TEST_ASSERT_EQUAL(0,             qr.warped   );
1099 	TEST_ASSERT_EQUAL(LSPROX_NOWARN, qr.proximity);
1100 
1101 	// second call, same time frame: no trigger!
1102 	rc = leapsec_query(&qr, lsec2009, NULL);
1103 	TEST_ASSERT_EQUAL(FALSE, rc);
1104 	TEST_ASSERT_EQUAL(0,             qr.warped   );
1105 	TEST_ASSERT_EQUAL(LSPROX_NOWARN, qr.proximity);
1106 }
1107 
1108 // ----------------------------------------------------------------------
1109 // fake leap second remove at 2009.01.01. dumb mode
1110 extern void test_ls2009seqDelDumb(void);
1111 void test_ls2009seqDelDumb(void)
1112 {
1113 	int            rc;
1114 	leap_result_t  qr;
1115 
1116 	rc = setup_load_table(leap3,FALSE);
1117 	TEST_ASSERT_EQUAL(1, rc);
1118 	TEST_ASSERT_EQUAL(0, leapsec_electric(-1));
1119 
1120 	rc = leapsec_query(&qr, lsec2009 - 60*SECSPERDAY, NULL);
1121 	TEST_ASSERT_EQUAL(FALSE, rc);
1122 	TEST_ASSERT_EQUAL(0,             qr.warped   );
1123 	TEST_ASSERT_EQUAL(LSPROX_NOWARN, qr.proximity);
1124 
1125 	rc = leapsec_query(&qr, lsec2009 - 7*SECSPERDAY, NULL);
1126 	TEST_ASSERT_EQUAL(FALSE, rc);
1127 	TEST_ASSERT_EQUAL(0,               qr.warped   );
1128 	TEST_ASSERT_EQUAL(LSPROX_SCHEDULE, qr.proximity);
1129 
1130 	rc = leapsec_query(&qr, lsec2009 - SECSPERHR, NULL);
1131 	TEST_ASSERT_EQUAL(FALSE, rc);
1132 	TEST_ASSERT_EQUAL(0,               qr.warped   );
1133 	TEST_ASSERT_EQUAL(LSPROX_ANNOUNCE, qr.proximity);
1134 
1135 	rc = leapsec_query(&qr, lsec2009 - 2, NULL);
1136 	TEST_ASSERT_EQUAL(FALSE, rc);
1137 	TEST_ASSERT_EQUAL(0,               qr.warped   );
1138 	TEST_ASSERT_EQUAL(LSPROX_ALERT,    qr.proximity);
1139 
1140 	rc = leapsec_query(&qr, lsec2009 - 1, NULL);
1141 	TEST_ASSERT_EQUAL(TRUE, rc);
1142 	TEST_ASSERT_EQUAL(1,             qr.warped   );
1143 	TEST_ASSERT_EQUAL(LSPROX_NOWARN, qr.proximity);
1144 
1145 	// second call, same time frame: no trigger!
1146 	rc = leapsec_query(&qr, lsec2009, NULL);
1147 	TEST_ASSERT_EQUAL(FALSE, rc);
1148 	TEST_ASSERT_EQUAL(0,             qr.warped   );
1149 	TEST_ASSERT_EQUAL(LSPROX_NOWARN, qr.proximity);
1150 }
1151 
1152 // ----------------------------------------------------------------------
1153 // leap second insert at 2012.07.01, electric mode
1154 extern void test_ls2012seqInsElectric(void);
1155 void test_ls2012seqInsElectric(void)
1156 {
1157 	int            rc;
1158 	leap_result_t  qr;
1159 
1160 	rc = setup_load_table(leap1,FALSE);
1161 	TEST_ASSERT_EQUAL(1, rc);
1162 	leapsec_electric(1);
1163 	TEST_ASSERT_EQUAL(1, leapsec_electric(-1));
1164 
1165 	rc = leapsec_query(&qr, lsec2012 - 60*SECSPERDAY, NULL);
1166 	TEST_ASSERT_EQUAL(FALSE, rc);
1167 	TEST_ASSERT_EQUAL(0,             qr.warped   );
1168 	TEST_ASSERT_EQUAL(LSPROX_NOWARN, qr.proximity);
1169 
1170 	rc = leapsec_query(&qr, lsec2012 - 7*SECSPERDAY, NULL);
1171 	TEST_ASSERT_EQUAL(FALSE, rc);
1172 	TEST_ASSERT_EQUAL(0,               qr.warped   );
1173 	TEST_ASSERT_EQUAL(LSPROX_SCHEDULE, qr.proximity);
1174 
1175 	rc = leapsec_query(&qr, lsec2012 - SECSPERHR, NULL);
1176 	TEST_ASSERT_EQUAL(FALSE, rc);
1177 	TEST_ASSERT_EQUAL(0,               qr.warped   );
1178 	TEST_ASSERT_EQUAL(LSPROX_ANNOUNCE, qr.proximity);
1179 
1180 	rc = leapsec_query(&qr, lsec2012 - 1, NULL);
1181 	TEST_ASSERT_EQUAL(FALSE, rc);
1182 	TEST_ASSERT_EQUAL(0,               qr.warped   );
1183 	TEST_ASSERT_EQUAL(LSPROX_ALERT,    qr.proximity);
1184 
1185 	rc = leapsec_query(&qr, lsec2012, NULL);
1186 	TEST_ASSERT_EQUAL(TRUE, rc);
1187 	TEST_ASSERT_EQUAL(0,            qr.warped   );
1188 	TEST_ASSERT_EQUAL(LSPROX_NOWARN, qr.proximity);
1189 
1190 	// second call, same time frame: no trigger!
1191 	rc = leapsec_query(&qr, lsec2012, NULL);
1192 	TEST_ASSERT_EQUAL(FALSE, rc);
1193 	TEST_ASSERT_EQUAL(0,             qr.warped   );
1194 	TEST_ASSERT_EQUAL(LSPROX_NOWARN, qr.proximity);
1195 }
1196 
1197 // ----------------------------------------------------------------------
1198 // leap second insert at 2012.07.01, dumb mode
1199 extern void test_ls2012seqInsDumb(void);
1200 void test_ls2012seqInsDumb(void)
1201 {
1202 	int            rc;
1203 	leap_result_t  qr;
1204 
1205 	rc = setup_load_table(leap1,FALSE);
1206 	TEST_ASSERT_EQUAL(1, rc);
1207 	TEST_ASSERT_EQUAL(0, leapsec_electric(-1));
1208 
1209 	rc = leapsec_query(&qr, lsec2012 - 60*SECSPERDAY, NULL);
1210 	TEST_ASSERT_EQUAL(FALSE, rc);
1211 	TEST_ASSERT_EQUAL(0,             qr.warped   );
1212 	TEST_ASSERT_EQUAL(LSPROX_NOWARN, qr.proximity);
1213 
1214 	rc = leapsec_query(&qr, lsec2012 - 7*SECSPERDAY, NULL);
1215 	TEST_ASSERT_EQUAL(FALSE, rc);
1216 	TEST_ASSERT_EQUAL(0,               qr.warped   );
1217 	TEST_ASSERT_EQUAL(LSPROX_SCHEDULE, qr.proximity);
1218 
1219 	rc = leapsec_query(&qr, lsec2012 - SECSPERHR, NULL);
1220 	TEST_ASSERT_EQUAL(FALSE, rc);
1221 	TEST_ASSERT_EQUAL(0,               qr.warped   );
1222 	TEST_ASSERT_EQUAL(LSPROX_ANNOUNCE, qr.proximity);
1223 
1224 	rc = leapsec_query(&qr, lsec2012 - 1, NULL);
1225 	TEST_ASSERT_EQUAL(FALSE, rc);
1226 	TEST_ASSERT_EQUAL(0,               qr.warped   );
1227 	TEST_ASSERT_EQUAL(LSPROX_ALERT,    qr.proximity);
1228 
1229 	// This is just 1 sec before transition!
1230 	rc = leapsec_query(&qr, lsec2012, NULL);
1231 	TEST_ASSERT_EQUAL(FALSE, rc);
1232 	TEST_ASSERT_EQUAL(0,            qr.warped   );
1233 	TEST_ASSERT_EQUAL(LSPROX_ALERT, qr.proximity);
1234 
1235 	// NOW the insert/backwarp must happen
1236 	rc = leapsec_query(&qr, lsec2012+1, NULL);
1237 	TEST_ASSERT_EQUAL(TRUE, rc);
1238 	TEST_ASSERT_EQUAL(-1,            qr.warped   );
1239 	TEST_ASSERT_EQUAL(LSPROX_NOWARN, qr.proximity);
1240 
1241 	// second call with transition time: no trigger!
1242 	rc = leapsec_query(&qr, lsec2012, NULL);
1243 	TEST_ASSERT_EQUAL(FALSE, rc);
1244 	TEST_ASSERT_EQUAL(0,             qr.warped   );
1245 	TEST_ASSERT_EQUAL(LSPROX_NOWARN, qr.proximity);
1246 }
1247 
1248 // ----------------------------------------------------------------------
1249 // test repeated query on empty table in dumb mode
1250 extern void test_lsEmptyTableDumb(void);
1251 void test_lsEmptyTableDumb(void)
1252 {
1253 	int            rc;
1254 	leap_result_t  qr;
1255 
1256 	const time_t   pivot = lsec2012;
1257 	const uint32_t t0 = lsec2012 - 10;
1258 	const uint32_t tE = lsec2012 + 10;
1259 
1260 	TEST_ASSERT_EQUAL(0, leapsec_electric(-1));
1261 
1262 	uint32_t t;
1263 	for (t = t0; t != tE; ++t) {
1264 		rc = leapsec_query(&qr, t, &pivot);
1265 		TEST_ASSERT_EQUAL(FALSE, rc);
1266 		TEST_ASSERT_EQUAL(0,             qr.warped   );
1267 		TEST_ASSERT_EQUAL(LSPROX_NOWARN, qr.proximity);
1268 	}
1269 }
1270 
1271 // ----------------------------------------------------------------------
1272 // test repeated query on empty table in electric mode
1273 extern void test_lsEmptyTableElectric(void);
1274 void test_lsEmptyTableElectric(void)
1275 {
1276 	int            rc;
1277 	leap_result_t  qr;
1278 
1279 	leapsec_electric(1);
1280 	TEST_ASSERT_EQUAL(1, leapsec_electric(-1));
1281 
1282 	const time_t   pivot = lsec2012;
1283 	const uint32_t t0 = lsec2012 - 10;
1284 	const uint32_t tE = lsec2012 + 10;
1285 
1286 	time_t t;
1287 	for (t = t0; t != tE; ++t) {
1288 		rc = leapsec_query(&qr, t, &pivot);
1289 		TEST_ASSERT_EQUAL(FALSE, rc);
1290 		TEST_ASSERT_EQUAL(0,             qr.warped   );
1291 		TEST_ASSERT_EQUAL(LSPROX_NOWARN, qr.proximity);
1292 	}
1293 }
1294