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