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