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