]> gitweb.fperrin.net Git - Dictionary.git/blob - jars/icu4j-4_4_2-src/main/tests/framework/src/com/ibm/icu/dev/test/TestBoilerplate.java
go
[Dictionary.git] / jars / icu4j-4_4_2-src / main / tests / framework / src / com / ibm / icu / dev / test / TestBoilerplate.java
1 /*\r
2  *******************************************************************************\r
3  * Copyright (C) 2004-2007, International Business Machines Corporation and         *\r
4  * others. All Rights Reserved.                                                *\r
5  *******************************************************************************\r
6  */\r
7 package com.ibm.icu.dev.test;\r
8 \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
18 \r
19 import com.ibm.icu.text.UnicodeSet;\r
20 \r
21 /**\r
22  * To use, override the abstract and the protected methods as necessary.\r
23  * Tests boilerplate invariants:\r
24  * <br>a.equals(a)\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
33  * @author Davis\r
34  */\r
35 public abstract class TestBoilerplate extends TestFmwk {\r
36 \r
37     public final void TestMain() throws Exception {\r
38         List list = new LinkedList();\r
39         while (_addTestObject(list)) {\r
40         }\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
48             }\r
49             if (!a.equals(a)) {\r
50                 errln("Self-Equality invariant fails: " + i);\r
51             }\r
52             Object b;                \r
53             if (_canClone(a)) {\r
54                 b = _clone(a);\r
55                 if (b == a) {\r
56                     if (_isMutable(a)) {\r
57                         errln("Clone/Mutability invariant fails: " + i);\r
58                     }\r
59                 } else {\r
60                     if (!a.equals(b)) {\r
61                         errln("Clone/Equality invariant fails: " + i);\r
62                     }\r
63                 }\r
64                 _checkEquals(i, -1, a, aHash, b);\r
65             }\r
66             for (int j = i; j < testArray.length; ++j) {\r
67                 b = testArray[j];\r
68                 if (a.equals(b)) _checkEquals(i, j, a, aHash, b);\r
69             }\r
70         }\r
71     }\r
72 \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
79         }\r
80     }\r
81 \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
85     }\r
86 \r
87     /**\r
88      * Must be overridden to check whether a and be behave the same\r
89      */\r
90     protected abstract boolean _hasSameBehavior(Object a, Object b);\r
91 \r
92     /**\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
99      * count.\r
100      * NOTE: this method will only be called if the objects test as equal.\r
101      */\r
102     protected abstract boolean _addTestObject(List c);\r
103     /**\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
107      */\r
108     protected boolean _isMutable(Object a) {\r
109         return true;\r
110     }\r
111     /**\r
112      * Override if the tested objects can be cloned.\r
113      */\r
114     protected boolean _canClone(Object a) {\r
115         return true;\r
116     }\r
117     /**\r
118      * Produce a clone of the object. Tries two methods\r
119      * (a) clone\r
120      * (b) constructor\r
121      * Must be overridden if _canClone returns true and\r
122      * the above methods don't work.\r
123      * @param a\r
124      * @return clone\r
125      */\r
126     protected Object _clone(Object a) throws Exception {\r
127         Class aClass = a.getClass();\r
128         try {\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
134         }\r
135     }\r
136     \r
137     /* Utilities */\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
145         return false;\r
146     }\r
147 \r
148     public static boolean verifySetsIdentical(AbstractTestLog here, Set values1, Set values2) {\r
149         if (values1.equals(values2)) return true;\r
150         Set temp;\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
160         return false;\r
161     }\r
162     \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
168         }\r
169         return buffer.toString();\r
170     }\r
171     \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
179         }\r
180         return result;\r
181     }\r
182     \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
187         }\r
188         return buffer.toString();\r
189     }\r
190     \r
191 \r
192 }\r