/*
 *  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.
 */
package org.apache.harmony.tests.java.io;

import java.io.IOException;
import java.io.NotSerializableException;
import java.io.Serializable;
import java.util.Arrays;
import java.util.Hashtable;
import java.util.Vector;

@SuppressWarnings({ "serial", "unused" })
public class SerializationStressTest1 extends SerializationStressTest {

    // The purpose of these two classes is to test if serialization, when
    // loading, runs the object's constructor (wrong) or the constructor defined
    // at the topmost Serializable superclass(correct).
    static final int INIT_INT_VALUE = 7;

    // HAS to be static class so that our constructor signature will remain
    // untouched (no synthetic param)
    private static class SerializationTest implements java.io.Serializable {
        int anInt = INIT_INT_VALUE;

        public SerializationTest() {
            super();
        }
    }

    static final String INIT_STR_VALUE = "a string that is blortz";

    // HAS to be static class so that our constructor signature will remain
    // untouched (no synthetic param)
    private static class SerializationTestSubclass1 extends SerializationTest {
        String aString = INIT_STR_VALUE;

        public SerializationTestSubclass1() {
            super();
            // Just to change default superclass init value
            anInt = INIT_INT_VALUE / 2;
        }
    }

    // -----------------------------------------------------------------------------------

    private static class SpecTestSuperClass implements Runnable {
        protected java.lang.String instVar;

        public SpecTestSuperClass() {
        }

        public void run() {
        }
    }

    private static class SpecTest extends SpecTestSuperClass implements
            Cloneable, Serializable {
        public java.lang.String instVar1;

        public static java.lang.String staticVar1;

        public static java.lang.String staticVar2;

        {
            instVar1 = "NonStaticInitialValue";
        }

        static {
            staticVar1 = "StaticInitialValue";
            staticVar1 = new String(staticVar1);
        }

        public Object method(Object objParam, Object objParam2) {
            return new Object();
        }

        public boolean method(boolean bParam, Object objParam) {
            return true;
        }

        public boolean method(boolean bParam, Object objParam, Object objParam2) {
            return true;
        }

    }

    private static class SpecTestSubclass extends SpecTest {
        public transient java.lang.String transientInstVar = "transientValue";
    }

    // -----------------------------------------------------------------------------------

    // This one tests what happens if the read/writeObject methods are defined
    // Serialization should work fine.
    private static class ReadWriteObject implements java.io.Serializable {
        public boolean calledWriteObject = false;

        public boolean calledReadObject = false;

        public ReadWriteObject() {
            super();
        }

        private void readObject(java.io.ObjectInputStream in)
                throws java.io.IOException, ClassNotFoundException {
            calledReadObject = true;
            in.readObject();
        }

        private void writeObject(java.io.ObjectOutputStream out)
                throws java.io.IOException {
            calledWriteObject = true;
            out.writeObject(FOO);
        }
    }

    // This one tests what happens if the read/writeObject methods are not
    // private.
    // Serialization should fail.
    private static class PublicReadWriteObject implements java.io.Serializable {
        public boolean calledWriteObject = false;

        public boolean calledReadObject = false;

        public PublicReadWriteObject() {
            super();
        }

        public void readObject(java.io.ObjectInputStream in)
                throws java.io.IOException, ClassNotFoundException {
            calledReadObject = true;
            in.readObject();
        }

        public void writeObject(java.io.ObjectOutputStream out)
                throws java.io.IOException {
            calledWriteObject = true;
            out.writeObject(FOO);
        }
    }

    // This one tests if field names are serialized in the same way (sorting)
    // across different VMs
    private static class FieldOrder implements Serializable {
        String aaa1NonPrimitive = "aaa1";

        int bbb1PrimitiveInt = 5;

        boolean aaa2PrimitiveBoolean = true;

        String bbb2NonPrimitive = "bbb2";
    }

    // This one tests what happens if you define just readObject, but not
    // writeObject.
    // Does it run or not ?
    private static class JustReadObject implements java.io.Serializable {
        public boolean calledReadObject = false;

        public JustReadObject() {
            super();
        }

        private void readObject(java.io.ObjectInputStream in)
                throws java.io.IOException, ClassNotFoundException {
            calledReadObject = true;
            in.defaultReadObject();
        }
    }

    // This one tests what happens if you define just writeObject, but not
    // readObject.
    // Does it run or not ?
    private static class JustWriteObject implements java.io.Serializable {
        public boolean calledWriteObject = false;

        public JustWriteObject() {
            super();
        }

        private void writeObject(java.io.ObjectOutputStream out)
                throws java.io.IOException, ClassNotFoundException {
            calledWriteObject = true;
            out.defaultWriteObject();
        }
    }

    // This one tests class-based replacement when dumping
    private static class ClassBasedReplacementWhenDumping implements
            java.io.Serializable {
        public boolean calledReplacement = false;

        public ClassBasedReplacementWhenDumping() {
            super();
        }

        private Object writeReplace() {
            calledReplacement = true;
            return FOO; // Replacement is a String
        }
    }

    // This one tests whether class-based replacement supports multiple levels.
    // MultipleClassBasedReplacementWhenDumping -> C1 -> C2 -> C3 -> FOO
    private static class MultipleClassBasedReplacementWhenDumping implements
            java.io.Serializable {
        private static class C1 implements java.io.Serializable {
            private Object writeReplace() {
                return new C2();
            }
        }

        private static class C2 implements java.io.Serializable {
            private Object writeReplace() {
                return new C3();
            }
        }

        private static class C3 implements java.io.Serializable {
            private Object writeReplace() {
                return FOO;
            }
        }

        public MultipleClassBasedReplacementWhenDumping() {
            super();
        }

        private Object writeReplace() {
            return new C1();
        }
    }

    // This one tests class-based replacement when loading
    private static class ClassBasedReplacementWhenLoading implements
            java.io.Serializable {
        public ClassBasedReplacementWhenLoading() {
            super();
        }

        private Object readResolve() {
            return FOO; // Replacement is a String
        }
    }

    // This one tests what happens if a loading-replacement is not
    // type-compatible with the original object
    private static class ClassBasedReplacementWhenLoadingViolatesFieldType
            implements java.io.Serializable {
        public ClassBasedReplacementWhenLoading classBasedReplacementWhenLoading = new ClassBasedReplacementWhenLoading();

        public ClassBasedReplacementWhenLoadingViolatesFieldType() {
            super();
        }
    }

