tests: add signature checks
[gnulib.git] / tests / test-mbrtowc.c
1 /* Test of conversion of multibyte character to wide character.
2    Copyright (C) 2008, 2009 Free Software Foundation, Inc.
3
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.
8
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.
13
14    You should have received a copy of the GNU General Public License
15    along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
16
17 /* Written by Bruno Haible <bruno@clisp.org>, 2008.  */
18
19 #include <config.h>
20
21 #include <wchar.h>
22
23 #include "signature.h"
24 SIGNATURE_CHECK (mbrtowc, size_t, (wchar_t *, char const *, size_t,
25                                    mbstate_t *));
26
27 #include <locale.h>
28 #include <stdio.h>
29 #include <stdlib.h>
30 #include <string.h>
31
32 #define ASSERT(expr) \
33   do                                                                         \
34     {                                                                        \
35       if (!(expr))                                                           \
36         {                                                                    \
37           fprintf (stderr, "%s:%d: assertion failed\n", __FILE__, __LINE__); \
38           fflush (stderr);                                                   \
39           abort ();                                                          \
40         }                                                                    \
41     }                                                                        \
42   while (0)
43
44 int
45 main (int argc, char *argv[])
46 {
47   mbstate_t state;
48   wchar_t wc;
49   size_t ret;
50
51   /* configure should already have checked that the locale is supported.  */
52   if (setlocale (LC_ALL, "") == NULL)
53     return 1;
54
55   /* Test zero-length input.  */
56   {
57     memset (&state, '\0', sizeof (mbstate_t));
58     wc = (wchar_t) 0xBADFACE;
59     ret = mbrtowc (&wc, "x", 0, &state);
60     /* gnulib's implementation returns (size_t)(-2).
61        The AIX 5.1 implementation returns (size_t)(-1).
62        glibc's implementation returns 0.  */
63     ASSERT (ret == (size_t)(-2) || ret == (size_t)(-1) || ret == 0);
64     ASSERT (mbsinit (&state));
65   }
66
67   /* Test NUL byte input.  */
68   {
69     memset (&state, '\0', sizeof (mbstate_t));
70     wc = (wchar_t) 0xBADFACE;
71     ret = mbrtowc (&wc, "", 1, &state);
72     ASSERT (ret == 0);
73     ASSERT (wc == 0);
74     ASSERT (mbsinit (&state));
75     ret = mbrtowc (NULL, "", 1, &state);
76     ASSERT (ret == 0);
77     ASSERT (mbsinit (&state));
78   }
79
80   /* Test single-byte input.  */
81   {
82     int c;
83     char buf[1];
84
85     memset (&state, '\0', sizeof (mbstate_t));
86     for (c = 0; c < 0x100; c++)
87       switch (c)
88         {
89         case '\t': case '\v': case '\f':
90         case ' ': case '!': case '"': case '#': case '%':
91         case '&': case '\'': case '(': case ')': case '*':
92         case '+': case ',': case '-': case '.': case '/':
93         case '0': case '1': case '2': case '3': case '4':
94         case '5': case '6': case '7': case '8': case '9':
95         case ':': case ';': case '<': case '=': case '>':
96         case '?':
97         case 'A': case 'B': case 'C': case 'D': case 'E':
98         case 'F': case 'G': case 'H': case 'I': case 'J':
99         case 'K': case 'L': case 'M': case 'N': case 'O':
100         case 'P': case 'Q': case 'R': case 'S': case 'T':
101         case 'U': case 'V': case 'W': case 'X': case 'Y':
102         case 'Z':
103         case '[': case '\\': case ']': case '^': case '_':
104         case 'a': case 'b': case 'c': case 'd': case 'e':
105         case 'f': case 'g': case 'h': case 'i': case 'j':
106         case 'k': case 'l': case 'm': case 'n': case 'o':
107         case 'p': case 'q': case 'r': case 's': case 't':
108         case 'u': case 'v': case 'w': case 'x': case 'y':
109         case 'z': case '{': case '|': case '}': case '~':
110           /* c is in the ISO C "basic character set".  */
111           buf[0] = c;
112           wc = (wchar_t) 0xBADFACE;
113           ret = mbrtowc (&wc, buf, 1, &state);
114           ASSERT (ret == 1);
115           ASSERT (wc == c);
116           ASSERT (mbsinit (&state));
117           ret = mbrtowc (NULL, buf, 1, &state);
118           ASSERT (ret == 1);
119           ASSERT (mbsinit (&state));
120           break;
121         }
122   }
123
124   /* Test special calling convention, passing a NULL pointer.  */
125   {
126     memset (&state, '\0', sizeof (mbstate_t));
127     wc = (wchar_t) 0xBADFACE;
128     ret = mbrtowc (&wc, NULL, 5, &state);
129     ASSERT (ret == 0);
130     ASSERT (wc == (wchar_t) 0xBADFACE);
131     ASSERT (mbsinit (&state));
132   }
133
134   if (argc > 1)
135     switch (argv[1][0])
136       {
137       case '1':
138         /* Locale encoding is ISO-8859-1 or ISO-8859-15.  */
139         {
140           char input[] = "B\374\337er"; /* "Büßer" */
141           memset (&state, '\0', sizeof (mbstate_t));
142
143           wc = (wchar_t) 0xBADFACE;
144           ret = mbrtowc (&wc, input, 1, &state);
145           ASSERT (ret == 1);
146           ASSERT (wc == 'B');
147           ASSERT (mbsinit (&state));
148           input[0] = '\0';
149
150           wc = (wchar_t) 0xBADFACE;
151           ret = mbrtowc (&wc, input + 1, 1, &state);
152           ASSERT (ret == 1);
153           ASSERT (wctob (wc) == (unsigned char) '\374');
154           ASSERT (mbsinit (&state));
155           input[1] = '\0';
156
157           wc = (wchar_t) 0xBADFACE;
158           ret = mbrtowc (&wc, input + 2, 3, &state);
159           ASSERT (ret == 1);
160           ASSERT (wctob (wc) == (unsigned char) '\337');
161           ASSERT (mbsinit (&state));
162           input[2] = '\0';
163
164           wc = (wchar_t) 0xBADFACE;
165           ret = mbrtowc (&wc, input + 3, 2, &state);
166           ASSERT (ret == 1);
167           ASSERT (wc == 'e');
168           ASSERT (mbsinit (&state));
169           input[3] = '\0';
170
171           wc = (wchar_t) 0xBADFACE;
172           ret = mbrtowc (&wc, input + 4, 1, &state);
173           ASSERT (ret == 1);
174           ASSERT (wc == 'r');
175           ASSERT (mbsinit (&state));
176         }
177         return 0;
178
179       case '2':
180         /* Locale encoding is UTF-8.  */
181         {
182           char input[] = "B\303\274\303\237er"; /* "Büßer" */
183           memset (&state, '\0', sizeof (mbstate_t));
184
185           wc = (wchar_t) 0xBADFACE;
186           ret = mbrtowc (&wc, input, 1, &state);
187           ASSERT (ret == 1);
188           ASSERT (wc == 'B');
189           ASSERT (mbsinit (&state));
190           input[0] = '\0';
191
192           wc = (wchar_t) 0xBADFACE;
193           ret = mbrtowc (&wc, input + 1, 1, &state);
194           ASSERT (ret == (size_t)(-2));
195           ASSERT (wc == (wchar_t) 0xBADFACE);
196           ASSERT (!mbsinit (&state));
197           input[1] = '\0';
198
199           wc = (wchar_t) 0xBADFACE;
200           ret = mbrtowc (&wc, input + 2, 5, &state);
201           ASSERT (ret == 1);
202           ASSERT (wctob (wc) == EOF);
203           ASSERT (mbsinit (&state));
204           input[2] = '\0';
205
206           wc = (wchar_t) 0xBADFACE;
207           ret = mbrtowc (&wc, input + 3, 4, &state);
208           ASSERT (ret == 2);
209           ASSERT (wctob (wc) == EOF);
210           ASSERT (mbsinit (&state));
211           input[3] = '\0';
212           input[4] = '\0';
213
214           wc = (wchar_t) 0xBADFACE;
215           ret = mbrtowc (&wc, input + 5, 2, &state);
216           ASSERT (ret == 1);
217           ASSERT (wc == 'e');
218           ASSERT (mbsinit (&state));
219           input[5] = '\0';
220
221           wc = (wchar_t) 0xBADFACE;
222           ret = mbrtowc (&wc, input + 6, 1, &state);
223           ASSERT (ret == 1);
224           ASSERT (wc == 'r');
225           ASSERT (mbsinit (&state));
226         }
227         return 0;
228
229       case '3':
230         /* Locale encoding is EUC-JP.  */
231         {
232           char input[] = "<\306\374\313\334\270\354>"; /* "<日本語>" */
233           memset (&state, '\0', sizeof (mbstate_t));
234
235           wc = (wchar_t) 0xBADFACE;
236           ret = mbrtowc (&wc, input, 1, &state);
237           ASSERT (ret == 1);
238           ASSERT (wc == '<');
239           ASSERT (mbsinit (&state));
240           input[0] = '\0';
241
242           wc = (wchar_t) 0xBADFACE;
243           ret = mbrtowc (&wc, input + 1, 2, &state);
244           ASSERT (ret == 2);
245           ASSERT (wctob (wc) == EOF);
246           ASSERT (mbsinit (&state));
247           input[1] = '\0';
248           input[2] = '\0';
249
250           wc = (wchar_t) 0xBADFACE;
251           ret = mbrtowc (&wc, input + 3, 1, &state);
252           ASSERT (ret == (size_t)(-2));
253           ASSERT (wc == (wchar_t) 0xBADFACE);
254           ASSERT (!mbsinit (&state));
255           input[3] = '\0';
256
257           wc = (wchar_t) 0xBADFACE;
258           ret = mbrtowc (&wc, input + 4, 4, &state);
259           ASSERT (ret == 1);
260           ASSERT (wctob (wc) == EOF);
261           ASSERT (mbsinit (&state));
262           input[4] = '\0';
263
264           wc = (wchar_t) 0xBADFACE;
265           ret = mbrtowc (&wc, input + 5, 3, &state);
266           ASSERT (ret == 2);
267           ASSERT (wctob (wc) == EOF);
268           ASSERT (mbsinit (&state));
269           input[5] = '\0';
270           input[6] = '\0';
271
272           wc = (wchar_t) 0xBADFACE;
273           ret = mbrtowc (&wc, input + 7, 1, &state);
274           ASSERT (ret == 1);
275           ASSERT (wc == '>');
276           ASSERT (mbsinit (&state));
277         }
278         return 0;
279
280       case '4':
281         /* Locale encoding is GB18030.  */
282         {
283           char input[] = "B\250\271\201\060\211\070er"; /* "Büßer" */
284           memset (&state, '\0', sizeof (mbstate_t));
285
286           wc = (wchar_t) 0xBADFACE;
287           ret = mbrtowc (&wc, input, 1, &state);
288           ASSERT (ret == 1);
289           ASSERT (wc == 'B');
290           ASSERT (mbsinit (&state));
291           input[0] = '\0';
292
293           wc = (wchar_t) 0xBADFACE;
294           ret = mbrtowc (&wc, input + 1, 1, &state);
295           ASSERT (ret == (size_t)(-2));
296           ASSERT (wc == (wchar_t) 0xBADFACE);
297           ASSERT (!mbsinit (&state));
298           input[1] = '\0';
299
300           wc = (wchar_t) 0xBADFACE;
301           ret = mbrtowc (&wc, input + 2, 7, &state);
302           ASSERT (ret == 1);
303           ASSERT (wctob (wc) == EOF);
304           ASSERT (mbsinit (&state));
305           input[2] = '\0';
306
307           wc = (wchar_t) 0xBADFACE;
308           ret = mbrtowc (&wc, input + 3, 6, &state);
309           ASSERT (ret == 4);
310           ASSERT (wctob (wc) == EOF);
311           ASSERT (mbsinit (&state));
312           input[3] = '\0';
313           input[4] = '\0';
314           input[5] = '\0';
315           input[6] = '\0';
316
317           wc = (wchar_t) 0xBADFACE;
318           ret = mbrtowc (&wc, input + 7, 2, &state);
319           ASSERT (ret == 1);
320           ASSERT (wc == 'e');
321           ASSERT (mbsinit (&state));
322           input[5] = '\0';
323
324           wc = (wchar_t) 0xBADFACE;
325           ret = mbrtowc (&wc, input + 8, 1, &state);
326           ASSERT (ret == 1);
327           ASSERT (wc == 'r');
328           ASSERT (mbsinit (&state));
329         }
330         return 0;
331       }
332
333   return 1;
334 }