603142f75d8877b7b60e78efe4965e21bcc99009
[platform/upstream/glib.git] / glib / tests / convert.c
1 /* GLIB - Library of useful routines for C programming
2  * Copyright (C) 1995-1997  Peter Mattis, Spencer Kimball and Josh MacDonald
3  *
4  * This library is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU Lesser General Public
6  * License as published by the Free Software Foundation; either
7  * version 2 of the License, or (at your option) any later version.
8  *
9  * This library 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 GNU
12  * Lesser General Public License for more details.
13  *
14  * You should have received a copy of the GNU Lesser General Public
15  * License along with this library; if not, write to the
16  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
17  * Boston, MA 02111-1307, USA.
18  */
19
20 /*
21  * Modified by the GLib Team and others 1997-2000.  See the AUTHORS
22  * file for a list of people on the GLib Team.  See the ChangeLog
23  * files for a list of changes.  These files are distributed with
24  * GLib at ftp://ftp.gtk.org/pub/gtk/. 
25  */
26
27 #undef G_DISABLE_ASSERT
28 #undef G_LOG_DOMAIN
29
30 #include <string.h>
31
32 #include <glib.h>
33
34 /* Bug 311337 */
35 static void
36 test_iconv_state (void)
37 {
38   gchar *in = "\xf4\xe5\xf8\xe5\xed";
39   gchar *expected = "\xd7\xa4\xd7\x95\xd7\xa8\xd7\x95\xd7\x9d";
40   gchar *out;
41   gsize bytes_read = 0;
42   gsize bytes_written = 0;
43   GError *error = NULL;
44
45   out = g_convert (in, -1, "UTF-8", "CP1255", 
46                    &bytes_read, &bytes_written, &error);
47
48   if (error && error->code == G_CONVERT_ERROR_NO_CONVERSION)
49     return; /* silently skip if CP1255 is not supported, see bug 467707 */ 
50
51   g_assert_no_error (error);
52   g_assert (bytes_read == 5);
53   g_assert (bytes_written == 10);
54   g_assert (strcmp (out, expected) == 0);
55   g_free (out);
56 }
57
58 /* some tests involving "vulgar fraction one half" */
59 static void 
60 test_one_half (void)
61 {
62   gchar *in = "\xc2\xbd";
63   gchar *out;
64   gsize bytes_read = 0;
65   gsize bytes_written = 0;
66   GError *error = NULL;  
67
68   out = g_convert (in, -1, 
69                    "ISO-8859-1", "UTF-8",
70                    &bytes_read, &bytes_written,
71                    &error);
72
73   g_assert_no_error (error);
74   g_assert (bytes_read == 2);
75   g_assert (bytes_written == 1);
76   g_assert (strcmp (out, "\xbd") == 0);
77   g_free (out);
78
79   out = g_convert (in, -1, 
80                    "ISO-8859-15", "UTF-8",
81                    &bytes_read, &bytes_written,
82                    &error);
83
84   g_assert_error (error, G_CONVERT_ERROR, G_CONVERT_ERROR_ILLEGAL_SEQUENCE);
85   g_assert (bytes_read == 0);
86   g_assert (bytes_written == 0);
87   g_assert (out == NULL);
88   g_clear_error (&error);
89   g_free (out);
90
91   out = g_convert_with_fallback (in, -1, 
92                                  "ISO8859-15", "UTF-8",
93                                  "a",
94                                  &bytes_read, &bytes_written,
95                                  &error);
96
97   g_assert_no_error (error);
98   g_assert (bytes_read == 2);
99   g_assert (bytes_written == 1);
100   g_assert (strcmp (out, "a") == 0);
101   g_free (out);
102 }
103
104 static void
105 test_byte_order (void)
106 {
107   gchar in_be[4] = { 0xfe, 0xff, 0x03, 0x93}; /* capital gamma */
108   gchar in_le[4] = { 0xff, 0xfe, 0x93, 0x03};
109   gchar *expected = "\xce\x93";
110   gchar *out;
111   gsize bytes_read = 0;
112   gsize bytes_written = 0;
113   GError *error = NULL;  
114
115   out = g_convert (in_be, sizeof (in_be), 
116                    "UTF-8", "UTF-16",
117                    &bytes_read, &bytes_written,
118                    &error);
119
120   g_assert_no_error (error);
121   g_assert (bytes_read == 4);
122   g_assert (bytes_written == 2);
123   g_assert (strcmp (out, expected) == 0);
124   g_free (out);
125
126   out = g_convert (in_le, sizeof (in_le), 
127                    "UTF-8", "UTF-16",
128                    &bytes_read, &bytes_written,
129                    &error);
130
131   g_assert_no_error (error);
132   g_assert (bytes_read == 4);
133   g_assert (bytes_written == 2);
134   g_assert (strcmp (out, expected) == 0);
135   g_free (out);
136 }
137
138 static void
139 check_utf8_to_ucs4 (const char     *utf8,
140                     glong           utf8_len,
141                     const gunichar *ucs4,
142                     glong           ucs4_len,
143                     glong           error_pos)
144 {
145   gunichar *result, *result2, *result3;
146   glong items_read, items_read2;
147   glong items_written, items_written2;
148   GError *error, *error2, *error3;
149   gint i;
150
151   if (!error_pos)
152     {
153       /* check the fast conversion */
154       result = g_utf8_to_ucs4_fast (utf8, utf8_len, &items_written);
155
156       g_assert (items_written == ucs4_len);
157       g_assert (result);
158       for (i = 0; i <= items_written; i++)
159         g_assert (result[i] == ucs4[i]);      
160
161       g_free (result);
162     }
163
164   error = NULL;
165   result = g_utf8_to_ucs4 (utf8, utf8_len, &items_read, &items_written, &error);
166   
167   if (utf8_len == strlen (utf8))
168     {
169       /* check that len == -1 yields identical results */
170       error2 = NULL;
171       result2 = g_utf8_to_ucs4 (utf8, -1, &items_read2, &items_written2, &error2);
172       g_assert (error || items_read2 == items_read);
173       g_assert (error || items_written2 == items_written2);
174       g_assert (!!result == !!result2);
175       g_assert (!!error == !!error2);
176       if (result)
177         for (i = 0; i <= items_written; i++)
178           g_assert (result[i] == result2[i]);
179
180       g_free (result2);
181       if (error2)
182         g_error_free (error2);
183     }
184
185   error3 = NULL;
186   result3 = g_utf8_to_ucs4 (utf8, utf8_len, NULL, NULL, &error3);
187       
188   if (error3 && error3->code == G_CONVERT_ERROR_PARTIAL_INPUT)
189     {
190       g_assert_no_error (error);
191       g_assert (items_read == error_pos);
192       g_assert (items_written == ucs4_len);
193       g_assert (result);
194       for (i = 0; i <= items_written; i++)
195         g_assert (result[i] == ucs4[i]);
196       g_error_free (error3);
197     }
198   else if (error_pos)
199     {
200       g_assert (error != NULL);
201       g_assert (result == NULL);
202       g_assert (items_read == error_pos);
203       g_error_free (error);
204
205       g_assert (error3 != NULL);
206       g_assert (result3 == NULL);
207       g_error_free (error3);
208     }
209   else
210     {
211       g_assert_no_error (error);
212       g_assert (items_read == utf8_len);
213       g_assert (items_written == ucs4_len);
214       g_assert (result);
215       for (i = 0; i <= items_written; i++)
216         g_assert (result[i] == ucs4[i]);
217
218       g_assert_no_error (error3);
219       g_assert (result3);
220       for (i = 0; i <= ucs4_len; i++)
221         g_assert (result3[i] == ucs4[i]);
222     }
223
224   g_free (result);
225   g_free (result3);
226 }
227
228 static void
229 check_ucs4_to_utf8 (const gunichar *ucs4,
230                     glong           ucs4_len,
231                     const char     *utf8,
232                     glong           utf8_len,
233                     glong           error_pos)
234 {
235   gchar *result, *result2, *result3;
236   glong items_read, items_read2;
237   glong items_written, items_written2;
238   GError *error, *error2, *error3;
239
240   error = NULL;
241   result = g_ucs4_to_utf8 (ucs4, ucs4_len, &items_read, &items_written, &error);
242
243   if (ucs4[ucs4_len] == 0)
244     {
245       /* check that len == -1 yields identical results */
246       error2 = NULL;
247       result2 = g_ucs4_to_utf8 (ucs4, -1, &items_read2, &items_written2, &error2);
248       
249       g_assert (error || items_read2 == items_read);
250       g_assert (error || items_written2 == items_written);
251       g_assert (!!result == !!result2);
252       g_assert (!!error == !!error2);
253       if (result)
254         g_assert (strcmp (result, result2) == 0);
255
256       g_free (result2);
257       if (error2)
258         g_error_free (error2);
259     }
260
261   error3 = NULL;
262   result3 = g_ucs4_to_utf8 (ucs4, ucs4_len, NULL, NULL, &error3);
263       
264   if (error_pos)
265     {
266       g_assert (error != NULL);
267       g_assert (result == NULL);
268       g_assert (items_read == error_pos);
269       g_error_free (error);
270
271       g_assert (error3 != NULL);
272       g_assert (result3 == NULL);
273       g_error_free (error3);
274     }
275   else
276     {
277       g_assert_no_error (error);
278       g_assert (items_read == ucs4_len);
279       g_assert (items_written == utf8_len);
280       g_assert (result);
281       g_assert (strcmp (result, utf8) == 0);
282
283       g_assert_no_error (error3);
284       g_assert (result3);
285       g_assert (strcmp (result3, utf8) == 0);
286     }
287
288   g_free (result);
289   g_free (result3);
290 }
291
292 static void
293 check_utf8_to_utf16 (const char      *utf8,
294                      glong            utf8_len,
295                      const gunichar2 *utf16,
296                      glong            utf16_len,
297                      glong            error_pos)
298 {
299   gunichar2 *result, *result2, *result3;
300   glong items_read, items_read2;
301   glong items_written, items_written2;
302   GError *error, *error2, *error3;
303   gint i;
304
305   error = NULL;
306   result = g_utf8_to_utf16 (utf8, utf8_len, &items_read, &items_written, &error);
307
308   if (utf8_len == strlen (utf8))
309     {
310       /* check that len == -1 yields identical results */
311       error2 = NULL;
312       result2 = g_utf8_to_utf16 (utf8, -1, &items_read2, &items_written2, &error2);
313       g_assert (error || items_read2 == items_read);
314       g_assert (error || items_written2 == items_written2);
315       g_assert (!!result == !!result2);
316       g_assert (!!error == !!error2);
317       if (result)
318         for (i = 0; i <= items_written; i++)
319           g_assert (result[i] == result2[i]);
320       
321       g_free (result2);
322       if (error2)
323         g_error_free (error2);
324     }
325
326   error3 = NULL;
327   result3 = g_utf8_to_utf16 (utf8, utf8_len, NULL, NULL, &error3);
328       
329   if (error3 && error3->code == G_CONVERT_ERROR_PARTIAL_INPUT)
330     {
331       g_assert_no_error (error);
332       g_assert (items_read == error_pos);
333       g_assert (items_written == utf16_len);
334       g_assert (result);
335       for (i = 0; i <= items_written; i++)
336         g_assert (result[i] == utf16[i]);
337       g_error_free (error3);
338     }
339   else if (error_pos)
340     {
341       g_assert (error != NULL);
342       g_assert (result == NULL);
343       g_assert (items_read == error_pos);
344       g_error_free (error);
345
346       g_assert (error3 != NULL);
347       g_assert (result3 == NULL);
348       g_error_free (error3);
349     }
350   else
351     {
352       g_assert_no_error (error);
353       g_assert (items_read == utf8_len);
354       g_assert (items_written == utf16_len);
355       g_assert (result);
356       for (i = 0; i <= items_written; i++)
357         g_assert (result[i] == utf16[i]);
358
359       g_assert_no_error (error3);
360       g_assert (result3);
361       for (i = 0; i <= utf16_len; i++)
362         g_assert (result3[i] == utf16[i]);
363     }
364
365   g_free (result);
366   g_free (result3);
367 }
368
369 static void
370 check_utf16_to_utf8 (const gunichar2 *utf16,
371                      glong            utf16_len,
372                      const char      *utf8,
373                      glong            utf8_len,
374                      glong            error_pos)
375 {
376   gchar *result, *result2, *result3;
377   glong items_read, items_read2;
378   glong items_written, items_written2;
379   GError *error, *error2, *error3;
380
381   error = NULL;
382   result = g_utf16_to_utf8 (utf16, utf16_len, &items_read, &items_written, &error);
383   if (utf16[utf16_len] == 0)
384     {
385       /* check that len == -1 yields identical results */
386       error2 = NULL;
387       result2 = g_utf16_to_utf8 (utf16, -1, &items_read2, &items_written2, &error2);
388       
389       g_assert (error || items_read2 == items_read);
390       g_assert (error || items_written2 == items_written);
391       g_assert (!!result == !!result2);
392       g_assert (!!error == !!error2);
393       if (result)
394         g_assert (strcmp (result, result2) == 0);
395
396       g_free (result2);
397       if (error2)
398         g_error_free (error2);
399     }
400
401   error3 = NULL;
402   result3 = g_utf16_to_utf8 (utf16, utf16_len, NULL, NULL, &error3);
403   
404   if (error3 && error3->code == G_CONVERT_ERROR_PARTIAL_INPUT)
405     {
406       g_assert_no_error (error);
407       g_assert (items_read == error_pos);
408       g_assert (items_read + 1 == utf16_len);
409       g_assert (items_written == utf8_len);
410       g_assert (result);
411       g_assert (strcmp (result, utf8) == 0);
412       g_error_free (error3);
413     }
414   else if (error_pos)
415     {
416       g_assert (error != NULL);
417       g_assert (result == NULL);
418       g_assert (items_read == error_pos);
419       g_error_free (error);
420
421       g_assert (error3 != NULL);
422       g_assert (result3 == NULL);
423       g_error_free (error3);
424     }
425   else
426     {
427       g_assert_no_error (error);
428       g_assert (items_read == utf16_len);
429       g_assert (items_written == utf8_len);
430       g_assert (result);
431       g_assert (strcmp (result, utf8) == 0);
432
433       g_assert_no_error (error3);
434       g_assert (result3);
435       g_assert (strcmp (result3, utf8) == 0);
436     }
437
438   g_free (result);
439   g_free (result3);
440 }
441
442 static void
443 check_ucs4_to_utf16 (const gunichar  *ucs4,
444                      glong            ucs4_len,
445                      const gunichar2 *utf16,
446                      glong            utf16_len,
447                      glong            error_pos)
448 {
449   gunichar2 *result, *result2, *result3;
450   glong items_read, items_read2;
451   glong items_written, items_written2;
452   GError *error, *error2, *error3;
453   gint i;
454
455   error = NULL;
456   result = g_ucs4_to_utf16 (ucs4, ucs4_len, &items_read, &items_written, &error);
457
458   if (ucs4[ucs4_len] == 0)
459     {
460       /* check that len == -1 yields identical results */
461       error2 = NULL;
462       result2 = g_ucs4_to_utf16 (ucs4, -1, &items_read2, &items_written2, &error2);
463       
464       g_assert (error || items_read2 == items_read);
465       g_assert (error || items_written2 == items_written);
466       g_assert (!!result == !!result2);
467       g_assert (!!error == !!error2);
468       if (result)
469       for (i = 0; i <= utf16_len; i++)
470         g_assert (result[i] == result2[i]);
471
472       g_free (result2);
473       if (error2)
474         g_error_free (error2);
475     }
476
477   error3 = NULL;
478   result3 = g_ucs4_to_utf16 (ucs4, -1, NULL, NULL, &error3);
479       
480   if (error_pos)
481     {
482       g_assert (error != NULL);
483       g_assert (result == NULL);
484       g_assert (items_read == error_pos);
485       g_error_free (error);
486
487       g_assert (error3 != NULL);
488       g_assert (result3 == NULL);
489       g_error_free (error3);
490     }
491   else
492     {
493       g_assert_no_error (error);
494       g_assert (items_read == ucs4_len);
495       g_assert (items_written == utf16_len);
496       g_assert (result);
497       for (i = 0; i <= utf16_len; i++)
498         g_assert (result[i] == utf16[i]);
499
500       g_assert_no_error (error3);
501       g_assert (result3);
502       for (i = 0; i <= utf16_len; i++)
503         g_assert (result3[i] == utf16[i]);
504     }
505
506   g_free (result);
507   g_free (result3);
508 }
509
510 static void
511 check_utf16_to_ucs4 (const gunichar2 *utf16,
512                      glong            utf16_len,
513                      const gunichar  *ucs4,
514                      glong            ucs4_len,
515                      glong            error_pos)
516 {
517   gunichar *result, *result2, *result3;
518   glong items_read, items_read2;
519   glong items_written, items_written2;
520   GError *error, *error2, *error3;
521   gint i;
522
523   error = NULL;
524   result = g_utf16_to_ucs4 (utf16, utf16_len, &items_read, &items_written, &error);
525   if (utf16[utf16_len] == 0)
526     {
527       /* check that len == -1 yields identical results */
528       error2 = NULL;
529       result2 = g_utf16_to_ucs4 (utf16, -1, &items_read2, &items_written2, &error2);
530       g_assert (error || items_read2 == items_read);
531       g_assert (error || items_written2 == items_written2);
532       g_assert (!!result == !!result2);
533       g_assert (!!error == !!error2);
534       if (result)
535         for (i = 0; i <= items_written; i++)
536           g_assert (result[i] == result2[i]);
537
538       g_free (result2);
539       if (error2)
540         g_error_free (error2);
541     }
542
543   error3 = NULL;
544   result3 = g_utf16_to_ucs4 (utf16, utf16_len, NULL, NULL, &error3);
545       
546   if (error3 && error3->code == G_CONVERT_ERROR_PARTIAL_INPUT)
547     {
548       g_assert_no_error (error);
549       g_assert (items_read == error_pos);
550       g_assert (items_read + 1 == utf16_len);
551       g_assert (items_written == ucs4_len);
552       g_assert (result);
553       for (i = 0; i <= items_written; i++)
554         g_assert (result[i] == ucs4[i]);
555       g_error_free (error3);
556     }
557   else if (error_pos)
558     {
559       g_assert (error != NULL);
560       g_assert (result == NULL);
561       g_assert (items_read == error_pos);
562       g_error_free (error);
563
564       g_assert (error3 != NULL);
565       g_assert (result3 == NULL);
566       g_error_free (error3);
567     }
568   else
569     {
570       g_assert_no_error (error);
571       g_assert (items_read == utf16_len);
572       g_assert (items_written == ucs4_len);
573       g_assert (result);
574       for (i = 0; i <= ucs4_len; i++)
575         g_assert (result[i] == ucs4[i]);
576
577       g_assert_no_error (error3);
578       g_assert (result3);
579       for (i = 0; i <= ucs4_len; i++)
580         g_assert (result3[i] == ucs4[i]);
581     }
582
583   g_free (result);
584   g_free (result3);
585 }
586
587 static void
588 test_unicode_conversions (void)
589 {
590   char *utf8;
591   gunichar ucs4[100];
592   gunichar2 utf16[100];
593
594   utf8 = "abc";
595   ucs4[0] = 0x61; ucs4[1] = 0x62; ucs4[2] = 0x63; ucs4[3] = 0;
596   utf16[0] = 0x61; utf16[1] = 0x62; utf16[2] = 0x63; utf16[3] = 0;
597
598   check_utf8_to_ucs4 (utf8, 3, ucs4, 3, 0);
599   check_ucs4_to_utf8 (ucs4, 3, utf8, 3, 0);
600   check_utf8_to_utf16 (utf8, 3, utf16, 3, 0);
601   check_utf16_to_utf8 (utf16, 3, utf8, 3, 0);
602   check_ucs4_to_utf16 (ucs4, 3, utf16, 3, 0);
603   check_utf16_to_ucs4 (utf16, 3, ucs4, 3, 0);
604
605   utf8 = "\316\261\316\262\316\263";
606   ucs4[0] = 0x03b1; ucs4[1] = 0x03b2; ucs4[2] = 0x03b3; ucs4[3] = 0;
607   utf16[0] = 0x03b1; utf16[1] = 0x03b2; utf16[2] = 0x03b3; utf16[3] = 0;
608
609   check_utf8_to_ucs4 (utf8, 6, ucs4, 3, 0);
610   check_ucs4_to_utf8 (ucs4, 3, utf8, 6, 0);
611   check_utf8_to_utf16 (utf8, 6, utf16, 3, 0);
612   check_utf16_to_utf8 (utf16, 3, utf8, 6, 0);
613   check_ucs4_to_utf16 (ucs4, 3, utf16, 3, 0);
614   check_utf16_to_ucs4 (utf16, 3, ucs4, 3, 0);
615
616   /* partial utf8 character */
617   utf8 = "abc\316";
618   ucs4[0] = 0x61; ucs4[1] = 0x62; ucs4[2] = 0x63; ucs4[3] = 0;
619   utf16[0] = 0x61; utf16[1] = 0x62; utf16[2] = 0x63; utf16[3] = 0;
620
621   check_utf8_to_ucs4 (utf8, 4, ucs4, 3, 3);
622   check_utf8_to_utf16 (utf8, 4, utf16, 3, 3);
623
624   /* invalid utf8 */
625   utf8 = "abc\316\316";
626   ucs4[0] = 0; 
627   utf16[0] = 0; 
628
629   check_utf8_to_ucs4 (utf8, 5, ucs4, 0, 3);
630   check_utf8_to_utf16 (utf8, 5, utf16, 0, 3);
631
632   /* partial utf16 character */
633   utf8 = "ab";
634   ucs4[0] = 0x61; ucs4[1] = 0x62; ucs4[2] = 0;
635   utf16[0] = 0x61; utf16[1] = 0x62; utf16[2] = 0xd801; utf16[3] = 0;
636   
637   check_utf16_to_utf8 (utf16, 3, utf8, 2, 2);
638   check_utf16_to_ucs4 (utf16, 3, ucs4, 2, 2);
639
640   /* invalid utf16 */
641   utf8 = NULL;
642   ucs4[0] = 0;
643   utf16[0] = 0x61; utf16[1] = 0x62; utf16[2] = 0xdc01; utf16[3] = 0;
644
645   check_utf16_to_utf8 (utf16, 3, utf8, 0, 2);
646   check_utf16_to_ucs4 (utf16, 3, ucs4, 0, 2);
647
648   /* invalid ucs4 */
649   utf8 = NULL;
650   ucs4[0] = 0x61; ucs4[1] = 0x62; ucs4[2] = 0x80000000; ucs4[3] = 0;
651   utf16[0] = 0;
652
653   check_ucs4_to_utf8 (ucs4, 3, utf8, 0, 2);
654   check_ucs4_to_utf16 (ucs4, 3, utf16, 0, 2);
655 }
656
657 static void
658 test_filename_utf8 (void)
659 {
660   const gchar *filename = "/my/path/to/foo";
661   gchar *utf8;
662   gchar *back;
663   GError *error;
664
665   error = NULL;
666   utf8 = g_filename_to_utf8 (filename, -1, NULL, NULL, &error);
667   g_assert_no_error (error);
668   back = g_filename_from_utf8 (utf8, -1, NULL, NULL, &error);
669   g_assert_no_error (error);
670   g_assert_cmpstr (back, ==, filename);
671
672   g_free (utf8);
673   g_free (back);
674 }
675
676 static void
677 test_filename_display (void)
678 {
679   const gchar *filename = "/my/path/to/foo";
680   char *display;
681
682   display = g_filename_display_basename (filename);
683   g_assert_cmpstr (display, ==, "foo");
684
685   g_free (display);
686 }
687
688 int
689 main (int argc, char *argv[])
690 {
691   g_test_init (&argc, &argv, NULL);
692
693   g_test_add_func ("/conversion/iconv-state", test_iconv_state);
694   g_test_add_func ("/conversion/illegal-sequence", test_one_half);
695   g_test_add_func ("/conversion/byte-order", test_byte_order);
696   g_test_add_func ("/conversion/unicode", test_unicode_conversions);
697   g_test_add_func ("/conversion/filename-utf8", test_filename_utf8);
698   g_test_add_func ("/conversion/filename-display", test_filename_display);
699
700   return g_test_run ();
701 }