    // What happens if dumping causes an error and you try to reload ?
    // Should the load throw the same exception ?
    private static class MyExceptionWhenDumping1 implements
            java.io.Serializable {
        private static class MyException extends java.io.IOException {
        }

        // A primitive instance variable exposes a bug in the serialization
        // spec.
        // Primitive instance variables are written without primitive data tags
        // and so are read without checking for tags. If an exception is
        // written, reading primitive data will just read bytes from the stream
        // which may be tags
        public boolean anInstanceVar = false;

        public MyExceptionWhenDumping1() {
            super();
        }

        private void readObject(java.io.ObjectInputStream in)
                throws java.io.IOException, ClassNotFoundException {
            in.defaultReadObject();
        }

        private void writeObject(java.io.ObjectOutputStream out)
                throws java.io.IOException, ClassNotFoundException {
            throw new MyException();
        }
    }

    // What happens if dumping causes an error and you try to reload ?
    // Should the load throw the same exception ?
    private static class MyExceptionWhenDumping2 implements
            java.io.Serializable {
        private static class MyException extends java.io.IOException {
        }

        ;

        public Integer anInstanceVar = new Integer(0xA1);

        public MyExceptionWhenDumping2() {
            super();
        }

        private void readObject(java.io.ObjectInputStream in)
                throws java.io.IOException, ClassNotFoundException {
            in.defaultReadObject();
        }

        private void writeObject(java.io.ObjectOutputStream out)
                throws java.io.IOException, ClassNotFoundException {
            throw new MyException();
        }
    }

    // What happens if dumping causes an error (NonSerializable inst var) and
    // you try to reload ?
    // Should the load throw the same exception ?
    private static class NonSerializableExceptionWhenDumping implements
            java.io.Serializable {
        public Object anInstanceVar = new Object();

        public NonSerializableExceptionWhenDumping() {
            super();
        }
    }

    // What happens if dumping causes an error (which is not serializable) and
    // you try to reload ?
    // Should the load throw the same exception ?
    private static class MyUnserializableExceptionWhenDumping implements
            java.io.Serializable {
        private static class MyException extends java.io.IOException {
            private Object notSerializable = new Object();
        }

        public boolean anInstanceVar = false;

        public MyUnserializableExceptionWhenDumping() {
            super();
        }

        private void readObject(java.io.ObjectInputStream in)
                throws java.io.IOException, ClassNotFoundException {
            in.defaultReadObject();
        }

        private void writeObject(java.io.ObjectOutputStream out)
                throws java.io.IOException, ClassNotFoundException {
            throw new MyException();
        }
    }

    public SerializationStressTest1(String name) {
        super(name);
    }

    public void test_18_1_writeObject() {
        // Test for method void
        // java.io.ObjectOutputStream.writeObject(java.lang.Object)

        Object objToSave = null;
        Object objLoaded;

        try {
            objToSave = "HelloWorld";
            if (DEBUG)
                System.out.println("Obj = " + objToSave);
            objLoaded = dumpAndReload(objToSave);
            assertTrue(MSG_TEST_FAILED + objToSave, (((String) objLoaded)
                    .equals((String) objToSave)));

        } catch (IOException e) {
            fail("IOException serializing data : " + e.getMessage());
        } catch (ClassNotFoundException e) {
            fail("ClassNotFoundException reading Object type: "
                    + e.getMessage());
        } catch (Error err) {
            System.out.println("Error when obj = " + objToSave);
            // err.printStackTrace();
            throw err;
        }
    }

    public void test_18_2_writeObject() {
        // Test for method void
        // java.io.ObjectOutputStream.writeObject(java.lang.Object)

        Object objToSave = null;
        Object objLoaded;

        try {
            objToSave = null;
            if (DEBUG)
                System.out.println("Obj = " + objToSave);
            objLoaded = dumpAndReload(objToSave);
            assertTrue(MSG_TEST_FAILED + objToSave, objLoaded == objToSave);

        } catch (IOException e) {
            fail("IOException serializing data : " + e.getMessage());
        } catch (ClassNotFoundException e) {
            fail("ClassNotFoundException reading Object type : "
                    + e.getMessage());
        } catch (Error err) {
            System.out.println("Error when obj = " + objToSave);
            // err.printStackTrace();
            throw err;
        }
    }

    public void test_18_3_writeObject() {
        // Test for method void
        // java.io.ObjectOutputStream.writeObject(java.lang.Object)

        Object objToSave = null;
        Object objLoaded;

        try {
            byte[] bytes = { 0, 1, 2, 3 };
            objToSave = bytes;
            if (DEBUG)
                System.out.println("Obj = " + objToSave);
            objLoaded = dumpAndReload(objToSave);
            assertTrue(MSG_TEST_FAILED + objToSave, Arrays.equals(
                    (byte[]) objLoaded, (byte[]) objToSave));

        } catch (IOException e) {
            fail("IOException serializing data : " + e.getMessage());
        } catch (ClassNotFoundException e) {
            fail("ClassNotFoundException reading Object type : "
                    + e.getMessage());
        } catch (Error err) {
            System.out.println("Error when obj = " + objToSave);
            // err.printStackTrace();
            throw err;
        }
    }

    public void test_18_4_writeObject() {
        // Test for method void
        // java.io.ObjectOutputStream.writeObject(java.lang.Object)

        Object objToSave = null;
        Object objLoaded;

        try {
            int[] ints = { 0, 1, 2, 3 };
            objToSave = ints;
            if (DEBUG)
                System.out.println("Obj = " + objToSave);
            objLoaded = dumpAndReload(objToSave);
            assertTrue(MSG_TEST_FAILED + objToSave, Arrays.equals(
                    (int[]) objLoaded, (int[]) objToSave));

        } catch (IOException e) {
            fail("IOException serializing data : " + e.getMessage());
        } catch (ClassNotFoundException e) {
            fail("ClassNotFoundException reading Object type : "
                    + e.getMessage());
        } catch (Error err) {
            System.out.println("Error when obj = " + objToSave);
            throw err;
        }
    }

