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