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