    public void test_18_5_writeObject() {
        // Test for method void
        // java.io.ObjectOutputStream.writeObject(java.lang.Object)

        Object objToSave = null;
        Object objLoaded;

        try {

            short[] shorts = { 0, 1, 2, 3 };
            objToSave = shorts;
            if (DEBUG)
                System.out.println("Obj = " + objToSave);
            objLoaded = dumpAndReload(objToSave);
            assertTrue(MSG_TEST_FAILED + objToSave, Arrays.equals(
                    (short[]) objLoaded, (short[]) objToSave));

        } catch (IOException e) {
            fail("IOException serializing data : " + e.getMessage());
        } catch (ClassNotFoundException e) {
            fail("ClassNotFoundException reading Object type : "
                    + e.getMessage());
        } catch (Error err) {
            System.out.println("Error when obj = " + objToSave);
            // err.printStackTrace();
            throw err;
        }
    }

    public void test_18_6_writeObject() {
        // Test for method void
        // java.io.ObjectOutputStream.writeObject(java.lang.Object)

        Object objToSave = null;
        Object objLoaded;

        try {
            long[] longs = { 0, 1, 2, 3 };
            objToSave = longs;
            if (DEBUG)
                System.out.println("Obj = " + objToSave);
            objLoaded = dumpAndReload(objToSave);
            assertTrue(MSG_TEST_FAILED + objToSave, Arrays.equals(
                    (long[]) objLoaded, (long[]) objToSave));

        } catch (IOException e) {
            fail("IOException serializing data : " + e.getMessage());
        } catch (ClassNotFoundException e) {
            fail("ClassNotFoundException reading Object type : "
                    + e.getMessage());
        } catch (Error err) {
            System.out.println("Error when obj = " + objToSave);
            // err.printStackTrace();
            throw err;
        }
    }

    public void test_18_7_writeObject() {
        // Test for method void
        // java.io.ObjectOutputStream.writeObject(java.lang.Object)

        Object objToSave = null;
        Object objLoaded;

        try {
            float[] floats = { 0.0f, 1.1f, 2.2f, 3.3f };
            objToSave = floats;
            if (DEBUG)
                System.out.println("Obj = " + objToSave);
            objLoaded = dumpAndReload(objToSave);
            assertTrue(MSG_TEST_FAILED + objToSave, Arrays.equals(
                    (float[]) objLoaded, (float[]) objToSave));

        } catch (IOException e) {
            fail("IOException serializing data: " + e.getMessage());
        } catch (ClassNotFoundException e) {
            fail("ClassNotFoundException reading Object type : "
                    + e.getMessage());
        } catch (Error err) {
            System.out.println("Error when obj = " + objToSave);
            // err.printStackTrace();
            throw err;
        }
    }

    public void test_18_8_writeObject() {
        // Test for method void
        // java.io.ObjectOutputStream.writeObject(java.lang.Object)

        Object objToSave = null;
        Object objLoaded;

        try {
            double[] doubles = { 0.0, 1.1, 2.2, 3.3 };
            objToSave = doubles;
            if (DEBUG)
                System.out.println("Obj = " + objToSave);
            objLoaded = dumpAndReload(objToSave);
            assertTrue(MSG_TEST_FAILED + objToSave, Arrays.equals(
                    (double[]) objLoaded, (double[]) objToSave));

        } catch (IOException e) {
            fail("IOException serializing data : " + e.getMessage());
        } catch (ClassNotFoundException e) {
            fail("ClassNotFoundException reading Object type : "
                    + e.getMessage());
        } catch (Error err) {
            System.out.println("Error when obj = " + objToSave);
            // err.printStackTrace();
            throw err;
        }
    }

    public void test_18_9_writeObject() {
        // Test for method void
        // java.io.ObjectOutputStream.writeObject(java.lang.Object)

        Object objToSave = null;
        Object objLoaded;

        try {
            boolean[] booleans = { true, false, false, true };
            objToSave = booleans;
            if (DEBUG)
                System.out.println("Obj = " + objToSave);
            objLoaded = dumpAndReload(objToSave);
            assertTrue(MSG_TEST_FAILED + objToSave, Arrays.equals(
                    (boolean[]) objLoaded, (boolean[]) objToSave));

        } catch (IOException e) {
            fail("IOException serializing data : " + e.getMessage());
        } catch (ClassNotFoundException e) {
            fail("ClassNotFoundException reading Object type : " + e.getMessage());
        } catch (Error err) {
            System.out.println("Error when obj = " + objToSave);
            // err.printStackTrace();
            throw err;
        }
    }

    public void test_18_10_writeObject() {
        // Test for method void
        // java.io.ObjectOutputStream.writeObject(java.lang.Object)

        Object objToSave = null;
        Object objLoaded;

        try {

            String[] strings = { "foo", "bar", "java" };
            objToSave = strings;
            if (DEBUG)
                System.out.println("Obj = " + objToSave);
            objLoaded = dumpAndReload(objToSave);
            assertTrue(MSG_TEST_FAILED + objToSave, Arrays.equals(
                    (Object[]) objLoaded, (Object[]) objToSave));

        } catch (IOException e) {
            fail("IOException serializing " + objToSave + " : "
                    + e.getMessage());
        } catch (ClassNotFoundException e) {
            fail("Unable to read Object type: " + e.toString());
        } catch (Error err) {
            System.out.println("Error when obj = " + objToSave);
            // err.printStackTrace();
            throw err;
        }
    }

    public void test_18_11_writeObject() {
        // Test for method void
        // java.io.ObjectOutputStream.writeObject(java.lang.Object)

        Object objToSave = null;
        Object objLoaded;

        try {

            objToSave = new Object(); // Not serializable
            if (DEBUG)
                System.out.println("Obj = " + objToSave);
            boolean passed = false;
            Throwable t = null;
            try {
                objLoaded = dumpAndReload(objToSave);
            } catch (NotSerializableException ns) {
                passed = true;
                t = ns;
            } catch (Exception wrongExc) {
                passed = false;
                t = wrongExc;
            }
            assertTrue(
                    "Failed to throw NotSerializableException when serializing "
                            + objToSave + " Threw(if non-null) this: " + t,
                    passed);
        } catch (Error err) {
            System.out.println("Error when obj = " + objToSave);
            // err.printStackTrace();
            throw err;
        }
    }

