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 }