1 /*
2 * Copyright (c) 2026, 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 * @summary Test jdk.internal.value.ValueClass against preview-only things
27 * @modules java.base/jdk.internal.value
28 * @library /test/lib
29 * @enablePreview
30 * @compile ${test.file}
31 * @run driver jdk.test.lib.helpers.StrictProcessor
32 * ValueClassPreviewTest$StrictStuff
33 * @run junit ${test.main.class}
34 */
35
36 import java.util.Optional;
37 import java.util.OptionalInt;
38
39 import jdk.internal.value.ValueClass;
40 import jdk.test.lib.helpers.StrictInit;
41 import org.junit.jupiter.api.Test;
42
43 import static org.junit.jupiter.api.Assertions.*;
44
45 class ValueClassPreviewTest {
46 @Test
47 void testHasBinaryPayload() {
48 assertTrue(ValueClass.hasBinaryPayload(Integer.class));
49 assertTrue(ValueClass.hasBinaryPayload(OptionalInt.class));
50 assertFalse(ValueClass.hasBinaryPayload(Optional.class));
51
52 value record R1(int a, long b, float c) {}
53 assertTrue(ValueClass.hasBinaryPayload(R1.class));
54 value record R2(R1 a) {}
55 assertTrue(ValueClass.hasBinaryPayload(R2.class));
56 value record R3(String a) {}
57 assertFalse(ValueClass.hasBinaryPayload(R3.class));
58 value record R4(R3 a) {}
59 assertFalse(ValueClass.hasBinaryPayload(R4.class));
60 }
61
62 @Test
63 void testSpecialCopy() {
64 Object[] original = makeArray(4);
65 assertThrows(NegativeArraySizeException.class, () -> ValueClass.copyOfSpecialArray(original, -1));
66 assertArrayEquals(original, ValueClass.copyOfSpecialArray(original, 4));
67 Object[] padded = makeArray(5);
68 padded[4] = null;
69 assertArrayEquals(padded, ValueClass.copyOfSpecialArray(original, 5));
70 Object[] truncated = makeArray(3);
71 assertArrayEquals(truncated, ValueClass.copyOfSpecialArray(original, 3));
72 }
73
74 @Test
75 void testSpecialCopyOfRange() {
76 Object[] original = makeArray(4);
77 assertThrows(ArrayIndexOutOfBoundsException.class, () -> ValueClass.copyOfRangeSpecialArray(original, -1, 5));
78 assertThrows(ArrayIndexOutOfBoundsException.class, () -> ValueClass.copyOfRangeSpecialArray(original, 5, 5));
79 assertThrows(IllegalArgumentException.class, () -> ValueClass.copyOfRangeSpecialArray(original, 4, 2));
80 assertArrayEquals(original, ValueClass.copyOfRangeSpecialArray(original, 0, 4));
81 Object[] padded = makeArray(5);
82 padded[4] = null;
83 assertArrayEquals(padded, ValueClass.copyOfRangeSpecialArray(original, 0, 5));
84 Object[] truncated = makeArray(3);
85 assertArrayEquals(truncated, ValueClass.copyOfRangeSpecialArray(original, 0, 3));
86 }
87
88 private static Object[] makeArray(int l) {
89 Object[] arr = ValueClass.newNullableAtomicArray(Integer.class, l);
90 for (int i = 0; i < l; i++) {
91 arr[i] = Integer.valueOf(i);
92 }
93 return arr;
94 }
95
96 abstract static value class AbstractValue {
97 int a;
98
99 AbstractValue(int a) {
100 this.a = a;
101 }
102 }
103
104 static value class ChildValue extends AbstractValue {
105 ChildValue(int a) {
106 super(a);
107 }
108 }
109
110 static class StrictStuff {
111 @StrictInit int i;
112
113 StrictStuff() {
114 i = 5;
115 super();
116 }
117 }
118
119 @Test
120 void testHasStrictInstanceField() {
121 assertFalse(ValueClass.hasStrictInstanceField(int.class), "primitive");
122 assertFalse(ValueClass.hasStrictInstanceField(int[].class), "array");
123 assertFalse(ValueClass.hasStrictInstanceField(Runnable.class), "interface");
124 assertTrue(ValueClass.hasStrictInstanceField(Integer.class), "1 prim field");
125 assertTrue(ValueClass.hasStrictInstanceField(Optional.class), "1 ref field");
126 assertFalse(ValueClass.hasStrictInstanceField(Number.class), "no-field AVC");
127 assertTrue(ValueClass.hasStrictInstanceField(AbstractValue.class), "AVC with field");
128 assertFalse(ValueClass.hasStrictInstanceField(ChildValue.class), "no immediately declared field");
129 record EmptyRec() {}
130 value record EmptyValueRec() {}
131 record Rec(String s) {}
132 value record ValueRec(String s) {}
133 assertFalse(ValueClass.hasStrictInstanceField(EmptyRec.class), "empty identity record");
134 assertFalse(ValueClass.hasStrictInstanceField(EmptyValueRec.class), "empty value record");
135 assertTrue(ValueClass.hasStrictInstanceField(Rec.class), "identity record");
136 assertTrue(ValueClass.hasStrictInstanceField(ValueRec.class), "value record");
137 }
138 }