    public void test_18_12_writeObject() {
        // Test for method void
        // java.io.ObjectOutputStream.writeObject(java.lang.Object)

        try {
            if (DEBUG)
                System.out.println("Obj = <mixed>");
            t_MixPrimitivesAndObjects();
        } catch (IOException e) {
            fail("IOException serializing data : " + e.getMessage());
        } catch (ClassNotFoundException e) {
            fail("ClassNotFoundException reading Object type : "
                    + e.getMessage());
        } catch (Error err) {
            System.out.println("Error when dumping mixed types");
            // err.printStackTrace();
            throw err;
        }
    }

    public void test_18_13_writeObject() {
        // Test for method void
        // java.io.ObjectOutputStream.writeObject(java.lang.Object)

        Object objToSave = null;
        Object objLoaded;

        try {
            SerializationTestSubclass1 st = new SerializationTestSubclass1();
            // Just change the default ivar values
            st.anInt = Integer.MAX_VALUE;
            st.aString = FOO;
            objToSave = st;
            if (DEBUG)
                System.out.println("Obj = " + objToSave);
            objLoaded = dumpAndReload(objToSave);
            // non-serializable inst var has to be initialized from top
            // constructor
            assertTrue(
                    MSG_TEST_FAILED + objToSave,
                    ((SerializationTestSubclass1) objLoaded).anInt == Integer.MAX_VALUE);
            // but serialized var has to be restored as it was in the object
            // when dumped
            assertTrue(MSG_TEST_FAILED + objToSave,
                    ((SerializationTestSubclass1) objLoaded).aString
                            .equals(FOO));
        } catch (IOException e) {
            fail("Exception serializing " + objToSave + "\t->"
                    + e.toString());
        } catch (ClassNotFoundException e) {
            fail("ClassNotFoundException reading Object type : "
                    + e.getMessage());
        } catch (Error err) {
            System.out.println("Error when obj = " + objToSave);
            err.printStackTrace();
            throw err;
        }
    }

    public void test_18_14_writeObject() {
        // Test for method void
        // java.io.ObjectOutputStream.writeObject(java.lang.Object)

        Object objToSave = null;
        Object objLoaded;

        try {
            SpecTest specTest = new SpecTest();
            // Just change the default ivar values
            specTest.instVar = FOO;
            specTest.instVar1 = specTest.instVar;
            objToSave = specTest;
            if (DEBUG)
                System.out.println("Obj = " + objToSave);
            objLoaded = dumpAndReload(objToSave);
            // non-serializable inst var has to be initialized from top
            // constructor
            assertNull(MSG_TEST_FAILED + objToSave,
                    ((SpecTest) objLoaded).instVar);
            // instVar from non-serialized class, cant  be  saved/restored
            // by serialization but serialized ivar has to be restored as it
            // was in the object when dumped
            assertTrue(MSG_TEST_FAILED + objToSave,
                    ((SpecTest) objLoaded).instVar1.equals(FOO));

        } catch (IOException e) {
            fail("Exception serializing " + objToSave + "\t->"
                    + e.toString());
        } catch (ClassNotFoundException e) {
            fail("ClassNotFoundException reading Object type : "
                    + e.getMessage());
        } catch (Error err) {
            System.out.println("Error when obj = " + objToSave);
            // err.printStackTrace();
            throw err;
        }
    }

    public void test_18_15_writeObject() {
        // Test for method void
        // java.io.ObjectOutputStream.writeObject(java.lang.Object)

        Object objToSave = null;
        Object objLoaded;

        try {
            SpecTestSubclass specTestSubclass = new SpecTestSubclass();
            // Just change the default ivar values
            specTestSubclass.transientInstVar = FOO;
            objToSave = specTestSubclass;
            if (DEBUG)
                System.out.println("Obj = " + objToSave);
            objLoaded = dumpAndReload(objToSave);
            // non-serializable inst var cant be saved, and it is not init'ed
            // from top constructor in this case
            assertNull(MSG_TEST_FAILED + objToSave,
                    ((SpecTestSubclass) objLoaded).transientInstVar);
            // transient slot, cant be saved/restored by serialization
        } catch (IOException e) {
            fail("Exception serializing " + objToSave + "\t->"
                    + e.toString());
        } catch (ClassNotFoundException e) {
            fail("ClassNotFoundException reading Object type : "
                    + e.getMessage());
        } catch (Error err) {
            System.out.println("Error when obj = " + objToSave);
            // err.printStackTrace();
            throw err;
        }
    }

    public void test_18_16_writeObject() {
        // Test for method void
        // java.io.ObjectOutputStream.writeObject(java.lang.Object)

        Object objToSave = null;
        Object objLoaded;

        try {

            String[] strings = new String[2];
            strings[0] = FOO;
            strings[1] = (" " + FOO + " ").trim(); // Safe way to get a copy
            // that is not ==
            objToSave = strings;
            if (DEBUG)
                System.out.println("Obj = " + objToSave);
            objLoaded = dumpAndReload(objToSave);
            String[] stringsLoaded = (String[]) objLoaded;
            // Serialization has to use identity-based table for assigning IDs
            assertTrue(MSG_TEST_FAILED + objToSave,
                    !(stringsLoaded[0] == stringsLoaded[1]));
        } catch (IOException e) {
            fail("Exception serializing " + objToSave + "\t->"
                    + e.toString());
        } catch (ClassNotFoundException e) {
            fail("ClassNotFoundException reading Object type : "
                    + e.getMessage());
        } catch (Error err) {
            System.out.println("Error when obj = " + objToSave);
            // err.printStackTrace();
            throw err;
        }
    }

    public void test_18_17_writeObject() {
        // Test for method void
        // java.io.ObjectOutputStream.writeObject(java.lang.Object)

        Object objToSave = null;
        Object objLoaded;

        try {

            ReadWriteObject readWrite = new ReadWriteObject();
            objToSave = readWrite;
            if (DEBUG)
                System.out.println("Obj = " + objToSave);
            objLoaded = dumpAndReload(objToSave);
            // has to have called the writeObject on the instance to dump
            assertTrue(MSG_TEST_FAILED + objToSave, readWrite.calledWriteObject);
            // has to have called the readObject on the instance loaded
            assertTrue(MSG_TEST_FAILED + objToSave,
                    ((ReadWriteObject) objLoaded).calledReadObject);

        } catch (IOException e) {
            fail("Exception serializing " + objToSave + "\t->"
                    + e.toString());
        } catch (ClassNotFoundException e) {
            fail("ClassNotFoundException reading Object type : "
                    + e.getMessage());
        } catch (Error err) {
            System.out.println("Error when obj = " + objToSave);
            // err.printStackTrace();
            throw err;
        }
    }

