1/*
2 *  Licensed to the Apache Software Foundation (ASF) under one or more
3 *  contributor license agreements.  See the NOTICE file distributed with
4 *  this work for additional information regarding copyright ownership.
5 *  The ASF licenses this file to You under the Apache License, Version 2.0
6 *  (the "License"); you may not use this file except in compliance with
7 *  the License.  You may obtain a copy of the License at
8 *
9 *     http://www.apache.org/licenses/LICENSE-2.0
10 *
11 *  Unless required by applicable law or agreed to in writing, software
12 *  distributed under the License is distributed on an "AS IS" BASIS,
13 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 *  See the License for the specific language governing permissions and
15 *  limitations under the License.
16 */
17
18package org.apache.harmony.tests.java.io;
19
20import java.io.ByteArrayInputStream;
21import java.io.ByteArrayOutputStream;
22import java.io.DataInputStream;
23import java.io.FileInputStream;
24import java.io.FileOutputStream;
25import java.io.IOException;
26import java.io.InputStream;
27import java.io.InvalidObjectException;
28import java.io.NotActiveException;
29import java.io.ObjectInputStream;
30import java.io.ObjectOutputStream;
31import java.io.ObjectStreamClass;
32import java.io.ObjectStreamException;
33import java.io.Serializable;
34import java.io.StreamCorruptedException;
35import java.io.WriteAbortedException;
36import java.security.Permission;
37import java.security.PermissionCollection;
38import java.util.ArrayList;
39import java.util.Arrays;
40import java.util.Calendar;
41import java.util.GregorianCalendar;
42import java.util.HashMap;
43import java.util.HashSet;
44import java.util.Hashtable;
45import java.util.IdentityHashMap;
46import java.util.LinkedHashMap;
47import java.util.LinkedHashSet;
48import java.util.LinkedList;
49import java.util.List;
50import java.util.Map;
51import java.util.PropertyPermission;
52import java.util.Set;
53import java.util.SimpleTimeZone;
54import java.util.SortedMap;
55import java.util.SortedSet;
56import java.util.TimeZone;
57import java.util.TreeMap;
58import java.util.TreeSet;
59import java.util.Vector;
60import libcore.io.Streams;
61
62/**
63 * Automated Test Suite for class java.io.ObjectOutputStream
64 */
65@SuppressWarnings("serial")
66public 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