ReflectionFactoryTest.java revision 15893:5c851d70cb76
1/* 2 * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. 8 * 9 * This code is distributed in the hope that it will be useful, but WITHOUT 10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 12 * version 2 for more details (a copy is included in the LICENSE file that 13 * accompanied this code). 14 * 15 * You should have received a copy of the GNU General Public License version 16 * 2 along with this work; if not, write to the Free Software Foundation, 17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 18 * 19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 20 * or visit www.oracle.com if you need additional information or have any 21 * questions. 22 */ 23 24import java.io.ByteArrayInputStream; 25import java.io.ByteArrayOutputStream; 26import java.io.Externalizable; 27import java.io.IOException; 28import java.io.ObjectInput; 29import java.io.ObjectInputStream; 30import java.io.ObjectOutput; 31import java.io.ObjectOutputStream; 32import java.io.OptionalDataException; 33import java.io.Serializable; 34import java.lang.invoke.MethodHandle; 35import java.lang.reflect.Constructor; 36import java.lang.reflect.InvocationTargetException; 37 38import sun.reflect.ReflectionFactory; 39 40import org.testng.Assert; 41import org.testng.annotations.BeforeClass; 42import org.testng.annotations.Test; 43import org.testng.annotations.DataProvider; 44import org.testng.TestNG; 45 46/* 47 * @test 48 * @bug 8137058 8164908 49 * @run testng ReflectionFactoryTest 50 * @run testng/othervm/policy=security.policy ReflectionFactoryTest 51 * @summary Basic test for the unsupported ReflectionFactory 52 * @modules jdk.unsupported 53 */ 54 55public class ReflectionFactoryTest { 56 57 // Initialized by init() 58 static ReflectionFactory factory; 59 60 @DataProvider(name = "ClassConstructors") 61 static Object[][] classConstructors() { 62 return new Object[][] { 63 {Object.class}, 64 {Foo.class}, 65 {Bar.class}, 66 }; 67 } 68 69 @BeforeClass 70 static void init() { 71 factory = ReflectionFactory.getReflectionFactory(); 72 } 73 74 /** 75 * Test that the correct Constructor is selected and run. 76 * @param type type of object to create 77 * @throws NoSuchMethodException - error 78 * @throws InstantiationException - error 79 * @throws IllegalAccessException - error 80 * @throws InvocationTargetException - error 81 */ 82 @Test(dataProvider="ClassConstructors") 83 static void testConstructor(Class<?> type) 84 throws NoSuchMethodException, InstantiationException, 85 IllegalAccessException, InvocationTargetException 86 { 87 @SuppressWarnings("unchecked") 88 Constructor<?> c = factory.newConstructorForSerialization(type); 89 90 Object o = c.newInstance(); 91 Assert.assertEquals(o.getClass(), type, "Instance is wrong type"); 92 if (o instanceof Foo) { 93 Foo foo = (Foo)o; 94 foo.check(); 95 } 96 } 97 98 static class Foo { 99 private int foo; 100 public Foo() { 101 this.foo = 1; 102 } 103 104 public String toString() { 105 return "foo: " + foo; 106 } 107 108 public void check() { 109 int expectedFoo = 1; 110 Assert.assertEquals(foo, expectedFoo, "foo() constructor not run"); 111 } 112 } 113 114 static class Bar extends Foo implements Serializable { 115 private int bar; 116 public Bar() { 117 this.bar = 1; 118 } 119 120 public String toString() { 121 return super.toString() + ", bar: " + bar; 122 } 123 124 public void check() { 125 super.check(); 126 int expectedBar = 0; 127 Assert.assertEquals(bar, expectedBar, "bar() constructor not run"); 128 } 129 } 130 131 /** 132 * Test newConstructorForExternalization returns the constructor and it can be called. 133 * @throws NoSuchMethodException - error 134 * @throws InstantiationException - error 135 * @throws IllegalAccessException - error 136 * @throws InvocationTargetException - error 137 */ 138 @Test 139 static void newConstructorForExternalization() 140 throws NoSuchMethodException, InstantiationException, 141 IllegalAccessException, InvocationTargetException { 142 Constructor<?> cons = factory.newConstructorForExternalization(Ext.class); 143 Ext ext = (Ext)cons.newInstance(); 144 Assert.assertEquals(ext.ext, 1, "Constructor not run"); 145 } 146 147 static class Ext implements Externalizable { 148 private static final long serialVersionUID = 1L; 149 150 int ext; 151 152 public Ext() { 153 ext = 1; 154 } 155 156 @Override 157 public void writeExternal(ObjectOutput out) throws IOException {} 158 159 @Override 160 public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException {} 161 } 162 163 @Test 164 static void testReadWriteObjectForSerialization() throws Throwable { 165 MethodHandle readObjectMethod = factory.readObjectForSerialization(Ser.class); 166 Assert.assertNotNull(readObjectMethod, "readObjectMethod not found"); 167 168 MethodHandle readObjectNoDataMethod = factory.readObjectNoDataForSerialization(Ser.class); 169 Assert.assertNotNull(readObjectNoDataMethod, "readObjectNoDataMethod not found"); 170 171 MethodHandle writeObjectMethod = factory.writeObjectForSerialization(Ser.class); 172 Assert.assertNotNull(writeObjectMethod, "writeObjectMethod not found"); 173 174 MethodHandle readResolveMethod = factory.readResolveForSerialization(Ser.class); 175 Assert.assertNotNull(readResolveMethod, "readResolveMethod not found"); 176 177 MethodHandle writeReplaceMethod = factory.writeReplaceForSerialization(Ser.class); 178 Assert.assertNotNull(writeReplaceMethod, "writeReplaceMethod not found"); 179 180 byte[] data = null; 181 try (ByteArrayOutputStream baos = new ByteArrayOutputStream(); 182 ObjectOutputStream oos = new ObjectOutputStream(baos)) { 183 Ser ser = new Ser(); 184 185 writeReplaceMethod.invoke(ser); 186 Assert.assertTrue(ser.writeReplaceCalled, "writeReplace not called"); 187 Assert.assertFalse(ser.writeObjectCalled, "writeObject should not have been called"); 188 189 writeObjectMethod.invoke(ser, oos); 190 Assert.assertTrue(ser.writeReplaceCalled, "writeReplace should have been called"); 191 Assert.assertTrue(ser.writeObjectCalled, "writeObject not called"); 192 oos.flush(); 193 data = baos.toByteArray(); 194 } 195 196 try (ByteArrayInputStream bais = new ByteArrayInputStream(data); 197 ObjectInputStream ois = new ObjectInputStream(bais)) { 198 Ser ser2 = new Ser(); 199 200 readObjectMethod.invoke(ser2, ois); 201 Assert.assertTrue(ser2.readObjectCalled, "readObject not called"); 202 Assert.assertFalse(ser2.readObjectNoDataCalled, "readObjectNoData should not be called"); 203 Assert.assertFalse(ser2.readResolveCalled, "readResolve should not be called"); 204 205 readObjectNoDataMethod.invoke(ser2, ois); 206 Assert.assertTrue(ser2.readObjectCalled, "readObject should have been called"); 207 Assert.assertTrue(ser2.readObjectNoDataCalled, "readObjectNoData not called"); 208 Assert.assertFalse(ser2.readResolveCalled, "readResolve should not be called"); 209 210 readResolveMethod.invoke(ser2); 211 Assert.assertTrue(ser2.readObjectCalled, "readObject should have been called"); 212 Assert.assertTrue(ser2.readObjectNoDataCalled, "readObjectNoData not called"); 213 Assert.assertTrue(ser2.readResolveCalled, "readResolve not called"); 214 } 215 } 216 217 @Test 218 static void hasStaticInitializer() { 219 boolean actual = factory.hasStaticInitializerForSerialization(Ser.class); 220 Assert.assertTrue(actual, "hasStaticInitializerForSerialization is wrong"); 221 } 222 223 static class Ser implements Serializable { 224 private static final long serialVersionUID = 2L; 225 static { 226 // Define a static class initialization method 227 } 228 229 boolean readObjectCalled = false; 230 boolean readObjectNoDataCalled = false; 231 boolean writeObjectCalled = false; 232 boolean readResolveCalled = false; 233 boolean writeReplaceCalled = false; 234 235 public Ser() {} 236 237 private void readObject(ObjectInputStream ois) throws IOException { 238 Assert.assertFalse(writeObjectCalled, "readObject called too many times"); 239 readObjectCalled = ois.readBoolean(); 240 } 241 242 private void readObjectNoData(ObjectInputStream ois) throws IOException { 243 Assert.assertFalse(readObjectNoDataCalled, "readObjectNoData called too many times"); 244 readObjectNoDataCalled = true; 245 } 246 247 private void writeObject(ObjectOutputStream oos) throws IOException { 248 Assert.assertFalse(writeObjectCalled, "writeObject called too many times"); 249 writeObjectCalled = true; 250 oos.writeBoolean(writeObjectCalled); 251 } 252 253 private Object writeReplace() { 254 Assert.assertFalse(writeReplaceCalled, "writeReplace called too many times"); 255 writeReplaceCalled = true; 256 return this; 257 } 258 259 private Object readResolve() { 260 Assert.assertFalse(readResolveCalled, "readResolve called too many times"); 261 readResolveCalled = true; 262 return this; 263 } 264 } 265 266 /** 267 * Test the constructor of OptionalDataExceptions. 268 */ 269 @Test 270 static void newOptionalDataException() { 271 OptionalDataException ode = factory.newOptionalDataExceptionForSerialization(true); 272 Assert.assertTrue(ode.eof, "eof wrong"); 273 ode = factory.newOptionalDataExceptionForSerialization(false); 274 Assert.assertFalse(ode.eof, "eof wrong"); 275 276 } 277 278 279 280 // Main can be used to run the tests from the command line with only testng.jar. 281 @SuppressWarnings("raw_types") 282 @Test(enabled = false) 283 public static void main(String[] args) { 284 Class<?>[] testclass = {ReflectionFactoryTest.class}; 285 TestNG testng = new TestNG(); 286 testng.setTestClasses(testclass); 287 testng.run(); 288 } 289} 290