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