Home | History | Annotate | Download | only in cintltst
      1 /*
      2 ******************************************************************************
      3 *
      4 *   Copyright (C) 2001-2014, International Business Machines
      5 *   Corporation and others.  All Rights Reserved.
      6 *
      7 ******************************************************************************
      8 *   file name:  trietest.c
      9 *   encoding:   US-ASCII
     10 *   tab size:   8 (not used)
     11 *   indentation:4
     12 *
     13 *   created on: 2008sep01 (starting from a copy of trietest.c)
     14 *   created by: Markus W. Scherer
     15 */
     16 
     17 #include <stdio.h>
     18 #include "unicode/utypes.h"
     19 #include "utrie2.h"
     20 #include "utrie.h"
     21 #include "cstring.h"
     22 #include "cmemory.h"
     23 #include "udataswp.h"
     24 #include "cintltst.h"
     25 
     26 void addTrie2Test(TestNode** root);
     27 
     28 /* Values for setting possibly overlapping, out-of-order ranges of values */
     29 typedef struct SetRange {
     30     UChar32 start, limit;
     31     uint32_t value;
     32     UBool overwrite;
     33 } SetRange;
     34 
     35 /*
     36  * Values for testing:
     37  * value is set from the previous boundary's limit to before
     38  * this boundary's limit
     39  *
     40  * There must be an entry with limit 0 and the intialValue.
     41  * It may be preceded by an entry with negative limit and the errorValue.
     42  */
     43 typedef struct CheckRange {
     44     UChar32 limit;
     45     uint32_t value;
     46 } CheckRange;
     47 
     48 static int32_t
     49 skipSpecialValues(const CheckRange checkRanges[], int32_t countCheckRanges) {
     50     int32_t i;
     51     for(i=0; i<countCheckRanges && checkRanges[i].limit<=0; ++i) {}
     52     return i;
     53 }
     54 
     55 static int32_t
     56 getSpecialValues(const CheckRange checkRanges[], int32_t countCheckRanges,
     57                  uint32_t *pInitialValue, uint32_t *pErrorValue) {
     58     int32_t i=0;
     59     if(i<countCheckRanges && checkRanges[i].limit<0) {
     60         *pErrorValue=checkRanges[i++].value;
     61     } else {
     62         *pErrorValue=0xbad;
     63     }
     64     if(i<countCheckRanges && checkRanges[i].limit==0) {
     65         *pInitialValue=checkRanges[i++].value;
     66     } else {
     67         *pInitialValue=0;
     68     }
     69     return i;
     70 }
     71 
     72 /* utrie2_enum() callback, modifies a value */
     73 static uint32_t U_CALLCONV
     74 testEnumValue(const void *context, uint32_t value) {
     75     return value^0x5555;
     76 }
     77 
     78 /* utrie2_enum() callback, verifies a range */
     79 static UBool U_CALLCONV
     80 testEnumRange(const void *context, UChar32 start, UChar32 end, uint32_t value) {
     81     const CheckRange **pb=(const CheckRange **)context;
     82     const CheckRange *b=(*pb)++;
     83     UChar32 limit=end+1;
     84 
     85     value^=0x5555;
     86     if(start!=(b-1)->limit || limit!=b->limit || value!=b->value) {
     87         log_err("error: utrie2_enum() delivers wrong range [U+%04lx..U+%04lx].0x%lx instead of [U+%04lx..U+%04lx].0x%lx\n",
     88             (long)start, (long)end, (long)value,
     89             (long)(b-1)->limit, (long)b->limit-1, (long)b->value);
     90     }
     91     return TRUE;
     92 }
     93 
     94 static void
     95 testTrieEnum(const char *testName,
     96              const UTrie2 *trie,
     97              const CheckRange checkRanges[], int32_t countCheckRanges) {
     98     /* skip over special values */
     99     while(countCheckRanges>0 && checkRanges[0].limit<=0) {
    100         ++checkRanges;
    101         --countCheckRanges;
    102     }
    103     utrie2_enum(trie, testEnumValue, testEnumRange, &checkRanges);
    104 }
    105 
    106 /* verify all expected values via UTRIE2_GETxx() */
    107 static void
    108 testTrieGetters(const char *testName,
    109                 const UTrie2 *trie, UTrie2ValueBits valueBits,
    110                 const CheckRange checkRanges[], int32_t countCheckRanges) {
    111     uint32_t initialValue, errorValue;
    112     uint32_t value, value2;
    113     UChar32 start, limit;
    114     int32_t i, countSpecials;
    115 
    116     UBool isFrozen=utrie2_isFrozen(trie);
    117     const char *const typeName= isFrozen ? "frozen trie" : "newTrie";
    118 
    119     countSpecials=getSpecialValues(checkRanges, countCheckRanges, &initialValue, &errorValue);
    120 
    121     start=0;
    122     for(i=countSpecials; i<countCheckRanges; ++i) {
    123         limit=checkRanges[i].limit;
    124         value=checkRanges[i].value;
    125 
    126         while(start<limit) {
    127             if(isFrozen) {
    128                 if(start<=0xffff) {
    129                     if(!U_IS_LEAD(start)) {
    130                         if(valueBits==UTRIE2_16_VALUE_BITS) {
    131                             value2=UTRIE2_GET16_FROM_U16_SINGLE_LEAD(trie, start);
    132                         } else {
    133                             value2=UTRIE2_GET32_FROM_U16_SINGLE_LEAD(trie, start);
    134                         }
    135                         if(value!=value2) {
    136                             log_err("error: %s(%s).fromBMP(U+%04lx)==0x%lx instead of 0x%lx\n",
    137                                     typeName, testName, (long)start, (long)value2, (long)value);
    138                         }
    139                     }
    140                 } else {
    141                     if(valueBits==UTRIE2_16_VALUE_BITS) {
    142                         value2=UTRIE2_GET16_FROM_SUPP(trie, start);
    143                     } else {
    144                         value2=UTRIE2_GET32_FROM_SUPP(trie, start);
    145                     }
    146                     if(value!=value2) {
    147                         log_err("error: %s(%s).fromSupp(U+%04lx)==0x%lx instead of 0x%lx\n",
    148                                 typeName, testName, (long)start, (long)value2, (long)value);
    149                     }
    150                 }
    151                 if(valueBits==UTRIE2_16_VALUE_BITS) {
    152                     value2=UTRIE2_GET16(trie, start);
    153                 } else {
    154                     value2=UTRIE2_GET32(trie, start);
    155                 }
    156                 if(value!=value2) {
    157                     log_err("error: %s(%s).get(U+%04lx)==0x%lx instead of 0x%lx\n",
    158                             typeName, testName, (long)start, (long)value2, (long)value);
    159                 }
    160             }
    161             value2=utrie2_get32(trie, start);
    162             if(value!=value2) {
    163                 log_err("error: %s(%s).get32(U+%04lx)==0x%lx instead of 0x%lx\n",
    164                         typeName, testName, (long)start, (long)value2, (long)value);
    165             }
    166             ++start;
    167         }
    168     }
    169 
    170     if(isFrozen) {
    171         /* test linear ASCII range from the data array pointer (access to "internal" field) */
    172         start=0;
    173         for(i=countSpecials; i<countCheckRanges && start<=0x7f; ++i) {
    174             limit=checkRanges[i].limit;
    175             value=checkRanges[i].value;
    176 
    177             while(start<limit && start<=0x7f) {
    178                 if(valueBits==UTRIE2_16_VALUE_BITS) {
    179                     value2=trie->data16[start];
    180                 } else {
    181                     value2=trie->data32[start];
    182                 }
    183                 if(value!=value2) {
    184                     log_err("error: %s(%s).asciiData[U+%04lx]==0x%lx instead of 0x%lx\n",
    185                             typeName, testName, (long)start, (long)value2, (long)value);
    186                 }
    187                 ++start;
    188             }
    189         }
    190         while(start<=0xbf) {
    191             if(valueBits==UTRIE2_16_VALUE_BITS) {
    192                 value2=trie->data16[start];
    193             } else {
    194                 value2=trie->data32[start];
    195             }
    196             if(errorValue!=value2) {
    197                 log_err("error: %s(%s).badData[U+%04lx]==0x%lx instead of 0x%lx\n",
    198                         typeName, testName, (long)start, (long)value2, (long)errorValue);
    199             }
    200             ++start;
    201         }
    202     }
    203 
    204     if(0!=strncmp(testName, "dummy", 5) && 0!=strncmp(testName, "trie1", 5)) {
    205         /* test values for lead surrogate code units */
    206         for(start=0xd7ff; start<0xdc01; ++start) {
    207             switch(start) {
    208             case 0xd7ff:
    209             case 0xdc00:
    210                 value=errorValue;
    211                 break;
    212             case 0xd800:
    213                 value=90;
    214                 break;
    215             case 0xd999:
    216                 value=94;
    217                 break;
    218             case 0xdbff:
    219                 value=99;
    220                 break;
    221             default:
    222                 value=initialValue;
    223                 break;
    224             }
    225             if(isFrozen && U_IS_LEAD(start)) {
    226                 if(valueBits==UTRIE2_16_VALUE_BITS) {
    227                     value2=UTRIE2_GET16_FROM_U16_SINGLE_LEAD(trie, start);
    228                 } else {
    229                     value2=UTRIE2_GET32_FROM_U16_SINGLE_LEAD(trie, start);
    230                 }
    231                 if(value2!=value) {
    232                     log_err("error: %s(%s).LSCU(U+%04lx)==0x%lx instead of 0x%lx\n",
    233                             typeName, testName, (long)start, (long)value2, (long)value);
    234                 }
    235             }
    236             value2=utrie2_get32FromLeadSurrogateCodeUnit(trie, start);
    237             if(value2!=value) {
    238                 log_err("error: %s(%s).lscu(U+%04lx)==0x%lx instead of 0x%lx\n",
    239                         typeName, testName, (long)start, (long)value2, (long)value);
    240             }
    241         }
    242     }
    243 
    244     /* test errorValue */
    245     if(isFrozen) {
    246         if(valueBits==UTRIE2_16_VALUE_BITS) {
    247             value=UTRIE2_GET16(trie, -1);
    248             value2=UTRIE2_GET16(trie, 0x110000);
    249         } else {
    250             value=UTRIE2_GET32(trie, -1);
    251             value2=UTRIE2_GET32(trie, 0x110000);
    252         }
    253         if(value!=errorValue || value2!=errorValue) {
    254             log_err("error: %s(%s).get(out of range) != errorValue\n",
    255                     typeName, testName);
    256         }
    257     }
    258     value=utrie2_get32(trie, -1);
    259     value2=utrie2_get32(trie, 0x110000);
    260     if(value!=errorValue || value2!=errorValue) {
    261         log_err("error: %s(%s).get32(out of range) != errorValue\n",
    262                 typeName, testName);
    263     }
    264 }
    265 
    266 static void
    267 testTrieUTF16(const char *testName,
    268               const UTrie2 *trie, UTrie2ValueBits valueBits,
    269               const CheckRange checkRanges[], int32_t countCheckRanges) {
    270     UChar s[200];
    271     uint32_t values[100];
    272 
    273     const UChar *p, *limit;
    274 
    275     uint32_t value;
    276     UChar32 prevCP, c, c2;
    277     int32_t i, length, sIndex, countValues;
    278 
    279     /* write a string */
    280     prevCP=0;
    281     length=countValues=0;
    282     for(i=skipSpecialValues(checkRanges, countCheckRanges); i<countCheckRanges; ++i) {
    283         value=checkRanges[i].value;
    284         /* write three code points */
    285         U16_APPEND_UNSAFE(s, length, prevCP);   /* start of the range */
    286         values[countValues++]=value;
    287         c=checkRanges[i].limit;
    288         prevCP=(prevCP+c)/2;                    /* middle of the range */
    289         U16_APPEND_UNSAFE(s, length, prevCP);
    290         values[countValues++]=value;
    291         prevCP=c;
    292         --c;                                    /* end of the range */
    293         U16_APPEND_UNSAFE(s, length, c);
    294         values[countValues++]=value;
    295     }
    296     limit=s+length;
    297 
    298     /* try forward */
    299     p=s;
    300     i=0;
    301     while(p<limit) {
    302         sIndex=(int32_t)(p-s);
    303         U16_NEXT(s, sIndex, length, c2);
    304         c=0x33;
    305         if(valueBits==UTRIE2_16_VALUE_BITS) {
    306             UTRIE2_U16_NEXT16(trie, p, limit, c, value);
    307         } else {
    308             UTRIE2_U16_NEXT32(trie, p, limit, c, value);
    309         }
    310         if(value!=values[i]) {
    311             log_err("error: wrong value from UTRIE2_NEXT(%s)(U+%04lx): 0x%lx instead of 0x%lx\n",
    312                     testName, (long)c, (long)value, (long)values[i]);
    313         }
    314         if(c!=c2) {
    315             log_err("error: wrong code point from UTRIE2_NEXT(%s): U+%04lx != U+%04lx\n",
    316                     testName, (long)c, (long)c2);
    317             continue;
    318         }
    319         ++i;
    320     }
    321 
    322     /* try backward */
    323     p=limit;
    324     i=countValues;
    325     while(s<p) {
    326         --i;
    327         sIndex=(int32_t)(p-s);
    328         U16_PREV(s, 0, sIndex, c2);
    329         c=0x33;
    330         if(valueBits==UTRIE2_16_VALUE_BITS) {
    331             UTRIE2_U16_PREV16(trie, s, p, c, value);
    332         } else {
    333             UTRIE2_U16_PREV32(trie, s, p, c, value);
    334         }
    335         if(value!=values[i]) {
    336             log_err("error: wrong value from UTRIE2_PREV(%s)(U+%04lx): 0x%lx instead of 0x%lx\n",
    337                     testName, (long)c, (long)value, (long)values[i]);
    338         }
    339         if(c!=c2) {
    340             log_err("error: wrong code point from UTRIE2_PREV(%s): U+%04lx != U+%04lx\n",
    341                     testName, c, c2);
    342         }
    343     }
    344 }
    345 
    346 static void
    347 testTrieUTF8(const char *testName,
    348              const UTrie2 *trie, UTrie2ValueBits valueBits,
    349              const CheckRange checkRanges[], int32_t countCheckRanges) {
    350     static const uint8_t illegal[]={
    351         0xc0, 0x80,                         /* non-shortest U+0000 */
    352         0xc1, 0xbf,                         /* non-shortest U+007f */
    353         0xc2,                               /* truncated */
    354         0xe0, 0x90, 0x80,                   /* non-shortest U+0400 */
    355         0xe0, 0xa0,                         /* truncated */
    356         0xed, 0xa0, 0x80,                   /* lead surrogate U+d800 */
    357         0xed, 0xbf, 0xbf,                   /* trail surrogate U+dfff */
    358         0xf0, 0x8f, 0xbf, 0xbf,             /* non-shortest U+ffff */
    359         0xf0, 0x90, 0x80,                   /* truncated */
    360         0xf4, 0x90, 0x80, 0x80,             /* beyond-Unicode U+110000 */
    361         0xf8, 0x80, 0x80, 0x80,             /* truncated */
    362         0xf8, 0x80, 0x80, 0x80, 0x80,       /* 5-byte UTF-8 */
    363         0xfd, 0xbf, 0xbf, 0xbf, 0xbf,       /* truncated */
    364         0xfd, 0xbf, 0xbf, 0xbf, 0xbf, 0xbf, /* 6-byte UTF-8 */
    365         0xfe,
    366         0xff
    367     };
    368     uint8_t s[600];
    369     uint32_t values[200];
    370 
    371     const uint8_t *p, *limit;
    372 
    373     uint32_t initialValue, errorValue;
    374     uint32_t value, bytes;
    375     UChar32 prevCP, c;
    376     int32_t i, countSpecials, length, countValues;
    377     int32_t prev8, i8;
    378 
    379     countSpecials=getSpecialValues(checkRanges, countCheckRanges, &initialValue, &errorValue);
    380 
    381     /* write a string */
    382     prevCP=0;
    383     length=countValues=0;
    384     /* first a couple of trail bytes in lead position */
    385     s[length++]=0x80;
    386     values[countValues++]=errorValue;
    387     s[length++]=0xbf;
    388     values[countValues++]=errorValue;
    389     prev8=i8=0;
    390     for(i=countSpecials; i<countCheckRanges; ++i) {
    391         value=checkRanges[i].value;
    392         /* write three legal (or surrogate) code points */
    393         U8_APPEND_UNSAFE(s, length, prevCP);    /* start of the range */
    394         values[countValues++]=U_IS_SURROGATE(prevCP) ? errorValue : value;
    395         c=checkRanges[i].limit;
    396         prevCP=(prevCP+c)/2;                    /* middle of the range */
    397         U8_APPEND_UNSAFE(s, length, prevCP);
    398         values[countValues++]=U_IS_SURROGATE(prevCP) ? errorValue : value;
    399         prevCP=c;
    400         --c;                                    /* end of the range */
    401         U8_APPEND_UNSAFE(s, length, c);
    402         values[countValues++]=U_IS_SURROGATE(c) ? errorValue : value;
    403         /* write an illegal byte sequence */
    404         if(i8<sizeof(illegal)) {
    405             U8_FWD_1(illegal, i8, sizeof(illegal));
    406             while(prev8<i8) {
    407                 s[length++]=illegal[prev8++];
    408             }
    409             values[countValues++]=errorValue;
    410         }
    411     }
    412     /* write the remaining illegal byte sequences */
    413     while(i8<sizeof(illegal)) {
    414         U8_FWD_1(illegal, i8, sizeof(illegal));
    415         while(prev8<i8) {
    416             s[length++]=illegal[prev8++];
    417         }
    418         values[countValues++]=errorValue;
    419     }
    420     limit=s+length;
    421 
    422     /* try forward */
    423     p=s;
    424     i=0;
    425     while(p<limit) {
    426         prev8=i8=(int32_t)(p-s);
    427         U8_NEXT(s, i8, length, c);
    428         if(valueBits==UTRIE2_16_VALUE_BITS) {
    429             UTRIE2_U8_NEXT16(trie, p, limit, value);
    430         } else {
    431             UTRIE2_U8_NEXT32(trie, p, limit, value);
    432         }
    433         bytes=0;
    434         if(value!=values[i] || i8!=(p-s)) {
    435             while(prev8<i8) {
    436                 bytes=(bytes<<8)|s[prev8++];
    437             }
    438         }
    439         if(value!=values[i]) {
    440             log_err("error: wrong value from UTRIE2_U8_NEXT(%s)(%lx->U+%04lx): 0x%lx instead of 0x%lx\n",
    441                     testName, (unsigned long)bytes, (long)c, (long)value, (long)values[i]);
    442         }
    443         if(i8!=(p-s)) {
    444             log_err("error: wrong end index from UTRIE2_U8_NEXT(%s)(%lx->U+%04lx): %ld != %ld\n",
    445                     testName, (unsigned long)bytes, (long)c, (long)(p-s), (long)i8);
    446             continue;
    447         }
    448         ++i;
    449     }
    450 
    451     /* try backward */
    452     p=limit;
    453     i=countValues;
    454     while(s<p) {
    455         --i;
    456         prev8=i8=(int32_t)(p-s);
    457         U8_PREV(s, 0, i8, c);
    458         if(valueBits==UTRIE2_16_VALUE_BITS) {
    459             UTRIE2_U8_PREV16(trie, s, p, value);
    460         } else {
    461             UTRIE2_U8_PREV32(trie, s, p, value);
    462         }
    463         bytes=0;
    464         if(value!=values[i] || i8!=(p-s)) {
    465             int32_t k=i8;
    466             while(k<prev8) {
    467                 bytes=(bytes<<8)|s[k++];
    468             }
    469         }
    470         if(value!=values[i]) {
    471             log_err("error: wrong value from UTRIE2_U8_PREV(%s)(%lx->U+%04lx): 0x%lx instead of 0x%lx\n",
    472                     testName, (unsigned long)bytes, (long)c, (long)value, (long)values[i]);
    473         }
    474         if(i8!=(p-s)) {
    475             log_err("error: wrong end index from UTRIE2_U8_PREV(%s)(%lx->U+%04lx): %ld != %ld\n",
    476                     testName, (unsigned long)bytes, (long)c, (long)(p-s), (long)i8);
    477             continue;
    478         }
    479     }
    480 }
    481 
    482 static void
    483 testFrozenTrie(const char *testName,
    484                UTrie2 *trie, UTrie2ValueBits valueBits,
    485                const CheckRange checkRanges[], int32_t countCheckRanges) {
    486     UErrorCode errorCode;
    487     uint32_t value, value2;
    488 
    489     if(!utrie2_isFrozen(trie)) {
    490         log_err("error: utrie2_isFrozen(frozen %s) returned FALSE (not frozen)\n",
    491                 testName);
    492         return;
    493     }
    494 
    495     testTrieGetters(testName, trie, valueBits, checkRanges, countCheckRanges);
    496     testTrieEnum(testName, trie, checkRanges, countCheckRanges);
    497     testTrieUTF16(testName, trie, valueBits, checkRanges, countCheckRanges);
    498     testTrieUTF8(testName, trie, valueBits, checkRanges, countCheckRanges);
    499 
    500     errorCode=U_ZERO_ERROR;
    501     value=utrie2_get32(trie, 1);
    502     utrie2_set32(trie, 1, 234, &errorCode);
    503     value2=utrie2_get32(trie, 1);
    504     if(errorCode!=U_NO_WRITE_PERMISSION || value2!=value) {
    505         log_err("error: utrie2_set32(frozen %s) failed: it set %s != U_NO_WRITE_PERMISSION\n",
    506                 testName, u_errorName(errorCode));
    507         return;
    508     }
    509 
    510     errorCode=U_ZERO_ERROR;
    511     utrie2_setRange32(trie, 1, 5, 234, TRUE, &errorCode);
    512     value2=utrie2_get32(trie, 1);
    513     if(errorCode!=U_NO_WRITE_PERMISSION || value2!=value) {
    514         log_err("error: utrie2_setRange32(frozen %s) failed: it set %s != U_NO_WRITE_PERMISSION\n",
    515                 testName, u_errorName(errorCode));
    516         return;
    517     }
    518 
    519     errorCode=U_ZERO_ERROR;
    520     value=utrie2_get32FromLeadSurrogateCodeUnit(trie, 0xd801);
    521     utrie2_set32ForLeadSurrogateCodeUnit(trie, 0xd801, 234, &errorCode);
    522     value2=utrie2_get32FromLeadSurrogateCodeUnit(trie, 0xd801);
    523     if(errorCode!=U_NO_WRITE_PERMISSION || value2!=value) {
    524         log_err("error: utrie2_set32ForLeadSurrogateCodeUnit(frozen %s) failed: "
    525                 "it set %s != U_NO_WRITE_PERMISSION\n",
    526                 testName, u_errorName(errorCode));
    527         return;
    528     }
    529 }
    530 
    531 static void
    532 testNewTrie(const char *testName, const UTrie2 *trie,
    533             const CheckRange checkRanges[], int32_t countCheckRanges) {
    534     /* The valueBits are ignored for an unfrozen trie. */
    535     testTrieGetters(testName, trie, UTRIE2_COUNT_VALUE_BITS, checkRanges, countCheckRanges);
    536     testTrieEnum(testName, trie, checkRanges, countCheckRanges);
    537 }
    538 
    539 static void
    540 testTrieSerialize(const char *testName,
    541                   UTrie2 *trie, UTrie2ValueBits valueBits,
    542                   UBool withSwap,
    543                   const CheckRange checkRanges[], int32_t countCheckRanges) {
    544     uint32_t storage[10000];
    545     int32_t length1, length2, length3;
    546     UTrie2ValueBits otherValueBits;
    547     UErrorCode errorCode;
    548 
    549     /* clone the trie so that the caller can reuse the original */
    550     errorCode=U_ZERO_ERROR;
    551     trie=utrie2_clone(trie, &errorCode);
    552     if(U_FAILURE(errorCode)) {
    553         log_err("error: utrie2_clone(unfrozen %s) failed - %s\n",
    554                 testName, u_errorName(errorCode));
    555         return;
    556     }
    557 
    558     /*
    559      * This is not a loop, but simply a block that we can exit with "break"
    560      * when something goes wrong.
    561      */
    562     do {
    563         errorCode=U_ZERO_ERROR;
    564         utrie2_serialize(trie, storage, sizeof(storage), &errorCode);
    565         if(errorCode!=U_ILLEGAL_ARGUMENT_ERROR) {
    566             log_err("error: utrie2_serialize(unfrozen %s) set %s != U_ILLEGAL_ARGUMENT_ERROR\n",
    567                     testName, u_errorName(errorCode));
    568             break;
    569         }
    570         errorCode=U_ZERO_ERROR;
    571         utrie2_freeze(trie, valueBits, &errorCode);
    572         if(U_FAILURE(errorCode) || !utrie2_isFrozen(trie)) {
    573             log_err("error: utrie2_freeze(%s) failed: %s isFrozen: %d\n",
    574                     testName, u_errorName(errorCode), utrie2_isFrozen(trie));
    575             break;
    576         }
    577         otherValueBits= valueBits==UTRIE2_16_VALUE_BITS ? UTRIE2_32_VALUE_BITS : UTRIE2_16_VALUE_BITS;
    578         utrie2_freeze(trie, otherValueBits, &errorCode);
    579         if(errorCode!=U_ILLEGAL_ARGUMENT_ERROR) {
    580             log_err("error: utrie2_freeze(already-frozen with other valueBits %s) "
    581                     "set %s != U_ILLEGAL_ARGUMENT_ERROR\n",
    582                     testName, u_errorName(errorCode));
    583             break;
    584         }
    585         errorCode=U_ZERO_ERROR;
    586         if(withSwap) {
    587             /* clone a frozen trie */
    588             UTrie2 *clone=utrie2_clone(trie, &errorCode);
    589             if(U_FAILURE(errorCode)) {
    590                 log_err("error: cloning a frozen UTrie2 failed (%s) - %s\n",
    591                         testName, u_errorName(errorCode));
    592                 errorCode=U_ZERO_ERROR;  /* continue with the original */
    593             } else {
    594                 utrie2_close(trie);
    595                 trie=clone;
    596             }
    597         }
    598         length1=utrie2_serialize(trie, NULL, 0, &errorCode);
    599         if(errorCode!=U_BUFFER_OVERFLOW_ERROR) {
    600             log_err("error: utrie2_serialize(%s) preflighting set %s != U_BUFFER_OVERFLOW_ERROR\n",
    601                     testName, u_errorName(errorCode));
    602             break;
    603         }
    604         errorCode=U_ZERO_ERROR;
    605         length2=utrie2_serialize(trie, storage, sizeof(storage), &errorCode);
    606         if(errorCode==U_BUFFER_OVERFLOW_ERROR) {
    607             log_err("error: utrie2_serialize(%s) needs more memory\n", testName);
    608             break;
    609         }
    610         if(U_FAILURE(errorCode)) {
    611             log_err("error: utrie2_serialize(%s) failed: %s\n", testName, u_errorName(errorCode));
    612             break;
    613         }
    614         if(length1!=length2) {
    615             log_err("error: trie serialization (%s) lengths different: "
    616                     "preflight vs. serialize\n", testName);
    617             break;
    618         }
    619 
    620         testFrozenTrie(testName, trie, valueBits, checkRanges, countCheckRanges);
    621         utrie2_close(trie);
    622         trie=NULL;
    623 
    624         if(withSwap) {
    625             uint32_t swapped[10000];
    626             int32_t swappedLength;
    627 
    628             UDataSwapper *ds;
    629 
    630             /* swap to opposite-endian */
    631             uprv_memset(swapped, 0x55, length2);
    632             ds=udata_openSwapper(U_IS_BIG_ENDIAN, U_CHARSET_FAMILY,
    633                                  !U_IS_BIG_ENDIAN, U_CHARSET_FAMILY, &errorCode);
    634             swappedLength=utrie2_swap(ds, storage, -1, NULL, &errorCode);
    635             if(U_FAILURE(errorCode) || swappedLength!=length2) {
    636                 log_err("error: utrie2_swap(%s to OE preflighting) failed (%s) "
    637                         "or before/after lengths different\n",
    638                         testName, u_errorName(errorCode));
    639                 udata_closeSwapper(ds);
    640                 break;
    641             }
    642             swappedLength=utrie2_swap(ds, storage, length2, swapped, &errorCode);
    643             udata_closeSwapper(ds);
    644             if(U_FAILURE(errorCode) || swappedLength!=length2) {
    645                 log_err("error: utrie2_swap(%s to OE) failed (%s) or before/after lengths different\n",
    646                         testName, u_errorName(errorCode));
    647                 break;
    648             }
    649 
    650             /* swap back to platform-endian */
    651             uprv_memset(storage, 0xaa, length2);
    652             ds=udata_openSwapper(!U_IS_BIG_ENDIAN, U_CHARSET_FAMILY,
    653                                  U_IS_BIG_ENDIAN, U_CHARSET_FAMILY, &errorCode);
    654             swappedLength=utrie2_swap(ds, swapped, -1, NULL, &errorCode);
    655             if(U_FAILURE(errorCode) || swappedLength!=length2) {
    656                 log_err("error: utrie2_swap(%s to PE preflighting) failed (%s) "
    657                         "or before/after lengths different\n",
    658                         testName, u_errorName(errorCode));
    659                 udata_closeSwapper(ds);
    660                 break;
    661             }
    662             swappedLength=utrie2_swap(ds, swapped, length2, storage, &errorCode);
    663             udata_closeSwapper(ds);
    664             if(U_FAILURE(errorCode) || swappedLength!=length2) {
    665                 log_err("error: utrie2_swap(%s to PE) failed (%s) or before/after lengths different\n",
    666                         testName, u_errorName(errorCode));
    667                 break;
    668             }
    669         }
    670 
    671         trie=utrie2_openFromSerialized(valueBits, storage, length2, &length3, &errorCode);
    672         if(U_FAILURE(errorCode)) {
    673             log_err("error: utrie2_openFromSerialized(%s) failed, %s\n", testName, u_errorName(errorCode));
    674             break;
    675         }
    676         if((valueBits==UTRIE2_16_VALUE_BITS)!=(trie->data32==NULL)) {
    677             log_err("error: trie serialization (%s) did not preserve 32-bitness\n", testName);
    678             break;
    679         }
    680         if(length2!=length3) {
    681             log_err("error: trie serialization (%s) lengths different: "
    682                     "serialize vs. unserialize\n", testName);
    683             break;
    684         }
    685         /* overwrite the storage that is not supposed to be needed */
    686         uprv_memset((char *)storage+length3, 0xfa, (int32_t)(sizeof(storage)-length3));
    687 
    688         utrie2_freeze(trie, valueBits, &errorCode);
    689         if(U_FAILURE(errorCode) || !utrie2_isFrozen(trie)) {
    690             log_err("error: utrie2_freeze(unserialized %s) failed: %s isFrozen: %d\n",
    691                     testName, u_errorName(errorCode), utrie2_isFrozen(trie));
    692             break;
    693         }
    694         utrie2_freeze(trie, otherValueBits, &errorCode);
    695         if(errorCode!=U_ILLEGAL_ARGUMENT_ERROR) {
    696             log_err("error: utrie2_freeze(unserialized with other valueBits %s) "
    697                     "set %s != U_ILLEGAL_ARGUMENT_ERROR\n",
    698                     testName, u_errorName(errorCode));
    699             break;
    700         }
    701         errorCode=U_ZERO_ERROR;
    702         if(withSwap) {
    703             /* clone an unserialized trie */
    704             UTrie2 *clone=utrie2_clone(trie, &errorCode);
    705             if(U_FAILURE(errorCode)) {
    706                 log_err("error: utrie2_clone(unserialized %s) failed - %s\n",
    707                         testName, u_errorName(errorCode));
    708                 errorCode=U_ZERO_ERROR;
    709                 /* no need to break: just test the original trie */
    710             } else {
    711                 utrie2_close(trie);
    712                 trie=clone;
    713                 uprv_memset(storage, 0, sizeof(storage));
    714             }
    715         }
    716         testFrozenTrie(testName, trie, valueBits, checkRanges, countCheckRanges);
    717         {
    718             /* clone-as-thawed an unserialized trie */
    719             UTrie2 *clone=utrie2_cloneAsThawed(trie, &errorCode);
    720             if(U_FAILURE(errorCode) || utrie2_isFrozen(clone)) {
    721                 log_err("error: utrie2_cloneAsThawed(unserialized %s) failed - "
    722                         "%s (isFrozen: %d)\n",
    723                         testName, u_errorName(errorCode), clone!=NULL && utrie2_isFrozen(trie));
    724                 break;
    725             } else {
    726                 utrie2_close(trie);
    727                 trie=clone;
    728             }
    729         }
    730         {
    731             uint32_t value, value2;
    732 
    733             value=utrie2_get32(trie, 0xa1);
    734             utrie2_set32(trie, 0xa1, 789, &errorCode);
    735             value2=utrie2_get32(trie, 0xa1);
    736             utrie2_set32(trie, 0xa1, value, &errorCode);
    737             if(U_FAILURE(errorCode) || value2!=789) {
    738                 log_err("error: modifying a cloneAsThawed UTrie2 (%s) failed - %s\n",
    739                         testName, u_errorName(errorCode));
    740             }
    741         }
    742         testNewTrie(testName, trie, checkRanges, countCheckRanges);
    743     } while(0);
    744 
    745     utrie2_close(trie);
    746 }
    747 
    748 static UTrie2 *
    749 testTrieSerializeAllValueBits(const char *testName,
    750                               UTrie2 *trie, UBool withClone,
    751                               const CheckRange checkRanges[], int32_t countCheckRanges) {
    752     char name[40];
    753 
    754     /* verify that all the expected values are in the unfrozen trie */
    755     testNewTrie(testName, trie, checkRanges, countCheckRanges);
    756 
    757     /*
    758      * Test with both valueBits serializations,
    759      * and that utrie2_serialize() can be called multiple times.
    760      */
    761     uprv_strcpy(name, testName);
    762     uprv_strcat(name, ".16");
    763     testTrieSerialize(name, trie,
    764                       UTRIE2_16_VALUE_BITS, withClone,
    765                       checkRanges, countCheckRanges);
    766 
    767     if(withClone) {
    768         /*
    769          * try cloning after the first serialization;
    770          * clone-as-thawed just to sometimes try it on an unfrozen trie
    771          */
    772         UErrorCode errorCode=U_ZERO_ERROR;
    773         UTrie2 *clone=utrie2_cloneAsThawed(trie, &errorCode);
    774         if(U_FAILURE(errorCode)) {
    775             log_err("error: utrie2_cloneAsThawed(%s) after serialization failed - %s\n",
    776                     testName, u_errorName(errorCode));
    777         } else {
    778             utrie2_close(trie);
    779             trie=clone;
    780 
    781             testNewTrie(testName, trie, checkRanges, countCheckRanges);
    782         }
    783     }
    784 
    785     uprv_strcpy(name, testName);
    786     uprv_strcat(name, ".32");
    787     testTrieSerialize(name, trie,
    788                       UTRIE2_32_VALUE_BITS, withClone,
    789                       checkRanges, countCheckRanges);
    790 
    791     return trie; /* could be the clone */
    792 }
    793 
    794 static UTrie2 *
    795 makeTrieWithRanges(const char *testName, UBool withClone,
    796                    const SetRange setRanges[], int32_t countSetRanges,
    797                    const CheckRange checkRanges[], int32_t countCheckRanges) {
    798     UTrie2 *trie;
    799     uint32_t initialValue, errorValue;
    800     uint32_t value;
    801     UChar32 start, limit;
    802     int32_t i;
    803     UErrorCode errorCode;
    804     UBool overwrite;
    805 
    806     log_verbose("\ntesting Trie '%s'\n", testName);
    807     errorCode=U_ZERO_ERROR;
    808     getSpecialValues(checkRanges, countCheckRanges, &initialValue, &errorValue);
    809     trie=utrie2_open(initialValue, errorValue, &errorCode);
    810     if(U_FAILURE(errorCode)) {
    811         log_err("error: utrie2_open(%s) failed: %s\n", testName, u_errorName(errorCode));
    812         return NULL;
    813     }
    814 
    815     /* set values from setRanges[] */
    816     for(i=0; i<countSetRanges; ++i) {
    817         if(withClone && i==countSetRanges/2) {
    818             /* switch to a clone in the middle of setting values */
    819             UTrie2 *clone=utrie2_clone(trie, &errorCode);
    820             if(U_FAILURE(errorCode)) {
    821                 log_err("error: utrie2_clone(%s) failed - %s\n",
    822                         testName, u_errorName(errorCode));
    823                 errorCode=U_ZERO_ERROR;  /* continue with the original */
    824             } else {
    825                 utrie2_close(trie);
    826                 trie=clone;
    827             }
    828         }
    829         start=setRanges[i].start;
    830         limit=setRanges[i].limit;
    831         value=setRanges[i].value;
    832         overwrite=setRanges[i].overwrite;
    833         if((limit-start)==1 && overwrite) {
    834             utrie2_set32(trie, start, value, &errorCode);
    835         } else {
    836             utrie2_setRange32(trie, start, limit-1, value, overwrite, &errorCode);
    837         }
    838     }
    839 
    840     /* set some values for lead surrogate code units */
    841     utrie2_set32ForLeadSurrogateCodeUnit(trie, 0xd800, 90, &errorCode);
    842     utrie2_set32ForLeadSurrogateCodeUnit(trie, 0xd999, 94, &errorCode);
    843     utrie2_set32ForLeadSurrogateCodeUnit(trie, 0xdbff, 99, &errorCode);
    844     if(U_SUCCESS(errorCode)) {
    845         return trie;
    846     } else {
    847         log_err("error: setting values into a trie (%s) failed - %s\n",
    848                 testName, u_errorName(errorCode));
    849         utrie2_close(trie);
    850         return NULL;
    851     }
    852 }
    853 
    854 static void
    855 testTrieRanges(const char *testName, UBool withClone,
    856                const SetRange setRanges[], int32_t countSetRanges,
    857                const CheckRange checkRanges[], int32_t countCheckRanges) {
    858     UTrie2 *trie=makeTrieWithRanges(testName, withClone,
    859                                     setRanges, countSetRanges,
    860                                     checkRanges, countCheckRanges);
    861     if(trie!=NULL) {
    862         trie=testTrieSerializeAllValueBits(testName, trie, withClone,
    863                                            checkRanges, countCheckRanges);
    864         utrie2_close(trie);
    865     }
    866 }
    867 
    868 /* test data ----------------------------------------------------------------*/
    869 
    870 /* set consecutive ranges, even with value 0 */
    871 static const SetRange
    872 setRanges1[]={
    873     { 0,        0x40,     0,      FALSE },
    874     { 0x40,     0xe7,     0x1234, FALSE },
    875     { 0xe7,     0x3400,   0,      FALSE },
    876     { 0x3400,   0x9fa6,   0x6162, FALSE },
    877     { 0x9fa6,   0xda9e,   0x3132, FALSE },
    878     { 0xdada,   0xeeee,   0x87ff, FALSE },
    879     { 0xeeee,   0x11111,  1,      FALSE },
    880     { 0x11111,  0x44444,  0x6162, FALSE },
    881     { 0x44444,  0x60003,  0,      FALSE },
    882     { 0xf0003,  0xf0004,  0xf,    FALSE },
    883     { 0xf0004,  0xf0006,  0x10,   FALSE },
    884     { 0xf0006,  0xf0007,  0x11,   FALSE },
    885     { 0xf0007,  0xf0040,  0x12,   FALSE },
    886     { 0xf0040,  0x110000, 0,      FALSE }
    887 };
    888 
    889 static const CheckRange
    890 checkRanges1[]={
    891     { 0,        0 },
    892     { 0x40,     0 },
    893     { 0xe7,     0x1234 },
    894     { 0x3400,   0 },
    895     { 0x9fa6,   0x6162 },
    896     { 0xda9e,   0x3132 },
    897     { 0xdada,   0 },
    898     { 0xeeee,   0x87ff },
    899     { 0x11111,  1 },
    900     { 0x44444,  0x6162 },
    901     { 0xf0003,  0 },
    902     { 0xf0004,  0xf },
    903     { 0xf0006,  0x10 },
    904     { 0xf0007,  0x11 },
    905     { 0xf0040,  0x12 },
    906     { 0x110000, 0 }
    907 };
    908 
    909 /* set some interesting overlapping ranges */
    910 static const SetRange
    911 setRanges2[]={
    912     { 0x21,     0x7f,     0x5555, TRUE },
    913     { 0x2f800,  0x2fedc,  0x7a,   TRUE },
    914     { 0x72,     0xdd,     3,      TRUE },
    915     { 0xdd,     0xde,     4,      FALSE },
    916     { 0x201,    0x240,    6,      TRUE },  /* 3 consecutive blocks with the same pattern but */
    917     { 0x241,    0x280,    6,      TRUE },  /* discontiguous value ranges, testing utrie2_enum() */
    918     { 0x281,    0x2c0,    6,      TRUE },
    919     { 0x2f987,  0x2fa98,  5,      TRUE },
    920     { 0x2f777,  0x2f883,  0,      TRUE },
    921     { 0x2f900,  0x2ffaa,  1,      FALSE },
    922     { 0x2ffaa,  0x2ffab,  2,      TRUE },
    923     { 0x2ffbb,  0x2ffc0,  7,      TRUE }
    924 };
    925 
    926 static const CheckRange
    927 checkRanges2[]={
    928     { 0,        0 },
    929     { 0x21,     0 },
    930     { 0x72,     0x5555 },
    931     { 0xdd,     3 },
    932     { 0xde,     4 },
    933     { 0x201,    0 },
    934     { 0x240,    6 },
    935     { 0x241,    0 },
    936     { 0x280,    6 },
    937     { 0x281,    0 },
    938     { 0x2c0,    6 },
    939     { 0x2f883,  0 },
    940     { 0x2f987,  0x7a },
    941     { 0x2fa98,  5 },
    942     { 0x2fedc,  0x7a },
    943     { 0x2ffaa,  1 },
    944     { 0x2ffab,  2 },
    945     { 0x2ffbb,  0 },
    946     { 0x2ffc0,  7 },
    947     { 0x110000, 0 }
    948 };
    949 
    950 static const CheckRange
    951 checkRanges2_d800[]={
    952     { 0x10000,  0 },
    953     { 0x10400,  0 }
    954 };
    955 
    956 static const CheckRange
    957 checkRanges2_d87e[]={
    958     { 0x2f800,  6 },
    959     { 0x2f883,  0 },
    960     { 0x2f987,  0x7a },
    961     { 0x2fa98,  5 },
    962     { 0x2fc00,  0x7a }
    963 };
    964 
    965 static const CheckRange
    966 checkRanges2_d87f[]={
    967     { 0x2fc00,  0 },
    968     { 0x2fedc,  0x7a },
    969     { 0x2ffaa,  1 },
    970     { 0x2ffab,  2 },
    971     { 0x2ffbb,  0 },
    972     { 0x2ffc0,  7 },
    973     { 0x30000,  0 }
    974 };
    975 
    976 static const CheckRange
    977 checkRanges2_dbff[]={
    978     { 0x10fc00, 0 },
    979     { 0x110000, 0 }
    980 };
    981 
    982 /* use a non-zero initial value */
    983 static const SetRange
    984 setRanges3[]={
    985     { 0x31,     0xa4,     1, FALSE },
    986     { 0x3400,   0x6789,   2, FALSE },
    987     { 0x8000,   0x89ab,   9, TRUE },
    988     { 0x9000,   0xa000,   4, TRUE },
    989     { 0xabcd,   0xbcde,   3, TRUE },
    990     { 0x55555,  0x110000, 6, TRUE },  /* highStart<U+ffff with non-initialValue */
    991     { 0xcccc,   0x55555,  6, TRUE }
    992 };
    993 
    994 static const CheckRange
    995 checkRanges3[]={
    996     { 0,        9 },  /* non-zero initialValue */
    997     { 0x31,     9 },
    998     { 0xa4,     1 },
    999     { 0x3400,   9 },
   1000     { 0x6789,   2 },
   1001     { 0x9000,   9 },
   1002     { 0xa000,   4 },
   1003     { 0xabcd,   9 },
   1004     { 0xbcde,   3 },
   1005     { 0xcccc,   9 },
   1006     { 0x110000, 6 }
   1007 };
   1008 
   1009 /* empty or single-value tries, testing highStart==0 */
   1010 static const SetRange
   1011 setRangesEmpty[]={
   1012     { 0,        0,        0, FALSE },  /* need some values for it to compile */
   1013 };
   1014 
   1015 static const CheckRange
   1016 checkRangesEmpty[]={
   1017     { 0,        3 },
   1018     { 0x110000, 3 }
   1019 };
   1020 
   1021 static const SetRange
   1022 setRangesSingleValue[]={
   1023     { 0,        0x110000, 5, TRUE },
   1024 };
   1025 
   1026 static const CheckRange
   1027 checkRangesSingleValue[]={
   1028     { 0,        3 },
   1029     { 0x110000, 5 }
   1030 };
   1031 
   1032 static void
   1033 TrieTest(void) {
   1034     testTrieRanges("set1", FALSE,
   1035         setRanges1, UPRV_LENGTHOF(setRanges1),
   1036         checkRanges1, UPRV_LENGTHOF(checkRanges1));
   1037     testTrieRanges("set2-overlap", FALSE,
   1038         setRanges2, UPRV_LENGTHOF(setRanges2),
   1039         checkRanges2, UPRV_LENGTHOF(checkRanges2));
   1040     testTrieRanges("set3-initial-9", FALSE,
   1041         setRanges3, UPRV_LENGTHOF(setRanges3),
   1042         checkRanges3, UPRV_LENGTHOF(checkRanges3));
   1043     testTrieRanges("set-empty", FALSE,
   1044         setRangesEmpty, 0,
   1045         checkRangesEmpty, UPRV_LENGTHOF(checkRangesEmpty));
   1046     testTrieRanges("set-single-value", FALSE,
   1047         setRangesSingleValue, UPRV_LENGTHOF(setRangesSingleValue),
   1048         checkRangesSingleValue, UPRV_LENGTHOF(checkRangesSingleValue));
   1049 
   1050     testTrieRanges("set2-overlap.withClone", TRUE,
   1051         setRanges2, UPRV_LENGTHOF(setRanges2),
   1052         checkRanges2, UPRV_LENGTHOF(checkRanges2));
   1053 }
   1054 
   1055 static void
   1056 EnumNewTrieForLeadSurrogateTest(void) {
   1057     static const char *const testName="enum-for-lead";
   1058     UTrie2 *trie=makeTrieWithRanges(testName, FALSE,
   1059                                     setRanges2, UPRV_LENGTHOF(setRanges2),
   1060                                     checkRanges2, UPRV_LENGTHOF(checkRanges2));
   1061     while(trie!=NULL) {
   1062         const CheckRange *checkRanges;
   1063 
   1064         checkRanges=checkRanges2_d800+1;
   1065         utrie2_enumForLeadSurrogate(trie, 0xd800,
   1066                                     testEnumValue, testEnumRange,
   1067                                     &checkRanges);
   1068         checkRanges=checkRanges2_d87e+1;
   1069         utrie2_enumForLeadSurrogate(trie, 0xd87e,
   1070                                     testEnumValue, testEnumRange,
   1071                                     &checkRanges);
   1072         checkRanges=checkRanges2_d87f+1;
   1073         utrie2_enumForLeadSurrogate(trie, 0xd87f,
   1074                                     testEnumValue, testEnumRange,
   1075                                     &checkRanges);
   1076         checkRanges=checkRanges2_dbff+1;
   1077         utrie2_enumForLeadSurrogate(trie, 0xdbff,
   1078                                     testEnumValue, testEnumRange,
   1079                                     &checkRanges);
   1080         if(!utrie2_isFrozen(trie)) {
   1081             UErrorCode errorCode=U_ZERO_ERROR;
   1082             utrie2_freeze(trie, UTRIE2_16_VALUE_BITS, &errorCode);
   1083             if(U_FAILURE(errorCode)) {
   1084                 log_err("error: utrie2_freeze(%s) failed\n", testName);
   1085                 utrie2_close(trie);
   1086                 return;
   1087             }
   1088         } else {
   1089             utrie2_close(trie);
   1090             break;
   1091         }
   1092     }
   1093 }
   1094 
   1095 /* test utrie2_openDummy() -------------------------------------------------- */
   1096 
   1097 static void
   1098 dummyTest(UTrie2ValueBits valueBits) {
   1099     CheckRange
   1100     checkRanges[]={
   1101         { -1,       0 },
   1102         { 0,        0 },
   1103         { 0x110000, 0 }
   1104     };
   1105 
   1106     UTrie2 *trie;
   1107     UErrorCode errorCode;
   1108 
   1109     const char *testName;
   1110     uint32_t initialValue, errorValue;
   1111 
   1112     if(valueBits==UTRIE2_16_VALUE_BITS) {
   1113         testName="dummy.16";
   1114         initialValue=0x313;
   1115         errorValue=0xaffe;
   1116     } else {
   1117         testName="dummy.32";
   1118         initialValue=0x01234567;
   1119         errorValue=0x89abcdef;
   1120     }
   1121     checkRanges[0].value=errorValue;
   1122     checkRanges[1].value=checkRanges[2].value=initialValue;
   1123 
   1124     errorCode=U_ZERO_ERROR;
   1125     trie=utrie2_openDummy(valueBits, initialValue, errorValue, &errorCode);
   1126     if(U_FAILURE(errorCode)) {
   1127         log_err("utrie2_openDummy(valueBits=%d) failed - %s\n", valueBits, u_errorName(errorCode));
   1128         return;
   1129     }
   1130 
   1131     testFrozenTrie(testName, trie, valueBits, checkRanges, UPRV_LENGTHOF(checkRanges));
   1132     utrie2_close(trie);
   1133 }
   1134 
   1135 static void
   1136 DummyTrieTest(void) {
   1137     dummyTest(UTRIE2_16_VALUE_BITS);
   1138     dummyTest(UTRIE2_32_VALUE_BITS);
   1139 }
   1140 
   1141 /* test builder memory management ------------------------------------------- */
   1142 
   1143 static void
   1144 FreeBlocksTest(void) {
   1145     static const CheckRange
   1146     checkRanges[]={
   1147         { 0,        1 },
   1148         { 0x740,    1 },
   1149         { 0x780,    2 },
   1150         { 0x880,    3 },
   1151         { 0x110000, 1 }
   1152     };
   1153     static const char *const testName="free-blocks";
   1154 
   1155     UTrie2 *trie;
   1156     int32_t i;
   1157     UErrorCode errorCode;
   1158 
   1159     errorCode=U_ZERO_ERROR;
   1160     trie=utrie2_open(1, 0xbad, &errorCode);
   1161     if(U_FAILURE(errorCode)) {
   1162         log_err("error: utrie2_open(%s) failed: %s\n", testName, u_errorName(errorCode));
   1163         return;
   1164     }
   1165 
   1166     /*
   1167      * Repeatedly set overlapping same-value ranges to stress the free-data-block management.
   1168      * If it fails, it will overflow the data array.
   1169      */
   1170     for(i=0; i<(0x120000>>UTRIE2_SHIFT_2)/2; ++i) {
   1171         utrie2_setRange32(trie, 0x740, 0x840-1, 1, TRUE, &errorCode);
   1172         utrie2_setRange32(trie, 0x780, 0x880-1, 1, TRUE, &errorCode);
   1173         utrie2_setRange32(trie, 0x740, 0x840-1, 2, TRUE, &errorCode);
   1174         utrie2_setRange32(trie, 0x780, 0x880-1, 3, TRUE, &errorCode);
   1175     }
   1176     /* make blocks that will be free during compaction */
   1177     utrie2_setRange32(trie, 0x1000, 0x3000-1, 2, TRUE, &errorCode);
   1178     utrie2_setRange32(trie, 0x2000, 0x4000-1, 3, TRUE, &errorCode);
   1179     utrie2_setRange32(trie, 0x1000, 0x4000-1, 1, TRUE, &errorCode);
   1180     /* set some values for lead surrogate code units */
   1181     utrie2_set32ForLeadSurrogateCodeUnit(trie, 0xd800, 90, &errorCode);
   1182     utrie2_set32ForLeadSurrogateCodeUnit(trie, 0xd999, 94, &errorCode);
   1183     utrie2_set32ForLeadSurrogateCodeUnit(trie, 0xdbff, 99, &errorCode);
   1184     if(U_FAILURE(errorCode)) {
   1185         log_err("error: setting lots of ranges into a trie (%s) failed - %s\n",
   1186                 testName, u_errorName(errorCode));
   1187         utrie2_close(trie);
   1188         return;
   1189     }
   1190 
   1191     trie=testTrieSerializeAllValueBits(testName, trie, FALSE,
   1192                                        checkRanges, UPRV_LENGTHOF(checkRanges));
   1193     utrie2_close(trie);
   1194 }
   1195 
   1196 static void
   1197 GrowDataArrayTest(void) {
   1198     static const CheckRange
   1199     checkRanges[]={
   1200         { 0,        1 },
   1201         { 0x720,    2 },
   1202         { 0x7a0,    3 },
   1203         { 0x8a0,    4 },
   1204         { 0x110000, 5 }
   1205     };
   1206     static const char *const testName="grow-data";
   1207 
   1208     UTrie2 *trie;
   1209     int32_t i;
   1210     UErrorCode errorCode;
   1211 
   1212     errorCode=U_ZERO_ERROR;
   1213     trie=utrie2_open(1, 0xbad, &errorCode);
   1214     if(U_FAILURE(errorCode)) {
   1215         log_err("error: utrie2_open(%s) failed: %s\n", testName, u_errorName(errorCode));
   1216         return;
   1217     }
   1218 
   1219     /*
   1220      * Use utrie2_set32() not utrie2_setRange32() to write non-initialValue-data.
   1221      * Should grow/reallocate the data array to a sufficient length.
   1222      */
   1223     for(i=0; i<0x1000; ++i) {
   1224         utrie2_set32(trie, i, 2, &errorCode);
   1225     }
   1226     for(i=0x720; i<0x1100; ++i) { /* some overlap */
   1227         utrie2_set32(trie, i, 3, &errorCode);
   1228     }
   1229     for(i=0x7a0; i<0x900; ++i) {
   1230         utrie2_set32(trie, i, 4, &errorCode);
   1231     }
   1232     for(i=0x8a0; i<0x110000; ++i) {
   1233         utrie2_set32(trie, i, 5, &errorCode);
   1234     }
   1235     for(i=0xd800; i<0xdc00; ++i) {
   1236         utrie2_set32ForLeadSurrogateCodeUnit(trie, i, 1, &errorCode);
   1237     }
   1238     /* set some values for lead surrogate code units */
   1239     utrie2_set32ForLeadSurrogateCodeUnit(trie, 0xd800, 90, &errorCode);
   1240     utrie2_set32ForLeadSurrogateCodeUnit(trie, 0xd999, 94, &errorCode);
   1241     utrie2_set32ForLeadSurrogateCodeUnit(trie, 0xdbff, 99, &errorCode);
   1242     if(U_FAILURE(errorCode)) {
   1243         log_err("error: setting lots of values into a trie (%s) failed - %s\n",
   1244                 testName, u_errorName(errorCode));
   1245         utrie2_close(trie);
   1246         return;
   1247     }
   1248 
   1249     trie=testTrieSerializeAllValueBits(testName, trie, FALSE,
   1250                                           checkRanges, UPRV_LENGTHOF(checkRanges));
   1251     utrie2_close(trie);
   1252 }
   1253 
   1254 /* versions 1 and 2 --------------------------------------------------------- */
   1255 
   1256 static void
   1257 GetVersionTest(void) {
   1258     uint32_t data[4];
   1259     if( /* version 1 */
   1260         (data[0]=0x54726965, 1!=utrie2_getVersion(data, sizeof(data), FALSE)) ||
   1261         (data[0]=0x54726965, 1!=utrie2_getVersion(data, sizeof(data), TRUE)) ||
   1262         (data[0]=0x65697254, 0!=utrie2_getVersion(data, sizeof(data), FALSE)) ||
   1263         (data[0]=0x65697254, 1!=utrie2_getVersion(data, sizeof(data), TRUE)) ||
   1264         /* version 2 */
   1265         (data[0]=0x54726932, 2!=utrie2_getVersion(data, sizeof(data), FALSE)) ||
   1266         (data[0]=0x54726932, 2!=utrie2_getVersion(data, sizeof(data), TRUE)) ||
   1267         (data[0]=0x32697254, 0!=utrie2_getVersion(data, sizeof(data), FALSE)) ||
   1268         (data[0]=0x32697254, 2!=utrie2_getVersion(data, sizeof(data), TRUE)) ||
   1269         /* illegal arguments */
   1270         (data[0]=0x54726932, 0!=utrie2_getVersion(NULL, sizeof(data), FALSE)) ||
   1271         (data[0]=0x54726932, 0!=utrie2_getVersion(data, 3, FALSE)) ||
   1272         (data[0]=0x54726932, 0!=utrie2_getVersion((char *)data+1, sizeof(data), FALSE)) ||
   1273         /* unknown signature values */
   1274         (data[0]=0x11223344, 0!=utrie2_getVersion(data, sizeof(data), FALSE)) ||
   1275         (data[0]=0x54726933, 0!=utrie2_getVersion(data, sizeof(data), FALSE))
   1276     ) {
   1277         log_err("error: utrie2_getVersion() is not working as expected\n");
   1278     }
   1279 }
   1280 
   1281 static UNewTrie *
   1282 makeNewTrie1WithRanges(const char *testName,
   1283                        const SetRange setRanges[], int32_t countSetRanges,
   1284                        const CheckRange checkRanges[], int32_t countCheckRanges) {
   1285     UNewTrie *newTrie;
   1286     uint32_t initialValue, errorValue;
   1287     uint32_t value;
   1288     UChar32 start, limit;
   1289     int32_t i;
   1290     UErrorCode errorCode;
   1291     UBool overwrite, ok;
   1292 
   1293     log_verbose("\ntesting Trie '%s'\n", testName);
   1294     errorCode=U_ZERO_ERROR;
   1295     getSpecialValues(checkRanges, countCheckRanges, &initialValue, &errorValue);
   1296     newTrie=utrie_open(NULL, NULL, 2000,
   1297                        initialValue, initialValue,
   1298                        FALSE);
   1299     if(U_FAILURE(errorCode)) {
   1300         log_err("error: utrie_open(%s) failed: %s\n", testName, u_errorName(errorCode));
   1301         return NULL;
   1302     }
   1303 
   1304     /* set values from setRanges[] */
   1305     ok=TRUE;
   1306     for(i=0; i<countSetRanges; ++i) {
   1307         start=setRanges[i].start;
   1308         limit=setRanges[i].limit;
   1309         value=setRanges[i].value;
   1310         overwrite=setRanges[i].overwrite;
   1311         if((limit-start)==1 && overwrite) {
   1312             ok&=utrie_set32(newTrie, start, value);
   1313         } else {
   1314             ok&=utrie_setRange32(newTrie, start, limit, value, overwrite);
   1315         }
   1316     }
   1317     if(ok) {
   1318         return newTrie;
   1319     } else {
   1320         log_err("error: setting values into a trie1 (%s) failed\n", testName);
   1321         utrie_close(newTrie);
   1322         return NULL;
   1323     }
   1324 }
   1325 
   1326 static void
   1327 testTrie2FromTrie1(const char *testName,
   1328                    const SetRange setRanges[], int32_t countSetRanges,
   1329                    const CheckRange checkRanges[], int32_t countCheckRanges) {
   1330     uint32_t memory1_16[3000], memory1_32[3000];
   1331     int32_t length16, length32;
   1332     UChar lead;
   1333 
   1334     char name[40];
   1335 
   1336     UNewTrie *newTrie1_16, *newTrie1_32;
   1337     UTrie trie1_16, trie1_32;
   1338     UTrie2 *trie2;
   1339     uint32_t initialValue, errorValue;
   1340     UErrorCode errorCode;
   1341 
   1342     newTrie1_16=makeNewTrie1WithRanges(testName,
   1343                                        setRanges, countSetRanges,
   1344                                        checkRanges, countCheckRanges);
   1345     if(newTrie1_16==NULL) {
   1346         return;
   1347     }
   1348     newTrie1_32=utrie_clone(NULL, newTrie1_16, NULL, 0);
   1349     if(newTrie1_32==NULL) {
   1350         utrie_close(newTrie1_16);
   1351         return;
   1352     }
   1353     errorCode=U_ZERO_ERROR;
   1354     length16=utrie_serialize(newTrie1_16, memory1_16, sizeof(memory1_16),
   1355                              NULL, TRUE, &errorCode);
   1356     length32=utrie_serialize(newTrie1_32, memory1_32, sizeof(memory1_32),
   1357                              NULL, FALSE, &errorCode);
   1358     utrie_unserialize(&trie1_16, memory1_16, length16, &errorCode);
   1359     utrie_unserialize(&trie1_32, memory1_32, length32, &errorCode);
   1360     utrie_close(newTrie1_16);
   1361     utrie_close(newTrie1_32);
   1362     if(U_FAILURE(errorCode)) {
   1363         log_err("error: utrie_serialize or unserialize(%s) failed: %s\n",
   1364                 testName, u_errorName(errorCode));
   1365         return;
   1366     }
   1367 
   1368     getSpecialValues(checkRanges, countCheckRanges, &initialValue, &errorValue);
   1369 
   1370     uprv_strcpy(name, testName);
   1371     uprv_strcat(name, ".16");
   1372     trie2=utrie2_fromUTrie(&trie1_16, errorValue, &errorCode);
   1373     if(U_SUCCESS(errorCode)) {
   1374         testFrozenTrie(name, trie2, UTRIE2_16_VALUE_BITS, checkRanges, countCheckRanges);
   1375         for(lead=0xd800; lead<0xdc00; ++lead) {
   1376             uint32_t value1, value2;
   1377             value1=UTRIE_GET16_FROM_LEAD(&trie1_16, lead);
   1378             value2=UTRIE2_GET16_FROM_U16_SINGLE_LEAD(trie2, lead);
   1379             if(value1!=value2) {
   1380                 log_err("error: utrie2_fromUTrie(%s) wrong value %ld!=%ld "
   1381                         "from lead surrogate code unit U+%04lx\n",
   1382                         name, (long)value2, (long)value1, (long)lead);
   1383                 break;
   1384             }
   1385         }
   1386     }
   1387     utrie2_close(trie2);
   1388 
   1389     uprv_strcpy(name, testName);
   1390     uprv_strcat(name, ".32");
   1391     trie2=utrie2_fromUTrie(&trie1_32, errorValue, &errorCode);
   1392     if(U_SUCCESS(errorCode)) {
   1393         testFrozenTrie(name, trie2, UTRIE2_32_VALUE_BITS, checkRanges, countCheckRanges);
   1394         for(lead=0xd800; lead<0xdc00; ++lead) {
   1395             uint32_t value1, value2;
   1396             value1=UTRIE_GET32_FROM_LEAD(&trie1_32, lead);
   1397             value2=UTRIE2_GET32_FROM_U16_SINGLE_LEAD(trie2, lead);
   1398             if(value1!=value2) {
   1399                 log_err("error: utrie2_fromUTrie(%s) wrong value %ld!=%ld "
   1400                         "from lead surrogate code unit U+%04lx\n",
   1401                         name, (long)value2, (long)value1, (long)lead);
   1402                 break;
   1403             }
   1404         }
   1405     }
   1406     utrie2_close(trie2);
   1407 }
   1408 
   1409 static void
   1410 Trie12ConversionTest(void) {
   1411     testTrie2FromTrie1("trie1->trie2",
   1412                        setRanges2, UPRV_LENGTHOF(setRanges2),
   1413                        checkRanges2, UPRV_LENGTHOF(checkRanges2));
   1414 }
   1415 
   1416 void
   1417 addTrie2Test(TestNode** root) {
   1418     addTest(root, &TrieTest, "tsutil/trie2test/TrieTest");
   1419     addTest(root, &EnumNewTrieForLeadSurrogateTest,
   1420                   "tsutil/trie2test/EnumNewTrieForLeadSurrogateTest");
   1421     addTest(root, &DummyTrieTest, "tsutil/trie2test/DummyTrieTest");
   1422     addTest(root, &FreeBlocksTest, "tsutil/trie2test/FreeBlocksTest");
   1423     addTest(root, &GrowDataArrayTest, "tsutil/trie2test/GrowDataArrayTest");
   1424     addTest(root, &GetVersionTest, "tsutil/trie2test/GetVersionTest");
   1425     addTest(root, &Trie12ConversionTest, "tsutil/trie2test/Trie12ConversionTest");
   1426 }
   1427