Line data Source code
1 : /* Test of gl_locale_name function and its variants.
2 : Copyright (C) 2007-2020 Free Software Foundation, Inc.
3 :
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.
8 :
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.
13 :
14 : You should have received a copy of the GNU General Public License
15 : along with this program. If not, see <https://www.gnu.org/licenses/>. */
16 :
17 : /* Written by Bruno Haible <bruno@clisp.org>, 2007. */
18 :
19 : #include <config.h>
20 :
21 : #include "localename.h"
22 :
23 : #include <locale.h>
24 : #include <stdlib.h>
25 : #include <string.h>
26 :
27 : #include "macros.h"
28 :
29 : #if HAVE_WORKING_NEWLOCALE && HAVE_WORKING_USELOCALE && !HAVE_FAKE_LOCALES
30 : # define HAVE_GOOD_USELOCALE 1
31 : #endif
32 :
33 :
34 : #if HAVE_GOOD_USELOCALE
35 :
36 : static struct { int cat; int mask; const char *string; } const categories[] =
37 : {
38 : { LC_CTYPE, LC_CTYPE_MASK, "LC_CTYPE" },
39 : { LC_NUMERIC, LC_NUMERIC_MASK, "LC_NUMERIC" },
40 : { LC_TIME, LC_TIME_MASK, "LC_TIME" },
41 : { LC_COLLATE, LC_COLLATE_MASK, "LC_COLLATE" },
42 : { LC_MONETARY, LC_MONETARY_MASK, "LC_MONETARY" },
43 : { LC_MESSAGES, LC_MESSAGES_MASK, "LC_MESSAGES" }
44 : # ifdef LC_PAPER
45 : , { LC_PAPER, LC_PAPER_MASK, "LC_PAPER" }
46 : # endif
47 : # ifdef LC_NAME
48 : , { LC_NAME, LC_NAME_MASK, "LC_NAME" }
49 : # endif
50 : # ifdef LC_ADDRESS
51 : , { LC_ADDRESS, LC_ADDRESS_MASK, "LC_ADDRESS" }
52 : # endif
53 : # ifdef LC_TELEPHONE
54 : , { LC_TELEPHONE, LC_TELEPHONE_MASK, "LC_TELEPHONE" }
55 : # endif
56 : # ifdef LC_MEASUREMENT
57 : , { LC_MEASUREMENT, LC_MEASUREMENT_MASK, "LC_MEASUREMENT" }
58 : # endif
59 : # ifdef LC_IDENTIFICATION
60 : , { LC_IDENTIFICATION, LC_IDENTIFICATION_MASK, "LC_IDENTIFICATION" }
61 : # endif
62 : };
63 :
64 : #endif
65 :
66 : /* Test the gl_locale_name() function. */
67 : static void
68 1 : test_locale_name (void)
69 : {
70 : const char *ret;
71 : const char *name;
72 :
73 : /* Check that gl_locale_name returns non-NULL. */
74 1 : ASSERT (gl_locale_name (LC_MESSAGES, "LC_MESSAGES") != NULL);
75 :
76 : /* Get into a defined state, */
77 1 : setlocale (LC_ALL, "en_US.UTF-8");
78 : #if HAVE_GOOD_USELOCALE
79 1 : uselocale (LC_GLOBAL_LOCALE);
80 : #endif
81 :
82 : /* Check that when all environment variables are unset,
83 : gl_locale_name returns the default locale. */
84 1 : unsetenv ("LC_ALL");
85 1 : unsetenv ("LC_CTYPE");
86 1 : unsetenv ("LC_MESSAGES");
87 1 : unsetenv ("LC_NUMERIC");
88 1 : unsetenv ("LANG");
89 : /* Need also to unset all environment variables that specify standard or
90 : non-standard locale categories. Otherwise, on glibc systems, when some
91 : of these variables are set and reference a nonexistent locale, the
92 : setlocale (LC_ALL, "") call below would fail. */
93 1 : unsetenv ("LC_COLLATE");
94 1 : unsetenv ("LC_MONETARY");
95 1 : unsetenv ("LC_TIME");
96 1 : unsetenv ("LC_ADDRESS");
97 1 : unsetenv ("LC_IDENTIFICATION");
98 1 : unsetenv ("LC_MEASUREMENT");
99 1 : unsetenv ("LC_NAME");
100 1 : unsetenv ("LC_PAPER");
101 1 : unsetenv ("LC_TELEPHONE");
102 1 : ret = setlocale (LC_ALL, "");
103 1 : ASSERT (ret != NULL);
104 1 : ASSERT (strcmp (gl_locale_name (LC_MESSAGES, "LC_MESSAGES"),
105 : gl_locale_name_default ()) == 0);
106 1 : ASSERT (strcmp (gl_locale_name (LC_NUMERIC, "LC_NUMERIC"),
107 : gl_locale_name_default ()) == 0);
108 :
109 : /* Check that an empty environment variable is treated like an unset
110 : environment variable. */
111 :
112 1 : setenv ("LC_ALL", "", 1);
113 1 : unsetenv ("LC_CTYPE");
114 1 : unsetenv ("LC_MESSAGES");
115 1 : unsetenv ("LANG");
116 1 : setlocale (LC_ALL, "");
117 1 : ASSERT (strcmp (gl_locale_name (LC_MESSAGES, "LC_MESSAGES"),
118 : gl_locale_name_default ()) == 0);
119 :
120 1 : unsetenv ("LC_ALL");
121 1 : setenv ("LC_CTYPE", "", 1);
122 1 : unsetenv ("LC_MESSAGES");
123 1 : unsetenv ("LANG");
124 1 : setlocale (LC_ALL, "");
125 1 : ASSERT (strcmp (gl_locale_name (LC_MESSAGES, "LC_MESSAGES"),
126 : gl_locale_name_default ()) == 0);
127 :
128 1 : unsetenv ("LC_ALL");
129 1 : unsetenv ("LC_CTYPE");
130 1 : setenv ("LC_MESSAGES", "", 1);
131 1 : unsetenv ("LANG");
132 1 : setlocale (LC_ALL, "");
133 1 : ASSERT (strcmp (gl_locale_name (LC_MESSAGES, "LC_MESSAGES"),
134 : gl_locale_name_default ()) == 0);
135 :
136 1 : unsetenv ("LC_ALL");
137 1 : unsetenv ("LC_CTYPE");
138 1 : unsetenv ("LC_MESSAGES");
139 1 : setenv ("LANG", "", 1);
140 1 : setlocale (LC_ALL, "");
141 1 : ASSERT (strcmp (gl_locale_name (LC_MESSAGES, "LC_MESSAGES"),
142 : gl_locale_name_default ()) == 0);
143 :
144 : /* Check that LC_ALL overrides the others, and LANG is overridden by the
145 : others. */
146 :
147 1 : setenv ("LC_ALL", "C", 1);
148 1 : unsetenv ("LC_CTYPE");
149 1 : unsetenv ("LC_MESSAGES");
150 1 : unsetenv ("LANG");
151 1 : setlocale (LC_ALL, "");
152 1 : ASSERT (strcmp (gl_locale_name (LC_MESSAGES, "LC_MESSAGES"), "C") == 0);
153 :
154 1 : unsetenv ("LC_ALL");
155 1 : setenv ("LC_CTYPE", "C", 1);
156 1 : setenv ("LC_MESSAGES", "C", 1);
157 1 : unsetenv ("LANG");
158 1 : setlocale (LC_ALL, "");
159 1 : ASSERT (strcmp (gl_locale_name (LC_MESSAGES, "LC_MESSAGES"), "C") == 0);
160 :
161 1 : unsetenv ("LC_ALL");
162 1 : unsetenv ("LC_CTYPE");
163 1 : unsetenv ("LC_MESSAGES");
164 1 : setenv ("LANG", "C", 1);
165 1 : setlocale (LC_ALL, "");
166 1 : ASSERT (strcmp (gl_locale_name (LC_MESSAGES, "LC_MESSAGES"), "C") == 0);
167 :
168 : /* Check mixed situations. */
169 :
170 1 : unsetenv ("LC_ALL");
171 1 : unsetenv ("LC_CTYPE");
172 1 : setenv ("LC_MESSAGES", "fr_FR.UTF-8", 1);
173 1 : setenv ("LANG", "de_DE.UTF-8", 1);
174 1 : if (setlocale (LC_ALL, "") != NULL)
175 : {
176 0 : name = gl_locale_name (LC_CTYPE, "LC_CTYPE");
177 : #if defined _WIN32 && !defined __CYGWIN__
178 : /* On native Windows, here,
179 : gl_locale_name_thread (LC_CTYPE, "LC_CTYPE")
180 : returns NULL and
181 : gl_locale_name_posix (LC_CTYPE, "LC_CTYPE")
182 : returns either "de_DE" or "de_DE.UTF-8". */
183 : ASSERT (strcmp (name, "de_DE") == 0 || strcmp (name, "de_DE.UTF-8") == 0);
184 : #else
185 0 : ASSERT (strcmp (name, "de_DE.UTF-8") == 0);
186 : #endif
187 0 : name = gl_locale_name (LC_MESSAGES, "LC_MESSAGES");
188 0 : ASSERT (strcmp (name, "fr_FR.UTF-8") == 0);
189 : }
190 :
191 1 : unsetenv ("LC_ALL");
192 1 : unsetenv ("LC_CTYPE");
193 1 : setenv ("LC_MESSAGES", "fr_FR.UTF-8", 1);
194 1 : unsetenv ("LANG");
195 1 : if (setlocale (LC_ALL, "") != NULL)
196 : {
197 0 : name = gl_locale_name (LC_CTYPE, "LC_CTYPE");
198 0 : ASSERT (strcmp (name, gl_locale_name_default ()) == 0);
199 0 : name = gl_locale_name (LC_MESSAGES, "LC_MESSAGES");
200 0 : ASSERT (strcmp (name, "fr_FR.UTF-8") == 0);
201 : }
202 :
203 : #if HAVE_GOOD_USELOCALE
204 : /* Check that gl_locale_name considers the thread locale. */
205 : {
206 1 : locale_t locale = newlocale (LC_ALL_MASK, "fr_FR.UTF-8", NULL);
207 1 : if (locale != NULL)
208 : {
209 0 : uselocale (locale);
210 0 : name = gl_locale_name (LC_CTYPE, "LC_CTYPE");
211 0 : ASSERT (strcmp (name, "fr_FR.UTF-8") == 0);
212 0 : name = gl_locale_name (LC_MESSAGES, "LC_MESSAGES");
213 0 : ASSERT (strcmp (name, "fr_FR.UTF-8") == 0);
214 0 : uselocale (LC_GLOBAL_LOCALE);
215 0 : freelocale (locale);
216 : }
217 : }
218 :
219 : /* Check that gl_locale_name distinguishes different categories of the
220 : thread locale, and that the name is the right one for each. */
221 : {
222 : unsigned int i;
223 :
224 13 : for (i = 0; i < SIZEOF (categories); i++)
225 : {
226 12 : int category_mask = categories[i].mask;
227 12 : locale_t loc = newlocale (LC_ALL_MASK, "fr_FR.UTF-8", NULL);
228 12 : if (loc != NULL)
229 : {
230 0 : locale_t locale = newlocale (category_mask, "de_DE.UTF-8", loc);
231 0 : if (locale == NULL)
232 0 : freelocale (loc);
233 : else
234 : {
235 : unsigned int j;
236 :
237 0 : uselocale (locale);
238 0 : for (j = 0; j < SIZEOF (categories); j++)
239 : {
240 : const char *name_j =
241 0 : gl_locale_name (categories[j].cat, categories[j].string);
242 0 : if (j == i)
243 0 : ASSERT (strcmp (name_j, "de_DE.UTF-8") == 0);
244 : else
245 0 : ASSERT (strcmp (name_j, "fr_FR.UTF-8") == 0);
246 : }
247 0 : uselocale (LC_GLOBAL_LOCALE);
248 0 : freelocale (locale);
249 : }
250 : }
251 : }
252 : }
253 : #endif
254 1 : }
255 :
256 : /* Test the gl_locale_name_thread() function. */
257 : static void
258 1 : test_locale_name_thread (void)
259 : {
260 : /* Get into a defined state, */
261 1 : setlocale (LC_ALL, "en_US.UTF-8");
262 :
263 : #if HAVE_GOOD_USELOCALE
264 : /* Check that gl_locale_name_thread returns NULL when no thread locale is
265 : set. */
266 1 : uselocale (LC_GLOBAL_LOCALE);
267 1 : ASSERT (gl_locale_name_thread (LC_CTYPE, "LC_CTYPE") == NULL);
268 1 : ASSERT (gl_locale_name_thread (LC_MESSAGES, "LC_MESSAGES") == NULL);
269 :
270 : /* Check that gl_locale_name_thread considers the thread locale. */
271 : {
272 1 : locale_t locale = newlocale (LC_ALL_MASK, "fr_FR.UTF-8", NULL);
273 1 : if (locale != NULL)
274 : {
275 : const char *name;
276 :
277 0 : uselocale (locale);
278 0 : name = gl_locale_name_thread (LC_CTYPE, "LC_CTYPE");
279 0 : ASSERT (strcmp (name, "fr_FR.UTF-8") == 0);
280 0 : name = gl_locale_name_thread (LC_MESSAGES, "LC_MESSAGES");
281 0 : ASSERT (strcmp (name, "fr_FR.UTF-8") == 0);
282 0 : uselocale (LC_GLOBAL_LOCALE);
283 0 : freelocale (locale);
284 : }
285 : }
286 :
287 : /* Check that gl_locale_name_thread distinguishes different categories of the
288 : thread locale, and that the name is the right one for each. */
289 : {
290 : unsigned int i;
291 :
292 13 : for (i = 0; i < SIZEOF (categories); i++)
293 : {
294 12 : int category_mask = categories[i].mask;
295 12 : locale_t loc = newlocale (LC_ALL_MASK, "fr_FR.UTF-8", NULL);
296 12 : if (loc != NULL)
297 : {
298 0 : locale_t locale = newlocale (category_mask, "de_DE.UTF-8", loc);
299 0 : if (locale == NULL)
300 0 : freelocale (loc);
301 : else
302 : {
303 : unsigned int j;
304 :
305 0 : uselocale (locale);
306 0 : for (j = 0; j < SIZEOF (categories); j++)
307 : {
308 : const char *name_j =
309 0 : gl_locale_name_thread (categories[j].cat,
310 : categories[j].string);
311 0 : if (j == i)
312 0 : ASSERT (strcmp (name_j, "de_DE.UTF-8") == 0);
313 : else
314 0 : ASSERT (strcmp (name_j, "fr_FR.UTF-8") == 0);
315 : }
316 0 : uselocale (LC_GLOBAL_LOCALE);
317 0 : freelocale (locale);
318 : }
319 : }
320 : }
321 : }
322 :
323 : /* Check that gl_locale_name_thread returns a string that is allocated with
324 : indefinite extent. */
325 : {
326 : /* Try many locale names in turn, in order to defeat possible caches. */
327 : static const char * const choices[] =
328 : {
329 : "C",
330 : "POSIX",
331 : "af_ZA",
332 : "af_ZA.UTF-8",
333 : "am_ET",
334 : "am_ET.UTF-8",
335 : "be_BY",
336 : "be_BY.UTF-8",
337 : "bg_BG",
338 : "bg_BG.UTF-8",
339 : "ca_ES",
340 : "ca_ES.UTF-8",
341 : "cs_CZ",
342 : "cs_CZ.UTF-8",
343 : "da_DK",
344 : "da_DK.UTF-8",
345 : "de_AT",
346 : "de_AT.UTF-8",
347 : "de_CH",
348 : "de_CH.UTF-8",
349 : "de_DE",
350 : "de_DE.UTF-8",
351 : "el_GR",
352 : "el_GR.UTF-8",
353 : "en_AU",
354 : "en_AU.UTF-8",
355 : "en_CA",
356 : "en_CA.UTF-8",
357 : "en_GB",
358 : "en_GB.UTF-8",
359 : "en_IE",
360 : "en_IE.UTF-8",
361 : "en_NZ",
362 : "en_NZ.UTF-8",
363 : "en_US",
364 : "en_US.UTF-8",
365 : "es_ES",
366 : "es_ES.UTF-8",
367 : "et_EE",
368 : "et_EE.UTF-8",
369 : "eu_ES",
370 : "eu_ES.UTF-8",
371 : "fi_FI",
372 : "fi_FI.UTF-8",
373 : "fr_BE",
374 : "fr_BE.UTF-8",
375 : "fr_CA",
376 : "fr_CA.UTF-8",
377 : "fr_CH",
378 : "fr_CH.UTF-8",
379 : "fr_FR",
380 : "fr_FR.UTF-8",
381 : "he_IL",
382 : "he_IL.UTF-8",
383 : "hr_HR",
384 : "hr_HR.UTF-8",
385 : "hu_HU",
386 : "hu_HU.UTF-8",
387 : "hy_AM",
388 : "is_IS",
389 : "is_IS.UTF-8",
390 : "it_CH",
391 : "it_CH.UTF-8",
392 : "it_IT",
393 : "it_IT.UTF-8",
394 : "ja_JP.UTF-8",
395 : "kk_KZ",
396 : "kk_KZ.UTF-8",
397 : "ko_KR.UTF-8",
398 : "lt_LT",
399 : "lt_LT.UTF-8",
400 : "nl_BE",
401 : "nl_BE.UTF-8",
402 : "nl_NL",
403 : "nl_NL.UTF-8",
404 : "no_NO",
405 : "no_NO.UTF-8",
406 : "pl_PL",
407 : "pl_PL.UTF-8",
408 : "pt_BR",
409 : "pt_BR.UTF-8",
410 : "pt_PT",
411 : "pt_PT.UTF-8",
412 : "ro_RO",
413 : "ro_RO.UTF-8",
414 : "ru_RU",
415 : "ru_RU.UTF-8",
416 : "sk_SK",
417 : "sk_SK.UTF-8",
418 : "sl_SI",
419 : "sl_SI.UTF-8",
420 : "sv_SE",
421 : "sv_SE.UTF-8",
422 : "tr_TR",
423 : "tr_TR.UTF-8",
424 : "uk_UA",
425 : "uk_UA.UTF-8",
426 : "zh_CN",
427 : "zh_CN.UTF-8",
428 : "zh_HK",
429 : "zh_HK.UTF-8",
430 : "zh_TW",
431 : "zh_TW.UTF-8"
432 : };
433 : /* Remember which locales are available. */
434 : unsigned char /* bool */ available[SIZEOF (choices)];
435 : /* Array of remembered results of gl_locale_name_thread. */
436 : const char *unsaved_names[SIZEOF (choices)][SIZEOF (categories)];
437 : /* Array of remembered results of gl_locale_name_thread, stored in safe
438 : memory. */
439 : char *saved_names[SIZEOF (choices)][SIZEOF (categories)];
440 : unsigned int j;
441 :
442 104 : for (j = 0; j < SIZEOF (choices); j++)
443 : {
444 103 : locale_t locale = newlocale (LC_ALL_MASK, choices[j], NULL);
445 103 : available[j] = (locale != NULL);
446 103 : if (locale != NULL)
447 : {
448 : unsigned int i;
449 :
450 3 : uselocale (locale);
451 39 : for (i = 0; i < SIZEOF (categories); i++)
452 : {
453 36 : unsaved_names[j][i] = gl_locale_name_thread (categories[i].cat, categories[i].string);
454 36 : saved_names[j][i] = strdup (unsaved_names[j][i]);
455 : }
456 3 : uselocale (LC_GLOBAL_LOCALE);
457 3 : freelocale (locale);
458 : }
459 : }
460 : /* Verify the unsaved_names are still valid. */
461 104 : for (j = 0; j < SIZEOF (choices); j++)
462 103 : if (available[j])
463 : {
464 : unsigned int i;
465 :
466 39 : for (i = 0; i < SIZEOF (categories); i++)
467 36 : ASSERT (strcmp (unsaved_names[j][i], saved_names[j][i]) == 0);
468 : }
469 : /* Allocate many locales, without freeing them. This is an attempt at
470 : overwriting as much of the previously allocated memory as possible. */
471 104 : for (j = SIZEOF (choices); j > 0; )
472 : {
473 103 : j--;
474 103 : if (available[j])
475 : {
476 3 : locale_t locale = newlocale (LC_ALL_MASK, choices[j], NULL);
477 : unsigned int i;
478 :
479 3 : ASSERT (locale != NULL);
480 3 : uselocale (locale);
481 39 : for (i = 0; i < SIZEOF (categories); i++)
482 : {
483 36 : const char *name = gl_locale_name_thread (categories[i].cat, categories[i].string);
484 36 : ASSERT (strcmp (unsaved_names[j][i], name) == 0);
485 : }
486 3 : uselocale (LC_GLOBAL_LOCALE);
487 3 : freelocale (locale);
488 : }
489 : }
490 : /* Verify the unsaved_names are still valid. */
491 104 : for (j = 0; j < SIZEOF (choices); j++)
492 103 : if (available[j])
493 : {
494 : unsigned int i;
495 :
496 39 : for (i = 0; i < SIZEOF (categories); i++)
497 : {
498 36 : ASSERT (strcmp (unsaved_names[j][i], saved_names[j][i]) == 0);
499 36 : free (saved_names[j][i]);
500 : }
501 : }
502 : }
503 : #else
504 : /* Check that gl_locale_name_thread always returns NULL. */
505 : ASSERT (gl_locale_name_thread (LC_CTYPE, "LC_CTYPE") == NULL);
506 : ASSERT (gl_locale_name_thread (LC_MESSAGES, "LC_MESSAGES") == NULL);
507 : #endif
508 1 : }
509 :
510 : /* Test the gl_locale_name_posix() function. */
511 : static void
512 1 : test_locale_name_posix (void)
513 : {
514 : const char *ret;
515 : const char *name;
516 :
517 : /* Get into a defined state, */
518 1 : setlocale (LC_ALL, "en_US.UTF-8");
519 : #if HAVE_GOOD_USELOCALE
520 1 : uselocale (LC_GLOBAL_LOCALE);
521 : #endif
522 :
523 : /* Check that when all environment variables are unset,
524 : gl_locale_name_posix returns either NULL or the default locale. */
525 1 : unsetenv ("LC_ALL");
526 1 : unsetenv ("LC_CTYPE");
527 1 : unsetenv ("LC_MESSAGES");
528 1 : unsetenv ("LC_NUMERIC");
529 1 : unsetenv ("LANG");
530 : /* Need also to unset all environment variables that specify standard or
531 : non-standard locale categories. Otherwise, on glibc systems, when some
532 : of these variables are set and reference a nonexistent locale, the
533 : setlocale (LC_ALL, "") call below would fail. */
534 1 : unsetenv ("LC_COLLATE");
535 1 : unsetenv ("LC_MONETARY");
536 1 : unsetenv ("LC_TIME");
537 1 : unsetenv ("LC_ADDRESS");
538 1 : unsetenv ("LC_IDENTIFICATION");
539 1 : unsetenv ("LC_MEASUREMENT");
540 1 : unsetenv ("LC_NAME");
541 1 : unsetenv ("LC_PAPER");
542 1 : unsetenv ("LC_TELEPHONE");
543 1 : ret = setlocale (LC_ALL, "");
544 1 : ASSERT (ret != NULL);
545 1 : name = gl_locale_name_posix (LC_MESSAGES, "LC_MESSAGES");
546 1 : ASSERT (name == NULL || strcmp (name, gl_locale_name_default ()) == 0);
547 1 : name = gl_locale_name_posix (LC_NUMERIC, "LC_NUMERIC");
548 1 : ASSERT (name == NULL || strcmp (name, gl_locale_name_default ()) == 0);
549 :
550 : /* Check that an empty environment variable is treated like an unset
551 : environment variable. */
552 :
553 1 : setenv ("LC_ALL", "", 1);
554 1 : unsetenv ("LC_CTYPE");
555 1 : unsetenv ("LC_MESSAGES");
556 1 : unsetenv ("LANG");
557 1 : setlocale (LC_ALL, "");
558 1 : name = gl_locale_name_posix (LC_MESSAGES, "LC_MESSAGES");
559 1 : ASSERT (name == NULL || strcmp (name, gl_locale_name_default ()) == 0);
560 :
561 1 : unsetenv ("LC_ALL");
562 1 : setenv ("LC_CTYPE", "", 1);
563 1 : unsetenv ("LC_MESSAGES");
564 1 : unsetenv ("LANG");
565 1 : setlocale (LC_ALL, "");
566 1 : name = gl_locale_name_posix (LC_MESSAGES, "LC_MESSAGES");
567 1 : ASSERT (name == NULL || strcmp (name, gl_locale_name_default ()) == 0);
568 :
569 1 : unsetenv ("LC_ALL");
570 1 : unsetenv ("LC_CTYPE");
571 1 : setenv ("LC_MESSAGES", "", 1);
572 1 : unsetenv ("LANG");
573 1 : setlocale (LC_ALL, "");
574 1 : name = gl_locale_name_posix (LC_MESSAGES, "LC_MESSAGES");
575 1 : ASSERT (name == NULL || strcmp (name, gl_locale_name_default ()) == 0);
576 :
577 1 : unsetenv ("LC_ALL");
578 1 : unsetenv ("LC_CTYPE");
579 1 : unsetenv ("LC_MESSAGES");
580 1 : setenv ("LANG", "", 1);
581 1 : setlocale (LC_ALL, "");
582 1 : name = gl_locale_name_posix (LC_MESSAGES, "LC_MESSAGES");
583 1 : ASSERT (name == NULL || strcmp (name, gl_locale_name_default ()) == 0);
584 :
585 : /* Check that LC_ALL overrides the others, and LANG is overridden by the
586 : others. */
587 :
588 1 : setenv ("LC_ALL", "C", 1);
589 1 : unsetenv ("LC_CTYPE");
590 1 : unsetenv ("LC_MESSAGES");
591 1 : unsetenv ("LANG");
592 1 : setlocale (LC_ALL, "");
593 1 : name = gl_locale_name_posix (LC_MESSAGES, "LC_MESSAGES");
594 1 : ASSERT (strcmp (name, "C") == 0);
595 :
596 1 : unsetenv ("LC_ALL");
597 1 : setenv ("LC_CTYPE", "C", 1);
598 1 : setenv ("LC_MESSAGES", "C", 1);
599 1 : unsetenv ("LANG");
600 1 : setlocale (LC_ALL, "");
601 1 : name = gl_locale_name_posix (LC_MESSAGES, "LC_MESSAGES");
602 1 : ASSERT (strcmp (name, "C") == 0);
603 :
604 1 : unsetenv ("LC_ALL");
605 1 : unsetenv ("LC_CTYPE");
606 1 : unsetenv ("LC_MESSAGES");
607 1 : setenv ("LANG", "C", 1);
608 1 : setlocale (LC_ALL, "");
609 1 : name = gl_locale_name_posix (LC_MESSAGES, "LC_MESSAGES");
610 1 : ASSERT (strcmp (name, "C") == 0);
611 :
612 : /* Check mixed situations. */
613 :
614 1 : unsetenv ("LC_ALL");
615 1 : unsetenv ("LC_CTYPE");
616 1 : setenv ("LC_MESSAGES", "fr_FR.UTF-8", 1);
617 1 : setenv ("LANG", "de_DE.UTF-8", 1);
618 1 : if (setlocale (LC_ALL, "") != NULL)
619 : {
620 0 : name = gl_locale_name_posix (LC_CTYPE, "LC_CTYPE");
621 : #if defined _WIN32 && !defined __CYGWIN__
622 : ASSERT (strcmp (name, "de_DE") == 0 || strcmp (name, "de_DE.UTF-8") == 0);
623 : #else
624 0 : ASSERT (strcmp (name, "de_DE.UTF-8") == 0);
625 : #endif
626 0 : name = gl_locale_name_posix (LC_MESSAGES, "LC_MESSAGES");
627 0 : ASSERT (strcmp (name, "fr_FR.UTF-8") == 0);
628 : }
629 :
630 1 : unsetenv ("LC_ALL");
631 1 : unsetenv ("LC_CTYPE");
632 1 : setenv ("LC_MESSAGES", "fr_FR.UTF-8", 1);
633 1 : unsetenv ("LANG");
634 1 : if (setlocale (LC_ALL, "") != NULL)
635 : {
636 0 : name = gl_locale_name_posix (LC_CTYPE, "LC_CTYPE");
637 0 : ASSERT (name == NULL || strcmp (name, gl_locale_name_default ()) == 0);
638 0 : name = gl_locale_name_posix (LC_MESSAGES, "LC_MESSAGES");
639 0 : ASSERT (strcmp (name, "fr_FR.UTF-8") == 0);
640 : }
641 :
642 : #if HAVE_GOOD_USELOCALE
643 : /* Check that gl_locale_name_posix ignores the thread locale. */
644 : {
645 1 : locale_t locale = newlocale (LC_ALL_MASK, "fr_FR.UTF-8", NULL);
646 1 : if (locale != NULL)
647 : {
648 0 : unsetenv ("LC_ALL");
649 0 : unsetenv ("LC_CTYPE");
650 0 : unsetenv ("LC_MESSAGES");
651 0 : setenv ("LANG", "C", 1);
652 0 : setlocale (LC_ALL, "");
653 0 : uselocale (locale);
654 0 : name = gl_locale_name_posix (LC_MESSAGES, "LC_MESSAGES");
655 0 : ASSERT (strcmp (name, "C") == 0);
656 0 : uselocale (LC_GLOBAL_LOCALE);
657 0 : freelocale (locale);
658 : }
659 : }
660 : #endif
661 1 : }
662 :
663 : /* Test the gl_locale_name_environ() function. */
664 : static void
665 1 : test_locale_name_environ (void)
666 : {
667 : const char *name;
668 :
669 : /* Get into a defined state, */
670 1 : setlocale (LC_ALL, "en_US.UTF-8");
671 : #if HAVE_GOOD_USELOCALE
672 1 : uselocale (LC_GLOBAL_LOCALE);
673 : #endif
674 :
675 : /* Check that when all environment variables are unset,
676 : gl_locale_name_environ returns NULL. */
677 1 : unsetenv ("LC_ALL");
678 1 : unsetenv ("LC_CTYPE");
679 1 : unsetenv ("LC_MESSAGES");
680 1 : unsetenv ("LC_NUMERIC");
681 1 : unsetenv ("LANG");
682 1 : ASSERT (gl_locale_name_environ (LC_MESSAGES, "LC_MESSAGES") == NULL);
683 1 : ASSERT (gl_locale_name_environ (LC_NUMERIC, "LC_NUMERIC") == NULL);
684 :
685 : /* Check that an empty environment variable is treated like an unset
686 : environment variable. */
687 :
688 1 : setenv ("LC_ALL", "", 1);
689 1 : unsetenv ("LC_CTYPE");
690 1 : unsetenv ("LC_MESSAGES");
691 1 : unsetenv ("LANG");
692 1 : ASSERT (gl_locale_name_environ (LC_MESSAGES, "LC_MESSAGES") == NULL);
693 :
694 1 : unsetenv ("LC_ALL");
695 1 : setenv ("LC_CTYPE", "", 1);
696 1 : unsetenv ("LC_MESSAGES");
697 1 : unsetenv ("LANG");
698 1 : ASSERT (gl_locale_name_environ (LC_MESSAGES, "LC_MESSAGES") == NULL);
699 :
700 1 : unsetenv ("LC_ALL");
701 1 : unsetenv ("LC_CTYPE");
702 1 : setenv ("LC_MESSAGES", "", 1);
703 1 : unsetenv ("LANG");
704 1 : ASSERT (gl_locale_name_environ (LC_MESSAGES, "LC_MESSAGES") == NULL);
705 :
706 1 : unsetenv ("LC_ALL");
707 1 : unsetenv ("LC_CTYPE");
708 1 : unsetenv ("LC_MESSAGES");
709 1 : setenv ("LANG", "", 1);
710 1 : ASSERT (gl_locale_name_environ (LC_MESSAGES, "LC_MESSAGES") == NULL);
711 :
712 : /* Check that LC_ALL overrides the others, and LANG is overridden by the
713 : others. */
714 :
715 1 : setenv ("LC_ALL", "C", 1);
716 1 : unsetenv ("LC_CTYPE");
717 1 : unsetenv ("LC_MESSAGES");
718 1 : unsetenv ("LANG");
719 1 : name = gl_locale_name_environ (LC_MESSAGES, "LC_MESSAGES");
720 1 : ASSERT (strcmp (name, "C") == 0);
721 :
722 1 : unsetenv ("LC_ALL");
723 1 : setenv ("LC_CTYPE", "C", 1);
724 1 : setenv ("LC_MESSAGES", "C", 1);
725 1 : unsetenv ("LANG");
726 1 : name = gl_locale_name_environ (LC_MESSAGES, "LC_MESSAGES");
727 1 : ASSERT (strcmp (name, "C") == 0);
728 :
729 1 : unsetenv ("LC_ALL");
730 1 : unsetenv ("LC_CTYPE");
731 1 : unsetenv ("LC_MESSAGES");
732 1 : setenv ("LANG", "C", 1);
733 1 : name = gl_locale_name_environ (LC_MESSAGES, "LC_MESSAGES");
734 1 : ASSERT (strcmp (name, "C") == 0);
735 :
736 : /* Check mixed situations. */
737 :
738 1 : unsetenv ("LC_ALL");
739 1 : unsetenv ("LC_CTYPE");
740 1 : setenv ("LC_MESSAGES", "fr_FR.UTF-8", 1);
741 1 : setenv ("LANG", "de_DE.UTF-8", 1);
742 1 : name = gl_locale_name_environ (LC_CTYPE, "LC_CTYPE");
743 1 : ASSERT (strcmp (name, "de_DE.UTF-8") == 0);
744 1 : name = gl_locale_name_environ (LC_MESSAGES, "LC_MESSAGES");
745 1 : ASSERT (strcmp (name, "fr_FR.UTF-8") == 0);
746 :
747 1 : unsetenv ("LC_ALL");
748 1 : unsetenv ("LC_CTYPE");
749 1 : setenv ("LC_MESSAGES", "fr_FR.UTF-8", 1);
750 1 : unsetenv ("LANG");
751 1 : name = gl_locale_name_environ (LC_CTYPE, "LC_CTYPE");
752 1 : ASSERT (name == NULL);
753 1 : name = gl_locale_name_environ (LC_MESSAGES, "LC_MESSAGES");
754 1 : ASSERT (strcmp (name, "fr_FR.UTF-8") == 0);
755 :
756 : #if HAVE_GOOD_USELOCALE
757 : /* Check that gl_locale_name_environ ignores the thread locale. */
758 : {
759 1 : locale_t locale = newlocale (LC_ALL_MASK, "fr_FR.UTF-8", NULL);
760 1 : if (locale != NULL)
761 : {
762 0 : unsetenv ("LC_ALL");
763 0 : unsetenv ("LC_CTYPE");
764 0 : unsetenv ("LC_MESSAGES");
765 0 : setenv ("LANG", "C", 1);
766 0 : setlocale (LC_ALL, "");
767 0 : uselocale (locale);
768 0 : name = gl_locale_name_environ (LC_MESSAGES, "LC_MESSAGES");
769 0 : ASSERT (strcmp (name, "C") == 0);
770 0 : uselocale (LC_GLOBAL_LOCALE);
771 0 : freelocale (locale);
772 : }
773 : }
774 : #endif
775 1 : }
776 :
777 : /* Test the gl_locale_name_default() function. */
778 : static void
779 1 : test_locale_name_default (void)
780 : {
781 1 : const char *name = gl_locale_name_default ();
782 :
783 1 : ASSERT (name != NULL);
784 :
785 : /* Only Mac OS X and Windows have a facility for the user to set the default
786 : locale. */
787 : #if !((defined __APPLE__ && defined __MACH__) || (defined _WIN32 || defined __CYGWIN__))
788 1 : ASSERT (strcmp (name, "C") == 0);
789 : #endif
790 :
791 : #if HAVE_GOOD_USELOCALE
792 : /* Check that gl_locale_name_default ignores the thread locale. */
793 : {
794 1 : locale_t locale = newlocale (LC_ALL_MASK, "fr_FR.UTF-8", NULL);
795 1 : if (locale != NULL)
796 : {
797 0 : uselocale (locale);
798 0 : ASSERT (strcmp (gl_locale_name_default (), name) == 0);
799 0 : uselocale (LC_GLOBAL_LOCALE);
800 0 : freelocale (locale);
801 : }
802 : }
803 : #endif
804 1 : }
805 :
806 : int
807 1 : main ()
808 : {
809 1 : test_locale_name ();
810 1 : test_locale_name_thread ();
811 1 : test_locale_name_posix ();
812 1 : test_locale_name_environ ();
813 1 : test_locale_name_default ();
814 :
815 1 : return 0;
816 : }
|