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