1 /* Test of gl_locale_name function and its variants.
2 Copyright (C) 2007-2009 Free Software Foundation, Inc.
4 This program is free software: you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation; either version 3 of the License, or
7 (at your option) any later version.
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
14 You should have received a copy of the GNU General Public License
15 along with this program. If not, see <http://www.gnu.org/licenses/>. */
17 /* Written by Bruno Haible <bruno@clisp.org>, 2007. */
21 #include "localename.h"
29 static struct { int cat; int mask; const char *string; } const categories[] =
31 { LC_CTYPE, LC_CTYPE_MASK, "LC_CTYPE" },
32 { LC_NUMERIC, LC_NUMERIC_MASK, "LC_NUMERIC" },
33 { LC_TIME, LC_TIME_MASK, "LC_TIME" },
34 { LC_COLLATE, LC_COLLATE_MASK, "LC_COLLATE" },
35 { LC_MONETARY, LC_MONETARY_MASK, "LC_MONETARY" },
36 { LC_MESSAGES, LC_MESSAGES_MASK, "LC_MESSAGES" }
38 , { LC_PAPER, LC_PAPER_MASK, "LC_PAPER" }
41 , { LC_NAME, LC_NAME_MASK, "LC_NAME" }
44 , { LC_ADDRESS, LC_ADDRESS_MASK, "LC_ADDRESS" }
47 , { LC_TELEPHONE, LC_TELEPHONE_MASK, "LC_TELEPHONE" }
49 # ifdef LC_MEASUREMENT
50 , { LC_MEASUREMENT, LC_MEASUREMENT_MASK, "LC_MEASUREMENT" }
52 # ifdef LC_IDENTIFICATION
53 , { LC_IDENTIFICATION, LC_IDENTIFICATION_MASK, "LC_IDENTIFICATION" }
57 /* Test the gl_locale_name() function. */
59 test_locale_name (void)
63 /* Check that gl_locale_name returns non-NULL. */
64 ASSERT (gl_locale_name (LC_MESSAGES, "LC_MESSAGES") != NULL);
66 /* Get into a defined state, */
67 setlocale (LC_ALL, "en_US.UTF-8");
69 uselocale (LC_GLOBAL_LOCALE);
72 /* Check that when all environment variables are unset,
73 gl_locale_name returns the default locale. */
75 unsetenv ("LC_CTYPE");
76 unsetenv ("LC_MESSAGES");
77 unsetenv ("LC_NUMERIC");
79 setlocale (LC_ALL, "");
80 ASSERT (strcmp (gl_locale_name (LC_MESSAGES, "LC_MESSAGES"),
81 gl_locale_name_default ()) == 0);
82 ASSERT (strcmp (gl_locale_name (LC_NUMERIC, "LC_NUMERIC"),
83 gl_locale_name_default ()) == 0);
85 /* Check that an empty environment variable is treated like an unset
86 environment variable. */
88 setenv ("LC_ALL", "", 1);
89 unsetenv ("LC_CTYPE");
90 unsetenv ("LC_MESSAGES");
92 setlocale (LC_ALL, "");
93 ASSERT (strcmp (gl_locale_name (LC_MESSAGES, "LC_MESSAGES"),
94 gl_locale_name_default ()) == 0);
97 setenv ("LC_CTYPE", "", 1);
98 unsetenv ("LC_MESSAGES");
100 setlocale (LC_ALL, "");
101 ASSERT (strcmp (gl_locale_name (LC_MESSAGES, "LC_MESSAGES"),
102 gl_locale_name_default ()) == 0);
105 unsetenv ("LC_CTYPE");
106 setenv ("LC_MESSAGES", "", 1);
108 setlocale (LC_ALL, "");
109 ASSERT (strcmp (gl_locale_name (LC_MESSAGES, "LC_MESSAGES"),
110 gl_locale_name_default ()) == 0);
113 unsetenv ("LC_CTYPE");
114 unsetenv ("LC_MESSAGES");
115 setenv ("LANG", "", 1);
116 setlocale (LC_ALL, "");
117 ASSERT (strcmp (gl_locale_name (LC_MESSAGES, "LC_MESSAGES"),
118 gl_locale_name_default ()) == 0);
120 /* Check that LC_ALL overrides the others, and LANG is overridden by the
123 setenv ("LC_ALL", "C", 1);
124 unsetenv ("LC_CTYPE");
125 unsetenv ("LC_MESSAGES");
127 setlocale (LC_ALL, "");
128 ASSERT (strcmp (gl_locale_name (LC_MESSAGES, "LC_MESSAGES"), "C") == 0);
131 setenv ("LC_CTYPE", "C", 1);
132 setenv ("LC_MESSAGES", "C", 1);
134 setlocale (LC_ALL, "");
135 ASSERT (strcmp (gl_locale_name (LC_MESSAGES, "LC_MESSAGES"), "C") == 0);
138 unsetenv ("LC_CTYPE");
139 unsetenv ("LC_MESSAGES");
140 setenv ("LANG", "C", 1);
141 setlocale (LC_ALL, "");
142 ASSERT (strcmp (gl_locale_name (LC_MESSAGES, "LC_MESSAGES"), "C") == 0);
144 /* Check mixed situations. */
147 unsetenv ("LC_CTYPE");
148 setenv ("LC_MESSAGES", "fr_FR.UTF-8", 1);
149 setenv ("LANG", "de_DE.UTF-8", 1);
150 if (setlocale (LC_ALL, "") != NULL)
152 name = gl_locale_name (LC_CTYPE, "LC_CTYPE");
153 ASSERT (strcmp (name, "de_DE.UTF-8") == 0);
154 name = gl_locale_name (LC_MESSAGES, "LC_MESSAGES");
155 ASSERT (strcmp (name, "fr_FR.UTF-8") == 0);
159 unsetenv ("LC_CTYPE");
160 setenv ("LC_MESSAGES", "fr_FR.UTF-8", 1);
162 if (setlocale (LC_ALL, "") != NULL)
164 name = gl_locale_name (LC_CTYPE, "LC_CTYPE");
165 ASSERT (strcmp (name, gl_locale_name_default ()) == 0);
166 name = gl_locale_name (LC_MESSAGES, "LC_MESSAGES");
167 ASSERT (strcmp (name, "fr_FR.UTF-8") == 0);
171 /* Check that gl_locale_name considers the thread locale. */
173 locale_t locale = newlocale (LC_ALL_MASK, "fr_FR.UTF-8", NULL);
177 name = gl_locale_name (LC_CTYPE, "LC_CTYPE");
178 ASSERT (strcmp (name, "fr_FR.UTF-8") == 0);
179 name = gl_locale_name (LC_MESSAGES, "LC_MESSAGES");
180 ASSERT (strcmp (name, "fr_FR.UTF-8") == 0);
184 /* Check that gl_locale_name distinguishes different categories of the
185 thread locale, and that the name is the right one for each. */
189 for (i = 0; i < SIZEOF (categories); i++)
191 int category_mask = categories[i].mask;
192 locale_t locale = newlocale (LC_ALL_MASK, "fr_FR.UTF-8", NULL);
195 locale = newlocale (category_mask, "de_DE.UTF-8", locale);
201 for (j = 0; j < SIZEOF (categories); j++)
204 gl_locale_name (categories[j].cat, categories[j].string);
206 ASSERT (strcmp (name_j, "de_DE.UTF-8") == 0);
208 ASSERT (strcmp (name_j, "fr_FR.UTF-8") == 0);
217 /* Test the gl_locale_name_thread() function. */
219 test_locale_name_thread (void)
221 /* Get into a defined state, */
222 setlocale (LC_ALL, "en_US.UTF-8");
225 /* Check that gl_locale_name_thread returns NULL when no thread locale is
227 uselocale (LC_GLOBAL_LOCALE);
228 ASSERT (gl_locale_name_thread (LC_CTYPE, "LC_CTYPE") == NULL);
229 ASSERT (gl_locale_name_thread (LC_MESSAGES, "LC_MESSAGES") == NULL);
231 /* Check that gl_locale_name_thread considers the thread locale. */
233 locale_t locale = newlocale (LC_ALL_MASK, "fr_FR.UTF-8", NULL);
239 name = gl_locale_name_thread (LC_CTYPE, "LC_CTYPE");
240 ASSERT (strcmp (name, "fr_FR.UTF-8") == 0);
241 name = gl_locale_name_thread (LC_MESSAGES, "LC_MESSAGES");
242 ASSERT (strcmp (name, "fr_FR.UTF-8") == 0);
246 /* Check that gl_locale_name_thread distinguishes different categories of the
247 thread locale, and that the name is the right one for each. */
251 for (i = 0; i < SIZEOF (categories); i++)
253 int category_mask = categories[i].mask;
254 locale_t locale = newlocale (LC_ALL_MASK, "fr_FR.UTF-8", NULL);
257 locale = newlocale (category_mask, "de_DE.UTF-8", locale);
263 for (j = 0; j < SIZEOF (categories); j++)
266 gl_locale_name_thread (categories[j].cat,
267 categories[j].string);
269 ASSERT (strcmp (name_j, "de_DE.UTF-8") == 0);
271 ASSERT (strcmp (name_j, "fr_FR.UTF-8") == 0);
278 /* Check that gl_locale_name_thread returns a string that is allocated with
279 indefinite extent. */
281 /* Try many locale names in turn, in order to defeat possible caches. */
282 static const char * const choices[] =
388 /* Remember which locales are available. */
389 unsigned char /* bool */ available[SIZEOF (choices)];
390 /* Array of remembered results of gl_locale_name_thread. */
391 const char *unsaved_names[SIZEOF (choices)][SIZEOF (categories)];
392 /* Array of remembered results of gl_locale_name_thread, stored in safe
394 char *saved_names[SIZEOF (choices)][SIZEOF (categories)];
397 for (j = 0; j < SIZEOF (choices); j++)
399 locale_t locale = newlocale (LC_ALL_MASK, choices[j], NULL);
400 available[j] = (locale != NULL);
406 for (i = 0; i < SIZEOF (categories); i++)
408 unsaved_names[j][i] = gl_locale_name_thread (categories[i].cat, categories[i].string);
409 saved_names[j][i] = strdup (unsaved_names[j][i]);
411 uselocale (LC_GLOBAL_LOCALE);
415 /* Verify the unsaved_names are still valid. */
416 for (j = 0; j < SIZEOF (choices); j++)
420 for (i = 0; i < SIZEOF (categories); i++)
421 ASSERT (strcmp (unsaved_names[j][i], saved_names[j][i]) == 0);
423 /* Allocate many locales, without freeing them. This is an attempt at
424 overwriting as much of the previously allocated memory as possible. */
425 for (j = SIZEOF (choices); j > 0; )
430 locale_t locale = newlocale (LC_ALL_MASK, choices[j], NULL);
433 ASSERT (locale != NULL);
435 for (i = 0; i < SIZEOF (categories); i++)
437 const char *name = gl_locale_name_thread (categories[i].cat, categories[i].string);
438 ASSERT (strcmp (unsaved_names[j][i], name) == 0);
440 uselocale (LC_GLOBAL_LOCALE);
443 /* Verify the unsaved_names are still valid. */
444 for (j = 0; j < SIZEOF (choices); j++)
448 for (i = 0; i < SIZEOF (categories); i++)
449 ASSERT (strcmp (unsaved_names[j][i], saved_names[j][i]) == 0);
453 /* Check that gl_locale_name_thread always returns NULL. */
454 ASSERT (gl_locale_name_thread (LC_CTYPE, "LC_CTYPE") == NULL);
455 ASSERT (gl_locale_name_thread (LC_MESSAGES, "LC_MESSAGES") == NULL);
459 /* Test the gl_locale_name_posix() function. */
461 test_locale_name_posix (void)
465 /* Get into a defined state, */
466 setlocale (LC_ALL, "en_US.UTF-8");
468 uselocale (LC_GLOBAL_LOCALE);
471 /* Check that when all environment variables are unset,
472 gl_locale_name_posix returns either NULL or the default locale. */
474 unsetenv ("LC_CTYPE");
475 unsetenv ("LC_MESSAGES");
476 unsetenv ("LC_NUMERIC");
478 setlocale (LC_ALL, "");
479 name = gl_locale_name_posix (LC_MESSAGES, "LC_MESSAGES");
480 ASSERT (name == NULL || strcmp (name, gl_locale_name_default ()) == 0);
481 name = gl_locale_name_posix (LC_NUMERIC, "LC_NUMERIC");
482 ASSERT (name == NULL || strcmp (name, gl_locale_name_default ()) == 0);
484 /* Check that an empty environment variable is treated like an unset
485 environment variable. */
487 setenv ("LC_ALL", "", 1);
488 unsetenv ("LC_CTYPE");
489 unsetenv ("LC_MESSAGES");
491 setlocale (LC_ALL, "");
492 name = gl_locale_name_posix (LC_MESSAGES, "LC_MESSAGES");
493 ASSERT (name == NULL || strcmp (name, gl_locale_name_default ()) == 0);
496 setenv ("LC_CTYPE", "", 1);
497 unsetenv ("LC_MESSAGES");
499 setlocale (LC_ALL, "");
500 name = gl_locale_name_posix (LC_MESSAGES, "LC_MESSAGES");
501 ASSERT (name == NULL || strcmp (name, gl_locale_name_default ()) == 0);
504 unsetenv ("LC_CTYPE");
505 setenv ("LC_MESSAGES", "", 1);
507 setlocale (LC_ALL, "");
508 name = gl_locale_name_posix (LC_MESSAGES, "LC_MESSAGES");
509 ASSERT (name == NULL || strcmp (name, gl_locale_name_default ()) == 0);
512 unsetenv ("LC_CTYPE");
513 unsetenv ("LC_MESSAGES");
514 setenv ("LANG", "", 1);
515 setlocale (LC_ALL, "");
516 name = gl_locale_name_posix (LC_MESSAGES, "LC_MESSAGES");
517 ASSERT (name == NULL || strcmp (name, gl_locale_name_default ()) == 0);
519 /* Check that LC_ALL overrides the others, and LANG is overridden by the
522 setenv ("LC_ALL", "C", 1);
523 unsetenv ("LC_CTYPE");
524 unsetenv ("LC_MESSAGES");
526 setlocale (LC_ALL, "");
527 name = gl_locale_name_posix (LC_MESSAGES, "LC_MESSAGES");
528 ASSERT (strcmp (name, "C") == 0);
531 setenv ("LC_CTYPE", "C", 1);
532 setenv ("LC_MESSAGES", "C", 1);
534 setlocale (LC_ALL, "");
535 name = gl_locale_name_posix (LC_MESSAGES, "LC_MESSAGES");
536 ASSERT (strcmp (name, "C") == 0);
539 unsetenv ("LC_CTYPE");
540 unsetenv ("LC_MESSAGES");
541 setenv ("LANG", "C", 1);
542 setlocale (LC_ALL, "");
543 name = gl_locale_name_posix (LC_MESSAGES, "LC_MESSAGES");
544 ASSERT (strcmp (name, "C") == 0);
546 /* Check mixed situations. */
549 unsetenv ("LC_CTYPE");
550 setenv ("LC_MESSAGES", "fr_FR.UTF-8", 1);
551 setenv ("LANG", "de_DE.UTF-8", 1);
552 if (setlocale (LC_ALL, "") != NULL)
554 name = gl_locale_name_posix (LC_CTYPE, "LC_CTYPE");
555 ASSERT (strcmp (name, "de_DE.UTF-8") == 0);
556 name = gl_locale_name_posix (LC_MESSAGES, "LC_MESSAGES");
557 ASSERT (strcmp (name, "fr_FR.UTF-8") == 0);
561 unsetenv ("LC_CTYPE");
562 setenv ("LC_MESSAGES", "fr_FR.UTF-8", 1);
564 if (setlocale (LC_ALL, "") != NULL)
566 name = gl_locale_name_posix (LC_CTYPE, "LC_CTYPE");
567 ASSERT (name == NULL || strcmp (name, gl_locale_name_default ()) == 0);
568 name = gl_locale_name_posix (LC_MESSAGES, "LC_MESSAGES");
569 ASSERT (strcmp (name, "fr_FR.UTF-8") == 0);
573 /* Check that gl_locale_name_posix ignores the thread locale. */
575 locale_t locale = newlocale (LC_ALL_MASK, "fr_FR.UTF-8", NULL);
579 unsetenv ("LC_CTYPE");
580 unsetenv ("LC_MESSAGES");
581 setenv ("LANG", "C", 1);
582 setlocale (LC_ALL, "");
584 name = gl_locale_name_posix (LC_MESSAGES, "LC_MESSAGES");
585 ASSERT (strcmp (name, "C") == 0);
591 /* Test the gl_locale_name_environ() function. */
593 test_locale_name_environ (void)
597 /* Get into a defined state, */
598 setlocale (LC_ALL, "en_US.UTF-8");
600 uselocale (LC_GLOBAL_LOCALE);
603 /* Check that when all environment variables are unset,
604 gl_locale_name_environ returns NULL. */
606 unsetenv ("LC_CTYPE");
607 unsetenv ("LC_MESSAGES");
608 unsetenv ("LC_NUMERIC");
610 ASSERT (gl_locale_name_environ (LC_MESSAGES, "LC_MESSAGES") == NULL);
611 ASSERT (gl_locale_name_environ (LC_NUMERIC, "LC_NUMERIC") == NULL);
613 /* Check that an empty environment variable is treated like an unset
614 environment variable. */
616 setenv ("LC_ALL", "", 1);
617 unsetenv ("LC_CTYPE");
618 unsetenv ("LC_MESSAGES");
620 ASSERT (gl_locale_name_environ (LC_MESSAGES, "LC_MESSAGES") == NULL);
623 setenv ("LC_CTYPE", "", 1);
624 unsetenv ("LC_MESSAGES");
626 ASSERT (gl_locale_name_environ (LC_MESSAGES, "LC_MESSAGES") == NULL);
629 unsetenv ("LC_CTYPE");
630 setenv ("LC_MESSAGES", "", 1);
632 ASSERT (gl_locale_name_environ (LC_MESSAGES, "LC_MESSAGES") == NULL);
635 unsetenv ("LC_CTYPE");
636 unsetenv ("LC_MESSAGES");
637 setenv ("LANG", "", 1);
638 ASSERT (gl_locale_name_environ (LC_MESSAGES, "LC_MESSAGES") == NULL);
640 /* Check that LC_ALL overrides the others, and LANG is overridden by the
643 setenv ("LC_ALL", "C", 1);
644 unsetenv ("LC_CTYPE");
645 unsetenv ("LC_MESSAGES");
647 name = gl_locale_name_environ (LC_MESSAGES, "LC_MESSAGES");
648 ASSERT (strcmp (name, "C") == 0);
651 setenv ("LC_CTYPE", "C", 1);
652 setenv ("LC_MESSAGES", "C", 1);
654 name = gl_locale_name_environ (LC_MESSAGES, "LC_MESSAGES");
655 ASSERT (strcmp (name, "C") == 0);
658 unsetenv ("LC_CTYPE");
659 unsetenv ("LC_MESSAGES");
660 setenv ("LANG", "C", 1);
661 name = gl_locale_name_environ (LC_MESSAGES, "LC_MESSAGES");
662 ASSERT (strcmp (name, "C") == 0);
664 /* Check mixed situations. */
667 unsetenv ("LC_CTYPE");
668 setenv ("LC_MESSAGES", "fr_FR.UTF-8", 1);
669 setenv ("LANG", "de_DE.UTF-8", 1);
670 name = gl_locale_name_environ (LC_CTYPE, "LC_CTYPE");
671 ASSERT (strcmp (name, "de_DE.UTF-8") == 0);
672 name = gl_locale_name_environ (LC_MESSAGES, "LC_MESSAGES");
673 ASSERT (strcmp (name, "fr_FR.UTF-8") == 0);
676 unsetenv ("LC_CTYPE");
677 setenv ("LC_MESSAGES", "fr_FR.UTF-8", 1);
679 name = gl_locale_name_environ (LC_CTYPE, "LC_CTYPE");
680 ASSERT (name == NULL);
681 name = gl_locale_name_environ (LC_MESSAGES, "LC_MESSAGES");
682 ASSERT (strcmp (name, "fr_FR.UTF-8") == 0);
685 /* Check that gl_locale_name_environ ignores the thread locale. */
687 locale_t locale = newlocale (LC_ALL_MASK, "fr_FR.UTF-8", NULL);
691 unsetenv ("LC_CTYPE");
692 unsetenv ("LC_MESSAGES");
693 setenv ("LANG", "C", 1);
694 setlocale (LC_ALL, "");
696 name = gl_locale_name_environ (LC_MESSAGES, "LC_MESSAGES");
697 ASSERT (strcmp (name, "C") == 0);
703 /* Test the gl_locale_name_default() function. */
705 test_locale_name_default (void)
707 const char *name = gl_locale_name_default ();
709 ASSERT (name != NULL);
711 /* Only MacOS X and Windows have a facility for the user to set the default
713 #if !((defined __APPLE__ && defined __MACH__) || (defined _WIN32 || defined __WIN32__ || defined __CYGWIN__))
714 ASSERT (strcmp (name, "C") == 0);
718 /* Check that gl_locale_name_default ignores the thread locale. */
720 locale_t locale = newlocale (LC_ALL_MASK, "fr_FR.UTF-8", NULL);
724 ASSERT (strcmp (gl_locale_name_default (), name) == 0);
734 test_locale_name_thread ();
735 test_locale_name_posix ();
736 test_locale_name_environ ();
737 test_locale_name_default ();