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