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  * @bug 8377576
 27  * @summary Test jdk.internal.value.ValueClass with and without preview
 28  * @modules java.base/jdk.internal.misc
 29  *          java.base/jdk.internal.value
 30  * @run junit ValueClassCompatibilityTest
 31  * @run junit/othervm --enable-preview ValueClassCompatibilityTest
 32  */
 33 
 34 import java.util.ArrayList;
 35 import java.util.Optional;
 36 
 37 import jdk.internal.misc.PreviewFeatures;
 38 import jdk.internal.value.ValueClass;
 39 import org.junit.jupiter.api.Test;
 40 
 41 import static org.junit.jupiter.api.Assertions.*;
 42 
 43 class ValueClassCompatibilityTest {
 44     @Test
 45     void testIsValueObjectCompatible() {
 46         isValueObjectCompatibleCase(false, int.class, "primitive");
 47         isValueObjectCompatibleCase(true, Object.class, "Object");
 48         isValueObjectCompatibleCase(true, Number.class, "abstract value class");
 49         isValueObjectCompatibleCase(true, Integer.class, "final value class");
 50         isValueObjectCompatibleCase(false, ClassValue.class, "abstract identity class");
 51         isValueObjectCompatibleCase(false, ArrayList.class, "identity class");
 52         isValueObjectCompatibleCase(false, String.class, "final identity class");
 53         isValueObjectCompatibleCase(true, Comparable.class, "interface");
 54         isValueObjectCompatibleCase(false, int[].class, "array class");
 55         isValueObjectCompatibleCase(false, Object[].class, "array class");
 56         isValueObjectCompatibleCase(false, Number[].class, "array class");
 57         isValueObjectCompatibleCase(false, Integer[].class, "array class");
 58         isValueObjectCompatibleCase(false, ClassValue[].class, "array class");
 59         isValueObjectCompatibleCase(false, ArrayList[].class, "array class");
 60         isValueObjectCompatibleCase(false, String[].class, "array class");
 61         isValueObjectCompatibleCase(false, Comparable[].class, "array class");
 62     }
 63 
 64     private static void isValueObjectCompatibleCase(boolean expected, Class<?> arg, String classification) {
 65         assertEquals(PreviewFeatures.isEnabled() && expected,
 66                      ValueClass.isValueObjectCompatible(arg),
 67                      () -> classification + ": " + arg.getTypeName());
 68     }
 69 
 70     @Test
 71     void testIsConcreteValueClass() {
 72         isConcreteValueClassCase(false, int.class, "primitive");
 73         isConcreteValueClassCase(false, Object.class, "Object");
 74         isConcreteValueClassCase(false, Number.class, "abstract value class");
 75         isConcreteValueClassCase(true, Integer.class, "final value class");
 76         isConcreteValueClassCase(false, ClassValue.class, "abstract identity class");
 77         isConcreteValueClassCase(false, ArrayList.class, "identity class");
 78         isConcreteValueClassCase(false, String.class, "final identity class");
 79         isConcreteValueClassCase(false, Comparable.class, "interface");
 80         isConcreteValueClassCase(false, int[].class, "array class");
 81         isConcreteValueClassCase(false, Object[].class, "array class");
 82         isConcreteValueClassCase(false, Number[].class, "array class");
 83         isConcreteValueClassCase(false, Integer[].class, "array class");
 84         isConcreteValueClassCase(false, ClassValue[].class, "array class");
 85         isConcreteValueClassCase(false, ArrayList[].class, "array class");
 86         isConcreteValueClassCase(false, String[].class, "array class");
 87         isConcreteValueClassCase(false, Comparable[].class, "array class");
 88     }
 89 
 90     private static void isConcreteValueClassCase(boolean expected, Class<?> arg, String classification) {
 91         assertEquals(PreviewFeatures.isEnabled() && expected,
 92                      ValueClass.isConcreteValueClass(arg),
 93                      () -> classification + ": " + arg.getTypeName());
 94     }
 95 
 96     @Test
 97     void testBinaryPayload() {
 98         // Actual value class cases are tested in ValueClassPreviewTest
 99         assertTrue(ValueClass.hasBinaryPayload(int.class), "primitive");
100         binaryPayloadCase(false, Object.class, "Object");
101         binaryPayloadCase(false, Number.class, "abstract value class");
102         binaryPayloadCase(true, Integer.class, "final value class (wrapper)");
103         binaryPayloadCase(false, Optional.class, "final value class (reference)");
104         binaryPayloadCase(false, ClassValue.class, "abstract identity class");
105         binaryPayloadCase(false, ArrayList.class, "identity class");
106         binaryPayloadCase(false, String.class, "final identity class");
107         binaryPayloadCase(false, Comparable.class, "interface");
108         binaryPayloadCase(false, int[].class, "array class");
109         binaryPayloadCase(false, Object[].class, "array class");
110         binaryPayloadCase(false, Number[].class, "array class");
111         binaryPayloadCase(false, Integer[].class, "array class");
112         binaryPayloadCase(false, ClassValue[].class, "array class");
113         binaryPayloadCase(false, ArrayList[].class, "array class");
114         binaryPayloadCase(false, String[].class, "array class");
115         binaryPayloadCase(false, Comparable[].class, "array class");
116     }
117 
118     private static void binaryPayloadCase(boolean expected, Class<?> arg, String classification) {
119         assertEquals(PreviewFeatures.isEnabled() && expected,
120                 ValueClass.hasBinaryPayload(arg),
121                 () -> classification + ": " + arg.getTypeName());
122     }
123 }