1 /*
2 * Copyright (c) 2025, 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 8364095
27 * @summary InnerClasses generation against an old class with and without preview;
28 * no SUPER pollution and no missing IDENTITY
29 * @library /tools/lib /test/lib
30 * @run junit InnerClassesIdentityFlagTest
31 */
32
33 import java.lang.classfile.Attributes;
34 import java.lang.classfile.ClassFile;
35 import java.nio.file.Path;
36
37 import jdk.test.lib.compiler.CompilerUtils;
38 import org.junit.jupiter.api.Test;
39 import toolbox.ToolBox;
40
41 import static java.lang.classfile.ClassFile.ACC_IDENTITY;
42 import static java.lang.classfile.ClassFile.ACC_SUPER;
43 import static org.junit.jupiter.api.Assertions.assertEquals;
44
45 final class InnerClassesIdentityFlagTest {
46 /// Last release feature number with no value classes (preview exempt)
47 private static final String LAST_NON_VALUE_FEATURE = "25";
48
49 @Test
50 void test() throws Exception {
51 ToolBox toolBox = new ToolBox();
52 var libSourceDir = Path.of("libsrc");
53 var libDestinationDir = Path.of("libdest");
54 toolBox.writeJavaFiles(libSourceDir, """
55 public class One {
56 public class Inner {}
57 }
58 """);
59 CompilerUtils.compile(libSourceDir, libDestinationDir, "--release", LAST_NON_VALUE_FEATURE);
60
61 var userSourceDir = Path.of("usersrc");
62 var userRegularDestinationDir = Path.of("userdest");
63 var userPreviewDestinationDir = Path.of("userdestPreview");
64 toolBox.writeJavaFiles(userSourceDir, """
65 class Observer {
66 Observer() {
67 new One().new Inner();
68 super(); // triggers -XDforcePreview
69 }
70 }
71 """);
72 CompilerUtils.compile(userSourceDir, userRegularDestinationDir, "--release", LAST_NON_VALUE_FEATURE,
73 "-cp", libDestinationDir.toString());
74 CompilerUtils.compile(userSourceDir, userPreviewDestinationDir, "--release",
75 Integer.toString(Runtime.version().feature()), "--enable-preview", "-XDforcePreview",
76 "-cp", libDestinationDir.toString());
77
78 var regularClass = ClassFile.of().parse(userRegularDestinationDir.resolve("Observer.class"));
79 var previewClass = ClassFile.of().parse(userPreviewDestinationDir.resolve("Observer.class"));
80 assertEquals(0, regularClass.minorVersion());
81 assertEquals(ClassFile.PREVIEW_MINOR_VERSION, previewClass.minorVersion());
82 var regularRelation = regularClass.findAttribute(Attributes.innerClasses()).orElseThrow().classes().getFirst();
83 var previewRelation = previewClass.findAttribute(Attributes.innerClasses()).orElseThrow().classes().getFirst();
84 assertEquals("One$Inner", regularRelation.innerClass().asInternalName());
85 assertEquals("One$Inner", previewRelation.innerClass().asInternalName());
86 int regularFlags = regularRelation.flagsMask();
87 int previewFlags = previewRelation.flagsMask();
88 assertEquals(0, regularFlags & ACC_SUPER, () -> "ACC_SUPER pollution: " + Integer.toHexString(regularFlags));
89 assertEquals(ACC_IDENTITY, previewFlags & ACC_IDENTITY, () -> "Missing ACC_IDENTITY: " + Integer.toHexString(previewFlags));
90 }
91 }