11ffc4b2e242d1ba40ceb30b21510f0f26bd5aaa2Jesse Wilson/*
21ffc4b2e242d1ba40ceb30b21510f0f26bd5aaa2Jesse Wilson * Copyright (C) 2011 The Android Open Source Project
31ffc4b2e242d1ba40ceb30b21510f0f26bd5aaa2Jesse Wilson *
41ffc4b2e242d1ba40ceb30b21510f0f26bd5aaa2Jesse Wilson * Licensed under the Apache License, Version 2.0 (the "License");
51ffc4b2e242d1ba40ceb30b21510f0f26bd5aaa2Jesse Wilson * you may not use this file except in compliance with the License.
61ffc4b2e242d1ba40ceb30b21510f0f26bd5aaa2Jesse Wilson * You may obtain a copy of the License at
71ffc4b2e242d1ba40ceb30b21510f0f26bd5aaa2Jesse Wilson *
81ffc4b2e242d1ba40ceb30b21510f0f26bd5aaa2Jesse Wilson *      http://www.apache.org/licenses/LICENSE-2.0
91ffc4b2e242d1ba40ceb30b21510f0f26bd5aaa2Jesse Wilson *
101ffc4b2e242d1ba40ceb30b21510f0f26bd5aaa2Jesse Wilson * Unless required by applicable law or agreed to in writing, software
111ffc4b2e242d1ba40ceb30b21510f0f26bd5aaa2Jesse Wilson * distributed under the License is distributed on an "AS IS" BASIS,
121ffc4b2e242d1ba40ceb30b21510f0f26bd5aaa2Jesse Wilson * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
131ffc4b2e242d1ba40ceb30b21510f0f26bd5aaa2Jesse Wilson * See the License for the specific language governing permissions and
141ffc4b2e242d1ba40ceb30b21510f0f26bd5aaa2Jesse Wilson * limitations under the License.
151ffc4b2e242d1ba40ceb30b21510f0f26bd5aaa2Jesse Wilson */
161ffc4b2e242d1ba40ceb30b21510f0f26bd5aaa2Jesse Wilson
171ffc4b2e242d1ba40ceb30b21510f0f26bd5aaa2Jesse Wilsonpackage libcore.java.io;
181ffc4b2e242d1ba40ceb30b21510f0f26bd5aaa2Jesse Wilson
19738c833d38d41f8f76eb7e77ab39add82b1ae1e2Neil Fullerimport junit.framework.TestCase;
20738c833d38d41f8f76eb7e77ab39add82b1ae1e2Neil Fuller
2147f29998eae296ad812d697c8da12e84e394fee2Jesse Wilsonimport java.io.InvalidClassException;
22738c833d38d41f8f76eb7e77ab39add82b1ae1e2Neil Fullerimport java.io.InvalidObjectException;
2355848681427721532161c63b43b3f99e912d071cNeil Fullerimport java.io.NotSerializableException;
2405895faacf43e6fd2bcd57baed31832f6888cb31Elliott Hughesimport java.io.ObjectStreamClass;
2505895faacf43e6fd2bcd57baed31832f6888cb31Elliott Hughesimport java.io.ObjectStreamField;
261ffc4b2e242d1ba40ceb30b21510f0f26bd5aaa2Jesse Wilsonimport java.io.Serializable;
27738c833d38d41f8f76eb7e77ab39add82b1ae1e2Neil Fullerimport java.lang.reflect.InvocationHandler;
28738c833d38d41f8f76eb7e77ab39add82b1ae1e2Neil Fullerimport java.lang.reflect.Method;
29b416ef5dc224630af2b9393a15ae120b27e4864aJesse Wilsonimport libcore.util.SerializationTester;
301ffc4b2e242d1ba40ceb30b21510f0f26bd5aaa2Jesse Wilson
311ffc4b2e242d1ba40ceb30b21510f0f26bd5aaa2Jesse Wilsonpublic final class SerializationTest extends TestCase {
321ffc4b2e242d1ba40ceb30b21510f0f26bd5aaa2Jesse Wilson
331ffc4b2e242d1ba40ceb30b21510f0f26bd5aaa2Jesse Wilson    // http://b/4471249
341ffc4b2e242d1ba40ceb30b21510f0f26bd5aaa2Jesse Wilson    public void testSerializeFieldMadeTransient() throws Exception {
3505895faacf43e6fd2bcd57baed31832f6888cb31Elliott Hughes        // Does ObjectStreamClass have the right idea?
3605895faacf43e6fd2bcd57baed31832f6888cb31Elliott Hughes        ObjectStreamClass osc = ObjectStreamClass.lookup(FieldMadeTransient.class);
3705895faacf43e6fd2bcd57baed31832f6888cb31Elliott Hughes        ObjectStreamField[] fields = osc.getFields();
3805895faacf43e6fd2bcd57baed31832f6888cb31Elliott Hughes        assertEquals(1, fields.length);
3905895faacf43e6fd2bcd57baed31832f6888cb31Elliott Hughes        assertEquals("nonTransientInt", fields[0].getName());
4005895faacf43e6fd2bcd57baed31832f6888cb31Elliott Hughes        assertEquals(int.class, fields[0].getType());
4105895faacf43e6fd2bcd57baed31832f6888cb31Elliott Hughes
428f99aa098c6a06b8be788abbca1c1d1060342709Jesse Wilson        // this was created by serializing a FieldMadeTransient with a non-0 transientInt
431ffc4b2e242d1ba40ceb30b21510f0f26bd5aaa2Jesse Wilson        String s = "aced0005737200346c6962636f72652e6a6176612e696f2e53657269616c697a6174696f6e54657"
441ffc4b2e242d1ba40ceb30b21510f0f26bd5aaa2Jesse Wilson                + "374244669656c644d6164655472616e7369656e74000000000000000002000149000c7472616e736"
451ffc4b2e242d1ba40ceb30b21510f0f26bd5aaa2Jesse Wilson                + "9656e74496e747870abababab";
46b416ef5dc224630af2b9393a15ae120b27e4864aJesse Wilson        FieldMadeTransient deserialized = (FieldMadeTransient) SerializationTester.deserializeHex(s);
471ffc4b2e242d1ba40ceb30b21510f0f26bd5aaa2Jesse Wilson        assertEquals(0, deserialized.transientInt);
481ffc4b2e242d1ba40ceb30b21510f0f26bd5aaa2Jesse Wilson    }
491ffc4b2e242d1ba40ceb30b21510f0f26bd5aaa2Jesse Wilson
501ffc4b2e242d1ba40ceb30b21510f0f26bd5aaa2Jesse Wilson    static class FieldMadeTransient implements Serializable {
511ffc4b2e242d1ba40ceb30b21510f0f26bd5aaa2Jesse Wilson        private static final long serialVersionUID = 0L;
52729d4ecafff8e6af5a71e4fecb2007917cbc2e2aNeil Fuller        @SuppressWarnings("unused")
531ffc4b2e242d1ba40ceb30b21510f0f26bd5aaa2Jesse Wilson        private transient int transientInt;
54729d4ecafff8e6af5a71e4fecb2007917cbc2e2aNeil Fuller        @SuppressWarnings("unused")
5505895faacf43e6fd2bcd57baed31832f6888cb31Elliott Hughes        private int nonTransientInt;
561ffc4b2e242d1ba40ceb30b21510f0f26bd5aaa2Jesse Wilson    }
5747f29998eae296ad812d697c8da12e84e394fee2Jesse Wilson
5855848681427721532161c63b43b3f99e912d071cNeil Fuller    public void testSerializeFieldMadeStatic() throws Exception {
5955848681427721532161c63b43b3f99e912d071cNeil Fuller        // Does ObjectStreamClass have the right idea?
6055848681427721532161c63b43b3f99e912d071cNeil Fuller        ObjectStreamClass osc = ObjectStreamClass.lookup(FieldMadeStatic.class);
6155848681427721532161c63b43b3f99e912d071cNeil Fuller        ObjectStreamField[] fields = osc.getFields();
6255848681427721532161c63b43b3f99e912d071cNeil Fuller        assertEquals(0, fields.length);
6355848681427721532161c63b43b3f99e912d071cNeil Fuller
6455848681427721532161c63b43b3f99e912d071cNeil Fuller        // This was created by serializing a FieldMadeStatic with a non-static staticInt
6555848681427721532161c63b43b3f99e912d071cNeil Fuller        String s = "aced0005737200316c6962636f72652e6a6176612e696f2e53657269616c697a6174696f6e54657"
6655848681427721532161c63b43b3f99e912d071cNeil Fuller                + "374244669656c644d6164655374617469630000000000000000020001490009737461746963496e7"
6755848681427721532161c63b43b3f99e912d071cNeil Fuller                + "47870000022b8";
6855848681427721532161c63b43b3f99e912d071cNeil Fuller        FieldMadeStatic deserialized = (FieldMadeStatic) SerializationTester.deserializeHex(s);
69729d4ecafff8e6af5a71e4fecb2007917cbc2e2aNeil Fuller        // The field data must be ignored if it is static.
7055848681427721532161c63b43b3f99e912d071cNeil Fuller        assertEquals(9999, deserialized.staticInt);
7155848681427721532161c63b43b3f99e912d071cNeil Fuller    }
7255848681427721532161c63b43b3f99e912d071cNeil Fuller
7355848681427721532161c63b43b3f99e912d071cNeil Fuller    static class FieldMadeStatic implements Serializable {
7455848681427721532161c63b43b3f99e912d071cNeil Fuller        private static final long serialVersionUID = 0L;
7555848681427721532161c63b43b3f99e912d071cNeil Fuller        // private int staticInt = 8888;
7655848681427721532161c63b43b3f99e912d071cNeil Fuller        private static int staticInt = 9999;
7755848681427721532161c63b43b3f99e912d071cNeil Fuller    }
7855848681427721532161c63b43b3f99e912d071cNeil Fuller
79729d4ecafff8e6af5a71e4fecb2007917cbc2e2aNeil Fuller    public static boolean serializableContainer1InitializedFlag = false;
80729d4ecafff8e6af5a71e4fecb2007917cbc2e2aNeil Fuller    public static boolean unserializable1InitializedFlag = false;
81729d4ecafff8e6af5a71e4fecb2007917cbc2e2aNeil Fuller
82729d4ecafff8e6af5a71e4fecb2007917cbc2e2aNeil Fuller    public static class Unserializable1 {
83729d4ecafff8e6af5a71e4fecb2007917cbc2e2aNeil Fuller        static {
84729d4ecafff8e6af5a71e4fecb2007917cbc2e2aNeil Fuller            SerializationTest.unserializable1InitializedFlag = true;
85729d4ecafff8e6af5a71e4fecb2007917cbc2e2aNeil Fuller        }
86729d4ecafff8e6af5a71e4fecb2007917cbc2e2aNeil Fuller    }
87729d4ecafff8e6af5a71e4fecb2007917cbc2e2aNeil Fuller
88729d4ecafff8e6af5a71e4fecb2007917cbc2e2aNeil Fuller    static class SerializableContainer1 implements Serializable {
89729d4ecafff8e6af5a71e4fecb2007917cbc2e2aNeil Fuller        private static final long serialVersionUID = 0L;
90729d4ecafff8e6af5a71e4fecb2007917cbc2e2aNeil Fuller        private Unserializable1 unserializable = null;
91729d4ecafff8e6af5a71e4fecb2007917cbc2e2aNeil Fuller
92729d4ecafff8e6af5a71e4fecb2007917cbc2e2aNeil Fuller        static {
93729d4ecafff8e6af5a71e4fecb2007917cbc2e2aNeil Fuller            serializableContainer1InitializedFlag = true;
94729d4ecafff8e6af5a71e4fecb2007917cbc2e2aNeil Fuller        }
95729d4ecafff8e6af5a71e4fecb2007917cbc2e2aNeil Fuller    }
96729d4ecafff8e6af5a71e4fecb2007917cbc2e2aNeil Fuller
9755848681427721532161c63b43b3f99e912d071cNeil Fuller    // We can serialize an object that has an unserializable field providing it is null.
9855848681427721532161c63b43b3f99e912d071cNeil Fuller    public void testDeserializeNullUnserializableField() throws Exception {
9955848681427721532161c63b43b3f99e912d071cNeil Fuller        // This was created by creating a new SerializableContainer and not setting the
10055848681427721532161c63b43b3f99e912d071cNeil Fuller        // unserializable field. A canned serialized form is used so we can tell if the static
10155848681427721532161c63b43b3f99e912d071cNeil Fuller        // initializers were executed during deserialization.
102729d4ecafff8e6af5a71e4fecb2007917cbc2e2aNeil Fuller        // SerializationTester.serializeHex(new SerializableContainer1());
103729d4ecafff8e6af5a71e4fecb2007917cbc2e2aNeil Fuller        String s = "aced0005737200386c6962636f72652e6a6176612e696f2e53657269616c697a6174696f6e54657"
104729d4ecafff8e6af5a71e4fecb2007917cbc2e2aNeil Fuller                  + "3742453657269616c697a61626c65436f6e7461696e65723100000000000000000200014c000e7"
105729d4ecafff8e6af5a71e4fecb2007917cbc2e2aNeil Fuller                  + "56e73657269616c697a61626c657400124c6a6176612f6c616e672f4f626a6563743b787070";
10655848681427721532161c63b43b3f99e912d071cNeil Fuller
107729d4ecafff8e6af5a71e4fecb2007917cbc2e2aNeil Fuller        assertFalse(serializableContainer1InitializedFlag);
108729d4ecafff8e6af5a71e4fecb2007917cbc2e2aNeil Fuller        assertFalse(unserializable1InitializedFlag);
10955848681427721532161c63b43b3f99e912d071cNeil Fuller
110729d4ecafff8e6af5a71e4fecb2007917cbc2e2aNeil Fuller        SerializableContainer1 sc = (SerializableContainer1) SerializationTester.deserializeHex(s);
11155848681427721532161c63b43b3f99e912d071cNeil Fuller        assertNull(sc.unserializable);
11255848681427721532161c63b43b3f99e912d071cNeil Fuller
11355848681427721532161c63b43b3f99e912d071cNeil Fuller        // Confirm the container was initialized, but the class for the null field was not.
114729d4ecafff8e6af5a71e4fecb2007917cbc2e2aNeil Fuller        assertTrue(serializableContainer1InitializedFlag);
115729d4ecafff8e6af5a71e4fecb2007917cbc2e2aNeil Fuller        assertFalse(unserializable1InitializedFlag);
11655848681427721532161c63b43b3f99e912d071cNeil Fuller    }
11755848681427721532161c63b43b3f99e912d071cNeil Fuller
118729d4ecafff8e6af5a71e4fecb2007917cbc2e2aNeil Fuller    static class Unserializable2 {
119729d4ecafff8e6af5a71e4fecb2007917cbc2e2aNeil Fuller    }
12055848681427721532161c63b43b3f99e912d071cNeil Fuller
121729d4ecafff8e6af5a71e4fecb2007917cbc2e2aNeil Fuller    static class HasUnserializableField implements Serializable {
12255848681427721532161c63b43b3f99e912d071cNeil Fuller        private static final long serialVersionUID = 0L;
123729d4ecafff8e6af5a71e4fecb2007917cbc2e2aNeil Fuller        @SuppressWarnings("unused") // Required to make objects unserializable.
124729d4ecafff8e6af5a71e4fecb2007917cbc2e2aNeil Fuller        private Unserializable2 unserializable = new Unserializable2();
12555848681427721532161c63b43b3f99e912d071cNeil Fuller    }
12655848681427721532161c63b43b3f99e912d071cNeil Fuller
12755848681427721532161c63b43b3f99e912d071cNeil Fuller    // We must not serialize an object that has a non-null unserializable field.
12855848681427721532161c63b43b3f99e912d071cNeil Fuller    public void testSerializeUnserializableField() throws Exception {
129729d4ecafff8e6af5a71e4fecb2007917cbc2e2aNeil Fuller        HasUnserializableField uf = new HasUnserializableField();
13055848681427721532161c63b43b3f99e912d071cNeil Fuller        try {
131729d4ecafff8e6af5a71e4fecb2007917cbc2e2aNeil Fuller            SerializationTester.serializeHex(uf);
13255848681427721532161c63b43b3f99e912d071cNeil Fuller            fail();
13355848681427721532161c63b43b3f99e912d071cNeil Fuller        } catch (NotSerializableException expected) {
13455848681427721532161c63b43b3f99e912d071cNeil Fuller        }
13555848681427721532161c63b43b3f99e912d071cNeil Fuller    }
13655848681427721532161c63b43b3f99e912d071cNeil Fuller
137729d4ecafff8e6af5a71e4fecb2007917cbc2e2aNeil Fuller    public static boolean serializableContainer2InitializedFlag = false;
138729d4ecafff8e6af5a71e4fecb2007917cbc2e2aNeil Fuller
139729d4ecafff8e6af5a71e4fecb2007917cbc2e2aNeil Fuller    @SuppressWarnings("unused") // Required for deserialization test
140729d4ecafff8e6af5a71e4fecb2007917cbc2e2aNeil Fuller    static class SerializableContainer2 implements Serializable {
141729d4ecafff8e6af5a71e4fecb2007917cbc2e2aNeil Fuller        private static final long serialVersionUID = 0L;
142729d4ecafff8e6af5a71e4fecb2007917cbc2e2aNeil Fuller        private WasSerializable unserializable = null;
143729d4ecafff8e6af5a71e4fecb2007917cbc2e2aNeil Fuller
144729d4ecafff8e6af5a71e4fecb2007917cbc2e2aNeil Fuller        static {
145729d4ecafff8e6af5a71e4fecb2007917cbc2e2aNeil Fuller            serializableContainer2InitializedFlag = true;
146729d4ecafff8e6af5a71e4fecb2007917cbc2e2aNeil Fuller        }
147729d4ecafff8e6af5a71e4fecb2007917cbc2e2aNeil Fuller    }
148729d4ecafff8e6af5a71e4fecb2007917cbc2e2aNeil Fuller
14955848681427721532161c63b43b3f99e912d071cNeil Fuller    // It must not be possible to deserialize an object if a field is no longer serializable.
15055848681427721532161c63b43b3f99e912d071cNeil Fuller    public void testDeserializeUnserializableField() throws Exception {
151729d4ecafff8e6af5a71e4fecb2007917cbc2e2aNeil Fuller        // This was generated by creating a SerializableContainer2 and setting the unserializable
15255848681427721532161c63b43b3f99e912d071cNeil Fuller        // field to a WasSerializable when it was still Serializable. A canned serialized form is
15355848681427721532161c63b43b3f99e912d071cNeil Fuller        // used so we can tell if the static initializers were executed during deserialization.
154729d4ecafff8e6af5a71e4fecb2007917cbc2e2aNeil Fuller        // SerializableContainer2 sc = new SerializableContainer2();
15555848681427721532161c63b43b3f99e912d071cNeil Fuller        // sc.unserializable = new WasSerializable();
15655848681427721532161c63b43b3f99e912d071cNeil Fuller        // SerializationTester.serializeHex(sc);
157729d4ecafff8e6af5a71e4fecb2007917cbc2e2aNeil Fuller        String s = "aced0005737200386c6962636f72652e6a6176612e696f2e53657269616c697a6174696f6e54657"
158729d4ecafff8e6af5a71e4fecb2007917cbc2e2aNeil Fuller                  + "3742453657269616c697a61626c65436f6e7461696e65723200000000000000000200014c000e7"
159729d4ecafff8e6af5a71e4fecb2007917cbc2e2aNeil Fuller                  + "56e73657269616c697a61626c657400334c6c6962636f72652f6a6176612f696f2f53657269616"
160729d4ecafff8e6af5a71e4fecb2007917cbc2e2aNeil Fuller                  + "c697a6174696f6e546573742457617353657269616c697a61626c653b7870737200316c6962636"
161729d4ecafff8e6af5a71e4fecb2007917cbc2e2aNeil Fuller                  + "f72652e6a6176612e696f2e53657269616c697a6174696f6e546573742457617353657269616c6"
162729d4ecafff8e6af5a71e4fecb2007917cbc2e2aNeil Fuller                  + "97a61626c65000000000000000002000149000169787000000000";
163729d4ecafff8e6af5a71e4fecb2007917cbc2e2aNeil Fuller
164729d4ecafff8e6af5a71e4fecb2007917cbc2e2aNeil Fuller        assertFalse(serializableContainer2InitializedFlag);
165729d4ecafff8e6af5a71e4fecb2007917cbc2e2aNeil Fuller        assertFalse(wasSerializableInitializedFlag);
16655848681427721532161c63b43b3f99e912d071cNeil Fuller        try {
16755848681427721532161c63b43b3f99e912d071cNeil Fuller            SerializationTester.deserializeHex(s);
16855848681427721532161c63b43b3f99e912d071cNeil Fuller            fail();
16955848681427721532161c63b43b3f99e912d071cNeil Fuller        } catch (InvalidClassException expected) {
17055848681427721532161c63b43b3f99e912d071cNeil Fuller        }
171729d4ecafff8e6af5a71e4fecb2007917cbc2e2aNeil Fuller        // The container class will be initialized to establish the serialVersionUID.
172729d4ecafff8e6af5a71e4fecb2007917cbc2e2aNeil Fuller        assertTrue(serializableContainer2InitializedFlag);
173729d4ecafff8e6af5a71e4fecb2007917cbc2e2aNeil Fuller        // Confirm the contained class was initialized.
17455848681427721532161c63b43b3f99e912d071cNeil Fuller        assertFalse(wasSerializableInitializedFlag);
17555848681427721532161c63b43b3f99e912d071cNeil Fuller    }
17655848681427721532161c63b43b3f99e912d071cNeil Fuller
17747f29998eae296ad812d697c8da12e84e394fee2Jesse Wilson    public void testSerialVersionUidChange() throws Exception {
17847f29998eae296ad812d697c8da12e84e394fee2Jesse Wilson        // this was created by serializing a SerialVersionUidChanged with serialVersionUID = 0L
17947f29998eae296ad812d697c8da12e84e394fee2Jesse Wilson        String s = "aced0005737200396c6962636f72652e6a6176612e696f2e53657269616c697a6174696f6e54657"
18047f29998eae296ad812d697c8da12e84e394fee2Jesse Wilson                + "3742453657269616c56657273696f6e5569644368616e67656400000000000000000200014900016"
18147f29998eae296ad812d697c8da12e84e394fee2Jesse Wilson                + "1787000000003";
18247f29998eae296ad812d697c8da12e84e394fee2Jesse Wilson        try {
18347f29998eae296ad812d697c8da12e84e394fee2Jesse Wilson            SerializationTester.deserializeHex(s);
18447f29998eae296ad812d697c8da12e84e394fee2Jesse Wilson            fail();
18547f29998eae296ad812d697c8da12e84e394fee2Jesse Wilson        } catch (InvalidClassException expected) {
18647f29998eae296ad812d697c8da12e84e394fee2Jesse Wilson        }
18747f29998eae296ad812d697c8da12e84e394fee2Jesse Wilson    }
18847f29998eae296ad812d697c8da12e84e394fee2Jesse Wilson
189738c833d38d41f8f76eb7e77ab39add82b1ae1e2Neil Fuller    @SuppressWarnings("unused") // Required for deserialization test
19047f29998eae296ad812d697c8da12e84e394fee2Jesse Wilson    static class SerialVersionUidChanged implements Serializable {
19147f29998eae296ad812d697c8da12e84e394fee2Jesse Wilson        private static final long serialVersionUID = 1L; // was 0L
19247f29998eae296ad812d697c8da12e84e394fee2Jesse Wilson        private int a;
19347f29998eae296ad812d697c8da12e84e394fee2Jesse Wilson    }
19447f29998eae296ad812d697c8da12e84e394fee2Jesse Wilson
19547f29998eae296ad812d697c8da12e84e394fee2Jesse Wilson    public void testMissingSerialVersionUid() throws Exception {
19647f29998eae296ad812d697c8da12e84e394fee2Jesse Wilson        // this was created by serializing a FieldsChanged with one int field named 'a'
19747f29998eae296ad812d697c8da12e84e394fee2Jesse Wilson        String s = "aced00057372002f6c6962636f72652e6a6176612e696f2e53657269616c697a6174696f6e54657"
19847f29998eae296ad812d697c8da12e84e394fee2Jesse Wilson                + "374244669656c64734368616e6765643bcfb934e310fa1c02000149000161787000000003";
19947f29998eae296ad812d697c8da12e84e394fee2Jesse Wilson        try {
20047f29998eae296ad812d697c8da12e84e394fee2Jesse Wilson            SerializationTester.deserializeHex(s);
20147f29998eae296ad812d697c8da12e84e394fee2Jesse Wilson            fail();
20247f29998eae296ad812d697c8da12e84e394fee2Jesse Wilson        } catch (InvalidClassException expected) {
20347f29998eae296ad812d697c8da12e84e394fee2Jesse Wilson        }
20447f29998eae296ad812d697c8da12e84e394fee2Jesse Wilson    }
20547f29998eae296ad812d697c8da12e84e394fee2Jesse Wilson
206738c833d38d41f8f76eb7e77ab39add82b1ae1e2Neil Fuller    @SuppressWarnings("unused") // Required for deserialization test
20747f29998eae296ad812d697c8da12e84e394fee2Jesse Wilson    static class FieldsChanged implements Serializable {
20847f29998eae296ad812d697c8da12e84e394fee2Jesse Wilson        private int b; // was 'a'
20947f29998eae296ad812d697c8da12e84e394fee2Jesse Wilson    }
210738c833d38d41f8f76eb7e77ab39add82b1ae1e2Neil Fuller
211738c833d38d41f8f76eb7e77ab39add82b1ae1e2Neil Fuller    public static boolean wasSerializableInitializedFlag = false;
212738c833d38d41f8f76eb7e77ab39add82b1ae1e2Neil Fuller
213738c833d38d41f8f76eb7e77ab39add82b1ae1e2Neil Fuller    @SuppressWarnings("unused")  // Required for deserialization test.
214738c833d38d41f8f76eb7e77ab39add82b1ae1e2Neil Fuller    public static class WasSerializable /* implements java.io.Serializable */ {
215738c833d38d41f8f76eb7e77ab39add82b1ae1e2Neil Fuller        static final long serialVersionUID = 0L;
216738c833d38d41f8f76eb7e77ab39add82b1ae1e2Neil Fuller        static {
217738c833d38d41f8f76eb7e77ab39add82b1ae1e2Neil Fuller            SerializationTest.wasSerializableInitializedFlag = true;
218738c833d38d41f8f76eb7e77ab39add82b1ae1e2Neil Fuller        }
219738c833d38d41f8f76eb7e77ab39add82b1ae1e2Neil Fuller        private int i;
220738c833d38d41f8f76eb7e77ab39add82b1ae1e2Neil Fuller    }
221738c833d38d41f8f76eb7e77ab39add82b1ae1e2Neil Fuller
222738c833d38d41f8f76eb7e77ab39add82b1ae1e2Neil Fuller    public void testDeserializeWasSerializableClass() throws Exception {
223738c833d38d41f8f76eb7e77ab39add82b1ae1e2Neil Fuller        // This was created by serializing a WasSerializable when it was serializable.
224738c833d38d41f8f76eb7e77ab39add82b1ae1e2Neil Fuller        // String s = SerializationTester.serializeHex(new WasSerializable());
225738c833d38d41f8f76eb7e77ab39add82b1ae1e2Neil Fuller        final String s = "aced0005737200316c6962636f72652e6a6176612e696f2e53657269616c697a6174696f6"
226738c833d38d41f8f76eb7e77ab39add82b1ae1e2Neil Fuller                + "e546573742457617353657269616c697a61626c65000000000000000002000149000169787000000"
227738c833d38d41f8f76eb7e77ab39add82b1ae1e2Neil Fuller                + "000";
228738c833d38d41f8f76eb7e77ab39add82b1ae1e2Neil Fuller
229729d4ecafff8e6af5a71e4fecb2007917cbc2e2aNeil Fuller        assertFalse(wasSerializableInitializedFlag);
230738c833d38d41f8f76eb7e77ab39add82b1ae1e2Neil Fuller        try {
231738c833d38d41f8f76eb7e77ab39add82b1ae1e2Neil Fuller            SerializationTester.deserializeHex(s);
232738c833d38d41f8f76eb7e77ab39add82b1ae1e2Neil Fuller            fail();
233738c833d38d41f8f76eb7e77ab39add82b1ae1e2Neil Fuller        } catch (InvalidClassException expected) {
234738c833d38d41f8f76eb7e77ab39add82b1ae1e2Neil Fuller        }
235738c833d38d41f8f76eb7e77ab39add82b1ae1e2Neil Fuller        assertFalse(wasSerializableInitializedFlag);
236738c833d38d41f8f76eb7e77ab39add82b1ae1e2Neil Fuller    }
237738c833d38d41f8f76eb7e77ab39add82b1ae1e2Neil Fuller
238738c833d38d41f8f76eb7e77ab39add82b1ae1e2Neil Fuller    // The WasExternalizable class before it was modified.
239738c833d38d41f8f76eb7e77ab39add82b1ae1e2Neil Fuller    /*
240738c833d38d41f8f76eb7e77ab39add82b1ae1e2Neil Fuller    public static class WasExternalizable implements Externalizable {
241738c833d38d41f8f76eb7e77ab39add82b1ae1e2Neil Fuller        static final long serialVersionUID = 0L;
242738c833d38d41f8f76eb7e77ab39add82b1ae1e2Neil Fuller
243738c833d38d41f8f76eb7e77ab39add82b1ae1e2Neil Fuller        @Override
244738c833d38d41f8f76eb7e77ab39add82b1ae1e2Neil Fuller        public void readExternal(ObjectInput input) throws IOException, ClassNotFoundException {
245738c833d38d41f8f76eb7e77ab39add82b1ae1e2Neil Fuller
246738c833d38d41f8f76eb7e77ab39add82b1ae1e2Neil Fuller        }
247738c833d38d41f8f76eb7e77ab39add82b1ae1e2Neil Fuller
248738c833d38d41f8f76eb7e77ab39add82b1ae1e2Neil Fuller        @Override
249738c833d38d41f8f76eb7e77ab39add82b1ae1e2Neil Fuller        public void writeExternal(ObjectOutput output) throws IOException {
250738c833d38d41f8f76eb7e77ab39add82b1ae1e2Neil Fuller
251738c833d38d41f8f76eb7e77ab39add82b1ae1e2Neil Fuller        }
252738c833d38d41f8f76eb7e77ab39add82b1ae1e2Neil Fuller    }
253738c833d38d41f8f76eb7e77ab39add82b1ae1e2Neil Fuller    */
254738c833d38d41f8f76eb7e77ab39add82b1ae1e2Neil Fuller
255738c833d38d41f8f76eb7e77ab39add82b1ae1e2Neil Fuller    public static boolean wasExternalizableInitializedFlag = false;
256738c833d38d41f8f76eb7e77ab39add82b1ae1e2Neil Fuller
257738c833d38d41f8f76eb7e77ab39add82b1ae1e2Neil Fuller    @SuppressWarnings("unused") // Required for deserialization test
258738c833d38d41f8f76eb7e77ab39add82b1ae1e2Neil Fuller    public static class WasExternalizable implements Serializable {
259738c833d38d41f8f76eb7e77ab39add82b1ae1e2Neil Fuller        static final long serialVersionUID = 0L;
260738c833d38d41f8f76eb7e77ab39add82b1ae1e2Neil Fuller        static {
261738c833d38d41f8f76eb7e77ab39add82b1ae1e2Neil Fuller            SerializationTest.wasExternalizableInitializedFlag = true;
262738c833d38d41f8f76eb7e77ab39add82b1ae1e2Neil Fuller        }
263738c833d38d41f8f76eb7e77ab39add82b1ae1e2Neil Fuller
264738c833d38d41f8f76eb7e77ab39add82b1ae1e2Neil Fuller    }
265738c833d38d41f8f76eb7e77ab39add82b1ae1e2Neil Fuller
266738c833d38d41f8f76eb7e77ab39add82b1ae1e2Neil Fuller    public void testDeserializeWasExternalizableClass() throws Exception {
267738c833d38d41f8f76eb7e77ab39add82b1ae1e2Neil Fuller        // This was created by serializing a WasExternalizable when it was externalizable.
268738c833d38d41f8f76eb7e77ab39add82b1ae1e2Neil Fuller        // String s = SerializationTester.serializeHex(new WasExternalizable());
269738c833d38d41f8f76eb7e77ab39add82b1ae1e2Neil Fuller        final String s = "aced0005737200336c6962636f72652e6a6176612e696f2e53657269616c697a6174696f6"
270738c833d38d41f8f76eb7e77ab39add82b1ae1e2Neil Fuller                + "e546573742457617345787465726e616c697a61626c6500000000000000000c0000787078";
271738c833d38d41f8f76eb7e77ab39add82b1ae1e2Neil Fuller
272729d4ecafff8e6af5a71e4fecb2007917cbc2e2aNeil Fuller        assertFalse(wasExternalizableInitializedFlag);
273738c833d38d41f8f76eb7e77ab39add82b1ae1e2Neil Fuller        try {
274738c833d38d41f8f76eb7e77ab39add82b1ae1e2Neil Fuller            SerializationTester.deserializeHex(s);
275738c833d38d41f8f76eb7e77ab39add82b1ae1e2Neil Fuller            fail();
276738c833d38d41f8f76eb7e77ab39add82b1ae1e2Neil Fuller        } catch (InvalidClassException expected) {
277738c833d38d41f8f76eb7e77ab39add82b1ae1e2Neil Fuller        }
278738c833d38d41f8f76eb7e77ab39add82b1ae1e2Neil Fuller        // Unlike other similar tests static initialization will take place if the local class is
279738c833d38d41f8f76eb7e77ab39add82b1ae1e2Neil Fuller        // Serializable or Externalizable because serialVersionUID field is accessed.
280738c833d38d41f8f76eb7e77ab39add82b1ae1e2Neil Fuller        // The RI appears to do the same.
281738c833d38d41f8f76eb7e77ab39add82b1ae1e2Neil Fuller        assertTrue(wasExternalizableInitializedFlag);
282738c833d38d41f8f76eb7e77ab39add82b1ae1e2Neil Fuller    }
283738c833d38d41f8f76eb7e77ab39add82b1ae1e2Neil Fuller
284738c833d38d41f8f76eb7e77ab39add82b1ae1e2Neil Fuller    // The WasEnum class before it was modified.
285738c833d38d41f8f76eb7e77ab39add82b1ae1e2Neil Fuller    /*
286738c833d38d41f8f76eb7e77ab39add82b1ae1e2Neil Fuller    public enum WasEnum {
287738c833d38d41f8f76eb7e77ab39add82b1ae1e2Neil Fuller        VALUE
288738c833d38d41f8f76eb7e77ab39add82b1ae1e2Neil Fuller    }
289738c833d38d41f8f76eb7e77ab39add82b1ae1e2Neil Fuller    */
290738c833d38d41f8f76eb7e77ab39add82b1ae1e2Neil Fuller
291738c833d38d41f8f76eb7e77ab39add82b1ae1e2Neil Fuller    public static boolean wasEnumInitializedFlag = false;
292738c833d38d41f8f76eb7e77ab39add82b1ae1e2Neil Fuller
293738c833d38d41f8f76eb7e77ab39add82b1ae1e2Neil Fuller    @SuppressWarnings("unused") // Required for deserialization test
294738c833d38d41f8f76eb7e77ab39add82b1ae1e2Neil Fuller    public static class WasEnum {
295738c833d38d41f8f76eb7e77ab39add82b1ae1e2Neil Fuller        static final long serialVersionUID = 0L;
296738c833d38d41f8f76eb7e77ab39add82b1ae1e2Neil Fuller        static {
297738c833d38d41f8f76eb7e77ab39add82b1ae1e2Neil Fuller            SerializationTest.wasEnumInitializedFlag = true;
298738c833d38d41f8f76eb7e77ab39add82b1ae1e2Neil Fuller        }
299738c833d38d41f8f76eb7e77ab39add82b1ae1e2Neil Fuller    }
300738c833d38d41f8f76eb7e77ab39add82b1ae1e2Neil Fuller
301738c833d38d41f8f76eb7e77ab39add82b1ae1e2Neil Fuller    public void testDeserializeWasEnum() throws Exception {
302738c833d38d41f8f76eb7e77ab39add82b1ae1e2Neil Fuller        // This was created by serializing a WasEnum when it was an enum.
303738c833d38d41f8f76eb7e77ab39add82b1ae1e2Neil Fuller        // String s = SerializationTester.serializeHex(WasEnum.VALUE);
304738c833d38d41f8f76eb7e77ab39add82b1ae1e2Neil Fuller        final String s = "aced00057e7200296c6962636f72652e6a6176612e696f2e53657269616c697a6174696f6"
305738c833d38d41f8f76eb7e77ab39add82b1ae1e2Neil Fuller                + "e5465737424576173456e756d00000000000000001200007872000e6a6176612e6c616e672e456e7"
306738c833d38d41f8f76eb7e77ab39add82b1ae1e2Neil Fuller                + "56d0000000000000000120000787074000556414c5545";
307738c833d38d41f8f76eb7e77ab39add82b1ae1e2Neil Fuller
308729d4ecafff8e6af5a71e4fecb2007917cbc2e2aNeil Fuller        assertFalse(wasEnumInitializedFlag);
309738c833d38d41f8f76eb7e77ab39add82b1ae1e2Neil Fuller        try {
310738c833d38d41f8f76eb7e77ab39add82b1ae1e2Neil Fuller            SerializationTester.deserializeHex(s);
311738c833d38d41f8f76eb7e77ab39add82b1ae1e2Neil Fuller            fail();
312738c833d38d41f8f76eb7e77ab39add82b1ae1e2Neil Fuller        } catch (InvalidClassException expected) {
313738c833d38d41f8f76eb7e77ab39add82b1ae1e2Neil Fuller        }
314738c833d38d41f8f76eb7e77ab39add82b1ae1e2Neil Fuller        assertFalse(wasEnumInitializedFlag);
315738c833d38d41f8f76eb7e77ab39add82b1ae1e2Neil Fuller    }
316738c833d38d41f8f76eb7e77ab39add82b1ae1e2Neil Fuller
317738c833d38d41f8f76eb7e77ab39add82b1ae1e2Neil Fuller    // The WasObject class before it was modified.
318738c833d38d41f8f76eb7e77ab39add82b1ae1e2Neil Fuller    /*
319738c833d38d41f8f76eb7e77ab39add82b1ae1e2Neil Fuller    public static class WasObject implements java.io.Serializable {
320738c833d38d41f8f76eb7e77ab39add82b1ae1e2Neil Fuller        static final long serialVersionUID = 0L;
321738c833d38d41f8f76eb7e77ab39add82b1ae1e2Neil Fuller        private int i;
322738c833d38d41f8f76eb7e77ab39add82b1ae1e2Neil Fuller    }
323738c833d38d41f8f76eb7e77ab39add82b1ae1e2Neil Fuller    */
324738c833d38d41f8f76eb7e77ab39add82b1ae1e2Neil Fuller
325738c833d38d41f8f76eb7e77ab39add82b1ae1e2Neil Fuller    public static boolean wasObjectInitializedFlag;
326738c833d38d41f8f76eb7e77ab39add82b1ae1e2Neil Fuller
327738c833d38d41f8f76eb7e77ab39add82b1ae1e2Neil Fuller    @SuppressWarnings("unused") // Required for deserialization test
328738c833d38d41f8f76eb7e77ab39add82b1ae1e2Neil Fuller    public enum WasObject {
329738c833d38d41f8f76eb7e77ab39add82b1ae1e2Neil Fuller        VALUE;
330738c833d38d41f8f76eb7e77ab39add82b1ae1e2Neil Fuller
331738c833d38d41f8f76eb7e77ab39add82b1ae1e2Neil Fuller        static {
332738c833d38d41f8f76eb7e77ab39add82b1ae1e2Neil Fuller            SerializationTest.wasObjectInitializedFlag = true;
333738c833d38d41f8f76eb7e77ab39add82b1ae1e2Neil Fuller        }
334738c833d38d41f8f76eb7e77ab39add82b1ae1e2Neil Fuller    }
335738c833d38d41f8f76eb7e77ab39add82b1ae1e2Neil Fuller
336738c833d38d41f8f76eb7e77ab39add82b1ae1e2Neil Fuller    public void testDeserializeWasObject() throws Exception {
337738c833d38d41f8f76eb7e77ab39add82b1ae1e2Neil Fuller        // This was created by serializing a WasObject when it wasn't yet an enum.
338738c833d38d41f8f76eb7e77ab39add82b1ae1e2Neil Fuller        // String s = SerializationTester.serializeHex(new WasObject());
339738c833d38d41f8f76eb7e77ab39add82b1ae1e2Neil Fuller        final String s = "aced00057372002b6c6962636f72652e6a6176612e696f2e53657269616c697a6174696f6"
340738c833d38d41f8f76eb7e77ab39add82b1ae1e2Neil Fuller                + "e54657374245761734f626a656374000000000000000002000149000169787000000000";
341738c833d38d41f8f76eb7e77ab39add82b1ae1e2Neil Fuller
342729d4ecafff8e6af5a71e4fecb2007917cbc2e2aNeil Fuller        assertFalse(wasObjectInitializedFlag);
343738c833d38d41f8f76eb7e77ab39add82b1ae1e2Neil Fuller        try {
344738c833d38d41f8f76eb7e77ab39add82b1ae1e2Neil Fuller            SerializationTester.deserializeHex(s);
345738c833d38d41f8f76eb7e77ab39add82b1ae1e2Neil Fuller            fail();
346738c833d38d41f8f76eb7e77ab39add82b1ae1e2Neil Fuller        } catch (InvalidClassException expected) {
347738c833d38d41f8f76eb7e77ab39add82b1ae1e2Neil Fuller        }
348738c833d38d41f8f76eb7e77ab39add82b1ae1e2Neil Fuller        assertFalse(wasObjectInitializedFlag);
349738c833d38d41f8f76eb7e77ab39add82b1ae1e2Neil Fuller    }
350738c833d38d41f8f76eb7e77ab39add82b1ae1e2Neil Fuller
351738c833d38d41f8f76eb7e77ab39add82b1ae1e2Neil Fuller    @SuppressWarnings("unused") // Required for deserialization test
352738c833d38d41f8f76eb7e77ab39add82b1ae1e2Neil Fuller    public enum EnumMissingValue {
353738c833d38d41f8f76eb7e77ab39add82b1ae1e2Neil Fuller        /*MISSING_VALUE*/
354738c833d38d41f8f76eb7e77ab39add82b1ae1e2Neil Fuller    }
355738c833d38d41f8f76eb7e77ab39add82b1ae1e2Neil Fuller
356738c833d38d41f8f76eb7e77ab39add82b1ae1e2Neil Fuller    public void testDeserializeEnumMissingValue() throws Exception {
357738c833d38d41f8f76eb7e77ab39add82b1ae1e2Neil Fuller        // This was created by serializing a EnumMissingValue when it had MISSING_VALUE.
358738c833d38d41f8f76eb7e77ab39add82b1ae1e2Neil Fuller        // String s = SerializationTester.serializeHex(EnumMissingValue.MISSING_VALUE);
359738c833d38d41f8f76eb7e77ab39add82b1ae1e2Neil Fuller        final String s = "aced00057e7200326c6962636f72652e6a6176612e696f2e53657269616c697a6174696f6"
360738c833d38d41f8f76eb7e77ab39add82b1ae1e2Neil Fuller                + "e5465737424456e756d4d697373696e6756616c756500000000000000001200007872000e6a61766"
361738c833d38d41f8f76eb7e77ab39add82b1ae1e2Neil Fuller                + "12e6c616e672e456e756d0000000000000000120000787074000d4d495353494e475f56414c5545";
362738c833d38d41f8f76eb7e77ab39add82b1ae1e2Neil Fuller
363738c833d38d41f8f76eb7e77ab39add82b1ae1e2Neil Fuller        try {
364738c833d38d41f8f76eb7e77ab39add82b1ae1e2Neil Fuller            SerializationTester.deserializeHex(s);
365738c833d38d41f8f76eb7e77ab39add82b1ae1e2Neil Fuller            fail();
366738c833d38d41f8f76eb7e77ab39add82b1ae1e2Neil Fuller        } catch (InvalidObjectException expected) {
367738c833d38d41f8f76eb7e77ab39add82b1ae1e2Neil Fuller        }
368738c833d38d41f8f76eb7e77ab39add82b1ae1e2Neil Fuller    }
369738c833d38d41f8f76eb7e77ab39add82b1ae1e2Neil Fuller
370738c833d38d41f8f76eb7e77ab39add82b1ae1e2Neil Fuller
371738c833d38d41f8f76eb7e77ab39add82b1ae1e2Neil Fuller    public static Object hasStaticInitializerObject;
372738c833d38d41f8f76eb7e77ab39add82b1ae1e2Neil Fuller
373738c833d38d41f8f76eb7e77ab39add82b1ae1e2Neil Fuller    public static class HasStaticInitializer implements Serializable {
374738c833d38d41f8f76eb7e77ab39add82b1ae1e2Neil Fuller        static {
375738c833d38d41f8f76eb7e77ab39add82b1ae1e2Neil Fuller            SerializationTest.hasStaticInitializerObject = new Object();
376738c833d38d41f8f76eb7e77ab39add82b1ae1e2Neil Fuller        }
377738c833d38d41f8f76eb7e77ab39add82b1ae1e2Neil Fuller    }
378738c833d38d41f8f76eb7e77ab39add82b1ae1e2Neil Fuller
379738c833d38d41f8f76eb7e77ab39add82b1ae1e2Neil Fuller    public void testDeserializeStaticInitializerIsRunEventually() throws Exception {
380738c833d38d41f8f76eb7e77ab39add82b1ae1e2Neil Fuller        // This was created by serializing a HasStaticInitializer
381738c833d38d41f8f76eb7e77ab39add82b1ae1e2Neil Fuller        // String s = SerializationTester.serializeHex(new HasStaticInitializer());
382738c833d38d41f8f76eb7e77ab39add82b1ae1e2Neil Fuller        final String s = "aced0005737200366c6962636f72652e6a6176612e696f2e53657269616c697a6174696f6"
383738c833d38d41f8f76eb7e77ab39add82b1ae1e2Neil Fuller                + "e5465737424486173537461746963496e697469616c697a6572138aa8ed9e9b660a0200007870";
384738c833d38d41f8f76eb7e77ab39add82b1ae1e2Neil Fuller
385738c833d38d41f8f76eb7e77ab39add82b1ae1e2Neil Fuller        // Confirm the ClassLoader behaves as it should.
386738c833d38d41f8f76eb7e77ab39add82b1ae1e2Neil Fuller        Class.forName(
387738c833d38d41f8f76eb7e77ab39add82b1ae1e2Neil Fuller                HasStaticInitializer.class.getName(),
388738c833d38d41f8f76eb7e77ab39add82b1ae1e2Neil Fuller                false /* shouldInitialize */,
389738c833d38d41f8f76eb7e77ab39add82b1ae1e2Neil Fuller                Thread.currentThread().getContextClassLoader());
390738c833d38d41f8f76eb7e77ab39add82b1ae1e2Neil Fuller        assertNull(hasStaticInitializerObject);
391738c833d38d41f8f76eb7e77ab39add82b1ae1e2Neil Fuller
392738c833d38d41f8f76eb7e77ab39add82b1ae1e2Neil Fuller        SerializationTester.deserializeHex(s);
393738c833d38d41f8f76eb7e77ab39add82b1ae1e2Neil Fuller
394738c833d38d41f8f76eb7e77ab39add82b1ae1e2Neil Fuller        assertNotNull(hasStaticInitializerObject);
395738c833d38d41f8f76eb7e77ab39add82b1ae1e2Neil Fuller    }
396738c833d38d41f8f76eb7e77ab39add82b1ae1e2Neil Fuller
397738c833d38d41f8f76eb7e77ab39add82b1ae1e2Neil Fuller    @SuppressWarnings("unused") // Required for deserialization test
398738c833d38d41f8f76eb7e77ab39add82b1ae1e2Neil Fuller    public static /*interface*/ class WasInterface {
399738c833d38d41f8f76eb7e77ab39add82b1ae1e2Neil Fuller    }
400738c833d38d41f8f76eb7e77ab39add82b1ae1e2Neil Fuller
401738c833d38d41f8f76eb7e77ab39add82b1ae1e2Neil Fuller    @SuppressWarnings("unused") // Required for deserialization test
402738c833d38d41f8f76eb7e77ab39add82b1ae1e2Neil Fuller    public static class SerializableInvocationHandler implements InvocationHandler, Serializable {
403738c833d38d41f8f76eb7e77ab39add82b1ae1e2Neil Fuller        @Override
404738c833d38d41f8f76eb7e77ab39add82b1ae1e2Neil Fuller        public Object invoke(Object proxy, Method method, Object[] args) {
405738c833d38d41f8f76eb7e77ab39add82b1ae1e2Neil Fuller            return null;
406738c833d38d41f8f76eb7e77ab39add82b1ae1e2Neil Fuller        }
407738c833d38d41f8f76eb7e77ab39add82b1ae1e2Neil Fuller    }
408738c833d38d41f8f76eb7e77ab39add82b1ae1e2Neil Fuller
409738c833d38d41f8f76eb7e77ab39add82b1ae1e2Neil Fuller    public void testDeserializeProxyWasInterface() throws Exception {
410738c833d38d41f8f76eb7e77ab39add82b1ae1e2Neil Fuller        // This was created by serializing a proxy referencing WasInterface when it was an
411738c833d38d41f8f76eb7e77ab39add82b1ae1e2Neil Fuller        // interface.
412738c833d38d41f8f76eb7e77ab39add82b1ae1e2Neil Fuller        // Object o = Proxy.newProxyInstance(
413738c833d38d41f8f76eb7e77ab39add82b1ae1e2Neil Fuller        //        Thread.currentThread().getContextClassLoader(),
414738c833d38d41f8f76eb7e77ab39add82b1ae1e2Neil Fuller        //        new Class[] { WasInterface.class },
415738c833d38d41f8f76eb7e77ab39add82b1ae1e2Neil Fuller        //        new SerializableInvocationHandler());
416738c833d38d41f8f76eb7e77ab39add82b1ae1e2Neil Fuller        // String s = SerializationTester.serializeHex(o);
417738c833d38d41f8f76eb7e77ab39add82b1ae1e2Neil Fuller        final String s = "aced0005737d00000001002e6c6962636f72652e6a6176612e696f2e53657269616c697a6"
418738c833d38d41f8f76eb7e77ab39add82b1ae1e2Neil Fuller                + "174696f6e5465737424576173496e74657266616365787200176a6176612e6c616e672e7265666c6"
419738c833d38d41f8f76eb7e77ab39add82b1ae1e2Neil Fuller                + "563742e50726f7879e127da20cc1043cb0200014c0001687400254c6a6176612f6c616e672f72656"
420738c833d38d41f8f76eb7e77ab39add82b1ae1e2Neil Fuller                + "66c6563742f496e766f636174696f6e48616e646c65723b78707372003f6c6962636f72652e6a617"
421738c833d38d41f8f76eb7e77ab39add82b1ae1e2Neil Fuller                + "6612e696f2e53657269616c697a6174696f6e546573742453657269616c697a61626c65496e766f6"
422738c833d38d41f8f76eb7e77ab39add82b1ae1e2Neil Fuller                + "36174696f6e48616e646c6572e6ceffa2941ee3210200007870";
423738c833d38d41f8f76eb7e77ab39add82b1ae1e2Neil Fuller        try {
424738c833d38d41f8f76eb7e77ab39add82b1ae1e2Neil Fuller            SerializationTester.deserializeHex(s);
425738c833d38d41f8f76eb7e77ab39add82b1ae1e2Neil Fuller            fail();
426738c833d38d41f8f76eb7e77ab39add82b1ae1e2Neil Fuller        } catch (ClassNotFoundException expected) {
427738c833d38d41f8f76eb7e77ab39add82b1ae1e2Neil Fuller        }
428738c833d38d41f8f76eb7e77ab39add82b1ae1e2Neil Fuller    }
429738c833d38d41f8f76eb7e77ab39add82b1ae1e2Neil Fuller
430738c833d38d41f8f76eb7e77ab39add82b1ae1e2Neil Fuller    @SuppressWarnings("unused") // Required for deserialization test
431738c833d38d41f8f76eb7e77ab39add82b1ae1e2Neil Fuller    public static class WasSerializableInvocationHandler
432738c833d38d41f8f76eb7e77ab39add82b1ae1e2Neil Fuller            implements InvocationHandler /*, Serializable*/ {
433738c833d38d41f8f76eb7e77ab39add82b1ae1e2Neil Fuller        static final long serialVersionUID = 0L;
434738c833d38d41f8f76eb7e77ab39add82b1ae1e2Neil Fuller
435738c833d38d41f8f76eb7e77ab39add82b1ae1e2Neil Fuller        @Override
436738c833d38d41f8f76eb7e77ab39add82b1ae1e2Neil Fuller        public Object invoke(Object proxy, Method method, Object[] args) {
437738c833d38d41f8f76eb7e77ab39add82b1ae1e2Neil Fuller            return null;
438738c833d38d41f8f76eb7e77ab39add82b1ae1e2Neil Fuller        }
439738c833d38d41f8f76eb7e77ab39add82b1ae1e2Neil Fuller    }
440738c833d38d41f8f76eb7e77ab39add82b1ae1e2Neil Fuller
441738c833d38d41f8f76eb7e77ab39add82b1ae1e2Neil Fuller    public void testDeserializeProxyInvocationHandlerWasSerializable() throws Exception {
442738c833d38d41f8f76eb7e77ab39add82b1ae1e2Neil Fuller        // This was created by serializing a proxy referencing WasSerializableInvocationHandler when
443738c833d38d41f8f76eb7e77ab39add82b1ae1e2Neil Fuller        // it was Serializable.
444738c833d38d41f8f76eb7e77ab39add82b1ae1e2Neil Fuller        // Object o = Proxy.newProxyInstance(
445738c833d38d41f8f76eb7e77ab39add82b1ae1e2Neil Fuller        //        Thread.currentThread().getContextClassLoader(),
446738c833d38d41f8f76eb7e77ab39add82b1ae1e2Neil Fuller        //        new Class[] { Comparable.class },
447738c833d38d41f8f76eb7e77ab39add82b1ae1e2Neil Fuller        //        new WasSerializableInvocationHandler());
448738c833d38d41f8f76eb7e77ab39add82b1ae1e2Neil Fuller        // String s = SerializationTester.serializeHex(o);
449738c833d38d41f8f76eb7e77ab39add82b1ae1e2Neil Fuller        final String s = "aced0005737d0000000100146a6176612e6c616e672e436f6d70617261626c65787200176"
450738c833d38d41f8f76eb7e77ab39add82b1ae1e2Neil Fuller                + "a6176612e6c616e672e7265666c6563742e50726f7879e127da20cc1043cb0200014c00016874002"
451738c833d38d41f8f76eb7e77ab39add82b1ae1e2Neil Fuller                + "54c6a6176612f6c616e672f7265666c6563742f496e766f636174696f6e48616e646c65723b78707"
452738c833d38d41f8f76eb7e77ab39add82b1ae1e2Neil Fuller                + "37200426c6962636f72652e6a6176612e696f2e53657269616c697a6174696f6e546573742457617"
453738c833d38d41f8f76eb7e77ab39add82b1ae1e2Neil Fuller                + "353657269616c697a61626c65496e766f636174696f6e48616e646c6572000000000000000002000"
454738c833d38d41f8f76eb7e77ab39add82b1ae1e2Neil Fuller                + "07870";
455738c833d38d41f8f76eb7e77ab39add82b1ae1e2Neil Fuller        try {
456738c833d38d41f8f76eb7e77ab39add82b1ae1e2Neil Fuller            SerializationTester.deserializeHex(s);
457738c833d38d41f8f76eb7e77ab39add82b1ae1e2Neil Fuller            fail();
458738c833d38d41f8f76eb7e77ab39add82b1ae1e2Neil Fuller        } catch (InvalidClassException expected) {
459738c833d38d41f8f76eb7e77ab39add82b1ae1e2Neil Fuller        }
460738c833d38d41f8f76eb7e77ab39add82b1ae1e2Neil Fuller    }
4611ffc4b2e242d1ba40ceb30b21510f0f26bd5aaa2Jesse Wilson}
462