OLD | NEW |
(Empty) | |
| 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 |
| 28 void addTrie2Test(TestNode** root); |
| 29 |
| 30 /* Values for setting possibly overlapping, out-of-order ranges of values */ |
| 31 typedef 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 */ |
| 45 typedef struct CheckRange { |
| 46 UChar32 limit; |
| 47 uint32_t value; |
| 48 } CheckRange; |
| 49 |
| 50 static int32_t |
| 51 skipSpecialValues(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 |
| 57 static int32_t |
| 58 getSpecialValues(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 */ |
| 75 static uint32_t U_CALLCONV |
| 76 testEnumValue(const void *context, uint32_t value) { |
| 77 return value^0x5555; |
| 78 } |
| 79 |
| 80 /* utrie2_enum() callback, verifies a range */ |
| 81 static UBool U_CALLCONV |
| 82 testEnumRange(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 |
| 96 static void |
| 97 testTrieEnum(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() */ |
| 109 static void |
| 110 testTrieGetters(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 inste
ad of 0x%lx\n", |
| 139 typeName, testName, (long)start, (long)value
2, (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)val
ue); |
| 167 } |
| 168 ++start; |
| 169 } |
| 170 } |
| 171 |
| 172 if(isFrozen) { |
| 173 /* test linear ASCII range from the data array pointer (access to "inter
nal" 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)err
orValue); |
| 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)val
ue); |
| 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 |
| 268 static void |
| 269 testTrieUTF16(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 ins
tead 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 ins
tead 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 |
| 348 static void |
| 349 testTrieUTF8(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): 0
x%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): 0
x%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 |
| 484 static void |
| 485 testFrozenTrie(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_W
RITE_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 |
| 533 static void |
| 534 testNewTrie(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, countC
heckRanges); |
| 538 testTrieEnum(testName, trie, checkRanges, countCheckRanges); |
| 539 } |
| 540 |
| 541 static void |
| 542 testTrieSerialize(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_AR
GUMENT_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_erro
rName(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/afte
r 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/afte
r lengths different\n", |
| 668 testName, u_errorName(errorCode)); |
| 669 break; |
| 670 } |
| 671 } |
| 672 |
| 673 trie=utrie2_openFromSerialized(valueBits, storage, length2, &length3, &e
rrorCode); |
| 674 if(U_FAILURE(errorCode)) { |
| 675 log_err("error: utrie2_openFromSerialized(%s) failed, %s\n", testNam
e, 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)-len
gth3)); |
| 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 |
| 750 static UTrie2 * |
| 751 testTrieSerializeAllValueBits(const char *testName, |
| 752 UTrie2 *trie, UBool withClone, |
| 753 const CheckRange checkRanges[], int32_t countCheck
Ranges) { |
| 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 |
| 796 static UTrie2 * |
| 797 makeTrieWithRanges(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(err
orCode)); |
| 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 |
| 856 static void |
| 857 testTrieRanges(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 */ |
| 873 static const SetRange |
| 874 setRanges1[]={ |
| 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 |
| 891 static const CheckRange |
| 892 checkRanges1[]={ |
| 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 */ |
| 912 static const SetRange |
| 913 setRanges2[]={ |
| 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, testin
g 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 |
| 928 static const CheckRange |
| 929 checkRanges2[]={ |
| 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 |
| 952 static const CheckRange |
| 953 checkRanges2_d800[]={ |
| 954 { 0x10000, 0 }, |
| 955 { 0x10400, 0 } |
| 956 }; |
| 957 |
| 958 static const CheckRange |
| 959 checkRanges2_d87e[]={ |
| 960 { 0x2f800, 6 }, |
| 961 { 0x2f883, 0 }, |
| 962 { 0x2f987, 0x7a }, |
| 963 { 0x2fa98, 5 }, |
| 964 { 0x2fc00, 0x7a } |
| 965 }; |
| 966 |
| 967 static const CheckRange |
| 968 checkRanges2_d87f[]={ |
| 969 { 0x2fc00, 0 }, |
| 970 { 0x2fedc, 0x7a }, |
| 971 { 0x2ffaa, 1 }, |
| 972 { 0x2ffab, 2 }, |
| 973 { 0x2ffbb, 0 }, |
| 974 { 0x2ffc0, 7 }, |
| 975 { 0x30000, 0 } |
| 976 }; |
| 977 |
| 978 static const CheckRange |
| 979 checkRanges2_dbff[]={ |
| 980 { 0x10fc00, 0 }, |
| 981 { 0x110000, 0 } |
| 982 }; |
| 983 |
| 984 /* use a non-zero initial value */ |
| 985 static const SetRange |
| 986 setRanges3[]={ |
| 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 |
| 996 static const CheckRange |
| 997 checkRanges3[]={ |
| 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 */ |
| 1012 static const SetRange |
| 1013 setRangesEmpty[]={ |
| 1014 { 0, 0, 0, FALSE }, /* need some values for it to compile */ |
| 1015 }; |
| 1016 |
| 1017 static const CheckRange |
| 1018 checkRangesEmpty[]={ |
| 1019 { 0, 3 }, |
| 1020 { 0x110000, 3 } |
| 1021 }; |
| 1022 |
| 1023 static const SetRange |
| 1024 setRangesSingleValue[]={ |
| 1025 { 0, 0x110000, 5, TRUE }, |
| 1026 }; |
| 1027 |
| 1028 static const CheckRange |
| 1029 checkRangesSingleValue[]={ |
| 1030 { 0, 3 }, |
| 1031 { 0x110000, 5 } |
| 1032 }; |
| 1033 |
| 1034 static void |
| 1035 TrieTest(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 |
| 1057 static void |
| 1058 EnumNewTrieForLeadSurrogateTest(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 |
| 1099 static void |
| 1100 dummyTest(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_err
orName(errorCode)); |
| 1130 return; |
| 1131 } |
| 1132 |
| 1133 testFrozenTrie(testName, trie, valueBits, checkRanges, LENGTHOF(checkRanges)
); |
| 1134 utrie2_close(trie); |
| 1135 } |
| 1136 |
| 1137 static void |
| 1138 DummyTrieTest(void) { |
| 1139 dummyTest(UTRIE2_16_VALUE_BITS); |
| 1140 dummyTest(UTRIE2_32_VALUE_BITS); |
| 1141 } |
| 1142 |
| 1143 /* test builder memory management ------------------------------------------- */ |
| 1144 |
| 1145 static void |
| 1146 FreeBlocksTest(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(err
orCode)); |
| 1165 return; |
| 1166 } |
| 1167 |
| 1168 /* |
| 1169 * Repeatedly set overlapping same-value ranges to stress the free-data-bloc
k 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 |
| 1198 static void |
| 1199 GrowDataArrayTest(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(err
orCode)); |
| 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 |
| 1258 static void |
| 1259 GetVersionTest(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 |
| 1283 static UNewTrie * |
| 1284 makeNewTrie1WithRanges(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(erro
rCode)); |
| 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 |
| 1328 static void |
| 1329 testTrie2FromTrie1(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, countChec
kRanges); |
| 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, countChec
kRanges); |
| 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 |
| 1411 static void |
| 1412 Trie12ConversionTest(void) { |
| 1413 testTrie2FromTrie1("trie1->trie2", |
| 1414 setRanges2, LENGTHOF(setRanges2), |
| 1415 checkRanges2, LENGTHOF(checkRanges2)); |
| 1416 } |
| 1417 |
| 1418 void |
| 1419 addTrie2Test(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 } |
OLD | NEW |