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.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 @SuppressWarnings("serial")
     66 public class SerializationStressTest extends junit.framework.TestCase implements
     67         Serializable {
     68 
     69     // protected static final String MODE_XLOAD = "xload";
     70 
     71     // protected static final String MODE_XDUMP = "xdump";
     72 
     73     static final String FOO = "foo";
     74 
     75     static final String MSG_TEST_FAILED = "Failed to write/read/assertion checking: ";
     76 
     77     protected static final boolean DEBUG = false;
     78 
     79     protected static boolean xload = false;
     80 
     81     protected static boolean xdump = false;
     82 
     83     protected static String xFileName = null;
     84 
     85     protected transient int dumpCount = 0;
     86 
     87     protected transient ObjectInputStream ois;
     88 
     89     protected transient ObjectOutputStream oos;
     90 
     91     protected transient ByteArrayOutputStream bao;
     92 
     93     // -----------------------------------------------------------------------------------
     94 
     95     private static class ObjectInputStreamSubclass extends ObjectInputStream {
     96         private Vector<Class> resolvedClasses = new Vector<Class>();
     97 
     98         public ObjectInputStreamSubclass(InputStream in) throws IOException,
     99                 StreamCorruptedException {
    100             super(in);
    101         }
    102 
    103         public Class<?> resolveClass(ObjectStreamClass osClass)
    104                 throws IOException, ClassNotFoundException {
    105             Class result = super.resolveClass(osClass);
    106             resolvedClasses.addElement(result);
    107             return result;
    108         }
    109 
    110         public Class[] resolvedClasses() {
    111             return (Class[]) resolvedClasses.toArray(new Class[resolvedClasses
    112                     .size()]);
    113         }
    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("#0.#"));
    188         DATEFORM.setTimeZone(TimeZone.getTimeZone("EST"));
    189         ((java.text.DecimalFormat) NUMBERFORM).applyPattern("#0.#");
    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