/*
 *  Licensed to the Apache Software Foundation (ASF) under one or more
 *  contributor license agreements.  See the NOTICE file distributed with
 *  this work for additional information regarding copyright ownership.
 *  The ASF licenses this file to You under the Apache License, Version 2.0
 *  (the "License"); you may not use this file except in compliance with
 *  the License.  You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 *  Unless required by applicable law or agreed to in writing, software
 *  distributed under the License is distributed on an "AS IS" BASIS,
 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *  See the License for the specific language governing permissions and
 *  limitations under the License.
 */

/**
* @author Alexey V. Varlamov
* @version $Revision$
*/

package org.apache.harmony.testframework.serialization;

import junit.framework.TestCase;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.OutputStream;
import java.io.Serializable;
import java.lang.reflect.Method;
import java.security.Permission;
import java.security.PermissionCollection;
import java.util.Collection;
import java.util.Collections;
import java.util.HashSet;

/**
 * Framework for serialization testing. Subclasses only need to override
 * getData() method and, optionally, assertDeserialized() method. The first one
 * returns array of objects to be de/serialized in tests, and the second
 * compares reference and deserialized objects (needed only if tested objects do
 * not provide specific method equals()). <br>
 * There are two modes of test run: <b>reference generation mode </b> and
 * <b>testing mode </b>. The actual mode is selected via
 * <b>&quot;test.mode&quot; </b> system property. The <b>testing mode </b> is
 * the default mode. <br>
 * To turn on the <b>reference generation mode </b>, the test.mode property
 * should be set to value &quot;serial.reference&quot;. In this mode, no testing
 * is performed but golden files are produced, which contain reference
 * serialized objects. This mode should be run on a pure
 * Implementation classes, which are targeted for compartibility. <br>
 * The location of golden files (in both modes) is controlled via
 * <b>&quot;RESOURCE_DIR&quot; </b> system property.
 *
 */
public abstract class SerializationTest extends TestCase {

    /**
     * Key to a system property defining root location of golden files.
     */
    public static final String GOLDEN_PATH = "RESOURCE_DIR";

    private static final String outputPath = System.getProperty(GOLDEN_PATH,
            "src/test/resources/serialization");

    /**
     * This is the main working method of this framework. Subclasses must
     * override it to provide actual objects for testing.
     *
     * @return array of objects to be de/serialized in tests.
     */
    protected abstract Object[] getData();

    /**
     * Tests that data objects can be serialized and deserialized without
     * exceptions, and that deserialization really produces deeply cloned
     * objects.
     */
    public void testSelf() throws Throwable {

        if (this instanceof SerializableAssert) {
            verifySelf(getData(), (SerializableAssert) this);
        } else {
            verifySelf(getData());

        }
    }

    /**
     * Tests that data objects can be deserialized from golden files, to verify
     * compatibility with Reference Implementation.
     */

    public void testGolden() throws Throwable {
        verifyGolden(this, getData());
    }

    /**
     * Returns golden file for an object being tested.
     *
     * @param index array index of tested data (as returned by
     *        {@link #getData() getData()})
     * @return corresponding golden file
     */
    protected File getDataFile(int index) {
        String name = this.getClass().getName();
        int dot = name.lastIndexOf(".");
        String path = name.substring(0, dot).replace('.', File.separatorChar);
        if (outputPath != null && outputPath.length() != 0) {
            path = outputPath + File.separator + path;
        }

        return new File(path, name.substring(dot + 1) + "." + index + ".dat");
    }

    /**
     * Working method for files generation mode. Serializes test objects
     * returned by {@link #getData() getData()}to golden files, each object to
     * a separate file.
     *
     * @throws IOException
     */
    protected void produceGoldenFiles() throws IOException {

        String goldenPath = outputPath + File.separatorChar
                + getClass().getName().replace('.', File.separatorChar)
                + ".golden.";

        Object[] data = getData();
        for (int i = 0; i < data.length; i++) {

            File goldenFile = new File(goldenPath + i + ".ser");
            goldenFile.getParentFile().mkdirs();
            goldenFile.createNewFile();

            putObjectToStream(data[i], new FileOutputStream(goldenFile));
        }
    }

    /**
     * Serializes specified object to an output stream.
     */
    public static void putObjectToStream(Object obj, OutputStream os)
            throws IOException {
        ObjectOutputStream oos = new ObjectOutputStream(os);
        oos.writeObject(obj);
        oos.flush();
        oos.close();
    }

    /**
     * Deserializes single object from an input stream.
     */
    public static Serializable getObjectFromStream(InputStream is)
            throws IOException, ClassNotFoundException {
        ObjectInputStream ois = new ObjectInputStream(is);
        Object result = ois.readObject();
        ois.close();
        return (Serializable)result;
    }

    /**
     * Interface to compare (de)serialized objects
     *
     * Should be implemented if a class under test does not provide specific
     * equals() method and it's instances should to be compared manually.
     */
    public interface SerializableAssert {

        /**
         * Compares deserialized and reference objects.
         *
         * @param initial - initial object used for creating serialized form
         * @param deserialized - deserialized object
         */
        void assertDeserialized(Serializable initial, Serializable deserialized);
    }

