-
-
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
Introduce feature flag for auto-closing AutoCloseable
in Jupiter's ExtensionContext.Store
#4452
base: main
Are you sure you want to change the base?
Conversation
Issue junit-team#4434
jupiter-tests/src/test/java/org/junit/jupiter/engine/descriptor/ResourceAutoClosingTests.java
Show resolved
Hide resolved
((CloseableResource) value).close(); | ||
} | ||
}; | ||
private static NamespacedHierarchicalStore.CloseAction<org.junit.platform.engine.support.store.Namespace> CLOSE_RESOURCES; |
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.
This should no longer be static
since it depends on the instance-specific JupiterConfiguration
.
jupiter-tests/src/test/java/org/junit/jupiter/engine/descriptor/ResourceAutoClosingTests.java
Outdated
Show resolved
Hide resolved
jupiter-tests/src/test/java/org/junit/jupiter/engine/descriptor/ResourceAutoClosingTests.java
Outdated
Show resolved
Hide resolved
jupiter-tests/src/test/java/org/junit/jupiter/engine/extension/TestInstanceFactoryTests.java
Outdated
Show resolved
Hide resolved
jupiter-tests/src/test/java/org/junit/jupiter/engine/descriptor/ResourceAutoClosingTests.java
Show resolved
Hide resolved
…r/ResourceAutoClosingTests.java Co-authored-by: Marc Philipp <[email protected]>
To determine if your extension is running under JUnit Jupiter 5.13+, you can check if auto-close is enabled via the configuration: | ||
|
||
[source,java,indent=0] | ||
---- | ||
boolean isJupiter513OrNewer = context.getConfigurationParameter("junit.jupiter.extensions.autoclose.enabled") | ||
.map(Boolean::parseBoolean) | ||
.orElse(true); // Default is true in 5.13+ | ||
---- | ||
|
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.
I'd omit that as it's not reliable since the config param could be set on earlier versions.
...piter-api/src/main/java/org/junit/jupiter/api/extension/TestInstantiationAwareExtension.java
Outdated
Show resolved
Hide resolved
@@ -65,7 +64,7 @@ public interface TestInstantiationAwareExtension extends Extension { | |||
* <li>{@link ExtensionContext#getTestMethod() getTestMethod()} is no longer | |||
* empty, unless the {@link TestInstance.Lifecycle#PER_CLASS PER_CLASS} | |||
* lifecycle is used.</li> | |||
* <li>If the callback adds a new {@link CloseableResource} to the | |||
* <li>If the callback adds a new {@link Store.CloseableResource} to the |
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.
Please also mention AutoCloseable
here as in the other places you've adapted the Javadoc.
@@ -42,14 +42,15 @@ public interface JupiterConfiguration { | |||
String EXTENSIONS_AUTODETECTION_EXCLUDE_PROPERTY_NAME = "junit.jupiter.extensions.autodetection.exclude"; | |||
String DEACTIVATE_CONDITIONS_PATTERN_PROPERTY_NAME = "junit.jupiter.conditions.deactivate"; | |||
String PARALLEL_EXECUTION_ENABLED_PROPERTY_NAME = "junit.jupiter.execution.parallel.enabled"; | |||
String AUTOCLOSE_ENABLED_PROPERTY_NAME = "junit.jupiter.extensions.autoclose.enabled"; |
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.
I'm not sure about the name. I'll discuss it with the team.
String AUTOCLOSE_ENABLED_PROPERTY_NAME = "junit.jupiter.extensions.autoclose.enabled"; | |
String CLOSING_STORED_AUTO_CLOSEABLE_ENABLED_PROPERTY_NAME = "junit.jupiter.extensions.store.close.autocloseable.enabled"; |
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.
IMHO, I think it's a good name.
Please discuss it with the team and let me know the outcome!
@@ -60,6 +61,8 @@ public interface JupiterConfiguration { | |||
|
|||
boolean isParallelExecutionEnabled(); | |||
|
|||
boolean isAutoCloseEnabled(); |
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.
🤔
boolean isAutoCloseEnabled(); | |
boolean isClosingStoredAutoCloseablesEnabled(); |
@@ -289,7 +288,7 @@ private static boolean selfOrChildFailed(ExtensionContext context) { | |||
|| context.getStore(NAMESPACE).getOrDefault(CHILD_FAILED, Boolean.class, false); | |||
} | |||
|
|||
static class CloseablePath implements CloseableResource { | |||
static class CloseablePath implements AutoCloseable { |
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.
We need to implement both here in case the new config param is set to false
(the same goes for all implementations of CloseableResource
in production code).
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.
We need to implement both here in case the new config param is set to
false
(the same goes for all implementations ofCloseableResource
in production code).
I overlooked the case where the config param could be set to false
.
I've updated the code to implement both, as you suggested. 🙂
Thank you @marcphilipp !!
@@ -129,7 +128,7 @@ public void beforeEach(ExtensionContext context) { | |||
} | |||
|
|||
private static void installFailureTracker(ExtensionContext context) { | |||
context.getStore(NAMESPACE).put(FAILURE_TRACKER, (CloseableResource) () -> context.getParent() // | |||
context.getStore(NAMESPACE).put(FAILURE_TRACKER, (AutoCloseable) () -> context.getParent() // |
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.
I think we should extract a class here that also implements both.
@@ -76,6 +76,7 @@ private void storeParameterInfo(ExtensionContext context) { | |||
new DefaultParameterInfo(declarations, accessor).store(context); | |||
} | |||
|
|||
@SuppressWarnings("deprecation") | |||
private static class CloseableArgument implements ExtensionContext.Store.CloseableResource { |
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.
Should also implement both
@@ -80,7 +79,7 @@ static class ThrowingOnCloseExtension implements BeforeEachCallback { | |||
|
|||
@Override | |||
public void beforeEach(ExtensionContext context) { | |||
context.getStore(GLOBAL).put("throwingResource", (ExtensionContext.Store.CloseableResource) () -> { | |||
context.getStore(GLOBAL).put("throwingResource", (AutoCloseable) () -> { |
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.
Ditto
@@ -1175,7 +1174,7 @@ public Object resolveParameter(ParameterContext parameterContext, ExtensionConte | |||
} | |||
} | |||
|
|||
static class SomeResource implements CloseableResource { | |||
static class SomeResource implements AutoCloseable { |
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.
This is fine in test code. 👍
* <p>If {@code type} implements {@link ExtensionContext.Store.CloseableResource} | ||
* the {@code close()} method will be invoked on the stored object when | ||
* or {@link AutoCloseable} the {@code close()} method will be invoked on the stored object when | ||
* the store is closed. |
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.
* <p>If {@code type} implements {@link CloseableResource} or
* {@link AutoCloseable} (unless the
* {@code junit.jupiter.extensions.store.close.autocloseable.enabled}
* configuration parameter is set to {@code false}), then the {@code close()}
* method will be invoked on the stored object when the store is closed.
private final ExecutableInvoker executableInvoker; | ||
private final ExtensionRegistry extensionRegistry; | ||
private final LauncherStoreFacade launcherStoreFacade; | ||
private final NamespacedHierarchicalStore.CloseAction<org.junit.platform.engine.support.store.Namespace> closeResources; |
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.
There's no need to store this in a field since it's only used in the constructor, isn't it?
private final NamespacedHierarchicalStore.CloseAction<org.junit.platform.engine.support.store.Namespace> closeResources; |
this.closeResources = createCloseResources(); | ||
this.valuesStore = createStore(parent, launcherStoreFacade); |
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.
this.closeResources = createCloseResources(); | |
this.valuesStore = createStore(parent, launcherStoreFacade); | |
this.valuesStore = createStore(parent, launcherStoreFacade, createCloseAction()); |
} | ||
|
||
@SuppressWarnings("deprecation") | ||
private NamespacedHierarchicalStore.CloseAction<org.junit.platform.engine.support.store.Namespace> createCloseResources() { |
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.
private NamespacedHierarchicalStore.CloseAction<org.junit.platform.engine.support.store.Namespace> createCloseResources() { | |
private NamespacedHierarchicalStore.CloseAction<org.junit.platform.engine.support.store.Namespace> createCloseAction() { |
} | ||
|
||
private static NamespacedHierarchicalStore<org.junit.platform.engine.support.store.Namespace> createStore( | ||
private NamespacedHierarchicalStore<org.junit.platform.engine.support.store.Namespace> createStore( |
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.
private NamespacedHierarchicalStore<org.junit.platform.engine.support.store.Namespace> createStore( | |
private static NamespacedHierarchicalStore<org.junit.platform.engine.support.store.Namespace> createStore( |
@@ -29,6 +31,8 @@ | |||
@API(status = INTERNAL, since = "5.0") | |||
public class NamespaceAwareStore implements Store { | |||
|
|||
private static final Logger LOGGER = LoggerFactory.getLogger(NamespaceAwareStore.class); |
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.
Please remove this logger again.
@@ -100,6 +100,7 @@ private <T> Resource<T> getOrCreateResource(ExtensionContext extensionContext, C | |||
} | |||
} | |||
|
|||
@SuppressWarnings("deprecation") | |||
class Resource<T> implements CloseableResource { |
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.
We should use AutoCloseable
here
@@ -76,6 +76,7 @@ private static boolean notEmpty(Path file) { | |||
} | |||
} | |||
|
|||
@SuppressWarnings("deprecation") | |||
record OutputDir(Path root) implements ExtensionContext.Store.CloseableResource { |
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.
Ditto.
store.put("resource", resource); | ||
|
||
((AutoCloseable) extensionContext).close(); | ||
assertThat(listener.stream(Level.WARNING)).map(LogRecord::getMessage).noneMatch(msg::equals); |
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.
Would be easier to assert that there are not log messages, WDYT?
*/ | ||
// tag::user_guide[] | ||
class HttpServerResource implements CloseableResource { | ||
class HttpServerResource implements AutoCloseable { |
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.
We also need to update the Asciidoc title for this snippet.
Overview
fix #4434
I hereby agree to the terms of the JUnit Contributor License Agreement.
Definition of Done
@API
annotations