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