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