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 
16 static 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 
51 static 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
77 static 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
110 static 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
130 static 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
150 static 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
170 static 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
190 static 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 
229 static const uint32_t lsec2006 = 3345062400u; // +33, 1 Jan 2006, 00:00:00 utc
230 static const uint32_t lsec2009 = 3439756800u; // +34, 1 Jan 2009, 00:00:00 utc
231 static const uint32_t lsec2012 = 3550089600u; // +35, 1 Jul 2012, 00:00:00 utc
232 static const uint32_t lsec2015 = 3644697600u; // +36, 1 Jul 2015, 00:00:00 utc
233 
stringreader(void * farg)234 int 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 
244 static int/*BOOL*/
setup_load_table(const char * cp,int blim)245 setup_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 
257 static int/*BOOL*/
setup_clear_table(void)258 setup_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 
270 char *
CalendarToString(const struct calendar cal)271 CalendarToString(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 
302 int
IsEqual(const struct calendar expected,const struct calendar actual)303 IsEqual(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 
328 void
setUp(void)329 setUp(void)
330 {
331     ntpcal_set_timefunc(timefunc);
332     settime(1970, 1, 1, 0, 0, 0);
333     leapsec_ut_pristine();
334 
335     return;
336 }
337 
338 void
tearDown(void)339 tearDown(void)
340 {
341     ntpcal_set_timefunc(NULL);
342     return;
343 }
344 
345 // =====================================================================
346 // VALIDATION TESTS
347 // =====================================================================
348 
349 // ----------------------------------------------------------------------
350 void
test_ValidateGood(void)351 test_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 // ----------------------------------------------------------------------
361 void
test_ValidateNoHash(void)362 test_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 // ----------------------------------------------------------------------
372 void
test_ValidateBad(void)373 test_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 // ----------------------------------------------------------------------
384 void
test_ValidateMalformed(void)385 test_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 // ----------------------------------------------------------------------
396 void
test_ValidateMalformedShort(void)397 test_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 // ----------------------------------------------------------------------
408 void
test_ValidateNoLeadZero(void)409 test_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
425 void
test_tableSelect(void)426 test_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 
465 void
test_loadFileExpire(void)466 test_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 
486 void
test_loadFileTTL(void)487 test_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)
521 void
test_lsQueryPristineState(void)522 test_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
537 void
test_ls2009faraway(void)538 test_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
558 void
test_ls2009weekaway(void)559 test_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
579 void
test_ls2009houraway(void)580 test_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
600 void
test_ls2009secaway(void)601 test_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
621 void
test_ls2009onspot(void)622 test_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
642 void
test_ls2009nodata(void)643 test_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
663 void
test_ls2009limdata(void)664 test_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.
688 void
test_qryJumpFarAhead(void)689 test_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
test_qryJumpAheadToTransition(void)712 void 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
736 void
test_qryJumpAheadOverTransition(void)737 test_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)
766 void
test_addDynamic(void)767 test_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 */
804 void
805 FAILtest_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 */
860 void
861 FAILtest_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 */
913 void
914 FAILtest_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
test_taiEmptyTable(void)961 void 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
973 void
test_taiTableFixed(void)974 test_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
989 void
test_taiTableDynamic(void)990 test_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
1019 void
test_taiTableDynamicDeadZone(void)1020 test_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
1043 void
test_ls2009seqInsElectric(void)1044 test_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
1090 void
test_ls2009seqInsDumb(void)1091 test_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
1142 void
test_ls2009seqDelElectric(void)1143 test_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
1189 void
test_ls2009seqDelDumb(void)1190 test_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
1235 void
test_ls2012seqInsElectric(void)1236 test_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
1282 void
test_ls2012seqInsDumb(void)1283 test_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
1335 void
test_lsEmptyTableDumb(void)1336 test_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
1364 void
test_lsEmptyTableElectric(void)1365 test_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