Add.
[libidn.git] / tst_punycode.c
blob97d6d33d959d5d2a571c0e029fd821c06361ac06
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 #include "internal.h"
24 static int debug = 0;
25 static int error_count = 0;
26 static int break_on_error = 0;
28 static void
29 fail (const char *format, ...)
31 va_list arg_ptr;
33 va_start (arg_ptr, format);
34 vfprintf (stderr, format, arg_ptr);
35 va_end (arg_ptr);
36 error_count++;
37 if (break_on_error)
38 exit (1);
41 static void
42 ucs4print (uint32_t *str, ssize_t len)
44 int i;
46 printf ("\t;; ");
47 for (i = 0; len >= 0 ? i < len : str[i]; i++)
49 printf ("U+%04lux ", str[i]);
50 if ((i + 1) % 4 == 0)
51 printf (" ");
52 if ((i + 1) % 8 == 0 && i + 1 < len)
53 printf ("\n\t;; ");
55 puts ("");
58 struct punycode
60 char *name;
61 size_t inlen;
62 uint32_t in[100];
63 char *out;
64 int rc;
65 } punycode[] =
68 "(A) Arabic (Egyptian)", 17,
70 0x0644, 0x064A, 0x0647, 0x0645, 0x0627, 0x0628, 0x062A, 0x0643,
71 0x0644, 0x0645, 0x0648, 0x0634, 0x0639, 0x0631, 0x0628, 0x064A,
72 0x061F}, "egbpdaj6bu4bxfgehfvwxn", PUNYCODE_SUCCESS},
74 "(B) Chinese (simplified)", 9,
76 0x4ED6, 0x4EEC, 0x4E3A, 0x4EC0, 0x4E48, 0x4E0D, 0x8BF4, 0x4E2D,
77 0x6587}, "ihqwcrb4cv8a8dqg056pqjye", PUNYCODE_SUCCESS},
79 "(C) Chinese (traditional)", 9,
81 0x4ED6, 0x5011, 0x7232, 0x4EC0, 0x9EBD, 0x4E0D, 0x8AAA, 0x4E2D,
82 0x6587}, "ihqwctvzc91f659drss3x8bo0yb", PUNYCODE_SUCCESS},
84 "(D) Czech: Pro<ccaron>prost<ecaron>nemluv<iacute><ccaron>esky", 22,
86 0x0050, 0x0072, 0x006F, 0x010D, 0x0070, 0x0072, 0x006F, 0x0073,
87 0x0074, 0x011B, 0x006E, 0x0065, 0x006D, 0x006C, 0x0075, 0x0076,
88 0x00ED, 0x010D, 0x0065, 0x0073, 0x006B, 0x0079},
89 "Proprostnemluvesky-uyb24dma41a", PUNYCODE_SUCCESS},
91 "(E) Hebrew:", 22,
93 0x05DC, 0x05DE, 0x05D4, 0x05D4, 0x05DD, 0x05E4, 0x05E9, 0x05D5,
94 0x05D8, 0x05DC, 0x05D0, 0x05DE, 0x05D3, 0x05D1, 0x05E8, 0x05D9,
95 0x05DD, 0x05E2, 0x05D1, 0x05E8, 0x05D9, 0x05EA},
96 "4dbcagdahymbxekheh6e0a7fei0b", PUNYCODE_SUCCESS},
98 "(F) Hindi (Devanagari):", 30,
100 0x092F, 0x0939, 0x0932, 0x094B, 0x0917, 0x0939, 0x093F, 0x0928,
101 0x094D, 0x0926, 0x0940, 0x0915, 0x094D, 0x092F, 0x094B, 0x0902,
102 0x0928, 0x0939, 0x0940, 0x0902, 0x092C, 0x094B, 0x0932, 0x0938,
103 0x0915, 0x0924, 0x0947, 0x0939, 0x0948, 0x0902},
104 "i1baa7eci9glrd9b2ae1bj0hfcgg6iyaf8o0a1dig0cd", PUNYCODE_SUCCESS},
106 "(G) Japanese (kanji and hiragana):", 18,
108 0x306A, 0x305C, 0x307F, 0x3093, 0x306A, 0x65E5, 0x672C, 0x8A9E,
109 0x3092, 0x8A71, 0x3057, 0x3066, 0x304F, 0x308C, 0x306A, 0x3044,
110 0x306E, 0x304B},
111 "n8jok5ay5dzabd5bym9f0cm5685rrjetr6pdxa", PUNYCODE_SUCCESS},
113 "(H) Korean (Hangul syllables):", 24,
115 0xC138, 0xACC4, 0xC758, 0xBAA8, 0xB4E0, 0xC0AC, 0xB78C, 0xB4E4,
116 0xC774, 0xD55C, 0xAD6D, 0xC5B4, 0xB97C, 0xC774, 0xD574, 0xD55C,
117 0xB2E4, 0xBA74, 0xC5BC, 0xB9C8, 0xB098, 0xC88B, 0xC744, 0xAE4C},
118 "989aomsvi5e83db1d2a355cv1e0vak1dwrv93d5xbh15a0dt30a5jpsd879ccm6fea98c",
119 PUNYCODE_SUCCESS},
121 "(I) Russian (Cyrillic):", 28,
123 0x043F, 0x043E, 0x0447, 0x0435, 0x043C, 0x0443, 0x0436, 0x0435,
124 0x043E, 0x043D, 0x0438, 0x043D, 0x0435, 0x0433, 0x043E, 0x0432,
125 0x043E, 0x0440, 0x044F, 0x0442, 0x043F, 0x043E, 0x0440, 0x0443,
126 0x0441, 0x0441, 0x043A, 0x0438},
127 "b1abfaaepdrnnbgefbadotcwatmq2g4l", PUNYCODE_SUCCESS},
129 "(J) Spanish: Porqu<eacute>nopuedensimplementehablarenEspa<ntilde>ol", 40,
131 0x0050, 0x006F, 0x0072, 0x0071, 0x0075, 0x00E9, 0x006E, 0x006F,
132 0x0070, 0x0075, 0x0065, 0x0064, 0x0065, 0x006E, 0x0073, 0x0069,
133 0x006D, 0x0070, 0x006C, 0x0065, 0x006D, 0x0065, 0x006E, 0x0074,
134 0x0065, 0x0068, 0x0061, 0x0062, 0x006C, 0x0061, 0x0072, 0x0065,
135 0x006E, 0x0045, 0x0073, 0x0070, 0x0061, 0x00F1, 0x006F, 0x006C},
136 "PorqunopuedensimplementehablarenEspaol-fmd56a", PUNYCODE_SUCCESS},
138 "(K) Vietnamese:", 31,
140 0x0054, 0x1EA1, 0x0069, 0x0073, 0x0061, 0x006F, 0x0068, 0x1ECD,
141 0x006B, 0x0068, 0x00F4, 0x006E, 0x0067, 0x0074, 0x0068, 0x1EC3,
142 0x0063, 0x0068, 0x1EC9, 0x006E, 0x00F3, 0x0069, 0x0074, 0x0069,
143 0x1EBF, 0x006E, 0x0067, 0x0056, 0x0069, 0x1EC7, 0x0074},
144 "TisaohkhngthchnitingVit-kjcr8268qyxafd2f1b9g", PUNYCODE_SUCCESS},
146 "(L) 3<nen>B<gumi><kinpachi><sensei>", 8,
148 0x0033, 0x5E74, 0x0042, 0x7D44, 0x91D1, 0x516B, 0x5148, 0x751F},
149 "3B-ww4c5e180e575a65lsy2b", PUNYCODE_SUCCESS},
151 "(M) <amuro><namie>-with-SUPER-MONKEYS", 24,
153 0x5B89, 0x5BA4, 0x5948, 0x7F8E, 0x6075, 0x002D, 0x0077, 0x0069,
154 0x0074, 0x0068, 0x002D, 0x0053, 0x0055, 0x0050, 0x0045, 0x0052,
155 0x002D, 0x004D, 0x004F, 0x004E, 0x004B, 0x0045, 0x0059, 0x0053},
156 "-with-SUPER-MONKEYS-pc58ag80a8qai00g7n9n", PUNYCODE_SUCCESS},
158 "(N) Hello-Another-Way-<sorezore><no><basho>", 25,
160 0x0048, 0x0065, 0x006C, 0x006C, 0x006F, 0x002D, 0x0041, 0x006E,
161 0x006F, 0x0074, 0x0068, 0x0065, 0x0072, 0x002D, 0x0057, 0x0061,
162 0x0079, 0x002D, 0x305D, 0x308C, 0x305E, 0x308C, 0x306E, 0x5834,
163 0x6240},
164 "Hello-Another-Way--fc4qua05auwb3674vfr0b", PUNYCODE_SUCCESS},
166 "(O) <hitotsu><yane><no><shita>2", 8,
168 0x3072, 0x3068, 0x3064, 0x5C4B, 0x6839, 0x306E, 0x4E0B, 0x0032},
169 "2-u9tlzr9756bt3uc0v", PUNYCODE_SUCCESS},
171 "(P) Maji<de>Koi<suru>5<byou><mae>", 13,
173 0x004D, 0x0061, 0x006A, 0x0069, 0x3067, 0x004B, 0x006F, 0x0069,
174 0x3059, 0x308B, 0x0035, 0x79D2, 0x524D},
175 "MajiKoi5-783gue6qz075azm5e", PUNYCODE_SUCCESS},
177 "(Q) <pafii>de<runba>", 9,
179 0x30D1, 0x30D5, 0x30A3, 0x30FC, 0x0064, 0x0065, 0x30EB, 0x30F3, 0x30D0},
180 "de-jg4avhby1noc0d", PUNYCODE_SUCCESS},
182 "(R) <sono><supiido><de>", 7,
184 0x305D, 0x306E, 0x30B9, 0x30D4, 0x30FC, 0x30C9, 0x3067},
185 "d9juau41awczczp", PUNYCODE_SUCCESS},
187 "(S) -> $1.00 <-", 11,
189 0x002D, 0x003E, 0x0020, 0x0024, 0x0031, 0x002E, 0x0030, 0x0030,
190 0x0020, 0x003C, 0x002D}, "-> $1.00 <--", PUNYCODE_SUCCESS}
194 main (int argc, char *argv[])
196 char *p;
197 uint32_t *q;
198 int rc;
199 size_t i, outlen;
202 if (strcmp (argv[argc - 1], "-v") == 0 ||
203 strcmp (argv[argc - 1], "--verbose") == 0)
204 debug = 1;
205 else if (strcmp (argv[argc - 1], "-b") == 0 ||
206 strcmp (argv[argc - 1], "--break-on-error") == 0)
207 break_on_error = 1;
208 else if (strcmp (argv[argc - 1], "-h") == 0 ||
209 strcmp (argv[argc - 1], "-?") == 0 ||
210 strcmp (argv[argc - 1], "--help") == 0)
212 printf ("Usage: %s [-vbh?] [--verbose] [--break-on-error] [--help]\n",
213 argv[0]);
214 return 1;
216 while (argc-- > 1);
218 p = malloc (sizeof (*p) * BUFSIZ);
219 if (p == NULL)
220 fail ("malloc() returned NULL\n");
222 q = malloc (sizeof (*q) * BUFSIZ);
223 if (q == NULL)
224 fail ("malloc() returned NULL\n");
226 for (i = 0; i < sizeof (punycode) / sizeof (punycode[0]); i++)
228 if (debug)
229 printf ("PUNYCODE entry %d: %s\n", i, punycode[i].name);
231 if (debug)
233 printf ("in:\n");
234 ucs4print (punycode[i].in, punycode[i].inlen);
237 outlen = BUFSIZ;
238 rc = punycode_encode (punycode[i].inlen, punycode[i].in,
239 NULL, &outlen, p);
240 if (rc != punycode[i].rc)
242 fail ("punycode_encode() entry %d failed: %d\n", i, rc);
243 if (debug)
244 printf ("FATAL\n");
245 continue;
248 if (rc == PUNYCODE_SUCCESS)
249 p[outlen] = '\0';
251 if (debug && rc == PUNYCODE_SUCCESS)
253 printf ("computed out: %s\n", p);
254 printf ("expected out: %s\n", punycode[i].out);
256 else if (debug)
257 printf ("returned %d expected %d\n", rc, punycode[i].rc);
259 if (rc == PUNYCODE_SUCCESS)
261 if (strlen (punycode[i].out) != strlen (p) ||
262 memcmp (punycode[i].out, p, strlen (p)) != 0)
264 fail ("punycode() entry %d failed\n", i);
265 if (debug)
266 printf ("ERROR\n");
268 else if (debug)
269 printf ("OK\n\n");
271 else if (debug)
272 printf ("OK\n\n");
274 if (debug)
276 printf ("in: %s\n", punycode[i].out);
279 outlen = BUFSIZ;
280 rc = punycode_decode (strlen (punycode[i].out), punycode[i].out,
281 &outlen, q, NULL);
282 if (rc != punycode[i].rc)
284 fail ("punycode() entry %d failed: %d\n", i, rc);
285 if (debug)
286 printf ("FATAL\n");
287 continue;
290 if (debug && rc == PUNYCODE_SUCCESS)
292 printf ("computed out:\n");
293 ucs4print (q, outlen);
294 printf ("expected out:\n");
295 ucs4print (punycode[i].in, punycode[i].inlen);
297 else if (debug)
298 printf ("returned %d expected %d\n", rc, punycode[i].rc);
300 if (rc == PUNYCODE_SUCCESS)
302 if (punycode[i].inlen != outlen ||
303 memcmp (punycode[i].in, q, outlen) != 0)
305 fail ("punycode_decode() entry %d failed\n", i);
306 if (debug)
307 printf ("ERROR\n");
309 else if (debug)
310 printf ("OK\n\n");
312 else if (debug)
313 printf ("OK\n\n");
316 free (q);
317 free (p);
319 if (debug)
320 printf ("Punycode self tests done with %d errors\n", error_count);
322 return error_count ? 1 : 0;