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) 1996-2016, International Business Machines Corporation and 7 * others. All Rights Reserved. 8 ******************************************************************************* 9 */ 10 package ohos.global.icu.dev.test.translit; 11 12 import java.util.Comparator; 13 import java.util.HashMap; 14 import java.util.HashSet; 15 import java.util.Iterator; 16 import java.util.Map; 17 import java.util.Map.Entry; 18 import java.util.Random; 19 import java.util.Set; 20 import java.util.SortedMap; 21 import java.util.SortedSet; 22 import java.util.TreeMap; 23 import java.util.TreeSet; 24 25 import org.junit.Test; 26 import org.junit.runner.RunWith; 27 import org.junit.runners.JUnit4; 28 29 import ohos.global.icu.dev.test.TestBoilerplate; 30 import ohos.global.icu.dev.test.TestFmwk; 31 import ohos.global.icu.dev.util.CollectionUtilities; 32 import ohos.global.icu.dev.util.UnicodeMap; 33 import ohos.global.icu.dev.util.UnicodeMap.EntryRange; 34 import ohos.global.icu.dev.util.UnicodeMapIterator; 35 import ohos.global.icu.impl.Utility; 36 import ohos.global.icu.lang.UCharacter; 37 import ohos.global.icu.lang.UProperty; 38 import ohos.global.icu.text.UTF16; 39 import ohos.global.icu.text.UnicodeSet; 40 41 42 /** 43 * @test 44 * @summary General test of UnicodeSet 45 */ 46 47 @RunWith(JUnit4.class) 48 public class UnicodeMapTest extends TestFmwk { 49 50 static final int MODIFY_TEST_LIMIT = 32; 51 static final int MODIFY_TEST_ITERATIONS = 100000; 52 53 @Test TestIterations()54 public void TestIterations() { 55 UnicodeMap<Double> foo = new UnicodeMap(); 56 checkToString(foo, ""); 57 foo.put(3, 6d).put(5, 10d); 58 checkToString(foo, "0003=6.0\n0005=10.0\n"); 59 foo.put(0x10FFFF, 666d); 60 checkToString(foo, "0003=6.0\n0005=10.0\n10FFFF=666.0\n"); 61 foo.put("neg", -555d); 62 checkToString(foo, "0003=6.0\n0005=10.0\n10FFFF=666.0\n006E,0065,0067=-555.0\n"); 63 64 double i = 0; 65 for (EntryRange<Double> entryRange : foo.entryRanges()) { 66 i += entryRange.value; 67 } 68 assertEquals("EntryRange<T>", 127d, i); 69 } 70 checkToString(UnicodeMap<Double> foo, String expected)71 public void checkToString(UnicodeMap<Double> foo, String expected) { 72 assertEquals("EntryRange<T>", expected, CollectionUtilities.join(foo.entryRanges(), "\n") + (foo.size() == 0 ? "" : "\n")); 73 assertEquals("EntryRange<T>", expected, foo.toString()); 74 } 75 76 @Test TestRemove()77 public void TestRemove() { 78 UnicodeMap<Double> foo = new UnicodeMap() 79 .putAll(0x20, 0x29, -2d) 80 .put("abc", 3d) 81 .put("xy", 2d) 82 .put("mark", 4d) 83 .freeze(); 84 UnicodeMap<Double> fii = new UnicodeMap() 85 .putAll(0x21, 0x25, -2d) 86 .putAll(0x26, 0x28, -3d) 87 .put("abc", 3d) 88 .put("mark", 999d) 89 .freeze(); 90 91 UnicodeMap<Double> afterFiiRemoval = new UnicodeMap() 92 .put(0x20, -2d) 93 .putAll(0x26, 0x29, -2d) 94 .put("xy", 2d) 95 .put("mark", 4d) 96 .freeze(); 97 98 UnicodeMap<Double> afterFiiRetained = new UnicodeMap() 99 .putAll(0x21, 0x25, -2d) 100 .put("abc", 3d) 101 .freeze(); 102 103 UnicodeMap<Double> test = new UnicodeMap<Double>().putAll(foo) 104 .removeAll(fii); 105 assertEquals("removeAll", afterFiiRemoval, test); 106 107 test = new UnicodeMap<Double>().putAll(foo) 108 .retainAll(fii); 109 assertEquals("retainAll", afterFiiRetained, test); 110 } 111 112 @Test TestAMonkey()113 public void TestAMonkey() { 114 SortedMap<String,Integer> stayWithMe = new TreeMap<String,Integer>(OneFirstComparator); 115 116 UnicodeMap<Integer> me = new UnicodeMap<Integer>().putAll(stayWithMe); 117 // check one special case, removal near end 118 me.putAll(0x10FFFE, 0x10FFFF, 666); 119 me.remove(0x10FFFF); 120 121 int iterations = 100000; 122 SortedMap<String,Integer> test = new TreeMap(); 123 124 Random rand = new Random(0); 125 String other; 126 Integer value; 127 // try modifications 128 for (int i = 0; i < iterations ; ++i) { 129 switch(rand.nextInt(20)) { 130 case 0: 131 logln("clear"); 132 stayWithMe.clear(); 133 me.clear(); 134 break; 135 case 1: 136 fillRandomMap(rand, 5, test); 137 logln("putAll\t" + test); 138 stayWithMe.putAll(test); 139 me.putAll(test); 140 break; 141 case 2: case 3: case 4: case 5: case 6: case 7: case 8: 142 other = getRandomKey(rand); 143 // if (other.equals("\uDBFF\uDFFF") && me.containsKey(0x10FFFF) && me.get(0x10FFFF).equals(me.get(0x10FFFE))) { 144 // System.out.println("Remove\t" + other + "\n" + me); 145 // } 146 logln("remove\t" + other); 147 stayWithMe.remove(other); 148 try { 149 me.remove(other); 150 } catch (IllegalArgumentException e) { 151 errln("remove\t" + other + "\tfailed: " + e.getMessage() + "\n" + me); 152 me.clear(); 153 stayWithMe.clear(); 154 } 155 break; 156 default: 157 other = getRandomKey(rand); 158 value = rand.nextInt(50)+50; 159 logln("put\t" + other + " = " + value); 160 stayWithMe.put(other, value); 161 me.put(other,value); 162 break; 163 } 164 checkEquals(me, stayWithMe); 165 } 166 } 167 168 /** 169 * @param rand 170 * @param nextInt 171 * @param test 172 * @return 173 */ fillRandomMap(Random rand, int max, SortedMap<String, Integer> test)174 private SortedMap<String, Integer> fillRandomMap(Random rand, int max, SortedMap<String, Integer> test) { 175 test.clear(); 176 max = rand.nextInt(max); 177 for (int i = 0; i < max; ++i) { 178 test.put(getRandomKey(rand), rand.nextInt(50)+50); 179 } 180 return test; 181 } 182 183 Set temp = new HashSet(); 184 /** 185 * @param me 186 * @param stayWithMe 187 */ checkEquals(UnicodeMap<Integer> me, SortedMap<String, Integer> stayWithMe)188 private void checkEquals(UnicodeMap<Integer> me, SortedMap<String, Integer> stayWithMe) { 189 temp.clear(); 190 for (Entry<String, Integer> e : me.entrySet()) { 191 temp.add(e); 192 } 193 Set<Entry<String, Integer>> entrySet = stayWithMe.entrySet(); 194 if (!entrySet.equals(temp)) { 195 logln(me.entrySet().toString()); 196 logln(me.toString()); 197 assertEquals("are in parallel", entrySet, temp); 198 // we failed. Reset and start again 199 entrySet.clear(); 200 temp.clear(); 201 return; 202 } 203 for (String key : stayWithMe.keySet()) { 204 assertEquals("containsKey", stayWithMe.containsKey(key), me.containsKey(key)); 205 Integer value = stayWithMe.get(key); 206 assertEquals("get", value, me.get(key)); 207 assertEquals("containsValue", stayWithMe.containsValue(value), me.containsValue(value)); 208 int cp = UnicodeSet.getSingleCodePoint(key); 209 if (cp != Integer.MAX_VALUE) { 210 assertEquals("get", value, me.get(cp)); 211 } 212 } 213 Set<String> nonCodePointStrings = stayWithMe.tailMap("").keySet(); 214 if (nonCodePointStrings.size() == 0) nonCodePointStrings = null; // for parallel api 215 assertEquals("getNonRangeStrings", nonCodePointStrings, me.getNonRangeStrings()); 216 217 TreeSet<Integer> values = new TreeSet<Integer>(stayWithMe.values()); 218 TreeSet<Integer> myValues = new TreeSet<Integer>(me.values()); 219 assertEquals("values", myValues, values); 220 221 for (String key : stayWithMe.keySet()) { 222 assertEquals("containsKey", stayWithMe.containsKey(key), me.containsKey(key)); 223 } 224 } 225 226 static Comparator<String> OneFirstComparator = new Comparator<String>() { 227 @Override 228 public int compare(String o1, String o2) { 229 int cp1 = UnicodeSet.getSingleCodePoint(o1); 230 int cp2 = UnicodeSet.getSingleCodePoint(o2); 231 int result = cp1 - cp2; 232 if (result != 0) { 233 return result; 234 } 235 if (cp1 == Integer.MAX_VALUE) { 236 return o1.compareTo(o2); 237 } 238 return 0; 239 } 240 241 }; 242 243 /** 244 * @param rand 245 * @param others 246 * @return 247 */ getRandomKey(Random rand)248 private String getRandomKey(Random rand) { 249 int r = rand.nextInt(30); 250 if (r == 0) { 251 return UTF16.valueOf(r); 252 } else if (r < 10) { 253 return UTF16.valueOf('A'-1+r); 254 } else if (r < 20) { 255 return UTF16.valueOf(0x10FFFF - (r-10)); 256 // } else if (r == 20) { 257 // return ""; 258 } 259 return "a" + UTF16.valueOf(r + 'a'-1); 260 } 261 262 @Test TestModify()263 public void TestModify() { 264 Random random = new Random(0); 265 UnicodeMap unicodeMap = new UnicodeMap(); 266 HashMap hashMap = new HashMap(); 267 String[] values = {null, "the", "quick", "brown", "fox"}; 268 for (int count = 1; count <= MODIFY_TEST_ITERATIONS; ++count) { 269 String value = values[random.nextInt(values.length)]; 270 int start = random.nextInt(MODIFY_TEST_LIMIT); // test limited range 271 int end = random.nextInt(MODIFY_TEST_LIMIT); 272 if (start > end) { 273 int temp = start; 274 start = end; 275 end = temp; 276 } 277 int modCount = count & 0xFF; 278 if (modCount == 0 && isVerbose()) { 279 logln("***"+count); 280 logln(unicodeMap.toString()); 281 } 282 unicodeMap.putAll(start, end, value); 283 if (modCount == 1 && isVerbose()) { 284 logln(">>>\t" + Utility.hex(start) + ".." + Utility.hex(end) + "\t" + value); 285 logln(unicodeMap.toString()); 286 } 287 for (int i = start; i <= end; ++i) { 288 hashMap.put(new Integer(i), value); 289 } 290 if (!hasSameValues(unicodeMap, hashMap)) { 291 errln("Failed at " + count); 292 } 293 } 294 } 295 hasSameValues(UnicodeMap unicodeMap, HashMap hashMap)296 private boolean hasSameValues(UnicodeMap unicodeMap, HashMap hashMap) { 297 for (int i = 0; i < MODIFY_TEST_LIMIT; ++i) { 298 Object unicodeMapValue = unicodeMap.getValue(i); 299 Object hashMapValue = hashMap.get(new Integer(i)); 300 if (unicodeMapValue != hashMapValue) { 301 return false; 302 } 303 } 304 return true; 305 } 306 307 @Test TestCloneAsThawed11721()308 public void TestCloneAsThawed11721 () { 309 UnicodeMap<Integer> test = new UnicodeMap().put("abc", 3).freeze(); 310 UnicodeMap<Integer> copy = test.cloneAsThawed(); 311 copy.put("def", 4); 312 assertEquals("original-abc", (Integer) 3, test.get("abc")); 313 assertNull("original-def", test.get("def")); 314 assertEquals("copy-def", (Integer) 4, copy.get("def")); 315 } 316 317 private static final int LIMIT = 0x15; // limit to make testing more realistic in terms of collisions 318 private static final int ITERATIONS = 1000000; 319 private static final boolean SHOW_PROGRESS = false; 320 private static final boolean DEBUG = false; 321 322 SortedSet<String> log = new TreeSet<String>(); 323 static String[] TEST_VALUES = {"A", "B", "C", "D", "E", "F"}; 324 static Random random = new Random(12345); 325 326 @Test TestUnicodeMapRandom()327 public void TestUnicodeMapRandom() { 328 // do random change to both, then compare 329 random.setSeed(12345); // reproducible results 330 logln("Comparing against HashMap"); 331 UnicodeMap<String> map1 = new UnicodeMap(); 332 Map<Integer, String> map2 = new HashMap<Integer, String>(); 333 for (int counter = 0; counter < ITERATIONS; ++counter) { 334 int start = random.nextInt(LIMIT); 335 String value = TEST_VALUES[random.nextInt(TEST_VALUES.length)]; 336 String logline = Utility.hex(start) + "\t" + value; 337 if (SHOW_PROGRESS) logln(counter + "\t" + logline); 338 log.add(logline); 339 if (DEBUG && counter == 144) { 340 System.out.println(" debug"); 341 } 342 map1.put(start, value); 343 map2.put(start, value); 344 check(map1, map2, counter); 345 } 346 checkNext(map1, map2, LIMIT); 347 } 348 349 private static final int propEnum = UProperty.GENERAL_CATEGORY; 350 351 @Test TestUnicodeMapGeneralCategory()352 public void TestUnicodeMapGeneralCategory() { 353 logln("Setting General Category"); 354 UnicodeMap<String> map1 = new UnicodeMap(); 355 Map<Integer, String> map2 = new HashMap<Integer, String>(); 356 //Map<Integer, String> map3 = new TreeMap<Integer, String>(); 357 map1 = new UnicodeMap<String>(); 358 map2 = new TreeMap<Integer,String>(); 359 for (int cp = 0;;) { 360 int enumValue = UCharacter.getIntPropertyValue(cp, propEnum); 361 //if (enumValue <= 0) continue; // for smaller set 362 String value = UCharacter.getPropertyValueName(propEnum,enumValue, UProperty.NameChoice.LONG); 363 map1.put(cp, value); 364 map2.put(cp, value); 365 cp++; 366 // Unicode is huge, skip over large parts of it. 367 if (cp == 0x08FF) { // General Scripts Area. 368 cp = 0xD700; // Hangul Syllables Area. 369 } else if (cp == 0x100FF) { // General Scripts Area. 370 cp = 0x1F000; // Symbols Area. 371 } else if (cp == 0x200FF) { // CJK Unified Ideographs Extensions. 372 cp = 0x10FF00; // Supplementary Private Use Area-B. 373 } else if (cp == 0x10FFFF) { // The end of Unicode. 374 break; 375 } 376 } 377 checkNext(map1, map2, Integer.MAX_VALUE); 378 379 logln("Comparing General Category"); 380 check(map1, map2, -1); 381 logln("Comparing Values"); 382 Set<String> values1 = map1.getAvailableValues(new TreeSet<String>()); 383 Set<String> values2 = new TreeSet<String>(map2.values()); 384 if (!TestBoilerplate.verifySetsIdentical(this, values1, values2)) { 385 throw new IllegalArgumentException("Halting"); 386 } 387 logln("Comparing Sets"); 388 for (Iterator<String> it = values1.iterator(); it.hasNext();) { 389 String value = it.next(); 390 logln(value == null ? "null" : value); 391 UnicodeSet set1 = map1.keySet(value); 392 UnicodeSet set2 = TestBoilerplate.getSet(map2, value); 393 if (!TestBoilerplate.verifySetsIdentical(this, set1, set2)) { 394 throw new IllegalArgumentException("Halting"); 395 } 396 } 397 } 398 399 @Test TestAUnicodeMap2()400 public void TestAUnicodeMap2() { 401 UnicodeMap foo = new UnicodeMap(); 402 @SuppressWarnings("unused") 403 int hash = foo.hashCode(); // make sure doesn't NPE 404 @SuppressWarnings("unused") 405 Set fii = foo.stringKeys(); // make sure doesn't NPE 406 } 407 408 @Test TestAUnicodeMapInverse()409 public void TestAUnicodeMapInverse() { 410 UnicodeMap<Character> foo1 = new UnicodeMap<Character>() 411 .putAll('a', 'z', 'b') 412 .put("ab", 'c') 413 .put('x', 'b') 414 .put("xy", 'c') 415 ; 416 Map<Character, UnicodeSet> target = new HashMap<Character, UnicodeSet>(); 417 foo1.addInverseTo(target); 418 UnicodeMap<Character> reverse = new UnicodeMap().putAllInverse(target); 419 assertEquals("", foo1, reverse); 420 } 421 checkNext(UnicodeMap<String> map1, Map<Integer,String> map2, int limit)422 private void checkNext(UnicodeMap<String> map1, Map<Integer,String> map2, int limit) { 423 logln("Comparing nextRange"); 424 Map localMap = new TreeMap(); 425 UnicodeMapIterator<String> mi = new UnicodeMapIterator<String>(map1); 426 while (mi.nextRange()) { 427 logln(Utility.hex(mi.codepoint) + ".." + Utility.hex(mi.codepointEnd) + " => " + mi.value); 428 for (int i = mi.codepoint; i <= mi.codepointEnd; ++i) { 429 //if (i >= limit) continue; 430 localMap.put(i, mi.value); 431 } 432 } 433 checkMap(map2, localMap); 434 435 logln("Comparing next"); 436 mi.reset(); 437 localMap = new TreeMap(); 438 // String lastValue = null; 439 while (mi.next()) { 440 // if (!UnicodeMap.areEqual(lastValue, mi.value)) { 441 // // System.out.println("Change: " + Utility.hex(mi.codepoint) + " => " + mi.value); 442 // lastValue = mi.value; 443 // } 444 //if (mi.codepoint >= limit) continue; 445 localMap.put(mi.codepoint, mi.value); 446 } 447 checkMap(map2, localMap); 448 } 449 check(UnicodeMap<String> map1, Map<Integer,String> map2, int counter)450 public void check(UnicodeMap<String> map1, Map<Integer,String> map2, int counter) { 451 for (int i = 0; i < LIMIT; ++i) { 452 String value1 = map1.getValue(i); 453 String value2 = map2.get(i); 454 if (!UnicodeMap.areEqual(value1, value2)) { 455 errln(counter + " Difference at " + Utility.hex(i) 456 + "\t UnicodeMap: " + value1 457 + "\t HashMap: " + value2); 458 errln("UnicodeMap: " + map1); 459 errln("Log: " + TestBoilerplate.show(log)); 460 errln("HashMap: " + TestBoilerplate.show(map2)); 461 } 462 } 463 } 464 checkMap(Map m1, Map m2)465 void checkMap(Map m1, Map m2) { 466 if (m1.equals(m2)) return; 467 StringBuilder buffer = new StringBuilder(); 468 Set m1entries = m1.entrySet(); 469 Set m2entries = m2.entrySet(); 470 getEntries("\r\nIn First, and not Second", m1entries, m2entries, buffer, 20); 471 getEntries("\r\nIn Second, and not First", m2entries, m1entries, buffer, 20); 472 errln(buffer.toString()); 473 } 474 475 static Comparator<Map.Entry<Integer, String>> ENTRY_COMPARATOR = new Comparator<Map.Entry<Integer, String>>() { 476 @Override 477 public int compare(Map.Entry<Integer, String> o1, Map.Entry<Integer, String> o2) { 478 if (o1 == o2) return 0; 479 if (o1 == null) return -1; 480 if (o2 == null) return 1; 481 Map.Entry<Integer, String> a = o1; 482 Map.Entry<Integer, String> b = o2; 483 int result = compare2(a.getKey(), b.getKey()); 484 if (result != 0) return result; 485 return compare2(a.getValue(), b.getValue()); 486 } 487 private <T extends Comparable> int compare2(T o1, T o2) { 488 if (o1 == o2) return 0; 489 if (o1 == null) return -1; 490 if (o2 == null) return 1; 491 return o1.compareTo(o2); 492 } 493 }; 494 getEntries(String title, Set<Map.Entry<Integer,String>> m1entries, Set<Map.Entry<Integer, String>> m2entries, StringBuilder buffer, int limit)495 private void getEntries(String title, Set<Map.Entry<Integer,String>> m1entries, Set<Map.Entry<Integer, String>> m2entries, StringBuilder buffer, int limit) { 496 Set<Map.Entry<Integer, String>> m1_m2 = new TreeSet<Map.Entry<Integer, String>>(ENTRY_COMPARATOR); 497 m1_m2.addAll(m1entries); 498 m1_m2.removeAll(m2entries); 499 buffer.append(title + ": " + m1_m2.size() + "\r\n"); 500 for (Entry<Integer, String> entry : m1_m2) { 501 if (limit-- < 0) return; 502 buffer.append(entry.getKey()).append(" => ") 503 .append(entry.getValue()).append("\r\n"); 504 } 505 } 506 } 507