Home | History | Annotate | Download | only in io
      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 
     18 package org.apache.harmony.tests.java.io;
     19 
     20 import java.io.Externalizable;
     21 import java.io.IOException;
     22 import java.io.ObjectInput;
     23 import java.io.ObjectOutput;
     24 import java.io.ObjectStreamClass;
     25 import java.io.ObjectStreamField;
     26 import java.io.Serializable;
     27 import java.lang.reflect.Method;
     28 import java.lang.reflect.Proxy;
     29 import junit.framework.TestCase;
     30 
     31 public class ObjectStreamClassTest extends TestCase {
     32 
     33     static class DummyClass implements Serializable {
     34         private static final long serialVersionUID = 999999999999999L;
     35 
     36         long bam = 999L;
     37 
     38         int ham = 9999;
     39 
     40         public static long getUID() {
     41             return serialVersionUID;
     42         }
     43     }
     44 
     45     /**
     46      * java.io.ObjectStreamClass#forClass()
     47      */
     48     public void test_forClass() {
     49         // Need to test during serialization to be sure an instance is
     50         // returned
     51         ObjectStreamClass osc = ObjectStreamClass.lookup(DummyClass.class);
     52         assertEquals("forClass returned an object: " + osc.forClass(),
     53                 DummyClass.class, osc.forClass());
     54     }
     55 
     56     /**
     57      * java.io.ObjectStreamClass#getField(java.lang.String)
     58      */
     59     public void test_getFieldLjava_lang_String() {
     60         ObjectStreamClass osc = ObjectStreamClass.lookup(DummyClass.class);
     61         assertEquals("getField did not return correct field", 'J', osc
     62                 .getField("bam").getTypeCode());
     63         assertNull("getField did not null for non-existent field", osc
     64                 .getField("wham"));
     65     }
     66 
     67     /**
     68      * java.io.ObjectStreamClass#getFields()
     69      */
     70     public void test_getFields() {
     71         ObjectStreamClass osc = ObjectStreamClass.lookup(DummyClass.class);
     72         ObjectStreamField[] osfArray = osc.getFields();
     73         assertTrue(
     74                 "Array of fields should be of length 2 but is instead of length: "
     75                         + osfArray.length, osfArray.length == 2);
     76     }
     77 
     78     /**
     79      * java.io.ObjectStreamClass#getName()
     80      */
     81     public void test_getName() {
     82         ObjectStreamClass osc = ObjectStreamClass.lookup(DummyClass.class);
     83         assertEquals(
     84                 "getName returned incorrect name: " + osc.getName(),
     85                 "org.apache.harmony.tests.java.io.ObjectStreamClassTest$DummyClass",
     86                 osc.getName());
     87     }
     88 
     89     /**
     90      * java.io.ObjectStreamClass#getSerialVersionUID()
     91      */
     92     public void test_getSerialVersionUID() {
     93         ObjectStreamClass osc = ObjectStreamClass.lookup(DummyClass.class);
     94         assertTrue("getSerialversionUID returned incorrect uid: "
     95                 + osc.getSerialVersionUID() + " instead of "
     96                 + DummyClass.getUID(), osc.getSerialVersionUID() == DummyClass
     97                 .getUID());
     98     }
     99 
    100     static class SyntheticTest implements Serializable {
    101         private int i;
    102 
    103         private class X implements Serializable {
    104             public int get() {
    105                 return i;
    106             }
    107         }
    108 
    109         public X foo() {
    110             return new X();
    111         }
    112     }
    113 
    114     /**
    115      * java.io.ObjectStreamClass#lookup(java.lang.Class)
    116      */
    117     public void test_lookupLjava_lang_Class() {
    118         ObjectStreamClass osc = ObjectStreamClass.lookup(DummyClass.class);
    119         assertEquals(
    120                 "lookup returned wrong class: " + osc.getName(),
    121                 "org.apache.harmony.tests.java.io.ObjectStreamClassTest$DummyClass",
    122                 osc.getName());
    123     }
    124 
    125     /**
    126      * java.io.ObjectStreamClass#toString()
    127      */
    128     public void test_toString() {
    129         ObjectStreamClass osc = ObjectStreamClass.lookup(DummyClass.class);
    130         String oscString = osc.toString();
    131 
    132         // The previous test was more specific than the spec so it was replaced
    133         // with the test below
    134         assertTrue("toString returned incorrect string: " + osc.toString(),
    135                 oscString.indexOf("serialVersionUID") >= 0
    136                         && oscString.indexOf("999999999999999L") >= 0);
    137     }
    138 
    139     public void testSerialization() {
    140         ObjectStreamClass osc = ObjectStreamClass
    141                 .lookup(ObjectStreamClass.class);
    142         assertEquals(0, osc.getFields().length);
    143     }
    144 
    145     public void test_specialTypes() {
    146         Class<?> proxyClass = Proxy.getProxyClass(this.getClass()
    147                 .getClassLoader(), new Class[] { Runnable.class });
    148 
    149         ObjectStreamClass proxyStreamClass = ObjectStreamClass
    150                 .lookup(proxyClass);
    151 
    152         assertEquals("Proxy classes should have zero serialVersionUID", 0,
    153                 proxyStreamClass.getSerialVersionUID());
    154         ObjectStreamField[] proxyFields = proxyStreamClass.getFields();
    155         assertEquals("Proxy classes should have no serialized fields", 0,
    156                 proxyFields.length);
    157 
    158         ObjectStreamClass enumStreamClass = ObjectStreamClass
    159                 .lookup(Thread.State.class);
    160 
    161         assertEquals("Enum classes should have zero serialVersionUID", 0,
    162                 enumStreamClass.getSerialVersionUID());
    163         ObjectStreamField[] enumFields = enumStreamClass.getFields();
    164         assertEquals("Enum classes should have no serialized fields", 0,
    165                 enumFields.length);
    166     }
    167 
    168     /**
    169      * @since 1.6
    170      */
    171     static class NonSerialzableClass {
    172         private static final long serialVersionUID = 1l;
    173 
    174         public static long getUID() {
    175             return serialVersionUID;
    176         }
    177     }
    178 
    179     /**
    180      * @since 1.6
    181      */
    182     static class ExternalizableClass implements Externalizable {
    183 
    184         private static final long serialVersionUID = -4285635779249689129L;
    185 
    186         public void readExternal(ObjectInput input) throws IOException, ClassNotFoundException {
    187             throw new ClassNotFoundException();
    188         }
    189 
    190         public void writeExternal(ObjectOutput output) throws IOException {
    191             throw new IOException();
    192         }
    193 
    194     }
    195 
    196     /**
    197      * java.io.ObjectStreamClass#lookupAny(java.lang.Class)
    198      * @since 1.6
    199      */
    200     public void test_lookupAnyLjava_lang_Class() {
    201         // Test for method java.io.ObjectStreamClass
    202         // java.io.ObjectStreamClass.lookupAny(java.lang.Class)
    203         ObjectStreamClass osc = ObjectStreamClass.lookupAny(DummyClass.class);
    204         assertEquals("lookup returned wrong class: " + osc.getName(),
    205                 "org.apache.harmony.tests.java.io.ObjectStreamClassTest$DummyClass", osc
    206                 .getName());
    207 
    208         osc = ObjectStreamClass.lookupAny(NonSerialzableClass.class);
    209         assertEquals("lookup returned wrong class: " + osc.getName(),
    210                 "org.apache.harmony.tests.java.io.ObjectStreamClassTest$NonSerialzableClass",
    211                 osc.getName());
    212 
    213         osc = ObjectStreamClass.lookupAny(ExternalizableClass.class);
    214         assertEquals("lookup returned wrong class: " + osc.getName(),
    215                 "org.apache.harmony.tests.java.io.ObjectStreamClassTest$ExternalizableClass",
    216                 osc.getName());
    217 
    218         osc = ObjectStreamClass.lookup(NonSerialzableClass.class);
    219         assertNull(osc);
    220     }
    221 
    222     // http://b/28106822
    223     public void testBug28106822() throws Exception {
    224         Method getConstructorId = ObjectStreamClass.class.getDeclaredMethod(
    225                 "getConstructorId", Class.class);
    226         getConstructorId.setAccessible(true);
    227 
    228         assertEquals(1189998819991197253L, getConstructorId.invoke(null, Object.class));
    229         assertEquals(1189998819991197253L, getConstructorId.invoke(null, String.class));
    230 
    231         Method newInstance = ObjectStreamClass.class.getDeclaredMethod("newInstance",
    232                 Class.class, Long.TYPE);
    233         newInstance.setAccessible(true);
    234 
    235         Object obj = newInstance.invoke(null, String.class, 0 /* ignored */);
    236         assertNotNull(obj);
    237         assertTrue(obj instanceof String);
    238     }
    239 
    240     // Class without <clinit> method
    241     public static class NoClinitParent {
    242     }
    243     // Class without <clinit> method
    244     public static class NoClinitChildWithNoClinitParent extends NoClinitParent {
    245     }
    246 
    247     // Class with <clinit> method
    248     public static class ClinitParent {
    249         // This field will trigger creation of <clinit> method for this class
    250         private static final String TAG = ClinitParent.class.getName();
    251         static {
    252 
    253         }
    254     }
    255     // Class without <clinit> but with parent that has <clinit> method
    256     public static class NoClinitChildWithClinitParent extends ClinitParent {
    257     }
    258 
    259     // http://b/29064453
    260     public void testHasClinit() throws Exception {
    261         Method hasStaticInitializer =
    262             ObjectStreamClass.class.getDeclaredMethod("hasStaticInitializer", Class.class,
    263                                                       boolean.class);
    264         hasStaticInitializer.setAccessible(true);
    265 
    266         assertTrue((Boolean)
    267                    hasStaticInitializer.invoke(null, ClinitParent.class,
    268                                                false /* checkSuperclass */));
    269 
    270         // RI will return correctly False in this case, but android has been returning true
    271         // in this particular case. We're returning true to enable deserializing classes
    272         // like NoClinitChildWithClinitParent without explicit serialVersionID field.
    273         assertTrue((Boolean)
    274                    hasStaticInitializer.invoke(null, NoClinitChildWithClinitParent.class,
    275                                                false /* checkSuperclass */));
    276         assertFalse((Boolean)
    277                     hasStaticInitializer.invoke(null, NoClinitParent.class,
    278                                                 false /* checkSuperclass */));
    279         assertFalse((Boolean)
    280                     hasStaticInitializer.invoke(null, NoClinitChildWithNoClinitParent.class,
    281                                                 false /* checkSuperclass */));
    282 
    283 
    284         assertTrue((Boolean)
    285                    hasStaticInitializer.invoke(null, ClinitParent.class,
    286                                                true /* checkSuperclass */));
    287         assertFalse((Boolean)
    288                    hasStaticInitializer.invoke(null, NoClinitChildWithClinitParent.class,
    289                                                true /* checkSuperclass */));
    290         assertFalse((Boolean)
    291                     hasStaticInitializer.invoke(null, NoClinitParent.class,
    292                                                 true /* checkSuperclass */));
    293         assertFalse((Boolean)
    294                     hasStaticInitializer.invoke(null, NoClinitChildWithNoClinitParent.class,
    295                                                 true /* checkSuperclass */));
    296     }
    297 }
    298