2 //#if defined(FOUNDATION10) || defined(J2SE13)
5 *******************************************************************************
6 * Copyright (C) 1996-2009, International Business Machines Corporation and *
7 * others. All Rights Reserved. *
8 *******************************************************************************
10 package com.ibm.icu.dev.test.util;
12 import java.text.NumberFormat;
13 import java.util.ArrayList;
14 import java.util.Arrays;
15 import java.util.Collection;
16 import java.util.Comparator;
17 import java.util.HashMap;
18 import java.util.HashSet;
19 import java.util.Iterator;
20 import java.util.List;
22 import java.util.Random;
24 import java.util.SortedSet;
25 import java.util.TreeMap;
26 import java.util.TreeSet;
28 import com.ibm.icu.dev.test.TestBoilerplate;
29 import com.ibm.icu.dev.test.TestFmwk;
30 import com.ibm.icu.impl.Utility;
31 import com.ibm.icu.lang.UCharacter;
32 import com.ibm.icu.lang.UProperty;
33 import com.ibm.icu.text.UnicodeSet;
35 public class TestUtilities extends TestFmwk {
36 static final int LIMIT = 0x15; // limit to make testing more realistic in terms of collisions
37 static final int ITERATIONS = 1000000;
38 static final boolean SHOW_PROGRESS = false;
39 static final boolean DEBUG = false;
41 public static void main(String[] args) throws Exception {
42 new TestUtilities().run(args);
45 UnicodeMap map1 = new UnicodeMap();
46 Map map2 = new HashMap();
47 Map map3 = new TreeMap();
48 SortedSet log = new TreeSet();
49 static String[] TEST_VALUES = {null, "A", "B", "C", "D", "E", "F"};
50 static Random random = new Random(12345);
52 public void TestUnicodeMap() {
53 random.setSeed(12345);
54 // do random change to both, then compare
55 logln("Comparing against HashMap");
56 for (int counter = 0; counter < ITERATIONS; ++counter) {
57 int start = random.nextInt(LIMIT);
58 String value = TEST_VALUES[random.nextInt(TEST_VALUES.length)];
59 String logline = Utility.hex(start) + "\t" + value;
60 if (SHOW_PROGRESS) logln(counter + "\t" + logline);
62 if (DEBUG && counter == 144) {
63 System.out.println(" debug");
65 map1.put(start, value);
66 map2.put(new Integer(start), value);
71 logln("Setting General Category");
72 map1 = new UnicodeMap();
74 for (int cp = 0; cp <= SET_LIMIT; ++cp) {
75 int enumValue = UCharacter.getIntPropertyValue(cp, propEnum);
76 //if (enumValue <= 0) continue; // for smaller set
77 String value = UCharacter.getPropertyValueName(propEnum,enumValue, UProperty.NameChoice.LONG);
79 map2.put(new Integer(cp), value);
81 checkNext(Integer.MAX_VALUE);
84 logln("Comparing General Category");
86 logln("Comparing Values");
87 Set values1 = (Set) map1.getAvailableValues(new TreeSet());
88 Set values2 = new TreeSet(map2.values());
89 if (!TestBoilerplate.verifySetsIdentical(this, values1, values2)) {
90 throw new IllegalArgumentException("Halting");
92 logln("Comparing Sets");
93 for (Iterator it = values1.iterator(); it.hasNext();) {
94 Object value = it.next();
95 logln(value == null ? "null" : value.toString());
96 UnicodeSet set1 = map1.getSet(value);
97 UnicodeSet set2 = TestBoilerplate.getSet(map2, value);
98 if (!TestBoilerplate.verifySetsIdentical(this, set1, set2)) {
99 throw new IllegalArgumentException("Halting");
103 logln("Getting Scripts");
104 UnicodeMap scripts = ICUPropertyFactory.make().getProperty("script").getUnicodeMap_internal();
105 UnicodeMap.Composer composer = new UnicodeMap.Composer() {
106 public Object compose(int codePoint, Object a, Object b) {
107 return a.toString() + "_" + b.toString();
111 logln("Trying Compose");
112 UnicodeMap composed = ((UnicodeMap)scripts.cloneAsThawed()).composeWith(map1, composer);
114 for (int i = 0; i < 0x10FFFF; ++i) {
115 Object comp = composed.getValue(i);
116 Object gc = map1.getValue(i);
117 Object sc = scripts.getValue(i);
118 if (!comp.equals(composer.compose(i, gc, sc))) {
119 errln("Failed compose at: " + i);
121 if (!last.equals(comp)) {
122 logln(Utility.hex(i) + "\t" + comp);
128 List argList = new ArrayList();
129 argList.add("TestMain");
130 if (params.nothrow) argList.add("-nothrow");
131 if (params.verbose) argList.add("-verbose");
132 String[] args = new String[argList.size()];
133 argList.toArray(args);
134 new UnicodeMapBoilerplate().run(args);
135 // TODO: the following is not being reached
136 new UnicodeSetBoilerplate().run(args);
139 public void TestCollectionUtilitySpeed() {
140 HashSet hs1 = new HashSet();
141 HashSet hs2 = new HashSet();
143 int iterations = 100;
144 String prefix = "abcde";
145 String postfix = "abcde";
146 int start1 = 0; // 1 for some, 0 for all
147 for (int i = 0; i < size; i += 2) hs1.add(prefix + String.valueOf(i) + postfix);
148 for (int i = start1; i < size; i += 2) hs2.add(prefix + String.valueOf(i) + postfix);
149 TreeSet ts1 = new TreeSet(hs1);
150 TreeSet ts2 = new TreeSet(hs2);
151 CollectionUtilities.containsAll(hs1, hs2);
152 CollectionUtilities.containsAll(ts1, ts2);
154 boolean temp = false;
155 start = System.currentTimeMillis();
156 for (int i = 0; i < iterations; ++i) temp = CollectionUtilities.containsAll(hs1, hs2);
157 end = System.currentTimeMillis();
158 logln(temp + " " + (end - start)/1000.0);
159 start = System.currentTimeMillis();
160 for (int i = 0; i < iterations; ++i) temp = CollectionUtilities.containsAll(ts1, ts2);
161 end = System.currentTimeMillis();
162 logln(temp + " " + (end - start)/1000.0);
165 public void TestCollectionUtilities() {
166 String[][] test = {{"a", "c", "e", "g", "h", "z"}, {"b", "d", "f", "h", "w"}, { "a", "b" }, { "a", "d" }, {"d"}, {}}; //
168 for (int i = 0; i < test.length; ++i) {
169 Collection a = new TreeSet(Arrays.asList(test[i]));
170 for (int j = 0; j < test.length; ++j) {
171 Collection b = new TreeSet(Arrays.asList(test[j]));
172 int relation = CollectionUtilities.getContainmentRelation(a, b);
173 resultMask |= (1 << relation);
175 case CollectionUtilities.ALL_EMPTY:
176 checkContainment(a.size() == 0 && b.size() == 0, a, relation, b);
178 case CollectionUtilities.NOT_A_SUPERSET_B:
179 checkContainment(a.size() == 0 && b.size() != 0, a, relation, b);
181 case CollectionUtilities.NOT_A_DISJOINT_B:
182 checkContainment(a.equals(b) && a.size() != 0, a, relation, b);
184 case CollectionUtilities.NOT_A_SUBSET_B:
185 checkContainment(a.size() != 0 && b.size() == 0, a, relation, b);
187 case CollectionUtilities.A_PROPER_SUBSET_OF_B:
188 checkContainment(b.containsAll(a) && !a.equals(b), a, relation, b);
190 case CollectionUtilities.NOT_A_EQUALS_B:
191 checkContainment(!CollectionUtilities.containsSome(a, b) && a.size() != 0 && b.size() != 0, a, relation, b);
193 case CollectionUtilities.A_PROPER_SUPERSET_B:
194 checkContainment(a.containsAll(b) && !a.equals(b), a, relation, b);
196 case CollectionUtilities.A_PROPER_OVERLAPS_B:
197 checkContainment(!b.containsAll(a) && !a.containsAll(b) && CollectionUtilities.containsSome(a, b), a, relation, b);
202 if (resultMask != 0xFF) {
204 for (int i = 0; i < 8; ++i) {
205 if ((resultMask & (1 << i)) == 0) {
206 if (missing.length() != 0) missing += ", ";
207 missing += RelationName[i];
210 errln("Not all ContainmentRelations checked: " + missing);
214 static final String[] RelationName = {"ALL_EMPTY",
218 "A_PROPER_SUBSET_OF_B",
219 "A_PROPER_DISJOINT_B",
220 "A_PROPER_SUPERSET_B",
221 "A_PROPER_OVERLAPS_B"};
226 private void checkContainment(boolean c, Collection a, int relation, Collection b) {
228 errln("Fails relation: " + a + " \t" + RelationName[relation] + " \t" + b);
232 private void checkNext(int limit) {
233 logln("Comparing nextRange");
234 UnicodeMap.MapIterator mi = new UnicodeMap.MapIterator(map1);
235 Map localMap = new TreeMap();
236 while (mi.nextRange()) {
237 logln(Utility.hex(mi.codepoint) + ".." + Utility.hex(mi.codepointEnd) + " => " + mi.value);
238 for (int i = mi.codepoint; i <= mi.codepointEnd; ++i) {
239 if (i >= limit) continue;
240 localMap.put(new Integer(i), mi.value);
243 checkMap(map2, localMap);
245 logln("Comparing next");
247 localMap = new TreeMap();
248 Object lastValue = new Object();
250 if (!UnicodeMap.areEqual(lastValue, mi.value)) {
251 // System.out.println("Change: " + Utility.hex(mi.codepoint) + " => " + mi.value);
252 lastValue = mi.value;
254 if (mi.codepoint >= limit) continue;
255 localMap.put(new Integer(mi.codepoint), mi.value);
257 checkMap(map2, localMap);
260 public void check(int counter) {
261 for (int i = 0; i < LIMIT; ++i) {
262 Object value1 = map1.getValue(i);
263 Object value2 = map2.get(new Integer(i));
264 if (!UnicodeMap.areEqual(value1, value2)) {
265 errln(counter + " Difference at " + Utility.hex(i)
266 + "\t UnicodeMap: " + value1
267 + "\t HashMap: " + value2);
268 errln("UnicodeMap: " + map1);
269 errln("Log: " + TestBoilerplate.show(log));
270 errln("HashMap: " + TestBoilerplate.show(map2));
275 void checkMap(Map m1, Map m2) {
276 if (m1.equals(m2)) return;
277 StringBuffer buffer = new StringBuffer();
278 Set m1entries = m1.entrySet();
279 Set m2entries = m2.entrySet();
280 getEntries("\r\nIn First, and not Second", m1entries, m2entries, buffer, 20);
281 getEntries("\r\nIn Second, and not First", m2entries, m1entries, buffer, 20);
282 errln(buffer.toString());
285 static Comparator ENTRY_COMPARATOR = new Comparator() {
286 public int compare(Object o1, Object o2) {
287 if (o1 == o2) return 0;
288 if (o1 == null) return -1;
289 if (o2 == null) return 1;
290 Map.Entry a = (Map.Entry) o1;
291 Map.Entry b = (Map.Entry) o2;
292 int result = compare2(a.getKey(), b.getKey());
293 if (result != 0) return result;
294 return compare2(a.getValue(), b.getValue());
296 private int compare2(Object o1, Object o2) {
297 if (o1 == o2) return 0;
298 if (o1 == null) return -1;
299 if (o2 == null) return 1;
300 return ((Comparable)o1).compareTo(o2);
304 private void getEntries(String title, Set m1entries, Set m2entries, StringBuffer buffer, int limit) {
305 Set m1_m2 = new TreeSet(ENTRY_COMPARATOR);
306 m1_m2.addAll(m1entries);
307 m1_m2.removeAll(m2entries);
308 buffer.append(title + ": " + m1_m2.size() + "\r\n");
309 for (Iterator it = m1_m2.iterator(); it.hasNext();) {
310 if (limit-- < 0) return;
311 Map.Entry entry = (Map.Entry) it.next();
312 buffer.append(entry.getKey()).append(" => ")
313 .append(entry.getValue()).append("\r\n");
317 static final int SET_LIMIT = 0x10FFFF;
318 static final int CHECK_LIMIT = 0xFFFF;
319 static final NumberFormat pf = NumberFormat.getPercentInstance();
320 static final NumberFormat nf = NumberFormat.getInstance();
322 public void TestTime() {
323 double hashTime, umTime, icuTime, treeTime;
324 umTime = checkSetTime(20, 0);
325 hashTime = checkSetTime(20, 1);
326 logln("Percentage: " + pf.format(hashTime/umTime));
327 treeTime = checkSetTime(20, 3);
328 logln("Percentage: " + pf.format(treeTime/umTime));
329 //logln(map1.toString());
331 umTime = checkGetTime(1000, 0);
332 hashTime = checkGetTime(1000, 1);
333 logln("Percentage: " + pf.format(hashTime/umTime));
334 icuTime = checkGetTime(1000, 2);
335 logln("Percentage: " + pf.format(icuTime/umTime));
336 treeTime = checkGetTime(1000, 3);
337 logln("Percentage: " + pf.format(treeTime/umTime));
340 int propEnum = UProperty.GENERAL_CATEGORY;
342 double checkSetTime(int iterations, int type) {
343 _checkSetTime(1,type);
344 double result = _checkSetTime(iterations, type);
345 logln((type == 0 ? "UnicodeMap" : type == 1 ? "HashMap" : type == 2 ? "ICU" : "TreeMap") + "\t" + nf.format(result));
348 double _checkSetTime(int iterations, int type) {
349 map1 = new UnicodeMap();
350 map2 = new HashMap();
352 double start = System.currentTimeMillis();
353 for (int j = 0; j < iterations; ++j)
354 for (int cp = 0; cp <= SET_LIMIT; ++cp) {
355 int enumValue = UCharacter.getIntPropertyValue(cp, propEnum);
356 if (enumValue <= 0) continue; // for smaller set
357 String value = UCharacter.getPropertyValueName(propEnum,enumValue, UProperty.NameChoice.LONG);
359 case 0: map1.put(cp, value); break;
360 case 1: map2.put(new Integer(cp), value); break;
361 case 3: map3.put(new Integer(cp), value); break;
364 double end = System.currentTimeMillis();
365 return (end-start)/1000/iterations;
368 double checkGetTime(int iterations, int type) {
369 _checkGetTime(1,type);
370 double result = _checkGetTime(iterations, type);
371 logln((type == 0 ? "UnicodeMap" : type == 1 ? "HashMap" : type == 2 ? "ICU" : "TreeMap") + "\t" + nf.format(result));
374 double _checkGetTime(int iterations, int type) {
376 double start = System.currentTimeMillis();
377 for (int j = 0; j < iterations; ++j)
378 for (int cp = 0; cp < CHECK_LIMIT; ++cp) {
380 case 0: map1.getValue(cp); break;
381 case 1: map2.get(new Integer(cp)); break;
383 int enumValue = UCharacter.getIntPropertyValue(cp, propEnum);
384 //if (enumValue <= 0) continue;
385 UCharacter.getPropertyValueName(propEnum,enumValue, UProperty.NameChoice.LONG);
387 case 3: map3.get(new Integer(cp)); break;
390 double end = System.currentTimeMillis();
391 return (end-start)/1000/iterations;
394 static class UnicodeMapBoilerplate extends TestBoilerplate {
397 * @see com.ibm.icu.dev.test.TestBoilerplate#_hasSameBehavior(java.lang.Object, java.lang.Object)
399 protected boolean _hasSameBehavior(Object a, Object b) {
400 // we are pretty confident in the equals method, so won't bother with this right now.
405 * @see com.ibm.icu.dev.test.TestBoilerplate#_createTestObject()
407 protected boolean _addTestObject(List list) {
408 if (list.size() > 30) return false;
409 UnicodeMap result = new UnicodeMap();
410 for (int i = 0; i < 50; ++i) {
411 int start = random.nextInt(25);
412 String value = TEST_VALUES[random.nextInt(TEST_VALUES.length)];
413 result.put(start, value);
420 static class StringBoilerplate extends TestBoilerplate {
423 * @see com.ibm.icu.dev.test.TestBoilerplate#_hasSameBehavior(java.lang.Object, java.lang.Object)
425 protected boolean _hasSameBehavior(Object a, Object b) {
426 // we are pretty confident in the equals method, so won't bother with this right now.
431 * @see com.ibm.icu.dev.test.TestBoilerplate#_createTestObject()
433 protected boolean _addTestObject(List list) {
434 if (list.size() > 31) return false;
435 StringBuffer result = new StringBuffer();
436 for (int i = 0; i < 10; ++i) {
437 result.append((char)random.nextInt(0xFF));
439 list.add(result.toString());
444 static class UnicodeSetBoilerplate extends TestBoilerplate {
447 * @see com.ibm.icu.dev.test.TestBoilerplate#_hasSameBehavior(java.lang.Object, java.lang.Object)
449 protected boolean _hasSameBehavior(Object a, Object b) {
450 // we are pretty confident in the equals method, so won't bother with this right now.
455 * @see com.ibm.icu.dev.test.TestBoilerplate#_createTestObject()
457 protected boolean _addTestObject(List list) {
458 if (list.size() > 32) return false;
459 UnicodeSet result = new UnicodeSet();
460 for (int i = 0; i < 50; ++i) {
461 result.add(random.nextInt(100));
463 list.add(result.toString());