From 8c09ff51c6e36db520637b8ef396f730908d2174 Mon Sep 17 00:00:00 2001 From: Severin Gehwolf Date: Tue, 22 Mar 2022 21:04:01 +0100 Subject: [PATCH] Add regression test for record annotations This adds a simple app using record annotations, for which a native image gets generated. This is a regression test for the fix described in issue #3984 --- .github/workflows/main.yml | 4 + .gitignore | 3 +- substratevm/mx.substratevm/mx_substratevm.py | 34 ++++++++ .../native-image-record-annot-tests/pom.xml | 53 +++++++++++++ .../src/main/java/recordannotations/F.java | 30 ++++++++ .../src/main/java/recordannotations/Main.java | 77 +++++++++++++++++++ .../src/main/java/recordannotations/RCA.java | 38 +++++++++ .../src/main/java/recordannotations/RCA2.java | 37 +++++++++ .../META-INF/native-image/reflect-config.json | 11 +++ 9 files changed, 286 insertions(+), 1 deletion(-) create mode 100644 substratevm/src/native-image-record-annot-tests/pom.xml create mode 100644 substratevm/src/native-image-record-annot-tests/src/main/java/recordannotations/F.java create mode 100644 substratevm/src/native-image-record-annot-tests/src/main/java/recordannotations/Main.java create mode 100644 substratevm/src/native-image-record-annot-tests/src/main/java/recordannotations/RCA.java create mode 100644 substratevm/src/native-image-record-annot-tests/src/main/java/recordannotations/RCA2.java create mode 100644 substratevm/src/native-image-record-annot-tests/src/main/resources/META-INF/native-image/reflect-config.json diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 25035d790e7b5..d7b3f934724f6 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -110,6 +110,10 @@ jobs: JDK: "labsjdk-ce-17" GATE: "style,fullbuild" PRIMARY: "espresso" + - env: + JDK: "labsjdk-ce-17" + GATE: "recordannotation" + PRIMARY: "substratevm" steps: - uses: actions/checkout@v2 with: diff --git a/.gitignore b/.gitignore index fb85d1054fb75..47681c8052db0 100644 --- a/.gitignore +++ b/.gitignore @@ -52,4 +52,5 @@ bench-results.json jmh_result.json /vm/src/installer/dist/ /tools/generators/node_modules/ -/tools/generators/out/ \ No newline at end of file +/tools/generators/out/ +target/ diff --git a/substratevm/mx.substratevm/mx_substratevm.py b/substratevm/mx.substratevm/mx_substratevm.py index 81a0c7d403755..f1e768074311b 100644 --- a/substratevm/mx.substratevm/mx_substratevm.py +++ b/substratevm/mx.substratevm/mx_substratevm.py @@ -227,6 +227,7 @@ def __getattr__(self, name): 'muslcbuild', 'hellomodule', 'condconfig', + 'recordannotion', ]) def vm_native_image_path(config=None): @@ -473,6 +474,10 @@ def help_stdout_check(output): if t: hellomodule([]) + with Task('record annotation tests', tasks, tags=[GraalTags.recordannotation]) as t: + if t: + recordannotation([]) + def native_unittests_task(extra_build_args=None): if mx.is_windows(): @@ -1212,6 +1217,35 @@ def helloworld(args, config=None): """ run_helloworld_command(args, config, "helloworld") +@mx.command(suite_name=suite.name, command_name='recordannotation') +def recordannotation(args, config=None): + """ + builds a native image of an annotated Record-using app. + """ + jdk = get_jdk() + if jdk.javaCompliance >= '17': + # Build a record app module with maven + module_path = [] + proj_dir = join(suite.dir, 'src', 'native-image-record-annot-tests') + mx.run_maven(['-e', 'package'], cwd=proj_dir) + module_path.append(join(proj_dir, 'target', 'recordannotations.jar')) + config = GraalVMConfig.build(native_images=['native-image', 'lib:native-image-agent', 'lib:native-image-diagnostics-agent']) + with native_image_context(hosted_assertions=False, config=config) as native_image: + module_path_sep = ';' if mx.is_windows() else ':' + run_args = [ + '-ea', + '-p', module_path_sep.join(module_path), 'recordannotations.Main' + ] + # Build into native image + mx.log('Building image recordannotion: ' + str(module_path)) + build_dir = join(svmbuild_dir(), 'recordannotations') + built_image = native_image([ + '--verbose', '-H:Path=' + build_dir, + ] + run_args) + mx.log('Running image ' + built_image) + mx.run([built_image]) + else: + mx.log('Record annotations test skipped as the JDK does not support it.') @mx.command(suite_name=suite.name, command_name='hellomodule') def hellomodule(args): diff --git a/substratevm/src/native-image-record-annot-tests/pom.xml b/substratevm/src/native-image-record-annot-tests/pom.xml new file mode 100644 index 0000000000000..8f005d8e35333 --- /dev/null +++ b/substratevm/src/native-image-record-annot-tests/pom.xml @@ -0,0 +1,53 @@ + + + 4.0.0 + records + recordannotations + 1 + + recordannotations + + + 3.2.0 + 3.10.1 + UTF-8 + UTF-8 + + + + + java-17 + + 17 + + + recordannotations + + + org.apache.maven.plugins + maven-compiler-plugin + ${maven-compiler-plugin.version} + + 17 + 17 + + + + org.apache.maven.plugins + maven-jar-plugin + ${maven-jar-plugin.version} + + + + recordannotations.Main + + + + + + + + + + diff --git a/substratevm/src/native-image-record-annot-tests/src/main/java/recordannotations/F.java b/substratevm/src/native-image-record-annot-tests/src/main/java/recordannotations/F.java new file mode 100644 index 0000000000000..0e089dfd17a28 --- /dev/null +++ b/substratevm/src/native-image-record-annot-tests/src/main/java/recordannotations/F.java @@ -0,0 +1,30 @@ +/* + * Copyright (c) 2022, 2022, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package recordannotations; + +// Main record under test. See Main. +@RCA2 +record F(@RCA @RCA2 String name, @RCA2 int i) { +} diff --git a/substratevm/src/native-image-record-annot-tests/src/main/java/recordannotations/Main.java b/substratevm/src/native-image-record-annot-tests/src/main/java/recordannotations/Main.java new file mode 100644 index 0000000000000..90645909f37ec --- /dev/null +++ b/substratevm/src/native-image-record-annot-tests/src/main/java/recordannotations/Main.java @@ -0,0 +1,77 @@ +/* + * Copyright (c) 2022, 2022, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package recordannotations; + +import java.lang.annotation.Annotation; +import java.lang.reflect.RecordComponent; +import java.util.Arrays; +import java.util.List; + +public class Main { + + public static void main(String[] args) { + failIfAssertionsAreDisabled(); + + F x = new F("x", 1); + + RecordComponent[] recordComponents = x.getClass().getRecordComponents(); + assert recordComponents.length == 2; + + // Verify String component annotations + RecordComponent stringComp = recordComponents[0]; + List stringCompAnnot = Arrays.asList(stringComp.getAnnotations()); + assert stringCompAnnot.size() == 2 : "expected 2 record annotations for string component"; + assert stringCompAnnot.stream().anyMatch(a -> a.annotationType().getName().equals("recordannotations.RCA")); + assert stringCompAnnot.stream().anyMatch(a -> a.annotationType().getName().equals("recordannotations.RCA2")); + assert stringComp.getAnnotatedType().getType().getTypeName().equals(String.class.getTypeName()); + Annotation rcaAnnotation = stringComp.getAnnotation(RCA.class); + assert rcaAnnotation != null : "expected RCA annotation to be present"; + assert String.class.getTypeName().equals(stringComp.getGenericType().getTypeName()); + + // Verify int component annotations + RecordComponent intComp = recordComponents[1]; + List intCompAnnot = Arrays.asList(intComp.getAnnotations()); + assert intCompAnnot.size() == 1 : "expected 1 record annotations for int component"; + assert intCompAnnot.stream().anyMatch(a -> a.annotationType().getName().equals("recordannotations.RCA2")); + assert intComp.getAnnotatedType().getType().getTypeName().equals(int.class.getTypeName()); + assert intComp.getAnnotation(RCA.class) == null; + assert intComp.getAnnotation(RCA2.class) != null; + assert int.class.getTypeName().equals(intComp.getGenericType().getTypeName()); + + assert x.i() == 1; + assert "x".equals(x.name()); + + System.out.println("Record annotation tests passed!"); + } + + private static void failIfAssertionsAreDisabled() { + boolean enabled = false; + assert enabled = true; + if (!enabled) { + throw new AssertionError("This example requires that assertions are enabled (-ea)"); + } + } + +} diff --git a/substratevm/src/native-image-record-annot-tests/src/main/java/recordannotations/RCA.java b/substratevm/src/native-image-record-annot-tests/src/main/java/recordannotations/RCA.java new file mode 100644 index 0000000000000..ea85ea37c7f7a --- /dev/null +++ b/substratevm/src/native-image-record-annot-tests/src/main/java/recordannotations/RCA.java @@ -0,0 +1,38 @@ +/* + * Copyright (c) 2022, 2022, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package recordannotations; + +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Retention; +import java.lang.annotation.Target; +import java.lang.annotation.ElementType; + +@Retention(RetentionPolicy.RUNTIME) +@Target({ ElementType.RECORD_COMPONENT, ElementType.FIELD }) +@interface RCA { + // empty +} + diff --git a/substratevm/src/native-image-record-annot-tests/src/main/java/recordannotations/RCA2.java b/substratevm/src/native-image-record-annot-tests/src/main/java/recordannotations/RCA2.java new file mode 100644 index 0000000000000..3fd5bef21bb02 --- /dev/null +++ b/substratevm/src/native-image-record-annot-tests/src/main/java/recordannotations/RCA2.java @@ -0,0 +1,37 @@ +/* + * Copyright (c) 2022, 2022, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package recordannotations; + +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Retention; +import java.lang.annotation.Target; +import java.lang.annotation.ElementType; + +@Retention(RetentionPolicy.RUNTIME) +@Target({ ElementType.RECORD_COMPONENT, ElementType.FIELD, ElementType.TYPE }) +@interface RCA2 { + // empty +} diff --git a/substratevm/src/native-image-record-annot-tests/src/main/resources/META-INF/native-image/reflect-config.json b/substratevm/src/native-image-record-annot-tests/src/main/resources/META-INF/native-image/reflect-config.json new file mode 100644 index 0000000000000..84cf575967e44 --- /dev/null +++ b/substratevm/src/native-image-record-annot-tests/src/main/resources/META-INF/native-image/reflect-config.json @@ -0,0 +1,11 @@ +[ + { + "name" : "recordannotations.F", + "allDeclaredConstructors" : true, + "allPublicConstructors" : true, + "allDeclaredMethods" : true, + "allPublicMethods" : true, + "allDeclaredClasses" : true, + "allPublicClasses" : true + } +]