2 * "$Id: testi18n.c 5195 2006-02-27 21:05:46Z mike $"
4 * Internationalization test for Common UNIX Printing System (CUPS).
6 * Copyright 1997-2005 by Easy Software Products.
8 * These coded instructions, statements, and computer programs are
9 * the property of Easy Software Products and are protected by Federal
10 * copyright law. Distribution and use rights are outlined in the
11 * file "LICENSE.txt" which should have been included with this file.
12 * If this file is missing or damaged please contact Easy Software
15 * Attn: CUPS Licensing Information
16 * Easy Software Products
17 * 44141 Airport View Drive, Suite 204
18 * Hollywood, Maryland 20636 USA
20 * Voice: (301) 373-9600
21 * EMail: cups-info@cups.org
22 * WWW: http://www.cups.org
26 * main() - Main entry for internationalization test module.
27 * print_synopsis() - Print program synopsis (help).
28 * print_utf8() - Print UTF-8 string with (optional) message.
29 * print_utf16() - Print UTF-16 string with (optional) message.
30 * print_utf32() - Print UTF-32 string with (optional) message.
31 * test_transcode() - Test 'transcode.c' module.
32 * test_normalize() - Test 'normalize.c' module.
36 * Include necessary headers...
46 #include "transcode.h"
47 #include "normalize.h"
54 static const char *program_synopsis
[] = /* Program help */
57 " -v verbose (print each called function and result)",
58 " -h help (print this synopsis)",
60 "'testi18n' is a utility to test CUPS internationalization",
61 "Copyright 1997-2005 by Easy Software Products.",
64 static int error_count
= 0; /* Total error count */
71 static void print_synopsis(void);
72 static void print_utf8(const char *msg
, const cups_utf8_t
*src
);
73 static void print_utf16(const char *msg
, const cups_utf16_t
*src
);
74 static void print_utf32(const char *msg
, const cups_utf32_t
*src
);
75 static int test_transcode(const int verbose
);
76 static int test_normalize(const int verbose
);
80 * 'main()' - Main entry for internationalization test module.
83 int /* O - Exit code */
84 main(int argc
, /* I - Argument Count */
85 char *argv
[]) /* I - Arguments */
87 int ai
; /* Argument index */
88 char *ap
; /* Argument pointer */
89 int verbose
; /* Verbose flag */
90 int errors
; /* Error count */
94 * Check for switches...
99 for (ai
= 1; ai
< argc
; ai
++)
105 for (ap
++; *ap
!= '\0'; ap
++)
109 case 'v': /* verbose */
125 * Test all internationalization modules and functions...
128 errors
= test_transcode(verbose
);
129 error_count
+= errors
;
130 printf("\ntesti18n: %d errors found in 'transcode.c'\n", errors
);
132 errors
= test_normalize(verbose
);
133 error_count
+= errors
;
134 printf("\ntesti18n: %d errors found in 'normalize.c'\n", errors
);
136 return (error_count
> 0);
141 * 'print_synopsis()' - Print program synopsis (help).
147 int i
; /* Looping variable */
150 for (i
= 0; program_synopsis
[i
]; i
++)
151 puts(program_synopsis
[i
]);
156 * 'print_utf8()' - Print UTF-8 string with (optional) message.
160 print_utf8(const char *msg
, /* I - Message String */
161 const cups_utf8_t
*src
) /* I - UTF-8 Source String */
167 printf(" %02x", *src
);
174 * 'print_utf16()' - Print UTF-16 string with (optional) message.
178 print_utf16(const char *msg
, /* I - Message String */
179 const cups_utf16_t
*src
) /* I - UTF-16 Source String */
184 printf(" %04x", (int) *src
);
191 * 'print_utf32()' - Print UTF-32 string with (optional) message.
195 print_utf32(const char *msg
, /* I - Message String */
196 const cups_utf32_t
*src
) /* I - UTF-32 Source String */
201 printf(" %04x", (int) *src
);
208 * 'test_transcode()' - Test 'transcode.c' module.
211 static int /* O - Zero or error count */
212 test_transcode(const int verbose
) /* I - Verbose flag */
214 FILE *fp
; /* File pointer */
215 int count
; /* File line counter */
216 char line
[1024]; /* File line source string */
217 int len
; /* Length (count) of string */
218 char legsrc
[1024]; /* Legacy source string */
219 char legdest
[1024]; /* Legacy destination string */
220 cups_utf8_t utf8latin
[] = /* UTF-8 Latin-1 source */
221 { 0x41, 0x20, 0x21, 0x3D, 0x20, 0xC3, 0x84, 0x2E, 0x00 };
222 /* "A != <A WITH DIAERESIS>." - use ISO 8859-1 */
223 cups_utf8_t utf8repla
[] = /* UTF-8 Latin-1 replacement */
224 { 0x41, 0x20, 0xE2, 0x89, 0xA2, 0x20, 0xC3, 0x84, 0x2E, 0x00 };
225 /* "A <NOT IDENTICAL TO> <A WITH DIAERESIS>." */
226 cups_utf8_t utf8greek
[] = /* UTF-8 Greek source string */
227 { 0x41, 0x20, 0x21, 0x3D, 0x20, 0xCE, 0x91, 0x2E, 0x00 };
228 /* "A != <ALHPA>." - use ISO 8859-7 */
229 cups_utf8_t utf8japan
[] = /* UTF-8 Japanese source */
230 { 0x41, 0x20, 0x21, 0x3D, 0x20, 0xEE, 0x9C, 0x80, 0x2E, 0x00 };
231 /* "A != <PRIVATE U+E700>." - use Windows 932 or EUC-JP */
232 cups_utf8_t utf8taiwan
[] = /* UTF-8 Chinese source */
233 { 0x41, 0x20, 0x21, 0x3D, 0x20, 0xE4, 0xB9, 0x82, 0x2E, 0x00 };
234 /* "A != <CJK U+4E42>." - use Windows 950 (Big5) or EUC-TW */
235 cups_utf8_t utf8good
[] = /* UTF-8 good 16-bit source */
236 { 0x41, 0x20, 0xE2, 0x89, 0xA2, 0x20, 0xC3, 0x84, 0x2E, 0x00 };
237 /* "A <NOT IDENTICAL TO> <A WITH DIAERESIS>." */
238 cups_utf8_t utf8bad
[] = /* UTF-8 bad 16-bit source */
239 { 0x41, 0x20, 0xE2, 0x89, 0xA2, 0x20, 0xF8, 0x84, 0x2E, 0x00 };
240 /* "A <NOT IDENTICAL TO> <...bad stuff...>." */
241 cups_utf8_t utf8dest
[1024]; /* UTF-8 destination string */
242 cups_utf16_t utf16sur
[] = /* UTF-16 with surrogates */
243 { 0xD800, 0xDC00, 0x20, 0x21, 0x3D, 0x20, 0xC4, 0x2E, 0x00 };
244 /* "<Surrogate pair> != <A WITH DIAERESIS>." */
245 cups_utf16_t utf16src
[1024]; /* UTF-16 source string */
246 cups_utf16_t utf16dest
[1024]; /* UTF-16 destination string */
247 cups_utf32_t utf32src
[1024]; /* UTF-32 source string */
248 cups_utf32_t utf32dest
[1024]; /* UTF-32 destination string */
249 _cups_vmap_t
*vmap
; /* VBCS charmap pointer */
253 * Test with (inserted) and (deleted) leading BOM...
258 printf("\ntesti18n: Testing 'transcode.c'...\n");
259 printf(" testing with insert/delete leading BOM...\n");
263 * Test UTF-8 to UTF-32/EUC-JP on demo file...
268 printf("\ntesti18n: Testing UTF-8 source 'utf8demo.txt'...\n");
269 printf(" testing UTF-8 to UTF-32...\n");
270 printf(" testing UTF-8 to EUC-JP...\n");
273 if ((fp
= fopen("utf8demo.txt", "r")) == NULL
)
278 if (fgets(line
, 1024, fp
) == NULL
)
283 len
= cupsUTF8ToUTF32(utf32dest
, (cups_utf8_t
*)line
, 1024);
285 printf(" error line: %d (UTF-8 to UTF-32)\n", count
);
287 len
= cupsUTF8ToCharset(legdest
, (cups_utf8_t
*)line
, 1024, CUPS_EUC_JP
);
289 printf(" error line: %d (UTF-8 to EUC-JP)\n", count
);
295 printf(" total lines: %d\n", count
);
298 * Test VBCS charmap load for EUC-JP...
302 printf("\ntesti18n: Loading VBCS charmap EUC-JP (Japanese)...\n");
304 vmap
= (_cups_vmap_t
*) cupsCharmapGet(CUPS_EUC_JP
);
310 printf(" charcount: %d\n", vmap
->charcount
);
311 printf(" widecount: %d\n", vmap
->widecount
);
315 * Test VBCS charmap load for EUC-TW...
319 printf("\ntesti18n: Loading VBCS charmap EUC-TW (Taiwan)...\n");
321 vmap
= (_cups_vmap_t
*) cupsCharmapGet(CUPS_EUC_TW
);
327 printf(" charcount: %d\n", vmap
->charcount
);
328 printf(" widecount: %d\n", vmap
->widecount
);
332 * Test UTF-8 to legacy charset (ISO 8859-1)...
336 printf("\ntesti18n: Testing UTF-8 to ISO 8859-1 (Latin1)...\n");
340 len
= cupsUTF8ToCharset(legdest
, utf8latin
, 1024, CUPS_ISO8859_1
);
346 print_utf8(" utf8latin", utf8latin
);
347 print_utf8(" legdest ", (cups_utf8_t
*) legdest
);
350 strcpy(legsrc
, legdest
);
352 len
= cupsCharsetToUTF8(utf8dest
, legsrc
, 1024, CUPS_ISO8859_1
);
357 if (len
!= strlen ((char *) utf8latin
))
360 if (memcmp(utf8latin
, utf8dest
, len
) != 0)
364 * Test UTF-8 to Latin-1 (ISO 8859-1) with replacement...
367 printf("\ntesti18n: Testing UTF-8 to ISO 8859-1 w/ replace...\n");
368 len
= cupsUTF8ToCharset(legdest
, utf8repla
, 1024, CUPS_ISO8859_1
);
373 print_utf8(" utf8repla", utf8repla
);
374 print_utf8(" legdest ", (cups_utf8_t
*) legdest
);
378 * Test UTF-8 to legacy charset (ISO 8859-7)...
381 printf("\ntesti18n: Testing UTF-8 to ISO 8859-7 (Greek)...\n");
383 len
= cupsUTF8ToCharset(legdest
, utf8greek
, 1024, CUPS_ISO8859_7
);
388 print_utf8(" utf8greek", utf8greek
);
389 print_utf8(" legdest ", (cups_utf8_t
*) legdest
);
391 strcpy(legsrc
, legdest
);
392 len
= cupsCharsetToUTF8(utf8dest
, legsrc
, 1024, CUPS_ISO8859_7
);
395 if (len
!= strlen ((char *) utf8greek
))
397 if (memcmp(utf8greek
, utf8dest
, len
) != 0)
401 * Test UTF-8 to legacy charset (Windows 932)...
404 printf("\ntesti18n: Testing UTF-8 to Windows 932 (Japanese)...\n");
406 len
= cupsUTF8ToCharset(legdest
, utf8japan
, 1024, CUPS_WINDOWS_932
);
411 print_utf8(" utf8japan", utf8japan
);
412 print_utf8(" legdest ", (cups_utf8_t
*) legdest
);
414 strcpy(legsrc
, legdest
);
415 len
= cupsCharsetToUTF8(utf8dest
, legsrc
, 1024, CUPS_WINDOWS_932
);
418 if (len
!= strlen ((char *) utf8japan
))
420 if (memcmp(utf8japan
, utf8dest
, len
) != 0)
424 * Test UTF-8 to legacy charset (EUC-JP)...
427 printf("\ntesti18n: Testing UTF-8 to EUC-JP (Japanese)...\n");
429 len
= cupsUTF8ToCharset(legdest
, utf8japan
, 1024, CUPS_EUC_JP
);
434 print_utf8(" utf8japan", utf8japan
);
435 print_utf8(" legdest ", (cups_utf8_t
*) legdest
);
437 strcpy(legsrc
, legdest
);
438 len
= cupsCharsetToUTF8(utf8dest
, legsrc
, 1024, CUPS_EUC_JP
);
441 if (len
!= strlen ((char *) utf8japan
))
443 if (memcmp(utf8japan
, utf8dest
, len
) != 0)
447 * Test UTF-8 to legacy charset (Windows 950)...
450 printf("\ntesti18n: Testing UTF-8 to Windows 950 (Chinese)...\n");
452 len
= cupsUTF8ToCharset(legdest
, utf8taiwan
, 1024, CUPS_WINDOWS_950
);
457 print_utf8(" utf8taiwan", utf8taiwan
);
458 print_utf8(" legdest ", (cups_utf8_t
*) legdest
);
460 strcpy(legsrc
, legdest
);
461 len
= cupsCharsetToUTF8(utf8dest
, legsrc
, 1024, CUPS_WINDOWS_950
);
464 if (len
!= strlen ((char *) utf8taiwan
))
466 if (memcmp(utf8taiwan
, utf8dest
, len
) != 0)
470 * Test UTF-8 to legacy charset (EUC-TW)...
473 printf("\ntesti18n: Testing UTF-8 to EUC-TW (Chinese)...\n");
475 len
= cupsUTF8ToCharset(legdest
, utf8taiwan
, 1024, CUPS_EUC_TW
);
480 print_utf8(" utf8taiwan", utf8taiwan
);
481 print_utf8(" legdest ", (cups_utf8_t
*) legdest
);
483 strcpy(legsrc
, legdest
);
484 len
= cupsCharsetToUTF8(utf8dest
, legsrc
, 1024, CUPS_EUC_TW
);
487 if (len
!= strlen ((char *) utf8taiwan
))
489 if (memcmp(utf8taiwan
, utf8dest
, len
) != 0)
493 * Test UTF-8 (16-bit) to UTF-32 (w/ BOM)...
496 printf("\ntesti18n: Testing UTF-8 to UTF-32 (w/ BOM)...\n");
497 len
= cupsUTF8ToUTF32(utf32dest
, utf8good
, 1024);
502 print_utf8(" utf8good ", utf8good
);
503 print_utf32(" utf32dest", utf32dest
);
505 memcpy (utf32src
, utf32dest
, (len
+ 1) * sizeof(cups_utf32_t
));
506 len
= cupsUTF32ToUTF8(utf8dest
, utf32src
, 1024);
509 if (len
!= strlen ((char *) utf8good
))
511 if (memcmp(utf8good
, utf8dest
, len
) != 0)
515 * Test invalid UTF-8 (16-bit) to UTF-32 (w/ BOM)...
518 printf("\ntesti18n: Testing UTF-8 bad 16-bit source string...\n");
519 len
= cupsUTF8ToUTF32(utf32dest
, utf8bad
, 1024);
523 print_utf8(" utf8bad ", utf8bad
);
526 * Test UTF-8 (16-bit) to UTF-16 (w/ BOM)...
529 printf("\ntesti18n: Testing UTF-8 to UTF-16 (w/ BOM)...\n");
530 len
= cupsUTF8ToUTF16(utf16dest
, utf8good
, 1024);
535 print_utf8(" utf8good ", utf8good
);
536 print_utf16(" utf16dest", utf16dest
);
538 memcpy (utf16src
, utf16dest
, (len
+ 1) * sizeof(cups_utf16_t
));
539 len
= cupsUTF16ToUTF8(utf8dest
, utf16src
, 1024);
542 if (len
!= strlen ((char *) utf8good
))
544 if (memcmp(utf8good
, utf8dest
, len
) != 0)
548 * Test UTF-16 to UTF-32 with surrogates...
551 printf("\ntesti18n: Testing UTF-16 to UTF-32 w/ surrogates...\n");
552 len
= cupsUTF16ToUTF32(utf32dest
, utf16sur
, 1024);
557 print_utf16(" utf16sur ", utf16sur
);
558 print_utf32(" utf32dest", utf32dest
);
562 * Test cupsCharmapFlush()...
565 printf("\ntesti18n: Testing cupsCharmapFlush()...\n");
572 * 'test_normalize()' - Test 'normalize.c' module.
575 static int /* O - Zero or error count */
576 test_normalize(const int verbose
) /* I - Verbose flag */
578 FILE *fp
; /* File pointer */
579 int count
; /* File line counter */
580 char line
[1024]; /* File line source string */
581 int len
; /* Length (count) of string */
582 int diff
; /* Difference of two strings */
583 int prop
; /* Property of a character */
584 int i
; /* Looping variable */
585 cups_utf32_t utf32char
; /* UTF-32 character */
586 cups_utf8_t utf8src
[1024]; /* UTF-8 source string */
587 cups_utf8_t utf8dest
[1024]; /* UTF-8 destination string */
588 cups_utf16_t utf16src
[] = /* UTF-16 non-normal source */
589 { 0x0149, 0x20, 0x21, 0x3D, 0x20, 0xC4, 0x2E, 0x00 };
590 /* "<SMALL N PRECEDED BY APOSTROPHE> != <A WITH DIAERESIS>." */
591 cups_utf16_t utf16dest
[1024]; /* UTF-16 destination string */
592 cups_utf32_t utf32dest
[1024]; /* UTF-32 destination string */
595 printf("\ntesti18n: Testing 'normalize.c'...\n");
598 * Test UTF-8 to NFKD/NFC/Properties on demo file...
602 printf("\ntesti18n: Testing UTF-8 source 'utf8demo.txt'...\n");
603 printf(" testing UTF-8 to NFKD...\n");
604 printf(" testing UTF-8 to NFC...\n");
605 printf(" testing UTF-8 to Character Properties...\n");
607 if ((fp
= fopen("utf8demo.txt", "r")) == NULL
)
611 if (fgets(line
, 1024, fp
) == NULL
)
614 len
= cupsUTF8Normalize(utf8dest
, (cups_utf8_t
*)line
, 1024, CUPS_NORM_NFKD
);
616 printf(" error line: %d (UTF-8 to NFKD)\n", count
);
617 len
= cupsUTF8Normalize(utf8dest
, (cups_utf8_t
*)line
, 1024, CUPS_NORM_NFC
);
619 printf(" error line: %d (UTF-8 to NFC)\n", count
);
620 len
= cupsUTF8ToUTF32(utf32dest
, (cups_utf8_t
*)line
, 1024);
623 printf(" error line: %d (UTF-8 to UTF-32)\n", count
);
626 for (i
= 0; i
< len
; i
++)
628 prop
= cupsUTF32CharacterProperty(utf32dest
[i
],
629 CUPS_PROP_GENERAL_CATEGORY
);
631 printf(" error line: %d (Prop - General Category)\n", count
);
632 prop
= cupsUTF32CharacterProperty(utf32dest
[i
],
633 CUPS_PROP_BIDI_CATEGORY
);
635 printf(" error line: %d (Prop - Bidi Category)\n", count
);
636 prop
= cupsUTF32CharacterProperty(utf32dest
[i
],
637 CUPS_PROP_COMBINING_CLASS
);
639 printf(" error line: %d (Prop - Combining Class)\n", count
);
640 prop
= cupsUTF32CharacterProperty(utf32dest
[i
],
641 CUPS_PROP_BREAK_CLASS
);
643 printf(" error line: %d (Prop - Break Class)\n", count
);
648 printf(" total lines: %d\n", count
);
651 * Test UTF-8 normalization NFKD...
654 printf("\ntesti18n: Testing UTF-8 normalization NFKD...\n");
655 len
= cupsUTF16ToUTF8(utf8dest
, utf16src
, 1024);
658 strcpy((char *) utf8src
, (char *) utf8dest
);
659 len
= cupsUTF8Normalize(utf8dest
, utf8src
, 1024, CUPS_NORM_NFKD
);
662 len
= cupsUTF8ToUTF16(utf16dest
, utf8dest
, 1024);
667 print_utf16(" utf16src ", utf16src
);
668 print_utf16(" utf16dest", utf16dest
);
672 * Test UTF-8 normalization NFD...
675 printf("\ntesti18n: Testing UTF-8 normalization NFD...\n");
676 len
= cupsUTF8Normalize(utf8dest
, utf8src
, 1024, CUPS_NORM_NFD
);
679 len
= cupsUTF8ToUTF16(utf16dest
, utf8dest
, 1024);
684 print_utf16(" utf16src ", utf16src
);
685 print_utf16(" utf16dest", utf16dest
);
689 * Test UTF-8 normalization NFC...
692 printf("\ntesti18n: Testing UTF-8 normalization NFC...\n");
693 len
= cupsUTF8Normalize(utf8dest
, utf8src
, 1024, CUPS_NORM_NFC
);
696 len
= cupsUTF8ToUTF16(utf16dest
, utf8dest
, 1024);
701 print_utf16(" utf16src ", utf16src
);
702 print_utf16(" utf16dest", utf16dest
);
706 * Test UTF-8 simple case folding...
709 printf("\ntesti18n: Testing UTF-8 simple case folding...\n");
710 len
= cupsUTF8CaseFold(utf8dest
, utf8src
, 1024, CUPS_FOLD_SIMPLE
);
713 len
= cupsUTF8ToUTF16(utf16dest
, utf8dest
, 1024);
718 print_utf16(" utf16src ", utf16src
);
719 print_utf16(" utf16dest", utf16dest
);
723 * Test UTF-8 full case folding...
726 printf("\ntesti18n: Testing UTF-8 full case folding...\n");
727 len
= cupsUTF8CaseFold(utf8dest
, utf8src
, 1024, CUPS_FOLD_FULL
);
730 len
= cupsUTF8ToUTF16(utf16dest
, utf8dest
, 1024);
735 print_utf16(" utf16src ", utf16src
);
736 print_utf16(" utf16dest", utf16dest
);
740 * Test UTF-8 caseless comparison...
743 printf("\ntesti18n: Testing UTF-8 caseless comparison..\n");
744 diff
= cupsUTF8CompareCaseless(utf8src
, utf8dest
);
746 printf(" diff: %d\n", diff
);
748 printf("\ntesti18n: Testing UTF-8 identifier comparison..\n");
749 diff
= cupsUTF8CompareIdentifier(utf8src
, utf8dest
);
751 printf(" diff: %d\n", diff
);
754 * Test UTF-32 character properties...
757 printf("\ntesti18n: Testing UTF-32 character properties..\n");
759 prop
= cupsUTF32CharacterProperty (utf32char
,
760 CUPS_PROP_GENERAL_CATEGORY
);
762 printf(" utf32char: %04lx general category %d\n", utf32char
, prop
);
764 prop
= cupsUTF32CharacterProperty (utf32char
,
765 CUPS_PROP_BIDI_CATEGORY
);
767 printf(" utf32char: %04lx bidi category %d\n", utf32char
, prop
);
769 prop
= cupsUTF32CharacterProperty (utf32char
,
770 CUPS_PROP_COMBINING_CLASS
);
772 printf(" utf32char: %04lx combining class %d\n", utf32char
, prop
);
774 prop
= cupsUTF32CharacterProperty (utf32char
,
775 CUPS_PROP_BREAK_CLASS
);
777 printf(" utf32char: %04lx break class %d\n", utf32char
, prop
);
780 * Test cupsNormalizeMapsFlush()...
783 printf("\ntesti18n: Testing cupsNormalizeMapsFlush()...\n");
784 cupsNormalizeMapsFlush();
790 * End of "$Id: testi18n.c 5195 2006-02-27 21:05:46Z mike $"