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