tests: add signature checks
[gnulib.git] / tests / test-mbsnrtowcs.c
1 /* Test of conversion of string to wide string.
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 (mbsnrtowcs, size_t, (wchar_t *, char const **, size_t, 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 NUL byte input.  */
56   {
57     const char *src;
58
59     memset (&state, '\0', sizeof (mbstate_t));
60
61     src = "";
62     ret = mbsnrtowcs (NULL, &src, 1, 0, &state);
63     ASSERT (ret == 0);
64     ASSERT (mbsinit (&state));
65
66     src = "";
67     ret = mbsnrtowcs (NULL, &src, 1, 1, &state);
68     ASSERT (ret == 0);
69     ASSERT (mbsinit (&state));
70
71     wc = (wchar_t) 0xBADFACE;
72     src = "";
73     ret = mbsnrtowcs (&wc, &src, 1, 0, &state);
74     ASSERT (ret == 0);
75     ASSERT (wc == (wchar_t) 0xBADFACE);
76     ASSERT (mbsinit (&state));
77
78     wc = (wchar_t) 0xBADFACE;
79     src = "";
80     ret = mbsnrtowcs (&wc, &src, 1, 1, &state);
81     ASSERT (ret == 0);
82     ASSERT (wc == 0);
83     ASSERT (mbsinit (&state));
84   }
85
86   if (argc > 1)
87     {
88       int unlimited;
89
90       for (unlimited = 0; unlimited < 2; unlimited++)
91         {
92           #define BUFSIZE 10
93           wchar_t buf[BUFSIZE];
94           const char *src;
95           mbstate_t temp_state;
96
97           {
98             size_t i;
99             for (i = 0; i < BUFSIZE; i++)
100               buf[i] = (wchar_t) 0xBADFACE;
101           }
102
103           switch (argv[1][0])
104             {
105             case '1':
106               /* Locale encoding is ISO-8859-1 or ISO-8859-15.  */
107               {
108                 char input[] = "B\374\337er"; /* "Büßer" */
109                 memset (&state, '\0', sizeof (mbstate_t));
110
111                 wc = (wchar_t) 0xBADFACE;
112                 ret = mbrtowc (&wc, input, 1, &state);
113                 ASSERT (ret == 1);
114                 ASSERT (wc == 'B');
115                 ASSERT (mbsinit (&state));
116                 input[0] = '\0';
117
118                 wc = (wchar_t) 0xBADFACE;
119                 ret = mbrtowc (&wc, input + 1, 1, &state);
120                 ASSERT (ret == 1);
121                 ASSERT (wctob (wc) == (unsigned char) '\374');
122                 ASSERT (mbsinit (&state));
123                 input[1] = '\0';
124
125                 src = input + 2;
126                 temp_state = state;
127                 ret = mbsnrtowcs (NULL, &src, 4, unlimited ? BUFSIZE : 1, &temp_state);
128                 ASSERT (ret == 3);
129                 ASSERT (src == input + 2);
130                 ASSERT (mbsinit (&state));
131
132                 src = input + 2;
133                 ret = mbsnrtowcs (buf, &src, 4, unlimited ? BUFSIZE : 1, &state);
134                 ASSERT (ret == (unlimited ? 3 : 1));
135                 ASSERT (src == (unlimited ? NULL : input + 3));
136                 ASSERT (wctob (buf[0]) == (unsigned char) '\337');
137                 if (unlimited)
138                   {
139                     ASSERT (buf[1] == 'e');
140                     ASSERT (buf[2] == 'r');
141                     ASSERT (buf[3] == 0);
142                     ASSERT (buf[4] == (wchar_t) 0xBADFACE);
143                   }
144                 else
145                   ASSERT (buf[1] == (wchar_t) 0xBADFACE);
146                 ASSERT (mbsinit (&state));
147               }
148               break;
149
150             case '2':
151               /* Locale encoding is UTF-8.  */
152               {
153                 char input[] = "B\303\274\303\237er"; /* "Büßer" */
154                 memset (&state, '\0', sizeof (mbstate_t));
155
156                 wc = (wchar_t) 0xBADFACE;
157                 ret = mbrtowc (&wc, input, 1, &state);
158                 ASSERT (ret == 1);
159                 ASSERT (wc == 'B');
160                 ASSERT (mbsinit (&state));
161                 input[0] = '\0';
162
163                 wc = (wchar_t) 0xBADFACE;
164                 ret = mbrtowc (&wc, input + 1, 1, &state);
165                 ASSERT (ret == (size_t)(-2));
166                 ASSERT (wc == (wchar_t) 0xBADFACE);
167                 ASSERT (!mbsinit (&state));
168                 input[1] = '\0';
169
170                 src = input + 2;
171                 temp_state = state;
172                 ret = mbsnrtowcs (NULL, &src, 6, unlimited ? BUFSIZE : 2, &temp_state);
173                 ASSERT (ret == 4);
174                 ASSERT (src == input + 2);
175                 ASSERT (!mbsinit (&state));
176
177                 src = input + 2;
178                 ret = mbsnrtowcs (buf, &src, 6, unlimited ? BUFSIZE : 2, &state);
179                 ASSERT (ret == (unlimited ? 4 : 2));
180                 ASSERT (src == (unlimited ? NULL : input + 5));
181                 ASSERT (wctob (buf[0]) == EOF);
182                 ASSERT (wctob (buf[1]) == EOF);
183                 if (unlimited)
184                   {
185                     ASSERT (buf[2] == 'e');
186                     ASSERT (buf[3] == 'r');
187                     ASSERT (buf[4] == 0);
188                     ASSERT (buf[5] == (wchar_t) 0xBADFACE);
189                   }
190                 else
191                   ASSERT (buf[2] == (wchar_t) 0xBADFACE);
192                 ASSERT (mbsinit (&state));
193               }
194               break;
195
196             case '3':
197               /* Locale encoding is EUC-JP.  */
198               {
199                 char input[] = "<\306\374\313\334\270\354>"; /* "<日本語>" */
200                 memset (&state, '\0', sizeof (mbstate_t));
201
202                 wc = (wchar_t) 0xBADFACE;
203                 ret = mbrtowc (&wc, input, 1, &state);
204                 ASSERT (ret == 1);
205                 ASSERT (wc == '<');
206                 ASSERT (mbsinit (&state));
207                 input[0] = '\0';
208
209                 wc = (wchar_t) 0xBADFACE;
210                 ret = mbrtowc (&wc, input + 1, 2, &state);
211                 ASSERT (ret == 2);
212                 ASSERT (wctob (wc) == EOF);
213                 ASSERT (mbsinit (&state));
214                 input[1] = '\0';
215                 input[2] = '\0';
216
217                 wc = (wchar_t) 0xBADFACE;
218                 ret = mbrtowc (&wc, input + 3, 1, &state);
219                 ASSERT (ret == (size_t)(-2));
220                 ASSERT (wc == (wchar_t) 0xBADFACE);
221                 ASSERT (!mbsinit (&state));
222                 input[3] = '\0';
223
224                 src = input + 4;
225                 temp_state = state;
226                 ret = mbsnrtowcs (NULL, &src, 5, unlimited ? BUFSIZE : 2, &temp_state);
227                 ASSERT (ret == 3);
228                 ASSERT (src == input + 4);
229                 ASSERT (!mbsinit (&state));
230
231                 src = input + 4;
232                 ret = mbsnrtowcs (buf, &src, 5, unlimited ? BUFSIZE : 2, &state);
233                 ASSERT (ret == (unlimited ? 3 : 2));
234                 ASSERT (src == (unlimited ? NULL : input + 7));
235                 ASSERT (wctob (buf[0]) == EOF);
236                 ASSERT (wctob (buf[1]) == EOF);
237                 if (unlimited)
238                   {
239                     ASSERT (buf[2] == '>');
240                     ASSERT (buf[3] == 0);
241                     ASSERT (buf[4] == (wchar_t) 0xBADFACE);
242                   }
243                 else
244                   ASSERT (buf[2] == (wchar_t) 0xBADFACE);
245                 ASSERT (mbsinit (&state));
246               }
247               break;
248
249             case '4':
250               /* Locale encoding is GB18030.  */
251               {
252                 char input[] = "B\250\271\201\060\211\070er"; /* "Büßer" */
253                 memset (&state, '\0', sizeof (mbstate_t));
254
255                 wc = (wchar_t) 0xBADFACE;
256                 ret = mbrtowc (&wc, input, 1, &state);
257                 ASSERT (ret == 1);
258                 ASSERT (wc == 'B');
259                 ASSERT (mbsinit (&state));
260                 input[0] = '\0';
261
262                 wc = (wchar_t) 0xBADFACE;
263                 ret = mbrtowc (&wc, input + 1, 1, &state);
264                 ASSERT (ret == (size_t)(-2));
265                 ASSERT (wc == (wchar_t) 0xBADFACE);
266                 ASSERT (!mbsinit (&state));
267                 input[1] = '\0';
268
269                 src = input + 2;
270                 temp_state = state;
271                 ret = mbsnrtowcs (NULL, &src, 8, unlimited ? BUFSIZE : 2, &temp_state);
272                 ASSERT (ret == 4);
273                 ASSERT (src == input + 2);
274                 ASSERT (!mbsinit (&state));
275
276                 src = input + 2;
277                 ret = mbsnrtowcs (buf, &src, 8, unlimited ? BUFSIZE : 2, &state);
278                 ASSERT (ret == (unlimited ? 4 : 2));
279                 ASSERT (src == (unlimited ? NULL : input + 7));
280                 ASSERT (wctob (buf[0]) == EOF);
281                 ASSERT (wctob (buf[1]) == EOF);
282                 if (unlimited)
283                   {
284                     ASSERT (buf[2] == 'e');
285                     ASSERT (buf[3] == 'r');
286                     ASSERT (buf[4] == 0);
287                     ASSERT (buf[5] == (wchar_t) 0xBADFACE);
288                   }
289                 else
290                   ASSERT (buf[2] == (wchar_t) 0xBADFACE);
291                 ASSERT (mbsinit (&state));
292               }
293               break;
294
295             default:
296               return 1;
297             }
298         }
299
300       return 0;
301     }
302
303   return 1;
304 }