Better ASSERT macro.
[gnulib.git] / tests / test-iconv.c
1 /* Test of character set conversion.
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 #if HAVE_ICONV
25 # include <iconv.h>
26 #endif
27
28 #include <errno.h>
29 #include <stdio.h>
30 #include <stdlib.h>
31 #include <string.h>
32
33 #define ASSERT(expr) \
34   do                                                                         \
35     {                                                                        \
36       if (!(expr))                                                           \
37         {                                                                    \
38           fprintf (stderr, "%s:%d: assertion failed\n", __FILE__, __LINE__); \
39           abort ();                                                          \
40         }                                                                    \
41     }                                                                        \
42   while (0)
43
44 int
45 main ()
46 {
47 #if HAVE_ICONV
48   /* Assume that iconv() supports at least the encodings ASCII, ISO-8859-1,
49      and UTF-8.  */
50   iconv_t cd_88591_to_utf8 = iconv_open ("UTF-8", "ISO-8859-1");
51   iconv_t cd_utf8_to_88591 = iconv_open ("ISO-8859-1", "UTF-8");
52
53   ASSERT (cd_88591_to_utf8 != (iconv_t)(-1));
54   ASSERT (cd_utf8_to_88591 != (iconv_t)(-1));
55
56   /* Test conversion from ISO-8859-1 to UTF-8 with no errors.  */
57   {
58     static const char input[] = "\304rger mit b\366sen B\374bchen ohne Augenma\337";
59     static const char expected[] = "\303\204rger mit b\303\266sen B\303\274bchen ohne Augenma\303\237";
60     char buf[50];
61     const char *inptr = input;
62     size_t inbytesleft = strlen (input);
63     char *outptr = buf;
64     size_t outbytesleft = sizeof (buf);
65     size_t res = iconv (cd_88591_to_utf8,
66                         (ICONV_CONST char **) &inptr, &inbytesleft,
67                         &outptr, &outbytesleft);
68     ASSERT (res == 0 && inbytesleft == 0);
69     ASSERT (outptr == buf + strlen (expected));
70     ASSERT (memcmp (buf, expected, strlen (expected)) == 0);
71   }
72
73   /* Test conversion from ISO-8859-1 to UTF-8 with E2BIG.  */
74   {
75     static const char input[] = "\304";
76     static char buf[2] = { (char)0xDE, (char)0xAD };
77     const char *inptr = input;
78     size_t inbytesleft = 1;
79     char *outptr = buf;
80     size_t outbytesleft = 1;
81     size_t res = iconv (cd_88591_to_utf8,
82                         (ICONV_CONST char **) &inptr, &inbytesleft,
83                         &outptr, &outbytesleft);
84     ASSERT (res == (size_t)(-1) && errno == E2BIG);
85     ASSERT (inbytesleft == 1);
86     ASSERT (outbytesleft == 1);
87     ASSERT ((unsigned char) buf[1] == 0xAD);
88     ASSERT ((unsigned char) buf[0] == 0xDE);
89   }
90
91   /* Test conversion from UTF-8 to ISO-8859-1 with no errors.  */
92   {
93     static const char input[] = "\303\204rger mit b\303\266sen B\303\274bchen ohne Augenma\303\237";
94     static const char expected[] = "\304rger mit b\366sen B\374bchen ohne Augenma\337";
95     char buf[50];
96     const char *inptr = input;
97     size_t inbytesleft = strlen (input);
98     char *outptr = buf;
99     size_t outbytesleft = sizeof (buf);
100     size_t res = iconv (cd_utf8_to_88591,
101                         (ICONV_CONST char **) &inptr, &inbytesleft,
102                         &outptr, &outbytesleft);
103     ASSERT (res == 0 && inbytesleft == 0);
104     ASSERT (outptr == buf + strlen (expected));
105     ASSERT (memcmp (buf, expected, strlen (expected)) == 0);
106   }
107
108   /* Test conversion from UTF-8 to ISO-8859-1 with EILSEQ.  */
109   {
110     static const char input[] = "\342\202\254"; /* EURO SIGN */
111     char buf[10];
112     const char *inptr = input;
113     size_t inbytesleft = strlen (input);
114     char *outptr = buf;
115     size_t outbytesleft = sizeof (buf);
116     size_t res = iconv (cd_utf8_to_88591,
117                         (ICONV_CONST char **) &inptr, &inbytesleft,
118                         &outptr, &outbytesleft);
119     if (res == (size_t)(-1))
120       {
121         ASSERT (errno == EILSEQ);
122         ASSERT (inbytesleft == strlen (input) && outptr == buf);
123       }
124     else
125       {
126         ASSERT (res == 1);
127         ASSERT (inbytesleft == 0);
128       }
129   }
130
131   /* Test conversion from UTF-8 to ISO-8859-1 with EINVAL.  */
132   {
133     static const char input[] = "\342";
134     char buf[10];
135     const char *inptr = input;
136     size_t inbytesleft = 1;
137     char *outptr = buf;
138     size_t outbytesleft = sizeof (buf);
139     size_t res = iconv (cd_utf8_to_88591,
140                         (ICONV_CONST char **) &inptr, &inbytesleft,
141                         &outptr, &outbytesleft);
142     ASSERT (res == (size_t)(-1) && errno == EINVAL);
143     ASSERT (inbytesleft == 1 && outptr == buf);
144   }
145
146   iconv_close (cd_88591_to_utf8);
147   iconv_close (cd_utf8_to_88591);
148 #endif
149
150   return 0;
151 }