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