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.NotActiveException;
25import java.io.ObjectInputStream;
26import java.io.ObjectOutputStream;
27import java.io.ObjectStreamClass;
28import java.io.ObjectStreamField;
29import java.io.OutputStream;
30import java.io.Serializable;
31import java.io.StreamCorruptedException;
32import java.util.Date;
33
34public class ObjectStreamFieldTest extends junit.framework.TestCase {
35
36    static class DummyClass implements Serializable {
37        private static final long serialVersionUID = 999999999999998L;
38
39        long bam = 999L;
40
41        int ham = 9999;
42
43        int sam = 8888;
44
45        Object hola = new Object();
46
47        public static long getUID() {
48            return serialVersionUID;
49        }
50    }
51
52    ObjectStreamClass osc;
53
54    ObjectStreamField hamField;
55
56    ObjectStreamField samField;
57
58    ObjectStreamField bamField;
59
60    ObjectStreamField holaField;
61
62    /**
63     * @tests java.io.ObjectStreamField#ObjectStreamField(java.lang.String,
64     *        java.lang.Class)
65     */
66    public void test_ConstructorLjava_lang_StringLjava_lang_Class() {
67        assertTrue("Used to test", true);
68    }
69
70    public void test_equalsLjava_lang_Object() {
71        // Regression test for HARMONY-4273
72        assertTrue(samField.equals(samField));
73        assertFalse(samField.equals(hamField));
74        assertFalse(samField.equals("fish"));
75        assertFalse(samField.equals(null));
76    }
77
78    /**
79     * @tests java.io.ObjectStreamField#compareTo(java.lang.Object)
80     */
81    public void test_compareToLjava_lang_Object() {
82        assertTrue("Object compared to int did not return > 0", holaField
83                .compareTo(hamField) > 0);
84        assertEquals("Int compared to itself did not return 0", 0, hamField
85                .compareTo(hamField));
86        assertTrue("(Int)ham compared to (Int)sam did not return < 0", hamField
87                .compareTo(samField) < 0);
88    }
89
90    /**
91     * @tests java.io.ObjectStreamField#getName()
92     */
93    public void test_getName() {
94        assertEquals("Field did not return correct name", "hola", holaField
95                .getName());
96    }
97
98    /**
99     * @tests java.io.ObjectStreamField#getOffset()
100     */
101    public void test_getOffset() {
102        ObjectStreamField[] osfArray;
103        osfArray = osc.getFields();
104        assertTrue("getOffset did not return reasonable values", osfArray[0]
105                .getOffset() != osfArray[1].getOffset());
106        assertEquals("getOffset for osfArray[0].getOffset() did not return 0",
107                0, osfArray[0].getOffset());
108        assertEquals("osfArray[1].getOffset() did not return	8", 8, osfArray[1]
109                .getOffset());
110        assertEquals("osfArray[2].getOffset() did not return 12", 12,
111                osfArray[2].getOffset());
112    }
113
114    /**
115     * @tests java.io.ObjectStreamField#getType()
116     */
117    public void test_getType() {
118        assertTrue("getType on an Object field did not answer Object",
119                holaField.getType().equals(Object.class));
120    }
121
122    /**
123     * @tests java.io.ObjectStreamField#getTypeCode()
124     */
125    public void test_getTypeCode() {
126        assertEquals("getTypeCode on an Object field did not answer 'L'", 'L',
127                holaField.getTypeCode());
128        assertEquals("getTypeCode on a long field did not answer 'J'", 'J',
129                bamField.getTypeCode());
130    }
131
132    /**
133     * @tests java.io.ObjectStreamField#getTypeString()
134     */
135    public void test_getTypeString() {
136        assertTrue("getTypeString returned: " + holaField.getTypeString(),
137                holaField.getTypeString().indexOf("Object") >= 0);
138        assertNull("Primitive types' strings should be null", hamField
139                .getTypeString());
140
141        ObjectStreamField osf = new ObjectStreamField("s", String.class, true);
142        assertTrue(osf.getTypeString() == "Ljava/lang/String;");
143    }
144
145    /**
146     * @tests java.io.ObjectStreamField#toString()
147     */
148    public void test_toString() {
149        assertTrue("toString on a long returned: " + bamField.toString(),
150                bamField.toString().indexOf("bam") >= 0);
151    }
152
153    /**
154     * @tests java.io.ObjectStreamField#getType()
155     */
156    public void test_getType_Deserialized() throws IOException,
157            ClassNotFoundException {
158        ByteArrayOutputStream baos = new ByteArrayOutputStream(1024);
159        ObjectOutputStream oos = new ObjectOutputStream(baos);
160        oos.writeObject(new SerializableObject());
161        oos.close();
162        baos.close();
163
164        byte[] bytes = baos.toByteArray();
165        ByteArrayInputStream bais = new ByteArrayInputStream(bytes);
166        ObjectInputStream ois = new ObjectInputStream(bais);
167        SerializableObject obj = (SerializableObject) ois.readObject();
168
169        ObjectStreamClass oc = obj.getObjectStreamClass();
170        ObjectStreamField field = oc.getField("i");
171        assertEquals(Object.class, field.getType());
172    }
173
174    /**
175     * @tests java.io.ObjectStreamField#getType()
176     */
177    public void test_getType_MockObjectInputStream() throws IOException,
178            ClassNotFoundException {
179        ByteArrayOutputStream baos = new ByteArrayOutputStream(1024);
180        ObjectOutputStream oos = new ObjectOutputStream(baos);
181        oos.writeObject(new SerializableObject());
182        oos.close();
183        baos.close();
184
185        byte[] bytes = baos.toByteArray();
186        ByteArrayInputStream bais = new ByteArrayInputStream(bytes);
187        MockObjectInputStream ois = new MockObjectInputStream(bais);
188        ois.readObject();
189
190        ObjectStreamClass oc = ois.getObjectStreamClass();
191        ObjectStreamField field = oc.getField("i");
192        assertEquals(Object.class, field.getType());
193    }
194
195    public void test_isUnshared() throws Exception {
196        SerializableObject2 obj = new SerializableObject2();
197
198        ByteArrayOutputStream baos = new ByteArrayOutputStream(1024);
199        ObjectOutputStream oos = new ObjectOutputStream(baos);
200        oos.writeObject(obj);
201        oos.close();
202        baos.close();
203        byte[] bytes = baos.toByteArray();
204        ByteArrayInputStream bais = new ByteArrayInputStream(bytes);
205        ObjectInputStream ois = new ObjectInputStream(bais);
206        SerializableObject2 newObj = (SerializableObject2) ois.readObject();
207
208        ObjectInputStream.GetField getField = newObj.getGetField();
209        ObjectStreamClass objectStreamClass = getField.getObjectStreamClass();
210
211        assertTrue(objectStreamClass.getField("i").isUnshared());
212        assertFalse(objectStreamClass.getField("d").isUnshared());
213        assertTrue(objectStreamClass.getField("s").isUnshared());
214
215        assertEquals(1000, getField.get("i", null));
216        assertEquals(SerializableObject2.today, getField.get("d", null));
217        assertEquals("Richard", getField.get("s", null));
218
219        assertTrue(objectStreamClass.getField("s").getTypeString() == "Ljava/lang/String;");
220
221        assertEquals(0, objectStreamClass.getField("d").getOffset());
222        assertEquals(1, objectStreamClass.getField("i").getOffset());
223        assertEquals(2, objectStreamClass.getField("s").getOffset());
224    }
225
226
227    /**
228     * Write/serialize and read/de-serialize an object with primitive field
229     */
230    public void test_ObjectWithPrimitiveField()
231        throws IOException, ClassNotFoundException {
232
233        final ByteArrayOutputStream baos = new ByteArrayOutputStream();
234        final MyObjectOutputStream oos = new MyObjectOutputStream(baos);
235        oos.writeObject(new MockClass());
236        final byte[] bytes = baos.toByteArray();
237        final ByteArrayInputStream bais = new ByteArrayInputStream(bytes);
238        final MyObjectInputStream ois = new MyObjectInputStream(bais);
239        // NullPointerException is thrown by the readObject call below.
240        ois.readObject();
241    }
242
243    /**
244     * Sets up the fixture, for example, open a network connection. This method
245     * is called before a test is executed.
246     */
247    protected void setUp() {
248        osc = ObjectStreamClass.lookup(DummyClass.class);
249        bamField = osc.getField("bam");
250        samField = osc.getField("sam");
251        hamField = osc.getField("ham");
252        holaField = osc.getField("hola");
253    }
254}
255
256class SerializableObject implements Serializable {
257    public ObjectInputStream.GetField getField = null;
258
259    private static final long serialVersionUID = -2953957835918368056L;
260
261    public Date d;
262
263    public Integer i;
264
265    public Exception e;
266
267    public SerializableObject() {
268        d = new Date();
269        i = new Integer(1);
270        e = new Exception("e");
271    }
272
273    private void writeObject(ObjectOutputStream o) throws IOException {
274        o.putFields().put("d", new Date());
275        o.putFields().put("i", new Integer(11));
276        o.writeFields();
277    }
278
279    private void readObject(ObjectInputStream in) throws NotActiveException,
280            IOException, ClassNotFoundException {
281        getField = in.readFields();
282        d = (Date) getField.get("d", null);
283        i = (Integer) getField.get("i", null);
284    }
285
286    public ObjectStreamClass getObjectStreamClass() {
287        return getField.getObjectStreamClass();
288    }
289}
290
291class MockObjectInputStream extends ObjectInputStream {
292    private ObjectStreamClass temp = null;
293
294    public MockObjectInputStream() throws SecurityException, IOException {
295        super();
296    }
297
298    public MockObjectInputStream(InputStream in)
299            throws StreamCorruptedException, IOException {
300        super(in);
301    }
302
303    public ObjectStreamClass readClassDescriptor() throws IOException,
304            ClassNotFoundException {
305        ObjectStreamClass osc = super.readClassDescriptor();
306        // To get the ObjectStreamClass of SerializableObject
307        if (osc.getSerialVersionUID() == -2953957835918368056L) {
308            temp = osc;
309        }
310        return osc;
311    }
312
313    public ObjectStreamClass getObjectStreamClass() {
314        return temp;
315    }
316}
317
318class SerializableObject2 implements Serializable {
319
320    private static final long serialVersionUID = 1L;
321
322    private static final ObjectStreamField[] serialPersistentFields = {
323            new ObjectStreamField("i", Integer.class, true),
324            new ObjectStreamField("d", Date.class, false),
325            new ObjectStreamField("s", String.class, true), };
326
327    private ObjectInputStream.GetField getField;
328
329    public static Date today = new Date(1172632429156l);
330
331    public ObjectInputStream.GetField getGetField() {
332        return getField;
333    }
334
335    private void writeObject(ObjectOutputStream o) throws IOException {
336        ObjectOutputStream.PutField putField = o.putFields();
337        putField.put("i", new Integer(1000));
338        putField.put("d", today);
339        putField.put("s", "Richard");
340        o.writeFields();
341    }
342
343    private void readObject(ObjectInputStream in) throws NotActiveException,
344            IOException, ClassNotFoundException {
345        getField = in.readFields();
346    }
347}
348
349
350// Primitive fields are necessary to cause the NullPointerException.
351class MockClass implements Serializable {
352    String str1 = "string 1";
353    String str2 = "string 2";
354    int int1 = 1;
355    int int2 = 2;
356    String str3 = "string 3";
357}
358
359
360// Overrides writeClassDescriptor to store ObjectStreamClass in map.
361class MyObjectOutputStream extends ObjectOutputStream {
362
363    // record the only ObjectStreamClass
364    static ObjectStreamClass descs;
365
366    MyObjectOutputStream(OutputStream out)
367        throws IOException {
368        super(out);
369    }
370
371    @Override
372    protected void writeClassDescriptor(ObjectStreamClass desc)
373        throws IOException {
374        descs = desc;
375        // Write a int
376        writeInt(1);
377    }
378}
379
380// Overrides readClassDescriptor to get ObjectStreamClass from map.
381class MyObjectInputStream extends ObjectInputStream {
382
383    MyObjectInputStream(InputStream in)
384        throws IOException {
385        super(in);
386    }
387
388    @Override
389    protected ObjectStreamClass readClassDescriptor()
390        throws IOException, ClassNotFoundException {
391        // Read a integer and get the only ObjectStreamClass for the test
392        final int id = readInt();
393        return MyObjectOutputStream.descs;
394    }
395}
396