]> git.saurik.com Git - apple/icu.git/blob - icuSources/test/cintltst/trietest.c
ICU-57132.0.1.tar.gz
[apple/icu.git] / icuSources / test / cintltst / trietest.c
1 /*
2 ******************************************************************************
3 *
4 * Copyright (C) 2001-2016, 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: 2001nov20
14 * created by: Markus W. Scherer
15 */
16
17 #include <stdio.h>
18 #include "unicode/utypes.h"
19 #include "unicode/utf16.h"
20 #include "utrie.h"
21 #include "cstring.h"
22 #include "cmemory.h"
23
24 #if 1
25 #include "cintltst.h"
26 #else
27 /* definitions from standalone utrie development */
28 #define log_err printf
29 #define log_verbose printf
30
31 #undef u_errorName
32 #define u_errorName(errorCode) "some error code"
33 #endif
34
35 /* Values for setting possibly overlapping, out-of-order ranges of values */
36 typedef struct SetRange {
37 UChar32 start, limit;
38 uint32_t value;
39 UBool overwrite;
40 } SetRange;
41
42 /*
43 * Values for testing:
44 * value is set from the previous boundary's limit to before
45 * this boundary's limit
46 */
47 typedef struct CheckRange {
48 UChar32 limit;
49 uint32_t value;
50 } CheckRange;
51
52
53 static uint32_t U_CALLCONV
54 _testFoldedValue32(UNewTrie *trie, UChar32 start, int32_t offset) {
55 uint32_t foldedValue, value;
56 UChar32 limit;
57 UBool inBlockZero;
58
59 foldedValue=0;
60
61 limit=start+0x400;
62 while(start<limit) {
63 value=utrie_get32(trie, start, &inBlockZero);
64 if(inBlockZero) {
65 start+=UTRIE_DATA_BLOCK_LENGTH;
66 } else {
67 foldedValue|=value;
68 ++start;
69 }
70 }
71
72 if(foldedValue!=0) {
73 return ((uint32_t)offset<<16)|foldedValue;
74 } else {
75 return 0;
76 }
77 }
78
79 static int32_t U_CALLCONV
80 _testFoldingOffset32(uint32_t data) {
81 return (int32_t)(data>>16);
82 }
83
84 static uint32_t U_CALLCONV
85 _testFoldedValue16(UNewTrie *trie, UChar32 start, int32_t offset) {
86 uint32_t foldedValue, value;
87 UChar32 limit;
88 UBool inBlockZero;
89
90 foldedValue=0;
91
92 limit=start+0x400;
93 while(start<limit) {
94 value=utrie_get32(trie, start, &inBlockZero);
95 if(inBlockZero) {
96 start+=UTRIE_DATA_BLOCK_LENGTH;
97 } else {
98 foldedValue|=value;
99 ++start;
100 }
101 }
102
103 if(foldedValue!=0) {
104 return (uint32_t)(offset|0x8000);
105 } else {
106 return 0;
107 }
108 }
109
110 static int32_t U_CALLCONV
111 _testFoldingOffset16(uint32_t data) {
112 if(data&0x8000) {
113 return (int32_t)(data&0x7fff);
114 } else {
115 return 0;
116 }
117 }
118
119 static uint32_t U_CALLCONV
120 _testEnumValue(const void *context, uint32_t value) {
121 return value^0x5555;
122 }
123
124 static UBool U_CALLCONV
125 _testEnumRange(const void *context, UChar32 start, UChar32 limit, uint32_t value) {
126 const CheckRange **pb=(const CheckRange **)context;
127 const CheckRange *b=(*pb)++;
128
129 value^=0x5555;
130 if(start!=(b-1)->limit || limit!=b->limit || value!=b->value) {
131 log_err("error: utrie_enum() delivers wrong range [U+%04lx..U+%04lx[.0x%lx instead of [U+%04lx..U+%04lx[.0x%lx\n",
132 start, limit, value,
133 (b-1)->limit, b->limit, b->value);
134 }
135 return TRUE;
136 }
137
138 static void
139 testTrieIteration(const char *testName,
140 const UTrie *trie,
141 const CheckRange checkRanges[], int32_t countCheckRanges) {
142 UChar s[100];
143 uint32_t values[30];
144
145 const UChar *p, *limit;
146
147 uint32_t value;
148 UChar32 c;
149 int32_t i, length, countValues;
150 UChar c2;
151
152 /* write a string */
153 length=countValues=0;
154 for(i=0; i<countCheckRanges; ++i) {
155 c=checkRanges[i].limit;
156 if(c!=0) {
157 --c;
158 U16_APPEND_UNSAFE(s, length, c);
159 values[countValues++]=checkRanges[i].value;
160 }
161 }
162 limit=s+length;
163
164 /* try forward */
165 p=s;
166 i=0;
167 while(p<limit) {
168 c=c2=0x33;
169 if(trie->data32!=NULL) {
170 UTRIE_NEXT32(trie, p, limit, c, c2, value);
171 } else {
172 UTRIE_NEXT16(trie, p, limit, c, c2, value);
173 }
174 if(value!=values[i]) {
175 log_err("error: wrong value from UTRIE_NEXT(%s)(U+%04lx, U+%04lx): 0x%lx instead of 0x%lx\n",
176 testName, c, c2, value, values[i]);
177 }
178 if(
179 c2==0 ?
180 c!=*(p-1) :
181 !U16_IS_LEAD(c) || !U16_IS_TRAIL(c2) || c!=*(p-2) || c2!=*(p-1)
182 ) {
183 log_err("error: wrong (c, c2) from UTRIE_NEXT(%s): (U+%04lx, U+%04lx)\n",
184 testName, c, c2);
185 continue;
186 }
187 if(c2!=0) {
188 int32_t offset;
189
190 if(trie->data32==NULL) {
191 value=UTRIE_GET16_FROM_LEAD(trie, c);
192 offset=trie->getFoldingOffset(value);
193 if(offset>0) {
194 value=UTRIE_GET16_FROM_OFFSET_TRAIL(trie, offset, c2);
195 } else {
196 value=trie->initialValue;
197 }
198 } else {
199 value=UTRIE_GET32_FROM_LEAD(trie, c);
200 offset=trie->getFoldingOffset(value);
201 if(offset>0) {
202 value=UTRIE_GET32_FROM_OFFSET_TRAIL(trie, offset, c2);
203 } else {
204 value=trie->initialValue;
205 }
206 }
207 if(value!=values[i]) {
208 log_err("error: wrong value from UTRIE_GETXX_FROM_OFFSET_TRAIL(%s)(U+%04lx, U+%04lx): 0x%lx instead of 0x%lx\n",
209 testName, c, c2, value, values[i]);
210 }
211 }
212 if(c2!=0) {
213 value=0x44;
214 if(trie->data32==NULL) {
215 UTRIE_GET16_FROM_PAIR(trie, c, c2, value);
216 } else {
217 UTRIE_GET32_FROM_PAIR(trie, c, c2, value);
218 }
219 if(value!=values[i]) {
220 log_err("error: wrong value from UTRIE_GETXX_FROM_PAIR(%s)(U+%04lx, U+%04lx): 0x%lx instead of 0x%lx\n",
221 testName, c, c2, value, values[i]);
222 }
223 }
224 ++i;
225 }
226
227 /* try backward */
228 p=limit;
229 i=countValues;
230 while(s<p) {
231 --i;
232 c=c2=0x33;
233 if(trie->data32!=NULL) {
234 UTRIE_PREVIOUS32(trie, s, p, c, c2, value);
235 } else {
236 UTRIE_PREVIOUS16(trie, s, p, c, c2, value);
237 }
238 if(value!=values[i]) {
239 log_err("error: wrong value from UTRIE_PREVIOUS(%s)(U+%04lx, U+%04lx): 0x%lx instead of 0x%lx\n",
240 testName, c, c2, value, values[i]);
241 }
242 if(
243 c2==0 ?
244 c!=*p:
245 !U16_IS_LEAD(c) || !U16_IS_TRAIL(c2) || c!=*p || c2!=*(p+1)
246 ) {
247 log_err("error: wrong (c, c2) from UTRIE_PREVIOUS(%s): (U+%04lx, U+%04lx)\n",
248 testName, c, c2);
249 }
250 }
251 }
252
253 static void
254 testTrieRangesWithMalloc(const char *testName,
255 const SetRange setRanges[], int32_t countSetRanges,
256 const CheckRange checkRanges[], int32_t countCheckRanges,
257 UBool dataIs32, UBool latin1Linear) {
258 UTrieGetFoldingOffset *getFoldingOffset;
259 const CheckRange *enumRanges;
260 UNewTrie *newTrie;
261 UTrie trie={ 0 };
262 uint32_t value, value2;
263 UChar32 start, limit;
264 int32_t i, length;
265 UErrorCode errorCode;
266 UBool overwrite, ok;
267 uint8_t* storage =NULL;
268 static const int32_t DEFAULT_STORAGE_SIZE = 32768;
269 storage = (uint8_t*) uprv_malloc(sizeof(uint8_t)*DEFAULT_STORAGE_SIZE);
270
271 log_verbose("\ntesting Trie '%s'\n", testName);
272 newTrie=utrie_open(NULL, NULL, 2000,
273 checkRanges[0].value, checkRanges[0].value,
274 latin1Linear);
275
276 /* set values from setRanges[] */
277 ok=TRUE;
278 for(i=0; i<countSetRanges; ++i) {
279 start=setRanges[i].start;
280 limit=setRanges[i].limit;
281 value=setRanges[i].value;
282 overwrite=setRanges[i].overwrite;
283 if((limit-start)==1 && overwrite) {
284 ok&=utrie_set32(newTrie, start, value);
285 } else {
286 ok&=utrie_setRange32(newTrie, start, limit, value, overwrite);
287 }
288 }
289 if(!ok) {
290 log_err("error: setting values into a trie failed (%s)\n", testName);
291 return;
292 }
293
294 /* verify that all these values are in the new Trie */
295 start=0;
296 for(i=0; i<countCheckRanges; ++i) {
297 limit=checkRanges[i].limit;
298 value=checkRanges[i].value;
299
300 while(start<limit) {
301 if(value!=utrie_get32(newTrie, start, NULL)) {
302 log_err("error: newTrie(%s)[U+%04lx]==0x%lx instead of 0x%lx\n",
303 testName, start, utrie_get32(newTrie, start, NULL), value);
304 }
305 ++start;
306 }
307 }
308
309 if(dataIs32) {
310 getFoldingOffset=_testFoldingOffset32;
311 } else {
312 getFoldingOffset=_testFoldingOffset16;
313 }
314
315 errorCode=U_ZERO_ERROR;
316 length=utrie_serialize(newTrie, storage, DEFAULT_STORAGE_SIZE,
317 dataIs32 ? _testFoldedValue32 : _testFoldedValue16,
318 (UBool)!dataIs32,
319 &errorCode);
320 if(U_FAILURE(errorCode)) {
321 log_err("error: utrie_serialize(%s) failed: %s\n", testName, u_errorName(errorCode));
322 utrie_close(newTrie);
323 return;
324 }
325
326 /* test linear Latin-1 range from utrie_getData() */
327 if(latin1Linear) {
328 uint32_t *data;
329 int32_t dataLength;
330
331 data=utrie_getData(newTrie, &dataLength);
332 start=0;
333 for(i=0; i<countCheckRanges && start<=0xff; ++i) {
334 limit=checkRanges[i].limit;
335 value=checkRanges[i].value;
336
337 while(start<limit && start<=0xff) {
338 if(value!=data[UTRIE_DATA_BLOCK_LENGTH+start]) {
339 log_err("error: newTrie(%s).latin1Data[U+%04lx]==0x%lx instead of 0x%lx\n",
340 testName, start, data[UTRIE_DATA_BLOCK_LENGTH+start], value);
341 }
342 ++start;
343 }
344 }
345 }
346
347 utrie_close(newTrie);
348
349 errorCode=U_ZERO_ERROR;
350 if(!utrie_unserialize(&trie, storage, length, &errorCode)) {
351 log_err("error: utrie_unserialize() failed, %s\n", u_errorName(errorCode));
352 return;
353 }
354 trie.getFoldingOffset=getFoldingOffset;
355
356 if(dataIs32!=(trie.data32!=NULL)) {
357 log_err("error: trie serialization (%s) did not preserve 32-bitness\n", testName);
358 }
359 if(latin1Linear!=trie.isLatin1Linear) {
360 log_err("error: trie serialization (%s) did not preserve Latin-1-linearity\n", testName);
361 }
362
363 /* verify that all these values are in the unserialized Trie */
364 start=0;
365 for(i=0; i<countCheckRanges; ++i) {
366 limit=checkRanges[i].limit;
367 value=checkRanges[i].value;
368
369 if(start==0xd800) {
370 /* skip surrogates */
371 start=limit;
372 continue;
373 }
374
375 while(start<limit) {
376 if(start<=0xffff) {
377 if(dataIs32) {
378 value2=UTRIE_GET32_FROM_BMP(&trie, start);
379 } else {
380 value2=UTRIE_GET16_FROM_BMP(&trie, start);
381 }
382 if(value!=value2) {
383 log_err("error: unserialized trie(%s).fromBMP(U+%04lx)==0x%lx instead of 0x%lx\n",
384 testName, start, value2, value);
385 }
386 if(!U16_IS_LEAD(start)) {
387 if(dataIs32) {
388 value2=UTRIE_GET32_FROM_LEAD(&trie, start);
389 } else {
390 value2=UTRIE_GET16_FROM_LEAD(&trie, start);
391 }
392 if(value!=value2) {
393 log_err("error: unserialized trie(%s).fromLead(U+%04lx)==0x%lx instead of 0x%lx\n",
394 testName, start, value2, value);
395 }
396 }
397 }
398 if(dataIs32) {
399 UTRIE_GET32(&trie, start, value2);
400 } else {
401 UTRIE_GET16(&trie, start, value2);
402 }
403 if(value!=value2) {
404 log_err("error: unserialized trie(%s).get(U+%04lx)==0x%lx instead of 0x%lx\n",
405 testName, start, value2, value);
406 }
407 ++start;
408 }
409 }
410
411 /* enumerate and verify all ranges */
412 enumRanges=checkRanges+1;
413 utrie_enum(&trie, _testEnumValue, _testEnumRange, &enumRanges);
414
415 /* test linear Latin-1 range */
416 if(trie.isLatin1Linear) {
417 if(trie.data32!=NULL) {
418 const uint32_t *latin1=UTRIE_GET32_LATIN1(&trie);
419
420 for(start=0; start<0x100; ++start) {
421 if(latin1[start]!=UTRIE_GET32_FROM_LEAD(&trie, start)) {
422 log_err("error: (%s) trie.latin1[U+%04lx]=0x%lx!=0x%lx=trie.get32(U+%04lx)\n",
423 testName, start, latin1[start], UTRIE_GET32_FROM_LEAD(&trie, start), start);
424 }
425 }
426 } else {
427 const uint16_t *latin1=UTRIE_GET16_LATIN1(&trie);
428
429 for(start=0; start<0x100; ++start) {
430 if(latin1[start]!=UTRIE_GET16_FROM_LEAD(&trie, start)) {
431 log_err("error: (%s) trie.latin1[U+%04lx]=0x%lx!=0x%lx=trie.get16(U+%04lx)\n",
432 testName, start, latin1[start], UTRIE_GET16_FROM_LEAD(&trie, start), start);
433 }
434 }
435 }
436 }
437
438 testTrieIteration(testName, &trie, checkRanges, countCheckRanges);
439 uprv_free(storage);
440 }
441
442 static void
443 testTrieRanges(const char *testName,
444 const SetRange setRanges[], int32_t countSetRanges,
445 const CheckRange checkRanges[], int32_t countCheckRanges,
446 UBool dataIs32, UBool latin1Linear) {
447 union{
448 double bogus; /* needed for aligining the storage */
449 uint8_t storage[32768];
450 } storageHolder;
451 UTrieGetFoldingOffset *getFoldingOffset;
452 UNewTrieGetFoldedValue *getFoldedValue;
453 const CheckRange *enumRanges;
454 UNewTrie *newTrie;
455 UTrie trie={ 0 };
456 uint32_t value, value2;
457 UChar32 start, limit;
458 int32_t i, length;
459 UErrorCode errorCode;
460 UBool overwrite, ok;
461
462 log_verbose("\ntesting Trie '%s'\n", testName);
463 newTrie=utrie_open(NULL, NULL, 2000,
464 checkRanges[0].value, checkRanges[0].value,
465 latin1Linear);
466
467 /* set values from setRanges[] */
468 ok=TRUE;
469 for(i=0; i<countSetRanges; ++i) {
470 start=setRanges[i].start;
471 limit=setRanges[i].limit;
472 value=setRanges[i].value;
473 overwrite=setRanges[i].overwrite;
474 if((limit-start)==1 && overwrite) {
475 ok&=utrie_set32(newTrie, start, value);
476 } else {
477 ok&=utrie_setRange32(newTrie, start, limit, value, overwrite);
478 }
479 }
480 if(!ok) {
481 log_err("error: setting values into a trie failed (%s)\n", testName);
482 return;
483 }
484
485 /* verify that all these values are in the new Trie */
486 start=0;
487 for(i=0; i<countCheckRanges; ++i) {
488 limit=checkRanges[i].limit;
489 value=checkRanges[i].value;
490
491 while(start<limit) {
492 if(value!=utrie_get32(newTrie, start, NULL)) {
493 log_err("error: newTrie(%s)[U+%04lx]==0x%lx instead of 0x%lx\n",
494 testName, start, utrie_get32(newTrie, start, NULL), value);
495 }
496 ++start;
497 }
498 }
499
500 if(dataIs32) {
501 getFoldingOffset=_testFoldingOffset32;
502 getFoldedValue=_testFoldedValue32;
503 } else {
504 getFoldingOffset=_testFoldingOffset16;
505 getFoldedValue=_testFoldedValue16;
506 }
507
508 /*
509 * code coverage for utrie.c/defaultGetFoldedValue(),
510 * pick some combination of parameters for selecting the UTrie defaults
511 */
512 if(!dataIs32 && latin1Linear) {
513 getFoldingOffset=NULL;
514 getFoldedValue=NULL;
515 }
516
517 errorCode=U_ZERO_ERROR;
518 length=utrie_serialize(newTrie, storageHolder.storage, sizeof(storageHolder.storage),
519 getFoldedValue,
520 (UBool)!dataIs32,
521 &errorCode);
522 if(U_FAILURE(errorCode)) {
523 log_err("error: utrie_serialize(%s) failed: %s\n", testName, u_errorName(errorCode));
524 utrie_close(newTrie);
525 return;
526 }
527 if (length >= (int32_t)sizeof(storageHolder.storage)) {
528 log_err("error: utrie_serialize(%s) needs more memory\n", testName);
529 utrie_close(newTrie);
530 return;
531 }
532
533 /* test linear Latin-1 range from utrie_getData() */
534 if(latin1Linear) {
535 uint32_t *data;
536 int32_t dataLength;
537
538 data=utrie_getData(newTrie, &dataLength);
539 start=0;
540 for(i=0; i<countCheckRanges && start<=0xff; ++i) {
541 limit=checkRanges[i].limit;
542 value=checkRanges[i].value;
543
544 while(start<limit && start<=0xff) {
545 if(value!=data[UTRIE_DATA_BLOCK_LENGTH+start]) {
546 log_err("error: newTrie(%s).latin1Data[U+%04lx]==0x%lx instead of 0x%lx\n",
547 testName, start, data[UTRIE_DATA_BLOCK_LENGTH+start], value);
548 }
549 ++start;
550 }
551 }
552 }
553
554 utrie_close(newTrie);
555
556 errorCode=U_ZERO_ERROR;
557 if(!utrie_unserialize(&trie, storageHolder.storage, length, &errorCode)) {
558 log_err("error: utrie_unserialize() failed, %s\n", u_errorName(errorCode));
559 return;
560 }
561 if(getFoldingOffset!=NULL) {
562 trie.getFoldingOffset=getFoldingOffset;
563 }
564
565 if(dataIs32!=(trie.data32!=NULL)) {
566 log_err("error: trie serialization (%s) did not preserve 32-bitness\n", testName);
567 }
568 if(latin1Linear!=trie.isLatin1Linear) {
569 log_err("error: trie serialization (%s) did not preserve Latin-1-linearity\n", testName);
570 }
571
572 /* verify that all these values are in the unserialized Trie */
573 start=0;
574 for(i=0; i<countCheckRanges; ++i) {
575 limit=checkRanges[i].limit;
576 value=checkRanges[i].value;
577
578 if(start==0xd800) {
579 /* skip surrogates */
580 start=limit;
581 continue;
582 }
583
584 while(start<limit) {
585 if(start<=0xffff) {
586 if(dataIs32) {
587 value2=UTRIE_GET32_FROM_BMP(&trie, start);
588 } else {
589 value2=UTRIE_GET16_FROM_BMP(&trie, start);
590 }
591 if(value!=value2) {
592 log_err("error: unserialized trie(%s).fromBMP(U+%04lx)==0x%lx instead of 0x%lx\n",
593 testName, start, value2, value);
594 }
595 if(!U16_IS_LEAD(start)) {
596 if(dataIs32) {
597 value2=UTRIE_GET32_FROM_LEAD(&trie, start);
598 } else {
599 value2=UTRIE_GET16_FROM_LEAD(&trie, start);
600 }
601 if(value!=value2) {
602 log_err("error: unserialized trie(%s).fromLead(U+%04lx)==0x%lx instead of 0x%lx\n",
603 testName, start, value2, value);
604 }
605 }
606 }
607 if(dataIs32) {
608 UTRIE_GET32(&trie, start, value2);
609 } else {
610 UTRIE_GET16(&trie, start, value2);
611 }
612 if(value!=value2) {
613 log_err("error: unserialized trie(%s).get(U+%04lx)==0x%lx instead of 0x%lx\n",
614 testName, start, value2, value);
615 }
616 ++start;
617 }
618 }
619
620 /* enumerate and verify all ranges */
621 enumRanges=checkRanges+1;
622 utrie_enum(&trie, _testEnumValue, _testEnumRange, &enumRanges);
623
624 /* test linear Latin-1 range */
625 if(trie.isLatin1Linear) {
626 if(trie.data32!=NULL) {
627 const uint32_t *latin1=UTRIE_GET32_LATIN1(&trie);
628
629 for(start=0; start<0x100; ++start) {
630 if(latin1[start]!=UTRIE_GET32_FROM_LEAD(&trie, start)) {
631 log_err("error: (%s) trie.latin1[U+%04lx]=0x%lx!=0x%lx=trie.get32(U+%04lx)\n",
632 testName, start, latin1[start], UTRIE_GET32_FROM_LEAD(&trie, start), start);
633 }
634 }
635 } else {
636 const uint16_t *latin1=UTRIE_GET16_LATIN1(&trie);
637
638 for(start=0; start<0x100; ++start) {
639 if(latin1[start]!=UTRIE_GET16_FROM_LEAD(&trie, start)) {
640 log_err("error: (%s) trie.latin1[U+%04lx]=0x%lx!=0x%lx=trie.get16(U+%04lx)\n",
641 testName, start, latin1[start], UTRIE_GET16_FROM_LEAD(&trie, start), start);
642 }
643 }
644 }
645 }
646
647 testTrieIteration(testName, &trie, checkRanges, countCheckRanges);
648 }
649
650 static void
651 testTrieRanges2(const char *testName,
652 const SetRange setRanges[], int32_t countSetRanges,
653 const CheckRange checkRanges[], int32_t countCheckRanges,
654 UBool dataIs32) {
655 char name[40];
656
657 testTrieRanges(testName,
658 setRanges, countSetRanges,
659 checkRanges, countCheckRanges,
660 dataIs32, FALSE);
661 testTrieRangesWithMalloc(testName,
662 setRanges, countSetRanges,
663 checkRanges, countCheckRanges,
664 dataIs32, FALSE);
665
666 uprv_strcpy(name, testName);
667 uprv_strcat(name, "-latin1Linear");
668 testTrieRanges(name,
669 setRanges, countSetRanges,
670 checkRanges, countCheckRanges,
671 dataIs32, TRUE);
672 testTrieRangesWithMalloc(name,
673 setRanges, countSetRanges,
674 checkRanges, countCheckRanges,
675 dataIs32, TRUE);
676 }
677
678 static void
679 testTrieRanges4(const char *testName,
680 const SetRange setRanges[], int32_t countSetRanges,
681 const CheckRange checkRanges[], int32_t countCheckRanges) {
682 char name[40];
683
684 uprv_strcpy(name, testName);
685 uprv_strcat(name, ".32");
686 testTrieRanges2(name,
687 setRanges, countSetRanges,
688 checkRanges, countCheckRanges,
689 TRUE);
690
691 uprv_strcpy(name, testName);
692 uprv_strcat(name, ".16");
693 testTrieRanges2(name,
694 setRanges, countSetRanges,
695 checkRanges, countCheckRanges,
696 FALSE);
697 }
698
699 /* test data ----------------------------------------------------------------*/
700
701 /* set consecutive ranges, even with value 0 */
702 static const SetRange
703 setRanges1[]={
704 {0, 0x20, 0, FALSE},
705 {0x20, 0xa7, 0x1234, FALSE},
706 {0xa7, 0x3400, 0, FALSE},
707 {0x3400, 0x9fa6, 0x6162, FALSE},
708 {0x9fa6, 0xda9e, 0x3132, FALSE},
709 {0xdada, 0xeeee, 0x87ff, FALSE}, /* try to disrupt _testFoldingOffset16() */
710 {0xeeee, 0x11111, 1, FALSE},
711 {0x11111, 0x44444, 0x6162, FALSE},
712 {0x44444, 0x60003, 0, FALSE},
713 {0xf0003, 0xf0004, 0xf, FALSE},
714 {0xf0004, 0xf0006, 0x10, FALSE},
715 {0xf0006, 0xf0007, 0x11, FALSE},
716 {0xf0007, 0xf0020, 0x12, FALSE},
717 {0xf0020, 0x110000, 0, FALSE}
718 };
719
720 static const CheckRange
721 checkRanges1[]={
722 {0, 0}, /* dummy start range to make _testEnumRange() simpler */
723 {0x20, 0},
724 {0xa7, 0x1234},
725 {0x3400, 0},
726 {0x9fa6, 0x6162},
727 {0xda9e, 0x3132},
728 {0xdada, 0},
729 {0xeeee, 0x87ff},
730 {0x11111,1},
731 {0x44444,0x6162},
732 {0xf0003,0},
733 {0xf0004,0xf},
734 {0xf0006,0x10},
735 {0xf0007,0x11},
736 {0xf0020,0x12},
737 {0x110000, 0}
738 };
739
740 /* set some interesting overlapping ranges */
741 static const SetRange
742 setRanges2[]={
743 {0x21, 0x7f, 0x5555, TRUE},
744 {0x2f800,0x2fedc, 0x7a, TRUE},
745 {0x72, 0xdd, 3, TRUE},
746 {0xdd, 0xde, 4, FALSE},
747 {0x201, 0x220, 6, TRUE}, /* 3 consecutive blocks with the same pattern but discontiguous value ranges */
748 {0x221, 0x240, 6, TRUE},
749 {0x241, 0x260, 6, TRUE},
750 {0x2f987,0x2fa98, 5, TRUE},
751 {0x2f777,0x2f833, 0, TRUE},
752 {0x2f900,0x2ffee, 1, FALSE},
753 {0x2ffee,0x2ffef, 2, TRUE}
754 };
755
756 static const CheckRange
757 checkRanges2[]={
758 {0, 0}, /* dummy start range to make _testEnumRange() simpler */
759 {0x21, 0},
760 {0x72, 0x5555},
761 {0xdd, 3},
762 {0xde, 4},
763 {0x201, 0},
764 {0x220, 6},
765 {0x221, 0},
766 {0x240, 6},
767 {0x241, 0},
768 {0x260, 6},
769 {0x2f833,0},
770 {0x2f987,0x7a},
771 {0x2fa98,5},
772 {0x2fedc,0x7a},
773 {0x2ffee,1},
774 {0x2ffef,2},
775 {0x110000, 0}
776 };
777
778 /* use a non-zero initial value */
779 static const SetRange
780 setRanges3[]={
781 {0x31, 0xa4, 1, FALSE},
782 {0x3400, 0x6789, 2, FALSE},
783 {0x30000,0x34567,9, TRUE},
784 {0x45678,0x56789,3, TRUE}
785 };
786
787 static const CheckRange
788 checkRanges3[]={
789 {0, 9}, /* dummy start range, also carries the initial value */
790 {0x31, 9},
791 {0xa4, 1},
792 {0x3400, 9},
793 {0x6789, 2},
794 {0x45678,9},
795 {0x56789,3},
796 {0x110000,9}
797 };
798
799 static void
800 TrieTest(void) {
801 testTrieRanges4("set1",
802 setRanges1, UPRV_LENGTHOF(setRanges1),
803 checkRanges1, UPRV_LENGTHOF(checkRanges1));
804 testTrieRanges4("set2-overlap",
805 setRanges2, UPRV_LENGTHOF(setRanges2),
806 checkRanges2, UPRV_LENGTHOF(checkRanges2));
807 testTrieRanges4("set3-initial-9",
808 setRanges3, UPRV_LENGTHOF(setRanges3),
809 checkRanges3, UPRV_LENGTHOF(checkRanges3));
810 }
811
812 /* test utrie_unserializeDummy() -------------------------------------------- */
813
814 static int32_t U_CALLCONV
815 dummyGetFoldingOffset(uint32_t data) {
816 return -1; /* never get non-initialValue data for supplementary code points */
817 }
818
819 static void
820 dummyTest(UBool make16BitTrie) {
821 int32_t mem[UTRIE_DUMMY_SIZE/4];
822
823 UTrie trie;
824 UErrorCode errorCode;
825 UChar32 c;
826
827 uint32_t value, initialValue, leadUnitValue;
828
829 if(make16BitTrie) {
830 initialValue=0x313;
831 leadUnitValue=0xaffe;
832 } else {
833 initialValue=0x01234567;
834 leadUnitValue=0x89abcdef;
835 }
836
837 errorCode=U_ZERO_ERROR;
838 utrie_unserializeDummy(&trie, mem, sizeof(mem), initialValue, leadUnitValue, make16BitTrie, &errorCode);
839 if(U_FAILURE(errorCode)) {
840 log_err("utrie_unserializeDummy(make16BitTrie=%d) failed - %s\n", make16BitTrie, u_errorName(errorCode));
841 return;
842 }
843 trie.getFoldingOffset=dummyGetFoldingOffset;
844
845 /* test that all code points have initialValue */
846 for(c=0; c<=0x10ffff; ++c) {
847 if(make16BitTrie) {
848 UTRIE_GET16(&trie, c, value);
849 } else {
850 UTRIE_GET32(&trie, c, value);
851 }
852 if(value!=initialValue) {
853 log_err("UTRIE_GET%s(dummy, U+%04lx)=0x%lx instead of 0x%lx\n",
854 make16BitTrie ? "16" : "32", (long)c, (long)value, (long)initialValue);
855 }
856 }
857
858 /* test that the lead surrogate code units have leadUnitValue */
859 for(c=0xd800; c<=0xdbff; ++c) {
860 if(make16BitTrie) {
861 value=UTRIE_GET16_FROM_LEAD(&trie, c);
862 } else {
863 value=UTRIE_GET32_FROM_LEAD(&trie, c);
864 }
865 if(value!=leadUnitValue) {
866 log_err("UTRIE_GET%s_FROM_LEAD(dummy, U+%04lx)=0x%lx instead of 0x%lx\n",
867 make16BitTrie ? "16" : "32", (long)c, (long)value, (long)leadUnitValue);
868 }
869 }
870 }
871
872 static void
873 DummyTrieTest(void) {
874 dummyTest(TRUE);
875 dummyTest(FALSE);
876 }
877
878 void
879 addTrieTest(TestNode** root);
880
881 void
882 addTrieTest(TestNode** root) {
883 addTest(root, &TrieTest, "tsutil/trietest/TrieTest");
884 addTest(root, &DummyTrieTest, "tsutil/trietest/DummyTrieTest");
885 }