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