1 /* Test of gl_locale_name function and its variants.
2 Copyright (C) 2007-2017 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"
30 #if HAVE_NEWLOCALE && HAVE_USELOCALE
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");
73 #if HAVE_NEWLOCALE && HAVE_USELOCALE
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);
175 #if HAVE_NEWLOCALE && HAVE_USELOCALE
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);
186 uselocale (LC_GLOBAL_LOCALE
);
191 /* Check that gl_locale_name distinguishes different categories of the
192 thread locale, and that the name is the right one for each. */
196 for (i
= 0; i
< SIZEOF (categories
); i
++)
198 int category_mask
= categories
[i
].mask
;
199 locale_t loc
= newlocale (LC_ALL_MASK
, "fr_FR.UTF-8", NULL
);
202 locale_t locale
= newlocale (category_mask
, "de_DE.UTF-8", loc
);
210 for (j
= 0; j
< SIZEOF (categories
); j
++)
213 gl_locale_name (categories
[j
].cat
, categories
[j
].string
);
215 ASSERT (strcmp (name_j
, "de_DE.UTF-8") == 0);
217 ASSERT (strcmp (name_j
, "fr_FR.UTF-8") == 0);
219 uselocale (LC_GLOBAL_LOCALE
);
228 /* Test the gl_locale_name_thread() function. */
230 test_locale_name_thread (void)
232 /* Get into a defined state, */
233 setlocale (LC_ALL
, "en_US.UTF-8");
235 #if HAVE_NEWLOCALE && HAVE_USELOCALE
236 /* Check that gl_locale_name_thread returns NULL when no thread locale is
238 uselocale (LC_GLOBAL_LOCALE
);
239 ASSERT (gl_locale_name_thread (LC_CTYPE
, "LC_CTYPE") == NULL
);
240 ASSERT (gl_locale_name_thread (LC_MESSAGES
, "LC_MESSAGES") == NULL
);
242 /* Check that gl_locale_name_thread considers the thread locale. */
244 locale_t locale
= newlocale (LC_ALL_MASK
, "fr_FR.UTF-8", NULL
);
250 name
= gl_locale_name_thread (LC_CTYPE
, "LC_CTYPE");
251 ASSERT (strcmp (name
, "fr_FR.UTF-8") == 0);
252 name
= gl_locale_name_thread (LC_MESSAGES
, "LC_MESSAGES");
253 ASSERT (strcmp (name
, "fr_FR.UTF-8") == 0);
254 uselocale (LC_GLOBAL_LOCALE
);
259 /* Check that gl_locale_name_thread distinguishes different categories of the
260 thread locale, and that the name is the right one for each. */
264 for (i
= 0; i
< SIZEOF (categories
); i
++)
266 int category_mask
= categories
[i
].mask
;
267 locale_t loc
= newlocale (LC_ALL_MASK
, "fr_FR.UTF-8", NULL
);
270 locale_t locale
= newlocale (category_mask
, "de_DE.UTF-8", loc
);
278 for (j
= 0; j
< SIZEOF (categories
); j
++)
281 gl_locale_name_thread (categories
[j
].cat
,
282 categories
[j
].string
);
284 ASSERT (strcmp (name_j
, "de_DE.UTF-8") == 0);
286 ASSERT (strcmp (name_j
, "fr_FR.UTF-8") == 0);
288 uselocale (LC_GLOBAL_LOCALE
);
295 /* Check that gl_locale_name_thread returns a string that is allocated with
296 indefinite extent. */
298 /* Try many locale names in turn, in order to defeat possible caches. */
299 static const char * const choices
[] =
405 /* Remember which locales are available. */
406 unsigned char /* bool */ available
[SIZEOF (choices
)];
407 /* Array of remembered results of gl_locale_name_thread. */
408 const char *unsaved_names
[SIZEOF (choices
)][SIZEOF (categories
)];
409 /* Array of remembered results of gl_locale_name_thread, stored in safe
411 char *saved_names
[SIZEOF (choices
)][SIZEOF (categories
)];
414 for (j
= 0; j
< SIZEOF (choices
); j
++)
416 locale_t locale
= newlocale (LC_ALL_MASK
, choices
[j
], NULL
);
417 available
[j
] = (locale
!= NULL
);
423 for (i
= 0; i
< SIZEOF (categories
); i
++)
425 unsaved_names
[j
][i
] = gl_locale_name_thread (categories
[i
].cat
, categories
[i
].string
);
426 saved_names
[j
][i
] = strdup (unsaved_names
[j
][i
]);
428 uselocale (LC_GLOBAL_LOCALE
);
432 /* Verify the unsaved_names are still valid. */
433 for (j
= 0; j
< SIZEOF (choices
); j
++)
438 for (i
= 0; i
< SIZEOF (categories
); i
++)
439 ASSERT (strcmp (unsaved_names
[j
][i
], saved_names
[j
][i
]) == 0);
441 /* Allocate many locales, without freeing them. This is an attempt at
442 overwriting as much of the previously allocated memory as possible. */
443 for (j
= SIZEOF (choices
); j
> 0; )
448 locale_t locale
= newlocale (LC_ALL_MASK
, choices
[j
], NULL
);
451 ASSERT (locale
!= NULL
);
453 for (i
= 0; i
< SIZEOF (categories
); i
++)
455 const char *name
= gl_locale_name_thread (categories
[i
].cat
, categories
[i
].string
);
456 ASSERT (strcmp (unsaved_names
[j
][i
], name
) == 0);
458 uselocale (LC_GLOBAL_LOCALE
);
462 /* Verify the unsaved_names are still valid. */
463 for (j
= 0; j
< SIZEOF (choices
); j
++)
468 for (i
= 0; i
< SIZEOF (categories
); i
++)
470 ASSERT (strcmp (unsaved_names
[j
][i
], saved_names
[j
][i
]) == 0);
471 free (saved_names
[j
][i
]);
476 /* Check that gl_locale_name_thread always returns NULL. */
477 ASSERT (gl_locale_name_thread (LC_CTYPE
, "LC_CTYPE") == NULL
);
478 ASSERT (gl_locale_name_thread (LC_MESSAGES
, "LC_MESSAGES") == NULL
);
482 /* Test the gl_locale_name_posix() function. */
484 test_locale_name_posix (void)
488 /* Get into a defined state, */
489 setlocale (LC_ALL
, "en_US.UTF-8");
490 #if HAVE_NEWLOCALE && HAVE_USELOCALE
491 uselocale (LC_GLOBAL_LOCALE
);
494 /* Check that when all environment variables are unset,
495 gl_locale_name_posix returns either NULL or the default locale. */
497 unsetenv ("LC_CTYPE");
498 unsetenv ("LC_MESSAGES");
499 unsetenv ("LC_NUMERIC");
501 setlocale (LC_ALL
, "");
502 name
= gl_locale_name_posix (LC_MESSAGES
, "LC_MESSAGES");
503 ASSERT (name
== NULL
|| strcmp (name
, gl_locale_name_default ()) == 0);
504 name
= gl_locale_name_posix (LC_NUMERIC
, "LC_NUMERIC");
505 ASSERT (name
== NULL
|| strcmp (name
, gl_locale_name_default ()) == 0);
507 /* Check that an empty environment variable is treated like an unset
508 environment variable. */
510 setenv ("LC_ALL", "", 1);
511 unsetenv ("LC_CTYPE");
512 unsetenv ("LC_MESSAGES");
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 setenv ("LC_CTYPE", "", 1);
520 unsetenv ("LC_MESSAGES");
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);
527 unsetenv ("LC_CTYPE");
528 setenv ("LC_MESSAGES", "", 1);
530 setlocale (LC_ALL
, "");
531 name
= gl_locale_name_posix (LC_MESSAGES
, "LC_MESSAGES");
532 ASSERT (name
== NULL
|| strcmp (name
, gl_locale_name_default ()) == 0);
535 unsetenv ("LC_CTYPE");
536 unsetenv ("LC_MESSAGES");
537 setenv ("LANG", "", 1);
538 setlocale (LC_ALL
, "");
539 name
= gl_locale_name_posix (LC_MESSAGES
, "LC_MESSAGES");
540 ASSERT (name
== NULL
|| strcmp (name
, gl_locale_name_default ()) == 0);
542 /* Check that LC_ALL overrides the others, and LANG is overridden by the
545 setenv ("LC_ALL", "C", 1);
546 unsetenv ("LC_CTYPE");
547 unsetenv ("LC_MESSAGES");
549 setlocale (LC_ALL
, "");
550 name
= gl_locale_name_posix (LC_MESSAGES
, "LC_MESSAGES");
551 ASSERT (strcmp (name
, "C") == 0);
554 setenv ("LC_CTYPE", "C", 1);
555 setenv ("LC_MESSAGES", "C", 1);
557 setlocale (LC_ALL
, "");
558 name
= gl_locale_name_posix (LC_MESSAGES
, "LC_MESSAGES");
559 ASSERT (strcmp (name
, "C") == 0);
562 unsetenv ("LC_CTYPE");
563 unsetenv ("LC_MESSAGES");
564 setenv ("LANG", "C", 1);
565 setlocale (LC_ALL
, "");
566 name
= gl_locale_name_posix (LC_MESSAGES
, "LC_MESSAGES");
567 ASSERT (strcmp (name
, "C") == 0);
569 /* Check mixed situations. */
572 unsetenv ("LC_CTYPE");
573 setenv ("LC_MESSAGES", "fr_FR.UTF-8", 1);
574 setenv ("LANG", "de_DE.UTF-8", 1);
575 if (setlocale (LC_ALL
, "") != NULL
)
577 name
= gl_locale_name_posix (LC_CTYPE
, "LC_CTYPE");
578 ASSERT (strcmp (name
, "de_DE.UTF-8") == 0);
579 name
= gl_locale_name_posix (LC_MESSAGES
, "LC_MESSAGES");
580 ASSERT (strcmp (name
, "fr_FR.UTF-8") == 0);
584 unsetenv ("LC_CTYPE");
585 setenv ("LC_MESSAGES", "fr_FR.UTF-8", 1);
587 if (setlocale (LC_ALL
, "") != NULL
)
589 name
= gl_locale_name_posix (LC_CTYPE
, "LC_CTYPE");
590 ASSERT (name
== NULL
|| strcmp (name
, gl_locale_name_default ()) == 0);
591 name
= gl_locale_name_posix (LC_MESSAGES
, "LC_MESSAGES");
592 ASSERT (strcmp (name
, "fr_FR.UTF-8") == 0);
595 #if HAVE_NEWLOCALE && HAVE_USELOCALE
596 /* Check that gl_locale_name_posix ignores the thread locale. */
598 locale_t locale
= newlocale (LC_ALL_MASK
, "fr_FR.UTF-8", NULL
);
602 unsetenv ("LC_CTYPE");
603 unsetenv ("LC_MESSAGES");
604 setenv ("LANG", "C", 1);
605 setlocale (LC_ALL
, "");
607 name
= gl_locale_name_posix (LC_MESSAGES
, "LC_MESSAGES");
608 ASSERT (strcmp (name
, "C") == 0);
609 uselocale (LC_GLOBAL_LOCALE
);
616 /* Test the gl_locale_name_environ() function. */
618 test_locale_name_environ (void)
622 /* Get into a defined state, */
623 setlocale (LC_ALL
, "en_US.UTF-8");
624 #if HAVE_NEWLOCALE && HAVE_USELOCALE
625 uselocale (LC_GLOBAL_LOCALE
);
628 /* Check that when all environment variables are unset,
629 gl_locale_name_environ returns NULL. */
631 unsetenv ("LC_CTYPE");
632 unsetenv ("LC_MESSAGES");
633 unsetenv ("LC_NUMERIC");
635 ASSERT (gl_locale_name_environ (LC_MESSAGES
, "LC_MESSAGES") == NULL
);
636 ASSERT (gl_locale_name_environ (LC_NUMERIC
, "LC_NUMERIC") == NULL
);
638 /* Check that an empty environment variable is treated like an unset
639 environment variable. */
641 setenv ("LC_ALL", "", 1);
642 unsetenv ("LC_CTYPE");
643 unsetenv ("LC_MESSAGES");
645 ASSERT (gl_locale_name_environ (LC_MESSAGES
, "LC_MESSAGES") == NULL
);
648 setenv ("LC_CTYPE", "", 1);
649 unsetenv ("LC_MESSAGES");
651 ASSERT (gl_locale_name_environ (LC_MESSAGES
, "LC_MESSAGES") == NULL
);
654 unsetenv ("LC_CTYPE");
655 setenv ("LC_MESSAGES", "", 1);
657 ASSERT (gl_locale_name_environ (LC_MESSAGES
, "LC_MESSAGES") == NULL
);
660 unsetenv ("LC_CTYPE");
661 unsetenv ("LC_MESSAGES");
662 setenv ("LANG", "", 1);
663 ASSERT (gl_locale_name_environ (LC_MESSAGES
, "LC_MESSAGES") == NULL
);
665 /* Check that LC_ALL overrides the others, and LANG is overridden by the
668 setenv ("LC_ALL", "C", 1);
669 unsetenv ("LC_CTYPE");
670 unsetenv ("LC_MESSAGES");
672 name
= gl_locale_name_environ (LC_MESSAGES
, "LC_MESSAGES");
673 ASSERT (strcmp (name
, "C") == 0);
676 setenv ("LC_CTYPE", "C", 1);
677 setenv ("LC_MESSAGES", "C", 1);
679 name
= gl_locale_name_environ (LC_MESSAGES
, "LC_MESSAGES");
680 ASSERT (strcmp (name
, "C") == 0);
683 unsetenv ("LC_CTYPE");
684 unsetenv ("LC_MESSAGES");
685 setenv ("LANG", "C", 1);
686 name
= gl_locale_name_environ (LC_MESSAGES
, "LC_MESSAGES");
687 ASSERT (strcmp (name
, "C") == 0);
689 /* Check mixed situations. */
692 unsetenv ("LC_CTYPE");
693 setenv ("LC_MESSAGES", "fr_FR.UTF-8", 1);
694 setenv ("LANG", "de_DE.UTF-8", 1);
695 name
= gl_locale_name_environ (LC_CTYPE
, "LC_CTYPE");
696 ASSERT (strcmp (name
, "de_DE.UTF-8") == 0);
697 name
= gl_locale_name_environ (LC_MESSAGES
, "LC_MESSAGES");
698 ASSERT (strcmp (name
, "fr_FR.UTF-8") == 0);
701 unsetenv ("LC_CTYPE");
702 setenv ("LC_MESSAGES", "fr_FR.UTF-8", 1);
704 name
= gl_locale_name_environ (LC_CTYPE
, "LC_CTYPE");
705 ASSERT (name
== NULL
);
706 name
= gl_locale_name_environ (LC_MESSAGES
, "LC_MESSAGES");
707 ASSERT (strcmp (name
, "fr_FR.UTF-8") == 0);
709 #if HAVE_NEWLOCALE && HAVE_USELOCALE
710 /* Check that gl_locale_name_environ ignores the thread locale. */
712 locale_t locale
= newlocale (LC_ALL_MASK
, "fr_FR.UTF-8", NULL
);
716 unsetenv ("LC_CTYPE");
717 unsetenv ("LC_MESSAGES");
718 setenv ("LANG", "C", 1);
719 setlocale (LC_ALL
, "");
721 name
= gl_locale_name_environ (LC_MESSAGES
, "LC_MESSAGES");
722 ASSERT (strcmp (name
, "C") == 0);
723 uselocale (LC_GLOBAL_LOCALE
);
730 /* Test the gl_locale_name_default() function. */
732 test_locale_name_default (void)
734 const char *name
= gl_locale_name_default ();
736 ASSERT (name
!= NULL
);
738 /* Only Mac OS X and Windows have a facility for the user to set the default
740 #if !((defined __APPLE__ && defined __MACH__) || (defined _WIN32 || defined __WIN32__ || defined __CYGWIN__))
741 ASSERT (strcmp (name
, "C") == 0);
744 #if HAVE_NEWLOCALE && HAVE_USELOCALE
745 /* Check that gl_locale_name_default ignores the thread locale. */
747 locale_t locale
= newlocale (LC_ALL_MASK
, "fr_FR.UTF-8", NULL
);
751 ASSERT (strcmp (gl_locale_name_default (), name
) == 0);
752 uselocale (LC_GLOBAL_LOCALE
);
763 test_locale_name_thread ();
764 test_locale_name_posix ();
765 test_locale_name_environ ();
766 test_locale_name_default ();