maint.mk: Update system header list for #include syntax checks.
[gnulib.git] / tests / test-duplocale.c
bloba27f1378f0b8ba4bbc7708a8227786637103fca5
1 /* Test of duplicating a locale object.
2 Copyright (C) 2009-2024 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 <https://www.gnu.org/licenses/>. */
17 /* Written by Bruno Haible <bruno@clisp.org>, 2007. */
19 #include <config.h>
21 #include <locale.h>
23 #if HAVE_WORKING_DUPLOCALE
25 #include "signature.h"
26 SIGNATURE_CHECK (duplocale, locale_t, (locale_t));
28 #include <langinfo.h>
29 #if HAVE_MONETARY_H
30 # include <monetary.h>
31 #endif
32 #include <stdio.h>
33 #include <string.h>
35 #include "macros.h"
37 struct locale_dependent_values
39 #if HAVE_MONETARY_H
40 char monetary[100];
41 #endif
42 char numeric[100];
43 char time[100];
46 static void
47 get_locale_dependent_values (struct locale_dependent_values *result)
49 #if HAVE_MONETARY_H
50 strfmon (result->monetary, sizeof (result->monetary),
51 "%n", 123.75);
52 /* result->monetary is usually "$123.75" */
53 #endif
54 snprintf (result->numeric, sizeof (result->numeric),
55 "%g", 3.5);
56 /* result->numeric is usually "3,5" */
57 strncpy (result->time, nl_langinfo (MON_1), sizeof result->time - 1);
58 result->time[sizeof result->time - 1] = '\0';
59 /* result->time is usually "janvier" */
62 #if HAVE_WORKING_USELOCALE
64 static int
65 test_with_uselocale (void)
67 struct locale_dependent_values expected_results;
68 locale_t mixed1;
69 locale_t mixed2;
70 locale_t perthread;
72 /* Set up a locale which is a mix between different system locales. */
73 setlocale (LC_ALL, "en_US.UTF-8");
74 setlocale (LC_NUMERIC, "de_DE.UTF-8");
75 setlocale (LC_TIME, "fr_FR.UTF-8");
76 get_locale_dependent_values (&expected_results);
78 /* Save the locale in a locale_t object. */
79 mixed1 = duplocale (LC_GLOBAL_LOCALE);
80 ASSERT (mixed1 != NULL);
82 /* Use a per-thread locale. */
83 perthread = newlocale (LC_ALL_MASK, "es_ES.UTF-8", NULL);
84 if (perthread == NULL)
85 return 1;
86 uselocale (perthread);
88 /* Save the locale in a locale_t object again. */
89 mixed2 = duplocale (LC_GLOBAL_LOCALE);
90 ASSERT (mixed2 != NULL);
92 /* Set up a default locale. */
93 setlocale (LC_ALL, "C");
94 uselocale (LC_GLOBAL_LOCALE);
96 struct locale_dependent_values c_results;
97 get_locale_dependent_values (&c_results);
100 /* Now use the saved locale mixed1 again. */
101 setlocale (LC_ALL, "C");
102 uselocale (LC_GLOBAL_LOCALE);
103 uselocale (mixed1);
105 struct locale_dependent_values results;
106 get_locale_dependent_values (&results);
107 # if HAVE_MONETARY_H
108 ASSERT (strcmp (results.monetary, expected_results.monetary) == 0);
109 # endif
110 ASSERT (strcmp (results.numeric, expected_results.numeric) == 0);
111 ASSERT (strcmp (results.time, expected_results.time) == 0);
114 /* Now use the saved locale mixed2 again. */
115 setlocale (LC_ALL, "C");
116 uselocale (LC_GLOBAL_LOCALE);
117 uselocale (mixed2);
119 struct locale_dependent_values results;
120 get_locale_dependent_values (&results);
121 # if HAVE_MONETARY_H
122 ASSERT (strcmp (results.monetary, expected_results.monetary) == 0);
123 # endif
124 ASSERT (strcmp (results.numeric, expected_results.numeric) == 0);
125 ASSERT (strcmp (results.time, expected_results.time) == 0);
128 setlocale (LC_ALL, "C");
129 uselocale (LC_GLOBAL_LOCALE);
130 freelocale (mixed1);
131 freelocale (mixed2);
132 freelocale (perthread);
133 return 0;
136 #endif
138 #if HAVE_STRFMON_L || HAVE_SNPRINTF_L || (HAVE_NL_LANGINFO_L && HAVE_WORKING_USELOCALE)
140 static void
141 get_locale_dependent_values_from (struct locale_dependent_values *result, locale_t locale)
143 #if HAVE_STRFMON_L
144 strfmon_l (result->monetary, sizeof (result->monetary), locale,
145 "%n", 123.75);
146 /* result->monetary is usually "$123.75" */
147 #endif
148 #if HAVE_SNPRINTF_L
149 snprintf_l (result->numeric, sizeof (result->numeric), locale,
150 "%g", 3.5);
151 /* result->numeric is usually "3,5" */
152 #endif
153 #if HAVE_NL_LANGINFO_L && HAVE_WORKING_USELOCALE
154 strcpy (result->time, nl_langinfo_l (MON_1, locale));
155 /* result->time is usually "janvier" */
156 #endif
159 static int
160 test_with_locale_parameter (void)
162 struct locale_dependent_values expected_results;
163 locale_t mixed1;
164 locale_t mixed2;
166 /* Set up a locale which is a mix between different system locales. */
167 setlocale (LC_ALL, "en_US.UTF-8");
168 setlocale (LC_NUMERIC, "de_DE.UTF-8");
169 setlocale (LC_TIME, "fr_FR.UTF-8");
170 get_locale_dependent_values (&expected_results);
172 /* Save the locale in a locale_t object. */
173 mixed1 = duplocale (LC_GLOBAL_LOCALE);
174 ASSERT (mixed1 != NULL);
176 /* Create another locale_t object. */
177 mixed2 = newlocale (LC_ALL_MASK, "es_ES.UTF-8", NULL);
178 if (mixed2 == NULL)
179 return 1;
181 /* Set up a default locale. */
182 setlocale (LC_ALL, "C");
184 struct locale_dependent_values c_results;
185 get_locale_dependent_values (&c_results);
188 /* Now use the saved locale mixed2. */
190 struct locale_dependent_values results;
191 get_locale_dependent_values_from (&results, mixed2);
194 /* Now use the saved locale mixed1 again. */
196 struct locale_dependent_values results;
197 get_locale_dependent_values_from (&results, mixed1);
198 #if HAVE_STRFMON_L
199 ASSERT (strcmp (results.monetary, expected_results.monetary) == 0);
200 #endif
201 #if HAVE_SNPRINTF_L
202 ASSERT (strcmp (results.numeric, expected_results.numeric) == 0);
203 #endif
204 #if HAVE_NL_LANGINFO_L && HAVE_WORKING_USELOCALE
205 ASSERT (strcmp (results.time, expected_results.time) == 0);
206 #endif
209 freelocale (mixed1);
210 freelocale (mixed2);
211 return 0;
214 #endif
217 main ()
219 int skipped = 0;
220 #if HAVE_WORKING_USELOCALE
221 skipped |= test_with_uselocale ();
222 #endif
223 #if HAVE_STRFMON_L || HAVE_SNPRINTF_L || (HAVE_NL_LANGINFO_L && HAVE_WORKING_USELOCALE)
224 skipped |= test_with_locale_parameter ();
225 #endif
227 if (skipped)
229 if (test_exit_status != EXIT_SUCCESS)
230 return test_exit_status;
231 fprintf (stderr, "Skipping test: Spanish Unicode locale is not installed\n");
232 return 77;
235 return test_exit_status;
238 #else
240 #include <stdio.h>
243 main ()
245 fprintf (stderr, "Skipping test: function duplocale not available\n");
246 return 77;
249 #endif