1 // 2016 and later: Unicode, Inc. and others. 2 // License & terms of use: http://www.unicode.org/copyright.html#License 3 /* 4 ******************************************************************************* 5 * Copyright (C) 2009-2015, International Business Machines Corporation and 6 * others. All Rights Reserved. 7 ******************************************************************************* 8 */ 9 10 package com.ibm.icu.dev.test.util; 11 12 import java.io.ByteArrayInputStream; 13 import java.io.ByteArrayOutputStream; 14 import java.io.IOException; 15 import java.io.InputStream; 16 import java.nio.ByteBuffer; 17 import java.util.Iterator; 18 19 import org.junit.Test; 20 import org.junit.runner.RunWith; 21 import org.junit.runners.JUnit4; 22 23 import com.ibm.icu.dev.test.TestFmwk; 24 import com.ibm.icu.impl.ICUBinary; 25 import com.ibm.icu.impl.Trie2; 26 import com.ibm.icu.impl.Trie2Writable; 27 import com.ibm.icu.impl.Trie2_16; 28 import com.ibm.icu.impl.Trie2_32; 29 30 @RunWith(JUnit4.class) 31 public class Trie2Test extends TestFmwk { 32 /** 33 * Constructor 34 */ 35 public Trie2Test() 36 { 37 } 38 39 // public methods ----------------------------------------------- 40 41 // 42 // TestAPI. Check that all API methods can be called, and do at least some minimal 43 // operation correctly. This is not a full test of correct behavior. 44 // 45 @Test 46 public void TestTrie2API() { 47 // Trie2.createFromSerialized() 48 // This function is well exercised by TestRanges(). 49 50 // Trie2.getVersion(InputStream is, boolean anyEndianOk) 51 // 52 53 try { 54 Trie2Writable trie = new Trie2Writable(0,0); 55 ByteArrayOutputStream os = new ByteArrayOutputStream(); 56 trie.toTrie2_16().serialize(os); 57 ByteArrayInputStream is = new ByteArrayInputStream(os.toByteArray()); 58 assertEquals(null, 2, Trie2.getVersion(is, true)); 59 } catch (IOException e) { 60 errln(where() + e.toString()); 61 } 62 63 // Equals & hashCode 64 // 65 { 66 Trie2Writable trieWA = new Trie2Writable(0,0); 67 Trie2Writable trieWB = new Trie2Writable(0,0); 68 Trie2 trieA = trieWA; 69 Trie2 trieB = trieWB; 70 assertTrue("", trieA.equals(trieB)); 71 assertEquals("", trieA, trieB); 72 assertEquals("", trieA.hashCode(), trieB.hashCode()); 73 trieWA.set(500, 2); 74 assertNotEquals("", trieA, trieB); 75 // Note that the hash codes do not strictly need to be different, 76 // but it's highly likely that something is wrong if they are the same. 77 assertNotEquals("", trieA.hashCode(), trieB.hashCode()); 78 trieWB.set(500, 2); 79 trieA = trieWA.toTrie2_16(); 80 assertEquals("", trieA, trieB); 81 assertEquals("", trieA.hashCode(), trieB.hashCode()); 82 } 83 84 // 85 // Iterator creation 86 // 87 { 88 Trie2Writable trie = new Trie2Writable(17,0); 89 Iterator<Trie2.Range> it; 90 it = trie.iterator(); 91 92 Trie2.Range r = it.next(); 93 assertEquals("", 0, r.startCodePoint); 94 assertEquals("", 0x10ffff, r.endCodePoint); 95 assertEquals("", 17, r.value); 96 assertEquals("", false, r.leadSurrogate); 97 98 r = it.next(); 99 assertEquals("", 0xd800, r.startCodePoint); 100 assertEquals("", 0xdbff, r.endCodePoint); 101 assertEquals("", 17, r.value); 102 assertEquals("", true, r.leadSurrogate); 103 104 105 int i = 0; 106 for (Trie2.Range rr: trie) { 107 switch (i) { 108 case 0: 109 assertEquals("", 0, rr.startCodePoint); 110 assertEquals("", 0x10ffff, rr.endCodePoint); 111 assertEquals("", 17, rr.value); 112 assertEquals("", false, rr.leadSurrogate); 113 break; 114 case 1: 115 assertEquals("", 0xd800, rr.startCodePoint); 116 assertEquals("", 0xdbff, rr.endCodePoint); 117 assertEquals("", 17, rr.value); 118 assertEquals("", true, rr.leadSurrogate); 119 break; 120 default: 121 errln(where() + " Unexpected iteration result"); 122 } 123 i++; 124 } 125 } 126 127 // Iteration with a value mapping function 128 // 129 { 130 Trie2Writable trie = new Trie2Writable(0xbadfeed, 0); 131 trie.set(0x10123, 42); 132 133 Trie2.ValueMapper vm = new Trie2.ValueMapper() { 134 @Override 135 public int map(int v) { 136 if (v == 0xbadfeed) { 137 v = 42; 138 } 139 return v; 140 } 141 }; 142 Iterator<Trie2.Range> it = trie.iterator(vm); 143 Trie2.Range r = it.next(); 144 assertEquals("", 0, r.startCodePoint); 145 assertEquals("", 0x10ffff, r.endCodePoint); 146 assertEquals("", 42, r.value); 147 assertEquals("", false, r.leadSurrogate); 148 } 149 150 151 // Iteration over a leading surrogate range. 152 // 153 { 154 Trie2Writable trie = new Trie2Writable(0xdefa17, 0); 155 trie.set(0x2f810, 10); 156 Iterator<Trie2.Range> it = trie.iteratorForLeadSurrogate((char)0xd87e); 157 Trie2.Range r = it.next(); 158 assertEquals("", 0x2f800, r.startCodePoint); 159 assertEquals("", 0x2f80f, r.endCodePoint); 160 assertEquals("", 0xdefa17, r.value); 161 assertEquals("", false, r.leadSurrogate); 162 163 r = it.next(); 164 assertEquals("", 0x2f810, r.startCodePoint); 165 assertEquals("", 0x2f810, r.endCodePoint); 166 assertEquals("", 10, r.value); 167 assertEquals("", false, r.leadSurrogate); 168 169 r = it.next(); 170 assertEquals("", 0x2f811, r.startCodePoint); 171 assertEquals("", 0x2fbff, r.endCodePoint); 172 assertEquals("", 0xdefa17, r.value); 173 assertEquals("", false, r.leadSurrogate); 174 175 assertFalse("", it.hasNext()); 176 } 177 178 // Iteration over a leading surrogate range with a ValueMapper. 179 // 180 { 181 Trie2Writable trie = new Trie2Writable(0xdefa17, 0); 182 trie.set(0x2f810, 10); 183 Trie2.ValueMapper m = new Trie2.ValueMapper() { 184 @Override 185 public int map(int in) { 186 if (in==10) { 187 in = 0xdefa17; 188 } 189 return in; 190 } 191 }; 192 Iterator<Trie2.Range> it = trie.iteratorForLeadSurrogate((char)0xd87e, m); 193 Trie2.Range r = it.next(); 194 assertEquals("", 0x2f800, r.startCodePoint); 195 assertEquals("", 0x2fbff, r.endCodePoint); 196 assertEquals("", 0xdefa17, r.value); 197 assertEquals("", false, r.leadSurrogate); 198 199 assertFalse("", it.hasNext()); 200 } 201 202 // Trie2.serialize() 203 // Test the implementation in Trie2, which is used with Read Only Tries. 204 // 205 { 206 Trie2Writable trie = new Trie2Writable(101, 0); 207 trie.setRange(0xf000, 0x3c000, 200, true); 208 trie.set(0xffee, 300); 209 Trie2_16 frozen16 = trie.toTrie2_16(); 210 Trie2_32 frozen32 = trie.toTrie2_32(); 211 assertEquals("", trie, frozen16); 212 assertEquals("", trie, frozen32); 213 assertEquals("", frozen16, frozen32); 214 ByteArrayOutputStream os = new ByteArrayOutputStream(); 215 try { 216 frozen16.serialize(os); 217 Trie2 unserialized16 = Trie2.createFromSerialized(ByteBuffer.wrap(os.toByteArray())); 218 assertEquals("", trie, unserialized16); 219 assertEquals("", Trie2_16.class, unserialized16.getClass()); 220 221 os.reset(); 222 frozen32.serialize(os); 223 Trie2 unserialized32 = Trie2.createFromSerialized(ByteBuffer.wrap(os.toByteArray())); 224 assertEquals("", trie, unserialized32); 225 assertEquals("", Trie2_32.class, unserialized32.getClass()); 226 } catch (IOException e) { 227 errln(where() + " Unexpected exception: " + e); 228 } 229 230 231 } 232 } 233 234 235 @Test 236 public void TestTrie2WritableAPI() { 237 // 238 // Trie2Writable methods. Check that all functions are present and 239 // nominally working. Not an in-depth test. 240 // 241 242 // Trie2Writable constructor 243 Trie2 t1 = new Trie2Writable(6, 666); 244 245 // Constructor from another Trie2 246 Trie2 t2 = new Trie2Writable(t1); 247 assertTrue("", t1.equals(t2)); 248 249 // Set / Get 250 Trie2Writable t1w = new Trie2Writable(10, 666); 251 t1w.set(0x4567, 99); 252 assertEquals("", 10, t1w.get(0x4566)); 253 assertEquals("", 99, t1w.get(0x4567)); 254 assertEquals("", 666, t1w.get(-1)); 255 assertEquals("", 666, t1w.get(0x110000)); 256 257 258 // SetRange 259 t1w = new Trie2Writable(10, 666); 260 t1w.setRange(13 /*start*/, 6666 /*end*/, 7788 /*value*/, false /*overwrite */); 261 t1w.setRange(6000, 7000, 9900, true); 262 assertEquals("", 10, t1w.get(12)); 263 assertEquals("", 7788, t1w.get(13)); 264 assertEquals("", 7788, t1w.get(5999)); 265 assertEquals("", 9900, t1w.get(6000)); 266 assertEquals("", 9900, t1w.get(7000)); 267 assertEquals("", 10, t1w.get(7001)); 268 assertEquals("", 666, t1w.get(0x110000)); 269 270 // setRange from a Trie2.Range 271 // (Ranges are more commonly created by iterating over a Trie2, 272 // but create one by hand here) 273 Trie2.Range r = new Trie2.Range(); 274 r.startCodePoint = 50; 275 r.endCodePoint = 52; 276 r.value = 0x12345678; 277 r.leadSurrogate = false; 278 t1w = new Trie2Writable(0, 0xbad); 279 t1w.setRange(r, true); 280 assertEquals(null, 0, t1w.get(49)); 281 assertEquals("", 0x12345678, t1w.get(50)); 282 assertEquals("", 0x12345678, t1w.get(52)); 283 assertEquals("", 0, t1w.get(53)); 284 285 286 // setForLeadSurrogateCodeUnit / getFromU16SingleLead 287 t1w = new Trie2Writable(10, 0xbad); 288 assertEquals("", 10, t1w.getFromU16SingleLead((char)0x0d801)); 289 t1w.setForLeadSurrogateCodeUnit((char)0xd801, 5000); 290 t1w.set(0xd801, 6000); 291 assertEquals("", 5000, t1w.getFromU16SingleLead((char)0x0d801)); 292 assertEquals("", 6000, t1w.get(0x0d801)); 293 294 // get(). Is covered by nearly every other test. 295 296 297 // Trie2_16 getAsFrozen_16() 298 t1w = new Trie2Writable(10, 666); 299 t1w.set(42, 5555); 300 t1w.set(0x1ff00, 224); 301 Trie2_16 t1_16 = t1w.toTrie2_16(); 302 assertTrue("", t1w.equals(t1_16)); 303 // alter the writable Trie2 and then re-freeze. 304 t1w.set(152, 129); 305 t1_16 = t1w.toTrie2_16(); 306 assertTrue("", t1w.equals(t1_16)); 307 assertEquals("", 129, t1w.get(152)); 308 309 // Trie2_32 getAsFrozen_32() 310 // 311 t1w = new Trie2Writable(10, 666); 312 t1w.set(42, 5555); 313 t1w.set(0x1ff00, 224); 314 Trie2_32 t1_32 = t1w.toTrie2_32(); 315 assertTrue("", t1w.equals(t1_32)); 316 // alter the writable Trie2 and then re-freeze. 317 t1w.set(152, 129); 318 assertNotEquals("", t1_32, t1w); 319 t1_32 = t1w.toTrie2_32(); 320 assertTrue("", t1w.equals(t1_32)); 321 assertEquals("", 129, t1w.get(152)); 322 323 324 // serialize(OutputStream os, ValueWidth width) 325 // 326 ByteArrayOutputStream os = new ByteArrayOutputStream(); 327 t1w = new Trie2Writable(0, 0xbad); 328 t1w.set(0x41, 0x100); 329 t1w.set(0xc2, 0x200); 330 t1w.set(0x404, 0x300); 331 t1w.set(0xd903, 0x500); 332 t1w.set(0xdd29, 0x600); 333 t1w.set(0x1055d3, 0x700); 334 t1w.setForLeadSurrogateCodeUnit((char)0xda1a, 0x800); 335 try { 336 // Serialize to 16 bits. 337 int serializedLen = t1w.toTrie2_16().serialize(os); 338 // Fragile test. Serialized length could change with changes to compaction. 339 // But it should not change unexpectedly. 340 assertEquals("", 3508, serializedLen); 341 Trie2 t1ws16 = Trie2.createFromSerialized(ByteBuffer.wrap(os.toByteArray())); 342 assertEquals("", t1ws16.getClass(), Trie2_16.class); 343 assertEquals("", t1w, t1ws16); 344 345 // Serialize to 32 bits 346 os.reset(); 347 serializedLen = t1w.toTrie2_32().serialize(os); 348 // Fragile test. Serialized length could change with changes to compaction. 349 // But it should not change unexpectedly. 350 assertEquals("", 4332, serializedLen); 351 Trie2 t1ws32 = Trie2.createFromSerialized(ByteBuffer.wrap(os.toByteArray())); 352 assertEquals("", t1ws32.getClass(), Trie2_32.class); 353 assertEquals("", t1w, t1ws32); 354 } catch (IOException e) { 355 errln(where() + e.toString()); 356 } 357 358 359 } 360 361 @Test 362 public void TestCharSequenceIterator() { 363 String text = "abc123\ud800\udc01 "; // Includes a Unicode supplemental character 364 String vals = "LLLNNNX?S"; 365 366 Trie2Writable tw = new Trie2Writable(0, 666); 367 tw.setRange('a', 'z', 'L', false); 368 tw.setRange('1', '9', 'N', false); 369 tw.set(' ', 'S'); 370 tw.set(0x10001, 'X'); 371 372 Trie2.CharSequenceIterator it = tw.charSequenceIterator(text, 0); 373 374 // Check forwards iteration. 375 Trie2.CharSequenceValues ir; 376 int i; 377 for (i=0; it.hasNext(); i++) { 378 ir = it.next(); 379 int expectedCP = Character.codePointAt(text, i); 380 assertEquals("" + " i="+i, expectedCP, ir.codePoint); 381 assertEquals("" + " i="+i, i, ir.index); 382 assertEquals("" + " i="+i, vals.charAt(i), ir.value); 383 if (expectedCP >= 0x10000) { 384 i++; 385 } 386 } 387 assertEquals("", text.length(), i); 388 389 // Check reverse iteration, starting at an intermediate point. 390 it.set(5); 391 for (i=5; it.hasPrevious(); ) { 392 ir = it.previous(); 393 int expectedCP = Character.codePointBefore(text, i); 394 i -= (expectedCP < 0x10000? 1 : 2); 395 assertEquals("" + " i="+i, expectedCP, ir.codePoint); 396 assertEquals("" + " i="+i, i, ir.index); 397 assertEquals("" + " i="+i, vals.charAt(i), ir.value); 398 } 399 assertEquals("", 0, i); 400 401 } 402 403 404 // 405 // Port of Tests from ICU4C ... 406 // 407 // setRanges array elements are 408 // {start Code point, limit CP, value, overwrite} 409 // 410 // There must be an entry with limit 0 and with the intialValue. 411 // It may be preceded by an entry with negative limit and the errorValue. 412 // 413 // checkRanges array elemets are 414 // { limit code point, value} 415 // 416 // The expected value range is from the previous boundary's limit to before 417 // this boundary's limit 418 419 // 420 String[] trieNames = {"setRanges1", "setRanges2", "setRanges3", "setRangesEmpty", "setRangesSingleValue"}; 421 /* set consecutive ranges, even with value 0 */ 422 423 424 425 private static int[][] setRanges1 ={ 426 { 0, 0, 0, 0 }, 427 { 0, 0x40, 0, 0 }, 428 { 0x40, 0xe7, 0x1234, 0 }, 429 { 0xe7, 0x3400, 0, 0 }, 430 { 0x3400, 0x9fa6, 0x6162, 0 }, 431 { 0x9fa6, 0xda9e, 0x3132, 0 }, 432 { 0xdada, 0xeeee, 0x87ff, 0 }, 433 { 0xeeee, 0x11111, 1, 0 }, 434 { 0x11111, 0x44444, 0x6162, 0 }, 435 { 0x44444, 0x60003, 0, 0 }, 436 { 0xf0003, 0xf0004, 0xf, 0 }, 437 { 0xf0004, 0xf0006, 0x10, 0 }, 438 { 0xf0006, 0xf0007, 0x11, 0 }, 439 { 0xf0007, 0xf0040, 0x12, 0 }, 440 { 0xf0040, 0x110000, 0, 0 } 441 }; 442 443 private static int[][] checkRanges1 = { 444 { 0, 0 }, 445 { 0x40, 0 }, 446 { 0xe7, 0x1234 }, 447 { 0x3400, 0 }, 448 { 0x9fa6, 0x6162 }, 449 { 0xda9e, 0x3132 }, 450 { 0xdada, 0 }, 451 { 0xeeee, 0x87ff }, 452 { 0x11111, 1 }, 453 { 0x44444, 0x6162 }, 454 { 0xf0003, 0 }, 455 { 0xf0004, 0xf }, 456 { 0xf0006, 0x10 }, 457 { 0xf0007, 0x11 }, 458 { 0xf0040, 0x12 }, 459 { 0x110000, 0 } 460 }; 461 462 /* set some interesting overlapping ranges */ 463 private static int [][] setRanges2={ 464 { 0, 0, 0, 0 }, 465 { 0x21, 0x7f, 0x5555, 1 }, 466 { 0x2f800, 0x2fedc, 0x7a, 1 }, 467 { 0x72, 0xdd, 3, 1 }, 468 { 0xdd, 0xde, 4, 0 }, 469 { 0x201, 0x240, 6, 1 }, /* 3 consecutive blocks with the same pattern but */ 470 { 0x241, 0x280, 6, 1 }, /* discontiguous value ranges, testing utrie2_enum() */ 471 { 0x281, 0x2c0, 6, 1 }, 472 { 0x2f987, 0x2fa98, 5, 1 }, 473 { 0x2f777, 0x2f883, 0, 1 }, 474 { 0x2f900, 0x2ffaa, 1, 0 }, 475 { 0x2ffaa, 0x2ffab, 2, 1 }, 476 { 0x2ffbb, 0x2ffc0, 7, 1 } 477 }; 478 479 private static int[] [] checkRanges2={ 480 { 0, 0 }, 481 { 0x21, 0 }, 482 { 0x72, 0x5555 }, 483 { 0xdd, 3 }, 484 { 0xde, 4 }, 485 { 0x201, 0 }, 486 { 0x240, 6 }, 487 { 0x241, 0 }, 488 { 0x280, 6 }, 489 { 0x281, 0 }, 490 { 0x2c0, 6 }, 491 { 0x2f883, 0 }, 492 { 0x2f987, 0x7a }, 493 { 0x2fa98, 5 }, 494 { 0x2fedc, 0x7a }, 495 { 0x2ffaa, 1 }, 496 { 0x2ffab, 2 }, 497 { 0x2ffbb, 0 }, 498 { 0x2ffc0, 7 }, 499 { 0x110000, 0 } 500 }; 501 502 /* 503 private static int[] [] checkRanges2_d800={ 504 { 0x10000, 0 }, 505 { 0x10400, 0 } 506 }; 507 508 private static int[][] checkRanges2_d87e={ 509 { 0x2f800, 6 }, 510 { 0x2f883, 0 }, 511 { 0x2f987, 0x7a }, 512 { 0x2fa98, 5 }, 513 { 0x2fc00, 0x7a } 514 }; 515 516 private static int[][] checkRanges2_d87f={ 517 { 0x2fc00, 0 }, 518 { 0x2fedc, 0x7a }, 519 { 0x2ffaa, 1 }, 520 { 0x2ffab, 2 }, 521 { 0x2ffbb, 0 }, 522 { 0x2ffc0, 7 }, 523 { 0x30000, 0 } 524 }; 525 526 private static int[][] checkRanges2_dbff={ 527 { 0x10fc00, 0 }, 528 { 0x110000, 0 } 529 }; 530 */ 531 532 /* use a non-zero initial value */ 533 private static int[][] setRanges3={ 534 { 0, 0, 9, 0 }, // non-zero initial value. 535 { 0x31, 0xa4, 1, 0 }, 536 { 0x3400, 0x6789, 2, 0 }, 537 { 0x8000, 0x89ab, 9, 1 }, 538 { 0x9000, 0xa000, 4, 1 }, 539 { 0xabcd, 0xbcde, 3, 1 }, 540 { 0x55555, 0x110000, 6, 1 }, /* highStart<U+ffff with non-initialValue */ 541 { 0xcccc, 0x55555, 6, 1 } 542 }; 543 544 private static int[][] checkRanges3={ 545 { 0, 9 }, /* non-zero initialValue */ 546 { 0x31, 9 }, 547 { 0xa4, 1 }, 548 { 0x3400, 9 }, 549 { 0x6789, 2 }, 550 { 0x9000, 9 }, 551 { 0xa000, 4 }, 552 { 0xabcd, 9 }, 553 { 0xbcde, 3 }, 554 { 0xcccc, 9 }, 555 { 0x110000, 6 } 556 }; 557 558 /* empty or single-value tries, testing highStart==0 */ 559 private static int[][] setRangesEmpty={ 560 { 0, 0, 3, 0 } // Only the element with the initial value. 561 }; 562 563 private static int[][] checkRangesEmpty={ 564 { 0, 3 }, 565 { 0x110000, 3 } 566 }; 567 568 private static int[][] setRangesSingleValue={ 569 { 0, 0, 3, 0 }, // Initial value = 3 570 { 0, 0x110000, 5, 1 }, 571 }; 572 573 private static int[][] checkRangesSingleValue={ 574 { 0, 3 }, 575 { 0x110000, 5 } 576 }; 577 578 579 // 580 // Create a test Trie2 from a setRanges test array. 581 // Range data ported from C. 582 // 583 private Trie2Writable genTrieFromSetRanges(int [][] ranges) { 584 int i = 0; 585 int initialValue = 0; 586 int errorValue = 0x0bad; 587 588 if (ranges[i][1] < 0) { 589 errorValue = ranges[i][2]; 590 i++; 591 } 592 initialValue = ranges[i++][2]; 593 Trie2Writable trie = new Trie2Writable(initialValue, errorValue); 594 595 for (; i<ranges.length; i++) { 596 int rangeStart = ranges[i][0]; 597 int rangeEnd = ranges[i][1]-1; 598 int value = ranges[i][2]; 599 boolean overwrite = (ranges[i][3] != 0); 600 trie.setRange(rangeStart, rangeEnd, value, overwrite); 601 } 602 603 // Insert some non-default values for lead surrogates. 604 // TODO: this should be represented in the data. 605 trie.setForLeadSurrogateCodeUnit((char)0xd800, 90); 606 trie.setForLeadSurrogateCodeUnit((char)0xd999, 94); 607 trie.setForLeadSurrogateCodeUnit((char)0xdbff, 99); 608 609 return trie; 610 } 611 612 613 // 614 // Check the expected values from a single Trie2. 615 // 616 private void trieGettersTest(String testName, 617 Trie2 trie, // The Trie2 to test. 618 int[][] checkRanges) // Expected data. 619 // Tuples of (value, high limit code point) 620 // High limit is first code point following the range 621 // with the indicated value. 622 // (Structures copied from ICU4C tests.) 623 { 624 int countCheckRanges = checkRanges.length; 625 626 int initialValue, errorValue; 627 int value, value2; 628 int start, limit; 629 int i, countSpecials; 630 631 countSpecials=0; /*getSpecialValues(checkRanges, countCheckRanges, &initialValue, &errorValue);*/ 632 errorValue = 0x0bad; 633 initialValue = 0; 634 if (checkRanges[countSpecials][0] == 0) { 635 initialValue = checkRanges[countSpecials][1]; 636 countSpecials++; 637 } 638 639 start=0; 640 for(i=countSpecials; i<countCheckRanges; ++i) { 641 limit=checkRanges[i][0]; 642 value=checkRanges[i][1]; 643 644 while(start<limit) { 645 value2=trie.get(start); 646 if (value != value2) { 647 // The redundant if, outside of the assert, is for speed. 648 // It makes a significant difference for this test. 649 assertEquals("wrong value for " + testName + " of " + Integer.toHexString(start), value, value2); 650 } 651 ++start; 652 } 653 } 654 655 656 if(!testName.startsWith("dummy") && !testName.startsWith("trie1")) { 657 /* Test values for lead surrogate code units. 658 * For non-lead-surrogate code units, getFromU16SingleLead() and get() 659 * should be the same. 660 */ 661 for(start=0xd7ff; start<0xdc01; ++start) { 662 switch(start) { 663 case 0xd7ff: 664 case 0xdc00: 665 value=trie.get(start); 666 break; 667 case 0xd800: 668 value=90; 669 break; 670 case 0xd999: 671 value=94; 672 break; 673 case 0xdbff: 674 value=99; 675 break; 676 default: 677 value=initialValue; 678 break; 679 } 680 value2 = trie.getFromU16SingleLead((char)start); 681 if(value2!=value) { 682 errln(where() + " testName: " + testName + " getFromU16SingleLead() failed." + 683 "char, exected, actual = " + Integer.toHexString(start) + ", " + 684 Integer.toHexString(value) + ", " + Integer.toHexString(value2)); 685 } 686 } 687 } 688 689 /* test errorValue */ 690 value=trie.get(-1); 691 value2=trie.get(0x110000); 692 if(value!=errorValue || value2!=errorValue) { 693 errln("trie2.get() error value test. Expected, actual1, actual2 = " + 694 errorValue + ", " + value + ", " + value2); 695 } 696 697 // Check that Trie enumeration produces the same contents as simple get() 698 for (Trie2.Range range: trie) { 699 for (int cp=range.startCodePoint; cp<=range.endCodePoint; cp++) { 700 if (range.leadSurrogate) { 701 assertTrue(testName, cp>=(char)0xd800 && cp<(char)0xdc00); 702 assertEquals(testName, range.value, trie.getFromU16SingleLead((char)cp)); 703 } else { 704 assertEquals(testName, range.value, trie.get(cp)); 705 } 706 } 707 } 708 } 709 710 // Was testTrieRanges in ICU4C. Renamed to not conflict with ICU4J test framework. 711 private void checkTrieRanges(String testName, String serializedName, boolean withClone, 712 int[][] setRanges, int [][] checkRanges) throws IOException { 713 714 // Run tests against Tries that were built by ICU4C and serialized. 715 String fileName16 = "Trie2Test." + serializedName + ".16.tri2"; 716 String fileName32 = "Trie2Test." + serializedName + ".32.tri2"; 717 718 InputStream is = Trie2Test.class.getResourceAsStream(fileName16); 719 Trie2 trie16; 720 try { 721 trie16 = Trie2.createFromSerialized(ICUBinary.getByteBufferFromInputStreamAndCloseStream(is)); 722 } finally { 723 is.close(); 724 } 725 trieGettersTest(testName, trie16, checkRanges); 726 727 is = Trie2Test.class.getResourceAsStream(fileName32); 728 Trie2 trie32; 729 try { 730 trie32 = Trie2.createFromSerialized(ICUBinary.getByteBufferFromInputStreamAndCloseStream(is)); 731 } finally { 732 is.close(); 733 } 734 trieGettersTest(testName, trie32, checkRanges); 735 736 // Run the same tests against locally contructed Tries. 737 Trie2Writable trieW = genTrieFromSetRanges(setRanges); 738 trieGettersTest(testName, trieW, checkRanges); 739 assertEquals("", trieW, trie16); // Locally built tries must be 740 assertEquals("", trieW, trie32); // the same as those imported from ICU4C 741 742 743 Trie2_32 trie32a = trieW.toTrie2_32(); 744 trieGettersTest(testName, trie32a, checkRanges); 745 746 Trie2_16 trie16a = trieW.toTrie2_16(); 747 trieGettersTest(testName, trie16a, checkRanges); 748 749 } 750 751 // Was "TrieTest" in trie2test.c 752 @Test 753 public void TestRanges() throws IOException { 754 checkTrieRanges("set1", "setRanges1", false, setRanges1, checkRanges1); 755 checkTrieRanges("set2-overlap", "setRanges2", false, setRanges2, checkRanges2); 756 checkTrieRanges("set3-initial-9", "setRanges3", false, setRanges3, checkRanges3); 757 checkTrieRanges("set-empty", "setRangesEmpty", false, setRangesEmpty, checkRangesEmpty); 758 checkTrieRanges("set-single-value", "setRangesSingleValue", false, setRangesSingleValue, 759 checkRangesSingleValue); 760 checkTrieRanges("set2-overlap.withClone", "setRanges2", true, setRanges2, checkRanges2); 761 } 762 763 764 private String where() { 765 StackTraceElement[] st = new Throwable().getStackTrace(); 766 String w = "File: " + st[1].getFileName() + ", Line " + st[1].getLineNumber(); 767 return w; 768 } 769 } 770