From 3d9f6da25e1ff18ed71a916f75125db7f90f2625 Mon Sep 17 00:00:00 2001 From: Ashley Scopes <73482956+ascopes@users.noreply.github.com> Date: Sat, 21 Jan 2023 20:35:46 +0000 Subject: [PATCH] Implement ability to change default versioning strategy in JUnit support. If the user wishes to iterate across sources/targets instead of releases for the JUnit annotations, there is now an attribute that can be overridden to support that. --- .../jct/junit/AbstractCompilersProvider.java | 36 ++-- .../ascopes/jct/junit/JavacCompilerTest.java | 11 + .../jct/junit/JavacCompilersProvider.java | 7 +- .../ascopes/jct/junit/VersionStrategy.java | 95 +++++++++ .../junit/AbstractCompilersProviderTest.java | 191 +++++++++--------- .../junit/JavacCompilersProviderTest.java | 8 +- .../tests/unit/junit/VersionStrategyTest.java | 111 ++++++++++ 7 files changed, 347 insertions(+), 112 deletions(-) create mode 100644 java-compiler-testing/src/main/java/io/github/ascopes/jct/junit/VersionStrategy.java create mode 100644 java-compiler-testing/src/test/java/io/github/ascopes/jct/tests/unit/junit/VersionStrategyTest.java diff --git a/java-compiler-testing/src/main/java/io/github/ascopes/jct/junit/AbstractCompilersProvider.java b/java-compiler-testing/src/main/java/io/github/ascopes/jct/junit/AbstractCompilersProvider.java index 6717d551b..f3dcdf9a1 100644 --- a/java-compiler-testing/src/main/java/io/github/ascopes/jct/junit/AbstractCompilersProvider.java +++ b/java-compiler-testing/src/main/java/io/github/ascopes/jct/junit/AbstractCompilersProvider.java @@ -51,6 +51,7 @@ * int minVersion() default Integer.MIN_VALUE; * int maxVersion() default Integer.MAX_VALUE; * Class<? extends JctSimpleCompilerConfigurer>[] configurers() default {}; + * VersionStrategy versionStrategy() default VersionStrategy.RELEASE; * } * * @@ -62,18 +63,18 @@ * implements AnnotationConsumer<MyCompilerTest> { * * {@literal @Override} - * protected JctCompiler<?, ?> compilerForVersion(int release) { - * return new MyCompilerImpl().release(release); + * protected JctCompiler<?, ?> initializeNewCompiler() { + * return new MyCompilerImpl(); * } * * {@literal @Override} * protected int minSupportedVersion(boolean modules) { - * return 11; + * return 11; // Support Java 11 as the minimum. * } * * {@literal @Override} * protected int maxSupportedVersion(boolean modules) { - * return 19; + * return 19; // Support Java 19 as the maximum. * } * * {@literal @Override} @@ -82,7 +83,8 @@ * annotation.minVersion(), * annotation.maxVersion(), * true, - * annotation.configurers() + * annotation.configurers(), + * annotation.versionStrategy(), * ); * } * } @@ -121,6 +123,7 @@ public abstract class AbstractCompilersProvider implements ArgumentsProvider { private int minVersion; private int maxVersion; private Class>[] configurerClasses; + private VersionStrategy versionStrategy; /** * Initialise this provider. @@ -129,13 +132,18 @@ protected AbstractCompilersProvider() { minVersion = 0; maxVersion = Integer.MAX_VALUE; configurerClasses = emptyArray(); + versionStrategy = VersionStrategy.RELEASE; } @Override public Stream provideArguments(ExtensionContext context) { return IntStream .rangeClosed(minVersion, maxVersion) - .mapToObj(this::compilerForVersion) + .mapToObj(version -> { + var compiler = initializeNewCompiler(); + versionStrategy.configureCompiler(compiler, version); + return compiler; + }) .peek(this::applyConfigurers) .map(Arguments::of); } @@ -147,12 +155,14 @@ public Stream provideArguments(ExtensionContext context) { * @param max the inclusive maximum compiler version to use. * @param modules whether the compiler version must support modules. * @param configurerClasses the configurer classes to apply to each compiler. + * @param versionStrategy the version strategy to use. */ protected final void configure( int min, int max, boolean modules, - Class>[] configurerClasses + Class>[] configurerClasses, + VersionStrategy versionStrategy ) { min = Math.max(min, minSupportedVersion(modules)); max = Math.min(max, maxSupportedVersion(modules)); @@ -171,15 +181,15 @@ protected final void configure( maxVersion = max; this.configurerClasses = requireNonNullValues(configurerClasses, "configurerClasses"); + this.versionStrategy = requireNonNull(versionStrategy, "versionStrategy"); } /** - * Initialise a new compiler on the given release. + * Initialise a new compiler. * - * @param release the release version to use. - * @return the compiler. + * @return the compiler object. */ - protected abstract JctCompiler compilerForVersion(int release); + protected abstract JctCompiler initializeNewCompiler(); /** * Get the minimum supported compiler version. @@ -201,7 +211,7 @@ private void applyConfigurers(JctCompiler compiler) { var classes = requireNonNull(configurerClasses); for (var configurerClass : classes) { - var configurer = initialiseConfigurer(configurerClass); + var configurer = initializeConfigurer(configurerClass); try { configurer.configure(compiler); @@ -218,7 +228,7 @@ private void applyConfigurers(JctCompiler compiler) { } } - private JctCompilerConfigurer initialiseConfigurer( + private JctCompilerConfigurer initializeConfigurer( Class> configurerClass ) { Constructor> constructor; diff --git a/java-compiler-testing/src/main/java/io/github/ascopes/jct/junit/JavacCompilerTest.java b/java-compiler-testing/src/main/java/io/github/ascopes/jct/junit/JavacCompilerTest.java index 628208e77..8533fecf0 100644 --- a/java-compiler-testing/src/main/java/io/github/ascopes/jct/junit/JavacCompilerTest.java +++ b/java-compiler-testing/src/main/java/io/github/ascopes/jct/junit/JavacCompilerTest.java @@ -79,4 +79,15 @@ */ boolean modules() default false; + /** + * The version strategy to use. + * + *

This determines whether the version number being iterated across specifies the + * release, source, target, or source and target versions. + * + *

The default is to specify the release. + * + * @return the version strategy to use. + */ + VersionStrategy versionStrategy() default VersionStrategy.RELEASE; } diff --git a/java-compiler-testing/src/main/java/io/github/ascopes/jct/junit/JavacCompilersProvider.java b/java-compiler-testing/src/main/java/io/github/ascopes/jct/junit/JavacCompilersProvider.java index c9778da71..5f5f4733d 100644 --- a/java-compiler-testing/src/main/java/io/github/ascopes/jct/junit/JavacCompilersProvider.java +++ b/java-compiler-testing/src/main/java/io/github/ascopes/jct/junit/JavacCompilersProvider.java @@ -41,8 +41,8 @@ public JavacCompilersProvider() { } @Override - protected JctCompiler compilerForVersion(int release) { - return new JavacJctCompilerImpl("javac release " + release).release(release); + protected JctCompiler initializeNewCompiler() { + return new JavacJctCompilerImpl(); } @Override @@ -62,7 +62,8 @@ public void accept(JavacCompilerTest javacCompilers) { javacCompilers.minVersion(), javacCompilers.maxVersion(), javacCompilers.modules(), - javacCompilers.configurers() + javacCompilers.configurers(), + javacCompilers.versionStrategy() ); } } diff --git a/java-compiler-testing/src/main/java/io/github/ascopes/jct/junit/VersionStrategy.java b/java-compiler-testing/src/main/java/io/github/ascopes/jct/junit/VersionStrategy.java new file mode 100644 index 000000000..848dead3d --- /dev/null +++ b/java-compiler-testing/src/main/java/io/github/ascopes/jct/junit/VersionStrategy.java @@ -0,0 +1,95 @@ +/* + * Copyright (C) 2022 - 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 + * + * http://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 io.github.ascopes.jct.junit; + +import io.github.ascopes.jct.compilers.JctCompiler; +import java.util.function.BiConsumer; +import javax.annotation.concurrent.Immutable; +import javax.annotation.concurrent.ThreadSafe; +import org.apiguardian.api.API; +import org.apiguardian.api.API.Status; + +/** + * Strategy for setting a version on a JUnit compiler annotation. + * + * @author Ashley Scopes + * @since 0.0.1 (0.0.1-M7) + */ +@API(since = "0.0.1", status = Status.STABLE) +@Immutable +@ThreadSafe +public enum VersionStrategy { + + /** + * Set the {@link JctCompiler#release release}. + */ + RELEASE( + JctCompiler::release, + (compiler, version) -> compiler + .name(compiler.getName() + " (release = Java " + version + ")") + ), + + /** + * Set the {@link JctCompiler#source} source}. + */ + SOURCE( + JctCompiler::source, + (compiler, version) -> compiler + .name(compiler.getName() + " (source = Java " + version + ")") + ), + + /** + * Set the {@link JctCompiler#target} target}. + */ + TARGET( + JctCompiler::target, + (compiler, version) -> compiler + .name(compiler.getName() + " (target = Java " + version + ")") + ), + + /** + * Set the {@link JctCompiler#source source} and {@link JctCompiler#target target}. + */ + SOURCE_AND_TARGET( + (compiler, version) -> compiler + .source(version) + .target(version), + (compiler, version) -> compiler + .name(compiler.getName() + " (source and target = Java " + version + ")") + ); + + private final BiConsumer, Integer> versionSetter; + private final BiConsumer, Integer> descriptionFormatter; + + VersionStrategy( + BiConsumer, Integer> versionSetter, + BiConsumer, Integer> descriptionFormatter + ) { + this.versionSetter = versionSetter; + this.descriptionFormatter = descriptionFormatter; + } + + /** + * Set the given version on the compiler, according to the strategy in use. + * + * @param compiler the compiler to configure. + * @param version the version to set. + */ + public void configureCompiler(JctCompiler compiler, int version) { + versionSetter.accept(compiler, version); + descriptionFormatter.accept(compiler, version); + } +} diff --git a/java-compiler-testing/src/test/java/io/github/ascopes/jct/tests/unit/junit/AbstractCompilersProviderTest.java b/java-compiler-testing/src/test/java/io/github/ascopes/jct/tests/unit/junit/AbstractCompilersProviderTest.java index a7c632933..d45fb3805 100644 --- a/java-compiler-testing/src/test/java/io/github/ascopes/jct/tests/unit/junit/AbstractCompilersProviderTest.java +++ b/java-compiler-testing/src/test/java/io/github/ascopes/jct/tests/unit/junit/AbstractCompilersProviderTest.java @@ -18,19 +18,20 @@ import static io.github.ascopes.jct.tests.helpers.GenericMock.mockRaw; import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.AssertionsForClassTypes.assertThatThrownBy; -import static org.assertj.core.api.InstanceOfAssertFactories.STRING; import static org.assertj.core.api.InstanceOfAssertFactories.THROWABLE; import static org.assertj.core.api.InstanceOfAssertFactories.array; import static org.assertj.core.api.SoftAssertions.assertSoftly; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.mockConstruction; import static org.mockito.Mockito.verify; -import static org.mockito.Mockito.when; +import static org.mockito.Mockito.verifyNoMoreInteractions; +import static org.mockito.Mockito.withSettings; import io.github.ascopes.jct.compilers.JctCompiler; import io.github.ascopes.jct.compilers.JctCompilerConfigurer; import io.github.ascopes.jct.ex.JctJunitConfigurerException; import io.github.ascopes.jct.junit.AbstractCompilersProvider; +import io.github.ascopes.jct.junit.VersionStrategy; import java.lang.reflect.InvocationTargetException; import java.util.stream.Collectors; import org.junit.jupiter.api.DisplayName; @@ -49,64 +50,6 @@ @DisplayName("AbstractCompilersProvider tests") class AbstractCompilersProviderTest { - @DisplayName("Configuring the provider with a version too low will use the minimum version") - @Test - void configuringTheProviderWithTooLowVersionWillUseTheMinimumVersion() { - // Given - var provider = new CompilersProviderImpl(8, 17); - - // When - provider.configureInternals(5, 17); - var compilers = provider.provideArguments(mock(ExtensionContext.class)) - .map(args -> (JctCompiler) args.get()[0]) - .collect(Collectors.toList()); - - // Then - assertThat(compilers) - .as("compilers that were initialised (%s)", compilers) - .hasSize(17 - 8 + 1); - - assertSoftly(softly -> { - for (var i = 0; i < compilers.size(); ++i) { - softly.assertThat(compilers) - .as("compilers[%d]", i) - .element(i) - .as("compilers[%d].getRelease()", i) - .extracting(JctCompiler::getRelease, STRING) - .isEqualTo("%d", 8 + i); - } - }); - } - - @DisplayName("Configuring the provider with a version too high will use the maximum version") - @Test - void configuringTheProviderWithTooHighVersionWillUseTheMaximumVersion() { - // Given - var provider = new CompilersProviderImpl(8, 17); - - // When - provider.configureInternals(8, 30); - var compilers = provider.provideArguments(mock(ExtensionContext.class)) - .map(args -> (JctCompiler) args.get()[0]) - .collect(Collectors.toList()); - - // Then - assertThat(compilers) - .as("compilers that were initialised (%s)", compilers) - .hasSize(17 - 8 + 1); - - assertSoftly(softly -> { - for (var i = 0; i < compilers.size(); ++i) { - softly.assertThat(compilers) - .as("compilers[%d]", i) - .element(i) - .as("compilers[%d].getRelease()", i) - .extracting(JctCompiler::getRelease, STRING) - .isEqualTo("%d", 8 + i); - } - }); - } - @DisplayName("Configuring the provider with a version below Java 8 will raise an exception") @CsvSource({ "7, 12", @@ -118,7 +61,7 @@ void configuringTheProviderWithPreJava8WillRaiseException(int min, int max) { var provider = new CompilersProviderImpl(3, 17); // Then - assertThatThrownBy(() -> provider.configureInternals(min, max)) + assertThatThrownBy(() -> provider.configureInternals(min, max, VersionStrategy.RELEASE)) .isInstanceOf(IllegalArgumentException.class) .hasMessage("Cannot use a Java version less than Java 8"); } @@ -132,38 +75,91 @@ void configuringTheProviderWithMinAboveMaxWillRaiseException() { var provider = new CompilersProviderImpl(5, 17); // Then - assertThatThrownBy(() -> provider.configureInternals(11, 10)) + assertThatThrownBy(() -> provider.configureInternals(11, 10, VersionStrategy.RELEASE)) .isInstanceOf(IllegalArgumentException.class) .hasMessage("Cannot set min version to a version higher than the max version"); } - @DisplayName("Configuring the provider with a valid version range will use that range") + @DisplayName("Configuring the provider with a null version strategy will raise an exception") + @SuppressWarnings("DataFlowIssue") @Test - void configuringTheProviderWithValidVersionRangeWillUseThatRange() { + void configuringTheProviderWithNullVersionStrategyWillRaiseException() { // Given var provider = new CompilersProviderImpl(8, 17); + // Then + assertThatThrownBy(() -> provider.configureInternals(10, 15, null)) + .isInstanceOf(NullPointerException.class) + .hasMessage("versionStrategy"); + } + + @DisplayName("Configuring the provider with a version strategy uses that strategy") + @Test + void configuringTheProviderWithVersionStrategyUsesThatStrategy() { + // Given + var provider = new CompilersProviderImpl(8, 17); + var versionStrategy = mock(VersionStrategy.class); + // When - provider.configureInternals(10, 15); + provider.configureInternals(10, 15, versionStrategy); var compilers = provider.provideArguments(mock(ExtensionContext.class)) .map(args -> (JctCompiler) args.get()[0]) .collect(Collectors.toList()); // Then - assertThat(compilers) - .as("compilers that were initialised (%s)", compilers) - .hasSize(6); + for (var i = 0; i < compilers.size(); ++i) { + var compiler = compilers.get(i); + var version = 10 + i; + verify(versionStrategy).configureCompiler(compiler, version); + } - assertSoftly(softly -> { - for (var i = 0; i < compilers.size(); ++i) { - softly.assertThat(compilers) - .as("compilers[%d]", i) - .element(i) - .as("compilers[%d].getRelease()", i) - .extracting(JctCompiler::getRelease, STRING) - .isEqualTo("%d", 10 + i); - } - }); + verifyNoMoreInteractions(versionStrategy); + } + + @DisplayName("Configuring the provider respects the minimum version bound") + @Test + void configuringTheProviderRespectsTheMinimumVersionBound() { + // Given + var provider = new CompilersProviderImpl(15, 17); + var versionStrategy = mock(VersionStrategy.class); + + // When + provider.configureInternals(10, 17, versionStrategy); + var compilers = provider.provideArguments(mock(ExtensionContext.class)) + .map(args -> (JctCompiler) args.get()[0]) + .collect(Collectors.toList()); + + // Then + assertThat(compilers).hasSize(3); + + for (var i = 0; i < compilers.size(); ++i) { + var compiler = compilers.get(i); + var version = 15 + i; + verify(versionStrategy).configureCompiler(compiler, version); + } + } + + @DisplayName("Configuring the provider respects the maximum version bound") + @Test + void configuringTheProviderRespectsTheMaximumVersionBound() { + // Given + var provider = new CompilersProviderImpl(15, 17); + var versionStrategy = mock(VersionStrategy.class); + + // When + provider.configureInternals(15, 20, versionStrategy); + var compilers = provider.provideArguments(mock(ExtensionContext.class)) + .map(args -> (JctCompiler) args.get()[0]) + .collect(Collectors.toList()); + + // Then + assertThat(compilers).hasSize(3); + + for (var i = 0; i < compilers.size(); ++i) { + var compiler = compilers.get(i); + var version = 15 + i; + verify(versionStrategy).configureCompiler(compiler, version); + } } @DisplayName("Configuring the provider with configurers will initialise those configurers") @@ -179,7 +175,8 @@ void configuringTheProviderWithConfigurersWillUseConfigurers() { // When provider.configureInternals( - 10, 15, FooConfigurer.class, BarConfigurer.class, BazConfigurer.class + 10, 15, VersionStrategy.RELEASE, + FooConfigurer.class, BarConfigurer.class, BazConfigurer.class ); var compilers = provider.provideArguments(mock(ExtensionContext.class)) .map(args -> (JctCompiler) args.get()[0]) @@ -234,7 +231,9 @@ void configurersThrowingTestAbortedExceptionInConstructorsWillPropagate() { var provider = new CompilersProviderImpl(8, 17); // When - provider.configureInternals(10, 15, AbortedConstructorConfigurer.class); + provider.configureInternals( + 10, 15, VersionStrategy.RELEASE, AbortedConstructorConfigurer.class + ); // Then assertThatThrownBy(() -> provider.provideArguments(mock(ExtensionContext.class)).toArray()) @@ -255,7 +254,10 @@ void configurersThrowingTestAbortedExceptionWhenConfiguringWillPropagate() { var provider = new CompilersProviderImpl(8, 17); // When - provider.configureInternals(10, 15, AbortedConfigureConfigurer.class); + provider.configureInternals( + 10, 15, VersionStrategy.RELEASE, + AbortedConfigureConfigurer.class + ); // Then assertThatThrownBy(() -> provider.provideArguments(mock(ExtensionContext.class)).toArray()) @@ -271,7 +273,9 @@ void configurersThrowingExceptionsInConstructorsWillPropagate() { var provider = new CompilersProviderImpl(8, 17); // When - provider.configureInternals(10, 15, ThrowingConstructorConfigurer.class); + provider.configureInternals( + 10, 15, VersionStrategy.RELEASE, ThrowingConstructorConfigurer.class + ); // Then assertThatThrownBy(() -> provider.provideArguments(mock(ExtensionContext.class)).toArray()) @@ -292,7 +296,7 @@ void abstractConfigurersWillProduceExceptions() { var provider = new CompilersProviderImpl(8, 17); // When - provider.configureInternals(10, 15, AbstractConfigurer.class); + provider.configureInternals(10, 15, VersionStrategy.RELEASE, AbstractConfigurer.class); // Then assertThatThrownBy(() -> provider.provideArguments(mock(ExtensionContext.class)).toArray()) @@ -311,7 +315,9 @@ void configurersThrowingExceptionsWhenConfiguringWillPropagate() { var provider = new CompilersProviderImpl(8, 17); // When - provider.configureInternals(10, 15, ThrowingConfigureConfigurer.class); + provider.configureInternals( + 10, 15, VersionStrategy.RELEASE, ThrowingConfigureConfigurer.class + ); // Then assertThatThrownBy(() -> provider.provideArguments(mock(ExtensionContext.class)).toArray()) @@ -332,7 +338,9 @@ void configurersWithNonDefaultConstructorsWillProduceExceptions() { var provider = new CompilersProviderImpl(8, 17); // When - provider.configureInternals(10, 15, NonDefaultConstructorConfigurer.class); + provider.configureInternals( + 10, 15, VersionStrategy.RELEASE, NonDefaultConstructorConfigurer.class + ); // Then assertThatThrownBy(() -> provider.provideArguments(mock(ExtensionContext.class)).toArray()) @@ -362,20 +370,17 @@ public CompilersProviderImpl(int minSupportedVersion, int maxSupportedVersion) { final void configureInternals( int min, int max, + VersionStrategy versionStrategy, Class>... configurerClasses ) { - configure(min, max, false, configurerClasses); + configure(min, max, false, configurerClasses, versionStrategy); } @Override - protected JctCompiler compilerForVersion(int release) { - var mock = mockRaw(JctCompiler.class) + protected JctCompiler initializeNewCompiler() { + return mockRaw(JctCompiler.class) .>upcastedTo() - .build(); - - when(mock.getRelease()).thenReturn(Integer.toString(release)); - - return mock; + .build(withSettings().name("mock compiler")); } @Override diff --git a/java-compiler-testing/src/test/java/io/github/ascopes/jct/tests/unit/junit/JavacCompilersProviderTest.java b/java-compiler-testing/src/test/java/io/github/ascopes/jct/tests/unit/junit/JavacCompilersProviderTest.java index ffe4dd78c..16707264c 100644 --- a/java-compiler-testing/src/test/java/io/github/ascopes/jct/tests/unit/junit/JavacCompilersProviderTest.java +++ b/java-compiler-testing/src/test/java/io/github/ascopes/jct/tests/unit/junit/JavacCompilersProviderTest.java @@ -28,6 +28,7 @@ import io.github.ascopes.jct.compilers.javac.JavacJctCompilerImpl; import io.github.ascopes.jct.junit.JavacCompilerTest; import io.github.ascopes.jct.junit.JavacCompilersProvider; +import io.github.ascopes.jct.junit.VersionStrategy; import java.lang.reflect.AnnotatedElement; import java.util.stream.Collectors; import org.junit.jupiter.api.DisplayName; @@ -69,7 +70,7 @@ void providerUsesTheUserProvidedVersionRangesWhenValid(boolean modules) { var compiler = compilers.get(i); softly.assertThat(compiler.getName()) .as("compilers[%d].getName()", i) - .isEqualTo("javac release %d", 10 + i); + .isEqualTo("JDK Compiler (release = Java %d)", 10 + i); softly.assertThat(compiler.getRelease()) .as("compilers[%d].getRelease()", i) .isEqualTo("%d", 10 + i); @@ -106,7 +107,7 @@ void providerUsesTheMinCompilerVersionAllowedIfExceeded(boolean modules) { var compiler = compilers.get(i); softly.assertThat(compiler.getName()) .as("compilers[%d].getName()", i) - .isEqualTo("javac release %d", 8 + i); + .isEqualTo("JDK Compiler (release = Java %d)", 8 + i); softly.assertThat(compiler.getRelease()) .as("compilers[%d].getRelease()", i) .isEqualTo("%d", 8 + i); @@ -143,7 +144,7 @@ void providerUsesTheMaxCompilerVersionAllowedIfExceeded(boolean modules) { var compiler = compilers.get(i); softly.assertThat(compiler.getName()) .as("compilers[%d].getName()", i) - .isEqualTo("javac release %d", 10 + i); + .isEqualTo("JDK Compiler (release = Java %d)", 10 + i); softly.assertThat(compiler.getRelease()) .as("compilers[%d].getRelease()", i) .isEqualTo("%d", 10 + i); @@ -164,6 +165,7 @@ final JavacCompilerTest someAnnotation( when(annotation.maxVersion()).thenReturn(max); when(annotation.modules()).thenReturn(modules); when(annotation.configurers()).thenReturn(configurers); + when(annotation.versionStrategy()).thenReturn(VersionStrategy.RELEASE); when(annotation.annotationType()).thenAnswer(ctx -> JavacCompilerTest.class); return annotation; } diff --git a/java-compiler-testing/src/test/java/io/github/ascopes/jct/tests/unit/junit/VersionStrategyTest.java b/java-compiler-testing/src/test/java/io/github/ascopes/jct/tests/unit/junit/VersionStrategyTest.java new file mode 100644 index 000000000..e4fa31df4 --- /dev/null +++ b/java-compiler-testing/src/test/java/io/github/ascopes/jct/tests/unit/junit/VersionStrategyTest.java @@ -0,0 +1,111 @@ +/* + * Copyright (C) 2022 - 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 + * + * http://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 io.github.ascopes.jct.tests.unit.junit; + +import static io.github.ascopes.jct.tests.helpers.Fixtures.someText; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.verifyNoMoreInteractions; +import static org.mockito.Mockito.when; + +import io.github.ascopes.jct.compilers.JctCompiler; +import io.github.ascopes.jct.junit.VersionStrategy; +import io.github.ascopes.jct.tests.helpers.Fixtures; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.extension.ExtendWith; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.ValueSource; +import org.mockito.Answers; +import org.mockito.Mock; +import org.mockito.Mock.Strictness; +import org.mockito.junit.jupiter.MockitoExtension; + +/** + * {@link VersionStrategy} tests. + * + * @author Ashley Scopes + */ +@DisplayName("VersionStrategy tests") +@ExtendWith(MockitoExtension.class) +class VersionStrategyTest { + String baseName; + + @Mock(answer = Answers.RETURNS_SELF, strictness = Strictness.LENIENT) + JctCompiler compiler; + + @BeforeEach + void setUp() { + baseName = someText(); + when(compiler.getName()).thenReturn(baseName); + } + + @DisplayName("RELEASE sets the release") + @ValueSource(ints = {10, 15, 20}) + @ParameterizedTest(name = "for version {0}") + void releaseSetsTheRelease(int version) { + // When + VersionStrategy.RELEASE.configureCompiler(compiler, version); + + // Then + verify(compiler).release(version); + verify(compiler).getName(); + verify(compiler).name(baseName + " (release = Java " + version + ")"); + verifyNoMoreInteractions(compiler); + } + + @DisplayName("SOURCE sets the source") + @ValueSource(ints = {10, 15, 20}) + @ParameterizedTest(name = "for version {0}") + void sourceSetsTheSource(int version) { + // When + VersionStrategy.SOURCE.configureCompiler(compiler, version); + + // Then + verify(compiler).source(version); + verify(compiler).getName(); + verify(compiler).name(baseName + " (source = Java " + version + ")"); + verifyNoMoreInteractions(compiler); + } + + @DisplayName("TARGET sets the target") + @ValueSource(ints = {10, 15, 20}) + @ParameterizedTest(name = "for version {0}") + void targetSetsTheTarget(int version) { + // When + VersionStrategy.TARGET.configureCompiler(compiler, version); + + // Then + verify(compiler).target(version); + verify(compiler).getName(); + verify(compiler).name(baseName + " (target = Java " + version + ")"); + verifyNoMoreInteractions(compiler); + } + + @DisplayName("SOURCE_AND_TARGET sets the target") + @ValueSource(ints = {10, 15, 20}) + @ParameterizedTest(name = "for version {0}") + void sourceAndTargetSetsTheSourceAndTarget(int version) { + // When + VersionStrategy.SOURCE_AND_TARGET.configureCompiler(compiler, version); + + // Then + verify(compiler).source(version); + verify(compiler).target(version); + verify(compiler).getName(); + verify(compiler).name(baseName + " (source and target = Java " + version + ")"); + verifyNoMoreInteractions(compiler); + } +}