]>
Commit | Line | Data |
---|---|---|
92954ffa | 1 | /* Test for localedef path name handling and normalization. |
6d7e8eda | 2 | Copyright (C) 2020-2023 Free Software Foundation, Inc. |
92954ffa CD |
3 | This file is part of the GNU C Library. |
4 | ||
5 | The GNU C Library is free software; you can redistribute it and/or | |
6 | modify it under the terms of the GNU Lesser General Public | |
7 | License as published by the Free Software Foundation; either | |
8 | version 2.1 of the License, or (at your option) any later version. | |
9 | ||
10 | The GNU C Library is distributed in the hope that it will be useful, | |
11 | but WITHOUT ANY WARRANTY; without even the implied warranty of | |
12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
13 | Lesser General Public License for more details. | |
14 | ||
15 | You should have received a copy of the GNU Lesser General Public | |
16 | License along with the GNU C Library; if not, see | |
17 | <https://www.gnu.org/licenses/>. */ | |
18 | ||
19 | /* The test runs localedef with various named paths to test for expected | |
20 | behaviours dealing with codeset name normalization. That is to say that use | |
21 | of UTF-8, and it's variations, are normalized to utf8. Likewise that values | |
22 | after the @ are not normalized and left as-is. The test needs to run | |
23 | localedef with known input values and then check that the generated path | |
24 | matches the expected value after normalization. */ | |
25 | ||
26 | /* Note: In some cases adding -v (verbose) to localedef changes the exit | |
27 | status to a non-zero value because some warnings are only enabled in verbose | |
28 | mode. This should probably be changed so warnings are either present or not | |
29 | present, regardless of verbosity. POSIX requires that any warnings cause the | |
30 | exit status to be non-zero. */ | |
31 | ||
6c4ed247 | 32 | #include <array_length.h> |
92954ffa CD |
33 | #include <sys/types.h> |
34 | #include <sys/stat.h> | |
35 | #include <unistd.h> | |
36 | ||
37 | #include <support/capture_subprocess.h> | |
38 | #include <support/check.h> | |
39 | #include <support/support.h> | |
40 | #include <support/xunistd.h> | |
6c4ed247 | 41 | #include <support/xthread.h> |
92954ffa CD |
42 | |
43 | /* Full path to localedef. */ | |
6c4ed247 | 44 | static const char *prog; |
92954ffa CD |
45 | |
46 | /* Execute localedef in a subprocess. */ | |
47 | static void | |
48 | execv_wrapper (void *args) | |
49 | { | |
50 | char **argv = args; | |
51 | ||
52 | execv (prog, argv); | |
53 | FAIL_EXIT1 ("execv: %m"); | |
54 | } | |
55 | ||
56 | struct test_closure | |
57 | { | |
58 | /* Arguments for running localedef. */ | |
59 | const char *const argv[16]; | |
60 | /* Expected directory name for compiled locale. */ | |
61 | const char *exp; | |
62 | /* Expected path to compiled locale. */ | |
63 | const char *complocaledir; | |
64 | }; | |
65 | ||
66 | /* Run localedef with DATA.ARGV arguments (NULL terminated), and expect path to | |
67 | the compiled locale is "DATA.COMPLOCALEDIR/DATA.EXP". */ | |
6c4ed247 AZ |
68 | static void * |
69 | run_test (void *closure) | |
92954ffa | 70 | { |
6c4ed247 AZ |
71 | struct test_closure *data = closure; |
72 | const char * const *args = data->argv; | |
73 | const char *exp = data->exp; | |
74 | const char *complocaledir = data->complocaledir; | |
92954ffa CD |
75 | struct stat64 fs; |
76 | ||
77 | /* Expected output path. */ | |
78 | const char *path = xasprintf ("%s/%s", complocaledir, exp); | |
79 | ||
80 | /* Run test. */ | |
81 | struct support_capture_subprocess result; | |
82 | result = support_capture_subprocess (execv_wrapper, (void *)args); | |
83 | support_capture_subprocess_check (&result, "execv", 0, sc_allow_none); | |
84 | support_capture_subprocess_free (&result); | |
85 | ||
86 | /* Verify path is present and is a directory. */ | |
87 | xstat (path, &fs); | |
6c4ed247 AZ |
88 | if (!S_ISDIR (fs.st_mode)) |
89 | { | |
90 | support_record_failure (); | |
91 | printf ("error: Directory '%s' does not exist.\n", path); | |
92 | return (void *) -1ULL; | |
93 | } | |
94 | ||
95 | return NULL; | |
92954ffa CD |
96 | } |
97 | ||
98 | static int | |
99 | do_test (void) | |
100 | { | |
101 | /* We are running as root inside the container. */ | |
102 | prog = xasprintf ("%s/localedef", support_bindir_prefix); | |
103 | ||
6f0baacf CD |
104 | /* We need an arbitrary absolute path for localedef output. |
105 | Writing to a non-default absolute path disables any kind | |
92954ffa CD |
106 | of path normalization since we expect the user wants the path |
107 | exactly as they specified it. */ | |
6f0baacf CD |
108 | #define ABSDIR "/output" |
109 | xmkdirp (ABSDIR, 0777); | |
92954ffa | 110 | |
6c4ed247 AZ |
111 | /* It takes ~10 seconds to serially execute 9 localedef test. We run the |
112 | compilations in parallel to reduce test time. We don't want to split | |
113 | this out into distinct tests because it would require multiple chroots. | |
114 | Batching the same localedef tests saves disk space during testing. */ | |
92954ffa | 115 | |
6c4ed247 AZ |
116 | struct test_closure tests[] = |
117 | { | |
92954ffa | 118 | /* Test 1: Expected normalization. |
6f0baacf | 119 | Run localedef and expect output in $(complocaledir)/en_US1.utf8, |
92954ffa | 120 | with normalization changing UTF-8 to utf8. */ |
6c4ed247 AZ |
121 | { |
122 | .argv = { (const char *const) prog, | |
123 | "--no-archive", | |
124 | "-i", "en_US", | |
125 | "-f", "UTF-8", | |
126 | "en_US1.UTF-8", NULL }, | |
127 | .exp = "en_US1.utf8", | |
128 | .complocaledir = support_complocaledir_prefix | |
129 | }, | |
92954ffa | 130 | /* Test 2: No normalization past '@'. |
6f0baacf | 131 | Run localedef and expect output in $(complocaledir)/en_US2.utf8@tEsT, |
92954ffa CD |
132 | with normalization changing UTF-8@tEsT to utf8@tEsT (everything after |
133 | @ is untouched). */ | |
6c4ed247 AZ |
134 | { |
135 | .argv = { prog, | |
136 | "--no-archive", | |
137 | "-i", "en_US", | |
138 | "-f", "UTF-8", | |
139 | "en_US2.UTF-8@tEsT", NULL }, | |
140 | .exp = "en_US2.utf8@tEsT", | |
141 | .complocaledir = support_complocaledir_prefix | |
142 | }, | |
92954ffa | 143 | /* Test 3: No normalization past '@' despite period. |
6f0baacf | 144 | Run localedef and expect output in $(complocaledir)/en_US3@tEsT.UTF-8, |
92954ffa CD |
145 | with normalization changing nothing (everything after @ is untouched) |
146 | despite there being a period near the end. */ | |
6c4ed247 AZ |
147 | { |
148 | .argv = { prog, | |
149 | "--no-archive", | |
150 | "-i", "en_US", | |
151 | "-f", "UTF-8", | |
152 | "en_US3@tEsT.UTF-8", NULL }, | |
153 | .exp = "en_US3@tEsT.UTF-8", | |
154 | .complocaledir = support_complocaledir_prefix | |
155 | }, | |
92954ffa | 156 | /* Test 4: Normalize numeric codeset by adding 'iso' prefix. |
6f0baacf | 157 | Run localedef and expect output in $(complocaledir)/en_US4.88591, |
92954ffa | 158 | with normalization changing 88591 to iso88591. */ |
6c4ed247 AZ |
159 | { |
160 | .argv = { prog, | |
161 | "--no-archive", | |
162 | "-i", "en_US", | |
163 | "-f", "UTF-8", | |
164 | "en_US4.88591", NULL }, | |
165 | .exp = "en_US4.iso88591", | |
166 | .complocaledir = support_complocaledir_prefix | |
167 | }, | |
92954ffa | 168 | /* Test 5: Don't add 'iso' prefix if first char is alpha. |
6f0baacf | 169 | Run localedef and expect output in $(complocaledir)/en_US5.a88591, |
92954ffa | 170 | with normalization changing nothing. */ |
6c4ed247 AZ |
171 | { |
172 | .argv = { prog, | |
173 | "--no-archive", | |
174 | "-i", "en_US", | |
175 | "-f", "UTF-8", | |
176 | "en_US5.a88591", NULL }, | |
177 | .exp = "en_US5.a88591", | |
178 | .complocaledir = support_complocaledir_prefix | |
179 | }, | |
92954ffa | 180 | /* Test 6: Don't add 'iso' prefix if last char is alpha. |
6f0baacf | 181 | Run localedef and expect output in $(complocaledir)/en_US6.88591a, |
92954ffa | 182 | with normalization changing nothing. */ |
6c4ed247 AZ |
183 | { |
184 | .argv = { prog, | |
185 | "--no-archive", | |
186 | "-i", "en_US", | |
187 | "-f", "UTF-8", | |
188 | "en_US6.88591a", NULL }, | |
189 | .exp = "en_US6.88591a", | |
190 | .complocaledir = support_complocaledir_prefix | |
191 | }, | |
92954ffa | 192 | /* Test 7: Don't normalize anything with an absolute path. |
6f0baacf | 193 | Run localedef and expect output in ABSDIR/en_US7.UTF-8, |
92954ffa | 194 | with normalization changing nothing. */ |
6c4ed247 AZ |
195 | { |
196 | .argv = { prog, | |
197 | "--no-archive", | |
198 | "-i", "en_US", | |
199 | "-f", "UTF-8", | |
200 | ABSDIR "/en_US7.UTF-8", NULL }, | |
201 | .exp = "en_US7.UTF-8", | |
202 | .complocaledir = ABSDIR | |
203 | }, | |
92954ffa | 204 | /* Test 8: Don't normalize anything with an absolute path. |
6f0baacf | 205 | Run localedef and expect output in ABSDIR/en_US8.UTF-8@tEsT, |
92954ffa | 206 | with normalization changing nothing. */ |
6c4ed247 AZ |
207 | { |
208 | .argv = { prog, | |
209 | "--no-archive", | |
210 | "-i", "en_US", | |
211 | "-f", "UTF-8", | |
212 | ABSDIR "/en_US8.UTF-8@tEsT", NULL }, | |
213 | .exp = "en_US8.UTF-8@tEsT", | |
214 | .complocaledir = ABSDIR | |
215 | }, | |
92954ffa | 216 | /* Test 9: Don't normalize anything with an absolute path. |
6f0baacf | 217 | Run localedef and expect output in ABSDIR/en_US9@tEsT.UTF-8, |
92954ffa | 218 | with normalization changing nothing. */ |
6c4ed247 AZ |
219 | { |
220 | .argv = { prog, | |
221 | "--no-archive", | |
222 | "-i", "en_US", | |
223 | "-f", "UTF-8", | |
224 | ABSDIR "/en_US9@tEsT.UTF-8", NULL }, | |
225 | .exp = "en_US9@tEsT.UTF-8", | |
226 | .complocaledir = ABSDIR | |
227 | } | |
228 | }; | |
229 | ||
230 | /* Do not run more threads than the maximum of online CPUs. */ | |
231 | size_t ntests = array_length (tests); | |
232 | long int cpus = sysconf (_SC_NPROCESSORS_ONLN); | |
233 | cpus = cpus == -1 ? 1 : cpus; | |
234 | printf ("info: cpus=%ld ntests=%zu\n", cpus, ntests); | |
235 | ||
236 | pthread_t thr[ntests]; | |
237 | ||
238 | for (int i = 0; i < ntests; i += cpus) | |
239 | { | |
240 | int max = i + cpus; | |
241 | if (max > ntests) | |
242 | max = ntests; | |
243 | ||
244 | for (int j = i; j < max; j++) | |
245 | thr[j] = xpthread_create (NULL, run_test, &tests[j]); | |
246 | ||
247 | for (int j = i; j < max; j++) | |
248 | TEST_VERIFY (xpthread_join (thr[j]) == NULL); | |
249 | } | |
92954ffa CD |
250 | |
251 | return 0; | |
252 | } | |
253 | ||
d96cb376 | 254 | #define TIMEOUT 30 |
92954ffa | 255 | #include <support/test-driver.c> |