From 3c262cc4fbd739eada198db79bce87a7cb8609c7 Mon Sep 17 00:00:00 2001 From: Marc Philipp Date: Mon, 14 Nov 2022 08:16:12 +0100 Subject: [PATCH 0001/1473] Remove duplication --- .../launcher/core/LauncherFactoryTests.java | 24 ++++--------------- 1 file changed, 4 insertions(+), 20 deletions(-) diff --git a/platform-tests/src/test/java/org/junit/platform/launcher/core/LauncherFactoryTests.java b/platform-tests/src/test/java/org/junit/platform/launcher/core/LauncherFactoryTests.java index d33d88956201..5b6368f79eaf 100644 --- a/platform-tests/src/test/java/org/junit/platform/launcher/core/LauncherFactoryTests.java +++ b/platform-tests/src/test/java/org/junit/platform/launcher/core/LauncherFactoryTests.java @@ -124,12 +124,7 @@ void createWithPostDiscoveryFilters() { @Test void applyPostDiscoveryFiltersViaServiceApi() { - final var current = Thread.currentThread().getContextClassLoader(); - try { - var url = getClass().getClassLoader().getResource("testservices/"); - var classLoader = new URLClassLoader(new URL[] { url }, current); - Thread.currentThread().setContextClassLoader(classLoader); - + withTestServices(() -> { var discoveryRequest = createLauncherDiscoveryRequestForBothStandardEngineExampleClasses(); var config = LauncherConfig.builder()// @@ -141,20 +136,12 @@ void applyPostDiscoveryFiltersViaServiceApi() { final var jupiter = testPlan.getChildren(UniqueId.parse("[engine:junit-jupiter]")); assertThat(jupiter).hasSize(1); - } - finally { - Thread.currentThread().setContextClassLoader(current); - } + }); } @Test void notApplyIfDisabledPostDiscoveryFiltersViaServiceApi() { - final var current = Thread.currentThread().getContextClassLoader(); - try { - var url = getClass().getClassLoader().getResource("testservices/"); - var classLoader = new URLClassLoader(new URL[] { url }, current); - Thread.currentThread().setContextClassLoader(classLoader); - + withTestServices(() -> { var discoveryRequest = createLauncherDiscoveryRequestForBothStandardEngineExampleClasses(); var config = LauncherConfig.builder()// @@ -166,10 +153,7 @@ void notApplyIfDisabledPostDiscoveryFiltersViaServiceApi() { final var jupiter = testPlan.getChildren(UniqueId.parse("[engine:junit-jupiter]")); assertThat(jupiter).hasSize(1); - } - finally { - Thread.currentThread().setContextClassLoader(current); - } + }); } @Test From fa4760231c517218268147fa349c82743c1f8f91 Mon Sep 17 00:00:00 2001 From: Marc Philipp Date: Fri, 11 Nov 2022 16:29:56 +0100 Subject: [PATCH 0002/1473] Introduce LauncherInterceptor --- .../platform/launcher/LauncherConstants.java | 2 + .../launcher/LauncherInterceptor.java | 57 ++++++++++++ .../core/CloseableInternalLauncher.java | 19 ++++ .../launcher/core/DefaultLauncherSession.java | 71 +++++++-------- .../DelegatingCloseableInternalLauncher.java | 30 +++++++ .../core/DelegatingInternalLauncher.java | 63 ++++++++++++++ .../core/InterceptingInternalLauncher.java | 86 +++++++++++++++++++ .../launcher/core/LauncherFactory.java | 36 ++++++-- .../core/SessionPerRequestLauncher.java | 37 +++----- .../launcher/TestLauncherInterceptor1.java | 23 +++++ .../launcher/TestLauncherInterceptor2.java | 23 +++++ .../launcher/core/LauncherFactoryTests.java | 84 ++++++++++++++++++ ...unit.platform.launcher.LauncherInterceptor | 2 + 13 files changed, 461 insertions(+), 72 deletions(-) create mode 100644 junit-platform-launcher/src/main/java/org/junit/platform/launcher/LauncherInterceptor.java create mode 100644 junit-platform-launcher/src/main/java/org/junit/platform/launcher/core/CloseableInternalLauncher.java create mode 100644 junit-platform-launcher/src/main/java/org/junit/platform/launcher/core/DelegatingCloseableInternalLauncher.java create mode 100644 junit-platform-launcher/src/main/java/org/junit/platform/launcher/core/DelegatingInternalLauncher.java create mode 100644 junit-platform-launcher/src/main/java/org/junit/platform/launcher/core/InterceptingInternalLauncher.java create mode 100644 platform-tests/src/test/java/org/junit/platform/launcher/TestLauncherInterceptor1.java create mode 100644 platform-tests/src/test/java/org/junit/platform/launcher/TestLauncherInterceptor2.java create mode 100644 platform-tests/src/test/resources/testservices/META-INF/services/org.junit.platform.launcher.LauncherInterceptor diff --git a/junit-platform-launcher/src/main/java/org/junit/platform/launcher/LauncherConstants.java b/junit-platform-launcher/src/main/java/org/junit/platform/launcher/LauncherConstants.java index b4f5916f00c1..218bf3a077ed 100644 --- a/junit-platform-launcher/src/main/java/org/junit/platform/launcher/LauncherConstants.java +++ b/junit-platform-launcher/src/main/java/org/junit/platform/launcher/LauncherConstants.java @@ -135,6 +135,8 @@ public class LauncherConstants { */ public static final String DEACTIVATE_ALL_LISTENERS_PATTERN = ClassNamePatternFilterUtils.DEACTIVATE_ALL_PATTERN; + public static final String ENABLE_LAUNCHER_INTERCEPTORS = "junit.platform.launcher.interceptors.enabled"; + private LauncherConstants() { /* no-op */ } diff --git a/junit-platform-launcher/src/main/java/org/junit/platform/launcher/LauncherInterceptor.java b/junit-platform-launcher/src/main/java/org/junit/platform/launcher/LauncherInterceptor.java new file mode 100644 index 000000000000..cf91b3d67d10 --- /dev/null +++ b/junit-platform-launcher/src/main/java/org/junit/platform/launcher/LauncherInterceptor.java @@ -0,0 +1,57 @@ +/* + * Copyright 2015-2023 the original author or authors. + * + * All rights reserved. This program and the accompanying materials are + * made available under the terms of the Eclipse Public License v2.0 which + * accompanies this distribution and is available at + * + * https://www.eclipse.org/legal/epl-v20.html + */ + +package org.junit.platform.launcher; + +import static org.apiguardian.api.API.Status.EXPERIMENTAL; + +import org.apiguardian.api.API; + +/** + * Interceptor for test discovery and execution by a {@link Launcher}. + * + *

Interceptors are instantiated once per {@link LauncherSession} and closed + * when the session is about to be closed. + * + * @since 1.10 + * @see Launcher + * @see LauncherSession + * @see LauncherConstants#ENABLE_LAUNCHER_INTERCEPTORS + */ +@API(status = EXPERIMENTAL, since = "1.10") +public interface LauncherInterceptor { + + /** + * Intercept the supplied invocation. + * + *

Implementations must call {@link Invocation#proceed()} exactly once. + * + * @param invocation the intercepted invocation; never {@code null} + * @return the result of the invocation + */ + T intercept(Invocation invocation); + + /** + * Closes this interceptor. + * + *

Any resources held by this interceptor should be released by this + * method. + */ + void close(); + + /** + * An invocation that can be intercepted. + * + *

This interface is not intended to be implemented by clients. + */ + interface Invocation { + T proceed(); + } +} diff --git a/junit-platform-launcher/src/main/java/org/junit/platform/launcher/core/CloseableInternalLauncher.java b/junit-platform-launcher/src/main/java/org/junit/platform/launcher/core/CloseableInternalLauncher.java new file mode 100644 index 000000000000..110057708947 --- /dev/null +++ b/junit-platform-launcher/src/main/java/org/junit/platform/launcher/core/CloseableInternalLauncher.java @@ -0,0 +1,19 @@ +/* + * Copyright 2015-2023 the original author or authors. + * + * All rights reserved. This program and the accompanying materials are + * made available under the terms of the Eclipse Public License v2.0 which + * accompanies this distribution and is available at + * + * https://www.eclipse.org/legal/epl-v20.html + */ + +package org.junit.platform.launcher.core; + +/** + * @since 1.10 + */ +interface CloseableInternalLauncher extends InternalLauncher, AutoCloseable { + @Override + void close(); +} diff --git a/junit-platform-launcher/src/main/java/org/junit/platform/launcher/core/DefaultLauncherSession.java b/junit-platform-launcher/src/main/java/org/junit/platform/launcher/core/DefaultLauncherSession.java index 79f6d815fc76..a8fa1150fa5f 100644 --- a/junit-platform-launcher/src/main/java/org/junit/platform/launcher/core/DefaultLauncherSession.java +++ b/junit-platform-launcher/src/main/java/org/junit/platform/launcher/core/DefaultLauncherSession.java @@ -10,10 +10,13 @@ package org.junit.platform.launcher.core; +import java.util.List; + import org.junit.platform.commons.PreconditionViolationException; import org.junit.platform.launcher.Launcher; import org.junit.platform.launcher.LauncherDiscoveryListener; import org.junit.platform.launcher.LauncherDiscoveryRequest; +import org.junit.platform.launcher.LauncherInterceptor; import org.junit.platform.launcher.LauncherSession; import org.junit.platform.launcher.LauncherSessionListener; import org.junit.platform.launcher.TestExecutionListener; @@ -27,8 +30,9 @@ class DefaultLauncherSession implements LauncherSession { private final DelegatingLauncher launcher; private final LauncherSessionListener listener; - DefaultLauncherSession(Launcher launcher, LauncherSessionListener listener) { - this.launcher = new DelegatingLauncher(launcher); + DefaultLauncherSession(InternalLauncher launcher, LauncherSessionListener listener, + List interceptors) { + this.launcher = new DelegatingLauncher(InterceptingInternalLauncher.decorate(launcher, interceptors)); this.listener = listener; listener.launcherSessionOpened(this); } @@ -44,55 +48,31 @@ LauncherSessionListener getListener() { @Override public void close() { - if (launcher.getDelegate() != ClosedLauncher.INSTANCE) { - launcher.setDelegate(ClosedLauncher.INSTANCE); + if (launcher.isClosed()) { + launcher.close(); listener.launcherSessionClosed(this); } } - private static class DelegatingLauncher implements Launcher { - - private Launcher delegate; - - DelegatingLauncher(Launcher delegate) { - this.delegate = delegate; - } - - public Launcher getDelegate() { - return delegate; - } - - public void setDelegate(Launcher delegate) { - this.delegate = delegate; - } - - @Override - public void registerLauncherDiscoveryListeners(LauncherDiscoveryListener... listeners) { - delegate.registerLauncherDiscoveryListeners(listeners); - } - - @Override - public void registerTestExecutionListeners(TestExecutionListener... listeners) { - delegate.registerTestExecutionListeners(listeners); - } + private static class DelegatingLauncher extends DelegatingInternalLauncher + implements CloseableInternalLauncher { - @Override - public TestPlan discover(LauncherDiscoveryRequest launcherDiscoveryRequest) { - return delegate.discover(launcherDiscoveryRequest); + DelegatingLauncher(CloseableInternalLauncher delegate) { + super(delegate); } - @Override - public void execute(LauncherDiscoveryRequest launcherDiscoveryRequest, TestExecutionListener... listeners) { - delegate.execute(launcherDiscoveryRequest, listeners); + boolean isClosed() { + return delegate != ClosedLauncher.INSTANCE; } @Override - public void execute(TestPlan testPlan, TestExecutionListener... listeners) { - delegate.execute(testPlan, listeners); + public void close() { + delegate.close(); + delegate = ClosedLauncher.INSTANCE; } } - private static class ClosedLauncher implements Launcher { + private static class ClosedLauncher implements CloseableInternalLauncher { static final ClosedLauncher INSTANCE = new ClosedLauncher(); @@ -123,5 +103,20 @@ public void execute(LauncherDiscoveryRequest launcherDiscoveryRequest, TestExecu public void execute(TestPlan testPlan, TestExecutionListener... listeners) { throw new PreconditionViolationException("Launcher session has already been closed"); } + + @Override + public ListenerRegistry getTestExecutionListenerRegistry() { + throw new PreconditionViolationException("Launcher session has already been closed"); + } + + @Override + public ListenerRegistry getLauncherDiscoveryListenerRegistry() { + throw new PreconditionViolationException("Launcher session has already been closed"); + } + + @Override + public void close() { + // do nothing + } } } diff --git a/junit-platform-launcher/src/main/java/org/junit/platform/launcher/core/DelegatingCloseableInternalLauncher.java b/junit-platform-launcher/src/main/java/org/junit/platform/launcher/core/DelegatingCloseableInternalLauncher.java new file mode 100644 index 000000000000..1282cf7ac7d9 --- /dev/null +++ b/junit-platform-launcher/src/main/java/org/junit/platform/launcher/core/DelegatingCloseableInternalLauncher.java @@ -0,0 +1,30 @@ +/* + * Copyright 2015-2023 the original author or authors. + * + * All rights reserved. This program and the accompanying materials are + * made available under the terms of the Eclipse Public License v2.0 which + * accompanies this distribution and is available at + * + * https://www.eclipse.org/legal/epl-v20.html + */ + +package org.junit.platform.launcher.core; + +/** + * @since 1.10 + */ +class DelegatingCloseableInternalLauncher extends DelegatingInternalLauncher + implements CloseableInternalLauncher { + + private final Runnable onClose; + + public DelegatingCloseableInternalLauncher(T delegate, Runnable onClose) { + super(delegate); + this.onClose = onClose; + } + + @Override + public final void close() { + onClose.run(); + } +} diff --git a/junit-platform-launcher/src/main/java/org/junit/platform/launcher/core/DelegatingInternalLauncher.java b/junit-platform-launcher/src/main/java/org/junit/platform/launcher/core/DelegatingInternalLauncher.java new file mode 100644 index 000000000000..c4078ff94ae8 --- /dev/null +++ b/junit-platform-launcher/src/main/java/org/junit/platform/launcher/core/DelegatingInternalLauncher.java @@ -0,0 +1,63 @@ +/* + * Copyright 2015-2023 the original author or authors. + * + * All rights reserved. This program and the accompanying materials are + * made available under the terms of the Eclipse Public License v2.0 which + * accompanies this distribution and is available at + * + * https://www.eclipse.org/legal/epl-v20.html + */ + +package org.junit.platform.launcher.core; + +import org.junit.platform.launcher.LauncherDiscoveryListener; +import org.junit.platform.launcher.LauncherDiscoveryRequest; +import org.junit.platform.launcher.TestExecutionListener; +import org.junit.platform.launcher.TestPlan; + +/** + * @since 1.10 + */ +class DelegatingInternalLauncher implements InternalLauncher { + + protected T delegate; + + DelegatingInternalLauncher(T delegate) { + this.delegate = delegate; + } + + @Override + public void registerLauncherDiscoveryListeners(LauncherDiscoveryListener... listeners) { + delegate.registerLauncherDiscoveryListeners(listeners); + } + + @Override + public void registerTestExecutionListeners(TestExecutionListener... listeners) { + delegate.registerTestExecutionListeners(listeners); + } + + @Override + public TestPlan discover(LauncherDiscoveryRequest launcherDiscoveryRequest) { + return delegate.discover(launcherDiscoveryRequest); + } + + @Override + public void execute(LauncherDiscoveryRequest launcherDiscoveryRequest, TestExecutionListener... listeners) { + delegate.execute(launcherDiscoveryRequest, listeners); + } + + @Override + public void execute(TestPlan testPlan, TestExecutionListener... listeners) { + delegate.execute(testPlan, listeners); + } + + @Override + public ListenerRegistry getTestExecutionListenerRegistry() { + return delegate.getTestExecutionListenerRegistry(); + } + + @Override + public ListenerRegistry getLauncherDiscoveryListenerRegistry() { + return delegate.getLauncherDiscoveryListenerRegistry(); + } +} diff --git a/junit-platform-launcher/src/main/java/org/junit/platform/launcher/core/InterceptingInternalLauncher.java b/junit-platform-launcher/src/main/java/org/junit/platform/launcher/core/InterceptingInternalLauncher.java new file mode 100644 index 000000000000..4524a88fb5de --- /dev/null +++ b/junit-platform-launcher/src/main/java/org/junit/platform/launcher/core/InterceptingInternalLauncher.java @@ -0,0 +1,86 @@ +/* + * Copyright 2015-2023 the original author or authors. + * + * All rights reserved. This program and the accompanying materials are + * made available under the terms of the Eclipse Public License v2.0 which + * accompanies this distribution and is available at + * + * https://www.eclipse.org/legal/epl-v20.html + */ + +package org.junit.platform.launcher.core; + +import java.util.List; +import java.util.Optional; + +import org.junit.platform.launcher.LauncherDiscoveryRequest; +import org.junit.platform.launcher.LauncherInterceptor; +import org.junit.platform.launcher.TestExecutionListener; +import org.junit.platform.launcher.TestPlan; + +/** + * @since 1.10 + */ +class InterceptingInternalLauncher extends DelegatingCloseableInternalLauncher { + + static CloseableInternalLauncher decorate(InternalLauncher launcher, List interceptors) { + return composite(interceptors) // + .map(combinedInterceptor -> (CloseableInternalLauncher) new InterceptingInternalLauncher(launcher, + combinedInterceptor)) // + .orElse(new DelegatingCloseableInternalLauncher<>(launcher, () -> { + // do nothing + })); + } + + private static Optional composite(List interceptors) { + if (interceptors.isEmpty()) { + return Optional.empty(); + } + return Optional.of(interceptors.stream() // + .skip(1) // + .reduce(interceptors.get(0), (a, b) -> new LauncherInterceptor() { + @Override + public void close() { + try { + a.close(); + } + finally { + b.close(); + } + } + + @Override + public T intercept(Invocation invocation) { + return a.intercept(() -> b.intercept(invocation)); + } + })); + } + + private final LauncherInterceptor interceptor; + + private InterceptingInternalLauncher(InternalLauncher delegate, LauncherInterceptor interceptor) { + super(delegate, interceptor::close); + this.interceptor = interceptor; + } + + @Override + public TestPlan discover(LauncherDiscoveryRequest launcherDiscoveryRequest) { + return interceptor.intercept(() -> super.discover(launcherDiscoveryRequest)); + } + + @Override + public void execute(LauncherDiscoveryRequest launcherDiscoveryRequest, TestExecutionListener... listeners) { + interceptor.intercept(() -> { + super.execute(launcherDiscoveryRequest, listeners); + return null; + }); + } + + @Override + public void execute(TestPlan testPlan, TestExecutionListener... listeners) { + interceptor.intercept(() -> { + super.execute(testPlan, listeners); + return null; + }); + } +} diff --git a/junit-platform-launcher/src/main/java/org/junit/platform/launcher/core/LauncherFactory.java b/junit-platform-launcher/src/main/java/org/junit/platform/launcher/core/LauncherFactory.java index 3ac0b4c8330d..140cb4c58632 100644 --- a/junit-platform-launcher/src/main/java/org/junit/platform/launcher/core/LauncherFactory.java +++ b/junit-platform-launcher/src/main/java/org/junit/platform/launcher/core/LauncherFactory.java @@ -10,9 +10,11 @@ package org.junit.platform.launcher.core; +import static java.util.Collections.emptyList; import static org.apiguardian.api.API.Status.EXPERIMENTAL; import static org.apiguardian.api.API.Status.STABLE; import static org.junit.platform.launcher.LauncherConstants.DEACTIVATE_LISTENERS_PATTERN_PROPERTY_NAME; +import static org.junit.platform.launcher.LauncherConstants.ENABLE_LAUNCHER_INTERCEPTORS; import java.util.ArrayList; import java.util.LinkedHashSet; @@ -29,6 +31,7 @@ import org.junit.platform.engine.TestEngine; import org.junit.platform.launcher.Launcher; import org.junit.platform.launcher.LauncherDiscoveryListener; +import org.junit.platform.launcher.LauncherInterceptor; import org.junit.platform.launcher.LauncherSession; import org.junit.platform.launcher.LauncherSessionListener; import org.junit.platform.launcher.PostDiscoveryFilter; @@ -95,7 +98,9 @@ public static LauncherSession openSession() throws PreconditionViolationExceptio */ @API(status = EXPERIMENTAL, since = "1.8") public static LauncherSession openSession(LauncherConfig config) throws PreconditionViolationException { - return new DefaultLauncherSession(createDefaultLauncher(config), createLauncherSessionListener(config)); + LauncherConfigurationParameters configurationParameters = LauncherConfigurationParameters.builder().build(); + return new DefaultLauncherSession(createDefaultLauncher(config, configurationParameters), + createLauncherSessionListener(config), collectLauncherInterceptors(configurationParameters)); } /** @@ -122,10 +127,13 @@ public static Launcher create() throws PreconditionViolationException { */ @API(status = EXPERIMENTAL, since = "1.3") public static Launcher create(LauncherConfig config) throws PreconditionViolationException { - return new SessionPerRequestLauncher(createDefaultLauncher(config), createLauncherSessionListener(config)); + LauncherConfigurationParameters configurationParameters = LauncherConfigurationParameters.builder().build(); + return new SessionPerRequestLauncher(createDefaultLauncher(config, configurationParameters), + createLauncherSessionListener(config), () -> collectLauncherInterceptors(configurationParameters)); } - private static DefaultLauncher createDefaultLauncher(LauncherConfig config) { + private static DefaultLauncher createDefaultLauncher(LauncherConfig config, + LauncherConfigurationParameters configurationParameters) { Preconditions.notNull(config, "LauncherConfig must not be null"); Set engines = collectTestEngines(config); @@ -134,11 +142,21 @@ private static DefaultLauncher createDefaultLauncher(LauncherConfig config) { DefaultLauncher launcher = new DefaultLauncher(engines, filters); registerLauncherDiscoveryListeners(config, launcher); - registerTestExecutionListeners(config, launcher); + registerTestExecutionListeners(config, launcher, configurationParameters); return launcher; } + private static List collectLauncherInterceptors( + LauncherConfigurationParameters configurationParameters) { + if (configurationParameters.getBoolean(ENABLE_LAUNCHER_INTERCEPTORS).orElse(false)) { + List interceptors = new ArrayList<>(); + SERVICE_LOADER_REGISTRY.load(LauncherInterceptor.class).forEach(interceptors::add); + return interceptors; + } + return emptyList(); + } + private static Set collectTestEngines(LauncherConfig config) { Set engines = new LinkedHashSet<>(); if (config.isTestEngineAutoRegistrationEnabled()) { @@ -174,16 +192,18 @@ private static void registerLauncherDiscoveryListeners(LauncherConfig config, La config.getAdditionalLauncherDiscoveryListeners().forEach(launcher::registerLauncherDiscoveryListeners); } - private static void registerTestExecutionListeners(LauncherConfig config, Launcher launcher) { + private static void registerTestExecutionListeners(LauncherConfig config, Launcher launcher, + LauncherConfigurationParameters configurationParameters) { if (config.isTestExecutionListenerAutoRegistrationEnabled()) { - loadAndFilterTestExecutionListeners().forEach(launcher::registerTestExecutionListeners); + loadAndFilterTestExecutionListeners(configurationParameters).forEach( + launcher::registerTestExecutionListeners); } config.getAdditionalTestExecutionListeners().forEach(launcher::registerTestExecutionListeners); } - private static Stream loadAndFilterTestExecutionListeners() { + private static Stream loadAndFilterTestExecutionListeners( + ConfigurationParameters configurationParameters) { Iterable listeners = SERVICE_LOADER_REGISTRY.load(TestExecutionListener.class); - ConfigurationParameters configurationParameters = LauncherConfigurationParameters.builder().build(); String deactivatedListenersPattern = configurationParameters.get( DEACTIVATE_LISTENERS_PATTERN_PROPERTY_NAME).orElse(null); // @formatter:off diff --git a/junit-platform-launcher/src/main/java/org/junit/platform/launcher/core/SessionPerRequestLauncher.java b/junit-platform-launcher/src/main/java/org/junit/platform/launcher/core/SessionPerRequestLauncher.java index 9c0b7dd47e60..7de4df66d5e7 100644 --- a/junit-platform-launcher/src/main/java/org/junit/platform/launcher/core/SessionPerRequestLauncher.java +++ b/junit-platform-launcher/src/main/java/org/junit/platform/launcher/core/SessionPerRequestLauncher.java @@ -10,8 +10,11 @@ package org.junit.platform.launcher.core; -import org.junit.platform.launcher.LauncherDiscoveryListener; +import java.util.List; +import java.util.function.Supplier; + import org.junit.platform.launcher.LauncherDiscoveryRequest; +import org.junit.platform.launcher.LauncherInterceptor; import org.junit.platform.launcher.LauncherSession; import org.junit.platform.launcher.LauncherSessionListener; import org.junit.platform.launcher.TestExecutionListener; @@ -20,24 +23,16 @@ /** * @since 1.8 */ -class SessionPerRequestLauncher implements InternalLauncher { +class SessionPerRequestLauncher extends DelegatingInternalLauncher { - private final InternalLauncher delegate; private final LauncherSessionListener sessionListener; + private final Supplier> interceptorFactory; - SessionPerRequestLauncher(InternalLauncher delegate, LauncherSessionListener sessionListener) { - this.delegate = delegate; + SessionPerRequestLauncher(InternalLauncher delegate, LauncherSessionListener sessionListener, + Supplier> interceptorFactory) { + super(delegate); this.sessionListener = sessionListener; - } - - @Override - public void registerLauncherDiscoveryListeners(LauncherDiscoveryListener... listeners) { - delegate.registerLauncherDiscoveryListeners(listeners); - } - - @Override - public void registerTestExecutionListeners(TestExecutionListener... listeners) { - delegate.registerTestExecutionListeners(listeners); + this.interceptorFactory = interceptorFactory; } @Override @@ -61,17 +56,7 @@ public void execute(TestPlan testPlan, TestExecutionListener... listeners) { } } - @Override - public ListenerRegistry getTestExecutionListenerRegistry() { - return delegate.getTestExecutionListenerRegistry(); - } - - @Override - public ListenerRegistry getLauncherDiscoveryListenerRegistry() { - return delegate.getLauncherDiscoveryListenerRegistry(); - } - private LauncherSession createSession() { - return new DefaultLauncherSession(delegate, sessionListener); + return new DefaultLauncherSession(delegate, sessionListener, interceptorFactory.get()); } } diff --git a/platform-tests/src/test/java/org/junit/platform/launcher/TestLauncherInterceptor1.java b/platform-tests/src/test/java/org/junit/platform/launcher/TestLauncherInterceptor1.java new file mode 100644 index 000000000000..7bd8f95ff690 --- /dev/null +++ b/platform-tests/src/test/java/org/junit/platform/launcher/TestLauncherInterceptor1.java @@ -0,0 +1,23 @@ +/* + * Copyright 2015-2023 the original author or authors. + * + * All rights reserved. This program and the accompanying materials are + * made available under the terms of the Eclipse Public License v2.0 which + * accompanies this distribution and is available at + * + * https://www.eclipse.org/legal/epl-v20.html + */ + +package org.junit.platform.launcher; + +public class TestLauncherInterceptor1 implements LauncherInterceptor { + + @Override + public T intercept(Invocation invocation) { + return invocation.proceed(); + } + + @Override + public void close() { + } +} diff --git a/platform-tests/src/test/java/org/junit/platform/launcher/TestLauncherInterceptor2.java b/platform-tests/src/test/java/org/junit/platform/launcher/TestLauncherInterceptor2.java new file mode 100644 index 000000000000..bdc198e3ee06 --- /dev/null +++ b/platform-tests/src/test/java/org/junit/platform/launcher/TestLauncherInterceptor2.java @@ -0,0 +1,23 @@ +/* + * Copyright 2015-2023 the original author or authors. + * + * All rights reserved. This program and the accompanying materials are + * made available under the terms of the Eclipse Public License v2.0 which + * accompanies this distribution and is available at + * + * https://www.eclipse.org/legal/epl-v20.html + */ + +package org.junit.platform.launcher; + +public class TestLauncherInterceptor2 implements LauncherInterceptor { + + @Override + public T intercept(Invocation invocation) { + return invocation.proceed(); + } + + @Override + public void close() { + } +} diff --git a/platform-tests/src/test/java/org/junit/platform/launcher/core/LauncherFactoryTests.java b/platform-tests/src/test/java/org/junit/platform/launcher/core/LauncherFactoryTests.java index 5b6368f79eaf..36baca65a79d 100644 --- a/platform-tests/src/test/java/org/junit/platform/launcher/core/LauncherFactoryTests.java +++ b/platform-tests/src/test/java/org/junit/platform/launcher/core/LauncherFactoryTests.java @@ -14,22 +14,32 @@ import static org.assertj.core.api.Assertions.assertThat; import static org.junit.jupiter.api.Assertions.assertThrows; import static org.junit.platform.engine.discovery.DiscoverySelectors.selectClass; +import static org.junit.platform.launcher.LauncherConstants.ENABLE_LAUNCHER_INTERCEPTORS; import static org.junit.platform.launcher.core.LauncherDiscoveryRequestBuilder.request; import java.net.URL; import java.net.URLClassLoader; +import java.util.concurrent.atomic.AtomicReference; import org.junit.jupiter.api.Tag; import org.junit.jupiter.api.Test; import org.junit.jupiter.engine.JupiterTestEngine; import org.junit.platform.commons.PreconditionViolationException; +import org.junit.platform.engine.EngineDiscoveryRequest; +import org.junit.platform.engine.ExecutionRequest; +import org.junit.platform.engine.TestDescriptor; +import org.junit.platform.engine.TestExecutionResult; import org.junit.platform.engine.UniqueId; +import org.junit.platform.fakes.TestEngineSpy; import org.junit.platform.launcher.LauncherDiscoveryListener; import org.junit.platform.launcher.LauncherDiscoveryRequest; import org.junit.platform.launcher.LauncherSessionListener; import org.junit.platform.launcher.TagFilter; +import org.junit.platform.launcher.TestExecutionListener; import org.junit.platform.launcher.TestIdentifier; import org.junit.platform.launcher.TestLauncherDiscoveryListener; +import org.junit.platform.launcher.TestLauncherInterceptor1; +import org.junit.platform.launcher.TestLauncherInterceptor2; import org.junit.platform.launcher.TestLauncherSessionListener; import org.junit.platform.launcher.listeners.AnotherUnusedTestExecutionListener; import org.junit.platform.launcher.listeners.NoopTestExecutionListener; @@ -198,6 +208,80 @@ void discoversLauncherSessionListenerViaServiceApiByDefault() { }); } + @Test + void appliesLauncherInterceptorsToTestDiscovery() { + withTestServices(() -> withSystemProperty(ENABLE_LAUNCHER_INTERCEPTORS, "true", () -> { + var engine = new TestEngineSpy() { + @Override + public TestDescriptor discover(EngineDiscoveryRequest discoveryRequest, UniqueId uniqueId) { + throw new RuntimeException("from discovery"); + } + }; + var config = LauncherConfig.builder() // + .enableTestEngineAutoRegistration(false) // + .addTestEngines(engine) // + .build(); + var launcher = LauncherFactory.create(config); + var request = request().build(); + + var exception = assertThrows(RuntimeException.class, () -> launcher.discover(request)); + + assertThat(exception) // + .hasRootCauseMessage("from discovery") // + .hasStackTraceContaining(TestLauncherInterceptor1.class.getName() + ".intercept(") // + .hasStackTraceContaining(TestLauncherInterceptor2.class.getName() + ".intercept("); + })); + } + + @Test + void appliesLauncherInterceptorsToTestExecution() { + withTestServices(() -> withSystemProperty(ENABLE_LAUNCHER_INTERCEPTORS, "true", () -> { + var engine = new TestEngineSpy() { + @Override + public void execute(ExecutionRequest request) { + throw new RuntimeException("from execution"); + } + }; + var config = LauncherConfig.builder() // + .enableTestEngineAutoRegistration(false) // + .addTestEngines(engine) // + .build(); + var launcher = LauncherFactory.create(config); + var request = request().build(); + + AtomicReference result = new AtomicReference<>(); + launcher.execute(request, new TestExecutionListener() { + @Override + public void executionFinished(TestIdentifier testIdentifier, TestExecutionResult testExecutionResult) { + if (testIdentifier.getParentId().isEmpty()) { + result.set(testExecutionResult); + } + } + }); + + assertThat(result.get().getThrowable().orElseThrow()) // + .hasRootCauseMessage("from execution") // + .hasStackTraceContaining(TestLauncherInterceptor1.class.getName() + ".intercept(") // + .hasStackTraceContaining(TestLauncherInterceptor2.class.getName() + ".intercept("); + })); + } + + private static void withSystemProperty(String key, String value, Runnable runnable) { + var oldValue = System.getProperty(key); + System.setProperty(key, value); + try { + runnable.run(); + } + finally { + if (oldValue == null) { + System.clearProperty(key); + } + else { + System.setProperty(key, oldValue); + } + } + } + private static void withTestServices(Runnable runnable) { var current = Thread.currentThread().getContextClassLoader(); try { diff --git a/platform-tests/src/test/resources/testservices/META-INF/services/org.junit.platform.launcher.LauncherInterceptor b/platform-tests/src/test/resources/testservices/META-INF/services/org.junit.platform.launcher.LauncherInterceptor new file mode 100644 index 000000000000..2aa385ca1c2f --- /dev/null +++ b/platform-tests/src/test/resources/testservices/META-INF/services/org.junit.platform.launcher.LauncherInterceptor @@ -0,0 +1,2 @@ +org.junit.platform.launcher.TestLauncherInterceptor1 +org.junit.platform.launcher.TestLauncherInterceptor2 From a13b99a6484b909e1a91c1aed281f2399af2ca68 Mon Sep 17 00:00:00 2001 From: Marc Philipp Date: Tue, 15 Nov 2022 21:14:23 +0100 Subject: [PATCH 0003/1473] Create interceptors before launcher So they can influence the class loader used to load test engines etc. --- .../junit/platform/fakes/TestEngineSpy.java | 16 ++- ...alLauncher.java => CloseableLauncher.java} | 4 +- .../launcher/core/DefaultLauncher.java | 23 +--- .../launcher/core/DefaultLauncherSession.java | 45 ++----- .../DelegatingCloseableInternalLauncher.java | 30 ----- .../core/DelegatingCloseableLauncher.java | 41 +++++++ ...lLauncher.java => DelegatingLauncher.java} | 14 +-- ...java => InterceptingClosableLauncher.java} | 27 +++-- .../launcher/core/LauncherFactory.java | 10 +- ...her.java => LauncherListenerRegistry.java} | 12 +- .../core/SessionPerRequestLauncher.java | 28 ++++- .../launcher/InterceptedTestEngine.java | 22 ++++ .../TestLauncherDiscoveryListener.java | 16 +-- .../launcher/TestLauncherInterceptor1.java | 24 ++++ .../launcher/core/DefaultLauncherTests.java | 21 ++-- .../launcher/core/LauncherFactoryTests.java | 112 +++++++++++++----- .../AnotherUnusedTestExecutionListener.java | 8 +- .../listeners/NoopTestExecutionListener.java | 8 +- .../UnusedTestExecutionListener.java | 8 +- .../org.junit.platform.engine.TestEngine | 1 + .../testservices/junit-platform.properties | 1 - .../projects/standalone/expected-err.txt | 4 +- 22 files changed, 293 insertions(+), 182 deletions(-) rename junit-platform-launcher/src/main/java/org/junit/platform/launcher/core/{CloseableInternalLauncher.java => CloseableLauncher.java} (79%) delete mode 100644 junit-platform-launcher/src/main/java/org/junit/platform/launcher/core/DelegatingCloseableInternalLauncher.java create mode 100644 junit-platform-launcher/src/main/java/org/junit/platform/launcher/core/DelegatingCloseableLauncher.java rename junit-platform-launcher/src/main/java/org/junit/platform/launcher/core/{DelegatingInternalLauncher.java => DelegatingLauncher.java} (76%) rename junit-platform-launcher/src/main/java/org/junit/platform/launcher/core/{InterceptingInternalLauncher.java => InterceptingClosableLauncher.java} (68%) rename junit-platform-launcher/src/main/java/org/junit/platform/launcher/core/{InternalLauncher.java => LauncherListenerRegistry.java} (63%) create mode 100644 platform-tests/src/test/java/org/junit/platform/launcher/InterceptedTestEngine.java create mode 100644 platform-tests/src/test/resources/intercepted-testservices/META-INF/services/org.junit.platform.engine.TestEngine delete mode 100644 platform-tests/src/test/resources/testservices/junit-platform.properties diff --git a/junit-platform-engine/src/testFixtures/java/org/junit/platform/fakes/TestEngineSpy.java b/junit-platform-engine/src/testFixtures/java/org/junit/platform/fakes/TestEngineSpy.java index 2cb30350c351..cdf6c136345a 100644 --- a/junit-platform-engine/src/testFixtures/java/org/junit/platform/fakes/TestEngineSpy.java +++ b/junit-platform-engine/src/testFixtures/java/org/junit/platform/fakes/TestEngineSpy.java @@ -21,19 +21,27 @@ */ public class TestEngineSpy implements TestEngine { - public static final String ID = TestEngineSpy.class.getSimpleName(); + private final String id; public ExecutionRequest requestForExecution; + public TestEngineSpy() { + this(TestEngineSpy.class.getSimpleName()); + } + + public TestEngineSpy(String id) { + this.id = id; + } + @Override public String getId() { - return ID; + return id; } @Override public TestDescriptor discover(EngineDiscoveryRequest discoveryRequest, UniqueId uniqueId) { - var engineUniqueId = UniqueId.forEngine(ID); - var engineDescriptor = new TestDescriptorStub(engineUniqueId, ID); + var engineUniqueId = UniqueId.forEngine(id); + var engineDescriptor = new TestDescriptorStub(engineUniqueId, id); var testDescriptor = new TestDescriptorStub(engineUniqueId.append("test", "test"), "test"); engineDescriptor.addChild(testDescriptor); return engineDescriptor; diff --git a/junit-platform-launcher/src/main/java/org/junit/platform/launcher/core/CloseableInternalLauncher.java b/junit-platform-launcher/src/main/java/org/junit/platform/launcher/core/CloseableLauncher.java similarity index 79% rename from junit-platform-launcher/src/main/java/org/junit/platform/launcher/core/CloseableInternalLauncher.java rename to junit-platform-launcher/src/main/java/org/junit/platform/launcher/core/CloseableLauncher.java index 110057708947..1cc023471b22 100644 --- a/junit-platform-launcher/src/main/java/org/junit/platform/launcher/core/CloseableInternalLauncher.java +++ b/junit-platform-launcher/src/main/java/org/junit/platform/launcher/core/CloseableLauncher.java @@ -10,10 +10,12 @@ package org.junit.platform.launcher.core; +import org.junit.platform.launcher.Launcher; + /** * @since 1.10 */ -interface CloseableInternalLauncher extends InternalLauncher, AutoCloseable { +interface CloseableLauncher extends Launcher, AutoCloseable { @Override void close(); } diff --git a/junit-platform-launcher/src/main/java/org/junit/platform/launcher/core/DefaultLauncher.java b/junit-platform-launcher/src/main/java/org/junit/platform/launcher/core/DefaultLauncher.java index 3b0dc3e03f91..9f21595d0d64 100644 --- a/junit-platform-launcher/src/main/java/org/junit/platform/launcher/core/DefaultLauncher.java +++ b/junit-platform-launcher/src/main/java/org/junit/platform/launcher/core/DefaultLauncher.java @@ -35,12 +35,11 @@ * @see Launcher * @see LauncherFactory */ -class DefaultLauncher implements InternalLauncher { +class DefaultLauncher implements Launcher { - private final ListenerRegistry launcherDiscoveryListenerRegistry = ListenerRegistry.forLauncherDiscoveryListeners(); - private final ListenerRegistry testExecutionListenerRegistry = ListenerRegistry.forTestExecutionListeners(); + private final LauncherListenerRegistry listenerRegistry = new LauncherListenerRegistry(); private final EngineExecutionOrchestrator executionOrchestrator = new EngineExecutionOrchestrator( - testExecutionListenerRegistry); + listenerRegistry.testExecutionListeners);; private final EngineDiscoveryOrchestrator discoveryOrchestrator; /** @@ -59,17 +58,17 @@ class DefaultLauncher implements InternalLauncher { Preconditions.containsNoNullElements(postDiscoveryFilters, "PostDiscoveryFilter array must not contain null elements"); this.discoveryOrchestrator = new EngineDiscoveryOrchestrator(testEngines, - unmodifiableCollection(postDiscoveryFilters), launcherDiscoveryListenerRegistry); + unmodifiableCollection(postDiscoveryFilters), listenerRegistry.launcherDiscoveryListeners); } @Override public void registerLauncherDiscoveryListeners(LauncherDiscoveryListener... listeners) { - this.launcherDiscoveryListenerRegistry.addAll(listeners); + this.listenerRegistry.launcherDiscoveryListeners.addAll(listeners); } @Override public void registerTestExecutionListeners(TestExecutionListener... listeners) { - this.testExecutionListenerRegistry.addAll(listeners); + this.listenerRegistry.testExecutionListeners.addAll(listeners); } @Override @@ -95,16 +94,6 @@ public void execute(TestPlan testPlan, TestExecutionListener... listeners) { execute((InternalTestPlan) testPlan, listeners); } - @Override - public ListenerRegistry getTestExecutionListenerRegistry() { - return testExecutionListenerRegistry; - } - - @Override - public ListenerRegistry getLauncherDiscoveryListenerRegistry() { - return launcherDiscoveryListenerRegistry; - } - private LauncherDiscoveryResult discover(LauncherDiscoveryRequest discoveryRequest, EngineDiscoveryOrchestrator.Phase phase) { return discoveryOrchestrator.discover(discoveryRequest, phase); diff --git a/junit-platform-launcher/src/main/java/org/junit/platform/launcher/core/DefaultLauncherSession.java b/junit-platform-launcher/src/main/java/org/junit/platform/launcher/core/DefaultLauncherSession.java index a8fa1150fa5f..0a4436dd5ed1 100644 --- a/junit-platform-launcher/src/main/java/org/junit/platform/launcher/core/DefaultLauncherSession.java +++ b/junit-platform-launcher/src/main/java/org/junit/platform/launcher/core/DefaultLauncherSession.java @@ -11,6 +11,7 @@ package org.junit.platform.launcher.core; import java.util.List; +import java.util.function.Supplier; import org.junit.platform.commons.PreconditionViolationException; import org.junit.platform.launcher.Launcher; @@ -27,12 +28,16 @@ */ class DefaultLauncherSession implements LauncherSession { - private final DelegatingLauncher launcher; + private final DelegatingCloseableLauncher launcher; private final LauncherSessionListener listener; - DefaultLauncherSession(InternalLauncher launcher, LauncherSessionListener listener, - List interceptors) { - this.launcher = new DelegatingLauncher(InterceptingInternalLauncher.decorate(launcher, interceptors)); + DefaultLauncherSession(Supplier launcherSupplier, List interceptors, + LauncherSessionListener listener) { + CloseableLauncher closeableLauncher = InterceptingClosableLauncher.decorate(launcherSupplier, interceptors); + this.launcher = new DelegatingCloseableLauncher<>(closeableLauncher, delegate -> { + delegate.close(); + return ClosedLauncher.INSTANCE; + }); this.listener = listener; listener.launcherSessionOpened(this); } @@ -48,31 +53,13 @@ LauncherSessionListener getListener() { @Override public void close() { - if (launcher.isClosed()) { + if (!launcher.isClosed()) { launcher.close(); listener.launcherSessionClosed(this); } } - private static class DelegatingLauncher extends DelegatingInternalLauncher - implements CloseableInternalLauncher { - - DelegatingLauncher(CloseableInternalLauncher delegate) { - super(delegate); - } - - boolean isClosed() { - return delegate != ClosedLauncher.INSTANCE; - } - - @Override - public void close() { - delegate.close(); - delegate = ClosedLauncher.INSTANCE; - } - } - - private static class ClosedLauncher implements CloseableInternalLauncher { + private static class ClosedLauncher implements CloseableLauncher { static final ClosedLauncher INSTANCE = new ClosedLauncher(); @@ -104,16 +91,6 @@ public void execute(TestPlan testPlan, TestExecutionListener... listeners) { throw new PreconditionViolationException("Launcher session has already been closed"); } - @Override - public ListenerRegistry getTestExecutionListenerRegistry() { - throw new PreconditionViolationException("Launcher session has already been closed"); - } - - @Override - public ListenerRegistry getLauncherDiscoveryListenerRegistry() { - throw new PreconditionViolationException("Launcher session has already been closed"); - } - @Override public void close() { // do nothing diff --git a/junit-platform-launcher/src/main/java/org/junit/platform/launcher/core/DelegatingCloseableInternalLauncher.java b/junit-platform-launcher/src/main/java/org/junit/platform/launcher/core/DelegatingCloseableInternalLauncher.java deleted file mode 100644 index 1282cf7ac7d9..000000000000 --- a/junit-platform-launcher/src/main/java/org/junit/platform/launcher/core/DelegatingCloseableInternalLauncher.java +++ /dev/null @@ -1,30 +0,0 @@ -/* - * Copyright 2015-2023 the original author or authors. - * - * All rights reserved. This program and the accompanying materials are - * made available under the terms of the Eclipse Public License v2.0 which - * accompanies this distribution and is available at - * - * https://www.eclipse.org/legal/epl-v20.html - */ - -package org.junit.platform.launcher.core; - -/** - * @since 1.10 - */ -class DelegatingCloseableInternalLauncher extends DelegatingInternalLauncher - implements CloseableInternalLauncher { - - private final Runnable onClose; - - public DelegatingCloseableInternalLauncher(T delegate, Runnable onClose) { - super(delegate); - this.onClose = onClose; - } - - @Override - public final void close() { - onClose.run(); - } -} diff --git a/junit-platform-launcher/src/main/java/org/junit/platform/launcher/core/DelegatingCloseableLauncher.java b/junit-platform-launcher/src/main/java/org/junit/platform/launcher/core/DelegatingCloseableLauncher.java new file mode 100644 index 000000000000..a6ea513acf03 --- /dev/null +++ b/junit-platform-launcher/src/main/java/org/junit/platform/launcher/core/DelegatingCloseableLauncher.java @@ -0,0 +1,41 @@ +/* + * Copyright 2015-2023 the original author or authors. + * + * All rights reserved. This program and the accompanying materials are + * made available under the terms of the Eclipse Public License v2.0 which + * accompanies this distribution and is available at + * + * https://www.eclipse.org/legal/epl-v20.html + */ + +package org.junit.platform.launcher.core; + +import java.util.function.Function; + +import org.junit.platform.launcher.Launcher; + +/** + * @since 1.10 + */ +class DelegatingCloseableLauncher extends DelegatingLauncher implements CloseableLauncher { + + private final Function onClose; + private boolean closed; + + public DelegatingCloseableLauncher(T delegate, Function onClose) { + super(delegate); + this.onClose = onClose; + } + + @Override + public final void close() { + if (!closed) { + this.closed = true; + delegate = this.onClose.apply(this.delegate); + } + } + + public boolean isClosed() { + return closed; + } +} diff --git a/junit-platform-launcher/src/main/java/org/junit/platform/launcher/core/DelegatingInternalLauncher.java b/junit-platform-launcher/src/main/java/org/junit/platform/launcher/core/DelegatingLauncher.java similarity index 76% rename from junit-platform-launcher/src/main/java/org/junit/platform/launcher/core/DelegatingInternalLauncher.java rename to junit-platform-launcher/src/main/java/org/junit/platform/launcher/core/DelegatingLauncher.java index c4078ff94ae8..3e226af1255d 100644 --- a/junit-platform-launcher/src/main/java/org/junit/platform/launcher/core/DelegatingInternalLauncher.java +++ b/junit-platform-launcher/src/main/java/org/junit/platform/launcher/core/DelegatingLauncher.java @@ -10,6 +10,7 @@ package org.junit.platform.launcher.core; +import org.junit.platform.launcher.Launcher; import org.junit.platform.launcher.LauncherDiscoveryListener; import org.junit.platform.launcher.LauncherDiscoveryRequest; import org.junit.platform.launcher.TestExecutionListener; @@ -18,11 +19,11 @@ /** * @since 1.10 */ -class DelegatingInternalLauncher implements InternalLauncher { +class DelegatingLauncher implements Launcher { protected T delegate; - DelegatingInternalLauncher(T delegate) { + DelegatingLauncher(T delegate) { this.delegate = delegate; } @@ -51,13 +52,4 @@ public void execute(TestPlan testPlan, TestExecutionListener... listeners) { delegate.execute(testPlan, listeners); } - @Override - public ListenerRegistry getTestExecutionListenerRegistry() { - return delegate.getTestExecutionListenerRegistry(); - } - - @Override - public ListenerRegistry getLauncherDiscoveryListenerRegistry() { - return delegate.getLauncherDiscoveryListenerRegistry(); - } } diff --git a/junit-platform-launcher/src/main/java/org/junit/platform/launcher/core/InterceptingInternalLauncher.java b/junit-platform-launcher/src/main/java/org/junit/platform/launcher/core/InterceptingClosableLauncher.java similarity index 68% rename from junit-platform-launcher/src/main/java/org/junit/platform/launcher/core/InterceptingInternalLauncher.java rename to junit-platform-launcher/src/main/java/org/junit/platform/launcher/core/InterceptingClosableLauncher.java index 4524a88fb5de..20dbf2f6ed06 100644 --- a/junit-platform-launcher/src/main/java/org/junit/platform/launcher/core/InterceptingInternalLauncher.java +++ b/junit-platform-launcher/src/main/java/org/junit/platform/launcher/core/InterceptingClosableLauncher.java @@ -10,9 +10,13 @@ package org.junit.platform.launcher.core; +import static java.util.function.Function.identity; + import java.util.List; import java.util.Optional; +import java.util.function.Supplier; +import org.junit.platform.launcher.Launcher; import org.junit.platform.launcher.LauncherDiscoveryRequest; import org.junit.platform.launcher.LauncherInterceptor; import org.junit.platform.launcher.TestExecutionListener; @@ -21,15 +25,15 @@ /** * @since 1.10 */ -class InterceptingInternalLauncher extends DelegatingCloseableInternalLauncher { +class InterceptingClosableLauncher extends DelegatingCloseableLauncher { - static CloseableInternalLauncher decorate(InternalLauncher launcher, List interceptors) { - return composite(interceptors) // - .map(combinedInterceptor -> (CloseableInternalLauncher) new InterceptingInternalLauncher(launcher, - combinedInterceptor)) // - .orElse(new DelegatingCloseableInternalLauncher<>(launcher, () -> { - // do nothing - })); + static CloseableLauncher decorate(Supplier launcherSupplier, List interceptors) { + Optional combinedInterceptor = composite(interceptors); + Launcher launcher = combinedInterceptor.map(it -> it.intercept(launcherSupplier::get)).orElseGet( + launcherSupplier); + return combinedInterceptor // + .map(it -> (CloseableLauncher) new InterceptingClosableLauncher(launcher, it)) // + .orElse(new DelegatingCloseableLauncher<>(launcher, identity())); } private static Optional composite(List interceptors) { @@ -58,8 +62,11 @@ public T intercept(Invocation invocation) { private final LauncherInterceptor interceptor; - private InterceptingInternalLauncher(InternalLauncher delegate, LauncherInterceptor interceptor) { - super(delegate, interceptor::close); + private InterceptingClosableLauncher(Launcher delegate, LauncherInterceptor interceptor) { + super(delegate, it -> { + interceptor.close(); + return it; + }); this.interceptor = interceptor; } diff --git a/junit-platform-launcher/src/main/java/org/junit/platform/launcher/core/LauncherFactory.java b/junit-platform-launcher/src/main/java/org/junit/platform/launcher/core/LauncherFactory.java index 140cb4c58632..77edab9bbc67 100644 --- a/junit-platform-launcher/src/main/java/org/junit/platform/launcher/core/LauncherFactory.java +++ b/junit-platform-launcher/src/main/java/org/junit/platform/launcher/core/LauncherFactory.java @@ -98,9 +98,10 @@ public static LauncherSession openSession() throws PreconditionViolationExceptio */ @API(status = EXPERIMENTAL, since = "1.8") public static LauncherSession openSession(LauncherConfig config) throws PreconditionViolationException { + Preconditions.notNull(config, "LauncherConfig must not be null"); LauncherConfigurationParameters configurationParameters = LauncherConfigurationParameters.builder().build(); - return new DefaultLauncherSession(createDefaultLauncher(config, configurationParameters), - createLauncherSessionListener(config), collectLauncherInterceptors(configurationParameters)); + return new DefaultLauncherSession(() -> createDefaultLauncher(config, configurationParameters), + collectLauncherInterceptors(configurationParameters), createLauncherSessionListener(config)); } /** @@ -127,15 +128,14 @@ public static Launcher create() throws PreconditionViolationException { */ @API(status = EXPERIMENTAL, since = "1.3") public static Launcher create(LauncherConfig config) throws PreconditionViolationException { + Preconditions.notNull(config, "LauncherConfig must not be null"); LauncherConfigurationParameters configurationParameters = LauncherConfigurationParameters.builder().build(); - return new SessionPerRequestLauncher(createDefaultLauncher(config, configurationParameters), + return new SessionPerRequestLauncher(() -> createDefaultLauncher(config, configurationParameters), createLauncherSessionListener(config), () -> collectLauncherInterceptors(configurationParameters)); } private static DefaultLauncher createDefaultLauncher(LauncherConfig config, LauncherConfigurationParameters configurationParameters) { - Preconditions.notNull(config, "LauncherConfig must not be null"); - Set engines = collectTestEngines(config); List filters = collectPostDiscoveryFilters(config); diff --git a/junit-platform-launcher/src/main/java/org/junit/platform/launcher/core/InternalLauncher.java b/junit-platform-launcher/src/main/java/org/junit/platform/launcher/core/LauncherListenerRegistry.java similarity index 63% rename from junit-platform-launcher/src/main/java/org/junit/platform/launcher/core/InternalLauncher.java rename to junit-platform-launcher/src/main/java/org/junit/platform/launcher/core/LauncherListenerRegistry.java index 453be6931729..17b21b141f07 100644 --- a/junit-platform-launcher/src/main/java/org/junit/platform/launcher/core/InternalLauncher.java +++ b/junit-platform-launcher/src/main/java/org/junit/platform/launcher/core/LauncherListenerRegistry.java @@ -10,16 +10,10 @@ package org.junit.platform.launcher.core; -import org.junit.platform.launcher.Launcher; import org.junit.platform.launcher.LauncherDiscoveryListener; import org.junit.platform.launcher.TestExecutionListener; -/** - * @since 1.8 - */ -interface InternalLauncher extends Launcher { - - ListenerRegistry getTestExecutionListenerRegistry(); - - ListenerRegistry getLauncherDiscoveryListenerRegistry(); +class LauncherListenerRegistry { + final ListenerRegistry launcherDiscoveryListeners = ListenerRegistry.forLauncherDiscoveryListeners(); + final ListenerRegistry testExecutionListeners = ListenerRegistry.forTestExecutionListeners(); } diff --git a/junit-platform-launcher/src/main/java/org/junit/platform/launcher/core/SessionPerRequestLauncher.java b/junit-platform-launcher/src/main/java/org/junit/platform/launcher/core/SessionPerRequestLauncher.java index 7de4df66d5e7..1955bc625e56 100644 --- a/junit-platform-launcher/src/main/java/org/junit/platform/launcher/core/SessionPerRequestLauncher.java +++ b/junit-platform-launcher/src/main/java/org/junit/platform/launcher/core/SessionPerRequestLauncher.java @@ -13,6 +13,8 @@ import java.util.List; import java.util.function.Supplier; +import org.junit.platform.launcher.Launcher; +import org.junit.platform.launcher.LauncherDiscoveryListener; import org.junit.platform.launcher.LauncherDiscoveryRequest; import org.junit.platform.launcher.LauncherInterceptor; import org.junit.platform.launcher.LauncherSession; @@ -23,18 +25,30 @@ /** * @since 1.8 */ -class SessionPerRequestLauncher extends DelegatingInternalLauncher { +class SessionPerRequestLauncher implements Launcher { + private final LauncherListenerRegistry listenerRegistry = new LauncherListenerRegistry(); + private final Supplier launcherSupplier; private final LauncherSessionListener sessionListener; private final Supplier> interceptorFactory; - SessionPerRequestLauncher(InternalLauncher delegate, LauncherSessionListener sessionListener, + SessionPerRequestLauncher(Supplier launcherSupplier, LauncherSessionListener sessionListener, Supplier> interceptorFactory) { - super(delegate); + this.launcherSupplier = launcherSupplier; this.sessionListener = sessionListener; this.interceptorFactory = interceptorFactory; } + @Override + public void registerLauncherDiscoveryListeners(LauncherDiscoveryListener... listeners) { + listenerRegistry.launcherDiscoveryListeners.addAll(listeners); + } + + @Override + public void registerTestExecutionListeners(TestExecutionListener... listeners) { + listenerRegistry.testExecutionListeners.addAll(listeners); + } + @Override public TestPlan discover(LauncherDiscoveryRequest launcherDiscoveryRequest) { try (LauncherSession session = createSession()) { @@ -57,6 +71,12 @@ public void execute(TestPlan testPlan, TestExecutionListener... listeners) { } private LauncherSession createSession() { - return new DefaultLauncherSession(delegate, sessionListener, interceptorFactory.get()); + LauncherSession session = new DefaultLauncherSession(launcherSupplier, interceptorFactory.get(), + sessionListener); + Launcher launcher = session.getLauncher(); + listenerRegistry.launcherDiscoveryListeners.getListeners().forEach( + launcher::registerLauncherDiscoveryListeners); + listenerRegistry.testExecutionListeners.getListeners().forEach(launcher::registerTestExecutionListeners); + return session; } } diff --git a/platform-tests/src/test/java/org/junit/platform/launcher/InterceptedTestEngine.java b/platform-tests/src/test/java/org/junit/platform/launcher/InterceptedTestEngine.java new file mode 100644 index 000000000000..dc57b1ff7a22 --- /dev/null +++ b/platform-tests/src/test/java/org/junit/platform/launcher/InterceptedTestEngine.java @@ -0,0 +1,22 @@ +/* + * Copyright 2015-2023 the original author or authors. + * + * All rights reserved. This program and the accompanying materials are + * made available under the terms of the Eclipse Public License v2.0 which + * accompanies this distribution and is available at + * + * https://www.eclipse.org/legal/epl-v20.html + */ + +package org.junit.platform.launcher; + +import org.junit.platform.fakes.TestEngineSpy; + +public class InterceptedTestEngine extends TestEngineSpy { + + public static final String ID = "intercepted-engine"; + + public InterceptedTestEngine() { + super(ID); + } +} diff --git a/platform-tests/src/test/java/org/junit/platform/launcher/TestLauncherDiscoveryListener.java b/platform-tests/src/test/java/org/junit/platform/launcher/TestLauncherDiscoveryListener.java index 489f63caaeb3..7a5be0c967a4 100644 --- a/platform-tests/src/test/java/org/junit/platform/launcher/TestLauncherDiscoveryListener.java +++ b/platform-tests/src/test/java/org/junit/platform/launcher/TestLauncherDiscoveryListener.java @@ -11,20 +11,10 @@ package org.junit.platform.launcher; public class TestLauncherDiscoveryListener implements LauncherDiscoveryListener { + public static boolean called; @Override - public boolean equals(Object obj) { - if (this == obj) { - return true; - } - if (obj == null) { - return false; - } - return getClass() == obj.getClass(); - } - - @Override - public int hashCode() { - return 1; + public void launcherDiscoveryStarted(LauncherDiscoveryRequest request) { + called = true; } } diff --git a/platform-tests/src/test/java/org/junit/platform/launcher/TestLauncherInterceptor1.java b/platform-tests/src/test/java/org/junit/platform/launcher/TestLauncherInterceptor1.java index 7bd8f95ff690..585ccf74b6c4 100644 --- a/platform-tests/src/test/java/org/junit/platform/launcher/TestLauncherInterceptor1.java +++ b/platform-tests/src/test/java/org/junit/platform/launcher/TestLauncherInterceptor1.java @@ -10,8 +10,23 @@ package org.junit.platform.launcher; +import java.io.IOException; +import java.io.UncheckedIOException; +import java.net.URL; +import java.net.URLClassLoader; + public class TestLauncherInterceptor1 implements LauncherInterceptor { + private final ClassLoader originalClassLoader; + private final URLClassLoader replacedClassLoader; + + public TestLauncherInterceptor1() { + originalClassLoader = Thread.currentThread().getContextClassLoader(); + var url = getClass().getClassLoader().getResource("intercepted-testservices/"); + replacedClassLoader = new URLClassLoader(new URL[] { url }, originalClassLoader); + Thread.currentThread().setContextClassLoader(replacedClassLoader); + } + @Override public T intercept(Invocation invocation) { return invocation.proceed(); @@ -19,5 +34,14 @@ public T intercept(Invocation invocation) { @Override public void close() { + try { + replacedClassLoader.close(); + } + catch (IOException e) { + throw new UncheckedIOException(e); + } + finally { + Thread.currentThread().setContextClassLoader(originalClassLoader); + } } } diff --git a/platform-tests/src/test/java/org/junit/platform/launcher/core/DefaultLauncherTests.java b/platform-tests/src/test/java/org/junit/platform/launcher/core/DefaultLauncherTests.java index dce04470cd5c..e0e7a3c4bf57 100644 --- a/platform-tests/src/test/java/org/junit/platform/launcher/core/DefaultLauncherTests.java +++ b/platform-tests/src/test/java/org/junit/platform/launcher/core/DefaultLauncherTests.java @@ -76,17 +76,20 @@ class DefaultLauncherTests { @Test void constructLauncherWithoutAnyEngines() { + var launcher = createLauncher(); + Throwable exception = assertThrows(PreconditionViolationException.class, - LauncherFactoryForTestingPurposesOnly::createLauncher); + () -> launcher.discover(request().build())); assertThat(exception).hasMessageContaining("Cannot create Launcher without at least one TestEngine"); } @Test void constructLauncherWithMultipleTestEnginesWithDuplicateIds() { - var exception = assertThrows(JUnitException.class, - () -> createLauncher(new DemoHierarchicalTestEngine("dummy id"), - new DemoHierarchicalTestEngine("dummy id"))); + var launcher = createLauncher(new DemoHierarchicalTestEngine("dummy id"), + new DemoHierarchicalTestEngine("dummy id")); + + var exception = assertThrows(JUnitException.class, () -> launcher.discover(request().build())); assertThat(exception).hasMessageContaining("multiple engines with the same ID"); } @@ -486,11 +489,11 @@ public Type getType() { @Test void reportsDynamicTestDescriptorsCorrectly() { - var engineId = UniqueId.forEngine(TestEngineSpy.ID); + var engineId = UniqueId.forEngine("engine"); var containerAndTestId = engineId.append("c&t", "c&t"); var dynamicTestId = containerAndTestId.append("test", "test"); - var engine = new TestEngineSpy() { + var engine = new TestEngineSpy(engineId.getLastSegment().getValue()) { @Override public TestDescriptor discover(EngineDiscoveryRequest discoveryRequest, UniqueId uniqueId) { @@ -595,7 +598,8 @@ void testPlanThrowsExceptionWhenModified() { @TrackLogRecords void thirdPartyEngineUsingReservedEngineIdPrefixEmitsWarning(LogRecordListener listener) { var id = "junit-using-reserved-prefix"; - createLauncher(new TestEngineStub(id)); + var launcher = createLauncher(new TestEngineStub(id)); + launcher.discover(request().build()); assertThat(listener.stream(EngineIdValidator.class, Level.WARNING).map(LogRecord::getMessage)) // .containsExactly( "Third-party TestEngine implementations are forbidden to use the reserved 'junit-' prefix for their ID: '" @@ -614,7 +618,8 @@ void thirdPartyEngineClaimingToBeVintageResultsInException() { private void assertImposter(String id) { TestEngine impostor = new TestEngineStub(id); - Exception exception = assertThrows(JUnitException.class, () -> createLauncher(impostor)); + var launcher = createLauncher(impostor); + Exception exception = assertThrows(JUnitException.class, () -> launcher.discover(request().build())); assertThat(exception).hasMessage( "Third-party TestEngine '%s' is forbidden to use the reserved '%s' TestEngine ID.", impostor.getClass().getName(), id); diff --git a/platform-tests/src/test/java/org/junit/platform/launcher/core/LauncherFactoryTests.java b/platform-tests/src/test/java/org/junit/platform/launcher/core/LauncherFactoryTests.java index 36baca65a79d..072c6119e369 100644 --- a/platform-tests/src/test/java/org/junit/platform/launcher/core/LauncherFactoryTests.java +++ b/platform-tests/src/test/java/org/junit/platform/launcher/core/LauncherFactoryTests.java @@ -12,11 +12,16 @@ import static java.util.stream.Collectors.toList; import static org.assertj.core.api.Assertions.assertThat; +import static org.junit.jupiter.api.Assertions.assertFalse; import static org.junit.jupiter.api.Assertions.assertThrows; +import static org.junit.jupiter.api.Assertions.assertTrue; import static org.junit.platform.engine.discovery.DiscoverySelectors.selectClass; +import static org.junit.platform.launcher.LauncherConstants.DEACTIVATE_LISTENERS_PATTERN_PROPERTY_NAME; import static org.junit.platform.launcher.LauncherConstants.ENABLE_LAUNCHER_INTERCEPTORS; import static org.junit.platform.launcher.core.LauncherDiscoveryRequestBuilder.request; +import java.io.IOException; +import java.io.UncheckedIOException; import java.net.URL; import java.net.URLClassLoader; import java.util.concurrent.atomic.AtomicReference; @@ -31,7 +36,7 @@ import org.junit.platform.engine.TestExecutionResult; import org.junit.platform.engine.UniqueId; import org.junit.platform.fakes.TestEngineSpy; -import org.junit.platform.launcher.LauncherDiscoveryListener; +import org.junit.platform.launcher.InterceptedTestEngine; import org.junit.platform.launcher.LauncherDiscoveryRequest; import org.junit.platform.launcher.LauncherSessionListener; import org.junit.platform.launcher.TagFilter; @@ -56,24 +61,41 @@ void preconditions() { } @Test - void noopTestExecutionListenerIsLoadedViaServiceApi() { + void testExecutionListenerIsLoadedViaServiceApi() { withTestServices(() -> { - var launcher = (InternalLauncher) LauncherFactory.create(); - var listeners = launcher.getTestExecutionListenerRegistry().getListeners(); - var listener = listeners.stream().filter(NoopTestExecutionListener.class::isInstance).findFirst(); - assertThat(listener).isPresent(); + var config = LauncherConfig.builder() // + .addTestEngines(new TestEngineSpy()) // + .enableTestEngineAutoRegistration(false) // + .build(); + var launcher = LauncherFactory.create(config); + + NoopTestExecutionListener.called = false; + + launcher.execute(request().build()); + + assertTrue(NoopTestExecutionListener.called); }); } @Test - void unusedTestExecutionListenerIsNotLoadedViaServiceApi() { + void testExecutionListenersExcludedViaConfigParametersIsNotLoadedViaServiceApi() { withTestServices(() -> { - var launcher = (InternalLauncher) LauncherFactory.create(); - var listeners = launcher.getTestExecutionListenerRegistry().getListeners(); + var value = "org.junit.*.launcher.listeners.Unused*,org.junit.*.launcher.listeners.AnotherUnused*"; + withSystemProperty(DEACTIVATE_LISTENERS_PATTERN_PROPERTY_NAME, value, () -> { + var config = LauncherConfig.builder() // + .addTestEngines(new TestEngineSpy()) // + .enableTestEngineAutoRegistration(false) // + .build(); + var launcher = LauncherFactory.create(config); + + UnusedTestExecutionListener.called = false; + AnotherUnusedTestExecutionListener.called = false; - assertThat(listeners).filteredOn(AnotherUnusedTestExecutionListener.class::isInstance).isEmpty(); - assertThat(listeners).filteredOn(UnusedTestExecutionListener.class::isInstance).isEmpty(); - assertThat(listeners).filteredOn(NoopTestExecutionListener.class::isInstance).isNotEmpty(); + launcher.execute(request().build()); + + assertFalse(UnusedTestExecutionListener.called); + assertFalse(AnotherUnusedTestExecutionListener.called); + }); }); } @@ -169,45 +191,70 @@ void notApplyIfDisabledPostDiscoveryFiltersViaServiceApi() { @Test void doesNotDiscoverLauncherDiscoverRequestListenerViaServiceApiWhenDisabled() { withTestServices(() -> { - var launcher = (InternalLauncher) LauncherFactory.create( - LauncherConfig.builder().enableLauncherDiscoveryListenerAutoRegistration(false).build()); - var launcherDiscoveryListener = launcher.getLauncherDiscoveryListenerRegistry().getCompositeListener(); + var config = LauncherConfig.builder() // + .enableLauncherDiscoveryListenerAutoRegistration(false) // + .build(); + var launcher = LauncherFactory.create(config); + TestLauncherDiscoveryListener.called = false; + + launcher.discover(request().build()); - assertThat(launcherDiscoveryListener).isSameAs(LauncherDiscoveryListener.NOOP); + assertFalse(TestLauncherDiscoveryListener.called); }); } @Test void discoversLauncherDiscoverRequestListenerViaServiceApiByDefault() { withTestServices(() -> { - var launcher = (InternalLauncher) LauncherFactory.create(); - var launcherDiscoveryListener = launcher.getLauncherDiscoveryListenerRegistry().getCompositeListener(); + var launcher = LauncherFactory.create(); + TestLauncherDiscoveryListener.called = false; + + launcher.discover(request().build()); - assertThat(launcherDiscoveryListener.getClass().getSimpleName()).startsWith("Composite"); - assertThat(launcherDiscoveryListener).extracting("listeners").asList() // - .contains(new TestLauncherDiscoveryListener()); + assertTrue(TestLauncherDiscoveryListener.called); }); } @Test void doesNotDiscoverLauncherSessionListenerViaServiceApiWhenDisabled() { withTestServices(() -> { - var session = (DefaultLauncherSession) LauncherFactory.openSession( - LauncherConfig.builder().enableLauncherSessionListenerAutoRegistration(false).build()); + try (var session = (DefaultLauncherSession) LauncherFactory.openSession( + LauncherConfig.builder().enableLauncherSessionListenerAutoRegistration(false).build())) { - assertThat(session.getListener()).isSameAs(LauncherSessionListener.NOOP); + assertThat(session.getListener()).isSameAs(LauncherSessionListener.NOOP); + } }); } @Test void discoversLauncherSessionListenerViaServiceApiByDefault() { withTestServices(() -> { - var session = (DefaultLauncherSession) LauncherFactory.openSession(); - - assertThat(session.getListener()).isEqualTo(new TestLauncherSessionListener()); + try (var session = (DefaultLauncherSession) LauncherFactory.openSession()) { + assertThat(session.getListener()).isEqualTo(new TestLauncherSessionListener()); + } }); } + @Test + void createsLauncherInterceptorsBeforeDiscoveringTestEngines() { + withTestServices(() -> withSystemProperty(ENABLE_LAUNCHER_INTERCEPTORS, "true", () -> { + var config = LauncherConfig.builder() // + .enableTestEngineAutoRegistration(true) // + .build(); + var request = request().build(); + + var testPlan = LauncherFactory.create(config).discover(request); + + assertThat(testPlan.getRoots()) // + .map(TestIdentifier::getUniqueIdObject) // + .map(UniqueId::getLastSegment) // + .map(UniqueId.Segment::getValue) // + .describedAs( + "Intercepted test engine is added by class loader created by TestLauncherInterceptor1").contains( + InterceptedTestEngine.ID); + })); + } + @Test void appliesLauncherInterceptorsToTestDiscovery() { withTestServices(() -> withSystemProperty(ENABLE_LAUNCHER_INTERCEPTORS, "true", () -> { @@ -266,6 +313,7 @@ public void executionFinished(TestIdentifier testIdentifier, TestExecutionResult })); } + @SuppressWarnings("SameParameterValue") private static void withSystemProperty(String key, String value, Runnable runnable) { var oldValue = System.getProperty(key); System.setProperty(key, value); @@ -284,12 +332,14 @@ private static void withSystemProperty(String key, String value, Runnable runnab private static void withTestServices(Runnable runnable) { var current = Thread.currentThread().getContextClassLoader(); - try { - var url = LauncherFactoryTests.class.getClassLoader().getResource("testservices/"); - var classLoader = new URLClassLoader(new URL[] { url }, current); + var url = LauncherFactoryTests.class.getClassLoader().getResource("testservices/"); + try (var classLoader = new URLClassLoader(new URL[] { url }, current)) { Thread.currentThread().setContextClassLoader(classLoader); runnable.run(); } + catch (IOException e) { + throw new UncheckedIOException(e); + } finally { Thread.currentThread().setContextClassLoader(current); } @@ -304,6 +354,7 @@ private LauncherDiscoveryRequest createLauncherDiscoveryRequestForBothStandardEn // @formatter:on } + @SuppressWarnings("NewClassNamingConvention") public static class JUnit4Example { @org.junit.Test @@ -312,6 +363,7 @@ public void testJ4() { } + @SuppressWarnings("NewClassNamingConvention") static class JUnit5Example { @Tag("test-post-discovery") diff --git a/platform-tests/src/test/java/org/junit/platform/launcher/listeners/AnotherUnusedTestExecutionListener.java b/platform-tests/src/test/java/org/junit/platform/launcher/listeners/AnotherUnusedTestExecutionListener.java index c3d6cfaccd8a..a0ca73ca6361 100644 --- a/platform-tests/src/test/java/org/junit/platform/launcher/listeners/AnotherUnusedTestExecutionListener.java +++ b/platform-tests/src/test/java/org/junit/platform/launcher/listeners/AnotherUnusedTestExecutionListener.java @@ -11,7 +11,13 @@ package org.junit.platform.launcher.listeners; import org.junit.platform.launcher.TestExecutionListener; +import org.junit.platform.launcher.TestPlan; public class AnotherUnusedTestExecutionListener implements TestExecutionListener { - // empty on purpose + public static boolean called; + + @Override + public void testPlanExecutionStarted(TestPlan testPlan) { + called = true; + } } diff --git a/platform-tests/src/test/java/org/junit/platform/launcher/listeners/NoopTestExecutionListener.java b/platform-tests/src/test/java/org/junit/platform/launcher/listeners/NoopTestExecutionListener.java index d471e6e745c2..268dd599c80f 100644 --- a/platform-tests/src/test/java/org/junit/platform/launcher/listeners/NoopTestExecutionListener.java +++ b/platform-tests/src/test/java/org/junit/platform/launcher/listeners/NoopTestExecutionListener.java @@ -11,10 +11,16 @@ package org.junit.platform.launcher.listeners; import org.junit.platform.launcher.TestExecutionListener; +import org.junit.platform.launcher.TestPlan; /** * @since 1.0 */ public class NoopTestExecutionListener implements TestExecutionListener { - // empty on purpose + public static boolean called; + + @Override + public void testPlanExecutionStarted(TestPlan testPlan) { + called = true; + } } diff --git a/platform-tests/src/test/java/org/junit/platform/launcher/listeners/UnusedTestExecutionListener.java b/platform-tests/src/test/java/org/junit/platform/launcher/listeners/UnusedTestExecutionListener.java index cbf7e6f9bea9..53353c2ff3ff 100644 --- a/platform-tests/src/test/java/org/junit/platform/launcher/listeners/UnusedTestExecutionListener.java +++ b/platform-tests/src/test/java/org/junit/platform/launcher/listeners/UnusedTestExecutionListener.java @@ -11,7 +11,13 @@ package org.junit.platform.launcher.listeners; import org.junit.platform.launcher.TestExecutionListener; +import org.junit.platform.launcher.TestPlan; public class UnusedTestExecutionListener implements TestExecutionListener { - // empty on purpose + public static boolean called; + + @Override + public void testPlanExecutionStarted(TestPlan testPlan) { + called = true; + } } diff --git a/platform-tests/src/test/resources/intercepted-testservices/META-INF/services/org.junit.platform.engine.TestEngine b/platform-tests/src/test/resources/intercepted-testservices/META-INF/services/org.junit.platform.engine.TestEngine new file mode 100644 index 000000000000..c27ba1c33eee --- /dev/null +++ b/platform-tests/src/test/resources/intercepted-testservices/META-INF/services/org.junit.platform.engine.TestEngine @@ -0,0 +1 @@ +org.junit.platform.launcher.InterceptedTestEngine diff --git a/platform-tests/src/test/resources/testservices/junit-platform.properties b/platform-tests/src/test/resources/testservices/junit-platform.properties deleted file mode 100644 index 7b87d3ca34ff..000000000000 --- a/platform-tests/src/test/resources/testservices/junit-platform.properties +++ /dev/null @@ -1 +0,0 @@ -junit.platform.execution.listeners.deactivate=org.junit.*.launcher.listeners.Unused*,org.junit.*.launcher.listeners.AnotherUnused* \ No newline at end of file diff --git a/platform-tooling-support-tests/projects/standalone/expected-err.txt b/platform-tooling-support-tests/projects/standalone/expected-err.txt index 46cdad9ec4b2..5788d5f3db68 100644 --- a/platform-tooling-support-tests/projects/standalone/expected-err.txt +++ b/platform-tooling-support-tests/projects/standalone/expected-err.txt @@ -1,3 +1,5 @@ +.+ org.junit.platform.launcher.core.ServiceLoaderRegistry load +.+ Loaded LauncherSessionListener instances: .. .+ org.junit.platform.launcher.core.ServiceLoaderTestEngineRegistry loadTestEngines .+ Discovered TestEngines: - junit-jupiter .+ @@ -9,8 +11,6 @@ .+ Loaded LauncherDiscoveryListener instances: .. .+ org.junit.platform.launcher.core.ServiceLoaderRegistry load .+ Loaded TestExecutionListener instances: .+ -.+ org.junit.platform.launcher.core.ServiceLoaderRegistry load -.+ Loaded LauncherSessionListener instances: .. .+ org.junit.platform.launcher.core.ServiceLoaderTestEngineRegistry loadTestEngines .+ Discovered TestEngines: - junit-jupiter .+ From 7a056cd80940114502216a5fad97716aedc40e75 Mon Sep 17 00:00:00 2001 From: Marc Philipp Date: Wed, 16 Nov 2022 07:57:54 +0100 Subject: [PATCH 0004/1473] Load interceptors before session listeners --- .../launcher/LauncherInterceptor.java | 40 ++++++++ .../launcher/core/CloseableLauncher.java | 21 ----- .../launcher/core/DefaultLauncherSession.java | 38 ++++---- .../core/DelegatingCloseableLauncher.java | 41 -------- .../launcher/core/DelegatingLauncher.java | 6 +- .../core/InterceptingClosableLauncher.java | 93 ------------------- .../launcher/core/InterceptingLauncher.java | 51 ++++++++++ .../launcher/core/LauncherFactory.java | 6 +- .../core/SessionPerRequestLauncher.java | 11 ++- ...ceptorInjectedLauncherSessionListener.java | 35 +++++++ .../launcher/TestLauncherInterceptor1.java | 4 +- .../launcher/TestLauncherInterceptor2.java | 10 +- .../launcher/core/LauncherFactoryTests.java | 5 + ....platform.launcher.LauncherSessionListener | 1 + .../projects/standalone/expected-err.txt | 2 + .../support/tests/StandaloneTests.java | 3 + 16 files changed, 181 insertions(+), 186 deletions(-) delete mode 100644 junit-platform-launcher/src/main/java/org/junit/platform/launcher/core/CloseableLauncher.java delete mode 100644 junit-platform-launcher/src/main/java/org/junit/platform/launcher/core/DelegatingCloseableLauncher.java delete mode 100644 junit-platform-launcher/src/main/java/org/junit/platform/launcher/core/InterceptingClosableLauncher.java create mode 100644 junit-platform-launcher/src/main/java/org/junit/platform/launcher/core/InterceptingLauncher.java create mode 100644 platform-tests/src/test/java/org/junit/platform/launcher/InterceptorInjectedLauncherSessionListener.java create mode 100644 platform-tests/src/test/resources/intercepted-testservices/META-INF/services/org.junit.platform.launcher.LauncherSessionListener diff --git a/junit-platform-launcher/src/main/java/org/junit/platform/launcher/LauncherInterceptor.java b/junit-platform-launcher/src/main/java/org/junit/platform/launcher/LauncherInterceptor.java index cf91b3d67d10..a8a4111dd327 100644 --- a/junit-platform-launcher/src/main/java/org/junit/platform/launcher/LauncherInterceptor.java +++ b/junit-platform-launcher/src/main/java/org/junit/platform/launcher/LauncherInterceptor.java @@ -11,6 +11,9 @@ package org.junit.platform.launcher; import static org.apiguardian.api.API.Status.EXPERIMENTAL; +import static org.apiguardian.api.API.Status.INTERNAL; + +import java.util.List; import org.apiguardian.api.API; @@ -28,6 +31,18 @@ @API(status = EXPERIMENTAL, since = "1.10") public interface LauncherInterceptor { + LauncherInterceptor NOOP = new LauncherInterceptor() { + @Override + public T intercept(Invocation invocation) { + return invocation.proceed(); + } + + @Override + public void close() { + // do nothing + } + }; + /** * Intercept the supplied invocation. * @@ -54,4 +69,29 @@ public interface LauncherInterceptor { interface Invocation { T proceed(); } + + @API(status = INTERNAL, since = "1.10") + static LauncherInterceptor composite(List interceptors) { + if (interceptors.isEmpty()) { + return NOOP; + } + return interceptors.stream() // + .skip(1) // + .reduce(interceptors.get(0), (a, b) -> new LauncherInterceptor() { + @Override + public void close() { + try { + a.close(); + } + finally { + b.close(); + } + } + + @Override + public T intercept(Invocation invocation) { + return a.intercept(() -> b.intercept(invocation)); + } + }); + } } diff --git a/junit-platform-launcher/src/main/java/org/junit/platform/launcher/core/CloseableLauncher.java b/junit-platform-launcher/src/main/java/org/junit/platform/launcher/core/CloseableLauncher.java deleted file mode 100644 index 1cc023471b22..000000000000 --- a/junit-platform-launcher/src/main/java/org/junit/platform/launcher/core/CloseableLauncher.java +++ /dev/null @@ -1,21 +0,0 @@ -/* - * Copyright 2015-2023 the original author or authors. - * - * All rights reserved. This program and the accompanying materials are - * made available under the terms of the Eclipse Public License v2.0 which - * accompanies this distribution and is available at - * - * https://www.eclipse.org/legal/epl-v20.html - */ - -package org.junit.platform.launcher.core; - -import org.junit.platform.launcher.Launcher; - -/** - * @since 1.10 - */ -interface CloseableLauncher extends Launcher, AutoCloseable { - @Override - void close(); -} diff --git a/junit-platform-launcher/src/main/java/org/junit/platform/launcher/core/DefaultLauncherSession.java b/junit-platform-launcher/src/main/java/org/junit/platform/launcher/core/DefaultLauncherSession.java index 0a4436dd5ed1..42969448616e 100644 --- a/junit-platform-launcher/src/main/java/org/junit/platform/launcher/core/DefaultLauncherSession.java +++ b/junit-platform-launcher/src/main/java/org/junit/platform/launcher/core/DefaultLauncherSession.java @@ -28,17 +28,23 @@ */ class DefaultLauncherSession implements LauncherSession { - private final DelegatingCloseableLauncher launcher; + private final LauncherInterceptor interceptor; private final LauncherSessionListener listener; - - DefaultLauncherSession(Supplier launcherSupplier, List interceptors, - LauncherSessionListener listener) { - CloseableLauncher closeableLauncher = InterceptingClosableLauncher.decorate(launcherSupplier, interceptors); - this.launcher = new DelegatingCloseableLauncher<>(closeableLauncher, delegate -> { - delegate.close(); - return ClosedLauncher.INSTANCE; - }); - this.listener = listener; + private final DelegatingLauncher launcher; + + DefaultLauncherSession(List interceptors, Supplier listenerSupplier, + Supplier launcherSupplier) { + interceptor = LauncherInterceptor.composite(interceptors); + Launcher launcher; + if (interceptor == LauncherInterceptor.NOOP) { + this.listener = listenerSupplier.get(); + launcher = launcherSupplier.get(); + } + else { + this.listener = interceptor.intercept(listenerSupplier::get); + launcher = new InterceptingLauncher(interceptor.intercept(launcherSupplier::get), interceptor); + } + this.launcher = new DelegatingLauncher(launcher); listener.launcherSessionOpened(this); } @@ -53,13 +59,14 @@ LauncherSessionListener getListener() { @Override public void close() { - if (!launcher.isClosed()) { - launcher.close(); + if (launcher.delegate != ClosedLauncher.INSTANCE) { + launcher.delegate = ClosedLauncher.INSTANCE; listener.launcherSessionClosed(this); + interceptor.close(); } } - private static class ClosedLauncher implements CloseableLauncher { + private static class ClosedLauncher implements Launcher { static final ClosedLauncher INSTANCE = new ClosedLauncher(); @@ -90,10 +97,5 @@ public void execute(LauncherDiscoveryRequest launcherDiscoveryRequest, TestExecu public void execute(TestPlan testPlan, TestExecutionListener... listeners) { throw new PreconditionViolationException("Launcher session has already been closed"); } - - @Override - public void close() { - // do nothing - } } } diff --git a/junit-platform-launcher/src/main/java/org/junit/platform/launcher/core/DelegatingCloseableLauncher.java b/junit-platform-launcher/src/main/java/org/junit/platform/launcher/core/DelegatingCloseableLauncher.java deleted file mode 100644 index a6ea513acf03..000000000000 --- a/junit-platform-launcher/src/main/java/org/junit/platform/launcher/core/DelegatingCloseableLauncher.java +++ /dev/null @@ -1,41 +0,0 @@ -/* - * Copyright 2015-2023 the original author or authors. - * - * All rights reserved. This program and the accompanying materials are - * made available under the terms of the Eclipse Public License v2.0 which - * accompanies this distribution and is available at - * - * https://www.eclipse.org/legal/epl-v20.html - */ - -package org.junit.platform.launcher.core; - -import java.util.function.Function; - -import org.junit.platform.launcher.Launcher; - -/** - * @since 1.10 - */ -class DelegatingCloseableLauncher extends DelegatingLauncher implements CloseableLauncher { - - private final Function onClose; - private boolean closed; - - public DelegatingCloseableLauncher(T delegate, Function onClose) { - super(delegate); - this.onClose = onClose; - } - - @Override - public final void close() { - if (!closed) { - this.closed = true; - delegate = this.onClose.apply(this.delegate); - } - } - - public boolean isClosed() { - return closed; - } -} diff --git a/junit-platform-launcher/src/main/java/org/junit/platform/launcher/core/DelegatingLauncher.java b/junit-platform-launcher/src/main/java/org/junit/platform/launcher/core/DelegatingLauncher.java index 3e226af1255d..d4332b52fe35 100644 --- a/junit-platform-launcher/src/main/java/org/junit/platform/launcher/core/DelegatingLauncher.java +++ b/junit-platform-launcher/src/main/java/org/junit/platform/launcher/core/DelegatingLauncher.java @@ -19,11 +19,11 @@ /** * @since 1.10 */ -class DelegatingLauncher implements Launcher { +class DelegatingLauncher implements Launcher { - protected T delegate; + protected Launcher delegate; - DelegatingLauncher(T delegate) { + DelegatingLauncher(Launcher delegate) { this.delegate = delegate; } diff --git a/junit-platform-launcher/src/main/java/org/junit/platform/launcher/core/InterceptingClosableLauncher.java b/junit-platform-launcher/src/main/java/org/junit/platform/launcher/core/InterceptingClosableLauncher.java deleted file mode 100644 index 20dbf2f6ed06..000000000000 --- a/junit-platform-launcher/src/main/java/org/junit/platform/launcher/core/InterceptingClosableLauncher.java +++ /dev/null @@ -1,93 +0,0 @@ -/* - * Copyright 2015-2023 the original author or authors. - * - * All rights reserved. This program and the accompanying materials are - * made available under the terms of the Eclipse Public License v2.0 which - * accompanies this distribution and is available at - * - * https://www.eclipse.org/legal/epl-v20.html - */ - -package org.junit.platform.launcher.core; - -import static java.util.function.Function.identity; - -import java.util.List; -import java.util.Optional; -import java.util.function.Supplier; - -import org.junit.platform.launcher.Launcher; -import org.junit.platform.launcher.LauncherDiscoveryRequest; -import org.junit.platform.launcher.LauncherInterceptor; -import org.junit.platform.launcher.TestExecutionListener; -import org.junit.platform.launcher.TestPlan; - -/** - * @since 1.10 - */ -class InterceptingClosableLauncher extends DelegatingCloseableLauncher { - - static CloseableLauncher decorate(Supplier launcherSupplier, List interceptors) { - Optional combinedInterceptor = composite(interceptors); - Launcher launcher = combinedInterceptor.map(it -> it.intercept(launcherSupplier::get)).orElseGet( - launcherSupplier); - return combinedInterceptor // - .map(it -> (CloseableLauncher) new InterceptingClosableLauncher(launcher, it)) // - .orElse(new DelegatingCloseableLauncher<>(launcher, identity())); - } - - private static Optional composite(List interceptors) { - if (interceptors.isEmpty()) { - return Optional.empty(); - } - return Optional.of(interceptors.stream() // - .skip(1) // - .reduce(interceptors.get(0), (a, b) -> new LauncherInterceptor() { - @Override - public void close() { - try { - a.close(); - } - finally { - b.close(); - } - } - - @Override - public T intercept(Invocation invocation) { - return a.intercept(() -> b.intercept(invocation)); - } - })); - } - - private final LauncherInterceptor interceptor; - - private InterceptingClosableLauncher(Launcher delegate, LauncherInterceptor interceptor) { - super(delegate, it -> { - interceptor.close(); - return it; - }); - this.interceptor = interceptor; - } - - @Override - public TestPlan discover(LauncherDiscoveryRequest launcherDiscoveryRequest) { - return interceptor.intercept(() -> super.discover(launcherDiscoveryRequest)); - } - - @Override - public void execute(LauncherDiscoveryRequest launcherDiscoveryRequest, TestExecutionListener... listeners) { - interceptor.intercept(() -> { - super.execute(launcherDiscoveryRequest, listeners); - return null; - }); - } - - @Override - public void execute(TestPlan testPlan, TestExecutionListener... listeners) { - interceptor.intercept(() -> { - super.execute(testPlan, listeners); - return null; - }); - } -} diff --git a/junit-platform-launcher/src/main/java/org/junit/platform/launcher/core/InterceptingLauncher.java b/junit-platform-launcher/src/main/java/org/junit/platform/launcher/core/InterceptingLauncher.java new file mode 100644 index 000000000000..043d4e9688f5 --- /dev/null +++ b/junit-platform-launcher/src/main/java/org/junit/platform/launcher/core/InterceptingLauncher.java @@ -0,0 +1,51 @@ +/* + * Copyright 2015-2023 the original author or authors. + * + * All rights reserved. This program and the accompanying materials are + * made available under the terms of the Eclipse Public License v2.0 which + * accompanies this distribution and is available at + * + * https://www.eclipse.org/legal/epl-v20.html + */ + +package org.junit.platform.launcher.core; + +import org.junit.platform.launcher.Launcher; +import org.junit.platform.launcher.LauncherDiscoveryRequest; +import org.junit.platform.launcher.LauncherInterceptor; +import org.junit.platform.launcher.TestExecutionListener; +import org.junit.platform.launcher.TestPlan; + +/** + * @since 1.10 + */ +class InterceptingLauncher extends DelegatingLauncher { + + private final LauncherInterceptor interceptor; + + InterceptingLauncher(Launcher delegate, LauncherInterceptor interceptor) { + super(delegate); + this.interceptor = interceptor; + } + + @Override + public TestPlan discover(LauncherDiscoveryRequest launcherDiscoveryRequest) { + return interceptor.intercept(() -> super.discover(launcherDiscoveryRequest)); + } + + @Override + public void execute(LauncherDiscoveryRequest launcherDiscoveryRequest, TestExecutionListener... listeners) { + interceptor.intercept(() -> { + super.execute(launcherDiscoveryRequest, listeners); + return null; + }); + } + + @Override + public void execute(TestPlan testPlan, TestExecutionListener... listeners) { + interceptor.intercept(() -> { + super.execute(testPlan, listeners); + return null; + }); + } +} diff --git a/junit-platform-launcher/src/main/java/org/junit/platform/launcher/core/LauncherFactory.java b/junit-platform-launcher/src/main/java/org/junit/platform/launcher/core/LauncherFactory.java index 77edab9bbc67..eb60ce260404 100644 --- a/junit-platform-launcher/src/main/java/org/junit/platform/launcher/core/LauncherFactory.java +++ b/junit-platform-launcher/src/main/java/org/junit/platform/launcher/core/LauncherFactory.java @@ -100,8 +100,8 @@ public static LauncherSession openSession() throws PreconditionViolationExceptio public static LauncherSession openSession(LauncherConfig config) throws PreconditionViolationException { Preconditions.notNull(config, "LauncherConfig must not be null"); LauncherConfigurationParameters configurationParameters = LauncherConfigurationParameters.builder().build(); - return new DefaultLauncherSession(() -> createDefaultLauncher(config, configurationParameters), - collectLauncherInterceptors(configurationParameters), createLauncherSessionListener(config)); + return new DefaultLauncherSession(collectLauncherInterceptors(configurationParameters), + () -> createLauncherSessionListener(config), () -> createDefaultLauncher(config, configurationParameters)); } /** @@ -131,7 +131,7 @@ public static Launcher create(LauncherConfig config) throws PreconditionViolatio Preconditions.notNull(config, "LauncherConfig must not be null"); LauncherConfigurationParameters configurationParameters = LauncherConfigurationParameters.builder().build(); return new SessionPerRequestLauncher(() -> createDefaultLauncher(config, configurationParameters), - createLauncherSessionListener(config), () -> collectLauncherInterceptors(configurationParameters)); + () -> createLauncherSessionListener(config), () -> collectLauncherInterceptors(configurationParameters)); } private static DefaultLauncher createDefaultLauncher(LauncherConfig config, diff --git a/junit-platform-launcher/src/main/java/org/junit/platform/launcher/core/SessionPerRequestLauncher.java b/junit-platform-launcher/src/main/java/org/junit/platform/launcher/core/SessionPerRequestLauncher.java index 1955bc625e56..167efb6443ec 100644 --- a/junit-platform-launcher/src/main/java/org/junit/platform/launcher/core/SessionPerRequestLauncher.java +++ b/junit-platform-launcher/src/main/java/org/junit/platform/launcher/core/SessionPerRequestLauncher.java @@ -29,13 +29,14 @@ class SessionPerRequestLauncher implements Launcher { private final LauncherListenerRegistry listenerRegistry = new LauncherListenerRegistry(); private final Supplier launcherSupplier; - private final LauncherSessionListener sessionListener; + private final Supplier sessionListenerSupplier; private final Supplier> interceptorFactory; - SessionPerRequestLauncher(Supplier launcherSupplier, LauncherSessionListener sessionListener, + SessionPerRequestLauncher(Supplier launcherSupplier, + Supplier sessionListenerSupplier, Supplier> interceptorFactory) { this.launcherSupplier = launcherSupplier; - this.sessionListener = sessionListener; + this.sessionListenerSupplier = sessionListenerSupplier; this.interceptorFactory = interceptorFactory; } @@ -71,8 +72,8 @@ public void execute(TestPlan testPlan, TestExecutionListener... listeners) { } private LauncherSession createSession() { - LauncherSession session = new DefaultLauncherSession(launcherSupplier, interceptorFactory.get(), - sessionListener); + LauncherSession session = new DefaultLauncherSession(interceptorFactory.get(), sessionListenerSupplier, + launcherSupplier); Launcher launcher = session.getLauncher(); listenerRegistry.launcherDiscoveryListeners.getListeners().forEach( launcher::registerLauncherDiscoveryListeners); diff --git a/platform-tests/src/test/java/org/junit/platform/launcher/InterceptorInjectedLauncherSessionListener.java b/platform-tests/src/test/java/org/junit/platform/launcher/InterceptorInjectedLauncherSessionListener.java new file mode 100644 index 000000000000..87cd780ba6f9 --- /dev/null +++ b/platform-tests/src/test/java/org/junit/platform/launcher/InterceptorInjectedLauncherSessionListener.java @@ -0,0 +1,35 @@ +/* + * Copyright 2015-2023 the original author or authors. + * + * All rights reserved. This program and the accompanying materials are + * made available under the terms of the Eclipse Public License v2.0 which + * accompanies this distribution and is available at + * + * https://www.eclipse.org/legal/epl-v20.html + */ + +package org.junit.platform.launcher; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertTrue; + +public class InterceptorInjectedLauncherSessionListener implements LauncherSessionListener { + + public static int CALLS; + + public InterceptorInjectedLauncherSessionListener() { + assertEquals(TestLauncherInterceptor1.CLASSLOADER_NAME, + Thread.currentThread().getContextClassLoader().getName()); + assertTrue(TestLauncherInterceptor2.INTERCEPTING); + } + + @Override + public void launcherSessionOpened(LauncherSession session) { + CALLS++; + } + + @Override + public void launcherSessionClosed(LauncherSession session) { + assertEquals(TestLauncherInterceptor1.CLASSLOADER_NAME, Thread.currentThread().getContextClassLoader().getName()); + } +} diff --git a/platform-tests/src/test/java/org/junit/platform/launcher/TestLauncherInterceptor1.java b/platform-tests/src/test/java/org/junit/platform/launcher/TestLauncherInterceptor1.java index 585ccf74b6c4..6ff0dc7046dd 100644 --- a/platform-tests/src/test/java/org/junit/platform/launcher/TestLauncherInterceptor1.java +++ b/platform-tests/src/test/java/org/junit/platform/launcher/TestLauncherInterceptor1.java @@ -17,13 +17,15 @@ public class TestLauncherInterceptor1 implements LauncherInterceptor { + public static final String CLASSLOADER_NAME = "interceptor-loader"; + private final ClassLoader originalClassLoader; private final URLClassLoader replacedClassLoader; public TestLauncherInterceptor1() { originalClassLoader = Thread.currentThread().getContextClassLoader(); var url = getClass().getClassLoader().getResource("intercepted-testservices/"); - replacedClassLoader = new URLClassLoader(new URL[] { url }, originalClassLoader); + replacedClassLoader = new URLClassLoader(CLASSLOADER_NAME, new URL[] { url }, originalClassLoader); Thread.currentThread().setContextClassLoader(replacedClassLoader); } diff --git a/platform-tests/src/test/java/org/junit/platform/launcher/TestLauncherInterceptor2.java b/platform-tests/src/test/java/org/junit/platform/launcher/TestLauncherInterceptor2.java index bdc198e3ee06..04f9ad3e29a0 100644 --- a/platform-tests/src/test/java/org/junit/platform/launcher/TestLauncherInterceptor2.java +++ b/platform-tests/src/test/java/org/junit/platform/launcher/TestLauncherInterceptor2.java @@ -12,9 +12,17 @@ public class TestLauncherInterceptor2 implements LauncherInterceptor { + public static boolean INTERCEPTING; + @Override public T intercept(Invocation invocation) { - return invocation.proceed(); + INTERCEPTING = true; + try { + return invocation.proceed(); + } + finally { + INTERCEPTING = false; + } } @Override diff --git a/platform-tests/src/test/java/org/junit/platform/launcher/core/LauncherFactoryTests.java b/platform-tests/src/test/java/org/junit/platform/launcher/core/LauncherFactoryTests.java index 072c6119e369..e769149edfff 100644 --- a/platform-tests/src/test/java/org/junit/platform/launcher/core/LauncherFactoryTests.java +++ b/platform-tests/src/test/java/org/junit/platform/launcher/core/LauncherFactoryTests.java @@ -37,6 +37,7 @@ import org.junit.platform.engine.UniqueId; import org.junit.platform.fakes.TestEngineSpy; import org.junit.platform.launcher.InterceptedTestEngine; +import org.junit.platform.launcher.InterceptorInjectedLauncherSessionListener; import org.junit.platform.launcher.LauncherDiscoveryRequest; import org.junit.platform.launcher.LauncherSessionListener; import org.junit.platform.launcher.TagFilter; @@ -257,6 +258,7 @@ void createsLauncherInterceptorsBeforeDiscoveringTestEngines() { @Test void appliesLauncherInterceptorsToTestDiscovery() { + InterceptorInjectedLauncherSessionListener.CALLS = 0; withTestServices(() -> withSystemProperty(ENABLE_LAUNCHER_INTERCEPTORS, "true", () -> { var engine = new TestEngineSpy() { @Override @@ -277,11 +279,13 @@ public TestDescriptor discover(EngineDiscoveryRequest discoveryRequest, UniqueId .hasRootCauseMessage("from discovery") // .hasStackTraceContaining(TestLauncherInterceptor1.class.getName() + ".intercept(") // .hasStackTraceContaining(TestLauncherInterceptor2.class.getName() + ".intercept("); + assertThat(InterceptorInjectedLauncherSessionListener.CALLS).isEqualTo(1); })); } @Test void appliesLauncherInterceptorsToTestExecution() { + InterceptorInjectedLauncherSessionListener.CALLS = 0; withTestServices(() -> withSystemProperty(ENABLE_LAUNCHER_INTERCEPTORS, "true", () -> { var engine = new TestEngineSpy() { @Override @@ -310,6 +314,7 @@ public void executionFinished(TestIdentifier testIdentifier, TestExecutionResult .hasRootCauseMessage("from execution") // .hasStackTraceContaining(TestLauncherInterceptor1.class.getName() + ".intercept(") // .hasStackTraceContaining(TestLauncherInterceptor2.class.getName() + ".intercept("); + assertThat(InterceptorInjectedLauncherSessionListener.CALLS).isEqualTo(1); })); } diff --git a/platform-tests/src/test/resources/intercepted-testservices/META-INF/services/org.junit.platform.launcher.LauncherSessionListener b/platform-tests/src/test/resources/intercepted-testservices/META-INF/services/org.junit.platform.launcher.LauncherSessionListener new file mode 100644 index 000000000000..170360744b1c --- /dev/null +++ b/platform-tests/src/test/resources/intercepted-testservices/META-INF/services/org.junit.platform.launcher.LauncherSessionListener @@ -0,0 +1 @@ +org.junit.platform.launcher.InterceptorInjectedLauncherSessionListener diff --git a/platform-tooling-support-tests/projects/standalone/expected-err.txt b/platform-tooling-support-tests/projects/standalone/expected-err.txt index 5788d5f3db68..cc4b8df06ddd 100644 --- a/platform-tooling-support-tests/projects/standalone/expected-err.txt +++ b/platform-tooling-support-tests/projects/standalone/expected-err.txt @@ -1,4 +1,6 @@ .+ org.junit.platform.launcher.core.ServiceLoaderRegistry load +.+ Loaded LauncherInterceptor instances: .. +.+ org.junit.platform.launcher.core.ServiceLoaderRegistry load .+ Loaded LauncherSessionListener instances: .. .+ org.junit.platform.launcher.core.ServiceLoaderTestEngineRegistry loadTestEngines .+ Discovered TestEngines: diff --git a/platform-tooling-support-tests/src/test/java/platform/tooling/support/tests/StandaloneTests.java b/platform-tooling-support-tests/src/test/java/platform/tooling/support/tests/StandaloneTests.java index 6bd095431836..97f322765d28 100644 --- a/platform-tooling-support-tests/src/test/java/platform/tooling/support/tests/StandaloneTests.java +++ b/platform-tooling-support-tests/src/test/java/platform/tooling/support/tests/StandaloneTests.java @@ -120,6 +120,7 @@ void test() throws IOException { .addArguments("--show-version") // .addArguments("-enableassertions") // .addArguments("-Djava.util.logging.config.file=logging.properties") // + .addArguments("-Djunit.platform.launcher.interceptors.enabled=true") // .addArguments("-jar", MavenRepo.jar("junit-platform-console-standalone")) // .addArguments("--scan-class-path") // .addArguments("--disable-banner") // @@ -153,6 +154,7 @@ void testOnJava8() throws IOException { .addArguments("--show-version") // .addArguments("-enableassertions") // .addArguments("-Djava.util.logging.config.file=logging.properties") // + .addArguments("-Djunit.platform.launcher.interceptors.enabled=true") // .addArguments("-jar", MavenRepo.jar("junit-platform-console-standalone")) // .addArguments("--scan-class-path") // .addArguments("--disable-banner") // @@ -187,6 +189,7 @@ void testOnJava8SelectPackage() throws IOException { .addArguments("--show-version") // .addArguments("-enableassertions") // .addArguments("-Djava.util.logging.config.file=logging.properties") // + .addArguments("-Djunit.platform.launcher.interceptors.enabled=true") // .addArguments("-jar", MavenRepo.jar("junit-platform-console-standalone")) // .addArguments("--select-package", "standalone") // .addArguments("--disable-banner") // From 39bf72bf5ab8152a18aaeca95a83b86dcb3cacc4 Mon Sep 17 00:00:00 2001 From: Marc Philipp Date: Mon, 23 Jan 2023 09:37:10 +0100 Subject: [PATCH 0005/1473] Increase compatibility with GraalVM - Avoid early static initialization during native image compilation where possible - Use and document `--initialize-at-build-time` build argument --- .../release-notes/release-notes-5.10.0-M1.adoc | 3 ++- .../platform/launcher/core/EngineIdValidator.java | 9 ++++++--- .../platform/launcher/core/LauncherFactory.java | 12 +++++------- .../launcher/core/ServiceLoaderRegistry.java | 11 +++++++---- .../core/ServiceLoaderTestEngineRegistry.java | 9 ++++++--- .../InterceptorInjectedLauncherSessionListener.java | 9 +++++---- .../projects/graalvm-starter/build.gradle.kts | 9 +++++++++ 7 files changed, 40 insertions(+), 22 deletions(-) diff --git a/documentation/src/docs/asciidoc/release-notes/release-notes-5.10.0-M1.adoc b/documentation/src/docs/asciidoc/release-notes/release-notes-5.10.0-M1.adoc index daea2f4ed0f6..716d9b3ce7e6 100644 --- a/documentation/src/docs/asciidoc/release-notes/release-notes-5.10.0-M1.adoc +++ b/documentation/src/docs/asciidoc/release-notes/release-notes-5.10.0-M1.adoc @@ -19,7 +19,8 @@ repository on GitHub. ==== Deprecations and Breaking Changes -* ❓ +* Building native images with GraalVM now requires configuring the build arg + `--initialize-at-build-time=org.junit.platform.launcher.core.LauncherConfig`. ==== New Features and Improvements diff --git a/junit-platform-launcher/src/main/java/org/junit/platform/launcher/core/EngineIdValidator.java b/junit-platform-launcher/src/main/java/org/junit/platform/launcher/core/EngineIdValidator.java index adf3739b39e0..abeeb298acaa 100644 --- a/junit-platform-launcher/src/main/java/org/junit/platform/launcher/core/EngineIdValidator.java +++ b/junit-platform-launcher/src/main/java/org/junit/platform/launcher/core/EngineIdValidator.java @@ -23,8 +23,6 @@ */ class EngineIdValidator { - private static final Logger logger = LoggerFactory.getLogger(EngineIdValidator.class); - private EngineIdValidator() { } @@ -33,7 +31,7 @@ static Iterable validate(Iterable testEngines) { for (TestEngine testEngine : testEngines) { // check usage of reserved id prefix if (!validateReservedIds(testEngine)) { - logger.warn(() -> String.format( + getLogger().warn(() -> String.format( "Third-party TestEngine implementations are forbidden to use the reserved 'junit-' prefix for their ID: '%s'", testEngine.getId())); } @@ -47,6 +45,11 @@ static Iterable validate(Iterable testEngines) { return testEngines; } + private static Logger getLogger() { + // Not a constant to avoid problems with building GraalVM native images + return LoggerFactory.getLogger(EngineIdValidator.class); + } + // https://github.com/junit-team/junit5/issues/1557 private static boolean validateReservedIds(TestEngine testEngine) { String engineId = testEngine.getId(); diff --git a/junit-platform-launcher/src/main/java/org/junit/platform/launcher/core/LauncherFactory.java b/junit-platform-launcher/src/main/java/org/junit/platform/launcher/core/LauncherFactory.java index eb60ce260404..172db2b89a34 100644 --- a/junit-platform-launcher/src/main/java/org/junit/platform/launcher/core/LauncherFactory.java +++ b/junit-platform-launcher/src/main/java/org/junit/platform/launcher/core/LauncherFactory.java @@ -66,8 +66,6 @@ @API(status = STABLE, since = "1.0") public class LauncherFactory { - private static final ServiceLoaderRegistry SERVICE_LOADER_REGISTRY = new ServiceLoaderRegistry(); - private LauncherFactory() { /* no-op */ } @@ -151,7 +149,7 @@ private static List collectLauncherInterceptors( LauncherConfigurationParameters configurationParameters) { if (configurationParameters.getBoolean(ENABLE_LAUNCHER_INTERCEPTORS).orElse(false)) { List interceptors = new ArrayList<>(); - SERVICE_LOADER_REGISTRY.load(LauncherInterceptor.class).forEach(interceptors::add); + ServiceLoaderRegistry.load(LauncherInterceptor.class).forEach(interceptors::add); return interceptors; } return emptyList(); @@ -169,7 +167,7 @@ private static Set collectTestEngines(LauncherConfig config) { private static LauncherSessionListener createLauncherSessionListener(LauncherConfig config) { ListenerRegistry listenerRegistry = ListenerRegistry.forLauncherSessionListeners(); if (config.isLauncherSessionListenerAutoRegistrationEnabled()) { - SERVICE_LOADER_REGISTRY.load(LauncherSessionListener.class).forEach(listenerRegistry::add); + ServiceLoaderRegistry.load(LauncherSessionListener.class).forEach(listenerRegistry::add); } config.getAdditionalLauncherSessionListeners().forEach(listenerRegistry::add); return listenerRegistry.getCompositeListener(); @@ -178,7 +176,7 @@ private static LauncherSessionListener createLauncherSessionListener(LauncherCon private static List collectPostDiscoveryFilters(LauncherConfig config) { List filters = new ArrayList<>(); if (config.isPostDiscoveryFilterAutoRegistrationEnabled()) { - SERVICE_LOADER_REGISTRY.load(PostDiscoveryFilter.class).forEach(filters::add); + ServiceLoaderRegistry.load(PostDiscoveryFilter.class).forEach(filters::add); } filters.addAll(config.getAdditionalPostDiscoveryFilters()); return filters; @@ -186,7 +184,7 @@ private static List collectPostDiscoveryFilters(LauncherCon private static void registerLauncherDiscoveryListeners(LauncherConfig config, Launcher launcher) { if (config.isLauncherDiscoveryListenerAutoRegistrationEnabled()) { - SERVICE_LOADER_REGISTRY.load(LauncherDiscoveryListener.class).forEach( + ServiceLoaderRegistry.load(LauncherDiscoveryListener.class).forEach( launcher::registerLauncherDiscoveryListeners); } config.getAdditionalLauncherDiscoveryListeners().forEach(launcher::registerLauncherDiscoveryListeners); @@ -203,7 +201,7 @@ private static void registerTestExecutionListeners(LauncherConfig config, Launch private static Stream loadAndFilterTestExecutionListeners( ConfigurationParameters configurationParameters) { - Iterable listeners = SERVICE_LOADER_REGISTRY.load(TestExecutionListener.class); + Iterable listeners = ServiceLoaderRegistry.load(TestExecutionListener.class); String deactivatedListenersPattern = configurationParameters.get( DEACTIVATE_LISTENERS_PATTERN_PROPERTY_NAME).orElse(null); // @formatter:off diff --git a/junit-platform-launcher/src/main/java/org/junit/platform/launcher/core/ServiceLoaderRegistry.java b/junit-platform-launcher/src/main/java/org/junit/platform/launcher/core/ServiceLoaderRegistry.java index 47ccd2f23095..54b446cce41a 100644 --- a/junit-platform-launcher/src/main/java/org/junit/platform/launcher/core/ServiceLoaderRegistry.java +++ b/junit-platform-launcher/src/main/java/org/junit/platform/launcher/core/ServiceLoaderRegistry.java @@ -24,13 +24,16 @@ */ class ServiceLoaderRegistry { - private static final Logger logger = LoggerFactory.getLogger(ServiceLoaderRegistry.class); - - Iterable load(Class serviceProviderClass) { + static Iterable load(Class serviceProviderClass) { Iterable listeners = ServiceLoader.load(serviceProviderClass, ClassLoaderUtils.getDefaultClassLoader()); - logger.config(() -> "Loaded " + serviceProviderClass.getSimpleName() + " instances: " + getLogger().config(() -> "Loaded " + serviceProviderClass.getSimpleName() + " instances: " + stream(listeners.spliterator(), false).map(Object::toString).collect(toList())); return listeners; } + private static Logger getLogger() { + // Not a constant to avoid problems with building GraalVM native images + return LoggerFactory.getLogger(ServiceLoaderRegistry.class); + } + } diff --git a/junit-platform-launcher/src/main/java/org/junit/platform/launcher/core/ServiceLoaderTestEngineRegistry.java b/junit-platform-launcher/src/main/java/org/junit/platform/launcher/core/ServiceLoaderTestEngineRegistry.java index 00233a6b44db..9959e6e3a2e7 100644 --- a/junit-platform-launcher/src/main/java/org/junit/platform/launcher/core/ServiceLoaderTestEngineRegistry.java +++ b/junit-platform-launcher/src/main/java/org/junit/platform/launcher/core/ServiceLoaderTestEngineRegistry.java @@ -29,13 +29,16 @@ public final class ServiceLoaderTestEngineRegistry { public ServiceLoaderTestEngineRegistry() { } - private static final Logger logger = LoggerFactory.getLogger(ServiceLoaderTestEngineRegistry.class); - public Iterable loadTestEngines() { Iterable testEngines = ServiceLoader.load(TestEngine.class, ClassLoaderUtils.getDefaultClassLoader()); - logger.config(() -> TestEngineFormatter.format("Discovered TestEngines", testEngines)); + getLogger().config(() -> TestEngineFormatter.format("Discovered TestEngines", testEngines)); return testEngines; } + private static Logger getLogger() { + // Not a constant to avoid problems with building GraalVM native images + return LoggerFactory.getLogger(ServiceLoaderTestEngineRegistry.class); + } + } diff --git a/platform-tests/src/test/java/org/junit/platform/launcher/InterceptorInjectedLauncherSessionListener.java b/platform-tests/src/test/java/org/junit/platform/launcher/InterceptorInjectedLauncherSessionListener.java index 87cd780ba6f9..bbaed89e2e91 100644 --- a/platform-tests/src/test/java/org/junit/platform/launcher/InterceptorInjectedLauncherSessionListener.java +++ b/platform-tests/src/test/java/org/junit/platform/launcher/InterceptorInjectedLauncherSessionListener.java @@ -28,8 +28,9 @@ public void launcherSessionOpened(LauncherSession session) { CALLS++; } - @Override - public void launcherSessionClosed(LauncherSession session) { - assertEquals(TestLauncherInterceptor1.CLASSLOADER_NAME, Thread.currentThread().getContextClassLoader().getName()); - } + @Override + public void launcherSessionClosed(LauncherSession session) { + assertEquals(TestLauncherInterceptor1.CLASSLOADER_NAME, + Thread.currentThread().getContextClassLoader().getName()); + } } diff --git a/platform-tooling-support-tests/projects/graalvm-starter/build.gradle.kts b/platform-tooling-support-tests/projects/graalvm-starter/build.gradle.kts index edd8bd7b7474..cd346c7f1ac5 100644 --- a/platform-tooling-support-tests/projects/graalvm-starter/build.gradle.kts +++ b/platform-tooling-support-tests/projects/graalvm-starter/build.gradle.kts @@ -27,3 +27,12 @@ tasks.test { ) } } + +graalvmNative { + binaries { + named("test") { + buildArgs.add("--initialize-at-build-time=org.junit.platform.launcher.core.LauncherConfig") + buildArgs.add("-H:+ReportExceptionStackTraces") + } + } +} From 872146d6035e44f66e00195b43161b65d23f09b8 Mon Sep 17 00:00:00 2001 From: Marc Philipp Date: Tue, 31 Jan 2023 15:08:29 +0100 Subject: [PATCH 0006/1473] Document LauncherInterceptor --- .../src/docs/asciidoc/link-attributes.adoc | 1 + .../release-notes-5.10.0-M1.adoc | 5 ++ .../advanced-topics/launcher-api.adoc | 18 ++++++ .../asciidoc/user-guide/running-tests.adoc | 5 +- .../example/CustomLauncherInterceptor.java | 55 +++++++++++++++++++ .../platform/launcher/LauncherConstants.java | 11 ++++ .../launcher/LauncherInterceptor.java | 31 ++++++++++- 7 files changed, 123 insertions(+), 3 deletions(-) create mode 100644 documentation/src/test/java/example/CustomLauncherInterceptor.java diff --git a/documentation/src/docs/asciidoc/link-attributes.adoc b/documentation/src/docs/asciidoc/link-attributes.adoc index 025ab6fc86d4..224d99ea4bdd 100644 --- a/documentation/src/docs/asciidoc/link-attributes.adoc +++ b/documentation/src/docs/asciidoc/link-attributes.adoc @@ -33,6 +33,7 @@ endif::[] :LauncherDiscoveryRequest: {javadoc-root}/org.junit.platform.launcher/org/junit/platform/launcher/LauncherDiscoveryRequest.html[LauncherDiscoveryRequest] :LauncherDiscoveryRequestBuilder: {javadoc-root}/org.junit.platform.launcher/org/junit/platform/launcher/core/LauncherDiscoveryRequestBuilder.html[LauncherDiscoveryRequestBuilder] :LauncherFactory: {javadoc-root}/org.junit.platform.launcher/org/junit/platform/launcher/core/LauncherFactory.html[LauncherFactory] +:LauncherInterceptor: {javadoc-root}/org.junit.platform.launcher/org/junit/platform/launcher/LauncherInterceptor.html[LauncherInterceptor] :LauncherSession: {javadoc-root}/org.junit.platform.launcher/org/junit/platform/launcher/LauncherSession.html[LauncherSession] :LauncherSessionListener: {javadoc-root}/org.junit.platform.launcher/org/junit/platform/launcher/LauncherSessionListener.html[LauncherSessionListener] :LoggingListener: {javadoc-root}/org.junit.platform.launcher/org/junit/platform/launcher/listeners/LoggingListener.html[LoggingListener] diff --git a/documentation/src/docs/asciidoc/release-notes/release-notes-5.10.0-M1.adoc b/documentation/src/docs/asciidoc/release-notes/release-notes-5.10.0-M1.adoc index 716d9b3ce7e6..15f400b83b4e 100644 --- a/documentation/src/docs/asciidoc/release-notes/release-notes-5.10.0-M1.adoc +++ b/documentation/src/docs/asciidoc/release-notes/release-notes-5.10.0-M1.adoc @@ -31,6 +31,11 @@ repository on GitHub. methods are called in reverse order compared to the former when multiple listeners are registered. This affects the following listener interfaces: `TestExecutionListener`, `EngineExecutionListener`, `LauncherDiscoveryListener`, and `LauncherSessionListener`. +* Introduce `LauncherInterceptor` SPI for intercepting the creation of instances of + `Launcher` and `LauncherSessionlistener` as well as calls for `discover` and `execute` + of the former. Please refer to the + <<../user-guide/index.adoc#launcher-api-launcher-interceptors-custom, User Guide>> for + details. [[release-notes-5.10.0-M1-junit-jupiter]] === JUnit Jupiter diff --git a/documentation/src/docs/asciidoc/user-guide/advanced-topics/launcher-api.adoc b/documentation/src/docs/asciidoc/user-guide/advanced-topics/launcher-api.adoc index 4fcd0996c9df..8f98a7e825b1 100644 --- a/documentation/src/docs/asciidoc/user-guide/advanced-topics/launcher-api.adoc +++ b/documentation/src/docs/asciidoc/user-guide/advanced-topics/launcher-api.adoc @@ -163,6 +163,24 @@ include::{testDir}/example/session/HttpTests.java[tags=user_guide] <3> Send a request to the server <4> Check the status code of the response +[[launcher-api-launcher-interceptors-custom]] +==== Registering a LauncherInterceptor + +In order to intercept the creation of instances of `{Launcher}` and +`{LauncherSessionListener}` and calls to the `discover` and `execute` methods of the +former, clients can registercustom implementations of `{LauncherInterceptor}` via Java's +`{ServiceLoader}` mechanism by additionally setting the +`junit.platform.launcher.interceptors.enabled` <> to `true`. + +A typical use case is to create a custom replace the `ClassLoader` used by the JUnit +Platform to load test classes and engine implementations. + +[source,java] +---- +include::{testDir}/example/CustomLauncherInterceptor.java[tags=user_guide] +---- + [[launcher-api-launcher-discovery-listeners-custom]] ==== Registering a LauncherDiscoveryListener diff --git a/documentation/src/docs/asciidoc/user-guide/running-tests.adoc b/documentation/src/docs/asciidoc/user-guide/running-tests.adoc index e88d0056e5fe..cdff368b4f3a 100644 --- a/documentation/src/docs/asciidoc/user-guide/running-tests.adoc +++ b/documentation/src/docs/asciidoc/user-guide/running-tests.adoc @@ -979,7 +979,7 @@ because particularly when to attribute it to a specific test or container. [[running-tests-listeners]] -=== Using Listeners +=== Using Listeners and Interceptors The JUnit Platform provides the following listener APIs that allow JUnit, third parties, and custom user code to react to events fired at various points during the discovery and @@ -987,6 +987,8 @@ execution of a `TestPlan`. * `{LauncherSessionListener}`: receives events when a `{LauncherSession}` is opened and closed. +* `{LauncherInterceptor}`: intercepts test discovery and execution in the context of a + `LauncherSession`. * `{LauncherDiscoveryListener}`: receives events that occur during test discovery. * `{TestExecutionListener}`: receives events that occur during test execution. @@ -1003,6 +1005,7 @@ For details on registering and configuring listeners, see the following sections guide. * <> +* <> * <> * <> * <> diff --git a/documentation/src/test/java/example/CustomLauncherInterceptor.java b/documentation/src/test/java/example/CustomLauncherInterceptor.java new file mode 100644 index 000000000000..149cf7e45440 --- /dev/null +++ b/documentation/src/test/java/example/CustomLauncherInterceptor.java @@ -0,0 +1,55 @@ +/* + * Copyright 2015-2023 the original author or authors. + * + * All rights reserved. This program and the accompanying materials are + * made available under the terms of the Eclipse Public License v2.0 which + * accompanies this distribution and is available at + * + * https://www.eclipse.org/legal/epl-v20.html + */ + +package example; + +// tag::user_guide[] + +import java.io.IOException; +import java.io.UncheckedIOException; +import java.net.URI; +import java.net.URL; +import java.net.URLClassLoader; + +import org.junit.platform.launcher.LauncherInterceptor; + +public class CustomLauncherInterceptor implements LauncherInterceptor { + + private final URLClassLoader customClassLoader; + + public CustomLauncherInterceptor() throws Exception { + ClassLoader parent = Thread.currentThread().getContextClassLoader(); + customClassLoader = new URLClassLoader(new URL[] { URI.create("some.jar").toURL() }, parent); + } + + @Override + public T intercept(Invocation invocation) { + Thread currentThread = Thread.currentThread(); + ClassLoader originalClassLoader = currentThread.getContextClassLoader(); + currentThread.setContextClassLoader(customClassLoader); + try { + return invocation.proceed(); + } + finally { + currentThread.setContextClassLoader(originalClassLoader); + } + } + + @Override + public void close() { + try { + customClassLoader.close(); + } + catch (IOException e) { + throw new UncheckedIOException("Failed to close custom class loader", e); + } + } +} +// end::user_guide[] diff --git a/junit-platform-launcher/src/main/java/org/junit/platform/launcher/LauncherConstants.java b/junit-platform-launcher/src/main/java/org/junit/platform/launcher/LauncherConstants.java index 218bf3a077ed..12f52e2edf05 100644 --- a/junit-platform-launcher/src/main/java/org/junit/platform/launcher/LauncherConstants.java +++ b/junit-platform-launcher/src/main/java/org/junit/platform/launcher/LauncherConstants.java @@ -10,6 +10,7 @@ package org.junit.platform.launcher; +import static org.apiguardian.api.API.Status.EXPERIMENTAL; import static org.apiguardian.api.API.Status.STABLE; import org.apiguardian.api.API; @@ -135,6 +136,16 @@ public class LauncherConstants { */ public static final String DEACTIVATE_ALL_LISTENERS_PATTERN = ClassNamePatternFilterUtils.DEACTIVATE_ALL_PATTERN; + /** + * Property name used to enable support for + * {@link LauncherInterceptor} instances to be registered via the + * {@link java.util.ServiceLoader ServiceLoader} mechanism: {@value} + * + *

By default, interceptor registration is disabled. + * + * @see LauncherInterceptor + */ + @API(status = EXPERIMENTAL, since = "1.10") public static final String ENABLE_LAUNCHER_INTERCEPTORS = "junit.platform.launcher.interceptors.enabled"; private LauncherConstants() { diff --git a/junit-platform-launcher/src/main/java/org/junit/platform/launcher/LauncherInterceptor.java b/junit-platform-launcher/src/main/java/org/junit/platform/launcher/LauncherInterceptor.java index a8a4111dd327..7f4c0e17c70f 100644 --- a/junit-platform-launcher/src/main/java/org/junit/platform/launcher/LauncherInterceptor.java +++ b/junit-platform-launcher/src/main/java/org/junit/platform/launcher/LauncherInterceptor.java @@ -18,10 +18,37 @@ import org.apiguardian.api.API; /** - * Interceptor for test discovery and execution by a {@link Launcher}. + * Interceptor for test discovery and execution by a {@link Launcher} in the + * context of a {@link LauncherSession}. * *

Interceptors are instantiated once per {@link LauncherSession} and closed - * when the session is about to be closed. + * after the session is closed. They can + * {@linkplain #intercept(Invocation) intercept} the following invocations: + *

+ * + *

Implementations of this interface can be registered via the + * {@link java.util.ServiceLoader ServiceLoader} mechanism by additionally + * setting the {@value LauncherConstants#ENABLE_LAUNCHER_INTERCEPTORS} + * configuration parameter to {@code true}. + * + *

A typical use case is to create a custom {@link ClassLoader} in the + * constructor of the implementing class, replace the + * {@link Thread#setContextClassLoader(ClassLoader) contextClassLoader} of the + * current thread while {@link #intercept(Invocation) intercepting} invocations, + * and close the custom {@code ClassLoader} in {@link #close()} * * @since 1.10 * @see Launcher From 700c2d4f25b48bfc4970f99d3198af5e8c5e3f37 Mon Sep 17 00:00:00 2001 From: Marc Philipp Date: Tue, 31 Jan 2023 15:49:28 +0100 Subject: [PATCH 0007/1473] Hide implementation details --- .../launcher/LauncherInterceptor.java | 39 ------------------ .../launcher/core/DefaultLauncherSession.java | 40 ++++++++++++++++++- 2 files changed, 38 insertions(+), 41 deletions(-) diff --git a/junit-platform-launcher/src/main/java/org/junit/platform/launcher/LauncherInterceptor.java b/junit-platform-launcher/src/main/java/org/junit/platform/launcher/LauncherInterceptor.java index 7f4c0e17c70f..262a1d539809 100644 --- a/junit-platform-launcher/src/main/java/org/junit/platform/launcher/LauncherInterceptor.java +++ b/junit-platform-launcher/src/main/java/org/junit/platform/launcher/LauncherInterceptor.java @@ -11,9 +11,6 @@ package org.junit.platform.launcher; import static org.apiguardian.api.API.Status.EXPERIMENTAL; -import static org.apiguardian.api.API.Status.INTERNAL; - -import java.util.List; import org.apiguardian.api.API; @@ -58,18 +55,6 @@ @API(status = EXPERIMENTAL, since = "1.10") public interface LauncherInterceptor { - LauncherInterceptor NOOP = new LauncherInterceptor() { - @Override - public T intercept(Invocation invocation) { - return invocation.proceed(); - } - - @Override - public void close() { - // do nothing - } - }; - /** * Intercept the supplied invocation. * @@ -97,28 +82,4 @@ interface Invocation { T proceed(); } - @API(status = INTERNAL, since = "1.10") - static LauncherInterceptor composite(List interceptors) { - if (interceptors.isEmpty()) { - return NOOP; - } - return interceptors.stream() // - .skip(1) // - .reduce(interceptors.get(0), (a, b) -> new LauncherInterceptor() { - @Override - public void close() { - try { - a.close(); - } - finally { - b.close(); - } - } - - @Override - public T intercept(Invocation invocation) { - return a.intercept(() -> b.intercept(invocation)); - } - }); - } } diff --git a/junit-platform-launcher/src/main/java/org/junit/platform/launcher/core/DefaultLauncherSession.java b/junit-platform-launcher/src/main/java/org/junit/platform/launcher/core/DefaultLauncherSession.java index 42969448616e..b3743ac253a7 100644 --- a/junit-platform-launcher/src/main/java/org/junit/platform/launcher/core/DefaultLauncherSession.java +++ b/junit-platform-launcher/src/main/java/org/junit/platform/launcher/core/DefaultLauncherSession.java @@ -28,15 +28,27 @@ */ class DefaultLauncherSession implements LauncherSession { + private static final LauncherInterceptor NOOP_INTERCEPTOR = new LauncherInterceptor() { + @Override + public T intercept(Invocation invocation) { + return invocation.proceed(); + } + + @Override + public void close() { + // do nothing + } + }; + private final LauncherInterceptor interceptor; private final LauncherSessionListener listener; private final DelegatingLauncher launcher; DefaultLauncherSession(List interceptors, Supplier listenerSupplier, Supplier launcherSupplier) { - interceptor = LauncherInterceptor.composite(interceptors); + interceptor = composite(interceptors); Launcher launcher; - if (interceptor == LauncherInterceptor.NOOP) { + if (interceptor == NOOP_INTERCEPTOR) { this.listener = listenerSupplier.get(); launcher = launcherSupplier.get(); } @@ -98,4 +110,28 @@ public void execute(TestPlan testPlan, TestExecutionListener... listeners) { throw new PreconditionViolationException("Launcher session has already been closed"); } } + + private static LauncherInterceptor composite(List interceptors) { + if (interceptors.isEmpty()) { + return NOOP_INTERCEPTOR; + } + return interceptors.stream() // + .skip(1) // + .reduce(interceptors.get(0), (a, b) -> new LauncherInterceptor() { + @Override + public void close() { + try { + a.close(); + } + finally { + b.close(); + } + } + + @Override + public T intercept(Invocation invocation) { + return a.intercept(() -> b.intercept(invocation)); + } + }); + } } From 5b04c9492ab565f7a85bdf1789f7116f374a7a0d Mon Sep 17 00:00:00 2001 From: Marc Philipp Date: Mon, 6 Feb 2023 12:59:27 +0100 Subject: [PATCH 0008/1473] Upgradle to 8.0-rc-3 --- gradle/wrapper/gradle-wrapper.properties | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index 7bcc7d13f585..6bf23e12bda4 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,7 +1,7 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionSha256Sum=28ebe9afc20564bcdc39bfe36f6b60a373e40be2c3c307a0028b545b8ccf6ba0 -distributionUrl=https\://services.gradle.org/distributions/gradle-8.0-rc-2-bin.zip +distributionSha256Sum=9fb87bbe73f963a4c23daede3a5ed78e7ae770f3e980d3cb15d8df04518b542d +distributionUrl=https\://services.gradle.org/distributions/gradle-8.0-rc-3-bin.zip networkTimeout=10000 zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists From c0ebe649b2772cfae172ab9a2b531c1728d7b4a0 Mon Sep 17 00:00:00 2001 From: Marc Philipp Date: Tue, 14 Feb 2023 08:56:42 +0100 Subject: [PATCH 0009/1473] Upgradle to 8.0 --- gradle/wrapper/gradle-wrapper.properties | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index 6bf23e12bda4..c9b0f7a0a4ec 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,7 +1,7 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionSha256Sum=9fb87bbe73f963a4c23daede3a5ed78e7ae770f3e980d3cb15d8df04518b542d -distributionUrl=https\://services.gradle.org/distributions/gradle-8.0-rc-3-bin.zip +distributionSha256Sum=4159b938ec734a8388ce03f52aa8f3c7ed0d31f5438622545de4f83a89b79788 +distributionUrl=https\://services.gradle.org/distributions/gradle-8.0-bin.zip networkTimeout=10000 zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists From 07e788a249b37db4a1ffd6fd3d3217b9b182811f Mon Sep 17 00:00:00 2001 From: Marc Philipp Date: Tue, 14 Feb 2023 13:01:32 +0100 Subject: [PATCH 0010/1473] Fix --scan without access key --- buildSrc/src/main/kotlin/testing-conventions.gradle.kts | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/buildSrc/src/main/kotlin/testing-conventions.gradle.kts b/buildSrc/src/main/kotlin/testing-conventions.gradle.kts index d5a105f8a462..fb3a60defb20 100644 --- a/buildSrc/src/main/kotlin/testing-conventions.gradle.kts +++ b/buildSrc/src/main/kotlin/testing-conventions.gradle.kts @@ -1,4 +1,5 @@ import com.gradle.enterprise.gradleplugin.testretry.retry +import com.gradle.enterprise.gradleplugin.testselection.internal.PredictiveTestSelectionExtensionInternal import org.gradle.api.tasks.testing.logging.TestExceptionFormat.FULL import org.gradle.api.tasks.testing.logging.TestLogEvent.FAILED import org.gradle.internal.os.OperatingSystem @@ -37,6 +38,10 @@ tasks.withType().configureEach { } predictiveSelection { enabled.set(providers.gradleProperty("enablePredictiveTestSelection").map(String::toBoolean).orElse(true)) + + // Ensure PTS works when publishing Build Scans to scans.gradle.com + this as PredictiveTestSelectionExtensionInternal + server.set(uri("https://ge.junit.org")) } systemProperty("java.util.logging.manager", "org.apache.logging.log4j.jul.LogManager") // Required until ASM officially supports the JDK 14 From 988594eb57b30b9ca8dccc89eb2f0f589db5dca1 Mon Sep 17 00:00:00 2001 From: Marc Philipp Date: Wed, 15 Feb 2023 18:56:26 +0100 Subject: [PATCH 0011/1473] Fix formatting --- buildSrc/src/main/kotlin/testing-conventions.gradle.kts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/buildSrc/src/main/kotlin/testing-conventions.gradle.kts b/buildSrc/src/main/kotlin/testing-conventions.gradle.kts index fb3a60defb20..3a2c6a5e164d 100644 --- a/buildSrc/src/main/kotlin/testing-conventions.gradle.kts +++ b/buildSrc/src/main/kotlin/testing-conventions.gradle.kts @@ -39,7 +39,7 @@ tasks.withType().configureEach { predictiveSelection { enabled.set(providers.gradleProperty("enablePredictiveTestSelection").map(String::toBoolean).orElse(true)) - // Ensure PTS works when publishing Build Scans to scans.gradle.com + // Ensure PTS works when publishing Build Scans to scans.gradle.com this as PredictiveTestSelectionExtensionInternal server.set(uri("https://ge.junit.org")) } From 1711f1c7b9fca4d269c46046624e9b5b3136e861 Mon Sep 17 00:00:00 2001 From: Marc Philipp Date: Thu, 16 Feb 2023 13:21:13 +0100 Subject: [PATCH 0012/1473] Disable CodeQL Java check due to Kotlin 1.8.10 not yet being supported --- .github/workflows/codeql-analysis.yml | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/.github/workflows/codeql-analysis.yml b/.github/workflows/codeql-analysis.yml index cddd98a1e054..61e9b0b52914 100644 --- a/.github/workflows/codeql-analysis.yml +++ b/.github/workflows/codeql-analysis.yml @@ -23,7 +23,9 @@ jobs: strategy: fail-fast: false matrix: - language: ['java', 'javascript'] + language: + # - java # Currently broken because it doesn't support Kotlin 1.8.10, yet (https://github.com/github/codeql/discussions/11460#discussioncomment-4879731) + - javascript steps: - name: Check out repository uses: actions/checkout@v3 From 98631e34f90c79e6d55d2c8f83e42cd0de2fc48f Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 16 Feb 2023 15:01:39 +0100 Subject: [PATCH 0013/1473] Bump Spotless from 6.14.0 to 6.15.0 (#3154) Bumps [com.diffplug.spotless:spotless-plugin-gradle](https://github.com/diffplug/spotless) from 6.14.0 to 6.15.0. - [Release notes](https://github.com/diffplug/spotless/releases) - [Changelog](https://github.com/diffplug/spotless/blob/main/CHANGES.md) - [Commits](https://github.com/diffplug/spotless/compare/gradle/6.14.0...gradle/6.15.0) --- updated-dependencies: - dependency-name: com.diffplug.spotless:spotless-plugin-gradle dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- buildSrc/build.gradle.kts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/buildSrc/build.gradle.kts b/buildSrc/build.gradle.kts index b3fa9bb68f0f..a947c105fadf 100644 --- a/buildSrc/build.gradle.kts +++ b/buildSrc/build.gradle.kts @@ -12,7 +12,7 @@ repositories { dependencies { implementation(kotlin("gradle-plugin")) implementation("biz.aQute.bnd:biz.aQute.bnd.gradle:6.4.0") - implementation("com.diffplug.spotless:spotless-plugin-gradle:6.14.0") + implementation("com.diffplug.spotless:spotless-plugin-gradle:6.15.0") implementation("com.github.ben-manes:gradle-versions-plugin:0.44.0") implementation("gradle.plugin.com.github.johnrengelman:shadow:7.1.2") compileOnly("com.gradle:gradle-enterprise-gradle-plugin:3.12.2") // keep in sync with root settings.gradle.kts From e89c798df0bff645fb0f70c1af230f5bbc82c23a Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 16 Feb 2023 15:02:04 +0100 Subject: [PATCH 0014/1473] Bump Kotlin from 1.8.0 to 1.8.10 (#3145) Bumps Kotlin Gradle plugin from 1.8.0 to 1.8.10. --- updated-dependencies: - dependency-name: jvm dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- settings.gradle.kts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/settings.gradle.kts b/settings.gradle.kts index 0f6ac2c4f56c..69afba8a852d 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -9,7 +9,7 @@ pluginManagement { id("com.gradle.common-custom-user-data-gradle-plugin") version "1.8.2" id("org.gradle.toolchains.foojay-resolver-convention") version "0.4.0" id("org.ajoberstar.git-publish") version "4.1.1" - kotlin("jvm") version "1.8.0" + kotlin("jvm") version "1.8.10" // Check if workaround in documentation.gradle.kts can be removed when upgrading id("org.asciidoctor.jvm.convert") version "4.0.0-alpha.1" id("org.asciidoctor.jvm.pdf") version "4.0.0-alpha.1" From 9264ec7c7d0998590236cebaa8542a02865b6722 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 16 Feb 2023 15:07:55 +0100 Subject: [PATCH 0015/1473] Bump com.github.ben-manes.versions from 0.44.0 to 0.45.0 (#3144) Bumps com.github.ben-manes.versions from 0.44.0 to 0.45.0. --- updated-dependencies: - dependency-name: com.github.ben-manes.versions dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- buildSrc/build.gradle.kts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/buildSrc/build.gradle.kts b/buildSrc/build.gradle.kts index a947c105fadf..678acfa3d06f 100644 --- a/buildSrc/build.gradle.kts +++ b/buildSrc/build.gradle.kts @@ -2,7 +2,7 @@ import org.jetbrains.kotlin.gradle.tasks.KotlinCompile plugins { `kotlin-dsl` - id("com.github.ben-manes.versions") version "0.44.0" + id("com.github.ben-manes.versions") version "0.45.0" } repositories { From 919ca032be57e95651f756b9f0e7ba947548c415 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 16 Feb 2023 15:08:12 +0100 Subject: [PATCH 0016/1473] Bump com.gradle.enterprise from 3.12.2 to 3.12.3 (#3147) Bumps com.gradle.enterprise from 3.12.2 to 3.12.3. --- updated-dependencies: - dependency-name: com.gradle.enterprise dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- settings.gradle.kts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/settings.gradle.kts b/settings.gradle.kts index 69afba8a852d..4270d9d8df17 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -5,7 +5,7 @@ pluginManagement { gradlePluginPortal() } plugins { - id("com.gradle.enterprise") version "3.12.2" // keep in sync with buildSrc/build.gradle.kts + id("com.gradle.enterprise") version "3.12.3" // keep in sync with buildSrc/build.gradle.kts id("com.gradle.common-custom-user-data-gradle-plugin") version "1.8.2" id("org.gradle.toolchains.foojay-resolver-convention") version "0.4.0" id("org.ajoberstar.git-publish") version "4.1.1" From cae2bff03d63c956f6f7e06f18128babad44fdd8 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 16 Feb 2023 15:08:42 +0100 Subject: [PATCH 0017/1473] Bump gradle-enterprise-gradle-plugin in buildSrc to 3.12.3 (#3146) Bumps com.gradle:gradle-enterprise-gradle-plugin from 3.12.2 to 3.12.3. --- updated-dependencies: - dependency-name: com.gradle:gradle-enterprise-gradle-plugin dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- buildSrc/build.gradle.kts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/buildSrc/build.gradle.kts b/buildSrc/build.gradle.kts index 678acfa3d06f..4ffac612a5b4 100644 --- a/buildSrc/build.gradle.kts +++ b/buildSrc/build.gradle.kts @@ -15,7 +15,7 @@ dependencies { implementation("com.diffplug.spotless:spotless-plugin-gradle:6.15.0") implementation("com.github.ben-manes:gradle-versions-plugin:0.44.0") implementation("gradle.plugin.com.github.johnrengelman:shadow:7.1.2") - compileOnly("com.gradle:gradle-enterprise-gradle-plugin:3.12.2") // keep in sync with root settings.gradle.kts + compileOnly("com.gradle:gradle-enterprise-gradle-plugin:3.12.3") // keep in sync with root settings.gradle.kts } tasks { From 4b1de7de4afc50f84116ca69c30011f4ac622282 Mon Sep 17 00:00:00 2001 From: Benedikt Ritter Date: Thu, 16 Feb 2023 15:56:47 +0100 Subject: [PATCH 0018/1473] Replace buildSrc with an included build (#3151) - moved `buildSrc` to `gradle/plugins` - added `junitbuild` as group to all plugins - moved build logic classes from `org.junit.gradle` package to `junitbuild` package Resolves #3149. --- .gitignore | 3 +-- build.gradle.kts | 12 ++++++------ buildSrc/settings.gradle.kts | 1 - buildSrc/src/main/kotlin/base-conventions.gradle.kts | 6 ------ documentation/documentation.gradle.kts | 8 ++++---- {buildSrc => gradle/plugins}/build.gradle.kts | 4 ++-- gradle/plugins/settings.gradle.kts | 0 .../plugins}/src/main/kotlin/JavaLibraryExtension.kt | 0 .../plugins}/src/main/kotlin/License.kt | 0 .../plugins}/src/main/kotlin/ProjectExtensions.kt | 0 .../plugins}/src/main/kotlin/TaskExtensions.kt | 0 .../kotlin/junitbuild.base-conventions.gradle.kts | 6 ++++++ .../main/kotlin/junitbuild.build-metadata.gradle.kts | 0 .../junitbuild.dependency-update-check.gradle.kts | 0 ...itbuild.jacoco-aggregation-conventions.gradle.kts | 2 +- .../kotlin/junitbuild.jacoco-conventions.gradle.kts | 0 .../junitbuild.jacoco-java-conventions.gradle.kts | 2 +- .../junitbuild.java-library-conventions.gradle.kts | 12 ++++++------ .../junitbuild.java-multi-release-sources.gradle.kts | 2 +- .../kotlin/junitbuild.java-repackage-jars.gradle.kts | 0 .../junitbuild.java-toolchain-conventions.gradle.kts | 0 .../junitbuild.junit4-compatibility.gradle.kts | 2 +- .../junitbuild.kotlin-library-conventions.gradle.kts | 2 +- .../kotlin/junitbuild.osgi-conventions.gradle.kts | 0 .../junitbuild.publishing-conventions.gradle.kts | 2 +- .../kotlin/junitbuild.shadow-conventions.gradle.kts | 2 +- .../junitbuild.spotless-conventions.gradle.kts | 0 .../kotlin/junitbuild.temp-maven-repo.gradle.kts | 0 .../kotlin/junitbuild.testing-conventions.gradle.kts | 0 .../exec/ClasspathSystemPropertyProvider.kt | 2 +- .../kotlin/junitbuild}/exec/RunConsoleLauncher.kt | 2 +- .../main/kotlin/junitbuild}/java/ExecJarAction.kt | 2 +- .../junitbuild}/java/ModulePathArgumentProvider.kt | 2 +- .../junitbuild}/java/PatchModuleArgumentProvider.kt | 2 +- .../kotlin/junitbuild}/java/WriteArtifactsFile.kt | 2 +- .../javadoc/ModuleSpecificJavadocFileOption.kt | 2 +- junit-bom/junit-bom.gradle.kts | 2 +- junit-jupiter-api/junit-jupiter-api.gradle.kts | 2 +- junit-jupiter-engine/junit-jupiter-engine.gradle.kts | 4 ++-- .../junit-jupiter-migrationsupport.gradle.kts | 6 +++--- junit-jupiter-params/junit-jupiter-params.gradle.kts | 6 +++--- junit-jupiter/junit-jupiter.gradle.kts | 2 +- .../junit-platform-commons.gradle.kts | 8 ++++---- .../junit-platform-console-standalone.gradle.kts | 6 +++--- .../junit-platform-console.gradle.kts | 10 +++++----- .../junit-platform-engine.gradle.kts | 2 +- junit-platform-jfr/junit-platform-jfr.gradle.kts | 2 +- .../junit-platform-launcher.gradle.kts | 2 +- .../junit-platform-reporting.gradle.kts | 4 ++-- .../junit-platform-runner.gradle.kts | 4 ++-- .../junit-platform-suite-api.gradle.kts | 2 +- .../junit-platform-suite-commons.gradle.kts | 2 +- .../junit-platform-suite-engine.gradle.kts | 2 +- junit-platform-suite/junit-platform-suite.gradle.kts | 2 +- .../junit-platform-testkit.gradle.kts | 2 +- junit-vintage-engine/junit-vintage-engine.gradle.kts | 6 +++--- platform-tests/platform-tests.gradle.kts | 6 +++--- .../platform-tooling-support-tests.gradle.kts | 4 ++-- settings.gradle.kts | 1 + 59 files changed, 83 insertions(+), 84 deletions(-) delete mode 100644 buildSrc/settings.gradle.kts delete mode 100644 buildSrc/src/main/kotlin/base-conventions.gradle.kts rename {buildSrc => gradle/plugins}/build.gradle.kts (94%) create mode 100644 gradle/plugins/settings.gradle.kts rename {buildSrc => gradle/plugins}/src/main/kotlin/JavaLibraryExtension.kt (100%) rename {buildSrc => gradle/plugins}/src/main/kotlin/License.kt (100%) rename {buildSrc => gradle/plugins}/src/main/kotlin/ProjectExtensions.kt (100%) rename {buildSrc => gradle/plugins}/src/main/kotlin/TaskExtensions.kt (100%) create mode 100644 gradle/plugins/src/main/kotlin/junitbuild.base-conventions.gradle.kts rename buildSrc/src/main/kotlin/build-metadata.gradle.kts => gradle/plugins/src/main/kotlin/junitbuild.build-metadata.gradle.kts (100%) rename buildSrc/src/main/kotlin/dependency-update-check.gradle.kts => gradle/plugins/src/main/kotlin/junitbuild.dependency-update-check.gradle.kts (100%) rename buildSrc/src/main/kotlin/jacoco-aggregation-conventions.gradle.kts => gradle/plugins/src/main/kotlin/junitbuild.jacoco-aggregation-conventions.gradle.kts (90%) rename buildSrc/src/main/kotlin/jacoco-conventions.gradle.kts => gradle/plugins/src/main/kotlin/junitbuild.jacoco-conventions.gradle.kts (100%) rename buildSrc/src/main/kotlin/jacoco-java-conventions.gradle.kts => gradle/plugins/src/main/kotlin/junitbuild.jacoco-java-conventions.gradle.kts (95%) rename buildSrc/src/main/kotlin/java-library-conventions.gradle.kts => gradle/plugins/src/main/kotlin/junitbuild.java-library-conventions.gradle.kts (96%) rename buildSrc/src/main/kotlin/java-multi-release-sources.gradle.kts => gradle/plugins/src/main/kotlin/junitbuild.java-multi-release-sources.gradle.kts (96%) rename buildSrc/src/main/kotlin/java-repackage-jars.gradle.kts => gradle/plugins/src/main/kotlin/junitbuild.java-repackage-jars.gradle.kts (100%) rename buildSrc/src/main/kotlin/java-toolchain-conventions.gradle.kts => gradle/plugins/src/main/kotlin/junitbuild.java-toolchain-conventions.gradle.kts (100%) rename buildSrc/src/main/kotlin/junit4-compatibility.gradle.kts => gradle/plugins/src/main/kotlin/junitbuild.junit4-compatibility.gradle.kts (90%) rename buildSrc/src/main/kotlin/kotlin-library-conventions.gradle.kts => gradle/plugins/src/main/kotlin/junitbuild.kotlin-library-conventions.gradle.kts (92%) rename buildSrc/src/main/kotlin/osgi-conventions.gradle.kts => gradle/plugins/src/main/kotlin/junitbuild.osgi-conventions.gradle.kts (100%) rename buildSrc/src/main/kotlin/publishing-conventions.gradle.kts => gradle/plugins/src/main/kotlin/junitbuild.publishing-conventions.gradle.kts (98%) rename buildSrc/src/main/kotlin/shadow-conventions.gradle.kts => gradle/plugins/src/main/kotlin/junitbuild.shadow-conventions.gradle.kts (96%) rename buildSrc/src/main/kotlin/spotless-conventions.gradle.kts => gradle/plugins/src/main/kotlin/junitbuild.spotless-conventions.gradle.kts (100%) rename buildSrc/src/main/kotlin/temp-maven-repo.gradle.kts => gradle/plugins/src/main/kotlin/junitbuild.temp-maven-repo.gradle.kts (100%) rename buildSrc/src/main/kotlin/testing-conventions.gradle.kts => gradle/plugins/src/main/kotlin/junitbuild.testing-conventions.gradle.kts (100%) rename {buildSrc/src/main/kotlin/org/junit/gradle => gradle/plugins/src/main/kotlin/junitbuild}/exec/ClasspathSystemPropertyProvider.kt (92%) rename {buildSrc/src/main/kotlin/org/junit/gradle => gradle/plugins/src/main/kotlin/junitbuild}/exec/RunConsoleLauncher.kt (98%) rename {buildSrc/src/main/kotlin/org/junit/gradle => gradle/plugins/src/main/kotlin/junitbuild}/java/ExecJarAction.kt (96%) rename {buildSrc/src/main/kotlin/org/junit/gradle => gradle/plugins/src/main/kotlin/junitbuild}/java/ModulePathArgumentProvider.kt (97%) rename {buildSrc/src/main/kotlin/org/junit/gradle => gradle/plugins/src/main/kotlin/junitbuild}/java/PatchModuleArgumentProvider.kt (98%) rename {buildSrc/src/main/kotlin/org/junit/gradle => gradle/plugins/src/main/kotlin/junitbuild}/java/WriteArtifactsFile.kt (97%) rename {buildSrc/src/main/kotlin/org/junit/gradle => gradle/plugins/src/main/kotlin/junitbuild}/javadoc/ModuleSpecificJavadocFileOption.kt (96%) diff --git a/.gitignore b/.gitignore index e5f0af67bde0..6d276115b4be 100644 --- a/.gitignore +++ b/.gitignore @@ -1,7 +1,6 @@ # Gradle .gradle -/build/ -/*/build/ +build # Ignore Gradle GUI config gradle-app.setting diff --git a/build.gradle.kts b/build.gradle.kts index 5379f61f82be..0fc9203523f2 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -1,11 +1,11 @@ plugins { id("io.spring.nohttp") id("io.github.gradle-nexus.publish-plugin") - `base-conventions` - `build-metadata` - `dependency-update-check` - `jacoco-aggregation-conventions` - `temp-maven-repo` + id("junitbuild.base-conventions") + id("junitbuild.build-metadata") + id("junitbuild.dependency-update-check") + id("junitbuild.jacoco-aggregation-conventions") + id("junitbuild.temp-maven-repo") } description = "JUnit 5" @@ -61,5 +61,5 @@ nexusPublishing { } nohttp { - source.exclude("buildSrc/build/generated-sources/**") + source.exclude("**/.gradle/**", "gradle/plugins/build/generated-sources/**") } diff --git a/buildSrc/settings.gradle.kts b/buildSrc/settings.gradle.kts deleted file mode 100644 index 29744ec1bcde..000000000000 --- a/buildSrc/settings.gradle.kts +++ /dev/null @@ -1 +0,0 @@ -rootProject.name = "buildSrc" diff --git a/buildSrc/src/main/kotlin/base-conventions.gradle.kts b/buildSrc/src/main/kotlin/base-conventions.gradle.kts deleted file mode 100644 index 0c4c4c5f7a29..000000000000 --- a/buildSrc/src/main/kotlin/base-conventions.gradle.kts +++ /dev/null @@ -1,6 +0,0 @@ -plugins { - eclipse - idea - id("java-toolchain-conventions") - id("spotless-conventions") -} diff --git a/documentation/documentation.gradle.kts b/documentation/documentation.gradle.kts index 760c6c3d00d6..a357d9f2d421 100644 --- a/documentation/documentation.gradle.kts +++ b/documentation/documentation.gradle.kts @@ -2,9 +2,9 @@ import org.asciidoctor.gradle.base.AsciidoctorAttributeProvider import org.asciidoctor.gradle.jvm.AbstractAsciidoctorTask import org.gradle.api.tasks.PathSensitivity.RELATIVE import org.jetbrains.kotlin.gradle.plugin.KotlinSourceSet -import org.junit.gradle.exec.ClasspathSystemPropertyProvider -import org.junit.gradle.exec.RunConsoleLauncher -import org.junit.gradle.javadoc.ModuleSpecificJavadocFileOption +import junitbuild.exec.ClasspathSystemPropertyProvider +import junitbuild.exec.RunConsoleLauncher +import junitbuild.javadoc.ModuleSpecificJavadocFileOption import java.io.ByteArrayOutputStream import java.nio.file.Files @@ -12,7 +12,7 @@ plugins { id("org.asciidoctor.jvm.convert") id("org.asciidoctor.jvm.pdf") id("org.ajoberstar.git-publish") - `kotlin-library-conventions` + id("junitbuild.kotlin-library-conventions") } val modularProjects: List by rootProject diff --git a/buildSrc/build.gradle.kts b/gradle/plugins/build.gradle.kts similarity index 94% rename from buildSrc/build.gradle.kts rename to gradle/plugins/build.gradle.kts index 4ffac612a5b4..5afee3e2d70d 100644 --- a/buildSrc/build.gradle.kts +++ b/gradle/plugins/build.gradle.kts @@ -20,11 +20,11 @@ dependencies { tasks { withType().configureEach { - options.release.set(8) + options.release.set(11) } withType().configureEach { kotlinOptions { - jvmTarget = "1.8" + jvmTarget = "11" allWarningsAsErrors = true } } diff --git a/gradle/plugins/settings.gradle.kts b/gradle/plugins/settings.gradle.kts new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/buildSrc/src/main/kotlin/JavaLibraryExtension.kt b/gradle/plugins/src/main/kotlin/JavaLibraryExtension.kt similarity index 100% rename from buildSrc/src/main/kotlin/JavaLibraryExtension.kt rename to gradle/plugins/src/main/kotlin/JavaLibraryExtension.kt diff --git a/buildSrc/src/main/kotlin/License.kt b/gradle/plugins/src/main/kotlin/License.kt similarity index 100% rename from buildSrc/src/main/kotlin/License.kt rename to gradle/plugins/src/main/kotlin/License.kt diff --git a/buildSrc/src/main/kotlin/ProjectExtensions.kt b/gradle/plugins/src/main/kotlin/ProjectExtensions.kt similarity index 100% rename from buildSrc/src/main/kotlin/ProjectExtensions.kt rename to gradle/plugins/src/main/kotlin/ProjectExtensions.kt diff --git a/buildSrc/src/main/kotlin/TaskExtensions.kt b/gradle/plugins/src/main/kotlin/TaskExtensions.kt similarity index 100% rename from buildSrc/src/main/kotlin/TaskExtensions.kt rename to gradle/plugins/src/main/kotlin/TaskExtensions.kt diff --git a/gradle/plugins/src/main/kotlin/junitbuild.base-conventions.gradle.kts b/gradle/plugins/src/main/kotlin/junitbuild.base-conventions.gradle.kts new file mode 100644 index 000000000000..4bd5a4660201 --- /dev/null +++ b/gradle/plugins/src/main/kotlin/junitbuild.base-conventions.gradle.kts @@ -0,0 +1,6 @@ +plugins { + eclipse + idea + id("junitbuild.java-toolchain-conventions") + id("junitbuild.spotless-conventions") +} diff --git a/buildSrc/src/main/kotlin/build-metadata.gradle.kts b/gradle/plugins/src/main/kotlin/junitbuild.build-metadata.gradle.kts similarity index 100% rename from buildSrc/src/main/kotlin/build-metadata.gradle.kts rename to gradle/plugins/src/main/kotlin/junitbuild.build-metadata.gradle.kts diff --git a/buildSrc/src/main/kotlin/dependency-update-check.gradle.kts b/gradle/plugins/src/main/kotlin/junitbuild.dependency-update-check.gradle.kts similarity index 100% rename from buildSrc/src/main/kotlin/dependency-update-check.gradle.kts rename to gradle/plugins/src/main/kotlin/junitbuild.dependency-update-check.gradle.kts diff --git a/buildSrc/src/main/kotlin/jacoco-aggregation-conventions.gradle.kts b/gradle/plugins/src/main/kotlin/junitbuild.jacoco-aggregation-conventions.gradle.kts similarity index 90% rename from buildSrc/src/main/kotlin/jacoco-aggregation-conventions.gradle.kts rename to gradle/plugins/src/main/kotlin/junitbuild.jacoco-aggregation-conventions.gradle.kts index cd32b2d65517..e611a9f622d1 100644 --- a/buildSrc/src/main/kotlin/jacoco-aggregation-conventions.gradle.kts +++ b/gradle/plugins/src/main/kotlin/junitbuild.jacoco-aggregation-conventions.gradle.kts @@ -4,7 +4,7 @@ import org.gradle.kotlin.dsl.`jacoco-report-aggregation` import org.gradle.testing.jacoco.plugins.JacocoCoverageReport plugins { - id("jacoco-conventions") + id("junitbuild.jacoco-conventions") `jacoco-report-aggregation` } diff --git a/buildSrc/src/main/kotlin/jacoco-conventions.gradle.kts b/gradle/plugins/src/main/kotlin/junitbuild.jacoco-conventions.gradle.kts similarity index 100% rename from buildSrc/src/main/kotlin/jacoco-conventions.gradle.kts rename to gradle/plugins/src/main/kotlin/junitbuild.jacoco-conventions.gradle.kts diff --git a/buildSrc/src/main/kotlin/jacoco-java-conventions.gradle.kts b/gradle/plugins/src/main/kotlin/junitbuild.jacoco-java-conventions.gradle.kts similarity index 95% rename from buildSrc/src/main/kotlin/jacoco-java-conventions.gradle.kts rename to gradle/plugins/src/main/kotlin/junitbuild.jacoco-java-conventions.gradle.kts index 265ff8937069..42f7c754fd4e 100644 --- a/buildSrc/src/main/kotlin/jacoco-java-conventions.gradle.kts +++ b/gradle/plugins/src/main/kotlin/junitbuild.jacoco-java-conventions.gradle.kts @@ -3,7 +3,7 @@ import org.gradle.api.attributes.LibraryElements.LIBRARY_ELEMENTS_ATTRIBUTE plugins { java - id("jacoco-conventions") + id("junitbuild.jacoco-conventions") } val mavenizedProjects: List by rootProject.extra diff --git a/buildSrc/src/main/kotlin/java-library-conventions.gradle.kts b/gradle/plugins/src/main/kotlin/junitbuild.java-library-conventions.gradle.kts similarity index 96% rename from buildSrc/src/main/kotlin/java-library-conventions.gradle.kts rename to gradle/plugins/src/main/kotlin/junitbuild.java-library-conventions.gradle.kts index e2df86c8984f..bb586e37605c 100644 --- a/buildSrc/src/main/kotlin/java-library-conventions.gradle.kts +++ b/gradle/plugins/src/main/kotlin/junitbuild.java-library-conventions.gradle.kts @@ -1,14 +1,14 @@ import com.github.jengelman.gradle.plugins.shadow.tasks.ShadowJar -import org.junit.gradle.java.ModulePathArgumentProvider -import org.junit.gradle.java.PatchModuleArgumentProvider +import junitbuild.java.ModulePathArgumentProvider +import junitbuild.java.PatchModuleArgumentProvider plugins { `java-library` eclipse idea checkstyle - id("base-conventions") - id("jacoco-java-conventions") + id("junitbuild.base-conventions") + id("junitbuild.jacoco-java-conventions") } val mavenizedProjects: List by rootProject.extra @@ -42,8 +42,8 @@ java { if (project in mavenizedProjects) { - apply(plugin = "publishing-conventions") - apply(plugin = "osgi-conventions") + apply(plugin = "junitbuild.publishing-conventions") + apply(plugin = "junitbuild.osgi-conventions") java { withJavadocJar() diff --git a/buildSrc/src/main/kotlin/java-multi-release-sources.gradle.kts b/gradle/plugins/src/main/kotlin/junitbuild.java-multi-release-sources.gradle.kts similarity index 96% rename from buildSrc/src/main/kotlin/java-multi-release-sources.gradle.kts rename to gradle/plugins/src/main/kotlin/junitbuild.java-multi-release-sources.gradle.kts index fb71c3e95003..7f2af9d50e7e 100644 --- a/buildSrc/src/main/kotlin/java-multi-release-sources.gradle.kts +++ b/gradle/plugins/src/main/kotlin/junitbuild.java-multi-release-sources.gradle.kts @@ -1,5 +1,5 @@ plugins { - id("java-library-conventions") + id("junitbuild.java-library-conventions") } val mavenizedProjects: List by rootProject.extra diff --git a/buildSrc/src/main/kotlin/java-repackage-jars.gradle.kts b/gradle/plugins/src/main/kotlin/junitbuild.java-repackage-jars.gradle.kts similarity index 100% rename from buildSrc/src/main/kotlin/java-repackage-jars.gradle.kts rename to gradle/plugins/src/main/kotlin/junitbuild.java-repackage-jars.gradle.kts diff --git a/buildSrc/src/main/kotlin/java-toolchain-conventions.gradle.kts b/gradle/plugins/src/main/kotlin/junitbuild.java-toolchain-conventions.gradle.kts similarity index 100% rename from buildSrc/src/main/kotlin/java-toolchain-conventions.gradle.kts rename to gradle/plugins/src/main/kotlin/junitbuild.java-toolchain-conventions.gradle.kts diff --git a/buildSrc/src/main/kotlin/junit4-compatibility.gradle.kts b/gradle/plugins/src/main/kotlin/junitbuild.junit4-compatibility.gradle.kts similarity index 90% rename from buildSrc/src/main/kotlin/junit4-compatibility.gradle.kts rename to gradle/plugins/src/main/kotlin/junitbuild.junit4-compatibility.gradle.kts index 89ca169b699e..e43c938e5ca4 100644 --- a/buildSrc/src/main/kotlin/junit4-compatibility.gradle.kts +++ b/gradle/plugins/src/main/kotlin/junitbuild.junit4-compatibility.gradle.kts @@ -12,7 +12,7 @@ dependencies { strictly("4.12") } } - pluginManager.withPlugin("osgi-conventions") { + pluginManager.withPlugin("junitbuild.osgi-conventions") { val junit4Osgi = requiredVersionFromLibs("junit4Osgi") "osgiVerification"("org.apache.servicemix.bundles:org.apache.servicemix.bundles.junit:${junit4Osgi}") } diff --git a/buildSrc/src/main/kotlin/kotlin-library-conventions.gradle.kts b/gradle/plugins/src/main/kotlin/junitbuild.kotlin-library-conventions.gradle.kts similarity index 92% rename from buildSrc/src/main/kotlin/kotlin-library-conventions.gradle.kts rename to gradle/plugins/src/main/kotlin/junitbuild.kotlin-library-conventions.gradle.kts index 163190944bae..bfb33224a709 100644 --- a/buildSrc/src/main/kotlin/kotlin-library-conventions.gradle.kts +++ b/gradle/plugins/src/main/kotlin/junitbuild.kotlin-library-conventions.gradle.kts @@ -1,7 +1,7 @@ import org.jetbrains.kotlin.gradle.tasks.KotlinCompile plugins { - id("java-library-conventions") + id("junitbuild.java-library-conventions") kotlin("jvm") } diff --git a/buildSrc/src/main/kotlin/osgi-conventions.gradle.kts b/gradle/plugins/src/main/kotlin/junitbuild.osgi-conventions.gradle.kts similarity index 100% rename from buildSrc/src/main/kotlin/osgi-conventions.gradle.kts rename to gradle/plugins/src/main/kotlin/junitbuild.osgi-conventions.gradle.kts diff --git a/buildSrc/src/main/kotlin/publishing-conventions.gradle.kts b/gradle/plugins/src/main/kotlin/junitbuild.publishing-conventions.gradle.kts similarity index 98% rename from buildSrc/src/main/kotlin/publishing-conventions.gradle.kts rename to gradle/plugins/src/main/kotlin/junitbuild.publishing-conventions.gradle.kts index c4e28d5bb3a9..7f8b617b3084 100644 --- a/buildSrc/src/main/kotlin/publishing-conventions.gradle.kts +++ b/gradle/plugins/src/main/kotlin/junitbuild.publishing-conventions.gradle.kts @@ -1,7 +1,7 @@ plugins { `maven-publish` signing - id("base-conventions") + id("junitbuild.base-conventions") } val isSnapshot = project.version.toString().contains("SNAPSHOT") diff --git a/buildSrc/src/main/kotlin/shadow-conventions.gradle.kts b/gradle/plugins/src/main/kotlin/junitbuild.shadow-conventions.gradle.kts similarity index 96% rename from buildSrc/src/main/kotlin/shadow-conventions.gradle.kts rename to gradle/plugins/src/main/kotlin/junitbuild.shadow-conventions.gradle.kts index 19028422c41e..d9f93aa3839d 100644 --- a/buildSrc/src/main/kotlin/shadow-conventions.gradle.kts +++ b/gradle/plugins/src/main/kotlin/junitbuild.shadow-conventions.gradle.kts @@ -1,5 +1,5 @@ plugins { - id("java-library-conventions") + id("junitbuild.java-library-conventions") id("com.github.johnrengelman.shadow") } diff --git a/buildSrc/src/main/kotlin/spotless-conventions.gradle.kts b/gradle/plugins/src/main/kotlin/junitbuild.spotless-conventions.gradle.kts similarity index 100% rename from buildSrc/src/main/kotlin/spotless-conventions.gradle.kts rename to gradle/plugins/src/main/kotlin/junitbuild.spotless-conventions.gradle.kts diff --git a/buildSrc/src/main/kotlin/temp-maven-repo.gradle.kts b/gradle/plugins/src/main/kotlin/junitbuild.temp-maven-repo.gradle.kts similarity index 100% rename from buildSrc/src/main/kotlin/temp-maven-repo.gradle.kts rename to gradle/plugins/src/main/kotlin/junitbuild.temp-maven-repo.gradle.kts diff --git a/buildSrc/src/main/kotlin/testing-conventions.gradle.kts b/gradle/plugins/src/main/kotlin/junitbuild.testing-conventions.gradle.kts similarity index 100% rename from buildSrc/src/main/kotlin/testing-conventions.gradle.kts rename to gradle/plugins/src/main/kotlin/junitbuild.testing-conventions.gradle.kts diff --git a/buildSrc/src/main/kotlin/org/junit/gradle/exec/ClasspathSystemPropertyProvider.kt b/gradle/plugins/src/main/kotlin/junitbuild/exec/ClasspathSystemPropertyProvider.kt similarity index 92% rename from buildSrc/src/main/kotlin/org/junit/gradle/exec/ClasspathSystemPropertyProvider.kt rename to gradle/plugins/src/main/kotlin/junitbuild/exec/ClasspathSystemPropertyProvider.kt index 9c6423dca171..2faeb2acaeef 100644 --- a/buildSrc/src/main/kotlin/org/junit/gradle/exec/ClasspathSystemPropertyProvider.kt +++ b/gradle/plugins/src/main/kotlin/junitbuild/exec/ClasspathSystemPropertyProvider.kt @@ -1,4 +1,4 @@ -package org.junit.gradle.exec +package junitbuild.exec import org.gradle.api.file.FileCollection import org.gradle.api.tasks.Classpath diff --git a/buildSrc/src/main/kotlin/org/junit/gradle/exec/RunConsoleLauncher.kt b/gradle/plugins/src/main/kotlin/junitbuild/exec/RunConsoleLauncher.kt similarity index 98% rename from buildSrc/src/main/kotlin/org/junit/gradle/exec/RunConsoleLauncher.kt rename to gradle/plugins/src/main/kotlin/junitbuild/exec/RunConsoleLauncher.kt index 88889bcfbb1f..4ba265061662 100644 --- a/buildSrc/src/main/kotlin/org/junit/gradle/exec/RunConsoleLauncher.kt +++ b/gradle/plugins/src/main/kotlin/junitbuild/exec/RunConsoleLauncher.kt @@ -1,4 +1,4 @@ -package org.junit.gradle.exec +package junitbuild.exec import org.gradle.api.DefaultTask import org.gradle.api.file.ConfigurableFileCollection diff --git a/buildSrc/src/main/kotlin/org/junit/gradle/java/ExecJarAction.kt b/gradle/plugins/src/main/kotlin/junitbuild/java/ExecJarAction.kt similarity index 96% rename from buildSrc/src/main/kotlin/org/junit/gradle/java/ExecJarAction.kt rename to gradle/plugins/src/main/kotlin/junitbuild/java/ExecJarAction.kt index afc97f404fcc..a900b9c646c3 100644 --- a/buildSrc/src/main/kotlin/org/junit/gradle/java/ExecJarAction.kt +++ b/gradle/plugins/src/main/kotlin/junitbuild/java/ExecJarAction.kt @@ -1,4 +1,4 @@ -package org.junit.gradle.java +package junitbuild.java import org.gradle.api.Action import org.gradle.api.Task diff --git a/buildSrc/src/main/kotlin/org/junit/gradle/java/ModulePathArgumentProvider.kt b/gradle/plugins/src/main/kotlin/junitbuild/java/ModulePathArgumentProvider.kt similarity index 97% rename from buildSrc/src/main/kotlin/org/junit/gradle/java/ModulePathArgumentProvider.kt rename to gradle/plugins/src/main/kotlin/junitbuild/java/ModulePathArgumentProvider.kt index adb478c42f82..3133c35a2ead 100644 --- a/buildSrc/src/main/kotlin/org/junit/gradle/java/ModulePathArgumentProvider.kt +++ b/gradle/plugins/src/main/kotlin/junitbuild/java/ModulePathArgumentProvider.kt @@ -1,4 +1,4 @@ -package org.junit.gradle.java +package junitbuild.java import org.gradle.api.Named import org.gradle.api.Project diff --git a/buildSrc/src/main/kotlin/org/junit/gradle/java/PatchModuleArgumentProvider.kt b/gradle/plugins/src/main/kotlin/junitbuild/java/PatchModuleArgumentProvider.kt similarity index 98% rename from buildSrc/src/main/kotlin/org/junit/gradle/java/PatchModuleArgumentProvider.kt rename to gradle/plugins/src/main/kotlin/junitbuild/java/PatchModuleArgumentProvider.kt index f13fd8b9a83b..93210bfc41a7 100644 --- a/buildSrc/src/main/kotlin/org/junit/gradle/java/PatchModuleArgumentProvider.kt +++ b/gradle/plugins/src/main/kotlin/junitbuild/java/PatchModuleArgumentProvider.kt @@ -1,4 +1,4 @@ -package org.junit.gradle.java +package junitbuild.java import javaModuleName import org.gradle.api.Named diff --git a/buildSrc/src/main/kotlin/org/junit/gradle/java/WriteArtifactsFile.kt b/gradle/plugins/src/main/kotlin/junitbuild/java/WriteArtifactsFile.kt similarity index 97% rename from buildSrc/src/main/kotlin/org/junit/gradle/java/WriteArtifactsFile.kt rename to gradle/plugins/src/main/kotlin/junitbuild/java/WriteArtifactsFile.kt index 12107fc8f824..d0b56930cf08 100644 --- a/buildSrc/src/main/kotlin/org/junit/gradle/java/WriteArtifactsFile.kt +++ b/gradle/plugins/src/main/kotlin/junitbuild/java/WriteArtifactsFile.kt @@ -1,4 +1,4 @@ -package org.junit.gradle.java +package junitbuild.java import org.gradle.api.DefaultTask import org.gradle.api.artifacts.Configuration diff --git a/buildSrc/src/main/kotlin/org/junit/gradle/javadoc/ModuleSpecificJavadocFileOption.kt b/gradle/plugins/src/main/kotlin/junitbuild/javadoc/ModuleSpecificJavadocFileOption.kt similarity index 96% rename from buildSrc/src/main/kotlin/org/junit/gradle/javadoc/ModuleSpecificJavadocFileOption.kt rename to gradle/plugins/src/main/kotlin/junitbuild/javadoc/ModuleSpecificJavadocFileOption.kt index e9391b22d1b8..f4c6f124b65e 100644 --- a/buildSrc/src/main/kotlin/org/junit/gradle/javadoc/ModuleSpecificJavadocFileOption.kt +++ b/gradle/plugins/src/main/kotlin/junitbuild/javadoc/ModuleSpecificJavadocFileOption.kt @@ -1,4 +1,4 @@ -package org.junit.gradle.javadoc +package junitbuild.javadoc import org.gradle.external.javadoc.JavadocOptionFileOption import org.gradle.external.javadoc.internal.JavadocOptionFileWriterContext diff --git a/junit-bom/junit-bom.gradle.kts b/junit-bom/junit-bom.gradle.kts index fae23ee37eab..485bb50d2ea3 100644 --- a/junit-bom/junit-bom.gradle.kts +++ b/junit-bom/junit-bom.gradle.kts @@ -1,6 +1,6 @@ plugins { `java-platform` - `publishing-conventions` + id("junitbuild.publishing-conventions") } description = "${rootProject.description} (Bill of Materials)" diff --git a/junit-jupiter-api/junit-jupiter-api.gradle.kts b/junit-jupiter-api/junit-jupiter-api.gradle.kts index d28dec7bf358..e4f2869ae39f 100644 --- a/junit-jupiter-api/junit-jupiter-api.gradle.kts +++ b/junit-jupiter-api/junit-jupiter-api.gradle.kts @@ -1,5 +1,5 @@ plugins { - `kotlin-library-conventions` + id("junitbuild.kotlin-library-conventions") `java-test-fixtures` } diff --git a/junit-jupiter-engine/junit-jupiter-engine.gradle.kts b/junit-jupiter-engine/junit-jupiter-engine.gradle.kts index e15a42bf136e..7ce27bcf32e7 100644 --- a/junit-jupiter-engine/junit-jupiter-engine.gradle.kts +++ b/junit-jupiter-engine/junit-jupiter-engine.gradle.kts @@ -1,8 +1,8 @@ import org.gradle.api.tasks.PathSensitivity.RELATIVE plugins { - `kotlin-library-conventions` - `testing-conventions` + id("junitbuild.kotlin-library-conventions") + id("junitbuild.testing-conventions") groovy `java-test-fixtures` } diff --git a/junit-jupiter-migrationsupport/junit-jupiter-migrationsupport.gradle.kts b/junit-jupiter-migrationsupport/junit-jupiter-migrationsupport.gradle.kts index ff570cc7c87c..e9b8e0c049fd 100644 --- a/junit-jupiter-migrationsupport/junit-jupiter-migrationsupport.gradle.kts +++ b/junit-jupiter-migrationsupport/junit-jupiter-migrationsupport.gradle.kts @@ -1,7 +1,7 @@ plugins { - `java-library-conventions` - `junit4-compatibility` - `testing-conventions` + id("junitbuild.java-library-conventions") + id("junitbuild.junit4-compatibility") + id("junitbuild.testing-conventions") } description = "JUnit Jupiter Migration Support" diff --git a/junit-jupiter-params/junit-jupiter-params.gradle.kts b/junit-jupiter-params/junit-jupiter-params.gradle.kts index 528ef09c7435..44e065e118ed 100644 --- a/junit-jupiter-params/junit-jupiter-params.gradle.kts +++ b/junit-jupiter-params/junit-jupiter-params.gradle.kts @@ -1,7 +1,7 @@ plugins { - `kotlin-library-conventions` - `shadow-conventions` - `testing-conventions` + id("junitbuild.kotlin-library-conventions") + id("junitbuild.shadow-conventions") + id("junitbuild.testing-conventions") } description = "JUnit Jupiter Params" diff --git a/junit-jupiter/junit-jupiter.gradle.kts b/junit-jupiter/junit-jupiter.gradle.kts index 181698f09437..83230d0b4226 100644 --- a/junit-jupiter/junit-jupiter.gradle.kts +++ b/junit-jupiter/junit-jupiter.gradle.kts @@ -1,5 +1,5 @@ plugins { - `java-library-conventions` + id("junitbuild.java-library-conventions") } description = "JUnit Jupiter (Aggregator)" diff --git a/junit-platform-commons/junit-platform-commons.gradle.kts b/junit-platform-commons/junit-platform-commons.gradle.kts index 393d655e86d7..3ffc32815fb2 100644 --- a/junit-platform-commons/junit-platform-commons.gradle.kts +++ b/junit-platform-commons/junit-platform-commons.gradle.kts @@ -1,9 +1,9 @@ -import org.junit.gradle.java.ExecJarAction +import junitbuild.java.ExecJarAction plugins { - `java-library-conventions` - `java-multi-release-sources` - `java-repackage-jars` + id("junitbuild.java-library-conventions") + id("junitbuild.java-multi-release-sources") + id("junitbuild.java-repackage-jars") `java-test-fixtures` } diff --git a/junit-platform-console-standalone/junit-platform-console-standalone.gradle.kts b/junit-platform-console-standalone/junit-platform-console-standalone.gradle.kts index 6a42539e5a98..61d35dedab17 100644 --- a/junit-platform-console-standalone/junit-platform-console-standalone.gradle.kts +++ b/junit-platform-console-standalone/junit-platform-console-standalone.gradle.kts @@ -1,8 +1,8 @@ -import org.junit.gradle.java.WriteArtifactsFile +import junitbuild.java.WriteArtifactsFile plugins { - `java-library-conventions` - `shadow-conventions` + id("junitbuild.java-library-conventions") + id("junitbuild.shadow-conventions") } description = "JUnit Platform Console Standalone" diff --git a/junit-platform-console/junit-platform-console.gradle.kts b/junit-platform-console/junit-platform-console.gradle.kts index 6006a8c880af..d7bec605761e 100644 --- a/junit-platform-console/junit-platform-console.gradle.kts +++ b/junit-platform-console/junit-platform-console.gradle.kts @@ -1,8 +1,8 @@ plugins { - `java-library-conventions` - `shadow-conventions` - `java-multi-release-sources` - `java-repackage-jars` + id("junitbuild.java-library-conventions") + id("junitbuild.shadow-conventions") + id("junitbuild.java-multi-release-sources") + id("junitbuild.java-repackage-jars") } description = "JUnit Platform Console" @@ -38,7 +38,7 @@ tasks { into("META-INF") } from(sourceSets.mainRelease9.get().output.classesDirs) - doLast(objects.newInstance(org.junit.gradle.java.ExecJarAction::class).apply { + doLast(objects.newInstance(junitbuild.java.ExecJarAction::class).apply { javaLauncher.set(project.javaToolchains.launcherFor(java.toolchain)) args.addAll( "--update", diff --git a/junit-platform-engine/junit-platform-engine.gradle.kts b/junit-platform-engine/junit-platform-engine.gradle.kts index 6c780cea7658..416b227b00c1 100644 --- a/junit-platform-engine/junit-platform-engine.gradle.kts +++ b/junit-platform-engine/junit-platform-engine.gradle.kts @@ -1,5 +1,5 @@ plugins { - `java-library-conventions` + id("junitbuild.java-library-conventions") `java-test-fixtures` } diff --git a/junit-platform-jfr/junit-platform-jfr.gradle.kts b/junit-platform-jfr/junit-platform-jfr.gradle.kts index 00198d86a540..c0df2b512652 100644 --- a/junit-platform-jfr/junit-platform-jfr.gradle.kts +++ b/junit-platform-jfr/junit-platform-jfr.gradle.kts @@ -1,5 +1,5 @@ plugins { - `java-library-conventions` + id("junitbuild.java-library-conventions") } description = "JUnit Platform Flight Recorder Support" diff --git a/junit-platform-launcher/junit-platform-launcher.gradle.kts b/junit-platform-launcher/junit-platform-launcher.gradle.kts index d51d0df34677..228ecb35b734 100644 --- a/junit-platform-launcher/junit-platform-launcher.gradle.kts +++ b/junit-platform-launcher/junit-platform-launcher.gradle.kts @@ -1,5 +1,5 @@ plugins { - `java-library-conventions` + id("junitbuild.java-library-conventions") `java-test-fixtures` } diff --git a/junit-platform-reporting/junit-platform-reporting.gradle.kts b/junit-platform-reporting/junit-platform-reporting.gradle.kts index 144c3fbe5bbc..84eb0fa0f75c 100644 --- a/junit-platform-reporting/junit-platform-reporting.gradle.kts +++ b/junit-platform-reporting/junit-platform-reporting.gradle.kts @@ -1,6 +1,6 @@ plugins { - `java-library-conventions` - `shadow-conventions` + id("junitbuild.java-library-conventions") + id("junitbuild.shadow-conventions") } description = "JUnit Platform Reporting" diff --git a/junit-platform-runner/junit-platform-runner.gradle.kts b/junit-platform-runner/junit-platform-runner.gradle.kts index 78205ecebbed..c62d027f6c67 100644 --- a/junit-platform-runner/junit-platform-runner.gradle.kts +++ b/junit-platform-runner/junit-platform-runner.gradle.kts @@ -1,6 +1,6 @@ plugins { - `java-library-conventions` - `junit4-compatibility` + id("junitbuild.java-library-conventions") + id("junitbuild.junit4-compatibility") } description = "JUnit Platform Runner" diff --git a/junit-platform-suite-api/junit-platform-suite-api.gradle.kts b/junit-platform-suite-api/junit-platform-suite-api.gradle.kts index 7be1b0a2a9ce..cc5eb1d08bb7 100644 --- a/junit-platform-suite-api/junit-platform-suite-api.gradle.kts +++ b/junit-platform-suite-api/junit-platform-suite-api.gradle.kts @@ -1,5 +1,5 @@ plugins { - `java-library-conventions` + id("junitbuild.java-library-conventions") } description = "JUnit Platform Suite API" diff --git a/junit-platform-suite-commons/junit-platform-suite-commons.gradle.kts b/junit-platform-suite-commons/junit-platform-suite-commons.gradle.kts index 8f578b0b9c30..f65b677db193 100644 --- a/junit-platform-suite-commons/junit-platform-suite-commons.gradle.kts +++ b/junit-platform-suite-commons/junit-platform-suite-commons.gradle.kts @@ -1,5 +1,5 @@ plugins { - `java-library-conventions` + id("junitbuild.java-library-conventions") } description = "JUnit Platform Suite Commons" diff --git a/junit-platform-suite-engine/junit-platform-suite-engine.gradle.kts b/junit-platform-suite-engine/junit-platform-suite-engine.gradle.kts index 12e7f6746752..36abcdbc088d 100644 --- a/junit-platform-suite-engine/junit-platform-suite-engine.gradle.kts +++ b/junit-platform-suite-engine/junit-platform-suite-engine.gradle.kts @@ -1,5 +1,5 @@ plugins { - `java-library-conventions` + id("junitbuild.java-library-conventions") } description = "JUnit Platform Suite Engine" diff --git a/junit-platform-suite/junit-platform-suite.gradle.kts b/junit-platform-suite/junit-platform-suite.gradle.kts index 8615483d2723..83e475a2a689 100644 --- a/junit-platform-suite/junit-platform-suite.gradle.kts +++ b/junit-platform-suite/junit-platform-suite.gradle.kts @@ -1,5 +1,5 @@ plugins { - `java-library-conventions` + id("junitbuild.java-library-conventions") } description = "JUnit Platform Suite (Aggregator)" diff --git a/junit-platform-testkit/junit-platform-testkit.gradle.kts b/junit-platform-testkit/junit-platform-testkit.gradle.kts index 6a574bcf3882..38e89344db34 100644 --- a/junit-platform-testkit/junit-platform-testkit.gradle.kts +++ b/junit-platform-testkit/junit-platform-testkit.gradle.kts @@ -1,5 +1,5 @@ plugins { - `java-library-conventions` + id("junitbuild.java-library-conventions") } description = "JUnit Platform Test Kit" diff --git a/junit-vintage-engine/junit-vintage-engine.gradle.kts b/junit-vintage-engine/junit-vintage-engine.gradle.kts index b92fffa50337..9f68f7de0475 100644 --- a/junit-vintage-engine/junit-vintage-engine.gradle.kts +++ b/junit-vintage-engine/junit-vintage-engine.gradle.kts @@ -1,7 +1,7 @@ plugins { - `java-library-conventions` - `junit4-compatibility` - `testing-conventions` + id("junitbuild.java-library-conventions") + id("junitbuild.junit4-compatibility") + id("junitbuild.testing-conventions") `java-test-fixtures` groovy } diff --git a/platform-tests/platform-tests.gradle.kts b/platform-tests/platform-tests.gradle.kts index cca78db6b588..7ec818dc927f 100644 --- a/platform-tests/platform-tests.gradle.kts +++ b/platform-tests/platform-tests.gradle.kts @@ -3,9 +3,9 @@ import org.gradle.api.tasks.PathSensitivity.RELATIVE import org.gradle.internal.os.OperatingSystem plugins { - `java-library-conventions` - `junit4-compatibility` - `testing-conventions` + id("junitbuild.java-library-conventions") + id("junitbuild.junit4-compatibility") + id("junitbuild.testing-conventions") id("me.champeau.jmh") } diff --git a/platform-tooling-support-tests/platform-tooling-support-tests.gradle.kts b/platform-tooling-support-tests/platform-tooling-support-tests.gradle.kts index f594af846257..61bec5e11ec0 100644 --- a/platform-tooling-support-tests/platform-tooling-support-tests.gradle.kts +++ b/platform-tooling-support-tests/platform-tooling-support-tests.gradle.kts @@ -2,8 +2,8 @@ import org.gradle.api.tasks.PathSensitivity.RELATIVE import org.gradle.jvm.toolchain.internal.NoToolchainAvailableException plugins { - `kotlin-library-conventions` - `testing-conventions` + id("junitbuild.kotlin-library-conventions") + id("junitbuild.testing-conventions") } javaLibrary { diff --git a/settings.gradle.kts b/settings.gradle.kts index 4270d9d8df17..96269d277097 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -2,6 +2,7 @@ import com.gradle.enterprise.gradleplugin.internal.extension.BuildScanExtensionW pluginManagement { repositories { + includeBuild("gradle/plugins") gradlePluginPortal() } plugins { From 0fe3447b642ad9a7116ba34f1e5e68fba6a37c52 Mon Sep 17 00:00:00 2001 From: Marc Philipp Date: Thu, 16 Feb 2023 17:51:06 +0100 Subject: [PATCH 0019/1473] Update comment after migrating buildSrc to included build --- settings.gradle.kts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/settings.gradle.kts b/settings.gradle.kts index 96269d277097..3418ab49c4f3 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -6,7 +6,7 @@ pluginManagement { gradlePluginPortal() } plugins { - id("com.gradle.enterprise") version "3.12.3" // keep in sync with buildSrc/build.gradle.kts + id("com.gradle.enterprise") version "3.12.3" // keep in sync with gradle/plugins/build.gradle.kts id("com.gradle.common-custom-user-data-gradle-plugin") version "1.8.2" id("org.gradle.toolchains.foojay-resolver-convention") version "0.4.0" id("org.ajoberstar.git-publish") version "4.1.1" From 944354971030ef7987aafeb38120d8df6b6bebb3 Mon Sep 17 00:00:00 2001 From: Marc Philipp Date: Fri, 17 Feb 2023 22:14:30 +0100 Subject: [PATCH 0020/1473] Upgradle to 8.0.1 --- gradle/wrapper/gradle-wrapper.properties | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index c9b0f7a0a4ec..f396aaac2d31 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,7 +1,7 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionSha256Sum=4159b938ec734a8388ce03f52aa8f3c7ed0d31f5438622545de4f83a89b79788 -distributionUrl=https\://services.gradle.org/distributions/gradle-8.0-bin.zip +distributionSha256Sum=1b6b558be93f29438d3df94b7dfee02e794b94d9aca4611a92cdb79b6b88e909 +distributionUrl=https\://services.gradle.org/distributions/gradle-8.0.1-bin.zip networkTimeout=10000 zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists From ba57321ed59d0c596facaf711499875a154c7be3 Mon Sep 17 00:00:00 2001 From: Marc Philipp Date: Sat, 18 Feb 2023 07:57:29 +0100 Subject: [PATCH 0021/1473] Move build-related config and scripts to gradle directory --- .github/workflows/main.yml | 2 +- .github/workflows/reproducible-build.yml | 2 +- CONTRIBUTING.md | 4 ++-- build.gradle.kts | 2 +- {src => gradle/config}/checkstyle/checkstyleMain.xml | 0 {src => gradle/config}/checkstyle/checkstyleTest.xml | 0 {src => gradle/config}/checkstyle/suppressions.xml | 0 .../config}/eclipse/junit-eclipse-formatter-settings.xml | 0 {src => gradle/config}/eclipse/junit-eclipse.importorder | 0 .../config}/spotless/eclipse-public-license-2.0.java | 0 gradle/plugins/src/main/kotlin/License.kt | 4 ++-- .../kotlin/junitbuild.java-library-conventions.gradle.kts | 8 ++++---- .../junitbuild.java-multi-release-sources.gradle.kts | 2 +- .../kotlin/junitbuild.spotless-conventions.gradle.kts | 8 +++----- {src => gradle/scripts}/checkBuildReproducibility.sh | 0 .../publishDocumentationSnapshotOnlyIfNecessary.sh | 0 platform-tests/platform-tests.gradle.kts | 2 +- 17 files changed, 16 insertions(+), 18 deletions(-) rename {src => gradle/config}/checkstyle/checkstyleMain.xml (100%) rename {src => gradle/config}/checkstyle/checkstyleTest.xml (100%) rename {src => gradle/config}/checkstyle/suppressions.xml (100%) rename {src => gradle/config}/eclipse/junit-eclipse-formatter-settings.xml (100%) rename {src => gradle/config}/eclipse/junit-eclipse.importorder (100%) rename {src => gradle/config}/spotless/eclipse-public-license-2.0.java (100%) rename {src => gradle/scripts}/checkBuildReproducibility.sh (100%) rename {src => gradle/scripts}/publishDocumentationSnapshotOnlyIfNecessary.sh (100%) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index f66220f261d1..25b8e9db7f72 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -107,4 +107,4 @@ jobs: - name: Upload Documentation env: GRGIT_USER: ${{ secrets.GH_TOKEN }} - run: ./src/publishDocumentationSnapshotOnlyIfNecessary.sh + run: ./gradle/scripts/publishDocumentationSnapshotOnlyIfNecessary.sh diff --git a/.github/workflows/reproducible-build.yml b/.github/workflows/reproducible-build.yml index f7e365c436ce..a32a51ac0002 100644 --- a/.github/workflows/reproducible-build.yml +++ b/.github/workflows/reproducible-build.yml @@ -28,4 +28,4 @@ jobs: - name: Build and compare checksums shell: bash run: | - ./src/checkBuildReproducibility.sh + ./gradle/scripts/checkBuildReproducibility.sh diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index e2a44b38b935..2078c532b4c8 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -71,8 +71,8 @@ Code formatting is enforced using the [Spotless](https://github.com/diffplug/spo Gradle plugin. You can use `gradle spotlessApply` to format new code and add missing license headers to source files. Formatter and import order settings for Eclipse are available in the repository under -[src/eclipse/junit-eclipse-formatter-settings.xml](src/eclipse/junit-eclipse-formatter-settings.xml) -and [src/eclipse/junit-eclipse.importorder](src/eclipse/junit-eclipse.importorder), +[junit-eclipse-formatter-settings.xml](gradle/config/eclipse/junit-eclipse-formatter-settings.xml) +and [junit-eclipse.importorder](gradle/config/eclipse/junit-eclipse.importorder), respectively. For IntelliJ IDEA there's a [plugin](https://plugins.jetbrains.com/plugin/6546) you can use in conjunction with the Eclipse settings. diff --git a/build.gradle.kts b/build.gradle.kts index 0fc9203523f2..c91646fd46bf 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -13,7 +13,7 @@ description = "JUnit 5" val license by extra(License( name = "Eclipse Public License v2.0", url = uri("https://www.eclipse.org/legal/epl-v20.html"), - headerFile = file("src/spotless/eclipse-public-license-2.0.java") + headerFile = layout.projectDirectory.file("gradle/config/spotless/eclipse-public-license-2.0.java") )) val platformProjects by extra(listOf( diff --git a/src/checkstyle/checkstyleMain.xml b/gradle/config/checkstyle/checkstyleMain.xml similarity index 100% rename from src/checkstyle/checkstyleMain.xml rename to gradle/config/checkstyle/checkstyleMain.xml diff --git a/src/checkstyle/checkstyleTest.xml b/gradle/config/checkstyle/checkstyleTest.xml similarity index 100% rename from src/checkstyle/checkstyleTest.xml rename to gradle/config/checkstyle/checkstyleTest.xml diff --git a/src/checkstyle/suppressions.xml b/gradle/config/checkstyle/suppressions.xml similarity index 100% rename from src/checkstyle/suppressions.xml rename to gradle/config/checkstyle/suppressions.xml diff --git a/src/eclipse/junit-eclipse-formatter-settings.xml b/gradle/config/eclipse/junit-eclipse-formatter-settings.xml similarity index 100% rename from src/eclipse/junit-eclipse-formatter-settings.xml rename to gradle/config/eclipse/junit-eclipse-formatter-settings.xml diff --git a/src/eclipse/junit-eclipse.importorder b/gradle/config/eclipse/junit-eclipse.importorder similarity index 100% rename from src/eclipse/junit-eclipse.importorder rename to gradle/config/eclipse/junit-eclipse.importorder diff --git a/src/spotless/eclipse-public-license-2.0.java b/gradle/config/spotless/eclipse-public-license-2.0.java similarity index 100% rename from src/spotless/eclipse-public-license-2.0.java rename to gradle/config/spotless/eclipse-public-license-2.0.java diff --git a/gradle/plugins/src/main/kotlin/License.kt b/gradle/plugins/src/main/kotlin/License.kt index 4f4e78eaa5b2..9d83baeaf8c1 100644 --- a/gradle/plugins/src/main/kotlin/License.kt +++ b/gradle/plugins/src/main/kotlin/License.kt @@ -1,4 +1,4 @@ -import java.io.File +import org.gradle.api.file.RegularFile import java.net.URI -data class License(val name: String, val url: URI, val headerFile: File) +data class License(val name: String, val url: URI, val headerFile: RegularFile) diff --git a/gradle/plugins/src/main/kotlin/junitbuild.java-library-conventions.gradle.kts b/gradle/plugins/src/main/kotlin/junitbuild.java-library-conventions.gradle.kts index bb586e37605c..4961dccee0ff 100644 --- a/gradle/plugins/src/main/kotlin/junitbuild.java-library-conventions.gradle.kts +++ b/gradle/plugins/src/main/kotlin/junitbuild.java-library-conventions.gradle.kts @@ -267,21 +267,21 @@ afterEvaluate { checkstyle { toolVersion = requiredVersionFromLibs("checkstyle") - configDirectory.set(rootProject.file("src/checkstyle")) + configDirectory.set(rootProject.layout.projectDirectory.dir("gradle/config/checkstyle")) } tasks { checkstyleMain { - configFile = rootProject.file("src/checkstyle/checkstyleMain.xml") + config = resources.text.fromFile(checkstyle.configDirectory.file("checkstyleMain.xml")) } checkstyleTest { - configFile = rootProject.file("src/checkstyle/checkstyleTest.xml") + config = resources.text.fromFile(checkstyle.configDirectory.file("checkstyleTest.xml")) } } pluginManager.withPlugin("java-test-fixtures") { tasks.named("checkstyleTestFixtures") { - configFile = rootProject.file("src/checkstyle/checkstyleTest.xml") + config = resources.text.fromFile(checkstyle.configDirectory.file("checkstyleTest.xml")) } tasks.named("compileTestFixturesJava") { options.release.set(extension.testJavaVersion.majorVersion.toInt()) diff --git a/gradle/plugins/src/main/kotlin/junitbuild.java-multi-release-sources.gradle.kts b/gradle/plugins/src/main/kotlin/junitbuild.java-multi-release-sources.gradle.kts index 7f2af9d50e7e..b78098f3743e 100644 --- a/gradle/plugins/src/main/kotlin/junitbuild.java-multi-release-sources.gradle.kts +++ b/gradle/plugins/src/main/kotlin/junitbuild.java-multi-release-sources.gradle.kts @@ -28,7 +28,7 @@ listOf(9, 17).forEach { javaVersion -> } named("checkstyle${sourceSet.name.replaceFirstChar(Char::titlecase)}").configure { - configFile = rootProject.file("src/checkstyle/checkstyleMain.xml") + config = resources.text.fromFile(checkstyle.configDirectory.file("checkstyleMain.xml")) } if (project in mavenizedProjects) { diff --git a/gradle/plugins/src/main/kotlin/junitbuild.spotless-conventions.gradle.kts b/gradle/plugins/src/main/kotlin/junitbuild.spotless-conventions.gradle.kts index 9f82998c135c..026eebbf40a5 100644 --- a/gradle/plugins/src/main/kotlin/junitbuild.spotless-conventions.gradle.kts +++ b/gradle/plugins/src/main/kotlin/junitbuild.spotless-conventions.gradle.kts @@ -1,6 +1,3 @@ -import org.gradle.kotlin.dsl.extra -import org.gradle.kotlin.dsl.provideDelegate - plugins { id("com.diffplug.spotless") } @@ -25,8 +22,9 @@ spotless { pluginManager.withPlugin("java") { - val importOrderConfigFile = rootProject.file("src/eclipse/junit-eclipse.importorder") - val javaFormatterConfigFile = rootProject.file("src/eclipse/junit-eclipse-formatter-settings.xml") + val configDir = rootProject.layout.projectDirectory.dir("gradle/config/eclipse") + val importOrderConfigFile = configDir.file("junit-eclipse.importorder") + val javaFormatterConfigFile = configDir.file("junit-eclipse-formatter-settings.xml") java { licenseHeaderFile(license.headerFile, "(package|import|open|module) ") diff --git a/src/checkBuildReproducibility.sh b/gradle/scripts/checkBuildReproducibility.sh similarity index 100% rename from src/checkBuildReproducibility.sh rename to gradle/scripts/checkBuildReproducibility.sh diff --git a/src/publishDocumentationSnapshotOnlyIfNecessary.sh b/gradle/scripts/publishDocumentationSnapshotOnlyIfNecessary.sh similarity index 100% rename from src/publishDocumentationSnapshotOnlyIfNecessary.sh rename to gradle/scripts/publishDocumentationSnapshotOnlyIfNecessary.sh diff --git a/platform-tests/platform-tests.gradle.kts b/platform-tests/platform-tests.gradle.kts index 7ec818dc927f..2990064246c6 100644 --- a/platform-tests/platform-tests.gradle.kts +++ b/platform-tests/platform-tests.gradle.kts @@ -79,7 +79,7 @@ tasks { } } checkstyleJmh { // use same style rules as defined for tests - configFile = rootProject.file("src/checkstyle/checkstyleTest.xml") + config = resources.text.fromFile(checkstyle.configDirectory.file("checkstyleTest.xml")) } } From 3d9c273e43e4a74f34eef32b4e3bdf50df6794df Mon Sep 17 00:00:00 2001 From: Marc Philipp Date: Sat, 18 Feb 2023 16:03:13 +0100 Subject: [PATCH 0022/1473] Simplify build script --- junit-jupiter-engine/junit-jupiter-engine.gradle.kts | 3 --- 1 file changed, 3 deletions(-) diff --git a/junit-jupiter-engine/junit-jupiter-engine.gradle.kts b/junit-jupiter-engine/junit-jupiter-engine.gradle.kts index 7ce27bcf32e7..8d9112ccba1a 100644 --- a/junit-jupiter-engine/junit-jupiter-engine.gradle.kts +++ b/junit-jupiter-engine/junit-jupiter-engine.gradle.kts @@ -33,9 +33,6 @@ tasks { inputs.dir("src/test/resources").withPathSensitivity(RELATIVE) systemProperty("developmentVersion", version) } -} - -tasks { jar { bundle { bnd(""" From d6f8728265fcaac2e3160f9d390f660c8a4a1e46 Mon Sep 17 00:00:00 2001 From: Marc Philipp Date: Sat, 18 Feb 2023 16:12:16 +0100 Subject: [PATCH 0023/1473] Resolve warnings for configurations being resolvable and consumable --- documentation/documentation.gradle.kts | 4 ++-- .../kotlin/ConfigurationContainerExtensions.kt | 14 ++++++++++++++ .../junitbuild.junit4-compatibility.gradle.kts | 2 +- .../kotlin/junitbuild.osgi-conventions.gradle.kts | 2 +- .../junitbuild.shadow-conventions.gradle.kts | 2 +- .../platform-tooling-support-tests.gradle.kts | 6 +++--- 6 files changed, 22 insertions(+), 8 deletions(-) create mode 100644 gradle/plugins/src/main/kotlin/ConfigurationContainerExtensions.kt diff --git a/documentation/documentation.gradle.kts b/documentation/documentation.gradle.kts index a357d9f2d421..01b138459d86 100644 --- a/documentation/documentation.gradle.kts +++ b/documentation/documentation.gradle.kts @@ -25,8 +25,8 @@ javaLibrary { testJavaVersion = JavaVersion.VERSION_1_8 } -val apiReport by configurations.creating -val standaloneConsoleLauncher by configurations.creating +val apiReport by configurations.creatingResolvable +val standaloneConsoleLauncher by configurations.creatingResolvable dependencies { implementation(projects.junitJupiterApi) { diff --git a/gradle/plugins/src/main/kotlin/ConfigurationContainerExtensions.kt b/gradle/plugins/src/main/kotlin/ConfigurationContainerExtensions.kt new file mode 100644 index 000000000000..ebe7399e9f15 --- /dev/null +++ b/gradle/plugins/src/main/kotlin/ConfigurationContainerExtensions.kt @@ -0,0 +1,14 @@ + +import org.gradle.api.artifacts.Configuration +import org.gradle.api.artifacts.ConfigurationContainer +import org.gradle.kotlin.dsl.NamedDomainObjectContainerCreatingDelegateProvider + +val ConfigurationContainer.creatingResolvable + get() = creatingResolvable {} + +fun ConfigurationContainer.creatingResolvable(configuration: Configuration.() -> Unit) = + NamedDomainObjectContainerCreatingDelegateProvider.of(this) { + isCanBeResolved = true + isCanBeConsumed = false + configuration() + } diff --git a/gradle/plugins/src/main/kotlin/junitbuild.junit4-compatibility.gradle.kts b/gradle/plugins/src/main/kotlin/junitbuild.junit4-compatibility.gradle.kts index e43c938e5ca4..dd1e08fed717 100644 --- a/gradle/plugins/src/main/kotlin/junitbuild.junit4-compatibility.gradle.kts +++ b/gradle/plugins/src/main/kotlin/junitbuild.junit4-compatibility.gradle.kts @@ -2,7 +2,7 @@ plugins { `java-library` } -val junit_4_12 by configurations.creating { +val junit_4_12 by configurations.creatingResolvable { extendsFrom(configurations.testRuntimeClasspath.get()) } diff --git a/gradle/plugins/src/main/kotlin/junitbuild.osgi-conventions.gradle.kts b/gradle/plugins/src/main/kotlin/junitbuild.osgi-conventions.gradle.kts index 3a2bf7c6db66..d41f23f6ef64 100644 --- a/gradle/plugins/src/main/kotlin/junitbuild.osgi-conventions.gradle.kts +++ b/gradle/plugins/src/main/kotlin/junitbuild.osgi-conventions.gradle.kts @@ -87,7 +87,7 @@ val osgiProperties by tasks.registering(WriteProperties::class) { property("-runblacklist", "org.apiguardian.api") } -val osgiVerification by configurations.creating { +val osgiVerification by configurations.creatingResolvable { extendsFrom(configurations.runtimeClasspath.get()) } diff --git a/gradle/plugins/src/main/kotlin/junitbuild.shadow-conventions.gradle.kts b/gradle/plugins/src/main/kotlin/junitbuild.shadow-conventions.gradle.kts index d9f93aa3839d..9ae82635c4b3 100644 --- a/gradle/plugins/src/main/kotlin/junitbuild.shadow-conventions.gradle.kts +++ b/gradle/plugins/src/main/kotlin/junitbuild.shadow-conventions.gradle.kts @@ -3,7 +3,7 @@ plugins { id("com.github.johnrengelman.shadow") } -val shadowed by configurations.creating +val shadowed by configurations.creatingResolvable configurations { listOf(apiElements, runtimeElements).forEach { diff --git a/platform-tooling-support-tests/platform-tooling-support-tests.gradle.kts b/platform-tooling-support-tests/platform-tooling-support-tests.gradle.kts index 61bec5e11ec0..21c6f6c08d11 100644 --- a/platform-tooling-support-tests/platform-tooling-support-tests.gradle.kts +++ b/platform-tooling-support-tests/platform-tooling-support-tests.gradle.kts @@ -24,9 +24,9 @@ spotless { } } -val thirdPartyJars by configurations.creating -val antJars by configurations.creating -val mavenDistribution by configurations.creating +val thirdPartyJars by configurations.creatingResolvable +val antJars by configurations.creatingResolvable +val mavenDistribution by configurations.creatingResolvable dependencies { implementation(libs.bartholdy) { From 3d3b2a95167de053ae2104271eaab4fa12b422c4 Mon Sep 17 00:00:00 2001 From: Marc Philipp Date: Sat, 18 Feb 2023 17:00:29 +0100 Subject: [PATCH 0024/1473] Remove unused imports --- .../src/main/kotlin/junitbuild/java/ExecJarAction.kt | 3 --- .../kotlin/junitbuild/java/ModulePathArgumentProvider.kt | 5 ----- .../kotlin/junitbuild/java/PatchModuleArgumentProvider.kt | 2 -- .../src/main/kotlin/junitbuild/java/WriteArtifactsFile.kt | 6 +++--- 4 files changed, 3 insertions(+), 13 deletions(-) diff --git a/gradle/plugins/src/main/kotlin/junitbuild/java/ExecJarAction.kt b/gradle/plugins/src/main/kotlin/junitbuild/java/ExecJarAction.kt index a900b9c646c3..8a3cf49ad70e 100644 --- a/gradle/plugins/src/main/kotlin/junitbuild/java/ExecJarAction.kt +++ b/gradle/plugins/src/main/kotlin/junitbuild/java/ExecJarAction.kt @@ -4,10 +4,7 @@ import org.gradle.api.Action import org.gradle.api.Task import org.gradle.api.provider.ListProperty import org.gradle.api.provider.Property -import org.gradle.jvm.tasks.Jar import org.gradle.jvm.toolchain.JavaLauncher -import org.gradle.jvm.toolchain.JavaToolchainService -import org.gradle.jvm.toolchain.JavaToolchainSpec import org.gradle.process.ExecOperations import javax.inject.Inject diff --git a/gradle/plugins/src/main/kotlin/junitbuild/java/ModulePathArgumentProvider.kt b/gradle/plugins/src/main/kotlin/junitbuild/java/ModulePathArgumentProvider.kt index 3133c35a2ead..ec79fdfaade8 100644 --- a/gradle/plugins/src/main/kotlin/junitbuild/java/ModulePathArgumentProvider.kt +++ b/gradle/plugins/src/main/kotlin/junitbuild/java/ModulePathArgumentProvider.kt @@ -2,13 +2,8 @@ package junitbuild.java import org.gradle.api.Named import org.gradle.api.Project -import org.gradle.api.artifacts.Configuration import org.gradle.api.file.ConfigurableFileCollection -import org.gradle.api.file.FileCollection -import org.gradle.api.provider.Property -import org.gradle.api.provider.Provider import org.gradle.api.tasks.* -import org.gradle.kotlin.dsl.get import org.gradle.process.CommandLineArgumentProvider import javax.inject.Inject diff --git a/gradle/plugins/src/main/kotlin/junitbuild/java/PatchModuleArgumentProvider.kt b/gradle/plugins/src/main/kotlin/junitbuild/java/PatchModuleArgumentProvider.kt index 93210bfc41a7..0c7f330f8adf 100644 --- a/gradle/plugins/src/main/kotlin/junitbuild/java/PatchModuleArgumentProvider.kt +++ b/gradle/plugins/src/main/kotlin/junitbuild/java/PatchModuleArgumentProvider.kt @@ -4,9 +4,7 @@ import javaModuleName import org.gradle.api.Named import org.gradle.api.Project import org.gradle.api.file.ConfigurableFileCollection -import org.gradle.api.file.FileCollection import org.gradle.api.provider.Property -import org.gradle.api.provider.Provider import org.gradle.api.tasks.* import org.gradle.kotlin.dsl.get import org.gradle.kotlin.dsl.the diff --git a/gradle/plugins/src/main/kotlin/junitbuild/java/WriteArtifactsFile.kt b/gradle/plugins/src/main/kotlin/junitbuild/java/WriteArtifactsFile.kt index d0b56930cf08..684c20364597 100644 --- a/gradle/plugins/src/main/kotlin/junitbuild/java/WriteArtifactsFile.kt +++ b/gradle/plugins/src/main/kotlin/junitbuild/java/WriteArtifactsFile.kt @@ -3,12 +3,12 @@ package junitbuild.java import org.gradle.api.DefaultTask import org.gradle.api.artifacts.Configuration import org.gradle.api.artifacts.ModuleVersionIdentifier -import org.gradle.api.artifacts.ResolvedArtifact import org.gradle.api.file.RegularFileProperty -import org.gradle.api.provider.Property import org.gradle.api.provider.Provider import org.gradle.api.provider.SetProperty -import org.gradle.api.tasks.* +import org.gradle.api.tasks.Input +import org.gradle.api.tasks.OutputFile +import org.gradle.api.tasks.TaskAction abstract class WriteArtifactsFile : DefaultTask() { From 19fa80afec41cbd88c981a4f9e426ac6a53f460c Mon Sep 17 00:00:00 2001 From: Marc Philipp Date: Sat, 18 Feb 2023 18:27:38 +0100 Subject: [PATCH 0025/1473] Ignore build output of included build to avoid unstable inputs --- build.gradle.kts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle.kts b/build.gradle.kts index c91646fd46bf..7662a5524b31 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -61,5 +61,5 @@ nexusPublishing { } nohttp { - source.exclude("**/.gradle/**", "gradle/plugins/build/generated-sources/**") + source.exclude("**/.gradle/**", "gradle/plugins/build/**") } From 97d9c2ec57e24736788df8f732de9456d3edaacb Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 20 Feb 2023 07:53:10 +0100 Subject: [PATCH 0026/1473] Bump com.github.ben-manes:gradle-versions-plugin to 0.45.0 (#3161) Bumps [com.github.ben-manes:gradle-versions-plugin](https://github.com/ben-manes/gradle-versions-plugin) from 0.44.0 to 0.45.0. - [Release notes](https://github.com/ben-manes/gradle-versions-plugin/releases) - [Commits](https://github.com/ben-manes/gradle-versions-plugin/compare/v0.44.0...v0.45.0) --- updated-dependencies: - dependency-name: com.github.ben-manes:gradle-versions-plugin dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- gradle/plugins/build.gradle.kts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle/plugins/build.gradle.kts b/gradle/plugins/build.gradle.kts index 5afee3e2d70d..823a90510165 100644 --- a/gradle/plugins/build.gradle.kts +++ b/gradle/plugins/build.gradle.kts @@ -13,7 +13,7 @@ dependencies { implementation(kotlin("gradle-plugin")) implementation("biz.aQute.bnd:biz.aQute.bnd.gradle:6.4.0") implementation("com.diffplug.spotless:spotless-plugin-gradle:6.15.0") - implementation("com.github.ben-manes:gradle-versions-plugin:0.44.0") + implementation("com.github.ben-manes:gradle-versions-plugin:0.45.0") implementation("gradle.plugin.com.github.johnrengelman:shadow:7.1.2") compileOnly("com.gradle:gradle-enterprise-gradle-plugin:3.12.3") // keep in sync with root settings.gradle.kts } From 40b715df632e2379b2acb2d6f8f94f16066f76e5 Mon Sep 17 00:00:00 2001 From: Marc Philipp Date: Fri, 17 Feb 2023 21:42:29 +0100 Subject: [PATCH 0027/1473] Make it possible to pass args to ConsoleLauncher Gradle task The task can now be called as: :documentation:consoleLauncher --args="--help ..." --- .../junitbuild/exec/RunConsoleLauncher.kt | 20 +++++++++++++------ 1 file changed, 14 insertions(+), 6 deletions(-) diff --git a/gradle/plugins/src/main/kotlin/junitbuild/exec/RunConsoleLauncher.kt b/gradle/plugins/src/main/kotlin/junitbuild/exec/RunConsoleLauncher.kt index 4ba265061662..bd07e328b672 100644 --- a/gradle/plugins/src/main/kotlin/junitbuild/exec/RunConsoleLauncher.kt +++ b/gradle/plugins/src/main/kotlin/junitbuild/exec/RunConsoleLauncher.kt @@ -1,22 +1,20 @@ package junitbuild.exec +import org.apache.tools.ant.types.Commandline import org.gradle.api.DefaultTask import org.gradle.api.file.ConfigurableFileCollection import org.gradle.api.file.DirectoryProperty import org.gradle.api.provider.ListProperty import org.gradle.api.provider.Property -import org.gradle.api.tasks.Classpath -import org.gradle.api.tasks.Input -import org.gradle.api.tasks.Internal -import org.gradle.api.tasks.OutputDirectory -import org.gradle.api.tasks.SourceSetContainer -import org.gradle.api.tasks.TaskAction +import org.gradle.api.tasks.* +import org.gradle.api.tasks.options.Option import org.gradle.kotlin.dsl.get import org.gradle.kotlin.dsl.the import org.gradle.process.CommandLineArgumentProvider import org.gradle.process.ExecOperations import trackOperationSystemAsInput import java.io.ByteArrayOutputStream +import java.util.* import javax.inject.Inject abstract class RunConsoleLauncher @Inject constructor(private val execOperations: ExecOperations): DefaultTask() { @@ -27,6 +25,9 @@ abstract class RunConsoleLauncher @Inject constructor(private val execOperations @get:Input abstract val args: ListProperty + @get:Input + abstract val commandLineArgs: ListProperty + @get:OutputDirectory abstract val reportsDir: DirectoryProperty @@ -62,6 +63,7 @@ abstract class RunConsoleLauncher @Inject constructor(private val execOperations args("--scan-classpath") args("--config=junit.platform.reporting.open.xml.enabled=true") args(this@RunConsoleLauncher.args.get()) + args(this@RunConsoleLauncher.commandLineArgs.get()) argumentProviders += CommandLineArgumentProvider { listOf( "--reports-dir=${reportsDir.get()}", @@ -83,4 +85,10 @@ abstract class RunConsoleLauncher @Inject constructor(private val execOperations } result.rethrowFailure().assertNormalExitValue() } + + @Suppress("unused") + @Option(option = "args", description = "Additional command line arguments for the console launcher") + fun setCliArgs(args: String) { + commandLineArgs.set(Commandline.translateCommandline(args).toList()) + } } From 91b9308b0b637862327c354b60a1fa089c6e1c47 Mon Sep 17 00:00:00 2001 From: Marc Philipp Date: Fri, 17 Feb 2023 22:03:18 +0100 Subject: [PATCH 0028/1473] Add --debug-jvm option to RunConsoleLauncher --- .../junitbuild/exec/RunConsoleLauncher.kt | 19 +++++++++++++------ 1 file changed, 13 insertions(+), 6 deletions(-) diff --git a/gradle/plugins/src/main/kotlin/junitbuild/exec/RunConsoleLauncher.kt b/gradle/plugins/src/main/kotlin/junitbuild/exec/RunConsoleLauncher.kt index bd07e328b672..e8de805b8425 100644 --- a/gradle/plugins/src/main/kotlin/junitbuild/exec/RunConsoleLauncher.kt +++ b/gradle/plugins/src/main/kotlin/junitbuild/exec/RunConsoleLauncher.kt @@ -17,7 +17,7 @@ import java.io.ByteArrayOutputStream import java.util.* import javax.inject.Inject -abstract class RunConsoleLauncher @Inject constructor(private val execOperations: ExecOperations): DefaultTask() { +abstract class RunConsoleLauncher @Inject constructor(private val execOperations: ExecOperations) : DefaultTask() { @get:Classpath abstract val runtimeClasspath: ConfigurableFileCollection @@ -41,11 +41,8 @@ abstract class RunConsoleLauncher @Inject constructor(private val execOperations runtimeClasspath.from(project.the()["test"].runtimeClasspath) reportsDir.convention(project.layout.buildDirectory.dir("test-results")) - debugging.convention( - project.providers.gradleProperty("consoleLauncherTestDebug") - .map { it != "false" } - .orElse(false) - ) + debugging.convention(false) + commandLineArgs.convention(emptyList()) outputs.cacheIf { !debugging.get() } outputs.upToDateWhen { !debugging.get() } @@ -91,4 +88,14 @@ abstract class RunConsoleLauncher @Inject constructor(private val execOperations fun setCliArgs(args: String) { commandLineArgs.set(Commandline.translateCommandline(args).toList()) } + + @Suppress("unused") + @Option( + option = "debug-jvm", + description = "Enable debugging. The process is started suspended and listening on port 5005." + ) + fun setDebug(enabled: Boolean) { + debugging.set(enabled) + } + } From d590e57d72a79a2e9dc9cb285f1ea81d981d6c4f Mon Sep 17 00:00:00 2001 From: Marc Philipp Date: Mon, 20 Feb 2023 18:41:51 +0100 Subject: [PATCH 0029/1473] Use the configured Java toolchain to run the ConsoleLauncher --- .../src/main/kotlin/junitbuild/exec/RunConsoleLauncher.kt | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/gradle/plugins/src/main/kotlin/junitbuild/exec/RunConsoleLauncher.kt b/gradle/plugins/src/main/kotlin/junitbuild/exec/RunConsoleLauncher.kt index e8de805b8425..2dc13d501b75 100644 --- a/gradle/plugins/src/main/kotlin/junitbuild/exec/RunConsoleLauncher.kt +++ b/gradle/plugins/src/main/kotlin/junitbuild/exec/RunConsoleLauncher.kt @@ -4,10 +4,13 @@ import org.apache.tools.ant.types.Commandline import org.gradle.api.DefaultTask import org.gradle.api.file.ConfigurableFileCollection import org.gradle.api.file.DirectoryProperty +import org.gradle.api.plugins.JavaPluginExtension import org.gradle.api.provider.ListProperty import org.gradle.api.provider.Property import org.gradle.api.tasks.* import org.gradle.api.tasks.options.Option +import org.gradle.jvm.toolchain.JavaLauncher +import org.gradle.jvm.toolchain.JavaToolchainService import org.gradle.kotlin.dsl.get import org.gradle.kotlin.dsl.the import org.gradle.process.CommandLineArgumentProvider @@ -28,6 +31,9 @@ abstract class RunConsoleLauncher @Inject constructor(private val execOperations @get:Input abstract val commandLineArgs: ListProperty + @get:Nested + abstract val javaLauncher: Property + @get:OutputDirectory abstract val reportsDir: DirectoryProperty @@ -40,6 +46,7 @@ abstract class RunConsoleLauncher @Inject constructor(private val execOperations init { runtimeClasspath.from(project.the()["test"].runtimeClasspath) reportsDir.convention(project.layout.buildDirectory.dir("test-results")) + javaLauncher.set(project.the().launcherFor(project.the().toolchain)) debugging.convention(false) commandLineArgs.convention(emptyList()) @@ -55,6 +62,7 @@ abstract class RunConsoleLauncher @Inject constructor(private val execOperations fun execute() { val output = ByteArrayOutputStream() val result = execOperations.javaexec { + executable = javaLauncher.get().executablePath.asFile.absolutePath classpath = runtimeClasspath mainClass.set("org.junit.platform.console.ConsoleLauncher") args("--scan-classpath") From 4e35f3fbe1d3a920224e8d6b3f6ef3204be498c0 Mon Sep 17 00:00:00 2001 From: Marc Philipp Date: Sat, 18 Feb 2023 18:08:49 +0100 Subject: [PATCH 0030/1473] Compile main sources on module path as well In order to detect JPMS issues the main sources are now compiled along with the module descriptor but only the compiled module descriptor is packaged in the jar. --- ...tbuild.java-library-conventions.gradle.kts | 28 +++++++++++++++++-- .../junitbuild.shadow-conventions.gradle.kts | 5 ++++ .../junitbuild/java/ModuleCompileOptions.kt | 7 +++++ .../java/ModulePathArgumentProvider.kt | 10 +++++-- 4 files changed, 45 insertions(+), 5 deletions(-) create mode 100644 gradle/plugins/src/main/kotlin/junitbuild/java/ModuleCompileOptions.kt diff --git a/gradle/plugins/src/main/kotlin/junitbuild.java-library-conventions.gradle.kts b/gradle/plugins/src/main/kotlin/junitbuild.java-library-conventions.gradle.kts index 4961dccee0ff..6c0e5462486c 100644 --- a/gradle/plugins/src/main/kotlin/junitbuild.java-library-conventions.gradle.kts +++ b/gradle/plugins/src/main/kotlin/junitbuild.java-library-conventions.gradle.kts @@ -1,4 +1,5 @@ import com.github.jengelman.gradle.plugins.shadow.tasks.ShadowJar +import junitbuild.java.ModuleCompileOptions import junitbuild.java.ModulePathArgumentProvider import junitbuild.java.PatchModuleArgumentProvider @@ -21,6 +22,7 @@ val builtByValue: String by rootProject.extra val extension = extensions.create("javaLibrary") val moduleSourceDir = file("src/module/$javaModuleName") +val combinedModuleSourceDir = layout.buildDirectory.dir("module") val moduleOutputDir = file("$buildDir/classes/java/module") val javaVersion = JavaVersion.current() @@ -143,9 +145,17 @@ val allMainClasses by tasks.registering { dependsOn(tasks.classes) } +val prepareModuleSourceDir by tasks.registering(Sync::class) { + from(moduleSourceDir) + from(sourceSets.matching { it.name.startsWith("main") }.map { it.allJava }) + into(combinedModuleSourceDir.map { it.dir(javaModuleName) }) + duplicatesStrategy = DuplicatesStrategy.EXCLUDE +} + val compileModule by tasks.registering(JavaCompile::class) { dependsOn(allMainClasses) - source = fileTree(moduleSourceDir) + enabled = project in modularProjects + source = fileTree(combinedModuleSourceDir).builtBy(prepareModuleSourceDir) destinationDirectory.set(moduleOutputDir) sourceCompatibility = "9" targetCompatibility = "9" @@ -157,9 +167,23 @@ val compileModule by tasks.registering(JavaCompile::class) { "-Werror", // Terminates compilation when warnings occur. "--module-version", "${project.version}", )) - options.compilerArgumentProviders.add(objects.newInstance(ModulePathArgumentProvider::class, project, modularProjects)) + + val moduleOptions = objects.newInstance(ModuleCompileOptions::class) + extensions.add("moduleOptions", moduleOptions) + moduleOptions.modulePath.from(configurations.compileClasspath) + + options.compilerArgumentProviders.add(objects.newInstance(ModulePathArgumentProvider::class, project, combinedModuleSourceDir, modularProjects).apply { + modulePath.from(moduleOptions.modulePath) + }) options.compilerArgumentProviders.addAll(modularProjects.map { objects.newInstance(PatchModuleArgumentProvider::class, project, it) }) + modularity.inferModulePath.set(false) + + doFirst { + options.allCompilerArgs.forEach { + logger.info(it) + } + } } tasks.withType().configureEach { diff --git a/gradle/plugins/src/main/kotlin/junitbuild.shadow-conventions.gradle.kts b/gradle/plugins/src/main/kotlin/junitbuild.shadow-conventions.gradle.kts index 9ae82635c4b3..4863c00576fa 100644 --- a/gradle/plugins/src/main/kotlin/junitbuild.shadow-conventions.gradle.kts +++ b/gradle/plugins/src/main/kotlin/junitbuild.shadow-conventions.gradle.kts @@ -1,3 +1,5 @@ +import junitbuild.java.ModuleCompileOptions + plugins { id("junitbuild.java-library-conventions") id("com.github.johnrengelman.shadow") @@ -66,4 +68,7 @@ tasks { classpath -= sourceSets.main.get().output classpath += files(shadowJar.map { it.archiveFile }) } + named("compileModule") { + the().modulePath.from(shadowed) + } } diff --git a/gradle/plugins/src/main/kotlin/junitbuild/java/ModuleCompileOptions.kt b/gradle/plugins/src/main/kotlin/junitbuild/java/ModuleCompileOptions.kt new file mode 100644 index 000000000000..13c6fde1c09d --- /dev/null +++ b/gradle/plugins/src/main/kotlin/junitbuild/java/ModuleCompileOptions.kt @@ -0,0 +1,7 @@ +package junitbuild.java + +import org.gradle.api.file.ConfigurableFileCollection + +abstract class ModuleCompileOptions { + abstract val modulePath: ConfigurableFileCollection +} diff --git a/gradle/plugins/src/main/kotlin/junitbuild/java/ModulePathArgumentProvider.kt b/gradle/plugins/src/main/kotlin/junitbuild/java/ModulePathArgumentProvider.kt index ec79fdfaade8..9d05430ad810 100644 --- a/gradle/plugins/src/main/kotlin/junitbuild/java/ModulePathArgumentProvider.kt +++ b/gradle/plugins/src/main/kotlin/junitbuild/java/ModulePathArgumentProvider.kt @@ -3,11 +3,13 @@ package junitbuild.java import org.gradle.api.Named import org.gradle.api.Project import org.gradle.api.file.ConfigurableFileCollection +import org.gradle.api.file.Directory +import org.gradle.api.provider.Provider import org.gradle.api.tasks.* import org.gradle.process.CommandLineArgumentProvider import javax.inject.Inject -abstract class ModulePathArgumentProvider @Inject constructor(project: Project, modularProjects: List) : +abstract class ModulePathArgumentProvider @Inject constructor(project: Project, combinedModuleSourceDir: Provider, modularProjects: List) : CommandLineArgumentProvider, Named { @get:CompileClasspath @@ -18,9 +20,11 @@ abstract class ModulePathArgumentProvider @Inject constructor(project: Project, abstract val moduleSourceDirs: ConfigurableFileCollection init { - modulePath.from(project.configurations.named("compileClasspath")) modularProjects.forEach { - moduleSourceDirs.from(project.files("${it.projectDir}/src/module")) + if (it == project) + moduleSourceDirs.from(combinedModuleSourceDir) + else + moduleSourceDirs.from(project.files("${it.projectDir}/src/module")) } } From 8be55d0dc4cc709a32b71eb8b934a9a9d0ed654f Mon Sep 17 00:00:00 2001 From: Marc Philipp Date: Sat, 18 Feb 2023 18:10:27 +0100 Subject: [PATCH 0031/1473] Manually add shadowed dependencies as modules during compilation --- junit-jupiter-params/junit-jupiter-params.gradle.kts | 6 ++++++ junit-platform-console/junit-platform-console.gradle.kts | 4 +++- .../junit-platform-reporting.gradle.kts | 6 ++++++ 3 files changed, 15 insertions(+), 1 deletion(-) diff --git a/junit-jupiter-params/junit-jupiter-params.gradle.kts b/junit-jupiter-params/junit-jupiter-params.gradle.kts index 44e065e118ed..6d98446d921d 100644 --- a/junit-jupiter-params/junit-jupiter-params.gradle.kts +++ b/junit-jupiter-params/junit-jupiter-params.gradle.kts @@ -48,4 +48,10 @@ tasks { into("META-INF") } } + compileModule { + options.compilerArgs.addAll(listOf( + "--add-modules", "univocity.parsers", + "--add-reads", "${javaModuleName}=univocity.parsers" + )) + } } diff --git a/junit-platform-console/junit-platform-console.gradle.kts b/junit-platform-console/junit-platform-console.gradle.kts index d7bec605761e..7893568a0967 100644 --- a/junit-platform-console/junit-platform-console.gradle.kts +++ b/junit-platform-console/junit-platform-console.gradle.kts @@ -25,7 +25,9 @@ tasks { compileModule { options.compilerArgs.addAll(listOf( "--add-modules", "org.opentest4j.reporting.events", - "--add-reads", "org.junit.platform.reporting=org.opentest4j.reporting.events" + "--add-reads", "${project.projects.junitPlatformReporting.dependencyProject.javaModuleName}=org.opentest4j.reporting.events", + "--add-modules", "info.picocli", + "--add-reads", "${javaModuleName}=info.picocli" )) } shadowJar { diff --git a/junit-platform-reporting/junit-platform-reporting.gradle.kts b/junit-platform-reporting/junit-platform-reporting.gradle.kts index 84eb0fa0f75c..b95816fcfc2d 100644 --- a/junit-platform-reporting/junit-platform-reporting.gradle.kts +++ b/junit-platform-reporting/junit-platform-reporting.gradle.kts @@ -25,4 +25,10 @@ tasks { into("META-INF") } } + compileModule { + options.compilerArgs.addAll(listOf( + "--add-modules", "org.opentest4j.reporting.events", + "--add-reads", "${javaModuleName}=org.opentest4j.reporting.events" + )) + } } From a76e1a5da74f97e0ac335fc874265bb5454b2866 Mon Sep 17 00:00:00 2001 From: Marc Philipp Date: Sat, 18 Feb 2023 18:12:12 +0100 Subject: [PATCH 0032/1473] Suppress export warnings Since these packages are opened for reflection to org.junit.platform.commons the warnings can safely be ignored. --- .../org/junit/jupiter/api/condition/DisabledForJreRange.java | 1 + .../main/java/org/junit/jupiter/api/condition/DisabledIf.java | 1 + .../jupiter/api/condition/DisabledIfEnvironmentVariable.java | 1 + .../junit/jupiter/api/condition/DisabledIfSystemProperty.java | 1 + .../main/java/org/junit/jupiter/api/condition/DisabledOnJre.java | 1 + .../main/java/org/junit/jupiter/api/condition/DisabledOnOs.java | 1 + .../java/org/junit/jupiter/api/condition/EnabledForJreRange.java | 1 + .../src/main/java/org/junit/jupiter/api/condition/EnabledIf.java | 1 + .../jupiter/api/condition/EnabledIfEnvironmentVariable.java | 1 + .../org/junit/jupiter/api/condition/EnabledIfSystemProperty.java | 1 + .../main/java/org/junit/jupiter/api/condition/EnabledOnJre.java | 1 + .../main/java/org/junit/jupiter/api/condition/EnabledOnOs.java | 1 + .../main/java/org/junit/jupiter/params/ParameterizedTest.java | 1 + .../jupiter/params/converter/JavaTimeConversionPattern.java | 1 + .../java/org/junit/jupiter/params/provider/CsvFileSource.java | 1 + .../main/java/org/junit/jupiter/params/provider/CsvSource.java | 1 + .../main/java/org/junit/jupiter/params/provider/EmptySource.java | 1 + .../main/java/org/junit/jupiter/params/provider/EnumSource.java | 1 + .../java/org/junit/jupiter/params/provider/MethodSource.java | 1 + .../main/java/org/junit/jupiter/params/provider/NullSource.java | 1 + .../main/java/org/junit/jupiter/params/provider/ValueSource.java | 1 + .../platform/engine/support/filter/ClasspathScanningSupport.java | 1 + 22 files changed, 22 insertions(+) diff --git a/junit-jupiter-api/src/main/java/org/junit/jupiter/api/condition/DisabledForJreRange.java b/junit-jupiter-api/src/main/java/org/junit/jupiter/api/condition/DisabledForJreRange.java index 57341bfaf79c..a3b0762e0de5 100644 --- a/junit-jupiter-api/src/main/java/org/junit/jupiter/api/condition/DisabledForJreRange.java +++ b/junit-jupiter-api/src/main/java/org/junit/jupiter/api/condition/DisabledForJreRange.java @@ -71,6 +71,7 @@ @Documented @ExtendWith(DisabledForJreRangeCondition.class) @API(status = STABLE, since = "5.6") +@SuppressWarnings("exports") public @interface DisabledForJreRange { /** diff --git a/junit-jupiter-api/src/main/java/org/junit/jupiter/api/condition/DisabledIf.java b/junit-jupiter-api/src/main/java/org/junit/jupiter/api/condition/DisabledIf.java index 8ab454fb6a17..06bdd569048a 100644 --- a/junit-jupiter-api/src/main/java/org/junit/jupiter/api/condition/DisabledIf.java +++ b/junit-jupiter-api/src/main/java/org/junit/jupiter/api/condition/DisabledIf.java @@ -70,6 +70,7 @@ @Documented @ExtendWith(DisabledIfCondition.class) @API(status = STABLE, since = "5.7") +@SuppressWarnings("exports") public @interface DisabledIf { /** diff --git a/junit-jupiter-api/src/main/java/org/junit/jupiter/api/condition/DisabledIfEnvironmentVariable.java b/junit-jupiter-api/src/main/java/org/junit/jupiter/api/condition/DisabledIfEnvironmentVariable.java index a98c31bb4e0a..0cc90eec72a4 100644 --- a/junit-jupiter-api/src/main/java/org/junit/jupiter/api/condition/DisabledIfEnvironmentVariable.java +++ b/junit-jupiter-api/src/main/java/org/junit/jupiter/api/condition/DisabledIfEnvironmentVariable.java @@ -73,6 +73,7 @@ @Repeatable(DisabledIfEnvironmentVariables.class) @ExtendWith(DisabledIfEnvironmentVariableCondition.class) @API(status = STABLE, since = "5.1") +@SuppressWarnings("exports") public @interface DisabledIfEnvironmentVariable { /** diff --git a/junit-jupiter-api/src/main/java/org/junit/jupiter/api/condition/DisabledIfSystemProperty.java b/junit-jupiter-api/src/main/java/org/junit/jupiter/api/condition/DisabledIfSystemProperty.java index c8bfe4fc8cdf..ac7d0937d848 100644 --- a/junit-jupiter-api/src/main/java/org/junit/jupiter/api/condition/DisabledIfSystemProperty.java +++ b/junit-jupiter-api/src/main/java/org/junit/jupiter/api/condition/DisabledIfSystemProperty.java @@ -73,6 +73,7 @@ @Repeatable(DisabledIfSystemProperties.class) @ExtendWith(DisabledIfSystemPropertyCondition.class) @API(status = STABLE, since = "5.1") +@SuppressWarnings("exports") public @interface DisabledIfSystemProperty { /** diff --git a/junit-jupiter-api/src/main/java/org/junit/jupiter/api/condition/DisabledOnJre.java b/junit-jupiter-api/src/main/java/org/junit/jupiter/api/condition/DisabledOnJre.java index ef1b5d8a5387..2aa7f012c947 100644 --- a/junit-jupiter-api/src/main/java/org/junit/jupiter/api/condition/DisabledOnJre.java +++ b/junit-jupiter-api/src/main/java/org/junit/jupiter/api/condition/DisabledOnJre.java @@ -71,6 +71,7 @@ @Documented @ExtendWith(DisabledOnJreCondition.class) @API(status = STABLE, since = "5.1") +@SuppressWarnings("exports") public @interface DisabledOnJre { /** diff --git a/junit-jupiter-api/src/main/java/org/junit/jupiter/api/condition/DisabledOnOs.java b/junit-jupiter-api/src/main/java/org/junit/jupiter/api/condition/DisabledOnOs.java index 5f1e08d70a59..f067c2290083 100644 --- a/junit-jupiter-api/src/main/java/org/junit/jupiter/api/condition/DisabledOnOs.java +++ b/junit-jupiter-api/src/main/java/org/junit/jupiter/api/condition/DisabledOnOs.java @@ -76,6 +76,7 @@ @Documented @ExtendWith(DisabledOnOsCondition.class) @API(status = STABLE, since = "5.1") +@SuppressWarnings("exports") public @interface DisabledOnOs { /** diff --git a/junit-jupiter-api/src/main/java/org/junit/jupiter/api/condition/EnabledForJreRange.java b/junit-jupiter-api/src/main/java/org/junit/jupiter/api/condition/EnabledForJreRange.java index 9e3154d85385..b1efb7c88e0d 100644 --- a/junit-jupiter-api/src/main/java/org/junit/jupiter/api/condition/EnabledForJreRange.java +++ b/junit-jupiter-api/src/main/java/org/junit/jupiter/api/condition/EnabledForJreRange.java @@ -71,6 +71,7 @@ @Documented @ExtendWith(EnabledForJreRangeCondition.class) @API(status = STABLE, since = "5.6") +@SuppressWarnings("exports") public @interface EnabledForJreRange { /** diff --git a/junit-jupiter-api/src/main/java/org/junit/jupiter/api/condition/EnabledIf.java b/junit-jupiter-api/src/main/java/org/junit/jupiter/api/condition/EnabledIf.java index 18e8a8395c46..5bd4b3df30e7 100644 --- a/junit-jupiter-api/src/main/java/org/junit/jupiter/api/condition/EnabledIf.java +++ b/junit-jupiter-api/src/main/java/org/junit/jupiter/api/condition/EnabledIf.java @@ -70,6 +70,7 @@ @Documented @ExtendWith(EnabledIfCondition.class) @API(status = STABLE, since = "5.7") +@SuppressWarnings("exports") public @interface EnabledIf { /** diff --git a/junit-jupiter-api/src/main/java/org/junit/jupiter/api/condition/EnabledIfEnvironmentVariable.java b/junit-jupiter-api/src/main/java/org/junit/jupiter/api/condition/EnabledIfEnvironmentVariable.java index d7cab6c3dddf..44cf3bf5940f 100644 --- a/junit-jupiter-api/src/main/java/org/junit/jupiter/api/condition/EnabledIfEnvironmentVariable.java +++ b/junit-jupiter-api/src/main/java/org/junit/jupiter/api/condition/EnabledIfEnvironmentVariable.java @@ -72,6 +72,7 @@ @Repeatable(EnabledIfEnvironmentVariables.class) @ExtendWith(EnabledIfEnvironmentVariableCondition.class) @API(status = STABLE, since = "5.1") +@SuppressWarnings("exports") public @interface EnabledIfEnvironmentVariable { /** diff --git a/junit-jupiter-api/src/main/java/org/junit/jupiter/api/condition/EnabledIfSystemProperty.java b/junit-jupiter-api/src/main/java/org/junit/jupiter/api/condition/EnabledIfSystemProperty.java index cd658e4e0aad..26cbcc10743a 100644 --- a/junit-jupiter-api/src/main/java/org/junit/jupiter/api/condition/EnabledIfSystemProperty.java +++ b/junit-jupiter-api/src/main/java/org/junit/jupiter/api/condition/EnabledIfSystemProperty.java @@ -72,6 +72,7 @@ @Repeatable(EnabledIfSystemProperties.class) @ExtendWith(EnabledIfSystemPropertyCondition.class) @API(status = STABLE, since = "5.1") +@SuppressWarnings("exports") public @interface EnabledIfSystemProperty { /** diff --git a/junit-jupiter-api/src/main/java/org/junit/jupiter/api/condition/EnabledOnJre.java b/junit-jupiter-api/src/main/java/org/junit/jupiter/api/condition/EnabledOnJre.java index c5ca85ea4dbb..ab6e18a193e4 100644 --- a/junit-jupiter-api/src/main/java/org/junit/jupiter/api/condition/EnabledOnJre.java +++ b/junit-jupiter-api/src/main/java/org/junit/jupiter/api/condition/EnabledOnJre.java @@ -71,6 +71,7 @@ @Documented @ExtendWith(EnabledOnJreCondition.class) @API(status = STABLE, since = "5.1") +@SuppressWarnings("exports") public @interface EnabledOnJre { /** diff --git a/junit-jupiter-api/src/main/java/org/junit/jupiter/api/condition/EnabledOnOs.java b/junit-jupiter-api/src/main/java/org/junit/jupiter/api/condition/EnabledOnOs.java index 2805fc40025e..de284cd68654 100644 --- a/junit-jupiter-api/src/main/java/org/junit/jupiter/api/condition/EnabledOnOs.java +++ b/junit-jupiter-api/src/main/java/org/junit/jupiter/api/condition/EnabledOnOs.java @@ -76,6 +76,7 @@ @Documented @ExtendWith(EnabledOnOsCondition.class) @API(status = STABLE, since = "5.1") +@SuppressWarnings("exports") public @interface EnabledOnOs { /** diff --git a/junit-jupiter-params/src/main/java/org/junit/jupiter/params/ParameterizedTest.java b/junit-jupiter-params/src/main/java/org/junit/jupiter/params/ParameterizedTest.java index 1fcdd80bb829..61fd036c0d9a 100644 --- a/junit-jupiter-params/src/main/java/org/junit/jupiter/params/ParameterizedTest.java +++ b/junit-jupiter-params/src/main/java/org/junit/jupiter/params/ParameterizedTest.java @@ -123,6 +123,7 @@ @API(status = STABLE, since = "5.7") @TestTemplate @ExtendWith(ParameterizedTestExtension.class) +@SuppressWarnings("exports") public @interface ParameterizedTest { /** diff --git a/junit-jupiter-params/src/main/java/org/junit/jupiter/params/converter/JavaTimeConversionPattern.java b/junit-jupiter-params/src/main/java/org/junit/jupiter/params/converter/JavaTimeConversionPattern.java index bbfab9e6f006..b6c03e76ca67 100644 --- a/junit-jupiter-params/src/main/java/org/junit/jupiter/params/converter/JavaTimeConversionPattern.java +++ b/junit-jupiter-params/src/main/java/org/junit/jupiter/params/converter/JavaTimeConversionPattern.java @@ -35,6 +35,7 @@ @Documented @API(status = STABLE, since = "5.7") @ConvertWith(JavaTimeArgumentConverter.class) +@SuppressWarnings("exports") public @interface JavaTimeConversionPattern { /** diff --git a/junit-jupiter-params/src/main/java/org/junit/jupiter/params/provider/CsvFileSource.java b/junit-jupiter-params/src/main/java/org/junit/jupiter/params/provider/CsvFileSource.java index 6c0a765c54e6..177790713575 100644 --- a/junit-jupiter-params/src/main/java/org/junit/jupiter/params/provider/CsvFileSource.java +++ b/junit-jupiter-params/src/main/java/org/junit/jupiter/params/provider/CsvFileSource.java @@ -66,6 +66,7 @@ @Documented @API(status = STABLE, since = "5.7") @ArgumentsSource(CsvFileArgumentsProvider.class) +@SuppressWarnings("exports") public @interface CsvFileSource { /** diff --git a/junit-jupiter-params/src/main/java/org/junit/jupiter/params/provider/CsvSource.java b/junit-jupiter-params/src/main/java/org/junit/jupiter/params/provider/CsvSource.java index be44973c9031..f5985b458cfe 100644 --- a/junit-jupiter-params/src/main/java/org/junit/jupiter/params/provider/CsvSource.java +++ b/junit-jupiter-params/src/main/java/org/junit/jupiter/params/provider/CsvSource.java @@ -68,6 +68,7 @@ @Documented @API(status = STABLE, since = "5.7") @ArgumentsSource(CsvArgumentsProvider.class) +@SuppressWarnings("exports") public @interface CsvSource { /** diff --git a/junit-jupiter-params/src/main/java/org/junit/jupiter/params/provider/EmptySource.java b/junit-jupiter-params/src/main/java/org/junit/jupiter/params/provider/EmptySource.java index 99023a73e9dd..553192a2d036 100644 --- a/junit-jupiter-params/src/main/java/org/junit/jupiter/params/provider/EmptySource.java +++ b/junit-jupiter-params/src/main/java/org/junit/jupiter/params/provider/EmptySource.java @@ -49,5 +49,6 @@ @Documented @API(status = STABLE, since = "5.7") @ArgumentsSource(EmptyArgumentsProvider.class) +@SuppressWarnings("exports") public @interface EmptySource { } diff --git a/junit-jupiter-params/src/main/java/org/junit/jupiter/params/provider/EnumSource.java b/junit-jupiter-params/src/main/java/org/junit/jupiter/params/provider/EnumSource.java index 2a215ae10865..ee98d2e5322a 100644 --- a/junit-jupiter-params/src/main/java/org/junit/jupiter/params/provider/EnumSource.java +++ b/junit-jupiter-params/src/main/java/org/junit/jupiter/params/provider/EnumSource.java @@ -51,6 +51,7 @@ @Documented @API(status = STABLE, since = "5.7") @ArgumentsSource(EnumArgumentsProvider.class) +@SuppressWarnings("exports") public @interface EnumSource { /** diff --git a/junit-jupiter-params/src/main/java/org/junit/jupiter/params/provider/MethodSource.java b/junit-jupiter-params/src/main/java/org/junit/jupiter/params/provider/MethodSource.java index 2d0ffe9eb8a5..dbd41bd66b7a 100644 --- a/junit-jupiter-params/src/main/java/org/junit/jupiter/params/provider/MethodSource.java +++ b/junit-jupiter-params/src/main/java/org/junit/jupiter/params/provider/MethodSource.java @@ -104,6 +104,7 @@ @Documented @API(status = STABLE, since = "5.7") @ArgumentsSource(MethodArgumentsProvider.class) +@SuppressWarnings("exports") public @interface MethodSource { /** diff --git a/junit-jupiter-params/src/main/java/org/junit/jupiter/params/provider/NullSource.java b/junit-jupiter-params/src/main/java/org/junit/jupiter/params/provider/NullSource.java index 283e78bf212c..c1b82b4842e4 100644 --- a/junit-jupiter-params/src/main/java/org/junit/jupiter/params/provider/NullSource.java +++ b/junit-jupiter-params/src/main/java/org/junit/jupiter/params/provider/NullSource.java @@ -39,5 +39,6 @@ @Documented @API(status = STABLE, since = "5.7") @ArgumentsSource(NullArgumentsProvider.class) +@SuppressWarnings("exports") public @interface NullSource { } diff --git a/junit-jupiter-params/src/main/java/org/junit/jupiter/params/provider/ValueSource.java b/junit-jupiter-params/src/main/java/org/junit/jupiter/params/provider/ValueSource.java index bc63eb037203..e349a07893ff 100644 --- a/junit-jupiter-params/src/main/java/org/junit/jupiter/params/provider/ValueSource.java +++ b/junit-jupiter-params/src/main/java/org/junit/jupiter/params/provider/ValueSource.java @@ -42,6 +42,7 @@ @Documented @API(status = STABLE, since = "5.7") @ArgumentsSource(ValueArgumentsProvider.class) +@SuppressWarnings("exports") public @interface ValueSource { /** diff --git a/junit-platform-engine/src/main/java/org/junit/platform/engine/support/filter/ClasspathScanningSupport.java b/junit-platform-engine/src/main/java/org/junit/platform/engine/support/filter/ClasspathScanningSupport.java index 9169ea77ead6..6699df7eddb6 100644 --- a/junit-platform-engine/src/main/java/org/junit/platform/engine/support/filter/ClasspathScanningSupport.java +++ b/junit-platform-engine/src/main/java/org/junit/platform/engine/support/filter/ClasspathScanningSupport.java @@ -63,6 +63,7 @@ public static Predicate buildClassNamePredicate(EngineDiscoveryRequest r * @deprecated Please use {@link org.junit.platform.engine.support.discovery.EngineDiscoveryRequestResolver} instead. */ @Deprecated + @SuppressWarnings("exports") public static ClassFilter buildClassFilter(EngineDiscoveryRequest request, Predicate> classPredicate) { return ClassFilter.of(buildClassNamePredicate(request), classPredicate); } From d7c3af599e75adb857e1fa70528a92165d99d3b3 Mon Sep 17 00:00:00 2001 From: Marc Philipp Date: Sat, 18 Feb 2023 18:13:35 +0100 Subject: [PATCH 0033/1473] Add missing explicit constructors for exported types With the exception of one deprecated type, public constructors are added to exported types to make their existence explicit. --- .../jupiter/migrationsupport/conditions/IgnoreCondition.java | 3 +++ .../migrationsupport/rules/ExpectedExceptionSupport.java | 3 +++ .../migrationsupport/rules/ExternalResourceSupport.java | 3 +++ .../junit/jupiter/migrationsupport/rules/VerifierSupport.java | 3 +++ .../jupiter/params/converter/SimpleArgumentConverter.java | 3 +++ .../engine/support/hierarchical/SingleTestExecutor.java | 1 + .../org/junit/platform/testkit/engine/ExecutionRecorder.java | 3 +++ 7 files changed, 19 insertions(+) diff --git a/junit-jupiter-migrationsupport/src/main/java/org/junit/jupiter/migrationsupport/conditions/IgnoreCondition.java b/junit-jupiter-migrationsupport/src/main/java/org/junit/jupiter/migrationsupport/conditions/IgnoreCondition.java index 477cedcb6213..c73546afc46e 100644 --- a/junit-jupiter-migrationsupport/src/main/java/org/junit/jupiter/migrationsupport/conditions/IgnoreCondition.java +++ b/junit-jupiter-migrationsupport/src/main/java/org/junit/jupiter/migrationsupport/conditions/IgnoreCondition.java @@ -38,6 +38,9 @@ public class IgnoreCondition implements ExecutionCondition { private static final ConditionEvaluationResult ENABLED = // ConditionEvaluationResult.enabled("@org.junit.Ignore is not present"); + public IgnoreCondition() { + } + /** * Containers/tests are disabled if {@link Ignore @Ignore} is present on * the test class or method. diff --git a/junit-jupiter-migrationsupport/src/main/java/org/junit/jupiter/migrationsupport/rules/ExpectedExceptionSupport.java b/junit-jupiter-migrationsupport/src/main/java/org/junit/jupiter/migrationsupport/rules/ExpectedExceptionSupport.java index 538a053b1e32..cd25a1190ff0 100644 --- a/junit-jupiter-migrationsupport/src/main/java/org/junit/jupiter/migrationsupport/rules/ExpectedExceptionSupport.java +++ b/junit-jupiter-migrationsupport/src/main/java/org/junit/jupiter/migrationsupport/rules/ExpectedExceptionSupport.java @@ -46,6 +46,9 @@ public class ExpectedExceptionSupport implements AfterEachCallback, TestExecutio private final TestRuleSupport support = new TestRuleSupport(ExpectedExceptionAdapter::new, ExpectedException.class); + public ExpectedExceptionSupport() { + } + @Override public void handleTestExecutionException(ExtensionContext context, Throwable throwable) throws Throwable { getStore(context).put(EXCEPTION_WAS_HANDLED, TRUE); diff --git a/junit-jupiter-migrationsupport/src/main/java/org/junit/jupiter/migrationsupport/rules/ExternalResourceSupport.java b/junit-jupiter-migrationsupport/src/main/java/org/junit/jupiter/migrationsupport/rules/ExternalResourceSupport.java index f31d6bc1f9dd..43ceaea7ed32 100644 --- a/junit-jupiter-migrationsupport/src/main/java/org/junit/jupiter/migrationsupport/rules/ExternalResourceSupport.java +++ b/junit-jupiter-migrationsupport/src/main/java/org/junit/jupiter/migrationsupport/rules/ExternalResourceSupport.java @@ -43,6 +43,9 @@ public class ExternalResourceSupport implements BeforeEachCallback, AfterEachCal private final TestRuleSupport support = new TestRuleSupport(ExternalResourceAdapter::new, ExternalResource.class); + public ExternalResourceSupport() { + } + @Override public void beforeEach(ExtensionContext context) throws Exception { this.support.beforeEach(context); diff --git a/junit-jupiter-migrationsupport/src/main/java/org/junit/jupiter/migrationsupport/rules/VerifierSupport.java b/junit-jupiter-migrationsupport/src/main/java/org/junit/jupiter/migrationsupport/rules/VerifierSupport.java index dca4784fddba..73781be2910b 100644 --- a/junit-jupiter-migrationsupport/src/main/java/org/junit/jupiter/migrationsupport/rules/VerifierSupport.java +++ b/junit-jupiter-migrationsupport/src/main/java/org/junit/jupiter/migrationsupport/rules/VerifierSupport.java @@ -42,6 +42,9 @@ public class VerifierSupport implements AfterEachCallback { private final TestRuleSupport support = new TestRuleSupport(VerifierAdapter::new, Verifier.class); + public VerifierSupport() { + } + @Override public void afterEach(ExtensionContext context) throws Exception { this.support.afterEach(context); diff --git a/junit-jupiter-params/src/main/java/org/junit/jupiter/params/converter/SimpleArgumentConverter.java b/junit-jupiter-params/src/main/java/org/junit/jupiter/params/converter/SimpleArgumentConverter.java index dc1a32ea8742..b6a0d15045f8 100644 --- a/junit-jupiter-params/src/main/java/org/junit/jupiter/params/converter/SimpleArgumentConverter.java +++ b/junit-jupiter-params/src/main/java/org/junit/jupiter/params/converter/SimpleArgumentConverter.java @@ -28,6 +28,9 @@ @API(status = STABLE, since = "5.7") public abstract class SimpleArgumentConverter implements ArgumentConverter { + public SimpleArgumentConverter() { + } + @Override public final Object convert(Object source, ParameterContext context) throws ArgumentConversionException { return convert(source, context.getParameter().getType()); diff --git a/junit-platform-engine/src/main/java/org/junit/platform/engine/support/hierarchical/SingleTestExecutor.java b/junit-platform-engine/src/main/java/org/junit/platform/engine/support/hierarchical/SingleTestExecutor.java index 6c87fb116517..0496a61e4ded 100644 --- a/junit-platform-engine/src/main/java/org/junit/platform/engine/support/hierarchical/SingleTestExecutor.java +++ b/junit-platform-engine/src/main/java/org/junit/platform/engine/support/hierarchical/SingleTestExecutor.java @@ -31,6 +31,7 @@ */ @Deprecated @API(status = DEPRECATED, since = "1.2") +@SuppressWarnings("missing-explicit-ctor") public class SingleTestExecutor { /** diff --git a/junit-platform-testkit/src/main/java/org/junit/platform/testkit/engine/ExecutionRecorder.java b/junit-platform-testkit/src/main/java/org/junit/platform/testkit/engine/ExecutionRecorder.java index b11a1e44b8fb..15db74b2b7d6 100644 --- a/junit-platform-testkit/src/main/java/org/junit/platform/testkit/engine/ExecutionRecorder.java +++ b/junit-platform-testkit/src/main/java/org/junit/platform/testkit/engine/ExecutionRecorder.java @@ -37,6 +37,9 @@ public class ExecutionRecorder implements EngineExecutionListener { private final List events = new CopyOnWriteArrayList<>(); + public ExecutionRecorder() { + } + /** * Record an {@link Event} for a dynamically registered container * or test. From 9494da3a4fa8110e5fa83aa1b4b29ed0f2ae695c Mon Sep 17 00:00:00 2001 From: Marc Philipp Date: Sat, 18 Feb 2023 18:14:35 +0100 Subject: [PATCH 0034/1473] Make TestKit export module dependency on Launcher Since types for the Launcher module are used in exported API of the TestKit module the `requires` statement is changed to be `transitive`. --- .../src/module/org.junit.platform.testkit/module-info.java | 2 +- .../jar-describe-module/junit-platform-testkit.expected.txt | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/junit-platform-testkit/src/module/org.junit.platform.testkit/module-info.java b/junit-platform-testkit/src/module/org.junit.platform.testkit/module-info.java index c0ae31818be7..2a53f5ad647c 100644 --- a/junit-platform-testkit/src/module/org.junit.platform.testkit/module-info.java +++ b/junit-platform-testkit/src/module/org.junit.platform.testkit/module-info.java @@ -19,7 +19,7 @@ requires transitive org.assertj.core; requires org.junit.platform.commons; requires transitive org.junit.platform.engine; - requires org.junit.platform.launcher; + requires transitive org.junit.platform.launcher; requires transitive org.opentest4j; // exports org.junit.platform.testkit; empty package diff --git a/platform-tooling-support-tests/projects/jar-describe-module/junit-platform-testkit.expected.txt b/platform-tooling-support-tests/projects/jar-describe-module/junit-platform-testkit.expected.txt index 2ad3e8d1c77b..c530e1bf68f8 100644 --- a/platform-tooling-support-tests/projects/jar-describe-module/junit-platform-testkit.expected.txt +++ b/platform-tooling-support-tests/projects/jar-describe-module/junit-platform-testkit.expected.txt @@ -5,6 +5,6 @@ requires org.apiguardian.api static transitive requires org.assertj.core transitive requires org.junit.platform.commons requires org.junit.platform.engine transitive -requires org.junit.platform.launcher +requires org.junit.platform.launcher transitive requires org.opentest4j transitive uses org.junit.platform.engine.TestEngine From e0e8778e4842433bcefee156524f0d32b7b6e592 Mon Sep 17 00:00:00 2001 From: Stefano Cordio Date: Tue, 21 Feb 2023 09:16:25 +0100 Subject: [PATCH 0035/1473] Add support for concrete Collection/Map types to EmptySource (#3159) This adds support for: * `Collection` and subtypes with a public no-arg constructor * `SortedSet` * `NavigableSet` * `Map` subtypes with a public no-arg constructor * `SortedMap` * `NavigableMap` Resolves #2791. --- .../release-notes-5.10.0-M1.adoc | 2 + .../asciidoc/user-guide/writing-tests.adoc | 10 +- .../provider/EmptyArgumentsProvider.java | 38 ++++ .../jupiter/params/provider/EmptySource.java | 9 +- .../ParameterizedTestIntegrationTests.java | 166 ++++++++++++++++-- 5 files changed, 202 insertions(+), 23 deletions(-) diff --git a/documentation/src/docs/asciidoc/release-notes/release-notes-5.10.0-M1.adoc b/documentation/src/docs/asciidoc/release-notes/release-notes-5.10.0-M1.adoc index 15f400b83b4e..6fd5d6d7ef2b 100644 --- a/documentation/src/docs/asciidoc/release-notes/release-notes-5.10.0-M1.adoc +++ b/documentation/src/docs/asciidoc/release-notes/release-notes-5.10.0-M1.adoc @@ -62,6 +62,8 @@ repository on GitHub. `@ParameterizedTest` invocation. * `DisplayNameGenerator` methods are now allowed to return `null`, in order to signal to fall back to the default display name generator. +* `@EmptySource` now supports additional types, including `Collection` and `Map` subtypes + with a public no-arg constructor. [[release-notes-5.10.0-M1-junit-vintage]] diff --git a/documentation/src/docs/asciidoc/user-guide/writing-tests.adoc b/documentation/src/docs/asciidoc/user-guide/writing-tests.adoc index 7b0c29a35a36..62642cb68f53 100644 --- a/documentation/src/docs/asciidoc/user-guide/writing-tests.adoc +++ b/documentation/src/docs/asciidoc/user-guide/writing-tests.adoc @@ -1257,10 +1257,12 @@ for parameterized tests that accept a single argument. method. - `@NullSource` cannot be used for a parameter that has a primitive type. * `{EmptySource}`: provides a single _empty_ argument to the annotated `@ParameterizedTest` - method for parameters of the following types: `java.lang.String`, `java.util.List`, - `java.util.Set`, `java.util.Map`, primitive arrays (e.g., `int[]`, `char[][]`, etc.), - object arrays (e.g.,`String[]`, `Integer[][]`, etc.). - - Subtypes of the supported types are not supported. + method for parameters of the following types: `java.lang.String`, `java.util.Collection` + and subtypes with a public no-arg constructor, `java.util.List`, `java.util.Set`, + `java.util.SortedSet`, `java.util.NavigableSet`, `java.util.Map` and subtypes with a + public no-arg constructor, `java.util.SortedMap`, `java.util.NavigableMap`, primitive + arrays (e.g., `int[]`, `char[][]`, etc.), object arrays (e.g.,`String[]`, `Integer[][]`, + etc.). * `{NullAndEmptySource}`: a _composed annotation_ that combines the functionality of `@NullSource` and `@EmptySource`. diff --git a/junit-jupiter-params/src/main/java/org/junit/jupiter/params/provider/EmptyArgumentsProvider.java b/junit-jupiter-params/src/main/java/org/junit/jupiter/params/provider/EmptyArgumentsProvider.java index 8debbb3a86ff..dc0f82b5b37f 100644 --- a/junit-jupiter-params/src/main/java/org/junit/jupiter/params/provider/EmptyArgumentsProvider.java +++ b/junit-jupiter-params/src/main/java/org/junit/jupiter/params/provider/EmptyArgumentsProvider.java @@ -11,13 +11,21 @@ package org.junit.jupiter.params.provider; import static org.junit.jupiter.params.provider.Arguments.arguments; +import static org.junit.platform.commons.util.ReflectionUtils.newInstance; import java.lang.reflect.Array; +import java.lang.reflect.Constructor; import java.lang.reflect.Method; +import java.util.Collection; import java.util.Collections; import java.util.List; import java.util.Map; +import java.util.NavigableMap; +import java.util.NavigableSet; +import java.util.Optional; import java.util.Set; +import java.util.SortedMap; +import java.util.SortedSet; import java.util.stream.Stream; import org.junit.jupiter.api.extension.ExtensionContext; @@ -44,15 +52,36 @@ public Stream provideArguments(ExtensionContext context) { if (String.class.equals(parameterType)) { return Stream.of(arguments("")); } + if (Collection.class.equals(parameterType)) { + return Stream.of(arguments(Collections.emptySet())); + } if (List.class.equals(parameterType)) { return Stream.of(arguments(Collections.emptyList())); } if (Set.class.equals(parameterType)) { return Stream.of(arguments(Collections.emptySet())); } + if (SortedSet.class.equals(parameterType)) { + return Stream.of(arguments(Collections.emptySortedSet())); + } + if (NavigableSet.class.equals(parameterType)) { + return Stream.of(arguments(Collections.emptyNavigableSet())); + } if (Map.class.equals(parameterType)) { return Stream.of(arguments(Collections.emptyMap())); } + if (SortedMap.class.equals(parameterType)) { + return Stream.of(arguments(Collections.emptySortedMap())); + } + if (NavigableMap.class.equals(parameterType)) { + return Stream.of(arguments(Collections.emptyNavigableMap())); + } + if (Collection.class.isAssignableFrom(parameterType) || Map.class.isAssignableFrom(parameterType)) { + Optional> defaultConstructor = getDefaultConstructor(parameterType); + if (defaultConstructor.isPresent()) { + return Stream.of(arguments(newInstance(defaultConstructor.get()))); + } + } if (parameterType.isArray()) { Object array = Array.newInstance(parameterType.getComponentType(), 0); return Stream.of(arguments(array)); @@ -63,4 +92,13 @@ public Stream provideArguments(ExtensionContext context) { testMethod.toGenericString(), parameterType.getName())); } + private static Optional> getDefaultConstructor(Class clazz) { + try { + return Optional.of(clazz.getConstructor()); + } + catch (NoSuchMethodException e) { + return Optional.empty(); + } + } + } diff --git a/junit-jupiter-params/src/main/java/org/junit/jupiter/params/provider/EmptySource.java b/junit-jupiter-params/src/main/java/org/junit/jupiter/params/provider/EmptySource.java index 553192a2d036..cd1104a1d6e8 100644 --- a/junit-jupiter-params/src/main/java/org/junit/jupiter/params/provider/EmptySource.java +++ b/junit-jupiter-params/src/main/java/org/junit/jupiter/params/provider/EmptySource.java @@ -27,13 +27,18 @@ *

Supported Parameter Types

* *

This argument source will only provide an empty argument for the following - * method parameter types. Subtypes of the supported types are not supported. + * method parameter types. * *

diff --git a/junit-jupiter-params/src/test/java/org/junit/jupiter/params/ParameterizedTestIntegrationTests.java b/junit-jupiter-params/src/test/java/org/junit/jupiter/params/ParameterizedTestIntegrationTests.java index 24d2a711960d..e4da1e737710 100644 --- a/junit-jupiter-params/src/test/java/org/junit/jupiter/params/ParameterizedTestIntegrationTests.java +++ b/junit-jupiter-params/src/test/java/org/junit/jupiter/params/ParameterizedTestIntegrationTests.java @@ -43,12 +43,21 @@ import java.lang.annotation.Target; import java.util.ArrayList; import java.util.Arrays; +import java.util.Collection; import java.util.HashMap; import java.util.HashSet; +import java.util.LinkedHashMap; import java.util.LinkedHashSet; +import java.util.LinkedList; import java.util.List; import java.util.Map; +import java.util.NavigableMap; +import java.util.NavigableSet; import java.util.Set; +import java.util.SortedMap; +import java.util.SortedSet; +import java.util.TreeMap; +import java.util.TreeSet; import java.util.stream.Stream; import org.junit.jupiter.api.AfterAll; @@ -459,24 +468,78 @@ void executesWithEmptySourceForStringAndTestInfo() { results.testEvents().succeeded().assertEventsMatchExactly(event(test(), displayName("[1] argument="))); } + /** + * @since 5.10 + */ + @Test + void executesWithEmptySourceForCollection() { + var results = execute("testWithEmptySourceForCollection", Collection.class); + results.testEvents().succeeded().assertEventsMatchExactly(event(test(), displayName("[1] argument=[]"))); + } + @Test void executesWithEmptySourceForList() { var results = execute("testWithEmptySourceForList", List.class); results.testEvents().succeeded().assertEventsMatchExactly(event(test(), displayName("[1] argument=[]"))); } + /** + * @since 5.10 + */ + @ParameterizedTest(name = "{1}") + @CsvSource({ // + "testWithEmptySourceForArrayList, java.util.ArrayList", // + "testWithEmptySourceForLinkedList, java.util.LinkedList"// + }) + void executesWithEmptySourceForListSubtype(String methodName, Class parameterType) { + var results = execute(methodName, parameterType); + results.testEvents().succeeded().assertEventsMatchExactly(event(test(), displayName("[1] argument=[]"))); + } + @Test void executesWithEmptySourceForSet() { var results = execute("testWithEmptySourceForSet", Set.class); results.testEvents().succeeded().assertEventsMatchExactly(event(test(), displayName("[1] argument=[]"))); } + /** + * @since 5.10 + */ + @ParameterizedTest(name = "{1}") + @CsvSource({ // + "testWithEmptySourceForSortedSet, java.util.SortedSet", // + "testWithEmptySourceForNavigableSet, java.util.NavigableSet", // + "testWithEmptySourceForHashSet, java.util.HashSet", // + "testWithEmptySourceForTreeSet, java.util.TreeSet", // + "testWithEmptySourceForLinkedHashSet, java.util.LinkedHashSet"// + }) + void executesWithEmptySourceForSetSubtype(String methodName, Class parameterType) { + var results = execute(methodName, parameterType); + results.testEvents().succeeded().assertEventsMatchExactly(event(test(), displayName("[1] argument=[]"))); + } + @Test void executesWithEmptySourceForMap() { var results = execute("testWithEmptySourceForMap", Map.class); results.testEvents().succeeded().assertEventsMatchExactly(event(test(), displayName("[1] argument={}"))); } + /** + * @since 5.10 + */ + @ParameterizedTest(name = "{1}") + @CsvSource({ // + "testWithEmptySourceForSortedMap, java.util.SortedMap", // + "testWithEmptySourceForNavigableMap, java.util.NavigableMap", // + "testWithEmptySourceForHashMap, java.util.HashMap", // + "testWithEmptySourceForTreeMap, java.util.TreeMap", // + "testWithEmptySourceForLinkedHashMap, java.util.LinkedHashMap"// + }) + void executesWithEmptySourceForMapSubtype(String methodName, Class parameterType) { + var results = execute(methodName, parameterType); + results.testEvents().succeeded().assertEventsMatchExactly(event(test(), displayName("[1] argument={}"))); + } + @Test void executesWithEmptySourceForOneDimensionalPrimitiveArray() { var results = execute("testWithEmptySourceForOneDimensionalPrimitiveArray", int[].class); @@ -515,10 +578,7 @@ void failsWithEmptySourceWithZeroFormalParameters() { @ParameterizedTest(name = "{1}") @CsvSource({ // "testWithEmptySourceForPrimitive, int", // - "testWithEmptySourceForUnsupportedReferenceType, java.lang.Integer", // - "testWithEmptySourceForUnsupportedListSubtype, java.util.ArrayList", // - "testWithEmptySourceForUnsupportedSetSubtype, java.util.HashSet", // - "testWithEmptySourceForUnsupportedMapSubtype, java.util.HashMap"// + "testWithEmptySourceForUnsupportedReferenceType, java.lang.Integer"// }) void failsWithEmptySourceForUnsupportedType(String methodName, Class parameterType) { execute(methodName, parameterType).containerEvents().failed().assertEventsMatchExactly(// @@ -561,6 +621,12 @@ void executesWithNullAndEmptySourceForList() { assertNullAndEmpty(results); } + @Test + void executesWithNullAndEmptySourceForArrayList() { + var results = execute("testWithNullAndEmptySourceForArrayList", ArrayList.class); + assertNullAndEmpty(results); + } + @Test void executesWithNullAndEmptySourceForOneDimensionalPrimitiveArray() { var results = execute("testWithNullAndEmptySourceForOneDimensionalPrimitiveArray", int[].class); @@ -982,18 +1048,66 @@ void testWithEmptySourceForStringAndTestInfo(String argument, TestInfo testInfo) assertThat(testInfo).isNotNull(); } + @ParameterizedTest + @EmptySource + void testWithEmptySourceForCollection(Collection argument) { + assertThat(argument).isEmpty(); + } + @ParameterizedTest @EmptySource void testWithEmptySourceForList(List argument) { assertThat(argument).isEmpty(); } + @ParameterizedTest + @EmptySource + void testWithEmptySourceForArrayList(ArrayList argument) { + assertThat(argument).isEmpty(); + } + + @ParameterizedTest + @EmptySource + void testWithEmptySourceForLinkedList(LinkedList argument) { + assertThat(argument).isEmpty(); + } + @ParameterizedTest @EmptySource void testWithEmptySourceForSet(Set argument) { assertThat(argument).isEmpty(); } + @ParameterizedTest + @EmptySource + void testWithEmptySourceForSortedSet(SortedSet argument) { + assertThat(argument).isEmpty(); + } + + @ParameterizedTest + @EmptySource + void testWithEmptySourceForNavigableSet(NavigableSet argument) { + assertThat(argument).isEmpty(); + } + + @ParameterizedTest + @EmptySource + void testWithEmptySourceForHashSet(HashSet argument) { + assertThat(argument).isEmpty(); + } + + @ParameterizedTest + @EmptySource + void testWithEmptySourceForTreeSet(TreeSet argument) { + assertThat(argument).isEmpty(); + } + + @ParameterizedTest + @EmptySource + void testWithEmptySourceForLinkedHashSet(LinkedHashSet argument) { + assertThat(argument).isEmpty(); + } + @ParameterizedTest @EmptySource void testWithEmptySourceForMap(Map argument) { @@ -1002,61 +1116,73 @@ void testWithEmptySourceForMap(Map argument) { @ParameterizedTest @EmptySource - void testWithEmptySourceForOneDimensionalPrimitiveArray(int[] argument) { + void testWithEmptySourceForSortedMap(SortedMap argument) { assertThat(argument).isEmpty(); } @ParameterizedTest @EmptySource - void testWithEmptySourceForOneDimensionalStringArray(String[] argument) { + void testWithEmptySourceForNavigableMap(NavigableMap argument) { assertThat(argument).isEmpty(); } @ParameterizedTest @EmptySource - void testWithEmptySourceForTwoDimensionalPrimitiveArray(int[][] argument) { + void testWithEmptySourceForHashMap(HashMap argument) { assertThat(argument).isEmpty(); } @ParameterizedTest @EmptySource - void testWithEmptySourceForTwoDimensionalStringArray(String[][] argument) { + void testWithEmptySourceForTreeMap(TreeMap argument) { assertThat(argument).isEmpty(); } @ParameterizedTest @EmptySource - void testWithEmptySourceWithZeroFormalParameters() { - fail("should not have been executed"); + void testWithEmptySourceForLinkedHashMap(LinkedHashMap argument) { + assertThat(argument).isEmpty(); } @ParameterizedTest @EmptySource - void testWithEmptySourceForPrimitive(int argument) { - fail("should not have been executed"); + void testWithEmptySourceForOneDimensionalPrimitiveArray(int[] argument) { + assertThat(argument).isEmpty(); } @ParameterizedTest @EmptySource - void testWithEmptySourceForUnsupportedReferenceType(Integer argument) { - fail("should not have been executed"); + void testWithEmptySourceForOneDimensionalStringArray(String[] argument) { + assertThat(argument).isEmpty(); } @ParameterizedTest @EmptySource - void testWithEmptySourceForUnsupportedListSubtype(ArrayList argument) { + void testWithEmptySourceForTwoDimensionalPrimitiveArray(int[][] argument) { + assertThat(argument).isEmpty(); + } + + @ParameterizedTest + @EmptySource + void testWithEmptySourceForTwoDimensionalStringArray(String[][] argument) { + assertThat(argument).isEmpty(); + } + + @ParameterizedTest + @EmptySource + void testWithEmptySourceWithZeroFormalParameters() { fail("should not have been executed"); } @ParameterizedTest @EmptySource - void testWithEmptySourceForUnsupportedSetSubtype(HashSet argument) { + void testWithEmptySourceForPrimitive(int argument) { fail("should not have been executed"); } @ParameterizedTest @EmptySource - void testWithEmptySourceForUnsupportedMapSubtype(HashMap argument) { + void testWithEmptySourceForUnsupportedReferenceType(Integer argument) { fail("should not have been executed"); } @@ -1083,6 +1209,12 @@ void testWithNullAndEmptySourceForList(List argument) { assertTrue(argument == null || argument.isEmpty()); } + @ParameterizedTest + @NullAndEmptySource + void testWithNullAndEmptySourceForArrayList(ArrayList argument) { + assertTrue(argument == null || argument.isEmpty()); + } + @ParameterizedTest @NullAndEmptySource void testWithNullAndEmptySourceForOneDimensionalPrimitiveArray(int[] argument) { From 4e64cf2a28481751ba19f7b57bc1e7db409e3e2a Mon Sep 17 00:00:00 2001 From: Marc Philipp Date: Tue, 21 Feb 2023 20:06:14 +0100 Subject: [PATCH 0036/1473] Run timeout tests via Gradle test task so they can be retried Since some of these tests occasionally fail on CI, in particular on Windows, they are now run via Gradle so that they are retried on CI automatically and reported as flaky rather than failing the build. --- documentation/documentation.gradle.kts | 14 +++++++++++--- .../src/test/java/example/AssertionsDemo.java | 12 ++++++++++++ documentation/src/test/java/example/SlowTests.java | 4 ++-- .../src/test/java/example/TimeoutDemo.java | 2 ++ .../test/kotlin/example/KotlinAssertionsDemo.kt | 5 +++++ .../junitbuild.testing-conventions.gradle.kts | 1 - .../junit-jupiter-engine.gradle.kts | 1 + .../junit-vintage-engine.gradle.kts | 1 + platform-tests/platform-tests.gradle.kts | 1 + 9 files changed, 35 insertions(+), 6 deletions(-) diff --git a/documentation/documentation.gradle.kts b/documentation/documentation.gradle.kts index 01b138459d86..c90891a62be6 100644 --- a/documentation/documentation.gradle.kts +++ b/documentation/documentation.gradle.kts @@ -13,6 +13,7 @@ plugins { id("org.asciidoctor.jvm.pdf") id("org.ajoberstar.git-publish") id("junitbuild.kotlin-library-conventions") + id("junitbuild.testing-conventions") } val modularProjects: List by rootProject @@ -37,7 +38,6 @@ dependencies { // in reports generated by the ApiReportGenerator. modularProjects.forEach { apiReport(it) } - testImplementation(projects.junitJupiter) testImplementation(projects.junitJupiterMigrationsupport) testImplementation(projects.junitPlatformConsole) testImplementation(projects.junitPlatformRunner) @@ -46,7 +46,6 @@ dependencies { testImplementation(kotlin("stdlib")) testImplementation(projects.junitVintageEngine) - testRuntimeOnly(libs.bundles.log4j) testRuntimeOnly(libs.apiguardian) { because("it's required to generate API tables") } @@ -121,6 +120,7 @@ tasks { args.addAll("--include-classname", ".*Tests") args.addAll("--include-classname", ".*Demo") args.addAll("--exclude-tag", "exclude") + args.addAll("--exclude-tag", "timeout") } register("consoleLauncher") { @@ -131,11 +131,19 @@ tasks { args.addAll("--include-classname", ".*Tests") args.addAll("--include-classname", ".*Demo") args.addAll("--exclude-tag", "exclude") + args.addAll("--exclude-tag", "timeout") } test { + include("**/*Demo.class") + (options as JUnitPlatformOptions).apply { + includeEngines("junit-vintage") + includeTags("timeout") + } + } + + check { dependsOn(consoleLauncherTest) - exclude("**/*") } val generateConsoleLauncherOptions by registering(JavaExec::class) { diff --git a/documentation/src/test/java/example/AssertionsDemo.java b/documentation/src/test/java/example/AssertionsDemo.java index a9cd383df6c1..476434da44f6 100644 --- a/documentation/src/test/java/example/AssertionsDemo.java +++ b/documentation/src/test/java/example/AssertionsDemo.java @@ -27,6 +27,7 @@ import example.domain.Person; import example.util.Calculator; +import org.junit.jupiter.api.Tag; import org.junit.jupiter.api.Test; class AssertionsDemo { @@ -91,6 +92,9 @@ void exceptionTesting() { assertEquals("/ by zero", exception.getMessage()); } + // end::user_guide[] + @Tag("timeout") + // tag::user_guide[] @Test void timeoutNotExceeded() { // The following assertion succeeds. @@ -99,6 +103,9 @@ void timeoutNotExceeded() { }); } + // end::user_guide[] + @Tag("timeout") + // tag::user_guide[] @Test void timeoutNotExceededWithResult() { // The following assertion succeeds, and returns the supplied object. @@ -108,6 +115,9 @@ void timeoutNotExceededWithResult() { assertEquals("a result", actualResult); } + // end::user_guide[] + @Tag("timeout") + // tag::user_guide[] @Test void timeoutNotExceededWithMethod() { // The following assertion invokes a method reference and returns an object. @@ -116,6 +126,7 @@ void timeoutNotExceededWithMethod() { } // end::user_guide[] + @Tag("timeout") @extensions.ExpectToFail // tag::user_guide[] @Test @@ -129,6 +140,7 @@ void timeoutExceeded() { } // end::user_guide[] + @Tag("timeout") @extensions.ExpectToFail // tag::user_guide[] @Test diff --git a/documentation/src/test/java/example/SlowTests.java b/documentation/src/test/java/example/SlowTests.java index f3c711e7b393..6fef77843145 100644 --- a/documentation/src/test/java/example/SlowTests.java +++ b/documentation/src/test/java/example/SlowTests.java @@ -10,15 +10,16 @@ package example; -// tag::user_guide[] import static org.junit.jupiter.api.parallel.ExecutionMode.SAME_THREAD; import java.util.stream.IntStream; import org.junit.jupiter.api.Disabled; +import org.junit.jupiter.api.Tag; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.parallel.Execution; +@Tag("exclude") @Disabled class SlowTests { @@ -123,4 +124,3 @@ private void foo() { IntStream.range(1, 100_000_000).mapToDouble(i -> Math.pow(i, i)).map(Math::sqrt).max(); } } -// end::user_guide[] diff --git a/documentation/src/test/java/example/TimeoutDemo.java b/documentation/src/test/java/example/TimeoutDemo.java index 8700f23e4bad..82e89ce48479 100644 --- a/documentation/src/test/java/example/TimeoutDemo.java +++ b/documentation/src/test/java/example/TimeoutDemo.java @@ -13,10 +13,12 @@ import java.util.concurrent.TimeUnit; import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Tag; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Timeout; import org.junit.jupiter.api.Timeout.ThreadMode; +@Tag("timeout") // tag::user_guide[] class TimeoutDemo { diff --git a/documentation/src/test/kotlin/example/KotlinAssertionsDemo.kt b/documentation/src/test/kotlin/example/KotlinAssertionsDemo.kt index 2870ae95ac25..0ea73f7f99d8 100644 --- a/documentation/src/test/kotlin/example/KotlinAssertionsDemo.kt +++ b/documentation/src/test/kotlin/example/KotlinAssertionsDemo.kt @@ -15,6 +15,7 @@ import example.domain.Person import example.util.Calculator import org.junit.jupiter.api.Assertions.assertEquals import org.junit.jupiter.api.Assertions.assertTrue +import org.junit.jupiter.api.Tag import org.junit.jupiter.api.Test import org.junit.jupiter.api.assertAll import org.junit.jupiter.api.assertDoesNotThrow @@ -76,6 +77,9 @@ class KotlinAssertionsDemo { ) } + // end::user_guide[] + @Tag("timeout") + // tag::user_guide[] @Test fun `timeout not exceeded testing`() { val fibonacciCalculator = FibonacciCalculator() @@ -86,6 +90,7 @@ class KotlinAssertionsDemo { } // end::user_guide[] + @Tag("timeout") @extensions.ExpectToFail // tag::user_guide[] @Test diff --git a/gradle/plugins/src/main/kotlin/junitbuild.testing-conventions.gradle.kts b/gradle/plugins/src/main/kotlin/junitbuild.testing-conventions.gradle.kts index 3a2c6a5e164d..a11546e4d937 100644 --- a/gradle/plugins/src/main/kotlin/junitbuild.testing-conventions.gradle.kts +++ b/gradle/plugins/src/main/kotlin/junitbuild.testing-conventions.gradle.kts @@ -79,7 +79,6 @@ dependencies { if (!project.name.startsWith("junit-jupiter")) { testImplementation(project(":junit-jupiter")) } - testImplementation(testFixtures(project(":junit-jupiter-api"))) testRuntimeOnly(project(":junit-platform-engine")) testRuntimeOnly(project(":junit-platform-jfr")) diff --git a/junit-jupiter-engine/junit-jupiter-engine.gradle.kts b/junit-jupiter-engine/junit-jupiter-engine.gradle.kts index 8d9112ccba1a..daa45cd35487 100644 --- a/junit-jupiter-engine/junit-jupiter-engine.gradle.kts +++ b/junit-jupiter-engine/junit-jupiter-engine.gradle.kts @@ -24,6 +24,7 @@ dependencies { testImplementation(libs.junit4) testImplementation(libs.kotlinx.coroutines) testImplementation(libs.groovy4) + testImplementation(testFixtures(projects.junitJupiterApi)) osgiVerification(projects.junitPlatformLauncher) } diff --git a/junit-vintage-engine/junit-vintage-engine.gradle.kts b/junit-vintage-engine/junit-vintage-engine.gradle.kts index 9f68f7de0475..c740522e0bf4 100644 --- a/junit-vintage-engine/junit-vintage-engine.gradle.kts +++ b/junit-vintage-engine/junit-vintage-engine.gradle.kts @@ -22,6 +22,7 @@ dependencies { testImplementation(projects.junitPlatformLauncher) testImplementation(projects.junitPlatformSuiteEngine) testImplementation(projects.junitPlatformTestkit) + testImplementation(testFixtures(projects.junitJupiterApi)) osgiVerification(projects.junitPlatformLauncher) } diff --git a/platform-tests/platform-tests.gradle.kts b/platform-tests/platform-tests.gradle.kts index 2990064246c6..ebdd20a6788a 100644 --- a/platform-tests/platform-tests.gradle.kts +++ b/platform-tests/platform-tests.gradle.kts @@ -33,6 +33,7 @@ dependencies { testImplementation(libs.joox) testImplementation(libs.openTestReporting.tooling) testImplementation(libs.bundles.xmlunit) + testImplementation(testFixtures(projects.junitJupiterApi)) // --- Test run-time dependencies --------------------------------------------- testRuntimeOnly(projects.junitVintageEngine) From 8bb3a4c2981b190152d88d446be62d3f065b5901 Mon Sep 17 00:00:00 2001 From: Marc Philipp Date: Mon, 27 Feb 2023 14:04:18 +0100 Subject: [PATCH 0037/1473] Prevent Dependabot from adding labels --- .github/dependabot.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.github/dependabot.yml b/.github/dependabot.yml index a6f0f7d26fdb..96ab685e82d0 100644 --- a/.github/dependabot.yml +++ b/.github/dependabot.yml @@ -12,7 +12,9 @@ updates: - gradle-plugin-portal schedule: interval: "weekly" + labels: [ ] - package-ecosystem: "github-actions" directory: "/" schedule: interval: "weekly" + labels: [ ] From 6de4938892b7ca0954181cd0db82cfc987a74f8d Mon Sep 17 00:00:00 2001 From: Marc Philipp Date: Tue, 28 Feb 2023 19:55:17 +0100 Subject: [PATCH 0038/1473] Add GH action to combine dependabot PRs --- .github/workflows/combine-prs.yml | 15 +++++++++++++++ 1 file changed, 15 insertions(+) create mode 100644 .github/workflows/combine-prs.yml diff --git a/.github/workflows/combine-prs.yml b/.github/workflows/combine-prs.yml new file mode 100644 index 000000000000..1669807c6890 --- /dev/null +++ b/.github/workflows/combine-prs.yml @@ -0,0 +1,15 @@ +name: Combine PRs + +on: + schedule: + - cron: '0 0 * * *' # Wednesday at 01:00 + workflow_dispatch: + +jobs: + combine-prs: + runs-on: ubuntu-latest + steps: + - name: combine-prs + uses: github/combine-prs@v2.0.0 + with: + github_token: ${{ secrets.GH_TOKEN }} From a2817c7d419691f0d4aad9fc53cafe912c877631 Mon Sep 17 00:00:00 2001 From: JUnit Build Master Date: Tue, 28 Feb 2023 20:06:11 +0100 Subject: [PATCH 0039/1473] Update Gradle plugins (#3179) * Bump me.champeau.jmh from 0.6.8 to 0.7.0 * Bump com.github.ben-manes.versions from 0.45.0 to 0.46.0 * Bump io.github.gradle-nexus.publish-plugin from 1.1.0 to 1.2.0 * Bump gradle.plugin.com.github.johnrengelman:shadow from 7.1.2 to 8.0.0 --- gradle/plugins/build.gradle.kts | 4 ++-- settings.gradle.kts | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/gradle/plugins/build.gradle.kts b/gradle/plugins/build.gradle.kts index 823a90510165..bc575c595282 100644 --- a/gradle/plugins/build.gradle.kts +++ b/gradle/plugins/build.gradle.kts @@ -2,7 +2,7 @@ import org.jetbrains.kotlin.gradle.tasks.KotlinCompile plugins { `kotlin-dsl` - id("com.github.ben-manes.versions") version "0.45.0" + id("com.github.ben-manes.versions") version "0.46.0" } repositories { @@ -14,7 +14,7 @@ dependencies { implementation("biz.aQute.bnd:biz.aQute.bnd.gradle:6.4.0") implementation("com.diffplug.spotless:spotless-plugin-gradle:6.15.0") implementation("com.github.ben-manes:gradle-versions-plugin:0.45.0") - implementation("gradle.plugin.com.github.johnrengelman:shadow:7.1.2") + implementation("gradle.plugin.com.github.johnrengelman:shadow:8.0.0") compileOnly("com.gradle:gradle-enterprise-gradle-plugin:3.12.3") // keep in sync with root settings.gradle.kts } diff --git a/settings.gradle.kts b/settings.gradle.kts index 3418ab49c4f3..07d42905f4fe 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -14,9 +14,9 @@ pluginManagement { // Check if workaround in documentation.gradle.kts can be removed when upgrading id("org.asciidoctor.jvm.convert") version "4.0.0-alpha.1" id("org.asciidoctor.jvm.pdf") version "4.0.0-alpha.1" - id("me.champeau.jmh") version "0.6.8" + id("me.champeau.jmh") version "0.7.0" id("io.spring.nohttp") version "0.0.11" - id("io.github.gradle-nexus.publish-plugin") version "1.1.0" + id("io.github.gradle-nexus.publish-plugin") version "1.2.0" } } From 739cb7c99e0a6a7dc9532ac676f5a689c574a80e Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 1 Mar 2023 07:48:11 +0100 Subject: [PATCH 0040/1473] Bump com.github.ben-manes:gradle-versions-plugin to 0.46.0 (#3174) Bumps [com.github.ben-manes:gradle-versions-plugin](https://github.com/ben-manes/gradle-versions-plugin) from 0.45.0 to 0.46.0. - [Release notes](https://github.com/ben-manes/gradle-versions-plugin/releases) - [Commits](https://github.com/ben-manes/gradle-versions-plugin/compare/v0.45.0...v0.46.0) --- updated-dependencies: - dependency-name: com.github.ben-manes:gradle-versions-plugin dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- gradle/plugins/build.gradle.kts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle/plugins/build.gradle.kts b/gradle/plugins/build.gradle.kts index bc575c595282..e499f8cca6f5 100644 --- a/gradle/plugins/build.gradle.kts +++ b/gradle/plugins/build.gradle.kts @@ -13,7 +13,7 @@ dependencies { implementation(kotlin("gradle-plugin")) implementation("biz.aQute.bnd:biz.aQute.bnd.gradle:6.4.0") implementation("com.diffplug.spotless:spotless-plugin-gradle:6.15.0") - implementation("com.github.ben-manes:gradle-versions-plugin:0.45.0") + implementation("com.github.ben-manes:gradle-versions-plugin:0.46.0") implementation("gradle.plugin.com.github.johnrengelman:shadow:8.0.0") compileOnly("com.gradle:gradle-enterprise-gradle-plugin:3.12.3") // keep in sync with root settings.gradle.kts } From ac8a5bd6c70244a0a5ba8073469452d20af3f671 Mon Sep 17 00:00:00 2001 From: Marc Philipp Date: Wed, 1 Mar 2023 20:02:33 +0100 Subject: [PATCH 0041/1473] Re-enable CodeQL check for Java (#3163) --- .github/workflows/codeql-analysis.yml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.github/workflows/codeql-analysis.yml b/.github/workflows/codeql-analysis.yml index 61e9b0b52914..82ee018479e3 100644 --- a/.github/workflows/codeql-analysis.yml +++ b/.github/workflows/codeql-analysis.yml @@ -24,7 +24,7 @@ jobs: fail-fast: false matrix: language: - # - java # Currently broken because it doesn't support Kotlin 1.8.10, yet (https://github.com/github/codeql/discussions/11460#discussioncomment-4879731) + - java - javascript steps: - name: Check out repository @@ -33,6 +33,7 @@ jobs: uses: github/codeql-action/init@v2 with: languages: ${{ matrix.language }} + tools: latest - name: Build uses: ./.github/actions/run-gradle with: From bac21211e4af9c97d208acf83bb943ae422addf3 Mon Sep 17 00:00:00 2001 From: Marc Philipp Date: Sat, 4 Mar 2023 14:09:45 +0100 Subject: [PATCH 0042/1473] Upgradle to 8.0.2 --- gradle/wrapper/gradle-wrapper.properties | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index f396aaac2d31..19acfb4ef2f6 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,7 +1,7 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionSha256Sum=1b6b558be93f29438d3df94b7dfee02e794b94d9aca4611a92cdb79b6b88e909 -distributionUrl=https\://services.gradle.org/distributions/gradle-8.0.1-bin.zip +distributionSha256Sum=ff7bf6a86f09b9b2c40bb8f48b25fc19cf2b2664fd1d220cd7ab833ec758d0d7 +distributionUrl=https\://services.gradle.org/distributions/gradle-8.0.2-bin.zip networkTimeout=10000 zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists From 6976f0dd4d5789dfd288ca9183ab05079e4fd98a Mon Sep 17 00:00:00 2001 From: Marc Philipp Date: Sat, 4 Mar 2023 14:20:11 +0100 Subject: [PATCH 0043/1473] Fix comment --- .github/workflows/combine-prs.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/combine-prs.yml b/.github/workflows/combine-prs.yml index 1669807c6890..95cb7ed5dce5 100644 --- a/.github/workflows/combine-prs.yml +++ b/.github/workflows/combine-prs.yml @@ -2,7 +2,7 @@ name: Combine PRs on: schedule: - - cron: '0 0 * * *' # Wednesday at 01:00 + - cron: '0 0 * * *' # Every day at 00:00 UTC workflow_dispatch: jobs: From 557c419c1723791b7750543f69a64b4632102518 Mon Sep 17 00:00:00 2001 From: Benedikt Ritter Date: Thu, 9 Mar 2023 08:28:23 +0100 Subject: [PATCH 0044/1473] Model parameters using org.gradlex.build-parameters (#3170) Introduces the org.gradlex.build-parameters plugin to model parameters that can be supplied to this build. For this the existing build logic in gradle/plugins is moved to a submodule called 'common' and a new module called 'build-parameters' is introduced. This way, build logic can access build parameters using the `buildParameters` pre-compiled accessor in Kotlin. Occurences of project.findProperty as well as project.hasProperty are replaced by properly modeled build parameters. Since validation of parameters is not turned off, the build-parameters plugin will fail the build is a parameter is supplied which is not modeled. For that reason, any other parameters, such as signing or deployment parameters that are supplied by developers only during releasing need to be added before this can be merged. --- .editorconfig | 3 + .github/actions/run-gradle/action.yml | 2 +- .github/workflows/cross-version.yml | 6 +- .github/workflows/main.yml | 8 +- README.md | 2 +- build.gradle.kts | 2 +- documentation/documentation.gradle.kts | 3 +- .../plugins/build-parameters/build.gradle.kts | 81 +++++++++++++++++++ gradle/plugins/{ => common}/build.gradle.kts | 1 + .../ConfigurationContainerExtensions.kt | 0 .../src/main/kotlin/JavaLibraryExtension.kt | 0 .../{ => common}/src/main/kotlin/License.kt | 0 .../src/main/kotlin/ProjectExtensions.kt | 0 .../src/main/kotlin/TaskExtensions.kt | 0 .../junitbuild.base-conventions.gradle.kts | 0 .../junitbuild.build-metadata.gradle.kts | 0 ...itbuild.dependency-update-check.gradle.kts | 0 ....jacoco-aggregation-conventions.gradle.kts | 0 .../junitbuild.jacoco-conventions.gradle.kts | 5 +- ...itbuild.jacoco-java-conventions.gradle.kts | 4 +- ...tbuild.java-library-conventions.gradle.kts | 0 ...uild.java-multi-release-sources.gradle.kts | 0 .../junitbuild.java-repackage-jars.gradle.kts | 0 ...uild.java-toolchain-conventions.gradle.kts | 7 +- ...junitbuild.junit4-compatibility.gradle.kts | 0 ...uild.kotlin-library-conventions.gradle.kts | 0 .../junitbuild.osgi-conventions.gradle.kts | 0 ...nitbuild.publishing-conventions.gradle.kts | 4 +- .../junitbuild.shadow-conventions.gradle.kts | 0 ...junitbuild.spotless-conventions.gradle.kts | 0 .../junitbuild.temp-maven-repo.gradle.kts | 0 .../junitbuild.testing-conventions.gradle.kts | 21 +++-- .../exec/ClasspathSystemPropertyProvider.kt | 0 .../junitbuild/exec/RunConsoleLauncher.kt | 0 .../kotlin/junitbuild/java/ExecJarAction.kt | 0 .../junitbuild/java/ModuleCompileOptions.kt | 0 .../java/ModulePathArgumentProvider.kt | 0 .../java/PatchModuleArgumentProvider.kt | 0 .../junitbuild/java/WriteArtifactsFile.kt | 0 .../ModuleSpecificJavadocFileOption.kt | 0 gradle/plugins/settings.gradle.kts | 2 + .../platform-tooling-support-tests.gradle.kts | 5 +- settings.gradle.kts | 30 +++---- 43 files changed, 136 insertions(+), 50 deletions(-) create mode 100644 gradle/plugins/build-parameters/build.gradle.kts rename gradle/plugins/{ => common}/build.gradle.kts (94%) rename gradle/plugins/{ => common}/src/main/kotlin/ConfigurationContainerExtensions.kt (100%) rename gradle/plugins/{ => common}/src/main/kotlin/JavaLibraryExtension.kt (100%) rename gradle/plugins/{ => common}/src/main/kotlin/License.kt (100%) rename gradle/plugins/{ => common}/src/main/kotlin/ProjectExtensions.kt (100%) rename gradle/plugins/{ => common}/src/main/kotlin/TaskExtensions.kt (100%) rename gradle/plugins/{ => common}/src/main/kotlin/junitbuild.base-conventions.gradle.kts (100%) rename gradle/plugins/{ => common}/src/main/kotlin/junitbuild.build-metadata.gradle.kts (100%) rename gradle/plugins/{ => common}/src/main/kotlin/junitbuild.dependency-update-check.gradle.kts (100%) rename gradle/plugins/{ => common}/src/main/kotlin/junitbuild.jacoco-aggregation-conventions.gradle.kts (100%) rename gradle/plugins/{ => common}/src/main/kotlin/junitbuild.jacoco-conventions.gradle.kts (61%) rename gradle/plugins/{ => common}/src/main/kotlin/junitbuild.jacoco-java-conventions.gradle.kts (90%) rename gradle/plugins/{ => common}/src/main/kotlin/junitbuild.java-library-conventions.gradle.kts (100%) rename gradle/plugins/{ => common}/src/main/kotlin/junitbuild.java-multi-release-sources.gradle.kts (100%) rename gradle/plugins/{ => common}/src/main/kotlin/junitbuild.java-repackage-jars.gradle.kts (100%) rename gradle/plugins/{ => common}/src/main/kotlin/junitbuild.java-toolchain-conventions.gradle.kts (87%) rename gradle/plugins/{ => common}/src/main/kotlin/junitbuild.junit4-compatibility.gradle.kts (100%) rename gradle/plugins/{ => common}/src/main/kotlin/junitbuild.kotlin-library-conventions.gradle.kts (100%) rename gradle/plugins/{ => common}/src/main/kotlin/junitbuild.osgi-conventions.gradle.kts (100%) rename gradle/plugins/{ => common}/src/main/kotlin/junitbuild.publishing-conventions.gradle.kts (94%) rename gradle/plugins/{ => common}/src/main/kotlin/junitbuild.shadow-conventions.gradle.kts (100%) rename gradle/plugins/{ => common}/src/main/kotlin/junitbuild.spotless-conventions.gradle.kts (100%) rename gradle/plugins/{ => common}/src/main/kotlin/junitbuild.temp-maven-repo.gradle.kts (100%) rename gradle/plugins/{ => common}/src/main/kotlin/junitbuild.testing-conventions.gradle.kts (75%) rename gradle/plugins/{ => common}/src/main/kotlin/junitbuild/exec/ClasspathSystemPropertyProvider.kt (100%) rename gradle/plugins/{ => common}/src/main/kotlin/junitbuild/exec/RunConsoleLauncher.kt (100%) rename gradle/plugins/{ => common}/src/main/kotlin/junitbuild/java/ExecJarAction.kt (100%) rename gradle/plugins/{ => common}/src/main/kotlin/junitbuild/java/ModuleCompileOptions.kt (100%) rename gradle/plugins/{ => common}/src/main/kotlin/junitbuild/java/ModulePathArgumentProvider.kt (100%) rename gradle/plugins/{ => common}/src/main/kotlin/junitbuild/java/PatchModuleArgumentProvider.kt (100%) rename gradle/plugins/{ => common}/src/main/kotlin/junitbuild/java/WriteArtifactsFile.kt (100%) rename gradle/plugins/{ => common}/src/main/kotlin/junitbuild/javadoc/ModuleSpecificJavadocFileOption.kt (100%) diff --git a/.editorconfig b/.editorconfig index 063e4a874109..2a4ad4ec1b55 100644 --- a/.editorconfig +++ b/.editorconfig @@ -1,3 +1,6 @@ [*.{kt,kts}] ij_kotlin_allow_trailing_comma = false ij_kotlin_allow_trailing_comma_on_call_site = false + +[*.kts] +indent_style = tab diff --git a/.github/actions/run-gradle/action.yml b/.github/actions/run-gradle/action.yml index 501393593a6c..a4b1bc129f6c 100644 --- a/.github/actions/run-gradle/action.yml +++ b/.github/actions/run-gradle/action.yml @@ -19,7 +19,7 @@ runs: with: arguments: | -Porg.gradle.java.installations.auto-download=false - -PenablePredictiveTestSelection=${{ github.event_name == 'pull_request' }} + -Penterprise.predictiveTestSelection.enabled=${{ github.event_name == 'pull_request' }} "-Dscan.value.GitHub job=${{ github.job }}" javaToolchains ${{ inputs.arguments }} diff --git a/.github/workflows/cross-version.yml b/.github/workflows/cross-version.yml index 4786e5b3c07f..13c93692b87a 100644 --- a/.github/workflows/cross-version.yml +++ b/.github/workflows/cross-version.yml @@ -10,9 +10,9 @@ on: - '*' env: - ORG_GRADLE_PROJECT_enableTestDistribution: true - ORG_GRADLE_PROJECT_junitBuildCacheUsername: ${{ secrets.BUILD_CACHE_USERNAME }} - ORG_GRADLE_PROJECT_junitBuildCachePassword: ${{ secrets.BUILD_CACHE_PASSWORD }} + ENTERPRISE_TESTDISTRIBUTION_ENABLED: true + BUILDCACHE_USERNAME: ${{ secrets.BUILD_CACHE_USERNAME }} + BUILDCACHE_PASSWORD: ${{ secrets.BUILD_CACHE_PASSWORD }} GRADLE_ENTERPRISE_ACCESS_KEY: ${{ secrets.GRADLE_ENTERPRISE_ACCESS_KEY }} jobs: diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 25b8e9db7f72..676ec1a2f87a 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -10,9 +10,9 @@ on: - '*' env: - ORG_GRADLE_PROJECT_enableTestDistribution: true - ORG_GRADLE_PROJECT_junitBuildCacheUsername: ${{ secrets.BUILD_CACHE_USERNAME }} - ORG_GRADLE_PROJECT_junitBuildCachePassword: ${{ secrets.BUILD_CACHE_PASSWORD }} + ENTERPRISE_TESTDISTRIBUTION_ENABLED: true + BUILDCACHE_USERNAME: ${{ secrets.BUILD_CACHE_USERNAME }} + BUILDCACHE_PASSWORD: ${{ secrets.BUILD_CACHE_PASSWORD }} GRADLE_ENTERPRISE_ACCESS_KEY: ${{ secrets.GRADLE_ENTERPRISE_ACCESS_KEY }} jobs: @@ -38,7 +38,7 @@ jobs: uses: ./.github/actions/main-build with: arguments: | - -PenableJaCoCo + -Ptesting.enableJaCoCo build jacocoRootReport prepareDocsForUploadToGhPages diff --git a/README.md b/README.md index 7b4bb98a40c3..aa095c5e67be 100644 --- a/README.md +++ b/README.md @@ -43,7 +43,7 @@ builds of the next OpenJDK. Code coverage using [JaCoCo] for the latest build is available on [Codecov]. A code coverage report can also be generated locally via the [Gradle Wrapper] by -executing `./gradlew -PenableJaCoCo clean jacocoRootReport`. The results will be available +executing `./gradlew -Ptesting.enableJaCoCo clean jacocoRootReport`. The results will be available in `build/reports/jacoco/jacocoRootReport/html/index.html`. ## Gradle Enterprise diff --git a/build.gradle.kts b/build.gradle.kts index 7662a5524b31..f1cf305950ea 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -61,5 +61,5 @@ nexusPublishing { } nohttp { - source.exclude("**/.gradle/**", "gradle/plugins/build/**") + source.exclude("**/.gradle/**", "gradle/plugins/**/build/**") } diff --git a/documentation/documentation.gradle.kts b/documentation/documentation.gradle.kts index c90891a62be6..2c2ac600ba6a 100644 --- a/documentation/documentation.gradle.kts +++ b/documentation/documentation.gradle.kts @@ -12,6 +12,7 @@ plugins { id("org.asciidoctor.jvm.convert") id("org.asciidoctor.jvm.pdf") id("org.ajoberstar.git-publish") + id("junitbuild.build-parameters") id("junitbuild.kotlin-library-conventions") id("junitbuild.testing-conventions") } @@ -71,7 +72,7 @@ val snapshot = rootProject.version.toString().contains("SNAPSHOT") val docsVersion = if (snapshot) "snapshot" else rootProject.version val releaseBranch = if (snapshot) "HEAD" else "r${rootProject.version}" val docsDir = file("$buildDir/ghpages-docs") -val replaceCurrentDocs = project.hasProperty("replaceCurrentDocs") +val replaceCurrentDocs = buildParameters.documentation.replaceCurrentDocs val uploadPdfs = !snapshot val userGuidePdfFileName = "junit-user-guide-${rootProject.version}.pdf" val ota4jDocVersion = if (libs.versions.opentest4j.get().contains("SNAPSHOT")) "snapshot" else libs.versions.opentest4j.get() diff --git a/gradle/plugins/build-parameters/build.gradle.kts b/gradle/plugins/build-parameters/build.gradle.kts new file mode 100644 index 000000000000..d246161af8fa --- /dev/null +++ b/gradle/plugins/build-parameters/build.gradle.kts @@ -0,0 +1,81 @@ +plugins { + id("org.gradlex.build-parameters") version "1.4.3" +} + +group = "junitbuild" + +buildParameters { + pluginId("junitbuild.build-parameters") + bool("ci") { + description.set("Whether or not this build is running in a CI environment") + defaultValue.set(false) + fromEnvironment() + } + integer("javaToolchainVersion") { + description.set("Defines the Java toolchain version to use for compiling code") + } + group("buildCache") { + string("username") { + description.set("Username to authenticate with the remote build cache") + fromEnvironment() + } + string("password") { + description.set("Password to authenticate with the remote build cache") + fromEnvironment() + } + string("url") { + description.set("URL to the remote build cache") + fromEnvironment() + } + } + group("documentation") { + description.set("Parameters controlling how the documentation is built") + bool("replaceCurrentDocs") { + description.set("The documentation that is being deployed will replace what's currently deployed as 'current'") + defaultValue.set(false) + } + } + group("enterprise") { + description.set("Parameters controlling Gradle Enterprise features") + group("predictiveTestSelection") { + bool("enabled") { + description.set("Whether or not to use Predictive Test Selection for selecting tests to execute") + defaultValue.set(true) + } + } + group("testDistribution") { + bool("enabled") { + description.set("Whether or not to use Test Distribution for executing tests") + defaultValue.set(false) + fromEnvironment() + } + integer("maxLocalExecutors") { + description.set("How many local executors to use for executing tests") + defaultValue.set(1) + } + integer("maxRemoteExecutors") { + description.set("How many remote executors to request for executing tests") + } + } + } + group("testing") { + description.set("Testing related parameters") + bool("enableJaCoCo") { + description.set("Enables JaCoCo test coverage reporting") + defaultValue.set(false) + } + bool("enableJFR") { + description.set("Enables Java Flight Recorder functionality") + defaultValue.set(false) + } + integer("retries") { + description.set("Configures the number of times failing test are retried") + } + } +} + +tasks { + withType().configureEach { + options.release.set(11) + } +} diff --git a/gradle/plugins/build.gradle.kts b/gradle/plugins/common/build.gradle.kts similarity index 94% rename from gradle/plugins/build.gradle.kts rename to gradle/plugins/common/build.gradle.kts index e499f8cca6f5..88ec294b01fd 100644 --- a/gradle/plugins/build.gradle.kts +++ b/gradle/plugins/common/build.gradle.kts @@ -10,6 +10,7 @@ repositories { } dependencies { + implementation(project(":build-parameters")) implementation(kotlin("gradle-plugin")) implementation("biz.aQute.bnd:biz.aQute.bnd.gradle:6.4.0") implementation("com.diffplug.spotless:spotless-plugin-gradle:6.15.0") diff --git a/gradle/plugins/src/main/kotlin/ConfigurationContainerExtensions.kt b/gradle/plugins/common/src/main/kotlin/ConfigurationContainerExtensions.kt similarity index 100% rename from gradle/plugins/src/main/kotlin/ConfigurationContainerExtensions.kt rename to gradle/plugins/common/src/main/kotlin/ConfigurationContainerExtensions.kt diff --git a/gradle/plugins/src/main/kotlin/JavaLibraryExtension.kt b/gradle/plugins/common/src/main/kotlin/JavaLibraryExtension.kt similarity index 100% rename from gradle/plugins/src/main/kotlin/JavaLibraryExtension.kt rename to gradle/plugins/common/src/main/kotlin/JavaLibraryExtension.kt diff --git a/gradle/plugins/src/main/kotlin/License.kt b/gradle/plugins/common/src/main/kotlin/License.kt similarity index 100% rename from gradle/plugins/src/main/kotlin/License.kt rename to gradle/plugins/common/src/main/kotlin/License.kt diff --git a/gradle/plugins/src/main/kotlin/ProjectExtensions.kt b/gradle/plugins/common/src/main/kotlin/ProjectExtensions.kt similarity index 100% rename from gradle/plugins/src/main/kotlin/ProjectExtensions.kt rename to gradle/plugins/common/src/main/kotlin/ProjectExtensions.kt diff --git a/gradle/plugins/src/main/kotlin/TaskExtensions.kt b/gradle/plugins/common/src/main/kotlin/TaskExtensions.kt similarity index 100% rename from gradle/plugins/src/main/kotlin/TaskExtensions.kt rename to gradle/plugins/common/src/main/kotlin/TaskExtensions.kt diff --git a/gradle/plugins/src/main/kotlin/junitbuild.base-conventions.gradle.kts b/gradle/plugins/common/src/main/kotlin/junitbuild.base-conventions.gradle.kts similarity index 100% rename from gradle/plugins/src/main/kotlin/junitbuild.base-conventions.gradle.kts rename to gradle/plugins/common/src/main/kotlin/junitbuild.base-conventions.gradle.kts diff --git a/gradle/plugins/src/main/kotlin/junitbuild.build-metadata.gradle.kts b/gradle/plugins/common/src/main/kotlin/junitbuild.build-metadata.gradle.kts similarity index 100% rename from gradle/plugins/src/main/kotlin/junitbuild.build-metadata.gradle.kts rename to gradle/plugins/common/src/main/kotlin/junitbuild.build-metadata.gradle.kts diff --git a/gradle/plugins/src/main/kotlin/junitbuild.dependency-update-check.gradle.kts b/gradle/plugins/common/src/main/kotlin/junitbuild.dependency-update-check.gradle.kts similarity index 100% rename from gradle/plugins/src/main/kotlin/junitbuild.dependency-update-check.gradle.kts rename to gradle/plugins/common/src/main/kotlin/junitbuild.dependency-update-check.gradle.kts diff --git a/gradle/plugins/src/main/kotlin/junitbuild.jacoco-aggregation-conventions.gradle.kts b/gradle/plugins/common/src/main/kotlin/junitbuild.jacoco-aggregation-conventions.gradle.kts similarity index 100% rename from gradle/plugins/src/main/kotlin/junitbuild.jacoco-aggregation-conventions.gradle.kts rename to gradle/plugins/common/src/main/kotlin/junitbuild.jacoco-aggregation-conventions.gradle.kts diff --git a/gradle/plugins/src/main/kotlin/junitbuild.jacoco-conventions.gradle.kts b/gradle/plugins/common/src/main/kotlin/junitbuild.jacoco-conventions.gradle.kts similarity index 61% rename from gradle/plugins/src/main/kotlin/junitbuild.jacoco-conventions.gradle.kts rename to gradle/plugins/common/src/main/kotlin/junitbuild.jacoco-conventions.gradle.kts index 03e5c8851345..ef29df71f8c0 100644 --- a/gradle/plugins/src/main/kotlin/junitbuild.jacoco-conventions.gradle.kts +++ b/gradle/plugins/common/src/main/kotlin/junitbuild.jacoco-conventions.gradle.kts @@ -1,13 +1,12 @@ plugins { jacoco + id("junitbuild.build-parameters") } -val enableJaCoCo = project.hasProperty("enableJaCoCo") - jacoco { toolVersion = requiredVersionFromLibs("jacoco") } tasks.withType().configureEach { - enabled = enableJaCoCo + enabled = buildParameters.testing.enableJaCoCo } diff --git a/gradle/plugins/src/main/kotlin/junitbuild.jacoco-java-conventions.gradle.kts b/gradle/plugins/common/src/main/kotlin/junitbuild.jacoco-java-conventions.gradle.kts similarity index 90% rename from gradle/plugins/src/main/kotlin/junitbuild.jacoco-java-conventions.gradle.kts rename to gradle/plugins/common/src/main/kotlin/junitbuild.jacoco-java-conventions.gradle.kts index 42f7c754fd4e..7bc6a3a8e214 100644 --- a/gradle/plugins/src/main/kotlin/junitbuild.jacoco-java-conventions.gradle.kts +++ b/gradle/plugins/common/src/main/kotlin/junitbuild.jacoco-java-conventions.gradle.kts @@ -3,15 +3,15 @@ import org.gradle.api.attributes.LibraryElements.LIBRARY_ELEMENTS_ATTRIBUTE plugins { java + id("junitbuild.build-parameters") id("junitbuild.jacoco-conventions") } val mavenizedProjects: List by rootProject.extra -val enableJaCoCo = project.hasProperty("enableJaCoCo") tasks.withType().configureEach { configure { - isEnabled = enableJaCoCo + isEnabled = buildParameters.testing.enableJaCoCo } } diff --git a/gradle/plugins/src/main/kotlin/junitbuild.java-library-conventions.gradle.kts b/gradle/plugins/common/src/main/kotlin/junitbuild.java-library-conventions.gradle.kts similarity index 100% rename from gradle/plugins/src/main/kotlin/junitbuild.java-library-conventions.gradle.kts rename to gradle/plugins/common/src/main/kotlin/junitbuild.java-library-conventions.gradle.kts diff --git a/gradle/plugins/src/main/kotlin/junitbuild.java-multi-release-sources.gradle.kts b/gradle/plugins/common/src/main/kotlin/junitbuild.java-multi-release-sources.gradle.kts similarity index 100% rename from gradle/plugins/src/main/kotlin/junitbuild.java-multi-release-sources.gradle.kts rename to gradle/plugins/common/src/main/kotlin/junitbuild.java-multi-release-sources.gradle.kts diff --git a/gradle/plugins/src/main/kotlin/junitbuild.java-repackage-jars.gradle.kts b/gradle/plugins/common/src/main/kotlin/junitbuild.java-repackage-jars.gradle.kts similarity index 100% rename from gradle/plugins/src/main/kotlin/junitbuild.java-repackage-jars.gradle.kts rename to gradle/plugins/common/src/main/kotlin/junitbuild.java-repackage-jars.gradle.kts diff --git a/gradle/plugins/src/main/kotlin/junitbuild.java-toolchain-conventions.gradle.kts b/gradle/plugins/common/src/main/kotlin/junitbuild.java-toolchain-conventions.gradle.kts similarity index 87% rename from gradle/plugins/src/main/kotlin/junitbuild.java-toolchain-conventions.gradle.kts rename to gradle/plugins/common/src/main/kotlin/junitbuild.java-toolchain-conventions.gradle.kts index 87c334d2621e..5cd96cf5180e 100644 --- a/gradle/plugins/src/main/kotlin/junitbuild.java-toolchain-conventions.gradle.kts +++ b/gradle/plugins/common/src/main/kotlin/junitbuild.java-toolchain-conventions.gradle.kts @@ -1,9 +1,12 @@ import org.jetbrains.kotlin.gradle.dsl.KotlinJvmProjectExtension +plugins { + id("junitbuild.build-parameters") +} + project.pluginManager.withPlugin("java") { - val javaToolchainVersion: String? by project val defaultLanguageVersion = JavaLanguageVersion.of(17) - val javaLanguageVersion = javaToolchainVersion?.let { JavaLanguageVersion.of(it) } ?: defaultLanguageVersion + val javaLanguageVersion = buildParameters.javaToolchainVersion.map { JavaLanguageVersion.of(it) }.getOrElse(defaultLanguageVersion) val extension = the() val javaToolchainService = the() diff --git a/gradle/plugins/src/main/kotlin/junitbuild.junit4-compatibility.gradle.kts b/gradle/plugins/common/src/main/kotlin/junitbuild.junit4-compatibility.gradle.kts similarity index 100% rename from gradle/plugins/src/main/kotlin/junitbuild.junit4-compatibility.gradle.kts rename to gradle/plugins/common/src/main/kotlin/junitbuild.junit4-compatibility.gradle.kts diff --git a/gradle/plugins/src/main/kotlin/junitbuild.kotlin-library-conventions.gradle.kts b/gradle/plugins/common/src/main/kotlin/junitbuild.kotlin-library-conventions.gradle.kts similarity index 100% rename from gradle/plugins/src/main/kotlin/junitbuild.kotlin-library-conventions.gradle.kts rename to gradle/plugins/common/src/main/kotlin/junitbuild.kotlin-library-conventions.gradle.kts diff --git a/gradle/plugins/src/main/kotlin/junitbuild.osgi-conventions.gradle.kts b/gradle/plugins/common/src/main/kotlin/junitbuild.osgi-conventions.gradle.kts similarity index 100% rename from gradle/plugins/src/main/kotlin/junitbuild.osgi-conventions.gradle.kts rename to gradle/plugins/common/src/main/kotlin/junitbuild.osgi-conventions.gradle.kts diff --git a/gradle/plugins/src/main/kotlin/junitbuild.publishing-conventions.gradle.kts b/gradle/plugins/common/src/main/kotlin/junitbuild.publishing-conventions.gradle.kts similarity index 94% rename from gradle/plugins/src/main/kotlin/junitbuild.publishing-conventions.gradle.kts rename to gradle/plugins/common/src/main/kotlin/junitbuild.publishing-conventions.gradle.kts index 7f8b617b3084..876612f0609c 100644 --- a/gradle/plugins/src/main/kotlin/junitbuild.publishing-conventions.gradle.kts +++ b/gradle/plugins/common/src/main/kotlin/junitbuild.publishing-conventions.gradle.kts @@ -2,10 +2,10 @@ plugins { `maven-publish` signing id("junitbuild.base-conventions") + id("junitbuild.build-parameters") } val isSnapshot = project.version.toString().contains("SNAPSHOT") -val isContinuousIntegrationEnvironment = System.getenv("CI")?.toBoolean() ?: false val jupiterProjects: List by rootProject val platformProjects: List by rootProject @@ -43,7 +43,7 @@ tasks.withType().configureEach { signing { useGpgCmd() sign(publishing.publications) - isRequired = !(isSnapshot || isContinuousIntegrationEnvironment) + isRequired = !(isSnapshot || buildParameters.ci) } tasks.withType().configureEach { diff --git a/gradle/plugins/src/main/kotlin/junitbuild.shadow-conventions.gradle.kts b/gradle/plugins/common/src/main/kotlin/junitbuild.shadow-conventions.gradle.kts similarity index 100% rename from gradle/plugins/src/main/kotlin/junitbuild.shadow-conventions.gradle.kts rename to gradle/plugins/common/src/main/kotlin/junitbuild.shadow-conventions.gradle.kts diff --git a/gradle/plugins/src/main/kotlin/junitbuild.spotless-conventions.gradle.kts b/gradle/plugins/common/src/main/kotlin/junitbuild.spotless-conventions.gradle.kts similarity index 100% rename from gradle/plugins/src/main/kotlin/junitbuild.spotless-conventions.gradle.kts rename to gradle/plugins/common/src/main/kotlin/junitbuild.spotless-conventions.gradle.kts diff --git a/gradle/plugins/src/main/kotlin/junitbuild.temp-maven-repo.gradle.kts b/gradle/plugins/common/src/main/kotlin/junitbuild.temp-maven-repo.gradle.kts similarity index 100% rename from gradle/plugins/src/main/kotlin/junitbuild.temp-maven-repo.gradle.kts rename to gradle/plugins/common/src/main/kotlin/junitbuild.temp-maven-repo.gradle.kts diff --git a/gradle/plugins/src/main/kotlin/junitbuild.testing-conventions.gradle.kts b/gradle/plugins/common/src/main/kotlin/junitbuild.testing-conventions.gradle.kts similarity index 75% rename from gradle/plugins/src/main/kotlin/junitbuild.testing-conventions.gradle.kts rename to gradle/plugins/common/src/main/kotlin/junitbuild.testing-conventions.gradle.kts index a11546e4d937..032661be08d0 100644 --- a/gradle/plugins/src/main/kotlin/junitbuild.testing-conventions.gradle.kts +++ b/gradle/plugins/common/src/main/kotlin/junitbuild.testing-conventions.gradle.kts @@ -6,6 +6,7 @@ import org.gradle.internal.os.OperatingSystem plugins { `java-library` + id("junitbuild.build-parameters") } tasks.withType().configureEach { @@ -17,18 +18,14 @@ tasks.withType().configureEach { events = setOf(FAILED) exceptionFormat = FULL } - val isCiServer = System.getenv("CI") != null retry { - maxRetries.set(providers.gradleProperty("retries").map(String::toInt).orElse(if (isCiServer) 2 else 0)) + maxRetries.set(buildParameters.testing.retries.orElse(if (buildParameters.ci) 2 else 0)) } distribution { - enabled.convention(providers.gradleProperty("enableTestDistribution") - .map(String::toBoolean) - .map { enabled -> enabled && (!isCiServer || System.getenv("GRADLE_ENTERPRISE_ACCESS_KEY").isNotBlank()) } - .orElse(false)) - maxLocalExecutors.set(providers.gradleProperty("testDistribution.maxLocalExecutors").map(String::toInt).orElse(1)) - maxRemoteExecutors.set(providers.gradleProperty("testDistribution.maxRemoteExecutors").map(String::toInt)) - if (isCiServer) { + enabled.convention(buildParameters.enterprise.testDistribution.enabled && (!buildParameters.ci || System.getenv("GRADLE_ENTERPRISE_ACCESS_KEY").isNotBlank())) + maxLocalExecutors.set(buildParameters.enterprise.testDistribution.maxLocalExecutors) + maxRemoteExecutors.set(buildParameters.enterprise.testDistribution.maxRemoteExecutors) + if (buildParameters.ci) { when { OperatingSystem.current().isLinux -> requirements.add("os=linux") OperatingSystem.current().isWindows -> requirements.add("os=windows") @@ -37,7 +34,7 @@ tasks.withType().configureEach { } } predictiveSelection { - enabled.set(providers.gradleProperty("enablePredictiveTestSelection").map(String::toBoolean).orElse(true)) + enabled.set(buildParameters.enterprise.predictiveTestSelection.enabled) // Ensure PTS works when publishing Build Scans to scans.gradle.com this as PredictiveTestSelectionExtensionInternal @@ -46,7 +43,7 @@ tasks.withType().configureEach { systemProperty("java.util.logging.manager", "org.apache.logging.log4j.jul.LogManager") // Required until ASM officially supports the JDK 14 systemProperty("net.bytebuddy.experimental", true) - if (project.hasProperty("enableJFR")) { + if (buildParameters.testing.enableJFR) { jvmArgs( "-XX:+UnlockDiagnosticVMOptions", "-XX:+DebugNonSafepoints", @@ -59,7 +56,7 @@ tasks.withType().configureEach { trackOperationSystemAsInput() // Avoid passing unnecessary environment variables to the JVM (from GitHub Actions) - if (isCiServer) { + if (buildParameters.ci) { environment.remove("RUNNER_TEMP") environment.remove("GITHUB_ACTION") } diff --git a/gradle/plugins/src/main/kotlin/junitbuild/exec/ClasspathSystemPropertyProvider.kt b/gradle/plugins/common/src/main/kotlin/junitbuild/exec/ClasspathSystemPropertyProvider.kt similarity index 100% rename from gradle/plugins/src/main/kotlin/junitbuild/exec/ClasspathSystemPropertyProvider.kt rename to gradle/plugins/common/src/main/kotlin/junitbuild/exec/ClasspathSystemPropertyProvider.kt diff --git a/gradle/plugins/src/main/kotlin/junitbuild/exec/RunConsoleLauncher.kt b/gradle/plugins/common/src/main/kotlin/junitbuild/exec/RunConsoleLauncher.kt similarity index 100% rename from gradle/plugins/src/main/kotlin/junitbuild/exec/RunConsoleLauncher.kt rename to gradle/plugins/common/src/main/kotlin/junitbuild/exec/RunConsoleLauncher.kt diff --git a/gradle/plugins/src/main/kotlin/junitbuild/java/ExecJarAction.kt b/gradle/plugins/common/src/main/kotlin/junitbuild/java/ExecJarAction.kt similarity index 100% rename from gradle/plugins/src/main/kotlin/junitbuild/java/ExecJarAction.kt rename to gradle/plugins/common/src/main/kotlin/junitbuild/java/ExecJarAction.kt diff --git a/gradle/plugins/src/main/kotlin/junitbuild/java/ModuleCompileOptions.kt b/gradle/plugins/common/src/main/kotlin/junitbuild/java/ModuleCompileOptions.kt similarity index 100% rename from gradle/plugins/src/main/kotlin/junitbuild/java/ModuleCompileOptions.kt rename to gradle/plugins/common/src/main/kotlin/junitbuild/java/ModuleCompileOptions.kt diff --git a/gradle/plugins/src/main/kotlin/junitbuild/java/ModulePathArgumentProvider.kt b/gradle/plugins/common/src/main/kotlin/junitbuild/java/ModulePathArgumentProvider.kt similarity index 100% rename from gradle/plugins/src/main/kotlin/junitbuild/java/ModulePathArgumentProvider.kt rename to gradle/plugins/common/src/main/kotlin/junitbuild/java/ModulePathArgumentProvider.kt diff --git a/gradle/plugins/src/main/kotlin/junitbuild/java/PatchModuleArgumentProvider.kt b/gradle/plugins/common/src/main/kotlin/junitbuild/java/PatchModuleArgumentProvider.kt similarity index 100% rename from gradle/plugins/src/main/kotlin/junitbuild/java/PatchModuleArgumentProvider.kt rename to gradle/plugins/common/src/main/kotlin/junitbuild/java/PatchModuleArgumentProvider.kt diff --git a/gradle/plugins/src/main/kotlin/junitbuild/java/WriteArtifactsFile.kt b/gradle/plugins/common/src/main/kotlin/junitbuild/java/WriteArtifactsFile.kt similarity index 100% rename from gradle/plugins/src/main/kotlin/junitbuild/java/WriteArtifactsFile.kt rename to gradle/plugins/common/src/main/kotlin/junitbuild/java/WriteArtifactsFile.kt diff --git a/gradle/plugins/src/main/kotlin/junitbuild/javadoc/ModuleSpecificJavadocFileOption.kt b/gradle/plugins/common/src/main/kotlin/junitbuild/javadoc/ModuleSpecificJavadocFileOption.kt similarity index 100% rename from gradle/plugins/src/main/kotlin/junitbuild/javadoc/ModuleSpecificJavadocFileOption.kt rename to gradle/plugins/common/src/main/kotlin/junitbuild/javadoc/ModuleSpecificJavadocFileOption.kt diff --git a/gradle/plugins/settings.gradle.kts b/gradle/plugins/settings.gradle.kts index e69de29bb2d1..ac0f7bb49c42 100644 --- a/gradle/plugins/settings.gradle.kts +++ b/gradle/plugins/settings.gradle.kts @@ -0,0 +1,2 @@ +include("build-parameters") +include("common") diff --git a/platform-tooling-support-tests/platform-tooling-support-tests.gradle.kts b/platform-tooling-support-tests/platform-tooling-support-tests.gradle.kts index 21c6f6c08d11..5be604bd0a8d 100644 --- a/platform-tooling-support-tests/platform-tooling-support-tests.gradle.kts +++ b/platform-tooling-support-tests/platform-tooling-support-tests.gradle.kts @@ -2,6 +2,7 @@ import org.gradle.api.tasks.PathSensitivity.RELATIVE import org.gradle.jvm.toolchain.internal.NoToolchainAvailableException plugins { + id("junitbuild.build-parameters") id("junitbuild.kotlin-library-conventions") id("junitbuild.testing-conventions") } @@ -135,8 +136,6 @@ class MavenRepo(@get:InputDirectory @get:PathSensitive(RELATIVE) val repoDir: Fi } class JavaHomeDir(project: Project, @Input val version: Int) : CommandLineArgumentProvider { - @Internal - val passToolchain = project.providers.gradleProperty("enableTestDistribution").map(String::toBoolean).orElse(false).map { !it } @Internal val javaLauncher: Property = project.objects.property() @@ -151,7 +150,7 @@ class JavaHomeDir(project: Project, @Input val version: Int) : CommandLineArgume }) override fun asArguments(): List { - if (passToolchain.get()) { + if (buildParameters.enterprise.testDistribution.enabled) { val metadata = javaLauncher.map { it.metadata } val javaHome = metadata.map { it.installationPath.asFile.absolutePath }.orNull return javaHome?.let { listOf("-Djava.home.$version=$it") } ?: emptyList() diff --git a/settings.gradle.kts b/settings.gradle.kts index 07d42905f4fe..cc8b9fb0b8fc 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -1,3 +1,4 @@ +import buildparameters.BuildParametersExtension import com.gradle.enterprise.gradleplugin.internal.extension.BuildScanExtensionWithHiddenFeatures pluginManagement { @@ -24,6 +25,7 @@ plugins { id("com.gradle.enterprise") id("com.gradle.common-custom-user-data-gradle-plugin") id("org.gradle.toolchains.foojay-resolver-convention") + id("junitbuild.build-parameters") } dependencyResolutionManagement { @@ -38,15 +40,11 @@ dependencyResolutionManagement { } val gradleEnterpriseServer = "https://ge.junit.org" -val isCiServer = System.getenv("CI") != null -val junitBuildCacheUrl: String? by extra -val junitBuildCacheUsername: String? by extra -val junitBuildCachePassword: String? by extra gradleEnterprise { buildScan { capture.isTaskInputFiles = true - isUploadInBackground = !isCiServer + isUploadInBackground = !buildParameters.ci publishAlways() @@ -58,7 +56,7 @@ gradleEnterprise { } obfuscation { - if (isCiServer) { + if (buildParameters.ci) { username { "github" } } else { hostname { null } @@ -66,10 +64,7 @@ gradleEnterprise { } } - val enableTestDistribution = providers.gradleProperty("enableTestDistribution") - .map(String::toBoolean) - .getOrElse(false) - if (enableTestDistribution) { + if (buildParameters.enterprise.testDistribution.enabled) { tag("test-distribution") } } @@ -77,14 +72,16 @@ gradleEnterprise { buildCache { local { - isEnabled = !isCiServer + isEnabled = !buildParameters.ci } remote { - url = uri(junitBuildCacheUrl ?: "$gradleEnterpriseServer/cache/") - isPush = isCiServer && !junitBuildCacheUsername.isNullOrEmpty() && !junitBuildCachePassword.isNullOrEmpty() + url = uri(buildParameters.buildCache.url.getOrElse("$gradleEnterpriseServer/cache/")) + val buildCacheUsername = buildParameters.buildCache.username.map { it.ifBlank { null } } + val buildCachePassword = buildParameters.buildCache.password.map { it.ifBlank { null } } + isPush = buildParameters.ci && buildCacheUsername.isPresent && buildCachePassword.isPresent credentials { - username = junitBuildCacheUsername?.ifEmpty { null } - password = junitBuildCachePassword?.ifEmpty { null } + username = buildCacheUsername.orNull + password = buildCachePassword.orNull } } } @@ -132,4 +129,7 @@ rootProject.children.forEach { project -> } } +val buildParameters: BuildParametersExtension + get() = the() + enableFeaturePreview("TYPESAFE_PROJECT_ACCESSORS") From 3ba144efdb38181d13132a552988e69c35c619a2 Mon Sep 17 00:00:00 2001 From: Marc Philipp Date: Fri, 10 Mar 2023 17:42:26 +0100 Subject: [PATCH 0045/1473] Fix integration tests running on Test Distribution agents The logic of passing the `java.home.8` system property was accidentally inverted in #3170. --- .../platform-tooling-support-tests.gradle.kts | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/platform-tooling-support-tests/platform-tooling-support-tests.gradle.kts b/platform-tooling-support-tests/platform-tooling-support-tests.gradle.kts index 5be604bd0a8d..20cd17024bcb 100644 --- a/platform-tooling-support-tests/platform-tooling-support-tests.gradle.kts +++ b/platform-tooling-support-tests/platform-tooling-support-tests.gradle.kts @@ -151,11 +151,11 @@ class JavaHomeDir(project: Project, @Input val version: Int) : CommandLineArgume override fun asArguments(): List { if (buildParameters.enterprise.testDistribution.enabled) { - val metadata = javaLauncher.map { it.metadata } - val javaHome = metadata.map { it.installationPath.asFile.absolutePath }.orNull - return javaHome?.let { listOf("-Djava.home.$version=$it") } ?: emptyList() + return emptyList() } - return emptyList() + val metadata = javaLauncher.map { it.metadata } + val javaHome = metadata.map { it.installationPath.asFile.absolutePath }.orNull + return javaHome?.let { listOf("-Djava.home.$version=$it") } ?: emptyList() } } From cd043e3cf2c221dae04acf567f783dc51ee51b29 Mon Sep 17 00:00:00 2001 From: JUnit Builds Date: Fri, 17 Mar 2023 11:58:15 +0100 Subject: [PATCH 0046/1473] Update dependencies (#3194) * Bump com.gradle.enterprise from 3.12.3 to 3.12.4 * Bump com.diffplug.spotless:spotless-plugin-gradle from 6.15.0 to 6.16.0 * Bump ant from 1.10.12 to 1.10.13 --- gradle/libs.versions.toml | 2 +- gradle/plugins/common/build.gradle.kts | 4 ++-- settings.gradle.kts | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 9628dd4e764f..89551967cc86 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -1,5 +1,5 @@ [versions] -ant = "1.10.12" +ant = "1.10.13" apiguardian = "1.1.2" asciidoctor-pdf = "1.5.3" assertj = "3.23.1" diff --git a/gradle/plugins/common/build.gradle.kts b/gradle/plugins/common/build.gradle.kts index 88ec294b01fd..6732672e0adf 100644 --- a/gradle/plugins/common/build.gradle.kts +++ b/gradle/plugins/common/build.gradle.kts @@ -13,10 +13,10 @@ dependencies { implementation(project(":build-parameters")) implementation(kotlin("gradle-plugin")) implementation("biz.aQute.bnd:biz.aQute.bnd.gradle:6.4.0") - implementation("com.diffplug.spotless:spotless-plugin-gradle:6.15.0") + implementation("com.diffplug.spotless:spotless-plugin-gradle:6.16.0") implementation("com.github.ben-manes:gradle-versions-plugin:0.46.0") implementation("gradle.plugin.com.github.johnrengelman:shadow:8.0.0") - compileOnly("com.gradle:gradle-enterprise-gradle-plugin:3.12.3") // keep in sync with root settings.gradle.kts + compileOnly("com.gradle:gradle-enterprise-gradle-plugin:3.12.4") // keep in sync with root settings.gradle.kts } tasks { diff --git a/settings.gradle.kts b/settings.gradle.kts index cc8b9fb0b8fc..0b6976d133f1 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -7,7 +7,7 @@ pluginManagement { gradlePluginPortal() } plugins { - id("com.gradle.enterprise") version "3.12.3" // keep in sync with gradle/plugins/build.gradle.kts + id("com.gradle.enterprise") version "3.12.4" // keep in sync with gradle/plugins/build.gradle.kts id("com.gradle.common-custom-user-data-gradle-plugin") version "1.8.2" id("org.gradle.toolchains.foojay-resolver-convention") version "0.4.0" id("org.ajoberstar.git-publish") version "4.1.1" From 7210d99972475812c63425a874a32eb241651a78 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 17 Mar 2023 12:16:43 +0100 Subject: [PATCH 0047/1473] Bump common-custom-user-data-gradle-plugin from 1.8.2 to 1.9 (#3183) --- settings.gradle.kts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/settings.gradle.kts b/settings.gradle.kts index 0b6976d133f1..2a8f5ffce8d9 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -8,7 +8,7 @@ pluginManagement { } plugins { id("com.gradle.enterprise") version "3.12.4" // keep in sync with gradle/plugins/build.gradle.kts - id("com.gradle.common-custom-user-data-gradle-plugin") version "1.8.2" + id("com.gradle.common-custom-user-data-gradle-plugin") version "1.9" id("org.gradle.toolchains.foojay-resolver-convention") version "0.4.0" id("org.ajoberstar.git-publish") version "4.1.1" kotlin("jvm") version "1.8.10" From 43d8dac8903e1d2b7a89bb40c2d24c6e7d7824b5 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 20 Mar 2023 06:01:13 +0000 Subject: [PATCH 0048/1473] Bump log4j from 2.19.0 to 2.20.0 Bumps `log4j` from 2.19.0 to 2.20.0. Updates `org.apache.logging.log4j:log4j-core` from 2.19.0 to 2.20.0 - [Release notes](https://github.com/apache/logging-log4j2/releases) - [Changelog](https://github.com/apache/logging-log4j2/blob/2.x/CHANGELOG.adoc) - [Commits](https://github.com/apache/logging-log4j2/compare/rel/2.19.0...rel/2.20.0) Updates `org.apache.logging.log4j:log4j-jul` from 2.19.0 to 2.20.0 - [Release notes](https://github.com/apache/logging-log4j2/releases) - [Changelog](https://github.com/apache/logging-log4j2/blob/2.x/CHANGELOG.adoc) - [Commits](https://github.com/apache/logging-log4j2/compare/rel/2.19.0...rel/2.20.0) --- updated-dependencies: - dependency-name: org.apache.logging.log4j:log4j-core dependency-type: direct:production update-type: version-update:semver-minor - dependency-name: org.apache.logging.log4j:log4j-jul dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- gradle/libs.versions.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 89551967cc86..a50049465b28 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -10,7 +10,7 @@ junit4 = "4.13.2" junit4Osgi = "4.13.2_1" junit4Min = "4.12" ktlint = "0.48.2" -log4j = "2.19.0" +log4j = "2.20.0" opentest4j = "1.2.0" openTestReporting = "0.1.0-M1" surefire = "3.0.0-M7" From b18b5a9481f59f64108df73529869f7b9a552f2b Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 20 Mar 2023 06:01:15 +0000 Subject: [PATCH 0049/1473] Bump com.gradle.common-custom-user-data-gradle-plugin from 1.9 to 1.10 Bumps com.gradle.common-custom-user-data-gradle-plugin from 1.9 to 1.10. --- updated-dependencies: - dependency-name: com.gradle.common-custom-user-data-gradle-plugin dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- settings.gradle.kts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/settings.gradle.kts b/settings.gradle.kts index 2a8f5ffce8d9..064b7f8b8211 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -8,7 +8,7 @@ pluginManagement { } plugins { id("com.gradle.enterprise") version "3.12.4" // keep in sync with gradle/plugins/build.gradle.kts - id("com.gradle.common-custom-user-data-gradle-plugin") version "1.9" + id("com.gradle.common-custom-user-data-gradle-plugin") version "1.10" id("org.gradle.toolchains.foojay-resolver-convention") version "0.4.0" id("org.ajoberstar.git-publish") version "4.1.1" kotlin("jvm") version "1.8.10" From cee1450d74565d593e0ebc86e7289106f12a21e2 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 20 Mar 2023 06:06:00 +0000 Subject: [PATCH 0050/1473] Bump github/combine-prs from 2.0.0 to 2.0.3 Bumps [github/combine-prs](https://github.com/github/combine-prs) from 2.0.0 to 2.0.3. - [Release notes](https://github.com/github/combine-prs/releases) - [Commits](https://github.com/github/combine-prs/compare/v2.0.0...v2.0.3) --- updated-dependencies: - dependency-name: github/combine-prs dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- .github/workflows/combine-prs.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/combine-prs.yml b/.github/workflows/combine-prs.yml index 95cb7ed5dce5..18deff854a67 100644 --- a/.github/workflows/combine-prs.yml +++ b/.github/workflows/combine-prs.yml @@ -10,6 +10,6 @@ jobs: runs-on: ubuntu-latest steps: - name: combine-prs - uses: github/combine-prs@v2.0.0 + uses: github/combine-prs@v2.0.3 with: github_token: ${{ secrets.GH_TOKEN }} From 0fcc03762edfe2b2a8a35b3bba838de729a1eebc Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 20 Mar 2023 11:09:55 +0000 Subject: [PATCH 0051/1473] Bump org.assertj:assertj-core from 3.23.1 to 3.24.2 Bumps org.assertj:assertj-core from 3.23.1 to 3.24.2. --- updated-dependencies: - dependency-name: org.assertj:assertj-core dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- gradle/libs.versions.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index a50049465b28..3c3705ea4f41 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -2,7 +2,7 @@ ant = "1.10.13" apiguardian = "1.1.2" asciidoctor-pdf = "1.5.3" -assertj = "3.23.1" +assertj = "3.24.2" checkstyle = "9.0" jacoco = "0.8.7" jmh = "1.36" From 46350d09c9d0298ff6b1344bfcaec22e44c8e77c Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 20 Mar 2023 11:11:23 +0000 Subject: [PATCH 0052/1473] Bump com.diffplug.spotless:spotless-plugin-gradle from 6.16.0 to 6.17.0 Bumps [com.diffplug.spotless:spotless-plugin-gradle](https://github.com/diffplug/spotless) from 6.16.0 to 6.17.0. - [Release notes](https://github.com/diffplug/spotless/releases) - [Changelog](https://github.com/diffplug/spotless/blob/main/CHANGES.md) - [Commits](https://github.com/diffplug/spotless/compare/gradle/6.16.0...gradle/6.17.0) --- updated-dependencies: - dependency-name: com.diffplug.spotless:spotless-plugin-gradle dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- gradle/plugins/common/build.gradle.kts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle/plugins/common/build.gradle.kts b/gradle/plugins/common/build.gradle.kts index 6732672e0adf..123fba670a5f 100644 --- a/gradle/plugins/common/build.gradle.kts +++ b/gradle/plugins/common/build.gradle.kts @@ -13,7 +13,7 @@ dependencies { implementation(project(":build-parameters")) implementation(kotlin("gradle-plugin")) implementation("biz.aQute.bnd:biz.aQute.bnd.gradle:6.4.0") - implementation("com.diffplug.spotless:spotless-plugin-gradle:6.16.0") + implementation("com.diffplug.spotless:spotless-plugin-gradle:6.17.0") implementation("com.github.ben-manes:gradle-versions-plugin:0.46.0") implementation("gradle.plugin.com.github.johnrengelman:shadow:8.0.0") compileOnly("com.gradle:gradle-enterprise-gradle-plugin:3.12.4") // keep in sync with root settings.gradle.kts From a65be48157b23ae22be9685a6d65e349a9b49c52 Mon Sep 17 00:00:00 2001 From: JUnit Team Date: Mon, 20 Mar 2023 12:30:36 +0100 Subject: [PATCH 0053/1473] Update formatting after Eclipse formatter update --- .../java/platform/tooling/support/tests/ManifestTests.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/platform-tooling-support-tests/src/test/java/platform/tooling/support/tests/ManifestTests.java b/platform-tooling-support-tests/src/test/java/platform/tooling/support/tests/ManifestTests.java index 4fabbb75a062..b09a64bc8bc6 100644 --- a/platform-tooling-support-tests/src/test/java/platform/tooling/support/tests/ManifestTests.java +++ b/platform-tooling-support-tests/src/test/java/platform/tooling/support/tests/ManifestTests.java @@ -56,8 +56,8 @@ void manifestEntriesAdhereToConventions(String module) throws Exception { MavenVersion.parseMavenString(version).getOSGiVersion().toString()); switch (module) { case "junit-platform-commons" -> assertValue(attributes, "Multi-Release", "true"); - case "junit-platform-console" -> assertValue(attributes, "Main-Class", - "org.junit.platform.console.ConsoleLauncher"); + case "junit-platform-console" -> + assertValue(attributes, "Main-Class", "org.junit.platform.console.ConsoleLauncher"); } var domain = Domain.domain(manifest); domain.getExportPackage().forEach((pkg, attrs) -> { From acae66ddd329660ab6eed2d6b076b7df794ad1ac Mon Sep 17 00:00:00 2001 From: Gilberto J Requena Date: Sat, 9 Jul 2022 23:49:36 +0200 Subject: [PATCH 0054/1473] Introduce AnnotationBasedArgumentsProvider Issue #2622 Closes #2978 --- .../AnnotationBasedArgumentsProvider.java | 67 +++++++++++++ .../params/provider/CsvArgumentsProvider.java | 33 +++---- .../provider/CsvFileArgumentsProvider.java | 39 ++++---- .../provider/EnumArgumentsProvider.java | 20 ++-- .../provider/MethodArgumentsProvider.java | 14 +-- .../provider/ValueArgumentsProvider.java | 49 +++++----- .../AnnotationConsumerInitializer.java | 48 +++++++--- .../AnnotationBasedArgumentsProviderTest.java | 63 +++++++++++++ .../provider/CsvArgumentsProviderTests.java | 4 +- .../provider/ValueArgumentsProviderTests.java | 3 +- .../AnnotationConsumerInitializerTest.java | 94 +++++++++++++++++++ 11 files changed, 327 insertions(+), 107 deletions(-) create mode 100644 junit-jupiter-params/src/main/java/org/junit/jupiter/params/provider/AnnotationBasedArgumentsProvider.java create mode 100644 junit-jupiter-params/src/test/java/org/junit/jupiter/params/provider/AnnotationBasedArgumentsProviderTest.java create mode 100644 junit-jupiter-params/src/test/java/org/junit/jupiter/params/support/AnnotationConsumerInitializerTest.java diff --git a/junit-jupiter-params/src/main/java/org/junit/jupiter/params/provider/AnnotationBasedArgumentsProvider.java b/junit-jupiter-params/src/main/java/org/junit/jupiter/params/provider/AnnotationBasedArgumentsProvider.java new file mode 100644 index 000000000000..8a04f7a0bbd9 --- /dev/null +++ b/junit-jupiter-params/src/main/java/org/junit/jupiter/params/provider/AnnotationBasedArgumentsProvider.java @@ -0,0 +1,67 @@ +/* + * Copyright 2015-2022 the original author or authors. + * + * All rights reserved. This program and the accompanying materials are + * made available under the terms of the Eclipse Public License v2.0 which + * accompanies this distribution and is available at + * + * https://www.eclipse.org/legal/epl-v20.html + */ + +package org.junit.jupiter.params.provider; + +import static org.apiguardian.api.API.Status.EXPERIMENTAL; + +import java.lang.annotation.Annotation; +import java.util.stream.Stream; + +import org.apiguardian.api.API; +import org.junit.jupiter.api.extension.ExtensionContext; +import org.junit.jupiter.params.support.AnnotationConsumer; +import org.junit.platform.commons.util.Preconditions; + +/** + * The implementations of an {@code AnnotationBasedArgumentsProvider} are responsible + * for {@linkplain #provideArguments providing} a stream of arguments to be passed to + * a {@code @ParameterizedTest} method, by using the data given by an annotation. + * + *

An {@code ArgumentsProvider} can be registered via the + * {@link ArgumentsSource @ArgumentsSource} annotation. + * + * @since 5.9 + * @see org.junit.jupiter.params.ParameterizedTest + * @see org.junit.jupiter.params.provider.ArgumentsSource + * @see org.junit.jupiter.params.provider.Arguments + * @see org.junit.jupiter.params.support.AnnotationConsumer + */ +@API(status = EXPERIMENTAL, since = "5.9") +public abstract class AnnotationBasedArgumentsProvider + implements ArgumentsProvider, AnnotationConsumer { + + private A annotation; + + /** + * @param annotation that provides the source of the parameters, never {@code null} + */ + @Override + public final void accept(A annotation) { + Preconditions.notNull(annotation, "annotation must not be null"); + this.annotation = annotation; + } + + @Override + public final Stream provideArguments(ExtensionContext context) { + Preconditions.notNull(context, "context must not be null"); + return provideArguments(context, annotation); + } + + /** + * Provide a {@link Stream} of {@link Arguments} to be passed to a + * {@code @ParameterizedTest} method, by using the data given by an annotation. + * + * @param context the current extension context; never {@code null} + * @param annotation that provides the source of the parameters, never {@code null} + * @return a stream of arguments; never {@code null} + */ + protected abstract Stream provideArguments(ExtensionContext context, A annotation); +} diff --git a/junit-jupiter-params/src/main/java/org/junit/jupiter/params/provider/CsvArgumentsProvider.java b/junit-jupiter-params/src/main/java/org/junit/jupiter/params/provider/CsvArgumentsProvider.java index ceecaccb2ab7..3722aa2a0087 100644 --- a/junit-jupiter-params/src/main/java/org/junit/jupiter/params/provider/CsvArgumentsProvider.java +++ b/junit-jupiter-params/src/main/java/org/junit/jupiter/params/provider/CsvArgumentsProvider.java @@ -26,7 +26,6 @@ import org.junit.jupiter.api.Named; import org.junit.jupiter.api.extension.ExtensionContext; -import org.junit.jupiter.params.support.AnnotationConsumer; import org.junit.platform.commons.PreconditionViolationException; import org.junit.platform.commons.util.Preconditions; import org.junit.platform.commons.util.UnrecoverableExceptions; @@ -34,33 +33,27 @@ /** * @since 5.0 */ -class CsvArgumentsProvider implements ArgumentsProvider, AnnotationConsumer { +class CsvArgumentsProvider extends AnnotationBasedArgumentsProvider { private static final String LINE_SEPARATOR = "\n"; - private CsvSource annotation; private Set nullValues; private CsvParser csvParser; @Override - public void accept(CsvSource annotation) { - this.annotation = annotation; + public Stream provideArguments(ExtensionContext context, CsvSource annotation) { this.nullValues = toSet(annotation.nullValues()); this.csvParser = createParserFor(annotation); - } - - @Override - public Stream provideArguments(ExtensionContext context) { - final boolean textBlockDeclared = !this.annotation.textBlock().isEmpty(); - Preconditions.condition(this.annotation.value().length > 0 ^ textBlockDeclared, + final boolean textBlockDeclared = !annotation.textBlock().isEmpty(); + Preconditions.condition(annotation.value().length > 0 ^ textBlockDeclared, () -> "@CsvSource must be declared with either `value` or `textBlock` but not both"); - return textBlockDeclared ? parseTextBlock() : parseValueArray(); + return textBlockDeclared ? parseTextBlock(annotation) : parseValueArray(annotation); } - private Stream parseTextBlock() { - String textBlock = this.annotation.textBlock(); - boolean useHeadersInDisplayName = this.annotation.useHeadersInDisplayName(); + private Stream parseTextBlock(CsvSource annotation) { + String textBlock = annotation.textBlock(); + boolean useHeadersInDisplayName = annotation.useHeadersInDisplayName(); List argumentsList = new ArrayList<>(); try { @@ -76,20 +69,20 @@ private Stream parseTextBlock() { } } catch (Throwable throwable) { - throw handleCsvException(throwable, this.annotation); + throw handleCsvException(throwable, annotation); } return argumentsList.stream(); } - private Stream parseValueArray() { - boolean useHeadersInDisplayName = this.annotation.useHeadersInDisplayName(); + private Stream parseValueArray(CsvSource annotation) { + boolean useHeadersInDisplayName = annotation.useHeadersInDisplayName(); List argumentsList = new ArrayList<>(); try { String[] headers = null; AtomicInteger index = new AtomicInteger(0); - for (String input : this.annotation.value()) { + for (String input : annotation.value()) { index.incrementAndGet(); String[] csvRecord = this.csvParser.parseLine(input + LINE_SEPARATOR); // Lazily retrieve headers if necessary. @@ -103,7 +96,7 @@ private Stream parseValueArray() { } } catch (Throwable throwable) { - throw handleCsvException(throwable, this.annotation); + throw handleCsvException(throwable, annotation); } return argumentsList.stream(); diff --git a/junit-jupiter-params/src/main/java/org/junit/jupiter/params/provider/CsvFileArgumentsProvider.java b/junit-jupiter-params/src/main/java/org/junit/jupiter/params/provider/CsvFileArgumentsProvider.java index 14650f66e26d..e78a52dc8e22 100644 --- a/junit-jupiter-params/src/main/java/org/junit/jupiter/params/provider/CsvFileArgumentsProvider.java +++ b/junit-jupiter-params/src/main/java/org/junit/jupiter/params/provider/CsvFileArgumentsProvider.java @@ -34,7 +34,6 @@ import com.univocity.parsers.csv.CsvParser; import org.junit.jupiter.api.extension.ExtensionContext; -import org.junit.jupiter.params.support.AnnotationConsumer; import org.junit.platform.commons.JUnitException; import org.junit.platform.commons.PreconditionViolationException; import org.junit.platform.commons.util.Preconditions; @@ -42,11 +41,10 @@ /** * @since 5.0 */ -class CsvFileArgumentsProvider implements ArgumentsProvider, AnnotationConsumer { +class CsvFileArgumentsProvider extends AnnotationBasedArgumentsProvider { private final InputStreamProvider inputStreamProvider; - private CsvFileSource annotation; private List sources; private Charset charset; private int numLinesToSkip; @@ -61,8 +59,18 @@ class CsvFileArgumentsProvider implements ArgumentsProvider, AnnotationConsumer< } @Override - public void accept(CsvFileSource annotation) { - this.annotation = annotation; + public Stream provideArguments(ExtensionContext context, CsvFileSource annotation) { + initialize(annotation); + // @formatter:off + return Preconditions.notEmpty(this.sources, "Resources or files must not be empty") + .stream() + .map(source -> source.open(context)) + .map(inputStream -> beginParsing(inputStream, annotation)) + .flatMap(parser -> toStream(parser, annotation)); + // @formatter:on + } + + private void initialize(CsvFileSource annotation) { Stream resources = Arrays.stream(annotation.resources()).map(inputStreamProvider::classpathResource); Stream files = Arrays.stream(annotation.files()).map(inputStreamProvider::file); this.sources = Stream.concat(resources, files).collect(toList()); @@ -80,29 +88,18 @@ private Charset getCharsetFrom(CsvFileSource annotation) { } } - @Override - public Stream provideArguments(ExtensionContext context) { - // @formatter:off - return Preconditions.notEmpty(this.sources, "Resources or files must not be empty") - .stream() - .map(source -> source.open(context)) - .map(this::beginParsing) - .flatMap(this::toStream); - // @formatter:on - } - - private CsvParser beginParsing(InputStream inputStream) { + private CsvParser beginParsing(InputStream inputStream, CsvFileSource annotation) { try { this.csvParser.beginParsing(inputStream, this.charset); } catch (Throwable throwable) { - handleCsvException(throwable, this.annotation); + handleCsvException(throwable, annotation); } return this.csvParser; } - private Stream toStream(CsvParser csvParser) { - CsvParserIterator iterator = new CsvParserIterator(csvParser, this.annotation); + private Stream toStream(CsvParser csvParser, CsvFileSource annotation) { + CsvParserIterator iterator = new CsvParserIterator(csvParser, annotation); return stream(spliteratorUnknownSize(iterator, Spliterator.ORDERED), false) // .skip(this.numLinesToSkip) // .onClose(() -> { @@ -110,7 +107,7 @@ private Stream toStream(CsvParser csvParser) { csvParser.stopParsing(); } catch (Throwable throwable) { - handleCsvException(throwable, this.annotation); + handleCsvException(throwable, annotation); } }); } diff --git a/junit-jupiter-params/src/main/java/org/junit/jupiter/params/provider/EnumArgumentsProvider.java b/junit-jupiter-params/src/main/java/org/junit/jupiter/params/provider/EnumArgumentsProvider.java index a4853eeb9339..04bbf7f7ca0c 100644 --- a/junit-jupiter-params/src/main/java/org/junit/jupiter/params/provider/EnumArgumentsProvider.java +++ b/junit-jupiter-params/src/main/java/org/junit/jupiter/params/provider/EnumArgumentsProvider.java @@ -19,24 +19,16 @@ import java.util.stream.Stream; import org.junit.jupiter.api.extension.ExtensionContext; -import org.junit.jupiter.params.support.AnnotationConsumer; import org.junit.platform.commons.util.Preconditions; /** * @since 5.0 */ -class EnumArgumentsProvider implements ArgumentsProvider, AnnotationConsumer { - - private EnumSource enumSource; - - @Override - public void accept(EnumSource enumSource) { - this.enumSource = enumSource; - } +class EnumArgumentsProvider extends AnnotationBasedArgumentsProvider { @Override - public Stream provideArguments(ExtensionContext context) { - Set> constants = getEnumConstants(context); + public Stream provideArguments(ExtensionContext context, EnumSource enumSource) { + Set> constants = getEnumConstants(context, enumSource); EnumSource.Mode mode = enumSource.mode(); String[] declaredConstantNames = enumSource.names(); if (declaredConstantNames.length > 0) { @@ -49,13 +41,13 @@ public Stream provideArguments(ExtensionContext context) { return constants.stream().map(Arguments::of); } - private > Set getEnumConstants(ExtensionContext context) { - Class enumClass = determineEnumClass(context); + private > Set getEnumConstants(ExtensionContext context, EnumSource enumSource) { + Class enumClass = determineEnumClass(context, enumSource); return EnumSet.allOf(enumClass); } @SuppressWarnings({ "unchecked", "rawtypes" }) - private > Class determineEnumClass(ExtensionContext context) { + private > Class determineEnumClass(ExtensionContext context, EnumSource enumSource) { Class enumClass = enumSource.value(); if (enumClass.equals(NullEnum.class)) { Method method = context.getRequiredTestMethod(); diff --git a/junit-jupiter-params/src/main/java/org/junit/jupiter/params/provider/MethodArgumentsProvider.java b/junit-jupiter-params/src/main/java/org/junit/jupiter/params/provider/MethodArgumentsProvider.java index 9c1b88cd1d93..a42677fd1ab2 100644 --- a/junit-jupiter-params/src/main/java/org/junit/jupiter/params/provider/MethodArgumentsProvider.java +++ b/junit-jupiter-params/src/main/java/org/junit/jupiter/params/provider/MethodArgumentsProvider.java @@ -26,7 +26,6 @@ import org.junit.jupiter.api.TestFactory; import org.junit.jupiter.api.TestTemplate; import org.junit.jupiter.api.extension.ExtensionContext; -import org.junit.jupiter.params.support.AnnotationConsumer; import org.junit.platform.commons.JUnitException; import org.junit.platform.commons.util.CollectionUtils; import org.junit.platform.commons.util.Preconditions; @@ -36,22 +35,15 @@ /** * @since 5.0 */ -class MethodArgumentsProvider implements ArgumentsProvider, AnnotationConsumer { - - private String[] methodNames; - - @Override - public void accept(MethodSource annotation) { - this.methodNames = annotation.value(); - } +class MethodArgumentsProvider extends AnnotationBasedArgumentsProvider { @Override - public Stream provideArguments(ExtensionContext context) { + public Stream provideArguments(ExtensionContext context, MethodSource annotation) { Class testClass = context.getRequiredTestClass(); Method testMethod = context.getRequiredTestMethod(); Object testInstance = context.getTestInstance().orElse(null); // @formatter:off - return stream(this.methodNames) + return stream(annotation.value()) .map(factoryMethodName -> getFactoryMethod(testClass, testMethod, factoryMethodName)) .map(factoryMethod -> context.getExecutableInvoker().invoke(factoryMethod, testInstance)) .flatMap(CollectionUtils::toStream) diff --git a/junit-jupiter-params/src/main/java/org/junit/jupiter/params/provider/ValueArgumentsProvider.java b/junit-jupiter-params/src/main/java/org/junit/jupiter/params/provider/ValueArgumentsProvider.java index 8bda32cf50e4..3d7fc6f65ceb 100644 --- a/junit-jupiter-params/src/main/java/org/junit/jupiter/params/provider/ValueArgumentsProvider.java +++ b/junit-jupiter-params/src/main/java/org/junit/jupiter/params/provider/ValueArgumentsProvider.java @@ -19,48 +19,45 @@ import java.util.stream.Stream; import org.junit.jupiter.api.extension.ExtensionContext; -import org.junit.jupiter.params.support.AnnotationConsumer; import org.junit.platform.commons.util.Preconditions; /** * @since 5.0 */ -class ValueArgumentsProvider implements ArgumentsProvider, AnnotationConsumer { - - private Object[] arguments; +class ValueArgumentsProvider extends AnnotationBasedArgumentsProvider { @Override - public void accept(ValueSource source) { + public Stream provideArguments(ExtensionContext context, ValueSource source) { + Object[] arguments = getArgumentsFromSource(source); + + return Arrays.stream(arguments).map(Arguments::of); + } + + private Object[] getArgumentsFromSource(ValueSource source) { // @formatter:off List arrays = - Stream.of( - source.shorts(), - source.bytes(), - source.ints(), - source.longs(), - source.floats(), - source.doubles(), - source.chars(), - source.booleans(), - source.strings(), - source.classes() - ) - .filter(array -> Array.getLength(array) > 0) - .collect(toList()); + Stream.of( + source.shorts(), + source.bytes(), + source.ints(), + source.longs(), + source.floats(), + source.doubles(), + source.chars(), + source.booleans(), + source.strings(), + source.classes() + ) + .filter(array -> Array.getLength(array) > 0) + .collect(toList()); // @formatter:on Preconditions.condition(arrays.size() == 1, () -> "Exactly one type of input must be provided in the @" + ValueSource.class.getSimpleName() + " annotation, but there were " + arrays.size()); Object originalArray = arrays.get(0); - arguments = IntStream.range(0, Array.getLength(originalArray)) // + return IntStream.range(0, Array.getLength(originalArray)) // .mapToObj(index -> Array.get(originalArray, index)) // .toArray(); } - - @Override - public Stream provideArguments(ExtensionContext context) { - return Arrays.stream(arguments).map(Arguments::of); - } - } diff --git a/junit-jupiter-params/src/main/java/org/junit/jupiter/params/support/AnnotationConsumerInitializer.java b/junit-jupiter-params/src/main/java/org/junit/jupiter/params/support/AnnotationConsumerInitializer.java index a9e2f01a6a32..a5cf81304c45 100644 --- a/junit-jupiter-params/src/main/java/org/junit/jupiter/params/support/AnnotationConsumerInitializer.java +++ b/junit-jupiter-params/src/main/java/org/junit/jupiter/params/support/AnnotationConsumerInitializer.java @@ -36,24 +36,46 @@ private AnnotationConsumerInitializer() { /* no-op */ } - // @formatter:off - private static final Predicate isAnnotationConsumerAcceptMethod = method -> - method.getName().equals("accept") - && method.getParameterCount() == 1 - && method.getParameterTypes()[0].isAnnotation(); - // @formatter:on + private static final Predicate isAcceptOrProvideArgumentsMethod = method -> isAnnotationConsumerAcceptMethod( + method) || isAnnotationBasedArgumentsProviderMethod(method); @SuppressWarnings({ "unchecked", "rawtypes" }) - public static T initialize(AnnotatedElement annotatedElement, T instance) { - if (instance instanceof AnnotationConsumer) { - Method method = findMethods(instance.getClass(), isAnnotationConsumerAcceptMethod, BOTTOM_UP).get(0); - Class annotationType = (Class) method.getParameterTypes()[0]; + public static T initialize(AnnotatedElement annotatedElement, T annotationConsumerInstance) { + if (annotationConsumerInstance instanceof AnnotationConsumer) { + Method method = findMethods(annotationConsumerInstance.getClass(), isAcceptOrProvideArgumentsMethod, + BOTTOM_UP).get(0); + Class annotationType = getAnnotationType(method); Annotation annotation = AnnotationUtils.findAnnotation(annotatedElement, annotationType) // - .orElseThrow(() -> new JUnitException(instance.getClass().getName() + .orElseThrow(() -> new JUnitException(annotationConsumerInstance.getClass().getName() + " must be used with an annotation of type " + annotationType.getName())); - initializeAnnotationConsumer((AnnotationConsumer) instance, annotation); + initializeAnnotationConsumer((AnnotationConsumer) annotationConsumerInstance, annotation); + } + return annotationConsumerInstance; + } + + private static boolean isAnnotationConsumerAcceptMethod(Method method) { + return isMethodWith(method, "accept", 1, 0); + } + + private static boolean isAnnotationBasedArgumentsProviderMethod(Method method) { + return isMethodWith(method, "provideArguments", 2, 1); + } + + // @formatter:off + private static boolean isMethodWith(Method method, String methodName, int parameterCount, + int annotationInParameterIndex) { + return method.getName().equals(methodName) + && method.getParameterCount() == parameterCount + && method.getParameterTypes()[annotationInParameterIndex].isAnnotation(); + } + // @formatter:on + + @SuppressWarnings({ "unchecked" }) + private static Class getAnnotationType(Method method) { + if (isAnnotationConsumerAcceptMethod(method)) { + return (Class) method.getParameterTypes()[0]; } - return instance; + return (Class) method.getParameterTypes()[1]; } private static void initializeAnnotationConsumer(AnnotationConsumer instance, diff --git a/junit-jupiter-params/src/test/java/org/junit/jupiter/params/provider/AnnotationBasedArgumentsProviderTest.java b/junit-jupiter-params/src/test/java/org/junit/jupiter/params/provider/AnnotationBasedArgumentsProviderTest.java new file mode 100644 index 000000000000..4d2ea8215b02 --- /dev/null +++ b/junit-jupiter-params/src/test/java/org/junit/jupiter/params/provider/AnnotationBasedArgumentsProviderTest.java @@ -0,0 +1,63 @@ +/* + * Copyright 2015-2022 the original author or authors. + * + * All rights reserved. This program and the accompanying materials are + * made available under the terms of the Eclipse Public License v2.0 which + * accompanies this distribution and is available at + * + * https://www.eclipse.org/legal/epl-v20.html + */ + +package org.junit.jupiter.params.provider; + +import static org.assertj.core.api.Assertions.assertThatThrownBy; +import static org.junit.jupiter.params.provider.MockCsvAnnotationBuilder.csvSource; +import static org.mockito.ArgumentMatchers.eq; +import static org.mockito.Mockito.atMostOnce; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.spy; +import static org.mockito.Mockito.verify; + +import java.util.stream.Stream; + +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtensionContext; + +@DisplayName("AnnotationBasedArgumentsProvider") +class AnnotationBasedArgumentsProviderTest { + + private final AnnotationBasedArgumentsProvider annotationBasedArgumentsProvider = new AnnotationBasedArgumentsProvider<>() { + @Override + protected Stream provideArguments(ExtensionContext context, CsvSource annotation) { + return Stream.empty(); + } + }; + + @Test + @DisplayName("should throw exception when null annotation is provided to accept method") + void shouldThrowExceptionWhenNullAnnotationIsProvidedToAccept() { + assertThatThrownBy(() -> annotationBasedArgumentsProvider.accept(null)) // + .hasMessage("annotation must not be null"); + } + + @Test + @DisplayName("should throw exception when null context is provided to provideArguments method") + void shouldThrowExceptionWhenNullContextIsProvidedToProvideArguments() { + assertThatThrownBy(() -> annotationBasedArgumentsProvider.provideArguments(null)) // + .hasMessage("context must not be null"); + } + + @Test + @DisplayName("should invoke the provideArguments template method with the accepted annotation") + void shouldInvokeTemplateMethodWithTheAnnotationProvidedWithAccept() { + var spiedProvider = spy(annotationBasedArgumentsProvider); + var extensionContext = mock(ExtensionContext.class); + var annotation = csvSource("0", "1", "2"); + + annotationBasedArgumentsProvider.accept(annotation); + annotationBasedArgumentsProvider.provideArguments(extensionContext); + + verify(spiedProvider, atMostOnce()).provideArguments(eq(extensionContext), eq(annotation)); + } +} diff --git a/junit-jupiter-params/src/test/java/org/junit/jupiter/params/provider/CsvArgumentsProviderTests.java b/junit-jupiter-params/src/test/java/org/junit/jupiter/params/provider/CsvArgumentsProviderTests.java index 67acc181a2d2..74be497abbaa 100644 --- a/junit-jupiter-params/src/test/java/org/junit/jupiter/params/provider/CsvArgumentsProviderTests.java +++ b/junit-jupiter-params/src/test/java/org/junit/jupiter/params/provider/CsvArgumentsProviderTests.java @@ -13,10 +13,12 @@ import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThatExceptionOfType; import static org.junit.jupiter.params.provider.MockCsvAnnotationBuilder.csvSource; +import static org.mockito.Mockito.mock; import java.util.stream.Stream; import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtensionContext; import org.junit.platform.commons.JUnitException; import org.junit.platform.commons.PreconditionViolationException; @@ -378,7 +380,7 @@ void throwsExceptionIfColumnCountExceedsHeaderCount() { private Stream provideArguments(CsvSource annotation) { var provider = new CsvArgumentsProvider(); provider.accept(annotation); - return provider.provideArguments(null).map(Arguments::get); + return provider.provideArguments(mock(ExtensionContext.class)).map(Arguments::get); } @SuppressWarnings("unchecked") diff --git a/junit-jupiter-params/src/test/java/org/junit/jupiter/params/provider/ValueArgumentsProviderTests.java b/junit-jupiter-params/src/test/java/org/junit/jupiter/params/provider/ValueArgumentsProviderTests.java index b9416ba418ce..88699a610f21 100644 --- a/junit-jupiter-params/src/test/java/org/junit/jupiter/params/provider/ValueArgumentsProviderTests.java +++ b/junit-jupiter-params/src/test/java/org/junit/jupiter/params/provider/ValueArgumentsProviderTests.java @@ -18,6 +18,7 @@ import java.util.stream.Stream; import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtensionContext; import org.junit.platform.commons.PreconditionViolationException; /** @@ -160,7 +161,7 @@ private static Stream provideArguments(short[] shorts, byte[] bytes, i var provider = new ValueArgumentsProvider(); provider.accept(annotation); - return provider.provideArguments(null).map(Arguments::get); + return provider.provideArguments(mock(ExtensionContext.class)).map(Arguments::get); } private static Object[] array(Object... objects) { diff --git a/junit-jupiter-params/src/test/java/org/junit/jupiter/params/support/AnnotationConsumerInitializerTest.java b/junit-jupiter-params/src/test/java/org/junit/jupiter/params/support/AnnotationConsumerInitializerTest.java new file mode 100644 index 000000000000..cb38fea558e9 --- /dev/null +++ b/junit-jupiter-params/src/test/java/org/junit/jupiter/params/support/AnnotationConsumerInitializerTest.java @@ -0,0 +1,94 @@ +/* + * Copyright 2015-2022 the original author or authors. + * + * All rights reserved. This program and the accompanying materials are + * made available under the terms of the Eclipse Public License v2.0 which + * accompanies this distribution and is available at + * + * https://www.eclipse.org/legal/epl-v20.html + */ + +package org.junit.jupiter.params.support; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatThrownBy; +import static org.junit.jupiter.params.support.AnnotationConsumerInitializer.initialize; +import static org.mockito.Mockito.mock; + +import java.util.stream.Stream; + +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtensionContext; +import org.junit.jupiter.params.provider.AnnotationBasedArgumentsProvider; +import org.junit.jupiter.params.provider.Arguments; +import org.junit.jupiter.params.provider.CsvSource; +import org.junit.platform.commons.JUnitException; + +@DisplayName("AnnotationConsumerInitializer") +class AnnotationConsumerInitializerTest { + + @Test + @DisplayName("should initialize annotation consumer") + void shouldInitializeAnnotationConsumer() throws NoSuchMethodException { + var instance = new SomeAnnotationConsumer(); + var method = SubjectClass.class.getDeclaredMethod("foo"); + var initialisedAnnotationConsumer = initialize(method, instance); + + assertThat(initialisedAnnotationConsumer.annotation).isInstanceOf(CsvSource.class); + } + + @Test + @DisplayName("should initialize annotation based arguments provider") + void shouldInitializeAnnotationBasedArgumentsProvider() throws NoSuchMethodException { + var instance = new SomeAnnotationBasedArgumentProvider(); + var method = SubjectClass.class.getDeclaredMethod("foo"); + var initialisedAnnotationConsumer = initialize(method, instance); + + initialisedAnnotationConsumer.provideArguments(mock(ExtensionContext.class)); + + assertThat(initialisedAnnotationConsumer.assignedAnnotation).isInstanceOf(CsvSource.class); + } + + @Test + @DisplayName("should throw exception when method is not annotated") + void shouldThrowExceptionWhenMethodIsNotAnnotated() throws NoSuchMethodException { + var instance = new SomeAnnotationConsumer(); + var method = SubjectClass.class.getDeclaredMethod("noAnnotation"); + + assertThatThrownBy(() -> initialize(method, instance)).isInstanceOf(JUnitException.class); + } + + private static class SomeAnnotationBasedArgumentProvider extends AnnotationBasedArgumentsProvider { + + CsvSource assignedAnnotation; + + @Override + protected Stream provideArguments(ExtensionContext context, CsvSource annotation) { + assignedAnnotation = annotation; + return Stream.empty(); + } + } + + private static class SomeAnnotationConsumer implements AnnotationConsumer { + + CsvSource annotation; + + @Override + public void accept(CsvSource csvSource) { + annotation = csvSource; + } + } + + private static class SubjectClass { + + @CsvSource("") + void foo() { + + } + + void noAnnotation() { + + } + } +} From 8771694d835bc041afacc8abe3c663c05204267a Mon Sep 17 00:00:00 2001 From: Juliette de Rancourt Date: Thu, 9 Mar 2023 19:31:56 +0100 Subject: [PATCH 0055/1473] Polish contribution --- .../AnnotationBasedArgumentsProvider.java | 26 +++++++++---------- .../provider/CsvFileArgumentsProvider.java | 21 +++++++-------- .../provider/MethodArgumentsProvider.java | 3 ++- .../provider/ValueArgumentsProvider.java | 1 - .../AnnotationBasedArgumentsProviderTest.java | 10 ++----- .../provider/CsvArgumentsProviderTests.java | 3 +-- .../provider/ValueArgumentsProviderTests.java | 3 +-- .../AnnotationConsumerInitializerTest.java | 15 +++++++---- 8 files changed, 37 insertions(+), 45 deletions(-) diff --git a/junit-jupiter-params/src/main/java/org/junit/jupiter/params/provider/AnnotationBasedArgumentsProvider.java b/junit-jupiter-params/src/main/java/org/junit/jupiter/params/provider/AnnotationBasedArgumentsProvider.java index 8a04f7a0bbd9..2dbfd70e6348 100644 --- a/junit-jupiter-params/src/main/java/org/junit/jupiter/params/provider/AnnotationBasedArgumentsProvider.java +++ b/junit-jupiter-params/src/main/java/org/junit/jupiter/params/provider/AnnotationBasedArgumentsProvider.java @@ -1,5 +1,5 @@ /* - * Copyright 2015-2022 the original author or authors. + * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which @@ -21,28 +21,26 @@ import org.junit.platform.commons.util.Preconditions; /** - * The implementations of an {@code AnnotationBasedArgumentsProvider} are responsible - * for {@linkplain #provideArguments providing} a stream of arguments to be passed to - * a {@code @ParameterizedTest} method, by using the data given by an annotation. + * {@code AnnotationBasedArgumentsProvider} is an abstract base class for + * {@link ArgumentsProvider} implementations that also need to consume an + * annotation in order to provide the arguments. * - *

An {@code ArgumentsProvider} can be registered via the - * {@link ArgumentsSource @ArgumentsSource} annotation. - * - * @since 5.9 + * @since 5.10 * @see org.junit.jupiter.params.ParameterizedTest * @see org.junit.jupiter.params.provider.ArgumentsSource * @see org.junit.jupiter.params.provider.Arguments + * @see org.junit.jupiter.params.provider.ArgumentsProvider * @see org.junit.jupiter.params.support.AnnotationConsumer */ -@API(status = EXPERIMENTAL, since = "5.9") +@API(status = EXPERIMENTAL, since = "5.10") public abstract class AnnotationBasedArgumentsProvider implements ArgumentsProvider, AnnotationConsumer { + public AnnotationBasedArgumentsProvider() { + } + private A annotation; - /** - * @param annotation that provides the source of the parameters, never {@code null} - */ @Override public final void accept(A annotation) { Preconditions.notNull(annotation, "annotation must not be null"); @@ -51,7 +49,6 @@ public final void accept(A annotation) { @Override public final Stream provideArguments(ExtensionContext context) { - Preconditions.notNull(context, "context must not be null"); return provideArguments(context, annotation); } @@ -60,8 +57,9 @@ public final Stream provideArguments(ExtensionContext conte * {@code @ParameterizedTest} method, by using the data given by an annotation. * * @param context the current extension context; never {@code null} - * @param annotation that provides the source of the parameters, never {@code null} + * @param annotation the annotation used to specify the arguments; never {@code null} * @return a stream of arguments; never {@code null} */ protected abstract Stream provideArguments(ExtensionContext context, A annotation); + } diff --git a/junit-jupiter-params/src/main/java/org/junit/jupiter/params/provider/CsvFileArgumentsProvider.java b/junit-jupiter-params/src/main/java/org/junit/jupiter/params/provider/CsvFileArgumentsProvider.java index e78a52dc8e22..f4ccca49432f 100644 --- a/junit-jupiter-params/src/main/java/org/junit/jupiter/params/provider/CsvFileArgumentsProvider.java +++ b/junit-jupiter-params/src/main/java/org/junit/jupiter/params/provider/CsvFileArgumentsProvider.java @@ -45,7 +45,6 @@ class CsvFileArgumentsProvider extends AnnotationBasedArgumentsProvider sources; private Charset charset; private int numLinesToSkip; private CsvParser csvParser; @@ -60,9 +59,16 @@ class CsvFileArgumentsProvider extends AnnotationBasedArgumentsProvider provideArguments(ExtensionContext context, CsvFileSource annotation) { - initialize(annotation); + this.charset = getCharsetFrom(annotation); + this.numLinesToSkip = annotation.numLinesToSkip(); + this.csvParser = createParserFor(annotation); + + Stream resources = Arrays.stream(annotation.resources()).map(inputStreamProvider::classpathResource); + Stream files = Arrays.stream(annotation.files()).map(inputStreamProvider::file); + List sources = Stream.concat(resources, files).collect(toList()); + // @formatter:off - return Preconditions.notEmpty(this.sources, "Resources or files must not be empty") + return Preconditions.notEmpty(sources, "Resources or files must not be empty") .stream() .map(source -> source.open(context)) .map(inputStream -> beginParsing(inputStream, annotation)) @@ -70,15 +76,6 @@ public Stream provideArguments(ExtensionContext context, Cs // @formatter:on } - private void initialize(CsvFileSource annotation) { - Stream resources = Arrays.stream(annotation.resources()).map(inputStreamProvider::classpathResource); - Stream files = Arrays.stream(annotation.files()).map(inputStreamProvider::file); - this.sources = Stream.concat(resources, files).collect(toList()); - this.charset = getCharsetFrom(annotation); - this.numLinesToSkip = annotation.numLinesToSkip(); - this.csvParser = createParserFor(annotation); - } - private Charset getCharsetFrom(CsvFileSource annotation) { try { return Charset.forName(annotation.encoding()); diff --git a/junit-jupiter-params/src/main/java/org/junit/jupiter/params/provider/MethodArgumentsProvider.java b/junit-jupiter-params/src/main/java/org/junit/jupiter/params/provider/MethodArgumentsProvider.java index a42677fd1ab2..6ad6069e9d3c 100644 --- a/junit-jupiter-params/src/main/java/org/junit/jupiter/params/provider/MethodArgumentsProvider.java +++ b/junit-jupiter-params/src/main/java/org/junit/jupiter/params/provider/MethodArgumentsProvider.java @@ -42,8 +42,9 @@ public Stream provideArguments(ExtensionContext context, Me Class testClass = context.getRequiredTestClass(); Method testMethod = context.getRequiredTestMethod(); Object testInstance = context.getTestInstance().orElse(null); + String[] methodNames = annotation.value(); // @formatter:off - return stream(annotation.value()) + return stream(methodNames) .map(factoryMethodName -> getFactoryMethod(testClass, testMethod, factoryMethodName)) .map(factoryMethod -> context.getExecutableInvoker().invoke(factoryMethod, testInstance)) .flatMap(CollectionUtils::toStream) diff --git a/junit-jupiter-params/src/main/java/org/junit/jupiter/params/provider/ValueArgumentsProvider.java b/junit-jupiter-params/src/main/java/org/junit/jupiter/params/provider/ValueArgumentsProvider.java index 3d7fc6f65ceb..0845f03c51b5 100644 --- a/junit-jupiter-params/src/main/java/org/junit/jupiter/params/provider/ValueArgumentsProvider.java +++ b/junit-jupiter-params/src/main/java/org/junit/jupiter/params/provider/ValueArgumentsProvider.java @@ -29,7 +29,6 @@ class ValueArgumentsProvider extends AnnotationBasedArgumentsProvider provideArguments(ExtensionContext context, ValueSource source) { Object[] arguments = getArgumentsFromSource(source); - return Arrays.stream(arguments).map(Arguments::of); } diff --git a/junit-jupiter-params/src/test/java/org/junit/jupiter/params/provider/AnnotationBasedArgumentsProviderTest.java b/junit-jupiter-params/src/test/java/org/junit/jupiter/params/provider/AnnotationBasedArgumentsProviderTest.java index 4d2ea8215b02..ae54960f289c 100644 --- a/junit-jupiter-params/src/test/java/org/junit/jupiter/params/provider/AnnotationBasedArgumentsProviderTest.java +++ b/junit-jupiter-params/src/test/java/org/junit/jupiter/params/provider/AnnotationBasedArgumentsProviderTest.java @@ -1,5 +1,5 @@ /* - * Copyright 2015-2022 the original author or authors. + * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which @@ -41,13 +41,6 @@ void shouldThrowExceptionWhenNullAnnotationIsProvidedToAccept() { .hasMessage("annotation must not be null"); } - @Test - @DisplayName("should throw exception when null context is provided to provideArguments method") - void shouldThrowExceptionWhenNullContextIsProvidedToProvideArguments() { - assertThatThrownBy(() -> annotationBasedArgumentsProvider.provideArguments(null)) // - .hasMessage("context must not be null"); - } - @Test @DisplayName("should invoke the provideArguments template method with the accepted annotation") void shouldInvokeTemplateMethodWithTheAnnotationProvidedWithAccept() { @@ -60,4 +53,5 @@ void shouldInvokeTemplateMethodWithTheAnnotationProvidedWithAccept() { verify(spiedProvider, atMostOnce()).provideArguments(eq(extensionContext), eq(annotation)); } + } diff --git a/junit-jupiter-params/src/test/java/org/junit/jupiter/params/provider/CsvArgumentsProviderTests.java b/junit-jupiter-params/src/test/java/org/junit/jupiter/params/provider/CsvArgumentsProviderTests.java index 74be497abbaa..767768ce6bac 100644 --- a/junit-jupiter-params/src/test/java/org/junit/jupiter/params/provider/CsvArgumentsProviderTests.java +++ b/junit-jupiter-params/src/test/java/org/junit/jupiter/params/provider/CsvArgumentsProviderTests.java @@ -18,7 +18,6 @@ import java.util.stream.Stream; import org.junit.jupiter.api.Test; -import org.junit.jupiter.api.extension.ExtensionContext; import org.junit.platform.commons.JUnitException; import org.junit.platform.commons.PreconditionViolationException; @@ -380,7 +379,7 @@ void throwsExceptionIfColumnCountExceedsHeaderCount() { private Stream provideArguments(CsvSource annotation) { var provider = new CsvArgumentsProvider(); provider.accept(annotation); - return provider.provideArguments(mock(ExtensionContext.class)).map(Arguments::get); + return provider.provideArguments(mock()).map(Arguments::get); } @SuppressWarnings("unchecked") diff --git a/junit-jupiter-params/src/test/java/org/junit/jupiter/params/provider/ValueArgumentsProviderTests.java b/junit-jupiter-params/src/test/java/org/junit/jupiter/params/provider/ValueArgumentsProviderTests.java index 88699a610f21..213178fa805a 100644 --- a/junit-jupiter-params/src/test/java/org/junit/jupiter/params/provider/ValueArgumentsProviderTests.java +++ b/junit-jupiter-params/src/test/java/org/junit/jupiter/params/provider/ValueArgumentsProviderTests.java @@ -18,7 +18,6 @@ import java.util.stream.Stream; import org.junit.jupiter.api.Test; -import org.junit.jupiter.api.extension.ExtensionContext; import org.junit.platform.commons.PreconditionViolationException; /** @@ -161,7 +160,7 @@ private static Stream provideArguments(short[] shorts, byte[] bytes, i var provider = new ValueArgumentsProvider(); provider.accept(annotation); - return provider.provideArguments(mock(ExtensionContext.class)).map(Arguments::get); + return provider.provideArguments(mock()).map(Arguments::get); } private static Object[] array(Object... objects) { diff --git a/junit-jupiter-params/src/test/java/org/junit/jupiter/params/support/AnnotationConsumerInitializerTest.java b/junit-jupiter-params/src/test/java/org/junit/jupiter/params/support/AnnotationConsumerInitializerTest.java index cb38fea558e9..43da248a78a8 100644 --- a/junit-jupiter-params/src/test/java/org/junit/jupiter/params/support/AnnotationConsumerInitializerTest.java +++ b/junit-jupiter-params/src/test/java/org/junit/jupiter/params/support/AnnotationConsumerInitializerTest.java @@ -1,5 +1,5 @@ /* - * Copyright 2015-2022 the original author or authors. + * Copyright 2015-2023 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v2.0 which @@ -15,6 +15,7 @@ import static org.junit.jupiter.params.support.AnnotationConsumerInitializer.initialize; import static org.mockito.Mockito.mock; +import java.util.Arrays; import java.util.stream.Stream; import org.junit.jupiter.api.DisplayName; @@ -35,7 +36,9 @@ void shouldInitializeAnnotationConsumer() throws NoSuchMethodException { var method = SubjectClass.class.getDeclaredMethod("foo"); var initialisedAnnotationConsumer = initialize(method, instance); - assertThat(initialisedAnnotationConsumer.annotation).isInstanceOf(CsvSource.class); + assertThat(initialisedAnnotationConsumer.annotation) // + .isInstanceOf(CsvSource.class) // + .matches(annotation -> Arrays.equals(annotation.value(), new String[] { "a", "b" })); } @Test @@ -45,9 +48,11 @@ void shouldInitializeAnnotationBasedArgumentsProvider() throws NoSuchMethodExcep var method = SubjectClass.class.getDeclaredMethod("foo"); var initialisedAnnotationConsumer = initialize(method, instance); - initialisedAnnotationConsumer.provideArguments(mock(ExtensionContext.class)); + initialisedAnnotationConsumer.provideArguments(mock()); - assertThat(initialisedAnnotationConsumer.assignedAnnotation).isInstanceOf(CsvSource.class); + assertThat(initialisedAnnotationConsumer.assignedAnnotation) // + .isInstanceOf(CsvSource.class) // + .matches(annotation -> Arrays.equals(annotation.value(), new String[] { "a", "b" })); } @Test @@ -82,7 +87,7 @@ public void accept(CsvSource csvSource) { private static class SubjectClass { - @CsvSource("") + @CsvSource({ "a", "b" }) void foo() { } From 6df798ae272683cbef834d83f98cf2c191327cad Mon Sep 17 00:00:00 2001 From: Juliette de Rancourt Date: Thu, 9 Mar 2023 19:32:27 +0100 Subject: [PATCH 0056/1473] Document new `AnnotationBasedArgumentsProvider` in user guide and release notes --- documentation/src/docs/asciidoc/link-attributes.adoc | 3 +++ .../docs/asciidoc/release-notes/release-notes-5.10.0-M1.adoc | 2 ++ documentation/src/docs/asciidoc/user-guide/writing-tests.adoc | 3 +++ 3 files changed, 8 insertions(+) diff --git a/documentation/src/docs/asciidoc/link-attributes.adoc b/documentation/src/docs/asciidoc/link-attributes.adoc index 224d99ea4bdd..7bc5bc848b0b 100644 --- a/documentation/src/docs/asciidoc/link-attributes.adoc +++ b/documentation/src/docs/asciidoc/link-attributes.adoc @@ -138,13 +138,16 @@ endif::[] :TempDir: {javadoc-root}/org.junit.jupiter.api/org/junit/jupiter/api/io/TempDir.html[@TempDir] // Jupiter Params :params-provider-package: {javadoc-root}/org.junit.jupiter.params/org/junit/jupiter/params/provider/package-summary.html[org.junit.jupiter.params.provider] +:AnnotationBasedArgumentsProvider: {javadoc-root}/org.junit.jupiter.params/org/junit/jupiter/params/provider/AnnotationBasedArgumentsProvider.html[AnnotationBasedArgumentsProvider] :ArgumentsAccessor: {javadoc-root}/org.junit.jupiter.params/org/junit/jupiter/params/aggregator/ArgumentsAccessor.html[ArgumentsAccessor] :ArgumentsAggregator: {javadoc-root}/org.junit.jupiter.params/org/junit/jupiter/params/aggregator/ArgumentsAggregator.html[ArgumentsAggregator] +:CsvArgumentsProvider: {javadoc-root}/org.junit.jupiter.params/org/junit/jupiter/params/provider/CsvArgumentsProvider.html[CsvArgumentsProvider] :EmptySource: {javadoc-root}/org.junit.jupiter.params/org/junit/jupiter/params/provider/EmptySource.html[@EmptySource] :MethodSource: {javadoc-root}/org.junit.jupiter.params/org/junit/jupiter/params/provider/MethodSource.html[@MethodSource] :NullAndEmptySource: {javadoc-root}/org.junit.jupiter.params/org/junit/jupiter/params/provider/NullAndEmptySource.html[@NullAndEmptySource] :NullSource: {javadoc-root}/org.junit.jupiter.params/org/junit/jupiter/params/provider/NullSource.html[@NullSource] :ParameterizedTest: {javadoc-root}/org.junit.jupiter.params/org/junit/jupiter/params/ParameterizedTest.html[@ParameterizedTest] +:ValueArgumentsProvider: {javadoc-root}/org.junit.jupiter.params/org/junit/jupiter/params/provider/ValueArgumentsProvider.html[ValueArgumentsProvider] // Jupiter Engine :junit-jupiter-engine: {javadoc-root}/org.junit.jupiter.engine/org/junit/jupiter/engine/package-summary.html[junit-jupiter-engine] // Jupiter Extension Implementations diff --git a/documentation/src/docs/asciidoc/release-notes/release-notes-5.10.0-M1.adoc b/documentation/src/docs/asciidoc/release-notes/release-notes-5.10.0-M1.adoc index 6fd5d6d7ef2b..0a0b57d779df 100644 --- a/documentation/src/docs/asciidoc/release-notes/release-notes-5.10.0-M1.adoc +++ b/documentation/src/docs/asciidoc/release-notes/release-notes-5.10.0-M1.adoc @@ -64,6 +64,8 @@ repository on GitHub. to fall back to the default display name generator. * `@EmptySource` now supports additional types, including `Collection` and `Map` subtypes with a public no-arg constructor. +* New `AnnotationBasedArgumentsProvider` that implements both `ArgumentsProvider` and + `AnnotationConsumer` interfaces. [[release-notes-5.10.0-M1-junit-vintage]] diff --git a/documentation/src/docs/asciidoc/user-guide/writing-tests.adoc b/documentation/src/docs/asciidoc/user-guide/writing-tests.adoc index 62642cb68f53..4187c34d578f 100644 --- a/documentation/src/docs/asciidoc/user-guide/writing-tests.adoc +++ b/documentation/src/docs/asciidoc/user-guide/writing-tests.adoc @@ -1622,6 +1622,9 @@ include::{testDir}/example/ParameterizedTestDemo.java[tags=ArgumentsSource_examp include::{testDir}/example/ParameterizedTestDemo.java[tags=ArgumentsProvider_example] ---- +If you wish to implement a custom `ArgumentsProvider` that also consumes an annotation +(like built-in providers such as `{ValueArgumentsProvider}` or `{CsvArgumentsProvider}`), +you have the possibility to extend the `{AnnotationBasedArgumentsProvider}` class. [[writing-tests-parameterized-tests-argument-conversion]] ==== Argument Conversion From 31689deb659278e54e4e7a8c438e70514ab96d1d Mon Sep 17 00:00:00 2001 From: Juliette de Rancourt Date: Wed, 22 Mar 2023 17:45:29 +0100 Subject: [PATCH 0057/1473] Introduce `AnnotationBasedArgumentConverter` This abstract base class has been created to mirror newly introduced `AnnotationBasedArgumentsProvider`. Resolves #2622 --- .../src/docs/asciidoc/link-attributes.adoc | 1 + .../release-notes-5.10.0-M1.adoc | 2 + .../asciidoc/user-guide/writing-tests.adoc | 4 ++ .../AnnotationBasedArgumentConverter.java | 67 +++++++++++++++++++ .../converter/JavaTimeArgumentConverter.java | 15 +---- .../AnnotationConsumerInitializer.java | 45 +++++++------ .../JavaTimeArgumentConverterTests.java | 3 +- .../AnnotationConsumerInitializerTest.java | 60 +++++++++++++++-- 8 files changed, 157 insertions(+), 40 deletions(-) create mode 100644 junit-jupiter-params/src/main/java/org/junit/jupiter/params/converter/AnnotationBasedArgumentConverter.java diff --git a/documentation/src/docs/asciidoc/link-attributes.adoc b/documentation/src/docs/asciidoc/link-attributes.adoc index 7bc5bc848b0b..dc101db7079a 100644 --- a/documentation/src/docs/asciidoc/link-attributes.adoc +++ b/documentation/src/docs/asciidoc/link-attributes.adoc @@ -138,6 +138,7 @@ endif::[] :TempDir: {javadoc-root}/org.junit.jupiter.api/org/junit/jupiter/api/io/TempDir.html[@TempDir] // Jupiter Params :params-provider-package: {javadoc-root}/org.junit.jupiter.params/org/junit/jupiter/params/provider/package-summary.html[org.junit.jupiter.params.provider] +:AnnotationBasedArgumentConverter: {javadoc-root}/org.junit.jupiter.params/org/junit/jupiter/params/provider/AnnotationBasedArgumentConverter.html[AnnotationBasedArgumentConverter] :AnnotationBasedArgumentsProvider: {javadoc-root}/org.junit.jupiter.params/org/junit/jupiter/params/provider/AnnotationBasedArgumentsProvider.html[AnnotationBasedArgumentsProvider] :ArgumentsAccessor: {javadoc-root}/org.junit.jupiter.params/org/junit/jupiter/params/aggregator/ArgumentsAccessor.html[ArgumentsAccessor] :ArgumentsAggregator: {javadoc-root}/org.junit.jupiter.params/org/junit/jupiter/params/aggregator/ArgumentsAggregator.html[ArgumentsAggregator] diff --git a/documentation/src/docs/asciidoc/release-notes/release-notes-5.10.0-M1.adoc b/documentation/src/docs/asciidoc/release-notes/release-notes-5.10.0-M1.adoc index 0a0b57d779df..2f8ebd6bf778 100644 --- a/documentation/src/docs/asciidoc/release-notes/release-notes-5.10.0-M1.adoc +++ b/documentation/src/docs/asciidoc/release-notes/release-notes-5.10.0-M1.adoc @@ -66,6 +66,8 @@ repository on GitHub. with a public no-arg constructor. * New `AnnotationBasedArgumentsProvider` that implements both `ArgumentsProvider` and `AnnotationConsumer` interfaces. +* New `AnnotationBasedArgumentConverter` that implements both `ArgumentConverter` and + `AnnotationConsumer` interfaces. [[release-notes-5.10.0-M1-junit-vintage]] diff --git a/documentation/src/docs/asciidoc/user-guide/writing-tests.adoc b/documentation/src/docs/asciidoc/user-guide/writing-tests.adoc index 4187c34d578f..a0fc45f2934c 100644 --- a/documentation/src/docs/asciidoc/user-guide/writing-tests.adoc +++ b/documentation/src/docs/asciidoc/user-guide/writing-tests.adoc @@ -1772,6 +1772,10 @@ composed annotation `JavaTimeConversionPattern`. include::{testDir}/example/ParameterizedTestDemo.java[tags=explicit_java_time_converter] ---- +If you wish to implement a custom `ArgumentConverter` that also consumes an annotation +(like `JavaTimeArgumentConverter`), you have the possibility to extend the +`{AnnotationBasedArgumentConverter}` class. + [[writing-tests-parameterized-tests-argument-aggregation]] ==== Argument Aggregation diff --git a/junit-jupiter-params/src/main/java/org/junit/jupiter/params/converter/AnnotationBasedArgumentConverter.java b/junit-jupiter-params/src/main/java/org/junit/jupiter/params/converter/AnnotationBasedArgumentConverter.java new file mode 100644 index 000000000000..964c0c23616a --- /dev/null +++ b/junit-jupiter-params/src/main/java/org/junit/jupiter/params/converter/AnnotationBasedArgumentConverter.java @@ -0,0 +1,67 @@ +/* + * Copyright 2015-2023 the original author or authors. + * + * All rights reserved. This program and the accompanying materials are + * made available under the terms of the Eclipse Public License v2.0 which + * accompanies this distribution and is available at + * + * https://www.eclipse.org/legal/epl-v20.html + */ + +package org.junit.jupiter.params.converter; + +import static org.apiguardian.api.API.Status.EXPERIMENTAL; + +import java.lang.annotation.Annotation; + +import org.apiguardian.api.API; +import org.junit.jupiter.api.extension.ParameterContext; +import org.junit.jupiter.params.support.AnnotationConsumer; +import org.junit.platform.commons.util.Preconditions; + +/** + * {@code SimpleArgumentConverter} is an abstract base class for + * {@link ArgumentConverter} implementations that also need to consume an + * annotation in order to perform the conversion. + * + * @since 5.10 + * @see ArgumentConverter + * @see AnnotationConsumer + * @see SimpleArgumentConverter + */ +@API(status = EXPERIMENTAL, since = "5.10") +public abstract class AnnotationBasedArgumentConverter + implements ArgumentConverter, AnnotationConsumer { + + public AnnotationBasedArgumentConverter() { + } + + private A annotation; + + @Override + public final void accept(A annotation) { + Preconditions.notNull(annotation, "annotation must not be null"); + this.annotation = annotation; + } + + @Override + public final Object convert(Object source, ParameterContext context) throws ArgumentConversionException { + return convert(source, context.getParameter().getType(), annotation); + } + + /** + * Convert the supplied {@code source} object into the supplied + * {@code targetType}. + * + * @param source the source object to convert; may be {@code null} + * @param targetType the target type the source object should be converted + * into; never {@code null} + * @param annotation the annotation needed to convert the source; never {@code null} + * @return the converted object; may be {@code null} but only if the target + * type is a reference type + * @throws ArgumentConversionException in case an error occurs during the + * conversion + */ + protected abstract Object convert(Object source, Class targetType, A annotation); + +} diff --git a/junit-jupiter-params/src/main/java/org/junit/jupiter/params/converter/JavaTimeArgumentConverter.java b/junit-jupiter-params/src/main/java/org/junit/jupiter/params/converter/JavaTimeArgumentConverter.java index 7c1defaa3180..aef6e5a44cc8 100644 --- a/junit-jupiter-params/src/main/java/org/junit/jupiter/params/converter/JavaTimeArgumentConverter.java +++ b/junit-jupiter-params/src/main/java/org/junit/jupiter/params/converter/JavaTimeArgumentConverter.java @@ -27,13 +27,10 @@ import java.util.LinkedHashMap; import java.util.Map; -import org.junit.jupiter.params.support.AnnotationConsumer; - /** * @since 5.0 */ -class JavaTimeArgumentConverter extends SimpleArgumentConverter - implements AnnotationConsumer { +class JavaTimeArgumentConverter extends AnnotationBasedArgumentConverter { private static final Map, TemporalQuery> TEMPORAL_QUERIES; static { @@ -52,15 +49,9 @@ class JavaTimeArgumentConverter extends SimpleArgumentConverter TEMPORAL_QUERIES = Collections.unmodifiableMap(queries); } - private String pattern; - - @Override - public void accept(JavaTimeConversionPattern annotation) { - pattern = annotation.value(); - } - @Override - public Object convert(Object input, Class targetClass) throws ArgumentConversionException { + protected Object convert(Object input, Class targetClass, JavaTimeConversionPattern annotation) { + String pattern = annotation.value(); if (!TEMPORAL_QUERIES.containsKey(targetClass)) { throw new ArgumentConversionException("Cannot convert to " + targetClass.getName() + ": " + input); } diff --git a/junit-jupiter-params/src/main/java/org/junit/jupiter/params/support/AnnotationConsumerInitializer.java b/junit-jupiter-params/src/main/java/org/junit/jupiter/params/support/AnnotationConsumerInitializer.java index a5cf81304c45..83d9fd8fd2b0 100644 --- a/junit-jupiter-params/src/main/java/org/junit/jupiter/params/support/AnnotationConsumerInitializer.java +++ b/junit-jupiter-params/src/main/java/org/junit/jupiter/params/support/AnnotationConsumerInitializer.java @@ -36,15 +36,10 @@ private AnnotationConsumerInitializer() { /* no-op */ } - private static final Predicate isAcceptOrProvideArgumentsMethod = method -> isAnnotationConsumerAcceptMethod( - method) || isAnnotationBasedArgumentsProviderMethod(method); - @SuppressWarnings({ "unchecked", "rawtypes" }) public static T initialize(AnnotatedElement annotatedElement, T annotationConsumerInstance) { if (annotationConsumerInstance instanceof AnnotationConsumer) { - Method method = findMethods(annotationConsumerInstance.getClass(), isAcceptOrProvideArgumentsMethod, - BOTTOM_UP).get(0); - Class annotationType = getAnnotationType(method); + Class annotationType = findAnnotationType(annotationConsumerInstance); Annotation annotation = AnnotationUtils.findAnnotation(annotatedElement, annotationType) // .orElseThrow(() -> new JUnitException(annotationConsumerInstance.getClass().getName() + " must be used with an annotation of type " + annotationType.getName())); @@ -53,7 +48,25 @@ public static T initialize(AnnotatedElement annotatedElement, T annotationCo return annotationConsumerInstance; } - private static boolean isAnnotationConsumerAcceptMethod(Method method) { + private static Class findAnnotationType(T annotationConsumerInstance) { + Predicate hasAnnotationParameter = method -> isAnnotationConsumerMethod(method) + || isAnnotationBasedArgumentsProviderMethod(method) || isAnnotationBasedArgumentConverterMethod(method); + Method method = findMethods(annotationConsumerInstance.getClass(), hasAnnotationParameter, BOTTOM_UP).get(0); + return getAnnotationType(method); + } + + @SuppressWarnings("unchecked") + private static Class getAnnotationType(Method method) { + if (isAnnotationConsumerMethod(method)) { + return (Class) method.getParameterTypes()[0]; + } + if (isAnnotationBasedArgumentsProviderMethod(method)) { + return (Class) method.getParameterTypes()[1]; + } + return (Class) method.getParameterTypes()[2]; + } + + private static boolean isAnnotationConsumerMethod(Method method) { return isMethodWith(method, "accept", 1, 0); } @@ -61,22 +74,16 @@ private static boolean isAnnotationBasedArgumentsProviderMethod(Method method) { return isMethodWith(method, "provideArguments", 2, 1); } - // @formatter:off + private static boolean isAnnotationBasedArgumentConverterMethod(Method method) { + return isMethodWith(method, "convert", 3, 2); + } + private static boolean isMethodWith(Method method, String methodName, int parameterCount, int annotationInParameterIndex) { - return method.getName().equals(methodName) - && method.getParameterCount() == parameterCount + return method.getName().equals(methodName) // + && method.getParameterCount() == parameterCount // && method.getParameterTypes()[annotationInParameterIndex].isAnnotation(); } - // @formatter:on - - @SuppressWarnings({ "unchecked" }) - private static Class getAnnotationType(Method method) { - if (isAnnotationConsumerAcceptMethod(method)) { - return (Class) method.getParameterTypes()[0]; - } - return (Class) method.getParameterTypes()[1]; - } private static void initializeAnnotationConsumer(AnnotationConsumer instance, A annotation) { diff --git a/junit-jupiter-params/src/test/java/org/junit/jupiter/params/converter/JavaTimeArgumentConverterTests.java b/junit-jupiter-params/src/test/java/org/junit/jupiter/params/converter/JavaTimeArgumentConverterTests.java index 3bb890746dd9..5e3a54e2d271 100644 --- a/junit-jupiter-params/src/test/java/org/junit/jupiter/params/converter/JavaTimeArgumentConverterTests.java +++ b/junit-jupiter-params/src/test/java/org/junit/jupiter/params/converter/JavaTimeArgumentConverterTests.java @@ -114,9 +114,8 @@ private Object convert(Object input, String pattern, Class targetClass) { var converter = new JavaTimeArgumentConverter(); var annotation = mock(JavaTimeConversionPattern.class); when(annotation.value()).thenReturn(pattern); - converter.accept(annotation); - return converter.convert(input, targetClass); + return converter.convert(input, targetClass, annotation); } } diff --git a/junit-jupiter-params/src/test/java/org/junit/jupiter/params/support/AnnotationConsumerInitializerTest.java b/junit-jupiter-params/src/test/java/org/junit/jupiter/params/support/AnnotationConsumerInitializerTest.java index 43da248a78a8..0c22504d9236 100644 --- a/junit-jupiter-params/src/test/java/org/junit/jupiter/params/support/AnnotationConsumerInitializerTest.java +++ b/junit-jupiter-params/src/test/java/org/junit/jupiter/params/support/AnnotationConsumerInitializerTest.java @@ -14,13 +14,18 @@ import static org.assertj.core.api.Assertions.assertThatThrownBy; import static org.junit.jupiter.params.support.AnnotationConsumerInitializer.initialize; import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; +import java.time.LocalDate; import java.util.Arrays; import java.util.stream.Stream; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtensionContext; +import org.junit.jupiter.api.extension.ParameterContext; +import org.junit.jupiter.params.converter.AnnotationBasedArgumentConverter; +import org.junit.jupiter.params.converter.JavaTimeConversionPattern; import org.junit.jupiter.params.provider.AnnotationBasedArgumentsProvider; import org.junit.jupiter.params.provider.Arguments; import org.junit.jupiter.params.provider.CsvSource; @@ -44,37 +49,74 @@ void shouldInitializeAnnotationConsumer() throws NoSuchMethodException { @Test @DisplayName("should initialize annotation based arguments provider") void shouldInitializeAnnotationBasedArgumentsProvider() throws NoSuchMethodException { - var instance = new SomeAnnotationBasedArgumentProvider(); + var instance = new SomeAnnotationBasedArgumentsProvider(); var method = SubjectClass.class.getDeclaredMethod("foo"); var initialisedAnnotationConsumer = initialize(method, instance); initialisedAnnotationConsumer.provideArguments(mock()); - assertThat(initialisedAnnotationConsumer.assignedAnnotation) // + assertThat(initialisedAnnotationConsumer.annotation) // .isInstanceOf(CsvSource.class) // .matches(annotation -> Arrays.equals(annotation.value(), new String[] { "a", "b" })); } + @Test + @DisplayName("should initialize annotation based argument converter") + void shouldInitializeAnnotationBasedArgumentConverter() throws NoSuchMethodException { + var instance = new SomeAnnotationBasedArgumentConverter(); + var parameter = SubjectClass.class.getDeclaredMethod("bar", LocalDate.class).getParameters()[0]; + var initialisedAnnotationConsumer = initialize(parameter, instance); + + ParameterContext parameterContext = mock(); + when(parameterContext.getParameter()).thenReturn(parameter); + initialisedAnnotationConsumer.convert("source", parameterContext); + + assertThat(initialisedAnnotationConsumer.annotation) // + .isInstanceOf(JavaTimeConversionPattern.class) // + .matches(annotation -> annotation.value().equals("pattern")); + } + @Test @DisplayName("should throw exception when method is not annotated") void shouldThrowExceptionWhenMethodIsNotAnnotated() throws NoSuchMethodException { var instance = new SomeAnnotationConsumer(); - var method = SubjectClass.class.getDeclaredMethod("noAnnotation"); + var method = SubjectClass.class.getDeclaredMethod("noAnnotation", String.class); assertThatThrownBy(() -> initialize(method, instance)).isInstanceOf(JUnitException.class); } - private static class SomeAnnotationBasedArgumentProvider extends AnnotationBasedArgumentsProvider { + @Test + @DisplayName("should throw exception when parameter is not annotated") + void shouldThrowExceptionWhenParameterIsNotAnnotated() throws NoSuchMethodException { + var instance = new SomeAnnotationConsumer(); + var parameter = SubjectClass.class.getDeclaredMethod("noAnnotation", String.class).getParameters()[0]; + + assertThatThrownBy(() -> initialize(parameter, instance)).isInstanceOf(JUnitException.class); + } + + private static class SomeAnnotationBasedArgumentsProvider extends AnnotationBasedArgumentsProvider { - CsvSource assignedAnnotation; + CsvSource annotation; @Override protected Stream provideArguments(ExtensionContext context, CsvSource annotation) { - assignedAnnotation = annotation; + this.annotation = annotation; return Stream.empty(); } } + private static class SomeAnnotationBasedArgumentConverter + extends AnnotationBasedArgumentConverter { + + JavaTimeConversionPattern annotation; + + @Override + protected Object convert(Object source, Class targetType, JavaTimeConversionPattern annotation) { + this.annotation = annotation; + return null; + } + } + private static class SomeAnnotationConsumer implements AnnotationConsumer { CsvSource annotation; @@ -92,7 +134,11 @@ void foo() { } - void noAnnotation() { + void bar(@JavaTimeConversionPattern("pattern") LocalDate date) { + + } + + void noAnnotation(String param) { } } From ee2926889fa36f5ed0adb889fb3996d40cdbfac3 Mon Sep 17 00:00:00 2001 From: Juliette de Rancourt Date: Wed, 22 Mar 2023 19:51:23 +0100 Subject: [PATCH 0058/1473] Refactor `AnnotationConsumerInitializer` Following introduction of new `AnnotationConsumer` implementations (`AnnotationBasedArgumentsProvider` and `AnnotationBasedArgumentConverter`) --- .../AnnotationConsumerInitializer.java | 73 +++++++++++-------- 1 file changed, 43 insertions(+), 30 deletions(-) diff --git a/junit-jupiter-params/src/main/java/org/junit/jupiter/params/support/AnnotationConsumerInitializer.java b/junit-jupiter-params/src/main/java/org/junit/jupiter/params/support/AnnotationConsumerInitializer.java index 83d9fd8fd2b0..b495f79c5b50 100644 --- a/junit-jupiter-params/src/main/java/org/junit/jupiter/params/support/AnnotationConsumerInitializer.java +++ b/junit-jupiter-params/src/main/java/org/junit/jupiter/params/support/AnnotationConsumerInitializer.java @@ -10,6 +10,7 @@ package org.junit.jupiter.params.support; +import static java.util.Arrays.asList; import static org.apiguardian.api.API.Status.INTERNAL; import static org.junit.platform.commons.util.ReflectionUtils.HierarchyTraversalMode.BOTTOM_UP; import static org.junit.platform.commons.util.ReflectionUtils.findMethods; @@ -17,6 +18,7 @@ import java.lang.annotation.Annotation; import java.lang.reflect.AnnotatedElement; import java.lang.reflect.Method; +import java.util.List; import java.util.function.Predicate; import org.apiguardian.api.API; @@ -32,6 +34,11 @@ @API(status = INTERNAL, since = "5.0") public final class AnnotationConsumerInitializer { + private static final List annotationConsumingMethodSignatures = asList( // + new AnnotationConsumingMethodSignature("accept", 1, 0), // + new AnnotationConsumingMethodSignature("provideArguments", 2, 1), // + new AnnotationConsumingMethodSignature("convert", 3, 2)); + private AnnotationConsumerInitializer() { /* no-op */ } @@ -39,7 +46,7 @@ private AnnotationConsumerInitializer() { @SuppressWarnings({ "unchecked", "rawtypes" }) public static T initialize(AnnotatedElement annotatedElement, T annotationConsumerInstance) { if (annotationConsumerInstance instanceof AnnotationConsumer) { - Class annotationType = findAnnotationType(annotationConsumerInstance); + Class annotationType = findConsumedAnnotationType(annotationConsumerInstance); Annotation annotation = AnnotationUtils.findAnnotation(annotatedElement, annotationType) // .orElseThrow(() -> new JUnitException(annotationConsumerInstance.getClass().getName() + " must be used with an annotation of type " + annotationType.getName())); @@ -48,41 +55,23 @@ public static T initialize(AnnotatedElement annotatedElement, T annotationCo return annotationConsumerInstance; } - private static Class findAnnotationType(T annotationConsumerInstance) { - Predicate hasAnnotationParameter = method -> isAnnotationConsumerMethod(method) - || isAnnotationBasedArgumentsProviderMethod(method) || isAnnotationBasedArgumentConverterMethod(method); - Method method = findMethods(annotationConsumerInstance.getClass(), hasAnnotationParameter, BOTTOM_UP).get(0); + private static Class findConsumedAnnotationType(T annotationConsumerInstance) { + Predicate consumesAnnotation = annotationConsumingMethodSignatures.stream() // + .map(signature -> (Predicate) signature::isMatchingWith) // + .reduce(method -> false, Predicate::or); + Method method = findMethods(annotationConsumerInstance.getClass(), consumesAnnotation, BOTTOM_UP).get(0); return getAnnotationType(method); } @SuppressWarnings("unchecked") private static Class getAnnotationType(Method method) { - if (isAnnotationConsumerMethod(method)) { - return (Class) method.getParameterTypes()[0]; - } - if (isAnnotationBasedArgumentsProviderMethod(method)) { - return (Class) method.getParameterTypes()[1]; - } - return (Class) method.getParameterTypes()[2]; - } - - private static boolean isAnnotationConsumerMethod(Method method) { - return isMethodWith(method, "accept", 1, 0); - } - - private static boolean isAnnotationBasedArgumentsProviderMethod(Method method) { - return isMethodWith(method, "provideArguments", 2, 1); - } - - private static boolean isAnnotationBasedArgumentConverterMethod(Method method) { - return isMethodWith(method, "convert", 3, 2); - } + int annotationIndex = annotationConsumingMethodSignatures.stream() // + .filter(signature -> signature.isMatchingWith(method)) // + .findFirst() // + .map(AnnotationConsumingMethodSignature::getAnnotationParameterIndex) // + .orElse(0); - private static boolean isMethodWith(Method method, String methodName, int parameterCount, - int annotationInParameterIndex) { - return method.getName().equals(methodName) // - && method.getParameterCount() == parameterCount // - && method.getParameterTypes()[annotationInParameterIndex].isAnnotation(); + return (Class) method.getParameterTypes()[annotationIndex]; } private static void initializeAnnotationConsumer(AnnotationConsumer instance, @@ -95,4 +84,28 @@ private static void initializeAnnotationConsumer(Annotati } } + private static class AnnotationConsumingMethodSignature { + + private final String methodName; + private final int parameterCount; + private final int annotationParameterIndex; + + AnnotationConsumingMethodSignature(String methodName, int parameterCount, int annotationParameterIndex) { + this.methodName = methodName; + this.parameterCount = parameterCount; + this.annotationParameterIndex = annotationParameterIndex; + } + + boolean isMatchingWith(Method method) { + return method.getName().equals(methodName) // + && method.getParameterCount() == parameterCount // + && method.getParameterTypes()[annotationParameterIndex].isAnnotation(); + } + + int getAnnotationParameterIndex() { + return annotationParameterIndex; + } + + } + } From 8893a8ad6651c1c19e84f3400b83c5810067ddc9 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 27 Mar 2023 06:03:17 +0000 Subject: [PATCH 0059/1473] Bump xmlunit from 2.9.0 to 2.9.1 Bumps `xmlunit` from 2.9.0 to 2.9.1. Updates `org.xmlunit:xmlunit-assertj3` from 2.9.0 to 2.9.1 - [Release notes](https://github.com/xmlunit/xmlunit/releases) - [Changelog](https://github.com/xmlunit/xmlunit/blob/main/RELEASE_NOTES.md) - [Commits](https://github.com/xmlunit/xmlunit/compare/v2.9.0...v2.9.1) Updates `org.xmlunit:xmlunit-placeholders` from 2.9.0 to 2.9.1 - [Release notes](https://github.com/xmlunit/xmlunit/releases) - [Changelog](https://github.com/xmlunit/xmlunit/blob/main/RELEASE_NOTES.md) - [Commits](https://github.com/xmlunit/xmlunit/compare/v2.9.0...v2.9.1) --- updated-dependencies: - dependency-name: org.xmlunit:xmlunit-assertj3 dependency-type: direct:production update-type: version-update:semver-patch - dependency-name: org.xmlunit:xmlunit-placeholders dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- gradle/libs.versions.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 3c3705ea4f41..923927f3aa49 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -14,7 +14,7 @@ log4j = "2.20.0" opentest4j = "1.2.0" openTestReporting = "0.1.0-M1" surefire = "3.0.0-M7" -xmlunit = "2.9.0" +xmlunit = "2.9.1" [libraries] ant = { module = "org.apache.ant:ant", version.ref = "ant" } From 81643825552e1cf287f7caab25d67493d26a65ec Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 27 Mar 2023 06:03:19 +0000 Subject: [PATCH 0060/1473] Bump com.gradle.enterprise from 3.12.4 to 3.12.6 Bumps com.gradle.enterprise from 3.12.4 to 3.12.6. --- updated-dependencies: - dependency-name: com.gradle.enterprise dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- settings.gradle.kts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/settings.gradle.kts b/settings.gradle.kts index 064b7f8b8211..bb610b13e6ee 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -7,7 +7,7 @@ pluginManagement { gradlePluginPortal() } plugins { - id("com.gradle.enterprise") version "3.12.4" // keep in sync with gradle/plugins/build.gradle.kts + id("com.gradle.enterprise") version "3.12.6" // keep in sync with gradle/plugins/build.gradle.kts id("com.gradle.common-custom-user-data-gradle-plugin") version "1.10" id("org.gradle.toolchains.foojay-resolver-convention") version "0.4.0" id("org.ajoberstar.git-publish") version "4.1.1" From 849e61d263c865a808066f8d72119232e7c242b3 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 27 Mar 2023 06:03:27 +0000 Subject: [PATCH 0061/1473] Bump com.gradle:gradle-enterprise-gradle-plugin from 3.12.4 to 3.12.6 Bumps com.gradle:gradle-enterprise-gradle-plugin from 3.12.4 to 3.12.6. --- updated-dependencies: - dependency-name: com.gradle:gradle-enterprise-gradle-plugin dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- gradle/plugins/common/build.gradle.kts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle/plugins/common/build.gradle.kts b/gradle/plugins/common/build.gradle.kts index 123fba670a5f..f07c0917e92c 100644 --- a/gradle/plugins/common/build.gradle.kts +++ b/gradle/plugins/common/build.gradle.kts @@ -16,7 +16,7 @@ dependencies { implementation("com.diffplug.spotless:spotless-plugin-gradle:6.17.0") implementation("com.github.ben-manes:gradle-versions-plugin:0.46.0") implementation("gradle.plugin.com.github.johnrengelman:shadow:8.0.0") - compileOnly("com.gradle:gradle-enterprise-gradle-plugin:3.12.4") // keep in sync with root settings.gradle.kts + compileOnly("com.gradle:gradle-enterprise-gradle-plugin:3.12.6") // keep in sync with root settings.gradle.kts } tasks { From a47cb448e3cb3869e364e04248b261669caeda4f Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 27 Mar 2023 06:03:31 +0000 Subject: [PATCH 0062/1473] Bump org.apache.groovy:groovy from 4.0.7 to 4.0.10 Bumps [org.apache.groovy:groovy](https://github.com/apache/groovy) from 4.0.7 to 4.0.10. - [Release notes](https://github.com/apache/groovy/releases) - [Commits](https://github.com/apache/groovy/commits) --- updated-dependencies: - dependency-name: org.apache.groovy:groovy dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- gradle/libs.versions.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 923927f3aa49..ec74903eee48 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -27,7 +27,7 @@ bartholdy = { module = "de.sormuras:bartholdy", version = "0.2.3" } bnd = { module = "biz.aQute.bnd:biz.aQute.bndlib", version = "6.4.0" } classgraph = { module = "io.github.classgraph:classgraph", version = "4.8.153" } commons-io = { module = "commons-io:commons-io", version = "2.11.0" } -groovy4 = { module = "org.apache.groovy:groovy", version = "4.0.7" } +groovy4 = { module = "org.apache.groovy:groovy", version = "4.0.10" } groovy2-bom = { module = "org.codehaus.groovy:groovy-bom", version = "2.5.14" } hamcrest = { module = "org.hamcrest:hamcrest", version = "2.2" } jfrunit = { module = "org.moditect.jfrunit:jfrunit-core", version = "1.0.0.Alpha2" } From d5a9364735829417c94b7fd66e809dc3042ddfed Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 27 Mar 2023 06:06:31 +0000 Subject: [PATCH 0063/1473] Bump github/combine-prs from 2.0.3 to 2.1.0 Bumps [github/combine-prs](https://github.com/github/combine-prs) from 2.0.3 to 2.1.0. - [Release notes](https://github.com/github/combine-prs/releases) - [Commits](https://github.com/github/combine-prs/compare/v2.0.3...v2.1.0) --- updated-dependencies: - dependency-name: github/combine-prs dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- .github/workflows/combine-prs.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/combine-prs.yml b/.github/workflows/combine-prs.yml index 18deff854a67..eff6a10a2cf2 100644 --- a/.github/workflows/combine-prs.yml +++ b/.github/workflows/combine-prs.yml @@ -10,6 +10,6 @@ jobs: runs-on: ubuntu-latest steps: - name: combine-prs - uses: github/combine-prs@v2.0.3 + uses: github/combine-prs@v2.1.0 with: github_token: ${{ secrets.GH_TOKEN }} From e188b1eae321866f8fe87c9736f8c5d6e41cba24 Mon Sep 17 00:00:00 2001 From: Marc Philipp Date: Mon, 27 Mar 2023 18:22:30 +0200 Subject: [PATCH 0064/1473] Update Groovy to 2.5.21 --- gradle/libs.versions.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index ec74903eee48..9d5be3d62323 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -28,7 +28,7 @@ bnd = { module = "biz.aQute.bnd:biz.aQute.bndlib", version = "6.4.0" } classgraph = { module = "io.github.classgraph:classgraph", version = "4.8.153" } commons-io = { module = "commons-io:commons-io", version = "2.11.0" } groovy4 = { module = "org.apache.groovy:groovy", version = "4.0.10" } -groovy2-bom = { module = "org.codehaus.groovy:groovy-bom", version = "2.5.14" } +groovy2-bom = { module = "org.codehaus.groovy:groovy-bom", version = "2.5.21" } hamcrest = { module = "org.hamcrest:hamcrest", version = "2.2" } jfrunit = { module = "org.moditect.jfrunit:jfrunit-core", version = "1.0.0.Alpha2" } jmh-core = { module = "org.openjdk.jmh:jmh-core", version.ref = "jmh" } From a5b642b5a44a4d4d5d63cf2b79854cb469149a6b Mon Sep 17 00:00:00 2001 From: Mahdi Hosseinzadeh <29678011+mahozad@users.noreply.github.com> Date: Sun, 2 Apr 2023 17:08:56 +0330 Subject: [PATCH 0065/1473] Document `@MethodSource` as use case for `@TestInstance` per-class lifecycle This commit documents another use case for TestInstace.PER_CLASS in Kotlin, namely, using a regular simple class method as a factory method for @MethodSource (which is used for parameterized tests). Closes: #3219 --- documentation/src/docs/asciidoc/user-guide/writing-tests.adoc | 4 ++-- .../src/main/java/org/junit/jupiter/api/TestInstance.java | 3 ++- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/documentation/src/docs/asciidoc/user-guide/writing-tests.adoc b/documentation/src/docs/asciidoc/user-guide/writing-tests.adoc index a0fc45f2934c..e2431391e330 100644 --- a/documentation/src/docs/asciidoc/user-guide/writing-tests.adoc +++ b/documentation/src/docs/asciidoc/user-guide/writing-tests.adoc @@ -751,8 +751,8 @@ NOTE: Beginning with Java 16, `@BeforeAll` and `@AfterAll` methods can be declar `static` in `@Nested` test classes. If you are authoring tests using the Kotlin programming language, you may also find it -easier to implement `@BeforeAll` and `@AfterAll` methods by switching to the "per-class" -test instance lifecycle mode. +easier to implement `@BeforeAll` and `@AfterAll` methods and also factory methods for +`@MethodSource` by switching to the "per-class" test instance lifecycle mode. [[writing-tests-test-instance-lifecycle-changing-default]] ==== Changing the Default Test Instance Lifecycle diff --git a/junit-jupiter-api/src/main/java/org/junit/jupiter/api/TestInstance.java b/junit-jupiter-api/src/main/java/org/junit/jupiter/api/TestInstance.java index 0e6ae3758b63..ac7840503c0f 100644 --- a/junit-jupiter-api/src/main/java/org/junit/jupiter/api/TestInstance.java +++ b/junit-jupiter-api/src/main/java/org/junit/jupiter/api/TestInstance.java @@ -51,7 +51,8 @@ *

  • Declaration of {@code @BeforeAll} and {@code @AfterAll} on interface * {@code default} methods.
  • *
  • Simplified declaration of non-static {@code @BeforeAll} and {@code @AfterAll} - * methods in test classes implemented with the Kotlin programming language.
  • + * methods and also factory methods for {@code @MethodSource} in test classes + * implemented with the Kotlin programming language. * * *

    {@code @TestInstance} may also be used as a meta-annotation in order to From 78aaadeae0fdf4d4eb4aee82ef1ba6a3cf5b8d1f Mon Sep 17 00:00:00 2001 From: Sam Brannen Date: Sun, 2 Apr 2023 15:44:33 +0200 Subject: [PATCH 0066/1473] Polishing --- .../src/docs/asciidoc/user-guide/writing-tests.adoc | 5 +++-- .../src/main/java/org/junit/jupiter/api/TestInstance.java | 2 +- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/documentation/src/docs/asciidoc/user-guide/writing-tests.adoc b/documentation/src/docs/asciidoc/user-guide/writing-tests.adoc index e2431391e330..e22203936216 100644 --- a/documentation/src/docs/asciidoc/user-guide/writing-tests.adoc +++ b/documentation/src/docs/asciidoc/user-guide/writing-tests.adoc @@ -751,8 +751,9 @@ NOTE: Beginning with Java 16, `@BeforeAll` and `@AfterAll` methods can be declar `static` in `@Nested` test classes. If you are authoring tests using the Kotlin programming language, you may also find it -easier to implement `@BeforeAll` and `@AfterAll` methods and also factory methods for -`@MethodSource` by switching to the "per-class" test instance lifecycle mode. +easier to implement non-static `@BeforeAll` and `@AfterAll` lifecycle methods as well as +`@MethodSource` factory methods by switching to the "per-class" test instance lifecycle +mode. [[writing-tests-test-instance-lifecycle-changing-default]] ==== Changing the Default Test Instance Lifecycle diff --git a/junit-jupiter-api/src/main/java/org/junit/jupiter/api/TestInstance.java b/junit-jupiter-api/src/main/java/org/junit/jupiter/api/TestInstance.java index ac7840503c0f..5c57e95e4a14 100644 --- a/junit-jupiter-api/src/main/java/org/junit/jupiter/api/TestInstance.java +++ b/junit-jupiter-api/src/main/java/org/junit/jupiter/api/TestInstance.java @@ -51,7 +51,7 @@ *

  • Declaration of {@code @BeforeAll} and {@code @AfterAll} on interface * {@code default} methods.
  • *
  • Simplified declaration of non-static {@code @BeforeAll} and {@code @AfterAll} - * methods and also factory methods for {@code @MethodSource} in test classes + * lifecycle methods as well as {@code @MethodSource} factory methods in test classes * implemented with the Kotlin programming language.
  • * * From b56de5743cdb7fcda2afd01f8cb9b4bfac68c6e6 Mon Sep 17 00:00:00 2001 From: Sam Brannen Date: Sun, 2 Apr 2023 16:40:49 +0200 Subject: [PATCH 0067/1473] Rename test classes to adhere to naming policy --- ...ionTest.java => SeparateThreadTimeoutInvocationTests.java} | 4 ++-- ...tionFactoryTest.java => TimeoutExceptionFactoryTests.java} | 2 +- ...ionFactoryTest.java => TimeoutInvocationFactoryTests.java} | 4 ++-- ...erTest.java => AnnotationBasedArgumentsProviderTests.java} | 2 +- ...lizerTest.java => AnnotationConsumerInitializerTests.java} | 2 +- 5 files changed, 7 insertions(+), 7 deletions(-) rename junit-jupiter-engine/src/test/java/org/junit/jupiter/engine/extension/{SeparateThreadTimeoutInvocationTest.java => SeparateThreadTimeoutInvocationTests.java} (97%) rename junit-jupiter-engine/src/test/java/org/junit/jupiter/engine/extension/{TimeoutExceptionFactoryTest.java => TimeoutExceptionFactoryTests.java} (98%) rename junit-jupiter-engine/src/test/java/org/junit/jupiter/engine/extension/{TimeoutInvocationFactoryTest.java => TimeoutInvocationFactoryTests.java} (98%) rename junit-jupiter-params/src/test/java/org/junit/jupiter/params/provider/{AnnotationBasedArgumentsProviderTest.java => AnnotationBasedArgumentsProviderTests.java} (97%) rename junit-jupiter-params/src/test/java/org/junit/jupiter/params/support/{AnnotationConsumerInitializerTest.java => AnnotationConsumerInitializerTests.java} (99%) diff --git a/junit-jupiter-engine/src/test/java/org/junit/jupiter/engine/extension/SeparateThreadTimeoutInvocationTest.java b/junit-jupiter-engine/src/test/java/org/junit/jupiter/engine/extension/SeparateThreadTimeoutInvocationTests.java similarity index 97% rename from junit-jupiter-engine/src/test/java/org/junit/jupiter/engine/extension/SeparateThreadTimeoutInvocationTest.java rename to junit-jupiter-engine/src/test/java/org/junit/jupiter/engine/extension/SeparateThreadTimeoutInvocationTests.java index 8ea41562ddf6..7ec645925f5f 100644 --- a/junit-jupiter-engine/src/test/java/org/junit/jupiter/engine/extension/SeparateThreadTimeoutInvocationTest.java +++ b/junit-jupiter-engine/src/test/java/org/junit/jupiter/engine/extension/SeparateThreadTimeoutInvocationTests.java @@ -31,7 +31,7 @@ * @since 5.9 */ @DisplayName("SeparateThreadTimeoutInvocation") -class SeparateThreadTimeoutInvocationTest { +class SeparateThreadTimeoutInvocationTests { private static final long PREEMPTIVE_TIMEOUT_MILLIS = WINDOWS.isCurrentOs() ? 1000 : 100; @@ -70,7 +70,7 @@ void shouldThrowInvocationException() { } private static SeparateThreadTimeoutInvocation aSeparateThreadInvocation(Invocation invocation) { - var namespace = ExtensionContext.Namespace.create(SeparateThreadTimeoutInvocationTest.class); + var namespace = ExtensionContext.Namespace.create(SeparateThreadTimeoutInvocationTests.class); var store = new NamespaceAwareStore(new ExtensionValuesStore(null), namespace); var parameters = new TimeoutInvocationParameters<>(invocation, new TimeoutDuration(PREEMPTIVE_TIMEOUT_MILLIS, MILLISECONDS), () -> "method()"); diff --git a/junit-jupiter-engine/src/test/java/org/junit/jupiter/engine/extension/TimeoutExceptionFactoryTest.java b/junit-jupiter-engine/src/test/java/org/junit/jupiter/engine/extension/TimeoutExceptionFactoryTests.java similarity index 98% rename from junit-jupiter-engine/src/test/java/org/junit/jupiter/engine/extension/TimeoutExceptionFactoryTest.java rename to junit-jupiter-engine/src/test/java/org/junit/jupiter/engine/extension/TimeoutExceptionFactoryTests.java index 95aa77c42c42..66ca3ce8d613 100644 --- a/junit-jupiter-engine/src/test/java/org/junit/jupiter/engine/extension/TimeoutExceptionFactoryTest.java +++ b/junit-jupiter-engine/src/test/java/org/junit/jupiter/engine/extension/TimeoutExceptionFactoryTests.java @@ -25,7 +25,7 @@ * @since 5.9 */ @DisplayName("TimeoutExceptionFactory") -class TimeoutExceptionFactoryTest { +class TimeoutExceptionFactoryTests { private static final TimeoutDuration tenMillisDuration = new TimeoutDuration(10, MILLISECONDS); private static final Exception suppressedException = new Exception("Winke!"); diff --git a/junit-jupiter-engine/src/test/java/org/junit/jupiter/engine/extension/TimeoutInvocationFactoryTest.java b/junit-jupiter-engine/src/test/java/org/junit/jupiter/engine/extension/TimeoutInvocationFactoryTests.java similarity index 98% rename from junit-jupiter-engine/src/test/java/org/junit/jupiter/engine/extension/TimeoutInvocationFactoryTest.java rename to junit-jupiter-engine/src/test/java/org/junit/jupiter/engine/extension/TimeoutInvocationFactoryTests.java index 31dda7730477..a6b2b650afbd 100644 --- a/junit-jupiter-engine/src/test/java/org/junit/jupiter/engine/extension/TimeoutInvocationFactoryTest.java +++ b/junit-jupiter-engine/src/test/java/org/junit/jupiter/engine/extension/TimeoutInvocationFactoryTests.java @@ -32,11 +32,11 @@ @DisplayName("TimeoutInvocationFactory") @ExtendWith(MockitoExtension.class) -class TimeoutInvocationFactoryTest { +class TimeoutInvocationFactoryTests { @Spy private final Store store = new NamespaceAwareStore(new ExtensionValuesStore(null), - ExtensionContext.Namespace.create(TimeoutInvocationFactoryTest.class)); + ExtensionContext.Namespace.create(TimeoutInvocationFactoryTests.class)); @Mock private Invocation invocation; @Mock diff --git a/junit-jupiter-params/src/test/java/org/junit/jupiter/params/provider/AnnotationBasedArgumentsProviderTest.java b/junit-jupiter-params/src/test/java/org/junit/jupiter/params/provider/AnnotationBasedArgumentsProviderTests.java similarity index 97% rename from junit-jupiter-params/src/test/java/org/junit/jupiter/params/provider/AnnotationBasedArgumentsProviderTest.java rename to junit-jupiter-params/src/test/java/org/junit/jupiter/params/provider/AnnotationBasedArgumentsProviderTests.java index ae54960f289c..757190eb9371 100644 --- a/junit-jupiter-params/src/test/java/org/junit/jupiter/params/provider/AnnotationBasedArgumentsProviderTest.java +++ b/junit-jupiter-params/src/test/java/org/junit/jupiter/params/provider/AnnotationBasedArgumentsProviderTests.java @@ -25,7 +25,7 @@ import org.junit.jupiter.api.extension.ExtensionContext; @DisplayName("AnnotationBasedArgumentsProvider") -class AnnotationBasedArgumentsProviderTest { +class AnnotationBasedArgumentsProviderTests { private final AnnotationBasedArgumentsProvider annotationBasedArgumentsProvider = new AnnotationBasedArgumentsProvider<>() { @Override diff --git a/junit-jupiter-params/src/test/java/org/junit/jupiter/params/support/AnnotationConsumerInitializerTest.java b/junit-jupiter-params/src/test/java/org/junit/jupiter/params/support/AnnotationConsumerInitializerTests.java similarity index 99% rename from junit-jupiter-params/src/test/java/org/junit/jupiter/params/support/AnnotationConsumerInitializerTest.java rename to junit-jupiter-params/src/test/java/org/junit/jupiter/params/support/AnnotationConsumerInitializerTests.java index 0c22504d9236..2faee8a27ff9 100644 --- a/junit-jupiter-params/src/test/java/org/junit/jupiter/params/support/AnnotationConsumerInitializerTest.java +++ b/junit-jupiter-params/src/test/java/org/junit/jupiter/params/support/AnnotationConsumerInitializerTests.java @@ -32,7 +32,7 @@ import org.junit.platform.commons.JUnitException; @DisplayName("AnnotationConsumerInitializer") -class AnnotationConsumerInitializerTest { +class AnnotationConsumerInitializerTests { @Test @DisplayName("should initialize annotation consumer") From 1c294651ab3965a8bfe8909f6efdc56c5a47c4f0 Mon Sep 17 00:00:00 2001 From: Sam Brannen Date: Sun, 2 Apr 2023 17:27:45 +0200 Subject: [PATCH 0068/1473] Polishing --- .../release-notes-5.10.0-M1.adoc | 35 ++++++++------- .../asciidoc/user-guide/writing-tests.adoc | 14 +++--- .../AnnotationBasedArgumentConverter.java | 11 ++--- .../converter/JavaTimeArgumentConverter.java | 9 ++-- .../AnnotationBasedArgumentsProvider.java | 8 ++-- .../params/provider/CsvArgumentsProvider.java | 2 +- .../provider/CsvFileArgumentsProvider.java | 2 +- .../jupiter/params/provider/EmptySource.java | 4 +- .../provider/EnumArgumentsProvider.java | 2 +- .../provider/MethodArgumentsProvider.java | 2 +- .../provider/ValueArgumentsProvider.java | 2 +- .../ParameterizedTestIntegrationTests.java | 44 +++++++++---------- ...AnnotationBasedArgumentsProviderTests.java | 2 +- .../AnnotationConsumerInitializerTests.java | 22 +++++----- 14 files changed, 82 insertions(+), 77 deletions(-) diff --git a/documentation/src/docs/asciidoc/release-notes/release-notes-5.10.0-M1.adoc b/documentation/src/docs/asciidoc/release-notes/release-notes-5.10.0-M1.adoc index 2f8ebd6bf778..b1a7b61e62d7 100644 --- a/documentation/src/docs/asciidoc/release-notes/release-notes-5.10.0-M1.adoc +++ b/documentation/src/docs/asciidoc/release-notes/release-notes-5.10.0-M1.adoc @@ -24,19 +24,22 @@ repository on GitHub. ==== New Features and Improvements -* All utility methods from `ReflectionSupport` now have counterparts returning `Stream` - instead of `List`. -* For consistency with Jupiter lifecycle callbacks, listener method pairs for started/ - finished and opened/closed events are now called using "wrap" semantics, i.e. the latter - methods are called in reverse order compared to the former when multiple listeners are - registered. This affects the following listener interfaces: `TestExecutionListener`, - `EngineExecutionListener`, `LauncherDiscoveryListener`, and `LauncherSessionListener`. -* Introduce `LauncherInterceptor` SPI for intercepting the creation of instances of - `Launcher` and `LauncherSessionlistener` as well as calls for `discover` and `execute` - of the former. Please refer to the +* All utility methods in `ReflectionSupport` that return a `List` now have counterparts + which return a `Stream`. +* For consistency with JUnit Jupiter lifecycle callbacks, listener method pairs for + started/finished and opened/closed events are now invoked using "wrapping" semantics. + This means that finished/closed event methods are invoked in reverse order compared to + the corresponding started/opened event methods when multiple listeners are registered. + This affects the following listener interfaces: + `TestExecutionListener`, `EngineExecutionListener`, `LauncherDiscoveryListener`, and + `LauncherSessionListener`. +* New `LauncherInterceptor` SPI for intercepting the creation of instances of `Launcher` + and `LauncherSessionlistener` as well as invocations of the `discover` and `execute` + methods of the former. Please refer to the <<../user-guide/index.adoc#launcher-api-launcher-interceptors-custom, User Guide>> for details. + [[release-notes-5.10.0-M1-junit-jupiter]] === JUnit Jupiter @@ -60,14 +63,14 @@ repository on GitHub. * New `ArgumentsAccessor.getInvocationIndex()` method that supplies the index of a `@ParameterizedTest` invocation. -* `DisplayNameGenerator` methods are now allowed to return `null`, in order to signal - to fall back to the default display name generator. +* `DisplayNameGenerator` methods are now allowed to return `null`, in order to signal to + fall back to the default display name generator. * `@EmptySource` now supports additional types, including `Collection` and `Map` subtypes with a public no-arg constructor. -* New `AnnotationBasedArgumentsProvider` that implements both `ArgumentsProvider` and - `AnnotationConsumer` interfaces. -* New `AnnotationBasedArgumentConverter` that implements both `ArgumentConverter` and - `AnnotationConsumer` interfaces. +* New `AnnotationBasedArgumentsProvider` convenience base class which implements both + `ArgumentsProvider` and `AnnotationConsumer`. +* New `AnnotationBasedArgumentConverter` convenience base class which implements both + `ArgumentConverter` and `AnnotationConsumer`. [[release-notes-5.10.0-M1-junit-vintage]] diff --git a/documentation/src/docs/asciidoc/user-guide/writing-tests.adoc b/documentation/src/docs/asciidoc/user-guide/writing-tests.adoc index e22203936216..eefe3f682d85 100644 --- a/documentation/src/docs/asciidoc/user-guide/writing-tests.adoc +++ b/documentation/src/docs/asciidoc/user-guide/writing-tests.adoc @@ -1257,13 +1257,13 @@ for parameterized tests that accept a single argument. * `{NullSource}`: provides a single `null` argument to the annotated `@ParameterizedTest` method. - `@NullSource` cannot be used for a parameter that has a primitive type. -* `{EmptySource}`: provides a single _empty_ argument to the annotated `@ParameterizedTest` - method for parameters of the following types: `java.lang.String`, `java.util.Collection` - and subtypes with a public no-arg constructor, `java.util.List`, `java.util.Set`, - `java.util.SortedSet`, `java.util.NavigableSet`, `java.util.Map` and subtypes with a - public no-arg constructor, `java.util.SortedMap`, `java.util.NavigableMap`, primitive - arrays (e.g., `int[]`, `char[][]`, etc.), object arrays (e.g.,`String[]`, `Integer[][]`, - etc.). +* `{EmptySource}`: provides a single _empty_ argument to the annotated + `@ParameterizedTest` method for parameters of the following types: `java.lang.String`, + `java.util.Collection` (and concrete subtypes with a `public` no-arg constructor), + `java.util.List`, `java.util.Set`, `java.util.SortedSet`, `java.util.NavigableSet`, + `java.util.Map` (and concrete subtypes with a `public` no-arg constructor, + `java.util.SortedMap`, `java.util.NavigableMap`, primitive arrays (e.g., `int[]`, + `char[][]`, etc.), object arrays (e.g.,`String[]`, `Integer[][]`, etc.). * `{NullAndEmptySource}`: a _composed annotation_ that combines the functionality of `@NullSource` and `@EmptySource`. diff --git a/junit-jupiter-params/src/main/java/org/junit/jupiter/params/converter/AnnotationBasedArgumentConverter.java b/junit-jupiter-params/src/main/java/org/junit/jupiter/params/converter/AnnotationBasedArgumentConverter.java index 964c0c23616a..fa67ae7c8d74 100644 --- a/junit-jupiter-params/src/main/java/org/junit/jupiter/params/converter/AnnotationBasedArgumentConverter.java +++ b/junit-jupiter-params/src/main/java/org/junit/jupiter/params/converter/AnnotationBasedArgumentConverter.java @@ -46,22 +46,23 @@ public final void accept(A annotation) { @Override public final Object convert(Object source, ParameterContext context) throws ArgumentConversionException { - return convert(source, context.getParameter().getType(), annotation); + return convert(source, context.getParameter().getType(), this.annotation); } /** - * Convert the supplied {@code source} object into the supplied - * {@code targetType}. + * Convert the supplied {@code source} object into the supplied {@code targetType}, + * based on metadata in the provided annotation. * * @param source the source object to convert; may be {@code null} * @param targetType the target type the source object should be converted * into; never {@code null} - * @param annotation the annotation needed to convert the source; never {@code null} + * @param annotation the annotation to process; never {@code null} * @return the converted object; may be {@code null} but only if the target * type is a reference type * @throws ArgumentConversionException in case an error occurs during the * conversion */ - protected abstract Object convert(Object source, Class targetType, A annotation); + protected abstract Object convert(Object source, Class targetType, A annotation) + throws ArgumentConversionException; } diff --git a/junit-jupiter-params/src/main/java/org/junit/jupiter/params/converter/JavaTimeArgumentConverter.java b/junit-jupiter-params/src/main/java/org/junit/jupiter/params/converter/JavaTimeArgumentConverter.java index aef6e5a44cc8..3af740fa7a3c 100644 --- a/junit-jupiter-params/src/main/java/org/junit/jupiter/params/converter/JavaTimeArgumentConverter.java +++ b/junit-jupiter-params/src/main/java/org/junit/jupiter/params/converter/JavaTimeArgumentConverter.java @@ -51,12 +51,15 @@ class JavaTimeArgumentConverter extends AnnotationBasedArgumentConverter targetClass, JavaTimeConversionPattern annotation) { - String pattern = annotation.value(); - if (!TEMPORAL_QUERIES.containsKey(targetClass)) { + if (input == null) { + throw new ArgumentConversionException("Cannot convert null to " + targetClass.getName()); + } + TemporalQuery temporalQuery = TEMPORAL_QUERIES.get(targetClass); + if (temporalQuery == null) { throw new ArgumentConversionException("Cannot convert to " + targetClass.getName() + ": " + input); } + String pattern = annotation.value(); DateTimeFormatter formatter = DateTimeFormatter.ofPattern(pattern); - TemporalQuery temporalQuery = TEMPORAL_QUERIES.get(targetClass); return formatter.parse(input.toString(), temporalQuery); } diff --git a/junit-jupiter-params/src/main/java/org/junit/jupiter/params/provider/AnnotationBasedArgumentsProvider.java b/junit-jupiter-params/src/main/java/org/junit/jupiter/params/provider/AnnotationBasedArgumentsProvider.java index 2dbfd70e6348..a4a5971ecff1 100644 --- a/junit-jupiter-params/src/main/java/org/junit/jupiter/params/provider/AnnotationBasedArgumentsProvider.java +++ b/junit-jupiter-params/src/main/java/org/junit/jupiter/params/provider/AnnotationBasedArgumentsProvider.java @@ -49,15 +49,15 @@ public final void accept(A annotation) { @Override public final Stream provideArguments(ExtensionContext context) { - return provideArguments(context, annotation); + return provideArguments(context, this.annotation); } /** - * Provide a {@link Stream} of {@link Arguments} to be passed to a - * {@code @ParameterizedTest} method, by using the data given by an annotation. + * Provide a {@link Stream} of {@link Arguments} — based on metadata in the + * provided annotation — to be passed to a {@code @ParameterizedTest} method. * * @param context the current extension context; never {@code null} - * @param annotation the annotation used to specify the arguments; never {@code null} + * @param annotation the annotation to process; never {@code null} * @return a stream of arguments; never {@code null} */ protected abstract Stream provideArguments(ExtensionContext context, A annotation); diff --git a/junit-jupiter-params/src/main/java/org/junit/jupiter/params/provider/CsvArgumentsProvider.java b/junit-jupiter-params/src/main/java/org/junit/jupiter/params/provider/CsvArgumentsProvider.java index 3722aa2a0087..4d715c96c240 100644 --- a/junit-jupiter-params/src/main/java/org/junit/jupiter/params/provider/CsvArgumentsProvider.java +++ b/junit-jupiter-params/src/main/java/org/junit/jupiter/params/provider/CsvArgumentsProvider.java @@ -41,7 +41,7 @@ class CsvArgumentsProvider extends AnnotationBasedArgumentsProvider { private CsvParser csvParser; @Override - public Stream provideArguments(ExtensionContext context, CsvSource annotation) { + protected Stream provideArguments(ExtensionContext context, CsvSource annotation) { this.nullValues = toSet(annotation.nullValues()); this.csvParser = createParserFor(annotation); final boolean textBlockDeclared = !annotation.textBlock().isEmpty(); diff --git a/junit-jupiter-params/src/main/java/org/junit/jupiter/params/provider/CsvFileArgumentsProvider.java b/junit-jupiter-params/src/main/java/org/junit/jupiter/params/provider/CsvFileArgumentsProvider.java index f4ccca49432f..30e389b39a0a 100644 --- a/junit-jupiter-params/src/main/java/org/junit/jupiter/params/provider/CsvFileArgumentsProvider.java +++ b/junit-jupiter-params/src/main/java/org/junit/jupiter/params/provider/CsvFileArgumentsProvider.java @@ -58,7 +58,7 @@ class CsvFileArgumentsProvider extends AnnotationBasedArgumentsProvider provideArguments(ExtensionContext context, CsvFileSource annotation) { + protected Stream provideArguments(ExtensionContext context, CsvFileSource annotation) { this.charset = getCharsetFrom(annotation); this.numLinesToSkip = annotation.numLinesToSkip(); this.csvParser = createParserFor(annotation); diff --git a/junit-jupiter-params/src/main/java/org/junit/jupiter/params/provider/EmptySource.java b/junit-jupiter-params/src/main/java/org/junit/jupiter/params/provider/EmptySource.java index cd1104a1d6e8..4b628171deca 100644 --- a/junit-jupiter-params/src/main/java/org/junit/jupiter/params/provider/EmptySource.java +++ b/junit-jupiter-params/src/main/java/org/junit/jupiter/params/provider/EmptySource.java @@ -31,12 +31,12 @@ * *