Home | History | Annotate | Download | only in cintltst
      1 /********************************************************************
      2  * COPYRIGHT:
      3  * Copyright (c) 1997-2010, International Business Machines Corporation and
      4  * others. All Rights Reserved.
      5  ********************************************************************/
      6 /********************************************************************************
      7 *
      8 * File CNORMTST.C
      9 *
     10 * Modification History:
     11 *        Name                     Description
     12 *     Madhu Katragadda            Ported for C API
     13 *     synwee                      added test for quick check
     14 *     synwee                      added test for checkFCD
     15 *********************************************************************************/
     16 /*tests for u_normalization*/
     17 #include "unicode/utypes.h"
     18 #include "unicode/unorm.h"
     19 #include "cintltst.h"
     20 
     21 #if UCONFIG_NO_NORMALIZATION
     22 
     23 void addNormTest(TestNode** root) {
     24     /* no normalization - nothing to do */
     25 }
     26 
     27 #else
     28 
     29 #include <stdlib.h>
     30 #include <time.h>
     31 #include "unicode/uchar.h"
     32 #include "unicode/ustring.h"
     33 #include "unicode/unorm.h"
     34 #include "cnormtst.h"
     35 
     36 #define LENGTHOF(array) (int32_t)(sizeof(array)/sizeof ((array)[0]))
     37 
     38 static void
     39 TestAPI(void);
     40 
     41 static void
     42 TestNormCoverage(void);
     43 
     44 static void
     45 TestConcatenate(void);
     46 
     47 static void
     48 TestNextPrevious(void);
     49 
     50 static void TestIsNormalized(void);
     51 
     52 static void
     53 TestFCNFKCClosure(void);
     54 
     55 static void
     56 TestQuickCheckPerCP(void);
     57 
     58 static void
     59 TestComposition(void);
     60 
     61 const static char* canonTests[][3] = {
     62     /* Input*/                    /*Decomposed*/                /*Composed*/
     63     { "cat",                    "cat",                        "cat"                    },
     64     { "\\u00e0ardvark",            "a\\u0300ardvark",            "\\u00e0ardvark",        },
     65 
     66     { "\\u1e0a",                "D\\u0307",                    "\\u1e0a"                }, /* D-dot_above*/
     67     { "D\\u0307",                "D\\u0307",                    "\\u1e0a"                }, /* D dot_above*/
     68 
     69     { "\\u1e0c\\u0307",            "D\\u0323\\u0307",            "\\u1e0c\\u0307"        }, /* D-dot_below dot_above*/
     70     { "\\u1e0a\\u0323",            "D\\u0323\\u0307",            "\\u1e0c\\u0307"        }, /* D-dot_above dot_below */
     71     { "D\\u0307\\u0323",        "D\\u0323\\u0307",            "\\u1e0c\\u0307"        }, /* D dot_below dot_above */
     72 
     73     { "\\u1e10\\u0307\\u0323",    "D\\u0327\\u0323\\u0307",    "\\u1e10\\u0323\\u0307"    }, /*D dot_below cedilla dot_above*/
     74     { "D\\u0307\\u0328\\u0323",    "D\\u0328\\u0323\\u0307",    "\\u1e0c\\u0328\\u0307"    }, /* D dot_above ogonek dot_below*/
     75 
     76     { "\\u1E14",                "E\\u0304\\u0300",            "\\u1E14"                }, /* E-macron-grave*/
     77     { "\\u0112\\u0300",            "E\\u0304\\u0300",            "\\u1E14"                }, /* E-macron + grave*/
     78     { "\\u00c8\\u0304",            "E\\u0300\\u0304",            "\\u00c8\\u0304"        }, /* E-grave + macron*/
     79 
     80     { "\\u212b",                "A\\u030a",                    "\\u00c5"                }, /* angstrom_sign*/
     81     { "\\u00c5",                "A\\u030a",                    "\\u00c5"                }, /* A-ring*/
     82 
     83     { "\\u00C4ffin",            "A\\u0308ffin",                "\\u00C4ffin"                    },
     84     { "\\u00C4\\uFB03n",        "A\\u0308\\uFB03n",            "\\u00C4\\uFB03n"                },
     85 
     86     { "Henry IV",                "Henry IV",                    "Henry IV"                },
     87     { "Henry \\u2163",            "Henry \\u2163",            "Henry \\u2163"            },
     88 
     89     { "\\u30AC",                "\\u30AB\\u3099",            "\\u30AC"                }, /* ga (Katakana)*/
     90     { "\\u30AB\\u3099",            "\\u30AB\\u3099",            "\\u30AC"                }, /*ka + ten*/
     91     { "\\uFF76\\uFF9E",            "\\uFF76\\uFF9E",            "\\uFF76\\uFF9E"        }, /* hw_ka + hw_ten*/
     92     { "\\u30AB\\uFF9E",            "\\u30AB\\uFF9E",            "\\u30AB\\uFF9E"        }, /* ka + hw_ten*/
     93     { "\\uFF76\\u3099",            "\\uFF76\\u3099",            "\\uFF76\\u3099"        },  /* hw_ka + ten*/
     94     { "A\\u0300\\u0316",           "A\\u0316\\u0300",           "\\u00C0\\u0316"        }  /* hw_ka + ten*/
     95 };
     96 
     97 const static char* compatTests[][3] = {
     98     /* Input*/                        /*Decomposed    */                /*Composed*/
     99     { "cat",                        "cat",                            "cat"                },
    100 
    101     { "\\uFB4f",                    "\\u05D0\\u05DC",                "\\u05D0\\u05DC"    }, /* Alef-Lamed vs. Alef, Lamed*/
    102 
    103     { "\\u00C4ffin",                "A\\u0308ffin",                    "\\u00C4ffin"             },
    104     { "\\u00C4\\uFB03n",            "A\\u0308ffin",                    "\\u00C4ffin"                }, /* ffi ligature -> f + f + i*/
    105 
    106     { "Henry IV",                    "Henry IV",                        "Henry IV"            },
    107     { "Henry \\u2163",                "Henry IV",                        "Henry IV"            },
    108 
    109     { "\\u30AC",                    "\\u30AB\\u3099",                "\\u30AC"            }, /* ga (Katakana)*/
    110     { "\\u30AB\\u3099",                "\\u30AB\\u3099",                "\\u30AC"            }, /*ka + ten*/
    111 
    112     { "\\uFF76\\u3099",                "\\u30AB\\u3099",                "\\u30AC"            }, /* hw_ka + ten*/
    113 
    114     /*These two are broken in Unicode 2.1.2 but fixed in 2.1.5 and later*/
    115     { "\\uFF76\\uFF9E",                "\\u30AB\\u3099",                "\\u30AC"            }, /* hw_ka + hw_ten*/
    116     { "\\u30AB\\uFF9E",                "\\u30AB\\u3099",                "\\u30AC"            } /* ka + hw_ten*/
    117 
    118 };
    119 
    120 void addNormTest(TestNode** root);
    121 
    122 void addNormTest(TestNode** root)
    123 {
    124     addTest(root, &TestAPI, "tsnorm/cnormtst/TestAPI");
    125     addTest(root, &TestDecomp, "tsnorm/cnormtst/TestDecomp");
    126     addTest(root, &TestCompatDecomp, "tsnorm/cnormtst/TestCompatDecomp");
    127     addTest(root, &TestCanonDecompCompose, "tsnorm/cnormtst/TestCanonDecompCompose");
    128     addTest(root, &TestCompatDecompCompose, "tsnorm/cnormtst/CompatDecompCompose");
    129     addTest(root, &TestNull, "tsnorm/cnormtst/TestNull");
    130     addTest(root, &TestQuickCheck, "tsnorm/cnormtst/TestQuickCheck");
    131     addTest(root, &TestQuickCheckPerCP, "tsnorm/cnormtst/TestQuickCheckPerCP");
    132     addTest(root, &TestIsNormalized, "tsnorm/cnormtst/TestIsNormalized");
    133     addTest(root, &TestCheckFCD, "tsnorm/cnormtst/TestCheckFCD");
    134     addTest(root, &TestNormCoverage, "tsnorm/cnormtst/TestNormCoverage");
    135     addTest(root, &TestConcatenate, "tsnorm/cnormtst/TestConcatenate");
    136     addTest(root, &TestNextPrevious, "tsnorm/cnormtst/TestNextPrevious");
    137     addTest(root, &TestFCNFKCClosure, "tsnorm/cnormtst/TestFCNFKCClosure");
    138     addTest(root, &TestComposition, "tsnorm/cnormtst/TestComposition");
    139 }
    140 
    141 void TestDecomp()
    142 {
    143     UErrorCode status = U_ZERO_ERROR;
    144     int32_t x, neededLen, resLen;
    145     UChar *source=NULL, *result=NULL;
    146     status = U_ZERO_ERROR;
    147     resLen=0;
    148     log_verbose("Testing unorm_normalize with  Decomp canonical\n");
    149     for(x=0; x < LENGTHOF(canonTests); x++)
    150     {
    151         source=CharsToUChars(canonTests[x][0]);
    152         neededLen= unorm_normalize(source, u_strlen(source), UNORM_NFD, 0, NULL, 0, &status);
    153         if(status==U_BUFFER_OVERFLOW_ERROR)
    154         {
    155             status=U_ZERO_ERROR;
    156             resLen=neededLen+1;
    157             result=(UChar*)malloc(sizeof(UChar*) * resLen);
    158             unorm_normalize(source, u_strlen(source), UNORM_NFD, 0, result, resLen, &status);
    159         }
    160         if(U_FAILURE(status)){
    161             log_data_err("ERROR in unorm_normalize at %s:  %s - (Are you missing data?)\n", austrdup(source), myErrorName(status) );
    162         } else {
    163           assertEqual(result, canonTests[x][1], x);
    164         }
    165         free(result);
    166         free(source);
    167     }
    168 }
    169 
    170 void TestCompatDecomp()
    171 {
    172     UErrorCode status = U_ZERO_ERROR;
    173     int32_t x, neededLen, resLen;
    174     UChar *source=NULL, *result=NULL;
    175     status = U_ZERO_ERROR;
    176     resLen=0;
    177     log_verbose("Testing unorm_normalize with  Decomp compat\n");
    178     for(x=0; x < LENGTHOF(compatTests); x++)
    179     {
    180         source=CharsToUChars(compatTests[x][0]);
    181         neededLen= unorm_normalize(source, u_strlen(source), UNORM_NFKD, 0, NULL, 0, &status);
    182         if(status==U_BUFFER_OVERFLOW_ERROR)
    183         {
    184             status=U_ZERO_ERROR;
    185             resLen=neededLen+1;
    186             result=(UChar*)malloc(sizeof(UChar*) * resLen);
    187             unorm_normalize(source, u_strlen(source), UNORM_NFKD, 0, result, resLen, &status);
    188         }
    189         if(U_FAILURE(status)){
    190             log_data_err("ERROR in unorm_normalize at %s:  %s - (Are you missing data?)\n", austrdup(source), myErrorName(status) );
    191         } else {
    192           assertEqual(result, compatTests[x][1], x);
    193         }
    194         free(result);
    195         free(source);
    196     }
    197 }
    198 
    199 void TestCanonDecompCompose()
    200 {
    201     UErrorCode status = U_ZERO_ERROR;
    202     int32_t x, neededLen, resLen;
    203     UChar *source=NULL, *result=NULL;
    204     status = U_ZERO_ERROR;
    205     resLen=0;
    206     log_verbose("Testing unorm_normalize with Decomp can compose compat\n");
    207     for(x=0; x < LENGTHOF(canonTests); x++)
    208     {
    209         source=CharsToUChars(canonTests[x][0]);
    210         neededLen= unorm_normalize(source, u_strlen(source), UNORM_NFC, 0, NULL, 0, &status);
    211         if(status==U_BUFFER_OVERFLOW_ERROR)
    212         {
    213             status=U_ZERO_ERROR;
    214             resLen=neededLen+1;
    215             result=(UChar*)malloc(sizeof(UChar*) * resLen);
    216             unorm_normalize(source, u_strlen(source), UNORM_NFC, 0, result, resLen, &status);
    217         }
    218         if(U_FAILURE(status)){
    219             log_data_err("ERROR in unorm_normalize at %s:  %s - (Are you missing data?)\n", austrdup(source),myErrorName(status) );
    220         } else {
    221           assertEqual(result, canonTests[x][2], x);
    222         }
    223         free(result);
    224         free(source);
    225     }
    226 }
    227 
    228 void TestCompatDecompCompose()
    229 {
    230     UErrorCode status = U_ZERO_ERROR;
    231     int32_t x, neededLen, resLen;
    232     UChar *source=NULL, *result=NULL;
    233     status = U_ZERO_ERROR;
    234     resLen=0;
    235     log_verbose("Testing unorm_normalize with compat decomp compose can\n");
    236     for(x=0; x < LENGTHOF(compatTests); x++)
    237     {
    238         source=CharsToUChars(compatTests[x][0]);
    239         neededLen= unorm_normalize(source, u_strlen(source), UNORM_NFKC, 0, NULL, 0, &status);
    240         if(status==U_BUFFER_OVERFLOW_ERROR)
    241         {
    242             status=U_ZERO_ERROR;
    243             resLen=neededLen+1;
    244             result=(UChar*)malloc(sizeof(UChar*) * resLen);
    245             unorm_normalize(source, u_strlen(source), UNORM_NFKC, 0, result, resLen, &status);
    246         }
    247         if(U_FAILURE(status)){
    248             log_data_err("ERROR in unorm_normalize at %s:  %s - (Are you missing data?)\n", austrdup(source), myErrorName(status) );
    249         } else {
    250           assertEqual(result, compatTests[x][2], x);
    251         }
    252         free(result);
    253         free(source);
    254     }
    255 }
    256 
    257 
    258 /*
    259 static void assertEqual(const UChar* result, const UChar* expected, int32_t index)
    260 {
    261     if(u_strcmp(result, expected)!=0){
    262         log_err("ERROR in decomposition at index = %d. EXPECTED: %s , GOT: %s\n", index, austrdup(expected),
    263             austrdup(result) );
    264     }
    265 }
    266 */
    267 
    268 static void assertEqual(const UChar* result, const char* expected, int32_t index)
    269 {
    270     UChar *expectedUni = CharsToUChars(expected);
    271     if(u_strcmp(result, expectedUni)!=0){
    272         log_err("ERROR in decomposition at index = %d. EXPECTED: %s , GOT: %s\n", index, expected,
    273             austrdup(result) );
    274     }
    275     free(expectedUni);
    276 }
    277 
    278 static void TestNull_check(UChar *src, int32_t srcLen,
    279                     UChar *exp, int32_t expLen,
    280                     UNormalizationMode mode,
    281                     const char *name)
    282 {
    283     UErrorCode status = U_ZERO_ERROR;
    284     int32_t len, i;
    285 
    286     UChar   result[50];
    287 
    288 
    289     status = U_ZERO_ERROR;
    290 
    291     for(i=0;i<50;i++)
    292       {
    293         result[i] = 0xFFFD;
    294       }
    295 
    296     len = unorm_normalize(src, srcLen, mode, 0, result, 50, &status);
    297 
    298     if(U_FAILURE(status)) {
    299       log_data_err("unorm_normalize(%s) with 0x0000 failed: %s - (Are you missing data?)\n", name, u_errorName(status));
    300     } else if (len != expLen) {
    301       log_err("unorm_normalize(%s) with 0x0000 failed: Expected len %d, got %d\n", name, expLen, len);
    302     }
    303 
    304     {
    305       for(i=0;i<len;i++){
    306         if(exp[i] != result[i]) {
    307           log_err("unorm_normalize(%s): @%d, expected \\u%04X got \\u%04X\n",
    308                   name,
    309                   i,
    310                   exp[i],
    311                   result[i]);
    312           return;
    313         }
    314         log_verbose("     %d: \\u%04X\n", i, result[i]);
    315       }
    316     }
    317 
    318     log_verbose("unorm_normalize(%s) with 0x0000: OK\n", name);
    319 }
    320 
    321 void TestNull()
    322 {
    323 
    324     UChar   source_comp[] = { 0x0061, 0x0000, 0x0044, 0x0307 };
    325     int32_t source_comp_len = 4;
    326     UChar   expect_comp[] = { 0x0061, 0x0000, 0x1e0a };
    327     int32_t expect_comp_len = 3;
    328 
    329     UChar   source_dcmp[] = { 0x1e0A, 0x0000, 0x0929 };
    330     int32_t source_dcmp_len = 3;
    331     UChar   expect_dcmp[] = { 0x0044, 0x0307, 0x0000, 0x0928, 0x093C };
    332     int32_t expect_dcmp_len = 5;
    333 
    334     TestNull_check(source_comp,
    335                    source_comp_len,
    336                    expect_comp,
    337                    expect_comp_len,
    338                    UNORM_NFC,
    339                    "UNORM_NFC");
    340 
    341     TestNull_check(source_dcmp,
    342                    source_dcmp_len,
    343                    expect_dcmp,
    344                    expect_dcmp_len,
    345                    UNORM_NFD,
    346                    "UNORM_NFD");
    347 
    348     TestNull_check(source_comp,
    349                    source_comp_len,
    350                    expect_comp,
    351                    expect_comp_len,
    352                    UNORM_NFKC,
    353                    "UNORM_NFKC");
    354 
    355 
    356 }
    357 
    358 static void TestQuickCheckResultNO()
    359 {
    360   const UChar CPNFD[] = {0x00C5, 0x0407, 0x1E00, 0x1F57, 0x220C,
    361                          0x30AE, 0xAC00, 0xD7A3, 0xFB36, 0xFB4E};
    362   const UChar CPNFC[] = {0x0340, 0x0F93, 0x1F77, 0x1FBB, 0x1FEB,
    363                           0x2000, 0x232A, 0xF900, 0xFA1E, 0xFB4E};
    364   const UChar CPNFKD[] = {0x00A0, 0x02E4, 0x1FDB, 0x24EA, 0x32FE,
    365                            0xAC00, 0xFB4E, 0xFA10, 0xFF3F, 0xFA2D};
    366   const UChar CPNFKC[] = {0x00A0, 0x017F, 0x2000, 0x24EA, 0x32FE,
    367                            0x33FE, 0xFB4E, 0xFA10, 0xFF3F, 0xFA2D};
    368 
    369 
    370   const int SIZE = 10;
    371 
    372   int count = 0;
    373   UErrorCode error = U_ZERO_ERROR;
    374 
    375   for (; count < SIZE; count ++)
    376   {
    377     if (unorm_quickCheck(&(CPNFD[count]), 1, UNORM_NFD, &error) !=
    378                                                               UNORM_NO)
    379     {
    380       log_err("ERROR in NFD quick check at U+%04x\n", CPNFD[count]);
    381       return;
    382     }
    383     if (unorm_quickCheck(&(CPNFC[count]), 1, UNORM_NFC, &error) !=
    384                                                               UNORM_NO)
    385     {
    386       log_err("ERROR in NFC quick check at U+%04x\n", CPNFC[count]);
    387       return;
    388     }
    389     if (unorm_quickCheck(&(CPNFKD[count]), 1, UNORM_NFKD, &error) !=
    390                                                               UNORM_NO)
    391     {
    392       log_err("ERROR in NFKD quick check at U+%04x\n", CPNFKD[count]);
    393       return;
    394     }
    395     if (unorm_quickCheck(&(CPNFKC[count]), 1, UNORM_NFKC, &error) !=
    396                                                               UNORM_NO)
    397     {
    398       log_err("ERROR in NFKC quick check at U+%04x\n", CPNFKC[count]);
    399       return;
    400     }
    401   }
    402 }
    403 
    404 
    405 static void TestQuickCheckResultYES()
    406 {
    407   const UChar CPNFD[] = {0x00C6, 0x017F, 0x0F74, 0x1000, 0x1E9A,
    408                          0x2261, 0x3075, 0x4000, 0x5000, 0xF000};
    409   const UChar CPNFC[] = {0x0400, 0x0540, 0x0901, 0x1000, 0x1500,
    410                          0x1E9A, 0x3000, 0x4000, 0x5000, 0xF000};
    411   const UChar CPNFKD[] = {0x00AB, 0x02A0, 0x1000, 0x1027, 0x2FFB,
    412                           0x3FFF, 0x4FFF, 0xA000, 0xF000, 0xFA27};
    413   const UChar CPNFKC[] = {0x00B0, 0x0100, 0x0200, 0x0A02, 0x1000,
    414                           0x2010, 0x3030, 0x4000, 0xA000, 0xFA0E};
    415 
    416   const int SIZE = 10;
    417   int count = 0;
    418   UErrorCode error = U_ZERO_ERROR;
    419 
    420   UChar cp = 0;
    421   while (cp < 0xA0)
    422   {
    423     if (unorm_quickCheck(&cp, 1, UNORM_NFD, &error) != UNORM_YES)
    424     {
    425       log_data_err("ERROR in NFD quick check at U+%04x - (Are you missing data?)\n", cp);
    426       return;
    427     }
    428     if (unorm_quickCheck(&cp, 1, UNORM_NFC, &error) !=
    429                                                              UNORM_YES)
    430     {
    431       log_err("ERROR in NFC quick check at U+%04x\n", cp);
    432       return;
    433     }
    434     if (unorm_quickCheck(&cp, 1, UNORM_NFKD, &error) != UNORM_YES)
    435     {
    436       log_err("ERROR in NFKD quick check at U+%04x\n", cp);
    437       return;
    438     }
    439     if (unorm_quickCheck(&cp, 1, UNORM_NFKC, &error) !=
    440                                                              UNORM_YES)
    441     {
    442       log_err("ERROR in NFKC quick check at U+%04x\n", cp);
    443       return;
    444     }
    445     cp ++;
    446   }
    447 
    448   for (; count < SIZE; count ++)
    449   {
    450     if (unorm_quickCheck(&(CPNFD[count]), 1, UNORM_NFD, &error) !=
    451                                                              UNORM_YES)
    452     {
    453       log_err("ERROR in NFD quick check at U+%04x\n", CPNFD[count]);
    454       return;
    455     }
    456     if (unorm_quickCheck(&(CPNFC[count]), 1, UNORM_NFC, &error)
    457                                                           != UNORM_YES)
    458     {
    459       log_err("ERROR in NFC quick check at U+%04x\n", CPNFC[count]);
    460       return;
    461     }
    462     if (unorm_quickCheck(&(CPNFKD[count]), 1, UNORM_NFKD, &error) !=
    463                                                              UNORM_YES)
    464     {
    465       log_err("ERROR in NFKD quick check at U+%04x\n", CPNFKD[count]);
    466       return;
    467     }
    468     if (unorm_quickCheck(&(CPNFKC[count]), 1, UNORM_NFKC, &error) !=
    469                                                              UNORM_YES)
    470     {
    471       log_err("ERROR in NFKC quick check at U+%04x\n", CPNFKC[count]);
    472       return;
    473     }
    474   }
    475 }
    476 
    477 static void TestQuickCheckResultMAYBE()
    478 {
    479   const UChar CPNFC[] = {0x0306, 0x0654, 0x0BBE, 0x102E, 0x1161,
    480                          0x116A, 0x1173, 0x1175, 0x3099, 0x309A};
    481   const UChar CPNFKC[] = {0x0300, 0x0654, 0x0655, 0x09D7, 0x0B3E,
    482                           0x0DCF, 0xDDF, 0x102E, 0x11A8, 0x3099};
    483 
    484 
    485   const int SIZE = 10;
    486 
    487   int count = 0;
    488   UErrorCode error = U_ZERO_ERROR;
    489 
    490   /* NFD and NFKD does not have any MAYBE codepoints */
    491   for (; count < SIZE; count ++)
    492   {
    493     if (unorm_quickCheck(&(CPNFC[count]), 1, UNORM_NFC, &error) !=
    494                                                            UNORM_MAYBE)
    495     {
    496       log_data_err("ERROR in NFC quick check at U+%04x - (Are you missing data?)\n", CPNFC[count]);
    497       return;
    498     }
    499     if (unorm_quickCheck(&(CPNFKC[count]), 1, UNORM_NFKC, &error) !=
    500                                                            UNORM_MAYBE)
    501     {
    502       log_err("ERROR in NFKC quick check at U+%04x\n", CPNFKC[count]);
    503       return;
    504     }
    505   }
    506 }
    507 
    508 static void TestQuickCheckStringResult()
    509 {
    510   int count;
    511   UChar *d = NULL;
    512   UChar *c = NULL;
    513   UErrorCode error = U_ZERO_ERROR;
    514 
    515   for (count = 0; count < LENGTHOF(canonTests); count ++)
    516   {
    517     d = CharsToUChars(canonTests[count][1]);
    518     c = CharsToUChars(canonTests[count][2]);
    519     if (unorm_quickCheck(d, u_strlen(d), UNORM_NFD, &error) !=
    520                                                             UNORM_YES)
    521     {
    522       log_data_err("ERROR in NFD quick check for string at count %d - (Are you missing data?)\n", count);
    523       return;
    524     }
    525 
    526     if (unorm_quickCheck(c, u_strlen(c), UNORM_NFC, &error) ==
    527                                                             UNORM_NO)
    528     {
    529       log_err("ERROR in NFC quick check for string at count %d\n", count);
    530       return;
    531     }
    532 
    533     free(d);
    534     free(c);
    535   }
    536 
    537   for (count = 0; count < LENGTHOF(compatTests); count ++)
    538   {
    539     d = CharsToUChars(compatTests[count][1]);
    540     c = CharsToUChars(compatTests[count][2]);
    541     if (unorm_quickCheck(d, u_strlen(d), UNORM_NFKD, &error) !=
    542                                                             UNORM_YES)
    543     {
    544       log_err("ERROR in NFKD quick check for string at count %d\n", count);
    545       return;
    546     }
    547 
    548     if (unorm_quickCheck(c, u_strlen(c), UNORM_NFKC, &error) !=
    549                                                             UNORM_YES)
    550     {
    551       log_err("ERROR in NFKC quick check for string at count %d\n", count);
    552       return;
    553     }
    554 
    555     free(d);
    556     free(c);
    557   }
    558 }
    559 
    560 void TestQuickCheck()
    561 {
    562   TestQuickCheckResultNO();
    563   TestQuickCheckResultYES();
    564   TestQuickCheckResultMAYBE();
    565   TestQuickCheckStringResult();
    566 }
    567 
    568 /*
    569  * The intltest/NormalizerConformanceTest tests a lot of strings that _are_
    570  * normalized, and some that are not.
    571  * Here we pick some specific cases and test the C API.
    572  */
    573 static void TestIsNormalized(void) {
    574     static const UChar notNFC[][8]={            /* strings that are not in NFC */
    575         { 0x62, 0x61, 0x300, 0x63, 0 },         /* 0061 0300 compose */
    576         { 0xfb1d, 0 },                          /* excluded from composition */
    577         { 0x0627, 0x0653, 0 },                  /* 0627 0653 compose */
    578         { 0x3071, 0x306f, 0x309a, 0x3073, 0 }   /* 306F 309A compose */
    579     };
    580     static const UChar notNFKC[][8]={           /* strings that are not in NFKC */
    581         { 0x1100, 0x1161, 0 },                  /* Jamo compose */
    582         { 0x1100, 0x314f, 0 },                  /* compatibility Jamo compose */
    583         { 0x03b1, 0x1f00, 0x0345, 0x03b3, 0 }   /* 1F00 0345 compose */
    584     };
    585 
    586     int32_t i;
    587     UErrorCode errorCode;
    588 
    589     /* API test */
    590 
    591     /* normal case with length>=0 (length -1 used for special cases below) */
    592     errorCode=U_ZERO_ERROR;
    593     if(!unorm_isNormalized(notNFC[0]+2, 1, UNORM_NFC, &errorCode) || U_FAILURE(errorCode)) {
    594         log_data_err("error: !isNormalized(<U+0300>, NFC) (%s) - (Are you missing data?)\n", u_errorName(errorCode));
    595     }
    596 
    597     /* incoming U_FAILURE */
    598     errorCode=U_TRUNCATED_CHAR_FOUND;
    599     (void)unorm_isNormalized(notNFC[0]+2, 1, UNORM_NFC, &errorCode);
    600     if(errorCode!=U_TRUNCATED_CHAR_FOUND) {
    601         log_err("error: isNormalized(U_TRUNCATED_CHAR_FOUND) changed the error code to %s\n", u_errorName(errorCode));
    602     }
    603 
    604     /* NULL source */
    605     errorCode=U_ZERO_ERROR;
    606     (void)unorm_isNormalized(NULL, 1, UNORM_NFC, &errorCode);
    607     if(errorCode!=U_ILLEGAL_ARGUMENT_ERROR) {
    608         log_data_err("error: isNormalized(NULL) did not set U_ILLEGAL_ARGUMENT_ERROR but %s - (Are you missing data?)\n", u_errorName(errorCode));
    609     }
    610 
    611     /* bad length */
    612     errorCode=U_ZERO_ERROR;
    613     (void)unorm_isNormalized(notNFC[0]+2, -2, UNORM_NFC, &errorCode);
    614     if(errorCode!=U_ILLEGAL_ARGUMENT_ERROR) {
    615         log_data_err("error: isNormalized([-2]) did not set U_ILLEGAL_ARGUMENT_ERROR but %s - (Are you missing data?)\n", u_errorName(errorCode));
    616     }
    617 
    618     /* specific cases */
    619     for(i=0; i<LENGTHOF(notNFC); ++i) {
    620         errorCode=U_ZERO_ERROR;
    621         if(unorm_isNormalized(notNFC[i], -1, UNORM_NFC, &errorCode) || U_FAILURE(errorCode)) {
    622             log_data_err("error: isNormalized(notNFC[%d], NFC) is wrong (%s) - (Are you missing data?)\n", i, u_errorName(errorCode));
    623         }
    624         errorCode=U_ZERO_ERROR;
    625         if(unorm_isNormalized(notNFC[i], -1, UNORM_NFKC, &errorCode) || U_FAILURE(errorCode)) {
    626             log_data_err("error: isNormalized(notNFC[%d], NFKC) is wrong (%s) - (Are you missing data?)\n", i, u_errorName(errorCode));
    627         }
    628     }
    629     for(i=0; i<LENGTHOF(notNFKC); ++i) {
    630         errorCode=U_ZERO_ERROR;
    631         if(unorm_isNormalized(notNFKC[i], -1, UNORM_NFKC, &errorCode) || U_FAILURE(errorCode)) {
    632             log_data_err("error: isNormalized(notNFKC[%d], NFKC) is wrong (%s) - (Are you missing data?)\n", i, u_errorName(errorCode));
    633         }
    634     }
    635 }
    636 
    637 void TestCheckFCD()
    638 {
    639   UErrorCode status = U_ZERO_ERROR;
    640   static const UChar FAST_[] = {0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09,
    641                          0x0A};
    642   static const UChar FALSE_[] = {0x0001, 0x0002, 0x02EA, 0x03EB, 0x0300, 0x0301,
    643                           0x02B9, 0x0314, 0x0315, 0x0316};
    644   static const UChar TRUE_[] = {0x0030, 0x0040, 0x0440, 0x056D, 0x064F, 0x06E7,
    645                          0x0050, 0x0730, 0x09EE, 0x1E10};
    646 
    647   static const UChar datastr[][5] =
    648   { {0x0061, 0x030A, 0x1E05, 0x0302, 0},
    649     {0x0061, 0x030A, 0x00E2, 0x0323, 0},
    650     {0x0061, 0x0323, 0x00E2, 0x0323, 0},
    651     {0x0061, 0x0323, 0x1E05, 0x0302, 0} };
    652   static const UBool result[] = {UNORM_YES, UNORM_NO, UNORM_NO, UNORM_YES};
    653 
    654   static const UChar datachar[] = {0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69,
    655                             0x6a,
    656                             0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9,
    657                             0xea,
    658                             0x0300, 0x0301, 0x0302, 0x0303, 0x0304, 0x0305, 0x0306,
    659                             0x0307, 0x0308, 0x0309, 0x030a,
    660                             0x0320, 0x0321, 0x0322, 0x0323, 0x0324, 0x0325, 0x0326,
    661                             0x0327, 0x0328, 0x0329, 0x032a,
    662                             0x1e00, 0x1e01, 0x1e02, 0x1e03, 0x1e04, 0x1e05, 0x1e06,
    663                             0x1e07, 0x1e08, 0x1e09, 0x1e0a};
    664 
    665   int count = 0;
    666 
    667   if (unorm_quickCheck(FAST_, 10, UNORM_FCD, &status) != UNORM_YES)
    668     log_data_err("unorm_quickCheck(FCD) failed: expected value for fast unorm_quickCheck is UNORM_YES - (Are you missing data?)\n");
    669   if (unorm_quickCheck(FALSE_, 10, UNORM_FCD, &status) != UNORM_NO)
    670     log_err("unorm_quickCheck(FCD) failed: expected value for error unorm_quickCheck is UNORM_NO\n");
    671   if (unorm_quickCheck(TRUE_, 10, UNORM_FCD, &status) != UNORM_YES)
    672     log_data_err("unorm_quickCheck(FCD) failed: expected value for correct unorm_quickCheck is UNORM_YES - (Are you missing data?)\n");
    673 
    674   if (U_FAILURE(status))
    675     log_data_err("unorm_quickCheck(FCD) failed: %s - (Are you missing data?)\n", u_errorName(status));
    676 
    677   while (count < 4)
    678   {
    679     UBool fcdresult = unorm_quickCheck(datastr[count], 4, UNORM_FCD, &status);
    680     if (U_FAILURE(status)) {
    681       log_data_err("unorm_quickCheck(FCD) failed: exception occured at data set %d - (Are you missing data?)\n", count);
    682       break;
    683     }
    684     else {
    685       if (result[count] != fcdresult) {
    686         log_err("unorm_quickCheck(FCD) failed: Data set %d expected value %d\n", count,
    687                  result[count]);
    688       }
    689     }
    690     count ++;
    691   }
    692 
    693   /* random checks of long strings */
    694   status = U_ZERO_ERROR;
    695   srand((unsigned)time( NULL ));
    696 
    697   for (count = 0; count < 50; count ++)
    698   {
    699     int size = 0;
    700     UBool testresult = UNORM_YES;
    701     UChar data[20];
    702     UChar norm[100];
    703     UChar nfd[100];
    704     int normsize = 0;
    705     int nfdsize = 0;
    706 
    707     while (size != 19) {
    708       data[size] = datachar[(rand() * 50) / RAND_MAX];
    709       log_verbose("0x%x", data[size]);
    710       normsize += unorm_normalize(data + size, 1, UNORM_NFD, 0,
    711                                   norm + normsize, 100 - normsize, &status);
    712       if (U_FAILURE(status)) {
    713         log_data_err("unorm_quickCheck(FCD) failed: exception occured at data generation - (Are you missing data?)\n");
    714         break;
    715       }
    716       size ++;
    717     }
    718     log_verbose("\n");
    719 
    720     nfdsize = unorm_normalize(data, size, UNORM_NFD, 0,
    721                               nfd, 100, &status);
    722     if (U_FAILURE(status)) {
    723       log_data_err("unorm_quickCheck(FCD) failed: exception occured at normalized data generation - (Are you missing data?)\n");
    724     }
    725 
    726     if (nfdsize != normsize || u_memcmp(nfd, norm, nfdsize) != 0) {
    727       testresult = UNORM_NO;
    728     }
    729     if (testresult == UNORM_YES) {
    730       log_verbose("result UNORM_YES\n");
    731     }
    732     else {
    733       log_verbose("result UNORM_NO\n");
    734     }
    735 
    736     if (unorm_quickCheck(data, size, UNORM_FCD, &status) != testresult || U_FAILURE(status)) {
    737       log_data_err("unorm_quickCheck(FCD) failed: expected %d for random data - (Are you missing data?)\n", testresult);
    738     }
    739   }
    740 }
    741 
    742 static void
    743 TestAPI() {
    744     static const UChar in[]={ 0x68, 0xe4 };
    745     UChar out[20]={ 0xffff, 0xffff, 0xffff, 0xffff };
    746     UErrorCode errorCode;
    747     int32_t length;
    748 
    749     /* try preflighting */
    750     errorCode=U_ZERO_ERROR;
    751     length=unorm_normalize(in, 2, UNORM_NFD, 0, NULL, 0, &errorCode);
    752     if(errorCode!=U_BUFFER_OVERFLOW_ERROR || length!=3) {
    753         log_data_err("unorm_normalize(pure preflighting NFD)=%ld failed with %s - (Are you missing data?)\n", length, u_errorName(errorCode));
    754         return;
    755     }
    756 
    757     errorCode=U_ZERO_ERROR;
    758     length=unorm_normalize(in, 2, UNORM_NFD, 0, out, 3, &errorCode);
    759     if(U_FAILURE(errorCode)) {
    760         log_err("unorm_normalize(NFD)=%ld failed with %s\n", length, u_errorName(errorCode));
    761         return;
    762     }
    763     if(length!=3 || out[2]!=0x308 || out[3]!=0xffff) {
    764         log_err("unorm_normalize(NFD ma<umlaut>)=%ld failed with out[]=U+%04x U+%04x U+%04x U+%04x\n", length, out[0], out[1], out[2], out[3]);
    765         return;
    766     }
    767 }
    768 
    769 /* test cases to improve test code coverage */
    770 enum {
    771     HANGUL_K_KIYEOK=0x3131,         /* NFKD->Jamo L U+1100 */
    772     HANGUL_K_WEO=0x315d,            /* NFKD->Jamo V U+116f */
    773     HANGUL_K_KIYEOK_SIOS=0x3133,    /* NFKD->Jamo T U+11aa */
    774 
    775     HANGUL_KIYEOK=0x1100,           /* Jamo L U+1100 */
    776     HANGUL_WEO=0x116f,              /* Jamo V U+116f */
    777     HANGUL_KIYEOK_SIOS=0x11aa,      /* Jamo T U+11aa */
    778 
    779     HANGUL_AC00=0xac00,             /* Hangul syllable = Jamo LV U+ac00 */
    780     HANGUL_SYLLABLE=0xac00+14*28+3, /* Hangul syllable = U+1100 * U+116f * U+11aa */
    781 
    782     MUSICAL_VOID_NOTEHEAD=0x1d157,
    783     MUSICAL_HALF_NOTE=0x1d15e,  /* NFC/NFD->Notehead+Stem */
    784     MUSICAL_STEM=0x1d165,       /* cc=216 */
    785     MUSICAL_STACCATO=0x1d17c    /* cc=220 */
    786 };
    787 
    788 static void
    789 TestNormCoverage() {
    790     UChar input[1000], expect[1000], output[1000];
    791     UErrorCode errorCode;
    792     int32_t i, length, inLength, expectLength, hangulPrefixLength, preflightLength;
    793 
    794     /* create a long and nasty string with NFKC-unsafe characters */
    795     inLength=0;
    796 
    797     /* 3 Jamos L/V/T, all 8 combinations normal/compatibility */
    798     input[inLength++]=HANGUL_KIYEOK;
    799     input[inLength++]=HANGUL_WEO;
    800     input[inLength++]=HANGUL_KIYEOK_SIOS;
    801 
    802     input[inLength++]=HANGUL_KIYEOK;
    803     input[inLength++]=HANGUL_WEO;
    804     input[inLength++]=HANGUL_K_KIYEOK_SIOS;
    805 
    806     input[inLength++]=HANGUL_KIYEOK;
    807     input[inLength++]=HANGUL_K_WEO;
    808     input[inLength++]=HANGUL_KIYEOK_SIOS;
    809 
    810     input[inLength++]=HANGUL_KIYEOK;
    811     input[inLength++]=HANGUL_K_WEO;
    812     input[inLength++]=HANGUL_K_KIYEOK_SIOS;
    813 
    814     input[inLength++]=HANGUL_K_KIYEOK;
    815     input[inLength++]=HANGUL_WEO;
    816     input[inLength++]=HANGUL_KIYEOK_SIOS;
    817 
    818     input[inLength++]=HANGUL_K_KIYEOK;
    819     input[inLength++]=HANGUL_WEO;
    820     input[inLength++]=HANGUL_K_KIYEOK_SIOS;
    821 
    822     input[inLength++]=HANGUL_K_KIYEOK;
    823     input[inLength++]=HANGUL_K_WEO;
    824     input[inLength++]=HANGUL_KIYEOK_SIOS;
    825 
    826     input[inLength++]=HANGUL_K_KIYEOK;
    827     input[inLength++]=HANGUL_K_WEO;
    828     input[inLength++]=HANGUL_K_KIYEOK_SIOS;
    829 
    830     /* Hangul LV with normal/compatibility Jamo T */
    831     input[inLength++]=HANGUL_AC00;
    832     input[inLength++]=HANGUL_KIYEOK_SIOS;
    833 
    834     input[inLength++]=HANGUL_AC00;
    835     input[inLength++]=HANGUL_K_KIYEOK_SIOS;
    836 
    837     /* compatibility Jamo L, V */
    838     input[inLength++]=HANGUL_K_KIYEOK;
    839     input[inLength++]=HANGUL_K_WEO;
    840 
    841     hangulPrefixLength=inLength;
    842 
    843     input[inLength++]=UTF16_LEAD(MUSICAL_HALF_NOTE);
    844     input[inLength++]=UTF16_TRAIL(MUSICAL_HALF_NOTE);
    845     for(i=0; i<200; ++i) {
    846         input[inLength++]=UTF16_LEAD(MUSICAL_STACCATO);
    847         input[inLength++]=UTF16_TRAIL(MUSICAL_STACCATO);
    848         input[inLength++]=UTF16_LEAD(MUSICAL_STEM);
    849         input[inLength++]=UTF16_TRAIL(MUSICAL_STEM);
    850     }
    851 
    852     /* (compatibility) Jamo L, T do not compose */
    853     input[inLength++]=HANGUL_K_KIYEOK;
    854     input[inLength++]=HANGUL_K_KIYEOK_SIOS;
    855 
    856     /* quick checks */
    857     errorCode=U_ZERO_ERROR;
    858     if(UNORM_NO!=unorm_quickCheck(input, inLength, UNORM_NFD, &errorCode) || U_FAILURE(errorCode)) {
    859         log_data_err("error unorm_quickCheck(long input, UNORM_NFD)!=NO (%s) - (Are you missing data?)\n", u_errorName(errorCode));
    860     }
    861     errorCode=U_ZERO_ERROR;
    862     if(UNORM_NO!=unorm_quickCheck(input, inLength, UNORM_NFKD, &errorCode) || U_FAILURE(errorCode)) {
    863         log_data_err("error unorm_quickCheck(long input, UNORM_NFKD)!=NO (%s) - (Are you missing data?)\n", u_errorName(errorCode));
    864     }
    865     errorCode=U_ZERO_ERROR;
    866     if(UNORM_NO!=unorm_quickCheck(input, inLength, UNORM_NFC, &errorCode) || U_FAILURE(errorCode)) {
    867         log_data_err("error unorm_quickCheck(long input, UNORM_NFC)!=NO (%s) - (Are you missing data?)\n", u_errorName(errorCode));
    868     }
    869     errorCode=U_ZERO_ERROR;
    870     if(UNORM_NO!=unorm_quickCheck(input, inLength, UNORM_NFKC, &errorCode) || U_FAILURE(errorCode)) {
    871         log_data_err("error unorm_quickCheck(long input, UNORM_NFKC)!=NO (%s) - (Are you missing data?)\n", u_errorName(errorCode));
    872     }
    873     errorCode=U_ZERO_ERROR;
    874     if(UNORM_NO!=unorm_quickCheck(input, inLength, UNORM_FCD, &errorCode) || U_FAILURE(errorCode)) {
    875         log_data_err("error unorm_quickCheck(long input, UNORM_FCD)!=NO (%s) - (Are you missing data?)\n", u_errorName(errorCode));
    876     }
    877 
    878     /* NFKC */
    879     expectLength=0;
    880     expect[expectLength++]=HANGUL_SYLLABLE;
    881 
    882     expect[expectLength++]=HANGUL_SYLLABLE;
    883 
    884     expect[expectLength++]=HANGUL_SYLLABLE;
    885 
    886     expect[expectLength++]=HANGUL_SYLLABLE;
    887 
    888     expect[expectLength++]=HANGUL_SYLLABLE;
    889 
    890     expect[expectLength++]=HANGUL_SYLLABLE;
    891 
    892     expect[expectLength++]=HANGUL_SYLLABLE;
    893 
    894     expect[expectLength++]=HANGUL_SYLLABLE;
    895 
    896     expect[expectLength++]=HANGUL_AC00+3;
    897 
    898     expect[expectLength++]=HANGUL_AC00+3;
    899 
    900     expect[expectLength++]=HANGUL_AC00+14*28;
    901 
    902     expect[expectLength++]=UTF16_LEAD(MUSICAL_VOID_NOTEHEAD);
    903     expect[expectLength++]=UTF16_TRAIL(MUSICAL_VOID_NOTEHEAD);
    904     expect[expectLength++]=UTF16_LEAD(MUSICAL_STEM);
    905     expect[expectLength++]=UTF16_TRAIL(MUSICAL_STEM);
    906     for(i=0; i<200; ++i) {
    907         expect[expectLength++]=UTF16_LEAD(MUSICAL_STEM);
    908         expect[expectLength++]=UTF16_TRAIL(MUSICAL_STEM);
    909     }
    910     for(i=0; i<200; ++i) {
    911         expect[expectLength++]=UTF16_LEAD(MUSICAL_STACCATO);
    912         expect[expectLength++]=UTF16_TRAIL(MUSICAL_STACCATO);
    913     }
    914 
    915     expect[expectLength++]=HANGUL_KIYEOK;
    916     expect[expectLength++]=HANGUL_KIYEOK_SIOS;
    917 
    918     /* try destination overflow first */
    919     errorCode=U_ZERO_ERROR;
    920     preflightLength=unorm_normalize(input, inLength,
    921                            UNORM_NFKC, 0,
    922                            output, 100, /* too short */
    923                            &errorCode);
    924     if(errorCode!=U_BUFFER_OVERFLOW_ERROR) {
    925         log_data_err("error unorm_normalize(long input, output too short, UNORM_NFKC) did not overflow but %s - (Are you missing data?)\n", u_errorName(errorCode));
    926     }
    927 
    928     /* real NFKC */
    929     errorCode=U_ZERO_ERROR;
    930     length=unorm_normalize(input, inLength,
    931                            UNORM_NFKC, 0,
    932                            output, sizeof(output)/U_SIZEOF_UCHAR,
    933                            &errorCode);
    934     if(U_FAILURE(errorCode)) {
    935         log_data_err("error unorm_normalize(long input, UNORM_NFKC) failed with %s - (Are you missing data?)\n", u_errorName(errorCode));
    936     } else if(length!=expectLength || u_memcmp(output, expect, length)!=0) {
    937         log_err("error unorm_normalize(long input, UNORM_NFKC) produced wrong result\n");
    938         for(i=0; i<length; ++i) {
    939             if(output[i]!=expect[i]) {
    940                 log_err("    NFKC[%d]==U+%04lx expected U+%04lx\n", i, output[i], expect[i]);
    941                 break;
    942             }
    943         }
    944     }
    945     if(length!=preflightLength) {
    946         log_err("error unorm_normalize(long input, UNORM_NFKC)==%ld but preflightLength==%ld\n", length, preflightLength);
    947     }
    948 
    949     /* FCD */
    950     u_memcpy(expect, input, hangulPrefixLength);
    951     expectLength=hangulPrefixLength;
    952 
    953     expect[expectLength++]=UTF16_LEAD(MUSICAL_VOID_NOTEHEAD);
    954     expect[expectLength++]=UTF16_TRAIL(MUSICAL_VOID_NOTEHEAD);
    955     expect[expectLength++]=UTF16_LEAD(MUSICAL_STEM);
    956     expect[expectLength++]=UTF16_TRAIL(MUSICAL_STEM);
    957     for(i=0; i<200; ++i) {
    958         expect[expectLength++]=UTF16_LEAD(MUSICAL_STEM);
    959         expect[expectLength++]=UTF16_TRAIL(MUSICAL_STEM);
    960     }
    961     for(i=0; i<200; ++i) {
    962         expect[expectLength++]=UTF16_LEAD(MUSICAL_STACCATO);
    963         expect[expectLength++]=UTF16_TRAIL(MUSICAL_STACCATO);
    964     }
    965 
    966     expect[expectLength++]=HANGUL_K_KIYEOK;
    967     expect[expectLength++]=HANGUL_K_KIYEOK_SIOS;
    968 
    969     errorCode=U_ZERO_ERROR;
    970     length=unorm_normalize(input, inLength,
    971                            UNORM_FCD, 0,
    972                            output, sizeof(output)/U_SIZEOF_UCHAR,
    973                            &errorCode);
    974     if(U_FAILURE(errorCode)) {
    975         log_data_err("error unorm_normalize(long input, UNORM_FCD) failed with %s - (Are you missing data?)\n", u_errorName(errorCode));
    976     } else if(length!=expectLength || u_memcmp(output, expect, length)!=0) {
    977         log_err("error unorm_normalize(long input, UNORM_FCD) produced wrong result\n");
    978         for(i=0; i<length; ++i) {
    979             if(output[i]!=expect[i]) {
    980                 log_err("    FCD[%d]==U+%04lx expected U+%04lx\n", i, output[i], expect[i]);
    981                 break;
    982             }
    983         }
    984     }
    985 }
    986 
    987 /* API test for unorm_concatenate() - for real test strings see intltest/tstnorm.cpp */
    988 static void
    989 TestConcatenate(void) {
    990     /* "re + 'sume'" */
    991     static const UChar
    992     left[]={
    993         0x72, 0x65, 0
    994     },
    995     right[]={
    996         0x301, 0x73, 0x75, 0x6d, 0xe9, 0
    997     },
    998     expect[]={
    999         0x72, 0xe9, 0x73, 0x75, 0x6d, 0xe9, 0
   1000     };
   1001 
   1002     UChar buffer[100];
   1003     UErrorCode errorCode;
   1004     int32_t length;
   1005 
   1006     /* left with length, right NUL-terminated */
   1007     errorCode=U_ZERO_ERROR;
   1008     length=unorm_concatenate(left, 2, right, -1, buffer, 100, UNORM_NFC, 0, &errorCode);
   1009     if(U_FAILURE(errorCode) || length!=6 || 0!=u_memcmp(buffer, expect, length)) {
   1010         log_data_err("error: unorm_concatenate()=%ld (expect 6) failed with %s - (Are you missing data?)\n", length, u_errorName(errorCode));
   1011     }
   1012 
   1013     /* preflighting */
   1014     errorCode=U_ZERO_ERROR;
   1015     length=unorm_concatenate(left, 2, right, -1, NULL, 0, UNORM_NFC, 0, &errorCode);
   1016     if(errorCode!=U_BUFFER_OVERFLOW_ERROR || length!=6) {
   1017         log_data_err("error: unorm_concatenate(preflighting)=%ld (expect 6) failed with %s - (Are you missing data?)\n", length, u_errorName(errorCode));
   1018     }
   1019 
   1020     buffer[2]=0x5555;
   1021     errorCode=U_ZERO_ERROR;
   1022     length=unorm_concatenate(left, 2, right, -1, buffer, 1, UNORM_NFC, 0, &errorCode);
   1023     if(errorCode!=U_BUFFER_OVERFLOW_ERROR || length!=6 || buffer[2]!=0x5555) {
   1024         log_data_err("error: unorm_concatenate(preflighting 2)=%ld (expect 6) failed with %s - (Are you missing data?)\n", length, u_errorName(errorCode));
   1025     }
   1026 
   1027     /* enter with U_FAILURE */
   1028     buffer[2]=0xaaaa;
   1029     errorCode=U_UNEXPECTED_TOKEN;
   1030     length=unorm_concatenate(left, 2, right, -1, buffer, 100, UNORM_NFC, 0, &errorCode);
   1031     if(errorCode!=U_UNEXPECTED_TOKEN || buffer[2]!=0xaaaa) {
   1032         log_err("error: unorm_concatenate(failure)=%ld failed with %s\n", length, u_errorName(errorCode));
   1033     }
   1034 
   1035     /* illegal arguments */
   1036     buffer[2]=0xaaaa;
   1037     errorCode=U_ZERO_ERROR;
   1038     length=unorm_concatenate(NULL, 2, right, -1, buffer, 100, UNORM_NFC, 0, &errorCode);
   1039     if(errorCode!=U_ILLEGAL_ARGUMENT_ERROR || buffer[2]!=0xaaaa) {
   1040         log_data_err("error: unorm_concatenate(left=NULL)=%ld failed with %s - (Are you missing data?)\n", length, u_errorName(errorCode));
   1041     }
   1042 
   1043     errorCode=U_ZERO_ERROR;
   1044     length=unorm_concatenate(left, 2, right, -1, NULL, 100, UNORM_NFC, 0, &errorCode);
   1045     if(errorCode!=U_ILLEGAL_ARGUMENT_ERROR) {
   1046         log_data_err("error: unorm_concatenate(buffer=NULL)=%ld failed with %s - (Are you missing data?)\n", length, u_errorName(errorCode));
   1047     }
   1048 }
   1049 
   1050 enum {
   1051     _PLUS=0x2b
   1052 };
   1053 
   1054 static const char *const _modeString[UNORM_MODE_COUNT]={
   1055     "0", "NONE", "NFD", "NFKD", "NFC", "NFKC", "FCD"
   1056 };
   1057 
   1058 static void
   1059 _testIter(const UChar *src, int32_t srcLength,
   1060           UCharIterator *iter, UNormalizationMode mode, UBool forward,
   1061           const UChar *out, int32_t outLength,
   1062           const int32_t *srcIndexes, int32_t srcIndexesLength) {
   1063     UChar buffer[4];
   1064     const UChar *expect, *outLimit, *in;
   1065     int32_t length, i, expectLength, expectIndex, prevIndex, index, inLength;
   1066     UErrorCode errorCode;
   1067     UBool neededToNormalize, expectNeeded;
   1068 
   1069     errorCode=U_ZERO_ERROR;
   1070     outLimit=out+outLength;
   1071     if(forward) {
   1072         expect=out;
   1073         i=index=0;
   1074     } else {
   1075         expect=outLimit;
   1076         i=srcIndexesLength-2;
   1077         index=srcLength;
   1078     }
   1079 
   1080     for(;;) {
   1081         prevIndex=index;
   1082         if(forward) {
   1083             if(!iter->hasNext(iter)) {
   1084                 return;
   1085             }
   1086             length=unorm_next(iter,
   1087                               buffer, sizeof(buffer)/U_SIZEOF_UCHAR,
   1088                               mode, 0,
   1089                               (UBool)(out!=NULL), &neededToNormalize,
   1090                               &errorCode);
   1091             expectIndex=srcIndexes[i+1];
   1092             in=src+prevIndex;
   1093             inLength=expectIndex-prevIndex;
   1094 
   1095             if(out!=NULL) {
   1096                 /* get output piece from between plus signs */
   1097                 expectLength=0;
   1098                 while((expect+expectLength)!=outLimit && expect[expectLength]!=_PLUS) {
   1099                     ++expectLength;
   1100                 }
   1101                 expectNeeded=(UBool)(0!=u_memcmp(buffer, in, inLength));
   1102             } else {
   1103                 expect=in;
   1104                 expectLength=inLength;
   1105                 expectNeeded=FALSE;
   1106             }
   1107         } else {
   1108             if(!iter->hasPrevious(iter)) {
   1109                 return;
   1110             }
   1111             length=unorm_previous(iter,
   1112                                   buffer, sizeof(buffer)/U_SIZEOF_UCHAR,
   1113                                   mode, 0,
   1114                                   (UBool)(out!=NULL), &neededToNormalize,
   1115                                   &errorCode);
   1116             expectIndex=srcIndexes[i];
   1117             in=src+expectIndex;
   1118             inLength=prevIndex-expectIndex;
   1119 
   1120             if(out!=NULL) {
   1121                 /* get output piece from between plus signs */
   1122                 expectLength=0;
   1123                 while(expect!=out && expect[-1]!=_PLUS) {
   1124                     ++expectLength;
   1125                     --expect;
   1126                 }
   1127                 expectNeeded=(UBool)(0!=u_memcmp(buffer, in, inLength));
   1128             } else {
   1129                 expect=in;
   1130                 expectLength=inLength;
   1131                 expectNeeded=FALSE;
   1132             }
   1133         }
   1134         index=iter->getIndex(iter, UITER_CURRENT);
   1135 
   1136         if(U_FAILURE(errorCode)) {
   1137             log_data_err("error unorm iteration (next/previous %d %s)[%d]: %s - (Are you missing data?)\n",
   1138                     forward, _modeString[mode], i, u_errorName(errorCode));
   1139             return;
   1140         }
   1141         if(expectIndex!=index) {
   1142             log_err("error unorm iteration (next/previous %d %s): index[%d] wrong, got %d expected %d\n",
   1143                     forward, _modeString[mode], i, index, expectIndex);
   1144             return;
   1145         }
   1146         if(expectLength!=length) {
   1147             log_err("error unorm iteration (next/previous %d %s): length[%d] wrong, got %d expected %d\n",
   1148                     forward, _modeString[mode], i, length, expectLength);
   1149             return;
   1150         }
   1151         if(0!=u_memcmp(expect, buffer, length)) {
   1152             log_err("error unorm iteration (next/previous %d %s): output string[%d] wrong\n",
   1153                     forward, _modeString[mode], i);
   1154             return;
   1155         }
   1156         if(neededToNormalize!=expectNeeded) {
   1157         }
   1158 
   1159         if(forward) {
   1160             expect+=expectLength+1; /* go after the + */
   1161             ++i;
   1162         } else {
   1163             --expect; /* go before the + */
   1164             --i;
   1165         }
   1166     }
   1167 }
   1168 
   1169 static void
   1170 TestNextPrevious() {
   1171     static const UChar
   1172     src[]={ /* input string */
   1173         0xa0, 0xe4, 0x63, 0x302, 0x327, 0xac00, 0x3133
   1174     },
   1175     nfd[]={ /* + separates expected output pieces */
   1176         0xa0, _PLUS, 0x61, 0x308, _PLUS, 0x63, 0x327, 0x302, _PLUS, 0x1100, 0x1161, _PLUS, 0x3133
   1177     },
   1178     nfkd[]={
   1179         0x20, _PLUS, 0x61, 0x308, _PLUS, 0x63, 0x327, 0x302, _PLUS, 0x1100, 0x1161, _PLUS, 0x11aa
   1180     },
   1181     nfc[]={
   1182         0xa0, _PLUS, 0xe4, _PLUS, 0xe7, 0x302, _PLUS, 0xac00, _PLUS, 0x3133
   1183     },
   1184     nfkc[]={
   1185         0x20, _PLUS, 0xe4, _PLUS, 0xe7, 0x302, _PLUS, 0xac03
   1186     },
   1187     fcd[]={
   1188         0xa0, _PLUS, 0xe4, _PLUS, 0x63, 0x327, 0x302, _PLUS, 0xac00, _PLUS, 0x3133
   1189     };
   1190 
   1191     /* expected iterator indexes in the source string for each iteration piece */
   1192     static const int32_t
   1193     nfdIndexes[]={
   1194         0, 1, 2, 5, 6, 7
   1195     },
   1196     nfkdIndexes[]={
   1197         0, 1, 2, 5, 6, 7
   1198     },
   1199     nfcIndexes[]={
   1200         0, 1, 2, 5, 6, 7
   1201     },
   1202     nfkcIndexes[]={
   1203         0, 1, 2, 5, 7
   1204     },
   1205     fcdIndexes[]={
   1206         0, 1, 2, 5, 6, 7
   1207     };
   1208 
   1209     UCharIterator iter;
   1210 
   1211     UChar buffer[4];
   1212     int32_t length;
   1213 
   1214     UBool neededToNormalize;
   1215     UErrorCode errorCode;
   1216 
   1217     uiter_setString(&iter, src, sizeof(src)/U_SIZEOF_UCHAR);
   1218 
   1219     /* test iteration with doNormalize */
   1220     iter.index=0;
   1221     _testIter(src, sizeof(src)/U_SIZEOF_UCHAR, &iter, UNORM_NFD, TRUE, nfd, sizeof(nfd)/U_SIZEOF_UCHAR, nfdIndexes, sizeof(nfdIndexes)/4);
   1222     iter.index=0;
   1223     _testIter(src, sizeof(src)/U_SIZEOF_UCHAR, &iter, UNORM_NFKD, TRUE, nfkd, sizeof(nfkd)/U_SIZEOF_UCHAR, nfkdIndexes, sizeof(nfkdIndexes)/4);
   1224     iter.index=0;
   1225     _testIter(src, sizeof(src)/U_SIZEOF_UCHAR, &iter, UNORM_NFC, TRUE, nfc, sizeof(nfc)/U_SIZEOF_UCHAR, nfcIndexes, sizeof(nfcIndexes)/4);
   1226     iter.index=0;
   1227     _testIter(src, sizeof(src)/U_SIZEOF_UCHAR, &iter, UNORM_NFKC, TRUE, nfkc, sizeof(nfkc)/U_SIZEOF_UCHAR, nfkcIndexes, sizeof(nfkcIndexes)/4);
   1228     iter.index=0;
   1229     _testIter(src, sizeof(src)/U_SIZEOF_UCHAR, &iter, UNORM_FCD, TRUE, fcd, sizeof(fcd)/U_SIZEOF_UCHAR, fcdIndexes, sizeof(fcdIndexes)/4);
   1230 
   1231     iter.index=iter.length;
   1232     _testIter(src, sizeof(src)/U_SIZEOF_UCHAR, &iter, UNORM_NFD, FALSE, nfd, sizeof(nfd)/U_SIZEOF_UCHAR, nfdIndexes, sizeof(nfdIndexes)/4);
   1233     iter.index=iter.length;
   1234     _testIter(src, sizeof(src)/U_SIZEOF_UCHAR, &iter, UNORM_NFKD, FALSE, nfkd, sizeof(nfkd)/U_SIZEOF_UCHAR, nfkdIndexes, sizeof(nfkdIndexes)/4);
   1235     iter.index=iter.length;
   1236     _testIter(src, sizeof(src)/U_SIZEOF_UCHAR, &iter, UNORM_NFC, FALSE, nfc, sizeof(nfc)/U_SIZEOF_UCHAR, nfcIndexes, sizeof(nfcIndexes)/4);
   1237     iter.index=iter.length;
   1238     _testIter(src, sizeof(src)/U_SIZEOF_UCHAR, &iter, UNORM_NFKC, FALSE, nfkc, sizeof(nfkc)/U_SIZEOF_UCHAR, nfkcIndexes, sizeof(nfkcIndexes)/4);
   1239     iter.index=iter.length;
   1240     _testIter(src, sizeof(src)/U_SIZEOF_UCHAR, &iter, UNORM_FCD, FALSE, fcd, sizeof(fcd)/U_SIZEOF_UCHAR, fcdIndexes, sizeof(fcdIndexes)/4);
   1241 
   1242     /* test iteration without doNormalize */
   1243     iter.index=0;
   1244     _testIter(src, sizeof(src)/U_SIZEOF_UCHAR, &iter, UNORM_NFD, TRUE, NULL, 0, nfdIndexes, sizeof(nfdIndexes)/4);
   1245     iter.index=0;
   1246     _testIter(src, sizeof(src)/U_SIZEOF_UCHAR, &iter, UNORM_NFKD, TRUE, NULL, 0, nfkdIndexes, sizeof(nfkdIndexes)/4);
   1247     iter.index=0;
   1248     _testIter(src, sizeof(src)/U_SIZEOF_UCHAR, &iter, UNORM_NFC, TRUE, NULL, 0, nfcIndexes, sizeof(nfcIndexes)/4);
   1249     iter.index=0;
   1250     _testIter(src, sizeof(src)/U_SIZEOF_UCHAR, &iter, UNORM_NFKC, TRUE, NULL, 0, nfkcIndexes, sizeof(nfkcIndexes)/4);
   1251     iter.index=0;
   1252     _testIter(src, sizeof(src)/U_SIZEOF_UCHAR, &iter, UNORM_FCD, TRUE, NULL, 0, fcdIndexes, sizeof(fcdIndexes)/4);
   1253 
   1254     iter.index=iter.length;
   1255     _testIter(src, sizeof(src)/U_SIZEOF_UCHAR, &iter, UNORM_NFD, FALSE, NULL, 0, nfdIndexes, sizeof(nfdIndexes)/4);
   1256     iter.index=iter.length;
   1257     _testIter(src, sizeof(src)/U_SIZEOF_UCHAR, &iter, UNORM_NFKD, FALSE, NULL, 0, nfkdIndexes, sizeof(nfkdIndexes)/4);
   1258     iter.index=iter.length;
   1259     _testIter(src, sizeof(src)/U_SIZEOF_UCHAR, &iter, UNORM_NFC, FALSE, NULL, 0, nfcIndexes, sizeof(nfcIndexes)/4);
   1260     iter.index=iter.length;
   1261     _testIter(src, sizeof(src)/U_SIZEOF_UCHAR, &iter, UNORM_NFKC, FALSE, NULL, 0, nfkcIndexes, sizeof(nfkcIndexes)/4);
   1262     iter.index=iter.length;
   1263     _testIter(src, sizeof(src)/U_SIZEOF_UCHAR, &iter, UNORM_FCD, FALSE, NULL, 0, fcdIndexes, sizeof(fcdIndexes)/4);
   1264 
   1265     /* try without neededToNormalize */
   1266     errorCode=U_ZERO_ERROR;
   1267     buffer[0]=5;
   1268     iter.index=1;
   1269     length=unorm_next(&iter, buffer, sizeof(buffer)/U_SIZEOF_UCHAR,
   1270                       UNORM_NFD, 0, TRUE, NULL,
   1271                       &errorCode);
   1272     if(U_FAILURE(errorCode) || length!=2 || buffer[0]!=nfd[2] || buffer[1]!=nfd[3]) {
   1273         log_data_err("error unorm_next(without needed) %s - (Are you missing data?)\n", u_errorName(errorCode));
   1274         return;
   1275     }
   1276 
   1277     /* preflight */
   1278     neededToNormalize=9;
   1279     iter.index=1;
   1280     length=unorm_next(&iter, NULL, 0,
   1281                       UNORM_NFD, 0, TRUE, &neededToNormalize,
   1282                       &errorCode);
   1283     if(errorCode!=U_BUFFER_OVERFLOW_ERROR || neededToNormalize!=FALSE || length!=2) {
   1284         log_err("error unorm_next(pure preflighting) %s\n", u_errorName(errorCode));
   1285         return;
   1286     }
   1287 
   1288     errorCode=U_ZERO_ERROR;
   1289     buffer[0]=buffer[1]=5;
   1290     neededToNormalize=9;
   1291     iter.index=1;
   1292     length=unorm_next(&iter, buffer, 1,
   1293                       UNORM_NFD, 0, TRUE, &neededToNormalize,
   1294                       &errorCode);
   1295     if(errorCode!=U_BUFFER_OVERFLOW_ERROR || neededToNormalize!=FALSE || length!=2 || buffer[1]!=5) {
   1296         log_err("error unorm_next(preflighting) %s\n", u_errorName(errorCode));
   1297         return;
   1298     }
   1299 
   1300     /* no iterator */
   1301     errorCode=U_ZERO_ERROR;
   1302     buffer[0]=buffer[1]=5;
   1303     neededToNormalize=9;
   1304     iter.index=1;
   1305     length=unorm_next(NULL, buffer, sizeof(buffer)/U_SIZEOF_UCHAR,
   1306                       UNORM_NFD, 0, TRUE, &neededToNormalize,
   1307                       &errorCode);
   1308     if(errorCode!=U_ILLEGAL_ARGUMENT_ERROR) {
   1309         log_err("error unorm_next(no iterator) %s\n", u_errorName(errorCode));
   1310         return;
   1311     }
   1312 
   1313     /* illegal mode */
   1314     buffer[0]=buffer[1]=5;
   1315     neededToNormalize=9;
   1316     iter.index=1;
   1317     length=unorm_next(&iter, buffer, sizeof(buffer)/U_SIZEOF_UCHAR,
   1318                       (UNormalizationMode)0, 0, TRUE, &neededToNormalize,
   1319                       &errorCode);
   1320     if(errorCode!=U_ILLEGAL_ARGUMENT_ERROR) {
   1321         log_err("error unorm_next(illegal mode) %s\n", u_errorName(errorCode));
   1322         return;
   1323     }
   1324 
   1325     /* error coming in */
   1326     errorCode=U_MISPLACED_QUANTIFIER;
   1327     buffer[0]=5;
   1328     iter.index=1;
   1329     length=unorm_next(&iter, buffer, sizeof(buffer)/U_SIZEOF_UCHAR,
   1330                       UNORM_NFD, 0, TRUE, NULL,
   1331                       &errorCode);
   1332     if(errorCode!=U_MISPLACED_QUANTIFIER) {
   1333         log_err("error unorm_next(U_MISPLACED_QUANTIFIER) %s\n", u_errorName(errorCode));
   1334         return;
   1335     }
   1336 }
   1337 
   1338 static void
   1339 TestFCNFKCClosure(void) {
   1340     static const struct {
   1341         UChar32 c;
   1342         const UChar s[6];
   1343     } tests[]={
   1344         { 0x00C4, { 0 } },
   1345         { 0x00E4, { 0 } },
   1346         { 0x037A, { 0x0020, 0x03B9, 0 } },
   1347         { 0x03D2, { 0x03C5, 0 } },
   1348         { 0x20A8, { 0x0072, 0x0073, 0 } },
   1349         { 0x210B, { 0x0068, 0 } },
   1350         { 0x210C, { 0x0068, 0 } },
   1351         { 0x2121, { 0x0074, 0x0065, 0x006C, 0 } },
   1352         { 0x2122, { 0x0074, 0x006D, 0 } },
   1353         { 0x2128, { 0x007A, 0 } },
   1354         { 0x1D5DB, { 0x0068, 0 } },
   1355         { 0x1D5ED, { 0x007A, 0 } },
   1356         { 0x0061, { 0 } }
   1357     };
   1358 
   1359     UChar buffer[8];
   1360     UErrorCode errorCode;
   1361     int32_t i, length;
   1362 
   1363     for(i=0; i<LENGTHOF(tests); ++i) {
   1364         errorCode=U_ZERO_ERROR;
   1365         length=u_getFC_NFKC_Closure(tests[i].c, buffer, LENGTHOF(buffer), &errorCode);
   1366         if(U_FAILURE(errorCode) || length!=u_strlen(buffer) || 0!=u_strcmp(tests[i].s, buffer)) {
   1367             log_data_err("u_getFC_NFKC_Closure(U+%04lx) is wrong (%s) - (Are you missing data?)\n", tests[i].c, u_errorName(errorCode));
   1368         }
   1369     }
   1370 
   1371     /* error handling */
   1372     errorCode=U_ZERO_ERROR;
   1373     length=u_getFC_NFKC_Closure(0x5c, NULL, LENGTHOF(buffer), &errorCode);
   1374     if(errorCode!=U_ILLEGAL_ARGUMENT_ERROR) {
   1375         log_err("u_getFC_NFKC_Closure(dest=NULL) is wrong (%s)\n", u_errorName(errorCode));
   1376     }
   1377 
   1378     length=u_getFC_NFKC_Closure(0x5c, buffer, LENGTHOF(buffer), &errorCode);
   1379     if(errorCode!=U_ILLEGAL_ARGUMENT_ERROR) {
   1380         log_err("u_getFC_NFKC_Closure(U_FAILURE) is wrong (%s)\n", u_errorName(errorCode));
   1381     }
   1382 }
   1383 
   1384 static void
   1385 TestQuickCheckPerCP() {
   1386     UErrorCode errorCode;
   1387     UChar32 c, lead, trail;
   1388     UChar s[U16_MAX_LENGTH], nfd[16];
   1389     int32_t length, lccc1, lccc2, tccc1, tccc2;
   1390     int32_t qc1, qc2;
   1391 
   1392     if(
   1393         u_getIntPropertyMaxValue(UCHAR_NFD_QUICK_CHECK)!=(int32_t)UNORM_YES ||
   1394         u_getIntPropertyMaxValue(UCHAR_NFKD_QUICK_CHECK)!=(int32_t)UNORM_YES ||
   1395         u_getIntPropertyMaxValue(UCHAR_NFC_QUICK_CHECK)!=(int32_t)UNORM_MAYBE ||
   1396         u_getIntPropertyMaxValue(UCHAR_NFKC_QUICK_CHECK)!=(int32_t)UNORM_MAYBE ||
   1397         u_getIntPropertyMaxValue(UCHAR_LEAD_CANONICAL_COMBINING_CLASS)!=u_getIntPropertyMaxValue(UCHAR_CANONICAL_COMBINING_CLASS) ||
   1398         u_getIntPropertyMaxValue(UCHAR_TRAIL_CANONICAL_COMBINING_CLASS)!=u_getIntPropertyMaxValue(UCHAR_CANONICAL_COMBINING_CLASS)
   1399     ) {
   1400         log_err("wrong result from one of the u_getIntPropertyMaxValue(UCHAR_NF*_QUICK_CHECK) or UCHAR_*_CANONICAL_COMBINING_CLASS\n");
   1401     }
   1402 
   1403     /*
   1404      * compare the quick check property values for some code points
   1405      * to the quick check results for checking same-code point strings
   1406      */
   1407     errorCode=U_ZERO_ERROR;
   1408     c=0;
   1409     while(c<0x110000) {
   1410         length=0;
   1411         U16_APPEND_UNSAFE(s, length, c);
   1412 
   1413         qc1=u_getIntPropertyValue(c, UCHAR_NFC_QUICK_CHECK);
   1414         qc2=unorm_quickCheck(s, length, UNORM_NFC, &errorCode);
   1415         if(qc1!=qc2) {
   1416             log_data_err("u_getIntPropertyValue(NFC)=%d != %d=unorm_quickCheck(NFC) for U+%04x - (Are you missing data?)\n", qc1, qc2, c);
   1417         }
   1418 
   1419         qc1=u_getIntPropertyValue(c, UCHAR_NFD_QUICK_CHECK);
   1420         qc2=unorm_quickCheck(s, length, UNORM_NFD, &errorCode);
   1421         if(qc1!=qc2) {
   1422             log_data_err("u_getIntPropertyValue(NFD)=%d != %d=unorm_quickCheck(NFD) for U+%04x - (Are you missing data?)\n", qc1, qc2, c);
   1423         }
   1424 
   1425         qc1=u_getIntPropertyValue(c, UCHAR_NFKC_QUICK_CHECK);
   1426         qc2=unorm_quickCheck(s, length, UNORM_NFKC, &errorCode);
   1427         if(qc1!=qc2) {
   1428             log_data_err("u_getIntPropertyValue(NFKC)=%d != %d=unorm_quickCheck(NFKC) for U+%04x - (Are you missing data?)\n", qc1, qc2, c);
   1429         }
   1430 
   1431         qc1=u_getIntPropertyValue(c, UCHAR_NFKD_QUICK_CHECK);
   1432         qc2=unorm_quickCheck(s, length, UNORM_NFKD, &errorCode);
   1433         if(qc1!=qc2) {
   1434             log_data_err("u_getIntPropertyValue(NFKD)=%d != %d=unorm_quickCheck(NFKD) for U+%04x - (Are you missing data?)\n", qc1, qc2, c);
   1435         }
   1436 
   1437         length=unorm_normalize(s, length, UNORM_NFD, 0, nfd, LENGTHOF(nfd), &errorCode);
   1438         /* length-length == 0 is used to get around a compiler warning. */
   1439         U16_GET(nfd, 0, length-length, length, lead);
   1440         U16_GET(nfd, 0, length-1, length, trail);
   1441 
   1442         lccc1=u_getIntPropertyValue(c, UCHAR_LEAD_CANONICAL_COMBINING_CLASS);
   1443         lccc2=u_getCombiningClass(lead);
   1444         tccc1=u_getIntPropertyValue(c, UCHAR_TRAIL_CANONICAL_COMBINING_CLASS);
   1445         tccc2=u_getCombiningClass(trail);
   1446 
   1447         if(lccc1!=lccc2) {
   1448             log_err("u_getIntPropertyValue(lccc)=%d != %d=u_getCombiningClass(lead) for U+%04x\n",
   1449                     lccc1, lccc2, c);
   1450         }
   1451         if(tccc1!=tccc2) {
   1452             log_err("u_getIntPropertyValue(tccc)=%d != %d=u_getCombiningClass(trail) for U+%04x\n",
   1453                     tccc1, tccc2, c);
   1454         }
   1455 
   1456         /* skip some code points */
   1457         c=(20*c)/19+1;
   1458     }
   1459 }
   1460 
   1461 static void
   1462 TestComposition(void) {
   1463     static const struct {
   1464         UNormalizationMode mode;
   1465         uint32_t options;
   1466         UChar input[12];
   1467         UChar expect[12];
   1468     } cases[]={
   1469         /*
   1470          * special cases for UAX #15 bug
   1471          * see Unicode Corrigendum #5: Normalization Idempotency
   1472          * at http://unicode.org/versions/corrigendum5.html
   1473          * (was Public Review Issue #29)
   1474          */
   1475         { UNORM_NFC, 0, { 0x1100, 0x0300, 0x1161, 0x0327 },         { 0x1100, 0x0300, 0x1161, 0x0327 } },
   1476         { UNORM_NFC, 0, { 0x1100, 0x0300, 0x1161, 0x0327, 0x11a8 }, { 0x1100, 0x0300, 0x1161, 0x0327, 0x11a8 } },
   1477         { UNORM_NFC, 0, { 0xac00, 0x0300, 0x0327, 0x11a8 },         { 0xac00, 0x0327, 0x0300, 0x11a8 } },
   1478         { UNORM_NFC, 0, { 0x0b47, 0x0300, 0x0b3e },                 { 0x0b47, 0x0300, 0x0b3e } },
   1479 
   1480         /* TODO: add test cases for UNORM_FCC here (j2151) */
   1481     };
   1482 
   1483     UChar output[16];
   1484     UErrorCode errorCode;
   1485     int32_t i, length;
   1486 
   1487     for(i=0; i<LENGTHOF(cases); ++i) {
   1488         errorCode=U_ZERO_ERROR;
   1489         length=unorm_normalize(
   1490                     cases[i].input, -1,
   1491                     cases[i].mode, cases[i].options,
   1492                     output, LENGTHOF(output),
   1493                     &errorCode);
   1494         if( U_FAILURE(errorCode) ||
   1495             length!=u_strlen(cases[i].expect) ||
   1496             0!=u_memcmp(output, cases[i].expect, length)
   1497         ) {
   1498             log_data_err("unexpected result for case %d - (Are you missing data?)\n", i);
   1499         }
   1500     }
   1501 }
   1502 
   1503 #endif /* #if !UCONFIG_NO_NORMALIZATION */
   1504