1 /* 2 * Copyright (c) 2019, 2020, 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 24 /* 25 * @test 26 * @bug 8246774 27 * @summary Ensures that the serialization implementation can *always* access 28 * the record constructor 29 * @run testng ConstructorAccessTest 30 * @run testng/othervm/java.security.policy=empty_security.policy ConstructorAccessTest 31 */ 32 package test.java.io.Serializable.records; 33 34 import java.io.ByteArrayInputStream; 35 import java.io.ByteArrayOutputStream; 36 import java.io.IOException; 37 import java.io.ObjectInput; 38 import java.io.ObjectInputStream; 39 import java.io.ObjectOutput; 40 import java.io.ObjectOutputStream; 41 import java.io.Externalizable; 42 import java.io.Serializable; 43 import org.testng.annotations.DataProvider; 44 import org.testng.annotations.Test; 45 import static java.lang.System.out; 46 import static org.testng.Assert.assertEquals; 47 import static org.testng.Assert.fail; 48 49 /*implicit*/ record Aux1 (int x) implements Serializable { } 50 51 /*implicit*/ record Aux2 (int x) implements Serializable { } 52 53 public class ConstructorAccessTest { 54 55 public record A (int x) implements Serializable { } 56 57 protected static record B (long l) implements Serializable { } 58 59 /*implicit*/ static record C (float f) implements Serializable { } 60 61 private record D (double d) implements Serializable { } 62 63 interface ThrowingExternalizable extends Externalizable { writeExternal(ObjectOutput out)64 default void writeExternal(ObjectOutput out) { 65 fail("should not reach here"); 66 } readExternal(ObjectInput in)67 default void readExternal(ObjectInput in) { 68 fail("should not reach here"); 69 } 70 } 71 72 public record E (short s) implements ThrowingExternalizable { } 73 74 protected static record F (long l) implements ThrowingExternalizable { } 75 76 /*implicit*/ static record G (double d) implements ThrowingExternalizable { } 77 78 private record H (double d) implements ThrowingExternalizable { } 79 80 @DataProvider(name = "recordInstances") recordInstances()81 public Object[][] recordInstances() { 82 return new Object[][] { 83 new Object[] { new A(34) }, 84 new Object[] { new B(44L) }, 85 new Object[] { new C(4.5f) }, 86 new Object[] { new D(440d) }, 87 new Object[] { new E((short)12) }, 88 new Object[] { new F(45L) }, 89 new Object[] { new G(0.4d) }, 90 new Object[] { new H(440d) }, 91 new Object[] { new Aux1(63) }, 92 new Object[] { new Aux2(64) }, 93 }; 94 } 95 96 @Test(dataProvider = "recordInstances") roundTrip(Object objToSerialize)97 public void roundTrip(Object objToSerialize) throws Exception { 98 out.println("\n---"); 99 out.println("serializing : " + objToSerialize); 100 var objDeserialized = serializeDeserialize(objToSerialize); 101 out.println("deserialized: " + objDeserialized); 102 assertEquals(objToSerialize, objDeserialized); 103 assertEquals(objDeserialized, objToSerialize); 104 } 105 106 // --- 107 serialize(T obj)108 static <T> byte[] serialize(T obj) throws IOException { 109 ByteArrayOutputStream baos = new ByteArrayOutputStream(); 110 ObjectOutputStream oos = new ObjectOutputStream(baos); 111 oos.writeObject(obj); 112 oos.close(); 113 return baos.toByteArray(); 114 } 115 116 @SuppressWarnings("unchecked") deserialize(byte[] streamBytes)117 static <T> T deserialize(byte[] streamBytes) 118 throws IOException, ClassNotFoundException 119 { 120 ByteArrayInputStream bais = new ByteArrayInputStream(streamBytes); 121 ObjectInputStream ois = new ObjectInputStream(bais); 122 return (T) ois.readObject(); 123 } 124 serializeDeserialize(T obj)125 static <T> T serializeDeserialize(T obj) 126 throws IOException, ClassNotFoundException 127 { 128 return deserialize(serialize(obj)); 129 } 130 } 131