Bug 648271 - Add g_unicode_script_to_iso15924()
[platform/upstream/glib.git] / glib / tests / unicode.c
1 /* Unit tests for utilities
2  * Copyright (C) 2010 Red Hat, Inc.
3  * Copyright (C) 2011 Google, Inc.
4  *
5  * This work is provided "as is"; redistribution and modification
6  * in whole or in part, in any medium, physical or electronic is
7  * permitted without restriction.
8  *
9  * This work 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.
12  *
13  * In no event shall the authors or contributors be liable for any
14  * direct, indirect, incidental, special, exemplary, or consequential
15  * damages (including, but not limited to, procurement of substitute
16  * goods or services; loss of use, data, or profits; or business
17  * interruption) however caused and on any theory of liability, whether
18  * in contract, strict liability, or tort (including negligence or
19  * otherwise) arising in any way out of the use of this software, even
20  * if advised of the possibility of such damage.
21  *
22  * Author: Matthias Clasen, Behdad Esfahbod
23  */
24
25 #include "glib.h"
26
27 static void
28 test_unichar_validate (void)
29 {
30   g_assert (g_unichar_validate ('j'));
31   g_assert (g_unichar_validate (8356));
32   g_assert (g_unichar_validate (8356));
33   g_assert (!g_unichar_validate (0xfdd1));
34   g_assert (g_unichar_validate (917760));
35   g_assert (!g_unichar_validate (0x110000));
36 }
37
38 static void
39 test_unichar_character_type (void)
40 {
41   guint i;
42   struct {
43     GUnicodeType type;
44     gunichar     c;
45   } examples[] = {
46     { G_UNICODE_CONTROL,              0x000D },
47     { G_UNICODE_FORMAT,               0x200E },
48      /* G_UNICODE_UNASSIGNED */
49     { G_UNICODE_PRIVATE_USE,          0xE000 },
50     { G_UNICODE_SURROGATE,            0xD800 },
51     { G_UNICODE_LOWERCASE_LETTER,     0x0061 },
52     { G_UNICODE_MODIFIER_LETTER,      0x02B0 },
53     { G_UNICODE_OTHER_LETTER,         0x3400 },
54     { G_UNICODE_TITLECASE_LETTER,     0x01C5 },
55     { G_UNICODE_UPPERCASE_LETTER,     0xFF21 },
56     { G_UNICODE_COMBINING_MARK,       0x0903 },
57     { G_UNICODE_ENCLOSING_MARK,       0x20DD },
58     { G_UNICODE_NON_SPACING_MARK,     0xA806 },
59     { G_UNICODE_DECIMAL_NUMBER,       0xFF10 },
60     { G_UNICODE_LETTER_NUMBER,        0x16EE },
61     { G_UNICODE_OTHER_NUMBER,         0x17F0 },
62     { G_UNICODE_CONNECT_PUNCTUATION,  0x005F },
63     { G_UNICODE_DASH_PUNCTUATION,     0x058A },
64     { G_UNICODE_CLOSE_PUNCTUATION,    0x0F3B },
65     { G_UNICODE_FINAL_PUNCTUATION,    0x2019 },
66     { G_UNICODE_INITIAL_PUNCTUATION,  0x2018 },
67     { G_UNICODE_OTHER_PUNCTUATION,    0x2016 },
68     { G_UNICODE_OPEN_PUNCTUATION,     0x0F3A },
69     { G_UNICODE_CURRENCY_SYMBOL,      0x20A0 },
70     { G_UNICODE_MODIFIER_SYMBOL,      0x309B },
71     { G_UNICODE_MATH_SYMBOL,          0xFB29 },
72     { G_UNICODE_OTHER_SYMBOL,         0x00A6 },
73     { G_UNICODE_LINE_SEPARATOR,       0x2028 },
74     { G_UNICODE_PARAGRAPH_SEPARATOR,  0x2029 },
75     { G_UNICODE_SPACE_SEPARATOR,      0x202F },
76   };
77
78   for (i = 0; i < G_N_ELEMENTS (examples); i++)
79     {
80       g_assert (g_unichar_type (examples[i].c) == examples[i].type);
81     }
82 }
83
84 static void
85 test_unichar_break_type (void)
86 {
87   guint i;
88   struct {
89     GUnicodeBreakType type;
90     gunichar          c;
91   } examples[] = {
92     { G_UNICODE_BREAK_MANDATORY,           0x2028 },
93     { G_UNICODE_BREAK_CARRIAGE_RETURN,     0x000D },
94     { G_UNICODE_BREAK_LINE_FEED,           0x000A },
95     { G_UNICODE_BREAK_COMBINING_MARK,      0x0300 },
96     { G_UNICODE_BREAK_SURROGATE,           0xD800 },
97     { G_UNICODE_BREAK_ZERO_WIDTH_SPACE,    0x200B },
98     { G_UNICODE_BREAK_INSEPARABLE,         0x2024 },
99     { G_UNICODE_BREAK_NON_BREAKING_GLUE,   0x00A0 },
100     { G_UNICODE_BREAK_CONTINGENT,          0xFFFC },
101     { G_UNICODE_BREAK_SPACE,               0x0020 },
102     { G_UNICODE_BREAK_AFTER,               0x05BE },
103     { G_UNICODE_BREAK_BEFORE,              0x02C8 },
104     { G_UNICODE_BREAK_BEFORE_AND_AFTER,    0x2014 },
105     { G_UNICODE_BREAK_HYPHEN,              0x002D },
106     { G_UNICODE_BREAK_NON_STARTER,         0x17D6 },
107     { G_UNICODE_BREAK_OPEN_PUNCTUATION,    0x0028 },
108     { G_UNICODE_BREAK_CLOSE_PARANTHESIS,   0x0029 },
109     { G_UNICODE_BREAK_CLOSE_PUNCTUATION,   0x007D },
110     { G_UNICODE_BREAK_QUOTATION,           0x0022 },
111     { G_UNICODE_BREAK_EXCLAMATION,         0x0021 },
112     { G_UNICODE_BREAK_IDEOGRAPHIC,         0x2E80 },
113     { G_UNICODE_BREAK_NUMERIC,             0x0030 },
114     { G_UNICODE_BREAK_INFIX_SEPARATOR,     0x002C },
115     { G_UNICODE_BREAK_SYMBOL,              0x002F },
116     { G_UNICODE_BREAK_ALPHABETIC,          0x0023 },
117     { G_UNICODE_BREAK_PREFIX,              0x0024 },
118     { G_UNICODE_BREAK_POSTFIX,             0x0025 },
119     { G_UNICODE_BREAK_COMPLEX_CONTEXT,     0x0E01 },
120     { G_UNICODE_BREAK_AMBIGUOUS,           0x00F7 },
121     { G_UNICODE_BREAK_UNKNOWN,             0xE000 },
122     { G_UNICODE_BREAK_NEXT_LINE,           0x0085 },
123     { G_UNICODE_BREAK_WORD_JOINER,         0x2060 },
124     { G_UNICODE_BREAK_HANGUL_L_JAMO,       0x1100 },
125     { G_UNICODE_BREAK_HANGUL_V_JAMO,       0x1160 },
126     { G_UNICODE_BREAK_HANGUL_T_JAMO,       0x11A8 },
127     { G_UNICODE_BREAK_HANGUL_LV_SYLLABLE,  0xAC00 },
128     { G_UNICODE_BREAK_HANGUL_LVT_SYLLABLE, 0xAC01 }
129   };
130
131   for (i = 0; i < G_N_ELEMENTS (examples); i++)
132     {
133       g_assert (g_unichar_break_type (examples[i].c) == examples[i].type);
134     }
135 }
136
137 static void
138 test_unichar_script (void)
139 {
140   guint i;
141   struct {
142     GUnicodeScript script;
143     gunichar          c;
144   } examples[] = {
145     { G_UNICODE_SCRIPT_COMMON,                  0x002A },
146     { G_UNICODE_SCRIPT_INHERITED,               0x1CED },
147     { G_UNICODE_SCRIPT_INHERITED,               0x0670 },
148     { G_UNICODE_SCRIPT_ARABIC,                  0x060D },
149     { G_UNICODE_SCRIPT_ARMENIAN,                0x0559 },
150     { G_UNICODE_SCRIPT_BENGALI,                 0x09CD },
151     { G_UNICODE_SCRIPT_BOPOMOFO,                0x31B6 },
152     { G_UNICODE_SCRIPT_CHEROKEE,                0x13A2 },
153     { G_UNICODE_SCRIPT_COPTIC,                  0x2CFD },
154     { G_UNICODE_SCRIPT_CYRILLIC,                0x0482 },
155     { G_UNICODE_SCRIPT_DESERET,                0x10401 },
156     { G_UNICODE_SCRIPT_DEVANAGARI,              0x094D },
157     { G_UNICODE_SCRIPT_ETHIOPIC,                0x1258 },
158     { G_UNICODE_SCRIPT_GEORGIAN,                0x10FC },
159     { G_UNICODE_SCRIPT_GOTHIC,                 0x10341 },
160     { G_UNICODE_SCRIPT_GREEK,                   0x0375 },
161     { G_UNICODE_SCRIPT_GUJARATI,                0x0A83 },
162     { G_UNICODE_SCRIPT_GURMUKHI,                0x0A3C },
163     { G_UNICODE_SCRIPT_HAN,                     0x3005 },
164     { G_UNICODE_SCRIPT_HANGUL,                  0x1100 },
165     { G_UNICODE_SCRIPT_HEBREW,                  0x05BF },
166     { G_UNICODE_SCRIPT_HIRAGANA,                0x309F },
167     { G_UNICODE_SCRIPT_KANNADA,                 0x0CBC },
168     { G_UNICODE_SCRIPT_KATAKANA,                0x30FF },
169     { G_UNICODE_SCRIPT_KHMER,                   0x17DD },
170     { G_UNICODE_SCRIPT_LAO,                     0x0EDD },
171     { G_UNICODE_SCRIPT_LATIN,                   0x0061 },
172     { G_UNICODE_SCRIPT_MALAYALAM,               0x0D3D },
173     { G_UNICODE_SCRIPT_MONGOLIAN,               0x1843 },
174     { G_UNICODE_SCRIPT_MYANMAR,                 0x1031 },
175     { G_UNICODE_SCRIPT_OGHAM,                   0x169C },
176     { G_UNICODE_SCRIPT_OLD_ITALIC,             0x10322 },
177     { G_UNICODE_SCRIPT_ORIYA,                   0x0B3C },
178     { G_UNICODE_SCRIPT_RUNIC,                   0x16EF },
179     { G_UNICODE_SCRIPT_SINHALA,                 0x0DBD },
180     { G_UNICODE_SCRIPT_SYRIAC,                  0x0711 },
181     { G_UNICODE_SCRIPT_TAMIL,                   0x0B82 },
182     { G_UNICODE_SCRIPT_TELUGU,                  0x0C03 },
183     { G_UNICODE_SCRIPT_THAANA,                  0x07B1 },
184     { G_UNICODE_SCRIPT_THAI,                    0x0E31 },
185     { G_UNICODE_SCRIPT_TIBETAN,                 0x0FD4 },
186     { G_UNICODE_SCRIPT_CANADIAN_ABORIGINAL,     0x1400 },
187     { G_UNICODE_SCRIPT_CANADIAN_ABORIGINAL,     0x1401 },
188     { G_UNICODE_SCRIPT_YI,                      0xA015 },
189     { G_UNICODE_SCRIPT_TAGALOG,                 0x1700 },
190     { G_UNICODE_SCRIPT_HANUNOO,                 0x1720 },
191     { G_UNICODE_SCRIPT_BUHID,                   0x1740 },
192     { G_UNICODE_SCRIPT_TAGBANWA,                0x1760 },
193     { G_UNICODE_SCRIPT_BRAILLE,                 0x2800 },
194     { G_UNICODE_SCRIPT_CYPRIOT,                0x10808 },
195     { G_UNICODE_SCRIPT_LIMBU,                   0x1932 },
196     { G_UNICODE_SCRIPT_OSMANYA,                0x10480 },
197     { G_UNICODE_SCRIPT_SHAVIAN,                0x10450 },
198     { G_UNICODE_SCRIPT_LINEAR_B,               0x10000 },
199     { G_UNICODE_SCRIPT_TAI_LE,                  0x1950 },
200     { G_UNICODE_SCRIPT_UGARITIC,               0x1039F },
201     { G_UNICODE_SCRIPT_NEW_TAI_LUE,             0x1980 },
202     { G_UNICODE_SCRIPT_BUGINESE,                0x1A1F },
203     { G_UNICODE_SCRIPT_GLAGOLITIC,              0x2C00 },
204     { G_UNICODE_SCRIPT_TIFINAGH,                0x2D6F },
205     { G_UNICODE_SCRIPT_SYLOTI_NAGRI,            0xA800 },
206     { G_UNICODE_SCRIPT_OLD_PERSIAN,            0x103D0 },
207     { G_UNICODE_SCRIPT_KHAROSHTHI,             0x10A3F },
208     { G_UNICODE_SCRIPT_UNKNOWN,              0x1111111 },
209     { G_UNICODE_SCRIPT_BALINESE,                0x1B04 },
210     { G_UNICODE_SCRIPT_CUNEIFORM,              0x12000 },
211     { G_UNICODE_SCRIPT_PHOENICIAN,             0x10900 },
212     { G_UNICODE_SCRIPT_PHAGS_PA,                0xA840 },
213     { G_UNICODE_SCRIPT_NKO,                     0x07C0 },
214     { G_UNICODE_SCRIPT_KAYAH_LI,                0xA900 },
215     { G_UNICODE_SCRIPT_LEPCHA,                  0x1C00 },
216     { G_UNICODE_SCRIPT_REJANG,                  0xA930 },
217     { G_UNICODE_SCRIPT_SUNDANESE,               0x1B80 },
218     { G_UNICODE_SCRIPT_SAURASHTRA,              0xA880 },
219     { G_UNICODE_SCRIPT_CHAM,                    0xAA00 },
220     { G_UNICODE_SCRIPT_OL_CHIKI,                0x1C50 },
221     { G_UNICODE_SCRIPT_VAI,                     0xA500 },
222     { G_UNICODE_SCRIPT_CARIAN,                 0x102A0 },
223     { G_UNICODE_SCRIPT_LYCIAN,                 0x10280 },
224     { G_UNICODE_SCRIPT_LYDIAN,                 0x1093F },
225     { G_UNICODE_SCRIPT_AVESTAN,                0x10B00 },
226     { G_UNICODE_SCRIPT_BAMUM,                   0xA6A0 },
227     { G_UNICODE_SCRIPT_EGYPTIAN_HIEROGLYPHS,   0x13000 },
228     { G_UNICODE_SCRIPT_IMPERIAL_ARAMAIC,       0x10840 },
229     { G_UNICODE_SCRIPT_INSCRIPTIONAL_PAHLAVI,  0x10B60 },
230     { G_UNICODE_SCRIPT_INSCRIPTIONAL_PARTHIAN, 0x10B40 },
231     { G_UNICODE_SCRIPT_JAVANESE,                0xA980 },
232     { G_UNICODE_SCRIPT_KAITHI,                 0x11082 },
233     { G_UNICODE_SCRIPT_LISU,                    0xA4D0 },
234     { G_UNICODE_SCRIPT_MEETEI_MAYEK,            0xABE5 },
235     { G_UNICODE_SCRIPT_OLD_SOUTH_ARABIAN,      0x10A60 },
236     { G_UNICODE_SCRIPT_OLD_TURKIC,             0x10C00 },
237     { G_UNICODE_SCRIPT_SAMARITAN,               0x0800 },
238     { G_UNICODE_SCRIPT_TAI_THAM,                0x1A20 },
239     { G_UNICODE_SCRIPT_TAI_VIET,                0xAA80 },
240     { G_UNICODE_SCRIPT_BATAK,                   0x1BC0 },
241     { G_UNICODE_SCRIPT_BRAHMI,                 0x11000 },
242     { G_UNICODE_SCRIPT_MANDAIC,                 0x0840 }
243   };
244   for (i = 0; i < G_N_ELEMENTS (examples); i++)
245     {
246       g_assert (g_unichar_get_script (examples[i].c) == examples[i].script);
247     }
248 }
249
250 static void
251 test_combining_class (void)
252 {
253   guint i;
254   struct {
255     gint class;
256     gunichar          c;
257   } examples[] = {
258     {   0, 0x0020 },
259     {   1, 0x0334 },
260     {   7, 0x093C },
261     {   8, 0x3099 },
262     {   9, 0x094D },
263     {  10, 0x05B0 },
264     {  11, 0x05B1 },
265     {  12, 0x05B2 },
266     {  13, 0x05B3 },
267     {  14, 0x05B4 },
268     {  15, 0x05B5 },
269     {  16, 0x05B6 },
270     {  17, 0x05B7 },
271     {  18, 0x05B8 },
272     {  19, 0x05B9 },
273     {  20, 0x05BB },
274     {  21, 0x05BC },
275     {  22, 0x05BD },
276     {  23, 0x05BF },
277     {  24, 0x05C1 },
278     {  25, 0x05C2 },
279     {  26, 0xFB1E },
280     {  27, 0x064B },
281     {  28, 0x064C },
282     {  29, 0x064D },
283     /* ... */
284     { 228, 0x05AE },
285     { 230, 0x0300 },
286     { 232, 0x302C },
287     { 233, 0x0362 },
288     { 234, 0x0360 },
289     { 234, 0x1DCD },
290     { 240, 0x0345 }
291   };
292   for (i = 0; i < G_N_ELEMENTS (examples); i++)
293     {
294       g_assert (g_unichar_combining_class (examples[i].c) == examples[i].class);
295     }
296 }
297
298 static void
299 test_mirror (void)
300 {
301   gunichar mirror;
302
303   g_assert (g_unichar_get_mirror_char ('(', &mirror));
304   g_assert_cmpint (mirror, ==, ')');
305   g_assert (g_unichar_get_mirror_char (')', &mirror));
306   g_assert_cmpint (mirror, ==, '(');
307   g_assert (g_unichar_get_mirror_char ('{', &mirror));
308   g_assert_cmpint (mirror, ==, '}');
309   g_assert (g_unichar_get_mirror_char ('}', &mirror));
310   g_assert_cmpint (mirror, ==, '{');
311   g_assert (g_unichar_get_mirror_char (0x208D, &mirror));
312   g_assert_cmpint (mirror, ==, 0x208E);
313   g_assert (g_unichar_get_mirror_char (0x208E, &mirror));
314   g_assert_cmpint (mirror, ==, 0x208D);
315   g_assert (!g_unichar_get_mirror_char ('a', &mirror));
316 }
317
318 static void
319 test_mark (void)
320 {
321   g_assert (g_unichar_ismark (0x0903));
322   g_assert (g_unichar_ismark (0x20DD));
323   g_assert (g_unichar_ismark (0xA806));
324   g_assert (!g_unichar_ismark ('a'));
325 }
326
327 static void
328 test_title (void)
329 {
330   g_assert (g_unichar_istitle (0x01c5));
331   g_assert (g_unichar_istitle (0x1f88));
332   g_assert (g_unichar_istitle (0x1fcc));
333
334   g_assert (g_unichar_totitle (0x01c6) == 0x01c5);
335   g_assert (g_unichar_totitle (0x01c4) == 0x01c5);
336   g_assert (g_unichar_totitle (0x01c5) == 0x01c5);
337   g_assert (g_unichar_totitle (0x1f80) == 0x1f88);
338   g_assert (g_unichar_totitle (0x1f88) == 0x1f88);
339   g_assert (g_unichar_totitle ('a') == 'A');
340   g_assert (g_unichar_totitle ('A') == 'A');
341 }
342
343 static void
344 test_wide (void)
345 {
346   guint i;
347   struct {
348     gunichar c;
349     enum {
350       NOT_WIDE,
351       WIDE_CJK,
352       WIDE
353     } wide;
354   } examples[] = {
355     /* Neutral */
356     {   0x0000, NOT_WIDE },
357     {   0x0483, NOT_WIDE },
358     {   0x0641, NOT_WIDE },
359     {   0xFFFC, NOT_WIDE },
360     {  0x10000, NOT_WIDE },
361     {  0xE0001, NOT_WIDE },
362
363     /* Narrow */
364     {   0x0020, NOT_WIDE },
365     {   0x0041, NOT_WIDE },
366     {   0x27E6, NOT_WIDE },
367
368     /* Halfwidth */
369     {   0x20A9, NOT_WIDE },
370     {   0xFF61, NOT_WIDE },
371     {   0xFF69, NOT_WIDE },
372     {   0xFFEE, NOT_WIDE },
373
374     /* Ambiguous */
375     {   0x00A1, WIDE_CJK },
376     {   0x00BE, WIDE_CJK },
377     {   0x02DD, WIDE_CJK },
378     {   0x2020, WIDE_CJK },
379     {   0xFFFD, WIDE_CJK },
380     {   0x00A1, WIDE_CJK },
381     {  0x1F100, WIDE_CJK },
382     {  0xE0100, WIDE_CJK },
383     { 0x100000, WIDE_CJK },
384     { 0x10FFFD, WIDE_CJK },
385
386     /* Fullwidth */
387     {   0x3000, WIDE },
388     {   0xFF60, WIDE },
389
390     /* Wide */
391     {   0x2329, WIDE },
392     {   0x3001, WIDE },
393     {   0xFE69, WIDE },
394     {  0x30000, WIDE },
395     {  0x3FFFD, WIDE },
396
397     /* Default Wide blocks */
398     {   0x4DBF, WIDE },
399     {   0x9FFF, WIDE },
400     {   0xFAFF, WIDE },
401     {  0x2A6DF, WIDE },
402     {  0x2B73F, WIDE },
403     {  0x2B81F, WIDE },
404     {  0x2FA1F, WIDE },
405
406     /* Uniode-5.2 character additions */
407     /* Wide */
408     {   0x115F, WIDE },
409
410     /* Uniode-6.0 character additions */
411     /* Wide */
412     {  0x2B740, WIDE },
413     {  0x1B000, WIDE },
414
415     { 0x111111, NOT_WIDE }
416   };
417
418   for (i = 0; i < G_N_ELEMENTS (examples); i++)
419     {
420       g_assert (g_unichar_iswide (examples[i].c) == (examples[i].wide == WIDE));
421       g_assert (g_unichar_iswide_cjk (examples[i].c) == (examples[i].wide != NOT_WIDE));
422     }
423 };
424
425 static void
426 test_compose (void)
427 {
428   gunichar ch;
429
430   /* Not composable */
431   g_assert (!g_unichar_compose (0x0041, 0x0042, &ch) && ch == 0);
432   g_assert (!g_unichar_compose (0x0041, 0, &ch) && ch == 0);
433   g_assert (!g_unichar_compose (0x0066, 0x0069, &ch) && ch == 0);
434
435   /* Singletons should not compose */
436   g_assert (!g_unichar_compose (0x212B, 0, &ch) && ch == 0);
437   g_assert (!g_unichar_compose (0x00C5, 0, &ch) && ch == 0);
438   g_assert (!g_unichar_compose (0x2126, 0, &ch) && ch == 0);
439   g_assert (!g_unichar_compose (0x03A9, 0, &ch) && ch == 0);
440
441   /* Pairs */
442   g_assert (g_unichar_compose (0x0041, 0x030A, &ch) && ch == 0x00C5);
443   g_assert (g_unichar_compose (0x006F, 0x0302, &ch) && ch == 0x00F4);
444   g_assert (g_unichar_compose (0x1E63, 0x0307, &ch) && ch == 0x1E69);
445   g_assert (g_unichar_compose (0x0073, 0x0323, &ch) && ch == 0x1E63);
446   g_assert (g_unichar_compose (0x0064, 0x0307, &ch) && ch == 0x1E0B);
447   g_assert (g_unichar_compose (0x0064, 0x0323, &ch) && ch == 0x1E0D);
448
449   /* Hangul */
450   g_assert (g_unichar_compose (0xD4CC, 0x11B6, &ch) && ch == 0xD4DB);
451   g_assert (g_unichar_compose (0x1111, 0x1171, &ch) && ch == 0xD4CC);
452   g_assert (g_unichar_compose (0xCE20, 0x11B8, &ch) && ch == 0xCE31);
453   g_assert (g_unichar_compose (0x110E, 0x1173, &ch) && ch == 0xCE20);
454 }
455
456 static void
457 test_decompose (void)
458 {
459   gunichar a, b;
460
461   /* Not decomposable */
462   g_assert (!g_unichar_decompose (0x0041, &a, &b) && a == 0x0041 && b == 0);
463   g_assert (!g_unichar_decompose (0xFB01, &a, &b) && a == 0xFB01 && b == 0);
464
465   /* Singletons */
466   g_assert (g_unichar_decompose (0x212B, &a, &b) && a == 0x00C5 && b == 0);
467   g_assert (g_unichar_decompose (0x2126, &a, &b) && a == 0x03A9 && b == 0);
468
469   /* Pairs */
470   g_assert (g_unichar_decompose (0x00C5, &a, &b) && a == 0x0041 && b == 0x030A);
471   g_assert (g_unichar_decompose (0x00F4, &a, &b) && a == 0x006F && b == 0x0302);
472   g_assert (g_unichar_decompose (0x1E69, &a, &b) && a == 0x1E63 && b == 0x0307);
473   g_assert (g_unichar_decompose (0x1E63, &a, &b) && a == 0x0073 && b == 0x0323);
474   g_assert (g_unichar_decompose (0x1E0B, &a, &b) && a == 0x0064 && b == 0x0307);
475   g_assert (g_unichar_decompose (0x1E0D, &a, &b) && a == 0x0064 && b == 0x0323);
476
477   /* Hangul */
478   g_assert (g_unichar_decompose (0xD4DB, &a, &b) && a == 0xD4CC && b == 0x11B6);
479   g_assert (g_unichar_decompose (0xD4CC, &a, &b) && a == 0x1111 && b == 0x1171);
480   g_assert (g_unichar_decompose (0xCE31, &a, &b) && a == 0xCE20 && b == 0x11B8);
481   g_assert (g_unichar_decompose (0xCE20, &a, &b) && a == 0x110E && b == 0x1173);
482 }
483
484 static void
485 test_fully_decompose_canonical (void)
486 {
487   gunichar decomp[5];
488   gsize len;
489
490 #define TEST_DECOMP(ch, expected_len, a, b, c, d) \
491   len = g_unichar_fully_decompose (ch, FALSE, decomp, G_N_ELEMENTS (decomp)); \
492   g_assert_cmpint (expected_len, ==, len); \
493   if (expected_len >= 1) g_assert_cmphex (decomp[0], ==, a); \
494   if (expected_len >= 2) g_assert_cmphex (decomp[1], ==, b); \
495   if (expected_len >= 3) g_assert_cmphex (decomp[2], ==, c); \
496   if (expected_len >= 4) g_assert_cmphex (decomp[3], ==, d); \
497
498 #define TEST0(ch)               TEST_DECOMP (ch, 1, ch, 0, 0, 0)
499 #define TEST1(ch, a)            TEST_DECOMP (ch, 1, a, 0, 0, 0)
500 #define TEST2(ch, a, b)         TEST_DECOMP (ch, 2, a, b, 0, 0)
501 #define TEST3(ch, a, b, c)      TEST_DECOMP (ch, 3, a, b, c, 0)
502 #define TEST4(ch, a, b, c, d)   TEST_DECOMP (ch, 4, a, b, c, d)
503
504   /* Not decomposable */
505   TEST0 (0x0041);
506   TEST0 (0xFB01);
507
508   /* Singletons */
509   TEST2 (0x212B, 0x0041, 0x030A);
510   TEST1 (0x2126, 0x03A9);
511
512   /* General */
513   TEST2 (0x00C5, 0x0041, 0x030A);
514   TEST2 (0x00F4, 0x006F, 0x0302);
515   TEST3 (0x1E69, 0x0073, 0x0323, 0x0307);
516   TEST2 (0x1E63, 0x0073, 0x0323);
517   TEST2 (0x1E0B, 0x0064, 0x0307);
518   TEST2 (0x1E0D, 0x0064, 0x0323);
519
520   /* Hangul */
521   TEST3 (0xD4DB, 0x1111, 0x1171, 0x11B6);
522   TEST2 (0xD4CC, 0x1111, 0x1171);
523   TEST3 (0xCE31, 0x110E, 0x1173, 0x11B8);
524   TEST2 (0xCE20, 0x110E, 0x1173);
525
526 #undef TEST_DECOMP
527 }
528
529 static void
530 test_canonical_decomposition (void)
531 {
532   gunichar *decomp;
533   gsize len;
534
535 #define TEST_DECOMP(ch, expected_len, a, b, c, d) \
536   decomp = g_unicode_canonical_decomposition (ch, &len); \
537   g_assert_cmpint (expected_len, ==, len); \
538   if (expected_len >= 1) g_assert_cmphex (decomp[0], ==, a); \
539   if (expected_len >= 2) g_assert_cmphex (decomp[1], ==, b); \
540   if (expected_len >= 3) g_assert_cmphex (decomp[2], ==, c); \
541   if (expected_len >= 4) g_assert_cmphex (decomp[3], ==, d); \
542   g_free (decomp);
543
544 #define TEST0(ch)               TEST_DECOMP (ch, 1, ch, 0, 0, 0)
545 #define TEST1(ch, a)            TEST_DECOMP (ch, 1, a, 0, 0, 0)
546 #define TEST2(ch, a, b)         TEST_DECOMP (ch, 2, a, b, 0, 0)
547 #define TEST3(ch, a, b, c)      TEST_DECOMP (ch, 3, a, b, c, 0)
548 #define TEST4(ch, a, b, c, d)   TEST_DECOMP (ch, 4, a, b, c, d)
549
550   /* Not decomposable */
551   TEST0 (0x0041);
552   TEST0 (0xFB01);
553
554   /* Singletons */
555   TEST2 (0x212B, 0x0041, 0x030A);
556   TEST1 (0x2126, 0x03A9);
557
558   /* General */
559   TEST2 (0x00C5, 0x0041, 0x030A);
560   TEST2 (0x00F4, 0x006F, 0x0302);
561   TEST3 (0x1E69, 0x0073, 0x0323, 0x0307);
562   TEST2 (0x1E63, 0x0073, 0x0323);
563   TEST2 (0x1E0B, 0x0064, 0x0307);
564   TEST2 (0x1E0D, 0x0064, 0x0323);
565
566   /* Hangul */
567   TEST3 (0xD4DB, 0x1111, 0x1171, 0x11B6);
568   TEST2 (0xD4CC, 0x1111, 0x1171);
569   TEST3 (0xCE31, 0x110E, 0x1173, 0x11B8);
570   TEST2 (0xCE20, 0x110E, 0x1173);
571
572 #undef TEST_DECOMP
573 }
574
575 static void
576 test_decompose_tail (void)
577 {
578   gunichar ch, a, b, c, d;
579
580   /* Test that whenever a char ch decomposes into a and b, b itself
581    * won't decompose any further. */
582
583   for (ch = 0; ch < 0x110000; ch++)
584     if (g_unichar_decompose (ch, &a, &b))
585       g_assert (!g_unichar_decompose (b, &c, &d));
586     else
587       g_assert (a == ch && b == 0);
588 }
589
590 static void
591 test_fully_decompose_len (void)
592 {
593   gunichar ch;
594
595   /* Test that all canonical decompositions are at most 4 in length,
596    * and compatibility decompositions are at most 18 in length.
597    */
598
599   for (ch = 0; ch < 0x110000; ch++) {
600     g_assert_cmpint (g_unichar_fully_decompose (ch, FALSE, NULL, 0), <=, 4);
601     g_assert_cmpint (g_unichar_fully_decompose (ch, TRUE,  NULL, 0), <=, 18);
602   }
603 }
604
605 static void
606 test_script_to_iso15924 (void)
607 {
608   g_assert_cmphex (0, ==, g_unicode_script_to_iso15924 (G_UNICODE_SCRIPT_INVALID_CODE));
609   g_assert_cmphex (0x41726162, ==, g_unicode_script_to_iso15924 (G_UNICODE_SCRIPT_ARABIC));
610 }
611
612 int
613 main (int   argc,
614       char *argv[])
615 {
616   g_test_init (&argc, &argv, NULL);
617
618   g_test_add_func ("/unicode/validate", test_unichar_validate);
619   g_test_add_func ("/unicode/character-type", test_unichar_character_type);
620   g_test_add_func ("/unicode/break-type", test_unichar_break_type);
621   g_test_add_func ("/unicode/script", test_unichar_script);
622   g_test_add_func ("/unicode/combining-class", test_combining_class);
623   g_test_add_func ("/unicode/mirror", test_mirror);
624   g_test_add_func ("/unicode/mark", test_mark);
625   g_test_add_func ("/unicode/title", test_title);
626   g_test_add_func ("/unicode/wide", test_wide);
627   g_test_add_func ("/unicode/compose", test_compose);
628   g_test_add_func ("/unicode/decompose", test_decompose);
629   g_test_add_func ("/unicode/fully-decompose-canonical", test_fully_decompose_canonical);
630   g_test_add_func ("/unicode/canonical-decomposition", test_canonical_decomposition);
631   g_test_add_func ("/unicode/decompose-tail", test_decompose_tail);
632   g_test_add_func ("/unicode/fully-decompose-len", test_fully_decompose_len);
633   g_test_add_func ("/unicode/script-to-iso15924", test_script_to_iso15924);
634
635   return g_test_run();
636 }