write_archive_locales: Fix memory leak
[platform/upstream/glibc.git] / locale / tst-localedef-path-norm.c
1 /* Test for localedef path name handling and normalization.
2    Copyright (C) 2020-2021 Free Software Foundation, Inc.
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
32 #include <sys/types.h>
33 #include <sys/stat.h>
34 #include <unistd.h>
35
36 #include <support/capture_subprocess.h>
37 #include <support/check.h>
38 #include <support/support.h>
39 #include <support/xunistd.h>
40
41 /* Full path to localedef.  */
42 char *prog;
43
44 /* Execute localedef in a subprocess.  */
45 static void
46 execv_wrapper (void *args)
47 {
48   char **argv = args;
49
50   execv (prog, argv);
51   FAIL_EXIT1 ("execv: %m");
52 }
53
54 struct test_closure
55 {
56   /* Arguments for running localedef.  */
57   const char *const argv[16];
58   /* Expected directory name for compiled locale.  */
59   const char *exp;
60   /* Expected path to compiled locale.  */
61   const char *complocaledir;
62 };
63
64 /* Run localedef with DATA.ARGV arguments (NULL terminated), and expect path to
65    the compiled locale is "DATA.COMPLOCALEDIR/DATA.EXP".  */
66 static void
67 run_test (struct test_closure data)
68 {
69   const char * const *args = data.argv;
70   const char *exp = data.exp;
71   const char *complocaledir = data.complocaledir;
72   struct stat64 fs;
73
74   /* Expected output path.  */
75   const char *path = xasprintf ("%s/%s", complocaledir, exp);
76
77   /* Run test.  */
78   struct support_capture_subprocess result;
79   result = support_capture_subprocess (execv_wrapper, (void *)args);
80   support_capture_subprocess_check (&result, "execv", 0, sc_allow_none);
81   support_capture_subprocess_free (&result);
82
83   /* Verify path is present and is a directory.  */
84   xstat (path, &fs);
85   TEST_VERIFY_EXIT (S_ISDIR (fs.st_mode));
86   printf ("info: Directory '%s' exists.\n", path);
87 }
88
89 static int
90 do_test (void)
91 {
92   /* We are running as root inside the container.  */
93   prog = xasprintf ("%s/localedef", support_bindir_prefix);
94
95   /* We need an arbitrary absolute path for localedef output.
96      Writing to a non-default absolute path disables any kind
97      of path normalization since we expect the user wants the path
98      exactly as they specified it.  */
99 #define ABSDIR "/output"
100   xmkdirp (ABSDIR, 0777);
101
102   /* It takes ~10 seconds to serially execute 9 localedef test.  We
103      could run the compilations in parallel if we want to reduce test
104      time.  We don't want to split this out into distinct tests because
105      it would require multiple chroots.  Batching the same localedef
106      tests saves disk space during testing.  */
107
108   /* Test 1: Expected normalization.
109      Run localedef and expect output in $(complocaledir)/en_US1.utf8,
110      with normalization changing UTF-8 to utf8.  */
111   run_test ((struct test_closure)
112             {
113               .argv = { prog,
114                         "--no-archive",
115                         "-i", "en_US",
116                         "-f", "UTF-8",
117                         "en_US1.UTF-8", NULL },
118               .exp = "en_US1.utf8",
119               .complocaledir = support_complocaledir_prefix
120             });
121
122   /* Test 2: No normalization past '@'.
123      Run localedef and expect output in $(complocaledir)/en_US2.utf8@tEsT,
124      with normalization changing UTF-8@tEsT to utf8@tEsT (everything after
125      @ is untouched).  */
126   run_test ((struct test_closure)
127             {
128               .argv = { prog,
129                         "--no-archive",
130                         "-i", "en_US",
131                         "-f", "UTF-8",
132                         "en_US2.UTF-8@tEsT", NULL },
133               .exp = "en_US2.utf8@tEsT",
134               .complocaledir = support_complocaledir_prefix
135             });
136
137   /* Test 3: No normalization past '@' despite period.
138      Run localedef and expect output in $(complocaledir)/en_US3@tEsT.UTF-8,
139      with normalization changing nothing (everything after @ is untouched)
140      despite there being a period near the end.  */
141   run_test ((struct test_closure)
142             {
143               .argv = { prog,
144                         "--no-archive",
145                         "-i", "en_US",
146                         "-f", "UTF-8",
147                         "en_US3@tEsT.UTF-8", NULL },
148               .exp = "en_US3@tEsT.UTF-8",
149               .complocaledir = support_complocaledir_prefix
150             });
151
152   /* Test 4: Normalize numeric codeset by adding 'iso' prefix.
153      Run localedef and expect output in $(complocaledir)/en_US4.88591,
154      with normalization changing 88591 to iso88591.  */
155   run_test ((struct test_closure)
156             {
157               .argv = { prog,
158                         "--no-archive",
159                         "-i", "en_US",
160                         "-f", "UTF-8",
161                         "en_US4.88591", NULL },
162               .exp = "en_US4.iso88591",
163               .complocaledir = support_complocaledir_prefix
164             });
165
166   /* Test 5: Don't add 'iso' prefix if first char is alpha.
167      Run localedef and expect output in $(complocaledir)/en_US5.a88591,
168      with normalization changing nothing.  */
169   run_test ((struct test_closure)
170             {
171               .argv = { prog,
172                         "--no-archive",
173                         "-i", "en_US",
174                         "-f", "UTF-8",
175                         "en_US5.a88591", NULL },
176               .exp = "en_US5.a88591",
177               .complocaledir = support_complocaledir_prefix
178             });
179
180   /* Test 6: Don't add 'iso' prefix if last char is alpha.
181      Run localedef and expect output in $(complocaledir)/en_US6.88591a,
182      with normalization changing nothing.  */
183   run_test ((struct test_closure)
184             {
185               .argv = { prog,
186                         "--no-archive",
187                         "-i", "en_US",
188                         "-f", "UTF-8",
189                         "en_US6.88591a", NULL },
190               .exp = "en_US6.88591a",
191               .complocaledir = support_complocaledir_prefix
192             });
193
194   /* Test 7: Don't normalize anything with an absolute path.
195      Run localedef and expect output in ABSDIR/en_US7.UTF-8,
196      with normalization changing nothing.  */
197   run_test ((struct test_closure)
198             {
199               .argv = { prog,
200                         "--no-archive",
201                         "-i", "en_US",
202                         "-f", "UTF-8",
203                         ABSDIR "/en_US7.UTF-8", NULL },
204               .exp = "en_US7.UTF-8",
205               .complocaledir = ABSDIR
206             });
207
208   /* Test 8: Don't normalize anything with an absolute path.
209      Run localedef and expect output in ABSDIR/en_US8.UTF-8@tEsT,
210      with normalization changing nothing.  */
211   run_test ((struct test_closure)
212             {
213               .argv = { prog,
214                         "--no-archive",
215                         "-i", "en_US",
216                         "-f", "UTF-8",
217                         ABSDIR "/en_US8.UTF-8@tEsT", NULL },
218               .exp = "en_US8.UTF-8@tEsT",
219               .complocaledir = ABSDIR
220             });
221
222   /* Test 9: Don't normalize anything with an absolute path.
223      Run localedef and expect output in ABSDIR/en_US9@tEsT.UTF-8,
224      with normalization changing nothing.  */
225   run_test ((struct test_closure)
226             {
227               .argv = { prog,
228                         "--no-archive",
229                         "-i", "en_US",
230                         "-f", "UTF-8",
231                         ABSDIR "/en_US9@tEsT.UTF-8", NULL },
232               .exp = "en_US9@tEsT.UTF-8",
233               .complocaledir = ABSDIR
234             });
235
236   return 0;
237 }
238
239 #define TIMEOUT 30
240 #include <support/test-driver.c>