    // default comparator for a class that has equals(Object) method
    private final static SerializableAssert DEFAULT_COMPARATOR = new SerializableAssert() {
        public void assertDeserialized(Serializable initial, Serializable deserialized) {
            assertEquals(initial, deserialized);
        }
    };

    /**
     * Comparator for verifying that deserialized object is the same as initial.
     */
    public final static SerializableAssert SAME_COMPARATOR = new SerializableAssert() {
        public void assertDeserialized(Serializable initial, Serializable deserialized) {
            assertSame(initial, deserialized);
        }
    };

    /**
     * Comparator for Throwable objects
     */
    public final static SerializableAssert THROWABLE_COMPARATOR = new SerializableAssert() {
        public void assertDeserialized(Serializable initial, Serializable deserialized) {
            Throwable initThr = (Throwable) initial;
            Throwable dserThr = (Throwable) deserialized;

            // verify class
            assertEquals(initThr.getClass(), dserThr.getClass());

            // verify message
            assertEquals(initThr.getMessage(), dserThr.getMessage());

            // verify cause
            if (initThr.getCause() == null) {
                assertNull(dserThr.getCause());
            } else {
                assertNotNull(dserThr.getCause());
                THROWABLE_COMPARATOR.assertDeserialized(initThr.getCause(),
                        dserThr.getCause());
            }
        }
    };

    /**
     * Comparator for PermissionCollection objects
     */
    public final static SerializableAssert PERMISSION_COLLECTION_COMPARATOR = new SerializableAssert() {
        public void assertDeserialized(Serializable initial, Serializable deserialized) {

            PermissionCollection initPC = (PermissionCollection) initial;
            PermissionCollection dserPC = (PermissionCollection) deserialized;

            // verify class
            assertEquals(initPC.getClass(), dserPC.getClass());

            // verify 'readOnly' field
            assertEquals(initPC.isReadOnly(), dserPC.isReadOnly());

            // verify collection of permissions
            Collection<Permission> refCollection = new HashSet<Permission>(
                    Collections.list(initPC.elements()));
            Collection<Permission> tstCollection = new HashSet<Permission>(
                    Collections.list(dserPC.elements()));

            assertEquals(refCollection, tstCollection);
        }
    };

    /**
     * Returns <code>comparator</code> for provided serializable
     * <code>object</code>.
     *
     * The <code>comparator</code> is searched in the following order: <br>
     * - if <code>test</code> implements SerializableAssert interface then it is
     * selected as </code>comparator</code>.<br>- if passed <code>object</code>
     * has class in its classes hierarchy that overrides <code>equals(Object)</code>
     * method then <code>DEFAULT_COMPARATOR</code> is selected.<br> - the
     * method tries to select one of known comparators basing on <code>object's</code>
     * class,for example, if passed <code>object</code> is instance of
     * Throwable then <code>THROWABLE_COMPARATOR</code> is used.<br>
     * - otherwise RuntimeException is thrown
     *
     * @param test - test case
     * @param object - object to be compared
     * @return object's comparator
     */
    public static SerializableAssert defineComparator(Object test, Object object)
            throws Exception {

        if (test instanceof SerializableAssert) {
            return (SerializableAssert) test;
        }

        Method m = object.getClass().getMethod("equals", new Class[] { Object.class });
        if (m.getDeclaringClass() != Object.class) {
            // one of classes overrides Object.equals(Object) method
            // use default comparator
            return DEFAULT_COMPARATOR;
        }

        // TODO use generics to detect comparator
        // instead of 'instanceof' for the first element
        if (object instanceof Throwable) {
            return THROWABLE_COMPARATOR;
        }
        if (object instanceof PermissionCollection) {
            return PERMISSION_COLLECTION_COMPARATOR;
        }
        throw new RuntimeException("Failed to detect comparator");
    }

    /**
     * Verifies that object deserialized from golden file correctly.
     *
     * The method invokes <br>
     * verifyGolden(test, object, defineComparator(test, object));
     *
     * @param test - test case
     * @param object - to be compared
     */
    public static void verifyGolden(Object test, Object object) throws Exception {
        verifyGolden(test, object, defineComparator(test, object));
    }

    /**
     * Verifies that object deserialized from golden file correctly.
     *
     * The method loads "<code>testName</code>.golden.ser" resource file
     * from "<module root>/src/test/resources/serialization/<code>testPackage</code>"
     * folder, reads an object from the loaded file and compares it with
     * <code>object</code> using specified <code>comparator</code>.
     *
     * @param test - test case
     * @param object - to be compared
     * @param comparator - for comparing (de)serialized objects
     */
    public static void verifyGolden(Object test, Object object, SerializableAssert comparator)
            throws Exception {
        assertNotNull("Null comparator", comparator);
        Serializable deserialized = getObject(test, ".golden.ser");
        comparator.assertDeserialized((Serializable) object, deserialized);
    }

