SerializationStressTest.java revision fc95c99cfa4921fef424f3f411d013b821589e69
1/*
2 *  Licensed to the Apache Software Foundation (ASF) under one or more
3 *  contributor license agreements.  See the NOTICE file distributed with
4 *  this work for additional information regarding copyright ownership.
5 *  The ASF licenses this file to You under the Apache License, Version 2.0
6 *  (the "License"); you may not use this file except in compliance with
7 *  the License.  You may obtain a copy of the License at
8 *
9 *     http://www.apache.org/licenses/LICENSE-2.0
10 *
11 *  Unless required by applicable law or agreed to in writing, software
12 *  distributed under the License is distributed on an "AS IS" BASIS,
13 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 *  See the License for the specific language governing permissions and
15 *  limitations under the License.
16 */
17
18package org.apache.harmony.luni.tests.java.io;
19
20import java.io.ByteArrayInputStream;
21import java.io.ByteArrayOutputStream;
22import java.io.DataInputStream;
23import java.io.FileInputStream;
24import java.io.FileOutputStream;
25import java.io.IOException;
26import java.io.InputStream;
27import java.io.InvalidObjectException;
28import java.io.NotActiveException;
29import java.io.ObjectInputStream;
30import java.io.ObjectOutputStream;
31import java.io.ObjectStreamClass;
32import java.io.ObjectStreamException;
33import java.io.Serializable;
34import java.io.StreamCorruptedException;
35import java.io.WriteAbortedException;
36import java.security.Permission;
37import java.security.PermissionCollection;
38import java.util.ArrayList;
39import java.util.Arrays;
40import java.util.Calendar;
41import java.util.GregorianCalendar;
42import java.util.HashMap;
43import java.util.HashSet;
44import java.util.Hashtable;
45import java.util.IdentityHashMap;
46import java.util.LinkedHashMap;
47import java.util.LinkedHashSet;
48import java.util.LinkedList;
49import java.util.List;
50import java.util.Map;
51import java.util.PropertyPermission;
52import java.util.Set;
53import java.util.SimpleTimeZone;
54import java.util.SortedMap;
55import java.util.SortedSet;
56import java.util.TimeZone;
57import java.util.TreeMap;
58import java.util.TreeSet;
59import java.util.Vector;
60import libcore.io.Streams;
61
62/**
63 * Automated Test Suite for class java.io.ObjectOutputStream
64 *
65 */
66@SuppressWarnings("serial")
67public class SerializationStressTest extends junit.framework.TestCase implements
68		Serializable {
69
70	// protected static final String MODE_XLOAD = "xload";
71
72	// protected static final String MODE_XDUMP = "xdump";
73
74	static final String FOO = "foo";
75
76	static final String MSG_TEST_FAILED = "Failed to write/read/assertion checking: ";
77
78	protected static final boolean DEBUG = false;
79
80	protected static boolean xload = false;
81
82	protected static boolean xdump = false;
83
84	protected static String xFileName = null;
85
86	protected transient int dumpCount = 0;
87
88	protected transient ObjectInputStream ois;
89
90	protected transient ObjectOutputStream oos;
91
92	protected transient ByteArrayOutputStream bao;
93
94	// -----------------------------------------------------------------------------------
95
96	private static class ObjectInputStreamSubclass extends ObjectInputStream {
97		private Vector<Class> resolvedClasses = new Vector<Class>();
98
99		public ObjectInputStreamSubclass(InputStream in) throws IOException,
100				StreamCorruptedException {
101			super(in);
102		}
103
104		public Class<?> resolveClass(ObjectStreamClass osClass)
105				throws IOException, ClassNotFoundException {
106			Class result = super.resolveClass(osClass);
107			resolvedClasses.addElement(result);
108			return result;
109		}
110
111		public Class[] resolvedClasses() {
112			return (Class[]) resolvedClasses.toArray(new Class[resolvedClasses
113					.size()]);
114		}
115	}
116	static final Map<String , String> TABLE = new Hashtable<String , String>();
117
118	static final Map<String , String> MAP = new HashMap<String , String>();
119
120	static final SortedMap<String , String> TREE = new TreeMap<String , String>();
121
122	static final LinkedHashMap<String , String> LINKEDMAP = new LinkedHashMap<String , String>();
123
124	static final LinkedHashSet<String> LINKEDSET = new LinkedHashSet<String>();
125
126	static final IdentityHashMap<String , String> IDENTITYMAP = new IdentityHashMap<String , String>();
127
128	static final List<String> ALIST = Arrays.asList(new String[] { "a", "list", "of",
129			"strings" });
130
131	static final List<String> LIST = new ArrayList<String>(ALIST);
132
133	static final Set<String> SET = new HashSet<String>(Arrays.asList(new String[] { "one",
134			"two", "three" }));
135
136	static final Permission PERM = new PropertyPermission("file.encoding",
137			"write");
138
139	static final PermissionCollection PERMCOL = PERM.newPermissionCollection();
140
141	static final SortedSet<String> SORTSET = new TreeSet<String>(Arrays.asList(new String[] {
142			"one", "two", "three" }));
143
144	static final java.text.DateFormat DATEFORM = java.text.DateFormat
145			.getInstance();
146
147	static final java.text.ChoiceFormat CHOICE = new java.text.ChoiceFormat(
148			"1#one|2#two|3#three");
149
150	static final java.text.NumberFormat NUMBERFORM = java.text.NumberFormat
151			.getInstance();
152
153	static final java.text.MessageFormat MESSAGE = new java.text.MessageFormat(
154			"the time: {0,time} and date {0,date}");
155
156	static final LinkedList<String> LINKEDLIST = new LinkedList<String>(Arrays
157			.asList(new String[] { "a", "linked", "list", "of", "strings" }));
158
159	static final SimpleTimeZone TIME_ZONE = new SimpleTimeZone(3600000,
160			"S-TEST");
161
162	static final Calendar CALENDAR = new GregorianCalendar(TIME_ZONE);
163
164	static {
165		TABLE.put("one", "1");
166		TABLE.put("two", "2");
167		TABLE.put("three", "3");
168		MAP.put("one", "1");
169		MAP.put("two", "2");
170		MAP.put("three", "3");
171		LINKEDMAP.put("one", "1");
172		LINKEDMAP.put("two", "2");
173		LINKEDMAP.put("three", "3");
174		IDENTITYMAP.put("one", "1");
175		IDENTITYMAP.put("two", "2");
176		IDENTITYMAP.put("three", "3");
177		LINKEDSET.add("one");
178		LINKEDSET.add("two");
179		LINKEDSET.add("three");
180		TREE.put("one", "1");
181		TREE.put("two", "2");
182		TREE.put("three", "3");
183		PERMCOL.add(PERM);
184		// To make sure they all use the same Calendar
185		CALENDAR.setTimeZone(new SimpleTimeZone(0, "GMT"));
186		CALENDAR.set(1999, Calendar.JUNE, 23, 15, 47, 13);
187		CALENDAR.set(Calendar.MILLISECOND, 553);
188		DATEFORM.setCalendar(CALENDAR);
189		java.text.DateFormatSymbols symbols = new java.text.DateFormatSymbols();
190		symbols.setZoneStrings(new String[][] { { "a", "b", "c", "d", "e" },
191				{ "f", "g", "h", "i", "j" } });
192		((java.text.SimpleDateFormat) DATEFORM).setDateFormatSymbols(symbols);
193		DATEFORM.setNumberFormat(new java.text.DecimalFormat("#.#;'-'#.#"));
194		DATEFORM.setTimeZone(TimeZone.getTimeZone("EST"));
195		((java.text.DecimalFormat) NUMBERFORM).applyPattern("#.#;'-'#.#");
196		MESSAGE.setFormat(0, DATEFORM);
197		MESSAGE.setFormat(1, DATEFORM);
198	}
199
200	public SerializationStressTest() {
201	}
202
203	public SerializationStressTest(String name) {
204		super(name);
205	}
206
207	public String getDumpName() {
208		return getName() + dumpCount;
209	}
210
211	protected void dump(Object o) throws IOException, ClassNotFoundException {
212		if (dumpCount > 0)
213			setUp();
214		// Dump the object
215		try {
216			oos.writeObject(o);
217		} finally {
218			oos.close();
219		}
220	}
221
222	protected Object dumpAndReload(Object o) throws IOException,
223			ClassNotFoundException {
224		dump(o);
225		return reload();
226	}
227
228	protected InputStream loadStream() throws IOException {
229		// Choose the load stream
230		if (xload || xdump) {
231			// Load from pre-existing file
232			return new FileInputStream(xFileName + "-" + getDumpName() + ".ser");
233		} else {
234			// Just load from memory, we dumped to memory
235			return new ByteArrayInputStream(bao.toByteArray());
236		}
237	}
238
239	protected Object reload() throws IOException, ClassNotFoundException {
240		ois = new ObjectInputStream(loadStream());
241		dumpCount++;
242		try {
243			return ois.readObject();
244		} finally {
245			ois.close();
246		}
247	}
248
249	/**
250	 * Sets up the fixture, for example, open a network connection. This method
251	 * is called before a test is executed.
252	 */
253	protected void setUp() {
254		try {
255			if (xdump) {
256				oos = new ObjectOutputStream(new FileOutputStream(xFileName
257						+ "-" + getDumpName() + ".ser"));
258			} else {
259				oos = new ObjectOutputStream(bao = new ByteArrayOutputStream());
260			}
261		} catch (Exception e) {
262			fail("Exception thrown during setup : " + e.getMessage());
263		}
264	}
265
266	/**
267	 * Tears down the fixture, for example, close a network connection. This
268	 * method is called after a test is executed.
269	 */
270	protected void tearDown() {
271		if (oos != null) {
272			try {
273				oos.close();
274			} catch (Exception e) {
275			}
276		}
277	}
278
279	public void test_1_Constructor() throws Exception {
280		// Test for method java.io.ObjectOutputStream(java.io.OutputStream)
281                oos.close();
282                oos = new ObjectOutputStream(new ByteArrayOutputStream());
283                oos.close();
284	}
285
286	public void test_2_close() {
287		// Test for method void java.io.ObjectOutputStream.close()
288		try {
289			oos.close();
290			oos = new ObjectOutputStream(bao = new ByteArrayOutputStream());
291			oos.close();
292			oos.writeChar('T');
293			oos.writeObject(FOO);
294			// Writing to a closed stream does not cause problems. This is
295			// the expected behavior
296		} catch (IOException e) {
297			fail("Operation on closed stream threw IOException : "
298					+ e.getMessage());
299		}
300	}
301
302	public void test_3_defaultWriteObject() {
303		// Test for method void java.io.ObjectOutputStream.defaultWriteObject()
304
305		try {
306			oos.defaultWriteObject();
307		} catch (NotActiveException e) {
308			// Correct
309			return;
310		} catch (IOException e) {
311		}
312		fail(
313				"Failed to throw NotActiveException when invoked outside readObject");
314	}
315
316	public void test_4_flush() {
317		// Test for method void java.io.ObjectOutputStream.flush()
318		try {
319			oos.close();
320			oos = new ObjectOutputStream(bao = new ByteArrayOutputStream());
321			int size = bao.size();
322			oos.writeByte(127);
323			assertTrue("Data flushed already", bao.size() == size);
324			oos.flush();
325			assertTrue("Failed to flush data", bao.size() > size);
326			// we don't know how many bytes are actually written for 1 byte,
327			// so we test > <before>
328			oos.close();
329			oos = null;
330		} catch (IOException e) {
331			fail("IOException serializing data : " + e.getMessage());
332		}
333	}
334
335	public void test_5_reset() {
336		// Test for method void java.io.ObjectOutputStream.reset()
337		try {
338			String o = "HelloWorld";
339			oos.writeObject(o);
340			oos.writeObject(o);
341			oos.reset();
342			oos.writeObject(o);
343			ois = new ObjectInputStream(loadStream());
344			ois.close();
345		} catch (IOException e) {
346			fail("IOException serializing data : " + e.getMessage());
347		}
348	}
349
350	public void test_6_write() {
351		// Test for method void java.io.ObjectOutputStream.write(byte [], int,
352		// int)
353		try {
354			byte[] buf = new byte[255];
355			byte[] output = new byte[255];
356			for (int i = 0; i < output.length; i++)
357				output[i] = (byte) i;
358			oos.write(output, 0, output.length);
359			oos.close();
360			ois = new ObjectInputStream(loadStream());
361			ois.readFully(buf);
362			ois.close();
363			for (int i = 0; i < output.length; i++)
364				if (buf[i] != output[i])
365					fail("Read incorrect byte: " + i);
366		} catch (IOException e) {
367			fail("IOException serializing data : " + e.getMessage());
368		}
369	}
370
371	public void test_6a_write() {
372		// Test for method void java.io.ObjectOutputStream.write(byte [], int,
373		// int)
374		try {
375			byte[] buf = new byte[256];
376			byte[] output = new byte[256];
377			for (int i = 0; i < output.length; i++)
378				output[i] = (byte) (i & 0xff);
379			oos.write(output, 0, output.length);
380			oos.close();
381			ois = new ObjectInputStream(loadStream());
382			ois.readFully(buf);
383			ois.close();
384			for (int i = 0; i < output.length; i++)
385				if (buf[i] != output[i])
386					fail("Read incorrect byte: " + i);
387		} catch (IOException e) {
388			fail("IOException serializing data : " + e.getMessage());
389		}
390	}
391
392	public void test_7_write() {
393		// Test for method void java.io.ObjectOutputStream.write(int)
394		try {
395			oos.write('T');
396			oos.close();
397			ois = new ObjectInputStream(loadStream());
398			assertEquals("Read incorrect byte", 'T', ois.read());
399			ois.close();
400		} catch (IOException e) {
401			fail("IOException serializing data : " + e.getMessage());
402		}
403	}
404
405	public void test_8_write() {
406		// Test for method void java.io.ObjectOutputStream.write(byte [])
407		try {
408			byte[] buf = new byte[10];
409			oos.write("HelloWorld".getBytes());
410			oos.close();
411			ois = new ObjectInputStream(loadStream());
412			ois.read(buf, 0, 10);
413			ois.close();
414			assertEquals("Read incorrect bytes", "HelloWorld", new String(buf, 0, 10)
415					);
416		} catch (IOException e) {
417			fail("IOException serializing data : " + e.getMessage());
418		}
419	}
420
421	public void test_9_writeBoolean() {
422		// Test for method void java.io.ObjectOutputStream.writeBoolean(boolean)
423		try {
424			oos.writeBoolean(true);
425			oos.close();
426			ois = new ObjectInputStream(loadStream());
427			assertTrue("Wrote incorrect byte value", ois.readBoolean());
428		} catch (IOException e) {
429			fail("IOException serializing data : " + e.getMessage());
430		}
431	}
432
433	public void test_10_writeByte() {
434		// Test for method void java.io.ObjectOutputStream.writeByte(int)
435		try {
436			oos.writeByte(127);
437			oos.close();
438			ois = new ObjectInputStream(loadStream());
439			assertEquals("Wrote incorrect byte value", 127, ois.readByte());
440		} catch (IOException e) {
441			fail("IOException serializing data : " + e.getMessage());
442		}
443	}
444
445	public void test_11_writeBytes() {
446		// Test for method void
447		// java.io.ObjectOutputStream.writeBytes(java.lang.String)
448		try {
449			byte[] buf = new byte[10];
450			oos.writeBytes("HelloWorld");
451			oos.close();
452			ois = new ObjectInputStream(loadStream());
453			ois.readFully(buf);
454			ois.close();
455			assertEquals("Wrote incorrect bytes value", "HelloWorld", new String(buf, 0, 10, "UTF-8")
456					);
457		} catch (IOException e) {
458			fail("IOException serializing data : " + e.getMessage());
459		}
460	}
461
462	public void test_12_writeChar() {
463		// Test for method void java.io.ObjectOutputStream.writeChar(int)
464		try {
465			oos.writeChar('T');
466			oos.close();
467			ois = new ObjectInputStream(loadStream());
468			assertEquals("Wrote incorrect char value", 'T', ois.readChar());
469		} catch (IOException e) {
470			fail("IOException serializing data : " + e.getMessage());
471		}
472	}
473
474	public void test_13_writeChars() {
475		// Test for method void
476		// java.io.ObjectOutputStream.writeChars(java.lang.String)
477		try {
478			int avail = 0;
479			char[] buf = new char[10];
480			oos.writeChars("HelloWorld");
481			oos.close();
482			ois = new ObjectInputStream(loadStream());
483			// Number of prim data bytes in stream / 2 to give char index
484			avail = ois.available() / 2;
485			for (int i = 0; i < avail; ++i)
486				buf[i] = ois.readChar();
487			ois.close();
488			assertEquals("Wrote incorrect chars", "HelloWorld", new String(buf, 0, 10)
489					);
490		} catch (IOException e) {
491			fail("IOException serializing data : " + e.getMessage());
492		}
493	}
494
495	public void test_14_writeDouble() {
496		// Test for method void java.io.ObjectOutputStream.writeDouble(double)
497		try {
498			oos.writeDouble(Double.MAX_VALUE);
499			oos.close();
500			ois = new ObjectInputStream(loadStream());
501			assertTrue("Wrote incorrect double value",
502					ois.readDouble() == Double.MAX_VALUE);
503		} catch (IOException e) {
504			fail("IOException serializing data : " + e.getMessage());
505		}
506	}
507
508	public void test_15_writeFloat() {
509		// Test for method void java.io.ObjectOutputStream.writeFloat(float)
510		try {
511			oos.writeFloat(Float.MAX_VALUE);
512			oos.close();
513			ois = new ObjectInputStream(loadStream());
514			assertTrue("Wrote incorrect double value",
515					ois.readFloat() == Float.MAX_VALUE);
516			ois.close();
517			ois = null;
518		} catch (IOException e) {
519			fail("IOException serializing data : " + e.getMessage());
520		}
521	}
522
523	public void test_16_writeInt() {
524		// Test for method void java.io.ObjectOutputStream.writeInt(int)
525		try {
526			oos.writeInt(Integer.MAX_VALUE);
527			oos.close();
528			ois = new ObjectInputStream(loadStream());
529			assertTrue("Wrote incorrect double value",
530					ois.readInt() == Integer.MAX_VALUE);
531			ois.close();
532		} catch (IOException e) {
533			fail("IOException serializing data : " + e.getMessage());
534		}
535	}
536
537	public void test_17_writeLong() {
538		// Test for method void java.io.ObjectOutputStream.writeLong(long)
539		try {
540			oos.writeLong(Long.MAX_VALUE);
541			oos.close();
542			ois = new ObjectInputStream(loadStream());
543			assertTrue("Wrote incorrect double value",
544					ois.readLong() == Long.MAX_VALUE);
545		} catch (IOException e) {
546			fail("IOException serializing data : " + e.getMessage());
547		}
548	}
549
550	public void test_19_writeShort() {
551		// Test for method void java.io.ObjectOutputStream.writeShort(int)
552		try {
553			oos.writeShort(127);
554			oos.close();
555			ois = new ObjectInputStream(loadStream());
556			assertEquals("Wrote incorrect short value", 127, ois.readShort());
557		} catch (IOException e) {
558			fail("IOException serializing data : " + e.getMessage());
559		}
560	}
561
562	public void test_20_writeUTF() {
563		// Test for method void
564		// java.io.ObjectOutputStream.writeUTF(java.lang.String)
565		try {
566			oos.writeUTF("HelloWorld");
567			oos.close();
568			ois = new ObjectInputStream(loadStream());
569			assertEquals("Wrote incorrect UTF value",
570					"HelloWorld", ois.readUTF());
571		} catch (IOException e) {
572			fail("IOException serializing data : " + e.getMessage());
573		}
574	}
575
576	public void test_25_available() {
577		try {
578			oos.writeObject(FOO);
579			oos.writeObject(FOO);
580			oos.flush();
581			int available1 = 0;
582			int available2 = 0;
583			Object obj1 = null;
584			Object obj2 = null;
585			ObjectInputStream ois = new ObjectInputStream(loadStream());
586			available1 = ois.available();
587			obj1 = ois.readObject();
588			available2 = ois.available();
589			obj2 = ois.readObject();
590
591			assertEquals("available returned incorrect value", 0, available1);
592			assertEquals("available returned incorrect value", 0, available2);
593
594			assertTrue("available caused incorrect reading", FOO.equals(obj1));
595			assertTrue("available returned incorrect value", FOO.equals(obj2));
596
597		} catch (IOException e) {
598			fail("IOException serializing object : " + e.getMessage());
599		} catch (ClassNotFoundException e) {
600			fail("Unable to read Object type : " + e.toString());
601		} catch (Error err) {
602			System.out.println("Error " + err);
603			throw err;
604		}
605
606	}
607
608	protected void t_MixPrimitivesAndObjects() throws IOException,
609			ClassNotFoundException {
610		int i = 7;
611		String s1 = "string 1";
612		String s2 = "string 2";
613		byte[] bytes = { 1, 2, 3 };
614
615		oos.writeInt(i);
616		oos.writeObject(s1);
617		oos.writeUTF(s2);
618		oos.writeObject(bytes);
619		oos.close();
620		try {
621			ois = new ObjectInputStream(loadStream());
622
623			int j = ois.readInt();
624			assertTrue("Wrong int :" + j, i == j);
625
626			String l1 = (String) ois.readObject();
627			assertTrue("Wrong obj String :" + l1, s1.equals(l1));
628
629			String l2 = (String) ois.readUTF();
630			assertTrue("Wrong UTF String :" + l2, s2.equals(l2));
631
632			byte[] bytes2 = (byte[]) ois.readObject();
633			assertTrue("Wrong byte[]", Arrays.equals(bytes, bytes2));
634
635		} finally {
636			ois.close();
637		}
638	}
639
640	public void test_resolveClass() {
641		try {
642			oos.writeObject(new Object[] { Integer.class, new Integer(1) });
643			oos.close();
644
645			ois = new ObjectInputStreamSubclass(loadStream());
646			ois.readObject();
647			ois.close();
648		} catch (IOException e1) {
649			fail("IOException : " + e1.getMessage());
650		} catch (ClassNotFoundException e2) {
651			fail("ClassNotFoundException : " + e2.getMessage());
652		}
653
654		Class[] resolvedClasses = ((ObjectInputStreamSubclass) ois)
655				.resolvedClasses();
656		assertEquals("missing resolved", 3, resolvedClasses.length);
657		assertTrue("resolved class 1", resolvedClasses[0] == Object[].class);
658		assertTrue("resolved class 2", resolvedClasses[1] == Integer.class);
659		assertTrue("resolved class 3", resolvedClasses[2] == Number.class);
660	}
661
662    public void test_reset() throws IOException, ClassNotFoundException {
663        oos.reset();
664        oos.writeObject("R");
665        oos.reset();
666        oos.writeByte(24);
667        oos.close();
668
669        DataInputStream dis = new DataInputStream(loadStream());
670        byte[] input = Streams.readFully(dis);
671        byte[] result = new byte[] { (byte) 0xac, (byte) 0xed, (byte) 0,
672                (byte) 5, (byte) 0x79, (byte) 0x74, (byte) 0, (byte) 1,
673                (byte) 'R', (byte) 0x79, (byte) 0x77, (byte) 1, (byte) 24 };
674        assertTrue("incorrect output", Arrays.equals(input, result));
675
676        ois = new ObjectInputStreamSubclass(loadStream());
677        assertEquals("Wrong result from readObject()", "R", ois.readObject());
678        assertEquals("Wrong result from readByte()", 24, ois.readByte());
679        ois.close();
680    }
681
682	public void test_serialVersionUID(Class clazz, long svUID) throws Exception {
683		final String idWrong = "serialVersionUID is wrong for: ";
684		long reflectedSvUID = 0L;
685		reflectedSvUID = clazz.getField("serialVersionUID").getLong(null);
686		assertTrue(idWrong + clazz + ": " + reflectedSvUID + " does not equal "
687				+ svUID, reflectedSvUID == svUID);
688	}
689
690	private static class ResolveObjectTest implements Serializable {
691		Object field1, field2;
692	}
693
694	private static class ResolveObjectInputStream extends ObjectInputStream {
695		ResolveObjectInputStream(InputStream in)
696				throws StreamCorruptedException, IOException {
697			super(in);
698		}
699
700		public void enableResolve() {
701			enableResolveObject(true);
702		}
703
704		public Object resolveObject(Object obj) {
705			if (obj instanceof Vector) // test_1_resolveObject()
706				return new Hashtable();
707			else if ("abc".equals(obj)) // test_2_resolveObject()
708				return "ABC";
709			else if (obj instanceof String) // test_3_resolveObject()
710				return String.valueOf(((String) obj).length());
711			else if (obj instanceof int[]) // test_4_resolveObject()
712				return new Object[1];
713			else if (obj instanceof Object[] && ((Object[]) obj).length == 2) // test_5_resolveObject()
714				return new char[1];
715			return obj;
716		}
717	}
718
719	public void test_1_resolveObject() {
720		try {
721			ResolveObjectTest obj = new ResolveObjectTest();
722			obj.field1 = new Vector();
723			obj.field2 = obj.field1;
724			oos.writeObject(obj);
725			oos.close();
726			ois = new ResolveObjectInputStream(loadStream());
727			((ResolveObjectInputStream) ois).enableResolve();
728			ResolveObjectTest result = null;
729			try {
730				result = (ResolveObjectTest) ois.readObject();
731			} catch (ClassNotFoundException e) {
732				fail(e.toString());
733			}
734			assertTrue("Object not resolved",
735					result.field1 instanceof Hashtable);
736			assertTrue("Second reference not resolved",
737					result.field1 == result.field2);
738		} catch (IOException e) {
739			fail("IOException serializing data : " + e.getMessage());
740		}
741	}
742
743	public void test_2_resolveObject() {
744		try {
745			ResolveObjectTest obj = new ResolveObjectTest();
746			obj.field1 = "abc";
747			obj.field2 = obj.field1;
748			oos.writeObject(obj);
749			oos.close();
750			ois = new ResolveObjectInputStream(loadStream());
751			((ResolveObjectInputStream) ois).enableResolve();
752			ResolveObjectTest result = null;
753			try {
754				result = (ResolveObjectTest) ois.readObject();
755			} catch (ClassNotFoundException e) {
756				fail(e.toString());
757			}
758			assertEquals("String not resolved", "ABC", result.field1);
759			assertTrue("Second reference not resolved",
760					result.field1 == result.field2);
761		} catch (IOException e) {
762			fail("IOException serializing data : " + e.getMessage());
763		}
764	}
765
766	public void test_3_resolveObject() {
767		try {
768			ResolveObjectTest obj = new ResolveObjectTest();
769			char[] lchars = new char[70000];
770			obj.field1 = new String(lchars);
771			obj.field2 = obj.field1;
772			oos.writeObject(obj);
773			oos.close();
774			ois = new ResolveObjectInputStream(loadStream());
775			((ResolveObjectInputStream) ois).enableResolve();
776			ResolveObjectTest result = null;
777			try {
778				result = (ResolveObjectTest) ois.readObject();
779			} catch (ClassNotFoundException e) {
780				fail(e.toString());
781			}
782			assertTrue("Long String not resolved", "70000"
783					.equals(result.field1));
784			assertTrue("Second reference not resolved",
785					result.field1 == result.field2);
786		} catch (IOException e) {
787			fail("IOException serializing data : " + e.getMessage());
788		}
789	}
790
791	public void test_4_resolveObject() {
792		try {
793			ResolveObjectTest obj = new ResolveObjectTest();
794			obj.field1 = new int[5];
795			obj.field2 = obj.field1;
796			oos.writeObject(obj);
797			oos.close();
798			ois = new ResolveObjectInputStream(loadStream());
799			((ResolveObjectInputStream) ois).enableResolve();
800			ResolveObjectTest result = null;
801			try {
802				result = (ResolveObjectTest) ois.readObject();
803			} catch (ClassNotFoundException e) {
804				fail(e.toString());
805			}
806			Class cl = new Object[0].getClass();
807			assertTrue("int[] not resolved", result.field1.getClass() == cl);
808			assertTrue("Second reference not resolved",
809					result.field1 == result.field2);
810		} catch (IOException e) {
811			fail("IOException serializing data : " + e.getMessage());
812		}
813	}
814
815	public void test_5_resolveObject() {
816		try {
817			ResolveObjectTest obj = new ResolveObjectTest();
818			obj.field1 = new Object[2];
819			obj.field2 = obj.field1;
820			oos.writeObject(obj);
821			oos.close();
822			ois = new ResolveObjectInputStream(loadStream());
823			((ResolveObjectInputStream) ois).enableResolve();
824			ResolveObjectTest result = null;
825			try {
826				result = (ResolveObjectTest) ois.readObject();
827			} catch (ClassNotFoundException e) {
828				fail(e.toString());
829			}
830			Class cl = new char[0].getClass();
831			assertTrue("int[] not resolved", result.field1.getClass() == cl);
832			assertTrue("Second reference not resolved",
833					result.field1 == result.field2);
834		} catch (IOException e) {
835			fail("IOException serializing data : " + e.getMessage());
836		}
837	}
838
839	static class WriteReplaceTestA implements Serializable {
840		public Object writeReplace() throws ObjectStreamException {
841			return new ReadResolveTestB();
842		}
843	}
844
845	static class WriteReplaceTestB extends WriteReplaceTestA {
846	}
847
848	static class WriteReplaceTestC extends WriteReplaceTestA {
849		public Object writeReplace() throws ObjectStreamException {
850			return new ReadResolveTestC();
851		}
852	}
853
854	static class WriteReplaceTestD implements Serializable {
855		private Object writeReplace() throws ObjectStreamException {
856			return new ReadResolveTestD();
857		}
858	}
859
860	static class WriteReplaceTestE extends WriteReplaceTestD {
861	}
862
863	static class WriteReplaceTestF implements Serializable {
864		int type, readType;
865
866		public WriteReplaceTestF(int type, int readType) {
867			this.type = type;
868			this.readType = readType;
869		}
870
871		public Object writeReplace() throws ObjectStreamException {
872			switch (type) {
873			case 0:
874				throw new InvalidObjectException("invalid");
875			case 1:
876				throw new RuntimeException("runtime");
877			case 2:
878				throw new Error("error");
879			default:
880				return new ReadResolveTestE(readType);
881			}
882		}
883	}
884
885	static class ReadResolveTestA implements Serializable {
886		public Object readResolve() throws ObjectStreamException {
887			return new ReadResolveTestA();
888		}
889	}
890
891	static class ReadResolveTestB extends ReadResolveTestA {
892	}
893
894	static class ReadResolveTestC implements Serializable {
895		private Object readResolve() throws ObjectStreamException {
896			return new ReadResolveTestB();
897		}
898	}
899
900	static class ReadResolveTestD extends ReadResolveTestC {
901	}
902
903	static class ReadResolveTestE implements Serializable {
904		int type;
905
906		public ReadResolveTestE(int type) {
907			this.type = type;
908		}
909
910		public Object readResolve() throws ObjectStreamException {
911			switch (type) {
912			case 0:
913				throw new InvalidObjectException("invalid");
914			case 1:
915				throw new RuntimeException("runtime");
916			case 2:
917				throw new Error("error");
918			case 3:
919				return this;
920			default:
921				return new ReadResolveTestF();
922			}
923		}
924	}
925
926	static class ReadResolveTestF implements Serializable {
927	}
928
929	public void test_1_writeReplace() {
930		try {
931			Vector<Object> v = new Vector<Object>();
932			v.addElement(new WriteReplaceTestA());
933			v.addElement(new WriteReplaceTestB());
934			v.addElement(new WriteReplaceTestB());
935			v.addElement(new WriteReplaceTestC());
936			v.addElement(new WriteReplaceTestD());
937			v.addElement(new WriteReplaceTestE());
938			oos.writeObject(v);
939			oos.close();
940			ois = new ObjectInputStream(loadStream());
941			Vector result = (Vector) ois.readObject();
942			assertTrue("invalid 0 : " + result.elementAt(0), result
943					.elementAt(0).getClass() == ReadResolveTestA.class);
944			assertTrue("invalid 1 : " + result.elementAt(1), result
945					.elementAt(1).getClass() == ReadResolveTestA.class);
946			assertTrue("invalid 2 : " + result.elementAt(2), result
947					.elementAt(2).getClass() == ReadResolveTestA.class);
948			assertTrue("invalid 3 : " + result.elementAt(3), result
949					.elementAt(3).getClass() == ReadResolveTestB.class);
950			assertTrue("invalid 4 : " + result.elementAt(4), result
951					.elementAt(4).getClass() == ReadResolveTestD.class);
952			assertTrue("invalid 5 : " + result.elementAt(5), result
953					.elementAt(5).getClass() == WriteReplaceTestE.class);
954		} catch (IOException e) {
955			fail("IOException serializing data : " + e.getMessage());
956		} catch (ClassNotFoundException e) {
957			fail("ClassNotFoundException serializing data : " + e.getMessage());
958		}
959	}
960
961	public void test_2_writeReplace() {
962		try {
963			boolean exception = false;
964			try {
965				oos.writeObject(new WriteReplaceTestF(0, -1));
966			} catch (ObjectStreamException e) {
967				exception = true;
968			}
969			assertTrue("Should throw ObjectStreamException", exception);
970			exception = false;
971			try {
972				oos.writeObject(new WriteReplaceTestF(1, -1));
973			} catch (RuntimeException e) {
974				exception = true;
975			}
976			assertTrue("Should throw RuntimeException", exception);
977			exception = false;
978			try {
979				oos.writeObject(new WriteReplaceTestF(2, -1));
980			} catch (Error e) {
981				exception = true;
982			}
983			assertTrue("Should throw Error", exception);
984
985			oos.writeObject(new WriteReplaceTestF(3, 0));
986			oos.writeObject(new WriteReplaceTestF(3, 1));
987			oos.writeObject(new WriteReplaceTestF(3, 2));
988			WriteReplaceTestF test = new WriteReplaceTestF(3, 3);
989			oos.writeObject(test);
990			oos.writeObject(test);
991			WriteReplaceTestF test2 = new WriteReplaceTestF(3, 4);
992			oos.writeObject(test2);
993			oos.writeObject(test2);
994			oos.close();
995			ois = new ObjectInputStream(loadStream());
996			try {
997				ois.readObject();
998			} catch (WriteAbortedException e) {
999			}
1000
1001			exception = false;
1002			try {
1003				ois.readObject();
1004			} catch (ObjectStreamException e) {
1005				exception = true;
1006			}
1007			assertTrue("Expected ObjectStreamException", exception);
1008			exception = false;
1009			try {
1010				ois.readObject();
1011			} catch (RuntimeException e) {
1012				exception = true;
1013			}
1014			assertTrue("Expected RuntimeException", exception);
1015			exception = false;
1016			try {
1017				ois.readObject();
1018			} catch (Error e) {
1019				exception = true;
1020			}
1021			assertTrue("Expected Error", exception);
1022
1023			Object readE1 = ois.readObject();
1024			Object readE2 = ois.readObject();
1025			assertTrue("Replaced objects should be identical", readE1 == readE2);
1026			Object readF1 = ois.readObject();
1027			Object readF2 = ois.readObject();
1028			assertTrue("Replaced resolved objects should be identical: "
1029					+ readF1 + " " + readF2, readF1 == readF2);
1030		} catch (IOException e) {
1031			fail("IOException serializing data : " + e.getMessage());
1032		} catch (ClassNotFoundException e) {
1033			fail("ClassNotFoundException serializing data : " + e.getMessage());
1034		}
1035	}
1036}
1037