// © 2016 and later: Unicode, Inc. and others.
// License & terms of use: http://www.unicode.org/copyright.html#License
/*
 *******************************************************************************
 * Copyright (C) 2006-2011, International Business Machines Corporation and    *
 * others. All Rights Reserved.                                                *
 *******************************************************************************
 */

package com.ibm.icu.tests;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.Externalizable;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.Serializable;
import java.lang.reflect.Array;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.Locale;

import com.ibm.icu.util.TimeZone;
import com.ibm.icu.util.ULocale;

import junit.framework.TestCase;

/**
 * Implement boilerplate tests.
 * Currently there is only one method, testEHCS, which tests equals, hashCode, 
 * clone, and serialization.
 */
public abstract class ICUTestCase extends TestCase {
    private static final Object[] EMPTY_ARGS = {};
	private static final Class<?>[] EMPTY_CLASSES = {};
        
    private static final Locale oldLocale = Locale.getDefault();
    private static final ULocale oldULocale = ULocale.getDefault();
    private static final java.util.TimeZone oldJTimeZone = java.util.TimeZone.getDefault();
    private static final TimeZone oldITimeZone = TimeZone.getDefault();
                
    // TODO: what's the best way to check this?
    public static final boolean testingWrapper = true;

    protected void setUp() throws Exception {
        super.setUp();
        Locale.setDefault(Locale.US);
        ULocale.setDefault(ULocale.US);
        java.util.TimeZone.setDefault(java.util.TimeZone.getTimeZone("PST"));
        TimeZone.setDefault(TimeZone.getTimeZone("PST"));
    }
        
    protected void tearDown() throws Exception {
        ULocale.setDefault(oldULocale);
        Locale.setDefault(oldLocale);
        TimeZone.setDefault(oldITimeZone);
        java.util.TimeZone.setDefault(oldJTimeZone);
        super.tearDown();
    }

    private static final Object test = new Object();
        
    /**
     * Assert that two objects are _not_ equal.  Curiously missing from Assert.
     * @param lhs an object to test, may be null
     * @param rhs an object to test, may be null
     */
    public static void assertNotEqual(Object lhs, Object rhs) {
        if (lhs == null) {
            if (rhs == null) fail("null equals null");
        } else {
            if (lhs.equals(rhs)) {
                fail(lhs.toString() + " equals " + rhs);
            }
        }
    }
        
    public static void assertNotEqual(long lhs, long rhs) {
        if (lhs == rhs) {
            fail("values are equal: " + lhs);
        }
    }
        
    /**
     * Test whether equality, hashCode, clone, and serialization work as expected.  
     * Equals(Object) is assumed to return false (not throw an exception) if passed 
     * null or an object of an incompatible class.
     * Hashcodes must be equal iff the two objects compare equal.  No attempt is made to
     * evaluate the quality of the hashcode distribution, so (in particular) degenerate 
     * hashcode implementations will pass this test.
     * Clone will be tested if the method "clone" is public on the class of obj.  
     * It is assumed to return an object that compares equal to obj.
     * Serialization will be tested if object implements Serializable or Externalizable.
     * It is assumed the serialized/deserialized object compares equal to obj.
     * @param obj the object to test
     * @param eq an object that should compare equal to, but is not the same as, obj.  
     *     it should be assignable to the class of obj.
     * @param neq a non-null object that should not compare equal to obj.  
     *     it should be assignable to the class of obj.
     */
	public static void testEHCS(Object obj, Object eq, Object neq) {
        if (obj == null || eq == null || neq == null) {
            throw new NullPointerException();
        }
        Class<? extends Object> cls = obj.getClass();
        if (!(cls.isAssignableFrom(eq.getClass()) && cls.isAssignableFrom(neq.getClass()))) {
            throw new IllegalArgumentException("unassignable classes");
        }
                
        // reflexive
        assertEquals(obj, obj);
                
        // should return false, not throw exception
        assertNotEqual(obj, test);
        assertNotEqual(obj, null);
                
        // commutative
        assertEquals(obj, eq);
        assertEquals(eq, obj);
                
        assertNotEqual(obj, neq);
        assertNotEqual(neq, obj);
                
        // equal objects MUST have equal hashes, unequal objects MAY have equal hashes
        assertEquals(obj.hashCode(), eq.hashCode());
                
        Object clone = null;
        try {
            // look for public clone method and call it if available
            Method method_clone = cls.getMethod("clone", EMPTY_CLASSES);
            clone = method_clone.invoke(obj, EMPTY_ARGS);
            assertNotNull(clone);
        }
        catch(NoSuchMethodException e) {
            // ok
        }
        catch(InvocationTargetException e) {
            // ok
        }
        catch(IllegalAccessException e) {
            // ok
        }
                
        if (clone != null) {
            assertEquals(obj, clone);
            assertEquals(clone, obj);
        }
                
        if (obj instanceof Serializable || obj instanceof Externalizable) {
            Object ser = null;
            try {
                ByteArrayOutputStream bos = new ByteArrayOutputStream();
                ObjectOutputStream oos = new ObjectOutputStream(bos);
                oos.writeObject(clone);
                oos.close();
                                
                ByteArrayInputStream bis = new ByteArrayInputStream(bos.toByteArray());
                ObjectInputStream ois = new ObjectInputStream(bis);
                ser = ois.readObject();
                ois.close();
            }
            catch(IOException e) {
                System.err.println(e.getMessage());
                throw new RuntimeException(e);
            }
            catch(ClassNotFoundException e) {
                System.err.println(e.getMessage());
                throw new RuntimeException(e);
            }
                        
            if (ser != null) {
                assertEquals(obj, ser);
                assertEquals(ser, obj);
                assertEquals(obj.hashCode(), ser.hashCode());
            }
        }
    }

