1/*
2 *  Licensed to the Apache Software Foundation (ASF) under one or more
3 *  contributor license agreements.  See the NOTICE file distributed with
4 *  this work for additional information regarding copyright ownership.
5 *  The ASF licenses this file to You under the Apache License, Version 2.0
6 *  (the "License"); you may not use this file except in compliance with
7 *  the License.  You may obtain a copy of the License at
8 *
9 *     http://www.apache.org/licenses/LICENSE-2.0
10 *
11 *  Unless required by applicable law or agreed to in writing, software
12 *  distributed under the License is distributed on an "AS IS" BASIS,
13 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 *  See the License for the specific language governing permissions and
15 *  limitations under the License.
16 */
17
18package org.apache.harmony.luni.tests.java.io;
19
20import java.io.BufferedInputStream;
21import java.io.ByteArrayInputStream;
22import java.io.ByteArrayOutputStream;
23import java.io.Externalizable;
24import java.io.File;
25import java.io.FileInputStream;
26import java.io.FileNotFoundException;
27import java.io.FileOutputStream;
28import java.io.IOException;
29import java.io.InputStream;
30import java.io.InvalidObjectException;
31import java.io.NotActiveException;
32import java.io.ObjectInput;
33import java.io.ObjectInputStream;
34import java.io.ObjectInputValidation;
35import java.io.ObjectOutput;
36import java.io.ObjectOutputStream;
37import java.io.ObjectStreamClass;
38import java.io.ObjectStreamException;
39import java.io.OutputStream;
40import java.io.PipedInputStream;
41import java.io.PipedOutputStream;
42import java.io.Serializable;
43import java.io.SerializablePermission;
44import java.io.StreamCorruptedException;
45import java.lang.reflect.Proxy;
46import java.security.Permission;
47import java.util.Arrays;
48import java.util.HashMap;
49import java.util.Hashtable;
50import java.util.Vector;
51
52import junit.framework.TestCase;
53
54import org.apache.harmony.testframework.serialization.SerializationTest;
55import org.apache.harmony.testframework.serialization.SerializationTest.SerializableAssert;
56
57@SuppressWarnings("serial")
58public class ObjectInputStreamTest extends TestCase implements
59        Serializable {
60
61    ObjectInputStream ois;
62
63    ObjectOutputStream oos;
64
65    ByteArrayOutputStream bao;
66
67    public class SerializableTestHelper implements Serializable {
68
69        public String aField1;
70
71        public String aField2;
72
73        SerializableTestHelper() {
74            aField1 = null;
75            aField2 = null;
76        }
77
78        SerializableTestHelper(String s, String t) {
79            aField1 = s;
80            aField2 = t;
81        }
82
83        private void readObject(ObjectInputStream ois) throws Exception {
84            // note aField2 is not read
85            ObjectInputStream.GetField fields = ois.readFields();
86            aField1 = (String) fields.get("aField1", "Zap");
87        }
88
89        private void writeObject(ObjectOutputStream oos) throws IOException {
90            // note aField2 is not written
91            ObjectOutputStream.PutField fields = oos.putFields();
92            fields.put("aField1", aField1);
93            oos.writeFields();
94        }
95
96        public String getText1() {
97            return aField1;
98        }
99
100        public void setText1(String s) {
101            aField1 = s;
102        }
103
104        public String getText2() {
105            return aField2;
106        }
107
108        public void setText2(String s) {
109            aField2 = s;
110        }
111    }
112
113    public static class A1 implements Serializable {
114
115        private static final long serialVersionUID = 5942584913446079661L;
116
117        B1 b1 = new B1();
118
119        B1 b2 = b1;
120
121        Vector v = new Vector();
122    }
123
124    public static class B1 implements Serializable {
125
126        int i = 5;
127
128        Hashtable h = new Hashtable();
129    }
130
131    /**
132     * @tests java.io.ObjectInputStream#readObject()
133     */
134    public void test_readObjectMissingClasses() throws Exception {
135        SerializationTest.verifySelf(new A1(), new SerializableAssert() {
136            public void assertDeserialized(Serializable initial,
137                    Serializable deserialized) {
138                assertEquals(5, ((A1) deserialized).b1.i);
139            }
140        });
141    }
142
143    /**
144     * @tests java.io.ObjectInputStream#ObjectInputStream(java.io.InputStream)
145     */
146    public void test_ConstructorLjava_io_InputStream() throws IOException {
147        oos.writeDouble(Double.MAX_VALUE);
148        oos.close();
149        ois = new ObjectInputStream(new ByteArrayInputStream(bao.toByteArray()));
150        ois.close();
151        oos.close();
152
153        try {
154            ois = new ObjectInputStream(new ByteArrayInputStream(new byte[90]));
155            fail("StreamCorruptedException expected");
156        } catch (StreamCorruptedException e) {
157            // Expected
158        }
159    }
160
161    /**
162     * @tests {@link java.io.ObjectInputStream#resolveProxyClass(String[])}
163     */
164    public void test_resolveProxyClass() throws IOException,
165            ClassNotFoundException {
166        oos.writeBytes("HelloWorld");
167        oos.close();
168        ois = new ObjectInputStream(new ByteArrayInputStream(bao.toByteArray()));
169        MockObjectInputStream mockIn = new MockObjectInputStream(
170                new ByteArrayInputStream(bao.toByteArray()));
171        Class[] clazzs = { java.io.ObjectInputStream.class,
172                java.io.Reader.class };
173        for (int i = 0; i < clazzs.length; i++) {
174            Class clazz = clazzs[i];
175            Class[] interfaceNames = clazz.getInterfaces();
176            String[] interfaces = new String[interfaceNames.length];
177            int index = 0;
178            for (Class c : interfaceNames) {
179                interfaces[index] = c.getName();
180                index++;
181            }
182            Class<?> s = mockIn.resolveProxyClass(interfaces);
183
184            if (Proxy.isProxyClass(s)) {
185                Class[] implementedInterfaces = s.getInterfaces();
186                for (index = 0; index < implementedInterfaces.length; index++) {
187                    assertEquals(interfaceNames[index],
188                            implementedInterfaces[index]);
189                }
190            } else {
191                fail("Should return a proxy class that implements the interfaces named in a proxy class descriptor");
192            }
193        }
194        mockIn.close();
195    }
196
197    class MockObjectInputStream extends ObjectInputStream {
198
199        public MockObjectInputStream(InputStream input)
200                throws StreamCorruptedException, IOException {
201            super(input);
202        }
203
204        @Override
205        public Class<?> resolveProxyClass(String[] interfaceNames) throws IOException, ClassNotFoundException {
206            return super.resolveProxyClass(interfaceNames);
207        }
208
209    }
210
211    /**
212     * @tests java.io.ObjectInputStream#available()
213     */
214    public void test_available() throws IOException {
215        oos.writeBytes("HelloWorld");
216        oos.close();
217        ois = new ObjectInputStream(new ByteArrayInputStream(bao.toByteArray()));
218        assertEquals("Read incorrect bytes", 10, ois.available());
219        ois.close();
220    }
221
222    /**
223     * @tests java.io.ObjectInputStream#close()
224     */
225    public void test_close() throws IOException {
226        oos.writeBytes("HelloWorld");
227        oos.close();
228        ois = new ObjectInputStream(new ByteArrayInputStream(bao.toByteArray()));
229        ois.close();
230    }
231
232    /**
233     * @tests java.io.ObjectInputStream#defaultReadObject()
234     */
235    public void test_defaultReadObject() throws Exception {
236        // SM. This method may as well be private, as if called directly it
237        // throws an exception.
238        String s = "HelloWorld";
239        oos.writeObject(s);
240        oos.close();
241        ois = new ObjectInputStream(new ByteArrayInputStream(bao.toByteArray()));
242        try {
243            ois.defaultReadObject();
244            fail("NotActiveException expected");
245        } catch (NotActiveException e) {
246            // Desired behavior
247        } finally {
248            ois.close();
249        }
250    }
251
252    /**
253     * @tests java.io.ObjectInputStream#read()
254     */
255    public void test_read() throws IOException {
256        oos.write('T');
257        oos.close();
258        ois = new ObjectInputStream(new ByteArrayInputStream(bao.toByteArray()));
259        assertEquals("Read incorrect byte value", 'T', ois.read());
260        ois.close();
261    }
262
263    /**
264     * @tests java.io.ObjectInputStream#read(byte[], int, int)
265     */
266    public void test_read$BII() throws IOException {
267        byte[] buf = new byte[10];
268        oos.writeBytes("HelloWorld");
269        oos.close();
270        ois = new ObjectInputStream(new ByteArrayInputStream(bao.toByteArray()));
271        ois.read(buf, 0, 10);
272        ois.close();
273        assertEquals("Read incorrect bytes", "HelloWorld", new String(buf, 0,
274                10, "UTF-8"));
275    }
276
277    /**
278     * @tests java.io.ObjectInputStream#readBoolean()
279     */
280    public void test_readBoolean() throws IOException {
281        oos.writeBoolean(true);
282        oos.close();
283        ois = new ObjectInputStream(new ByteArrayInputStream(bao.toByteArray()));
284        assertTrue("Read incorrect boolean value", ois.readBoolean());
285        ois.close();
286    }
287
288    /**
289     * @tests java.io.ObjectInputStream#readByte()
290     */
291    public void test_readByte() throws IOException {
292        oos.writeByte(127);
293        oos.close();
294        ois = new ObjectInputStream(new ByteArrayInputStream(bao.toByteArray()));
295        assertEquals("Read incorrect byte value", 127, ois.readByte());
296        ois.close();
297    }
298
299    /**
300     * @tests java.io.ObjectInputStream#readChar()
301     */
302    public void test_readChar() throws IOException {
303        oos.writeChar('T');
304        oos.close();
305        ois = new ObjectInputStream(new ByteArrayInputStream(bao.toByteArray()));
306        assertEquals("Read incorrect char value", 'T', ois.readChar());
307        ois.close();
308    }
309
310    /**
311     * @tests java.io.ObjectInputStream#readDouble()
312     */
313    public void test_readDouble() throws IOException {
314        oos.writeDouble(Double.MAX_VALUE);
315        oos.close();
316        ois = new ObjectInputStream(new ByteArrayInputStream(bao.toByteArray()));
317        assertTrue("Read incorrect double value",
318                ois.readDouble() == Double.MAX_VALUE);
319        ois.close();
320    }
321
322    /**
323     * @tests java.io.ObjectInputStream#readFields()
324     */
325    public void test_readFields() throws Exception {
326
327        SerializableTestHelper sth;
328
329        /*
330         * "SerializableTestHelper" is an object created for these tests with
331         * two fields (Strings) and simple implementations of readObject and
332         * writeObject which simply read and write the first field but not the
333         * second
334         */
335
336        oos.writeObject(new SerializableTestHelper("Gabba", "Jabba"));
337        oos.flush();
338        ois = new ObjectInputStream(new ByteArrayInputStream(bao.toByteArray()));
339        sth = (SerializableTestHelper) (ois.readObject());
340        assertEquals("readFields / writeFields failed--first field not set",
341                "Gabba", sth.getText1());
342        assertNull(
343                "readFields / writeFields failed--second field should not have been set",
344                sth.getText2());
345    }
346
347    /**
348     * @tests java.io.ObjectInputStream#readFloat()
349     */
350    public void test_readFloat() throws IOException {
351        oos.writeFloat(Float.MAX_VALUE);
352        oos.close();
353        ois = new ObjectInputStream(new ByteArrayInputStream(bao.toByteArray()));
354        assertTrue("Read incorrect float value",
355                ois.readFloat() == Float.MAX_VALUE);
356        ois.close();
357    }
358
359    /**
360     * @tests java.io.ObjectInputStream#readFully(byte[])
361     */
362    public void test_readFully$B() throws IOException {
363        byte[] buf = new byte[10];
364        oos.writeBytes("HelloWorld");
365        oos.close();
366        ois = new ObjectInputStream(new ByteArrayInputStream(bao.toByteArray()));
367        ois.readFully(buf);
368        ois.close();
369        assertEquals("Read incorrect bytes", "HelloWorld", new String(buf, 0,
370                10, "UTF-8"));
371    }
372
373    /**
374     * @tests java.io.ObjectInputStream#readFully(byte[], int, int)
375     */
376    public void test_readFully$BII() throws IOException {
377        byte[] buf = new byte[10];
378        oos.writeBytes("HelloWorld");
379        oos.close();
380        ois = new ObjectInputStream(new ByteArrayInputStream(bao.toByteArray()));
381        ois.readFully(buf, 0, 10);
382        ois.close();
383        assertEquals("Read incorrect bytes", "HelloWorld", new String(buf, 0,
384                10, "UTF-8"));
385    }
386
387    /**
388     * @tests java.io.ObjectInputStream#readInt()
389     */
390    public void test_readInt() throws IOException {
391        oos.writeInt(Integer.MAX_VALUE);
392        oos.close();
393        ois = new ObjectInputStream(new ByteArrayInputStream(bao.toByteArray()));
394        assertTrue("Read incorrect int value",
395                ois.readInt() == Integer.MAX_VALUE);
396        ois.close();
397    }
398
399    /**
400     * @tests java.io.ObjectInputStream#readLine()
401     */
402    @SuppressWarnings("deprecation")
403    public void test_readLine() throws IOException {
404        oos.writeBytes("HelloWorld\nSecondLine");
405        oos.close();
406        ois = new ObjectInputStream(new ByteArrayInputStream(bao.toByteArray()));
407        ois.readLine();
408        assertEquals("Read incorrect string value", "SecondLine", ois
409                .readLine());
410        ois.close();
411    }
412
413    /**
414     * @tests java.io.ObjectInputStream#readLong()
415     */
416    public void test_readLong() throws IOException {
417        oos.writeLong(Long.MAX_VALUE);
418        oos.close();
419        ois = new ObjectInputStream(new ByteArrayInputStream(bao.toByteArray()));
420        assertTrue("Read incorrect long value",
421                ois.readLong() == Long.MAX_VALUE);
422        ois.close();
423    }
424
425    /**
426     * @tests java.io.ObjectInputStream#readObject()
427     */
428    public void test_readObject() throws Exception {
429        String s = "HelloWorld";
430        oos.writeObject(s);
431        oos.close();
432        ois = new ObjectInputStream(new ByteArrayInputStream(bao.toByteArray()));
433        assertEquals("Read incorrect Object value", s, ois.readObject());
434        ois.close();
435
436        // Regression for HARMONY-91
437        // dynamically create serialization byte array for the next hierarchy:
438        // - class A implements Serializable
439        // - class C extends A
440
441        byte[] cName = C.class.getName().getBytes("UTF-8");
442        byte[] aName = A.class.getName().getBytes("UTF-8");
443
444        ByteArrayOutputStream out = new ByteArrayOutputStream();
445
446        byte[] begStream = new byte[] { (byte) 0xac, (byte) 0xed, // STREAM_MAGIC
447                (byte) 0x00, (byte) 0x05, // STREAM_VERSION
448                (byte) 0x73, // TC_OBJECT
449                (byte) 0x72, // TC_CLASSDESC
450                (byte) 0x00, // only first byte for C class name length
451        };
452
453        out.write(begStream, 0, begStream.length);
454        out.write(cName.length); // second byte for C class name length
455        out.write(cName, 0, cName.length); // C class name
456
457        byte[] midStream = new byte[] { (byte) 0x00, (byte) 0x00, (byte) 0x00,
458                (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00,
459                (byte) 0x21, // serialVersionUID = 33L
460                (byte) 0x02, // flags
461                (byte) 0x00, (byte) 0x00, // fields : none
462                (byte) 0x78, // TC_ENDBLOCKDATA
463                (byte) 0x72, // Super class for C: TC_CLASSDESC for A class
464                (byte) 0x00, // only first byte for A class name length
465        };
466
467        out.write(midStream, 0, midStream.length);
468        out.write(aName.length); // second byte for A class name length
469        out.write(aName, 0, aName.length); // A class name
470
471        byte[] endStream = new byte[] { (byte) 0x00, (byte) 0x00, (byte) 0x00,
472                (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00,
473                (byte) 0x0b, // serialVersionUID = 11L
474                (byte) 0x02, // flags
475                (byte) 0x00, (byte) 0x01, // fields
476
477                (byte) 0x4c, // field description: type L (object)
478                (byte) 0x00, (byte) 0x04, // length
479                // field = 'name'
480                (byte) 0x6e, (byte) 0x61, (byte) 0x6d, (byte) 0x65,
481
482                (byte) 0x74, // className1: TC_STRING
483                (byte) 0x00, (byte) 0x12, // length
484                //
485                (byte) 0x4c, (byte) 0x6a, (byte) 0x61, (byte) 0x76,
486                (byte) 0x61, (byte) 0x2f, (byte) 0x6c, (byte) 0x61,
487                (byte) 0x6e, (byte) 0x67, (byte) 0x2f, (byte) 0x53,
488                (byte) 0x74, (byte) 0x72, (byte) 0x69, (byte) 0x6e,
489                (byte) 0x67, (byte) 0x3b,
490
491                (byte) 0x78, // TC_ENDBLOCKDATA
492                (byte) 0x70, // NULL super class for A class
493
494                // classdata
495                (byte) 0x74, // TC_STRING
496                (byte) 0x00, (byte) 0x04, // length
497                (byte) 0x6e, (byte) 0x61, (byte) 0x6d, (byte) 0x65, // value
498        };
499
500        out.write(endStream, 0, endStream.length);
501        out.flush();
502
503        // read created serial. form
504        ObjectInputStream ois = new ObjectInputStream(new ByteArrayInputStream(
505                out.toByteArray()));
506        Object o = ois.readObject();
507        assertEquals(C.class, o.getClass());
508
509		// Regression for HARMONY-846
510        assertNull(new ObjectInputStream() {}.readObject());
511    }
512
513    /**
514     * @tests java.io.ObjectInputStream#readObjectOverride()
515     */
516    public void test_readObjectOverride() throws Exception {
517        // Regression for HARMONY-846
518        assertNull(new ObjectInputStream() {
519
520            @Override
521            public Object readObjectOverride() throws IOException,
522                    ClassNotFoundException {
523                return super.readObjectOverride();
524            }
525
526        }.readObjectOverride());
527    }
528
529    public static class A implements Serializable {
530
531        private static final long serialVersionUID = 11L;
532
533        public String name = "name";
534    }
535
536    public static class B extends A {}
537
538    public static class C extends B {
539
540        private static final long serialVersionUID = 33L;
541    }
542
543    /**
544     * @tests java.io.ObjectInputStream#readObject()
545     */
546    public void test_readObjectCorrupt() throws IOException, ClassNotFoundException {
547        byte[] bytes = { 00, 00, 00, 0x64, 0x43, 0x48, (byte) 0xFD, 0x71, 00,
548                00, 0x0B, (byte) 0xB8, 0x4D, 0x65 };
549        ByteArrayInputStream bin = new ByteArrayInputStream(bytes);
550        try {
551            ObjectInputStream in = new ObjectInputStream(bin);
552            in.readObject();
553            fail("Unexpected read of corrupted stream");
554        } catch (StreamCorruptedException e) {
555            // Expected
556        }
557    }
558
559    /**
560     * @tests java.io.ObjectInputStream#readShort()
561     */
562    public void test_readShort() throws IOException {
563        oos.writeShort(Short.MAX_VALUE);
564        oos.close();
565        ois = new ObjectInputStream(new ByteArrayInputStream(bao.toByteArray()));
566        assertTrue("Read incorrect short value",
567                ois.readShort() == Short.MAX_VALUE);
568        ois.close();
569    }
570
571    /**
572     * @tests java.io.ObjectInputStream#readUnsignedByte()
573     */
574    public void test_readUnsignedByte() throws IOException {
575        oos.writeByte(-1);
576        oos.close();
577        ois = new ObjectInputStream(new ByteArrayInputStream(bao.toByteArray()));
578        assertEquals("Read incorrect unsignedByte value", 255, ois
579                .readUnsignedByte());
580        ois.close();
581    }
582
583    /**
584     * @tests java.io.ObjectInputStream#readUnsignedShort()
585     */
586    public void test_readUnsignedShort() throws IOException {
587        oos.writeShort(-1);
588        oos.close();
589        ois = new ObjectInputStream(new ByteArrayInputStream(bao.toByteArray()));
590        assertEquals("Read incorrect unsignedShort value", 65535, ois
591                .readUnsignedShort());
592        ois.close();
593    }
594
595    /**
596     * @tests java.io.ObjectInputStream#readUTF()
597     */
598    public void test_readUTF() throws IOException {
599        oos.writeUTF("HelloWorld");
600        oos.close();
601        ois = new ObjectInputStream(new ByteArrayInputStream(bao.toByteArray()));
602        assertEquals("Read incorrect utf value", "HelloWorld", ois.readUTF());
603        ois.close();
604    }
605
606    /**
607     * @tests java.io.ObjectInputStream#skipBytes(int)
608     */
609    public void test_skipBytesI() throws IOException {
610        byte[] buf = new byte[10];
611        oos.writeBytes("HelloWorld");
612        oos.close();
613        ois = new ObjectInputStream(new ByteArrayInputStream(bao.toByteArray()));
614        ois.skipBytes(5);
615        ois.read(buf, 0, 5);
616        ois.close();
617        assertEquals("Skipped incorrect bytes", "World", new String(buf, 0, 5, "UTF-8"));
618
619        // Regression for HARMONY-844
620        try {
621            new ObjectInputStream() {}.skipBytes(0);
622            fail("NullPointerException expected");
623        } catch (NullPointerException e) {}
624    }
625
626    // Regression Test for JIRA 2192
627	public void test_readObject_withPrimitiveClass() throws Exception {
628		File file = new File("test.ser");
629		file.deleteOnExit();
630		Test test = new Test();
631		ObjectOutputStream out = new ObjectOutputStream(new FileOutputStream(
632				file));
633		out.writeObject(test);
634		out.close();
635
636		ObjectInputStream in = new ObjectInputStream(new FileInputStream(file));
637		Test another = (Test) in.readObject();
638		in.close();
639		assertEquals(test, another);
640	}
641
642    //Regression Test for JIRA-2249
643    public static class ObjectOutputStreamWithWriteDesc extends
644            ObjectOutputStream {
645        public ObjectOutputStreamWithWriteDesc(OutputStream os)
646                throws IOException {
647            super(os);
648        }
649
650        @Override
651        public void writeClassDescriptor(ObjectStreamClass desc)
652                throws IOException {
653        }
654    }
655
656    public static class ObjectIutputStreamWithReadDesc extends
657            ObjectInputStream {
658        private Class returnClass;
659
660        public ObjectIutputStreamWithReadDesc(InputStream is, Class returnClass)
661                throws IOException {
662            super(is);
663            this.returnClass = returnClass;
664        }
665
666        @Override
667        public ObjectStreamClass readClassDescriptor() throws IOException,
668                ClassNotFoundException {
669            return ObjectStreamClass.lookup(returnClass);
670
671        }
672    }
673
674    static class TestClassForSerialization implements Serializable {
675		private static final long serialVersionUID = 1L;
676	}
677
678    public void test_ClassDescriptor() throws IOException,
679			ClassNotFoundException {
680
681		ByteArrayOutputStream baos = new ByteArrayOutputStream();
682		ObjectOutputStreamWithWriteDesc oos = new ObjectOutputStreamWithWriteDesc(
683				baos);
684		oos.writeObject(String.class);
685		oos.close();
686		Class cls = TestClassForSerialization.class;
687		ByteArrayInputStream bais = new ByteArrayInputStream(baos.toByteArray());
688		ObjectIutputStreamWithReadDesc ois = new ObjectIutputStreamWithReadDesc(
689				bais, cls);
690		Object obj = ois.readObject();
691		ois.close();
692		assertEquals(cls, obj);
693	}
694
695	// Regression Test for JIRA-2340
696    public static class ObjectOutputStreamWithWriteDesc1 extends
697			ObjectOutputStream {
698		public ObjectOutputStreamWithWriteDesc1(OutputStream os)
699				throws IOException {
700			super(os);
701		}
702
703		@Override
704        public void writeClassDescriptor(ObjectStreamClass desc)
705				throws IOException {
706			super.writeClassDescriptor(desc);
707		}
708	}
709
710	public static class ObjectIutputStreamWithReadDesc1 extends
711			ObjectInputStream {
712
713		public ObjectIutputStreamWithReadDesc1(InputStream is)
714				throws IOException {
715			super(is);
716		}
717
718		@Override
719        public ObjectStreamClass readClassDescriptor() throws IOException,
720				ClassNotFoundException {
721			return super.readClassDescriptor();
722		}
723	}
724
725    // Regression test for Harmony-1921
726    public static class ObjectInputStreamWithResolve extends ObjectInputStream {
727        public ObjectInputStreamWithResolve(InputStream in) throws IOException {
728            super(in);
729        }
730
731        @Override
732        @SuppressWarnings("unchecked")
733        protected Class resolveClass(ObjectStreamClass desc)
734                throws IOException, ClassNotFoundException {
735            if (desc.getName().equals(
736                    "org.apache.harmony.luni.tests.pkg1.TestClass")) {
737                return org.apache.harmony.luni.tests.pkg2.TestClass.class;
738            }
739            return super.resolveClass(desc);
740        }
741    }
742
743    public void test_resolveClass() throws Exception {
744        org.apache.harmony.luni.tests.pkg1.TestClass to1 = new org.apache.harmony.luni.tests.pkg1.TestClass();
745        to1.i = 555;
746        ByteArrayOutputStream baos = new ByteArrayOutputStream();
747        ObjectOutputStream oos = new ObjectOutputStream(baos);
748        oos.writeObject(to1);
749        oos.flush();
750        byte[] bytes = baos.toByteArray();
751        ByteArrayInputStream bais = new ByteArrayInputStream(bytes);
752        ObjectInputStream ois = new ObjectInputStreamWithResolve(bais);
753        org.apache.harmony.luni.tests.pkg2.TestClass to2 = (org.apache.harmony.luni.tests.pkg2.TestClass) ois
754                .readObject();
755
756        if (to2.i != to1.i) {
757            fail("Wrong object read. Expected val: " + to1.i + ", got: "
758                    + to2.i);
759        }
760    }
761
762    static class ObjectInputStreamWithResolveObject extends ObjectInputStream {
763
764        public static Integer intObj = Integer.valueOf(1000);
765
766        public ObjectInputStreamWithResolveObject(InputStream in) throws IOException {
767            super(in);
768            enableResolveObject(true);
769        }
770
771        @Override
772        protected Object resolveObject(Object obj) throws IOException {
773            if(obj instanceof Integer){
774                obj = intObj;
775            }
776            return super.resolveObject(obj);
777        }
778    }
779
780    /**
781     * @tests java.io.ObjectInputStream#resolveObject(Object)
782     */
783    public void test_resolveObjectLjava_lang_Object() throws Exception {
784        // Write an Integer object into memory
785        Integer original = new Integer(10);
786        ByteArrayOutputStream baos = new ByteArrayOutputStream();
787        ObjectOutputStream oos = new ObjectOutputStream(baos);
788        oos.writeObject(original);
789        oos.flush();
790        oos.close();
791
792        // Read the object from memory
793        byte[] bytes = baos.toByteArray();
794        ByteArrayInputStream bais = new ByteArrayInputStream(bytes);
795        ObjectInputStreamWithResolveObject ois =
796            new ObjectInputStreamWithResolveObject(bais);
797        Integer actual = (Integer) ois.readObject();
798        ois.close();
799
800        // object should be resolved from 10 to 1000
801        assertEquals(ObjectInputStreamWithResolveObject.intObj, actual);
802    }
803
804	public void test_readClassDescriptor() throws IOException,
805			ClassNotFoundException {
806
807		ByteArrayOutputStream baos = new ByteArrayOutputStream();
808		ObjectOutputStreamWithWriteDesc1 oos = new ObjectOutputStreamWithWriteDesc1(
809				baos);
810		ObjectStreamClass desc = ObjectStreamClass
811		.lookup(TestClassForSerialization.class);
812		oos.writeClassDescriptor(desc);
813		oos.close();
814
815        byte[] bytes = baos.toByteArray();
816		ByteArrayInputStream bais = new ByteArrayInputStream(bytes);
817		ObjectIutputStreamWithReadDesc1 ois = new ObjectIutputStreamWithReadDesc1(
818				bais);
819		Object obj = ois.readClassDescriptor();
820		ois.close();
821		assertEquals(desc.getClass(), obj.getClass());
822
823        //eof
824        bais = new ByteArrayInputStream(bytes);
825        ExceptionalBufferedInputStream bis = new ExceptionalBufferedInputStream(
826                bais);
827        ois = new ObjectIutputStreamWithReadDesc1(bis);
828
829        bis.setEOF(true);
830
831        try {
832            obj = ois.readClassDescriptor();
833        } catch (IOException e) {
834            //e.printStackTrace();
835        } finally {
836            ois.close();
837        }
838
839        //throw exception
840        bais = new ByteArrayInputStream(bytes);
841        bis = new ExceptionalBufferedInputStream(bais);
842        ois = new ObjectIutputStreamWithReadDesc1(bis);
843
844        bis.setException(new IOException());
845
846        try {
847            obj = ois.readClassDescriptor();
848        } catch (IOException e) {
849            //e.printStackTrace();
850        } finally {
851            ois.close();
852        }
853
854        //corrupt
855        bais = new ByteArrayInputStream(bytes);
856        bis = new ExceptionalBufferedInputStream(bais);
857        ois = new ObjectIutputStreamWithReadDesc1(bis);
858
859        bis.setCorrupt(true);
860
861        try {
862            obj = ois.readClassDescriptor();
863        } catch (IOException e) {
864            //e.printStackTrace();
865        } finally {
866            ois.close();
867        }
868	}
869
870    static class ExceptionalBufferedInputStream extends BufferedInputStream {
871        private boolean eof = false;
872        private IOException exception = null;
873        private boolean corrupt = false;
874
875        public ExceptionalBufferedInputStream(InputStream in) {
876            super(in);
877        }
878
879        @Override
880        public int read() throws IOException {
881            if (exception != null) {
882                throw exception;
883            }
884
885            if (eof) {
886                return -1;
887            }
888
889            if (corrupt) {
890                return 0;
891            }
892            return super.read();
893        }
894
895        public void setEOF(boolean eof) {
896            this.eof = eof;
897        }
898
899        public void setException(IOException exception) {
900            this.exception = exception;
901        }
902
903        public void setCorrupt(boolean corrupt) {
904            this.corrupt = corrupt;
905        }
906    }
907
908    public static class ObjectIutputStreamWithReadDesc2 extends
909            ObjectInputStream {
910        private Class returnClass;
911
912        public ObjectIutputStreamWithReadDesc2(InputStream is, Class returnClass)
913                throws IOException {
914            super(is);
915            this.returnClass = returnClass;
916        }
917
918        @Override
919        public ObjectStreamClass readClassDescriptor() throws IOException,
920                ClassNotFoundException {
921            ObjectStreamClass osc = super.readClassDescriptor();
922
923            if (osc.getName().equals(returnClass.getName())) {
924                return ObjectStreamClass.lookup(returnClass);
925            }
926            return osc;
927        }
928    }
929
930    /*
931     * Testing classDescriptor replacement with the value generated by
932     * ObjectStreamClass.lookup() method.
933     * Regression test for HARMONY-4638
934     */
935    public void test_readClassDescriptor_1() throws IOException, ClassNotFoundException {
936        A a = new A();
937        a.name = "It's a test";
938        PipedOutputStream pout = new PipedOutputStream();
939        PipedInputStream pin = new PipedInputStream(pout);
940        ObjectOutputStream out = new ObjectOutputStream(pout);
941        ObjectInputStream in = new ObjectIutputStreamWithReadDesc2(pin, A.class);
942
943        // test single object
944        out.writeObject(a);
945        A a1 = (A) in.readObject();
946        assertEquals("Single case: incorrectly read the field of A", a.name, a1.name);
947
948        // test cyclic reference
949        HashMap m = new HashMap();
950        a = new A();
951        a.name = "It's a test 0";
952        a1 = new A();
953        a1.name = "It's a test 1";
954        m.put("0", a);
955        m.put("1", a1);
956        out.writeObject(m);
957        HashMap m1 = (HashMap) in.readObject();
958        assertEquals("Incorrectly read the field of A", a.name, ((A) m1.get("0")).name);
959        assertEquals("Incorrectly read the field of A1", a1.name, ((A) m1.get("1")).name);
960    }
961
962    public void test_registerValidation() throws Exception {
963        // Regression Test for Harmony-2402
964        ByteArrayOutputStream baos = new ByteArrayOutputStream();
965        new ObjectOutputStream(baos);
966        ObjectInputStream ois = new ObjectInputStream(
967                new ByteArrayInputStream(baos.toByteArray()));
968
969        try {
970            ois.registerValidation(null, 256);
971            fail("NotActiveException should be thrown");
972        } catch (NotActiveException nae) {
973            // expected
974        }
975
976        // Regression Test for Harmony-3916
977        baos = new ByteArrayOutputStream();
978        ObjectOutputStream oos = new ObjectOutputStream(baos);
979        oos.writeObject(new RegisterValidationClass());
980        oos.close();
981        ByteArrayInputStream bais = new ByteArrayInputStream(baos.toByteArray());
982        ObjectInputStream fis = new ObjectInputStream(bais);
983        // should not throw NotActiveException
984        fis.readObject();
985    }
986
987    private static class RegisterValidationClass implements Serializable {
988        @SuppressWarnings("unused")
989        private A a = new A();
990        private void readObject(ObjectInputStream stream) throws IOException, ClassNotFoundException {
991            stream.defaultReadObject();
992            stream.registerValidation(new MockObjectInputValidation(), 0);
993        }
994    }
995
996    private static class MockObjectInputValidation implements ObjectInputValidation {
997        public void validateObject() throws InvalidObjectException {
998
999        }
1000    }
1001
1002    //Regression Test for HARMONY-3726
1003    public void test_readObject_array() throws Exception {
1004
1005        final String resourcePrefix = ObjectInputStreamTest.class.getPackage().getName().replace('.', '/');
1006
1007//        ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("/temp/test_array_strings.ser"));
1008//        TestArray ta = new TestArray(new String[] { "AAA", "BBB" });
1009//        oos.writeObject(ta);
1010//        oos.close();
1011//        oos = new ObjectOutputStream(new FileOutputStream("/temp/test_array_integers.ser"));
1012//        ta = new TestArray(new Integer[] { 10, 20 });
1013//        oos.writeObject(ta);
1014//        oos.close();
1015
1016        ObjectInputStream oin = new ObjectInputStream(this.getClass().getClassLoader().getResourceAsStream(
1017                "serialization/" + resourcePrefix + "/test_array_strings.ser"));
1018        TestArray testArray = (TestArray) oin.readObject();
1019        String[] strings = new String[] { "AAA", "BBB" };
1020        assertTrue(java.util.Arrays.equals(strings, testArray.array));
1021
1022        oin = new ObjectInputStream(this.getClass().getClassLoader().getResourceAsStream(
1023                "serialization/" + resourcePrefix + "/test_array_integers.ser"));
1024        testArray = (TestArray) oin.readObject();
1025        Integer[] integers = new Integer[] { 10, 20 };
1026        assertTrue(java.util.Arrays.equals(integers, testArray.array));
1027    }
1028
1029    public static class TestExtObject implements Externalizable {
1030        public void writeExternal(ObjectOutput out) throws IOException {
1031            out.writeInt(10);
1032        }
1033
1034        public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException {
1035            in.readInt();
1036        }
1037    }
1038
1039    static class TestObjectOutputStream extends ObjectOutputStream {
1040        private ObjectStreamClass[] objs;
1041        private int pos = 0;
1042
1043        public TestObjectOutputStream(OutputStream out, ObjectStreamClass[] objs) throws IOException {
1044            super(out);
1045            this.objs = objs;
1046        }
1047
1048        @Override
1049        protected void writeClassDescriptor(ObjectStreamClass osc) throws IOException {
1050            objs[pos++] = osc;        }
1051    }
1052
1053    static class TestObjectInputStream extends ObjectInputStream {
1054        private ObjectStreamClass[] objs;
1055        private int pos = 0;
1056
1057        public TestObjectInputStream(InputStream in, ObjectStreamClass[] objs) throws IOException {
1058            super(in);
1059            this.objs = objs;
1060        }
1061
1062        @Override
1063        protected ObjectStreamClass readClassDescriptor() throws IOException, ClassNotFoundException {
1064            return objs[pos++];
1065        }
1066    }
1067
1068    // Regression test for HARMONY-4996
1069    public void test_readObject_replacedClassDescriptor() throws Exception {
1070        ObjectStreamClass[] objs = new ObjectStreamClass[1000];
1071        PipedOutputStream pout = new PipedOutputStream();
1072        PipedInputStream pin = new PipedInputStream(pout);
1073        ObjectOutputStream oout = new TestObjectOutputStream(pout, objs);
1074        oout.writeObject(new TestExtObject());
1075        oout.writeObject("test");
1076        oout.close();
1077        ObjectInputStream oin = new TestObjectInputStream(pin, objs);
1078        oin.readObject();
1079        oin.readObject();
1080    }
1081
1082    public void test_readObject_replacedClassField() throws Exception {
1083        ByteArrayOutputStream out = new ByteArrayOutputStream();
1084        ObjectOutputStream oos = new ObjectOutputStream(out);
1085        FieldReplacementTestClass obj = new FieldReplacementTestClass(1234);
1086        oos.writeObject(obj);
1087        out.flush();
1088        out.close();
1089
1090        ByteArrayInputStream in = new ByteArrayInputStream(out.toByteArray());
1091        ObjectInputStream ois = new ObjectInputStream(in);
1092
1093        try {
1094            FieldReplacementTestClass result =
1095                (FieldReplacementTestClass)ois.readObject();
1096            fail("should throw ClassCastException");
1097        } catch (ClassCastException e) {
1098            // expected
1099        }
1100        ois.close();
1101    }
1102
1103    /**
1104     * Sets up the fixture, for example, open a network connection. This method
1105     * is called before a test is executed.
1106     */
1107    @Override
1108    protected void setUp() throws Exception {
1109        super.setUp();
1110        oos = new ObjectOutputStream(bao = new ByteArrayOutputStream());
1111    }
1112
1113    public static class FieldReplacementTestClass implements Serializable {
1114        private FieldClass c;
1115        public FieldReplacementTestClass(int i) {
1116            super();
1117            c = new FieldClass(i);
1118        }
1119    }
1120    public static class FieldClass implements Serializable {
1121        private int i;
1122        public FieldClass(int i) {
1123            super();
1124            this.i = i;
1125        }
1126        protected Object writeReplace() throws ObjectStreamException {
1127            return new ReplacementFieldClass(i);
1128        }
1129    }
1130    public static class ReplacementFieldClass implements Serializable {
1131        private int i;
1132        public ReplacementFieldClass(int i) {
1133            super();
1134            this.i = i;
1135        }
1136    }
1137
1138}
1139
1140class TestArray implements Serializable
1141{
1142    private static final long serialVersionUID = 1L;
1143
1144    public Object[] array;
1145
1146    public TestArray(Object[] array) {
1147        this.array = array;
1148    }
1149
1150}
1151
1152class Test implements Serializable {
1153	private static final long serialVersionUID = 1L;
1154
1155	Class classes[] = new Class[] { byte.class, short.class, int.class,
1156			long.class, boolean.class, char.class, float.class,
1157                        double.class, void.class };
1158
1159	@Override
1160    public boolean equals(Object o) {
1161		if (!(o instanceof Test)) {
1162			return false;
1163		}
1164		return Arrays.equals(classes, ((Test) o).classes);
1165	}
1166}
1167