    public void test_18_18_writeObject() {
        // Test for method void
        // java.io.ObjectOutputStream.writeObject(java.lang.Object)

        Object objToSave = null;
        Object objLoaded;

        try {
            PublicReadWriteObject publicReadWrite = new PublicReadWriteObject();
            objToSave = publicReadWrite;
            if (DEBUG)
                System.out.println("Obj = " + objToSave);
            objLoaded = dumpAndReload(objToSave);
            // Can't have called the writeObject on the instance to dump
            assertTrue(MSG_TEST_FAILED + objToSave,
                    !publicReadWrite.calledWriteObject);
            // Can't have called the readObject on the instance loaded
            assertTrue(MSG_TEST_FAILED + objToSave,
                    !((PublicReadWriteObject) objLoaded).calledReadObject);

        } catch (IOException e) {
            fail("Exception serializing " + objToSave + "\t->"
                    + e.toString());
        } catch (ClassNotFoundException e) {
            fail("ClassNotFoundException reading Object type : "
                    + e.getMessage());
        } catch (Error err) {
            System.out.println("Error when obj = " + objToSave);
            // err.printStackTrace();
            throw err;
        }
    }

    public void test_18_19_writeObject() {
        // Test for method void
        // java.io.ObjectOutputStream.writeObject(java.lang.Object)

        Object objToSave = null;
        Object objLoaded;

        try {
            FieldOrder fieldOrder = new FieldOrder();
            objToSave = fieldOrder;
            if (DEBUG)
                System.out.println("Obj = " + objToSave);
            objLoaded = dumpAndReload(objToSave);
            // This test is only useful for X-loading, so if it managed to
            // dump&load, we passed the test
            assertTrue(MSG_TEST_FAILED + objToSave, true);

        } catch (IOException e) {
            fail("IOException serializing " + objToSave + " : "
                    + e.getMessage());
        } catch (ClassNotFoundException e) {
            fail("ClassNotFoundException reading Object type : "
                    + e.getMessage());
        } catch (Error err) {
            System.out.println("Error when obj = " + objToSave);
            // err.printStackTrace();
            throw err;
        }
    }

    public void test_18_20_writeObject() {
        // Test for method void
        // java.io.ObjectOutputStream.writeObject(java.lang.Object)

        Object objToSave = null;
        Object objLoaded;

        try {
            objToSave = Class.forName("java.lang.Integer");
            if (DEBUG)
                System.out.println("Obj = " + objToSave);
            objLoaded = dumpAndReload(objToSave);
            // Classes with the same name are unique, so test for ==
            assertTrue(MSG_TEST_FAILED + objToSave, objLoaded == objToSave);

        } catch (IOException e) {
            fail("IOException serializing " + objToSave + " : "
                    + e.getMessage());
        } catch (ClassNotFoundException e) {
            fail("ClassNotFoundException reading Object type : "
                    + e.getMessage());
        } catch (Error err) {
            System.out.println("Error when obj = " + objToSave);
            // err.printStackTrace();
            throw err;
        }
    }

    public void test_18_21_writeObject() {
        // Test for method void
        // java.io.ObjectOutputStream.writeObject(java.lang.Object)

        Object objToSave = null;
        Object objLoaded;

        try {
            // Even though instances of java.lang.Object are not Serializable,
            // instances of java.lang.Class are. So, the object
            // java.lang.Object.class
            // should be serializable
            objToSave = Class.forName("java.lang.Object");
            if (DEBUG)
                System.out.println("Obj = " + objToSave);
            objLoaded = dumpAndReload(objToSave);
            // Classes with the same name are unique, so test for ==
            assertTrue(MSG_TEST_FAILED + objToSave, objLoaded == objToSave);

        } catch (IOException e) {
            fail("IOException serializing " + objToSave + " : "
                    + e.getMessage());
        } catch (ClassNotFoundException e) {
            fail("ClassNotFoundException reading Object type : "
                    + e.getMessage());
        } catch (Error err) {
            System.out.println("Error when obj = " + objToSave);
            // err.printStackTrace();
            throw err;
        }
    }

    public void test_18_22_writeObject() {
        // Test for method void
        // java.io.ObjectOutputStream.writeObject(java.lang.Object)

        Object objToSave = null;
        Object objLoaded;

        try {
            java.net.URL url = new java.net.URL("http://localhost/a.txt");
            objToSave = url;
            if (DEBUG)
                System.out.println("Obj = " + objToSave);
            objLoaded = dumpAndReload(objToSave);
            assertTrue("URLs are not the same: " + url + "\t,\t" + objLoaded,
                    url.equals(objLoaded));

        } catch (IOException e) {
            fail("IOException serializing " + objToSave + " : "
                    + e.getMessage());
        } catch (ClassNotFoundException e) {
            fail("ClassNotFoundException reading Object type : "
                    + e.getMessage());
        } catch (Error err) {
            System.out.println("Error when obj = " + objToSave);
            // err.printStackTrace();
            throw err;
        }
    }

    public void test_18_23_writeObject() {
        // Test for method void
        // java.io.ObjectOutputStream.writeObject(java.lang.Object)

        Object objToSave = null;
        Object objLoaded;

        try {

            JustReadObject justReadObject = new JustReadObject();
            objToSave = justReadObject;
            if (DEBUG)
                System.out.println("Obj = " + objToSave);
            objLoaded = dumpAndReload(objToSave);
            // Only calls readObject on the instance loaded if writeObject was
            // also defined
            assertTrue("Called readObject on an object without a writeObject",
                    !((JustReadObject) objLoaded).calledReadObject);

        } catch (IOException e) {
            fail("IOException serializing " + objToSave + " : "
                    + e.getMessage());
        } catch (ClassNotFoundException e) {
            fail("ClassNotFoundException reading Object type : "
                    + e.getMessage());
        } catch (Error err) {
            System.out.println("Error when obj = " + objToSave);
            // err.printStackTrace();
            throw err;
        }
    }

