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