Added test case for bug #260
[yaz-moved-to-github.git] / test / tsticonv.c
1 /*
2  * Copyright (C) 1995-2005, Index Data ApS
3  * See the file LICENSE for details.
4  *
5  * $Id: tsticonv.c,v 1.7 2005-02-02 10:17:02 adam Exp $
6  */
7
8 #if HAVE_CONFIG_H
9 #include <config.h>
10 #endif
11
12 #include <stdlib.h>
13 #include <errno.h>
14 #include <string.h>
15 #include <ctype.h>
16
17 #include <yaz/yaz-util.h>
18
19 static int compare_buffers(char *msg, int no,
20                            int expect_len, const unsigned char *expect_buf,
21                            int got_len, const unsigned char *got_buf)
22 {
23     int i;
24     if (expect_len == got_len
25         && !memcmp(expect_buf, got_buf, expect_len))
26         return 1;
27     printf("tsticonv test=%s i=%d failed\n", msg, no);
28     printf("off got exp\n");
29     for (i = 0; i<got_len || i<expect_len; i++)
30     {
31         char got_char[10];
32         char expect_char[10];
33
34         if (i < got_len)
35             sprintf(got_char, "%02X", got_buf[i]);
36         else
37             sprintf(got_char, "?  ");
38
39         if (i < expect_len)
40             sprintf(expect_char, "%02X", expect_buf[i]);
41         else
42             sprintf(expect_char, "?  ");
43         
44         printf("%02d  %s  %s %c\n",
45                i, got_char, expect_char, got_buf[i] == expect_buf[i] ?
46                ' ' : '*');
47
48     }
49     exit(1);
50 }
51
52 /* some test strings in ISO-8859-1 format */
53 static const char *iso_8859_1_a[] = {
54     "ax" ,
55     "\330",
56     "eneb\346r",
57     0 };
58
59 /* same test strings in MARC-8 format */
60 static const char *marc8_a[] = {
61     "ax",   
62     "\xa2",          /* latin capital letter o with stroke */
63     "eneb\xb5r",     /* latin small letter ae */
64     0
65 };
66
67 static void tst_marc8_to_iso_8859_1()
68 {
69     int i;
70     yaz_iconv_t cd;
71
72     cd = yaz_iconv_open("ISO-8859-1", "MARC8");
73     if (!cd)
74     {
75         printf("tsticonv 10 yaz_iconv_open failed\n");
76         exit(10);
77     }
78     for (i = 0; iso_8859_1_a[i]; i++)
79     {
80         size_t r;
81         char *inbuf= (char*) marc8_a[i];
82         size_t inbytesleft = strlen(inbuf);
83         char outbuf0[32];
84         char *outbuf = outbuf0;
85         size_t outbytesleft = sizeof(outbuf0);
86
87         r = yaz_iconv(cd, &inbuf, &inbytesleft, &outbuf, &outbytesleft);
88         if (r == (size_t) (-1))
89         {
90             int e = yaz_iconv_error(cd);
91
92             printf ("tsticonv 11 i=%d e=%d\n", i, e);
93             exit(11);
94         }
95         compare_buffers("tsticonv 11", i,
96                         strlen(iso_8859_1_a[i]), iso_8859_1_a[i],
97                         outbuf - outbuf0, outbuf0);
98     }
99     yaz_iconv_close(cd);
100 }
101
102 static void tst_marc8_to_ucs4b()
103 {
104     static struct {
105         const unsigned char *marc8_b;
106         int len;
107         const unsigned char *ucs4_b;
108     } ar[] = {
109     { 
110         "\033$1" "\x21\x2B\x3B" /* FF1F */ "\033(B" "o",
111         8, "\x00\x00\xFF\x1F" "\x00\x00\x00o"
112     }, {
113         "\033$1" "\x6F\x77\x29" /* AE0E */ "\x6F\x52\x7C" /* c0F4 */ "\033(B",
114         8, "\x00\x00\xAE\x0E" "\x00\x00\xC0\xF4",
115     }, {
116         "\033$1"
117         "\x21\x50\x6E"  /* UCS 7CFB */
118         "\x21\x51\x31"  /* UCS 7D71 */
119         "\x21\x3A\x67"  /* UCS 5B89 */
120         "\x21\x33\x22"  /* UCS 5168 */
121         "\x21\x33\x53"  /* UCS 5206 */
122         "\x21\x44\x2B"  /* UCS 6790 */
123         "\033(B",
124         24, "\x00\x00\x7C\xFB"
125         "\x00\x00\x7D\x71"
126         "\x00\x00\x5B\x89"
127         "\x00\x00\x51\x68"
128         "\x00\x00\x52\x06"
129         "\x00\x00\x67\x90"
130     }, {
131         "\xB0\xB2",     /* AYN and oSLASH */
132         8, "\x00\x00\x02\xBB"  "\x00\x00\x00\xF8"
133     }, {
134         "\xF6\x61",     /* a underscore */
135         8, "\x00\x00\x00\x61"  "\x00\x00\x03\x32"
136     }, {
137         "\x61\xC2",     /* a, phonorecord mark */
138         8, "\x00\x00\x00\x61"  "\x00\x00\x21\x17"
139     },
140     {  /* bug #258 */
141         "el" "\xe8" "am\xe8" "an", /* elaman where a is a" */
142         32,
143         "\x00\x00\x00" "e"
144         "\x00\x00\x00" "l"
145         "\x00\x00\x00" "a"
146         "\x00\x00\x03\x08"
147         "\x00\x00\x00" "m"
148         "\x00\x00\x00" "a"
149         "\x00\x00\x03\x08"
150         "\x00\x00\x00" "n"
151     }, 
152 #if 0
153     { /* bug #260 */
154         "\xe5\xe8\x41",
155         12, "\x00\x00\x00\x41" "\x00\x00\x03\x04" "\x00\x00\x03\x08"
156     }, 
157 #endif
158     {
159         0, 0, 0
160     }
161     };
162     int i;
163     yaz_iconv_t cd;
164
165     cd = yaz_iconv_open("UCS4", "MARC8");
166     if (!cd)
167     {
168         printf ("tsticonv 20 yaz_iconv_open failed\n");
169         exit(20);
170     }
171     for (i = 6; ar[i].len; i++)
172     {
173         size_t r;
174         size_t expect_len = ar[i].len;
175         char *inbuf= (char*) ar[i].marc8_b;
176         size_t inbytesleft = strlen(inbuf);
177         char outbuf0[64];
178         char *outbuf = outbuf0;
179
180         while (inbytesleft)
181         {
182             size_t outbytesleft = outbuf0 + sizeof(outbuf0) - outbuf;
183             if (outbytesleft > 12)
184                 outbytesleft = 12;
185             r = yaz_iconv(cd, &inbuf, &inbytesleft, &outbuf, &outbytesleft);
186             if (r == (size_t) (-1))
187             {
188                 int e = yaz_iconv_error(cd);
189                 if (e != YAZ_ICONV_E2BIG)
190                 {
191                     printf ("tsticonv 21 i=%d e=%d\n", i, e);
192                     exit(21);
193                 }
194             }
195             else
196                 break;
197         }
198         compare_buffers("tsticonv 22", i,
199                         expect_len, ar[i].ucs4_b,
200                         outbuf - outbuf0, outbuf0);
201     }
202     yaz_iconv_close(cd);
203 }
204
205 static void tst_ucs4b_to_utf8()
206 {
207     static const char *ucs4_c[] = {
208         "\x00\x00\xFF\x1F\x00\x00\x00o",
209         "\x00\x00\xAE\x0E\x00\x00\xC0\xF4",
210         0
211     };
212     static const char *utf8_c[] = {
213         "\xEF\xBC\x9F\x6F",
214         "\xEA\xB8\x8E\xEC\x83\xB4",
215         0
216     };
217     
218     int i;
219     yaz_iconv_t cd;
220
221     cd = yaz_iconv_open("UTF8", "UCS4");
222     if (!cd)
223     {
224         printf ("tsticonv 30 yaz_iconv_open failed\n");
225         exit(30);
226     }
227     for (i = 0; ucs4_c[i]; i++)
228     {
229         size_t r;
230         char *inbuf= (char*) ucs4_c[i];
231         size_t inbytesleft = 8;
232         char outbuf0[24];
233         char *outbuf = outbuf0;
234         size_t outbytesleft = sizeof(outbuf0);
235
236         r = yaz_iconv(cd, &inbuf, &inbytesleft, &outbuf, &outbytesleft);
237         if (r == (size_t) (-1))
238         {
239             int e = yaz_iconv_error(cd);
240
241             printf ("tsticonv 31 i=%d e=%d\n", i, e);
242             exit(31);
243         }
244         compare_buffers("tsticonv 32", i,
245                         strlen(utf8_c[i]), utf8_c[i],
246                         outbuf - outbuf0, outbuf0);
247     }
248     yaz_iconv_close(cd);
249 }
250
251 static void dconvert(int mandatory, const char *tmpcode)
252 {
253     int i;
254     yaz_iconv_t cd;
255     for (i = 0; iso_8859_1_a[i]; i++)
256     {
257         size_t r;
258         char *inbuf = (char*) iso_8859_1_a[i];
259         size_t inbytesleft = strlen(inbuf);
260         char outbuf0[24];
261         char outbuf1[10];
262         char *outbuf = outbuf0;
263         size_t outbytesleft = sizeof(outbuf0);
264
265         cd = yaz_iconv_open(tmpcode, "ISO-8859-1");
266         if (!cd)
267         {
268             if (!mandatory)
269                 return;
270             printf ("tsticonv code=%s 1\n", tmpcode);
271             exit(1);
272         }
273         r = yaz_iconv(cd, &inbuf, &inbytesleft, &outbuf, &outbytesleft);
274         if (r == (size_t)(-1))
275         {
276             int e = yaz_iconv_error(cd);
277
278             printf ("tsticonv code=%s 2 e=%d\n", tmpcode, e);
279             exit(2);
280         }
281         yaz_iconv_close(cd);
282         
283         cd = yaz_iconv_open("ISO-8859-1", tmpcode);
284         if (!cd)
285         {
286             if (!mandatory)
287                 return;
288             printf ("tsticonv code=%s 3\n", tmpcode);
289             exit(3);
290         }
291         inbuf = outbuf0;
292         inbytesleft = sizeof(outbuf0) - outbytesleft;
293
294         outbuf = outbuf1;
295         outbytesleft = sizeof(outbuf1);
296         r = yaz_iconv(cd, &inbuf, &inbytesleft, &outbuf, &outbytesleft);
297         if (r == (size_t)(-1)) {
298             int e = yaz_iconv_error(cd);
299
300             printf ("tsticonv code=%s 4 e=%d\n", tmpcode, e);
301             exit(4);
302         }
303         compare_buffers("dconvert", i,
304                         strlen(iso_8859_1_a[i]), iso_8859_1_a[i],
305                         sizeof(outbuf1) - outbytesleft, outbuf1);
306         yaz_iconv_close(cd);
307     }
308 }
309         
310 int main (int argc, char **argv)
311 {
312     dconvert(1, "UTF-8");
313     dconvert(1, "ISO-8859-1");
314     dconvert(1, "UCS4");
315     dconvert(1, "UCS4LE");
316     dconvert(0, "CP865");
317     tst_marc8_to_iso_8859_1();
318     tst_marc8_to_ucs4b();
319     tst_ucs4b_to_utf8();
320     exit (0);
321 }