    public void test_18_24_writeObject() {
        // Test for method void
        // java.io.ObjectOutputStream.writeObject(java.lang.Object)

        Object objToSave = null;
        Object objLoaded;

        try {

            JustWriteObject justWriteObject = new JustWriteObject();
            objToSave = justWriteObject;
            if (DEBUG)
                System.out.println("Obj = " + objToSave);
            objLoaded = dumpAndReload(objToSave);
            // Call writeObject on the instance even if it does not define
            // readObject
            assertTrue(MSG_TEST_FAILED + objToSave,
                    justWriteObject.calledWriteObject);

        } catch (IOException e) {
            fail("IOException serializing " + objToSave + " : "
                    + e.getMessage());
        } catch (ClassNotFoundException e) {
            fail("ClassNotFoundException reading Object type: "
                    + e.getMessage());
        } catch (Error err) {
            System.out.println("Error when obj = " + objToSave);
            // err.printStackTrace();
            throw err;
        }
    }

    public void test_18_25_writeObject() {
        // Test for method void
        // java.io.ObjectOutputStream.writeObject(java.lang.Object)

        Object objToSave = null;
        Object objLoaded;

        try {
            Vector<String> vector = new Vector<String>(1);
            vector.add(FOO);
            objToSave = vector;
            if (DEBUG)
                System.out.println("Obj = " + objToSave);
            objLoaded = dumpAndReload(objToSave);
            // Has to have the string there
            assertTrue(MSG_TEST_FAILED + objToSave, FOO
                    .equals(((java.util.Vector) objLoaded).elementAt(0)));

        } catch (IOException e) {
            fail("IOException serializing " + objToSave + " : "
                    + e.getMessage());
        } catch (ClassNotFoundException e) {
            fail("ClassNotFoundException reading Object type : "
                    + e.getMessage());
        } catch (Error err) {
            System.out.println("Error when obj = " + objToSave);
            throw err;
        }
    }

    public void test_18_26_writeObject() {
        // Test for method void
        // java.io.ObjectOutputStream.writeObject(java.lang.Object)

        Object objToSave = null;
        Object objLoaded;

        try {
            Hashtable<String, String> hashTable = new Hashtable<String, String>(
                    5);
            hashTable.put(FOO, FOO);
            objToSave = hashTable;
            if (DEBUG)
                System.out.println("Obj = " + objToSave);
            objLoaded = dumpAndReload(objToSave);
            java.util.Hashtable loadedHashTable = (java.util.Hashtable) objLoaded;
            // Has to have the key/value there (FOO -> FOO)
            assertTrue(MSG_TEST_FAILED + objToSave, FOO.equals(loadedHashTable
                    .get(FOO)));

        } catch (IOException e) {
            fail("IOException serializing " + objToSave + " : "
                    + e.getMessage());
        } catch (ClassNotFoundException e) {
            fail("ClassNotFoundException reading Object type : "
                    + e.getMessage());
        } catch (Error err) {
            System.out.println("Error when obj = " + objToSave);
            throw err;
        }
    }

    public void test_18_27_writeObject() {
        // Test for method void
        // java.io.ObjectOutputStream.writeObject(java.lang.Object)

        Object objToSave = null;
        Object objLoaded;

        try {
            ClassBasedReplacementWhenDumping classBasedReplacementWhenDumping = new ClassBasedReplacementWhenDumping();
            objToSave = classBasedReplacementWhenDumping;
            if (DEBUG)
                System.out.println("Obj = " + objToSave);
            objLoaded = dumpAndReload(objToSave);
            // Has to have run the replacement method
            assertTrue("Did not run writeReplace",
                    classBasedReplacementWhenDumping.calledReplacement);

            // Has to have loaded a String (replacement object)
            assertTrue("Did not replace properly", FOO.equals(objLoaded));

        } catch (IOException e) {
            fail("IOException serializing " + objToSave + " : "
                    + e.getMessage());
        } catch (ClassNotFoundException e) {
            fail("ClassNotFoundException reading Object type : "
                    + e.getMessage());
        } catch (Error err) {
            System.out.println("Error when obj = " + objToSave);
            // err.printStackTrace();
            throw err;
        }
    }

    public void test_18_28_writeObject() {
        // Test for method void
        // java.io.ObjectOutputStream.writeObject(java.lang.Object)

        Object objToSave = null;
        Object objLoaded;

        try {
            MultipleClassBasedReplacementWhenDumping multipleClassBasedReplacementWhenDumping = new MultipleClassBasedReplacementWhenDumping();
            objToSave = multipleClassBasedReplacementWhenDumping;
            if (DEBUG)
                System.out.println("Obj = " + objToSave);
            objLoaded = dumpAndReload(objToSave);
            // Has to have loaded a String (replacement object)
            assertTrue(
                    "Executed multiple levels of replacement (see PR 1F9RNT1), loaded= "
                            + objLoaded,
                    objLoaded instanceof MultipleClassBasedReplacementWhenDumping.C1);

        } catch (IOException e) {
            fail("IOException serializing " + objToSave + " : "
                    + e.getMessage());
        } catch (ClassNotFoundException e) {
            fail("ClassNotFoundException reading Object type : "
                    + e.toString());
        } catch (Error err) {
            System.out.println("Error when obj = " + objToSave);
            // err.printStackTrace();
            throw err;
        }
    }

    public void test_18_29_writeObject() {
        // Test for method void
        // java.io.ObjectOutputStream.writeObject(java.lang.Object)

        Object objToSave = null;
        Object objLoaded;

        try {
            ClassBasedReplacementWhenLoading classBasedReplacementWhenLoading = new ClassBasedReplacementWhenLoading();
            objToSave = classBasedReplacementWhenLoading;
            if (DEBUG)
                System.out.println("Obj = " + objToSave);
            objLoaded = dumpAndReload(objToSave);
            // Has to have loaded a String (replacement object)
            assertTrue("Did not run readResolve", FOO.equals(objLoaded));

        } catch (IOException e) {
            fail("IOException serializing " + objToSave + " : "
                    + e.getMessage());
        } catch (ClassNotFoundException e) {
            fail("ClassNotFoundException reading Object type : "
                    + e.getMessage());
        } catch (Error err) {
            System.out.println("Error when obj = " + objToSave);
            // err.printStackTrace();
            throw err;
        }
    }

