Tests for striconveh module.
[gnulib.git] / tests / test-striconveh.c
1 /* Test of character set conversion with error handling.
2    Copyright (C) 2007 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 2, or (at your option)
7    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, write to the Free Software Foundation,
16    Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.  */
17
18 /* Written by Bruno Haible <bruno@clisp.org>, 2007.  */
19
20 #ifdef HAVE_CONFIG_H
21 # include <config.h>
22 #endif
23
24 #include "striconveh.h"
25
26 #if HAVE_ICONV
27 # include <iconv.h>
28 #endif
29
30 #include <errno.h>
31 #include <stdlib.h>
32 #include <string.h>
33
34 #define SIZEOF(array) (sizeof (array) / sizeof (array[0]))
35 #define ASSERT(expr) if (!(expr)) abort ();
36
37 int
38 main ()
39 {
40   static enum iconv_ilseq_handler handlers[] =
41     { iconveh_error, iconveh_question_mark, iconveh_escape_sequence };
42   size_t h;
43
44 #if HAVE_ICONV
45   /* Assume that iconv() supports at least the encodings ASCII, ISO-8859-1,
46      ISO-8859-2, and UTF-8.  */
47   iconv_t cd_88591_to_88592 = iconv_open ("ISO-8859-2", "ISO-8859-1");
48   iconv_t cd_88592_to_88591 = iconv_open ("ISO-8859-1", "ISO-8859-2");
49   iconv_t cd_88591_to_utf8 = iconv_open ("UTF-8", "ISO-8859-1");
50   iconv_t cd_utf8_to_88591 = iconv_open ("ISO-8859-1", "UTF-8");
51   iconv_t cd_88592_to_utf8 = iconv_open ("UTF-8", "ISO-8859-2");
52   iconv_t cd_utf8_to_88592 = iconv_open ("ISO-8859-2", "UTF-8");
53
54   ASSERT (cd_88591_to_88592 != (iconv_t)(-1));
55   ASSERT (cd_88592_to_88591 != (iconv_t)(-1));
56   ASSERT (cd_88591_to_utf8 != (iconv_t)(-1));
57   ASSERT (cd_utf8_to_88591 != (iconv_t)(-1));
58   ASSERT (cd_88592_to_utf8 != (iconv_t)(-1));
59   ASSERT (cd_utf8_to_88592 != (iconv_t)(-1));
60
61   /* ------------------------ Test mem_cd_iconveh() ------------------------ */
62
63   /* Test conversion from ISO-8859-2 to ISO-8859-1 with no errors.  */
64   for (h = 0; h < SIZEOF (handlers); h++)
65     {
66       enum iconv_ilseq_handler handler = handlers[h];
67       static const char input[] = "\304rger mit b\366sen B\374bchen ohne Augenma\337";
68       static const char expected[] = "\304rger mit b\366sen B\374bchen ohne Augenma\337";
69       char *result = NULL;
70       size_t length;
71       int retval = mem_cd_iconveh (input, strlen (input),
72                                    cd_88592_to_88591,
73                                    cd_88592_to_utf8, cd_utf8_to_88591,
74                                    handler,
75                                    &result, &length);
76       ASSERT (retval == 0);
77       ASSERT (length == strlen (expected));
78       ASSERT (result != NULL && memcmp (result, expected, strlen (expected)) == 0);
79       free (result);
80     }
81
82   /* Test conversion from ISO-8859-2 to ISO-8859-1 with EILSEQ.  */
83   for (h = 0; h < SIZEOF (handlers); h++)
84     {
85       enum iconv_ilseq_handler handler = handlers[h];
86       static const char input[] = "Rafa\263 Maszkowski"; /* Rafał Maszkowski */
87       char *result = NULL;
88       size_t length;
89       int retval = mem_cd_iconveh (input, strlen (input),
90                                    cd_88592_to_88591,
91                                    cd_88592_to_utf8, cd_utf8_to_88591,
92                                    handler,
93                                    &result, &length);
94       switch (handler)
95         {
96         case iconveh_error:
97           ASSERT (retval == -1 && errno == EILSEQ);
98           ASSERT (result == NULL);
99           break;
100         case iconveh_question_mark:
101           {
102             static const char expected[] = "Rafa? Maszkowski";
103             ASSERT (retval == 0);
104             ASSERT (length == strlen (expected));
105             ASSERT (result != NULL && memcmp (result, expected, strlen (expected)) == 0);
106             free (result);
107           }
108           break;
109         case iconveh_escape_sequence:
110           {
111             static const char expected[] = "Rafa\\u0142 Maszkowski";
112             ASSERT (retval == 0);
113             ASSERT (length == strlen (expected));
114             ASSERT (result != NULL && memcmp (result, expected, strlen (expected)) == 0);
115             free (result);
116           }
117           break;
118         }
119     }
120
121   /* Test conversion from ISO-8859-1 to UTF-8 with no errors.  */
122   for (h = 0; h < SIZEOF (handlers); h++)
123     {
124       enum iconv_ilseq_handler handler = handlers[h];
125       static const char input[] = "\304rger mit b\366sen B\374bchen ohne Augenma\337";
126       static const char expected[] = "\303\204rger mit b\303\266sen B\303\274bchen ohne Augenma\303\237";
127       char *result = NULL;
128       size_t length;
129       int retval = mem_cd_iconveh (input, strlen (input),
130                                    cd_88591_to_utf8,
131                                    cd_88591_to_utf8, (iconv_t)(-1),
132                                    handler,
133                                    &result, &length);
134       ASSERT (retval == 0);
135       ASSERT (length == strlen (expected));
136       ASSERT (result != NULL && memcmp (result, expected, strlen (expected)) == 0);
137       free (result);
138     }
139
140   /* Test conversion from UTF-8 to ISO-8859-1 with no errors.  */
141   for (h = 0; h < SIZEOF (handlers); h++)
142     {
143       enum iconv_ilseq_handler handler = handlers[h];
144       static const char input[] = "\303\204rger mit b\303\266sen B\303\274bchen ohne Augenma\303\237";
145       static const char expected[] = "\304rger mit b\366sen B\374bchen ohne Augenma\337";
146       char *result = NULL;
147       size_t length;
148       int retval = mem_cd_iconveh (input, strlen (input),
149                                    cd_utf8_to_88591,
150                                    (iconv_t)(-1), cd_utf8_to_88591,
151                                    handler,
152                                    &result, &length);
153       ASSERT (retval == 0);
154       ASSERT (length == strlen (expected));
155       ASSERT (result != NULL && memcmp (result, expected, strlen (expected)) == 0);
156       free (result);
157     }
158
159   /* Test conversion from UTF-8 to ISO-8859-1 with EILSEQ.  */
160   for (h = 0; h < SIZEOF (handlers); h++)
161     {
162       enum iconv_ilseq_handler handler = handlers[h];
163       static const char input[] = "Rafa\305\202 Maszkowski"; /* Rafał Maszkowski */
164       char *result = NULL;
165       size_t length;
166       int retval = mem_cd_iconveh (input, strlen (input),
167                                    cd_utf8_to_88591,
168                                    (iconv_t)(-1), cd_utf8_to_88591,
169                                    handler,
170                                    &result, &length);
171       switch (handler)
172         {
173         case iconveh_error:
174           ASSERT (retval == -1 && errno == EILSEQ);
175           ASSERT (result == NULL);
176           break;
177         case iconveh_question_mark:
178           {
179             static const char expected[] = "Rafa? Maszkowski";
180             ASSERT (retval == 0);
181             ASSERT (length == strlen (expected));
182             ASSERT (result != NULL && memcmp (result, expected, strlen (expected)) == 0);
183             free (result);
184           }
185           break;
186         case iconveh_escape_sequence:
187           {
188             static const char expected[] = "Rafa\\u0142 Maszkowski";
189             ASSERT (retval == 0);
190             ASSERT (length == strlen (expected));
191             ASSERT (result != NULL && memcmp (result, expected, strlen (expected)) == 0);
192             free (result);
193           }
194           break;
195         }
196     }
197
198   /* Test conversion from UTF-8 to ISO-8859-1 with EINVAL.  */
199   for (h = 0; h < SIZEOF (handlers); h++)
200     {
201       enum iconv_ilseq_handler handler = handlers[h];
202       static const char input[] = "\342";
203       char *result = NULL;
204       size_t length;
205       int retval = mem_cd_iconveh (input, strlen (input),
206                                    cd_utf8_to_88591,
207                                    (iconv_t)(-1), cd_utf8_to_88591,
208                                    handler,
209                                    &result, &length);
210       ASSERT (retval == 0);
211       ASSERT (length == 0);
212       if (result != NULL)
213         free (result);
214     }
215
216   /* ------------------------ Test str_cd_iconveh() ------------------------ */
217
218   /* Test conversion from ISO-8859-2 to ISO-8859-1 with no errors.  */
219   for (h = 0; h < SIZEOF (handlers); h++)
220     {
221       enum iconv_ilseq_handler handler = handlers[h];
222       static const char input[] = "\304rger mit b\366sen B\374bchen ohne Augenma\337";
223       static const char expected[] = "\304rger mit b\366sen B\374bchen ohne Augenma\337";
224       char *result = str_cd_iconveh (input,
225                                      cd_88592_to_88591,
226                                      cd_88592_to_utf8, cd_utf8_to_88591,
227                                      handler);
228       ASSERT (result != NULL);
229       ASSERT (strcmp (result, expected) == 0);
230       free (result);
231     }
232
233   /* Test conversion from ISO-8859-2 to ISO-8859-1 with EILSEQ.  */
234   for (h = 0; h < SIZEOF (handlers); h++)
235     {
236       enum iconv_ilseq_handler handler = handlers[h];
237       static const char input[] = "Rafa\263 Maszkowski"; /* Rafał Maszkowski */
238       char *result = str_cd_iconveh (input,
239                                      cd_88592_to_88591,
240                                      cd_88592_to_utf8, cd_utf8_to_88591,
241                                      handler);
242       switch (handler)
243         {
244         case iconveh_error:
245           ASSERT (result == NULL && errno == EILSEQ);
246           break;
247         case iconveh_question_mark:
248           {
249             static const char expected[] = "Rafa? Maszkowski";
250             ASSERT (result != NULL);
251             ASSERT (strcmp (result, expected) == 0);
252             free (result);
253           }
254           break;
255         case iconveh_escape_sequence:
256           {
257             static const char expected[] = "Rafa\\u0142 Maszkowski";
258             ASSERT (result != NULL);
259             ASSERT (strcmp (result, expected) == 0);
260             free (result);
261           }
262           break;
263         }
264     }
265
266   /* Test conversion from ISO-8859-1 to UTF-8 with no errors.  */
267   for (h = 0; h < SIZEOF (handlers); h++)
268     {
269       enum iconv_ilseq_handler handler = handlers[h];
270       static const char input[] = "\304rger mit b\366sen B\374bchen ohne Augenma\337";
271       static const char expected[] = "\303\204rger mit b\303\266sen B\303\274bchen ohne Augenma\303\237";
272       char *result = str_cd_iconveh (input,
273                                      cd_88591_to_utf8,
274                                      cd_88591_to_utf8, (iconv_t)(-1),
275                                      handler);
276       ASSERT (result != NULL);
277       ASSERT (strcmp (result, expected) == 0);
278       free (result);
279     }
280
281   /* Test conversion from UTF-8 to ISO-8859-1 with no errors.  */
282   for (h = 0; h < SIZEOF (handlers); h++)
283     {
284       enum iconv_ilseq_handler handler = handlers[h];
285       static const char input[] = "\303\204rger mit b\303\266sen B\303\274bchen ohne Augenma\303\237";
286       static const char expected[] = "\304rger mit b\366sen B\374bchen ohne Augenma\337";
287       char *result = str_cd_iconveh (input,
288                                      cd_utf8_to_88591,
289                                      (iconv_t)(-1), cd_utf8_to_88591,
290                                      handler);
291       ASSERT (result != NULL);
292       ASSERT (strcmp (result, expected) == 0);
293       free (result);
294     }
295
296   /* Test conversion from UTF-8 to ISO-8859-1 with EILSEQ.  */
297   for (h = 0; h < SIZEOF (handlers); h++)
298     {
299       enum iconv_ilseq_handler handler = handlers[h];
300       static const char input[] = "Costs: 27 \342\202\254"; /* EURO SIGN */
301       char *result = str_cd_iconveh (input,
302                                      cd_utf8_to_88591,
303                                      (iconv_t)(-1), cd_utf8_to_88591,
304                                      handler);
305       switch (handler)
306         {
307         case iconveh_error:
308           ASSERT (result == NULL && errno == EILSEQ);
309           break;
310         case iconveh_question_mark:
311           {
312             static const char expected[] = "Costs: 27 ?";
313             ASSERT (result != NULL);
314             ASSERT (strcmp (result, expected) == 0);
315             free (result);
316           }
317           break;
318         case iconveh_escape_sequence:
319           {
320             static const char expected[] = "Costs: 27 \\u20AC";
321             ASSERT (result != NULL);
322             ASSERT (strcmp (result, expected) == 0);
323             free (result);
324           }
325           break;
326         }
327     }
328
329   /* Test conversion from UTF-8 to ISO-8859-1 with EINVAL.  */
330   for (h = 0; h < SIZEOF (handlers); h++)
331     {
332       enum iconv_ilseq_handler handler = handlers[h];
333       static const char input[] = "\342";
334       char *result = str_cd_iconveh (input,
335                                      cd_utf8_to_88591,
336                                      (iconv_t)(-1), cd_utf8_to_88591,
337                                      handler);
338       ASSERT (result != NULL);
339       ASSERT (strcmp (result, "") == 0);
340       free (result);
341     }
342
343   iconv_close (cd_88591_to_88592);
344   iconv_close (cd_88592_to_88591);
345   iconv_close (cd_88591_to_utf8);
346   iconv_close (cd_utf8_to_88591);
347   iconv_close (cd_88592_to_utf8);
348   iconv_close (cd_utf8_to_88592);
349
350   /* ------------------------- Test str_iconveh() ------------------------- */
351
352   /* Test conversion from ISO-8859-2 to ISO-8859-1 with no errors.  */
353   for (h = 0; h < SIZEOF (handlers); h++)
354     {
355       enum iconv_ilseq_handler handler = handlers[h];
356       static const char input[] = "\304rger mit b\366sen B\374bchen ohne Augenma\337";
357       static const char expected[] = "\304rger mit b\366sen B\374bchen ohne Augenma\337";
358       char *result = str_iconveh (input, "ISO-8859-2", "ISO-8859-1", handler);
359       ASSERT (result != NULL);
360       ASSERT (strcmp (result, expected) == 0);
361       free (result);
362     }
363
364   /* Test conversion from ISO-8859-2 to ISO-8859-1 with EILSEQ.  */
365   for (h = 0; h < SIZEOF (handlers); h++)
366     {
367       enum iconv_ilseq_handler handler = handlers[h];
368       static const char input[] = "Rafa\263 Maszkowski"; /* Rafał Maszkowski */
369       char *result = str_iconveh (input, "ISO-8859-2", "ISO-8859-1", handler);
370       switch (handler)
371         {
372         case iconveh_error:
373           ASSERT (result == NULL && errno == EILSEQ);
374           break;
375         case iconveh_question_mark:
376           {
377             static const char expected[] = "Rafa? Maszkowski";
378             ASSERT (result != NULL);
379             ASSERT (strcmp (result, expected) == 0);
380             free (result);
381           }
382           break;
383         case iconveh_escape_sequence:
384           {
385             static const char expected[] = "Rafa\\u0142 Maszkowski";
386             ASSERT (result != NULL);
387             ASSERT (strcmp (result, expected) == 0);
388             free (result);
389           }
390           break;
391         }
392     }
393
394   /* Test conversion from ISO-8859-1 to UTF-8 with no errors.  */
395   for (h = 0; h < SIZEOF (handlers); h++)
396     {
397       enum iconv_ilseq_handler handler = handlers[h];
398       static const char input[] = "\304rger mit b\366sen B\374bchen ohne Augenma\337";
399       static const char expected[] = "\303\204rger mit b\303\266sen B\303\274bchen ohne Augenma\303\237";
400       char *result = str_iconveh (input, "ISO-8859-1", "UTF-8", handler);
401       ASSERT (result != NULL);
402       ASSERT (strcmp (result, expected) == 0);
403       free (result);
404     }
405
406   /* Test conversion from UTF-8 to ISO-8859-1 with no errors.  */
407   for (h = 0; h < SIZEOF (handlers); h++)
408     {
409       enum iconv_ilseq_handler handler = handlers[h];
410       static const char input[] = "\303\204rger mit b\303\266sen B\303\274bchen ohne Augenma\303\237";
411       static const char expected[] = "\304rger mit b\366sen B\374bchen ohne Augenma\337";
412       char *result = str_iconveh (input, "UTF-8", "ISO-8859-1", handler);
413       ASSERT (result != NULL);
414       ASSERT (strcmp (result, expected) == 0);
415       free (result);
416     }
417
418   /* Test conversion from UTF-8 to ISO-8859-1 with EILSEQ.  */
419   for (h = 0; h < SIZEOF (handlers); h++)
420     {
421       enum iconv_ilseq_handler handler = handlers[h];
422       static const char input[] = "Costs: 27 \342\202\254"; /* EURO SIGN */
423       char *result = str_iconveh (input, "UTF-8", "ISO-8859-1", handler);
424       switch (handler)
425         {
426         case iconveh_error:
427           ASSERT (result == NULL && errno == EILSEQ);
428           break;
429         case iconveh_question_mark:
430           {
431             static const char expected[] = "Costs: 27 ?";
432             ASSERT (result != NULL);
433             ASSERT (strcmp (result, expected) == 0);
434             free (result);
435           }
436           break;
437         case iconveh_escape_sequence:
438           {
439             static const char expected[] = "Costs: 27 \\u20AC";
440             ASSERT (result != NULL);
441             ASSERT (strcmp (result, expected) == 0);
442             free (result);
443           }
444           break;
445         }
446     }
447
448   /* Test conversion from UTF-8 to ISO-8859-1 with EINVAL.  */
449   for (h = 0; h < SIZEOF (handlers); h++)
450     {
451       enum iconv_ilseq_handler handler = handlers[h];
452       static const char input[] = "\342";
453       char *result = str_iconveh (input, "UTF-8", "ISO-8859-1", handler);
454       ASSERT (result != NULL);
455       ASSERT (strcmp (result, "") == 0);
456       free (result);
457     }
458
459 #endif
460
461   return 0;
462 }