1 /*
2 * libzvbi -- PDC functions unit test
3 *
4 * Copyright (C) 2008 Michael H. Schimek
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
19 * MA 02110-1301, USA.
20 */
21
22 /* $Id: test-pdc.cc,v 1.2 2009/03/23 01:30:45 mschimek Exp $ */
23
24 #undef NDEBUG
25
26 #include <errno.h>
27 #include "src/pdc.h"
28 #include "src/misc.h" /* mktime(), timegm() */
29 #include "test-pdc.h"
30
31 #if 0 /* for debugging */
32
33 static void
34 print_time (time_t time)
35 {
36 char buffer[80];
37 struct tm tm;
38
39 printf ("%ld ", (long) time);
40
41 memset (&tm, 0, sizeof (tm));
42 localtime_r (&time, &tm);
43 strftime (buffer, sizeof (buffer),
44 "%Y-%m-%d %H:%M:%S %Z = ", &tm);
45 fputs (buffer, stdout);
46
47 memset (&tm, 0, sizeof (tm));
48 gmtime_r (&time, &tm);
49 strftime (buffer, sizeof (buffer),
50 "%Y-%m-%d %H:%M:%S UTC", &tm);
51 puts (buffer);
52 }
53
54 #endif /* 0 */
55
56 static const vbi_pil
57 valid_dates [] = {
58 VBI_PIL (1, 1, 0, 0),
59 VBI_PIL (1, 1, 1, 0),
60 VBI_PIL (1, 1, 23, 0),
61 VBI_PIL (1, 1, 0, 1),
62 VBI_PIL (1, 1, 0, 59),
63 VBI_PIL (1, 31, 0, 0),
64 VBI_PIL (3, 31, 0, 0),
65 VBI_PIL (4, 30, 0, 0),
66 VBI_PIL (5, 31, 0, 0),
67 VBI_PIL (6, 30, 0, 0),
68 VBI_PIL (7, 31, 0, 0),
69 VBI_PIL (8, 31, 0, 0),
70 VBI_PIL (9, 30, 0, 0),
71 VBI_PIL (10, 31, 0, 0),
72 VBI_PIL (11, 30, 0, 0),
73 VBI_PIL (12, 1, 0, 0),
74 VBI_PIL (12, 31, 0, 0),
75 };
76
77 static const vbi_pil
78 invalid_dates [] = {
79 0,
80 VBI_PIL (0, 1, 0, 0),
81 VBI_PIL (1, 0, 0, 0),
82 VBI_PIL (1, 1, 24, 0),
83 VBI_PIL (1, 1, 31, 0),
84 VBI_PIL (1, 1, 0, 60),
85 VBI_PIL (1, 1, 0, 63),
86 VBI_PIL (2, 30, 0, 0),
87 VBI_PIL (2, 31, 0, 0),
88 VBI_PIL (4, 31, 0, 0),
89 VBI_PIL (6, 31, 0, 0),
90 VBI_PIL (9, 31, 0, 0),
91 VBI_PIL (11, 31, 0, 0),
92 VBI_PIL (13, 1, 0, 0),
93 VBI_PIL (15, 1, 0, 0),
94 VBI_PIL_TIMER_CONTROL,
95 VBI_PIL_INHIBIT_TERMINATE,
96 VBI_PIL_INTERRUPTION,
97 VBI_PIL_CONTINUE,
98 VBI_PIL_NSPV,
99 VBI_PIL_END,
100 };
101
102 /* EN 300 231 Annex F. */
103 static const vbi_pil
104 normal_dates [] = {
105 VBI_PIL (1, 1, 24, 0),
106 VBI_PIL (1, 1, 31, 0),
107 VBI_PIL (1, 1, 0, 60),
108 VBI_PIL (1, 1, 0, 63),
109 /* plus all valid_dates[] */
110 };
111
112 /* EN 300 231 Annex F. */
113 static const vbi_pil
114 unallocated_dates [] = {
115 0,
116 VBI_PIL (0, 1, 0, 0),
117 VBI_PIL (15, 0, 0, 0),
118 VBI_PIL (15, 0, 0, 63),
119 VBI_PIL (15, 0, 27, 63),
120 VBI_PIL (15, 0, 31, 0),
121 VBI_PIL (15, 0, 31, 62),
122 VBI_PIL (15, 31, 0, 0),
123 };
124
125 /* EN 300 231 Annex F. */
126 static const vbi_pil
127 indefinite_dates [] = {
128 VBI_PIL (1, 0, 0, 0),
129 VBI_PIL (2, 30, 0, 0),
130 VBI_PIL (2, 31, 0, 0),
131 VBI_PIL (4, 31, 0, 0),
132 VBI_PIL (6, 31, 0, 0),
133 VBI_PIL (9, 31, 0, 0),
134 VBI_PIL (11, 31, 0, 0),
135 VBI_PIL (13, 1, 0, 0),
136 VBI_PIL (14, 1, 0, 0),
137 VBI_PIL (14, 31, 31, 63),
138 VBI_PIL_TIMER_CONTROL,
139 VBI_PIL_INHIBIT_TERMINATE,
140 VBI_PIL_INTERRUPTION,
141 VBI_PIL_CONTINUE,
142 };
143
144 static void
assert_errno(int exp_errno)145 assert_errno (int exp_errno)
146 {
147 /* XXX later */
148 exp_errno = exp_errno;
149 }
150
151 static void
assert_pil_from_string(vbi_pil * pil,const char ** s,vbi_bool exp_success=TRUE)152 assert_pil_from_string (vbi_pil * pil,
153 const char ** s,
154 vbi_bool exp_success = TRUE)
155 {
156 const char *s1;
157 vbi_bool success;
158
159 s1 = *s;
160 *pil = 12345;
161
162 success = _vbi_pil_from_string (pil, s);
163 assert (exp_success == success);
164 if (!exp_success) {
165 assert (s1 == *s);
166 assert (12345 == *pil);
167 }
168 }
169
170 static void
test_pil_from_string(void)171 test_pil_from_string (void)
172 {
173 static const struct {
174 const char * name;
175 vbi_pil pil;
176 } good_pils [] = {
177 { "cont", VBI_PIL_CONTINUE },
178 { "continue", VBI_PIL_CONTINUE },
179 { "cOnTiNuE", VBI_PIL_CONTINUE },
180 { "end", VBI_PIL_END },
181 { "END", VBI_PIL_END },
182 { "inhibit", VBI_PIL_INHIBIT_TERMINATE },
183 { "int", VBI_PIL_INTERRUPTION },
184 { "interruption", VBI_PIL_INTERRUPTION },
185 { "nspv", VBI_PIL_NSPV },
186 { "rit", VBI_PIL_INHIBIT_TERMINATE },
187 { "terminate", VBI_PIL_INHIBIT_TERMINATE },
188 { "tc", VBI_PIL_TIMER_CONTROL },
189 { "timer", VBI_PIL_TIMER_CONTROL },
190 { " \t\n timer", VBI_PIL_TIMER_CONTROL },
191 { "00000000", VBI_PIL (0, 0, 0, 0) },
192 { "15000000", VBI_PIL (15, 0, 0, 0) },
193 { "00310000", VBI_PIL (0, 31, 0, 0) },
194 { "00003100", VBI_PIL (0, 0, 31, 0) },
195 { "00000063", VBI_PIL (0, 0, 0, 63) },
196 { "\n \t 11-12T13:14", VBI_PIL (11, 12, 13, 14) },
197 { "1112", VBI_PIL (0, 0, 11, 12) },
198 { "11:12", VBI_PIL (0, 0, 11, 12) },
199 { "11-12T13:14", VBI_PIL (11, 12, 13, 14) },
200 { "1112T13:14", VBI_PIL (11, 12, 13, 14) },
201 { "111213:14", VBI_PIL (11, 12, 13, 14) },
202 { "1112T1314", VBI_PIL (11, 12, 13, 14) },
203 { "11121314", VBI_PIL (11, 12, 13, 14) },
204 { "11-1213:14", VBI_PIL (11, 12, 13, 14) },
205 { "11-121314", VBI_PIL (11, 12, 13, 14) },
206 { "11-12T1314", VBI_PIL (11, 12, 13, 14) }
207 };
208 static const struct {
209 const char * name;
210 vbi_pil pil;
211 int c;
212 } trailing_garbage [] = {
213 { "int foo", VBI_PIL_INTERRUPTION, ' ' },
214 { "int-foo", VBI_PIL_INTERRUPTION, '-' },
215 { "int\n ", VBI_PIL_INTERRUPTION, '\n' },
216 { "int\t\n", VBI_PIL_INTERRUPTION, '\t' },
217 { "00-00T00:00 ", VBI_PIL (0, 0, 0, 0), ' ' },
218 { "00-00T00:00a", VBI_PIL (0, 0, 0, 0), 'a' },
219 { "00000000:00", VBI_PIL (0, 0, 0, 0), ':' },
220 { "01-02T03:04:00", VBI_PIL (1, 2, 3, 4), ':' },
221 { "1413:2016", VBI_PIL (0, 0, 14, 13), ':' },
222 { "14:132016", VBI_PIL (0, 0, 14, 13), '2' },
223 { "1413+2016", VBI_PIL (0, 0, 14, 13), '+' },
224 { "141320167", VBI_PIL (14, 13, 20, 16), '7' },
225 { "2004-01-01T01:01", VBI_PIL (0, 0, 20, 4), '-' }
226 };
227 static const char *bad_pils [] = {
228 "c",
229 "intc",
230 "endfish",
231 "tc2",
232 "T",
233 "8nspv",
234 "0",
235 "1",
236 "11",
237 "-11",
238 "+11",
239 "111",
240 "11-11",
241 "1111T",
242 "11T11",
243 "1-111",
244 "111:1",
245 "1-1T1:1",
246 "11111",
247 "11-111",
248 "11-1111",
249 "111111",
250 "111111",
251 "1111111",
252 "11-1111",
253 "11-11111",
254 "111111",
255 "1111111",
256 "11-11 11:11",
257 "11-11t11:11",
258 "11--111111",
259 "11+111111",
260 "11T+111111",
261 "11T-111111",
262 "111111T11",
263 "111111-11",
264 "200401010101",
265 "16000000",
266 "99000000",
267 "00320000",
268 "00990000",
269 "00003200",
270 "00009900",
271 "00000064",
272 "00000099"
273 };
274 vbi_pil p;
275 const char *s;
276 unsigned int i;
277
278 for (i = 0; i < N_ELEMENTS (good_pils); ++i) {
279 s = good_pils[i].name;
280 assert_pil_from_string (&p, &s);
281 assert (p == good_pils[i].pil);
282 assert (0 == *s);
283 }
284
285 for (i = 0; i < N_ELEMENTS (trailing_garbage); ++i) {
286 s = trailing_garbage[i].name;
287 assert_pil_from_string (&p, &s);
288 assert (p == trailing_garbage[i].pil);
289 assert (*s == trailing_garbage[i].c);
290 }
291
292 for (i = 0; i < N_ELEMENTS (bad_pils); ++i) {
293 s = bad_pils[i];
294 assert_pil_from_string (&p, &s, FALSE);
295 }
296 }
297
298 static void
assert_pty_validity_window(time_t * begin,time_t * end,time_t start,const char * tz,vbi_bool exp_success=TRUE,int exp_errno=0,time_t exp_begin=ANY_TIME,time_t exp_end=ANY_TIME)299 assert_pty_validity_window (time_t * begin,
300 time_t * end,
301 time_t start,
302 const char * tz,
303 vbi_bool exp_success = TRUE,
304 int exp_errno = 0,
305 time_t exp_begin = ANY_TIME,
306 time_t exp_end = ANY_TIME)
307 {
308 vbi_bool success;
309
310 *begin = 123;
311 *end = 456;
312
313 success = vbi_pty_validity_window (begin, end, start, tz);
314 assert (exp_success == success);
315 if (exp_success) {
316 if (ANY_TIME != exp_begin)
317 assert (exp_begin == *begin);
318 if (ANY_TIME != exp_end)
319 assert (exp_end == *end);
320 } else {
321 assert_errno (exp_errno);
322 assert (123 == *begin);
323 assert (456 == *end);
324 }
325 }
326
327 static void
assert_pty_validity_window(time_t start,const char * tz,vbi_bool exp_success=TRUE,int exp_errno=0,time_t exp_begin=ANY_TIME,time_t exp_end=ANY_TIME)328 assert_pty_validity_window (time_t start,
329 const char * tz,
330 vbi_bool exp_success = TRUE,
331 int exp_errno = 0,
332 time_t exp_begin = ANY_TIME,
333 time_t exp_end = ANY_TIME)
334 {
335 time_t begin1, end1;
336
337 assert_pty_validity_window (&begin1, &end1, start, tz,
338 exp_success, exp_errno,
339 exp_begin, exp_end);
340 }
341
342 static void
test_pty_validity_window(void)343 test_pty_validity_window (void)
344 {
345 time_t t;
346
347 assert_pty_validity_window ((time_t) -1, "UTC");
348 assert_pty_validity_window ((time_t) -1, "CET");
349
350 /* GNU libc setenv() doesn't seem to care. "" may be a
351 shorthand for UTC. */
352 if (0) {
353 t = ztime ("20010101T000000");
354 assert_pty_validity_window (t, "", FALSE, EINVAL);
355 assert_pty_validity_window (t, "CET=", FALSE, EINVAL);
356 }
357
358 if (TIME_MIN >= 0) {
359 /* 'begin' and 'end' cannot be smaller than 'time'
360 (unless there was a negative DST offset). */
361 assert_pty_validity_window (TIME_MIN, "UTC",
362 TRUE, 0, TIME_MIN);
363 assert_pty_validity_window (TIME_MIN, "CET",
364 TRUE, 0, TIME_MIN);
365 }
366
367 if (TIME_MAX <= 0x7FFFFFFF) {
368 t = TIME_MAX - 30 * 24 * 60 * 60;
369 assert_pty_validity_window (t, "UTC", TRUE, 0, t);
370 assert_pty_validity_window (t, "CET", TRUE, 0, t);
371 t = TIME_MAX - 26 * 24 * 60 * 60;
372 assert_pty_validity_window (t, "UTC", FALSE, EOVERFLOW);
373 assert_pty_validity_window (t, "CET", FALSE, EOVERFLOW);
374 assert_pty_validity_window (TIME_MAX, "UTC",
375 FALSE, EOVERFLOW);
376 assert_pty_validity_window (TIME_MAX, "CET",
377 FALSE, EOVERFLOW);
378 }
379
380 t = ztime ("20010101T000000");
381 assert_pty_validity_window (t, "UTC", TRUE, 0, t,
382 ztime ("20010130T040000"));
383 t = ztime ("20010415T111111");
384 assert_pty_validity_window (t, "UTC", TRUE, 0, t,
385 ztime ("20010514T040000"));
386 t = ztime ("20010630T222222");
387 assert_pty_validity_window (t, "UTC", TRUE, 0, t,
388 ztime ("20010729T040000"));
389 t = ztime ("20010701T031415");
390 assert_pty_validity_window (t, "UTC", TRUE, 0, t,
391 ztime ("20010730T040000"));
392 t = ztime ("20010915T150901");
393 assert_pty_validity_window (t, "UTC", TRUE, 0, t,
394 ztime ("20011014T040000"));
395 t = ztime ("20011231T235959");
396 assert_pty_validity_window (t, "UTC", TRUE, 0, t,
397 ztime ("20020129T040000"));
398
399 /* Regular year. */
400 t = ztime ("20020131T000000");
401 assert_pty_validity_window (t, "UTC", TRUE, 0, t,
402 ztime ("20020301T040000"));
403 /* Leap year. */
404 t = ztime ("20040131T000000");
405 assert_pty_validity_window (t, "UTC", TRUE, 0, t,
406 ztime ("20040229T040000"));
407 t = ztime ("20040229T000000");
408 assert_pty_validity_window (t, "UTC", TRUE, 0, t,
409 ztime ("20040329T040000"));
410
411 /* 2004-03-28 01:00 UTC: London local time changes
412 from 01:00 GMT to 02:00 BST. */
413
414 /* Validity window entirely in GMT zone. */
415 t = ztime ("20040227T235959");
416 assert_pty_validity_window (t, "Europe/London", TRUE, 0, t,
417 ztime ("20040327T040000"));
418 /* Validity window begins in GMT zone, ends in BST zone. */
419 t = ztime ("20040228T000000");
420 assert_pty_validity_window (t, "Europe/London", TRUE, 0, t,
421 ztime ("20040328T030000"));
422 t = ztime ("20040328T010000");
423 assert_pty_validity_window (t, "Europe/London", TRUE, 0, t,
424 ztime ("20040426T030000"));
425 t = ztime ("20040328T020000");
426 assert_pty_validity_window (t, "Europe/London", TRUE, 0, t,
427 ztime ("20040426T030000"));
428 /* Validity window entirely in BST zone. */
429 t = ztime ("20040329T000000");
430 assert_pty_validity_window (t, "Europe/London", TRUE, 0, t,
431 ztime ("20040427T030000"));
432
433 /* 2004-10-31 01:00 UTC: London local time changes
434 from 02:00 BST to 01:00 GMT. */
435
436 /* Validity window entirely in BST zone. */
437 t = ztime ("20041001T225959"); /* = 2004-10-01 23:59:59 BST */
438 assert_pty_validity_window (t, "Europe/London", TRUE, 0, t,
439 ztime ("20041030T030000"));
440 t = ztime ("20041001T235959"); /* = 2004-10-02 00:59:59 BST */
441 assert_pty_validity_window (t, "Europe/London", TRUE, 0, t,
442 ztime ("20041031T040000"));
443 /* Validity window begins in BST zone, ends in GMT zone. */
444 t = ztime ("20041002T00000");
445 assert_pty_validity_window (t, "Europe/London", TRUE, 0, t,
446 ztime ("20041031T040000"));
447 t = ztime ("20041031T01000");
448 assert_pty_validity_window (t, "Europe/London", TRUE, 0, t,
449 ztime ("20041129T040000"));
450 t = ztime ("20041031T02000");
451 assert_pty_validity_window (t, "Europe/London", TRUE, 0, t,
452 ztime ("20041129T040000"));
453 /* Validity window entirely in GMT zone. */
454 t = ztime ("20041101T000000");
455 assert_pty_validity_window (t, "Europe/London", TRUE, 0, t,
456 ztime ("20041130T040000"));
457 }
458
459 static void
assert_pil_validity_window(time_t * begin,time_t * end,vbi_pil pil,time_t start,const char * tz,vbi_bool exp_success=TRUE,int exp_errno=0,time_t exp_begin=ANY_TIME,time_t exp_end=ANY_TIME)460 assert_pil_validity_window (time_t * begin,
461 time_t * end,
462 vbi_pil pil,
463 time_t start,
464 const char * tz,
465 vbi_bool exp_success = TRUE,
466 int exp_errno = 0,
467 time_t exp_begin = ANY_TIME,
468 time_t exp_end = ANY_TIME)
469 {
470 time_t begin2, end2;
471 vbi_bool success;
472 int seconds_east;
473
474 *begin = 123;
475 *end = 456;
476
477 success = vbi_pil_validity_window (begin, end,
478 pil, start, tz);
479 assert (exp_success == success);
480 if (exp_success) {
481 if (ANY_TIME != exp_begin)
482 assert (exp_begin == *begin);
483 if (ANY_TIME != exp_end)
484 assert (exp_end == *end);
485 } else {
486 assert_errno (exp_errno);
487 assert (123 == *begin);
488 assert (456 == *end);
489 }
490
491 if (NULL == tz) {
492 return;
493 } else if (0 == strcmp (tz, "UTC")) {
494 seconds_east = 0;
495 } else if (0 == strcmp (tz, "CET")) {
496 if (VBI_PIL_MONTH (pil) >= 3
497 && VBI_PIL_MONTH (pil) <= 10) {
498 /* GNU libc mktime() changes to CEST if DST is
499 in effect at the given date. Is that
500 expected? */
501 return;
502 } else {
503 seconds_east = 3600;
504 }
505 } else {
506 return;
507 }
508
509 begin2 = 123;
510 end2 = 456;
511
512 success = vbi_pil_lto_validity_window (&begin2, &end2,
513 pil, start, seconds_east);
514 assert (exp_success == success);
515 if (!exp_success)
516 assert_errno (exp_errno);
517 assert (begin2 == *begin);
518 assert (end2 == *end);
519 }
520
521 static void
assert_pil_validity_window(vbi_pil pil,time_t start,const char * tz,vbi_bool exp_success=TRUE,int exp_errno=0,time_t exp_begin=ANY_TIME,time_t exp_end=ANY_TIME)522 assert_pil_validity_window (vbi_pil pil,
523 time_t start,
524 const char * tz,
525 vbi_bool exp_success = TRUE,
526 int exp_errno = 0,
527 time_t exp_begin = ANY_TIME,
528 time_t exp_end = ANY_TIME)
529 {
530 time_t begin1, end1;
531
532 assert_pil_validity_window (&begin1, &end1,
533 pil, start, tz,
534 exp_success, exp_errno,
535 exp_begin, exp_end);
536 }
537
538 static void
test_pil_validity_window(void)539 test_pil_validity_window (void)
540 {
541 struct tm tm_min, tm_max;
542 vbi_pil p, p1;
543 time_t t, t1;
544 time_t begin, end;
545 time_t begin2, end2;
546 unsigned int i;
547
548 p1 = VBI_PIL (1, 1, 0, 0);
549 t1 = ztime ("20010101T000000");
550
551 for (i = 0; i < N_ELEMENTS (valid_dates); ++i) {
552 vbi_pil p = valid_dates[i];
553
554 assert_pil_validity_window (p, t1, "UTC");
555 assert_pil_validity_window (p, t1, "CET");
556 assert_pil_validity_window (p, t1, NULL);
557 }
558
559 for (i = 0; i < N_ELEMENTS (normal_dates); ++i) {
560 vbi_pil p = normal_dates[i];
561
562 assert_pil_validity_window (p, t1, "UTC");
563 assert_pil_validity_window (p, t1, "CET");
564 assert_pil_validity_window (p, t1, NULL);
565 }
566
567 for (i = 0; i < N_ELEMENTS (valid_dates); ++i) {
568 vbi_pil p = valid_dates[i];
569 int j;
570
571 for (j = -13 * 3600; j <= +13 * 3600; j += 3744) {
572 char tz[16];
573 time_t begin2, end2;
574
575 snprintf (tz, sizeof (tz), "UTC%c%02u:%02u:%02u",
576 (j < 0) ? '+' : '-',
577 abs (j) / 3600,
578 abs (j) / 60 % 60,
579 abs (j) % 60);
580 assert (TRUE == vbi_pil_validity_window
581 (&begin, &end, p, t1, tz));
582 assert (TRUE == vbi_pil_lto_validity_window
583 (&begin2, &end2, p, t1, j));
584 assert (begin == begin2);
585 assert (end == end2);
586 }
587 }
588
589 for (i = 0; i < N_ELEMENTS (unallocated_dates); ++i) {
590 vbi_pil p = unallocated_dates[i];
591
592 assert_pil_validity_window (p, t1, "UTC", FALSE, EINVAL);
593 assert_pil_validity_window (p, t1, "CET", FALSE, EINVAL);
594 assert_pil_validity_window (p, t1, NULL, FALSE, EINVAL);
595 }
596
597 for (i = 0; i < N_ELEMENTS (indefinite_dates); ++i) {
598 vbi_pil p = indefinite_dates[i];
599
600 assert_pil_validity_window (p, t1, "UTC", TRUE, 0,
601 TIME_MIN, TIME_MAX);
602 assert_pil_validity_window (p, t1, "CET", TRUE, 0,
603 TIME_MIN, TIME_MAX);
604 assert_pil_validity_window (p, t1, NULL, TRUE, 0,
605 TIME_MIN, TIME_MAX);
606 }
607
608 /* Invalid day in year 2001, therefore indefinite time window. */
609 assert_pil_validity_window (VBI_PIL (2, 29, 12, 0), t1, "UTC",
610 TRUE, 0, TIME_MIN, TIME_MAX);
611 assert_pil_validity_window (VBI_PIL (2, 29, 12, 0), t1, "CET",
612 TRUE, 0, TIME_MIN, TIME_MAX);
613 /* Valid day in year 2004. */
614 assert_pil_validity_window (VBI_PIL (2, 29, 12, 0),
615 ztime ("20040101T000000"), "UTC");
616
617 assert_pil_validity_window (p1, (time_t) -1, "UTC");
618 assert_pil_validity_window (p1, (time_t) -1, "CET");
619
620 /* GNU libc setenv() doesn't seem to care. "" may be a shorthand
621 for UTC. */
622 if (0) {
623 assert_pil_validity_window (p1, t1, "", FALSE, EINVAL);
624 assert_pil_validity_window (p1, t1, "CET=", FALSE, EINVAL);
625 }
626
627 if (TIME_MIN >= 0) {
628 t = TIME_MIN;
629 assert (NULL != gmtime_r (&t, &tm_min));
630 assert (t == timegm (&tm_min));
631 p = VBI_PIL (tm_min.tm_mon + 1, tm_min.tm_mday,
632 tm_min.tm_hour, /* minute */ 59),
633 assert_pil_validity_window (p, TIME_MIN, "UTC",
634 FALSE, EOVERFLOW);
635 }
636
637 if (TIME_MAX <= 0x7FFFFFFF) {
638 t = TIME_MAX;
639 assert (NULL != gmtime_r (&t, &tm_max));
640 assert (t == timegm (&tm_max));
641 p = VBI_PIL (tm_max.tm_mon + 1, tm_max.tm_mday,
642 tm_max.tm_hour, 0),
643 assert_pil_validity_window (p, TIME_MAX, "UTC",
644 FALSE, EOVERFLOW);
645 }
646
647 t = ztime ("20010101T000000");
648 assert_pil_validity_window (VBI_PIL (6, 30, 23, 59), t,
649 "UTC", TRUE, 0,
650 ztime ("20010630T000000"),
651 ztime ("20010701T040000"));
652 assert_pil_validity_window (VBI_PIL (7, 1, 0, 0), t,
653 "UTC", TRUE, 0,
654 ztime ("20000630T200000"),
655 ztime ("20000702T040000"));
656 t = ztime ("20010415T000000");
657 assert_pil_validity_window (VBI_PIL (7, 1, 0, 0), t,
658 "UTC", TRUE, 0,
659 ztime ("20010630T200000"),
660 ztime ("20010702T040000"));
661 t = ztime ("20010630T000000");
662 assert_pil_validity_window (VBI_PIL (7, 1, 23, 59), t,
663 "UTC", TRUE, 0,
664 ztime ("20010701T000000"),
665 ztime ("20010702T040000"));
666 assert_pil_validity_window (VBI_PIL (12, 31, 23, 59), t,
667 "UTC", TRUE, 0,
668 ztime ("20001231T000000"),
669 ztime ("20010101T040000"));
670 assert_pil_validity_window (VBI_PIL (1, 1, 0, 0), t,
671 "UTC", TRUE, 0,
672 ztime ("20001231T200000"),
673 ztime ("20010102T040000"));
674 t = ztime ("20010701T000000");
675 assert_pil_validity_window (VBI_PIL (1, 1, 0, 0), t,
676 "UTC", TRUE, 0,
677 ztime ("20001231T200000"),
678 ztime ("20010102T040000"));
679 assert_pil_validity_window (VBI_PIL (12, 31, 23, 59), t,
680 "UTC", TRUE, 0,
681 ztime ("20011231T000000"),
682 ztime ("20020101T040000"));
683 t = ztime ("20010915T000000");
684 assert_pil_validity_window (VBI_PIL (1, 1, 0, 0), t,
685 "UTC", TRUE, 0,
686 ztime ("20011231T200000"),
687 ztime ("20020102T040000"));
688 t = ztime ("20011231T000000");
689 assert_pil_validity_window (VBI_PIL (1, 1, 0, 0), t,
690 "UTC", TRUE, 0,
691 ztime ("20011231T200000"),
692 ztime ("20020102T040000"));
693 assert_pil_validity_window (VBI_PIL (6, 30, 23, 59), t,
694 "UTC", TRUE, 0,
695 ztime ("20010630T000000"),
696 ztime ("20010701T040000"));
697 assert_pil_validity_window (VBI_PIL (7, 1, 0, 0), t,
698 "UTC", TRUE, 0,
699 ztime ("20010630T200000"),
700 ztime ("20010702T040000"));
701
702 /* 2004-03-28 01:00 UTC: London local time changes
703 from 01:00 GMT to 02:00 BST. */
704 t = ztime ("20040301T000000");
705
706 /* Validity window entirely in GMT zone. */
707 assert_pil_validity_window (VBI_PIL (3, 26, 23, 59), t,
708 "Europe/London", TRUE, 0,
709 ztime ("20040326T000000"),
710 ztime ("20040327T040000"));
711 /* Validity window begins in GMT zone, ends in BST zone. */
712 assert_pil_validity_window (VBI_PIL (3, 27, 0, 0), t,
713 "Europe/London", TRUE, 0,
714 ztime ("20040326T200000"),
715 ztime ("20040328T030000"));
716 assert_pil_validity_window (VBI_PIL (3, 27, 23, 59), t,
717 "Europe/London", TRUE, 0,
718 ztime ("20040327T000000"),
719 ztime ("20040328T030000"));
720 assert_pil_validity_window (VBI_PIL (3, 28, 0, 0), t,
721 "Europe/London", TRUE, 0,
722 ztime ("20040327T200000"),
723 ztime ("20040329T030000"));
724 assert_pil_validity_window (VBI_PIL (3, 28, 1, 0), t,
725 "Europe/London", TRUE, 0,
726 ztime ("20040327T200000"),
727 ztime ("20040329T030000"));
728 assert_pil_validity_window (VBI_PIL (3, 28, 2, 0), t,
729 "Europe/London", TRUE, 0,
730 ztime ("20040327T200000"),
731 ztime ("20040329T030000"));
732 assert_pil_validity_window (VBI_PIL (3, 28, 3, 59), t,
733 "Europe/London", TRUE, 0,
734 ztime ("20040327T200000"),
735 ztime ("20040329T030000"));
736 /* Between 04:00-23:59 local time the validity window begins
737 at 00:00 local time of the same day, which is still 00:00
738 UTC. */
739 assert_pil_validity_window (VBI_PIL (3, 28, 4, 0), t,
740 "Europe/London", TRUE, 0,
741 ztime ("20040328T000000"),
742 ztime ("20040329T030000"));
743 /* Validity window entirely in BST zone. */
744 assert_pil_validity_window (VBI_PIL (3, 29, 0, 0), t,
745 "Europe/London", TRUE, 0,
746 ztime ("20040328T190000"),
747 ztime ("20040330T030000"));
748
749 /* 2004-10-31 01:00 UTC: London local time changes
750 from 02:00 BST to 01:00 GMT. */
751 t = ztime ("20041001T000000");
752
753 /* Validity window entirely in BST zone. */
754 assert_pil_validity_window (VBI_PIL (10, 29, 0, 0), t,
755 "Europe/London", TRUE, 0,
756 ztime ("20041028T190000"),
757 ztime ("20041030T030000"));
758 assert_pil_validity_window (VBI_PIL (10, 29, 23, 59), t,
759 "Europe/London", TRUE, 0,
760 ztime ("20041028T230000"),
761 ztime ("20041030T030000"));
762 /* Validity window begins in BST zone, ends in GMT zone. */
763 assert_pil_validity_window (VBI_PIL (10, 30, 0, 0), t,
764 "Europe/London", TRUE, 0,
765 ztime ("20041029T190000"),
766 ztime ("20041031T040000"));
767 assert_pil_validity_window (VBI_PIL (10, 30, 23, 59), t,
768 "Europe/London", TRUE, 0,
769 ztime ("20041029T230000"),
770 ztime ("20041031T040000"));
771 assert_pil_validity_window (VBI_PIL (10, 31, 0, 0), t,
772 "Europe/London", TRUE, 0,
773 ztime ("20041030T190000"),
774 ztime ("20041101T040000"));
775 assert_pil_validity_window (VBI_PIL (10, 31, 1, 0), t,
776 "Europe/London", TRUE, 0,
777 ztime ("20041030T190000"),
778 ztime ("20041101T040000"));
779 assert_pil_validity_window (VBI_PIL (10, 31, 2, 0), t,
780 "Europe/London", TRUE, 0,
781 ztime ("20041030T190000"),
782 ztime ("20041101T040000"));
783 assert_pil_validity_window (VBI_PIL (10, 31, 3, 59), t,
784 "Europe/London", TRUE, 0,
785 ztime ("20041030T190000"),
786 ztime ("20041101T040000"));
787 /* Between 04:00-23:59 local time the validity window begins
788 at 00:00 local time of the same day, which is still 23:00
789 UTC. */
790 assert_pil_validity_window (VBI_PIL (10, 31, 4, 0), t,
791 "Europe/London", TRUE, 0,
792 ztime ("20041030T230000"),
793 ztime ("20041101T040000"));
794 /* Validity window entirely in GMT zone. */
795 assert_pil_validity_window (VBI_PIL (11, 1, 0, 0), t,
796 "Europe/London", TRUE, 0,
797 ztime ("20041031T200000"),
798 ztime ("20041102T040000"));
799
800 assert (TRUE == vbi_pty_validity_window
801 (&begin, &end, t1, "UTC"));
802 assert (begin == t1);
803 assert (TRUE == vbi_pil_validity_window
804 (&begin2, &end2, VBI_PIL_NSPV, t1, "UTC"));
805 assert (begin2 == begin);
806 assert (end2 == end);
807 assert (TRUE == vbi_pil_lto_validity_window
808 (&begin2, &end2, VBI_PIL_NSPV, t1, 0));
809 assert (begin2 == begin);
810 assert (end2 == end);
811 /* 'pil' is assumed to be a time in the UTC + 'seconds_east'
812 zone, but seconds_east does not apply if pil is
813 NSPV. Instead '*begin' is defined only by 'start' here,
814 which is already given in UTC. vbi_pty_validity_window()
815 *may* use 'tz' to correct the validity window for DST, but
816 that is impossible with seconds_east. */
817 assert (TRUE == vbi_pil_lto_validity_window
818 (&begin2, &end2, VBI_PIL_NSPV, t1, 12345));
819 assert (begin2 == begin);
820 assert (end2 == end);
821
822 assert (TRUE == vbi_pty_validity_window
823 (&begin, &end, t1, "UTC+2"));
824 assert (TRUE == vbi_pil_validity_window
825 (&begin2, &end2, VBI_PIL_NSPV, t1, "UTC+2"));
826 assert (begin2 == begin);
827 assert (end2 == end);
828 }
829
830 static void
assert_pil_to_time(vbi_pil pil,time_t start,const char * tz,time_t exp_result=ANY_TIME,int exp_errno=0)831 assert_pil_to_time (vbi_pil pil,
832 time_t start,
833 const char * tz,
834 time_t exp_result = ANY_TIME,
835 int exp_errno = 0)
836 {
837 time_t result;
838 int seconds_east;
839
840 result = vbi_pil_to_time (pil, start, tz);
841 if (ANY_TIME == exp_result) {
842 assert ((time_t) -1 != result);
843 } else if ((time_t) -1 == exp_result) {
844 assert_errno (exp_errno);
845 }
846
847 if (NULL == tz) {
848 return;
849 } else if (0 == strcmp (tz, "UTC")) {
850 seconds_east = 0;
851 } else if (0 == strcmp (tz, "CET")) {
852 if (VBI_PIL_MONTH (pil) >= 3
853 && VBI_PIL_MONTH (pil) <= 10) {
854 /* GNU libc mktime() changes to CEST if DST is
855 in effect at the given date. Is that
856 expected? */
857 return;
858 } else {
859 seconds_east = 3600;
860 }
861 } else {
862 return;
863 }
864
865 result = vbi_pil_lto_to_time (pil, start, seconds_east);
866 if (ANY_TIME == exp_result) {
867 assert ((time_t) -1 != result);
868 } else if ((time_t) -1 == exp_result) {
869 assert_errno (exp_errno);
870 }
871 }
872
873 static void
assert_pil_to_time(vbi_pil pil,time_t start,unsigned int exp_year)874 assert_pil_to_time (vbi_pil pil,
875 time_t start,
876 unsigned int exp_year)
877 {
878 char tz[32];
879
880 snprintf (tz, sizeof (tz), "%04u%02u%02uT%02u%02u00",
881 exp_year,
882 VBI_PIL_MONTH (pil),
883 VBI_PIL_DAY (pil),
884 VBI_PIL_HOUR (pil),
885 VBI_PIL_MINUTE (pil));
886
887 assert_pil_to_time (pil, start, "UTC", ztime (tz));
888 }
889
890 static void
test_pil_to_time(void)891 test_pil_to_time (void)
892 {
893 struct tm tm_min, tm_max;
894 vbi_pil p, p1;
895 time_t t, t1;
896 unsigned int i;
897
898 p1 = VBI_PIL (1, 1, 0, 0);
899 t1 = ztime ("20010101T000000");
900
901 for (i = 0; i < N_ELEMENTS (valid_dates); ++i) {
902 vbi_pil p = valid_dates[i];
903
904 assert_pil_to_time (p, t1, "UTC");
905 assert_pil_to_time (p, t1, "CET");
906 assert_pil_to_time (p, t1, (const char *) NULL);
907 }
908
909 for (i = 0; i < N_ELEMENTS (valid_dates); ++i) {
910 vbi_pil p = valid_dates[i];
911 int j;
912
913 for (j = -13 * 3600; j <= +13 * 3600; j += 3744) {
914 char tz[16];
915
916 snprintf (tz, sizeof (tz), "UTC%c%02u:%02u:%02u",
917 (j < 0) ? '+' : '-',
918 abs (j) / 3600,
919 abs (j) / 60 % 60,
920 abs (j) % 60);
921 t = vbi_pil_to_time (p, t1, tz);
922 assert ((time_t) -1 != t);
923 assert (t == vbi_pil_lto_to_time (p, t1, j));
924 }
925 }
926
927 for (i = 0; i < N_ELEMENTS (invalid_dates); ++i) {
928 vbi_pil p = invalid_dates[i];
929
930 assert_pil_to_time (p, t1, "UTC",
931 /* exp_result */ -1, EINVAL);
932 assert_pil_to_time (p, t1, "CET",
933 /* exp_result */ -1, EINVAL);
934 assert_pil_to_time (p, t1, NULL,
935 /* exp_result */ -1, EINVAL);
936 }
937
938 assert_pil_to_time (VBI_PIL (2, 29, 12, 0), t1, "UTC",
939 -1, EINVAL);
940 assert_pil_to_time (VBI_PIL (2, 29, 12, 0), t1, "CET",
941 -1, EINVAL);
942 assert_pil_to_time (VBI_PIL (2, 29, 12, 0),
943 ztime ("20040101T000000"), "UTC",
944 ztime ("20040229T000000"));
945
946 /* GNU libc setenv() doesn't seem to care. "" may be a shorthand
947 for UTC. */
948 if (0) {
949 assert_pil_to_time (p1, t1, "",
950 /* exp_result */ -1, EINVAL);
951 assert_pil_to_time (p1, t1, "CET=",
952 /* exp_result */ -1, EINVAL);
953 }
954
955 assert_pil_to_time (p1, (time_t) -1, "UTC");
956 assert_pil_to_time (p1, (time_t) -1, "CET");
957
958 if (TIME_MIN >= 0) {
959 t = TIME_MIN;
960
961 assert (NULL != gmtime_r (&t, &tm_min));
962
963 assert (t == timegm (&tm_min));
964 p = VBI_PIL (tm_min.tm_mon + 1, tm_min.tm_mday,
965 tm_min.tm_hour, 59),
966 assert_pil_to_time (p, TIME_MIN, "UTC");
967 assert_pil_to_time (p, TIME_MIN, "UTC-1",
968 /* exp_result */ -1, EOVERFLOW);
969
970 assert ((time_t) -1 == vbi_pil_lto_to_time
971 (p, TIME_MIN, /* seconds_east */ -3600));
972 assert_errno (EOVERFLOW);
973 if (tm_min.tm_hour > 0) {
974 assert_pil_to_time (VBI_PIL (tm_min.tm_mon + 1,
975 tm_min.tm_mday,
976 tm_min.tm_hour - 1,
977 /* minute */ 59),
978 TIME_MIN, "UTC",
979 /* exp_result */ -1,
980 EOVERFLOW);
981 } else if (tm_min.tm_mday > 1) {
982 assert_pil_to_time (VBI_PIL (tm_min.tm_mon + 1,
983 tm_min.tm_mday - 1,
984 tm_min.tm_hour, 59),
985 TIME_MIN, "UTC",
986 /* exp_result */ -1,
987 EOVERFLOW);
988 } else if (tm_min.tm_mon > 0) {
989 assert_pil_to_time (VBI_PIL (tm_min.tm_mon + 1 - 1,
990 tm_min.tm_mday - 1,
991 tm_min.tm_hour, 59),
992 TIME_MIN, "UTC",
993 /* exp_result */ -1,
994 EOVERFLOW);
995 }
996 }
997
998 if (TIME_MAX <= 0x7FFFFFFF) {
999 /* -1 because GNU libc timegm() appears to clamp
1000 against TIME_MAX, which is catched by libzvbi. */
1001 t = TIME_MAX - 1;
1002 assert (NULL != gmtime_r (&t, &tm_max));
1003 assert (t == timegm (&tm_max));
1004 p = VBI_PIL (tm_max.tm_mon + 1, tm_max.tm_mday,
1005 tm_max.tm_hour, 0),
1006 assert_pil_to_time (p, TIME_MAX, "UTC");
1007 assert_pil_to_time (p, TIME_MAX, "UTC+1",
1008 /* exp_result */ -1, EOVERFLOW);
1009
1010 assert ((time_t) -1 == vbi_pil_lto_to_time
1011 (p, TIME_MAX, /* seconds_east */ 3600));
1012 assert_errno (EOVERFLOW);
1013 if (tm_max.tm_hour < 23) {
1014 assert_pil_to_time (VBI_PIL (tm_max.tm_mon + 1,
1015 tm_max.tm_mday,
1016 tm_max.tm_hour + 1,
1017 /* minute */ 0),
1018 TIME_MAX, "UTC",
1019 /* exp_result */ -1,
1020 EOVERFLOW);
1021 } else if (tm_max.tm_mday < 28) {
1022 assert_pil_to_time (VBI_PIL (tm_max.tm_mon + 1,
1023 tm_max.tm_mday + 1,
1024 tm_max.tm_hour, 0),
1025 TIME_MAX, "UTC",
1026 /* exp_result */ -1,
1027 EOVERFLOW);
1028 } else if (tm_max.tm_mon < 11) {
1029 assert_pil_to_time (VBI_PIL (tm_max.tm_mon + 1 + 1,
1030 tm_max.tm_mday + 1,
1031 tm_max.tm_hour, 0),
1032 TIME_MAX, "UTC",
1033 /* exp_result */ -1,
1034 EOVERFLOW);
1035 }
1036 }
1037
1038 t = ztime ("20010101T000000");
1039 assert_pil_to_time (VBI_PIL (1, 1, 0, 0), t, 2001);
1040 assert_pil_to_time (VBI_PIL (6, 30, 23, 59), t, 2001);
1041 assert_pil_to_time (VBI_PIL (7, 1, 0, 0), t, 2000);
1042 assert_pil_to_time (VBI_PIL (12, 31, 23, 59), t, 2000);
1043 t = ztime ("20010415T000000");
1044 assert_pil_to_time (VBI_PIL (1, 1, 0, 0), t, 2001);
1045 assert_pil_to_time (VBI_PIL (6, 30, 23, 59), t, 2001);
1046 assert_pil_to_time (VBI_PIL (7, 1, 0, 0), t, 2001);
1047 assert_pil_to_time (VBI_PIL (12, 31, 23, 59), t, 2000);
1048 t = ztime ("20010630T000000");
1049 assert_pil_to_time (VBI_PIL (1, 1, 0, 0), t, 2001);
1050 assert_pil_to_time (VBI_PIL (6, 30, 23, 59), t, 2001);
1051 assert_pil_to_time (VBI_PIL (7, 1, 0, 0), t, 2001);
1052 assert_pil_to_time (VBI_PIL (12, 31, 23, 59), t, 2000);
1053 t = ztime ("20010701T000000");
1054 assert_pil_to_time (VBI_PIL (1, 1, 0, 0), t, 2001);
1055 assert_pil_to_time (VBI_PIL (6, 30, 23, 59), t, 2001);
1056 assert_pil_to_time (VBI_PIL (7, 1, 0, 0), t, 2001);
1057 assert_pil_to_time (VBI_PIL (12, 31, 23, 59), t, 2001);
1058 t = ztime ("20010915T000000");
1059 assert_pil_to_time (VBI_PIL (1, 1, 0, 0), t, 2002);
1060 assert_pil_to_time (VBI_PIL (6, 30, 23, 59), t, 2001);
1061 assert_pil_to_time (VBI_PIL (7, 1, 0, 0), t, 2001);
1062 assert_pil_to_time (VBI_PIL (12, 31, 23, 59), t, 2001);
1063 t = ztime ("20011231T000000");
1064 assert_pil_to_time (VBI_PIL (1, 1, 0, 0), t, 2002);
1065 assert_pil_to_time (VBI_PIL (6, 30, 23, 59), t, 2001);
1066 assert_pil_to_time (VBI_PIL (7, 1, 0, 0), t, 2001);
1067 assert_pil_to_time (VBI_PIL (12, 31, 23, 59), t, 2001);
1068
1069 /* GMT */
1070 assert (ztime ("20010215T200000")
1071 == vbi_pil_to_time (VBI_PIL (2, 15, 20, 0), t1,
1072 "Europe/London"));
1073 assert (ztime ("20010215T200000")
1074 == vbi_pil_lto_to_time (VBI_PIL (2, 15, 20, 0), t1, 0));
1075 /* CET (UTC + 1h) */
1076 assert (ztime ("20010215T190000")
1077 == vbi_pil_to_time (VBI_PIL (2, 15, 20, 0), t1,
1078 "Europe/Paris"));
1079 assert (ztime ("20010215T190000")
1080 == vbi_pil_lto_to_time (VBI_PIL (2, 15, 20, 0), t1, 3600));
1081 /* CEST (UTC + 2h) */
1082 assert (ztime ("20010715T180000")
1083 == vbi_pil_to_time (VBI_PIL (7, 15, 20, 0),
1084 ztime ("20010701T000000"),
1085 "Europe/Paris"));
1086 /* CET because PIL month 2; year 2001 because 8 - 2 <= 6. */
1087 assert (ztime ("20010215T190000")
1088 == vbi_pil_to_time (VBI_PIL (2, 15, 20, 0),
1089 ztime ("20010831T210000"),
1090 "Europe/Paris"));
1091 /* CET because PIL month 2; year 2002 because 'start' is
1092 already 2001-09-01 01:00 in CEST zone. */
1093 assert (ztime ("20020215T190000")
1094 == vbi_pil_to_time (VBI_PIL (2, 15, 20, 0),
1095 ztime ("20010831T230000"),
1096 "Europe/Paris"));
1097
1098 /* XXX Maybe other DST conventions should be tested:
1099 http://en.wikipedia.org/wiki/Daylight_saving_time_around_the_world
1100 */
1101 }
1102
1103 static void
test_pil_is_valid_date(void)1104 test_pil_is_valid_date (void)
1105 {
1106 unsigned int i;
1107
1108 for (i = 0; i < N_ELEMENTS (valid_dates); ++i) {
1109 assert (vbi_pil_is_valid_date (valid_dates[i]));
1110 }
1111
1112 assert (vbi_pil_is_valid_date (VBI_PIL (2, 29, 0, 0)));
1113
1114 for (i = 0; i < N_ELEMENTS (invalid_dates); ++i) {
1115 assert (!vbi_pil_is_valid_date (invalid_dates[i]));
1116 }
1117
1118 assert (vbi_pil_is_valid_date (VBI_PIL (1, 1, 0, 0) | ~max_pil));
1119 }
1120
1121 int
main(void)1122 main (void)
1123 {
1124 test_pil_is_valid_date ();
1125 test_pil_to_time ();
1126 test_pil_validity_window ();
1127 test_pty_validity_window ();
1128 test_pil_from_string ();
1129
1130 return 0;
1131 }
1132
1133 /*
1134 Local variables:
1135 c-set-style: K&R
1136 c-basic-offset: 8
1137 End:
1138 */
1139