    public void test_18_30_writeObject() {
        // Test for method void
        // java.io.ObjectOutputStream.writeObject(java.lang.Object)

        Object objToSave = null;
        Object objLoaded;

        try {
            ClassBasedReplacementWhenLoadingViolatesFieldType classBasedReplacementWhenLoadingViolatesFieldType = new ClassBasedReplacementWhenLoadingViolatesFieldType();
            objToSave = classBasedReplacementWhenLoadingViolatesFieldType;
            if (DEBUG)
                System.out.println("Obj = " + objToSave);
            objLoaded = dumpAndReload(objToSave);
            // We cannot gere here, the load replacement must have caused a
            // field type violation
            fail(
                    "Loading replacements can cause field type violation in this implementation");

        } catch (IOException e) {
            fail("IOException serializing " + objToSave + " : "
                    + e.getMessage());
        } catch (ClassNotFoundException e) {
            fail("ClassNotFoundException reading Object type : "
                    + e.getMessage());
        } catch (ClassCastException e) {
            assertTrue(
                    "Loading replacements can NOT cause field type violation in this implementation",
                    true);
        } catch (Error err) {
            System.out.println("Error when obj = " + objToSave);
            // err.printStackTrace();
            throw err;
        }
    }

    public void test_18_31_writeObject() {
        // Test for method void
        // java.io.ObjectOutputStream.writeObject(java.lang.Object)

        Object objToSave = null;
        Object objLoaded;

        try {
            MyExceptionWhenDumping1 exceptionWhenDumping = new MyExceptionWhenDumping1();
            objToSave = exceptionWhenDumping;
            if (DEBUG)
                System.out.println("Obj = " + objToSave);
            boolean causedException = false;
            try {
                dump(objToSave);
            } catch (MyExceptionWhenDumping1.MyException e) {
                causedException = true;
            }
            ;
            assertTrue("Should have caused an exception when dumping",
                    causedException);
            causedException = false;
            try {
                objLoaded = reload();
                // Although the spec says we should get a WriteAbortedException,
                // the serialization format handle an Exception when reading
                // primitive data so we get ClassCastException instead
            } catch (ClassCastException e) {
                causedException = true;
            }
            ;
            assertTrue("Should have caused a ClassCastException when loading",
                    causedException);
        } catch (IOException e) {
            fail("IOException serializing " + objToSave + " : "
                    + e.getMessage());
        } catch (ClassNotFoundException e) {
            fail("ClassNotFoundException reading Object type : "
                    + e.getMessage());
        } catch (Error err) {
            System.out.println("Error when obj = " + objToSave);
            // err.printStackTrace();
            throw err;
        }
    }

    public void test_18_32_writeObject() {
        // Test for method void
        // java.io.ObjectOutputStream.writeObject(java.lang.Object)

        Object objToSave = null;
        Object objLoaded;

        try {
            MyExceptionWhenDumping2 exceptionWhenDumping = new MyExceptionWhenDumping2();
            objToSave = exceptionWhenDumping;
            if (DEBUG)
                System.out.println("Obj = " + objToSave);
            boolean causedException = false;
            try {
                dump(objToSave);
            } catch (MyExceptionWhenDumping2.MyException e) {
                causedException = true;
            }
            ;
            assertTrue("Should have caused an exception when dumping",
                    causedException);
            causedException = false;
            try {
                objLoaded = reload();
            } catch (java.io.WriteAbortedException e) {
                causedException = true;
            }
            ;
            assertTrue(
                    "Should have caused a java.io.WriteAbortedException when loading",
                    causedException);
        } catch (IOException e) {
            fail("IOException serializing " + objToSave + " : "
                    + e.getMessage());
        } catch (ClassNotFoundException e) {
            fail("ClassNotFoundException reading Object type : "
                    + e.getMessage());
        } catch (ClassCastException e) {
            fail("ClassCastException : " + e.getMessage());
        } catch (Error err) {
            System.out.println("Error when obj = " + objToSave);
            throw err;
        }
    }

    public void test_NonSerializableExceptionWhenDumping() {
        // Test for method void
        // java.io.ObjectOutputStream.writeObject(java.lang.Object)

        Object objToSave = null;
        Object objLoaded;

        try {
            NonSerializableExceptionWhenDumping nonSerializableExceptionWhenDumping = new NonSerializableExceptionWhenDumping();
            objToSave = nonSerializableExceptionWhenDumping;
            if (DEBUG)
                System.out.println("Obj = " + objToSave);
            boolean causedException = false;
            try {
                dump(objToSave);
            } catch (java.io.NotSerializableException e) {
                causedException = true;
            }
            ;
            assertTrue("Should have caused an exception when dumping",
                    causedException);
            causedException = false;
            try {
                objLoaded = reload();
            } catch (java.io.WriteAbortedException e) {
                causedException = true;
            }
            ;
            assertTrue(
                    "Should have caused a java.io.WriteAbortedException when loading",
                    causedException);
        } catch (IOException e) {
            fail("IOException serializing " + objToSave + " : "
                    + e.getMessage());
        } catch (ClassNotFoundException e) {
            fail("ClassNotFoundException reading Object type : "
                    + e.getMessage());
        } catch (Error err) {
            System.out.println("Error when obj = " + objToSave);
            // err.printStackTrace();
            throw err;
        }
    }

    public void test_18_33_writeObject() {
        // Test for method void
        // java.io.ObjectOutputStream.writeObject(java.lang.Object)

        Object objToSave = null;
        Object objLoaded;

        try {
            MyUnserializableExceptionWhenDumping exceptionWhenDumping = new MyUnserializableExceptionWhenDumping();
            objToSave = exceptionWhenDumping;
            if (DEBUG)
                System.out.println("Obj = " + objToSave);
            boolean causedException = false;
            try {
                dump(objToSave);
            } catch (MyUnserializableExceptionWhenDumping.MyException e) {
                causedException = true;
            }

            assertTrue("Should have caused an exception when dumping",
                    causedException);
            // As the stream is corrupted, reading the stream will have
            // undefined results
        } catch (IOException e) {
            fail("IOException serializing " + objToSave + " : "
                    + e.getMessage());
        } catch (ClassNotFoundException e) {
            fail("ClassNotFoundException reading Object type : "
                    + e.getMessage());
        } catch (Error err) {
            System.out.println("Error when obj = " + objToSave);
            // err.printStackTrace();
            throw err;
        }
    }

