Skip to content

Commit

Permalink
Merge pull request #506 from graalvm/fniephaus/dev-build
Browse files Browse the repository at this point in the history
Bug fixes and improvements for GraalVM for JDK 21.
  • Loading branch information
olpaw authored Sep 13, 2023
2 parents 37277ff + e13d517 commit 8325440
Show file tree
Hide file tree
Showing 13 changed files with 200 additions and 37 deletions.
33 changes: 33 additions & 0 deletions .github/workflows/test-native-gradle-plugin.yml
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,39 @@ jobs:
with:
name: unit-tests-results
path: native-gradle-plugin/build/reports/tests/test/
functional-testing-gradle-plugin-dev:
name: "Functional testing (GraalVM Dev Build)"
runs-on: ${{ matrix.os }}
env:
IS_GRAALVM_DEV_BUILD: 'true'
strategy:
fail-fast: false
matrix:
java-version: [ 17 ]
os: [ ubuntu-20.04 ]
steps:
- name: "☁️ Checkout repository"
uses: actions/checkout@v2
- uses: ./.github/actions/prepare-environment
with:
java-version: ${{ matrix.java-version }}
github-token: ${{ secrets.GITHUB_TOKEN }}
- name: "🔧 Install GraalVM (dev)"
uses: graalvm/setup-graalvm@main
with:
components: 'native-image'
github-token: ${{ inputs.github-token }}
java-version: 'dev'
distribution: 'graalvm'
set-java-home: 'false'
- name: "❓ Check and test the plugin"
run: ./gradlew :native-gradle-plugin:functionalTest
- name: "📜 Upload functional tests results"
if: always()
uses: actions/upload-artifact@v2
with:
name: functional-tests-results-graalvm-dev
path: native-gradle-plugin/build/reports/tests/functionalTest/
functional-testing-gradle-plugin:
name: "Functional testing"
runs-on: ${{ matrix.os }}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,8 @@ configurations {
gradlePlugin.testSourceSets(sourceSets.functionalTest)
configurations.functionalTestImplementation.extendsFrom(configurations.testImplementation)

def graalVmHomeProvider = providers.environmentVariable("GRAALVM_HOME")
def isGraalVmDevBuild = providers.environmentVariable("IS_GRAALVM_DEV_BUILD")
def graalVm = javaToolchains.launcherFor {
languageVersion.set(JavaLanguageVersion.of(17))
// vendor.set(JvmVendorSpec.matching("Oracle Corporation"))
Expand All @@ -99,7 +101,17 @@ def fullFunctionalTest = tasks.register("fullFunctionalTest")
systemProperty('common.repo.url', configurations.functionalTestCommonRepository.incoming.files.files[0])
systemProperty('gradle.test.version', effectiveVersion)
systemProperty('versions.junit', libs.versions.junitJupiter.get())
environment('GRAALVM_HOME', graalVm.get().metadata.installationPath.asFile.absolutePath)
environment('GRAALVM_HOME', graalVmHomeProvider.
orElse(providers.provider(() -> graalVm.get().metadata.installationPath.asFile.absolutePath))
.map {
println("Test task $taskName will use GRAALVM_HOME = $it")
it
}
.get()
)
if (isGraalVmDevBuild.isPresent()) {
environment('IS_GRAALVM_DEV_BUILD', 'true')
}
testClassesDirs = sourceSets.functionalTest.output.classesDirs
classpath = sourceSets.functionalTest.runtimeClasspath
javaLauncher.set(graalVm)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -65,18 +65,6 @@ public void registerForReflection(Field... fields) {
RuntimeReflection.register(fields);
}

@Override
public void initializeAtBuildTime(String... classNames) {
for (String className : classNames) {
Class<?> clazz;
try {
clazz = Class.forName(className);
initializeAtBuildTime(clazz);
} catch (ClassNotFoundException e) {
JUnitPlatformFeature.debug("[Native Image Configuration] Failed to register class for build time initialization: %s Reason: %s", className, e);
}
}
}

@Override
public void initializeAtBuildTime(Class<?>... classes) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@
package org.graalvm.junit.platform.config.core;

import org.graalvm.junit.platform.JUnitPlatformFeature;
import org.graalvm.junit.platform.config.util.Utils;

import java.lang.reflect.Executable;
import java.lang.reflect.Field;
Expand All @@ -54,6 +55,10 @@ public interface NativeImageConfiguration {

void registerForReflection(Field... fields);

default void registerAllClassMembersForReflection(String... classNames) {
registerAllClassMembersForReflection(Utils.toClasses(classNames));
};

default void registerAllClassMembersForReflection(Class<?>... classes) {
for (Class<?> clazz : classes) {
JUnitPlatformFeature.debug("[Native Image Configuration] Registering for reflection: %s", clazz.getName());
Expand All @@ -64,7 +69,9 @@ default void registerAllClassMembersForReflection(Class<?>... classes) {
}
}

void initializeAtBuildTime(String... classNames);
default void initializeAtBuildTime(String... classNames) {
initializeAtBuildTime(Utils.toClasses(classNames));
};

void initializeAtBuildTime(Class<?>... classes);
}
Original file line number Diff line number Diff line change
Expand Up @@ -47,4 +47,8 @@ public interface PluginConfigProvider {

void onTestClassRegistered(Class<?> testClass, NativeImageConfiguration registry);

default int getMajorJDKVersion() {
return Runtime.version().feature();
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,7 @@ public class JupiterConfigProvider implements PluginConfigProvider {

@Override
public void onLoad(NativeImageConfiguration config) {
String[] buildTimeInitializedClasses = new String[]{
config.initializeAtBuildTime(
"org.junit.jupiter.engine.config.EnumConfigurationParameterConverter",
"org.junit.jupiter.engine.descriptor.ClassTestDescriptor",
"org.junit.jupiter.engine.descriptor.ClassBasedTestDescriptor",
Expand All @@ -84,23 +84,33 @@ public void onLoad(NativeImageConfiguration config) {
// new in Junit 5.10
"org.junit.platform.launcher.core.LauncherConfig",
"org.junit.jupiter.engine.config.InstantiatingConfigurationParameterConverter"
};
for (String className : buildTimeInitializedClasses) {
config.initializeAtBuildTime(className);
);

if (getMajorJDKVersion() >= 21) {
/* new with simulated class initialization */
config.initializeAtBuildTime(
"org.junit.jupiter.api.DisplayNameGenerator$Standard",
"org.junit.jupiter.api.extension.ConditionEvaluationResult",
"org.junit.jupiter.api.TestInstance$Lifecycle",
"org.junit.jupiter.engine.config.CachingJupiterConfiguration",
"org.junit.jupiter.engine.config.DefaultJupiterConfiguration",
"org.junit.jupiter.engine.descriptor.DynamicDescendantFilter",
"org.junit.jupiter.engine.descriptor.JupiterEngineDescriptor",
"org.junit.jupiter.engine.descriptor.NestedClassTestDescriptor",
"org.junit.jupiter.engine.execution.InterceptingExecutableInvoker",
"org.junit.jupiter.engine.execution.InterceptingExecutableInvoker$ReflectiveInterceptorCall",
"org.junit.jupiter.engine.execution.InterceptingExecutableInvoker$ReflectiveInterceptorCall$VoidMethodInterceptorCall",
"org.junit.jupiter.engine.execution.InvocationInterceptorChain",
"org.junit.jupiter.engine.JupiterTestEngine",
"org.junit.jupiter.params.provider.EnumSource$Mode$Validator"
);
}

String[] registeredForReflection = {

config.registerAllClassMembersForReflection(
"org.junit.jupiter.engine.extension.TimeoutExtension$ExecutorResource",
"org.junit.jupiter.engine.extension.TimeoutInvocationFactory$SingleThreadExecutorResource"
};
for (String className : registeredForReflection) {
try {
Class <?> executor = Class.forName(className);
config.registerAllClassMembersForReflection(executor);
} catch (ClassNotFoundException e) {
debug("Failed to register class for reflection. Reason: %s", e);
}
}
);
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ public class PlatformConfigProvider implements PluginConfigProvider {

@Override
public void onLoad(NativeImageConfiguration config) {
String[] buildTimeInitializedClasses = new String[] {
config.initializeAtBuildTime(
"org.junit.platform.launcher.TestIdentifier",
"org.junit.platform.launcher.core.InternalTestPlan",
"org.junit.platform.commons.util.StringUtils",
Expand All @@ -61,9 +61,30 @@ public void onLoad(NativeImageConfiguration config) {
"org.junit.platform.commons.util.ReflectionUtils",
// https://github.com/graalvm/native-build-tools/issues/300
"org.junit.platform.reporting.open.xml.OpenTestReportGeneratingListener"
};
for (String className : buildTimeInitializedClasses) {
config.initializeAtBuildTime(className);
);

if (getMajorJDKVersion() >= 21) {
/* new with simulated class initialization */
config.initializeAtBuildTime(
"org.junit.platform.engine.support.descriptor.ClassSource",
"org.junit.platform.engine.support.descriptor.MethodSource",
"org.junit.platform.engine.support.hierarchical.Node$ExecutionMode",
"org.junit.platform.engine.TestDescriptor$Type",
"org.junit.platform.engine.UniqueId",
"org.junit.platform.engine.UniqueId$Segment",
"org.junit.platform.launcher.core.DefaultLauncher",
"org.junit.platform.launcher.core.DefaultLauncherConfig",
"org.junit.platform.launcher.core.EngineExecutionOrchestrator",
"org.junit.platform.launcher.core.LauncherConfigurationParameters$ParameterProvider$2",
"org.junit.platform.launcher.core.LauncherConfigurationParameters$ParameterProvider$3",
"org.junit.platform.launcher.core.LauncherDiscoveryResult",
"org.junit.platform.launcher.core.LauncherListenerRegistry",
"org.junit.platform.launcher.core.ListenerRegistry",
"org.junit.platform.launcher.core.SessionPerRequestLauncher",
"org.junit.platform.launcher.LauncherSessionListener$1",
"org.junit.platform.launcher.listeners.UniqueIdTrackingListener",
"org.junit.platform.reporting.shadow.org.opentest4j.reporting.events.api.DocumentWriter$1"
);
}

try {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
/*
* Copyright (c) 2023, 2023, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* The Universal Permissive License (UPL), Version 1.0
*
* Subject to the condition set forth below, permission is hereby granted to any
* person obtaining a copy of this software, associated documentation and/or
* data (collectively the "Software"), free of charge and under any and all
* copyright rights in the Software, and any and all patent rights owned or
* freely licensable by each licensor hereunder covering either (i) the
* unmodified Software as contributed to or provided by such licensor, or (ii)
* the Larger Works (as defined below), to deal in both
*
* (a) the Software, and
*
* (b) any piece of software and/or hardware listed in the lrgrwrks.txt file if
* one is included with the Software each a "Larger Work" to which the Software
* is contributed by such licensors),
*
* without restriction, including without limitation the rights to copy, create
* derivative works of, display, perform, and distribute the Software and make,
* use, sell, offer for sale, import, export, have made, and have sold the
* Software and the Larger Work(s), and to sublicense the foregoing rights on
* either these or other terms.
*
* This license is subject to the following condition:
*
* The above copyright notice and either this complete permission notice or at a
* minimum a reference to the UPL must be included in all copies or substantial
* portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/

package org.graalvm.junit.platform.config.util;

import org.graalvm.junit.platform.JUnitPlatformFeature;

import java.util.Arrays;

public class Utils {
public static Class<?>[] toClasses(String... classNames) {
return Arrays.stream(classNames).map(className -> {
Class<?> clazz = null;
try {
clazz = Class.forName(className);
} catch (ClassNotFoundException e) {
JUnitPlatformFeature.debug("[Native Image Configuration] Failed to resolve: %s Reason: %s", className, e);
}
return clazz;
}).filter(c -> c != null).toArray(Class[]::new);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ public class VintageConfigProvider implements PluginConfigProvider {

@Override
public void onLoad(NativeImageConfiguration config) {
String[] buildTimeInitializedClasses = new String[]{
config.initializeAtBuildTime(
"org.junit.vintage.engine.descriptor.RunnerTestDescriptor",
"org.junit.vintage.engine.support.UniqueIdReader",
"org.junit.vintage.engine.support.UniqueIdStringifier",
Expand All @@ -57,9 +57,19 @@ public void onLoad(NativeImageConfiguration config) {
"org.junit.runners.JUnit4",
/* Workaround until we can register serializable classes from a native-image feature */
"org.junit.runner.Result"
};
for (String className : buildTimeInitializedClasses) {
config.initializeAtBuildTime(className);
);

if (getMajorJDKVersion() >= 21) {
/* new with simulated class initialization */
config.initializeAtBuildTime(
"java.lang.annotation.Annotation",
"org.junit.runners.model.FrameworkMethod",
"org.junit.runners.model.TestClass",
"org.junit.runners.ParentRunner$1",
"org.junit.Test",
"org.junit.vintage.engine.descriptor.VintageEngineDescriptor",
"org.junit.vintage.engine.VintageTestEngine"
);
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -116,7 +116,10 @@ public static String escapeArg(String arg) {
if (m.matches()) {
return arg;
}
return "'" + arg.replace("'", "'\"'\"'") + "'";
return "'" + arg
.replace("'", "'\"'\"'")
.replace("\\", "\\\\") /* for Windows paths */
+ "'";
}


Expand Down
5 changes: 5 additions & 0 deletions docs/src/docs/asciidoc/index.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,11 @@ If you are using alternative build systems, see <<alternative-build-systems.adoc
[[changelog]]
== Changelog

=== Release 0.9.27

* Update JUnit configuration for native testing on GraalVM for JDK 21 with `--strict-image-heap` mode.
* Fix path escaping problem for Windows users

=== Release 0.9.26

* Relax GraalVM version check for dev versions
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ package org.graalvm.buildtools.gradle

import org.graalvm.buildtools.gradle.fixtures.AbstractFunctionalTest
import spock.lang.Ignore
import spock.lang.IgnoreIf
import spock.lang.Issue
import spock.lang.Requires

Expand Down Expand Up @@ -217,6 +218,7 @@ class JavaApplicationFunctionalTest extends AbstractFunctionalTest {

}

@IgnoreIf({ System.getenv("IS_GRAALVM_DEV_BUILD") })
def "can build a native image with PGO instrumentation"() {
def pgoDir = file("src/pgo-profiles/main").toPath()
def nativeApp = file("build/native/nativeCompile/java-application-instrumented")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,8 @@ configurations {
}
}

val graalVmHomeProvider = providers.environmentVariable("GRAALVM_HOME")

// Add a task to run the functional tests
tasks.register<Test>("functionalTest") {
// Any change to samples invalidates functional tests
Expand All @@ -82,4 +84,10 @@ tasks.named("check") {

tasks.withType<Test>().configureEach {
useJUnitPlatform()
if (graalVmHomeProvider.isPresent) {
val graalvmHome = graalVmHomeProvider.get()
inputs.property("GRAALVM_HOME", graalvmHome)
environment("GRAALVM_HOME", graalvmHome)
println("Task $name will use GRAALVM_HOME = $graalvmHome")
}
}

0 comments on commit 8325440

Please sign in to comment.