Parse tables conforming to draft-hoffman-idn-reg.
[libidn.git] / tests / tst_punycode.c
blob974e1bfbb21d6fa058718e84c8d03aecb00fd2f1
1 /* tst_punycode.c Self tests for punycode.
2 * Copyright (C) 2002, 2003 Simon Josefsson
4 * This file is part of GNU Libidn.
6 * GNU Libidn is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
11 * GNU Libidn is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with GNU Libidn; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
22 #if HAVE_CONFIG_H
23 # include "config.h"
24 #endif
26 #include <stdio.h>
27 #include <stdlib.h>
28 #include <stdarg.h>
29 #include <string.h>
31 #include <punycode.h>
33 static int debug = 0;
34 static int error_count = 0;
35 static int break_on_error = 0;
37 static void
38 fail (const char *format, ...)
40 va_list arg_ptr;
42 va_start (arg_ptr, format);
43 vfprintf (stderr, format, arg_ptr);
44 va_end (arg_ptr);
45 error_count++;
46 if (break_on_error)
47 exit (1);
50 static void
51 ucs4print (const uint32_t * str, size_t len)
53 size_t i;
55 printf ("\t;; ");
56 for (i = 0; i < len; i++)
58 printf ("U+%04ux ", str[i]);
59 if ((i + 1) % 4 == 0)
60 printf (" ");
61 if ((i + 1) % 8 == 0 && i + 1 < len)
62 printf ("\n\t;; ");
64 puts ("");
67 struct punycode
69 char *name;
70 size_t inlen;
71 uint32_t in[100];
72 char *out;
73 int rc;
76 const struct punycode punycode[] = {
78 "(A) Arabic (Egyptian)", 17,
80 0x0644, 0x064A, 0x0647, 0x0645, 0x0627, 0x0628, 0x062A, 0x0643,
81 0x0644, 0x0645, 0x0648, 0x0634, 0x0639, 0x0631, 0x0628, 0x064A,
82 0x061F}, "egbpdaj6bu4bxfgehfvwxn", PUNYCODE_SUCCESS},
84 "(B) Chinese (simplified)", 9,
86 0x4ED6, 0x4EEC, 0x4E3A, 0x4EC0, 0x4E48, 0x4E0D, 0x8BF4, 0x4E2D,
87 0x6587}, "ihqwcrb4cv8a8dqg056pqjye", PUNYCODE_SUCCESS},
89 "(C) Chinese (traditional)", 9,
91 0x4ED6, 0x5011, 0x7232, 0x4EC0, 0x9EBD, 0x4E0D, 0x8AAA, 0x4E2D,
92 0x6587}, "ihqwctvzc91f659drss3x8bo0yb", PUNYCODE_SUCCESS},
94 "(D) Czech: Pro<ccaron>prost<ecaron>nemluv<iacute><ccaron>esky", 22,
96 0x0050, 0x0072, 0x006F, 0x010D, 0x0070, 0x0072, 0x006F, 0x0073,
97 0x0074, 0x011B, 0x006E, 0x0065, 0x006D, 0x006C, 0x0075, 0x0076,
98 0x00ED, 0x010D, 0x0065, 0x0073, 0x006B, 0x0079},
99 "Proprostnemluvesky-uyb24dma41a", PUNYCODE_SUCCESS},
101 "(E) Hebrew:", 22,
103 0x05DC, 0x05DE, 0x05D4, 0x05D4, 0x05DD, 0x05E4, 0x05E9, 0x05D5,
104 0x05D8, 0x05DC, 0x05D0, 0x05DE, 0x05D3, 0x05D1, 0x05E8, 0x05D9,
105 0x05DD, 0x05E2, 0x05D1, 0x05E8, 0x05D9, 0x05EA},
106 "4dbcagdahymbxekheh6e0a7fei0b", PUNYCODE_SUCCESS},
108 "(F) Hindi (Devanagari):", 30,
110 0x092F, 0x0939, 0x0932, 0x094B, 0x0917, 0x0939, 0x093F, 0x0928,
111 0x094D, 0x0926, 0x0940, 0x0915, 0x094D, 0x092F, 0x094B, 0x0902,
112 0x0928, 0x0939, 0x0940, 0x0902, 0x092C, 0x094B, 0x0932, 0x0938,
113 0x0915, 0x0924, 0x0947, 0x0939, 0x0948, 0x0902},
114 "i1baa7eci9glrd9b2ae1bj0hfcgg6iyaf8o0a1dig0cd", PUNYCODE_SUCCESS},
116 "(G) Japanese (kanji and hiragana):", 18,
118 0x306A, 0x305C, 0x307F, 0x3093, 0x306A, 0x65E5, 0x672C, 0x8A9E,
119 0x3092, 0x8A71, 0x3057, 0x3066, 0x304F, 0x308C, 0x306A, 0x3044,
120 0x306E, 0x304B},
121 "n8jok5ay5dzabd5bym9f0cm5685rrjetr6pdxa", PUNYCODE_SUCCESS},
123 "(H) Korean (Hangul syllables):", 24,
125 0xC138, 0xACC4, 0xC758, 0xBAA8, 0xB4E0, 0xC0AC, 0xB78C, 0xB4E4,
126 0xC774, 0xD55C, 0xAD6D, 0xC5B4, 0xB97C, 0xC774, 0xD574, 0xD55C,
127 0xB2E4, 0xBA74, 0xC5BC, 0xB9C8, 0xB098, 0xC88B, 0xC744, 0xAE4C},
128 "989aomsvi5e83db1d2a355cv1e0vak1dwrv93d5xbh15a0dt30a5jpsd879ccm6fea98c",
129 PUNYCODE_SUCCESS},
131 "(I) Russian (Cyrillic):", 28,
133 0x043F, 0x043E, 0x0447, 0x0435, 0x043C, 0x0443, 0x0436, 0x0435,
134 0x043E, 0x043D, 0x0438, 0x043D, 0x0435, 0x0433, 0x043E, 0x0432,
135 0x043E, 0x0440, 0x044F, 0x0442, 0x043F, 0x043E, 0x0440, 0x0443,
136 0x0441, 0x0441, 0x043A, 0x0438},
137 "b1abfaaepdrnnbgefbadotcwatmq2g4l", PUNYCODE_SUCCESS},
139 "(J) Spanish: Porqu<eacute>nopuedensimplementehablarenEspa<ntilde>ol", 40,
141 0x0050, 0x006F, 0x0072, 0x0071, 0x0075, 0x00E9, 0x006E, 0x006F,
142 0x0070, 0x0075, 0x0065, 0x0064, 0x0065, 0x006E, 0x0073, 0x0069,
143 0x006D, 0x0070, 0x006C, 0x0065, 0x006D, 0x0065, 0x006E, 0x0074,
144 0x0065, 0x0068, 0x0061, 0x0062, 0x006C, 0x0061, 0x0072, 0x0065,
145 0x006E, 0x0045, 0x0073, 0x0070, 0x0061, 0x00F1, 0x006F, 0x006C},
146 "PorqunopuedensimplementehablarenEspaol-fmd56a", PUNYCODE_SUCCESS},
148 "(K) Vietnamese:", 31,
150 0x0054, 0x1EA1, 0x0069, 0x0073, 0x0061, 0x006F, 0x0068, 0x1ECD,
151 0x006B, 0x0068, 0x00F4, 0x006E, 0x0067, 0x0074, 0x0068, 0x1EC3,
152 0x0063, 0x0068, 0x1EC9, 0x006E, 0x00F3, 0x0069, 0x0074, 0x0069,
153 0x1EBF, 0x006E, 0x0067, 0x0056, 0x0069, 0x1EC7, 0x0074},
154 "TisaohkhngthchnitingVit-kjcr8268qyxafd2f1b9g", PUNYCODE_SUCCESS},
156 "(L) 3<nen>B<gumi><kinpachi><sensei>", 8,
158 0x0033, 0x5E74, 0x0042, 0x7D44, 0x91D1, 0x516B, 0x5148, 0x751F},
159 "3B-ww4c5e180e575a65lsy2b", PUNYCODE_SUCCESS},
161 "(M) <amuro><namie>-with-SUPER-MONKEYS", 24,
163 0x5B89, 0x5BA4, 0x5948, 0x7F8E, 0x6075, 0x002D, 0x0077, 0x0069,
164 0x0074, 0x0068, 0x002D, 0x0053, 0x0055, 0x0050, 0x0045, 0x0052,
165 0x002D, 0x004D, 0x004F, 0x004E, 0x004B, 0x0045, 0x0059, 0x0053},
166 "-with-SUPER-MONKEYS-pc58ag80a8qai00g7n9n", PUNYCODE_SUCCESS},
168 "(N) Hello-Another-Way-<sorezore><no><basho>", 25,
170 0x0048, 0x0065, 0x006C, 0x006C, 0x006F, 0x002D, 0x0041, 0x006E,
171 0x006F, 0x0074, 0x0068, 0x0065, 0x0072, 0x002D, 0x0057, 0x0061,
172 0x0079, 0x002D, 0x305D, 0x308C, 0x305E, 0x308C, 0x306E, 0x5834,
173 0x6240},
174 "Hello-Another-Way--fc4qua05auwb3674vfr0b", PUNYCODE_SUCCESS},
176 "(O) <hitotsu><yane><no><shita>2", 8,
178 0x3072, 0x3068, 0x3064, 0x5C4B, 0x6839, 0x306E, 0x4E0B, 0x0032},
179 "2-u9tlzr9756bt3uc0v", PUNYCODE_SUCCESS},
181 "(P) Maji<de>Koi<suru>5<byou><mae>", 13,
183 0x004D, 0x0061, 0x006A, 0x0069, 0x3067, 0x004B, 0x006F, 0x0069,
184 0x3059, 0x308B, 0x0035, 0x79D2, 0x524D},
185 "MajiKoi5-783gue6qz075azm5e", PUNYCODE_SUCCESS},
187 "(Q) <pafii>de<runba>", 9,
189 0x30D1, 0x30D5, 0x30A3, 0x30FC, 0x0064, 0x0065, 0x30EB, 0x30F3, 0x30D0},
190 "de-jg4avhby1noc0d", PUNYCODE_SUCCESS},
192 "(R) <sono><supiido><de>", 7,
194 0x305D, 0x306E, 0x30B9, 0x30D4, 0x30FC, 0x30C9, 0x3067},
195 "d9juau41awczczp", PUNYCODE_SUCCESS},
197 "(S) -> $1.00 <-", 11,
199 0x002D, 0x003E, 0x0020, 0x0024, 0x0031, 0x002E, 0x0030, 0x0030,
200 0x0020, 0x003C, 0x002D}, "-> $1.00 <--", PUNYCODE_SUCCESS}
204 main (int argc, char *argv[])
206 char *p;
207 uint32_t *q;
208 int rc;
209 size_t i, outlen;
212 if (strcmp (argv[argc - 1], "-v") == 0 ||
213 strcmp (argv[argc - 1], "--verbose") == 0)
214 debug = 1;
215 else if (strcmp (argv[argc - 1], "-b") == 0 ||
216 strcmp (argv[argc - 1], "--break-on-error") == 0)
217 break_on_error = 1;
218 else if (strcmp (argv[argc - 1], "-h") == 0 ||
219 strcmp (argv[argc - 1], "-?") == 0 ||
220 strcmp (argv[argc - 1], "--help") == 0)
222 printf ("Usage: %s [-vbh?] [--verbose] [--break-on-error] [--help]\n",
223 argv[0]);
224 return 1;
226 while (argc-- > 1);
228 p = malloc (sizeof (*p) * BUFSIZ);
229 if (p == NULL)
230 fail ("malloc() returned NULL\n");
232 q = malloc (sizeof (*q) * BUFSIZ);
233 if (q == NULL)
234 fail ("malloc() returned NULL\n");
236 for (i = 0; i < sizeof (punycode) / sizeof (punycode[0]); i++)
238 if (debug)
239 printf ("PUNYCODE entry %d: %s\n", i, punycode[i].name);
241 if (debug)
243 printf ("in:\n");
244 ucs4print (punycode[i].in, punycode[i].inlen);
247 outlen = BUFSIZ;
248 rc = punycode_encode (punycode[i].inlen, punycode[i].in,
249 NULL, &outlen, p);
250 if (rc != punycode[i].rc)
252 fail ("punycode_encode() entry %d failed: %d\n", i, rc);
253 if (debug)
254 printf ("FATAL\n");
255 continue;
258 if (rc == PUNYCODE_SUCCESS)
259 p[outlen] = '\0';
261 if (debug && rc == PUNYCODE_SUCCESS)
263 printf ("computed out: %s\n", p);
264 printf ("expected out: %s\n", punycode[i].out);
266 else if (debug)
267 printf ("returned %d expected %d\n", rc, punycode[i].rc);
269 if (rc == PUNYCODE_SUCCESS)
271 if (strlen (punycode[i].out) != strlen (p) ||
272 memcmp (punycode[i].out, p, strlen (p)) != 0)
274 fail ("punycode() entry %d failed\n", i);
275 if (debug)
276 printf ("ERROR\n");
278 else if (debug)
279 printf ("OK\n\n");
281 else if (debug)
282 printf ("OK\n\n");
284 if (debug)
286 printf ("in: %s\n", punycode[i].out);
289 outlen = BUFSIZ;
290 rc = punycode_decode (strlen (punycode[i].out), punycode[i].out,
291 &outlen, q, NULL);
292 if (rc != punycode[i].rc)
294 fail ("punycode() entry %d failed: %d\n", i, rc);
295 if (debug)
296 printf ("FATAL\n");
297 continue;
300 if (debug && rc == PUNYCODE_SUCCESS)
302 printf ("computed out:\n");
303 ucs4print (q, outlen);
304 printf ("expected out:\n");
305 ucs4print (punycode[i].in, punycode[i].inlen);
307 else if (debug)
308 printf ("returned %d expected %d\n", rc, punycode[i].rc);
310 if (rc == PUNYCODE_SUCCESS)
312 if (punycode[i].inlen != outlen ||
313 memcmp (punycode[i].in, q, outlen) != 0)
315 fail ("punycode_decode() entry %d failed\n", i);
316 if (debug)
317 printf ("ERROR\n");
319 else if (debug)
320 printf ("OK\n\n");
322 else if (debug)
323 printf ("OK\n\n");
326 free (q);
327 free (p);
329 if (debug)
330 printf ("Punycode self tests done with %d errors\n", error_count);
332 return error_count ? 1 : 0;