1#! /bin/sh
2
3# Test that a getdate executable meets its specification.
4#
5# Copyright (C) 2004 Free Software Foundation, Inc.
6#
7# This program is free software; you can redistribute it and/or modify
8# it under the terms of the GNU General Public License as published by
9# the Free Software Foundation; either version 2, or (at your option)
10# any later version.
11#
12# This program is distributed in the hope that it will be useful,
13# but WITHOUT ANY WARRANTY; without even the implied warranty of
14# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15# GNU General Public License for more details.
16#
17# You should have received a copy of the GNU General Public License
18# along with this program; if not, write to the Free Software Foundation,
19# Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
20
21
22
23###
24### Globals
25###
26LOGFILE=`pwd`/getdate.log
27if test -f "$LOGFILE"; then
28	mv $LOGFILE $LOGFILE~
29fi
30
31
32
33###
34### Functions
35###
36verify ()
37{
38	echo >>getdate-got
39	if cmp getdate-expected getdate-got >getdate.cmp; then
40		echo "PASS: $1" >>$LOGFILE
41	else
42		cat getdate.cmp >>$LOGFILE
43		echo "** expected: " >>$LOGFILE
44		cat getdate-expected >>$LOGFILE
45		echo "** got: " >>$LOGFILE
46		cat getdate-got >>$LOGFILE
47		echo "FAIL: $1" | tee -a $LOGFILE >&2
48		echo "Failed!  See $LOGFILE for more!" >&2
49		exit 1
50	fi
51}
52
53
54
55skip ()
56{
57	echo "SKIP: $1"${2+" ($2)"} >>$LOGFILE
58}
59
60
61
62# Prep for future calls to valid_timezone().
63#
64# This should set $UTZ to three spaces, `GMT', `Unrecognized/Unrecognized', or
65# possibly the empty string, depending on what system we are running on.  With
66# any luck, this will catch any other existing variations as well.  The way it
67# is used later does have the disadvantage of rejecting at least the
68# `Europe/London' timezone for half the year when $UTZ gets set to `GMT', like
69# happens on NetBSD, but, since I haven't come up with any better ideas and
70# since rejecting a timezone just causes a few tests to be skipped, this will
71# have to do for now.
72#
73# UTZ stands for Unrecognized Time Zone.
74UTZ=`TZ=Unrecognized/Unrecognized date +%Z`
75
76# The following function will return true if $1 is a valid timezone.  It will
77# return false and set $skipreason, otherwise.
78#
79# Clobbers $NTZ & $skipreason.
80#
81# SUS2 says `date +%Z' will return `no characters' if `no timezone is
82# determinable'.  It is, unfortunately, not very specific about what
83# `determinable' means.  On GNU/Linux, `date +%Z' returns $TZ when $TZ is not
84# recognized.  NetBSD 1.6.1 "determines" that an unrecognizable value in $TZ
85# really means `GMT'.  On Cray, the standard is ignored and `date +%Z' returns
86# three spaces when $TZ is not recognized.  We test for all three cases, plus
87# the empty string for good measure, though I know of no set of conditions
88# which will actually cause `date +%Z' to return the empty string SUS2
89# specifies.
90#
91# Due to the current nature of this test, this will not work for the
92# three-letter zone codes on some systems.  e.g.:
93#
94#	test `TZ=EST date +%Z` = "EST"
95#
96# should, quite correctly, evaluate to true on most systems, but:
97#
98#	TZ=Asia/Calcutta date +%Z
99#
100# would return `IST' on GNU/Linux, and hopefully any system which understands
101# the `Asia/Calcutta' timezone, and `   ' on Cray.  Similarly:
102#
103#	TZ=Doesnt_Exist/Doesnt_Exist date +%Z
104#
105# returns `Doesnt_Exist/Doesnt_Exist' on GNU/Linux and `   ' on Cray.
106#
107# Unfortunately, the %z date format string (-HHMM format time zone) supported
108# by the GNU `date' command is not part of any standard I know of and,
109# therefore, is probably not portable.
110#
111valid_timezone ()
112{
113	NTZ=`TZ=$1 date +%Z`
114	if test "$NTZ" = "$UTZ" || test "$NTZ" = "$1"; then
115		skipreason="$1 is not a recognized timezone on this system"
116		return `false`
117	else
118		return `:`
119	fi
120}
121
122
123
124###
125### Tests
126###
127
128# Why are these dates tested?
129#
130# February 29, 2003
131#   Is not a leap year - should be invalid.
132#
133# 2004-12-40
134#   Make sure get_date does not "roll" date forward to January 9th.  Some
135#   versions have been known to do this.
136#
137# Dec-5-1972
138#   This is my birthday.  :)
139#
140# 3/29/1974
141# 1996/05/12 13:57:45
142#   Because.
143#
144# 12-05-12
145#   This will be my 40th birthday.  Ouch.  :)
146#
147# 05/12/96
148#   Because.
149#
150# third tuesday in March, 2078
151#   Wanted this to work.
152#
153# 1969-12-32 2:00:00 UTC
154# 1970-01-01 2:00:00 UTC
155# 1969-12-32 2:00:00 +0400
156# 1970-01-01 2:00:00 +0400
157# 1969-12-32 2:00:00 -0400
158# 1970-01-01 2:00:00 -0400
159#   Playing near the UNIX Epoch boundry condition to make sure date rolling
160#   is also disabled there.
161#
162# 1996-12-12 1 month
163#   Test a relative date.
164
165
166
167# The following tests are currently being skipped for being unportable:
168#
169# Tue Jan 19 03:14:07 2038 +0000
170#   For machines with 31-bit time_t, any date past this date will be an
171#   invalid date. So, any test date with a value greater than this
172#   time is not portable.
173#
174# Feb. 29, 2096 4 years
175#   4 years from this date is _not_ a leap year, so Feb. 29th does not exist.
176#
177# Feb. 29, 2096 8 years
178#   8 years from this date is a leap year, so Feb. 29th does exist,
179#   but on many hosts with 32-bit time_t types time, this test will
180#   fail. So, this is not a portable test.
181#
182
183TZ=UTC0; export TZ
184
185cat >getdate-expected <<EOF
186Enter date, or blank line to exit.
187	> Bad format - couldn't convert.
188	> Bad format - couldn't convert.
189	> 1972-12-05 00:00:00.000000000
190	> 1974-03-29 00:00:00.000000000
191	> 1996-05-12 13:57:45.000000000
192	> 2012-05-12 00:00:00.000000000
193	> 1996-05-12 00:00:00.000000000
194	> Bad format - couldn't convert.
195	> Bad format - couldn't convert.
196	> 1970-01-01 02:00:00.000000000
197	> Bad format - couldn't convert.
198	> 1969-12-31 22:00:00.000000000
199	> Bad format - couldn't convert.
200	> 1970-01-01 06:00:00.000000000
201	> 1997-01-12 00:00:00.000000000
202	> 
203EOF
204
205./getdate >getdate-got <<EOF
206February 29, 2003
2072004-12-40
208Dec-5-1972
2093/29/1974
2101996/05/12 13:57:45
21112-05-12
21205/12/96
213third tuesday in March, 2078
2141969-12-32 2:00:00 UTC
2151970-01-01 2:00:00 UTC
2161969-12-32 2:00:00 +0400
2171970-01-01 2:00:00 +0400
2181969-12-32 2:00:00 -0400
2191970-01-01 2:00:00 -0400
2201996-12-12 1 month
221EOF
222
223verify getdate-1
224
225
226
227# Why are these dates tested?
228#
229# Ian Abbot reported these odd boundry cases.  After daylight savings time went
230# into effect, non-daylight time zones would cause
231# "Bad format - couldn't convert." errors, even when the non-daylight zone
232# happened to be a universal one, like GMT.
233
234TZ=Europe/London; export TZ
235if valid_timezone $TZ; then
236	cat >getdate-expected <<EOF
237Enter date, or blank line to exit.
238	> 2005-03-01 00:00:00.000000000
239	> 2005-03-27 00:00:00.000000000
240	> 2005-03-28 01:00:00.000000000
241	> 2005-03-28 01:00:00.000000000
242	> 2005-03-29 01:00:00.000000000
243	> 2005-03-29 01:00:00.000000000
244	> 2005-03-30 01:00:00.000000000
245	> 2005-03-30 01:00:00.000000000
246	> 2005-03-31 01:00:00.000000000
247	> 2005-03-31 01:00:00.000000000
248	> 2005-04-01 01:00:00.000000000
249	> 2005-04-01 01:00:00.000000000
250	> 2005-04-10 01:00:00.000000000
251	> 2005-04-10 01:00:00.000000000
252	> 2005-04-01 00:00:00.000000000
253	> 
254EOF
255
256	./getdate >getdate-got <<EOF
2572005-3-1 GMT
2582005-3-27 GMT
2592005-3-28 GMT
2602005-3-28 UTC0
2612005-3-29 GMT
2622005-3-29 UTC0
2632005-3-30 GMT
2642005-3-30 UTC0
2652005-3-31 GMT
2662005-3-31 UTC0
2672005-4-1 GMT
2682005-4-1 UTC0
2692005-4-10 GMT
2702005-4-10 UTC0
2712005-4-1 BST
272EOF
273
274	verify getdate-2
275else
276	skip getdate-2 "$skipreason"
277fi
278
279
280
281# Many of the following cases were also submitted by Ian Abbott, but the same
282# errors are not exhibited.  The original problem had a similar root, but
283# managed to produce errors with GMT, which is considered a "Universal Zone".
284# This was fixed.
285#
286# The deeper problem has to do with "local zone" processing in getdate.y
287# that causes local daylight zones to be excluded when local standard time is
288# in effect and vice versa.  This used to cause trouble with GMT in Britian
289# when British Summer Time was in effect, but this was overridden for the
290# "Universal Timezones" (GMT, UTC, & UT), that might double as a local zone in
291# some locales.  We still see in these tests the local daylight/standard zone
292# exclusion in EST/EDT.  According to Paul Eggert in a message to
293# bug-gnulib@gnu.org on 2005-04-12, this is considered a bug but may not be
294# fixed soon due to its complexity.
295
296TZ=America/New_York; export TZ
297if valid_timezone $TZ; then
298	cat >getdate-expected <<EOF
299Enter date, or blank line to exit.
300	> 2005-03-01 00:00:00.000000000
301	> 2005-02-28 18:00:00.000000000
302	> 2005-04-01 00:00:00.000000000
303	> Bad format - couldn't convert.
304	> 2005-04-30 19:00:00.000000000
305	> 2005-04-30 20:00:00.000000000
306	> 2005-05-01 00:00:00.000000000
307	> 2005-04-30 20:00:00.000000000
308	> Bad format - couldn't convert.
309	> 2005-05-31 19:00:00.000000000
310	> 2005-05-31 20:00:00.000000000
311	> 2005-06-01 00:00:00.000000000
312	> 2005-05-31 20:00:00.000000000
313	> 
314EOF
315
316	./getdate >getdate-got <<EOF
3172005-3-1 EST
3182005-3-1 BST
3192005-4-1 EST
3202005-5-1 EST
3212005-5-1 BST
3222005-5-1 GMT
3232005-5-1 EDT
3242005-5-1 UTC0
3252005-6-1 EST
3262005-6-1 BST
3272005-6-1 GMT
3282005-6-1 EDT
3292005-6-1 UTC0
330EOF
331
332	verify getdate-3
333else
334	skip getdate-3 "$skipreason"
335fi
336
337
338
339rm getdate-expected getdate-got getdate.cmp
340exit 0
341