• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // © 2017 and later: Unicode, Inc. and others.
2 // License & terms of use: http://www.unicode.org/copyright.html
3 
4 // ucptrietest.c (modified from trie2test.c)
5 // created: 2017dec29 Markus W. Scherer
6 
7 #include <stdio.h>
8 #include "unicode/utypes.h"
9 #include "unicode/ucptrie.h"
10 #include "unicode/umutablecptrie.h"
11 #include "unicode/utf.h"
12 #include "unicode/utf16.h"
13 #include "unicode/utf8.h"
14 #include "uassert.h"
15 #include "ucptrie_impl.h"
16 #include "utrie.h"
17 #include "cstring.h"
18 #include "cmemory.h"
19 #include "udataswp.h"
20 #include "cintltst.h"
21 
22 void addUCPTrieTest(TestNode** root);
23 
24 /* Values for setting possibly overlapping, out-of-order ranges of values */
25 typedef struct SetRange {
26     UChar32 start, limit;
27     uint32_t value;
28 } SetRange;
29 
30 /*
31  * Values for testing:
32  * value is set from the previous boundary's limit to before
33  * this boundary's limit
34  *
35  * There must be an entry with limit 0 and the intialValue.
36  * It may be preceded by an entry with negative limit and the errorValue.
37  */
38 typedef struct CheckRange {
39     UChar32 limit;
40     uint32_t value;
41 } CheckRange;
42 
43 static int32_t
skipSpecialValues(const CheckRange checkRanges[],int32_t countCheckRanges)44 skipSpecialValues(const CheckRange checkRanges[], int32_t countCheckRanges) {
45     int32_t i;
46     for(i=0; i<countCheckRanges && checkRanges[i].limit<=0; ++i) {}
47     return i;
48 }
49 
50 static int32_t
getSpecialValues(const CheckRange checkRanges[],int32_t countCheckRanges,uint32_t * pInitialValue,uint32_t * pErrorValue)51 getSpecialValues(const CheckRange checkRanges[], int32_t countCheckRanges,
52                  uint32_t *pInitialValue, uint32_t *pErrorValue) {
53     int32_t i=0;
54     if(i<countCheckRanges && checkRanges[i].limit<0) {
55         *pErrorValue=checkRanges[i++].value;
56     } else {
57         *pErrorValue=0xad;
58     }
59     if(i<countCheckRanges && checkRanges[i].limit==0) {
60         *pInitialValue=checkRanges[i++].value;
61     } else {
62         *pInitialValue=0;
63     }
64     return i;
65 }
66 
67 /* ucptrie_enum() callback, modifies a value */
68 static uint32_t U_CALLCONV
testFilter(const void * context,uint32_t value)69 testFilter(const void *context, uint32_t value) {
70     return value ^ 0x5555;
71 }
72 
73 static UBool
doCheckRange(const char * name,const char * variant,UChar32 start,UChar32 end,uint32_t value,UChar32 expEnd,uint32_t expValue)74 doCheckRange(const char *name, const char *variant,
75              UChar32 start, UChar32 end, uint32_t value,
76              UChar32 expEnd, uint32_t expValue) {
77     if (end < 0) {
78         if (expEnd >= 0) {
79             log_err("error: %s getRanges (%s) fails to deliver range [U+%04lx..U+%04lx].0x%lx\n",
80                     name, variant, (long)start, (long)expEnd, (long)expValue);
81         }
82         return FALSE;
83     }
84     if (expEnd < 0) {
85         log_err("error: %s getRanges (%s) delivers unexpected range [U+%04lx..U+%04lx].0x%lx\n",
86                 name, variant, (long)start, (long)end, (long)value);
87         return FALSE;
88     }
89     if (end != expEnd || value != expValue) {
90         log_err("error: %s getRanges (%s) delivers wrong range [U+%04lx..U+%04lx].0x%lx "
91                 "instead of [U+%04lx..U+%04lx].0x%lx\n",
92                 name, variant, (long)start, (long)end, (long)value,
93                 (long)start, (long)expEnd, (long)expValue);
94         return FALSE;
95     }
96     return TRUE;
97 }
98 
99 // Test iteration starting from various UTF-8/16 and trie structure boundaries.
100 // Also test starting partway through lead & trail surrogates for fixed-surrogate-value options,
101 // and partway through supplementary code points.
102 static UChar32 iterStarts[] = {
103     0, 0x7f, 0x80, 0x7ff, 0x800, 0xfff, 0x1000,
104     0xd7ff, 0xd800, 0xd888, 0xdddd, 0xdfff, 0xe000,
105     0xffff, 0x10000, 0x12345, 0x10ffff, 0x110000
106 };
107 
108 static void
testTrieGetRanges(const char * testName,const UCPTrie * trie,const UMutableCPTrie * mutableTrie,UCPMapRangeOption option,uint32_t surrValue,const CheckRange checkRanges[],int32_t countCheckRanges)109 testTrieGetRanges(const char *testName, const UCPTrie *trie, const UMutableCPTrie *mutableTrie,
110                   UCPMapRangeOption option, uint32_t surrValue,
111                   const CheckRange checkRanges[], int32_t countCheckRanges) {
112     const char *const typeName = trie == NULL ? "mutableTrie" : "trie";
113     const char *const optionName = option == UCPMAP_RANGE_NORMAL ? "normal" :
114         option == UCPMAP_RANGE_FIXED_LEAD_SURROGATES ? "fixedLeadSurr" : "fixedAllSurr";
115     char name[80];
116     int32_t s;
117     for (s = 0; s < UPRV_LENGTHOF(iterStarts); ++s) {
118         UChar32 start = iterStarts[s];
119         int32_t i, i0;
120         UChar32 end, expEnd;
121         uint32_t value, expValue;
122         // No need to go from each iteration start to the very end.
123         int32_t innerLoopCount;
124 
125         sprintf(name, "%s/%s(%s) min=U+%04lx", typeName, optionName, testName, (long)start);
126 
127         // Skip over special values and low ranges.
128         for (i = 0; i < countCheckRanges && checkRanges[i].limit <= start; ++i) {}
129         i0 = i;
130         // without value handler
131         for (innerLoopCount = 0;; ++i, start = end + 1) {
132             if (i < countCheckRanges) {
133                 expEnd = checkRanges[i].limit - 1;
134                 expValue = checkRanges[i].value;
135             } else {
136                 expEnd = -1;
137                 expValue = value = 0x5005;
138             }
139             end = trie != NULL ?
140                 ucptrie_getRange(trie, start, option, surrValue, NULL, NULL, &value) :
141                 umutablecptrie_getRange(mutableTrie, start, option, surrValue, NULL, NULL, &value);
142             if (!doCheckRange(name, "without value handler", start, end, value, expEnd, expValue)) {
143                 break;
144             }
145             if (s != 0 && ++innerLoopCount == 5) { break; }
146         }
147         // with value handler
148         for (i = i0, start = iterStarts[s], innerLoopCount = 0;; ++i, start = end + 1) {
149             if (i < countCheckRanges) {
150                 expEnd = checkRanges[i].limit - 1;
151                 expValue = checkRanges[i].value ^ 0x5555;
152             } else {
153                 expEnd = -1;
154                 expValue = value = 0x5005;
155             }
156             end = trie != NULL ?
157                 ucptrie_getRange(trie, start, option, surrValue ^ 0x5555, testFilter, NULL, &value) :
158                 umutablecptrie_getRange(mutableTrie, start, option, surrValue ^ 0x5555,
159                                         testFilter, NULL, &value);
160             if (!doCheckRange(name, "with value handler", start, end, value, expEnd, expValue)) {
161                 break;
162             }
163             if (s != 0 && ++innerLoopCount == 5) { break; }
164         }
165         // without value
166         for (i = i0, start = iterStarts[s], innerLoopCount = 0;; ++i, start = end + 1) {
167             if (i < countCheckRanges) {
168                 expEnd = checkRanges[i].limit - 1;
169             } else {
170                 expEnd = -1;
171             }
172             end = trie != NULL ?
173                 ucptrie_getRange(trie, start, option, surrValue, NULL, NULL, NULL) :
174                 umutablecptrie_getRange(mutableTrie, start, option, surrValue, NULL, NULL, NULL);
175             if (!doCheckRange(name, "without value", start, end, 0, expEnd, 0)) {
176                 break;
177             }
178             if (s != 0 && ++innerLoopCount == 5) { break; }
179         }
180     }
181 }
182 
183 static void
testTrieGetters(const char * testName,const UCPTrie * trie,UCPTrieType type,UCPTrieValueWidth valueWidth,const CheckRange checkRanges[],int32_t countCheckRanges)184 testTrieGetters(const char *testName, const UCPTrie *trie,
185                 UCPTrieType type, UCPTrieValueWidth valueWidth,
186                 const CheckRange checkRanges[], int32_t countCheckRanges) {
187     uint32_t initialValue, errorValue;
188     uint32_t value, value2;
189     UChar32 start, limit;
190     int32_t i, countSpecials;
191     int32_t countErrors=0;
192 
193     const char *const typeName = "trie";
194 
195     countSpecials=getSpecialValues(checkRanges, countCheckRanges, &initialValue, &errorValue);
196 
197     start=0;
198     for(i=countSpecials; i<countCheckRanges; ++i) {
199         limit=checkRanges[i].limit;
200         value=checkRanges[i].value;
201 
202         while(start<limit) {
203             if (start <= 0x7f) {
204                 if (valueWidth == UCPTRIE_VALUE_BITS_16) {
205                     value2 = UCPTRIE_ASCII_GET(trie, UCPTRIE_16, start);
206                 } else if (valueWidth == UCPTRIE_VALUE_BITS_32) {
207                     value2 = UCPTRIE_ASCII_GET(trie, UCPTRIE_32, start);
208                 } else {
209                     value2 = UCPTRIE_ASCII_GET(trie, UCPTRIE_8, start);
210                 }
211                 if (value != value2) {
212                     log_err("error: %s(%s).fromASCII(U+%04lx)==0x%lx instead of 0x%lx\n",
213                             typeName, testName, (long)start, (long)value2, (long)value);
214                     ++countErrors;
215                 }
216             }
217             if (type == UCPTRIE_TYPE_FAST) {
218                 if(start<=0xffff) {
219                     if(valueWidth==UCPTRIE_VALUE_BITS_16) {
220                         value2=UCPTRIE_FAST_BMP_GET(trie, UCPTRIE_16, start);
221                     } else if(valueWidth==UCPTRIE_VALUE_BITS_32) {
222                         value2=UCPTRIE_FAST_BMP_GET(trie, UCPTRIE_32, start);
223                     } else {
224                         value2=UCPTRIE_FAST_BMP_GET(trie, UCPTRIE_8, start);
225                     }
226                     if(value!=value2) {
227                         log_err("error: %s(%s).fromBMP(U+%04lx)==0x%lx instead of 0x%lx\n",
228                                 typeName, testName, (long)start, (long)value2, (long)value);
229                         ++countErrors;
230                     }
231                 } else {
232                     if(valueWidth==UCPTRIE_VALUE_BITS_16) {
233                         value2 = UCPTRIE_FAST_SUPP_GET(trie, UCPTRIE_16, start);
234                     } else if(valueWidth==UCPTRIE_VALUE_BITS_32) {
235                         value2 = UCPTRIE_FAST_SUPP_GET(trie, UCPTRIE_32, start);
236                     } else {
237                         value2 = UCPTRIE_FAST_SUPP_GET(trie, UCPTRIE_8, start);
238                     }
239                     if(value!=value2) {
240                         log_err("error: %s(%s).fromSupp(U+%04lx)==0x%lx instead of 0x%lx\n",
241                                 typeName, testName, (long)start, (long)value2, (long)value);
242                         ++countErrors;
243                     }
244                 }
245                 if(valueWidth==UCPTRIE_VALUE_BITS_16) {
246                     value2 = UCPTRIE_FAST_GET(trie, UCPTRIE_16, start);
247                 } else if(valueWidth==UCPTRIE_VALUE_BITS_32) {
248                     value2 = UCPTRIE_FAST_GET(trie, UCPTRIE_32, start);
249                 } else {
250                     value2 = UCPTRIE_FAST_GET(trie, UCPTRIE_8, start);
251                 }
252             } else {
253                 if(valueWidth==UCPTRIE_VALUE_BITS_16) {
254                     value2 = UCPTRIE_SMALL_GET(trie, UCPTRIE_16, start);
255                 } else if(valueWidth==UCPTRIE_VALUE_BITS_32) {
256                     value2 = UCPTRIE_SMALL_GET(trie, UCPTRIE_32, start);
257                 } else {
258                     value2 = UCPTRIE_SMALL_GET(trie, UCPTRIE_8, start);
259                 }
260             }
261             if(value!=value2) {
262                 log_err("error: %s(%s).get(U+%04lx)==0x%lx instead of 0x%lx\n",
263                         typeName, testName, (long)start, (long)value2, (long)value);
264                 ++countErrors;
265             }
266             value2=ucptrie_get(trie, start);
267             if(value!=value2) {
268                 log_err("error: %s(%s).get(U+%04lx)==0x%lx instead of 0x%lx\n",
269                         typeName, testName, (long)start, (long)value2, (long)value);
270                 ++countErrors;
271             }
272             ++start;
273             if(countErrors>10) {
274                 return;
275             }
276         }
277     }
278 
279     /* test linear ASCII range from the data array pointer (access to "internal" field) */
280     start=0;
281     for(i=countSpecials; i<countCheckRanges && start<=0x7f; ++i) {
282         limit=checkRanges[i].limit;
283         value=checkRanges[i].value;
284 
285         while(start<limit && start<=0x7f) {
286             if(valueWidth==UCPTRIE_VALUE_BITS_16) {
287                 value2=trie->data.ptr16[start];
288             } else if(valueWidth==UCPTRIE_VALUE_BITS_32) {
289                 value2=trie->data.ptr32[start];
290             } else {
291                 value2=trie->data.ptr8[start];
292             }
293             if(value!=value2) {
294                 log_err("error: %s(%s).asciiData[U+%04lx]==0x%lx instead of 0x%lx\n",
295                         typeName, testName, (long)start, (long)value2, (long)value);
296                 ++countErrors;
297             }
298             ++start;
299             if(countErrors>10) {
300                 return;
301             }
302         }
303     }
304 
305     /* test errorValue */
306     if (type == UCPTRIE_TYPE_FAST) {
307         if(valueWidth==UCPTRIE_VALUE_BITS_16) {
308             value = UCPTRIE_FAST_GET(trie, UCPTRIE_16, -1);
309             value2 = UCPTRIE_FAST_GET(trie, UCPTRIE_16, 0x110000);
310         } else if(valueWidth==UCPTRIE_VALUE_BITS_32) {
311             value = UCPTRIE_FAST_GET(trie, UCPTRIE_32, -1);
312             value2 = UCPTRIE_FAST_GET(trie, UCPTRIE_32, 0x110000);
313         } else {
314             value = UCPTRIE_FAST_GET(trie, UCPTRIE_8, -1);
315             value2 = UCPTRIE_FAST_GET(trie, UCPTRIE_8, 0x110000);
316         }
317     } else {
318         if(valueWidth==UCPTRIE_VALUE_BITS_16) {
319             value = UCPTRIE_SMALL_GET(trie, UCPTRIE_16, -1);
320             value2 = UCPTRIE_SMALL_GET(trie, UCPTRIE_16, 0x110000);
321         } else if(valueWidth==UCPTRIE_VALUE_BITS_32) {
322             value = UCPTRIE_SMALL_GET(trie, UCPTRIE_32, -1);
323             value2 = UCPTRIE_SMALL_GET(trie, UCPTRIE_32, 0x110000);
324         } else {
325             value = UCPTRIE_SMALL_GET(trie, UCPTRIE_8, -1);
326             value2 = UCPTRIE_SMALL_GET(trie, UCPTRIE_8, 0x110000);
327         }
328     }
329     if(value!=errorValue || value2!=errorValue) {
330         log_err("error: %s(%s).get(out of range) != errorValue\n",
331                 typeName, testName);
332     }
333     value=ucptrie_get(trie, -1);
334     value2=ucptrie_get(trie, 0x110000);
335     if(value!=errorValue || value2!=errorValue) {
336         log_err("error: %s(%s).get(out of range) != errorValue\n",
337                 typeName, testName);
338     }
339 }
340 
341 static void
testBuilderGetters(const char * testName,const UMutableCPTrie * mutableTrie,const CheckRange checkRanges[],int32_t countCheckRanges)342 testBuilderGetters(const char *testName, const UMutableCPTrie *mutableTrie,
343                    const CheckRange checkRanges[], int32_t countCheckRanges) {
344     uint32_t initialValue, errorValue;
345     uint32_t value, value2;
346     UChar32 start, limit;
347     int32_t i, countSpecials;
348     int32_t countErrors=0;
349 
350     const char *const typeName = "mutableTrie";
351 
352     countSpecials=getSpecialValues(checkRanges, countCheckRanges, &initialValue, &errorValue);
353 
354     start=0;
355     for(i=countSpecials; i<countCheckRanges; ++i) {
356         limit=checkRanges[i].limit;
357         value=checkRanges[i].value;
358 
359         while(start<limit) {
360             value2=umutablecptrie_get(mutableTrie, start);
361             if(value!=value2) {
362                 log_err("error: %s(%s).get(U+%04lx)==0x%lx instead of 0x%lx\n",
363                         typeName, testName, (long)start, (long)value2, (long)value);
364                 ++countErrors;
365             }
366             ++start;
367             if(countErrors>10) {
368                 return;
369             }
370         }
371     }
372 
373     /* test errorValue */
374     value=umutablecptrie_get(mutableTrie, -1);
375     value2=umutablecptrie_get(mutableTrie, 0x110000);
376     if(value!=errorValue || value2!=errorValue) {
377         log_err("error: %s(%s).get(out of range) != errorValue\n",
378                 typeName, testName);
379     }
380 }
381 
382 #define ACCIDENTAL_SURROGATE_PAIR(s, length, cp) (length > 0 && U16_IS_LEAD(s[length-1]) && U_IS_TRAIL(cp))
383 
384 static void
testTrieUTF16(const char * testName,const UCPTrie * trie,UCPTrieValueWidth valueWidth,const CheckRange checkRanges[],int32_t countCheckRanges)385 testTrieUTF16(const char *testName,
386               const UCPTrie *trie, UCPTrieValueWidth valueWidth,
387               const CheckRange checkRanges[], int32_t countCheckRanges) {
388     UChar s[30000];
389     uint32_t values[16000];
390 
391     const UChar *p, *limit;
392 
393     uint32_t errorValue = ucptrie_get(trie, -1);
394     uint32_t value, expected;
395     UChar32 prevCP, c, c2;
396     int32_t i, length, sIndex, countValues;
397 
398     /* write a string */
399     prevCP=0;
400     length=countValues=0;
401     for(i=skipSpecialValues(checkRanges, countCheckRanges); i<countCheckRanges; ++i) {
402         value=checkRanges[i].value;
403         /* write three code points */
404         if(!ACCIDENTAL_SURROGATE_PAIR(s, length, prevCP)) {
405             U16_APPEND_UNSAFE(s, length, prevCP);   /* start of the range */
406             values[countValues++]=value;
407         }
408         U_ASSERT(length < UPRV_LENGTHOF(s) && countValues < UPRV_LENGTHOF(values));
409         c=checkRanges[i].limit;
410         prevCP=(prevCP+c)/2;                    /* middle of the range */
411         if(!ACCIDENTAL_SURROGATE_PAIR(s, length, prevCP)) {
412             U16_APPEND_UNSAFE(s, length, prevCP);
413             values[countValues++]=value;
414         }
415         prevCP=c;
416         --c;                                    /* end of the range */
417         if(!ACCIDENTAL_SURROGATE_PAIR(s, length, c)) {
418             U16_APPEND_UNSAFE(s, length, c);
419             values[countValues++]=value;
420         }
421     }
422     limit=s+length;
423     if(length>UPRV_LENGTHOF(s)) {
424         log_err("UTF-16 test string length %d > capacity %d\n", (int)length, (int)UPRV_LENGTHOF(s));
425         return;
426     }
427     if(countValues>UPRV_LENGTHOF(values)) {
428         log_err("UTF-16 test values length %d > capacity %d\n", (int)countValues, (int)UPRV_LENGTHOF(values));
429         return;
430     }
431 
432     /* try forward */
433     p=s;
434     i=0;
435     while(p<limit) {
436         sIndex=(int32_t)(p-s);
437         U16_NEXT(s, sIndex, length, c2);
438         c=0x33;
439         if(valueWidth==UCPTRIE_VALUE_BITS_16) {
440             UCPTRIE_FAST_U16_NEXT(trie, UCPTRIE_16, p, limit, c, value);
441         } else if(valueWidth==UCPTRIE_VALUE_BITS_32) {
442             UCPTRIE_FAST_U16_NEXT(trie, UCPTRIE_32, p, limit, c, value);
443         } else {
444             UCPTRIE_FAST_U16_NEXT(trie, UCPTRIE_8, p, limit, c, value);
445         }
446         expected = U_IS_SURROGATE(c) ? errorValue : values[i];
447         if(value!=expected) {
448             log_err("error: wrong value from UCPTRIE_NEXT(%s)(U+%04lx): 0x%lx instead of 0x%lx\n",
449                     testName, (long)c, (long)value, (long)expected);
450         }
451         if(c!=c2) {
452             log_err("error: wrong code point from UCPTRIE_NEXT(%s): U+%04lx != U+%04lx\n",
453                     testName, (long)c, (long)c2);
454             continue;
455         }
456         ++i;
457     }
458 
459     /* try backward */
460     p=limit;
461     i=countValues;
462     while(s<p) {
463         --i;
464         sIndex=(int32_t)(p-s);
465         U16_PREV(s, 0, sIndex, c2);
466         c=0x33;
467         if(valueWidth==UCPTRIE_VALUE_BITS_16) {
468             UCPTRIE_FAST_U16_PREV(trie, UCPTRIE_16, s, p, c, value);
469         } else if(valueWidth==UCPTRIE_VALUE_BITS_32) {
470             UCPTRIE_FAST_U16_PREV(trie, UCPTRIE_32, s, p, c, value);
471         } else {
472             UCPTRIE_FAST_U16_PREV(trie, UCPTRIE_8, s, p, c, value);
473         }
474         expected = U_IS_SURROGATE(c) ? errorValue : values[i];
475         if(value!=expected) {
476             log_err("error: wrong value from UCPTRIE_PREV(%s)(U+%04lx): 0x%lx instead of 0x%lx\n",
477                     testName, (long)c, (long)value, (long)expected);
478         }
479         if(c!=c2) {
480             log_err("error: wrong code point from UCPTRIE_PREV(%s): U+%04lx != U+%04lx\n",
481                     testName, c, c2);
482         }
483     }
484 }
485 
486 static void
testTrieUTF8(const char * testName,const UCPTrie * trie,UCPTrieValueWidth valueWidth,const CheckRange checkRanges[],int32_t countCheckRanges)487 testTrieUTF8(const char *testName,
488              const UCPTrie *trie, UCPTrieValueWidth valueWidth,
489              const CheckRange checkRanges[], int32_t countCheckRanges) {
490     // Note: The byte sequence comments refer to the original UTF-8 definition.
491     // Starting with ICU 60, any sequence that is not a prefix of a valid one
492     // is treated as multiple single-byte errors.
493     // For testing, we only rely on U8_... and UCPTrie UTF-8 macros
494     // iterating consistently.
495     static const uint8_t illegal[]={
496         0xc0, 0x80,                         /* non-shortest U+0000 */
497         0xc1, 0xbf,                         /* non-shortest U+007f */
498         0xc2,                               /* truncated */
499         0xe0, 0x90, 0x80,                   /* non-shortest U+0400 */
500         0xe0, 0xa0,                         /* truncated */
501         0xed, 0xa0, 0x80,                   /* lead surrogate U+d800 */
502         0xed, 0xbf, 0xbf,                   /* trail surrogate U+dfff */
503         0xf0, 0x8f, 0xbf, 0xbf,             /* non-shortest U+ffff */
504         0xf0, 0x90, 0x80,                   /* truncated */
505         0xf4, 0x90, 0x80, 0x80,             /* beyond-Unicode U+110000 */
506         0xf8, 0x80, 0x80, 0x80,             /* truncated */
507         0xf8, 0x80, 0x80, 0x80, 0x80,       /* 5-byte UTF-8 */
508         0xfd, 0xbf, 0xbf, 0xbf, 0xbf,       /* truncated */
509         0xfd, 0xbf, 0xbf, 0xbf, 0xbf, 0xbf, /* 6-byte UTF-8 */
510         0xfe,
511         0xff
512     };
513     uint8_t s[60000];
514     uint32_t values[16000];
515 
516     const uint8_t *p, *limit;
517 
518     uint32_t initialValue, errorValue;
519     uint32_t value, expectedBytes, actualBytes;
520     UChar32 prevCP, c;
521     int32_t i, countSpecials, length, countValues;
522     int32_t prev8, i8;
523 
524     countSpecials=getSpecialValues(checkRanges, countCheckRanges, &initialValue, &errorValue);
525 
526     /* write a string */
527     prevCP=0;
528     length=countValues=0;
529     /* first a couple of trail bytes in lead position */
530     s[length++]=0x80;
531     values[countValues++]=errorValue;
532     s[length++]=0xbf;
533     values[countValues++]=errorValue;
534     prev8=i8=0;
535     for(i=countSpecials; i<countCheckRanges; ++i) {
536         value=checkRanges[i].value;
537         /* write three legal (or surrogate) code points */
538         U8_APPEND_UNSAFE(s, length, prevCP);    /* start of the range */
539         if(U_IS_SURROGATE(prevCP)) {
540             // A surrogate byte sequence counts as 3 single-byte errors.
541             values[countValues++]=errorValue;
542             values[countValues++]=errorValue;
543             values[countValues++]=errorValue;
544         } else {
545             values[countValues++]=value;
546         }
547         U_ASSERT(length < UPRV_LENGTHOF(s) && countValues < UPRV_LENGTHOF(values));
548         c=checkRanges[i].limit;
549         prevCP=(prevCP+c)/2;                    /* middle of the range */
550         U8_APPEND_UNSAFE(s, length, prevCP);
551         if(U_IS_SURROGATE(prevCP)) {
552             // A surrogate byte sequence counts as 3 single-byte errors.
553             values[countValues++]=errorValue;
554             values[countValues++]=errorValue;
555             values[countValues++]=errorValue;
556         } else {
557             values[countValues++]=value;
558         }
559         prevCP=c;
560         --c;                                    /* end of the range */
561         U8_APPEND_UNSAFE(s, length, c);
562         if(U_IS_SURROGATE(c)) {
563             // A surrogate byte sequence counts as 3 single-byte errors.
564             values[countValues++]=errorValue;
565             values[countValues++]=errorValue;
566             values[countValues++]=errorValue;
567         } else {
568             values[countValues++]=value;
569         }
570         /* write an illegal byte sequence */
571         if(i8<sizeof(illegal)) {
572             U8_FWD_1(illegal, i8, sizeof(illegal));
573             while(prev8<i8) {
574                 s[length++]=illegal[prev8++];
575             }
576             values[countValues++]=errorValue;
577         }
578     }
579     /* write the remaining illegal byte sequences */
580     while(i8<sizeof(illegal)) {
581         U8_FWD_1(illegal, i8, sizeof(illegal));
582         while(prev8<i8) {
583             s[length++]=illegal[prev8++];
584         }
585         values[countValues++]=errorValue;
586     }
587     limit=s+length;
588     if(length>UPRV_LENGTHOF(s)) {
589         log_err("UTF-8 test string length %d > capacity %d\n", (int)length, (int)UPRV_LENGTHOF(s));
590         return;
591     }
592     if(countValues>UPRV_LENGTHOF(values)) {
593         log_err("UTF-8 test values length %d > capacity %d\n", (int)countValues, (int)UPRV_LENGTHOF(values));
594         return;
595     }
596 
597     /* try forward */
598     p=s;
599     i=0;
600     while(p<limit) {
601         prev8=i8=(int32_t)(p-s);
602         U8_NEXT(s, i8, length, c);
603         if(valueWidth==UCPTRIE_VALUE_BITS_16) {
604             UCPTRIE_FAST_U8_NEXT(trie, UCPTRIE_16, p, limit, value);
605         } else if(valueWidth==UCPTRIE_VALUE_BITS_32) {
606             UCPTRIE_FAST_U8_NEXT(trie, UCPTRIE_32, p, limit, value);
607         } else {
608             UCPTRIE_FAST_U8_NEXT(trie, UCPTRIE_8, p, limit, value);
609         }
610         expectedBytes=0;
611         if(value!=values[i] || i8!=(p-s)) {
612             int32_t k=prev8;
613             while(k<i8) {
614                 expectedBytes=(expectedBytes<<8)|s[k++];
615             }
616         }
617         if(i8==(p-s)) {
618             actualBytes=expectedBytes;
619         } else {
620             actualBytes=0;
621             int32_t k=prev8;
622             while(k<(p-s)) {
623                 actualBytes=(actualBytes<<8)|s[k++];
624             }
625         }
626         if(value!=values[i]) {
627             log_err("error: wrong value from UCPTRIE_FAST_U8_NEXT(%s)(from %d %lx->U+%04lx) (read %d bytes): "
628                     "0x%lx instead of 0x%lx (from bytes %lx)\n",
629                     testName, (int)prev8, (unsigned long)actualBytes, (long)c, (int)((p-s)-prev8),
630                     (long)value, (long)values[i], (unsigned long)expectedBytes);
631         }
632         if(i8!=(p-s)) {
633             log_err("error: wrong end index from UCPTRIE_FAST_U8_NEXT(%s)(from %d %lx->U+%04lx): "
634                     "%ld != %ld (bytes %lx)\n",
635                     testName, (int)prev8, (unsigned long)actualBytes, (long)c,
636                     (long)(p-s), (long)i8, (unsigned long)expectedBytes);
637             break;
638         }
639         ++i;
640     }
641 
642     /* try backward */
643     p=limit;
644     i=countValues;
645     while(s<p) {
646         --i;
647         prev8=i8=(int32_t)(p-s);
648         U8_PREV(s, 0, i8, c);
649         if(valueWidth==UCPTRIE_VALUE_BITS_16) {
650             UCPTRIE_FAST_U8_PREV(trie, UCPTRIE_16, s, p, value);
651         } else if(valueWidth==UCPTRIE_VALUE_BITS_32) {
652             UCPTRIE_FAST_U8_PREV(trie, UCPTRIE_32, s, p, value);
653         } else {
654             UCPTRIE_FAST_U8_PREV(trie, UCPTRIE_8, s, p, value);
655         }
656         expectedBytes=0;
657         if(value!=values[i] || i8!=(p-s)) {
658             int32_t k=i8;
659             while(k<prev8) {
660                 expectedBytes=(expectedBytes<<8)|s[k++];
661             }
662         }
663         if(i8==(p-s)) {
664             actualBytes=expectedBytes;
665         } else {
666             actualBytes=0;
667             int32_t k=(int32_t)(p-s);
668             while(k<prev8) {
669                 actualBytes=(actualBytes<<8)|s[k++];
670             }
671         }
672         if(value!=values[i]) {
673             log_err("error: wrong value from UCPTRIE_FAST_U8_PREV(%s)(from %d %lx->U+%04lx) (read %d bytes): "
674                     "0x%lx instead of 0x%lx (from bytes %lx)\n",
675                     testName, (int)prev8, (unsigned long)actualBytes, (long)c, (int)(prev8-(p-s)),
676                     (long)value, (long)values[i], (unsigned long)expectedBytes);
677         }
678         if(i8!=(p-s)) {
679             log_err("error: wrong end index from UCPTRIE_FAST_U8_PREV(%s)(from %d %lx->U+%04lx): "
680                     "%ld != %ld (bytes %lx)\n",
681                     testName, (int)prev8, (unsigned long)actualBytes, (long)c,
682                     (long)(p-s), (long)i8, (unsigned long)expectedBytes);
683             break;
684         }
685     }
686 }
687 
688 static void
testTrie(const char * testName,const UCPTrie * trie,UCPTrieType type,UCPTrieValueWidth valueWidth,const CheckRange checkRanges[],int32_t countCheckRanges)689 testTrie(const char *testName, const UCPTrie *trie,
690          UCPTrieType type, UCPTrieValueWidth valueWidth,
691          const CheckRange checkRanges[], int32_t countCheckRanges) {
692     testTrieGetters(testName, trie, type, valueWidth, checkRanges, countCheckRanges);
693     testTrieGetRanges(testName, trie, NULL, UCPMAP_RANGE_NORMAL, 0, checkRanges, countCheckRanges);
694     if (type == UCPTRIE_TYPE_FAST) {
695         testTrieUTF16(testName, trie, valueWidth, checkRanges, countCheckRanges);
696         testTrieUTF8(testName, trie, valueWidth, checkRanges, countCheckRanges);
697     }
698 }
699 
700 static void
testBuilder(const char * testName,const UMutableCPTrie * mutableTrie,const CheckRange checkRanges[],int32_t countCheckRanges)701 testBuilder(const char *testName, const UMutableCPTrie *mutableTrie,
702             const CheckRange checkRanges[], int32_t countCheckRanges) {
703     testBuilderGetters(testName, mutableTrie, checkRanges, countCheckRanges);
704     testTrieGetRanges(testName, NULL, mutableTrie, UCPMAP_RANGE_NORMAL, 0, checkRanges, countCheckRanges);
705 }
706 
707 static uint32_t storage[120000];
708 static uint32_t swapped[120000];
709 
710 static void
testTrieSerialize(const char * testName,UMutableCPTrie * mutableTrie,UCPTrieType type,UCPTrieValueWidth valueWidth,UBool withSwap,const CheckRange checkRanges[],int32_t countCheckRanges)711 testTrieSerialize(const char *testName, UMutableCPTrie *mutableTrie,
712                   UCPTrieType type, UCPTrieValueWidth valueWidth, UBool withSwap,
713                   const CheckRange checkRanges[], int32_t countCheckRanges) {
714     UCPTrie *trie;
715     int32_t length1, length2, length3;
716     UErrorCode errorCode;
717 
718     /* clone the trie so that the caller can reuse the original */
719     errorCode=U_ZERO_ERROR;
720     mutableTrie = umutablecptrie_clone(mutableTrie, &errorCode);
721     if(U_FAILURE(errorCode)) {
722         log_err("error: umutablecptrie_clone(%s) failed - %s\n",
723                 testName, u_errorName(errorCode));
724         return;
725     }
726 
727     /*
728      * This is not a loop, but simply a block that we can exit with "break"
729      * when something goes wrong.
730      */
731     do {
732         errorCode=U_ZERO_ERROR;
733         trie = umutablecptrie_buildImmutable(mutableTrie, type, valueWidth, &errorCode);
734         if (U_FAILURE(errorCode)) {
735             log_err("error: umutablecptrie_buildImmutable(%s) failed: %s\n",
736                     testName, u_errorName(errorCode));
737             break;
738         }
739         errorCode=U_ZERO_ERROR;
740         length1=ucptrie_toBinary(trie, NULL, 0, &errorCode);
741         if(errorCode!=U_BUFFER_OVERFLOW_ERROR) {
742             log_err("error: ucptrie_toBinary(%s) preflighting set %s != U_BUFFER_OVERFLOW_ERROR\n",
743                     testName, u_errorName(errorCode));
744             break;
745         }
746         errorCode=U_ZERO_ERROR;
747         length2=ucptrie_toBinary(trie, storage, sizeof(storage), &errorCode);
748         if(errorCode==U_BUFFER_OVERFLOW_ERROR) {
749             log_err("error: ucptrie_toBinary(%s) needs more memory\n", testName);
750             break;
751         }
752         if(U_FAILURE(errorCode)) {
753             log_err("error: ucptrie_toBinary(%s) failed: %s\n", testName, u_errorName(errorCode));
754             break;
755         }
756         if(length1!=length2) {
757             log_err("error: trie serialization (%s) lengths different: "
758                     "preflight vs. serialize\n", testName);
759             break;
760         }
761 
762         testTrie(testName, trie, type, valueWidth, checkRanges, countCheckRanges);
763         ucptrie_close(trie);
764         trie=NULL;
765 
766         if(withSwap) {
767             int32_t swappedLength;
768 
769             UDataSwapper *ds;
770 
771             /* swap to opposite-endian */
772             uprv_memset(swapped, 0x55, length2);
773             ds=udata_openSwapper(U_IS_BIG_ENDIAN, U_CHARSET_FAMILY,
774                                  !U_IS_BIG_ENDIAN, U_CHARSET_FAMILY, &errorCode);
775             swappedLength=ucptrie_swap(ds, storage, -1, NULL, &errorCode);
776             if(U_FAILURE(errorCode) || swappedLength!=length2) {
777                 log_err("error: ucptrie_swap(%s to OE preflighting) failed (%s) "
778                         "or before/after lengths different\n",
779                         testName, u_errorName(errorCode));
780                 udata_closeSwapper(ds);
781                 break;
782             }
783             swappedLength=ucptrie_swap(ds, storage, length2, swapped, &errorCode);
784             udata_closeSwapper(ds);
785             if(U_FAILURE(errorCode) || swappedLength!=length2) {
786                 log_err("error: ucptrie_swap(%s to OE) failed (%s) or before/after lengths different\n",
787                         testName, u_errorName(errorCode));
788                 break;
789             }
790 
791             /* swap back to platform-endian */
792             uprv_memset(storage, 0xaa, length2);
793             ds=udata_openSwapper(!U_IS_BIG_ENDIAN, U_CHARSET_FAMILY,
794                                  U_IS_BIG_ENDIAN, U_CHARSET_FAMILY, &errorCode);
795             swappedLength=ucptrie_swap(ds, swapped, -1, NULL, &errorCode);
796             if(U_FAILURE(errorCode) || swappedLength!=length2) {
797                 log_err("error: ucptrie_swap(%s to PE preflighting) failed (%s) "
798                         "or before/after lengths different\n",
799                         testName, u_errorName(errorCode));
800                 udata_closeSwapper(ds);
801                 break;
802             }
803             swappedLength=ucptrie_swap(ds, swapped, length2, storage, &errorCode);
804             udata_closeSwapper(ds);
805             if(U_FAILURE(errorCode) || swappedLength!=length2) {
806                 log_err("error: ucptrie_swap(%s to PE) failed (%s) or before/after lengths different\n",
807                         testName, u_errorName(errorCode));
808                 break;
809             }
810         }
811 
812         trie = ucptrie_openFromBinary(type, valueWidth, storage, length2, &length3, &errorCode);
813         if(U_FAILURE(errorCode)) {
814             log_err("error: ucptrie_openFromBinary(%s) failed, %s\n", testName, u_errorName(errorCode));
815             break;
816         }
817         if(type != ucptrie_getType(trie)) {
818             log_err("error: trie serialization (%s) did not preserve trie type\n", testName);
819             break;
820         }
821         if(valueWidth != ucptrie_getValueWidth(trie)) {
822             log_err("error: trie serialization (%s) did not preserve data value width\n", testName);
823             break;
824         }
825         if(length2!=length3) {
826             log_err("error: trie serialization (%s) lengths different: "
827                     "serialize vs. unserialize\n", testName);
828             break;
829         }
830         /* overwrite the storage that is not supposed to be needed */
831         uprv_memset((char *)storage+length3, 0xfa, (int32_t)(sizeof(storage)-length3));
832 
833         {
834             errorCode=U_ZERO_ERROR;
835             UCPTrie *any = ucptrie_openFromBinary(UCPTRIE_TYPE_ANY, UCPTRIE_VALUE_BITS_ANY,
836                                                   storage, length3, NULL, &errorCode);
837             if (U_SUCCESS(errorCode)) {
838                 if (type != ucptrie_getType(any)) {
839                     log_err("error: ucptrie_openFromBinary("
840                             "UCPTRIE_TYPE_ANY, UCPTRIE_VALUE_BITS_ANY).getType() wrong\n");
841                 }
842                 if (valueWidth != ucptrie_getValueWidth(any)) {
843                     log_err("error: ucptrie_openFromBinary("
844                             "UCPTRIE_TYPE_ANY, UCPTRIE_VALUE_BITS_ANY).getValueWidth() wrong\n");
845                 }
846                 ucptrie_close(any);
847             } else {
848                 log_err("error: ucptrie_openFromBinary("
849                         "UCPTRIE_TYPE_ANY, UCPTRIE_VALUE_BITS_ANY) failed - %s\n",
850                         u_errorName(errorCode));
851             }
852         }
853 
854         errorCode=U_ZERO_ERROR;
855         testTrie(testName, trie, type, valueWidth, checkRanges, countCheckRanges);
856         {
857             /* make a mutable trie from an immutable one */
858             uint32_t value, value2;
859             UMutableCPTrie *mutable2 = umutablecptrie_fromUCPTrie(trie, &errorCode);
860             if(U_FAILURE(errorCode)) {
861                 log_err("error: umutablecptrie_fromUCPTrie(unserialized %s) failed - %s\n",
862                         testName, u_errorName(errorCode));
863                 break;
864             }
865 
866             value=umutablecptrie_get(mutable2, 0xa1);
867             umutablecptrie_set(mutable2, 0xa1, 789, &errorCode);
868             value2=umutablecptrie_get(mutable2, 0xa1);
869             umutablecptrie_set(mutable2, 0xa1, value, &errorCode);
870             if(U_FAILURE(errorCode) || value2!=789) {
871                 log_err("error: modifying a mutableTrie-from-UCPTrie (%s) failed - %s\n",
872                         testName, u_errorName(errorCode));
873             }
874             testBuilder(testName, mutable2, checkRanges, countCheckRanges);
875             umutablecptrie_close(mutable2);
876         }
877     } while(0);
878 
879     umutablecptrie_close(mutableTrie);
880     ucptrie_close(trie);
881 }
882 
883 static UMutableCPTrie *
testTrieSerializeAllValueWidth(const char * testName,UMutableCPTrie * mutableTrie,UBool withClone,const CheckRange checkRanges[],int32_t countCheckRanges)884 testTrieSerializeAllValueWidth(const char *testName,
885                                UMutableCPTrie *mutableTrie, UBool withClone,
886                                const CheckRange checkRanges[], int32_t countCheckRanges) {
887     char name[40];
888     uint32_t oredValues = 0;
889     int32_t i;
890     for (i = 0; i < countCheckRanges; ++i) {
891         oredValues |= checkRanges[i].value;
892     }
893 
894     testBuilder(testName, mutableTrie, checkRanges, countCheckRanges);
895 
896     if (oredValues <= 0xffff) {
897         uprv_strcpy(name, testName);
898         uprv_strcat(name, ".16");
899         testTrieSerialize(name, mutableTrie,
900                           UCPTRIE_TYPE_FAST, UCPTRIE_VALUE_BITS_16, withClone,
901                           checkRanges, countCheckRanges);
902     }
903 
904     uprv_strcpy(name, testName);
905     uprv_strcat(name, ".32");
906     testTrieSerialize(name, mutableTrie,
907                       UCPTRIE_TYPE_FAST, UCPTRIE_VALUE_BITS_32, withClone,
908                       checkRanges, countCheckRanges);
909 
910     if (oredValues <= 0xff) {
911         uprv_strcpy(name, testName);
912         uprv_strcat(name, ".8");
913         testTrieSerialize(name, mutableTrie,
914                           UCPTRIE_TYPE_FAST, UCPTRIE_VALUE_BITS_8, withClone,
915                           checkRanges, countCheckRanges);
916     }
917 
918     if (oredValues <= 0xffff) {
919         uprv_strcpy(name, testName);
920         uprv_strcat(name, ".small16");
921         testTrieSerialize(name, mutableTrie,
922                           UCPTRIE_TYPE_SMALL, UCPTRIE_VALUE_BITS_16, withClone,
923                           checkRanges, countCheckRanges);
924     }
925 
926     return mutableTrie;
927 }
928 
929 static UMutableCPTrie *
makeTrieWithRanges(const char * testName,UBool withClone,const SetRange setRanges[],int32_t countSetRanges,const CheckRange checkRanges[],int32_t countCheckRanges)930 makeTrieWithRanges(const char *testName, UBool withClone,
931                    const SetRange setRanges[], int32_t countSetRanges,
932                    const CheckRange checkRanges[], int32_t countCheckRanges) {
933     UMutableCPTrie *mutableTrie;
934     uint32_t initialValue, errorValue;
935     uint32_t value;
936     UChar32 start, limit;
937     int32_t i;
938     UErrorCode errorCode;
939 
940     log_verbose("\ntesting Trie '%s'\n", testName);
941     errorCode=U_ZERO_ERROR;
942     getSpecialValues(checkRanges, countCheckRanges, &initialValue, &errorValue);
943     mutableTrie = umutablecptrie_open(initialValue, errorValue, &errorCode);
944     if(U_FAILURE(errorCode)) {
945         log_err("error: umutablecptrie_open(%s) failed: %s\n", testName, u_errorName(errorCode));
946         return NULL;
947     }
948 
949     /* set values from setRanges[] */
950     for(i=0; i<countSetRanges; ++i) {
951         if(withClone && i==countSetRanges/2) {
952             /* switch to a clone in the middle of setting values */
953             UMutableCPTrie *clone = umutablecptrie_clone(mutableTrie, &errorCode);
954             if(U_FAILURE(errorCode)) {
955                 log_err("error: umutablecptrie_clone(%s) failed - %s\n",
956                         testName, u_errorName(errorCode));
957                 errorCode=U_ZERO_ERROR;  /* continue with the original */
958             } else {
959                 umutablecptrie_close(mutableTrie);
960                 mutableTrie = clone;
961             }
962         }
963         start=setRanges[i].start;
964         limit=setRanges[i].limit;
965         value=setRanges[i].value;
966         if ((limit - start) == 1) {
967             umutablecptrie_set(mutableTrie, start, value, &errorCode);
968         } else {
969             umutablecptrie_setRange(mutableTrie, start, limit-1, value, &errorCode);
970         }
971     }
972 
973     if(U_SUCCESS(errorCode)) {
974         return mutableTrie;
975     } else {
976         log_err("error: setting values into a mutable trie (%s) failed - %s\n",
977                 testName, u_errorName(errorCode));
978         umutablecptrie_close(mutableTrie);
979         return NULL;
980     }
981 }
982 
983 static void
testTrieRanges(const char * testName,UBool withClone,const SetRange setRanges[],int32_t countSetRanges,const CheckRange checkRanges[],int32_t countCheckRanges)984 testTrieRanges(const char *testName, UBool withClone,
985                const SetRange setRanges[], int32_t countSetRanges,
986                const CheckRange checkRanges[], int32_t countCheckRanges) {
987     UMutableCPTrie *mutableTrie = makeTrieWithRanges(
988         testName, withClone, setRanges, countSetRanges, checkRanges, countCheckRanges);
989     if (mutableTrie != NULL) {
990         mutableTrie = testTrieSerializeAllValueWidth(testName, mutableTrie, withClone,
991                                                      checkRanges, countCheckRanges);
992         umutablecptrie_close(mutableTrie);
993     }
994 }
995 
996 /* test data ----------------------------------------------------------------*/
997 
998 /* set consecutive ranges, even with value 0 */
999 static const SetRange
1000 setRanges1[]={
1001     { 0,        0x40,     0    },
1002     { 0x40,     0xe7,     0x34 },
1003     { 0xe7,     0x3400,   0    },
1004     { 0x3400,   0x9fa6,   0x61 },
1005     { 0x9fa6,   0xda9e,   0x31 },
1006     { 0xdada,   0xeeee,   0xff },
1007     { 0xeeee,   0x11111,  1    },
1008     { 0x11111,  0x44444,  0x61 },
1009     { 0x44444,  0x60003,  0    },
1010     { 0xf0003,  0xf0004,  0xf  },
1011     { 0xf0004,  0xf0006,  0x10 },
1012     { 0xf0006,  0xf0007,  0x11 },
1013     { 0xf0007,  0xf0040,  0x12 },
1014     { 0xf0040,  0x110000, 0    }
1015 };
1016 
1017 static const CheckRange
1018 checkRanges1[]={
1019     { 0,        0 },
1020     { 0x40,     0 },
1021     { 0xe7,     0x34 },
1022     { 0x3400,   0 },
1023     { 0x9fa6,   0x61 },
1024     { 0xda9e,   0x31 },
1025     { 0xdada,   0 },
1026     { 0xeeee,   0xff },
1027     { 0x11111,  1 },
1028     { 0x44444,  0x61 },
1029     { 0xf0003,  0 },
1030     { 0xf0004,  0xf },
1031     { 0xf0006,  0x10 },
1032     { 0xf0007,  0x11 },
1033     { 0xf0040,  0x12 },
1034     { 0x110000, 0 }
1035 };
1036 
1037 /* set some interesting overlapping ranges */
1038 static const SetRange
1039 setRanges2[]={
1040     { 0x21,     0x7f,     0x5555 },
1041     { 0x2f800,  0x2fedc,  0x7a   },
1042     { 0x72,     0xdd,     3      },
1043     { 0xdd,     0xde,     4      },
1044     { 0x201,    0x240,    6      },  /* 3 consecutive blocks with the same pattern but */
1045     { 0x241,    0x280,    6      },  /* discontiguous value ranges, testing iteration */
1046     { 0x281,    0x2c0,    6      },
1047     { 0x2f987,  0x2fa98,  5      },
1048     { 0x2f777,  0x2f883,  0      },
1049     { 0x2fedc,  0x2ffaa,  1      },
1050     { 0x2ffaa,  0x2ffab,  2      },
1051     { 0x2ffbb,  0x2ffc0,  7      }
1052 };
1053 
1054 static const CheckRange
1055 checkRanges2[]={
1056     { 0,        0 },
1057     { 0x21,     0 },
1058     { 0x72,     0x5555 },
1059     { 0xdd,     3 },
1060     { 0xde,     4 },
1061     { 0x201,    0 },
1062     { 0x240,    6 },
1063     { 0x241,    0 },
1064     { 0x280,    6 },
1065     { 0x281,    0 },
1066     { 0x2c0,    6 },
1067     { 0x2f883,  0 },
1068     { 0x2f987,  0x7a },
1069     { 0x2fa98,  5 },
1070     { 0x2fedc,  0x7a },
1071     { 0x2ffaa,  1 },
1072     { 0x2ffab,  2 },
1073     { 0x2ffbb,  0 },
1074     { 0x2ffc0,  7 },
1075     { 0x110000, 0 }
1076 };
1077 
1078 /* use a non-zero initial value */
1079 static const SetRange
1080 setRanges3[]={
1081     { 0x31,     0xa4,     1 },
1082     { 0x3400,   0x6789,   2 },
1083     { 0x8000,   0x89ab,   9 },
1084     { 0x9000,   0xa000,   4 },
1085     { 0xabcd,   0xbcde,   3 },
1086     { 0x55555,  0x110000, 6 },  /* highStart<U+ffff with non-initialValue */
1087     { 0xcccc,   0x55555,  6 }
1088 };
1089 
1090 static const CheckRange
1091 checkRanges3[]={
1092     { 0,        9 },  /* non-zero initialValue */
1093     { 0x31,     9 },
1094     { 0xa4,     1 },
1095     { 0x3400,   9 },
1096     { 0x6789,   2 },
1097     { 0x9000,   9 },
1098     { 0xa000,   4 },
1099     { 0xabcd,   9 },
1100     { 0xbcde,   3 },
1101     { 0xcccc,   9 },
1102     { 0x110000, 6 }
1103 };
1104 
1105 /* empty or single-value tries, testing highStart==0 */
1106 static const SetRange
1107 setRangesEmpty[]={
1108     { 0,        0,        0 },  /* need some values for it to compile */
1109 };
1110 
1111 static const CheckRange
1112 checkRangesEmpty[]={
1113     { 0,        3 },
1114     { 0x110000, 3 }
1115 };
1116 
1117 static const SetRange
1118 setRangesSingleValue[]={
1119     { 0,        0x110000, 5 },
1120 };
1121 
1122 static const CheckRange
1123 checkRangesSingleValue[]={
1124     { 0,        3 },
1125     { 0x110000, 5 }
1126 };
1127 
1128 static void
TrieTestSet1(void)1129 TrieTestSet1(void) {
1130     testTrieRanges("set1", FALSE,
1131         setRanges1, UPRV_LENGTHOF(setRanges1),
1132         checkRanges1, UPRV_LENGTHOF(checkRanges1));
1133 }
1134 
1135 static void
TrieTestSet2Overlap(void)1136 TrieTestSet2Overlap(void) {
1137     testTrieRanges("set2-overlap", FALSE,
1138         setRanges2, UPRV_LENGTHOF(setRanges2),
1139         checkRanges2, UPRV_LENGTHOF(checkRanges2));
1140 }
1141 
1142 static void
TrieTestSet3Initial9(void)1143 TrieTestSet3Initial9(void) {
1144     testTrieRanges("set3-initial-9", FALSE,
1145         setRanges3, UPRV_LENGTHOF(setRanges3),
1146         checkRanges3, UPRV_LENGTHOF(checkRanges3));
1147 }
1148 
1149 static void
TrieTestSetEmpty(void)1150 TrieTestSetEmpty(void) {
1151     testTrieRanges("set-empty", FALSE,
1152         setRangesEmpty, 0,
1153         checkRangesEmpty, UPRV_LENGTHOF(checkRangesEmpty));
1154 }
1155 
1156 static void
TrieTestSetSingleValue(void)1157 TrieTestSetSingleValue(void) {
1158     testTrieRanges("set-single-value", FALSE,
1159         setRangesSingleValue, UPRV_LENGTHOF(setRangesSingleValue),
1160         checkRangesSingleValue, UPRV_LENGTHOF(checkRangesSingleValue));
1161 }
1162 
1163 static void
TrieTestSet2OverlapWithClone(void)1164 TrieTestSet2OverlapWithClone(void) {
1165     testTrieRanges("set2-overlap.withClone", TRUE,
1166         setRanges2, UPRV_LENGTHOF(setRanges2),
1167         checkRanges2, UPRV_LENGTHOF(checkRanges2));
1168 }
1169 
1170 /* test mutable-trie memory management -------------------------------------- */
1171 
1172 static void
FreeBlocksTest(void)1173 FreeBlocksTest(void) {
1174     static const CheckRange
1175     checkRanges[]={
1176         { 0,        1 },
1177         { 0x740,    1 },
1178         { 0x780,    2 },
1179         { 0x880,    3 },
1180         { 0x110000, 1 }
1181     };
1182     static const char *const testName="free-blocks";
1183 
1184     UMutableCPTrie *mutableTrie;
1185     int32_t i;
1186     UErrorCode errorCode;
1187 
1188     errorCode=U_ZERO_ERROR;
1189     mutableTrie=umutablecptrie_open(1, 0xad, &errorCode);
1190     if(U_FAILURE(errorCode)) {
1191         log_err("error: umutablecptrie_open(%s) failed: %s\n", testName, u_errorName(errorCode));
1192         return;
1193     }
1194 
1195     /*
1196      * Repeatedly set overlapping same-value ranges to stress the free-data-block management.
1197      * If it fails, it will overflow the data array.
1198      */
1199     for(i=0; i<(0x120000>>4)/2; ++i) {  // 4=UCPTRIE_SHIFT_3
1200         umutablecptrie_setRange(mutableTrie, 0x740, 0x840-1, 1, &errorCode);
1201         umutablecptrie_setRange(mutableTrie, 0x780, 0x880-1, 1, &errorCode);
1202         umutablecptrie_setRange(mutableTrie, 0x740, 0x840-1, 2, &errorCode);
1203         umutablecptrie_setRange(mutableTrie, 0x780, 0x880-1, 3, &errorCode);
1204     }
1205     /* make blocks that will be free during compaction */
1206     umutablecptrie_setRange(mutableTrie, 0x1000, 0x3000-1, 2, &errorCode);
1207     umutablecptrie_setRange(mutableTrie, 0x2000, 0x4000-1, 3, &errorCode);
1208     umutablecptrie_setRange(mutableTrie, 0x1000, 0x4000-1, 1, &errorCode);
1209     if(U_FAILURE(errorCode)) {
1210         log_err("error: setting lots of ranges into a mutable trie (%s) failed - %s\n",
1211                 testName, u_errorName(errorCode));
1212         umutablecptrie_close(mutableTrie);
1213         return;
1214     }
1215 
1216     mutableTrie = testTrieSerializeAllValueWidth(testName, mutableTrie, FALSE,
1217                                                  checkRanges, UPRV_LENGTHOF(checkRanges));
1218     umutablecptrie_close(mutableTrie);
1219 }
1220 
1221 static void
GrowDataArrayTest(void)1222 GrowDataArrayTest(void) {
1223     static const CheckRange
1224     checkRanges[]={
1225         { 0,        1 },
1226         { 0x720,    2 },
1227         { 0x7a0,    3 },
1228         { 0x8a0,    4 },
1229         { 0x110000, 5 }
1230     };
1231     static const char *const testName="grow-data";
1232 
1233     UMutableCPTrie *mutableTrie;
1234     int32_t i;
1235     UErrorCode errorCode;
1236 
1237     errorCode=U_ZERO_ERROR;
1238     mutableTrie=umutablecptrie_open(1, 0xad, &errorCode);
1239     if(U_FAILURE(errorCode)) {
1240         log_err("error: umutablecptrie_open(%s) failed: %s\n", testName, u_errorName(errorCode));
1241         return;
1242     }
1243 
1244     /*
1245      * Use umutablecptrie_set() not umutablecptrie_setRange() to write non-initialValue-data.
1246      * Should grow/reallocate the data array to a sufficient length.
1247      */
1248     for(i=0; i<0x1000; ++i) {
1249         umutablecptrie_set(mutableTrie, i, 2, &errorCode);
1250     }
1251     for(i=0x720; i<0x1100; ++i) { /* some overlap */
1252         umutablecptrie_set(mutableTrie, i, 3, &errorCode);
1253     }
1254     for(i=0x7a0; i<0x900; ++i) {
1255         umutablecptrie_set(mutableTrie, i, 4, &errorCode);
1256     }
1257     for(i=0x8a0; i<0x110000; ++i) {
1258         umutablecptrie_set(mutableTrie, i, 5, &errorCode);
1259     }
1260     if(U_FAILURE(errorCode)) {
1261         log_err("error: setting lots of values into a mutable trie (%s) failed - %s\n",
1262                 testName, u_errorName(errorCode));
1263         umutablecptrie_close(mutableTrie);
1264         return;
1265     }
1266 
1267     mutableTrie = testTrieSerializeAllValueWidth(testName, mutableTrie, FALSE,
1268                                                  checkRanges, UPRV_LENGTHOF(checkRanges));
1269     umutablecptrie_close(mutableTrie);
1270 }
1271 
1272 static void
ManyAllSameBlocksTest(void)1273 ManyAllSameBlocksTest(void) {
1274     static const char *const testName="many-all-same";
1275 
1276     UMutableCPTrie *mutableTrie;
1277     int32_t i;
1278     UErrorCode errorCode;
1279     CheckRange checkRanges[(0x110000 >> 12) + 1];
1280 
1281     errorCode = U_ZERO_ERROR;
1282     mutableTrie = umutablecptrie_open(0xff33, 0xad, &errorCode);
1283     if (U_FAILURE(errorCode)) {
1284         log_err("error: umutablecptrie_open(%s) failed: %s\n", testName, u_errorName(errorCode));
1285         return;
1286     }
1287     checkRanges[0].limit = 0;
1288     checkRanges[0].value = 0xff33;  // initialValue
1289 
1290     // Many all-same-value blocks.
1291     for (i = 0; i < 0x110000; i += 0x1000) {
1292         uint32_t value = i >> 12;
1293         umutablecptrie_setRange(mutableTrie, i, i + 0xfff, value, &errorCode);
1294         checkRanges[value + 1].limit = i + 0x1000;
1295         checkRanges[value + 1].value = value;
1296     }
1297     for (i = 0; i < 0x110000; i += 0x1000) {
1298         uint32_t expected = i >> 12;
1299         uint32_t v0 = umutablecptrie_get(mutableTrie, i);
1300         uint32_t vfff = umutablecptrie_get(mutableTrie, i + 0xfff);
1301         if (v0 != expected || vfff != expected) {
1302             log_err("error: UMutableCPTrie U+%04lx unexpected value\n", (long)i);
1303         }
1304     }
1305 
1306     mutableTrie = testTrieSerializeAllValueWidth(testName, mutableTrie, FALSE,
1307                                                  checkRanges, UPRV_LENGTHOF(checkRanges));
1308     umutablecptrie_close(mutableTrie);
1309 }
1310 
1311 static void
MuchDataTest(void)1312 MuchDataTest(void) {
1313     static const char *const testName="much-data";
1314 
1315     UMutableCPTrie *mutableTrie;
1316     int32_t r, c;
1317     UErrorCode errorCode = U_ZERO_ERROR;
1318     CheckRange checkRanges[(0x10000 >> 6) + (0x10240 >> 4) + 10];
1319 
1320     mutableTrie = umutablecptrie_open(0xff33, 0xad, &errorCode);
1321     if (U_FAILURE(errorCode)) {
1322         log_err("error: umutablecptrie_open(%s) failed: %s\n", testName, u_errorName(errorCode));
1323         return;
1324     }
1325     checkRanges[0].limit = 0;
1326     checkRanges[0].value = 0xff33;  // initialValue
1327     r = 1;
1328 
1329     // Add much data that does not compact well,
1330     // to get more than 128k data values after compaction.
1331     for (c = 0; c < 0x10000; c += 0x40) {
1332         uint32_t value = c >> 4;
1333         umutablecptrie_setRange(mutableTrie, c, c + 0x3f, value, &errorCode);
1334         checkRanges[r].limit = c + 0x40;
1335         checkRanges[r++].value = value;
1336     }
1337     checkRanges[r].limit = 0x20000;
1338     checkRanges[r++].value = 0xff33;
1339     for (c = 0x20000; c < 0x30230; c += 0x10) {
1340         uint32_t value = c >> 4;
1341         umutablecptrie_setRange(mutableTrie, c, c + 0xf, value, &errorCode);
1342         checkRanges[r].limit = c + 0x10;
1343         checkRanges[r++].value = value;
1344     }
1345     umutablecptrie_setRange(mutableTrie, 0x30230, 0x30233, 0x3023, &errorCode);
1346     checkRanges[r].limit = 0x30234;
1347     checkRanges[r++].value = 0x3023;
1348     umutablecptrie_setRange(mutableTrie, 0x30234, 0xdffff, 0x5005, &errorCode);
1349     checkRanges[r].limit = 0xe0000;
1350     checkRanges[r++].value = 0x5005;
1351     umutablecptrie_setRange(mutableTrie, 0xe0000, 0x10ffff, 0x9009, &errorCode);
1352     checkRanges[r].limit = 0x110000;
1353     checkRanges[r++].value = 0x9009;
1354     if (U_FAILURE(errorCode)) {
1355         log_err("error: setting lots of values into a mutable trie (%s) failed - %s\n",
1356                 testName, u_errorName(errorCode));
1357         umutablecptrie_close(mutableTrie);
1358         return;
1359     }
1360     U_ASSERT(r <= UPRV_LENGTHOF(checkRanges));
1361 
1362     testBuilder(testName, mutableTrie, checkRanges, r);
1363     testTrieSerialize("much-data.16", mutableTrie,
1364                       UCPTRIE_TYPE_FAST, UCPTRIE_VALUE_BITS_16, FALSE, checkRanges, r);
1365     umutablecptrie_close(mutableTrie);
1366 }
1367 
testGetRangesFixedSurr(const char * testName,const UMutableCPTrie * mutableTrie,UCPMapRangeOption option,const CheckRange checkRanges[],int32_t countCheckRanges)1368 static void testGetRangesFixedSurr(const char *testName, const UMutableCPTrie *mutableTrie,
1369                                    UCPMapRangeOption option,
1370                                    const CheckRange checkRanges[], int32_t countCheckRanges) {
1371     testTrieGetRanges(testName, NULL, mutableTrie, option, 5, checkRanges, countCheckRanges);
1372     UErrorCode errorCode = U_ZERO_ERROR;
1373     UMutableCPTrie *clone = umutablecptrie_clone(mutableTrie, &errorCode);
1374     UCPTrie *trie;
1375     if (U_FAILURE(errorCode)) {
1376         log_err("error: umutablecptrie_clone(%s) failed: %s\n", testName, u_errorName(errorCode));
1377         return;
1378     }
1379     trie = umutablecptrie_buildImmutable(clone, UCPTRIE_TYPE_FAST, UCPTRIE_VALUE_BITS_16, &errorCode);
1380     umutablecptrie_close(clone);
1381     if (U_FAILURE(errorCode)) {
1382         log_err("error: umutablecptrie_buildImmutable(%s) failed: %s\n", testName, u_errorName(errorCode));
1383         return;
1384     }
1385     testTrieGetRanges(testName, trie, NULL, option, 5, checkRanges, countCheckRanges);
1386     ucptrie_close(trie);
1387 }
1388 
1389 static void
TrieTestGetRangesFixedSurr(void)1390 TrieTestGetRangesFixedSurr(void) {
1391     static const SetRange
1392     setRangesFixedSurr[]={
1393         { 0xd000, 0xd7ff, 5 },
1394         { 0xd7ff, 0xe001, 3 },
1395         { 0xe001, 0xf900, 5 },
1396     };
1397 
1398     static const CheckRange
1399     checkRangesFixedLeadSurr1[]={
1400         { 0,      0 },
1401         { 0xd000, 0 },
1402         { 0xd7ff, 5 },
1403         { 0xd800, 3 },
1404         { 0xdc00, 5 },
1405         { 0xe001, 3 },
1406         { 0xf900, 5 },
1407         { 0x110000, 0 }
1408     };
1409 
1410     static const CheckRange
1411     checkRangesFixedAllSurr1[]={
1412         { 0,      0 },
1413         { 0xd000, 0 },
1414         { 0xd7ff, 5 },
1415         { 0xd800, 3 },
1416         { 0xe000, 5 },
1417         { 0xe001, 3 },
1418         { 0xf900, 5 },
1419         { 0x110000, 0 }
1420     };
1421 
1422     static const CheckRange
1423     checkRangesFixedLeadSurr3[]={
1424         { 0,      0 },
1425         { 0xd000, 0 },
1426         { 0xdc00, 5 },
1427         { 0xe001, 3 },
1428         { 0xf900, 5 },
1429         { 0x110000, 0 }
1430     };
1431 
1432     static const CheckRange
1433     checkRangesFixedAllSurr3[]={
1434         { 0,      0 },
1435         { 0xd000, 0 },
1436         { 0xe000, 5 },
1437         { 0xe001, 3 },
1438         { 0xf900, 5 },
1439         { 0x110000, 0 }
1440     };
1441 
1442     static const CheckRange
1443     checkRangesFixedSurr4[]={
1444         { 0,      0 },
1445         { 0xd000, 0 },
1446         { 0xf900, 5 },
1447         { 0x110000, 0 }
1448     };
1449 
1450     UMutableCPTrie *mutableTrie = makeTrieWithRanges(
1451         "fixedSurr", FALSE, setRangesFixedSurr, UPRV_LENGTHOF(setRangesFixedSurr),
1452         checkRangesFixedLeadSurr1, UPRV_LENGTHOF(checkRangesFixedLeadSurr1));
1453     UErrorCode errorCode = U_ZERO_ERROR;
1454     if (mutableTrie == NULL) {
1455         return;
1456     }
1457     testGetRangesFixedSurr("fixedLeadSurr1", mutableTrie, UCPMAP_RANGE_FIXED_LEAD_SURROGATES,
1458                            checkRangesFixedLeadSurr1, UPRV_LENGTHOF(checkRangesFixedLeadSurr1));
1459     testGetRangesFixedSurr("fixedAllSurr1", mutableTrie, UCPMAP_RANGE_FIXED_ALL_SURROGATES,
1460                            checkRangesFixedAllSurr1, UPRV_LENGTHOF(checkRangesFixedAllSurr1));
1461     // Setting a range in the middle of lead surrogates makes no difference.
1462     umutablecptrie_setRange(mutableTrie, 0xd844, 0xd899, 5, &errorCode);
1463     if (U_FAILURE(errorCode)) {
1464         log_err("error: umutablecptrie_setRange(fixedSurr2) failed: %s\n", u_errorName(errorCode));
1465         umutablecptrie_close(mutableTrie);
1466         return;
1467     }
1468     testGetRangesFixedSurr("fixedLeadSurr2", mutableTrie, UCPMAP_RANGE_FIXED_LEAD_SURROGATES,
1469                            checkRangesFixedLeadSurr1, UPRV_LENGTHOF(checkRangesFixedLeadSurr1));
1470     // Bridge the gap before the lead surrogates.
1471     umutablecptrie_set(mutableTrie, 0xd7ff, 5, &errorCode);
1472     if (U_FAILURE(errorCode)) {
1473         log_err("error: umutablecptrie_set(fixedSurr3) failed: %s\n", u_errorName(errorCode));
1474         umutablecptrie_close(mutableTrie);
1475         return;
1476     }
1477     testGetRangesFixedSurr("fixedLeadSurr3", mutableTrie, UCPMAP_RANGE_FIXED_LEAD_SURROGATES,
1478                            checkRangesFixedLeadSurr3, UPRV_LENGTHOF(checkRangesFixedLeadSurr3));
1479     testGetRangesFixedSurr("fixedAllSurr3", mutableTrie, UCPMAP_RANGE_FIXED_ALL_SURROGATES,
1480                            checkRangesFixedAllSurr3, UPRV_LENGTHOF(checkRangesFixedAllSurr3));
1481     // Bridge the gap after the trail surrogates.
1482     umutablecptrie_set(mutableTrie, 0xe000, 5, &errorCode);
1483     if (U_FAILURE(errorCode)) {
1484         log_err("error: umutablecptrie_set(fixedSurr4) failed: %s\n", u_errorName(errorCode));
1485         umutablecptrie_close(mutableTrie);
1486         return;
1487     }
1488     testGetRangesFixedSurr("fixedSurr4", mutableTrie, UCPMAP_RANGE_FIXED_ALL_SURROGATES,
1489                            checkRangesFixedSurr4, UPRV_LENGTHOF(checkRangesFixedSurr4));
1490     umutablecptrie_close(mutableTrie);
1491 }
1492 
TestSmallNullBlockMatchesFast(void)1493 static void TestSmallNullBlockMatchesFast(void) {
1494     // The initial builder+getRange code had a bug:
1495     // When there is no null data block in the fast-index range,
1496     // but a fast-range data block starts with enough values to match a small data block,
1497     // then getRange() got confused.
1498     // The builder must prevent this.
1499     static const SetRange setRanges[] = {
1500         { 0, 0x880, 1 },
1501         // U+0880..U+088F map to initial value 0, potential match for small null data block.
1502         { 0x890, 0x1040, 2 },
1503         // U+1040..U+1050 map to 0.
1504         // First small null data block in a small-type trie.
1505         // In a fast-type trie, it is ok to match a small null data block at U+1041
1506         // but not at U+1040.
1507         { 0x1051, 0x10000, 3 },
1508         // No fast data block (block length 64) filled with 0 regardless of trie type.
1509         // Need more blocks filled with 0 than the largest range above,
1510         // and need a highStart above that so that it actually counts.
1511         { 0x20000, 0x110000, 9 }
1512     };
1513 
1514     static const CheckRange checkRanges[] = {
1515         { 0x0880, 1 },
1516         { 0x0890, 0 },
1517         { 0x1040, 2 },
1518         { 0x1051, 0 },
1519         { 0x10000, 3 },
1520         { 0x20000, 0 },
1521         { 0x110000, 9 }
1522     };
1523 
1524     testTrieRanges("small0-in-fast", FALSE,
1525         setRanges, UPRV_LENGTHOF(setRanges),
1526         checkRanges, UPRV_LENGTHOF(checkRanges));
1527 }
1528 
ShortAllSameBlocksTest(void)1529 static void ShortAllSameBlocksTest(void) {
1530     static const char *const testName = "short-all-same";
1531     // Many all-same-value blocks but only of the small block length used in the mutable trie.
1532     // The builder code needs to turn a group of short ALL_SAME blocks below fastLimit
1533     // into a MIXED block, and reserve data array capacity for that.
1534     UErrorCode errorCode = U_ZERO_ERROR;
1535     UMutableCPTrie *mutableTrie = umutablecptrie_open(0, 0xad, &errorCode);
1536     CheckRange checkRanges[0x101];
1537     int32_t i;
1538     if (U_FAILURE(errorCode)) {
1539         log_err("error: umutablecptrie_open(%s) failed: %s\n", testName, u_errorName(errorCode));
1540         return;
1541     }
1542     for (i = 0; i < 0x1000; i += 0x10) {
1543         uint32_t value = i >> 4;
1544         umutablecptrie_setRange(mutableTrie, i, i + 0xf, value, &errorCode);
1545         checkRanges[value].limit = i + 0x10;
1546         checkRanges[value].value = value;
1547     }
1548     checkRanges[0x100].limit = 0x110000;
1549     checkRanges[0x100].value = 0;
1550     if (U_FAILURE(errorCode)) {
1551         log_err("error: setting values into a mutable trie (%s) failed - %s\n",
1552                 testName, u_errorName(errorCode));
1553         umutablecptrie_close(mutableTrie);
1554         return;
1555     }
1556 
1557     mutableTrie = testTrieSerializeAllValueWidth(testName, mutableTrie, FALSE,
1558                                                  checkRanges, UPRV_LENGTHOF(checkRanges));
1559     umutablecptrie_close(mutableTrie);
1560 }
1561 
1562 void
addUCPTrieTest(TestNode ** root)1563 addUCPTrieTest(TestNode** root) {
1564     addTest(root, &TrieTestSet1, "tsutil/ucptrietest/TrieTestSet1");
1565     addTest(root, &TrieTestSet2Overlap, "tsutil/ucptrietest/TrieTestSet2Overlap");
1566     addTest(root, &TrieTestSet3Initial9, "tsutil/ucptrietest/TrieTestSet3Initial9");
1567     addTest(root, &TrieTestSetEmpty, "tsutil/ucptrietest/TrieTestSetEmpty");
1568     addTest(root, &TrieTestSetSingleValue, "tsutil/ucptrietest/TrieTestSetSingleValue");
1569     addTest(root, &TrieTestSet2OverlapWithClone, "tsutil/ucptrietest/TrieTestSet2OverlapWithClone");
1570     addTest(root, &FreeBlocksTest, "tsutil/ucptrietest/FreeBlocksTest");
1571     addTest(root, &GrowDataArrayTest, "tsutil/ucptrietest/GrowDataArrayTest");
1572     addTest(root, &ManyAllSameBlocksTest, "tsutil/ucptrietest/ManyAllSameBlocksTest");
1573     addTest(root, &MuchDataTest, "tsutil/ucptrietest/MuchDataTest");
1574     addTest(root, &TrieTestGetRangesFixedSurr, "tsutil/ucptrietest/TrieTestGetRangesFixedSurr");
1575     addTest(root, &TestSmallNullBlockMatchesFast, "tsutil/ucptrietest/TestSmallNullBlockMatchesFast");
1576     addTest(root, &ShortAllSameBlocksTest, "tsutil/ucptrietest/ShortAllSameBlocksTest");
1577 }
1578