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