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: 2001nov20
     14 *   created by: Markus W. Scherer
     15 */
     16 
     17 #include <stdio.h>
     18 #include "unicode/utypes.h"
     19 #include "utrie.h"
     20 #include "cstring.h"
     21 #include "cmemory.h"
     22 
     23 #if 1
     24 #include "cintltst.h"
     25 #else
     26 /* definitions from standalone utrie development */
     27 #define log_err printf
     28 #define log_verbose printf
     29 
     30 #undef u_errorName
     31 #define u_errorName(errorCode) "some error code"
     32 #endif
     33 
     34 #define ARRAY_LENGTH(array) (sizeof(array)/sizeof(array[0]))
     35 
     36 /* Values for setting possibly overlapping, out-of-order ranges of values */
     37 typedef struct SetRange {
     38     UChar32 start, limit;
     39     uint32_t value;
     40     UBool overwrite;
     41 } SetRange;
     42 
     43 /*
     44  * Values for testing:
     45  * value is set from the previous boundary's limit to before
     46  * this boundary's limit
     47  */
     48 typedef struct CheckRange {
     49     UChar32 limit;
     50     uint32_t value;
     51 } CheckRange;
     52 
     53 
     54 static uint32_t U_CALLCONV
     55 _testFoldedValue32(UNewTrie *trie, UChar32 start, int32_t offset) {
     56     uint32_t foldedValue, value;
     57     UChar32 limit;
     58     UBool inBlockZero;
     59 
     60     foldedValue=0;
     61 
     62     limit=start+0x400;
     63     while(start<limit) {
     64         value=utrie_get32(trie, start, &inBlockZero);
     65         if(inBlockZero) {
     66             start+=UTRIE_DATA_BLOCK_LENGTH;
     67         } else {
     68             foldedValue|=value;
     69             ++start;
     70         }
     71     }
     72 
     73     if(foldedValue!=0) {
     74         return ((uint32_t)offset<<16)|foldedValue;
     75     } else {
     76         return 0;
     77     }
     78 }
     79 
     80 static int32_t U_CALLCONV
     81 _testFoldingOffset32(uint32_t data) {
     82     return (int32_t)(data>>16);
     83 }
     84 
     85 static uint32_t U_CALLCONV
     86 _testFoldedValue16(UNewTrie *trie, UChar32 start, int32_t offset) {
     87     uint32_t foldedValue, value;
     88     UChar32 limit;
     89     UBool inBlockZero;
     90 
     91     foldedValue=0;
     92 
     93     limit=start+0x400;
     94     while(start<limit) {
     95         value=utrie_get32(trie, start, &inBlockZero);
     96         if(inBlockZero) {
     97             start+=UTRIE_DATA_BLOCK_LENGTH;
     98         } else {
     99             foldedValue|=value;
    100             ++start;
    101         }
    102     }
    103 
    104     if(foldedValue!=0) {
    105         return (uint32_t)(offset|0x8000);
    106     } else {
    107         return 0;
    108     }
    109 }
    110 
    111 static int32_t U_CALLCONV
    112 _testFoldingOffset16(uint32_t data) {
    113     if(data&0x8000) {
    114         return (int32_t)(data&0x7fff);
    115     } else {
    116         return 0;
    117     }
    118 }
    119 
    120 static uint32_t U_CALLCONV
    121 _testEnumValue(const void *context, uint32_t value) {
    122     return value^0x5555;
    123 }
    124 
    125 static UBool U_CALLCONV
    126 _testEnumRange(const void *context, UChar32 start, UChar32 limit, uint32_t value) {
    127     const CheckRange **pb=(const CheckRange **)context;
    128     const CheckRange *b=(*pb)++;
    129 
    130     value^=0x5555;
    131     if(start!=(b-1)->limit || limit!=b->limit || value!=b->value) {
    132         log_err("error: utrie_enum() delivers wrong range [U+%04lx..U+%04lx[.0x%lx instead of [U+%04lx..U+%04lx[.0x%lx\n",
    133             start, limit, value,
    134             (b-1)->limit, b->limit, b->value);
    135     }
    136     return TRUE;
    137 }
    138 
    139 static void
    140 testTrieIteration(const char *testName,
    141                   const UTrie *trie,
    142                   const CheckRange checkRanges[], int32_t countCheckRanges) {
    143     UChar s[100];
    144     uint32_t values[30];
    145 
    146     const UChar *p, *limit;
    147 
    148     uint32_t value;
    149     UChar32 c;
    150     int32_t i, length, countValues;
    151     UChar c2;
    152 
    153     /* write a string */
    154     length=countValues=0;
    155     for(i=0; i<countCheckRanges; ++i) {
    156         c=checkRanges[i].limit;
    157         if(c!=0) {
    158             --c;
    159             UTF_APPEND_CHAR_UNSAFE(s, length, c);
    160             values[countValues++]=checkRanges[i].value;
    161         }
    162     }
    163     limit=s+length;
    164 
    165     /* try forward */
    166     p=s;
    167     i=0;
    168     while(p<limit) {
    169         c=c2=0x33;
    170         if(trie->data32!=NULL) {
    171             UTRIE_NEXT32(trie, p, limit, c, c2, value);
    172         } else {
    173             UTRIE_NEXT16(trie, p, limit, c, c2, value);
    174         }
    175         if(value!=values[i]) {
    176             log_err("error: wrong value from UTRIE_NEXT(%s)(U+%04lx, U+%04lx): 0x%lx instead of 0x%lx\n",
    177                     testName, c, c2, value, values[i]);
    178         }
    179         if(
    180             c2==0 ?
    181                 c!=*(p-1) :
    182                 !UTF_IS_LEAD(c) || !UTF_IS_TRAIL(c2) || c!=*(p-2) || c2!=*(p-1)
    183         ) {
    184             log_err("error: wrong (c, c2) from UTRIE_NEXT(%s): (U+%04lx, U+%04lx)\n",
    185                     testName, c, c2);
    186             continue;
    187         }
    188         if(c2!=0) {
    189             int32_t offset;
    190 
    191             if(trie->data32==NULL) {
    192                 value=UTRIE_GET16_FROM_LEAD(trie, c);
    193                 offset=trie->getFoldingOffset(value);
    194                 if(offset>0) {
    195                     value=UTRIE_GET16_FROM_OFFSET_TRAIL(trie, offset, c2);
    196                 } else {
    197                     value=trie->initialValue;
    198                 }
    199             } else {
    200                 value=UTRIE_GET32_FROM_LEAD(trie, c);
    201                 offset=trie->getFoldingOffset(value);
    202                 if(offset>0) {
    203                     value=UTRIE_GET32_FROM_OFFSET_TRAIL(trie, offset, c2);
    204                 } else {
    205                     value=trie->initialValue;
    206                 }
    207             }
    208             if(value!=values[i]) {
    209                 log_err("error: wrong value from UTRIE_GETXX_FROM_OFFSET_TRAIL(%s)(U+%04lx, U+%04lx): 0x%lx instead of 0x%lx\n",
    210                         testName, c, c2, value, values[i]);
    211             }
    212         }
    213         if(c2!=0) {
    214             value=0x44;
    215             if(trie->data32==NULL) {
    216                 UTRIE_GET16_FROM_PAIR(trie, c, c2, value);
    217             } else {
    218                 UTRIE_GET32_FROM_PAIR(trie, c, c2, value);
    219             }
    220             if(value!=values[i]) {
    221                 log_err("error: wrong value from UTRIE_GETXX_FROM_PAIR(%s)(U+%04lx, U+%04lx): 0x%lx instead of 0x%lx\n",
    222                         testName, c, c2, value, values[i]);
    223             }
    224         }
    225         ++i;
    226     }
    227 
    228     /* try backward */
    229     p=limit;
    230     i=countValues;
    231     while(s<p) {
    232         --i;
    233         c=c2=0x33;
    234         if(trie->data32!=NULL) {
    235             UTRIE_PREVIOUS32(trie, s, p, c, c2, value);
    236         } else {
    237             UTRIE_PREVIOUS16(trie, s, p, c, c2, value);
    238         }
    239         if(value!=values[i]) {
    240             log_err("error: wrong value from UTRIE_PREVIOUS(%s)(U+%04lx, U+%04lx): 0x%lx instead of 0x%lx\n",
    241                     testName, c, c2, value, values[i]);
    242         }
    243         if(
    244             c2==0 ?
    245                 c!=*p:
    246                 !UTF_IS_LEAD(c) || !UTF_IS_TRAIL(c2) || c!=*p || c2!=*(p+1)
    247         ) {
    248             log_err("error: wrong (c, c2) from UTRIE_PREVIOUS(%s): (U+%04lx, U+%04lx)\n",
    249                     testName, c, c2);
    250         }
    251     }
    252 }
    253 
    254 static void
    255 testTrieRangesWithMalloc(const char *testName,
    256                const SetRange setRanges[], int32_t countSetRanges,
    257                const CheckRange checkRanges[], int32_t countCheckRanges,
    258                UBool dataIs32, UBool latin1Linear) {
    259     UTrieGetFoldingOffset *getFoldingOffset;
    260     const CheckRange *enumRanges;
    261     UNewTrie *newTrie;
    262     UTrie trie={ 0 };
    263     uint32_t value, value2;
    264     UChar32 start, limit;
    265     int32_t i, length;
    266     UErrorCode errorCode;
    267     UBool overwrite, ok;
    268     uint8_t* storage =NULL;
    269     static const int32_t DEFAULT_STORAGE_SIZE = 32768;
    270     storage = (uint8_t*) uprv_malloc(sizeof(uint8_t)*DEFAULT_STORAGE_SIZE);
    271 
    272     log_verbose("\ntesting Trie '%s'\n", testName);
    273     newTrie=utrie_open(NULL, NULL, 2000,
    274                        checkRanges[0].value, checkRanges[0].value,
    275                        latin1Linear);
    276 
    277     /* set values from setRanges[] */
    278     ok=TRUE;
    279     for(i=0; i<countSetRanges; ++i) {
    280         start=setRanges[i].start;
    281         limit=setRanges[i].limit;
    282         value=setRanges[i].value;
    283         overwrite=setRanges[i].overwrite;
    284         if((limit-start)==1 && overwrite) {
    285             ok&=utrie_set32(newTrie, start, value);
    286         } else {
    287             ok&=utrie_setRange32(newTrie, start, limit, value, overwrite);
    288         }
    289     }
    290     if(!ok) {
    291         log_err("error: setting values into a trie failed (%s)\n", testName);
    292         return;
    293     }
    294 
    295     /* verify that all these values are in the new Trie */
    296     start=0;
    297     for(i=0; i<countCheckRanges; ++i) {
    298         limit=checkRanges[i].limit;
    299         value=checkRanges[i].value;
    300 
    301         while(start<limit) {
    302             if(value!=utrie_get32(newTrie, start, NULL)) {
    303                 log_err("error: newTrie(%s)[U+%04lx]==0x%lx instead of 0x%lx\n",
    304                         testName, start, utrie_get32(newTrie, start, NULL), value);
    305             }
    306             ++start;
    307         }
    308     }
    309 
    310     if(dataIs32) {
    311         getFoldingOffset=_testFoldingOffset32;
    312     } else {
    313         getFoldingOffset=_testFoldingOffset16;
    314     }
    315 
    316     errorCode=U_ZERO_ERROR;
    317     length=utrie_serialize(newTrie, storage, DEFAULT_STORAGE_SIZE,
    318                            dataIs32 ? _testFoldedValue32 : _testFoldedValue16,
    319                            (UBool)!dataIs32,
    320                            &errorCode);
    321     if(U_FAILURE(errorCode)) {
    322         log_err("error: utrie_serialize(%s) failed: %s\n", testName, u_errorName(errorCode));
    323         utrie_close(newTrie);
    324         return;
    325     }
    326 
    327     /* test linear Latin-1 range from utrie_getData() */
    328     if(latin1Linear) {
    329         uint32_t *data;
    330         int32_t dataLength;
    331 
    332         data=utrie_getData(newTrie, &dataLength);
    333         start=0;
    334         for(i=0; i<countCheckRanges && start<=0xff; ++i) {
    335             limit=checkRanges[i].limit;
    336             value=checkRanges[i].value;
    337 
    338             while(start<limit && start<=0xff) {
    339                 if(value!=data[UTRIE_DATA_BLOCK_LENGTH+start]) {
    340                     log_err("error: newTrie(%s).latin1Data[U+%04lx]==0x%lx instead of 0x%lx\n",
    341                             testName, start, data[UTRIE_DATA_BLOCK_LENGTH+start], value);
    342                 }
    343                 ++start;
    344             }
    345         }
    346     }
    347 
    348     utrie_close(newTrie);
    349 
    350     errorCode=U_ZERO_ERROR;
    351     if(!utrie_unserialize(&trie, storage, length, &errorCode)) {
    352         log_err("error: utrie_unserialize() failed, %s\n", u_errorName(errorCode));
    353         return;
    354     }
    355     trie.getFoldingOffset=getFoldingOffset;
    356 
    357     if(dataIs32!=(trie.data32!=NULL)) {
    358         log_err("error: trie serialization (%s) did not preserve 32-bitness\n", testName);
    359     }
    360     if(latin1Linear!=trie.isLatin1Linear) {
    361         log_err("error: trie serialization (%s) did not preserve Latin-1-linearity\n", testName);
    362     }
    363 
    364     /* verify that all these values are in the unserialized Trie */
    365     start=0;
    366     for(i=0; i<countCheckRanges; ++i) {
    367         limit=checkRanges[i].limit;
    368         value=checkRanges[i].value;
    369 
    370         if(start==0xd800) {
    371             /* skip surrogates */
    372             start=limit;
    373             continue;
    374         }
    375 
    376         while(start<limit) {
    377             if(start<=0xffff) {
    378                 if(dataIs32) {
    379                     value2=UTRIE_GET32_FROM_BMP(&trie, start);
    380                 } else {
    381                     value2=UTRIE_GET16_FROM_BMP(&trie, start);
    382                 }
    383                 if(value!=value2) {
    384                     log_err("error: unserialized trie(%s).fromBMP(U+%04lx)==0x%lx instead of 0x%lx\n",
    385                             testName, start, value2, value);
    386                 }
    387                 if(!UTF_IS_LEAD(start)) {
    388                     if(dataIs32) {
    389                         value2=UTRIE_GET32_FROM_LEAD(&trie, start);
    390                     } else {
    391                         value2=UTRIE_GET16_FROM_LEAD(&trie, start);
    392                     }
    393                     if(value!=value2) {
    394                         log_err("error: unserialized trie(%s).fromLead(U+%04lx)==0x%lx instead of 0x%lx\n",
    395                                 testName, start, value2, value);
    396                     }
    397                 }
    398             }
    399             if(dataIs32) {
    400                 UTRIE_GET32(&trie, start, value2);
    401             } else {
    402                 UTRIE_GET16(&trie, start, value2);
    403             }
    404             if(value!=value2) {
    405                 log_err("error: unserialized trie(%s).get(U+%04lx)==0x%lx instead of 0x%lx\n",
    406                         testName, start, value2, value);
    407             }
    408             ++start;
    409         }
    410     }
    411 
    412     /* enumerate and verify all ranges */
    413     enumRanges=checkRanges+1;
    414     utrie_enum(&trie, _testEnumValue, _testEnumRange, &enumRanges);
    415 
    416     /* test linear Latin-1 range */
    417     if(trie.isLatin1Linear) {
    418         if(trie.data32!=NULL) {
    419             const uint32_t *latin1=UTRIE_GET32_LATIN1(&trie);
    420 
    421             for(start=0; start<0x100; ++start) {
    422                 if(latin1[start]!=UTRIE_GET32_FROM_LEAD(&trie, start)) {
    423                     log_err("error: (%s) trie.latin1[U+%04lx]=0x%lx!=0x%lx=trie.get32(U+%04lx)\n",
    424                             testName, start, latin1[start], UTRIE_GET32_FROM_LEAD(&trie, start), start);
    425                 }
    426             }
    427         } else {
    428             const uint16_t *latin1=UTRIE_GET16_LATIN1(&trie);
    429 
    430             for(start=0; start<0x100; ++start) {
    431                 if(latin1[start]!=UTRIE_GET16_FROM_LEAD(&trie, start)) {
    432                     log_err("error: (%s) trie.latin1[U+%04lx]=0x%lx!=0x%lx=trie.get16(U+%04lx)\n",
    433                             testName, start, latin1[start], UTRIE_GET16_FROM_LEAD(&trie, start), start);
    434                 }
    435             }
    436         }
    437     }
    438 
    439     testTrieIteration(testName, &trie, checkRanges, countCheckRanges);
    440     uprv_free(storage);
    441 }
    442 
    443 static void
    444 testTrieRanges(const char *testName,
    445                const SetRange setRanges[], int32_t countSetRanges,
    446                const CheckRange checkRanges[], int32_t countCheckRanges,
    447                UBool dataIs32, UBool latin1Linear) {
    448     union{
    449         double bogus; /* needed for aligining the storage */
    450         uint8_t storage[32768];
    451     } storageHolder;
    452     UTrieGetFoldingOffset *getFoldingOffset;
    453     UNewTrieGetFoldedValue *getFoldedValue;
    454     const CheckRange *enumRanges;
    455     UNewTrie *newTrie;
    456     UTrie trie={ 0 };
    457     uint32_t value, value2;
    458     UChar32 start, limit;
    459     int32_t i, length;
    460     UErrorCode errorCode;
    461     UBool overwrite, ok;
    462 
    463     log_verbose("\ntesting Trie '%s'\n", testName);
    464     newTrie=utrie_open(NULL, NULL, 2000,
    465                        checkRanges[0].value, checkRanges[0].value,
    466                        latin1Linear);
    467 
    468     /* set values from setRanges[] */
    469     ok=TRUE;
    470     for(i=0; i<countSetRanges; ++i) {
    471         start=setRanges[i].start;
    472         limit=setRanges[i].limit;
    473         value=setRanges[i].value;
    474         overwrite=setRanges[i].overwrite;
    475         if((limit-start)==1 && overwrite) {
    476             ok&=utrie_set32(newTrie, start, value);
    477         } else {
    478             ok&=utrie_setRange32(newTrie, start, limit, value, overwrite);
    479         }
    480     }
    481     if(!ok) {
    482         log_err("error: setting values into a trie failed (%s)\n", testName);
    483         return;
    484     }
    485 
    486     /* verify that all these values are in the new Trie */
    487     start=0;
    488     for(i=0; i<countCheckRanges; ++i) {
    489         limit=checkRanges[i].limit;
    490         value=checkRanges[i].value;
    491 
    492         while(start<limit) {
    493             if(value!=utrie_get32(newTrie, start, NULL)) {
    494                 log_err("error: newTrie(%s)[U+%04lx]==0x%lx instead of 0x%lx\n",
    495                         testName, start, utrie_get32(newTrie, start, NULL), value);
    496             }
    497             ++start;
    498         }
    499     }
    500 
    501     if(dataIs32) {
    502         getFoldingOffset=_testFoldingOffset32;
    503         getFoldedValue=_testFoldedValue32;
    504     } else {
    505         getFoldingOffset=_testFoldingOffset16;
    506         getFoldedValue=_testFoldedValue16;
    507     }
    508 
    509     /*
    510      * code coverage for utrie.c/defaultGetFoldedValue(),
    511      * pick some combination of parameters for selecting the UTrie defaults
    512      */
    513     if(!dataIs32 && latin1Linear) {
    514         getFoldingOffset=NULL;
    515         getFoldedValue=NULL;
    516     }
    517 
    518     errorCode=U_ZERO_ERROR;
    519     length=utrie_serialize(newTrie, storageHolder.storage, sizeof(storageHolder.storage),
    520                            getFoldedValue,
    521                            (UBool)!dataIs32,
    522                            &errorCode);
    523     if(U_FAILURE(errorCode)) {
    524         log_err("error: utrie_serialize(%s) failed: %s\n", testName, u_errorName(errorCode));
    525         utrie_close(newTrie);
    526         return;
    527     }
    528     if (length >= (int32_t)sizeof(storageHolder.storage)) {
    529         log_err("error: utrie_serialize(%s) needs more memory\n", testName);
    530         utrie_close(newTrie);
    531         return;
    532     }
    533 
    534     /* test linear Latin-1 range from utrie_getData() */
    535     if(latin1Linear) {
    536         uint32_t *data;
    537         int32_t dataLength;
    538 
    539         data=utrie_getData(newTrie, &dataLength);
    540         start=0;
    541         for(i=0; i<countCheckRanges && start<=0xff; ++i) {
    542             limit=checkRanges[i].limit;
    543             value=checkRanges[i].value;
    544 
    545             while(start<limit && start<=0xff) {
    546                 if(value!=data[UTRIE_DATA_BLOCK_LENGTH+start]) {
    547                     log_err("error: newTrie(%s).latin1Data[U+%04lx]==0x%lx instead of 0x%lx\n",
    548                             testName, start, data[UTRIE_DATA_BLOCK_LENGTH+start], value);
    549                 }
    550                 ++start;
    551             }
    552         }
    553     }
    554 
    555     utrie_close(newTrie);
    556 
    557     errorCode=U_ZERO_ERROR;
    558     if(!utrie_unserialize(&trie, storageHolder.storage, length, &errorCode)) {
    559         log_err("error: utrie_unserialize() failed, %s\n", u_errorName(errorCode));
    560         return;
    561     }
    562     if(getFoldingOffset!=NULL) {
    563         trie.getFoldingOffset=getFoldingOffset;
    564     }
    565 
    566     if(dataIs32!=(trie.data32!=NULL)) {
    567         log_err("error: trie serialization (%s) did not preserve 32-bitness\n", testName);
    568     }
    569     if(latin1Linear!=trie.isLatin1Linear) {
    570         log_err("error: trie serialization (%s) did not preserve Latin-1-linearity\n", testName);
    571     }
    572 
    573     /* verify that all these values are in the unserialized Trie */
    574     start=0;
    575     for(i=0; i<countCheckRanges; ++i) {
    576         limit=checkRanges[i].limit;
    577         value=checkRanges[i].value;
    578 
    579         if(start==0xd800) {
    580             /* skip surrogates */
    581             start=limit;
    582             continue;
    583         }
    584 
    585         while(start<limit) {
    586             if(start<=0xffff) {
    587                 if(dataIs32) {
    588                     value2=UTRIE_GET32_FROM_BMP(&trie, start);
    589                 } else {
    590                     value2=UTRIE_GET16_FROM_BMP(&trie, start);
    591                 }
    592                 if(value!=value2) {
    593                     log_err("error: unserialized trie(%s).fromBMP(U+%04lx)==0x%lx instead of 0x%lx\n",
    594                             testName, start, value2, value);
    595                 }
    596                 if(!UTF_IS_LEAD(start)) {
    597                     if(dataIs32) {
    598                         value2=UTRIE_GET32_FROM_LEAD(&trie, start);
    599                     } else {
    600                         value2=UTRIE_GET16_FROM_LEAD(&trie, start);
    601                     }
    602                     if(value!=value2) {
    603                         log_err("error: unserialized trie(%s).fromLead(U+%04lx)==0x%lx instead of 0x%lx\n",
    604                                 testName, start, value2, value);
    605                     }
    606                 }
    607             }
    608             if(dataIs32) {
    609                 UTRIE_GET32(&trie, start, value2);
    610             } else {
    611                 UTRIE_GET16(&trie, start, value2);
    612             }
    613             if(value!=value2) {
    614                 log_err("error: unserialized trie(%s).get(U+%04lx)==0x%lx instead of 0x%lx\n",
    615                         testName, start, value2, value);
    616             }
    617             ++start;
    618         }
    619     }
    620 
    621     /* enumerate and verify all ranges */
    622     enumRanges=checkRanges+1;
    623     utrie_enum(&trie, _testEnumValue, _testEnumRange, &enumRanges);
    624 
    625     /* test linear Latin-1 range */
    626     if(trie.isLatin1Linear) {
    627         if(trie.data32!=NULL) {
    628             const uint32_t *latin1=UTRIE_GET32_LATIN1(&trie);
    629 
    630             for(start=0; start<0x100; ++start) {
    631                 if(latin1[start]!=UTRIE_GET32_FROM_LEAD(&trie, start)) {
    632                     log_err("error: (%s) trie.latin1[U+%04lx]=0x%lx!=0x%lx=trie.get32(U+%04lx)\n",
    633                             testName, start, latin1[start], UTRIE_GET32_FROM_LEAD(&trie, start), start);
    634                 }
    635             }
    636         } else {
    637             const uint16_t *latin1=UTRIE_GET16_LATIN1(&trie);
    638 
    639             for(start=0; start<0x100; ++start) {
    640                 if(latin1[start]!=UTRIE_GET16_FROM_LEAD(&trie, start)) {
    641                     log_err("error: (%s) trie.latin1[U+%04lx]=0x%lx!=0x%lx=trie.get16(U+%04lx)\n",
    642                             testName, start, latin1[start], UTRIE_GET16_FROM_LEAD(&trie, start), start);
    643                 }
    644             }
    645         }
    646     }
    647 
    648     testTrieIteration(testName, &trie, checkRanges, countCheckRanges);
    649 }
    650 
    651 static void
    652 testTrieRanges2(const char *testName,
    653                 const SetRange setRanges[], int32_t countSetRanges,
    654                 const CheckRange checkRanges[], int32_t countCheckRanges,
    655                 UBool dataIs32) {
    656     char name[40];
    657 
    658     testTrieRanges(testName,
    659                    setRanges, countSetRanges,
    660                    checkRanges, countCheckRanges,
    661                    dataIs32, FALSE);
    662     testTrieRangesWithMalloc(testName,
    663                    setRanges, countSetRanges,
    664                    checkRanges, countCheckRanges,
    665                    dataIs32, FALSE);
    666 
    667     uprv_strcpy(name, testName);
    668     uprv_strcat(name, "-latin1Linear");
    669     testTrieRanges(name,
    670                    setRanges, countSetRanges,
    671                    checkRanges, countCheckRanges,
    672                    dataIs32, TRUE);
    673     testTrieRangesWithMalloc(name,
    674                    setRanges, countSetRanges,
    675                    checkRanges, countCheckRanges,
    676                    dataIs32, TRUE);
    677 }
    678 
    679 static void
    680 testTrieRanges4(const char *testName,
    681                 const SetRange setRanges[], int32_t countSetRanges,
    682                 const CheckRange checkRanges[], int32_t countCheckRanges) {
    683     char name[40];
    684 
    685     uprv_strcpy(name, testName);
    686     uprv_strcat(name, ".32");
    687     testTrieRanges2(name,
    688                     setRanges, countSetRanges,
    689                     checkRanges, countCheckRanges,
    690                     TRUE);
    691 
    692     uprv_strcpy(name, testName);
    693     uprv_strcat(name, ".16");
    694     testTrieRanges2(name,
    695                     setRanges, countSetRanges,
    696                     checkRanges, countCheckRanges,
    697                     FALSE);
    698 }
    699 
    700 /* test data ----------------------------------------------------------------*/
    701 
    702 /* set consecutive ranges, even with value 0 */
    703 static const SetRange
    704 setRanges1[]={
    705     {0,      0x20,       0,      FALSE},
    706     {0x20,   0xa7,       0x1234, FALSE},
    707     {0xa7,   0x3400,     0,      FALSE},
    708     {0x3400, 0x9fa6,     0x6162, FALSE},
    709     {0x9fa6, 0xda9e,     0x3132, FALSE},
    710     {0xdada, 0xeeee,     0x87ff, FALSE}, /* try to disrupt _testFoldingOffset16() */
    711     {0xeeee, 0x11111,    1,      FALSE},
    712     {0x11111, 0x44444,   0x6162, FALSE},
    713     {0x44444, 0x60003,   0,      FALSE},
    714     {0xf0003, 0xf0004,   0xf,    FALSE},
    715     {0xf0004, 0xf0006,   0x10,   FALSE},
    716     {0xf0006, 0xf0007,   0x11,   FALSE},
    717     {0xf0007, 0xf0020,   0x12,   FALSE},
    718     {0xf0020, 0x110000,  0,      FALSE}
    719 };
    720 
    721 static const CheckRange
    722 checkRanges1[]={
    723     {0,      0},      /* dummy start range to make _testEnumRange() simpler */
    724     {0x20,   0},
    725     {0xa7,   0x1234},
    726     {0x3400, 0},
    727     {0x9fa6, 0x6162},
    728     {0xda9e, 0x3132},
    729     {0xdada, 0},
    730     {0xeeee, 0x87ff},
    731     {0x11111,1},
    732     {0x44444,0x6162},
    733     {0xf0003,0},
    734     {0xf0004,0xf},
    735     {0xf0006,0x10},
    736     {0xf0007,0x11},
    737     {0xf0020,0x12},
    738     {0x110000, 0}
    739 };
    740 
    741 /* set some interesting overlapping ranges */
    742 static const SetRange
    743 setRanges2[]={
    744     {0x21,   0x7f,       0x5555, TRUE},
    745     {0x2f800,0x2fedc,    0x7a,   TRUE},
    746     {0x72,   0xdd,       3,      TRUE},
    747     {0xdd,   0xde,       4,      FALSE},
    748     {0x201,  0x220,      6,      TRUE},  /* 3 consecutive blocks with the same pattern but discontiguous value ranges */
    749     {0x221,  0x240,      6,      TRUE},
    750     {0x241,  0x260,      6,      TRUE},
    751     {0x2f987,0x2fa98,    5,      TRUE},
    752     {0x2f777,0x2f833,    0,      TRUE},
    753     {0x2f900,0x2ffee,    1,      FALSE},
    754     {0x2ffee,0x2ffef,    2,      TRUE}
    755 };
    756 
    757 static const CheckRange
    758 checkRanges2[]={
    759     {0,      0},      /* dummy start range to make _testEnumRange() simpler */
    760     {0x21,   0},
    761     {0x72,   0x5555},
    762     {0xdd,   3},
    763     {0xde,   4},
    764     {0x201,  0},
    765     {0x220,  6},
    766     {0x221,  0},
    767     {0x240,  6},
    768     {0x241,  0},
    769     {0x260,  6},
    770     {0x2f833,0},
    771     {0x2f987,0x7a},
    772     {0x2fa98,5},
    773     {0x2fedc,0x7a},
    774     {0x2ffee,1},
    775     {0x2ffef,2},
    776     {0x110000, 0}
    777 };
    778 
    779 /* use a non-zero initial value */
    780 static const SetRange
    781 setRanges3[]={
    782     {0x31,   0xa4,   1,  FALSE},
    783     {0x3400, 0x6789, 2,  FALSE},
    784     {0x30000,0x34567,9,  TRUE},
    785     {0x45678,0x56789,3,  TRUE}
    786 };
    787 
    788 static const CheckRange
    789 checkRanges3[]={
    790     {0,      9},      /* dummy start range, also carries the initial value */
    791     {0x31,   9},
    792     {0xa4,   1},
    793     {0x3400, 9},
    794     {0x6789, 2},
    795     {0x45678,9},
    796     {0x56789,3},
    797     {0x110000,9}
    798 };
    799 
    800 static void
    801 TrieTest(void) {
    802     testTrieRanges4("set1",
    803         setRanges1, ARRAY_LENGTH(setRanges1),
    804         checkRanges1, ARRAY_LENGTH(checkRanges1));
    805     testTrieRanges4("set2-overlap",
    806         setRanges2, ARRAY_LENGTH(setRanges2),
    807         checkRanges2, ARRAY_LENGTH(checkRanges2));
    808     testTrieRanges4("set3-initial-9",
    809         setRanges3, ARRAY_LENGTH(setRanges3),
    810         checkRanges3, ARRAY_LENGTH(checkRanges3));
    811 }
    812 
    813 /* test utrie_unserializeDummy() -------------------------------------------- */
    814 
    815 static int32_t U_CALLCONV
    816 dummyGetFoldingOffset(uint32_t data) {
    817     return -1; /* never get non-initialValue data for supplementary code points */
    818 }
    819 
    820 static void
    821 dummyTest(UBool make16BitTrie) {
    822     int32_t mem[UTRIE_DUMMY_SIZE/4];
    823 
    824     UTrie trie;
    825     UErrorCode errorCode;
    826     UChar32 c;
    827 
    828     uint32_t value, initialValue, leadUnitValue;
    829 
    830     if(make16BitTrie) {
    831         initialValue=0x313;
    832         leadUnitValue=0xaffe;
    833     } else {
    834         initialValue=0x01234567;
    835         leadUnitValue=0x89abcdef;
    836     }
    837 
    838     errorCode=U_ZERO_ERROR;
    839     utrie_unserializeDummy(&trie, mem, sizeof(mem), initialValue, leadUnitValue, make16BitTrie, &errorCode);
    840     if(U_FAILURE(errorCode)) {
    841         log_err("utrie_unserializeDummy(make16BitTrie=%d) failed - %s\n", make16BitTrie, u_errorName(errorCode));
    842         return;
    843     }
    844     trie.getFoldingOffset=dummyGetFoldingOffset;
    845 
    846     /* test that all code points have initialValue */
    847     for(c=0; c<=0x10ffff; ++c) {
    848         if(make16BitTrie) {
    849             UTRIE_GET16(&trie, c, value);
    850         } else {
    851             UTRIE_GET32(&trie, c, value);
    852         }
    853         if(value!=initialValue) {
    854             log_err("UTRIE_GET%s(dummy, U+%04lx)=0x%lx instead of 0x%lx\n",
    855                 make16BitTrie ? "16" : "32", (long)c, (long)value, (long)initialValue);
    856         }
    857     }
    858 
    859     /* test that the lead surrogate code units have leadUnitValue */
    860     for(c=0xd800; c<=0xdbff; ++c) {
    861         if(make16BitTrie) {
    862             value=UTRIE_GET16_FROM_LEAD(&trie, c);
    863         } else {
    864             value=UTRIE_GET32_FROM_LEAD(&trie, c);
    865         }
    866         if(value!=leadUnitValue) {
    867             log_err("UTRIE_GET%s_FROM_LEAD(dummy, U+%04lx)=0x%lx instead of 0x%lx\n",
    868                 make16BitTrie ? "16" : "32", (long)c, (long)value, (long)leadUnitValue);
    869         }
    870     }
    871 }
    872 
    873 static void
    874 DummyTrieTest(void) {
    875     dummyTest(TRUE);
    876     dummyTest(FALSE);
    877 }
    878 
    879 void
    880 addTrieTest(TestNode** root);
    881 
    882 void
    883 addTrieTest(TestNode** root) {
    884     addTest(root, &TrieTest, "tsutil/trietest/TrieTest");
    885     addTest(root, &DummyTrieTest, "tsutil/trietest/DummyTrieTest");
    886 }
    887