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
28void addTrie2Test(TestNode** root);
29
30/* Values for setting possibly overlapping, out-of-order ranges of values */
31typedef 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 */
45typedef struct CheckRange {
46    UChar32 limit;
47    uint32_t value;
48} CheckRange;
49
50static int32_t
51skipSpecialValues(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
57static int32_t
58getSpecialValues(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 */
75static uint32_t U_CALLCONV
76testEnumValue(const void *context, uint32_t value) {
77    return value^0x5555;
78}
79
80/* utrie2_enum() callback, verifies a range */
81static UBool U_CALLCONV
82testEnumRange(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
96static void
97testTrieEnum(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() */
109static void
110testTrieGetters(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
268static void
269testTrieUTF16(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
348static void
349testTrieUTF8(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
484static void
485testFrozenTrie(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
533static void
534testNewTrie(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
541static void
542testTrieSerialize(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
750static UTrie2 *
751testTrieSerializeAllValueBits(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
796static UTrie2 *
797makeTrieWithRanges(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
856static void
857testTrieRanges(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 */
873static const SetRange
874setRanges1[]={
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
891static const CheckRange
892checkRanges1[]={
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 */
912static const SetRange
913setRanges2[]={
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
928static const CheckRange
929checkRanges2[]={
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
952static const CheckRange
953checkRanges2_d800[]={
954    { 0x10000,  0 },
955    { 0x10400,  0 }
956};
957
958static const CheckRange
959checkRanges2_d87e[]={
960    { 0x2f800,  6 },
961    { 0x2f883,  0 },
962    { 0x2f987,  0x7a },
963    { 0x2fa98,  5 },
964    { 0x2fc00,  0x7a }
965};
966
967static const CheckRange
968checkRanges2_d87f[]={
969    { 0x2fc00,  0 },
970    { 0x2fedc,  0x7a },
971    { 0x2ffaa,  1 },
972    { 0x2ffab,  2 },
973    { 0x2ffbb,  0 },
974    { 0x2ffc0,  7 },
975    { 0x30000,  0 }
976};
977
978static const CheckRange
979checkRanges2_dbff[]={
980    { 0x10fc00, 0 },
981    { 0x110000, 0 }
982};
983
984/* use a non-zero initial value */
985static const SetRange
986setRanges3[]={
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
996static const CheckRange
997checkRanges3[]={
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 */
1012static const SetRange
1013setRangesEmpty[]={
1014    { 0,        0,        0, FALSE },  /* need some values for it to compile */
1015};
1016
1017static const CheckRange
1018checkRangesEmpty[]={
1019    { 0,        3 },
1020    { 0x110000, 3 }
1021};
1022
1023static const SetRange
1024setRangesSingleValue[]={
1025    { 0,        0x110000, 5, TRUE },
1026};
1027
1028static const CheckRange
1029checkRangesSingleValue[]={
1030    { 0,        3 },
1031    { 0x110000, 5 }
1032};
1033
1034static void
1035TrieTest(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
1057static void
1058EnumNewTrieForLeadSurrogateTest(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
1099static void
1100dummyTest(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
1137static void
1138DummyTrieTest(void) {
1139    dummyTest(UTRIE2_16_VALUE_BITS);
1140    dummyTest(UTRIE2_32_VALUE_BITS);
1141}
1142
1143/* test builder memory management ------------------------------------------- */
1144
1145static void
1146FreeBlocksTest(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
1198static void
1199GrowDataArrayTest(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
1258static void
1259GetVersionTest(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
1283static UNewTrie *
1284makeNewTrie1WithRanges(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
1328static void
1329testTrie2FromTrie1(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
1411static void
1412Trie12ConversionTest(void) {
1413    testTrie2FromTrie1("trie1->trie2",
1414                       setRanges2, LENGTHOF(setRanges2),
1415                       checkRanges2, LENGTHOF(checkRanges2));
1416}
1417
1418void
1419addTrie2Test(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