1 /* Regular expression tests.
2    Copyright (C) 2003-2022 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 #include <sys/types.h>
20 #include <mcheck.h>
21 #include <regex.h>
22 #include <stdio.h>
23 #include <stdlib.h>
24 #include <string.h>
25 #include <locale.h>
26 #include <libc-diag.h>
27 #include <support/support.h>
28 
29 #define BRE RE_SYNTAX_POSIX_BASIC
30 #define ERE RE_SYNTAX_POSIX_EXTENDED
31 
32 static struct test_s
33 {
34   int syntax;
35   const char *pattern;
36   const char *string;
37   int start, res;
38 } tests[] = {
39   {BRE, "\\<A", "CBAA", 0, -1},
40   {BRE, "\\<A", "CBAA", 2, -1},
41   {BRE, "A\\>", "CAAB", 1, -1},
42   {BRE, "\\bA", "CBAA", 0, -1},
43   {BRE, "\\bA", "CBAA", 2, -1},
44   {BRE, "A\\b", "CAAB", 1, -1},
45   {BRE, "\\<A", "AA", 0, 0},
46   {BRE, "\\<A", "C-AA", 2, 2},
47   {BRE, "A\\>", "CAA-", 1, 2},
48   {BRE, "A\\>", "CAA", 1, 2},
49   {BRE, "\\bA", "AA", 0, 0},
50   {BRE, "\\bA", "C-AA", 2, 2},
51   {BRE, "A\\b", "CAA-", 1, 2},
52   {BRE, "A\\b", "CAA", 1, 2},
53   {BRE, "\\<[A]", "CBAA", 0, -1},
54   {BRE, "\\<[A]", "CBAA", 2, -1},
55   {BRE, "[A]\\>", "CAAB", 1, -1},
56   {BRE, "\\b[A]", "CBAA", 0, -1},
57   {BRE, "\\b[A]", "CBAA", 2, -1},
58   {BRE, "[A]\\b", "CAAB", 1, -1},
59   {BRE, "\\<[A]", "AA", 0, 0},
60   {BRE, "\\<[A]", "C-AA", 2, 2},
61   {BRE, "[A]\\>", "CAA-", 1, 2},
62   {BRE, "[A]\\>", "CAA", 1, 2},
63   {BRE, "\\b[A]", "AA", 0, 0},
64   {BRE, "\\b[A]", "C-AA", 2, 2},
65   {BRE, "[A]\\b", "CAA-", 1, 2},
66   {BRE, "[A]\\b", "CAA", 1, 2},
67   {ERE, "\\b(A|!|.B)", "A=AC", 0, 0},
68   {ERE, "\\b(A|!|.B)", "=AC", 0, 1},
69   {ERE, "\\b(A|!|.B)", "!AC", 0, 1},
70   {ERE, "\\b(A|!|.B)", "=AB", 0, 1},
71   {ERE, "\\b(A|!|.B)", "DA!C", 0, 2},
72   {ERE, "\\b(A|!|.B)", "=CB", 0, 1},
73   {ERE, "\\b(A|!|.B)", "!CB", 0, 1},
74   {ERE, "\\b(A|!|.B)", "D,B", 0, 1},
75   {ERE, "\\b(A|!|.B)", "!.C", 0, -1},
76   {ERE, "\\b(A|!|.B)", "BCB", 0, -1},
77   {ERE, "(A|\\b)(A|B|C)", "DAAD", 0, 1},
78   {ERE, "(A|\\b)(A|B|C)", "DABD", 0, 1},
79   {ERE, "(A|\\b)(A|B|C)", "AD", 0, 0},
80   {ERE, "(A|\\b)(A|B|C)", "C!", 0, 0},
81   {ERE, "(A|\\b)(A|B|C)", "D,B", 0, 2},
82   {ERE, "(A|\\b)(A|B|C)", "DA?A", 0, 3},
83   {ERE, "(A|\\b)(A|B|C)", "BBC", 0, 0},
84   {ERE, "(A|\\b)(A|B|C)", "DA", 0, -1},
85   {ERE, "(!|\\b)(!|=|~)", "A!=\\", 0, 1},
86   {ERE, "(!|\\b)(!|=|~)", "/!=A", 0, 1},
87   {ERE, "(!|\\b)(!|=|~)", "A=A", 0, 1},
88   {ERE, "(!|\\b)(!|=|~)", "==!=", 0, 2},
89   {ERE, "(!|\\b)(!|=|~)", "==C~", 0, 3},
90   {ERE, "(!|\\b)(!|=|~)", "=~=", 0, -1},
91   {ERE, "(!|\\b)(!|=|~)", "~!", 0, -1},
92   {ERE, "(!|\\b)(!|=|~)", "~=~", 0, -1},
93   {ERE, "(\\b|A.)[ABC]", "AC", 0, 0},
94   {ERE, "(\\b|A.)[ABC]", "=A", 0, 1},
95   {ERE, "(\\b|A.)[ABC]", "DACC", 0, 1},
96   {ERE, "(\\b|A.)[A~C]", "AC", 0, 0},
97   {ERE, "(\\b|A.)[A~C]", "=A", 0, 1},
98   {ERE, "(\\b|A.)[A~C]", "DACC", 0, 1},
99   {ERE, "(\\b|A.)[A~C]", "B!A=", 0, 2},
100   {ERE, "(\\b|A.)[A~C]", "B~C", 0, 1},
101   {ERE, ".\\b.", "AA~", 0, 1},
102   {ERE, ".\\b.", "=A=", 0, 0},
103   {ERE, ".\\b.", "==", 0, -1},
104   {ERE, ".\\b.", "ABA", 0, -1},
105   {ERE, "[^k]\\b[^k]", "AA~", 0, 1},
106   {ERE, "[^k]\\b[^k]", "=A=", 0, 0},
107   {ERE, "[^k]\\b[^k]", "Ak~kA~", 0, 4},
108   {ERE, "[^k]\\b[^k]", "==", 0, -1},
109   {ERE, "[^k]\\b[^k]", "ABA", 0, -1},
110   {ERE, "[^k]\\b[^k]", "Ak~", 0, -1},
111   {ERE, "[^k]\\b[^k]", "k=k", 0, -1},
112   {ERE, "[^C]\\b[^C]", "AA~", 0, 1},
113   {ERE, "[^C]\\b[^C]", "=A=", 0, 0},
114   {ERE, "[^C]\\b[^C]", "AC~CA~", 0, 4},
115   {ERE, "[^C]\\b[^C]", "==", 0, -1},
116   {ERE, "[^C]\\b[^C]", "ABA", 0, -1},
117   {ERE, "[^C]\\b[^C]", "AC~", 0, -1},
118   {ERE, "[^C]\\b[^C]", "C=C", 0, -1},
119   {ERE, "\\<(A|!|.B)", "A=AC", 0, 0},
120   {ERE, "\\<(A|!|.B)", "=AC", 0, 1},
121   {ERE, "\\<(A|!|.B)", "!AC", 0, 1},
122   {ERE, "\\<(A|!|.B)", "=AB", 0, 1},
123   {ERE, "\\<(A|!|.B)", "=CB", 0, 1},
124   {ERE, "\\<(A|!|.B)", "!CB", 0, 1},
125   {ERE, "\\<(A|!|.B)", "DA!C", 0, -1},
126   {ERE, "\\<(A|!|.B)", "D,B", 0, -1},
127   {ERE, "\\<(A|!|.B)", "!.C", 0, -1},
128   {ERE, "\\<(A|!|.B)", "BCB", 0, -1},
129   {ERE, "(A|\\<)(A|B|C)", "DAAD", 0, 1},
130   {ERE, "(A|\\<)(A|B|C)", "DABD", 0, 1},
131   {ERE, "(A|\\<)(A|B|C)", "AD", 0, 0},
132   {ERE, "(A|\\<)(A|B|C)", "C!", 0, 0},
133   {ERE, "(A|\\<)(A|B|C)", "D,B", 0, 2},
134   {ERE, "(A|\\<)(A|B|C)", "DA?A", 0, 3},
135   {ERE, "(A|\\<)(A|B|C)", "BBC", 0, 0},
136   {ERE, "(A|\\<)(A|B|C)", "DA", 0, -1},
137   {ERE, "(!|\\<)(!|=|~)", "A!=\\", 0, 1},
138   {ERE, "(!|\\<)(!|=|~)", "/!=A", 0, 1},
139   {ERE, "(!|\\<)(!|=|~)", "==!=", 0, 2},
140   {ERE, "(!|\\<)(!|=|~)", "==C~", 0, -1},
141   {ERE, "(!|\\<)(!|=|~)", "A=A", 0, -1},
142   {ERE, "(!|\\<)(!|=|~)", "=~=", 0, -1},
143   {ERE, "(!|\\<)(!|=|~)", "~!", 0, -1},
144   {ERE, "(!|\\<)(!|=|~)", "~=~", 0, -1},
145   {ERE, "(\\<|A.)[ABC]", "AC", 0, 0},
146   {ERE, "(\\<|A.)[ABC]", "=A", 0, 1},
147   {ERE, "(\\<|A.)[ABC]", "DACC", 0, 1},
148   {ERE, "(\\<|A.)[A~C]", "AC", 0, 0},
149   {ERE, "(\\<|A.)[A~C]", "=A", 0, 1},
150   {ERE, "(\\<|A.)[A~C]", "DACC", 0, 1},
151   {ERE, "(\\<|A.)[A~C]", "B!A=", 0, 2},
152   {ERE, "(\\<|A.)[A~C]", "B~C", 0, 2},
153   {ERE, ".\\<.", "=A=", 0, 0},
154   {ERE, ".\\<.", "AA~", 0, -1},
155   {ERE, ".\\<.", "==", 0, -1},
156   {ERE, ".\\<.", "ABA", 0, -1},
157   {ERE, "[^k]\\<[^k]", "=k=A=", 0, 2},
158   {ERE, "[^k]\\<[^k]", "kk~", 0, -1},
159   {ERE, "[^k]\\<[^k]", "==", 0, -1},
160   {ERE, "[^k]\\<[^k]", "ABA", 0, -1},
161   {ERE, "[^k]\\<[^k]", "=k=", 0, -1},
162   {ERE, "[^C]\\<[^C]", "=C=A=", 0, 2},
163   {ERE, "[^C]\\<[^C]", "CC~", 0, -1},
164   {ERE, "[^C]\\<[^C]", "==", 0, -1},
165   {ERE, "[^C]\\<[^C]", "ABA", 0, -1},
166   {ERE, "[^C]\\<[^C]", "=C=", 0, -1},
167   {ERE, ".\\B.", "ABA", 0, 0},
168   {ERE, ".\\B.", "=BDC", 0, 1},
169   {ERE, "[^k]\\B[^k]", "kkkABA", 0, 3},
170   {ERE, "[^k]\\B[^k]", "kBk", 0, -1},
171   {ERE, "[^C]\\B[^C]", "CCCABA", 0, 3},
172   {ERE, "[^C]\\B[^C]", "CBC", 0, -1},
173   {ERE, ".(\\b|\\B).", "=~AB", 0, 0},
174   {ERE, ".(\\b|\\B).", "A=C", 0, 0},
175   {ERE, ".(\\b|\\B).", "ABC", 0, 0},
176   {ERE, ".(\\b|\\B).", "=~\\!", 0, 0},
177   {ERE, "[^k](\\b|\\B)[^k]", "=~AB", 0, 0},
178   {ERE, "[^k](\\b|\\B)[^k]", "A=C", 0, 0},
179   {ERE, "[^k](\\b|\\B)[^k]", "ABC", 0, 0},
180   {ERE, "[^k](\\b|\\B)[^k]", "=~kBD", 0, 0},
181   {ERE, "[^k](\\b|\\B)[^k]", "=~\\!", 0, 0},
182   {ERE, "[^k](\\b|\\B)[^k]", "=~kB", 0, 0},
183   {ERE, "[^C](\\b|\\B)[^C]", "=~AB", 0, 0},
184   {ERE, "[^C](\\b|\\B)[^C]", "A=C", 0, 0},
185   {ERE, "[^C](\\b|\\B)[^C]", "ABC", 0, 0},
186   {ERE, "[^C](\\b|\\B)[^C]", "=~CBD", 0, 0},
187   {ERE, "[^C](\\b|\\B)[^C]", "=~\\!", 0, 0},
188   {ERE, "[^C](\\b|\\B)[^C]", "=~CB", 0, 0},
189   {ERE, "\\b([A]|[!]|.B)", "A=AC", 0, 0},
190   {ERE, "\\b([A]|[!]|.B)", "=AC", 0, 1},
191   {ERE, "\\b([A]|[!]|.B)", "!AC", 0, 1},
192   {ERE, "\\b([A]|[!]|.B)", "=AB", 0, 1},
193   {ERE, "\\b([A]|[!]|.B)", "DA!C", 0, 2},
194   {ERE, "\\b([A]|[!]|.B)", "=CB", 0, 1},
195   {ERE, "\\b([A]|[!]|.B)", "!CB", 0, 1},
196   {ERE, "\\b([A]|[!]|.B)", "D,B", 0, 1},
197   {ERE, "\\b([A]|[!]|.B)", "!.C", 0, -1},
198   {ERE, "\\b([A]|[!]|.B)", "BCB", 0, -1},
199   {ERE, "([A]|\\b)([A]|[B]|[C])", "DAAD", 0, 1},
200   {ERE, "([A]|\\b)([A]|[B]|[C])", "DABD", 0, 1},
201   {ERE, "([A]|\\b)([A]|[B]|[C])", "AD", 0, 0},
202   {ERE, "([A]|\\b)([A]|[B]|[C])", "C!", 0, 0},
203   {ERE, "([A]|\\b)([A]|[B]|[C])", "D,B", 0, 2},
204   {ERE, "([A]|\\b)([A]|[B]|[C])", "DA?A", 0, 3},
205   {ERE, "([A]|\\b)([A]|[B]|[C])", "BBC", 0, 0},
206   {ERE, "([A]|\\b)([A]|[B]|[C])", "DA", 0, -1},
207   {ERE, "([!]|\\b)([!]|[=]|[~])", "A!=\\", 0, 1},
208   {ERE, "([!]|\\b)([!]|[=]|[~])", "/!=A", 0, 1},
209   {ERE, "([!]|\\b)([!]|[=]|[~])", "A=A", 0, 1},
210   {ERE, "([!]|\\b)([!]|[=]|[~])", "==!=", 0, 2},
211   {ERE, "([!]|\\b)([!]|[=]|[~])", "==C~", 0, 3},
212   {ERE, "([!]|\\b)([!]|[=]|[~])", "=~=", 0, -1},
213   {ERE, "([!]|\\b)([!]|[=]|[~])", "~!", 0, -1},
214   {ERE, "([!]|\\b)([!]|[=]|[~])", "~=~", 0, -1},
215   {ERE, "\\<([A]|[!]|.B)", "A=AC", 0, 0},
216   {ERE, "\\<([A]|[!]|.B)", "=AC", 0, 1},
217   {ERE, "\\<([A]|[!]|.B)", "!AC", 0, 1},
218   {ERE, "\\<([A]|[!]|.B)", "=AB", 0, 1},
219   {ERE, "\\<([A]|[!]|.B)", "=CB", 0, 1},
220   {ERE, "\\<([A]|[!]|.B)", "!CB", 0, 1},
221   {ERE, "\\<([A]|[!]|.B)", "DA!C", 0, -1},
222   {ERE, "\\<([A]|[!]|.B)", "D,B", 0, -1},
223   {ERE, "\\<([A]|[!]|.B)", "!.C", 0, -1},
224   {ERE, "\\<([A]|[!]|.B)", "BCB", 0, -1},
225   {ERE, "([A]|\\<)([A]|[B]|[C])", "DAAD", 0, 1},
226   {ERE, "([A]|\\<)([A]|[B]|[C])", "DABD", 0, 1},
227   {ERE, "([A]|\\<)([A]|[B]|[C])", "AD", 0, 0},
228   {ERE, "([A]|\\<)([A]|[B]|[C])", "C!", 0, 0},
229   {ERE, "([A]|\\<)([A]|[B]|[C])", "D,B", 0, 2},
230   {ERE, "([A]|\\<)([A]|[B]|[C])", "DA?A", 0, 3},
231   {ERE, "([A]|\\<)([A]|[B]|[C])", "BBC", 0, 0},
232   {ERE, "([A]|\\<)([A]|[B]|[C])", "DA", 0, -1},
233   {ERE, "([!]|\\<)([!=]|[~])", "A!=\\", 0, 1},
234   {ERE, "([!]|\\<)([!=]|[~])", "/!=A", 0, 1},
235   {ERE, "([!]|\\<)([!=]|[~])", "==!=", 0, 2},
236   {ERE, "([!]|\\<)([!=]|[~])", "==C~", 0, -1},
237   {ERE, "([!]|\\<)([!=]|[~])", "A=A", 0, -1},
238   {ERE, "([!]|\\<)([!=]|[~])", "=~=", 0, -1},
239   {ERE, "([!]|\\<)([!=]|[~])", "~!", 0, -1},
240   {ERE, "([!]|\\<)([!=]|[~])", "~=~", 0, -1},
241   {ERE, "(\\<|[A].)[ABC]", "AC", 0, 0},
242   {ERE, "(\\<|[A].)[ABC]", "=A", 0, 1},
243   {ERE, "(\\<|[A].)[ABC]", "DACC", 0, 1},
244   {ERE, "(\\<|[A].)[A~C]", "AC", 0, 0},
245   {ERE, "(\\<|[A].)[A~C]", "=A", 0, 1},
246   {ERE, "(\\<|[A].)[A~C]", "DACC", 0, 1},
247   {ERE, "(\\<|[A].)[A~C]", "B!A=", 0, 2},
248   {ERE, "(\\<|[A].)[A~C]", "B~C", 0, 2},
249   {ERE, "^[^A]*\\bB", "==B", 0, 0},
250   {ERE, "^[^A]*\\bB", "CBD!=B", 0, 0},
251   {ERE, "[^A]*\\bB", "==B", 2, 2}
252 };
253 
254 int
do_one_test(const struct test_s * test,const char * fail)255 do_one_test (const struct test_s *test, const char *fail)
256 {
257   int res;
258   const char *err;
259   struct re_pattern_buffer regbuf;
260 
261   re_set_syntax (test->syntax);
262   memset (&regbuf, '\0', sizeof (regbuf));
263   err = re_compile_pattern (test->pattern, strlen (test->pattern),
264 			    &regbuf);
265   if (err != NULL)
266     {
267       printf ("%sre_compile_pattern \"%s\" failed: %s\n", fail, test->pattern,
268 	      err);
269       return 1;
270     }
271 
272 #if __GNUC_PREREQ (10, 0) && !__GNUC_PREREQ (11, 0)
273   DIAG_PUSH_NEEDS_COMMENT;
274   /* Avoid GCC 10 false positive warning: specified size exceeds maximum
275      object size.  */
276   DIAG_IGNORE_NEEDS_COMMENT (10, "-Wstringop-overflow");
277 #endif
278   res = re_search (&regbuf, test->string, strlen (test->string),
279 		   test->start, strlen (test->string) - test->start, NULL);
280 #if __GNUC_PREREQ (10, 0) && !__GNUC_PREREQ (11, 0)
281   DIAG_POP_NEEDS_COMMENT;
282 #endif
283   if (res != test->res)
284     {
285       printf ("%sre_search \"%s\" \"%s\" failed: %d (expected %d)\n",
286 	      fail, test->pattern, test->string, res, test->res);
287       regfree (&regbuf);
288       return 1;
289     }
290 
291   if (test->res > 0 && test->start == 0)
292     {
293 #if __GNUC_PREREQ (10, 0) && !__GNUC_PREREQ (11, 0)
294   DIAG_PUSH_NEEDS_COMMENT;
295   /* Avoid GCC 10 false positive warning: specified size exceeds maximum
296      object size.  */
297   DIAG_IGNORE_NEEDS_COMMENT (10, "-Wstringop-overflow");
298 #endif
299       res = re_search (&regbuf, test->string, strlen (test->string),
300 		       test->res, strlen (test->string) - test->res, NULL);
301 #if __GNUC_PREREQ (10, 0) && !__GNUC_PREREQ (11, 0)
302   DIAG_POP_NEEDS_COMMENT;
303 #endif
304       if (res != test->res)
305 	{
306 	  printf ("%sre_search from expected \"%s\" \"%s\" failed: %d (expected %d)\n",
307 		  fail, test->pattern, test->string, res, test->res);
308 	  regfree (&regbuf);
309 	  return 1;
310 	}
311     }
312 
313   regfree (&regbuf);
314   return 0;
315 }
316 
317 static char *
replace(char * p,char c)318 replace (char *p, char c)
319 {
320   switch (c)
321     {
322       /* A -> A" */
323       case 'A': *p++ = '\xc3'; *p++ = '\x84'; break;
324       /* B -> O" */
325       case 'B': *p++ = '\xc3'; *p++ = '\x96'; break;
326       /* C -> U" */
327       case 'C': *p++ = '\xc3'; *p++ = '\x9c'; break;
328       /* D -> a" */
329       case 'D': *p++ = '\xc3'; *p++ = '\xa4'; break;
330       /* ! -> MULTIPLICATION SIGN */
331       case '!': *p++ = '\xc3'; *p++ = '\x97'; break;
332       /* = -> EM DASH */
333       case '=': *p++ = '\xe2'; *p++ = '\x80'; *p++ = '\x94'; break;
334       /* ~ -> MUSICAL SYMBOL HALF NOTE */
335       case '~': *p++ = '\xf0'; *p++ = '\x9d'; *p++ = '\x85'; *p++ = '\x9e';
336       break;
337     }
338   return p;
339 }
340 
341 int
do_mb_tests(const struct test_s * test)342 do_mb_tests (const struct test_s *test)
343 {
344   int i, j;
345   struct test_s t;
346   const char *const chars = "ABCD!=~";
347   char repl[8], *p;
348   char pattern[strlen (test->pattern) * 4 + 1];
349   char string[strlen (test->string) * 4 + 1];
350   char fail[8 + sizeof ("UTF-8 ")];
351 
352   t = *test;
353   t.pattern = pattern;
354   t.string = string;
355   strcpy (fail, "UTF-8 ");
356   for (i = 1; i < 128; ++i)
357     {
358       p = repl;
359       for (j = 0; j < 7; ++j)
360 	if (i & (1 << j))
361 	  {
362 	    if (!strchr (test->pattern, chars[j])
363 		&& !strchr (test->string, chars[j]))
364 	      break;
365 	    *p++ = chars[j];
366 	  }
367       if (j < 7)
368 	continue;
369       *p = '\0';
370 
371       for (j = 0, p = pattern; test->pattern[j]; ++j)
372 	if (strchr (repl, test->pattern[j]))
373 	  p = replace (p, test->pattern[j]);
374 	else if (test->pattern[j] == '\\' && test->pattern[j + 1])
375 	  {
376 	    *p++ = test->pattern[j++];
377 	    *p++ = test->pattern[j];
378 	  }
379 	else
380 	  *p++ = test->pattern[j];
381       *p = '\0';
382 
383       t.start = test->start;
384       t.res = test->res;
385 
386       for (j = 0, p = string; test->string[j]; ++j)
387 	if (strchr (repl, test->string[j]))
388 	  {
389 	    char *d = replace (p, test->string[j]);
390 	    if (test->start > j)
391 	      t.start += d - p - 1;
392 	    if (test->res > j)
393 	      t.res += d - p - 1;
394 	    p = d;
395 	  }
396 	else
397 	  *p++ = test->string[j];
398       *p = '\0';
399 
400       p = stpcpy (fail + strlen ("UTF-8 "), repl);
401       *p++ = ' ';
402       *p = '\0';
403 
404       if (do_one_test (&t, fail))
405 	return 1;
406     }
407   return 0;
408 }
409 
410 static int
do_test(void)411 do_test (void)
412 {
413   size_t i;
414   int ret = 0;
415 
416   mtrace ();
417 
418   for (i = 0; i < sizeof (tests) / sizeof (tests[0]); ++i)
419     {
420       xsetlocale (LC_ALL, "de_DE.ISO-8859-1");
421       ret |= do_one_test (&tests[i], "");
422       xsetlocale (LC_ALL, "de_DE.UTF-8");
423       ret |= do_one_test (&tests[i], "UTF-8 ");
424       ret |= do_mb_tests (&tests[i]);
425       xsetlocale (LC_ALL, "C.UTF-8");
426       ret |= do_one_test (&tests[i], "UTF-8 ");
427       ret |= do_mb_tests (&tests[i]);
428     }
429 
430   return ret;
431 }
432 
433 #include <support/test-driver.c>
434