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 (®buf, '\0', sizeof (regbuf));
263 err = re_compile_pattern (test->pattern, strlen (test->pattern),
264 ®buf);
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 (®buf, 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 (®buf);
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 (®buf, 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 (®buf);
309 return 1;
310 }
311 }
312
313 regfree (®buf);
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