diff --git a/spring-test/spring-test.gradle b/spring-test/spring-test.gradle index d8596d9110fe..d9b166b705b8 100644 --- a/spring-test/spring-test.gradle +++ b/spring-test/spring-test.gradle @@ -24,6 +24,7 @@ dependencies { optional("jakarta.websocket:jakarta.websocket-api") optional("junit:junit") optional("org.apache.tomcat.embed:tomcat-embed-core") + optional("org.junit.platform:junit-platform-launcher") // for AOT processing optional("org.junit.jupiter:junit-jupiter-api") optional("org.testng:testng") optional("org.aspectj:aspectjweaver") diff --git a/spring-test/src/main/java/org/springframework/test/context/aot/TestClassScanner.java b/spring-test/src/main/java/org/springframework/test/context/aot/TestClassScanner.java new file mode 100644 index 000000000000..d9b6942c9f46 --- /dev/null +++ b/spring-test/src/main/java/org/springframework/test/context/aot/TestClassScanner.java @@ -0,0 +1,198 @@ +/* + * Copyright 2002-2022 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.lang.annotation.Annotation; +import java.nio.file.Path; +import java.util.Arrays; +import java.util.Optional; +import java.util.Set; +import java.util.stream.Stream; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.junit.platform.engine.support.descriptor.ClassSource; +import org.junit.platform.launcher.Launcher; +import org.junit.platform.launcher.LauncherDiscoveryRequest; +import org.junit.platform.launcher.TestIdentifier; +import org.junit.platform.launcher.TestPlan; +import org.junit.platform.launcher.core.LauncherDiscoveryRequestBuilder; +import org.junit.platform.launcher.core.LauncherFactory; + +import org.springframework.core.annotation.MergedAnnotation; +import org.springframework.core.annotation.MergedAnnotations; +import org.springframework.test.context.BootstrapWith; +import org.springframework.test.context.ContextConfiguration; +import org.springframework.test.context.TestContextAnnotationUtils; +import org.springframework.util.Assert; + +import static org.junit.platform.engine.discovery.DiscoverySelectors.selectClasspathRoots; +import static org.junit.platform.engine.discovery.PackageNameFilter.includePackageNames; +import static org.springframework.core.annotation.MergedAnnotation.VALUE; +import static org.springframework.core.annotation.MergedAnnotations.SearchStrategy.INHERITED_ANNOTATIONS; +import static org.springframework.core.annotation.MergedAnnotations.SearchStrategy.TYPE_HIERARCHY; + +/** + * {@code TestClassScanner} scans provided classpath roots for Spring integration + * test classes using the JUnit Platform {@link Launcher} API which allows all + * registered {@link org.junit.platform.engine.TestEngine TestEngines} to discover + * tests according to their own rules. + * + *

The scanner currently detects the following categories of Spring integration + * test classes. + * + *

+ * + *

The scanner has been tested with the following + * {@link org.junit.platform.engine.TestEngine TestEngines}. + * + *

+ * + * @author Sam Brannen + * @since 6.0 + */ +class TestClassScanner { + + // JUnit 4 + private static final String RUN_WITH_ANNOTATION_NAME = "org.junit.runner.RunWith"; + private static final String SPRING_JUNIT4_CLASS_RUNNER_NAME = "org.springframework.test.context.junit4.SpringJUnit4ClassRunner"; + private static final String SPRING_RUNNER_NAME = "org.springframework.test.context.junit4.SpringRunner"; + + // JUnit Jupiter + private static final String EXTEND_WITH_ANNOTATION_NAME = "org.junit.jupiter.api.extension.ExtendWith"; + private static final String SPRING_EXTENSION_NAME = "org.springframework.test.context.junit.jupiter.SpringExtension"; + + + private final Log logger = LogFactory.getLog(TestClassScanner.class); + + private final Set classpathRoots; + + + TestClassScanner(Set classpathRoots) { + Assert.notEmpty(classpathRoots, "'classpathRoots' must not be null or empty"); + Assert.noNullElements(classpathRoots, "'classpathRoots' must not contain null elements"); + this.classpathRoots = classpathRoots; + } + + + /** + * Scan the configured classpath roots for Spring integration test classes. + */ + Stream> scan() { + return scan(new String[0]); + } + + /** + * Scan the configured classpath roots for Spring integration test classes + * in the given packages. + */ + Stream> scan(String... packageNames) { + Assert.notEmpty(packageNames, "'packageNames' must not be null or empty"); + Assert.noNullElements(packageNames, "'packageNames' must not contain null elements"); + + if (logger.isInfoEnabled()) { + if (packageNames.length > 0) { + logger.info("Scanning for Spring test classes in packages %s in classpath roots %s" + .formatted(Arrays.toString(packageNames), this.classpathRoots)); + } + else { + logger.info("Scanning for Spring test classes in all packages in classpath roots %s" + .formatted(this.classpathRoots)); + } + } + + LauncherDiscoveryRequestBuilder builder = LauncherDiscoveryRequestBuilder.request(); + builder.selectors(selectClasspathRoots(this.classpathRoots)); + if (packageNames.length > 0) { + builder.filters(includePackageNames(packageNames)); + } + LauncherDiscoveryRequest request = builder.build(); + Launcher launcher = LauncherFactory.create(); + TestPlan testPlan = launcher.discover(request); + + return testPlan.getRoots().stream() + .map(testPlan::getDescendants) + .flatMap(Set::stream) + .map(TestIdentifier::getSource) + .flatMap(Optional::stream) + .filter(ClassSource.class::isInstance) + .map(ClassSource.class::cast) + .map(this::getJavaClass) + .flatMap(Optional::stream) + .filter(this::isSpringTestClass) + .distinct(); + } + + private Optional> getJavaClass(ClassSource classSource) { + try { + return Optional.of(classSource.getJavaClass()); + } + catch (Exception ex) { + // ignore exception + return Optional.empty(); + } + } + + private boolean isSpringTestClass(Class clazz) { + boolean isSpringTestClass = (isJupiterSpringTestClass(clazz) || isJUnit4SpringTestClass(clazz) || + isGenericSpringTestClass(clazz)); + if (isSpringTestClass && logger.isTraceEnabled()) { + logger.trace("Found Spring test class: " + clazz.getName()); + } + return isSpringTestClass; + } + + private static boolean isJupiterSpringTestClass(Class clazz) { + return MergedAnnotations.search(TYPE_HIERARCHY) + .withEnclosingClasses(TestContextAnnotationUtils::searchEnclosingClass) + .from(clazz) + .stream(EXTEND_WITH_ANNOTATION_NAME) + .map(annotation -> annotation.getClassArray(VALUE)) + .flatMap(Arrays::stream) + .map(Class::getName) + .anyMatch(SPRING_EXTENSION_NAME::equals); + } + + private static boolean isJUnit4SpringTestClass(Class clazz) { + MergedAnnotation mergedAnnotation = + MergedAnnotations.from(clazz, INHERITED_ANNOTATIONS).get(RUN_WITH_ANNOTATION_NAME); + if (mergedAnnotation.isPresent()) { + String name = mergedAnnotation.getClass(VALUE).getName(); + return (SPRING_JUNIT4_CLASS_RUNNER_NAME.equals(name) || SPRING_RUNNER_NAME.equals(name)); + } + return false; + } + + private static boolean isGenericSpringTestClass(Class clazz) { + MergedAnnotations mergedAnnotations = MergedAnnotations.from(clazz, TYPE_HIERARCHY); + return (mergedAnnotations.isPresent(ContextConfiguration.class) || + mergedAnnotations.isPresent(BootstrapWith.class)); + } + +} diff --git a/spring-test/src/main/java/org/springframework/test/context/aot/package-info.java b/spring-test/src/main/java/org/springframework/test/context/aot/package-info.java new file mode 100644 index 000000000000..d673bff93ead --- /dev/null +++ b/spring-test/src/main/java/org/springframework/test/context/aot/package-info.java @@ -0,0 +1,9 @@ +/** + * Ahead-of-time (AOT) support for the Spring TestContext Framework. + */ +@NonNullApi +@NonNullFields +package org.springframework.test.context.aot; + +import org.springframework.lang.NonNullApi; +import org.springframework.lang.NonNullFields; diff --git a/spring-test/src/test/java/org/springframework/test/context/aot/TestClassScannerTests.java b/spring-test/src/test/java/org/springframework/test/context/aot/TestClassScannerTests.java new file mode 100644 index 000000000000..242467c37f4b --- /dev/null +++ b/spring-test/src/test/java/org/springframework/test/context/aot/TestClassScannerTests.java @@ -0,0 +1,101 @@ +/* + * Copyright 2002-2022 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.nio.file.Path; +import java.nio.file.Paths; +import java.util.Set; +import java.util.stream.Stream; + +import org.junit.jupiter.api.Test; + +import org.springframework.test.context.aot.samples.basic.BasicSpringJupiterTests; +import org.springframework.test.context.aot.samples.basic.BasicSpringTestNGTests; +import org.springframework.test.context.aot.samples.basic.BasicSpringVintageTests; + +import static org.assertj.core.api.Assertions.assertThat; + +/** + * Tests for {@link TestClassScanner}. + * + * @author Sam Brannen + * @since 6.0 + */ +class TestClassScannerTests { + + @Test + void scanBasicTestClasses() { + assertThat(scan("org.springframework.test.context.aot.samples.basic")) + .containsExactlyInAnyOrder( + BasicSpringJupiterTests.class, + BasicSpringJupiterTests.NestedTests.class, + BasicSpringVintageTests.class, + BasicSpringTestNGTests.class + ); + } + + @Test + void scanTestSuitesForJupiter() { + assertThat(scan("org.springframework.test.context.aot.samples.suites.jupiter")) + .containsExactlyInAnyOrder(BasicSpringJupiterTests.class, BasicSpringJupiterTests.NestedTests.class); + } + + @Test + void scanTestSuitesForVintage() { + assertThat(scan("org.springframework.test.context.aot.samples.suites.vintage")) + .containsExactly(BasicSpringVintageTests.class); + } + + @Test + void scanTestSuitesForTestNG() { + assertThat(scan("org.springframework.test.context.aot.samples.suites.testng")) + .containsExactly(BasicSpringTestNGTests.class); + } + + @Test + void scanTestSuitesForAllTestEngines() { + assertThat(scan("org.springframework.test.context.aot.samples.suites.all")) + .containsExactlyInAnyOrder( + BasicSpringJupiterTests.class, + BasicSpringJupiterTests.NestedTests.class, + BasicSpringVintageTests.class, + BasicSpringTestNGTests.class + ); + } + + @Test + void scanTestSuitesWithNestedSuites() { + assertThat(scan("org.springframework.test.context.aot.samples.suites.nested")) + .containsExactlyInAnyOrder( + BasicSpringJupiterTests.class, + BasicSpringJupiterTests.NestedTests.class, + BasicSpringVintageTests.class + ); + } + + private Stream> scan(String... packageNames) { + try { + Set classpathRoots = Set.of( + Paths.get(getClass().getProtectionDomain().getCodeSource().getLocation().toURI())); + return new TestClassScanner(classpathRoots).scan(packageNames); + } + catch (Exception ex) { + throw new RuntimeException(ex); + } + } + +} diff --git a/spring-test/src/test/java/org/springframework/test/context/aot/samples/basic/BasicJupiterTests.java b/spring-test/src/test/java/org/springframework/test/context/aot/samples/basic/BasicJupiterTests.java new file mode 100644 index 000000000000..c9db1f3474ef --- /dev/null +++ b/spring-test/src/test/java/org/springframework/test/context/aot/samples/basic/BasicJupiterTests.java @@ -0,0 +1,49 @@ +/* + * Copyright 2002-2022 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.basic; + +import org.junit.jupiter.api.Nested; + +import org.springframework.test.context.aot.samples.common.DefaultMessageService; +import org.springframework.test.context.aot.samples.common.MessageService; + +import static org.assertj.core.api.Assertions.assertThat; + +/** + * @author Sam Brannen + * @since 6.0 + */ +class BasicJupiterTests { + + private final MessageService messageService = new DefaultMessageService(); + + @org.junit.jupiter.api.Test + void test() { + assertThat(messageService.generateMessage()).isEqualTo("Hello, AOT!"); + } + + @Nested + class NestedTests { + + @org.junit.jupiter.api.Test + void test() { + assertThat(messageService.generateMessage()).isEqualTo("Hello, AOT!"); + } + + } + +} diff --git a/spring-test/src/test/java/org/springframework/test/context/aot/samples/basic/BasicSpringJupiterTests.java b/spring-test/src/test/java/org/springframework/test/context/aot/samples/basic/BasicSpringJupiterTests.java new file mode 100644 index 000000000000..e13a25afe3e9 --- /dev/null +++ b/spring-test/src/test/java/org/springframework/test/context/aot/samples/basic/BasicSpringJupiterTests.java @@ -0,0 +1,61 @@ +/* + * Copyright 2002-2022 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.basic; + +import org.junit.jupiter.api.Nested; +import org.junit.jupiter.api.extension.ExtendWith; +import org.junit.jupiter.api.extension.Extension; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.test.context.TestPropertySource; +import org.springframework.test.context.aot.samples.common.MessageService; +import org.springframework.test.context.junit.jupiter.SpringJUnitConfig; + +import static org.assertj.core.api.Assertions.assertThat; + +/** + * @author Sam Brannen + * @since 6.0 + */ +// Register an extension other than the SpringExtension to verify proper lookups +// for repeated annotations. +@ExtendWith(DummyExtension.class) +@SpringJUnitConfig(BasicTestConfiguration.class) +public class BasicSpringJupiterTests { + + @org.junit.jupiter.api.Test + void test(@Autowired MessageService messageService) { + assertThat(messageService.generateMessage()).isEqualTo("Hello, AOT!"); + } + + @Nested + @TestPropertySource(properties = "foo=bar") + public class NestedTests { + + @org.junit.jupiter.api.Test + void test(@Autowired MessageService messageService, @Value("${foo}") String foo) { + assertThat(messageService.generateMessage()).isEqualTo("Hello, AOT!"); + assertThat(foo).isEqualTo("bar"); + } + + } + +} + +class DummyExtension implements Extension { +} diff --git a/spring-test/src/test/java/org/springframework/test/context/aot/samples/basic/BasicSpringTestNGTests.java b/spring-test/src/test/java/org/springframework/test/context/aot/samples/basic/BasicSpringTestNGTests.java new file mode 100644 index 000000000000..bdcee045be2c --- /dev/null +++ b/spring-test/src/test/java/org/springframework/test/context/aot/samples/basic/BasicSpringTestNGTests.java @@ -0,0 +1,41 @@ +/* + * Copyright 2002-2022 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.basic; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.test.context.ContextConfiguration; +import org.springframework.test.context.aot.samples.common.MessageService; +import org.springframework.test.context.testng.AbstractTestNGSpringContextTests; + +import static org.assertj.core.api.Assertions.assertThat; + +/** + * @author Sam Brannen + * @since 6.0 + */ +@ContextConfiguration(classes = BasicTestConfiguration.class) +public class BasicSpringTestNGTests extends AbstractTestNGSpringContextTests { + + @Autowired + MessageService messageService; + + @org.testng.annotations.Test + public void test() { + assertThat(messageService.generateMessage()).isEqualTo("Hello, AOT!"); + } + +} 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 new file mode 100644 index 000000000000..6ec4ec6c61b8 --- /dev/null +++ b/spring-test/src/test/java/org/springframework/test/context/aot/samples/basic/BasicSpringVintageTests.java @@ -0,0 +1,44 @@ +/* + * Copyright 2002-2022 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.basic; + +import org.junit.runner.RunWith; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.test.context.ContextConfiguration; +import org.springframework.test.context.aot.samples.common.MessageService; +import org.springframework.test.context.junit4.SpringRunner; + +import static org.assertj.core.api.Assertions.assertThat; + +/** + * @author Sam Brannen + * @since 6.0 + */ +@RunWith(SpringRunner.class) +@ContextConfiguration(classes = BasicTestConfiguration.class) +public class BasicSpringVintageTests { + + @Autowired + MessageService messageService; + + @org.junit.Test + public void test() { + assertThat(messageService.generateMessage()).isEqualTo("Hello, AOT!"); + } + +} diff --git a/spring-test/src/test/java/org/springframework/test/context/aot/samples/basic/BasicTestConfiguration.java b/spring-test/src/test/java/org/springframework/test/context/aot/samples/basic/BasicTestConfiguration.java new file mode 100644 index 000000000000..886c1e19bcba --- /dev/null +++ b/spring-test/src/test/java/org/springframework/test/context/aot/samples/basic/BasicTestConfiguration.java @@ -0,0 +1,36 @@ +/* + * Copyright 2002-2022 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.basic; + +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.test.context.aot.samples.common.DefaultMessageService; +import org.springframework.test.context.aot.samples.common.MessageService; + +/** + * @author Sam Brannen + * @since 6.0 + */ +@Configuration(proxyBeanMethods = false) +class BasicTestConfiguration { + + @Bean + MessageService messageService() { + return new DefaultMessageService(); + } + +} diff --git a/spring-test/src/test/java/org/springframework/test/context/aot/samples/basic/BasicTestNGTests.java b/spring-test/src/test/java/org/springframework/test/context/aot/samples/basic/BasicTestNGTests.java new file mode 100644 index 000000000000..6e280eb99976 --- /dev/null +++ b/spring-test/src/test/java/org/springframework/test/context/aot/samples/basic/BasicTestNGTests.java @@ -0,0 +1,37 @@ +/* + * Copyright 2002-2022 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.basic; + +import org.springframework.test.context.aot.samples.common.DefaultMessageService; +import org.springframework.test.context.aot.samples.common.MessageService; + +import static org.assertj.core.api.Assertions.assertThat; + +/** + * @author Sam Brannen + * @since 6.0 + */ +public class BasicTestNGTests { + + private final MessageService messageService = new DefaultMessageService(); + + @org.testng.annotations.Test + public void test() { + assertThat(messageService.generateMessage()).isEqualTo("Hello, AOT!"); + } + +} diff --git a/spring-test/src/test/java/org/springframework/test/context/aot/samples/basic/BasicVintageTests.java b/spring-test/src/test/java/org/springframework/test/context/aot/samples/basic/BasicVintageTests.java new file mode 100644 index 000000000000..0e74eac737d7 --- /dev/null +++ b/spring-test/src/test/java/org/springframework/test/context/aot/samples/basic/BasicVintageTests.java @@ -0,0 +1,38 @@ +/* + * Copyright 2002-2022 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.basic; + + +import org.springframework.test.context.aot.samples.common.DefaultMessageService; +import org.springframework.test.context.aot.samples.common.MessageService; + +import static org.assertj.core.api.Assertions.assertThat; + +/** + * @author Sam Brannen + * @since 6.0 + */ +public class BasicVintageTests { + + private final MessageService messageService = new DefaultMessageService(); + + @org.junit.Test + public void test() { + assertThat(messageService.generateMessage()).isEqualTo("Hello, AOT!"); + } + +} diff --git a/spring-test/src/test/java/org/springframework/test/context/aot/samples/common/DefaultMessageService.java b/spring-test/src/test/java/org/springframework/test/context/aot/samples/common/DefaultMessageService.java new file mode 100644 index 000000000000..ac9d5a4a7bd2 --- /dev/null +++ b/spring-test/src/test/java/org/springframework/test/context/aot/samples/common/DefaultMessageService.java @@ -0,0 +1,30 @@ +/* + * Copyright 2002-2022 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.common; + +/** + * @author Sam Brannen + * @since 6.0 + */ +public class DefaultMessageService implements MessageService { + + @Override + public String generateMessage() { + return "Hello, AOT!"; + } + +} diff --git a/spring-test/src/test/java/org/springframework/test/context/aot/samples/common/MessageService.java b/spring-test/src/test/java/org/springframework/test/context/aot/samples/common/MessageService.java new file mode 100644 index 000000000000..98f2f03ce1b6 --- /dev/null +++ b/spring-test/src/test/java/org/springframework/test/context/aot/samples/common/MessageService.java @@ -0,0 +1,27 @@ +/* + * Copyright 2002-2022 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.common; + +/** + * @author Sam Brannen + * @since 6.0 + */ +public interface MessageService { + + String generateMessage(); + +} diff --git a/spring-test/src/test/java/org/springframework/test/context/aot/samples/suites/all/AllEnginesTestSuite.java b/spring-test/src/test/java/org/springframework/test/context/aot/samples/suites/all/AllEnginesTestSuite.java new file mode 100644 index 000000000000..15a323024211 --- /dev/null +++ b/spring-test/src/test/java/org/springframework/test/context/aot/samples/suites/all/AllEnginesTestSuite.java @@ -0,0 +1,29 @@ +/* + * Copyright 2002-2022 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.suites.all; + +import org.junit.platform.suite.api.SelectPackages; +import org.junit.platform.suite.api.Suite; + +/** + * @author Sam Brannen + * @since 6.0 + */ +@Suite +@SelectPackages("org.springframework.test.context.aot.samples.basic") +public class AllEnginesTestSuite { +} diff --git a/spring-test/src/test/java/org/springframework/test/context/aot/samples/suites/jupiter/JupiterTestSuite.java b/spring-test/src/test/java/org/springframework/test/context/aot/samples/suites/jupiter/JupiterTestSuite.java new file mode 100644 index 000000000000..0bc58735bedf --- /dev/null +++ b/spring-test/src/test/java/org/springframework/test/context/aot/samples/suites/jupiter/JupiterTestSuite.java @@ -0,0 +1,31 @@ +/* + * Copyright 2002-2022 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.suites.jupiter; + +import org.junit.platform.suite.api.IncludeEngines; +import org.junit.platform.suite.api.SelectPackages; +import org.junit.platform.suite.api.Suite; + +/** + * @author Sam Brannen + * @since 6.0 + */ +@Suite +@IncludeEngines("junit-jupiter") +@SelectPackages("org.springframework.test.context.aot.samples.basic") +public class JupiterTestSuite { +} diff --git a/spring-test/src/test/java/org/springframework/test/context/aot/samples/suites/nested/NestedTestSuite.java b/spring-test/src/test/java/org/springframework/test/context/aot/samples/suites/nested/NestedTestSuite.java new file mode 100644 index 000000000000..9309dbb37c2a --- /dev/null +++ b/spring-test/src/test/java/org/springframework/test/context/aot/samples/suites/nested/NestedTestSuite.java @@ -0,0 +1,34 @@ +/* + * Copyright 2002-2022 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.suites.nested; + +import org.junit.platform.suite.api.IncludeClassNamePatterns; +import org.junit.platform.suite.api.SelectPackages; +import org.junit.platform.suite.api.Suite; + +/** + * @author Sam Brannen + * @since 6.0 + */ +@Suite +@IncludeClassNamePatterns(".*Suite$") +@SelectPackages({ + "org.springframework.test.context.aot.samples.suites.jupiter", + "org.springframework.test.context.aot.samples.suites.vintage" +}) +public class NestedTestSuite { +} diff --git a/spring-test/src/test/java/org/springframework/test/context/aot/samples/suites/testng/TestNGTestSuite.java b/spring-test/src/test/java/org/springframework/test/context/aot/samples/suites/testng/TestNGTestSuite.java new file mode 100644 index 000000000000..a8a8b8a27f41 --- /dev/null +++ b/spring-test/src/test/java/org/springframework/test/context/aot/samples/suites/testng/TestNGTestSuite.java @@ -0,0 +1,31 @@ +/* + * Copyright 2002-2022 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.suites.testng; + +import org.junit.platform.suite.api.IncludeEngines; +import org.junit.platform.suite.api.SelectPackages; +import org.junit.platform.suite.api.Suite; + +/** + * @author Sam Brannen + * @since 6.0 + */ +@Suite +@IncludeEngines("testng") +@SelectPackages("org.springframework.test.context.aot.samples.basic") +public class TestNGTestSuite { +} diff --git a/spring-test/src/test/java/org/springframework/test/context/aot/samples/suites/vintage/VintageTestSuite.java b/spring-test/src/test/java/org/springframework/test/context/aot/samples/suites/vintage/VintageTestSuite.java new file mode 100644 index 000000000000..dab5e5c843a2 --- /dev/null +++ b/spring-test/src/test/java/org/springframework/test/context/aot/samples/suites/vintage/VintageTestSuite.java @@ -0,0 +1,31 @@ +/* + * Copyright 2002-2022 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.suites.vintage; + +import org.junit.platform.suite.api.IncludeEngines; +import org.junit.platform.suite.api.SelectPackages; +import org.junit.platform.suite.api.Suite; + +/** + * @author Sam Brannen + * @since 6.0 + */ +@Suite +@IncludeEngines("junit-vintage") +@SelectPackages("org.springframework.test.context.aot.samples.basic") +public class VintageTestSuite { +} diff --git a/spring-test/src/test/resources/log4j2-test.xml b/spring-test/src/test/resources/log4j2-test.xml index 89d254091a47..8fc877aff3f8 100644 --- a/spring-test/src/test/resources/log4j2-test.xml +++ b/spring-test/src/test/resources/log4j2-test.xml @@ -14,6 +14,7 @@ + diff --git a/src/checkstyle/checkstyle-suppressions.xml b/src/checkstyle/checkstyle-suppressions.xml index 24bbed66a8e2..26ed87a7d6a3 100644 --- a/src/checkstyle/checkstyle-suppressions.xml +++ b/src/checkstyle/checkstyle-suppressions.xml @@ -77,7 +77,7 @@ - + @@ -90,7 +90,7 @@ - +