    /**
     * Fail if the arrays are not equal.  To be equal, the arrays must
     * be the same length, and each element in the left array must compare
     * equal to the corresponding element of the right array.
     * Also fails if one of the objects is not an array.
     * @param lhs the left array
     * @param rhs the right array
     */
    public static void assertArraysEqual(Object lhs, Object rhs) {
        Class<? extends Object> lcls = lhs.getClass();
        Class<? extends Object> rcls = rhs.getClass();
        if (!(lcls.isArray() && rcls.isArray())) {
            fail("objects are not arrays");
        }
        String result = arraysAreEqual(lhs, rhs);
        if (result != null) {
            fail(result);
        }
    }

    /**
     * Fail if the arrays are equal.  Also fails if one or the other 
     * argument is not an array.
     * @param lhs the left array
     * @param rhs the right array
     */
    public static void assertArraysNotEqual(Object lhs, Object rhs) {
        Class<? extends Object> lcls = lhs.getClass();
        Class<? extends Object> rcls = rhs.getClass();
        if (!(lcls.isArray() && rcls.isArray())) {
            fail("objects are not arrays");
        }
        String result = arraysAreEqual(lhs, rhs);
        if (result == null) {
            fail("arrays are equal");
        }
    }
        
    // slow but general
    private static String arraysAreEqual(Object lhsa, Object rhsa) {
        int lhsl = Array.getLength(lhsa);
        int rhsl = Array.getLength(rhsa);
        if (lhsl != rhsl) {
            return "length " + lhsl + " != " + rhsl;
        }
        boolean lhsaA = lhsa.getClass().getComponentType().isArray();
        boolean rhsaA = rhsa.getClass().getComponentType().isArray();
        if (lhsaA != rhsaA) {
            return (lhsaA ? "" : "non-") + "array != " + (rhsaA ? "" : "non-") + "array";
        }
        for (int i = 0; i < lhsl; ++i) {
            Object lhse = Array.get(lhsa, i);
            Object rhse = Array.get(rhsa, i);
            if (lhse == null) {
                if (rhse != null) {
                    return "null != " + rhse;
                }
            } else {
                if (lhsaA) {
                    String result = arraysAreEqual(lhse, rhse);
                    if (result != null) {
                        if (result.charAt(0) != '[') {
                            result = " " + result;
                        }
                        return "[" + i + "]" + result;
                    }
                } else {
                    if (!lhse.equals(rhse)) {
                        return lhse.toString() + " != " + rhse;
                    }
                }
            }
        }
        return null;
    }
        
    // much more painful and slow than it should be... partly because of the
    // oddness of clone, partly because arrays don't provide a Method for 
    // 'clone' despite the fact that they implement it and make it public.
    public static Object cloneComplex(Object obj) {
        Object result = null;
        if (obj != null) {
            Class<? extends Object> cls = obj.getClass();
            if (cls.isArray()) {
                int len = Array.getLength(obj);
                Class<?> typ = cls.getComponentType();
                result = Array.newInstance(typ, len);
                boolean prim = typ.isPrimitive();
                for (int i = 0; i < len; ++i) {
                    Object elem = Array.get(obj, i);
                    Array.set(result, i, prim ? elem : cloneComplex(elem));
                }
            } else {
                result = obj; // default
                try {
                    Method cloneM = cls.getMethod("clone", EMPTY_CLASSES);
                    result = cloneM.invoke(obj, EMPTY_ARGS);
                }
                catch (NoSuchMethodException e) {
                }
                catch (IllegalAccessException e) {
                }
                catch (InvocationTargetException e) {
                }
            }
        }
        return result;
    }
}
