leapsec.c revision 290001
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	if (**cpp)
238		return *(*cpp)++;
239	else
240		return EOF;
241}
242
243static int/*BOOL*/
244setup_load_table(
245	const char * cp,
246	int          blim)
247{
248	int            rc;
249	leap_table_t * pt = leapsec_get_table(0);
250	rc = (pt != NULL) && leapsec_load(pt, stringreader, &cp, blim);
251	rc = rc && leapsec_set_table(pt);
252	return rc;
253}
254
255static int/*BOOL*/
256setup_clear_table(void)
257{
258	int            rc;
259	leap_table_t * pt = leapsec_get_table(0);
260	if (pt)
261		leapsec_clear(pt);
262	rc = leapsec_set_table(pt);
263	return rc;
264}
265
266
267char * CalendarToString(const struct calendar cal) {
268	char * ss = malloc (sizeof (char) * 100);
269
270	char buffer[100] ="";
271	sprintf(buffer, "%u", cal.year);
272	strcat(ss,buffer);
273	strcat(ss,"-");
274	sprintf(buffer, "%u", (u_int)cal.month);
275	strcat(ss,buffer);
276	strcat(ss,"-");
277	sprintf(buffer, "%u", (u_int)cal.monthday);
278	strcat(ss,buffer);
279	strcat(ss," (");
280	sprintf(buffer, "%u", (u_int) cal.yearday);
281	strcat(ss,buffer);
282	strcat(ss,") ");
283	sprintf(buffer, "%u", (u_int)cal.hour);
284	strcat(ss,buffer);
285	strcat(ss,":");
286	sprintf(buffer, "%u", (u_int)cal.minute);
287	strcat(ss,buffer);
288	strcat(ss,":");
289	sprintf(buffer, "%u", (u_int)cal.second);
290	strcat(ss,buffer);
291	//ss << cal.year << "-" << (u_int)cal.month << "-" << (u_int)cal.monthday << " (" << cal.yearday << ") " << (u_int)cal.hour << ":" << (u_int)cal.minute << ":" << (u_int)cal.second;
292	return ss;
293}
294
295
296int IsEqual(const struct calendar expected, const struct calendar actual) {
297	if (expected.year == actual.year &&
298		(expected.yearday == actual.yearday ||
299		 (expected.month == actual.month &&
300		  expected.monthday == actual.monthday)) &&
301		expected.hour == actual.hour &&
302		expected.minute == actual.minute &&
303		expected.second == actual.second) {
304		return TRUE;
305	} else {
306		printf("expected: %s but was %s", CalendarToString(expected) ,CalendarToString(actual));
307		return FALSE;
308
309	}
310}
311
312//-------------------------
313
314void setUp(void)
315{
316    ntpcal_set_timefunc(timefunc);
317    settime(1970, 1, 1, 0, 0, 0);
318    leapsec_ut_pristine();
319}
320
321void tearDown(void)
322{
323    ntpcal_set_timefunc(NULL);
324}
325
326// =====================================================================
327// VALIDATION TESTS
328// =====================================================================
329
330// ----------------------------------------------------------------------
331void test_ValidateGood(void) {
332	const char *cp = leap_ghash;
333	int         rc = leapsec_validate(stringreader, &cp);
334	TEST_ASSERT_EQUAL(LSVALID_GOODHASH, rc);
335}
336
337// ----------------------------------------------------------------------
338void test_ValidateNoHash(void) {
339	const char *cp = leap2;
340	int         rc = leapsec_validate(stringreader, &cp);
341	TEST_ASSERT_EQUAL(LSVALID_NOHASH, rc);
342}
343
344// ----------------------------------------------------------------------
345void test_ValidateBad(void) {
346	const char *cp = leap_bhash;
347	int         rc = leapsec_validate(stringreader, &cp);
348	TEST_ASSERT_EQUAL(LSVALID_BADHASH, rc);
349}
350
351// ----------------------------------------------------------------------
352void test_ValidateMalformed(void) {
353	const char *cp = leap_mhash;
354	int         rc = leapsec_validate(stringreader, &cp);
355	TEST_ASSERT_EQUAL(LSVALID_BADFORMAT, rc);
356}
357
358// ----------------------------------------------------------------------
359void test_ValidateMalformedShort(void) {
360	const char *cp = leap_shash;
361	int         rc = leapsec_validate(stringreader, &cp);
362	TEST_ASSERT_EQUAL(LSVALID_BADFORMAT, rc);
363}
364
365// ----------------------------------------------------------------------
366void test_ValidateNoLeadZero(void) {
367	const char *cp = leap_gthash;
368	int         rc = leapsec_validate(stringreader, &cp);
369	TEST_ASSERT_EQUAL(LSVALID_GOODHASH, rc);
370}
371
372// =====================================================================
373// BASIC FUNCTIONS
374// =====================================================================
375
376// ----------------------------------------------------------------------
377// test table selection
378void test_tableSelect(void) {
379	leap_table_t *pt1, *pt2, *pt3, *pt4;
380
381	pt1 = leapsec_get_table(0);
382	pt2 = leapsec_get_table(0);
383	TEST_ASSERT_EQUAL_MESSAGE(pt1, pt2,"first");
384
385	pt1 = leapsec_get_table(1);
386	pt2 = leapsec_get_table(1);
387	TEST_ASSERT_EQUAL_MESSAGE(pt1, pt2,"second");
388
389	pt1 = leapsec_get_table(1);
390	pt2 = leapsec_get_table(0);
391	TEST_ASSERT_NOT_EQUAL(pt1, pt2);
392
393	pt1 = leapsec_get_table(0);
394	pt2 = leapsec_get_table(1);
395	TEST_ASSERT_NOT_EQUAL(pt1, pt2);
396
397	leapsec_set_table(pt1);
398	pt2 = leapsec_get_table(0);
399	pt3 = leapsec_get_table(1);
400	TEST_ASSERT_EQUAL(pt1, pt2);
401	TEST_ASSERT_NOT_EQUAL(pt2, pt3);
402
403	pt1 = pt3;
404	leapsec_set_table(pt1);
405	pt2 = leapsec_get_table(0);
406	pt3 = leapsec_get_table(1);
407	TEST_ASSERT_EQUAL(pt1, pt2);
408	TEST_ASSERT_NOT_EQUAL(pt2, pt3);
409}
410
411// ----------------------------------------------------------------------
412// load file & check expiration
413
414void test_loadFileExpire(void) {
415	const char *cp = leap1;
416	int rc;
417	leap_table_t * pt = leapsec_get_table(0);
418
419	rc =   leapsec_load(pt, stringreader, &cp, FALSE)
420	    && leapsec_set_table(pt);
421	TEST_ASSERT_EQUAL_MESSAGE(1, rc,"first");
422	rc = leapsec_expired(3439756800u, NULL);
423	TEST_ASSERT_EQUAL(0, rc);
424	rc = leapsec_expired(3610569601u, NULL);
425	TEST_ASSERT_EQUAL(1, rc);
426}
427
428// ----------------------------------------------------------------------
429// load file & check time-to-live
430
431void test_loadFileTTL(void) {
432	const char *cp = leap1;
433	int rc;
434	leap_table_t * pt = leapsec_get_table(0);
435	time_t         pivot = 0x70000000u;
436
437	const uint32_t limit = 3610569600u;
438
439	rc =   leapsec_load(pt, stringreader, &cp, FALSE)
440	    && leapsec_set_table(pt);
441	TEST_ASSERT_EQUAL(1, rc); //
442
443	// exactly 1 day to live
444	rc = leapsec_daystolive(limit - 86400, &pivot);
445	TEST_ASSERT_EQUAL( 1, rc);
446	// less than 1 day to live
447	rc = leapsec_daystolive(limit - 86399, &pivot);
448	TEST_ASSERT_EQUAL( 0, rc);
449	// hit expiration exactly
450	rc = leapsec_daystolive(limit, &pivot);
451	TEST_ASSERT_EQUAL( 0, rc);
452	// expired since 1 sec
453	rc = leapsec_daystolive(limit + 1, &pivot);
454	TEST_ASSERT_EQUAL(-1, rc);
455}
456
457// =====================================================================
458// RANDOM QUERY TESTS
459// =====================================================================
460
461// ----------------------------------------------------------------------
462// test query in pristine state (bug#2745 misbehaviour)
463void test_lsQueryPristineState(void) {
464	int            rc;
465	leap_result_t  qr;
466
467	rc = leapsec_query(&qr, lsec2012, NULL);
468	TEST_ASSERT_EQUAL(FALSE, rc);
469	TEST_ASSERT_EQUAL(0,             qr.warped   );
470	TEST_ASSERT_EQUAL(LSPROX_NOWARN, qr.proximity);
471}
472
473// ----------------------------------------------------------------------
474// ad-hoc jump: leap second at 2009.01.01 -60days
475void test_ls2009faraway(void) {
476	int            rc;
477	leap_result_t  qr;
478
479	rc = setup_load_table(leap1,FALSE);
480	TEST_ASSERT_EQUAL(1, rc);
481
482	// test 60 days before leap. Nothing scheduled or indicated.
483	rc = leapsec_query(&qr, lsec2009 - 60*SECSPERDAY, NULL);
484	TEST_ASSERT_EQUAL(FALSE, rc);
485	TEST_ASSERT_EQUAL(33, qr.tai_offs);
486	TEST_ASSERT_EQUAL(0,  qr.tai_diff);
487	TEST_ASSERT_EQUAL(LSPROX_NOWARN, qr.proximity);
488}
489
490// ----------------------------------------------------------------------
491// ad-hoc jump: leap second at 2009.01.01 -1week
492void test_ls2009weekaway(void) {
493	int            rc;
494	leap_result_t  qr;
495
496	rc = setup_load_table(leap1,FALSE);
497	TEST_ASSERT_EQUAL(1, rc);
498
499	// test 7 days before leap. Leap scheduled, but not yet indicated.
500	rc = leapsec_query(&qr, lsec2009 - 7*SECSPERDAY, NULL);
501	TEST_ASSERT_EQUAL(FALSE, rc);
502	TEST_ASSERT_EQUAL(33, qr.tai_offs);
503	TEST_ASSERT_EQUAL(1,  qr.tai_diff);
504	TEST_ASSERT_EQUAL(LSPROX_SCHEDULE, qr.proximity);
505}
506
507// ----------------------------------------------------------------------
508// ad-hoc jump: leap second at 2009.01.01 -1hr
509void test_ls2009houraway(void) {
510	int            rc;
511	leap_result_t  qr;
512
513	rc = setup_load_table(leap1,FALSE);
514	TEST_ASSERT_EQUAL(1, rc);
515
516	// test 1 hour before leap. 61 true seconds to go.
517	rc = leapsec_query(&qr, lsec2009 - SECSPERHR, NULL);
518	TEST_ASSERT_EQUAL(FALSE, rc);
519	TEST_ASSERT_EQUAL(33, qr.tai_offs);
520	TEST_ASSERT_EQUAL(1,  qr.tai_diff);
521	TEST_ASSERT_EQUAL(LSPROX_ANNOUNCE, qr.proximity);
522}
523
524// ----------------------------------------------------------------------
525// ad-hoc jump: leap second at 2009.01.01 -1sec
526void test_ls2009secaway(void) {
527	int            rc;
528	leap_result_t  qr;
529
530	rc = setup_load_table(leap1,FALSE);
531	TEST_ASSERT_EQUAL(1, rc);
532
533	// test 1 second before leap (last boundary...) 2 true seconds to go.
534	rc = leapsec_query(&qr, lsec2009 - 1, NULL);
535	TEST_ASSERT_EQUAL(FALSE, rc);
536	TEST_ASSERT_EQUAL(33, qr.tai_offs);
537	TEST_ASSERT_EQUAL(1,  qr.tai_diff);
538	TEST_ASSERT_EQUAL(LSPROX_ALERT, qr.proximity);
539}
540
541// ----------------------------------------------------------------------
542// ad-hoc jump to leap second at 2009.01.01
543void test_ls2009onspot(void) {
544	int            rc;
545	leap_result_t  qr;
546
547	rc = setup_load_table(leap1,FALSE);
548	TEST_ASSERT_EQUAL(1, rc);
549
550	// test on-spot: treat leap second as already gone.
551	rc = leapsec_query(&qr, lsec2009, NULL);
552	TEST_ASSERT_EQUAL(FALSE, rc);
553	TEST_ASSERT_EQUAL(34, qr.tai_offs);
554	TEST_ASSERT_EQUAL(0,  qr.tai_diff);
555	TEST_ASSERT_EQUAL(LSPROX_NOWARN, qr.proximity);
556}
557
558// ----------------------------------------------------------------------
559// test handling of the leap second at 2009.01.01 without table
560void test_ls2009nodata(void) {
561	int            rc;
562	leap_result_t  qr;
563
564	rc = setup_clear_table();
565	TEST_ASSERT_EQUAL(1, rc);
566
567	// test on-spot with empty table
568	rc = leapsec_query(&qr, lsec2009, NULL);
569	TEST_ASSERT_EQUAL(FALSE, rc);
570	TEST_ASSERT_EQUAL(0,  qr.tai_offs);
571	TEST_ASSERT_EQUAL(0,  qr.tai_diff);
572	TEST_ASSERT_EQUAL(LSPROX_NOWARN, qr.proximity);
573}
574
575// ----------------------------------------------------------------------
576// test handling of the leap second at 2009.01.01 with culled data
577void test_ls2009limdata(void) {
578	int            rc;
579	leap_result_t  qr;
580
581	rc = setup_load_table(leap1, TRUE);
582	TEST_ASSERT_EQUAL(1, rc);
583
584	// test on-spot with limited table - this is tricky.
585	// The table used ends 2012; depending on the build date, the 2009 entry
586	// might be included or culled. The resulting TAI offset must be either
587	// 34 or 35 seconds, depending on the build date of the test.
588	rc = leapsec_query(&qr, lsec2009, NULL);
589	TEST_ASSERT_EQUAL(FALSE, rc);
590	TEST_ASSERT_TRUE(34 <= qr.tai_offs);
591	TEST_ASSERT_TRUE(35 >= qr.tai_offs);
592	TEST_ASSERT_EQUAL(0,  qr.tai_diff);
593	TEST_ASSERT_EQUAL(LSPROX_NOWARN, qr.proximity);
594}
595
596// ----------------------------------------------------------------------
597// Far-distance forward jump into a transiton window.
598void test_qryJumpFarAhead(void) {
599	int            rc;
600	leap_result_t  qr;
601	int            last, idx;
602	int 		mode;
603
604	for (mode=0; mode < 2; ++mode) {
605		leapsec_ut_pristine();
606		rc = setup_load_table(leap1, FALSE);
607		TEST_ASSERT_EQUAL(1, rc);
608		leapsec_electric(mode);
609
610		rc = leapsec_query(&qr, lsec2006, NULL);
611		TEST_ASSERT_EQUAL(FALSE, rc);
612
613		rc = leapsec_query(&qr, lsec2012, NULL);
614		TEST_ASSERT_EQUAL(FALSE, rc);
615	}
616}
617
618// ----------------------------------------------------------------------
619// Forward jump into the next transition window
620void test_qryJumpAheadToTransition(void) {
621	int            rc;
622	leap_result_t  qr;
623	int            last, idx;
624	int 		mode;
625
626	for (mode=0; mode < 2; ++mode) {
627		leapsec_ut_pristine();
628		rc = setup_load_table(leap1, FALSE);
629		TEST_ASSERT_EQUAL(1, rc);
630		leapsec_electric(mode);
631
632		rc = leapsec_query(&qr, lsec2009-SECSPERDAY, NULL);
633		TEST_ASSERT_EQUAL(FALSE, rc);
634
635		rc = leapsec_query(&qr, lsec2009+1, NULL);
636		TEST_ASSERT_EQUAL(TRUE, rc);
637	}
638}
639
640// ----------------------------------------------------------------------
641// Forward jump over the next transition window
642void test_qryJumpAheadOverTransition(void) {
643	int            rc;
644	leap_result_t  qr;
645	int            last, idx;
646	int 		mode;
647
648	for (mode=0; mode < 2; ++mode) {
649		leapsec_ut_pristine();
650		rc = setup_load_table(leap1, FALSE);
651		TEST_ASSERT_EQUAL(1, rc);
652		leapsec_electric(mode);
653
654		rc = leapsec_query(&qr, lsec2009-SECSPERDAY, NULL);
655		TEST_ASSERT_EQUAL(FALSE, rc);
656
657		rc = leapsec_query(&qr, lsec2009+5, NULL);
658		TEST_ASSERT_EQUAL(FALSE, rc);
659	}
660}
661
662// =====================================================================
663// TABLE MODIFICATION AT RUNTIME
664// =====================================================================
665
666// ----------------------------------------------------------------------
667// add dynamic leap second (like from peer/clock)
668void test_addDynamic(void) {
669	int            rc;
670	leap_result_t  qr;
671
672	static const uint32_t insns[] = {
673		2982009600u,	//	29	# 1 Jul 1994
674		3029443200u,	//	30	# 1 Jan 1996
675		3076704000u,	//	31	# 1 Jul 1997
676		3124137600u,	//	32	# 1 Jan 1999
677		3345062400u,	//	33	# 1 Jan 2006
678		3439756800u,	//	34	# 1 Jan 2009
679		3550089600u,	//	35	# 1 Jul 2012
680		0 // sentinel
681	};
682
683	rc = setup_load_table(leap2, FALSE);
684	TEST_ASSERT_EQUAL(1, rc);
685
686	leap_table_t * pt = leapsec_get_table(0);
687	int 		idx;
688
689	for (idx=1; insns[idx]; ++idx) {
690		rc = leapsec_add_dyn(TRUE, insns[idx] - 20*SECSPERDAY - 100, NULL);
691		TEST_ASSERT_EQUAL(TRUE, rc);
692	}
693	// try to slip in a previous entry
694	rc = leapsec_add_dyn(TRUE, insns[0] - 20*SECSPERDAY - 100, NULL);
695	TEST_ASSERT_EQUAL(FALSE, rc);
696	//leapsec_dump(pt, (leapsec_dumper)fprintf, stdout);
697}
698
699// ----------------------------------------------------------------------
700// add fixed leap seconds (like from network packet)
701#if 0 /* currently unused -- possibly revived later */
702void FAILtest_addFixed(void) {
703	int            rc;
704	leap_result_t  qr;
705
706	static const struct { uint32_t tt; int of; } insns[] = {
707		{2982009600u, 29},//	# 1 Jul 1994
708		{3029443200u, 30},//	# 1 Jan 1996
709		{3076704000u, 31},//	# 1 Jul 1997
710		{3124137600u, 32},//	# 1 Jan 1999
711		{3345062400u, 33},//	# 1 Jan 2006
712		{3439756800u, 34},//	# 1 Jan 2009
713		{3550089600u, 35},//	# 1 Jul 2012
714		{0,0} // sentinel
715	};
716
717	rc = setup_load_table(leap2, FALSE);
718	TEST_ASSERT_EQUAL(1, rc);
719	int idx;
720	leap_table_t * pt = leapsec_get_table(0);
721	// try to get in BAD time stamps...
722	for (idx=0; insns[idx].tt; ++idx) {
723	    rc = leapsec_add_fix(
724		insns[idx].of,
725		insns[idx].tt - 20*SECSPERDAY - 100,
726		insns[idx].tt + SECSPERDAY,
727		NULL);
728		TEST_ASSERT_EQUAL(FALSE, rc);
729	}
730	// now do it right
731	for (idx=0; insns[idx].tt; ++idx) {
732		rc = leapsec_add_fix(
733		    insns[idx].of,
734		    insns[idx].tt,
735		    insns[idx].tt + SECSPERDAY,
736		    NULL);
737		TEST_ASSERT_EQUAL(TRUE, rc);
738	}
739	// try to slip in a previous entry
740	rc = leapsec_add_fix(
741	    insns[0].of,
742	    insns[0].tt,
743	    insns[0].tt + SECSPERDAY,
744	    NULL);
745	TEST_ASSERT_EQUAL(FALSE, rc);
746	//leapsec_dump(pt, (leapsec_dumper)fprintf, stdout);
747}
748#endif
749
750// ----------------------------------------------------------------------
751// add fixed leap seconds (like from network packet)
752#if 0 /* currently unused -- possibly revived later */
753void FAILtest_addFixedExtend(void) {
754	int            rc;
755	leap_result_t  qr;
756	int            last, idx;
757
758	static const struct { uint32_t tt; int of; } insns[] = {
759		{2982009600u, 29},//	# 1 Jul 1994
760		{3029443200u, 30},//	# 1 Jan 1996
761		{0,0} // sentinel
762	};
763
764	rc = setup_load_table(leap2, FALSE);
765	TEST_ASSERT_EQUAL(1, rc);
766
767	leap_table_t * pt = leapsec_get_table(FALSE);
768	for (last=idx=0; insns[idx].tt; ++idx) {
769		last = idx;
770		rc = leapsec_add_fix(
771		    insns[idx].of,
772		    insns[idx].tt,
773		    insns[idx].tt + SECSPERDAY,
774		    NULL);
775		TEST_ASSERT_EQUAL(TRUE, rc);
776	}
777
778	// try to extend the expiration of the last entry
779	rc = leapsec_add_fix(
780	    insns[last].of,
781	    insns[last].tt,
782	    insns[last].tt + 128*SECSPERDAY,
783	    NULL);
784	TEST_ASSERT_EQUAL(TRUE, rc);
785
786	// try to extend the expiration of the last entry with wrong offset
787	rc = leapsec_add_fix(
788	    insns[last].of+1,
789	    insns[last].tt,
790	    insns[last].tt + 129*SECSPERDAY,
791	    NULL);
792	TEST_ASSERT_EQUAL(FALSE, rc);
793	//leapsec_dump(pt, (leapsec_dumper)fprintf, stdout);
794}
795#endif
796
797// ----------------------------------------------------------------------
798// add fixed leap seconds (like from network packet) in an otherwise
799// empty table and test queries before / between /after the tabulated
800// values.
801#if 0 /* currently unused -- possibly revived later */
802void FAILtest_setFixedExtend(void) {
803	int            rc;
804	leap_result_t  qr;
805	int            last, idx;
806
807	static const struct { uint32_t tt; int of; } insns[] = {
808		{2982009600u, 29},//	# 1 Jul 1994
809		{3029443200u, 30},//	# 1 Jan 1996
810		{0,0} // sentinel
811	};
812
813	leap_table_t * pt = leapsec_get_table(0);
814	for (last=idx=0; insns[idx].tt; ++idx) {
815		last = idx;
816		rc = leapsec_add_fix(
817		    insns[idx].of,
818		    insns[idx].tt,
819		    insns[idx].tt + 128*SECSPERDAY,
820		    NULL);
821		TEST_ASSERT_EQUAL(TRUE, rc);
822	}
823
824	rc = leapsec_query(&qr, insns[0].tt - 86400, NULL);
825	TEST_ASSERT_EQUAL(28, qr.tai_offs);
826
827	rc = leapsec_query(&qr, insns[0].tt + 86400, NULL);
828	TEST_ASSERT_EQUAL(29, qr.tai_offs);
829
830	rc = leapsec_query(&qr, insns[1].tt - 86400, NULL);
831	TEST_ASSERT_EQUAL(29, qr.tai_offs);
832
833	rc = leapsec_query(&qr, insns[1].tt + 86400, NULL);
834	TEST_ASSERT_EQUAL(30, qr.tai_offs);
835
836	//leapsec_dump(pt, (leapsec_dumper)fprintf, stdout);
837}
838#endif
839
840// =====================================================================
841// AUTOKEY LEAP TRANSFER TESTS
842// =====================================================================
843
844// ----------------------------------------------------------------------
845// Check if the offset can be applied to an empty table ONCE
846void test_taiEmptyTable(void) {
847	int rc;
848
849	rc = leapsec_autokey_tai(35, lsec2015-30*86400, NULL);
850	TEST_ASSERT_EQUAL(TRUE, rc);
851
852	rc = leapsec_autokey_tai(35, lsec2015-29*86400, NULL);
853	TEST_ASSERT_EQUAL(FALSE, rc);
854}
855
856// ----------------------------------------------------------------------
857// Check that with fixed entries the operation fails
858void test_taiTableFixed(void) {
859	int rc;
860
861	rc = setup_load_table(leap1, FALSE);
862	TEST_ASSERT_EQUAL(1, rc);
863
864	rc = leapsec_autokey_tai(35, lsec2015-30*86400, NULL);
865	TEST_ASSERT_EQUAL(FALSE, rc);
866}
867
868// ----------------------------------------------------------------------
869// test adjustment with a dynamic entry already there
870void test_taiTableDynamic(void) {
871	int        rc;
872	leap_era_t era;
873
874	rc = leapsec_add_dyn(TRUE, lsec2015-20*SECSPERDAY, NULL);
875	TEST_ASSERT_EQUAL(TRUE, rc);
876
877	leapsec_query_era(&era, lsec2015-10, NULL);
878	TEST_ASSERT_EQUAL(0, era.taiof);
879	leapsec_query_era(&era, lsec2015+10, NULL);
880	TEST_ASSERT_EQUAL(1, era.taiof);
881
882	rc = leapsec_autokey_tai(35, lsec2015-19*86400, NULL);
883	TEST_ASSERT_EQUAL(TRUE, rc);
884
885	rc = leapsec_autokey_tai(35, lsec2015-19*86400, NULL);
886	TEST_ASSERT_EQUAL(FALSE, rc);
887
888	leapsec_query_era(&era, lsec2015-10, NULL);
889	TEST_ASSERT_EQUAL(35, era.taiof);
890	leapsec_query_era(&era, lsec2015+10, NULL);
891	TEST_ASSERT_EQUAL(36, era.taiof);
892}
893
894// ----------------------------------------------------------------------
895// test adjustment with a dynamic entry already there in dead zone
896void test_taiTableDynamicDeadZone(void) {
897	int rc;
898
899	rc = leapsec_add_dyn(TRUE, lsec2015-20*SECSPERDAY, NULL);
900	TEST_ASSERT_EQUAL(TRUE, rc);
901
902	rc = leapsec_autokey_tai(35, lsec2015-5, NULL);
903	TEST_ASSERT_EQUAL(FALSE, rc);
904
905	rc = leapsec_autokey_tai(35, lsec2015+5, NULL);
906	TEST_ASSERT_EQUAL(FALSE, rc);
907}
908
909
910// =====================================================================
911// SEQUENCE TESTS
912// =====================================================================
913
914// ----------------------------------------------------------------------
915// leap second insert at 2009.01.01, electric mode
916void test_ls2009seqInsElectric(void) {
917	int            rc;
918	leap_result_t  qr;
919
920	rc = setup_load_table(leap1,FALSE);
921	TEST_ASSERT_EQUAL(1, rc);
922	leapsec_electric(1);
923	TEST_ASSERT_EQUAL(1, leapsec_electric(-1));
924
925	rc = leapsec_query(&qr, lsec2009 - 60*SECSPERDAY, NULL);
926	TEST_ASSERT_EQUAL(FALSE, rc);
927	TEST_ASSERT_EQUAL(0,             qr.warped   );
928	TEST_ASSERT_EQUAL(LSPROX_NOWARN, qr.proximity);
929
930	rc = leapsec_query(&qr, lsec2009 - 7*SECSPERDAY, NULL);
931	TEST_ASSERT_EQUAL(FALSE, rc);
932	TEST_ASSERT_EQUAL(0,               qr.warped   );
933	TEST_ASSERT_EQUAL(LSPROX_SCHEDULE, qr.proximity);
934
935	rc = leapsec_query(&qr, lsec2009 - SECSPERHR, NULL);
936	TEST_ASSERT_EQUAL(FALSE, rc);
937	TEST_ASSERT_EQUAL(0,               qr.warped   );
938	TEST_ASSERT_EQUAL(LSPROX_ANNOUNCE, qr.proximity);
939
940	rc = leapsec_query(&qr, lsec2009 - 1, NULL);
941	TEST_ASSERT_EQUAL(FALSE, rc);
942	TEST_ASSERT_EQUAL(0,               qr.warped   );
943	TEST_ASSERT_EQUAL(LSPROX_ALERT,    qr.proximity);
944
945	rc = leapsec_query(&qr, lsec2009, NULL);
946	TEST_ASSERT_EQUAL(TRUE, rc);
947	TEST_ASSERT_EQUAL(0,             qr.warped   );
948	TEST_ASSERT_EQUAL(LSPROX_NOWARN, qr.proximity);
949
950	// second call, same time frame: no trigger!
951	rc = leapsec_query(&qr, lsec2009, NULL);
952	TEST_ASSERT_EQUAL(FALSE, rc);
953	TEST_ASSERT_EQUAL(0,             qr.warped   );
954	TEST_ASSERT_EQUAL(LSPROX_NOWARN, qr.proximity);
955}
956
957// ----------------------------------------------------------------------
958// leap second insert at 2009.01.01, dumb mode
959void test_ls2009seqInsDumb(void) {
960	int            rc;
961	leap_result_t  qr;
962
963	rc = setup_load_table(leap1,FALSE);
964	TEST_ASSERT_EQUAL(1, rc);
965	TEST_ASSERT_EQUAL(0, leapsec_electric(-1));
966
967	rc = leapsec_query(&qr, lsec2009 - 60*SECSPERDAY, NULL);
968	TEST_ASSERT_EQUAL(FALSE, rc);
969	TEST_ASSERT_EQUAL(0,             qr.warped   );
970	TEST_ASSERT_EQUAL(LSPROX_NOWARN, qr.proximity);
971
972	rc = leapsec_query(&qr, lsec2009 - 7*SECSPERDAY, NULL);
973	TEST_ASSERT_EQUAL(FALSE, rc);
974	TEST_ASSERT_EQUAL(0,               qr.warped   );
975	TEST_ASSERT_EQUAL(LSPROX_SCHEDULE, qr.proximity);
976
977	rc = leapsec_query(&qr, lsec2009 - SECSPERHR, NULL);
978	TEST_ASSERT_EQUAL(FALSE, rc);
979	TEST_ASSERT_EQUAL(0,               qr.warped   );
980	TEST_ASSERT_EQUAL(LSPROX_ANNOUNCE, qr.proximity);
981
982	rc = leapsec_query(&qr, lsec2009 - 1, NULL);
983	TEST_ASSERT_EQUAL(FALSE, rc);
984	TEST_ASSERT_EQUAL(0,               qr.warped   );
985	TEST_ASSERT_EQUAL(LSPROX_ALERT,    qr.proximity);
986
987	rc = leapsec_query(&qr, lsec2009, NULL);
988	TEST_ASSERT_EQUAL(FALSE, rc);
989	TEST_ASSERT_EQUAL(0,               qr.warped   );
990	TEST_ASSERT_EQUAL(LSPROX_ALERT,    qr.proximity);
991
992	rc = leapsec_query(&qr, lsec2009+1, NULL);
993	TEST_ASSERT_EQUAL(TRUE, rc);
994	TEST_ASSERT_EQUAL(-1,             qr.warped   );
995	TEST_ASSERT_EQUAL(LSPROX_NOWARN, qr.proximity);
996
997	// second call, same time frame: no trigger!
998	rc = leapsec_query(&qr, lsec2009, NULL);
999	TEST_ASSERT_EQUAL(FALSE, rc);
1000	TEST_ASSERT_EQUAL(0,             qr.warped   );
1001	TEST_ASSERT_EQUAL(LSPROX_NOWARN, qr.proximity);
1002}
1003
1004
1005// ----------------------------------------------------------------------
1006// fake leap second remove at 2009.01.01, electric mode
1007void test_ls2009seqDelElectric(void) {
1008	int            rc;
1009	leap_result_t  qr;
1010
1011	rc = setup_load_table(leap3,FALSE);
1012	TEST_ASSERT_EQUAL(1, rc);
1013	leapsec_electric(1);
1014	TEST_ASSERT_EQUAL(1, leapsec_electric(-1));
1015
1016	rc = leapsec_query(&qr, lsec2009 - 60*SECSPERDAY, NULL);
1017	TEST_ASSERT_EQUAL(FALSE, rc);
1018	TEST_ASSERT_EQUAL(0,             qr.warped   );
1019	TEST_ASSERT_EQUAL(LSPROX_NOWARN, qr.proximity);
1020
1021	rc = leapsec_query(&qr, lsec2009 - 7*SECSPERDAY, NULL);
1022	TEST_ASSERT_EQUAL(FALSE, rc);
1023	TEST_ASSERT_EQUAL(0,               qr.warped   );
1024	TEST_ASSERT_EQUAL(LSPROX_SCHEDULE, qr.proximity);
1025
1026	rc = leapsec_query(&qr, lsec2009 - SECSPERHR, NULL);
1027	TEST_ASSERT_EQUAL(FALSE, rc);
1028	TEST_ASSERT_EQUAL(0,               qr.warped   );
1029	TEST_ASSERT_EQUAL(LSPROX_ANNOUNCE, qr.proximity);
1030
1031	rc = leapsec_query(&qr, lsec2009 - 1, NULL);
1032	TEST_ASSERT_EQUAL(FALSE, rc);
1033	TEST_ASSERT_EQUAL(0,               qr.warped   );
1034	TEST_ASSERT_EQUAL(LSPROX_ALERT,    qr.proximity);
1035
1036	rc = leapsec_query(&qr, lsec2009, NULL);
1037	TEST_ASSERT_EQUAL(TRUE, rc);
1038	TEST_ASSERT_EQUAL(0,             qr.warped   );
1039	TEST_ASSERT_EQUAL(LSPROX_NOWARN, qr.proximity);
1040
1041	// second call, same time frame: no trigger!
1042	rc = leapsec_query(&qr, lsec2009, NULL);
1043	TEST_ASSERT_EQUAL(FALSE, rc);
1044	TEST_ASSERT_EQUAL(0,             qr.warped   );
1045	TEST_ASSERT_EQUAL(LSPROX_NOWARN, qr.proximity);
1046}
1047
1048// ----------------------------------------------------------------------
1049// fake leap second remove at 2009.01.01. dumb mode
1050void test_ls2009seqDelDumb(void) {
1051	int            rc;
1052	leap_result_t  qr;
1053
1054	rc = setup_load_table(leap3,FALSE);
1055	TEST_ASSERT_EQUAL(1, rc);
1056	TEST_ASSERT_EQUAL(0, leapsec_electric(-1));
1057
1058	rc = leapsec_query(&qr, lsec2009 - 60*SECSPERDAY, NULL);
1059	TEST_ASSERT_EQUAL(FALSE, rc);
1060	TEST_ASSERT_EQUAL(0,             qr.warped   );
1061	TEST_ASSERT_EQUAL(LSPROX_NOWARN, qr.proximity);
1062
1063	rc = leapsec_query(&qr, lsec2009 - 7*SECSPERDAY, NULL);
1064	TEST_ASSERT_EQUAL(FALSE, rc);
1065	TEST_ASSERT_EQUAL(0,               qr.warped   );
1066	TEST_ASSERT_EQUAL(LSPROX_SCHEDULE, qr.proximity);
1067
1068	rc = leapsec_query(&qr, lsec2009 - SECSPERHR, NULL);
1069	TEST_ASSERT_EQUAL(FALSE, rc);
1070	TEST_ASSERT_EQUAL(0,               qr.warped   );
1071	TEST_ASSERT_EQUAL(LSPROX_ANNOUNCE, qr.proximity);
1072
1073	rc = leapsec_query(&qr, lsec2009 - 2, NULL);
1074	TEST_ASSERT_EQUAL(FALSE, rc);
1075	TEST_ASSERT_EQUAL(0,               qr.warped   );
1076	TEST_ASSERT_EQUAL(LSPROX_ALERT,    qr.proximity);
1077
1078	rc = leapsec_query(&qr, lsec2009 - 1, NULL);
1079	TEST_ASSERT_EQUAL(TRUE, rc);
1080	TEST_ASSERT_EQUAL(1,             qr.warped   );
1081	TEST_ASSERT_EQUAL(LSPROX_NOWARN, qr.proximity);
1082
1083	// second call, same time frame: no trigger!
1084	rc = leapsec_query(&qr, lsec2009, NULL);
1085	TEST_ASSERT_EQUAL(FALSE, rc);
1086	TEST_ASSERT_EQUAL(0,             qr.warped   );
1087	TEST_ASSERT_EQUAL(LSPROX_NOWARN, qr.proximity);
1088}
1089
1090// ----------------------------------------------------------------------
1091// leap second insert at 2012.07.01, electric mode
1092void test_ls2012seqInsElectric(void) {
1093	int            rc;
1094	leap_result_t  qr;
1095
1096	rc = setup_load_table(leap1,FALSE);
1097	TEST_ASSERT_EQUAL(1, rc);
1098	leapsec_electric(1);
1099	TEST_ASSERT_EQUAL(1, leapsec_electric(-1));
1100
1101	rc = leapsec_query(&qr, lsec2012 - 60*SECSPERDAY, NULL);
1102	TEST_ASSERT_EQUAL(FALSE, rc);
1103	TEST_ASSERT_EQUAL(0,             qr.warped   );
1104	TEST_ASSERT_EQUAL(LSPROX_NOWARN, qr.proximity);
1105
1106	rc = leapsec_query(&qr, lsec2012 - 7*SECSPERDAY, NULL);
1107	TEST_ASSERT_EQUAL(FALSE, rc);
1108	TEST_ASSERT_EQUAL(0,               qr.warped   );
1109	TEST_ASSERT_EQUAL(LSPROX_SCHEDULE, qr.proximity);
1110
1111	rc = leapsec_query(&qr, lsec2012 - SECSPERHR, NULL);
1112	TEST_ASSERT_EQUAL(FALSE, rc);
1113	TEST_ASSERT_EQUAL(0,               qr.warped   );
1114	TEST_ASSERT_EQUAL(LSPROX_ANNOUNCE, qr.proximity);
1115
1116	rc = leapsec_query(&qr, lsec2012 - 1, NULL);
1117	TEST_ASSERT_EQUAL(FALSE, rc);
1118	TEST_ASSERT_EQUAL(0,               qr.warped   );
1119	TEST_ASSERT_EQUAL(LSPROX_ALERT,    qr.proximity);
1120
1121	rc = leapsec_query(&qr, lsec2012, NULL);
1122	TEST_ASSERT_EQUAL(TRUE, rc);
1123	TEST_ASSERT_EQUAL(0,            qr.warped   );
1124	TEST_ASSERT_EQUAL(LSPROX_NOWARN, qr.proximity);
1125
1126	// second call, same time frame: no trigger!
1127	rc = leapsec_query(&qr, lsec2012, NULL);
1128	TEST_ASSERT_EQUAL(FALSE, rc);
1129	TEST_ASSERT_EQUAL(0,             qr.warped   );
1130	TEST_ASSERT_EQUAL(LSPROX_NOWARN, qr.proximity);
1131}
1132
1133// ----------------------------------------------------------------------
1134// leap second insert at 2012.07.01, dumb mode
1135void test_ls2012seqInsDumb(void) {
1136	int            rc;
1137	leap_result_t  qr;
1138
1139	rc = setup_load_table(leap1,FALSE);
1140	TEST_ASSERT_EQUAL(1, rc);
1141	TEST_ASSERT_EQUAL(0, leapsec_electric(-1));
1142
1143	rc = leapsec_query(&qr, lsec2012 - 60*SECSPERDAY, NULL);
1144	TEST_ASSERT_EQUAL(FALSE, rc);
1145	TEST_ASSERT_EQUAL(0,             qr.warped   );
1146	TEST_ASSERT_EQUAL(LSPROX_NOWARN, qr.proximity);
1147
1148	rc = leapsec_query(&qr, lsec2012 - 7*SECSPERDAY, NULL);
1149	TEST_ASSERT_EQUAL(FALSE, rc);
1150	TEST_ASSERT_EQUAL(0,               qr.warped   );
1151	TEST_ASSERT_EQUAL(LSPROX_SCHEDULE, qr.proximity);
1152
1153	rc = leapsec_query(&qr, lsec2012 - SECSPERHR, NULL);
1154	TEST_ASSERT_EQUAL(FALSE, rc);
1155	TEST_ASSERT_EQUAL(0,               qr.warped   );
1156	TEST_ASSERT_EQUAL(LSPROX_ANNOUNCE, qr.proximity);
1157
1158	rc = leapsec_query(&qr, lsec2012 - 1, NULL);
1159	TEST_ASSERT_EQUAL(FALSE, rc);
1160	TEST_ASSERT_EQUAL(0,               qr.warped   );
1161	TEST_ASSERT_EQUAL(LSPROX_ALERT,    qr.proximity);
1162
1163	// This is just 1 sec before transition!
1164	rc = leapsec_query(&qr, lsec2012, NULL);
1165	TEST_ASSERT_EQUAL(FALSE, rc);
1166	TEST_ASSERT_EQUAL(0,            qr.warped   );
1167	TEST_ASSERT_EQUAL(LSPROX_ALERT, qr.proximity);
1168
1169	// NOW the insert/backwarp must happen
1170	rc = leapsec_query(&qr, lsec2012+1, NULL);
1171	TEST_ASSERT_EQUAL(TRUE, rc);
1172	TEST_ASSERT_EQUAL(-1,            qr.warped   );
1173	TEST_ASSERT_EQUAL(LSPROX_NOWARN, qr.proximity);
1174
1175	// second call with transition time: no trigger!
1176	rc = leapsec_query(&qr, lsec2012, NULL);
1177	TEST_ASSERT_EQUAL(FALSE, rc);
1178	TEST_ASSERT_EQUAL(0,             qr.warped   );
1179	TEST_ASSERT_EQUAL(LSPROX_NOWARN, qr.proximity);
1180}
1181
1182// ----------------------------------------------------------------------
1183// test repeated query on empty table in dumb mode
1184void test_lsEmptyTableDumb(void) {
1185	int            rc;
1186	leap_result_t  qr;
1187
1188	//const
1189	time_t pivot;
1190	pivot = lsec2012;
1191	//	const
1192	//time_t   pivot(lsec2012);
1193	const uint32_t t0 = lsec2012 - 10;
1194	const uint32_t tE = lsec2012 + 10;
1195
1196	TEST_ASSERT_EQUAL(0, leapsec_electric(-1));
1197
1198	uint32_t t;
1199	for (t = t0; t != tE; ++t) {
1200		rc = leapsec_query(&qr, t, &pivot);
1201		TEST_ASSERT_EQUAL(FALSE, rc);
1202		TEST_ASSERT_EQUAL(0,             qr.warped   );
1203		TEST_ASSERT_EQUAL(LSPROX_NOWARN, qr.proximity);
1204	}
1205}
1206
1207// ----------------------------------------------------------------------
1208// test repeated query on empty table in electric mode
1209void test_lsEmptyTableElectric(void) {
1210	int            rc;
1211	leap_result_t  qr;
1212
1213	leapsec_electric(1);
1214	TEST_ASSERT_EQUAL(1, leapsec_electric(-1));
1215
1216	//const
1217	time_t   pivot;//(lsec2012);
1218	pivot = lsec2012;
1219	const uint32_t t0 = lsec2012 - 10;
1220	const uint32_t tE = lsec2012 + 10;
1221
1222	time_t t;
1223	for (t = t0; t != tE; ++t) {
1224		rc = leapsec_query(&qr, t, &pivot);
1225		TEST_ASSERT_EQUAL(FALSE, rc);
1226		TEST_ASSERT_EQUAL(0,             qr.warped   );
1227		TEST_ASSERT_EQUAL(LSPROX_NOWARN, qr.proximity);
1228	}
1229}
1230