localename: Fix unit test.
[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 #else
278   /* Check that gl_locale_name_thread always returns NULL.  */
279   ASSERT (gl_locale_name_thread (LC_CTYPE, "LC_CTYPE") == NULL);
280   ASSERT (gl_locale_name_thread (LC_MESSAGES, "LC_MESSAGES") == NULL);
281 #endif
282 }
283
284 /* Test the gl_locale_name_posix() function.  */
285 static void
286 test_locale_name_posix (void)
287 {
288   const char *name;
289
290   /* Get into a defined state,  */
291   setlocale (LC_ALL, "en_US.UTF-8");
292 #if HAVE_NEWLOCALE
293   uselocale (LC_GLOBAL_LOCALE);
294 #endif
295
296   /* Check that when all environment variables are unset,
297      gl_locale_name_posix returns either NULL or the default locale.  */
298   unsetenv ("LC_ALL");
299   unsetenv ("LC_CTYPE");
300   unsetenv ("LC_MESSAGES");
301   unsetenv ("LC_NUMERIC");
302   unsetenv ("LANG");
303   setlocale (LC_ALL, "");
304   name = gl_locale_name_posix (LC_MESSAGES, "LC_MESSAGES");
305   ASSERT (name == NULL || strcmp (name, gl_locale_name_default ()) == 0);
306   name = gl_locale_name_posix (LC_NUMERIC, "LC_NUMERIC");
307   ASSERT (name == NULL || strcmp (name, gl_locale_name_default ()) == 0);
308
309   /* Check that an empty environment variable is treated like an unset
310      environment variable.  */
311
312   setenv ("LC_ALL", "", 1);
313   unsetenv ("LC_CTYPE");
314   unsetenv ("LC_MESSAGES");
315   unsetenv ("LANG");
316   setlocale (LC_ALL, "");
317   name = gl_locale_name_posix (LC_MESSAGES, "LC_MESSAGES");
318   ASSERT (name == NULL || strcmp (name, gl_locale_name_default ()) == 0);
319
320   unsetenv ("LC_ALL");
321   setenv ("LC_CTYPE", "", 1);
322   unsetenv ("LC_MESSAGES");
323   unsetenv ("LANG");
324   setlocale (LC_ALL, "");
325   name = gl_locale_name_posix (LC_MESSAGES, "LC_MESSAGES");
326   ASSERT (name == NULL || strcmp (name, gl_locale_name_default ()) == 0);
327
328   unsetenv ("LC_ALL");
329   unsetenv ("LC_CTYPE");
330   setenv ("LC_MESSAGES", "", 1);
331   unsetenv ("LANG");
332   setlocale (LC_ALL, "");
333   name = gl_locale_name_posix (LC_MESSAGES, "LC_MESSAGES");
334   ASSERT (name == NULL || strcmp (name, gl_locale_name_default ()) == 0);
335
336   unsetenv ("LC_ALL");
337   unsetenv ("LC_CTYPE");
338   unsetenv ("LC_MESSAGES");
339   setenv ("LANG", "", 1);
340   setlocale (LC_ALL, "");
341   name = gl_locale_name_posix (LC_MESSAGES, "LC_MESSAGES");
342   ASSERT (name == NULL || strcmp (name, gl_locale_name_default ()) == 0);
343
344   /* Check that LC_ALL overrides the others, and LANG is overridden by the
345      others.  */
346
347   setenv ("LC_ALL", "C", 1);
348   unsetenv ("LC_CTYPE");
349   unsetenv ("LC_MESSAGES");
350   unsetenv ("LANG");
351   setlocale (LC_ALL, "");
352   name = gl_locale_name_posix (LC_MESSAGES, "LC_MESSAGES");
353   ASSERT (strcmp (name, "C") == 0);
354
355   unsetenv ("LC_ALL");
356   setenv ("LC_CTYPE", "C", 1);
357   setenv ("LC_MESSAGES", "C", 1);
358   unsetenv ("LANG");
359   setlocale (LC_ALL, "");
360   name = gl_locale_name_posix (LC_MESSAGES, "LC_MESSAGES");
361   ASSERT (strcmp (name, "C") == 0);
362
363   unsetenv ("LC_ALL");
364   unsetenv ("LC_CTYPE");
365   unsetenv ("LC_MESSAGES");
366   setenv ("LANG", "C", 1);
367   setlocale (LC_ALL, "");
368   name = gl_locale_name_posix (LC_MESSAGES, "LC_MESSAGES");
369   ASSERT (strcmp (name, "C") == 0);
370
371   /* Check mixed situations.  */
372
373   unsetenv ("LC_ALL");
374   unsetenv ("LC_CTYPE");
375   setenv ("LC_MESSAGES", "fr_FR.UTF-8", 1);
376   setenv ("LANG", "de_DE.UTF-8", 1);
377   if (setlocale (LC_ALL, "") != NULL)
378     {
379       name = gl_locale_name_posix (LC_CTYPE, "LC_CTYPE");
380       ASSERT (strcmp (name, "de_DE.UTF-8") == 0);
381       name = gl_locale_name_posix (LC_MESSAGES, "LC_MESSAGES");
382       ASSERT (strcmp (name, "fr_FR.UTF-8") == 0);
383     }
384
385   unsetenv ("LC_ALL");
386   unsetenv ("LC_CTYPE");
387   setenv ("LC_MESSAGES", "fr_FR.UTF-8", 1);
388   unsetenv ("LANG");
389   if (setlocale (LC_ALL, "") != NULL)
390     {
391       name = gl_locale_name_posix (LC_CTYPE, "LC_CTYPE");
392       ASSERT (name == NULL || strcmp (name, gl_locale_name_default ()) == 0);
393       name = gl_locale_name_posix (LC_MESSAGES, "LC_MESSAGES");
394       ASSERT (strcmp (name, "fr_FR.UTF-8") == 0);
395     }
396
397 #if HAVE_NEWLOCALE
398   /* Check that gl_locale_name_posix ignores the thread locale.  */
399   {
400     locale_t locale = newlocale (LC_ALL_MASK, "fr_FR.UTF-8", NULL);
401     if (locale != NULL)
402       {
403         unsetenv ("LC_ALL");
404         unsetenv ("LC_CTYPE");
405         unsetenv ("LC_MESSAGES");
406         setenv ("LANG", "C", 1);
407         setlocale (LC_ALL, "");
408         uselocale (locale);
409         name = gl_locale_name_posix (LC_MESSAGES, "LC_MESSAGES");
410         ASSERT (strcmp (name, "C") == 0);
411       }
412   }
413 #endif
414 }
415
416 /* Test the gl_locale_name_environ() function.  */
417 static void
418 test_locale_name_environ (void)
419 {
420   const char *name;
421
422   /* Get into a defined state,  */
423   setlocale (LC_ALL, "en_US.UTF-8");
424 #if HAVE_NEWLOCALE
425   uselocale (LC_GLOBAL_LOCALE);
426 #endif
427
428   /* Check that when all environment variables are unset,
429      gl_locale_name_environ returns NULL.  */
430   unsetenv ("LC_ALL");
431   unsetenv ("LC_CTYPE");
432   unsetenv ("LC_MESSAGES");
433   unsetenv ("LC_NUMERIC");
434   unsetenv ("LANG");
435   ASSERT (gl_locale_name_environ (LC_MESSAGES, "LC_MESSAGES") == NULL);
436   ASSERT (gl_locale_name_environ (LC_NUMERIC, "LC_NUMERIC") == NULL);
437
438   /* Check that an empty environment variable is treated like an unset
439      environment variable.  */
440
441   setenv ("LC_ALL", "", 1);
442   unsetenv ("LC_CTYPE");
443   unsetenv ("LC_MESSAGES");
444   unsetenv ("LANG");
445   ASSERT (gl_locale_name_environ (LC_MESSAGES, "LC_MESSAGES") == NULL);
446
447   unsetenv ("LC_ALL");
448   setenv ("LC_CTYPE", "", 1);
449   unsetenv ("LC_MESSAGES");
450   unsetenv ("LANG");
451   ASSERT (gl_locale_name_environ (LC_MESSAGES, "LC_MESSAGES") == NULL);
452
453   unsetenv ("LC_ALL");
454   unsetenv ("LC_CTYPE");
455   setenv ("LC_MESSAGES", "", 1);
456   unsetenv ("LANG");
457   ASSERT (gl_locale_name_environ (LC_MESSAGES, "LC_MESSAGES") == NULL);
458
459   unsetenv ("LC_ALL");
460   unsetenv ("LC_CTYPE");
461   unsetenv ("LC_MESSAGES");
462   setenv ("LANG", "", 1);
463   ASSERT (gl_locale_name_environ (LC_MESSAGES, "LC_MESSAGES") == NULL);
464
465   /* Check that LC_ALL overrides the others, and LANG is overridden by the
466      others.  */
467
468   setenv ("LC_ALL", "C", 1);
469   unsetenv ("LC_CTYPE");
470   unsetenv ("LC_MESSAGES");
471   unsetenv ("LANG");
472   name = gl_locale_name_environ (LC_MESSAGES, "LC_MESSAGES");
473   ASSERT (strcmp (name, "C") == 0);
474
475   unsetenv ("LC_ALL");
476   setenv ("LC_CTYPE", "C", 1);
477   setenv ("LC_MESSAGES", "C", 1);
478   unsetenv ("LANG");
479   name = gl_locale_name_environ (LC_MESSAGES, "LC_MESSAGES");
480   ASSERT (strcmp (name, "C") == 0);
481
482   unsetenv ("LC_ALL");
483   unsetenv ("LC_CTYPE");
484   unsetenv ("LC_MESSAGES");
485   setenv ("LANG", "C", 1);
486   name = gl_locale_name_environ (LC_MESSAGES, "LC_MESSAGES");
487   ASSERT (strcmp (name, "C") == 0);
488
489   /* Check mixed situations.  */
490
491   unsetenv ("LC_ALL");
492   unsetenv ("LC_CTYPE");
493   setenv ("LC_MESSAGES", "fr_FR.UTF-8", 1);
494   setenv ("LANG", "de_DE.UTF-8", 1);
495   name = gl_locale_name_environ (LC_CTYPE, "LC_CTYPE");
496   ASSERT (strcmp (name, "de_DE.UTF-8") == 0);
497   name = gl_locale_name_environ (LC_MESSAGES, "LC_MESSAGES");
498   ASSERT (strcmp (name, "fr_FR.UTF-8") == 0);
499
500   unsetenv ("LC_ALL");
501   unsetenv ("LC_CTYPE");
502   setenv ("LC_MESSAGES", "fr_FR.UTF-8", 1);
503   unsetenv ("LANG");
504   name = gl_locale_name_environ (LC_CTYPE, "LC_CTYPE");
505   ASSERT (name == NULL);
506   name = gl_locale_name_environ (LC_MESSAGES, "LC_MESSAGES");
507   ASSERT (strcmp (name, "fr_FR.UTF-8") == 0);
508
509 #if HAVE_NEWLOCALE
510   /* Check that gl_locale_name_environ ignores the thread locale.  */
511   {
512     locale_t locale = newlocale (LC_ALL_MASK, "fr_FR.UTF-8", NULL);
513     if (locale != NULL)
514       {
515         unsetenv ("LC_ALL");
516         unsetenv ("LC_CTYPE");
517         unsetenv ("LC_MESSAGES");
518         setenv ("LANG", "C", 1);
519         setlocale (LC_ALL, "");
520         uselocale (locale);
521         name = gl_locale_name_environ (LC_MESSAGES, "LC_MESSAGES");
522         ASSERT (strcmp (name, "C") == 0);
523       }
524   }
525 #endif
526 }
527
528 /* Test the gl_locale_name_default() function.  */
529 static void
530 test_locale_name_default (void)
531 {
532   const char *name = gl_locale_name_default ();
533
534   ASSERT (name != NULL);
535
536   /* Only MacOS X and Windows have a facility for the user to set the default
537      locale.  */
538 #if !((defined __APPLE__ && defined __MACH__) || (defined _WIN32 || defined __WIN32__ || defined __CYGWIN__))
539   ASSERT (strcmp (name, "C") == 0);
540 #endif
541
542 #if HAVE_NEWLOCALE
543   /* Check that gl_locale_name_default ignores the thread locale.  */
544   {
545     locale_t locale = newlocale (LC_ALL_MASK, "fr_FR.UTF-8", NULL);
546     if (locale != NULL)
547       {
548         uselocale (locale);
549         ASSERT (strcmp (gl_locale_name_default (), name) == 0);
550       }
551   }
552 #endif
553 }
554
555 int
556 main ()
557 {
558   test_locale_name ();
559   test_locale_name_thread ();
560   test_locale_name_posix ();
561   test_locale_name_environ ();
562   test_locale_name_default ();
563
564   return 0;
565 }