From: beck Date: Sun, 6 Nov 2022 12:57:08 +0000 (+0000) Subject: Add a bunch of regression tests for time conversion. X-Git-Url: http://artulab.com/gitweb/?a=commitdiff_plain;h=2dc6bcb07aa2e8935250f00b19a12a3d296c2db7;p=openbsd Add a bunch of regression tests for time conversion. This regression tests time conversion across various limits, leap seconds, and daylight transistions. gmtime_r, localtime_r, timegm, and mktime are tested against themselves and expected outputs. It requires the "posix" and "right" zoneinfo to be installed on the test running machine in order to access testable time zones. If those are not present the test is skipped successfully with a warning. --- diff --git a/regress/lib/libc/time/time_conversion/Makefile b/regress/lib/libc/time/time_conversion/Makefile new file mode 100644 index 00000000000..fa73d6acc05 --- /dev/null +++ b/regress/lib/libc/time/time_conversion/Makefile @@ -0,0 +1,11 @@ +# $OpenBSD: Makefile,v 1.1 2022/11/06 12:57:08 beck Exp $ + +PROG= timetest +SRCS= timetest.c + +REGRESS_TARGETS=do-timetest + +do-timetest: ${PROG} + ./${PROG} + +.include diff --git a/regress/lib/libc/time/time_conversion/timetest.c b/regress/lib/libc/time/time_conversion/timetest.c new file mode 100644 index 00000000000..825315c4643 --- /dev/null +++ b/regress/lib/libc/time/time_conversion/timetest.c @@ -0,0 +1,1725 @@ +/* $OpenBSD: timetest.c,v 1.1 2022/11/06 12:57:08 beck Exp $ */ + +/* + * Copyright (c) 2022 Bob Beck + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include +#include +#include + +#include +#include +#include +#include + +struct timetest { + char *descr; + char *timezone; + time_t time; + struct tm local_tm; + struct tm gmt_tm; +}; + +static int tm_match(struct tm * tm1, struct tm *tm2) { + if (tm2->tm_year != tm1->tm_year || + tm2->tm_mon != tm1->tm_mon || + tm2->tm_mday != tm1->tm_mday || + tm2->tm_hour != tm1->tm_hour || + tm2->tm_min != tm1->tm_min || + tm2->tm_sec != tm1->tm_sec || + tm2->tm_wday != tm1->tm_wday || + tm2->tm_yday != tm1->tm_yday || + tm2->tm_yday != tm1->tm_yday || + tm2->tm_isdst != tm1->tm_isdst || + tm2->tm_gmtoff != tm1->tm_gmtoff || + strcmp(tm2->tm_zone, tm1->tm_zone) != 0) + return 0; + return 1; +} + +struct timetest timetests[] = { + { + .descr="moon", + .timezone="posix/America/Edmonton", + .time=-16751025, + .local_tm= { + .tm_year=69, + .tm_mon=5, + .tm_mday=20, + .tm_hour=19, + .tm_min=56, + .tm_sec=15, + .tm_wday=5, + .tm_yday=170, + .tm_isdst=0, + .tm_gmtoff=-25200, + .tm_zone="MST" + }, + .gmt_tm= { + .tm_year=69, + .tm_mon=5, + .tm_mday=21, + .tm_hour=2, + .tm_min=56, + .tm_sec=15, + .tm_wday=6, + .tm_yday=171, + .tm_isdst=0, + .tm_gmtoff=0, + .tm_zone="GMT" + }, + }, + { + .descr="moon", + .timezone="right/UTC", + .time=-16751025, + .local_tm= { + .tm_year=69, + .tm_mon=5, + .tm_mday=21, + .tm_hour=2, + .tm_min=56, + .tm_sec=15, + .tm_wday=6, + .tm_yday=171, + .tm_isdst=0, + .tm_gmtoff=0, + .tm_zone="UTC" + }, + .gmt_tm= { + .tm_year=69, + .tm_mon=5, + .tm_mday=21, + .tm_hour=2, + .tm_min=56, + .tm_sec=15, + .tm_wday=6, + .tm_yday=171, + .tm_isdst=0, + .tm_gmtoff=0, + .tm_zone="GMT" + }, + }, + { + .descr="moon", + .timezone="right/America/Edmonton", + .time=-16751025, + .local_tm= { + .tm_year=69, + .tm_mon=5, + .tm_mday=20, + .tm_hour=19, + .tm_min=56, + .tm_sec=15, + .tm_wday=5, + .tm_yday=170, + .tm_isdst=0, + .tm_gmtoff=-25200, + .tm_zone="MST" + }, + .gmt_tm= { + .tm_year=69, + .tm_mon=5, + .tm_mday=21, + .tm_hour=2, + .tm_min=56, + .tm_sec=15, + .tm_wday=6, + .tm_yday=171, + .tm_isdst=0, + .tm_gmtoff=0, + .tm_zone="GMT" + }, + }, + { + .descr="epoch", + .timezone="posix/America/Edmonton", + .time=0, + .local_tm= { + .tm_year=69, + .tm_mon=11, + .tm_mday=31, + .tm_hour=17, + .tm_min=0, + .tm_sec=0, + .tm_wday=3, + .tm_yday=364, + .tm_isdst=0, + .tm_gmtoff=-25200, + .tm_zone="MST" + }, + .gmt_tm= { + .tm_year=70, + .tm_mon=0, + .tm_mday=1, + .tm_hour=0, + .tm_min=0, + .tm_sec=0, + .tm_wday=4, + .tm_yday=0, + .tm_isdst=0, + .tm_gmtoff=0, + .tm_zone="GMT" + }, + }, + { + .descr="epoch", + .timezone="right/UTC", + .time=0, + .local_tm= { + .tm_year=70, + .tm_mon=0, + .tm_mday=1, + .tm_hour=0, + .tm_min=0, + .tm_sec=0, + .tm_wday=4, + .tm_yday=0, + .tm_isdst=0, + .tm_gmtoff=0, + .tm_zone="UTC" + }, + .gmt_tm= { + .tm_year=70, + .tm_mon=0, + .tm_mday=1, + .tm_hour=0, + .tm_min=0, + .tm_sec=0, + .tm_wday=4, + .tm_yday=0, + .tm_isdst=0, + .tm_gmtoff=0, + .tm_zone="GMT" + }, + }, + { + .descr="epoch", + .timezone="right/America/Edmonton", + .time=0, + .local_tm= { + .tm_year=69, + .tm_mon=11, + .tm_mday=31, + .tm_hour=17, + .tm_min=0, + .tm_sec=0, + .tm_wday=3, + .tm_yday=364, + .tm_isdst=0, + .tm_gmtoff=-25200, + .tm_zone="MST" + }, + .gmt_tm= { + .tm_year=70, + .tm_mon=0, + .tm_mday=1, + .tm_hour=0, + .tm_min=0, + .tm_sec=0, + .tm_wday=4, + .tm_yday=0, + .tm_isdst=0, + .tm_gmtoff=0, + .tm_zone="GMT" + }, + }, + { + .descr="epoch - 1", + .timezone="posix/America/Edmonton", + .time=-1, + .local_tm= { + .tm_year=69, + .tm_mon=11, + .tm_mday=31, + .tm_hour=16, + .tm_min=59, + .tm_sec=59, + .tm_wday=3, + .tm_yday=364, + .tm_isdst=0, + .tm_gmtoff=-25200, + .tm_zone="MST" + }, + .gmt_tm= { + .tm_year=69, + .tm_mon=11, + .tm_mday=31, + .tm_hour=23, + .tm_min=59, + .tm_sec=59, + .tm_wday=3, + .tm_yday=364, + .tm_isdst=0, + .tm_gmtoff=0, + .tm_zone="GMT" + }, + }, + { + .descr="epoch - 1", + .timezone="right/UTC", + .time=-1, + .local_tm= { + .tm_year=69, + .tm_mon=11, + .tm_mday=31, + .tm_hour=23, + .tm_min=59, + .tm_sec=59, + .tm_wday=3, + .tm_yday=364, + .tm_isdst=0, + .tm_gmtoff=0, + .tm_zone="UTC" + }, + .gmt_tm= { + .tm_year=69, + .tm_mon=11, + .tm_mday=31, + .tm_hour=23, + .tm_min=59, + .tm_sec=59, + .tm_wday=3, + .tm_yday=364, + .tm_isdst=0, + .tm_gmtoff=0, + .tm_zone="GMT" + }, + }, + { + .descr="epoch - 1", + .timezone="right/America/Edmonton", + .time=-1, + .local_tm= { + .tm_year=69, + .tm_mon=11, + .tm_mday=31, + .tm_hour=16, + .tm_min=59, + .tm_sec=59, + .tm_wday=3, + .tm_yday=364, + .tm_isdst=0, + .tm_gmtoff=-25200, + .tm_zone="MST" + }, + .gmt_tm= { + .tm_year=69, + .tm_mon=11, + .tm_mday=31, + .tm_hour=23, + .tm_min=59, + .tm_sec=59, + .tm_wday=3, + .tm_yday=364, + .tm_isdst=0, + .tm_gmtoff=0, + .tm_zone="GMT" + }, + }, + { + .descr="legacy min", + .timezone="posix/America/Edmonton", + .time=-2147483648, + .local_tm= { + .tm_year=1, + .tm_mon=11, + .tm_mday=13, + .tm_hour=13, + .tm_min=12, + .tm_sec=0, + .tm_wday=5, + .tm_yday=346, + .tm_isdst=0, + .tm_gmtoff=-27232, + .tm_zone="LMT" + }, + .gmt_tm= { + .tm_year=1, + .tm_mon=11, + .tm_mday=13, + .tm_hour=20, + .tm_min=45, + .tm_sec=52, + .tm_wday=5, + .tm_yday=346, + .tm_isdst=0, + .tm_gmtoff=0, + .tm_zone="GMT" + }, + }, + { + .descr="legacy min", + .timezone="right/UTC", + .time=-2147483648, + .local_tm= { + .tm_year=1, + .tm_mon=11, + .tm_mday=13, + .tm_hour=20, + .tm_min=45, + .tm_sec=52, + .tm_wday=5, + .tm_yday=346, + .tm_isdst=0, + .tm_gmtoff=0, + .tm_zone="UTC" + }, + .gmt_tm= { + .tm_year=1, + .tm_mon=11, + .tm_mday=13, + .tm_hour=20, + .tm_min=45, + .tm_sec=52, + .tm_wday=5, + .tm_yday=346, + .tm_isdst=0, + .tm_gmtoff=0, + .tm_zone="GMT" + }, + }, + { + .descr="legacy min - 1", + .timezone="posix/America/Edmonton", + .time=-2147483649, + .local_tm= { + .tm_year=1, + .tm_mon=11, + .tm_mday=13, + .tm_hour=13, + .tm_min=11, + .tm_sec=59, + .tm_wday=5, + .tm_yday=346, + .tm_isdst=0, + .tm_gmtoff=-27232, + .tm_zone="LMT" + }, + .gmt_tm= { + .tm_year=1, + .tm_mon=11, + .tm_mday=13, + .tm_hour=20, + .tm_min=45, + .tm_sec=51, + .tm_wday=5, + .tm_yday=346, + .tm_isdst=0, + .tm_gmtoff=0, + .tm_zone="GMT" + }, + }, + { + .descr="legacy min - 1", + .timezone="right/UTC", + .time=-2147483649, + .local_tm= { + .tm_year=1, + .tm_mon=11, + .tm_mday=13, + .tm_hour=20, + .tm_min=45, + .tm_sec=51, + .tm_wday=5, + .tm_yday=346, + .tm_isdst=0, + .tm_gmtoff=0, + .tm_zone="UTC" + }, + .gmt_tm= { + .tm_year=1, + .tm_mon=11, + .tm_mday=13, + .tm_hour=20, + .tm_min=45, + .tm_sec=51, + .tm_wday=5, + .tm_yday=346, + .tm_isdst=0, + .tm_gmtoff=0, + .tm_zone="GMT" + }, + }, + { + .descr="legacy max", + .timezone="posix/America/Edmonton", + .time=2147483647, + .local_tm= { + .tm_year=138, + .tm_mon=0, + .tm_mday=18, + .tm_hour=20, + .tm_min=14, + .tm_sec=7, + .tm_wday=1, + .tm_yday=17, + .tm_isdst=0, + .tm_gmtoff=-25200, + .tm_zone="MST" + }, + .gmt_tm= { + .tm_year=138, + .tm_mon=0, + .tm_mday=19, + .tm_hour=3, + .tm_min=14, + .tm_sec=7, + .tm_wday=2, + .tm_yday=18, + .tm_isdst=0, + .tm_gmtoff=0, + .tm_zone="GMT" + }, + }, + { + .descr="legacy max", + .timezone="right/UTC", + .time=2147483647, + .local_tm= { + .tm_year=138, + .tm_mon=0, + .tm_mday=19, + .tm_hour=3, + .tm_min=13, + .tm_sec=40, + .tm_wday=2, + .tm_yday=18, + .tm_isdst=0, + .tm_gmtoff=0, + .tm_zone="UTC" + }, + .gmt_tm= { + .tm_year=138, + .tm_mon=0, + .tm_mday=19, + .tm_hour=3, + .tm_min=14, + .tm_sec=7, + .tm_wday=2, + .tm_yday=18, + .tm_isdst=0, + .tm_gmtoff=0, + .tm_zone="GMT" + }, + }, + { + .descr="legacy max + 1", + .timezone="posix/America/Edmonton", + .time=2147483648, + .local_tm= { + .tm_year=138, + .tm_mon=0, + .tm_mday=18, + .tm_hour=20, + .tm_min=14, + .tm_sec=8, + .tm_wday=1, + .tm_yday=17, + .tm_isdst=0, + .tm_gmtoff=-25200, + .tm_zone="MST" + }, + .gmt_tm= { + .tm_year=138, + .tm_mon=0, + .tm_mday=19, + .tm_hour=3, + .tm_min=14, + .tm_sec=8, + .tm_wday=2, + .tm_yday=18, + .tm_isdst=0, + .tm_gmtoff=0, + .tm_zone="GMT" + }, + }, + { + .descr="legacy max + 1", + .timezone="right/UTC", + .time=2147483648, + .local_tm= { + .tm_year=138, + .tm_mon=0, + .tm_mday=19, + .tm_hour=3, + .tm_min=13, + .tm_sec=41, + .tm_wday=2, + .tm_yday=18, + .tm_isdst=0, + .tm_gmtoff=0, + .tm_zone="UTC" + }, + .gmt_tm= { + .tm_year=138, + .tm_mon=0, + .tm_mday=19, + .tm_hour=3, + .tm_min=14, + .tm_sec=8, + .tm_wday=2, + .tm_yday=18, + .tm_isdst=0, + .tm_gmtoff=0, + .tm_zone="GMT" + }, + }, + { + .descr="min", + .timezone="posix/America/Edmonton", + .time=INT64_MIN, + .local_tm= { + .tm_year=0, + .tm_mon=0, + .tm_mday=0, + .tm_hour=0, + .tm_min=0, + .tm_sec=0, + .tm_wday=0, + .tm_yday=0, + .tm_isdst=0, + .tm_gmtoff=0, + .tm_zone="FAILURE" + }, + .gmt_tm= { + .tm_year=0, + .tm_mon=0, + .tm_mday=0, + .tm_hour=0, + .tm_min=0, + .tm_sec=0, + .tm_wday=0, + .tm_yday=0, + .tm_isdst=0, + .tm_gmtoff=0, + .tm_zone="FAILURE" + }, + }, + { + .descr="min", + .timezone="right/UTC", + .time=INT64_MIN, + .local_tm= { + .tm_year=0, + .tm_mon=0, + .tm_mday=0, + .tm_hour=0, + .tm_min=0, + .tm_sec=0, + .tm_wday=0, + .tm_yday=0, + .tm_isdst=0, + .tm_gmtoff=0, + .tm_zone="FAILURE" + }, + .gmt_tm= { + .tm_year=0, + .tm_mon=0, + .tm_mday=0, + .tm_hour=0, + .tm_min=0, + .tm_sec=0, + .tm_wday=0, + .tm_yday=0, + .tm_isdst=0, + .tm_gmtoff=0, + .tm_zone="FAILURE" + }, + }, + { + .descr="max", + .timezone="right/America/Edmonton", + .time=9223372036854775807, + .local_tm= { + .tm_year=0, + .tm_mon=0, + .tm_mday=0, + .tm_hour=0, + .tm_min=0, + .tm_sec=0, + .tm_wday=0, + .tm_yday=0, + .tm_isdst=0, + .tm_gmtoff=0, + .tm_zone="FAILURE" + }, + .gmt_tm= { + .tm_year=0, + .tm_mon=0, + .tm_mday=0, + .tm_hour=0, + .tm_min=0, + .tm_sec=0, + .tm_wday=0, + .tm_yday=0, + .tm_isdst=0, + .tm_gmtoff=0, + .tm_zone="FAILURE" + }, + }, + { + .descr="max", + .timezone="posix/America/Edmonton", + .time=9223372036854775807, + .local_tm= { + .tm_year=0, + .tm_mon=0, + .tm_mday=0, + .tm_hour=0, + .tm_min=0, + .tm_sec=0, + .tm_wday=0, + .tm_yday=0, + .tm_isdst=0, + .tm_gmtoff=0, + .tm_zone="FAILURE" + }, + .gmt_tm= { + .tm_year=0, + .tm_mon=0, + .tm_mday=0, + .tm_hour=0, + .tm_min=0, + .tm_sec=0, + .tm_wday=0, + .tm_yday=0, + .tm_isdst=0, + .tm_gmtoff=0, + .tm_zone="FAILURE" + }, + }, + { + .descr="max", + .timezone="right/UTC", + .time=9223372036854775807, + .local_tm= { + .tm_year=0, + .tm_mon=0, + .tm_mday=0, + .tm_hour=0, + .tm_min=0, + .tm_sec=0, + .tm_wday=0, + .tm_yday=0, + .tm_isdst=0, + .tm_gmtoff=0, + .tm_zone="FAILURE" + }, + .gmt_tm= { + .tm_year=0, + .tm_mon=0, + .tm_mday=0, + .tm_hour=0, + .tm_min=0, + .tm_sec=0, + .tm_wday=0, + .tm_yday=0, + .tm_isdst=0, + .tm_gmtoff=0, + .tm_zone="FAILURE" + }, + }, + { + .descr="min", + .timezone="right/America/Edmonton", + .time=INT64_MIN, + .local_tm= { + .tm_year=0, + .tm_mon=0, + .tm_mday=0, + .tm_hour=0, + .tm_min=0, + .tm_sec=0, + .tm_wday=0, + .tm_yday=0, + .tm_isdst=0, + .tm_gmtoff=0, + .tm_zone="FAILURE" + }, + .gmt_tm= { + .tm_year=0, + .tm_mon=0, + .tm_mday=0, + .tm_hour=0, + .tm_min=0, + .tm_sec=0, + .tm_wday=0, + .tm_yday=0, + .tm_isdst=0, + .tm_gmtoff=0, + .tm_zone="FAILURE" + }, + }, + { + .descr="0000", + .timezone="posix/America/Edmonton", + .time=-62167219200, + .local_tm= { + .tm_year=-1901, + .tm_mon=11, + .tm_mday=31, + .tm_hour=16, + .tm_min=26, + .tm_sec=8, + .tm_wday=5, + .tm_yday=364, + .tm_isdst=0, + .tm_gmtoff=-27232, + .tm_zone="LMT" + }, + .gmt_tm= { + .tm_year=-1900, + .tm_mon=0, + .tm_mday=1, + .tm_hour=0, + .tm_min=0, + .tm_sec=0, + .tm_wday=6, + .tm_yday=0, + .tm_isdst=0, + .tm_gmtoff=0, + .tm_zone="GMT" + }, + }, + { + .descr="0000", + .timezone="right/UTC", + .time=-62167219200, + .local_tm= { + .tm_year=-1900, + .tm_mon=0, + .tm_mday=1, + .tm_hour=0, + .tm_min=0, + .tm_sec=0, + .tm_wday=6, + .tm_yday=0, + .tm_isdst=0, + .tm_gmtoff=0, + .tm_zone="UTC" + }, + .gmt_tm= { + .tm_year=-1900, + .tm_mon=0, + .tm_mday=1, + .tm_hour=0, + .tm_min=0, + .tm_sec=0, + .tm_wday=6, + .tm_yday=0, + .tm_isdst=0, + .tm_gmtoff=0, + .tm_zone="GMT" + }, + }, + { + .descr="0000", + .timezone="right/America/Edmonton", + .time=-62167219200, + .local_tm= { + .tm_year=-1901, + .tm_mon=11, + .tm_mday=31, + .tm_hour=16, + .tm_min=26, + .tm_sec=8, + .tm_wday=5, + .tm_yday=364, + .tm_isdst=0, + .tm_gmtoff=-27232, + .tm_zone="LMT" + }, + .gmt_tm= { + .tm_year=-1900, + .tm_mon=0, + .tm_mday=1, + .tm_hour=0, + .tm_min=0, + .tm_sec=0, + .tm_wday=6, + .tm_yday=0, + .tm_isdst=0, + .tm_gmtoff=0, + .tm_zone="GMT" + }, + }, + { + .descr="9999", + .timezone="posix/America/Edmonton", + .time=253402300799, + .local_tm= { + .tm_year=8099, + .tm_mon=11, + .tm_mday=31, + .tm_hour=16, + .tm_min=59, + .tm_sec=59, + .tm_wday=5, + .tm_yday=364, + .tm_isdst=0, + .tm_gmtoff=-25200, + .tm_zone="MST" + }, + .gmt_tm= { + .tm_year=8099, + .tm_mon=11, + .tm_mday=31, + .tm_hour=23, + .tm_min=59, + .tm_sec=59, + .tm_wday=5, + .tm_yday=364, + .tm_isdst=0, + .tm_gmtoff=0, + .tm_zone="GMT" + }, + }, + { + .descr="9999", + .timezone="right/UTC", + .time=253402300799, + .local_tm= { + .tm_year=8099, + .tm_mon=11, + .tm_mday=31, + .tm_hour=23, + .tm_min=59, + .tm_sec=32, + .tm_wday=5, + .tm_yday=364, + .tm_isdst=0, + .tm_gmtoff=0, + .tm_zone="UTC" + }, + .gmt_tm= { + .tm_year=8099, + .tm_mon=11, + .tm_mday=31, + .tm_hour=23, + .tm_min=59, + .tm_sec=59, + .tm_wday=5, + .tm_yday=364, + .tm_isdst=0, + .tm_gmtoff=0, + .tm_zone="GMT" + }, + }, + { + .descr="9999", + .timezone="right/America/Edmonton", + .time=253402300799, + .local_tm= { + .tm_year=8099, + .tm_mon=11, + .tm_mday=31, + .tm_hour=16, + .tm_min=59, + .tm_sec=32, + .tm_wday=5, + .tm_yday=364, + .tm_isdst=0, + .tm_gmtoff=-25200, + .tm_zone="MST" + }, + .gmt_tm= { + .tm_year=8099, + .tm_mon=11, + .tm_mday=31, + .tm_hour=23, + .tm_min=59, + .tm_sec=59, + .tm_wday=5, + .tm_yday=364, + .tm_isdst=0, + .tm_gmtoff=0, + .tm_zone="GMT" + }, + }, + { + .descr="leap second - 1", + .timezone="posix/America/Edmonton", + .time=1483228825, + .local_tm= { + .tm_year=116, + .tm_mon=11, + .tm_mday=31, + .tm_hour=17, + .tm_min=0, + .tm_sec=25, + .tm_wday=6, + .tm_yday=365, + .tm_isdst=0, + .tm_gmtoff=-25200, + .tm_zone="MST" + }, + .gmt_tm= { + .tm_year=117, + .tm_mon=0, + .tm_mday=1, + .tm_hour=0, + .tm_min=0, + .tm_sec=25, + .tm_wday=0, + .tm_yday=0, + .tm_isdst=0, + .tm_gmtoff=0, + .tm_zone="GMT" + }, + }, + { + .descr="leap second", + .timezone="posix/America/Edmonton", + .time=1483228826, + .local_tm= { + .tm_year=116, + .tm_mon=11, + .tm_mday=31, + .tm_hour=17, + .tm_min=0, + .tm_sec=26, + .tm_wday=6, + .tm_yday=365, + .tm_isdst=0, + .tm_gmtoff=-25200, + .tm_zone="MST" + }, + .gmt_tm= { + .tm_year=117, + .tm_mon=0, + .tm_mday=1, + .tm_hour=0, + .tm_min=0, + .tm_sec=26, + .tm_wday=0, + .tm_yday=0, + .tm_isdst=0, + .tm_gmtoff=0, + .tm_zone="GMT" + }, + }, + { + .descr="leap second + 1", + .timezone="posix/America/Edmonton", + .time=1483228827, + .local_tm= { + .tm_year=116, + .tm_mon=11, + .tm_mday=31, + .tm_hour=17, + .tm_min=0, + .tm_sec=27, + .tm_wday=6, + .tm_yday=365, + .tm_isdst=0, + .tm_gmtoff=-25200, + .tm_zone="MST" + }, + .gmt_tm= { + .tm_year=117, + .tm_mon=0, + .tm_mday=1, + .tm_hour=0, + .tm_min=0, + .tm_sec=27, + .tm_wday=0, + .tm_yday=0, + .tm_isdst=0, + .tm_gmtoff=0, + .tm_zone="GMT" + }, + }, + { + .descr="leap second - 1", + .timezone="right/UTC", + .time=1483228825, + .local_tm= { + .tm_year=116, + .tm_mon=11, + .tm_mday=31, + .tm_hour=23, + .tm_min=59, + .tm_sec=59, + .tm_wday=6, + .tm_yday=365, + .tm_isdst=0, + .tm_gmtoff=0, + .tm_zone="UTC" + }, + .gmt_tm= { + .tm_year=117, + .tm_mon=0, + .tm_mday=1, + .tm_hour=0, + .tm_min=0, + .tm_sec=25, + .tm_wday=0, + .tm_yday=0, + .tm_isdst=0, + .tm_gmtoff=0, + .tm_zone="GMT" + }, + }, + { + .descr="leap second", + .timezone="right/UTC", + .time=1483228826, + .local_tm= { + .tm_year=116, + .tm_mon=11, + .tm_mday=31, + .tm_hour=23, + .tm_min=59, + .tm_sec=60, + .tm_wday=6, + .tm_yday=365, + .tm_isdst=0, + .tm_gmtoff=0, + .tm_zone="UTC" + }, + .gmt_tm= { + .tm_year=117, + .tm_mon=0, + .tm_mday=1, + .tm_hour=0, + .tm_min=0, + .tm_sec=26, + .tm_wday=0, + .tm_yday=0, + .tm_isdst=0, + .tm_gmtoff=0, + .tm_zone="GMT" + }, + }, + { + .descr="leap second + 1", + .timezone="right/UTC", + .time=1483228827, + .local_tm= { + .tm_year=117, + .tm_mon=0, + .tm_mday=1, + .tm_hour=0, + .tm_min=0, + .tm_sec=0, + .tm_wday=0, + .tm_yday=0, + .tm_isdst=0, + .tm_gmtoff=0, + .tm_zone="UTC" + }, + .gmt_tm= { + .tm_year=117, + .tm_mon=0, + .tm_mday=1, + .tm_hour=0, + .tm_min=0, + .tm_sec=27, + .tm_wday=0, + .tm_yday=0, + .tm_isdst=0, + .tm_gmtoff=0, + .tm_zone="GMT" + }, + }, + { + .descr="leap second - 1", + .timezone="right/America/Edmonton", + .time=1483228825, + .local_tm= { + .tm_year=116, + .tm_mon=11, + .tm_mday=31, + .tm_hour=16, + .tm_min=59, + .tm_sec=59, + .tm_wday=6, + .tm_yday=365, + .tm_isdst=0, + .tm_gmtoff=-25200, + .tm_zone="MST" + }, + .gmt_tm= { + .tm_year=117, + .tm_mon=0, + .tm_mday=1, + .tm_hour=0, + .tm_min=0, + .tm_sec=25, + .tm_wday=0, + .tm_yday=0, + .tm_isdst=0, + .tm_gmtoff=0, + .tm_zone="GMT" + }, + }, + { + .descr="leap second", + .timezone="right/America/Edmonton", + .time=1483228826, + .local_tm= { + .tm_year=116, + .tm_mon=11, + .tm_mday=31, + .tm_hour=16, + .tm_min=59, + .tm_sec=60, + .tm_wday=6, + .tm_yday=365, + .tm_isdst=0, + .tm_gmtoff=-25200, + .tm_zone="MST" + }, + .gmt_tm= { + .tm_year=117, + .tm_mon=0, + .tm_mday=1, + .tm_hour=0, + .tm_min=0, + .tm_sec=26, + .tm_wday=0, + .tm_yday=0, + .tm_isdst=0, + .tm_gmtoff=0, + .tm_zone="GMT" + }, + }, + { + .descr="leap second + 1", + .timezone="right/America/Edmonton", + .time=1483228827, + .local_tm= { + .tm_year=116, + .tm_mon=11, + .tm_mday=31, + .tm_hour=17, + .tm_min=0, + .tm_sec=0, + .tm_wday=6, + .tm_yday=365, + .tm_isdst=0, + .tm_gmtoff=-25200, + .tm_zone="MST" + }, + .gmt_tm= { + .tm_year=117, + .tm_mon=0, + .tm_mday=1, + .tm_hour=0, + .tm_min=0, + .tm_sec=27, + .tm_wday=0, + .tm_yday=0, + .tm_isdst=0, + .tm_gmtoff=0, + .tm_zone="GMT" + }, + }, + { + .descr="transition standard to daylight - 1", + .timezone="posix/America/Edmonton", + .time=1457859599, + .local_tm= { + .tm_year=116, + .tm_mon=2, + .tm_mday=13, + .tm_hour=1, + .tm_min=59, + .tm_sec=59, + .tm_wday=0, + .tm_yday=72, + .tm_isdst=0, + .tm_gmtoff=-25200, + .tm_zone="MST" + }, + .gmt_tm= { + .tm_year=116, + .tm_mon=2, + .tm_mday=13, + .tm_hour=8, + .tm_min=59, + .tm_sec=59, + .tm_wday=0, + .tm_yday=72, + .tm_isdst=0, + .tm_gmtoff=0, + .tm_zone="GMT" + }, + }, + { + .descr="transition standard to daylight", + .timezone="posix/America/Edmonton", + .time=1457859600, + .local_tm= { + .tm_year=116, + .tm_mon=2, + .tm_mday=13, + .tm_hour=3, + .tm_min=0, + .tm_sec=0, + .tm_wday=0, + .tm_yday=72, + .tm_isdst=1, + .tm_gmtoff=-21600, + .tm_zone="MDT" + }, + .gmt_tm= { + .tm_year=116, + .tm_mon=2, + .tm_mday=13, + .tm_hour=9, + .tm_min=0, + .tm_sec=0, + .tm_wday=0, + .tm_yday=72, + .tm_isdst=0, + .tm_gmtoff=0, + .tm_zone="GMT" + }, + }, + { + .descr="transition standard to daylight + 1", + .timezone="posix/America/Edmonton", + .time=1457859601, + .local_tm= { + .tm_year=116, + .tm_mon=2, + .tm_mday=13, + .tm_hour=3, + .tm_min=0, + .tm_sec=1, + .tm_wday=0, + .tm_yday=72, + .tm_isdst=1, + .tm_gmtoff=-21600, + .tm_zone="MDT" + }, + .gmt_tm= { + .tm_year=116, + .tm_mon=2, + .tm_mday=13, + .tm_hour=9, + .tm_min=0, + .tm_sec=1, + .tm_wday=0, + .tm_yday=72, + .tm_isdst=0, + .tm_gmtoff=0, + .tm_zone="GMT" + }, + }, + { + .descr="transition standard to daylight - 1", + .timezone="right/America/Edmonton", + .time=1457859625, + .local_tm= { + .tm_year=116, + .tm_mon=2, + .tm_mday=13, + .tm_hour=1, + .tm_min=59, + .tm_sec=59, + .tm_wday=0, + .tm_yday=72, + .tm_isdst=0, + .tm_gmtoff=-25200, + .tm_zone="MST" + }, + .gmt_tm= { + .tm_year=116, + .tm_mon=2, + .tm_mday=13, + .tm_hour=9, + .tm_min=0, + .tm_sec=25, + .tm_wday=0, + .tm_yday=72, + .tm_isdst=0, + .tm_gmtoff=0, + .tm_zone="GMT" + }, + }, + { + .descr="transition standard to daylight", + .timezone="right/America/Edmonton", + .time=1457859626, + .local_tm= { + .tm_year=116, + .tm_mon=2, + .tm_mday=13, + .tm_hour=3, + .tm_min=0, + .tm_sec=0, + .tm_wday=0, + .tm_yday=72, + .tm_isdst=1, + .tm_gmtoff=-21600, + .tm_zone="MDT" + }, + .gmt_tm= { + .tm_year=116, + .tm_mon=2, + .tm_mday=13, + .tm_hour=9, + .tm_min=0, + .tm_sec=26, + .tm_wday=0, + .tm_yday=72, + .tm_isdst=0, + .tm_gmtoff=0, + .tm_zone="GMT" + }, + }, + { + .descr="transition standard to daylight + 1", + .timezone="right/America/Edmonton", + .time=1457859627, + .local_tm= { + .tm_year=116, + .tm_mon=2, + .tm_mday=13, + .tm_hour=3, + .tm_min=0, + .tm_sec=1, + .tm_wday=0, + .tm_yday=72, + .tm_isdst=1, + .tm_gmtoff=-21600, + .tm_zone="MDT" + }, + .gmt_tm= { + .tm_year=116, + .tm_mon=2, + .tm_mday=13, + .tm_hour=9, + .tm_min=0, + .tm_sec=27, + .tm_wday=0, + .tm_yday=72, + .tm_isdst=0, + .tm_gmtoff=0, + .tm_zone="GMT" + }, + }, + { + .descr="transition daylight to standard - 1", + .timezone="posix/America/Edmonton", + .time=1478419199, + .local_tm= { + .tm_year=116, + .tm_mon=10, + .tm_mday=6, + .tm_hour=1, + .tm_min=59, + .tm_sec=59, + .tm_wday=0, + .tm_yday=310, + .tm_isdst=1, + .tm_gmtoff=-21600, + .tm_zone="MDT" + }, + .gmt_tm= { + .tm_year=116, + .tm_mon=10, + .tm_mday=6, + .tm_hour=7, + .tm_min=59, + .tm_sec=59, + .tm_wday=0, + .tm_yday=310, + .tm_isdst=0, + .tm_gmtoff=0, + .tm_zone="GMT" + }, + }, + { + .descr="transition daylight to standard", + .timezone="posix/America/Edmonton", + .time=1478419200, + .local_tm= { + .tm_year=116, + .tm_mon=10, + .tm_mday=6, + .tm_hour=1, + .tm_min=0, + .tm_sec=0, + .tm_wday=0, + .tm_yday=310, + .tm_isdst=0, + .tm_gmtoff=-25200, + .tm_zone="MST" + }, + .gmt_tm= { + .tm_year=116, + .tm_mon=10, + .tm_mday=6, + .tm_hour=8, + .tm_min=0, + .tm_sec=0, + .tm_wday=0, + .tm_yday=310, + .tm_isdst=0, + .tm_gmtoff=0, + .tm_zone="GMT" + }, + }, + { + .descr="transition daylight to standard + 1", + .timezone="posix/America/Edmonton", + .time=1478419201, + .local_tm= { + .tm_year=116, + .tm_mon=10, + .tm_mday=6, + .tm_hour=1, + .tm_min=0, + .tm_sec=1, + .tm_wday=0, + .tm_yday=310, + .tm_isdst=0, + .tm_gmtoff=-25200, + .tm_zone="MST" + }, + .gmt_tm= { + .tm_year=116, + .tm_mon=10, + .tm_mday=6, + .tm_hour=8, + .tm_min=0, + .tm_sec=1, + .tm_wday=0, + .tm_yday=310, + .tm_isdst=0, + .tm_gmtoff=0, + .tm_zone="GMT" + }, + }, + { + .descr="transition daylight to standard - 1", + .timezone="right/America/Edmonton", + .time=1478419225, + .local_tm= { + .tm_year=116, + .tm_mon=10, + .tm_mday=6, + .tm_hour=1, + .tm_min=59, + .tm_sec=59, + .tm_wday=0, + .tm_yday=310, + .tm_isdst=1, + .tm_gmtoff=-21600, + .tm_zone="MDT" + }, + .gmt_tm= { + .tm_year=116, + .tm_mon=10, + .tm_mday=6, + .tm_hour=8, + .tm_min=0, + .tm_sec=25, + .tm_wday=0, + .tm_yday=310, + .tm_isdst=0, + .tm_gmtoff=0, + .tm_zone="GMT" + }, + }, + { + .descr="transition daylight to standard", + .timezone="right/America/Edmonton", + .time=1478419226, + .local_tm= { + .tm_year=116, + .tm_mon=10, + .tm_mday=6, + .tm_hour=1, + .tm_min=0, + .tm_sec=0, + .tm_wday=0, + .tm_yday=310, + .tm_isdst=0, + .tm_gmtoff=-25200, + .tm_zone="MST" + }, + .gmt_tm= { + .tm_year=116, + .tm_mon=10, + .tm_mday=6, + .tm_hour=8, + .tm_min=0, + .tm_sec=26, + .tm_wday=0, + .tm_yday=310, + .tm_isdst=0, + .tm_gmtoff=0, + .tm_zone="GMT" + }, + }, + { + .descr="transition daylight to standard + 1", + .timezone="right/America/Edmonton", + .time=1478419227, + .local_tm= { + .tm_year=116, + .tm_mon=10, + .tm_mday=6, + .tm_hour=1, + .tm_min=0, + .tm_sec=1, + .tm_wday=0, + .tm_yday=310, + .tm_isdst=0, + .tm_gmtoff=-25200, + .tm_zone="MST" + }, + .gmt_tm= { + .tm_year=116, + .tm_mon=10, + .tm_mday=6, + .tm_hour=8, + .tm_min=0, + .tm_sec=27, + .tm_wday=0, + .tm_yday=310, + .tm_isdst=0, + .tm_gmtoff=0, + .tm_zone="GMT" + }, + }, + { + .descr = NULL, + }, +}; + +void printtm(FILE *f, struct tm *tm) +{ + fprintf(f, "\t\t{\n\t\t\t.tm_year=%d,\n\t\t\t.tm_mon=%d,\n\t\t\t" + ".tm_mday=%d,\n\t\t\t.tm_hour=%d,\n\t\t\t.tm_min=%d,\n\t\t\t" + ".tm_sec=%d,\n\t\t\t.tm_wday=%d,\n\t\t\t.tm_yday=%d,\n\t\t\t" + ".tm_isdst=%d,\n\t\t\t.tm_gmtoff=%ld,\n\t\t\t.tm_zone=\"%s\"" + "\n\t\t},\n", + tm->tm_year, + tm->tm_mon, + tm->tm_mday, + tm->tm_hour, + tm->tm_min, + tm->tm_sec, + tm->tm_wday, + tm->tm_yday, + tm->tm_isdst, + tm->tm_gmtoff, + tm->tm_zone); +} + +int dotimetest(struct timetest *test, int print) +{ + int failures = 0; + struct tm local = {}, gmt = {}; + time_t converted; + if (gmtime_r(&test->time, &gmt) == NULL) { + memset(&gmt, 0, sizeof(gmt)); + gmt.tm_zone="FAILURE"; + } else { + converted = timegm(&gmt); + if (converted != test->time) { + fprintf(stderr, "FAIL: test \"%s\", tz \"%s\" timegm " + "does not match expected value\n", test->descr, + test->timezone); + fprintf(stderr, "expected: %lld\n", test->time); + fprintf(stderr, "actual: %lld\n", converted); + failures++; + } + } + if (!tm_match(&test->gmt_tm, &gmt)) { + fprintf(stderr, "FAIL: test \"%s\", tz \"%s\" gmtime_r does not" + " match expected value\n", test->descr, test->timezone); + fprintf(stderr, "expected: "); + printtm(stderr, &test->gmt_tm); + fprintf(stderr, "actual: "); + printtm(stderr, &gmt); + failures++; + } + setenv("TZ", test->timezone, 1); + if (localtime_r(&test->time, &local) == NULL) { + memset(&local, 0, sizeof(local)); + local.tm_zone="FAILURE"; + } else { + converted = mktime(&local); + if (converted != test->time) { + fprintf(stderr, "FAIL: test \"%s\", tz \"%s\" mktime " + "does not match expected value\n", test->descr, + test->timezone); + fprintf(stderr, "expected: %lld\n", test->time); + fprintf(stderr, "actual: %lld\n", converted); + failures++; + } + } + if (!tm_match(&test->local_tm, &local)) { + fprintf(stderr, "FAIL: test \"%s\", tz \"%s\" localtime_r does " + "not match expected value\n", test->descr, test->timezone); + fprintf(stderr, "expected: "); + printtm(stderr, &test->local_tm); + fprintf(stderr, "actual: "); + printtm(stderr, &local); + failures++; + } + if (print) { + printf("\t{\n\t\t.descr=\"%s\",\n\t\t.timezone=\"%s\",\n\t\t" + ".time=%lld,\n", test->descr, test->timezone, test->time); + printf("\t\t.local_tm="); + printtm(stdout, &local); + printf("\t\t.gmt_tm="); + printtm(stdout, &gmt); + printf("\t},\n"); + } + return failures; +} + + +void printtmdescr(FILE *f, struct tm *tm, char * descr) +{ + fprintf(f, "%s: ", descr); + printtm(f, tm); +} + +int main() { + int failures = 0; + int verbose = 0; + struct stat sb; + + if (stat("/usr/share/zoneinfo/posix", &sb) == -1) { + fprintf(stderr, "WARNING: /usr/share/zoneinfo/posix not" + "present,\nCreate posix time zones to run this test.\n"); + exit(0); + } + if (stat("/usr/share/zoneinfo/right", &sb) == -1) { + fprintf(stderr, "WARNING: /usr/share/zoneinfo/right not" + "present,\nCreate right time zones to run this test.\n"); + exit(0); + } + + for (size_t i = 0; timetests[i].descr != NULL; i++) { + failures += dotimetest(&timetests[i], verbose); + } + if (failures) + fprintf(stderr, "FAIL: %d time test failures\n", failures); + else + printf("SUCCESS: no time test failures\n"); + exit(failures); +} +