    /**
     * Verifies that objects from array deserialized from golden files
     * correctly.
     *
     * The method invokes <br>
     * verifyGolden(test, objects, defineComparator(test, object[0]));
     *
     * @param test - test case
     * @param objects - array of objects to be compared
     */
    public static void verifyGolden(Object test, Object[] objects) throws Exception {
        assertFalse("Empty array", objects.length == 0);
        verifyGolden(test, objects, defineComparator(test, objects[0]));
    }

    /**
     * Verifies that objects from array deserialized from golden files
     * correctly.
     *
     * The method loads "<code>testName</code>.golden.<code>N</code>.ser"
     * resource files from "<module root>/src/test/resources/serialization/<code>testPackage</code>"
     * folder, from each loaded file it reads an object from and compares it
     * with corresponding object in provided array (i.e. <code>objects[N]</code>)
     * using specified <code>comparator</code>. (<code>N</code> is index
     * in object's array.)
     *
     * @param test - test case
     * @param objects - array of objects to be compared
     * @param comparator - for comparing (de)serialized objects
     */
    public static void verifyGolden(Object test, Object[] objects, SerializableAssert comparator)
            throws Exception {
        assertFalse("Empty array", objects.length == 0);
        for (int i = 0; i < objects.length; i++) {
            Serializable deserialized = getObject(test, ".golden." + i + ".ser");
            comparator.assertDeserialized((Serializable) objects[i], deserialized);
        }
    }

    /**
     * Verifies that object can be smoothly serialized/deserialized.
     *
     * The method invokes <br>
     * verifySelf(object, defineComparator(null, object));
     *
     * @param object - to be serialized/deserialized
     */
    public static void verifySelf(Object object) throws Exception {
        verifySelf(object, defineComparator(null, object));
    }

    /**
     * Verifies that object can be smoothly serialized/deserialized.
     *
     * The method serialize/deserialize <code>object</code> and compare it
     * with initial <code>object</code>.
     *
     * @param object - object to be serialized/deserialized
     * @param comparator - for comparing serialized/deserialized object with initial object
     */
    public static void verifySelf(Object object, SerializableAssert comparator) throws Exception {
        Serializable initial = (Serializable) object;
        comparator.assertDeserialized(initial, copySerializable(initial));
    }

    /**
     * Verifies that that objects from array can be smoothly
     * serialized/deserialized.
     *
     * The method invokes <br>
     * verifySelf(objects, defineComparator(null, object[0]));
     *
     * @param objects - array of objects to be serialized/deserialized
     */
    public static void verifySelf(Object[] objects) throws Exception {
        assertFalse("Empty array", objects.length == 0);
        verifySelf(objects, defineComparator(null, objects[0]));
    }

    /**
     * Verifies that that objects from array can be smoothly
     * serialized/deserialized.
     *
     * The method serialize/deserialize each object in <code>objects</code>
     * array and compare it with initial object.
     *
     * @param objects - array of objects to be serialized/deserialized
     * @param comparator - for comparing serialized/deserialized object with initial object
     */
    public static void verifySelf(Object[] objects, SerializableAssert comparator)
            throws Exception {
        assertFalse("Empty array", objects.length == 0);
        for (Object entry: objects){
            verifySelf(entry, comparator);
        }
    }

    private static Serializable getObject(Object test, String toAppend) throws Exception {
        StringBuilder path = new StringBuilder("/serialization");
        path.append(File.separatorChar);
        path.append(test.getClass().getName().replace('.', File.separatorChar));
        path.append(toAppend);

        String pathString = path.toString();

        InputStream in = SerializationTest.class.getResourceAsStream(pathString);
        assertNotNull("Failed to load serialization resource file: " + path, in);
        return getObjectFromStream(in);
    }

    /**
     * Creates golden file.
     *
     * The folder for created file is: <code>root + test's package name</code>.
     * The file name is: <code>test's name + "golden.ser"</code>
     *
     * @param root - root directory for serialization resource files
     * @param test - test case
     * @param object - to be serialized
     * @throws IOException - if I/O error
     */
    public static void createGoldenFile(String root, TestCase test, Object object)
            throws IOException {
        String goldenPath = (test.getClass().getName().replace('.', File.separatorChar)
                             + ".golden.ser");
        if (root != null) {
            goldenPath = root + File.separatorChar + goldenPath;
        }

        File goldenFile = new File(goldenPath);
        goldenFile.getParentFile().mkdirs();
        assertTrue("Could not create " + goldenFile.getParentFile(),
                   goldenFile.getParentFile().isDirectory());
        goldenFile.createNewFile();
        putObjectToStream(object, new FileOutputStream(goldenFile));

        // don't forget to remove it from test case after using
        fail("Generating golden file. Golden file name: " + goldenFile.getAbsolutePath());
    }

    /**
     * Copies an object by serializing/deserializing it.
     *
     * @param initial - an object to be copied
     * @return copy of provided object
     */
    public static Serializable copySerializable(Serializable initial)
            throws IOException, ClassNotFoundException {
        ByteArrayOutputStream out = new ByteArrayOutputStream();
        putObjectToStream(initial, out);
        ByteArrayInputStream in = new ByteArrayInputStream(out.toByteArray());
        return getObjectFromStream(in);
    }
}
