i18n: Always use locale-dependent string collation.
[bpt/guile.git] / test-suite / tests / i18n.test
CommitLineData
cdf52ff0 1;;;; i18n.test --- Exercise the i18n API. -*- coding: utf-8; mode: scheme; -*-
5b3a39c7 2;;;;
cdf52ff0
LC
3;;;; Copyright (C) 2006, 2007, 2009 Free Software Foundation, Inc.
4;;;; Ludovic Courtès
5b3a39c7
LC
5;;;;
6;;;; This library is free software; you can redistribute it and/or
7;;;; modify it under the terms of the GNU Lesser General Public
8;;;; License as published by the Free Software Foundation; either
53befeb7
NJ
9;;;; version 3 of the License, or (at your option) any later version.
10;;;;
5b3a39c7
LC
11;;;; This library 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 GNU
14;;;; Lesser General Public License for more details.
53befeb7 15;;;;
5b3a39c7
LC
16;;;; You should have received a copy of the GNU Lesser General Public
17;;;; License along with this library; if not, write to the Free Software
18;;;; Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
19
20(define-module (test-suite i18n)
21 :use-module (ice-9 i18n)
a2f00b9b 22 :use-module (srfi srfi-1)
5b3a39c7
LC
23 :use-module (test-suite lib))
24
25;; Start from a pristine locale state.
26(setlocale LC_ALL "C")
27
a2f00b9b
LC
28(define exception:locale-error
29 (cons 'system-error "Failed to install locale"))
30
31
5b3a39c7
LC
32\f
33(with-test-prefix "locale objects"
34
35 (pass-if "make-locale (2 args)"
a2f00b9b
LC
36 (not (not (make-locale LC_ALL "C"))))
37
38 (pass-if "make-locale (2 args, list)"
39 (not (not (make-locale (list LC_COLLATE LC_MESSAGES) "C"))))
5b3a39c7
LC
40
41 (pass-if "make-locale (3 args)"
a2f00b9b
LC
42 (not (not (make-locale (list LC_COLLATE) "C"
43 (make-locale (list LC_MESSAGES) "C")))))
44
45 (pass-if-exception "make-locale with unknown locale" exception:locale-error
46 (make-locale LC_ALL "does-not-exist"))
5b3a39c7
LC
47
48 (pass-if "locale?"
a2f00b9b
LC
49 (and (locale? (make-locale (list LC_ALL) "C"))
50 (locale? (make-locale (list LC_MESSAGES LC_NUMERIC) "C"
51 (make-locale (list LC_CTYPE) "C")))))
52
53 (pass-if "%global-locale"
54 (and (locale? %global-locale))
55 (locale? (make-locale (list LC_MONETARY) "C"
56 %global-locale))))
5b3a39c7
LC
57
58
59\f
60(with-test-prefix "text collation (English)"
61
62 (pass-if "string-locale<?"
63 (and (string-locale<? "hello" "world")
64 (string-locale<? "hello" "world"
a2f00b9b 65 (make-locale (list LC_COLLATE) "C"))))
5b3a39c7
LC
66
67 (pass-if "char-locale<?"
68 (and (char-locale<? #\a #\b)
a2f00b9b 69 (char-locale<? #\a #\b (make-locale (list LC_COLLATE) "C"))))
5b3a39c7
LC
70
71 (pass-if "string-locale-ci=?"
72 (and (string-locale-ci=? "Hello" "HELLO")
73 (string-locale-ci=? "Hello" "HELLO"
a2f00b9b 74 (make-locale (list LC_COLLATE) "C"))))
5b3a39c7
LC
75
76 (pass-if "string-locale-ci<?"
77 (and (string-locale-ci<? "hello" "WORLD")
78 (string-locale-ci<? "hello" "WORLD"
a2f00b9b 79 (make-locale (list LC_COLLATE) "C")))))
5b3a39c7
LC
80
81\f
a2f00b9b
LC
82(define %french-locale-name
83 "fr_FR.ISO-8859-1")
84
cdf52ff0
LC
85(define %french-utf8-locale-name
86 "fr_FR.UTF-8")
87
5b3a39c7
LC
88(define %french-locale
89 (false-if-exception
a2f00b9b
LC
90 (make-locale (list LC_CTYPE LC_COLLATE LC_NUMERIC LC_TIME)
91 %french-locale-name)))
5b3a39c7 92
cdf52ff0
LC
93(define %french-utf8-locale
94 (false-if-exception
95 (make-locale (list LC_CTYPE LC_COLLATE LC_NUMERIC LC_TIME)
96 %french-utf8-locale-name)))
97
98(define (under-locale-or-unresolved locale thunk)
5b3a39c7
LC
99 ;; On non-GNU systems, an exception may be raised only when the locale is
100 ;; actually used rather than at `make-locale'-time. Thus, we must guard
101 ;; against both.
cdf52ff0
LC
102 (if locale
103 (if (string-contains %host-type "-gnu")
104 (thunk)
105 (catch 'system-error thunk
106 (lambda (key . args)
107 (throw 'unresolved))))
5b3a39c7
LC
108 (throw 'unresolved)))
109
cdf52ff0
LC
110(define (under-french-locale-or-unresolved thunk)
111 (under-locale-or-unresolved %french-locale thunk))
112
113(define (under-french-utf8-locale-or-unresolved thunk)
114 (under-locale-or-unresolved %french-utf8-locale thunk))
115
116
5b3a39c7
LC
117(with-test-prefix "text collation (French)"
118
119 (pass-if "string-locale<?"
120 (under-french-locale-or-unresolved
121 (lambda ()
cdf52ff0 122 (string-locale<? "été" "hiver" %french-locale))))
5b3a39c7
LC
123
124 (pass-if "char-locale<?"
125 (under-french-locale-or-unresolved
126 (lambda ()
cdf52ff0 127 (char-locale<? #\é #\h %french-locale))))
5b3a39c7
LC
128
129 (pass-if "string-locale-ci=?"
130 (under-french-locale-or-unresolved
131 (lambda ()
cdf52ff0
LC
132 (string-locale-ci=? "ÉTÉ" "été" %french-locale))))
133
134 (pass-if "string-locale-ci=? (2 args, wide strings)"
135 (under-french-utf8-locale-or-unresolved
136 (lambda ()
137 ;; Note: Character `œ' is not part of Latin-1, so these are wide
138 ;; strings.
139 (dynamic-wind
140 (lambda ()
141 (setlocale LC_ALL "fr_FR.UTF-8"))
142 (lambda ()
143 (string-locale-ci=? "œuf" "ŒUF"))
144 (lambda ()
145 (setlocale LC_ALL "C"))))))
146
147 (pass-if "string-locale-ci=? (3 args, wide strings)"
148 (under-french-utf8-locale-or-unresolved
149 (lambda ()
150 (string-locale-ci=? "œuf" "ŒUF" %french-utf8-locale))))
5b3a39c7
LC
151
152 (pass-if "string-locale-ci<>?"
153 (under-french-locale-or-unresolved
154 (lambda ()
cdf52ff0
LC
155 (and (string-locale-ci<? "été" "Hiver" %french-locale)
156 (string-locale-ci>? "HiVeR" "été" %french-locale)))))
157
158 (pass-if "string-locale-ci<>? (wide strings)"
159 (under-french-utf8-locale-or-unresolved
160 (lambda ()
161 ;; One of the strings is UCS-4, the other is Latin-1.
162 (and (string-locale-ci<? "Œdème" "œuf" %french-utf8-locale)
163 (string-locale-ci>? "Œuf" "œdÈMe" %french-utf8-locale)))))
164
165 (pass-if "string-locale-ci<>? (wide and narrow strings)"
166 (under-french-utf8-locale-or-unresolved
167 (lambda ()
168 ;; One of the strings is UCS-4, the other is Latin-1.
169 (and (string-locale-ci>? "Œdème" "odyssée" %french-utf8-locale)
170 (string-locale-ci<? "Odyssée" "œdème" %french-utf8-locale)))))
5b3a39c7
LC
171
172 (pass-if "char-locale-ci<>?"
173 (under-french-locale-or-unresolved
174 (lambda ()
cdf52ff0
LC
175 (and (char-locale-ci<? #\é #\H %french-locale)
176 (char-locale-ci>? #\h #\É %french-locale)))))
177
178 (pass-if "char-locale-ci<>? (wide)"
179 (under-french-utf8-locale-or-unresolved
180 (lambda ()
181 (and (char-locale-ci<? #\o #\œ %french-utf8-locale)
182 (char-locale-ci>? #\Π#\e %french-utf8-locale))))))
5b3a39c7
LC
183
184\f
185(with-test-prefix "character mapping"
186
187 (pass-if "char-locale-downcase"
188 (and (eq? #\a (char-locale-downcase #\A))
a2f00b9b 189 (eq? #\a (char-locale-downcase #\A (make-locale LC_ALL "C")))))
5b3a39c7
LC
190
191 (pass-if "char-locale-upcase"
192 (and (eq? #\Z (char-locale-upcase #\z))
a2f00b9b 193 (eq? #\Z (char-locale-upcase #\z (make-locale LC_ALL "C"))))))
5b3a39c7
LC
194
195\f
196(with-test-prefix "number parsing"
197
198 (pass-if "locale-string->integer"
199 (call-with-values (lambda () (locale-string->integer "123"))
200 (lambda (result char-count)
201 (and (equal? result 123)
202 (equal? char-count 3)))))
203
204 (pass-if "locale-string->inexact"
205 (call-with-values
206 (lambda ()
207 (locale-string->inexact "123.456"
a2f00b9b 208 (make-locale (list LC_NUMERIC) "C")))
5b3a39c7
LC
209 (lambda (result char-count)
210 (and (equal? result 123.456)
a2f00b9b
LC
211 (equal? char-count 7)))))
212
213 (pass-if "locale-string->inexact (French)"
214 (under-french-locale-or-unresolved
215 (lambda ()
216 (call-with-values
217 (lambda ()
218 (locale-string->inexact "123,456" %french-locale))
219 (lambda (result char-count)
220 (and (equal? result 123.456)
221 (equal? char-count 7))))))))
222
223\f
224;;;
225;;; `nl-langinfo'
226;;;
227
228(setlocale LC_ALL "C")
229(define %c-locale (make-locale LC_ALL "C"))
230
231(define %english-days
232 '("Sunday" "Monday" "Tuesday" "Wednesday" "Thursday" "Friday" "Saturday"))
233
234(define (every? . args)
235 (not (not (apply every args))))
236
237
238(with-test-prefix "nl-langinfo et al."
239
240 (pass-if "locale-day (1 arg)"
241 (every? equal?
242 %english-days
243 (map locale-day (map 1+ (iota 7)))))
244
245 (pass-if "locale-day (2 args)"
246 (every? equal?
247 %english-days
248 (map (lambda (day)
249 (locale-day day %c-locale))
250 (map 1+ (iota 7)))))
251
252 (pass-if "locale-day (2 args, using `%global-locale')"
253 (every? equal?
254 %english-days
255 (map (lambda (day)
256 (locale-day day %global-locale))
257 (map 1+ (iota 7)))))
258
259 (pass-if "locale-day (French)"
260 (under-french-locale-or-unresolved
261 (lambda ()
262 (let ((result (locale-day 3 %french-locale)))
263 (and (string? result)
264 (string-ci=? result "mardi"))))))
265
266 (pass-if "locale-day (French, using `%global-locale')"
267 ;; Make sure `%global-locale' captures the current locale settings as
268 ;; installed using `setlocale'.
269 (under-french-locale-or-unresolved
270 (lambda ()
271 (dynamic-wind
272 (lambda ()
273 (setlocale LC_TIME %french-locale-name))
274 (lambda ()
275 (let* ((fr (make-locale (list LC_MONETARY) "C" %global-locale))
276 (result (locale-day 3 fr)))
277 (setlocale LC_ALL "C")
278 (and (string? result)
279 (string-ci=? result "mardi"))))
280 (lambda ()
281 (setlocale LC_ALL "C"))))))
282
283 (pass-if "default locale"
284 ;; Make sure the default locale does not capture the current locale
285 ;; settings as installed using `setlocale'. The default locale should be
286 ;; "C".
287 (under-french-locale-or-unresolved
288 (lambda ()
289 (dynamic-wind
290 (lambda ()
291 (setlocale LC_ALL %french-locale-name))
292 (lambda ()
293 (let* ((locale (make-locale (list LC_MONETARY) "C"))
294 (result (locale-day 3 locale)))
295 (setlocale LC_ALL "C")
296 (and (string? result)
297 (string-ci=? result "Tuesday"))))
298 (lambda ()
299 (setlocale LC_ALL "C")))))))