1 ;;;; time.test --- test suite for Guile's time functions -*- scheme -*-
2 ;;;; Jim Blandy <jimb@red-bean.com> --- June 1999, 2004
4 ;;;; Copyright (C) 1999, 2004, 2006, 2007, 2009 Free Software Foundation, Inc.
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, or (at your option)
9 ;;;; any later version.
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.
16 ;;;; You should have received a copy of the GNU General Public License
17 ;;;; along with this software; see the file COPYING. If not, write to
18 ;;;; the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
19 ;;;; Boston, MA 02110-1301 USA
21 (define-module (test-suite test-time)
22 #:use-module (test-suite lib)
23 #:use-module (ice-9 threads))
29 (with-test-prefix "gmtime"
32 (pass-if (list "in another thread after error" t)
33 (or (provided? 'threads) (throw 'unsupported))
36 (false-if-exception (gmtime t))
37 (join-thread (begin-thread (catch #t
38 (lambda () (gmtime t))
43 ;; time values that might provoke an error from libc
44 ;; on 32-bit glibc all values (which fit) are fine
45 ;; on 64-bit glibc apparently 2^63 can overflow a 32-bit tm_year
46 (list (1- (ash 1 31)) (1- (ash 1 63))
47 -1 (- (ash 1 31)) (- (ash 1 63)))))
50 ;;; internal-time-units-per-second
53 (with-test-prefix "internal-time-units-per-second"
55 ;; Check that sleep 1 gives about internal-time-units-per-second worth of
56 ;; elapsed time from times:clock. This mainly ensures
57 ;; internal-time-units-per-second correctly indicates CLK_TCK units.
59 (pass-if "versus times and sleep"
60 (or (defined? 'times) (throw 'unsupported))
65 (elapsed (- (tms:clock new) (tms:clock old))))
66 (<= (* 0.5 internal-time-units-per-second)
68 (* 2 internal-time-units-per-second))))))
74 (with-test-prefix "localtime"
76 ;; gmtoff is calculated with some explicit code, try to exercise that
77 ;; here, looking at cases where the localtime and gmtime are within the same
78 ;; day, or crossing midnight, or crossing new year
80 (pass-if "gmtoff of EST+5 at GMT 10:00am on 10 Jan 2000"
81 (let ((tm (gmtime 0)))
86 (let* ((t (car (mktime tm "GMT")))
87 (tm (localtime t "EST+5")))
88 (eqv? (* 5 3600) (tm:gmtoff tm)))))
90 ;; crossing forward over day boundary
91 (pass-if "gmtoff of EST+5 at GMT 3am on 10 Jan 2000"
92 (let ((tm (gmtime 0)))
97 (let* ((t (car (mktime tm "GMT")))
98 (tm (localtime t "EST+5")))
99 (eqv? (* 5 3600) (tm:gmtoff tm)))))
101 ;; crossing backward over day boundary
102 (pass-if "gmtoff of AST-10 at GMT 10pm on 10 Jan 2000"
103 (let ((tm (gmtime 0)))
108 (let* ((t (car (mktime tm "GMT")))
109 (tm (localtime t "AST-10")))
110 (eqv? (* -10 3600) (tm:gmtoff tm)))))
112 ;; crossing forward over year boundary
113 (pass-if "gmtoff of EST+5 at GMT 3am on 1 Jan 2000"
114 (let ((tm (gmtime 0)))
119 (let* ((t (car (mktime tm "GMT")))
120 (tm (localtime t "EST+5")))
121 (eqv? (* 5 3600) (tm:gmtoff tm)))))
123 ;; crossing backward over day boundary
124 (pass-if "gmtoff of AST-10 at GMT 10pm on 31 Dec 2000"
125 (let ((tm (gmtime 0)))
130 (let* ((t (car (mktime tm "GMT")))
131 (tm (localtime t "AST-10")))
132 (eqv? (* -10 3600) (tm:gmtoff tm))))))
138 (with-test-prefix "mktime"
140 ;; gmtoff is calculated with some explicit code, try to exercise that
141 ;; here, looking at cases where the mktime and gmtime are within the same
142 ;; day, or crossing midnight, or crossing new year
144 (pass-if "gmtoff of EST+5 at 10:00am on 10 Jan 2000"
145 (let ((tm (gmtime 0)))
150 (let ((tm (cdr (mktime tm "EST+5"))))
151 (eqv? (* 5 3600) (tm:gmtoff tm)))))
153 ;; crossing forward over day boundary
154 (pass-if "gmtoff of EST+5 at 10:00pm on 10 Jan 2000"
155 (let ((tm (gmtime 0)))
160 (let ((tm (cdr (mktime tm "EST+5"))))
161 (eqv? (* 5 3600) (tm:gmtoff tm)))))
163 ;; crossing backward over day boundary
164 (pass-if "gmtoff of AST-10 at 3:00am on 10 Jan 2000"
165 (let ((tm (gmtime 0)))
170 (let ((tm (cdr (mktime tm "AST-10"))))
171 (eqv? (* -10 3600) (tm:gmtoff tm)))))
173 ;; crossing forward over year boundary
174 (pass-if "gmtoff of EST+5 at 10:00pm on 31 Dec 2000"
175 (let ((tm (gmtime 0)))
180 (let ((tm (cdr (mktime tm "EST+5"))))
181 (eqv? (* 5 3600) (tm:gmtoff tm)))))
183 ;; crossing backward over day boundary
184 (pass-if "gmtoff of AST-10 at 3:00am on 1 Jan 2000"
185 (let ((tm (gmtime 0)))
190 (let ((tm (cdr (mktime tm "AST-10"))))
191 (eqv? (* -10 3600) (tm:gmtoff tm))))))
197 (with-test-prefix "strftime"
199 ;; Note we must force isdst to get the ZOW zone name out of %Z on HP-UX.
200 ;; If localtime is in daylight savings then it will decide there's no
201 ;; daylight savings zone name for the fake ZOW, and come back empty.
203 ;; This test is disabled because on NetBSD %Z doesn't look at the tm_zone
204 ;; field in struct tm passed by guile. That behaviour is reasonable
205 ;; enough since that field is not in C99 so a C99 program won't know it
206 ;; has to be set. For the details on that see
208 ;; http://www.netbsd.org/cgi-bin/query-pr-single.pl?number=21722
210 ;; Not sure what to do about this in guile, it'd be nice for %Z to look at
211 ;; tm:zone everywhere.
214 ;; (pass-if "strftime %Z doesn't return garbage"
215 ;; (let ((t (localtime (current-time))))
216 ;; (set-tm:zone t "ZOW")
217 ;; (set-tm:isdst t 0)
218 ;; (string=? (strftime "%Z" t)
221 (with-test-prefix "C99 %z format"
223 ;; C99 spec is empty string if no zone determinable
225 ;; On pre-C99 systems not sure what to expect if %z unsupported, probably
226 ;; "%z" unchanged in C99 if timezone. On AIX and Tru64 5.1b, it returns
227 ;; a string such as "GMT" or "EST", instead of "+0000" or "-0500". See
228 ;; https://savannah.gnu.org/bugs/index.php?24130 for details.
230 (define have-strftime-%z
231 (equal? (strftime "%z" (gmtime 0)) "+0000"))
233 ;; %z here is quite possibly affected by the same tm:gmtoff vs current
234 ;; zone as %Z above is, so in the following tests we make them the same.
237 (or have-strftime-%z (throw 'unsupported))
240 (let ((tm (localtime 86400)))
241 (string=? "+0000" (strftime "%z" tm))))
243 ;; prior to guile 1.6.9 and 1.8.1 this test failed, getting "+0500",
244 ;; because we didn't adjust for tm:gmtoff being west of Greenwich versus
245 ;; tm_gmtoff being east of Greenwich
247 (or have-strftime-%z (throw 'unsupported))
250 (let ((tm (localtime 86400)))
251 (string=? "-0500" (strftime "%z" tm))))))
257 (with-test-prefix "strptime"
259 (pass-if "in another thread after error"
260 (or (defined? 'strptime) (throw 'unsupported))
261 (or (provided? 'threads) (throw 'unsupported))
265 (strptime "%a" "nosuchday"))
266 (join-thread (begin-thread (strptime "%d" "1")))
270 (with-test-prefix "GNU %s format"
272 ;; "%s" to parse a count of seconds since 1970 is a GNU extension
273 (define have-strptime-%s
274 (false-if-exception (strptime "%s" "0")))
276 (pass-if "gmtoff on GMT"
277 (or have-strptime-%s (throw 'unsupported))
280 (let ((tm (car (strptime "%s" "86400"))))
281 (eqv? 0 (tm:gmtoff tm))))
283 ;; prior to guile 1.6.9 and 1.8.1 we didn't pass tm_gmtoff back from
285 (pass-if "gmtoff on EST+5"
286 (or have-strptime-%s (throw 'unsupported))
289 (let ((tm (car (strptime "%s" "86400"))))
290 (eqv? (* 5 3600) (tm:gmtoff tm))))))