Retain existing feature name as prefix in test AOT processing
Prior to this commit, test AOT processing failed if a feature name for generated class names was used for more than one ApplicationContext. For example, when generating code for org.example.MessageService with a "Management" feature name, the "BeanDefinitions" class was named as follows (without a uniquely identifying TestContext###_ feature name prefix). org/example/MessageService__ManagementBeanDefinitions.java When another attempt was made to generate code for the MessageService using the same "Management" feature name, a FileAlreadyExistsException was thrown denoting that the class/file name was already in use. To avoid such naming collisions, this commit introduces a TestContextGenerationContext which provides a custom implementation of withName(String) that prepends an existing feature name (if present) to a new feature name, thereby treating any existing feature name as a prefix to a new, nested feature name. Consequently, code generation for the above example now results in unique class/file names like the following (which retain the uniquely identifying TestContext###_ prefixes). org/example/MessageService__TestContext002_ManagementBeanDefinitions.java org/example/MessageService__TestContext003_ManagementBeanDefinitions.java Closes gh-30861
This commit is contained in:
@@ -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.
|
||||
@@ -45,14 +45,22 @@ abstract class AbstractAotTests {
|
||||
"org/springframework/context/event/EventListenerMethodProcessor__TestContext002_BeanDefinitions.java",
|
||||
"org/springframework/test/context/aot/samples/basic/BasicSpringJupiterSharedConfigTests__TestContext002_ApplicationContextInitializer.java",
|
||||
"org/springframework/test/context/aot/samples/basic/BasicSpringJupiterSharedConfigTests__TestContext002_BeanFactoryRegistrations.java",
|
||||
"org/springframework/test/context/aot/samples/basic/BasicSpringJupiterSharedConfigTests__TestContext002_ManagementApplicationContextInitializer.java",
|
||||
"org/springframework/test/context/aot/samples/basic/BasicSpringJupiterSharedConfigTests__TestContext002_ManagementBeanFactoryRegistrations.java",
|
||||
"org/springframework/test/context/aot/samples/basic/BasicTestConfiguration__TestContext002_BeanDefinitions.java",
|
||||
"org/springframework/test/context/aot/samples/management/ManagementConfiguration__TestContext002_BeanDefinitions.java",
|
||||
"org/springframework/test/context/aot/samples/management/ManagementMessageService__TestContext002_ManagementBeanDefinitions.java",
|
||||
// BasicSpringJupiterTests -- not generated b/c already generated for BasicSpringJupiterSharedConfigTests.
|
||||
// BasicSpringJupiterTests.NestedTests
|
||||
"org/springframework/context/event/DefaultEventListenerFactory__TestContext003_BeanDefinitions.java",
|
||||
"org/springframework/context/event/EventListenerMethodProcessor__TestContext003_BeanDefinitions.java",
|
||||
"org/springframework/test/context/aot/samples/basic/BasicSpringJupiterTests_NestedTests__TestContext003_ApplicationContextInitializer.java",
|
||||
"org/springframework/test/context/aot/samples/basic/BasicSpringJupiterTests_NestedTests__TestContext003_BeanFactoryRegistrations.java",
|
||||
"org/springframework/test/context/aot/samples/basic/BasicSpringJupiterTests_NestedTests__TestContext003_ManagementApplicationContextInitializer.java",
|
||||
"org/springframework/test/context/aot/samples/basic/BasicSpringJupiterTests_NestedTests__TestContext003_ManagementBeanFactoryRegistrations.java",
|
||||
"org/springframework/test/context/aot/samples/basic/BasicTestConfiguration__TestContext003_BeanDefinitions.java",
|
||||
"org/springframework/test/context/aot/samples/management/ManagementConfiguration__TestContext003_BeanDefinitions.java",
|
||||
"org/springframework/test/context/aot/samples/management/ManagementMessageService__TestContext003_ManagementBeanDefinitions.java",
|
||||
// BasicSpringTestNGTests
|
||||
"org/springframework/context/event/DefaultEventListenerFactory__TestContext004_BeanDefinitions.java",
|
||||
"org/springframework/context/event/EventListenerMethodProcessor__TestContext004_BeanDefinitions.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.
|
||||
@@ -36,6 +36,7 @@ import org.opentest4j.MultipleFailuresError;
|
||||
import org.springframework.aot.AotDetector;
|
||||
import org.springframework.aot.generate.GeneratedFiles.Kind;
|
||||
import org.springframework.aot.generate.InMemoryGeneratedFiles;
|
||||
import org.springframework.aot.hint.RuntimeHints;
|
||||
import org.springframework.aot.test.generate.CompilerFiles;
|
||||
import org.springframework.core.test.tools.CompileWithForkedClassLoader;
|
||||
import org.springframework.core.test.tools.TestCompiler;
|
||||
@@ -86,7 +87,7 @@ class AotIntegrationTests extends AbstractAotTests {
|
||||
|
||||
// AOT BUILD-TIME: PROCESSING
|
||||
InMemoryGeneratedFiles generatedFiles = new InMemoryGeneratedFiles();
|
||||
TestContextAotGenerator generator = new TestContextAotGenerator(generatedFiles);
|
||||
TestContextAotGenerator generator = new TestContextAotGenerator(generatedFiles, new RuntimeHints(), true);
|
||||
generator.processAheadOfTime(testClasses);
|
||||
|
||||
List<String> sourceFiles = generatedFiles.getGeneratedFiles(Kind.SOURCE).keySet().stream().toList();
|
||||
|
||||
@@ -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.
|
||||
@@ -366,14 +366,22 @@ class TestContextAotGeneratorTests extends AbstractAotTests {
|
||||
"org/springframework/context/event/EventListenerMethodProcessor__TestContext001_BeanDefinitions.java",
|
||||
"org/springframework/test/context/aot/samples/basic/BasicSpringJupiterSharedConfigTests__TestContext001_ApplicationContextInitializer.java",
|
||||
"org/springframework/test/context/aot/samples/basic/BasicSpringJupiterSharedConfigTests__TestContext001_BeanFactoryRegistrations.java",
|
||||
"org/springframework/test/context/aot/samples/basic/BasicSpringJupiterSharedConfigTests__TestContext001_ManagementApplicationContextInitializer.java",
|
||||
"org/springframework/test/context/aot/samples/basic/BasicSpringJupiterSharedConfigTests__TestContext001_ManagementBeanFactoryRegistrations.java",
|
||||
"org/springframework/test/context/aot/samples/basic/BasicTestConfiguration__TestContext001_BeanDefinitions.java",
|
||||
"org/springframework/test/context/aot/samples/management/ManagementConfiguration__TestContext001_BeanDefinitions.java",
|
||||
"org/springframework/test/context/aot/samples/management/ManagementMessageService__TestContext001_ManagementBeanDefinitions.java",
|
||||
// BasicSpringJupiterTests -- not generated b/c already generated for BasicSpringJupiterSharedConfigTests.
|
||||
// BasicSpringJupiterTests.NestedTests
|
||||
"org/springframework/context/event/DefaultEventListenerFactory__TestContext002_BeanDefinitions.java",
|
||||
"org/springframework/context/event/EventListenerMethodProcessor__TestContext002_BeanDefinitions.java",
|
||||
"org/springframework/test/context/aot/samples/basic/BasicSpringJupiterTests_NestedTests__TestContext002_ApplicationContextInitializer.java",
|
||||
"org/springframework/test/context/aot/samples/basic/BasicSpringJupiterTests_NestedTests__TestContext002_BeanFactoryRegistrations.java",
|
||||
"org/springframework/test/context/aot/samples/basic/BasicSpringJupiterTests_NestedTests__TestContext002_ManagementApplicationContextInitializer.java",
|
||||
"org/springframework/test/context/aot/samples/basic/BasicSpringJupiterTests_NestedTests__TestContext002_ManagementBeanFactoryRegistrations.java",
|
||||
"org/springframework/test/context/aot/samples/basic/BasicTestConfiguration__TestContext002_BeanDefinitions.java",
|
||||
"org/springframework/test/context/aot/samples/management/ManagementConfiguration__TestContext002_BeanDefinitions.java",
|
||||
"org/springframework/test/context/aot/samples/management/ManagementMessageService__TestContext002_ManagementBeanDefinitions.java",
|
||||
// BasicSpringTestNGTests
|
||||
"org/springframework/context/event/DefaultEventListenerFactory__TestContext003_BeanDefinitions.java",
|
||||
"org/springframework/context/event/EventListenerMethodProcessor__TestContext003_BeanDefinitions.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.
|
||||
@@ -21,6 +21,7 @@ import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.context.ApplicationContext;
|
||||
import org.springframework.test.context.TestPropertySource;
|
||||
import org.springframework.test.context.aot.samples.common.MessageService;
|
||||
import org.springframework.test.context.aot.samples.management.ManagementConfiguration;
|
||||
import org.springframework.test.context.junit.jupiter.SpringJUnitConfig;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
@@ -31,7 +32,7 @@ import static org.assertj.core.api.Assertions.assertThat;
|
||||
* @author Sam Brannen
|
||||
* @since 6.0
|
||||
*/
|
||||
@SpringJUnitConfig(BasicTestConfiguration.class)
|
||||
@SpringJUnitConfig({BasicTestConfiguration.class, ManagementConfiguration.class})
|
||||
@TestPropertySource(properties = "test.engine = jupiter")
|
||||
public class BasicSpringJupiterSharedConfigTests {
|
||||
|
||||
|
||||
@@ -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.
|
||||
@@ -26,6 +26,7 @@ import org.springframework.test.context.TestExecutionListeners;
|
||||
import org.springframework.test.context.TestPropertySource;
|
||||
import org.springframework.test.context.aot.samples.basic.BasicSpringJupiterTests.DummyTestExecutionListener;
|
||||
import org.springframework.test.context.aot.samples.common.MessageService;
|
||||
import org.springframework.test.context.aot.samples.management.ManagementConfiguration;
|
||||
import org.springframework.test.context.junit.jupiter.SpringJUnitConfig;
|
||||
import org.springframework.test.context.support.AbstractTestExecutionListener;
|
||||
|
||||
@@ -36,7 +37,7 @@ import static org.springframework.test.context.TestExecutionListeners.MergeMode.
|
||||
* @author Sam Brannen
|
||||
* @since 6.0
|
||||
*/
|
||||
@SpringJUnitConfig(BasicTestConfiguration.class)
|
||||
@SpringJUnitConfig({BasicTestConfiguration.class, ManagementConfiguration.class})
|
||||
@TestExecutionListeners(listeners = DummyTestExecutionListener.class, mergeMode = MERGE_WITH_DEFAULTS)
|
||||
@TestPropertySource(properties = "test.engine = jupiter")
|
||||
public class BasicSpringJupiterTests {
|
||||
|
||||
@@ -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.
|
||||
@@ -22,6 +22,7 @@ import org.springframework.context.annotation.Profile;
|
||||
import org.springframework.test.context.aot.samples.common.DefaultMessageService;
|
||||
import org.springframework.test.context.aot.samples.common.MessageService;
|
||||
import org.springframework.test.context.aot.samples.common.SpanishMessageService;
|
||||
import org.springframework.test.context.aot.samples.management.Managed;
|
||||
|
||||
/**
|
||||
* @author Sam Brannen
|
||||
@@ -32,12 +33,14 @@ class BasicTestConfiguration {
|
||||
|
||||
@Bean
|
||||
@Profile("default")
|
||||
@Managed
|
||||
MessageService defaultMessageService() {
|
||||
return new DefaultMessageService();
|
||||
}
|
||||
|
||||
@Bean
|
||||
@Profile("spanish")
|
||||
@Managed
|
||||
MessageService spanishMessageService() {
|
||||
return new SpanishMessageService();
|
||||
}
|
||||
|
||||
@@ -0,0 +1,35 @@
|
||||
/*
|
||||
* 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.samples.management;
|
||||
|
||||
import java.lang.annotation.Documented;
|
||||
import java.lang.annotation.ElementType;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
/**
|
||||
* Marker annotation for "managed" beans.
|
||||
*
|
||||
* @author Sam Brannen
|
||||
* @since 6.0.12
|
||||
*/
|
||||
@Documented
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@Target(ElementType.METHOD)
|
||||
public @interface Managed {
|
||||
}
|
||||
@@ -0,0 +1,83 @@
|
||||
/*
|
||||
* 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.samples.management;
|
||||
|
||||
import java.lang.reflect.Executable;
|
||||
|
||||
import org.springframework.aot.generate.GenerationContext;
|
||||
import org.springframework.beans.factory.aot.BeanRegistrationAotContribution;
|
||||
import org.springframework.beans.factory.aot.BeanRegistrationAotProcessor;
|
||||
import org.springframework.beans.factory.aot.BeanRegistrationCode;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.context.aot.ApplicationContextAotGenerator;
|
||||
import org.springframework.context.support.GenericApplicationContext;
|
||||
import org.springframework.core.annotation.AnnotatedElementUtils;
|
||||
|
||||
/**
|
||||
* Configuration class that mimics Spring Boot's AOT support for child management
|
||||
* contexts in
|
||||
* {@code org.springframework.boot.actuate.autoconfigure.web.server.ChildManagementContextInitializer}.
|
||||
*
|
||||
* <p>See <a href="https://github.com/spring-projects/spring-framework/issues/30861">gh-30861</a>.
|
||||
*
|
||||
* @author Sam Brannen
|
||||
* @since 6.0.12
|
||||
*/
|
||||
@Configuration
|
||||
public class ManagementConfiguration {
|
||||
|
||||
@Bean
|
||||
static BeanRegistrationAotProcessor beanRegistrationAotProcessor() {
|
||||
return registeredBean -> {
|
||||
Executable factoryMethod = registeredBean.resolveConstructorOrFactoryMethod();
|
||||
// Make AOT contribution for @Managed @Bean methods.
|
||||
if (AnnotatedElementUtils.hasAnnotation(factoryMethod, Managed.class)) {
|
||||
return new AotContribution(createManagementContext());
|
||||
}
|
||||
return null;
|
||||
};
|
||||
}
|
||||
|
||||
private static GenericApplicationContext createManagementContext() {
|
||||
GenericApplicationContext managementContext = new GenericApplicationContext();
|
||||
managementContext.registerBean(ManagementMessageService.class);
|
||||
return managementContext;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Mimics Spring Boot's AOT support for child management contexts in
|
||||
* {@code org.springframework.boot.actuate.autoconfigure.web.server.ChildManagementContextInitializer.AotContribution}.
|
||||
*/
|
||||
private static class AotContribution implements BeanRegistrationAotContribution {
|
||||
|
||||
private final GenericApplicationContext managementContext;
|
||||
|
||||
AotContribution(GenericApplicationContext managementContext) {
|
||||
this.managementContext = managementContext;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void applyTo(GenerationContext generationContext, BeanRegistrationCode beanRegistrationCode) {
|
||||
GenerationContext managementGenerationContext = generationContext.withName("Management");
|
||||
new ApplicationContextAotGenerator().processAheadOfTime(this.managementContext, managementGenerationContext);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,36 @@
|
||||
/*
|
||||
* 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.samples.management;
|
||||
|
||||
import org.springframework.test.context.aot.samples.common.MessageService;
|
||||
|
||||
/**
|
||||
* {@link MessageService} implemented in a different package.
|
||||
*
|
||||
* <p>See <a href="https://github.com/spring-projects/spring-framework/issues/30861">gh-30861</a>.
|
||||
*
|
||||
* @author Sam Brannen
|
||||
* @since 6.0.12
|
||||
*/
|
||||
class ManagementMessageService implements MessageService {
|
||||
|
||||
@Override
|
||||
public String generateMessage() {
|
||||
return "Hello, Management!";
|
||||
}
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user