-
-
Notifications
You must be signed in to change notification settings - Fork 1.5k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add timeout config parameter #2026
Changes from all commits
b33dbc4
5fc99d7
7b85300
5162dd3
29852d8
dec9f71
43a672e
1ba3bda
ce1892c
8eb8211
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -10,6 +10,8 @@ | |
|
||
package org.junit.jupiter.engine.extension; | ||
|
||
import static org.junit.jupiter.engine.config.JupiterConfiguration.TIMEOUT_MODE_PROPERTY_NAME; | ||
|
||
import java.lang.reflect.AnnotatedElement; | ||
import java.lang.reflect.Method; | ||
import java.util.Optional; | ||
|
@@ -21,6 +23,7 @@ | |
import org.junit.jupiter.api.Timeout; | ||
import org.junit.jupiter.api.extension.BeforeAllCallback; | ||
import org.junit.jupiter.api.extension.BeforeEachCallback; | ||
import org.junit.jupiter.api.extension.ExtensionConfigurationException; | ||
import org.junit.jupiter.api.extension.ExtensionContext; | ||
import org.junit.jupiter.api.extension.ExtensionContext.Store.CloseableResource; | ||
import org.junit.jupiter.api.extension.InvocationInterceptor; | ||
|
@@ -29,6 +32,7 @@ | |
import org.junit.platform.commons.support.AnnotationSupport; | ||
import org.junit.platform.commons.util.ClassUtils; | ||
import org.junit.platform.commons.util.ReflectionUtils; | ||
import org.junit.platform.commons.util.RuntimeUtils; | ||
|
||
/** | ||
* @since 5.5 | ||
|
@@ -38,6 +42,9 @@ class TimeoutExtension implements BeforeAllCallback, BeforeEachCallback, Invocat | |
private static final ExtensionContext.Namespace NAMESPACE = ExtensionContext.Namespace.create(Timeout.class); | ||
private static final String TESTABLE_METHOD_TIMEOUT_KEY = "testable_method_timeout_from_annotation"; | ||
private static final String GLOBAL_TIMEOUT_CONFIG_KEY = "global_timeout_config"; | ||
public static final String ENABLED_MODE_VALUE = "enabled"; | ||
public static final String DISABLED_MODE_VALUE = "disabled"; | ||
public static final String DISABLED_ON_DEBUG_MODE_VALUE = "disabled_on_debug"; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. These should be |
||
|
||
@Override | ||
public void beforeAll(ExtensionContext context) { | ||
|
@@ -145,7 +152,7 @@ private TimeoutConfiguration getGlobalTimeoutConfiguration(ExtensionContext exte | |
|
||
private <T> Invocation<T> decorate(Invocation<T> invocation, ReflectiveInvocationContext<Method> invocationContext, | ||
ExtensionContext extensionContext, TimeoutDuration timeout) { | ||
if (timeout == null) { | ||
if (timeout == null || isModeIndicatingDisabled(extensionContext)) { | ||
return invocation; | ||
} | ||
return new TimeoutInvocation<>(invocation, timeout, getExecutor(extensionContext), | ||
|
@@ -165,6 +172,24 @@ private ScheduledExecutorService getExecutor(ExtensionContext extensionContext) | |
return extensionContext.getRoot().getStore(NAMESPACE).getOrComputeIfAbsent(ExecutorResource.class).get(); | ||
} | ||
|
||
private boolean isModeIndicatingDisabled(ExtensionContext extensionContext) { | ||
Optional<String> mode = extensionContext.getConfigurationParameter(TIMEOUT_MODE_PROPERTY_NAME); | ||
return mode.filter(this::isDisabled).isPresent(); | ||
} | ||
|
||
private boolean isDisabled(String mode) { | ||
if (mode.equals(ENABLED_MODE_VALUE)) { | ||
return false; | ||
} | ||
if (mode.equals(DISABLED_MODE_VALUE)) { | ||
return true; | ||
} | ||
if (mode.equals(DISABLED_ON_DEBUG_MODE_VALUE)) { | ||
return RuntimeUtils.isDebug(); | ||
} | ||
throw new ExtensionConfigurationException("Unsupported timeout extension mode: " + mode); | ||
} | ||
|
||
@FunctionalInterface | ||
private interface TimeoutProvider extends Function<TimeoutConfiguration, Optional<TimeoutDuration>> { | ||
} | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,80 @@ | ||
/* | ||
* Copyright 2015-2019 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.commons.util; | ||
|
||
import static org.apiguardian.api.API.Status.INTERNAL; | ||
|
||
import java.util.List; | ||
import java.util.Optional; | ||
|
||
import org.apiguardian.api.API; | ||
|
||
/** | ||
* Collection of utilities for working with {@link Runtime}, | ||
* {@link java.lang.management.RuntimeMXBean}, etc. | ||
* | ||
* <h3>DISCLAIMER</h3> | ||
* | ||
* <p>These utilities are intended solely for usage within the JUnit framework | ||
* itself. <strong>Any usage by external parties is not supported.</strong> | ||
* Use at your own risk! | ||
* | ||
* @since 1.6 | ||
*/ | ||
@API(status = INTERNAL, since = "1.6") | ||
public final class RuntimeUtils { | ||
|
||
private RuntimeUtils() { | ||
/* no-op */ | ||
} | ||
|
||
/** | ||
* Try to get the input arguments the VM was started with. | ||
*/ | ||
public static Optional<List<String>> getInputArguments() { | ||
Optional<Class<?>> managementFactoryClass = ReflectionUtils.tryToLoadClass( | ||
"java.lang.management.ManagementFactory").toOptional(); | ||
if (!managementFactoryClass.isPresent()) { | ||
return Optional.empty(); | ||
} | ||
// Can't use "java.lang.management.ManagementFactory.getRuntimeMXBean().getInputArguments()" | ||
// directly as module "java.management" might not be available and/or the current platform | ||
// doesn't support the Java Management Extensions (JMX) API (like Android?). | ||
// See https://github.com/junit-team/junit4/pull/1187 | ||
try { | ||
Object bean = managementFactoryClass.get().getMethod("getRuntimeMXBean").invoke(null); | ||
Class<?> mx = ReflectionUtils.tryToLoadClass("java.lang.management.RuntimeMXBean").get(); | ||
@SuppressWarnings("unchecked") | ||
List<String> args = (List<String>) mx.getMethod("getInputArguments").invoke(bean); | ||
return Optional.of(args); | ||
} | ||
catch (Exception e) { | ||
return Optional.empty(); | ||
} | ||
} | ||
|
||
/** | ||
* Try to determine whether the VM was started in debug mode or not. | ||
*/ | ||
public static boolean isDebug() { | ||
Optional<List<String>> optionalArguments = getInputArguments(); | ||
if (!optionalArguments.isPresent()) { | ||
return false; | ||
} | ||
for (String argument : optionalArguments.get()) { | ||
if (argument.startsWith("-agentlib:jdwp")) { | ||
return true; | ||
} | ||
} | ||
return false; | ||
} | ||
|
||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -9,7 +9,8 @@ | |
*/ | ||
|
||
module org.junit.platform.commons { | ||
requires java.logging; // TODO Is "requires transitive java.logging" needed here? | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Removed the superseded |
||
requires java.logging; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I left the Otherwise, users have to add it via |
||
requires java.management; // needed by RuntimeUtils to determine input arguments | ||
requires transitive org.apiguardian.api; | ||
|
||
exports org.junit.platform.commons; | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,33 @@ | ||
/* | ||
* Copyright 2015-2019 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.commons.util; | ||
|
||
import static org.junit.jupiter.api.Assertions.assertNotNull; | ||
import static org.junit.jupiter.api.Assertions.assertTrue; | ||
|
||
import org.junit.jupiter.api.Test; | ||
|
||
/** | ||
* Unit tests for {@link RuntimeUtils}. | ||
* | ||
* @since 1.6 | ||
*/ | ||
class RuntimeUtilsTests { | ||
|
||
@Test | ||
void jmxIsAvailableAndInputArgumentsAreReturned() { | ||
var optionalArguments = RuntimeUtils.getInputArguments(); | ||
assertTrue(optionalArguments.isPresent(), "JMX not available or something else happened..."); | ||
var arguments = optionalArguments.get(); | ||
assertNotNull(arguments); | ||
} | ||
|
||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The Javadoc should document the default value.