Merge branch '6.0.x'
This commit is contained in:
commit
8a5f655a5c
|
@ -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));
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -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"),
|
||||
|
|
|
@ -43,8 +43,12 @@ abstract public class AbstractClassGenerator<T> 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<T> 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());
|
||||
}
|
||||
|
|
|
@ -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
|
||||
* <a href="https://github.com/oracle/graal/blob/master/sdk/src/org.graalvm.nativeimage/src/org/graalvm/nativeimage/ImageInfo.java">ImageInfo.java</a>.
|
||||
*
|
||||
* @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;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -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.
|
||||
*
|
||||
* <p>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);
|
||||
|
|
|
@ -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.
|
||||
* <p>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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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;
|
|||
*
|
||||
* <p>Intended solely for internal use within the framework.
|
||||
*
|
||||
* <p>If we are not running in {@linkplain TestAotDetector#useGeneratedArtifacts()
|
||||
* <p>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}.
|
||||
|
|
|
@ -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.
|
||||
* <p>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<String, Supplier<ApplicationContextInitializer<ConfigurableApplicationContext>>> 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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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");
|
||||
}
|
||||
|
|
|
@ -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.
|
||||
*
|
||||
* <p>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.
|
||||
* <p>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 <a href="https://github.com/oracle/graal/blob/master/sdk/src/org.graalvm.nativeimage/src/org/graalvm/nativeimage/ImageInfo.java">GraalVM's ImageInfo.java</a>
|
||||
* @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()));
|
||||
}
|
||||
|
||||
}
|
|
@ -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<Class<?>> 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();
|
||||
|
||||
|
|
|
@ -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<? extends ApplicationContextInitializer<?>> contextInitializerClass =
|
||||
this.aotTestContextInitializers.getContextInitializerClass(testClass);
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
}
|
|
@ -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");
|
||||
|
|
|
@ -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<ContextConfigurationAttributes> configAttributes) {
|
||||
|
||||
if (TestAotDetector.useGeneratedArtifacts()) {
|
||||
if (AotDetector.useGeneratedArtifacts()) {
|
||||
return null;
|
||||
}
|
||||
if (testClass.getName().startsWith("org.springframework.test.context.aot.samples") &&
|
||||
|
|
Loading…
Reference in New Issue