1 ;;;; i18n.test --- Exercise the i18n API. -*- coding: utf-8; mode: scheme; -*-
3 ;;;; Copyright (C) 2006, 2007, 2009, 2010, 2011, 2012 Free Software Foundation, Inc.
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
9 ;;;; version 3 of the License, or (at your option) any later version.
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.
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
20 (define-module (test-suite i18n)
21 :use-module (ice-9 i18n)
22 :use-module (srfi srfi-1)
23 :use-module (test-suite lib))
25 ;; Start from a pristine locale state.
26 (setlocale LC_ALL "C")
28 (define exception:locale-error
29 (cons 'system-error "Failed to install locale"))
33 (with-test-prefix "locale objects"
35 (pass-if "make-locale (2 args)"
36 (not (not (make-locale LC_ALL "C"))))
38 (pass-if "make-locale (2 args, list)"
39 (not (not (make-locale (list LC_COLLATE LC_MESSAGES) "C"))))
41 (pass-if "make-locale (3 args)"
42 (not (not (make-locale (list LC_COLLATE) "C"
43 (make-locale (list LC_MESSAGES) "C")))))
45 (pass-if-exception "make-locale with unknown locale" exception:locale-error
46 (make-locale LC_ALL "does-not-exist"))
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")))))
53 (pass-if "%global-locale"
54 (and (locale? %global-locale))
55 (locale? (make-locale (list LC_MONETARY) "C"
60 (with-test-prefix "text collation (English)"
62 (pass-if "string-locale<?"
63 (and (string-locale<? "hello" "world")
64 (string-locale<? "hello" "world"
65 (make-locale (list LC_COLLATE) "C"))))
67 (pass-if "char-locale<?"
68 (and (char-locale<? #\a #\b)
69 (char-locale<? #\a #\b (make-locale (list LC_COLLATE) "C"))))
71 (pass-if "string-locale-ci=?"
72 (and (string-locale-ci=? "Hello" "HELLO")
73 (string-locale-ci=? "Hello" "HELLO"
74 (make-locale (list LC_COLLATE) "C"))))
76 (pass-if "string-locale-ci<?"
77 (and (string-locale-ci<? "hello" "WORLD")
78 (string-locale-ci<? "hello" "WORLD"
79 (make-locale (list LC_COLLATE) "C")))))
82 (define %french-locale-name
85 (define %french-utf8-locale-name
88 (define %turkish-utf8-locale-name
91 (define %german-utf8-locale-name
94 (define %greek-utf8-locale-name
97 (define %french-locale
99 (make-locale (list LC_CTYPE LC_COLLATE LC_NUMERIC LC_TIME)
100 %french-locale-name)))
102 (define %french-utf8-locale
104 (make-locale (list LC_CTYPE LC_COLLATE LC_NUMERIC LC_TIME)
105 %french-utf8-locale-name)))
107 (define %german-utf8-locale
110 %german-utf8-locale-name)))
112 (define %greek-utf8-locale
115 %greek-utf8-locale-name)))
117 (define %turkish-utf8-locale
120 %turkish-utf8-locale-name)))
122 (define (under-locale-or-unresolved locale thunk)
123 ;; On non-GNU systems, an exception may be raised only when the locale is
124 ;; actually used rather than at `make-locale'-time. Thus, we must guard
127 (if (string-contains %host-type "-gnu")
129 (catch 'system-error thunk
131 (throw 'unresolved))))
132 (throw 'unresolved)))
134 (define (under-french-locale-or-unresolved thunk)
135 (under-locale-or-unresolved %french-locale thunk))
137 (define (under-french-utf8-locale-or-unresolved thunk)
138 (under-locale-or-unresolved %french-utf8-locale thunk))
140 (define (under-turkish-utf8-locale-or-unresolved thunk)
141 ;; FreeBSD 8.2, Solaris 2.10, and Darwin 8.11.0 have a broken tr_TR
142 ;; locale where `i' is mapped to uppercase `I' instead of `İ', so
143 ;; disable tests on that platform.
144 (if (or (string-contains %host-type "freebsd8")
145 (string-contains %host-type "solaris2.10")
146 (string-contains %host-type "darwin8"))
148 (under-locale-or-unresolved %turkish-utf8-locale thunk)))
150 (define (under-german-utf8-locale-or-unresolved thunk)
151 (under-locale-or-unresolved %german-utf8-locale thunk))
153 (define (under-greek-utf8-locale-or-unresolved thunk)
154 (under-locale-or-unresolved %greek-utf8-locale thunk))
156 (with-test-prefix "text collation (French)"
158 (pass-if "string-locale<?"
159 (under-french-locale-or-unresolved
161 (string-locale<? "été" "hiver" %french-locale))))
163 (pass-if "char-locale<?"
164 (under-french-locale-or-unresolved
166 (char-locale<? #\é #\h %french-locale))))
168 (pass-if "string-locale-ci=?"
169 (under-french-locale-or-unresolved
171 (string-locale-ci=? "ÉTÉ" "été" %french-locale))))
173 (pass-if "string-locale-ci=? (2 args, wide strings)"
174 (under-french-utf8-locale-or-unresolved
176 ;; Note: Character `œ' is not part of Latin-1, so these are wide
180 (setlocale LC_ALL "fr_FR.UTF-8"))
182 (string-locale-ci=? "œuf" "ŒUF"))
184 (setlocale LC_ALL "C"))))))
186 (pass-if "string-locale-ci=? (3 args, wide strings)"
187 (under-french-utf8-locale-or-unresolved
189 (string-locale-ci=? "œuf" "ŒUF" %french-utf8-locale))))
191 (pass-if "string-locale-ci<>?"
192 (under-french-locale-or-unresolved
194 (and (string-locale-ci<? "été" "Hiver" %french-locale)
195 (string-locale-ci>? "HiVeR" "été" %french-locale)))))
197 (pass-if "string-locale-ci<>? (wide strings)"
198 (under-french-utf8-locale-or-unresolved
200 ;; One of the strings is UCS-4, the other is Latin-1.
201 (and (string-locale-ci<? "Œdème" "œuf" %french-utf8-locale)
202 (string-locale-ci>? "Œuf" "œdÈMe" %french-utf8-locale)))))
204 (pass-if "string-locale-ci<>? (wide and narrow strings)"
205 (under-french-utf8-locale-or-unresolved
207 ;; One of the strings is UCS-4, the other is Latin-1.
208 (and (string-locale-ci>? "Œdème" "odyssée" %french-utf8-locale)
209 (string-locale-ci<? "Odyssée" "œdème" %french-utf8-locale)))))
211 (pass-if "char-locale-ci<>?"
212 (under-french-locale-or-unresolved
214 (and (char-locale-ci<? #\é #\H %french-locale)
215 (char-locale-ci>? #\h #\É %french-locale)))))
217 (pass-if "char-locale-ci<>? (wide)"
218 (under-french-utf8-locale-or-unresolved
220 (and (char-locale-ci<? #\o #\œ %french-utf8-locale)
221 (char-locale-ci>? #\Œ #\e %french-utf8-locale))))))
224 (with-test-prefix "text collation (German)"
226 (pass-if "string-locale-ci=?"
227 (under-german-utf8-locale-or-unresolved
229 (let ((de (make-locale LC_ALL %german-utf8-locale-name)))
230 (string-locale-ci=? "Straße" "STRASSE"))))))
233 (with-test-prefix "text collation (Greek)"
235 (pass-if "string-locale-ci=?"
236 (under-greek-utf8-locale-or-unresolved
238 (let ((gr (make-locale LC_ALL %greek-utf8-locale-name)))
239 (string-locale-ci=? "ΧΑΟΣ" "χαος" gr))))))
242 (with-test-prefix "character mapping"
244 (pass-if "char-locale-downcase"
245 (and (eq? #\a (char-locale-downcase #\A))
246 (eq? #\a (char-locale-downcase #\A (make-locale LC_ALL "C")))))
248 (pass-if "char-locale-upcase"
249 (and (eq? #\Z (char-locale-upcase #\z))
250 (eq? #\Z (char-locale-upcase #\z (make-locale LC_ALL "C")))))
252 (pass-if "char-locale-titlecase"
253 (and (eq? #\T (char-locale-titlecase #\t))
254 (eq? #\T (char-locale-titlecase #\t (make-locale LC_ALL "C")))))
256 (pass-if "char-locale-titlecase Dž"
257 (and (eq? #\762 (char-locale-titlecase #\763))
258 (eq? #\762 (char-locale-titlecase #\763 (make-locale LC_ALL "C")))))
260 (pass-if "char-locale-upcase Turkish"
261 (under-turkish-utf8-locale-or-unresolved
263 (eq? #\İ (char-locale-upcase #\i %turkish-utf8-locale)))))
265 (pass-if "char-locale-downcase Turkish"
266 (under-turkish-utf8-locale-or-unresolved
268 (eq? #\i (char-locale-downcase #\İ %turkish-utf8-locale))))))
271 (with-test-prefix "string mapping"
273 (pass-if "string-locale-downcase"
274 (and (string=? "a" (string-locale-downcase "A"))
275 (string=? "a" (string-locale-downcase "A" (make-locale LC_ALL "C")))))
277 (pass-if "string-locale-upcase"
278 (and (string=? "Z" (string-locale-upcase "z"))
279 (string=? "Z" (string-locale-upcase "z" (make-locale LC_ALL "C")))))
281 (pass-if "string-locale-titlecase"
282 (and (string=? "Hello, World" (string-locale-titlecase "hello, world"))
283 (string=? "Hello, World" (string-locale-titlecase
284 "hello, world" (make-locale LC_ALL "C")))))
286 (pass-if "string-locale-upcase German"
287 (under-german-utf8-locale-or-unresolved
289 (let ((de (make-locale LC_ALL %german-utf8-locale-name)))
291 (string-locale-upcase "Straße" de))))))
293 (pass-if "string-locale-upcase Greek"
294 (under-greek-utf8-locale-or-unresolved
296 (let ((el (make-locale LC_ALL %greek-utf8-locale-name)))
298 (string-locale-upcase "χαος" el))))))
300 (pass-if "string-locale-upcase Greek (two sigmas)"
301 (under-greek-utf8-locale-or-unresolved
303 (let ((el (make-locale LC_ALL %greek-utf8-locale-name)))
305 (string-locale-upcase "Γειά σας" el))))))
307 (pass-if "string-locale-downcase Greek"
308 (under-greek-utf8-locale-or-unresolved
310 (let ((el (make-locale LC_ALL %greek-utf8-locale-name)))
312 (string-locale-downcase "ΧΑΟΣ" el))))))
314 (pass-if "string-locale-downcase Greek (two sigmas)"
315 (under-greek-utf8-locale-or-unresolved
317 (let ((el (make-locale LC_ALL %greek-utf8-locale-name)))
319 (string-locale-downcase "ΓΕΙΆ ΣΑΣ" el))))))
321 (pass-if "string-locale-upcase Turkish"
322 (under-turkish-utf8-locale-or-unresolved
324 (string=? "İI" (string-locale-upcase "iı" %turkish-utf8-locale)))))
326 (pass-if "string-locale-downcase Turkish"
327 (under-turkish-utf8-locale-or-unresolved
329 (string=? "iı" (string-locale-downcase "İI" %turkish-utf8-locale))))))
332 (with-test-prefix "number parsing"
334 (pass-if "locale-string->integer"
335 (call-with-values (lambda () (locale-string->integer "123"))
336 (lambda (result char-count)
337 (and (equal? result 123)
338 (equal? char-count 3)))))
340 (pass-if "locale-string->inexact"
343 (locale-string->inexact "123.456"
344 (make-locale (list LC_NUMERIC) "C")))
345 (lambda (result char-count)
346 (and (equal? result 123.456)
347 (equal? char-count 7)))))
349 (pass-if "locale-string->inexact (French)"
350 (under-french-locale-or-unresolved
354 (locale-string->inexact "123,456" %french-locale))
355 (lambda (result char-count)
356 (and (equal? result 123.456)
357 (equal? char-count 7))))))))
364 (setlocale LC_ALL "C")
365 (define %c-locale (make-locale LC_ALL "C"))
367 (define %english-days
368 '("Sunday" "Monday" "Tuesday" "Wednesday" "Thursday" "Friday" "Saturday"))
370 (define (every? . args)
371 (not (not (apply every args))))
374 (with-test-prefix "nl-langinfo et al."
376 (pass-if "locale-day (1 arg)"
379 (map locale-day (map 1+ (iota 7)))))
381 (pass-if "locale-day (2 args)"
385 (locale-day day %c-locale))
388 (pass-if "locale-day (2 args, using `%global-locale')"
392 (locale-day day %global-locale))
395 (pass-if "locale-day (French)"
396 (under-french-locale-or-unresolved
398 (let ((result (locale-day 3 %french-locale)))
399 (and (string? result)
400 (string-ci=? result "mardi"))))))
402 (pass-if "locale-day (French, using `%global-locale')"
403 ;; Make sure `%global-locale' captures the current locale settings as
404 ;; installed using `setlocale'.
405 (under-french-locale-or-unresolved
409 (setlocale LC_TIME %french-locale-name))
411 (let* ((fr (make-locale (list LC_MONETARY) "C" %global-locale))
412 (result (locale-day 3 fr)))
413 (setlocale LC_ALL "C")
414 (and (string? result)
415 (string-ci=? result "mardi"))))
417 (setlocale LC_ALL "C"))))))
419 (pass-if "default locale"
420 ;; Make sure the default locale does not capture the current locale
421 ;; settings as installed using `setlocale'. The default locale should be
423 (under-french-locale-or-unresolved
427 (setlocale LC_ALL %french-locale-name))
429 (let* ((locale (make-locale (list LC_MONETARY) "C"))
430 (result (locale-day 3 locale)))
431 (setlocale LC_ALL "C")
432 (and (string? result)
433 (string-ci=? result "Tuesday"))))
435 (setlocale LC_ALL "C")))))))
442 (with-test-prefix "number->locale-string"
444 ;; We assume the global locale is "C" at this point.
446 (with-test-prefix "C"
448 (pass-if "no thousand separator"
449 ;; Unlike in English, the "C" locale has no thousand separator.
450 ;; If this doesn't hold, the following tests will fail.
451 (string=? "" (locale-thousands-separator)))
454 (string=? "123456" (number->locale-string 123456)))
457 (string=? "1234.567" (number->locale-string 1234.567)))
459 (pass-if "fraction, 1 digit"
460 (string=? "1234.5" (number->locale-string 1234.567 1))))
462 (with-test-prefix "French"
465 (under-french-locale-or-unresolved
467 (let ((fr (make-locale LC_ALL %french-locale-name)))
468 (string=? "123 456" (number->locale-string 123456 #t fr))))))
471 (under-french-locale-or-unresolved
473 (let ((fr (make-locale LC_ALL %french-locale-name)))
474 (string=? "1 234,567" (number->locale-string 1234.567 #t fr))))))
476 (pass-if "fraction, 1 digit"
477 (under-french-locale-or-unresolved
479 (let ((fr (make-locale LC_ALL %french-locale-name)))
481 (number->locale-string 1234.567 1 fr))))))))