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