diff --git a/spring-core/src/main/java/org/springframework/aot/AotDetector.java b/spring-core/src/main/java/org/springframework/aot/AotDetector.java index 556e58f9bb..a3c1740733 100644 --- a/spring-core/src/main/java/org/springframework/aot/AotDetector.java +++ b/spring-core/src/main/java/org/springframework/aot/AotDetector.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2022 the original author or authors. + * Copyright 2002-2023 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -19,11 +19,14 @@ package org.springframework.aot; import org.springframework.core.NativeDetector; import org.springframework.core.SpringProperties; +import static org.springframework.core.NativeDetector.Context; + /** * Utility for determining if AOT-processed optimizations must be used rather * than the regular runtime. Strictly for internal use within the framework. * * @author Stephane Nicoll + * @author Sebastien Deleuze * @since 6.0 */ public abstract class AotDetector { @@ -36,6 +39,8 @@ public abstract class AotDetector { */ public static final String AOT_ENABLED = "spring.aot.enabled"; + private static final boolean inNativeImage = NativeDetector.inNativeImage(Context.RUNTIME, Context.BUILD_TIME); + /** * Determine whether AOT optimizations must be considered at runtime. This * is mandatory in a native image but can be triggered on the JVM using @@ -43,7 +48,7 @@ public abstract class AotDetector { * @return whether AOT optimizations must be considered */ public static boolean useGeneratedArtifacts() { - return (NativeDetector.inNativeImage() || SpringProperties.getFlag(AOT_ENABLED)); + return (inNativeImage || SpringProperties.getFlag(AOT_ENABLED)); } } diff --git a/spring-core/src/main/java/org/springframework/aot/nativex/feature/PreComputeFieldFeature.java b/spring-core/src/main/java/org/springframework/aot/nativex/feature/PreComputeFieldFeature.java index 4c8596b30e..ae9c33052e 100644 --- a/spring-core/src/main/java/org/springframework/aot/nativex/feature/PreComputeFieldFeature.java +++ b/spring-core/src/main/java/org/springframework/aot/nativex/feature/PreComputeFieldFeature.java @@ -33,8 +33,9 @@ import org.graalvm.nativeimage.hosted.Feature; class PreComputeFieldFeature implements Feature { private static Pattern[] patterns = { - Pattern.compile(Pattern.quote("org.springframework.core.NativeDetector#imageCode")), - Pattern.compile(Pattern.quote("org.springframework.cglib.core.AbstractClassGenerator#imageCode")), + Pattern.compile(Pattern.quote("org.springframework.core.NativeDetector#inNativeImage")), + Pattern.compile(Pattern.quote("org.springframework.cglib.core.AbstractClassGenerator#inNativeImage")), + Pattern.compile(Pattern.quote("org.springframework.aot.AotDetector#inNativeImage")), Pattern.compile(Pattern.quote("org.springframework.") + ".*#.*Present"), Pattern.compile(Pattern.quote("org.springframework.") + ".*#.*PRESENT"), Pattern.compile(Pattern.quote("reactor.") + ".*#.*Available"), diff --git a/spring-core/src/main/java/org/springframework/cglib/core/AbstractClassGenerator.java b/spring-core/src/main/java/org/springframework/cglib/core/AbstractClassGenerator.java index 9196cdf1b9..af66af94c9 100644 --- a/spring-core/src/main/java/org/springframework/cglib/core/AbstractClassGenerator.java +++ b/spring-core/src/main/java/org/springframework/cglib/core/AbstractClassGenerator.java @@ -43,8 +43,12 @@ abstract public class AbstractClassGenerator implements ClassGenerator { private static final boolean DEFAULT_USE_CACHE = Boolean.parseBoolean(System.getProperty("cglib.useCache", "true")); - // See https://github.com/oracle/graal/blob/master/sdk/src/org.graalvm.nativeimage/src/org/graalvm/nativeimage/ImageInfo.java - private static final boolean imageCode = (System.getProperty("org.graalvm.nativeimage.imagecode") != null); + private static final boolean inNativeImage; + + static { + String imageCode = System.getProperty("org.graalvm.nativeimage.imagecode"); + inNativeImage = "buildtime".equals(imageCode) || "runtime".equals(imageCode); + } private GeneratorStrategy strategy = DefaultGeneratorStrategy.INSTANCE; @@ -354,7 +358,7 @@ abstract public class AbstractClassGenerator implements ClassGenerator { } } // SPRING PATCH BEGIN - if (imageCode) { + if (inNativeImage) { throw new UnsupportedOperationException("CGLIB runtime enhancement not supported on native image. " + "Make sure to include a pre-generated class on the classpath instead: " + getClassName()); } diff --git a/spring-core/src/main/java/org/springframework/core/NativeDetector.java b/spring-core/src/main/java/org/springframework/core/NativeDetector.java index c3419e85c8..697af695e6 100644 --- a/spring-core/src/main/java/org/springframework/core/NativeDetector.java +++ b/spring-core/src/main/java/org/springframework/core/NativeDetector.java @@ -16,6 +16,8 @@ package org.springframework.core; +import org.springframework.lang.Nullable; + /** * A common delegate for detecting a GraalVM native image environment. * @@ -25,12 +27,61 @@ package org.springframework.core; public abstract class NativeDetector { // See https://github.com/oracle/graal/blob/master/sdk/src/org.graalvm.nativeimage/src/org/graalvm/nativeimage/ImageInfo.java - private static final boolean imageCode = (System.getProperty("org.graalvm.nativeimage.imagecode") != null); + @Nullable + private static final String imageCode = System.getProperty("org.graalvm.nativeimage.imagecode"); + + private static final boolean inNativeImage = (imageCode != null); /** - * Returns {@code true} if invoked in the context of image building or during image runtime, else {@code false}. + * Returns {@code true} if running in a native image context (for example {@code buildtime}, {@code runtime} or + * {@code agent}) expressed by setting {@code org.graalvm.nativeimage.imagecode} system property to any value, else {@code false}. */ public static boolean inNativeImage() { - return imageCode; + return inNativeImage; } + + /** + * Returns {@code true} if running in any of the specified native image context(s), else {@code false}. + * @param contexts the native image context(s) + * @since 6.0.10 + */ + public static boolean inNativeImage(Context... contexts) { + for (Context context: contexts) { + if (context.key.equals(imageCode)) { + return true; + } + } + return false; + } + + /** + * Native image context as defined in + * ImageInfo.java. + * + * @since 6.0.10 + */ + public enum Context { + + /** + * The code is executing in the context of image building. + */ + BUILD_TIME("buildtime"), + + /** + * The code is executing at image runtime. + */ + RUNTIME("runtime"); + + private final String key; + + Context(final String key) { + this.key = key; + } + + @Override + public String toString() { + return this.key; + } + } + } diff --git a/spring-test/src/main/java/org/springframework/test/context/aot/AotTestAttributes.java b/spring-test/src/main/java/org/springframework/test/context/aot/AotTestAttributes.java index 2f86fda382..cfb243b491 100644 --- a/spring-test/src/main/java/org/springframework/test/context/aot/AotTestAttributes.java +++ b/spring-test/src/main/java/org/springframework/test/context/aot/AotTestAttributes.java @@ -16,6 +16,7 @@ package org.springframework.test.context.aot; +import org.springframework.aot.AotDetector; import org.springframework.lang.Nullable; /** @@ -26,7 +27,7 @@ import org.springframework.lang.Nullable; * and run-time. At build time, test components can {@linkplain #setAttribute contribute} * attributes during the AOT processing phase. At run time, test components can * {@linkplain #getString(String) retrieve} attributes that were contributed at - * build time. If {@link TestAotDetector#useGeneratedArtifacts()} returns {@code true}, + * build time. If {@link AotDetector#useGeneratedArtifacts()} returns {@code true}, * run-time mode applies. * *

For example, if a test component computes something at build time that @@ -43,7 +44,7 @@ import org.springframework.lang.Nullable; * — can choose to contribute an attribute at any point in time. Note that * contributing an attribute during standard JVM test execution will not have any * adverse side effect since AOT attributes will be ignored in that scenario. In - * any case, you should use {@link TestAotDetector#useGeneratedArtifacts()} to determine + * any case, you should use {@link AotDetector#useGeneratedArtifacts()} to determine * if invocations of {@link #setAttribute(String, String)} and * {@link #removeAttribute(String)} are permitted. * @@ -70,12 +71,12 @@ public interface AotTestAttributes { * @param name the unique attribute name * @param value the associated attribute value * @throws UnsupportedOperationException if invoked during - * {@linkplain TestAotDetector#useGeneratedArtifacts() AOT run-time execution} + * {@linkplain AotDetector#useGeneratedArtifacts() AOT run-time execution} * @throws IllegalArgumentException if the provided value is {@code null} or * if an attempt is made to override an existing attribute * @see #setAttribute(String, boolean) * @see #removeAttribute(String) - * @see TestAotDetector#useGeneratedArtifacts() + * @see AotDetector#useGeneratedArtifacts() */ void setAttribute(String name, String value); @@ -87,13 +88,13 @@ public interface AotTestAttributes { * @param name the unique attribute name * @param value the associated attribute value * @throws UnsupportedOperationException if invoked during - * {@linkplain TestAotDetector#useGeneratedArtifacts() AOT run-time execution} + * {@linkplain AotDetector#useGeneratedArtifacts() AOT run-time execution} * @throws IllegalArgumentException if an attempt is made to override an * existing attribute * @see #setAttribute(String, String) * @see #removeAttribute(String) * @see Boolean#toString(boolean) - * @see TestAotDetector#useGeneratedArtifacts() + * @see AotDetector#useGeneratedArtifacts() */ default void setAttribute(String name, boolean value) { setAttribute(name, Boolean.toString(value)); @@ -103,8 +104,8 @@ public interface AotTestAttributes { * Remove the attribute stored under the provided name. * @param name the unique attribute name * @throws UnsupportedOperationException if invoked during - * {@linkplain TestAotDetector#useGeneratedArtifacts() AOT run-time execution} - * @see TestAotDetector#useGeneratedArtifacts() + * {@linkplain AotDetector#useGeneratedArtifacts() AOT run-time execution} + * @see AotDetector#useGeneratedArtifacts() * @see #setAttribute(String, String) */ void removeAttribute(String name); diff --git a/spring-test/src/main/java/org/springframework/test/context/aot/AotTestAttributesFactory.java b/spring-test/src/main/java/org/springframework/test/context/aot/AotTestAttributesFactory.java index 185b6a573c..1414083bd6 100644 --- a/spring-test/src/main/java/org/springframework/test/context/aot/AotTestAttributesFactory.java +++ b/spring-test/src/main/java/org/springframework/test/context/aot/AotTestAttributesFactory.java @@ -19,6 +19,7 @@ package org.springframework.test.context.aot; import java.util.Map; import java.util.concurrent.ConcurrentHashMap; +import org.springframework.aot.AotDetector; import org.springframework.lang.Nullable; /** @@ -39,7 +40,7 @@ final class AotTestAttributesFactory { /** * Get the underlying attributes map. *

If the map is not already loaded, this method loads the map from the - * generated class when running in {@linkplain TestAotDetector#useGeneratedArtifacts() + * generated class when running in {@linkplain AotDetector#useGeneratedArtifacts() * AOT execution mode} and otherwise creates a new map for storing attributes * during the AOT processing phase. */ @@ -49,7 +50,7 @@ final class AotTestAttributesFactory { synchronized (AotTestAttributesFactory.class) { attrs = attributes; if (attrs == null) { - attrs = (TestAotDetector.useGeneratedArtifacts() ? loadAttributesMap() : new ConcurrentHashMap<>()); + attrs = (AotDetector.useGeneratedArtifacts() ? loadAttributesMap() : new ConcurrentHashMap<>()); attributes = attrs; } } diff --git a/spring-test/src/main/java/org/springframework/test/context/aot/AotTestContextInitializers.java b/spring-test/src/main/java/org/springframework/test/context/aot/AotTestContextInitializers.java index 0dd5d91266..15b95e18ec 100644 --- a/spring-test/src/main/java/org/springframework/test/context/aot/AotTestContextInitializers.java +++ b/spring-test/src/main/java/org/springframework/test/context/aot/AotTestContextInitializers.java @@ -19,6 +19,7 @@ package org.springframework.test.context.aot; import java.util.Map; import java.util.function.Supplier; +import org.springframework.aot.AotDetector; import org.springframework.context.ApplicationContextInitializer; import org.springframework.context.ConfigurableApplicationContext; import org.springframework.lang.Nullable; @@ -29,7 +30,7 @@ import org.springframework.lang.Nullable; * *

Intended solely for internal use within the framework. * - *

If we are not running in {@linkplain TestAotDetector#useGeneratedArtifacts() + *

If we are not running in {@linkplain AotDetector#useGeneratedArtifacts() * AOT mode} or if a test class is not {@linkplain #isSupportedTestClass(Class) * supported} in AOT mode, {@link #getContextInitializer(Class)} and * {@link #getContextInitializerClass(Class)} will return {@code null}. diff --git a/spring-test/src/main/java/org/springframework/test/context/aot/AotTestContextInitializersFactory.java b/spring-test/src/main/java/org/springframework/test/context/aot/AotTestContextInitializersFactory.java index 1e6685c109..e130258a8e 100644 --- a/spring-test/src/main/java/org/springframework/test/context/aot/AotTestContextInitializersFactory.java +++ b/spring-test/src/main/java/org/springframework/test/context/aot/AotTestContextInitializersFactory.java @@ -19,6 +19,7 @@ package org.springframework.test.context.aot; import java.util.Map; import java.util.function.Supplier; +import org.springframework.aot.AotDetector; import org.springframework.context.ApplicationContextInitializer; import org.springframework.context.ConfigurableApplicationContext; import org.springframework.lang.Nullable; @@ -44,7 +45,7 @@ final class AotTestContextInitializersFactory { /** * Get the underlying map. *

If the map is not already loaded, this method loads the map from the - * generated class when running in {@linkplain TestAotDetector#useGeneratedArtifacts() + * generated class when running in {@linkplain AotDetector#useGeneratedArtifacts() * AOT execution mode} and otherwise creates an immutable, empty map. */ static Map>> getContextInitializers() { @@ -53,7 +54,7 @@ final class AotTestContextInitializersFactory { synchronized (AotTestContextInitializersFactory.class) { initializers = contextInitializers; if (initializers == null) { - initializers = (TestAotDetector.useGeneratedArtifacts() ? loadContextInitializersMap() : Map.of()); + initializers = (AotDetector.useGeneratedArtifacts() ? loadContextInitializersMap() : Map.of()); contextInitializers = initializers; } } @@ -67,7 +68,7 @@ final class AotTestContextInitializersFactory { synchronized (AotTestContextInitializersFactory.class) { initializerClasses = contextInitializerClasses; if (initializerClasses == null) { - initializerClasses = (TestAotDetector.useGeneratedArtifacts() ? loadContextInitializerClassesMap() : Map.of()); + initializerClasses = (AotDetector.useGeneratedArtifacts() ? loadContextInitializerClassesMap() : Map.of()); contextInitializerClasses = initializerClasses; } } diff --git a/spring-test/src/main/java/org/springframework/test/context/aot/DefaultAotTestAttributes.java b/spring-test/src/main/java/org/springframework/test/context/aot/DefaultAotTestAttributes.java index ac3dbfa1bd..966485d5b5 100644 --- a/spring-test/src/main/java/org/springframework/test/context/aot/DefaultAotTestAttributes.java +++ b/spring-test/src/main/java/org/springframework/test/context/aot/DefaultAotTestAttributes.java @@ -18,6 +18,7 @@ package org.springframework.test.context.aot; import java.util.Map; +import org.springframework.aot.AotDetector; import org.springframework.lang.Nullable; import org.springframework.util.Assert; @@ -60,7 +61,7 @@ class DefaultAotTestAttributes implements AotTestAttributes { private static void assertNotInAotRuntime() { - if (TestAotDetector.useGeneratedArtifacts()) { + if (AotDetector.useGeneratedArtifacts()) { throw new UnsupportedOperationException( "AOT attributes cannot be modified during AOT run-time execution"); } diff --git a/spring-test/src/main/java/org/springframework/test/context/aot/TestAotDetector.java b/spring-test/src/main/java/org/springframework/test/context/aot/TestAotDetector.java deleted file mode 100644 index f095d40ff1..0000000000 --- a/spring-test/src/main/java/org/springframework/test/context/aot/TestAotDetector.java +++ /dev/null @@ -1,58 +0,0 @@ -/* - * Copyright 2002-2023 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.springframework.test.context.aot; - -import org.springframework.aot.AotDetector; -import org.springframework.core.SpringProperties; -import org.springframework.util.StringUtils; - -/** - * TestContext framework specific utility for determining if AOT-processed - * optimizations must be used rather than the regular runtime. - * - *

Strictly for internal use within the framework. - * - * @author Sam Brannen - * @since 6.0.9 - */ -public abstract class TestAotDetector { - - /** - * Determine whether AOT optimizations must be considered at runtime. - *

This can be triggered using the {@value AotDetector#AOT_ENABLED} - * Spring property or via GraalVM's {@code "org.graalvm.nativeimage.imagecode"} - * JVM system property (if set to any non-empty value other than {@code agent}). - * @return {@code true} if AOT optimizations must be considered - * @see GraalVM's ImageInfo.java - * @see AotDetector#useGeneratedArtifacts() - */ - public static boolean useGeneratedArtifacts() { - return (SpringProperties.getFlag(AotDetector.AOT_ENABLED) || inNativeImage()); - } - - /** - * Determine if we are currently running within a GraalVM native image from - * the perspective of the TestContext framework. - * @return {@code true} if the {@code org.graalvm.nativeimage.imagecode} JVM - * system property has been set to any value other than {@code agent}. - */ - private static boolean inNativeImage() { - String imageCode = System.getProperty("org.graalvm.nativeimage.imagecode"); - return (StringUtils.hasText(imageCode) && !"agent".equalsIgnoreCase(imageCode.trim())); - } - -} diff --git a/spring-test/src/main/java/org/springframework/test/context/aot/TestContextAotGenerator.java b/spring-test/src/main/java/org/springframework/test/context/aot/TestContextAotGenerator.java index 1909a5a056..cfeb405ab1 100644 --- a/spring-test/src/main/java/org/springframework/test/context/aot/TestContextAotGenerator.java +++ b/spring-test/src/main/java/org/springframework/test/context/aot/TestContextAotGenerator.java @@ -26,6 +26,7 @@ import java.util.stream.Stream; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; +import org.springframework.aot.AotDetector; import org.springframework.aot.generate.ClassNameGenerator; import org.springframework.aot.generate.DefaultGenerationContext; import org.springframework.aot.generate.GeneratedClasses; @@ -122,7 +123,7 @@ public class TestContextAotGenerator { * @throws TestContextAotException if an error occurs during AOT processing */ public void processAheadOfTime(Stream> testClasses) throws TestContextAotException { - Assert.state(!TestAotDetector.useGeneratedArtifacts(), "Cannot perform AOT processing during AOT run-time execution"); + Assert.state(!AotDetector.useGeneratedArtifacts(), "Cannot perform AOT processing during AOT run-time execution"); try { resetAotFactories(); diff --git a/spring-test/src/main/java/org/springframework/test/context/cache/DefaultCacheAwareContextLoaderDelegate.java b/spring-test/src/main/java/org/springframework/test/context/cache/DefaultCacheAwareContextLoaderDelegate.java index a6ae78aa5c..8f537a9e55 100644 --- a/spring-test/src/main/java/org/springframework/test/context/cache/DefaultCacheAwareContextLoaderDelegate.java +++ b/spring-test/src/main/java/org/springframework/test/context/cache/DefaultCacheAwareContextLoaderDelegate.java @@ -21,6 +21,7 @@ import java.util.List; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; +import org.springframework.aot.AotDetector; import org.springframework.context.ApplicationContext; import org.springframework.context.ApplicationContextInitializer; import org.springframework.context.ConfigurableApplicationContext; @@ -35,7 +36,6 @@ import org.springframework.test.context.MergedContextConfiguration; import org.springframework.test.context.SmartContextLoader; import org.springframework.test.context.aot.AotContextLoader; import org.springframework.test.context.aot.AotTestContextInitializers; -import org.springframework.test.context.aot.TestAotDetector; import org.springframework.test.context.aot.TestContextAotException; import org.springframework.test.context.util.TestContextSpringFactoriesUtils; import org.springframework.util.Assert; @@ -248,7 +248,7 @@ public class DefaultCacheAwareContextLoaderDelegate implements CacheAwareContext */ @SuppressWarnings("unchecked") private MergedContextConfiguration replaceIfNecessary(MergedContextConfiguration mergedConfig) { - if (TestAotDetector.useGeneratedArtifacts()) { + if (AotDetector.useGeneratedArtifacts()) { Class testClass = mergedConfig.getTestClass(); Class> contextInitializerClass = this.aotTestContextInitializers.getContextInitializerClass(testClass); diff --git a/spring-test/src/main/java/org/springframework/test/context/util/TestContextFailureHandler.java b/spring-test/src/main/java/org/springframework/test/context/util/TestContextFailureHandler.java index 0fbe8e4795..bac8625032 100644 --- a/spring-test/src/main/java/org/springframework/test/context/util/TestContextFailureHandler.java +++ b/spring-test/src/main/java/org/springframework/test/context/util/TestContextFailureHandler.java @@ -21,6 +21,7 @@ import java.lang.reflect.InvocationTargetException; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; +import org.springframework.core.NativeDetector; import org.springframework.core.io.support.SpringFactoriesLoader.FailureHandler; /** @@ -53,6 +54,13 @@ class TestContextFailureHandler implements FailureHandler { available.""".formatted(factoryType.getSimpleName(), factoryImplementationName), ex); } } + // Workaround for https://github.com/oracle/graal/issues/6691 + else if (NativeDetector.inNativeImage() && ex instanceof IllegalStateException) { + if (logger.isDebugEnabled()) { + logger.debug("Skipping candidate %1$s [%2$s] due to an error when loading it in a native image." + .formatted(factoryType.getSimpleName(), factoryImplementationName)); + } + } else { if (ex instanceof RuntimeException runtimeException) { throw runtimeException; diff --git a/spring-test/src/test/java/org/springframework/test/context/aot/TestContextAotGeneratorErrorCaseTests.java b/spring-test/src/test/java/org/springframework/test/context/aot/TestContextAotGeneratorErrorCaseTests.java deleted file mode 100644 index f886d96bd2..0000000000 --- a/spring-test/src/test/java/org/springframework/test/context/aot/TestContextAotGeneratorErrorCaseTests.java +++ /dev/null @@ -1,76 +0,0 @@ -/* - * Copyright 2002-2023 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.springframework.test.context.aot; - -import java.util.stream.Stream; - -import org.junit.jupiter.api.Test; -import org.junit.jupiter.params.ParameterizedTest; -import org.junit.jupiter.params.provider.CsvSource; - -import org.springframework.aot.generate.InMemoryGeneratedFiles; - -import static org.assertj.core.api.Assertions.assertThatIllegalStateException; -import static org.assertj.core.api.Assertions.assertThatNoException; - -/** - * Tests for error cases in {@link TestContextAotGenerator}. - * - * @author Sam Brannen - * @since 6.0.9 - */ -class TestContextAotGeneratorErrorCaseTests { - - @ParameterizedTest - @CsvSource(delimiter = '=', textBlock = """ - 'spring.aot.enabled' = 'true' - 'org.graalvm.nativeimage.imagecode' = 'buildtime' - 'org.graalvm.nativeimage.imagecode' = 'runtime' - 'org.graalvm.nativeimage.imagecode' = 'bogus' - """) - void attemptToProcessWhileRunningInAotMode(String property, String value) { - try { - System.setProperty(property, value); - - assertThatIllegalStateException() - .isThrownBy(() -> generator().processAheadOfTime(Stream.empty())) - .withMessage("Cannot perform AOT processing during AOT run-time execution"); - } - finally { - System.clearProperty(property); - } - } - - @Test - void attemptToProcessWhileRunningInGraalVmNativeBuildToolsAgentMode() { - final String IMAGECODE = "org.graalvm.nativeimage.imagecode"; - try { - System.setProperty(IMAGECODE, "AgenT"); - - assertThatNoException().isThrownBy(() -> generator().processAheadOfTime(Stream.empty())); - } - finally { - System.clearProperty(IMAGECODE); - } - } - - private static TestContextAotGenerator generator() { - InMemoryGeneratedFiles generatedFiles = new InMemoryGeneratedFiles(); - return new TestContextAotGenerator(generatedFiles); - } - -} diff --git a/spring-test/src/test/java/org/springframework/test/context/aot/samples/basic/BasicSpringVintageTests.java b/spring-test/src/test/java/org/springframework/test/context/aot/samples/basic/BasicSpringVintageTests.java index db63efb3b8..4e1189674b 100644 --- a/spring-test/src/test/java/org/springframework/test/context/aot/samples/basic/BasicSpringVintageTests.java +++ b/spring-test/src/test/java/org/springframework/test/context/aot/samples/basic/BasicSpringVintageTests.java @@ -18,6 +18,7 @@ package org.springframework.test.context.aot.samples.basic; import org.junit.runner.RunWith; +import org.springframework.aot.AotDetector; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; import org.springframework.context.ApplicationContext; @@ -27,7 +28,6 @@ import org.springframework.test.context.ContextLoader; import org.springframework.test.context.MergedContextConfiguration; import org.springframework.test.context.TestPropertySource; import org.springframework.test.context.aot.AotTestAttributes; -import org.springframework.test.context.aot.TestAotDetector; import org.springframework.test.context.aot.samples.basic.BasicSpringVintageTests.CustomXmlBootstrapper; import org.springframework.test.context.aot.samples.common.MessageService; import org.springframework.test.context.junit4.SpringRunner; @@ -78,7 +78,7 @@ public class BasicSpringVintageTests { String booleanKey1 = "@SpringBootConfiguration-" + mergedConfig.getTestClass().getName() + "-active1"; String booleanKey2 = "@SpringBootConfiguration-" + mergedConfig.getTestClass().getName() + "-active2"; AotTestAttributes aotAttributes = AotTestAttributes.getInstance(); - if (TestAotDetector.useGeneratedArtifacts()) { + if (AotDetector.useGeneratedArtifacts()) { assertThat(aotAttributes.getString(stringKey)) .as("AOT String attribute must already be present during AOT run-time execution") .isEqualTo("org.example.Main"); diff --git a/spring-test/src/test/java/org/springframework/test/context/aot/samples/basic/ImportsContextCustomizerFactory.java b/spring-test/src/test/java/org/springframework/test/context/aot/samples/basic/ImportsContextCustomizerFactory.java index 431ff14489..4fe84402eb 100644 --- a/spring-test/src/test/java/org/springframework/test/context/aot/samples/basic/ImportsContextCustomizerFactory.java +++ b/spring-test/src/test/java/org/springframework/test/context/aot/samples/basic/ImportsContextCustomizerFactory.java @@ -19,6 +19,7 @@ package org.springframework.test.context.aot.samples.basic; import java.util.Arrays; import java.util.List; +import org.springframework.aot.AotDetector; import org.springframework.context.ConfigurableApplicationContext; import org.springframework.context.annotation.AnnotatedBeanDefinitionReader; import org.springframework.context.annotation.Import; @@ -27,7 +28,6 @@ import org.springframework.test.context.ContextConfigurationAttributes; import org.springframework.test.context.ContextCustomizer; import org.springframework.test.context.ContextCustomizerFactory; import org.springframework.test.context.MergedContextConfiguration; -import org.springframework.test.context.aot.TestAotDetector; /** * Emulates {@code ImportsContextCustomizerFactory} from Spring Boot's testing support. @@ -41,7 +41,7 @@ class ImportsContextCustomizerFactory implements ContextCustomizerFactory { public ContextCustomizer createContextCustomizer(Class testClass, List configAttributes) { - if (TestAotDetector.useGeneratedArtifacts()) { + if (AotDetector.useGeneratedArtifacts()) { return null; } if (testClass.getName().startsWith("org.springframework.test.context.aot.samples") &&