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