1 /* Test of gl_locale_name function and its variants.
2 Copyright (C) 2007-2011 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"
32 static struct { int cat; int mask; const char *string; } const categories[] =
34 { LC_CTYPE, LC_CTYPE_MASK, "LC_CTYPE" },
35 { LC_NUMERIC, LC_NUMERIC_MASK, "LC_NUMERIC" },
36 { LC_TIME, LC_TIME_MASK, "LC_TIME" },
37 { LC_COLLATE, LC_COLLATE_MASK, "LC_COLLATE" },
38 { LC_MONETARY, LC_MONETARY_MASK, "LC_MONETARY" },
39 { LC_MESSAGES, LC_MESSAGES_MASK, "LC_MESSAGES" }
41 , { LC_PAPER, LC_PAPER_MASK, "LC_PAPER" }
44 , { LC_NAME, LC_NAME_MASK, "LC_NAME" }
47 , { LC_ADDRESS, LC_ADDRESS_MASK, "LC_ADDRESS" }
50 , { LC_TELEPHONE, LC_TELEPHONE_MASK, "LC_TELEPHONE" }
52 # ifdef LC_MEASUREMENT
53 , { LC_MEASUREMENT, LC_MEASUREMENT_MASK, "LC_MEASUREMENT" }
55 # ifdef LC_IDENTIFICATION
56 , { LC_IDENTIFICATION, LC_IDENTIFICATION_MASK, "LC_IDENTIFICATION" }
62 /* Test the gl_locale_name() function. */
64 test_locale_name (void)
68 /* Check that gl_locale_name returns non-NULL. */
69 ASSERT (gl_locale_name (LC_MESSAGES, "LC_MESSAGES") != NULL);
71 /* Get into a defined state, */
72 setlocale (LC_ALL, "en_US.UTF-8");
74 uselocale (LC_GLOBAL_LOCALE);
77 /* Check that when all environment variables are unset,
78 gl_locale_name returns the default locale. */
80 unsetenv ("LC_CTYPE");
81 unsetenv ("LC_MESSAGES");
82 unsetenv ("LC_NUMERIC");
84 setlocale (LC_ALL, "");
85 ASSERT (strcmp (gl_locale_name (LC_MESSAGES, "LC_MESSAGES"),
86 gl_locale_name_default ()) == 0);
87 ASSERT (strcmp (gl_locale_name (LC_NUMERIC, "LC_NUMERIC"),
88 gl_locale_name_default ()) == 0);
90 /* Check that an empty environment variable is treated like an unset
91 environment variable. */
93 setenv ("LC_ALL", "", 1);
94 unsetenv ("LC_CTYPE");
95 unsetenv ("LC_MESSAGES");
97 setlocale (LC_ALL, "");
98 ASSERT (strcmp (gl_locale_name (LC_MESSAGES, "LC_MESSAGES"),
99 gl_locale_name_default ()) == 0);
102 setenv ("LC_CTYPE", "", 1);
103 unsetenv ("LC_MESSAGES");
105 setlocale (LC_ALL, "");
106 ASSERT (strcmp (gl_locale_name (LC_MESSAGES, "LC_MESSAGES"),
107 gl_locale_name_default ()) == 0);
110 unsetenv ("LC_CTYPE");
111 setenv ("LC_MESSAGES", "", 1);
113 setlocale (LC_ALL, "");
114 ASSERT (strcmp (gl_locale_name (LC_MESSAGES, "LC_MESSAGES"),
115 gl_locale_name_default ()) == 0);
118 unsetenv ("LC_CTYPE");
119 unsetenv ("LC_MESSAGES");
120 setenv ("LANG", "", 1);
121 setlocale (LC_ALL, "");
122 ASSERT (strcmp (gl_locale_name (LC_MESSAGES, "LC_MESSAGES"),
123 gl_locale_name_default ()) == 0);
125 /* Check that LC_ALL overrides the others, and LANG is overridden by the
128 setenv ("LC_ALL", "C", 1);
129 unsetenv ("LC_CTYPE");
130 unsetenv ("LC_MESSAGES");
132 setlocale (LC_ALL, "");
133 ASSERT (strcmp (gl_locale_name (LC_MESSAGES, "LC_MESSAGES"), "C") == 0);
136 setenv ("LC_CTYPE", "C", 1);
137 setenv ("LC_MESSAGES", "C", 1);
139 setlocale (LC_ALL, "");
140 ASSERT (strcmp (gl_locale_name (LC_MESSAGES, "LC_MESSAGES"), "C") == 0);
143 unsetenv ("LC_CTYPE");
144 unsetenv ("LC_MESSAGES");
145 setenv ("LANG", "C", 1);
146 setlocale (LC_ALL, "");
147 ASSERT (strcmp (gl_locale_name (LC_MESSAGES, "LC_MESSAGES"), "C") == 0);
149 /* Check mixed situations. */
152 unsetenv ("LC_CTYPE");
153 setenv ("LC_MESSAGES", "fr_FR.UTF-8", 1);
154 setenv ("LANG", "de_DE.UTF-8", 1);
155 if (setlocale (LC_ALL, "") != NULL)
157 name = gl_locale_name (LC_CTYPE, "LC_CTYPE");
158 ASSERT (strcmp (name, "de_DE.UTF-8") == 0);
159 name = gl_locale_name (LC_MESSAGES, "LC_MESSAGES");
160 ASSERT (strcmp (name, "fr_FR.UTF-8") == 0);
164 unsetenv ("LC_CTYPE");
165 setenv ("LC_MESSAGES", "fr_FR.UTF-8", 1);
167 if (setlocale (LC_ALL, "") != NULL)
169 name = gl_locale_name (LC_CTYPE, "LC_CTYPE");
170 ASSERT (strcmp (name, gl_locale_name_default ()) == 0);
171 name = gl_locale_name (LC_MESSAGES, "LC_MESSAGES");
172 ASSERT (strcmp (name, "fr_FR.UTF-8") == 0);
176 /* Check that gl_locale_name considers the thread locale. */
178 locale_t locale = newlocale (LC_ALL_MASK, "fr_FR.UTF-8", NULL);
182 name = gl_locale_name (LC_CTYPE, "LC_CTYPE");
183 ASSERT (strcmp (name, "fr_FR.UTF-8") == 0);
184 name = gl_locale_name (LC_MESSAGES, "LC_MESSAGES");
185 ASSERT (strcmp (name, "fr_FR.UTF-8") == 0);
189 /* Check that gl_locale_name distinguishes different categories of the
190 thread locale, and that the name is the right one for each. */
194 for (i = 0; i < SIZEOF (categories); i++)
196 int category_mask = categories[i].mask;
197 locale_t locale = newlocale (LC_ALL_MASK, "fr_FR.UTF-8", NULL);
200 locale = newlocale (category_mask, "de_DE.UTF-8", locale);
206 for (j = 0; j < SIZEOF (categories); j++)
209 gl_locale_name (categories[j].cat, categories[j].string);
211 ASSERT (strcmp (name_j, "de_DE.UTF-8") == 0);
213 ASSERT (strcmp (name_j, "fr_FR.UTF-8") == 0);
222 /* Test the gl_locale_name_thread() function. */
224 test_locale_name_thread (void)
226 /* Get into a defined state, */
227 setlocale (LC_ALL, "en_US.UTF-8");
230 /* Check that gl_locale_name_thread returns NULL when no thread locale is
232 uselocale (LC_GLOBAL_LOCALE);
233 ASSERT (gl_locale_name_thread (LC_CTYPE, "LC_CTYPE") == NULL);
234 ASSERT (gl_locale_name_thread (LC_MESSAGES, "LC_MESSAGES") == NULL);
236 /* Check that gl_locale_name_thread considers the thread locale. */
238 locale_t locale = newlocale (LC_ALL_MASK, "fr_FR.UTF-8", NULL);
244 name = gl_locale_name_thread (LC_CTYPE, "LC_CTYPE");
245 ASSERT (strcmp (name, "fr_FR.UTF-8") == 0);
246 name = gl_locale_name_thread (LC_MESSAGES, "LC_MESSAGES");
247 ASSERT (strcmp (name, "fr_FR.UTF-8") == 0);
251 /* Check that gl_locale_name_thread distinguishes different categories of the
252 thread locale, and that the name is the right one for each. */
256 for (i = 0; i < SIZEOF (categories); i++)
258 int category_mask = categories[i].mask;
259 locale_t locale = newlocale (LC_ALL_MASK, "fr_FR.UTF-8", NULL);
262 locale = newlocale (category_mask, "de_DE.UTF-8", locale);
268 for (j = 0; j < SIZEOF (categories); j++)
271 gl_locale_name_thread (categories[j].cat,
272 categories[j].string);
274 ASSERT (strcmp (name_j, "de_DE.UTF-8") == 0);
276 ASSERT (strcmp (name_j, "fr_FR.UTF-8") == 0);
283 /* Check that gl_locale_name_thread returns a string that is allocated with
284 indefinite extent. */
286 /* Try many locale names in turn, in order to defeat possible caches. */
287 static const char * const choices[] =
393 /* Remember which locales are available. */
394 unsigned char /* bool */ available[SIZEOF (choices)];
395 /* Array of remembered results of gl_locale_name_thread. */
396 const char *unsaved_names[SIZEOF (choices)][SIZEOF (categories)];
397 /* Array of remembered results of gl_locale_name_thread, stored in safe
399 char *saved_names[SIZEOF (choices)][SIZEOF (categories)];
402 for (j = 0; j < SIZEOF (choices); j++)
404 locale_t locale = newlocale (LC_ALL_MASK, choices[j], NULL);
405 available[j] = (locale != NULL);
411 for (i = 0; i < SIZEOF (categories); i++)
413 unsaved_names[j][i] = gl_locale_name_thread (categories[i].cat, categories[i].string);
414 saved_names[j][i] = strdup (unsaved_names[j][i]);
416 uselocale (LC_GLOBAL_LOCALE);
420 /* Verify the unsaved_names are still valid. */
421 for (j = 0; j < SIZEOF (choices); j++)
426 for (i = 0; i < SIZEOF (categories); i++)
427 ASSERT (strcmp (unsaved_names[j][i], saved_names[j][i]) == 0);
429 /* Allocate many locales, without freeing them. This is an attempt at
430 overwriting as much of the previously allocated memory as possible. */
431 for (j = SIZEOF (choices); j > 0; )
436 locale_t locale = newlocale (LC_ALL_MASK, choices[j], NULL);
439 ASSERT (locale != NULL);
441 for (i = 0; i < SIZEOF (categories); i++)
443 const char *name = gl_locale_name_thread (categories[i].cat, categories[i].string);
444 ASSERT (strcmp (unsaved_names[j][i], name) == 0);
446 uselocale (LC_GLOBAL_LOCALE);
449 /* Verify the unsaved_names are still valid. */
450 for (j = 0; j < SIZEOF (choices); j++)
455 for (i = 0; i < SIZEOF (categories); i++)
456 ASSERT (strcmp (unsaved_names[j][i], saved_names[j][i]) == 0);
460 /* Check that gl_locale_name_thread always returns NULL. */
461 ASSERT (gl_locale_name_thread (LC_CTYPE, "LC_CTYPE") == NULL);
462 ASSERT (gl_locale_name_thread (LC_MESSAGES, "LC_MESSAGES") == NULL);
466 /* Test the gl_locale_name_posix() function. */
468 test_locale_name_posix (void)
472 /* Get into a defined state, */
473 setlocale (LC_ALL, "en_US.UTF-8");
475 uselocale (LC_GLOBAL_LOCALE);
478 /* Check that when all environment variables are unset,
479 gl_locale_name_posix returns either NULL or the default locale. */
481 unsetenv ("LC_CTYPE");
482 unsetenv ("LC_MESSAGES");
483 unsetenv ("LC_NUMERIC");
485 setlocale (LC_ALL, "");
486 name = gl_locale_name_posix (LC_MESSAGES, "LC_MESSAGES");
487 ASSERT (name == NULL || strcmp (name, gl_locale_name_default ()) == 0);
488 name = gl_locale_name_posix (LC_NUMERIC, "LC_NUMERIC");
489 ASSERT (name == NULL || strcmp (name, gl_locale_name_default ()) == 0);
491 /* Check that an empty environment variable is treated like an unset
492 environment variable. */
494 setenv ("LC_ALL", "", 1);
495 unsetenv ("LC_CTYPE");
496 unsetenv ("LC_MESSAGES");
498 setlocale (LC_ALL, "");
499 name = gl_locale_name_posix (LC_MESSAGES, "LC_MESSAGES");
500 ASSERT (name == NULL || strcmp (name, gl_locale_name_default ()) == 0);
503 setenv ("LC_CTYPE", "", 1);
504 unsetenv ("LC_MESSAGES");
506 setlocale (LC_ALL, "");
507 name = gl_locale_name_posix (LC_MESSAGES, "LC_MESSAGES");
508 ASSERT (name == NULL || strcmp (name, gl_locale_name_default ()) == 0);
511 unsetenv ("LC_CTYPE");
512 setenv ("LC_MESSAGES", "", 1);
514 setlocale (LC_ALL, "");
515 name = gl_locale_name_posix (LC_MESSAGES, "LC_MESSAGES");
516 ASSERT (name == NULL || strcmp (name, gl_locale_name_default ()) == 0);
519 unsetenv ("LC_CTYPE");
520 unsetenv ("LC_MESSAGES");
521 setenv ("LANG", "", 1);
522 setlocale (LC_ALL, "");
523 name = gl_locale_name_posix (LC_MESSAGES, "LC_MESSAGES");
524 ASSERT (name == NULL || strcmp (name, gl_locale_name_default ()) == 0);
526 /* Check that LC_ALL overrides the others, and LANG is overridden by the
529 setenv ("LC_ALL", "C", 1);
530 unsetenv ("LC_CTYPE");
531 unsetenv ("LC_MESSAGES");
533 setlocale (LC_ALL, "");
534 name = gl_locale_name_posix (LC_MESSAGES, "LC_MESSAGES");
535 ASSERT (strcmp (name, "C") == 0);
538 setenv ("LC_CTYPE", "C", 1);
539 setenv ("LC_MESSAGES", "C", 1);
541 setlocale (LC_ALL, "");
542 name = gl_locale_name_posix (LC_MESSAGES, "LC_MESSAGES");
543 ASSERT (strcmp (name, "C") == 0);
546 unsetenv ("LC_CTYPE");
547 unsetenv ("LC_MESSAGES");
548 setenv ("LANG", "C", 1);
549 setlocale (LC_ALL, "");
550 name = gl_locale_name_posix (LC_MESSAGES, "LC_MESSAGES");
551 ASSERT (strcmp (name, "C") == 0);
553 /* Check mixed situations. */
556 unsetenv ("LC_CTYPE");
557 setenv ("LC_MESSAGES", "fr_FR.UTF-8", 1);
558 setenv ("LANG", "de_DE.UTF-8", 1);
559 if (setlocale (LC_ALL, "") != NULL)
561 name = gl_locale_name_posix (LC_CTYPE, "LC_CTYPE");
562 ASSERT (strcmp (name, "de_DE.UTF-8") == 0);
563 name = gl_locale_name_posix (LC_MESSAGES, "LC_MESSAGES");
564 ASSERT (strcmp (name, "fr_FR.UTF-8") == 0);
568 unsetenv ("LC_CTYPE");
569 setenv ("LC_MESSAGES", "fr_FR.UTF-8", 1);
571 if (setlocale (LC_ALL, "") != NULL)
573 name = gl_locale_name_posix (LC_CTYPE, "LC_CTYPE");
574 ASSERT (name == NULL || strcmp (name, gl_locale_name_default ()) == 0);
575 name = gl_locale_name_posix (LC_MESSAGES, "LC_MESSAGES");
576 ASSERT (strcmp (name, "fr_FR.UTF-8") == 0);
580 /* Check that gl_locale_name_posix ignores the thread locale. */
582 locale_t locale = newlocale (LC_ALL_MASK, "fr_FR.UTF-8", NULL);
586 unsetenv ("LC_CTYPE");
587 unsetenv ("LC_MESSAGES");
588 setenv ("LANG", "C", 1);
589 setlocale (LC_ALL, "");
591 name = gl_locale_name_posix (LC_MESSAGES, "LC_MESSAGES");
592 ASSERT (strcmp (name, "C") == 0);
598 /* Test the gl_locale_name_environ() function. */
600 test_locale_name_environ (void)
604 /* Get into a defined state, */
605 setlocale (LC_ALL, "en_US.UTF-8");
607 uselocale (LC_GLOBAL_LOCALE);
610 /* Check that when all environment variables are unset,
611 gl_locale_name_environ returns NULL. */
613 unsetenv ("LC_CTYPE");
614 unsetenv ("LC_MESSAGES");
615 unsetenv ("LC_NUMERIC");
617 ASSERT (gl_locale_name_environ (LC_MESSAGES, "LC_MESSAGES") == NULL);
618 ASSERT (gl_locale_name_environ (LC_NUMERIC, "LC_NUMERIC") == NULL);
620 /* Check that an empty environment variable is treated like an unset
621 environment variable. */
623 setenv ("LC_ALL", "", 1);
624 unsetenv ("LC_CTYPE");
625 unsetenv ("LC_MESSAGES");
627 ASSERT (gl_locale_name_environ (LC_MESSAGES, "LC_MESSAGES") == NULL);
630 setenv ("LC_CTYPE", "", 1);
631 unsetenv ("LC_MESSAGES");
633 ASSERT (gl_locale_name_environ (LC_MESSAGES, "LC_MESSAGES") == NULL);
636 unsetenv ("LC_CTYPE");
637 setenv ("LC_MESSAGES", "", 1);
639 ASSERT (gl_locale_name_environ (LC_MESSAGES, "LC_MESSAGES") == NULL);
642 unsetenv ("LC_CTYPE");
643 unsetenv ("LC_MESSAGES");
644 setenv ("LANG", "", 1);
645 ASSERT (gl_locale_name_environ (LC_MESSAGES, "LC_MESSAGES") == NULL);
647 /* Check that LC_ALL overrides the others, and LANG is overridden by the
650 setenv ("LC_ALL", "C", 1);
651 unsetenv ("LC_CTYPE");
652 unsetenv ("LC_MESSAGES");
654 name = gl_locale_name_environ (LC_MESSAGES, "LC_MESSAGES");
655 ASSERT (strcmp (name, "C") == 0);
658 setenv ("LC_CTYPE", "C", 1);
659 setenv ("LC_MESSAGES", "C", 1);
661 name = gl_locale_name_environ (LC_MESSAGES, "LC_MESSAGES");
662 ASSERT (strcmp (name, "C") == 0);
665 unsetenv ("LC_CTYPE");
666 unsetenv ("LC_MESSAGES");
667 setenv ("LANG", "C", 1);
668 name = gl_locale_name_environ (LC_MESSAGES, "LC_MESSAGES");
669 ASSERT (strcmp (name, "C") == 0);
671 /* Check mixed situations. */
674 unsetenv ("LC_CTYPE");
675 setenv ("LC_MESSAGES", "fr_FR.UTF-8", 1);
676 setenv ("LANG", "de_DE.UTF-8", 1);
677 name = gl_locale_name_environ (LC_CTYPE, "LC_CTYPE");
678 ASSERT (strcmp (name, "de_DE.UTF-8") == 0);
679 name = gl_locale_name_environ (LC_MESSAGES, "LC_MESSAGES");
680 ASSERT (strcmp (name, "fr_FR.UTF-8") == 0);
683 unsetenv ("LC_CTYPE");
684 setenv ("LC_MESSAGES", "fr_FR.UTF-8", 1);
686 name = gl_locale_name_environ (LC_CTYPE, "LC_CTYPE");
687 ASSERT (name == NULL);
688 name = gl_locale_name_environ (LC_MESSAGES, "LC_MESSAGES");
689 ASSERT (strcmp (name, "fr_FR.UTF-8") == 0);
692 /* Check that gl_locale_name_environ ignores the thread locale. */
694 locale_t locale = newlocale (LC_ALL_MASK, "fr_FR.UTF-8", NULL);
698 unsetenv ("LC_CTYPE");
699 unsetenv ("LC_MESSAGES");
700 setenv ("LANG", "C", 1);
701 setlocale (LC_ALL, "");
703 name = gl_locale_name_environ (LC_MESSAGES, "LC_MESSAGES");
704 ASSERT (strcmp (name, "C") == 0);
710 /* Test the gl_locale_name_default() function. */
712 test_locale_name_default (void)
714 const char *name = gl_locale_name_default ();
716 ASSERT (name != NULL);
718 /* Only MacOS X and Windows have a facility for the user to set the default
720 #if !((defined __APPLE__ && defined __MACH__) || (defined _WIN32 || defined __WIN32__ || defined __CYGWIN__))
721 ASSERT (strcmp (name, "C") == 0);
725 /* Check that gl_locale_name_default ignores the thread locale. */
727 locale_t locale = newlocale (LC_ALL_MASK, "fr_FR.UTF-8", NULL);
731 ASSERT (strcmp (gl_locale_name_default (), name) == 0);
741 test_locale_name_thread ();
742 test_locale_name_posix ();
743 test_locale_name_environ ();
744 test_locale_name_default ();