/* * 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.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.DataInputStream; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; import java.io.InvalidObjectException; import java.io.NotActiveException; import java.io.ObjectInputStream; import java.io.ObjectOutputStream; import java.io.ObjectStreamClass; import java.io.ObjectStreamException; import java.io.Serializable; import java.io.StreamCorruptedException; import java.io.WriteAbortedException; import java.security.Permission; import java.security.PermissionCollection; import java.util.ArrayList; import java.util.Arrays; import java.util.Calendar; import java.util.GregorianCalendar; import java.util.HashMap; import java.util.HashSet; import java.util.Hashtable; import java.util.IdentityHashMap; import java.util.LinkedHashMap; import java.util.LinkedHashSet; import java.util.LinkedList; import java.util.List; import java.util.Map; import java.util.PropertyPermission; import java.util.Set; import java.util.SimpleTimeZone; import java.util.SortedMap; import java.util.SortedSet; import java.util.TimeZone; import java.util.TreeMap; import java.util.TreeSet; import java.util.Vector; import libcore.io.Streams; /** * Automated Test Suite for class java.io.ObjectOutputStream */ @SuppressWarnings("serial") public class SerializationStressTest extends junit.framework.TestCase implements Serializable { // protected static final String MODE_XLOAD = "xload"; // protected static final String MODE_XDUMP = "xdump"; static final String FOO = "foo"; static final String MSG_TEST_FAILED = "Failed to write/read/assertion checking: "; protected static final boolean DEBUG = false; protected static boolean xload = false; protected static boolean xdump = false; protected static String xFileName = null; protected transient int dumpCount = 0; protected transient ObjectInputStream ois; protected transient ObjectOutputStream oos; protected transient ByteArrayOutputStream bao; // ----------------------------------------------------------------------------------- private static class ObjectInputStreamSubclass extends ObjectInputStream { private Vector<Class> resolvedClasses = new Vector<Class>(); public ObjectInputStreamSubclass(InputStream in) throws IOException, StreamCorruptedException { super(in); } public Class<?> resolveClass(ObjectStreamClass osClass) throws IOException, ClassNotFoundException { Class result = super.resolveClass(osClass); resolvedClasses.addElement(result); return result; } public Class[] resolvedClasses() { return (Class[]) resolvedClasses.toArray(new Class[resolvedClasses .size()]); } } static final Map<String, String> TABLE = new Hashtable<String, String>(); static final Map<String, String> MAP = new HashMap<String, String>(); static final SortedMap<String, String> TREE = new TreeMap<String, String>(); static final LinkedHashMap<String, String> LINKEDMAP = new LinkedHashMap<String, String>(); static final LinkedHashSet<String> LINKEDSET = new LinkedHashSet<String>(); static final IdentityHashMap<String, String> IDENTITYMAP = new IdentityHashMap<String, String>(); static final List<String> ALIST = Arrays.asList(new String[] { "a", "list", "of", "strings" }); static final List<String> LIST = new ArrayList<String>(ALIST); static final Set<String> SET = new HashSet<String>(Arrays.asList(new String[] { "one", "two", "three" })); static final SortedSet<String> SORTSET = new TreeSet<String>(Arrays.asList(new String[] { "one", "two", "three" })); static final java.text.DateFormat DATEFORM = java.text.DateFormat .getInstance(); static final java.text.ChoiceFormat CHOICE = new java.text.ChoiceFormat( "1#one|2#two|3#three"); static final java.text.NumberFormat NUMBERFORM = java.text.NumberFormat .getInstance(); static final java.text.MessageFormat MESSAGE = new java.text.MessageFormat( "the time: {0,time} and date {0,date}"); static final LinkedList<String> LINKEDLIST = new LinkedList<String>(Arrays .asList(new String[] { "a", "linked", "list", "of", "strings" })); static final SimpleTimeZone TIME_ZONE = new SimpleTimeZone(3600000, "S-TEST"); static final Calendar CALENDAR = new GregorianCalendar(TIME_ZONE); static { TABLE.put("one", "1"); TABLE.put("two", "2"); TABLE.put("three", "3"); MAP.put("one", "1"); MAP.put("two", "2"); MAP.put("three", "3"); LINKEDMAP.put("one", "1"); LINKEDMAP.put("two", "2"); LINKEDMAP.put("three", "3"); IDENTITYMAP.put("one", "1"); IDENTITYMAP.put("two", "2"); IDENTITYMAP.put("three", "3"); LINKEDSET.add("one"); LINKEDSET.add("two"); LINKEDSET.add("three"); TREE.put("one", "1"); TREE.put("two", "2"); TREE.put("three", "3"); // To make sure they all use the same Calendar CALENDAR.setTimeZone(new SimpleTimeZone(0, "GMT")); CALENDAR.set(1999, Calendar.JUNE, 23, 15, 47, 13); CALENDAR.set(Calendar.MILLISECOND, 553); DATEFORM.setCalendar(CALENDAR); java.text.DateFormatSymbols symbols = new java.text.DateFormatSymbols(); symbols.setZoneStrings(new String[][] { { "a", "b", "c", "d", "e" }, { "f", "g", "h", "i", "j" } }); ((java.text.SimpleDateFormat) DATEFORM).setDateFormatSymbols(symbols); DATEFORM.setNumberFormat(new java.text.DecimalFormat("#0.#")); DATEFORM.setTimeZone(TimeZone.getTimeZone("EST")); ((java.text.DecimalFormat) NUMBERFORM).applyPattern("#0.#"); MESSAGE.setFormat(0, DATEFORM); MESSAGE.setFormat(1, DATEFORM); } public SerializationStressTest() { } public SerializationStressTest(String name) { super(name); } public String getDumpName() { return getName() + dumpCount; } protected void dump(Object o) throws IOException, ClassNotFoundException { if (dumpCount > 0) setUp(); // Dump the object try { oos.writeObject(o); } finally { oos.close(); } } protected Object dumpAndReload(Object o) throws IOException, ClassNotFoundException { dump(o); return reload(); } protected InputStream loadStream() throws IOException { // Choose the load stream if (xload || xdump) { // Load from pre-existing file return new FileInputStream(xFileName + "-" + getDumpName() + ".ser"); } else { // Just load from memory, we dumped to memory return new ByteArrayInputStream(bao.toByteArray()); } } protected Object reload() throws IOException, ClassNotFoundException { ois = new ObjectInputStream(loadStream()); dumpCount++; try { return ois.readObject(); } finally { ois.close(); } } /** * Sets up the fixture, for example, open a network connection. This method * is called before a test is executed. */ protected void setUp() { try { if (xdump) { oos = new ObjectOutputStream(new FileOutputStream(xFileName + "-" + getDumpName() + ".ser")); } else { oos = new ObjectOutputStream(bao = new ByteArrayOutputStream()); } } catch (Exception e) { fail("Exception thrown during setup : " + e.getMessage()); } } /** * Tears down the fixture, for example, close a network connection. This * method is called after a test is executed. */ protected void tearDown() { if (oos != null) { try { oos.close(); } catch (Exception e) { } } } public void test_1_Constructor() throws Exception { // Test for method java.io.ObjectOutputStream(java.io.OutputStream) oos.close(); oos = new ObjectOutputStream(new ByteArrayOutputStream()); oos.close(); } public void test_2_close() { // Test for method void java.io.ObjectOutputStream.close() try { oos.close(); oos = new ObjectOutputStream(bao = new ByteArrayOutputStream()); oos.close(); oos.writeChar('T'); oos.writeObject(FOO); // Writing to a closed stream does not cause problems. This is // the expected behavior } catch (IOException e) { fail("Operation on closed stream threw IOException : " + e.getMessage()); } } public void test_3_defaultWriteObject() { // Test for method void java.io.ObjectOutputStream.defaultWriteObject() try { oos.defaultWriteObject(); } catch (NotActiveException e) { // Correct return; } catch (IOException e) { } fail( "Failed to throw NotActiveException when invoked outside readObject"); } public void test_4_flush() { // Test for method void java.io.ObjectOutputStream.flush() try { oos.close(); oos = new ObjectOutputStream(bao = new ByteArrayOutputStream()); int size = bao.size(); oos.writeByte(127); assertTrue("Data flushed already", bao.size() == size); oos.flush(); assertTrue("Failed to flush data", bao.size() > size); // we don't know how many bytes are actually written for 1 byte, // so we test > <before> oos.close(); oos = null; } catch (IOException e) { fail("IOException serializing data : " + e.getMessage()); } } public void test_5_reset() { // Test for method void java.io.ObjectOutputStream.reset() try { String o = "HelloWorld"; oos.writeObject(o); oos.writeObject(o); oos.reset(); oos.writeObject(o); ois = new ObjectInputStream(loadStream()); ois.close(); } catch (IOException e) { fail("IOException serializing data : " + e.getMessage()); } } public void test_6_write() { // Test for method void java.io.ObjectOutputStream.write(byte [], int, // int) try { byte[] buf = new byte[255]; byte[] output = new byte[255]; for (int i = 0; i < output.length; i++) output[i] = (byte) i; oos.write(output, 0, output.length); oos.close(); ois = new ObjectInputStream(loadStream()); ois.readFully(buf); ois.close(); for (int i = 0; i < output.length; i++) if (buf[i] != output[i]) fail("Read incorrect byte: " + i); } catch (IOException e) { fail("IOException serializing data : " + e.getMessage()); } } public void test_6a_write() { // Test for method void java.io.ObjectOutputStream.write(byte [], int, // int) try { byte[] buf = new byte[256]; byte[] output = new byte[256]; for (int i = 0; i < output.length; i++) output[i] = (byte) (i & 0xff); oos.write(output, 0, output.length); oos.close(); ois = new ObjectInputStream(loadStream()); ois.readFully(buf); ois.close(); for (int i = 0; i < output.length; i++) if (buf[i] != output[i]) fail("Read incorrect byte: " + i); } catch (IOException e) { fail("IOException serializing data : " + e.getMessage()); } } public void test_7_write() { // Test for method void java.io.ObjectOutputStream.write(int) try { oos.write('T'); oos.close(); ois = new ObjectInputStream(loadStream()); assertEquals("Read incorrect byte", 'T', ois.read()); ois.close(); } catch (IOException e) { fail("IOException serializing data : " + e.getMessage()); } } public void test_8_write() { // Test for method void java.io.ObjectOutputStream.write(byte []) try { byte[] buf = new byte[10]; oos.write("HelloWorld".getBytes()); oos.close(); ois = new ObjectInputStream(loadStream()); ois.read(buf, 0, 10); ois.close(); assertEquals("Read incorrect bytes", "HelloWorld", new String(buf, 0, 10) ); } catch (IOException e) { fail("IOException serializing data : " + e.getMessage()); } } public void test_9_writeBoolean() { // Test for method void java.io.ObjectOutputStream.writeBoolean(boolean) try { oos.writeBoolean(true); oos.close(); ois = new ObjectInputStream(loadStream()); assertTrue("Wrote incorrect byte value", ois.readBoolean()); } catch (IOException e) { fail("IOException serializing data : " + e.getMessage()); } } public void test_10_writeByte() { // Test for method void java.io.ObjectOutputStream.writeByte(int) try { oos.writeByte(127); oos.close(); ois = new ObjectInputStream(loadStream()); assertEquals("Wrote incorrect byte value", 127, ois.readByte()); } catch (IOException e) { fail("IOException serializing data : " + e.getMessage()); } } public void test_11_writeBytes() { // Test for method void // java.io.ObjectOutputStream.writeBytes(java.lang.String) try { byte[] buf = new byte[10]; oos.writeBytes("HelloWorld"); oos.close(); ois = new ObjectInputStream(loadStream()); ois.readFully(buf); ois.close(); assertEquals("Wrote incorrect bytes value", "HelloWorld", new String(buf, 0, 10, "UTF-8") ); } catch (IOException e) { fail("IOException serializing data : " + e.getMessage()); } } public void test_12_writeChar() { // Test for method void java.io.ObjectOutputStream.writeChar(int) try { oos.writeChar('T'); oos.close(); ois = new ObjectInputStream(loadStream()); assertEquals("Wrote incorrect char value", 'T', ois.readChar()); } catch (IOException e) { fail("IOException serializing data : " + e.getMessage()); } } public void test_13_writeChars() { // Test for method void // java.io.ObjectOutputStream.writeChars(java.lang.String) try { int avail = 0; char[] buf = new char[10]; oos.writeChars("HelloWorld"); oos.close(); ois = new ObjectInputStream(loadStream()); // Number of prim data bytes in stream / 2 to give char index avail = ois.available() / 2; for (int i = 0; i < avail; ++i) buf[i] = ois.readChar(); ois.close(); assertEquals("Wrote incorrect chars", "HelloWorld", new String(buf, 0, 10) ); } catch (IOException e) { fail("IOException serializing data : " + e.getMessage()); } } public void test_14_writeDouble() { // Test for method void java.io.ObjectOutputStream.writeDouble(double) try { oos.writeDouble(Double.MAX_VALUE); oos.close(); ois = new ObjectInputStream(loadStream()); assertTrue("Wrote incorrect double value", ois.readDouble() == Double.MAX_VALUE); } catch (IOException e) { fail("IOException serializing data : " + e.getMessage()); } } public void test_15_writeFloat() { // Test for method void java.io.ObjectOutputStream.writeFloat(float) try { oos.writeFloat(Float.MAX_VALUE); oos.close(); ois = new ObjectInputStream(loadStream()); assertTrue("Wrote incorrect double value", ois.readFloat() == Float.MAX_VALUE); ois.close(); ois = null; } catch (IOException e) { fail("IOException serializing data : " + e.getMessage()); } } public void test_16_writeInt() { // Test for method void java.io.ObjectOutputStream.writeInt(int) try { oos.writeInt(Integer.MAX_VALUE); oos.close(); ois = new ObjectInputStream(loadStream()); assertTrue("Wrote incorrect double value", ois.readInt() == Integer.MAX_VALUE); ois.close(); } catch (IOException e) { fail("IOException serializing data : " + e.getMessage()); } } public void test_17_writeLong() { // Test for method void java.io.ObjectOutputStream.writeLong(long) try { oos.writeLong(Long.MAX_VALUE); oos.close(); ois = new ObjectInputStream(loadStream()); assertTrue("Wrote incorrect double value", ois.readLong() == Long.MAX_VALUE); } catch (IOException e) { fail("IOException serializing data : " + e.getMessage()); } } public void test_19_writeShort() { // Test for method void java.io.ObjectOutputStream.writeShort(int) try { oos.writeShort(127); oos.close(); ois = new ObjectInputStream(loadStream()); assertEquals("Wrote incorrect short value", 127, ois.readShort()); } catch (IOException e) { fail("IOException serializing data : " + e.getMessage()); } } public void test_20_writeUTF() { // Test for method void // java.io.ObjectOutputStream.writeUTF(java.lang.String) try { oos.writeUTF("HelloWorld"); oos.close(); ois = new ObjectInputStream(loadStream()); assertEquals("Wrote incorrect UTF value", "HelloWorld", ois.readUTF()); } catch (IOException e) { fail("IOException serializing data : " + e.getMessage()); } } public void test_25_available() { try { oos.writeObject(FOO); oos.writeObject(FOO); oos.flush(); int available1 = 0; int available2 = 0; Object obj1 = null; Object obj2 = null; ObjectInputStream ois = new ObjectInputStream(loadStream()); available1 = ois.available(); obj1 = ois.readObject(); available2 = ois.available(); obj2 = ois.readObject(); assertEquals("available returned incorrect value", 0, available1); assertEquals("available returned incorrect value", 0, available2); assertTrue("available caused incorrect reading", FOO.equals(obj1)); assertTrue("available returned incorrect value", FOO.equals(obj2)); } catch (IOException e) { fail("IOException serializing object : " + e.getMessage()); } catch (ClassNotFoundException e) { fail("Unable to read Object type : " + e.toString()); } catch (Error err) { System.out.println("Error " + err); throw err; } } protected void t_MixPrimitivesAndObjects() throws IOException, ClassNotFoundException { int i = 7; String s1 = "string 1"; String s2 = "string 2"; byte[] bytes = { 1, 2, 3 }; oos.writeInt(i); oos.writeObject(s1); oos.writeUTF(s2); oos.writeObject(bytes); oos.close(); try { ois = new ObjectInputStream(loadStream()); int j = ois.readInt(); assertTrue("Wrong int :" + j, i == j); String l1 = (String) ois.readObject(); assertTrue("Wrong obj String :" + l1, s1.equals(l1)); String l2 = (String) ois.readUTF(); assertTrue("Wrong UTF String :" + l2, s2.equals(l2)); byte[] bytes2 = (byte[]) ois.readObject(); assertTrue("Wrong byte[]", Arrays.equals(bytes, bytes2)); } finally { ois.close(); } } public void test_resolveClass() { try { oos.writeObject(new Object[] { Integer.class, new Integer(1) }); oos.close(); ois = new ObjectInputStreamSubclass(loadStream()); ois.readObject(); ois.close(); } catch (IOException e1) { fail("IOException : " + e1.getMessage()); } catch (ClassNotFoundException e2) { fail("ClassNotFoundException : " + e2.getMessage()); } Class[] resolvedClasses = ((ObjectInputStreamSubclass) ois) .resolvedClasses(); assertEquals("missing resolved", 3, resolvedClasses.length); assertTrue("resolved class 1", resolvedClasses[0] == Object[].class); assertTrue("resolved class 2", resolvedClasses[1] == Integer.class); assertTrue("resolved class 3", resolvedClasses[2] == Number.class); } public void test_reset() throws IOException, ClassNotFoundException { oos.reset(); oos.writeObject("R"); oos.reset(); oos.writeByte(24); oos.close(); DataInputStream dis = new DataInputStream(loadStream()); byte[] input = Streams.readFully(dis); byte[] result = new byte[] { (byte) 0xac, (byte) 0xed, (byte) 0, (byte) 5, (byte) 0x79, (byte) 0x74, (byte) 0, (byte) 1, (byte) 'R', (byte) 0x79, (byte) 0x77, (byte) 1, (byte) 24 }; assertTrue("incorrect output", Arrays.equals(input, result)); ois = new ObjectInputStreamSubclass(loadStream()); assertEquals("Wrong result from readObject()", "R", ois.readObject()); assertEquals("Wrong result from readByte()", 24, ois.readByte()); ois.close(); } private static class ResolveObjectTest implements Serializable { Object field1, field2; } private static class ResolveObjectInputStream extends ObjectInputStream { ResolveObjectInputStream(InputStream in) throws StreamCorruptedException, IOException { super(in); } public void enableResolve() { enableResolveObject(true); } public Object resolveObject(Object obj) { if (obj instanceof Vector) // test_1_resolveObject() return new Hashtable(); else if ("abc".equals(obj)) // test_2_resolveObject() return "ABC"; else if (obj instanceof String) // test_3_resolveObject() return String.valueOf(((String) obj).length()); else if (obj instanceof int[]) // test_4_resolveObject() return new Object[1]; else if (obj instanceof Object[] && ((Object[]) obj).length == 2) // test_5_resolveObject() return new char[1]; return obj; } } public void test_1_resolveObject() { try { ResolveObjectTest obj = new ResolveObjectTest(); obj.field1 = new Vector(); obj.field2 = obj.field1; oos.writeObject(obj); oos.close(); ois = new ResolveObjectInputStream(loadStream()); ((ResolveObjectInputStream) ois).enableResolve(); ResolveObjectTest result = null; try { result = (ResolveObjectTest) ois.readObject(); } catch (ClassNotFoundException e) { fail(e.toString()); } assertTrue("Object not resolved", result.field1 instanceof Hashtable); assertTrue("Second reference not resolved", result.field1 == result.field2); } catch (IOException e) { fail("IOException serializing data : " + e.getMessage()); } } public void test_2_resolveObject() { try { ResolveObjectTest obj = new ResolveObjectTest(); obj.field1 = "abc"; obj.field2 = obj.field1; oos.writeObject(obj); oos.close(); ois = new ResolveObjectInputStream(loadStream()); ((ResolveObjectInputStream) ois).enableResolve(); ResolveObjectTest result = null; try { result = (ResolveObjectTest) ois.readObject(); } catch (ClassNotFoundException e) { fail(e.toString()); } assertEquals("String not resolved", "ABC", result.field1); assertTrue("Second reference not resolved", result.field1 == result.field2); } catch (IOException e) { fail("IOException serializing data : " + e.getMessage()); } } public void test_3_resolveObject() { try { ResolveObjectTest obj = new ResolveObjectTest(); char[] lchars = new char[70000]; obj.field1 = new String(lchars); obj.field2 = obj.field1; oos.writeObject(obj); oos.close(); ois = new ResolveObjectInputStream(loadStream()); ((ResolveObjectInputStream) ois).enableResolve(); ResolveObjectTest result = null; try { result = (ResolveObjectTest) ois.readObject(); } catch (ClassNotFoundException e) { fail(e.toString()); } assertTrue("Long String not resolved", "70000" .equals(result.field1)); assertTrue("Second reference not resolved", result.field1 == result.field2); } catch (IOException e) { fail("IOException serializing data : " + e.getMessage()); } } public void test_4_resolveObject() { try { ResolveObjectTest obj = new ResolveObjectTest(); obj.field1 = new int[5]; obj.field2 = obj.field1; oos.writeObject(obj); oos.close(); ois = new ResolveObjectInputStream(loadStream()); ((ResolveObjectInputStream) ois).enableResolve(); ResolveObjectTest result = null; try { result = (ResolveObjectTest) ois.readObject(); } catch (ClassNotFoundException e) { fail(e.toString()); } Class cl = new Object[0].getClass(); assertTrue("int[] not resolved", result.field1.getClass() == cl); assertTrue("Second reference not resolved", result.field1 == result.field2); } catch (IOException e) { fail("IOException serializing data : " + e.getMessage()); } } public void test_5_resolveObject() { try { ResolveObjectTest obj = new ResolveObjectTest(); obj.field1 = new Object[2]; obj.field2 = obj.field1; oos.writeObject(obj); oos.close(); ois = new ResolveObjectInputStream(loadStream()); ((ResolveObjectInputStream) ois).enableResolve(); ResolveObjectTest result = null; try { result = (ResolveObjectTest) ois.readObject(); } catch (ClassNotFoundException e) { fail(e.toString()); } Class cl = new char[0].getClass(); assertTrue("int[] not resolved", result.field1.getClass() == cl); assertTrue("Second reference not resolved", result.field1 == result.field2); } catch (IOException e) { fail("IOException serializing data : " + e.getMessage()); } } static class WriteReplaceTestA implements Serializable { public Object writeReplace() throws ObjectStreamException { return new ReadResolveTestB(); } } static class WriteReplaceTestB extends WriteReplaceTestA { } static class WriteReplaceTestC extends WriteReplaceTestA { public Object writeReplace() throws ObjectStreamException { return new ReadResolveTestC(); } } static class WriteReplaceTestD implements Serializable { private Object writeReplace() throws ObjectStreamException { return new ReadResolveTestD(); } } static class WriteReplaceTestE extends WriteReplaceTestD { } static class WriteReplaceTestF implements Serializable { int type, readType; public WriteReplaceTestF(int type, int readType) { this.type = type; this.readType = readType; } public Object writeReplace() throws ObjectStreamException { switch (type) { case 0: throw new InvalidObjectException("invalid"); case 1: throw new RuntimeException("runtime"); case 2: throw new Error("error"); default: return new ReadResolveTestE(readType); } } } static class ReadResolveTestA implements Serializable { public Object readResolve() throws ObjectStreamException { return new ReadResolveTestA(); } } static class ReadResolveTestB extends ReadResolveTestA { } static class ReadResolveTestC implements Serializable { private Object readResolve() throws ObjectStreamException { return new ReadResolveTestB(); } } static class ReadResolveTestD extends ReadResolveTestC { } static class ReadResolveTestE implements Serializable { int type; public ReadResolveTestE(int type) { this.type = type; } public Object readResolve() throws ObjectStreamException { switch (type) { case 0: throw new InvalidObjectException("invalid"); case 1: throw new RuntimeException("runtime"); case 2: throw new Error("error"); case 3: return this; default: return new ReadResolveTestF(); } } } static class ReadResolveTestF implements Serializable { } public void test_1_writeReplace() { try { Vector<Object> v = new Vector<Object>(); v.addElement(new WriteReplaceTestA()); v.addElement(new WriteReplaceTestB()); v.addElement(new WriteReplaceTestB()); v.addElement(new WriteReplaceTestC()); v.addElement(new WriteReplaceTestD()); v.addElement(new WriteReplaceTestE()); oos.writeObject(v); oos.close(); ois = new ObjectInputStream(loadStream()); Vector result = (Vector) ois.readObject(); assertTrue("invalid 0 : " + result.elementAt(0), result .elementAt(0).getClass() == ReadResolveTestA.class); assertTrue("invalid 1 : " + result.elementAt(1), result .elementAt(1).getClass() == ReadResolveTestA.class); assertTrue("invalid 2 : " + result.elementAt(2), result .elementAt(2).getClass() == ReadResolveTestA.class); assertTrue("invalid 3 : " + result.elementAt(3), result .elementAt(3).getClass() == ReadResolveTestB.class); assertTrue("invalid 4 : " + result.elementAt(4), result .elementAt(4).getClass() == ReadResolveTestD.class); assertTrue("invalid 5 : " + result.elementAt(5), result .elementAt(5).getClass() == WriteReplaceTestE.class); } catch (IOException e) { fail("IOException serializing data : " + e.getMessage()); } catch (ClassNotFoundException e) { fail("ClassNotFoundException serializing data : " + e.getMessage()); } } public void test_2_writeReplace() { try { boolean exception = false; try { oos.writeObject(new WriteReplaceTestF(0, -1)); } catch (ObjectStreamException e) { exception = true; } assertTrue("Should throw ObjectStreamException", exception); exception = false; try { oos.writeObject(new WriteReplaceTestF(1, -1)); } catch (RuntimeException e) { exception = true; } assertTrue("Should throw RuntimeException", exception); exception = false; try { oos.writeObject(new WriteReplaceTestF(2, -1)); } catch (Error e) { exception = true; } assertTrue("Should throw Error", exception); oos.writeObject(new WriteReplaceTestF(3, 0)); oos.writeObject(new WriteReplaceTestF(3, 1)); oos.writeObject(new WriteReplaceTestF(3, 2)); WriteReplaceTestF test = new WriteReplaceTestF(3, 3); oos.writeObject(test); oos.writeObject(test); WriteReplaceTestF test2 = new WriteReplaceTestF(3, 4); oos.writeObject(test2); oos.writeObject(test2); oos.close(); ois = new ObjectInputStream(loadStream()); try { ois.readObject(); } catch (WriteAbortedException e) { } exception = false; try { ois.readObject(); } catch (ObjectStreamException e) { exception = true; } assertTrue("Expected ObjectStreamException", exception); exception = false; try { ois.readObject(); } catch (RuntimeException e) { exception = true; } assertTrue("Expected RuntimeException", exception); exception = false; try { ois.readObject(); } catch (Error e) { exception = true; } assertTrue("Expected Error", exception); Object readE1 = ois.readObject(); Object readE2 = ois.readObject(); assertTrue("Replaced objects should be identical", readE1 == readE2); Object readF1 = ois.readObject(); Object readF2 = ois.readObject(); assertTrue("Replaced resolved objects should be identical: " + readF1 + " " + readF2, readF1 == readF2); } catch (IOException e) { fail("IOException serializing data : " + e.getMessage()); } catch (ClassNotFoundException e) { fail("ClassNotFoundException serializing data : " + e.getMessage()); } } }