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 Basic tests for readResolve 28 * @run testng ReadResolveTest 29 * @run testng/othervm/java.security.policy=empty_security.policy ReadResolveTest 30 */ 31 package test.java.io.Serializable.records; 32 33 import java.io.ByteArrayInputStream; 34 import java.io.ByteArrayOutputStream; 35 import java.io.IOException; 36 import java.io.ObjectInputStream; 37 import java.io.ObjectOutputStream; 38 import java.io.Serial; 39 import java.io.Serializable; 40 import org.testng.annotations.DataProvider; 41 import org.testng.annotations.Test; 42 import static java.lang.String.format; 43 import static java.lang.System.out; 44 import static org.testng.Assert.assertEquals; 45 46 /** 47 * Tests records being used as a serial proxy. 48 */ 49 public class ReadResolveTest { 50 51 static class C1 implements Serializable { 52 private final int x; 53 private final int y; C1(int x, int y)54 C1(int x, int y) { this.x = x; this.y = y; } 55 private record SerProxy1(int x, int y) implements Serializable { 56 @Serial readResolve()57 private Object readResolve() { return new C1(x, y); } 58 } 59 @Serial writeReplace()60 private Object writeReplace() { 61 return new SerProxy1(x, y); 62 } 63 @Override equals(Object obj)64 public boolean equals(Object obj) { 65 return obj != null && obj instanceof C1 && ((C1)obj).x == this.x && ((C1)obj).y == y; 66 } 67 @Override toString()68 public String toString() { return format("C1[x=%x, y=%d]", x, y); } 69 } 70 71 static class C2 implements Serializable { 72 private record SerProxy2() implements Serializable { 73 @Serial readResolve()74 private Object readResolve() { return new C2(); } 75 } 76 @Serial writeReplace()77 private Object writeReplace() { 78 return new SerProxy2(); 79 } 80 @Override equals(Object obj)81 public boolean equals(Object obj) { 82 return obj != null && obj instanceof C2; 83 } 84 @Override toString()85 public String toString() { return "C2[]"; } 86 } 87 88 record R1 (int x, int y, String s) implements Serializable { 89 private record SerProxy3(int a, int b, String c) implements Serializable { 90 @Serial readResolve()91 private Object readResolve() { return new R1(a, b, c); } 92 } 93 @Serial writeReplace()94 private Object writeReplace() { 95 return new SerProxy3(x, y, s); 96 } 97 } 98 99 @DataProvider(name = "objectsToSerialize") objectsToSerialize()100 public Object[][] objectsToSerialize() { 101 return new Object[][] { 102 new Object[] { new C1(3,4) }, 103 new Object[] { new C2() }, 104 new Object[] { new R1(5, 6, "c") } 105 }; 106 } 107 108 @Test(dataProvider = "objectsToSerialize") testSerialize(Object objectToSerialize)109 public void testSerialize(Object objectToSerialize) throws Exception { 110 out.println("\n---"); 111 out.println("serializing : " + objectToSerialize); 112 Object deserializedObj = serializeDeserialize(objectToSerialize); 113 out.println("deserialized: " + deserializedObj); 114 assertEquals(deserializedObj, objectToSerialize); 115 } 116 117 // -- null replacement 118 119 record R10 () implements Serializable { 120 @Serial readResolve()121 private Object readResolve() { 122 return null; 123 } 124 } 125 126 @Test testNull()127 public void testNull() throws Exception { 128 out.println("\n---"); 129 Object objectToSerialize = new R10(); 130 out.println("serializing : " + objectToSerialize); 131 Object deserializedObj = serializeDeserialize(objectToSerialize); 132 out.println("deserialized: " + deserializedObj); 133 assertEquals(deserializedObj, null); 134 } 135 136 // --- infra 137 serialize(T obj)138 static <T> byte[] serialize(T obj) throws IOException { 139 ByteArrayOutputStream baos = new ByteArrayOutputStream(); 140 ObjectOutputStream oos = new ObjectOutputStream(baos); 141 oos.writeObject(obj); 142 oos.close(); 143 return baos.toByteArray(); 144 } 145 146 @SuppressWarnings("unchecked") deserialize(byte[] streamBytes)147 static <T> T deserialize(byte[] streamBytes) 148 throws IOException, ClassNotFoundException 149 { 150 ByteArrayInputStream bais = new ByteArrayInputStream(streamBytes); 151 ObjectInputStream ois = new ObjectInputStream(bais); 152 return (T) ois.readObject(); 153 } 154 serializeDeserialize(T obj)155 static <T> T serializeDeserialize(T obj) 156 throws IOException, ClassNotFoundException 157 { 158 return deserialize(serialize(obj)); 159 } 160 } 161 162