    public void test_18_34_writeObject() {
        // Test for method void
        // java.io.ObjectOutputStream.writeObject(java.lang.Object)

        Object objToSave = null;
        Object objLoaded;

        try {
            java.io.IOException ioe = new java.io.IOException();
            objToSave = ioe;
            if (DEBUG)
                System.out.println("Obj = " + objToSave);
            objLoaded = dumpAndReload(objToSave);
            // Has to be able to save/load an exception
            assertTrue(MSG_TEST_FAILED + objToSave, true);

        } catch (IOException e) {
            fail("IOException serializing " + objToSave + " : "
                    + e.getMessage());
        } catch (ClassNotFoundException e) {
            fail("ClassNotFoundException reading Object type : "
                    + e.getMessage());
        } catch (Error err) {
            System.out.println("Error when obj = " + objToSave);
            // err.printStackTrace();
            throw err;
        }
    }

    public void test_18_35_writeObject() {
        // Test for method void
        // java.io.ObjectOutputStream.writeObject(java.lang.Object)

        Object objToSave = null;
        Object objLoaded;

        try {
            objToSave = Class.forName("java.util.Hashtable");
            if (DEBUG)
                System.out.println("Obj = " + objToSave);
            objLoaded = dumpAndReload(objToSave);
            // Classes with the same name are unique, so test for ==
            assertTrue(MSG_TEST_FAILED + objToSave, objLoaded == objToSave);

        } catch (IOException e) {
            fail("IOException serializing " + objToSave + " : "
                    + e.getMessage());
        } catch (ClassNotFoundException e) {
            fail("ClassNotFoundException reading Object type : "
                    + e.getMessage());
        } catch (Error err) {
            System.out.println("Error when obj = " + objToSave);
            // err.printStackTrace();
            throw err;
        }
    }

    public void test_18_36_writeObject() {
        // Test for method void
        // java.io.ObjectOutputStream.writeObject(java.lang.Object)

        Object objToSave = null;
        Object objLoaded;

        try {
            java.io.IOException ex = new java.io.InvalidClassException(FOO);
            objToSave = ex;
            if (DEBUG)
                System.out.println("Obj = " + objToSave);
            objLoaded = dumpAndReload(objToSave);
            // Has to be able to save/load an exception
            assertTrue(MSG_TEST_FAILED + objToSave, true);

        } catch (IOException e) {
            fail("IOException serializing " + objToSave + " : "
                    + e.getMessage());
        } catch (ClassNotFoundException e) {
            fail("ClassNotFoundException reading Object type : "
                    + e.getMessage());
        } catch (Error err) {
            System.out.println("Error when obj = " + objToSave);
            // err.printStackTrace();
            throw err;
        }
    }

    public void test_18_37_writeObject() {
        // Test for method void
        // java.io.ObjectOutputStream.writeObject(java.lang.Object)

        Object objToSave = null;
        Object objLoaded;

        try {
            java.io.IOException ex = new java.io.InvalidObjectException(FOO);
            objToSave = ex;
            if (DEBUG)
                System.out.println("Obj = " + objToSave);
            objLoaded = dumpAndReload(objToSave);
            // Has to be able to save/load an exception
            assertTrue(MSG_TEST_FAILED + objToSave, true);

        } catch (IOException e) {
            fail("IOException serializing " + objToSave + " : "
                    + e.getMessage());
        } catch (ClassNotFoundException e) {
            fail("ClassNotFoundException reading Object type : "
                    + e.getMessage());
        } catch (Error err) {
            System.out.println("Error when obj = " + objToSave);
            // err.printStackTrace();
            throw err;
        }
    }

    public void test_18_38_writeObject() {
        // Test for method void
        // java.io.ObjectOutputStream.writeObject(java.lang.Object)

        Object objToSave = null;
        Object objLoaded;

        try {
            java.io.IOException ex = new java.io.NotActiveException(FOO);
            objToSave = ex;
            if (DEBUG)
                System.out.println("Obj = " + objToSave);
            objLoaded = dumpAndReload(objToSave);
            // Has to be able to save/load an exception
            assertTrue(MSG_TEST_FAILED + objToSave, true);

        } catch (IOException e) {
            fail("IOException serializing " + objToSave + " : "
                    + e.getMessage());
        } catch (ClassNotFoundException e) {
            fail("ClassNotFoundException reading Object type : "
                    + e.getMessage());
        } catch (Error err) {
            System.out.println("Error when obj = " + objToSave);
            // err.printStackTrace();
            throw err;
        }
    }

    public void test_18_39_writeObject() {
        // Test for method void
        // java.io.ObjectOutputStream.writeObject(java.lang.Object)

        Object objToSave = null;
        Object objLoaded;

        try {
            java.io.IOException ex = new java.io.NotSerializableException(FOO);
            objToSave = ex;
            if (DEBUG)
                System.out.println("Obj = " + objToSave);
            objLoaded = dumpAndReload(objToSave);
            // Has to be able to save/load an exception
            assertTrue(MSG_TEST_FAILED + objToSave, true);

        } catch (IOException e) {
            fail("IOException serializing " + objToSave + " : "
                    + e.getMessage());
        } catch (ClassNotFoundException e) {
            fail("ClassNotFoundException reading Object type : "
                    + e.getMessage());
        } catch (Error err) {
            System.out.println("Error when obj = " + objToSave);
            // err.printStackTrace();
            throw err;
        }
    }

    public void test_18_40_writeObject() {
        // Test for method void
        // java.io.ObjectOutputStream.writeObject(java.lang.Object)

        Object objToSave = null;
        Object objLoaded;

        try {
            java.io.IOException ex = new java.io.StreamCorruptedException(FOO);
            objToSave = ex;
            if (DEBUG)
                System.out.println("Obj = " + objToSave);
            objLoaded = dumpAndReload(objToSave);
            // Has to be able to save/load an exception
            assertTrue(MSG_TEST_FAILED + objToSave, true);

        } catch (IOException e) {
            fail("IOException serializing " + objToSave + " : "
                    + e.getMessage());
        } catch (ClassNotFoundException e) {
            fail("ClassNotFoundException reading Object type : "
                    + e.getMessage());
        } catch (Error err) {
            System.out.println("Error when obj = " + objToSave);
            // err.printStackTrace();
            throw err;
        }
    }
}
