2 *******************************************************************************
\r
3 * Copyright (C) 2006, International Business Machines Corporation and *
\r
4 * others. All Rights Reserved. *
\r
5 *******************************************************************************
\r
8 package com.ibm.icu.tests;
\r
10 import java.io.ByteArrayInputStream;
\r
11 import java.io.ByteArrayOutputStream;
\r
12 import java.io.Externalizable;
\r
13 import java.io.IOException;
\r
14 import java.io.ObjectInputStream;
\r
15 import java.io.ObjectOutputStream;
\r
16 import java.io.Serializable;
\r
17 import java.lang.reflect.Array;
\r
18 import java.lang.reflect.InvocationTargetException;
\r
19 import java.lang.reflect.Method;
\r
20 import java.util.Locale;
\r
22 import com.ibm.icu.util.TimeZone;
\r
23 import com.ibm.icu.util.ULocale;
\r
25 import junit.framework.TestCase;
\r
28 * Implement boilerplate tests.
\r
29 * Currently there is only one method, testEHCS, which tests equals, hashCode,
\r
30 * clone, and serialization.
\r
32 public abstract class ICUTestCase extends TestCase {
\r
33 private static final Object[] EMPTY_ARGS = {};
\r
34 private static final Class[] EMPTY_CLASSES = {};
\r
36 private static final Locale oldLocale = Locale.getDefault();
\r
37 private static final ULocale oldULocale = ULocale.getDefault();
\r
38 private static final java.util.TimeZone oldJTimeZone = java.util.TimeZone.getDefault();
\r
39 private static final TimeZone oldITimeZone = TimeZone.getDefault();
\r
41 // TODO: what's the best way to check this?
\r
42 public static final boolean testingWrapper = true;
\r
44 protected void setUp() throws Exception {
\r
46 Locale.setDefault(Locale.US);
\r
47 ULocale.setDefault(ULocale.US);
\r
48 java.util.TimeZone.setDefault(java.util.TimeZone.getTimeZone("PST"));
\r
49 TimeZone.setDefault(TimeZone.getTimeZone("PST"));
\r
52 protected void tearDown() throws Exception {
\r
53 ULocale.setDefault(oldULocale);
\r
54 Locale.setDefault(oldLocale);
\r
55 TimeZone.setDefault(oldITimeZone);
\r
56 java.util.TimeZone.setDefault(oldJTimeZone);
\r
60 private static final Object test = new Object();
\r
63 * Assert that two objects are _not_ equal. Curiously missing from Assert.
\r
64 * @param lhs an object to test, may be null
\r
65 * @param rhs an object to test, may be null
\r
67 public static void assertNotEqual(Object lhs, Object rhs) {
\r
69 if (rhs == null) fail("null equals null");
\r
71 if (lhs.equals(rhs)) {
\r
72 fail(lhs.toString() + " equals " + rhs);
\r
77 public static void assertNotEqual(long lhs, long rhs) {
\r
79 fail("values are equal: " + lhs);
\r
84 * Test whether equality, hashCode, clone, and serialization work as expected.
\r
85 * Equals(Object) is assumed to return false (not throw an exception) if passed
\r
86 * null or an object of an incompatible class.
\r
87 * Hashcodes must be equal iff the two objects compare equal. No attempt is made to
\r
88 * evaluate the quality of the hashcode distribution, so (in particular) degenerate
\r
89 * hashcode implementations will pass this test.
\r
90 * Clone will be tested if the method "clone" is public on the class of obj.
\r
91 * It is assumed to return an object that compares equal to obj.
\r
92 * Serialization will be tested if object implements Serializable or Externalizable.
\r
93 * It is assumed the serialized/deserialized object compares equal to obj.
\r
94 * @param obj the object to test
\r
95 * @param eq an object that should compare equal to, but is not the same as, obj.
\r
96 * it should be assignable to the class of obj.
\r
97 * @param neq a non-null object that should not compare equal to obj.
\r
98 * it should be assignable to the class of obj.
\r
100 public static void testEHCS(Object obj, Object eq, Object neq) {
\r
101 if (obj == null || eq == null || neq == null) {
\r
102 throw new NullPointerException();
\r
104 Class cls = obj.getClass();
\r
105 if (!(cls.isAssignableFrom(eq.getClass()) && cls.isAssignableFrom(neq.getClass()))) {
\r
106 throw new IllegalArgumentException("unassignable classes");
\r
110 assertEquals(obj, obj);
\r
112 // should return false, not throw exception
\r
113 assertNotEqual(obj, test);
\r
114 assertNotEqual(obj, null);
\r
117 assertEquals(obj, eq);
\r
118 assertEquals(eq, obj);
\r
120 assertNotEqual(obj, neq);
\r
121 assertNotEqual(neq, obj);
\r
123 // equal objects MUST have equal hashes, unequal objects MAY have equal hashes
\r
124 assertEquals(obj.hashCode(), eq.hashCode());
\r
126 Object clone = null;
\r
128 // look for public clone method and call it if available
\r
129 Method method_clone = cls.getMethod("clone", EMPTY_CLASSES);
\r
130 clone = method_clone.invoke(obj, EMPTY_ARGS);
\r
131 assertNotNull(clone);
\r
133 catch(NoSuchMethodException e) {
\r
136 catch(InvocationTargetException e) {
\r
139 catch(IllegalAccessException e) {
\r
143 if (clone != null) {
\r
144 assertEquals(obj, clone);
\r
145 assertEquals(clone, obj);
\r
148 if (obj instanceof Serializable || obj instanceof Externalizable) {
\r
151 ByteArrayOutputStream bos = new ByteArrayOutputStream();
\r
152 ObjectOutputStream oos = new ObjectOutputStream(bos);
\r
153 oos.writeObject(clone);
\r
156 ByteArrayInputStream bis = new ByteArrayInputStream(bos.toByteArray());
\r
157 ObjectInputStream ois = new ObjectInputStream(bis);
\r
158 ser = ois.readObject();
\r
161 catch(IOException e) {
\r
162 System.err.println(e.getMessage());
\r
163 throw new RuntimeException(e);
\r
165 catch(ClassNotFoundException e) {
\r
166 System.err.println(e.getMessage());
\r
167 throw new RuntimeException(e);
\r
171 assertEquals(obj, ser);
\r
172 assertEquals(ser, obj);
\r
173 assertEquals(obj.hashCode(), ser.hashCode());
\r
179 * Fail if the arrays are not equal. To be equal, the arrays must
\r
180 * be the same length, and each element in the left array must compare
\r
181 * equal to the corresponding element of the right array.
\r
182 * Also fails if one of the objects is not an array.
\r
183 * @param lhs the left array
\r
184 * @param rhs the right array
\r
186 public static void assertArraysEqual(Object lhs, Object rhs) {
\r
187 Class lcls = lhs.getClass();
\r
188 Class rcls = rhs.getClass();
\r
189 if (!(lcls.isArray() && rcls.isArray())) {
\r
190 fail("objects are not arrays");
\r
192 String result = arraysAreEqual(lhs, rhs);
\r
193 if (result != null) {
\r
199 * Fail if the arrays are equal. Also fails if one or the other
\r
200 * argument is not an array.
\r
201 * @param lhs the left array
\r
202 * @param rhs the right array
\r
204 public static void assertArraysNotEqual(Object lhs, Object rhs) {
\r
205 Class lcls = lhs.getClass();
\r
206 Class rcls = rhs.getClass();
\r
207 if (!(lcls.isArray() && rcls.isArray())) {
\r
208 fail("objects are not arrays");
\r
210 String result = arraysAreEqual(lhs, rhs);
\r
211 if (result == null) {
\r
212 fail("arrays are equal");
\r
216 // slow but general
\r
217 private static String arraysAreEqual(Object lhsa, Object rhsa) {
\r
218 int lhsl = Array.getLength(lhsa);
\r
219 int rhsl = Array.getLength(rhsa);
\r
220 if (lhsl != rhsl) {
\r
221 return "length " + lhsl + " != " + rhsl;
\r
223 boolean lhsaA = lhsa.getClass().getComponentType().isArray();
\r
224 boolean rhsaA = rhsa.getClass().getComponentType().isArray();
\r
225 if (lhsaA != rhsaA) {
\r
226 return (lhsaA ? "" : "non-") + "array != " + (rhsaA ? "" : "non-") + "array";
\r
228 for (int i = 0; i < lhsl; ++i) {
\r
229 Object lhse = Array.get(lhsa, i);
\r
230 Object rhse = Array.get(rhsa, i);
\r
231 if (lhse == null) {
\r
232 if (rhse != null) {
\r
233 return "null != " + rhse;
\r
237 String result = arraysAreEqual(lhse, rhse);
\r
238 if (result != null) {
\r
239 if (result.charAt(0) != '[') {
\r
240 result = " " + result;
\r
242 return "[" + i + "]" + result;
\r
245 if (!lhse.equals(rhse)) {
\r
246 return lhse.toString() + " != " + rhse;
\r
254 // much more painful and slow than it should be... partly because of the
\r
255 // oddness of clone, partly because arrays don't provide a Method for
\r
256 // 'clone' despite the fact that they implement it and make it public.
\r
257 public static Object cloneComplex(Object obj) {
\r
258 Object result = null;
\r
260 Class cls = obj.getClass();
\r
261 if (cls.isArray()) {
\r
262 int len = Array.getLength(obj);
\r
263 Class typ = cls.getComponentType();
\r
264 result = Array.newInstance(typ, len);
\r
265 boolean prim = typ.isPrimitive();
\r
266 for (int i = 0; i < len; ++i) {
\r
267 Object elem = Array.get(obj, i);
\r
268 Array.set(result, i, prim ? elem : cloneComplex(elem));
\r
271 result = obj; // default
\r
273 Method cloneM = cls.getMethod("clone", null);
\r
274 result = cloneM.invoke(obj, null);
\r
276 catch (NoSuchMethodException e) {
\r
278 catch (IllegalAccessException e) {
\r
280 catch (InvocationTargetException e) {
\r