2 *******************************************************************************
\r
3 * Copyright (C) 2004-2007, International Business Machines Corporation and *
\r
4 * others. All Rights Reserved. *
\r
5 *******************************************************************************
\r
7 package com.ibm.icu.dev.test;
\r
9 import java.lang.reflect.Constructor;
\r
10 import java.lang.reflect.Method;
\r
11 import java.util.Collection;
\r
12 import java.util.Iterator;
\r
13 import java.util.LinkedList;
\r
14 import java.util.List;
\r
15 import java.util.Map;
\r
16 import java.util.Set;
\r
17 import java.util.TreeSet;
\r
19 import com.ibm.icu.text.UnicodeSet;
\r
22 * To use, override the abstract and the protected methods as necessary.
\r
23 * Tests boilerplate invariants:
\r
25 * <br>!a.equals(null)
\r
26 * <br>if a.equals(b) then
\r
27 * <br>(1) a.hashCode() == b.hashCode // note: the reverse is not necessarily true.
\r
28 * <br>(2) a functions in all aspects as equivalent to b
\r
29 * <br>(3) b.equals(a)
\r
30 * <br>if b = clone(a)
\r
31 * <br>(1) b.equals(a), and the above checks
\r
32 * <br>(2) if mutable(a), then a.clone() != a // note: the reverse is not necessarily true.
\r
35 public abstract class TestBoilerplate extends TestFmwk {
\r
37 public final void TestMain() throws Exception {
\r
38 List list = new LinkedList();
\r
39 while (_addTestObject(list)) {
\r
41 Object[] testArray = list.toArray();
\r
42 for (int i = 0; i < testArray.length; ++i) {
\r
43 //logln("Testing " + i);
\r
44 Object a = testArray[i];
\r
45 int aHash = a.hashCode();
\r
46 if (a.equals(null)) {
\r
47 errln("Equality/Null invariant fails: " + i);
\r
50 errln("Self-Equality invariant fails: " + i);
\r
56 if (_isMutable(a)) {
\r
57 errln("Clone/Mutability invariant fails: " + i);
\r
61 errln("Clone/Equality invariant fails: " + i);
\r
64 _checkEquals(i, -1, a, aHash, b);
\r
66 for (int j = i; j < testArray.length; ++j) {
\r
68 if (a.equals(b)) _checkEquals(i, j, a, aHash, b);
\r
73 private void _checkEquals(int i, int j, Object a, int aHash, Object b) {
\r
74 int bHash = b.hashCode();
\r
75 if (!b.equals(a)) errln("Equality/Symmetry",i, j);
\r
76 if (aHash != bHash) errln("Equality/Hash",i, j);
\r
77 if (a != b && !_hasSameBehavior(a,b)) {
\r
78 errln("Equality/Equivalence",i, j);
\r
82 private void errln(String title, int i, int j) {
\r
83 if (j < 0) errln("Clone/" + title + "invariant fails: " + i);
\r
84 else errln(title + "invariant fails: " + i + "," + j);
\r
88 * Must be overridden to check whether a and be behave the same
\r
90 protected abstract boolean _hasSameBehavior(Object a, Object b);
\r
93 * This method will be called multiple times until false is returned.
\r
94 * The results should be a mixture of different objects of the same
\r
95 * type: some equal and most not equal.
\r
96 * The subclasser controls how many are produced (recommend about
\r
97 * 100, based on the size of the objects and how costly they are
\r
98 * to run this test on. The running time grows with the square of the
\r
100 * NOTE: this method will only be called if the objects test as equal.
\r
102 protected abstract boolean _addTestObject(List c);
\r
104 * Override if the tested objects are mutable.
\r
105 * <br>Since Java doesn't tell us, we need a function to tell if so.
\r
106 * The default is true, so must be overridden if not.
\r
108 protected boolean _isMutable(Object a) {
\r
112 * Override if the tested objects can be cloned.
\r
114 protected boolean _canClone(Object a) {
\r
118 * Produce a clone of the object. Tries two methods
\r
121 * Must be overridden if _canClone returns true and
\r
122 * the above methods don't work.
\r
126 protected Object _clone(Object a) throws Exception {
\r
127 Class aClass = a.getClass();
\r
129 Method cloner = aClass.getMethod("clone", (Class[])null);
\r
130 return cloner.invoke(a,(Object[])null);
\r
131 } catch (NoSuchMethodException e) {
\r
132 Constructor constructor = aClass.getConstructor(new Class[] {aClass});
\r
133 return constructor.newInstance(new Object[]{a});
\r
138 public static boolean verifySetsIdentical(AbstractTestLog here, UnicodeSet set1, UnicodeSet set2) {
\r
139 if (set1.equals(set2)) return true;
\r
140 here.errln("Sets differ:");
\r
141 here.errln("UnicodeMap - HashMap");
\r
142 here.errln(new UnicodeSet(set1).removeAll(set2).toPattern(true));
\r
143 here.errln("HashMap - UnicodeMap");
\r
144 here.errln(new UnicodeSet(set2).removeAll(set1).toPattern(true));
\r
148 public static boolean verifySetsIdentical(AbstractTestLog here, Set values1, Set values2) {
\r
149 if (values1.equals(values2)) return true;
\r
151 here.errln("Values differ:");
\r
152 here.errln("UnicodeMap - HashMap");
\r
153 temp = new TreeSet(values1);
\r
154 temp.removeAll(values2);
\r
155 here.errln(show(temp));
\r
156 here.errln("HashMap - UnicodeMap");
\r
157 temp = new TreeSet(values2);
\r
158 temp.removeAll(values1);
\r
159 here.errln(show(temp));
\r
163 public static String show(Map m) {
\r
164 StringBuffer buffer = new StringBuffer();
\r
165 for (Iterator it = m.keySet().iterator(); it.hasNext();) {
\r
166 Object key = it.next();
\r
167 buffer.append(key + "=>" + m.get(key) + "\r\n");
\r
169 return buffer.toString();
\r
172 public static UnicodeSet getSet(Map m, Object value) {
\r
173 UnicodeSet result = new UnicodeSet();
\r
174 for (Iterator it = m.keySet().iterator(); it.hasNext();) {
\r
175 Object key = it.next();
\r
176 Object val = m.get(key);
\r
177 if (!val.equals(value)) continue;
\r
178 result.add(((Integer)key).intValue());
\r
183 public static String show(Collection c) {
\r
184 StringBuffer buffer = new StringBuffer();
\r
185 for (Iterator it = c.iterator(); it.hasNext();) {
\r
186 buffer.append(it.next() + "\r\n");
\r
188 return buffer.toString();
\r