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 (ice-9 format)
23 #:use-module (srfi srfi-1)
24 #:use-module (test-suite lib))
26 ;; Start from a pristine locale state.
27 (setlocale LC_ALL "C")
29 (define exception:locale-error
30 (cons 'system-error "Failed to install locale"))
34 (with-test-prefix "locale objects"
36 (pass-if "make-locale (2 args)"
37 (not (not (make-locale LC_ALL "C"))))
39 (pass-if "make-locale (2 args, list)"
40 (not (not (make-locale (list LC_COLLATE LC_MESSAGES) "C"))))
42 (pass-if "make-locale (3 args)"
43 (not (not (make-locale (list LC_COLLATE) "C"
44 (make-locale (list LC_MESSAGES) "C")))))
46 (pass-if-exception "make-locale with unknown locale" exception:locale-error
47 (make-locale LC_ALL "does-not-exist"))
50 (and (locale? (make-locale (list LC_ALL) "C"))
51 (locale? (make-locale (list LC_MESSAGES LC_NUMERIC) "C"
52 (make-locale (list LC_CTYPE) "C")))))
54 (pass-if "%global-locale"
55 (and (locale? %global-locale))
56 (locale? (make-locale (list LC_MONETARY) "C"
61 (with-test-prefix "text collation (English)"
63 (pass-if "string-locale<?"
64 (and (string-locale<? "hello" "world")
65 (string-locale<? "hello" "world"
66 (make-locale (list LC_COLLATE) "C"))))
68 (pass-if "char-locale<?"
69 (and (char-locale<? #\a #\b)
70 (char-locale<? #\a #\b (make-locale (list LC_COLLATE) "C"))))
72 (pass-if "string-locale-ci=?"
73 (and (string-locale-ci=? "Hello" "HELLO")
74 (string-locale-ci=? "Hello" "HELLO"
75 (make-locale (list LC_COLLATE) "C"))))
77 (pass-if "string-locale-ci<?"
78 (and (string-locale-ci<? "hello" "WORLD")
79 (string-locale-ci<? "hello" "WORLD"
80 (make-locale (list LC_COLLATE) "C")))))
83 (define %french-locale-name
86 (define %french-utf8-locale-name
89 (define %turkish-utf8-locale-name
92 (define %german-utf8-locale-name
95 (define %greek-utf8-locale-name
98 (define %american-english-locale-name
101 (define %french-locale
103 (make-locale (list LC_CTYPE LC_COLLATE LC_NUMERIC LC_TIME)
104 %french-locale-name)))
106 (define %french-utf8-locale
108 (make-locale (list LC_CTYPE LC_COLLATE LC_NUMERIC LC_TIME)
109 %french-utf8-locale-name)))
111 (define %german-utf8-locale
114 %german-utf8-locale-name)))
116 (define %greek-utf8-locale
119 %greek-utf8-locale-name)))
121 (define %turkish-utf8-locale
124 %turkish-utf8-locale-name)))
126 (define %american-english-locale
129 %american-english-locale-name)))
131 (define (under-locale-or-unresolved locale thunk)
132 ;; On non-GNU systems, an exception may be raised only when the locale is
133 ;; actually used rather than at `make-locale'-time. Thus, we must guard
136 (if (string-contains %host-type "-gnu")
138 (catch 'system-error thunk
140 (throw 'unresolved))))
141 (throw 'unresolved)))
143 (define (under-french-locale-or-unresolved thunk)
144 (under-locale-or-unresolved %french-locale thunk))
146 (define (under-french-utf8-locale-or-unresolved thunk)
147 (under-locale-or-unresolved %french-utf8-locale thunk))
149 (define (under-turkish-utf8-locale-or-unresolved thunk)
150 ;; FreeBSD 8.2, Solaris 2.10, and Darwin 8.11.0 have a broken tr_TR
151 ;; locale where `i' is mapped to uppercase `I' instead of `İ', so
152 ;; disable tests on that platform.
153 (if (or (string-contains %host-type "freebsd8")
154 (string-contains %host-type "solaris2.10")
155 (string-contains %host-type "darwin8"))
157 (under-locale-or-unresolved %turkish-utf8-locale thunk)))
159 (define (under-german-utf8-locale-or-unresolved thunk)
160 (under-locale-or-unresolved %german-utf8-locale thunk))
162 (define (under-greek-utf8-locale-or-unresolved thunk)
163 (under-locale-or-unresolved %greek-utf8-locale thunk))
165 (define (under-american-english-locale-or-unresolved thunk)
166 (under-locale-or-unresolved %american-english-locale thunk))
169 (with-test-prefix "text collation (French)"
171 (pass-if "string-locale<?"
172 (under-french-locale-or-unresolved
174 (string-locale<? "été" "hiver" %french-locale))))
176 (pass-if "char-locale<?"
177 (under-french-locale-or-unresolved
179 (char-locale<? #\é #\h %french-locale))))
181 (pass-if "string-locale-ci=?"
182 (under-french-locale-or-unresolved
184 (string-locale-ci=? "ÉTÉ" "été" %french-locale))))
186 (pass-if "string-locale-ci=? (2 args, wide strings)"
187 (under-french-utf8-locale-or-unresolved
189 ;; Note: Character `œ' is not part of Latin-1, so these are wide
193 (setlocale LC_ALL "fr_FR.UTF-8"))
195 (string-locale-ci=? "œuf" "ŒUF"))
197 (setlocale LC_ALL "C"))))))
199 (pass-if "string-locale-ci=? (3 args, wide strings)"
200 (under-french-utf8-locale-or-unresolved
202 (string-locale-ci=? "œuf" "ŒUF" %french-utf8-locale))))
204 (pass-if "string-locale-ci<>?"
205 (under-french-locale-or-unresolved
207 (and (string-locale-ci<? "été" "Hiver" %french-locale)
208 (string-locale-ci>? "HiVeR" "été" %french-locale)))))
210 (pass-if "string-locale-ci<>? (wide strings)"
211 (under-french-utf8-locale-or-unresolved
213 ;; One of the strings is UCS-4, the other is Latin-1.
214 (and (string-locale-ci<? "Œdème" "œuf" %french-utf8-locale)
215 (string-locale-ci>? "Œuf" "œdÈMe" %french-utf8-locale)))))
217 (pass-if "string-locale-ci<>? (wide and narrow strings)"
218 (under-french-utf8-locale-or-unresolved
220 ;; One of the strings is UCS-4, the other is Latin-1.
221 (and (string-locale-ci>? "Œdème" "odyssée" %french-utf8-locale)
222 (string-locale-ci<? "Odyssée" "œdème" %french-utf8-locale)))))
224 (pass-if "char-locale-ci<>?"
225 (under-french-locale-or-unresolved
227 (and (char-locale-ci<? #\é #\H %french-locale)
228 (char-locale-ci>? #\h #\É %french-locale)))))
230 (pass-if "char-locale-ci<>? (wide)"
231 (under-french-utf8-locale-or-unresolved
233 (and (char-locale-ci<? #\o #\œ %french-utf8-locale)
234 (char-locale-ci>? #\Œ #\e %french-utf8-locale))))))
237 (with-test-prefix "text collation (German)"
239 (pass-if "string-locale-ci=?"
240 (under-german-utf8-locale-or-unresolved
242 (let ((de (make-locale LC_ALL %german-utf8-locale-name)))
243 (string-locale-ci=? "Straße" "STRASSE"))))))
246 (with-test-prefix "text collation (Greek)"
248 (pass-if "string-locale-ci=?"
249 (under-greek-utf8-locale-or-unresolved
251 (let ((gr (make-locale LC_ALL %greek-utf8-locale-name)))
252 (string-locale-ci=? "ΧΑΟΣ" "χαος" gr))))))
255 (with-test-prefix "character mapping"
257 (pass-if "char-locale-downcase"
258 (and (eq? #\a (char-locale-downcase #\A))
259 (eq? #\a (char-locale-downcase #\A (make-locale LC_ALL "C")))))
261 (pass-if "char-locale-upcase"
262 (and (eq? #\Z (char-locale-upcase #\z))
263 (eq? #\Z (char-locale-upcase #\z (make-locale LC_ALL "C")))))
265 (pass-if "char-locale-titlecase"
266 (and (eq? #\T (char-locale-titlecase #\t))
267 (eq? #\T (char-locale-titlecase #\t (make-locale LC_ALL "C")))))
269 (pass-if "char-locale-titlecase Dž"
270 (and (eq? #\762 (char-locale-titlecase #\763))
271 (eq? #\762 (char-locale-titlecase #\763 (make-locale LC_ALL "C")))))
273 (pass-if "char-locale-upcase Turkish"
274 (under-turkish-utf8-locale-or-unresolved
276 (eq? #\İ (char-locale-upcase #\i %turkish-utf8-locale)))))
278 (pass-if "char-locale-downcase Turkish"
279 (under-turkish-utf8-locale-or-unresolved
281 (eq? #\i (char-locale-downcase #\İ %turkish-utf8-locale))))))
284 (with-test-prefix "string mapping"
286 (pass-if "string-locale-downcase"
287 (and (string=? "a" (string-locale-downcase "A"))
288 (string=? "a" (string-locale-downcase "A" (make-locale LC_ALL "C")))))
290 (pass-if "string-locale-upcase"
291 (and (string=? "Z" (string-locale-upcase "z"))
292 (string=? "Z" (string-locale-upcase "z" (make-locale LC_ALL "C")))))
294 (pass-if "string-locale-titlecase"
295 (and (string=? "Hello, World" (string-locale-titlecase "hello, world"))
296 (string=? "Hello, World" (string-locale-titlecase
297 "hello, world" (make-locale LC_ALL "C")))))
299 (pass-if "string-locale-upcase German"
300 (under-german-utf8-locale-or-unresolved
302 (let ((de (make-locale LC_ALL %german-utf8-locale-name)))
304 (string-locale-upcase "Straße" de))))))
306 (pass-if "string-locale-upcase Greek"
307 (under-greek-utf8-locale-or-unresolved
309 (let ((el (make-locale LC_ALL %greek-utf8-locale-name)))
311 (string-locale-upcase "χαος" el))))))
313 (pass-if "string-locale-upcase Greek (two sigmas)"
314 (under-greek-utf8-locale-or-unresolved
316 (let ((el (make-locale LC_ALL %greek-utf8-locale-name)))
318 (string-locale-upcase "Γειά σας" el))))))
320 (pass-if "string-locale-downcase Greek"
321 (under-greek-utf8-locale-or-unresolved
323 (let ((el (make-locale LC_ALL %greek-utf8-locale-name)))
325 (string-locale-downcase "ΧΑΟΣ" el))))))
327 (pass-if "string-locale-downcase Greek (two sigmas)"
328 (under-greek-utf8-locale-or-unresolved
330 (let ((el (make-locale LC_ALL %greek-utf8-locale-name)))
332 (string-locale-downcase "ΓΕΙΆ ΣΑΣ" el))))))
334 (pass-if "string-locale-upcase Turkish"
335 (under-turkish-utf8-locale-or-unresolved
337 (string=? "İI" (string-locale-upcase "iı" %turkish-utf8-locale)))))
339 (pass-if "string-locale-downcase Turkish"
340 (under-turkish-utf8-locale-or-unresolved
342 (string=? "iı" (string-locale-downcase "İI" %turkish-utf8-locale))))))
345 (with-test-prefix "number parsing"
347 (pass-if "locale-string->integer"
348 (call-with-values (lambda () (locale-string->integer "123"))
349 (lambda (result char-count)
350 (and (equal? result 123)
351 (equal? char-count 3)))))
353 (pass-if "locale-string->inexact"
356 (locale-string->inexact "123.456"
357 (make-locale (list LC_NUMERIC) "C")))
358 (lambda (result char-count)
359 (and (equal? result 123.456)
360 (equal? char-count 7)))))
362 (pass-if "locale-string->inexact (French)"
363 (under-french-locale-or-unresolved
367 (locale-string->inexact "123,456" %french-locale))
368 (lambda (result char-count)
369 (and (equal? result 123.456)
370 (equal? char-count 7))))))))
377 (setlocale LC_ALL "C")
378 (define %c-locale (make-locale LC_ALL "C"))
380 (define %english-days
381 '("Sunday" "Monday" "Tuesday" "Wednesday" "Thursday" "Friday" "Saturday"))
383 (define (every? . args)
384 (not (not (apply every args))))
387 (with-test-prefix "nl-langinfo et al."
389 (pass-if "locale-day (1 arg)"
392 (map locale-day (map 1+ (iota 7)))))
394 (pass-if "locale-day (2 args)"
398 (locale-day day %c-locale))
401 (pass-if "locale-day (2 args, using `%global-locale')"
405 (locale-day day %global-locale))
408 (pass-if "locale-day (French)"
409 (under-french-locale-or-unresolved
411 (let ((result (locale-day 3 %french-locale)))
412 (and (string? result)
413 (string-ci=? result "mardi"))))))
415 (pass-if "locale-day (French, using `%global-locale')"
416 ;; Make sure `%global-locale' captures the current locale settings as
417 ;; installed using `setlocale'.
418 (under-french-locale-or-unresolved
422 (setlocale LC_TIME %french-locale-name))
424 (let* ((fr (make-locale (list LC_MONETARY) "C" %global-locale))
425 (result (locale-day 3 fr)))
426 (setlocale LC_ALL "C")
427 (and (string? result)
428 (string-ci=? result "mardi"))))
430 (setlocale LC_ALL "C"))))))
432 (pass-if "default locale"
433 ;; Make sure the default locale does not capture the current locale
434 ;; settings as installed using `setlocale'. The default locale should be
436 (under-french-locale-or-unresolved
440 (setlocale LC_ALL %french-locale-name))
442 (let* ((locale (make-locale (list LC_MONETARY) "C"))
443 (result (locale-day 3 locale)))
444 (setlocale LC_ALL "C")
445 (and (string? result)
446 (string-ci=? result "Tuesday"))))
448 (setlocale LC_ALL "C")))))))
455 (with-test-prefix "number->locale-string"
457 ;; We assume the global locale is "C" at this point.
459 (with-test-prefix "C"
461 (pass-if "no thousand separator"
462 ;; Unlike in English, the "C" locale has no thousand separator.
463 ;; If this doesn't hold, the following tests will fail.
464 (string=? "" (locale-thousands-separator)))
467 (string=? "123456" (number->locale-string 123456)))
470 (string=? "1234.567" (number->locale-string 1234.567)))
472 (pass-if "fraction, 1 digit"
473 (string=? "1234.5" (number->locale-string 1234.567 1))))
475 (with-test-prefix "French"
478 (under-french-locale-or-unresolved
480 (let ((fr (make-locale LC_ALL %french-locale-name)))
481 (string=? "123 456" (number->locale-string 123456 #t fr))))))
484 (under-french-locale-or-unresolved
486 (let ((fr (make-locale LC_ALL %french-locale-name)))
487 (string=? "1 234,567" (number->locale-string 1234.567 #t fr))))))
489 (pass-if "fraction, 1 digit"
490 (under-french-locale-or-unresolved
492 (let ((fr (make-locale LC_ALL %french-locale-name)))
494 (number->locale-string 1234.567 1 fr))))))))
496 (with-test-prefix "format ~h"
498 (with-test-prefix "French"
500 (pass-if "12345.5678"
501 (under-french-locale-or-unresolved
503 (string=? "12 345,6789"
504 (format #f "~:h" 12345.6789 %french-locale))))))
506 (with-test-prefix "English"
508 (pass-if "12345.5678"
509 (under-american-english-locale-or-unresolved
511 (string=? "12,345.6789"
512 (format #f "~:h" 12345.6789
513 %american-english-locale)))))))
515 (with-test-prefix "monetary-amount->locale-string"
517 (with-test-prefix "French"
520 (under-french-locale-or-unresolved
522 (let ((fr (make-locale LC_ALL %french-locale-name)))
523 (string=? "123 456 +EUR"
524 (monetary-amount->locale-string 123456 #f fr))))))
527 (under-french-locale-or-unresolved
529 (let ((fr (make-locale LC_ALL %french-locale-name)))
530 (string=? "1 234,56 EUR "
531 (monetary-amount->locale-string 1234.567 #t fr))))))))