srfi-19.test 9.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236
  1. ;;;; srfi-19.test --- test suite for SRFI-19 -*- scheme -*-
  2. ;;;; Matthias Koeppe <mkoeppe@mail.math.uni-magdeburg.de> --- June 2001
  3. ;;;;
  4. ;;;; Copyright (C) 2001, 2003, 2004, 2005, 2006, 2007, 2008,
  5. ;;;; 2011, 2014, 2017 Free Software Foundation, Inc.
  6. ;;;;
  7. ;;;; This library is free software; you can redistribute it and/or
  8. ;;;; modify it under the terms of the GNU Lesser General Public
  9. ;;;; License as published by the Free Software Foundation; either
  10. ;;;; version 3 of the License, or (at your option) any later version.
  11. ;;;;
  12. ;;;; This library 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 GNU
  15. ;;;; Lesser General Public License for more details.
  16. ;;;;
  17. ;;;; You should have received a copy of the GNU Lesser General Public
  18. ;;;; License along with this library; if not, write to the Free Software
  19. ;;;; Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
  20. ;; SRFI-19 overrides current-date, so we have to do the test in a
  21. ;; separate module, or later tests will fail.
  22. (define-module (test-suite test-srfi-19)
  23. :duplicates (last) ;; avoid warning about srfi-19 replacing `current-time'
  24. :use-module (test-suite lib)
  25. :use-module (srfi srfi-19)
  26. :use-module (ice-9 format))
  27. ;; Make sure we use the default locale.
  28. (when (defined? 'setlocale)
  29. (setlocale LC_ALL "C"))
  30. (define (with-tz* tz thunk)
  31. "Temporarily set the TZ environment variable to the passed string
  32. value and call THUNK."
  33. (let ((old-tz #f))
  34. (dynamic-wind
  35. (lambda ()
  36. (set! old-tz (getenv "TZ"))
  37. (putenv (format #f "TZ=~A" tz)))
  38. thunk
  39. (lambda ()
  40. (if old-tz
  41. (putenv (format #f "TZ=~A" old-tz))
  42. (putenv "TZ"))))))
  43. (defmacro with-tz (tz . body)
  44. `(with-tz* ,tz (lambda () ,@body)))
  45. (define (test-integral-time-structure date->time)
  46. "Test whether the given DATE->TIME procedure creates a time
  47. structure with integral seconds. (The seconds shall be maintained as
  48. integers, or precision may go away silently. The SRFI-19 reference
  49. implementation was not OK for Guile in this respect because of Guile's
  50. incomplete numerical tower implementation.)"
  51. (pass-if (format #f "~A makes integer seconds"
  52. date->time)
  53. (exact? (time-second
  54. (date->time (make-date 0 0 0 12 1 6 2001 0))))))
  55. (define (test-time->date time->date date->time)
  56. (pass-if (format #f "~A works"
  57. time->date)
  58. (begin
  59. (time->date (date->time (make-date 0 0 0 12 1 6 2001 0)))
  60. #t)))
  61. (define (test-dst time->date date->time)
  62. (pass-if (format #f "~A respects local DST if no TZ-OFFSET given"
  63. time->date)
  64. (let ((time (date->time (make-date 0 0 0 12 1 6 2001 0))))
  65. ;; on 2001-06-01, there should be 4 hours zone offset
  66. ;; between EST (EDT) and GMT
  67. (= (date-zone-offset
  68. (with-tz "EST5EDT"
  69. (time->date time)))
  70. -14400))))
  71. (define-macro (test-time-conversion a b)
  72. (let* ((a->b-sym (symbol-append a '-> b))
  73. (b->a-sym (symbol-append b '-> a)))
  74. `(pass-if (format #f "~A and ~A work and are inverses of each other"
  75. ',a->b-sym ',b->a-sym)
  76. (let ((time (make-time ,a 12345 67890123)))
  77. (time=? time (,b->a-sym (,a->b-sym time)))))))
  78. (define (test-time-comparison cmp a b)
  79. (pass-if (format #f "~A works" cmp)
  80. (cmp a b)))
  81. (define (test-time-arithmetic op a b res)
  82. (pass-if (format #f "~A works" op)
  83. (time=? (op a b) res)))
  84. ;; return true if time objects X and Y are equal
  85. (define (time-equal? x y)
  86. (and (eq? (time-type x) (time-type y))
  87. (eqv? (time-second x) (time-second y))
  88. (eqv? (time-nanosecond x) (time-nanosecond y))))
  89. (with-test-prefix "SRFI date/time library"
  90. ;; check for typos and silly errors
  91. (pass-if "date-zone-offset is defined"
  92. (and (defined? 'date-zone-offset)
  93. date-zone-offset
  94. #t))
  95. (pass-if "add-duration is defined"
  96. (and (defined? 'add-duration)
  97. add-duration
  98. #t))
  99. (pass-if "(current-time time-tai) works"
  100. (time? (current-time time-tai)))
  101. (pass-if "(current-time time-process) works"
  102. (time? (current-time time-process)))
  103. (test-time-conversion time-utc time-tai)
  104. (test-time-conversion time-utc time-monotonic)
  105. (test-time-conversion time-tai time-monotonic)
  106. (pass-if "string->date works"
  107. (begin (string->date "2001-06-01@14:00" "~Y-~m-~d@~H:~M")
  108. #t))
  109. ;; check for code paths where reals were passed to quotient, which
  110. ;; doesn't work in Guile (and is unspecified in R5RS)
  111. (test-time->date time-utc->date date->time-utc)
  112. (test-time->date time-tai->date date->time-tai)
  113. (test-time->date time-monotonic->date date->time-monotonic)
  114. (pass-if "Fractional nanoseconds are handled"
  115. (begin (make-time time-duration 1000000000.5 0) #t))
  116. ;; the seconds in a time shall be maintained as integers, or
  117. ;; precision may silently go away
  118. (test-integral-time-structure date->time-utc)
  119. (test-integral-time-structure date->time-tai)
  120. (test-integral-time-structure date->time-monotonic)
  121. ;; check for DST and zone related problems
  122. (pass-if "date->time-utc is the inverse of time-utc->date"
  123. (let ((time (date->time-utc
  124. (make-date 0 0 0 14 1 6 2001 7200))))
  125. (time=? time
  126. (date->time-utc (time-utc->date time 7200)))))
  127. (test-dst time-utc->date date->time-utc)
  128. (test-dst time-tai->date date->time-tai)
  129. (test-dst time-monotonic->date date->time-monotonic)
  130. (test-dst julian-day->date date->julian-day)
  131. (test-dst modified-julian-day->date date->modified-julian-day)
  132. (pass-if "`date->julian-day' honors timezone"
  133. (let ((now (current-date -14400)))
  134. (time=? (date->time-utc (julian-day->date (date->julian-day now)))
  135. (date->time-utc now))))
  136. (pass-if "string->date respects local DST if no time zone is read"
  137. (time=? (date->time-utc
  138. (with-tz "EST5EDT"
  139. (string->date "2001-06-01@08:00" "~Y-~m-~d@~H:~M")))
  140. (date->time-utc
  141. (make-date 0 0 0 12 1 6 2001 0))))
  142. (pass-if "string->date understands days and months"
  143. (time=? (let ((d (string->date "Saturday, December 9, 2006"
  144. "~A, ~B ~d, ~Y")))
  145. (date->time-utc (make-date (date-nanosecond d)
  146. (date-second d)
  147. (date-minute d)
  148. (date-hour d)
  149. (date-day d)
  150. (date-month d)
  151. (date-year d)
  152. 0)))
  153. (date->time-utc
  154. (make-date 0 0 0 0 9 12 2006 0))))
  155. (pass-if "string->date works on Sunday"
  156. ;; `string->date' never rests!
  157. (let* ((str "Sun, 05 Jun 2005 18:33:00 +0200")
  158. (date (string->date str "~a, ~d ~b ~Y ~H:~M:~S ~z")))
  159. (equal? "Sun Jun 05 18:33:00+0200 2005"
  160. (date->string date))))
  161. (pass-if "date->string pads small nanoseconds values correctly"
  162. (let* ((date (make-date 99999999 5 34 12 26 3 2017 0)))
  163. (equal? "099999999"
  164. (date->string date "~N"))))
  165. (pass-if "date->string ~f without leading zeroes"
  166. (let ((date (make-date 200000000 5 34 12 26 3 2017 0)))
  167. (equal? "5.2" (date->string date "~f"))))
  168. (pass-if "date->string ~f proper fractional part"
  169. (let ((date (make-date 550000 56 34 12 26 3 2017 0)))
  170. (equal? "56.00055" (date->string date "~f"))))
  171. ;; check time comparison procedures
  172. (let* ((time1 (make-time time-monotonic 0 0))
  173. (time2 (make-time time-monotonic 0 0))
  174. (time3 (make-time time-monotonic 385907 998360432))
  175. (time4 (make-time time-monotonic 385907 998360432)))
  176. (test-time-comparison time<=? time1 time3)
  177. (test-time-comparison time<? time1 time3)
  178. (test-time-comparison time=? time1 time2)
  179. (test-time-comparison time>=? time3 time3)
  180. (test-time-comparison time>? time3 time2))
  181. ;; check time arithmetic procedures
  182. (let* ((time1 (make-time time-monotonic 0 0))
  183. (time2 (make-time time-monotonic 385907 998360432))
  184. (diff (time-difference time2 time1)))
  185. (test-time-arithmetic add-duration time1 diff time2)
  186. (test-time-arithmetic subtract-duration time2 diff time1))
  187. (with-test-prefix "date->time-tai"
  188. ;; leap second 1 Jan 1999, 1 second of UTC in make-date is out as 2
  189. ;; seconds of TAI in date->time-tai
  190. (pass-if "31dec98 23:59:59"
  191. (time-equal? (make-time time-tai 0 915148830)
  192. (date->time-tai (make-date 0 59 59 23 31 12 1998 0))))
  193. (pass-if "1jan99 0:00:00"
  194. (time-equal? (make-time time-tai 0 915148832)
  195. (date->time-tai (make-date 0 0 0 0 1 1 1999 0))))
  196. ;; leap second 1 Jan 2006, 1 second of UTC in make-date is out as 2
  197. ;; seconds of TAI in date->time-tai
  198. (pass-if "31dec05 23:59:59"
  199. (time-equal? (make-time time-tai 0 1136073631)
  200. (date->time-tai (make-date 0 59 59 23 31 12 2005 0))))
  201. (pass-if "1jan06 0:00:00"
  202. (time-equal? (make-time time-tai 0 1136073633)
  203. (date->time-tai (make-date 0 0 0 0 1 1 2006 0)))))
  204. (with-test-prefix "date-week-number"
  205. (pass-if (= 0 (date-week-number (make-date 0 0 0 0 1 1 1984 0) 0)))
  206. (pass-if (= 0 (date-week-number (make-date 0 0 0 0 7 1 1984 0) 0)))
  207. (pass-if (= 1 (date-week-number (make-date 0 0 0 0 8 1 1984 0) 0)))))
  208. ;; Local Variables:
  209. ;; eval: (put 'with-tz 'scheme-indent-function 1)
  210. ;; End: