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