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