localename: Fix storage allocation of gl_locale_name_thread's result.
[gnulib.git] / tests / test-localename.c
1 /* Test of gl_locale_name function and its variants.
2    Copyright (C) 2007-2009 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 <http://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 static struct { int cat; int mask; const char *string; } const categories[] =
30   {
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" }
37 # ifdef LC_PAPER
38     , { LC_PAPER,          LC_PAPER_MASK,          "LC_PAPER" }
39 # endif
40 # ifdef LC_NAME
41     , { LC_NAME,           LC_NAME_MASK,           "LC_NAME" }
42 # endif
43 # ifdef LC_ADDRESS
44     , { LC_ADDRESS,        LC_ADDRESS_MASK,        "LC_ADDRESS" }
45 # endif
46 # ifdef LC_TELEPHONE
47     , { LC_TELEPHONE,      LC_TELEPHONE_MASK,      "LC_TELEPHONE" }
48 # endif
49 # ifdef LC_MEASUREMENT
50     , { LC_MEASUREMENT,    LC_MEASUREMENT_MASK,    "LC_MEASUREMENT" }
51 # endif
52 # ifdef LC_IDENTIFICATION
53     , { LC_IDENTIFICATION, LC_IDENTIFICATION_MASK, "LC_IDENTIFICATION" }
54 # endif
55   };
56
57 /* Test the gl_locale_name() function.  */
58 static void
59 test_locale_name (void)
60 {
61   const char *name;
62
63   /* Check that gl_locale_name returns non-NULL.  */
64   ASSERT (gl_locale_name (LC_MESSAGES, "LC_MESSAGES") != NULL);
65
66   /* Get into a defined state,  */
67   setlocale (LC_ALL, "en_US.UTF-8");
68 #if HAVE_NEWLOCALE
69   uselocale (LC_GLOBAL_LOCALE);
70 #endif
71
72   /* Check that when all environment variables are unset,
73      gl_locale_name returns the default locale.  */
74   unsetenv ("LC_ALL");
75   unsetenv ("LC_CTYPE");
76   unsetenv ("LC_MESSAGES");
77   unsetenv ("LC_NUMERIC");
78   unsetenv ("LANG");
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);
84
85   /* Check that an empty environment variable is treated like an unset
86      environment variable.  */
87
88   setenv ("LC_ALL", "", 1);
89   unsetenv ("LC_CTYPE");
90   unsetenv ("LC_MESSAGES");
91   unsetenv ("LANG");
92   setlocale (LC_ALL, "");
93   ASSERT (strcmp (gl_locale_name (LC_MESSAGES, "LC_MESSAGES"),
94                   gl_locale_name_default ()) == 0);
95
96   unsetenv ("LC_ALL");
97   setenv ("LC_CTYPE", "", 1);
98   unsetenv ("LC_MESSAGES");
99   unsetenv ("LANG");
100   setlocale (LC_ALL, "");
101   ASSERT (strcmp (gl_locale_name (LC_MESSAGES, "LC_MESSAGES"),
102                   gl_locale_name_default ()) == 0);
103
104   unsetenv ("LC_ALL");
105   unsetenv ("LC_CTYPE");
106   setenv ("LC_MESSAGES", "", 1);
107   unsetenv ("LANG");
108   setlocale (LC_ALL, "");
109   ASSERT (strcmp (gl_locale_name (LC_MESSAGES, "LC_MESSAGES"),
110                   gl_locale_name_default ()) == 0);
111
112   unsetenv ("LC_ALL");
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);
119
120   /* Check that LC_ALL overrides the others, and LANG is overridden by the
121      others.  */
122
123   setenv ("LC_ALL", "C", 1);
124   unsetenv ("LC_CTYPE");
125   unsetenv ("LC_MESSAGES");
126   unsetenv ("LANG");
127   setlocale (LC_ALL, "");
128   ASSERT (strcmp (gl_locale_name (LC_MESSAGES, "LC_MESSAGES"), "C") == 0);
129
130   unsetenv ("LC_ALL");
131   setenv ("LC_CTYPE", "C", 1);
132   setenv ("LC_MESSAGES", "C", 1);
133   unsetenv ("LANG");
134   setlocale (LC_ALL, "");
135   ASSERT (strcmp (gl_locale_name (LC_MESSAGES, "LC_MESSAGES"), "C") == 0);
136
137   unsetenv ("LC_ALL");
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);
143
144   /* Check mixed situations.  */
145
146   unsetenv ("LC_ALL");
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)
151     {
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);
156     }
157
158   unsetenv ("LC_ALL");
159   unsetenv ("LC_CTYPE");
160   setenv ("LC_MESSAGES", "fr_FR.UTF-8", 1);
161   unsetenv ("LANG");
162   if (setlocale (LC_ALL, "") != NULL)
163     {
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);
168     }
169
170 #if HAVE_NEWLOCALE
171   /* Check that gl_locale_name considers the thread locale.  */
172   {
173     locale_t locale = newlocale (LC_ALL_MASK, "fr_FR.UTF-8", NULL);
174     if (locale != NULL)
175       {
176         uselocale (locale);
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);
181       }
182   }
183
184   /* Check that gl_locale_name distinguishes different categories of the
185      thread locale, and that the name is the right one for each.  */
186   {
187     unsigned int i;
188
189     for (i = 0; i < SIZEOF (categories); i++)
190       {
191         int category_mask = categories[i].mask;
192         locale_t locale = newlocale (LC_ALL_MASK, "fr_FR.UTF-8", NULL);
193         if (locale != NULL)
194           {
195             locale = newlocale (category_mask, "de_DE.UTF-8", locale);
196             if (locale != NULL)
197               {
198                 unsigned int j;
199
200                 uselocale (locale);
201                 for (j = 0; j < SIZEOF (categories); j++)
202                   {
203                     const char *name_j =
204                       gl_locale_name (categories[j].cat, categories[j].string);
205                     if (j == i)
206                       ASSERT (strcmp (name_j, "de_DE.UTF-8") == 0);
207                     else
208                       ASSERT (strcmp (name_j, "fr_FR.UTF-8") == 0);
209                   }
210               }
211           }
212       }
213   }
214 #endif
215 }
216
217 /* Test the gl_locale_name_thread() function.  */
218 static void
219 test_locale_name_thread (void)
220 {
221   /* Get into a defined state,  */
222   setlocale (LC_ALL, "en_US.UTF-8");
223
224 #if HAVE_NEWLOCALE
225   /* Check that gl_locale_name_thread returns NULL when no thread locale is
226      set.  */
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);
230
231   /* Check that gl_locale_name_thread considers the thread locale.  */
232   {
233     locale_t locale = newlocale (LC_ALL_MASK, "fr_FR.UTF-8", NULL);
234     if (locale != NULL)
235       {
236         const char *name;
237
238         uselocale (locale);
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);
243       }
244   }
245
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.  */
248   {
249     unsigned int i;
250
251     for (i = 0; i < SIZEOF (categories); i++)
252       {
253         int category_mask = categories[i].mask;
254         locale_t locale = newlocale (LC_ALL_MASK, "fr_FR.UTF-8", NULL);
255         if (locale != NULL)
256           {
257             locale = newlocale (category_mask, "de_DE.UTF-8", locale);
258             if (locale != NULL)
259               {
260                 unsigned int j;
261
262                 uselocale (locale);
263                 for (j = 0; j < SIZEOF (categories); j++)
264                   {
265                     const char *name_j =
266                       gl_locale_name_thread (categories[j].cat,
267                                              categories[j].string);
268                     if (j == i)
269                       ASSERT (strcmp (name_j, "de_DE.UTF-8") == 0);
270                     else
271                       ASSERT (strcmp (name_j, "fr_FR.UTF-8") == 0);
272                   }
273               }
274           }
275       }
276   }
277
278   /* Check that gl_locale_name_thread returns a string that is allocated with
279      indefinite extent.  */
280   {
281     /* Try many locale names in turn, in order to defeat possible caches.  */
282     static const char * const choices[] =
283       {
284         "C",
285         "POSIX",
286         "af_ZA",
287         "af_ZA.UTF-8",
288         "am_ET",
289         "am_ET.UTF-8",
290         "be_BY",
291         "be_BY.UTF-8",
292         "bg_BG",
293         "bg_BG.UTF-8",
294         "ca_ES",
295         "ca_ES.UTF-8",
296         "cs_CZ",
297         "cs_CZ.UTF-8",
298         "da_DK",
299         "da_DK.UTF-8",
300         "de_AT",
301         "de_AT.UTF-8",
302         "de_CH",
303         "de_CH.UTF-8",
304         "de_DE",
305         "de_DE.UTF-8",
306         "el_GR",
307         "el_GR.UTF-8",
308         "en_AU",
309         "en_AU.UTF-8",
310         "en_CA",
311         "en_CA.UTF-8",
312         "en_GB",
313         "en_GB.UTF-8",
314         "en_IE",
315         "en_IE.UTF-8",
316         "en_NZ",
317         "en_NZ.UTF-8",
318         "en_US",
319         "en_US.UTF-8",
320         "es_ES",
321         "es_ES.UTF-8",
322         "et_EE",
323         "et_EE.UTF-8",
324         "eu_ES",
325         "eu_ES.UTF-8",
326         "fi_FI",
327         "fi_FI.UTF-8",
328         "fr_BE",
329         "fr_BE.UTF-8",
330         "fr_CA",
331         "fr_CA.UTF-8",
332         "fr_CH",
333         "fr_CH.UTF-8",
334         "fr_FR",
335         "fr_FR.UTF-8",
336         "he_IL",
337         "he_IL.UTF-8",
338         "hr_HR",
339         "hr_HR.UTF-8",
340         "hu_HU",
341         "hu_HU.UTF-8",
342         "hy_AM",
343         "is_IS",
344         "is_IS.UTF-8",
345         "it_CH",
346         "it_CH.UTF-8",
347         "it_IT",
348         "it_IT.UTF-8",
349         "ja_JP.UTF-8",
350         "kk_KZ",
351         "kk_KZ.UTF-8",
352         "ko_KR.UTF-8",
353         "lt_LT",
354         "lt_LT.UTF-8",
355         "nl_BE",
356         "nl_BE.UTF-8",
357         "nl_NL",
358         "nl_NL.UTF-8",
359         "no_NO",
360         "no_NO.UTF-8",
361         "pl_PL",
362         "pl_PL.UTF-8",
363         "pt_BR",
364         "pt_BR.UTF-8",
365         "pt_PT",
366         "pt_PT.UTF-8",
367         "ro_RO",
368         "ro_RO.UTF-8",
369         "ru_RU",
370         "ru_RU.UTF-8",
371         "sk_SK",
372         "sk_SK.UTF-8",
373         "sl_SI",
374         "sl_SI.UTF-8",
375         "sv_SE",
376         "sv_SE.UTF-8",
377         "tr_TR",
378         "tr_TR.UTF-8",
379         "uk_UA",
380         "uk_UA.UTF-8",
381         "zh_CN",
382         "zh_CN.UTF-8",
383         "zh_HK",
384         "zh_HK.UTF-8",
385         "zh_TW",
386         "zh_TW.UTF-8"
387       };
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
393        memory.  */
394     char *saved_names[SIZEOF (choices)][SIZEOF (categories)];
395     unsigned int j;
396
397     for (j = 0; j < SIZEOF (choices); j++)
398       {
399         locale_t locale = newlocale (LC_ALL_MASK, choices[j], NULL);
400         available[j] = (locale != NULL);
401         if (locale != NULL)
402           {
403             unsigned int i;
404
405             uselocale (locale);
406             for (i = 0; i < SIZEOF (categories); i++)
407               {
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]);
410               }
411             uselocale (LC_GLOBAL_LOCALE);
412             freelocale (locale);
413           }
414       }
415     /* Verify the unsaved_names are still valid.  */
416     for (j = 0; j < SIZEOF (choices); j++)
417       {
418         unsigned int i;
419
420         for (i = 0; i < SIZEOF (categories); i++)
421           ASSERT (strcmp (unsaved_names[j][i], saved_names[j][i]) == 0);
422       }
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; )
426       {
427         j--;
428         if (available[j])
429           {
430             locale_t locale = newlocale (LC_ALL_MASK, choices[j], NULL);
431             unsigned int i;
432
433             ASSERT (locale != NULL);
434             uselocale (locale);
435             for (i = 0; i < SIZEOF (categories); i++)
436               {
437                 const char *name = gl_locale_name_thread (categories[i].cat, categories[i].string);
438                 ASSERT (strcmp (unsaved_names[j][i], name) == 0);
439               }
440             uselocale (LC_GLOBAL_LOCALE);
441           }
442       }
443     /* Verify the unsaved_names are still valid.  */
444     for (j = 0; j < SIZEOF (choices); j++)
445       {
446         unsigned int i;
447
448         for (i = 0; i < SIZEOF (categories); i++)
449           ASSERT (strcmp (unsaved_names[j][i], saved_names[j][i]) == 0);
450       }
451   }
452 #else
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);
456 #endif
457 }
458
459 /* Test the gl_locale_name_posix() function.  */
460 static void
461 test_locale_name_posix (void)
462 {
463   const char *name;
464
465   /* Get into a defined state,  */
466   setlocale (LC_ALL, "en_US.UTF-8");
467 #if HAVE_NEWLOCALE
468   uselocale (LC_GLOBAL_LOCALE);
469 #endif
470
471   /* Check that when all environment variables are unset,
472      gl_locale_name_posix returns either NULL or the default locale.  */
473   unsetenv ("LC_ALL");
474   unsetenv ("LC_CTYPE");
475   unsetenv ("LC_MESSAGES");
476   unsetenv ("LC_NUMERIC");
477   unsetenv ("LANG");
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);
483
484   /* Check that an empty environment variable is treated like an unset
485      environment variable.  */
486
487   setenv ("LC_ALL", "", 1);
488   unsetenv ("LC_CTYPE");
489   unsetenv ("LC_MESSAGES");
490   unsetenv ("LANG");
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);
494
495   unsetenv ("LC_ALL");
496   setenv ("LC_CTYPE", "", 1);
497   unsetenv ("LC_MESSAGES");
498   unsetenv ("LANG");
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);
502
503   unsetenv ("LC_ALL");
504   unsetenv ("LC_CTYPE");
505   setenv ("LC_MESSAGES", "", 1);
506   unsetenv ("LANG");
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);
510
511   unsetenv ("LC_ALL");
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);
518
519   /* Check that LC_ALL overrides the others, and LANG is overridden by the
520      others.  */
521
522   setenv ("LC_ALL", "C", 1);
523   unsetenv ("LC_CTYPE");
524   unsetenv ("LC_MESSAGES");
525   unsetenv ("LANG");
526   setlocale (LC_ALL, "");
527   name = gl_locale_name_posix (LC_MESSAGES, "LC_MESSAGES");
528   ASSERT (strcmp (name, "C") == 0);
529
530   unsetenv ("LC_ALL");
531   setenv ("LC_CTYPE", "C", 1);
532   setenv ("LC_MESSAGES", "C", 1);
533   unsetenv ("LANG");
534   setlocale (LC_ALL, "");
535   name = gl_locale_name_posix (LC_MESSAGES, "LC_MESSAGES");
536   ASSERT (strcmp (name, "C") == 0);
537
538   unsetenv ("LC_ALL");
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);
545
546   /* Check mixed situations.  */
547
548   unsetenv ("LC_ALL");
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)
553     {
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);
558     }
559
560   unsetenv ("LC_ALL");
561   unsetenv ("LC_CTYPE");
562   setenv ("LC_MESSAGES", "fr_FR.UTF-8", 1);
563   unsetenv ("LANG");
564   if (setlocale (LC_ALL, "") != NULL)
565     {
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);
570     }
571
572 #if HAVE_NEWLOCALE
573   /* Check that gl_locale_name_posix ignores the thread locale.  */
574   {
575     locale_t locale = newlocale (LC_ALL_MASK, "fr_FR.UTF-8", NULL);
576     if (locale != NULL)
577       {
578         unsetenv ("LC_ALL");
579         unsetenv ("LC_CTYPE");
580         unsetenv ("LC_MESSAGES");
581         setenv ("LANG", "C", 1);
582         setlocale (LC_ALL, "");
583         uselocale (locale);
584         name = gl_locale_name_posix (LC_MESSAGES, "LC_MESSAGES");
585         ASSERT (strcmp (name, "C") == 0);
586       }
587   }
588 #endif
589 }
590
591 /* Test the gl_locale_name_environ() function.  */
592 static void
593 test_locale_name_environ (void)
594 {
595   const char *name;
596
597   /* Get into a defined state,  */
598   setlocale (LC_ALL, "en_US.UTF-8");
599 #if HAVE_NEWLOCALE
600   uselocale (LC_GLOBAL_LOCALE);
601 #endif
602
603   /* Check that when all environment variables are unset,
604      gl_locale_name_environ returns NULL.  */
605   unsetenv ("LC_ALL");
606   unsetenv ("LC_CTYPE");
607   unsetenv ("LC_MESSAGES");
608   unsetenv ("LC_NUMERIC");
609   unsetenv ("LANG");
610   ASSERT (gl_locale_name_environ (LC_MESSAGES, "LC_MESSAGES") == NULL);
611   ASSERT (gl_locale_name_environ (LC_NUMERIC, "LC_NUMERIC") == NULL);
612
613   /* Check that an empty environment variable is treated like an unset
614      environment variable.  */
615
616   setenv ("LC_ALL", "", 1);
617   unsetenv ("LC_CTYPE");
618   unsetenv ("LC_MESSAGES");
619   unsetenv ("LANG");
620   ASSERT (gl_locale_name_environ (LC_MESSAGES, "LC_MESSAGES") == NULL);
621
622   unsetenv ("LC_ALL");
623   setenv ("LC_CTYPE", "", 1);
624   unsetenv ("LC_MESSAGES");
625   unsetenv ("LANG");
626   ASSERT (gl_locale_name_environ (LC_MESSAGES, "LC_MESSAGES") == NULL);
627
628   unsetenv ("LC_ALL");
629   unsetenv ("LC_CTYPE");
630   setenv ("LC_MESSAGES", "", 1);
631   unsetenv ("LANG");
632   ASSERT (gl_locale_name_environ (LC_MESSAGES, "LC_MESSAGES") == NULL);
633
634   unsetenv ("LC_ALL");
635   unsetenv ("LC_CTYPE");
636   unsetenv ("LC_MESSAGES");
637   setenv ("LANG", "", 1);
638   ASSERT (gl_locale_name_environ (LC_MESSAGES, "LC_MESSAGES") == NULL);
639
640   /* Check that LC_ALL overrides the others, and LANG is overridden by the
641      others.  */
642
643   setenv ("LC_ALL", "C", 1);
644   unsetenv ("LC_CTYPE");
645   unsetenv ("LC_MESSAGES");
646   unsetenv ("LANG");
647   name = gl_locale_name_environ (LC_MESSAGES, "LC_MESSAGES");
648   ASSERT (strcmp (name, "C") == 0);
649
650   unsetenv ("LC_ALL");
651   setenv ("LC_CTYPE", "C", 1);
652   setenv ("LC_MESSAGES", "C", 1);
653   unsetenv ("LANG");
654   name = gl_locale_name_environ (LC_MESSAGES, "LC_MESSAGES");
655   ASSERT (strcmp (name, "C") == 0);
656
657   unsetenv ("LC_ALL");
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);
663
664   /* Check mixed situations.  */
665
666   unsetenv ("LC_ALL");
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);
674
675   unsetenv ("LC_ALL");
676   unsetenv ("LC_CTYPE");
677   setenv ("LC_MESSAGES", "fr_FR.UTF-8", 1);
678   unsetenv ("LANG");
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);
683
684 #if HAVE_NEWLOCALE
685   /* Check that gl_locale_name_environ ignores the thread locale.  */
686   {
687     locale_t locale = newlocale (LC_ALL_MASK, "fr_FR.UTF-8", NULL);
688     if (locale != NULL)
689       {
690         unsetenv ("LC_ALL");
691         unsetenv ("LC_CTYPE");
692         unsetenv ("LC_MESSAGES");
693         setenv ("LANG", "C", 1);
694         setlocale (LC_ALL, "");
695         uselocale (locale);
696         name = gl_locale_name_environ (LC_MESSAGES, "LC_MESSAGES");
697         ASSERT (strcmp (name, "C") == 0);
698       }
699   }
700 #endif
701 }
702
703 /* Test the gl_locale_name_default() function.  */
704 static void
705 test_locale_name_default (void)
706 {
707   const char *name = gl_locale_name_default ();
708
709   ASSERT (name != NULL);
710
711   /* Only MacOS X and Windows have a facility for the user to set the default
712      locale.  */
713 #if !((defined __APPLE__ && defined __MACH__) || (defined _WIN32 || defined __WIN32__ || defined __CYGWIN__))
714   ASSERT (strcmp (name, "C") == 0);
715 #endif
716
717 #if HAVE_NEWLOCALE
718   /* Check that gl_locale_name_default ignores the thread locale.  */
719   {
720     locale_t locale = newlocale (LC_ALL_MASK, "fr_FR.UTF-8", NULL);
721     if (locale != NULL)
722       {
723         uselocale (locale);
724         ASSERT (strcmp (gl_locale_name_default (), name) == 0);
725       }
726   }
727 #endif
728 }
729
730 int
731 main ()
732 {
733   test_locale_name ();
734   test_locale_name_thread ();
735   test_locale_name_posix ();
736   test_locale_name_environ ();
737   test_locale_name_default ();
738
739   return 0;
740 }