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