1 /*
  2  * Copyright (c) 2024, 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 8331461
 27  * @summary [lworld] javac is generating a class file with the LoadableDescriptors attribute but with minor version '0'
 28  * @library /tools/lib
 29  * @modules
 30  *      jdk.compiler/com.sun.tools.javac.code
 31  *      jdk.compiler/com.sun.tools.javac.util
 32  *      jdk.compiler/com.sun.tools.javac.api
 33  *      jdk.compiler/com.sun.tools.javac.file
 34  *      jdk.compiler/com.sun.tools.javac.main
 35  * @build toolbox.ToolBox toolbox.JavacTask
 36  * @run main LoadableDescriptorsAttrTest2
 37  */
 38 
 39 import java.lang.classfile.Attributes;
 40 import java.lang.classfile.ClassFile;
 41 import java.nio.file.Path;
 42 import java.nio.file.Paths;
 43 
 44 import com.sun.tools.javac.util.Assert;
 45 
 46 import toolbox.TestRunner;
 47 import toolbox.ToolBox;
 48 
 49 public class LoadableDescriptorsAttrTest2 extends TestRunner {
 50     ToolBox tb = new ToolBox();
 51 
 52     public LoadableDescriptorsAttrTest2() {
 53         super(System.err);
 54     }
 55 
 56     protected void runTests() throws Exception {
 57         runTests(m -> new Object[] { Paths.get(m.getName()) });
 58     }
 59 
 60     Path[] findJavaFiles(Path... paths) throws Exception {
 61         return tb.findJavaFiles(paths);
 62     }
 63 
 64     public static void main(String... args) throws Exception {
 65         new LoadableDescriptorsAttrTest2().runTests();
 66     }
 67 
 68     @Test
 69     public void testLoadableDescField(Path base) throws Exception {
 70         Path src = base.resolve("src");
 71         tb.writeJavaFiles(src,
 72                 """
 73                 value class Val {}
 74                 """,
 75                 """
 76                 class Ident {
 77                     Val val;
 78                 }
 79                 """);
 80         Path classes = base.resolve("classes");
 81         tb.createDirectories(classes);
 82 
 83         new toolbox.JavacTask(tb)
 84                 .options("--enable-preview", "-source", Integer.toString(Runtime.version().feature()))
 85                 .outdir(classes)
 86                 .files(findJavaFiles(src))
 87                 .run()
 88                 .writeAll();
 89         Path classFilePath = classes.resolve("Ident.class");
 90         var classFile = ClassFile.of().parse(classFilePath);
 91         Assert.check(classFile.minorVersion() == 65535);
 92         Assert.check(classFile.findAttribute(Attributes.loadableDescriptors()).isPresent());
 93 
 94         // now with the value class in the classpath
 95         new toolbox.JavacTask(tb)
 96                 .options("--enable-preview", "-source", Integer.toString(Runtime.version().feature()), "-cp", classes.toString())
 97                 .outdir(classes)
 98                 .files(src.resolve("Ident.java"))
 99                 .run()
100                 .writeAll();
101 
102         classFilePath = classes.resolve("Ident.class");
103         classFile = ClassFile.of().parse(classFilePath);
104         Assert.check(classFile.minorVersion() == 65535);
105         Assert.check(classFile.findAttribute(Attributes.loadableDescriptors()).isPresent());
106     }
107 
108     @Test
109     public void testLoadableDescMethodArg(Path base) throws Exception {
110         Path src = base.resolve("src");
111         tb.writeJavaFiles(src,
112                 """
113                 value class Val {}
114                 """,
115                 """
116                 class Ident {
117                     void m(Val val) {}
118                 }
119                 """);
120         Path classes = base.resolve("classes");
121         tb.createDirectories(classes);
122 
123         new toolbox.JavacTask(tb)
124                 .options("--enable-preview", "-source", Integer.toString(Runtime.version().feature()))
125                 .outdir(classes)
126                 .files(findJavaFiles(src))
127                 .run()
128                 .writeAll();
129         Path classFilePath = classes.resolve("Ident.class");
130         var classFile = ClassFile.of().parse(classFilePath);
131         Assert.check(classFile.minorVersion() == 65535);
132         Assert.check(classFile.findAttribute(Attributes.loadableDescriptors()).isPresent());
133 
134         // now with the value class in the classpath
135         new toolbox.JavacTask(tb)
136                 .options("--enable-preview", "-source", Integer.toString(Runtime.version().feature()), "-cp", classes.toString())
137                 .outdir(classes)
138                 .files(src.resolve("Ident.java"))
139                 .run()
140                 .writeAll();
141 
142         classFilePath = classes.resolve("Ident.class");
143         classFile = ClassFile.of().parse(classFilePath);
144         Assert.check(classFile.minorVersion() == 65535);
145         Assert.check(classFile.findAttribute(Attributes.loadableDescriptors()).isPresent());
146 
147     }
148 
149     @Test
150     public void testLoadableDescReturnType(Path base) throws Exception {
151         Path src = base.resolve("src");
152         tb.writeJavaFiles(src,
153                 """
154                 value class Val {}
155                 """,
156                 """
157                 class Ident {
158                     Val m() {
159                         return null;
160                     }
161                 }
162                 """);
163         Path classes = base.resolve("classes");
164         tb.createDirectories(classes);
165 
166         new toolbox.JavacTask(tb)
167                 .options("--enable-preview", "-source", Integer.toString(Runtime.version().feature()))
168                 .outdir(classes)
169                 .files(findJavaFiles(src))
170                 .run()
171                 .writeAll();
172         Path classFilePath = classes.resolve("Ident.class");
173         var classFile = ClassFile.of().parse(classFilePath);
174         Assert.check(classFile.minorVersion() == 65535);
175         Assert.check(classFile.findAttribute(Attributes.loadableDescriptors()).isPresent());
176 
177 
178         // now with the value class in the classpath
179         new toolbox.JavacTask(tb)
180                 .options("--enable-preview", "-source", Integer.toString(Runtime.version().feature()), "-cp", classes.toString())
181                 .outdir(classes)
182                 .files(src.resolve("Ident.java"))
183                 .run()
184                 .writeAll();
185 
186         classFilePath = classes.resolve("Ident.class");
187         classFile = ClassFile.of().parse(classFilePath);
188         Assert.check(classFile.minorVersion() == 65535);
189         Assert.check(classFile.findAttribute(Attributes.loadableDescriptors()).isPresent());
190 
191     }
192 }