• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 package test.java.io.Serializable.records;
24 
25 /*
26  * @test
27  * @bug 8246774
28  * @summary Checks that the appropriate default value is given to the canonical ctr
29  * @run testng AbsentStreamValuesTest
30  * @run testng/othervm/java.security.policy=empty_security.policy AbsentStreamValuesTest
31  */
32 
33 import java.io.ByteArrayInputStream;
34 import java.io.ByteArrayOutputStream;
35 import java.io.DataOutputStream;
36 import java.io.IOException;
37 import java.io.ObjectInputStream;
38 import java.io.Serializable;
39 import org.testng.annotations.DataProvider;
40 import org.testng.annotations.Test;
41 import static java.io.ObjectStreamConstants.*;
42 import static java.lang.System.out;
43 import static org.testng.Assert.*;
44 
45 /**
46  * Basic test to check that default primitive / reference values are presented
47  * to the record's canonical constructor, for fields not in the stream.
48  */
49 public class AbsentStreamValuesTest {
50 
51     record R01(boolean  x) implements Serializable { }
52     record R02(byte     x) implements Serializable { }
53     record R03(short    x) implements Serializable { }
54     record R04(char     x) implements Serializable { }
55     record R05(int      x) implements Serializable { }
56     record R06(long     x) implements Serializable { }
57     record R07(float    x) implements Serializable { }
58     record R08(double   x) implements Serializable { }
59     record R09(Object   x) implements Serializable { }
60     record R10(String   x) implements Serializable { }
61     record R11(int[]    x) implements Serializable { }
62     record R12(Object[] x) implements Serializable { }
63     record R13(R12      x) implements Serializable { }
64     record R14(R13[]    x) implements Serializable { }
65 
66     @DataProvider(name = "recordTypeAndExpectedValue")
recordTypeAndExpectedValue()67     public Object[][] recordTypeAndExpectedValue() {
68         return new Object[][] {
69                 new Object[] { R01.class, false    },
70                 new Object[] { R02.class, (byte)0  },
71                 new Object[] { R03.class, (short)0 },
72                 new Object[] { R04.class, '\u0000' },
73                 new Object[] { R05.class, 0        },
74                 new Object[] { R06.class, 0L       },
75                 new Object[] { R07.class, 0.0f     },
76                 new Object[] { R08.class, 0.0d     },
77                 new Object[] { R09.class, null     },
78                 new Object[] { R10.class, null     },
79                 new Object[] { R11.class, null     },
80                 new Object[] { R12.class, null     },
81                 new Object[] { R13.class, null     },
82                 new Object[] { R14.class, null     },
83         };
84     }
85 
86     @Test(dataProvider = "recordTypeAndExpectedValue")
testWithDifferentTypes(Class<?> clazz, Object expectedXValue)87     public void testWithDifferentTypes(Class<?> clazz, Object expectedXValue)
88         throws Exception
89     {
90         out.println("\n---");
91         assert clazz.isRecord();
92         byte[] bytes = minimalByteStreamFor(clazz.getName());
93 
94         Object obj = deserialize(bytes);
95         out.println("deserialized: " + obj);
96         Object actualXValue = clazz.getDeclaredMethod("x").invoke(obj);
97         assertEquals(actualXValue, expectedXValue);
98     }
99 
100     // --- all together
101 
102     record R15(boolean a, byte b, short c, char d, int e, long f, float g, double h, Object i, String j, long[] k, Object[] l)
103         implements Serializable { }
104 
105     @Test
testWithAllTogether()106     public void testWithAllTogether() throws Exception {
107         out.println("\n---");
108         byte[] bytes = minimalByteStreamFor(R15.class.getName());
109 
110         R15 obj = (R15)deserialize(bytes);
111         out.println("deserialized: " + obj);
112         assertEquals(obj.a, false);
113         assertEquals(obj.b, 0);
114         assertEquals(obj.c, 0);
115         assertEquals(obj.d, '\u0000');
116         assertEquals(obj.e, 0);
117         assertEquals(obj.f, 0l);
118         assertEquals(obj.g, 0f);
119         assertEquals(obj.h, 0d);
120         assertEquals(obj.i, null);
121         assertEquals(obj.j, null);
122         assertEquals(obj.k, null);
123         assertEquals(obj.l, null);
124     }
125 
126     // --- generic type
127 
128     record R16<T, U>(T t, U u) implements Serializable { }
129 
130     @Test
testGenericType()131     public void testGenericType() throws Exception {
132         out.println("\n---");
133         byte[] bytes = minimalByteStreamFor(R16.class.getName());
134 
135         R16 obj = (R16)deserialize(bytes);
136         out.println("deserialized: " + obj);
137         assertEquals(obj.t, null);
138         assertEquals(obj.u, null);
139     }
140 
141     // --- infra
142 
143     /**
144      * Returns the serial bytes for the given class name. The stream
145      * will have no stream field values.
146      */
minimalByteStreamFor(String className)147     static byte[] minimalByteStreamFor(String className) throws Exception {
148         ByteArrayOutputStream baos = new ByteArrayOutputStream();
149         DataOutputStream dos = new DataOutputStream(baos);
150         dos.writeShort(STREAM_MAGIC);
151         dos.writeShort(STREAM_VERSION);
152         dos.writeByte(TC_OBJECT);
153         dos.writeByte(TC_CLASSDESC);
154         dos.writeUTF(className);
155         dos.writeLong(0L);
156         dos.writeByte(SC_SERIALIZABLE);
157         dos.writeShort(0);             // number of fields
158         dos.writeByte(TC_ENDBLOCKDATA);   // no annotations
159         dos.writeByte(TC_NULL);           // no superclasses
160         dos.close();
161         return baos.toByteArray();
162     }
163 
164     @SuppressWarnings("unchecked")
deserialize(byte[] streamBytes)165     static <T> T deserialize(byte[] streamBytes)
166         throws IOException, ClassNotFoundException
167     {
168         ByteArrayInputStream bais = new ByteArrayInputStream(streamBytes);
169         ObjectInputStream ois  = new ObjectInputStream(bais);
170         return (T) ois.readObject();
171     }
172 }
173