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.ByteArrayInputStream;
21import java.io.ByteArrayOutputStream;
22import java.io.IOException;
23import java.io.InputStream;
24import java.io.InvalidClassException;
25import java.io.ObjectInputStream;
26import java.io.ObjectOutputStream;
27import java.io.ObjectStreamClass;
28import java.io.ObjectStreamException;
29import java.io.OptionalDataException;
30import java.io.Serializable;
31import java.io.StreamCorruptedException;
32import java.util.ArrayList;
33
34import junit.framework.TestCase;
35
36import org.apache.harmony.testframework.serialization.SerializationTest;
37
38import tests.support.Support_ASimpleInputStream;
39import dalvik.annotation.TestLevel;
40import dalvik.annotation.TestTargetClass;
41import dalvik.annotation.TestTargetNew;
42
43@TestTargetClass(ObjectInputStream.class)
44public class ObjectInputStreamTest extends TestCase {
45
46    ObjectInputStream ois;
47
48    ObjectOutputStream oos;
49
50    ByteArrayOutputStream bao;
51
52    private final String testString = "Lorem ipsum...";
53
54    protected void setUp() throws Exception {
55        super.setUp();
56        oos = new ObjectOutputStream(bao = new ByteArrayOutputStream());
57    }
58
59    @TestTargetNew(
60        level = TestLevel.PARTIAL_COMPLETE,
61        notes = "Checks ObjectStreamException and OptionalDataException.",
62        method = "readUnshared",
63        args = {}
64    )
65    public void test_readUnshared_1() throws IOException, ClassNotFoundException {
66        oos.writeObject(testString);
67        oos.writeObject(testString);
68        oos.writeInt(42);
69        oos.close();
70
71        ois = new ObjectInputStream(new ByteArrayInputStream(bao.toByteArray()));
72        try {
73            ois.readUnshared();
74            ois.readObject();
75            fail("Test 1: ObjectStreamException expected.");
76        } catch (ObjectStreamException e) {
77            // Expected.
78        }
79
80        try {
81            ois.readUnshared();
82            fail("Test 2: OptionalDataException expected.");
83        } catch (OptionalDataException e) {
84            // Expected.
85        }
86        ois.close();
87    }
88
89    /**
90     * @tests java.io.ObjectInputStream#readUnshared()
91     */
92    @TestTargetNew(
93        level = TestLevel.PARTIAL_COMPLETE,
94        notes = "Checks StreamCorruptedException.",
95        method = "readUnshared",
96        args = {}
97    )
98    public void test_readUnshared_2() throws IOException, ClassNotFoundException {
99        oos.close();
100        bao.write(testString.getBytes());
101
102        ois = new ObjectInputStream(new ByteArrayInputStream(bao.toByteArray()));
103        try {
104            ois.readUnshared();
105            fail("Test 1: StreamCorruptedException expected.");
106        } catch (StreamCorruptedException e) {
107            // Expected.
108        }
109        ois.close();
110    }
111
112    /**
113     * @tests java.io.ObjectInputStream#readUnshared()
114     */
115    @TestTargetNew(
116        level = TestLevel.PARTIAL_COMPLETE,
117        notes = "Checks IOException.",
118        method = "readUnshared",
119        args = {}
120    )
121    public void test_readUnshared_3() throws IOException, ClassNotFoundException {
122        bao.write(testString.getBytes());
123        oos.close();
124
125        Support_ASimpleInputStream sis = new Support_ASimpleInputStream(bao.toByteArray());
126        ois = new ObjectInputStream(sis);
127        sis.throwExceptionOnNextUse = true;
128        try {
129            ois.readUnshared();
130            fail("Test 1: IOException expected.");
131        } catch (IOException e) {
132            // Expected.
133        }
134        sis.throwExceptionOnNextUse = false;
135        ois.close();
136    }
137
138    /**
139     * Micro-scenario of de/serialization of an object with non-serializable superclass.
140     * The super-constructor only should be invoked on the deserialized instance.
141     */
142    @TestTargetNew(
143        level = TestLevel.PARTIAL_COMPLETE,
144        method = "readObject",
145        args = {}
146    )
147    public void test_readObject_Hierarchy() throws Exception {
148        ByteArrayOutputStream baos = new ByteArrayOutputStream();
149
150        ObjectOutputStream oos = new ObjectOutputStream(baos);
151        oos.writeObject(new B());
152        oos.close();
153
154        ObjectInputStream ois = new ObjectInputStream(new ByteArrayInputStream(baos.toByteArray()));
155        B b = (B) ois.readObject();
156        ois.close();
157
158        assertTrue("should construct super", A.list.contains(b));
159        assertFalse("should not construct self", B.list.contains(b));
160        assertEquals("super field A.s", A.DEFAULT, ((A)b).s);
161        assertNull("transient field B.s", b.s);
162    }
163
164    /**
165     * @tests {@link java.io.ObjectInputStream#readNewLongString()}
166     */
167    @TestTargetNew(
168        level = TestLevel.COMPLETE,
169        notes = "Verifies serialization.",
170        method = "!SerializationSelf",
171        args = {}
172    )
173    public void test_readNewLongString() throws Exception {
174        LongString longString = new LongString();
175        SerializationTest.verifySelf(longString);
176    }
177
178    private static class LongString implements Serializable{
179        private static final long serialVersionUID = 1L;
180        String lString;
181
182        public LongString() {
183            StringBuilder builder = new StringBuilder();
184            // construct a string whose length > 64K
185            for (int i = 0; i < 65636; i++) {
186                builder.append('1');
187            }
188            lString = builder.toString();
189        }
190
191        @Override
192        public boolean equals(Object o) {
193            if (o == this) {
194                return true;
195            }
196            if (o instanceof LongString) {
197                LongString l = (LongString) o;
198                return l.lString.equals(l.lString);
199            }
200            return true;
201        }
202
203        @Override
204        public int hashCode() {
205            return lString.hashCode();
206        }
207    }
208
209    static class A {
210        static final ArrayList<A> list = new ArrayList<A>();
211        String s;
212        public static final String DEFAULT = "aaa";
213        public A() {
214            s = DEFAULT;
215            list.add(this);
216        }
217    }
218
219    static class B extends A implements Serializable {
220        private static final long serialVersionUID = 1L;
221        static final ArrayList<A> list = new ArrayList<A>();
222        transient String s;
223        public B() {
224            s = "bbb";
225            list.add(this);
226        }
227    }
228
229    class OIS extends ObjectInputStream {
230
231        OIS () throws IOException {
232            super();
233         }
234
235        void test() throws ClassNotFoundException,IOException {
236            readClassDescriptor();
237        }
238
239    }
240
241    @TestTargetNew(
242        level = TestLevel.PARTIAL_COMPLETE,
243        method = "readClassDescriptor",
244        args = {}
245    )
246    public void test_readClassDescriptor() throws ClassNotFoundException, IOException {
247        try {
248            new OIS().test();
249            fail("Test 1: NullPointerException expected.");
250        } catch (NullPointerException e) {
251            // Expected.
252        }
253    }
254
255    static class TestObjectInputStream extends ObjectInputStream {
256        public TestObjectInputStream(InputStream in) throws IOException {
257            super(in);
258        }
259
260        protected Class<?> resolveClass(ObjectStreamClass desc)
261                throws IOException, ClassNotFoundException {
262            if (desc.getName().endsWith("ObjectInputStreamTest$TestClass1")) {
263                return TestClass2.class;
264            }
265            return super.resolveClass(desc);
266        }
267    }
268
269    static class TestClass1 implements Serializable {
270        private static final long serialVersionUID = 11111L;
271        int i = 0;
272    }
273
274    static class TestClass2 implements Serializable {
275        private static final long serialVersionUID = 11111L;
276        int i = 0;
277    }
278    @TestTargetNew(
279        level = TestLevel.PARTIAL_COMPLETE,
280        notes = "Checks InvalidClassException.",
281        method = "resolveClass",
282        args = {java.io.ObjectStreamClass.class}
283    )
284    public void test_resolveClass_invalidClassName()
285            throws Exception {
286        // Regression test for HARMONY-1920
287        TestClass1 to1 = new TestClass1();
288        ByteArrayOutputStream baos = new ByteArrayOutputStream();
289        ObjectOutputStream oos = new ObjectOutputStream(baos);
290        ByteArrayInputStream bais;
291        ObjectInputStream ois;
292
293        to1.i = 555;
294        oos.writeObject(to1);
295        oos.flush();
296        byte[] bytes = baos.toByteArray();
297        bais = new ByteArrayInputStream(bytes);
298        ois = new TestObjectInputStream(bais);
299
300        try {
301            ois.readObject();
302            fail("Test 1: InvalidClassException expected.");
303        } catch (InvalidClassException ice) {
304            // Expected.
305        }
306    }
307}
308
309
310