-
-
Notifications
You must be signed in to change notification settings - Fork 1.5k
Introduce feature flag for auto-closing AutoCloseable
in Jupiter's ExtensionContext.Store
#4452
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
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.
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.
Done in d498200 !
...piter-engine/src/main/java/org/junit/jupiter/engine/descriptor/AbstractExtensionContext.java
Outdated
Show resolved
Hide resolved
...piter-engine/src/main/java/org/junit/jupiter/engine/descriptor/AbstractExtensionContext.java
Outdated
Show resolved
Hide resolved
...piter-engine/src/main/java/org/junit/jupiter/engine/descriptor/AbstractExtensionContext.java
Outdated
Show resolved
Hide resolved
...piter-engine/src/main/java/org/junit/jupiter/engine/descriptor/AbstractExtensionContext.java
Outdated
Show resolved
Hide resolved
@@ -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?
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.
That seems like a better way. 🙂
*/ | ||
// 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.
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, Since HttpServerResource
is used as an example to explain CloseableResource
, I think it would be better to revert it back to CloseableResource
instead of AutoCloseable
.
.`ExtensionContext.Store.CloseableResource`
NOTE: An extension context store is bound to its extension context lifecycle. When an
extension context lifecycle ends it closes its associated store. All stored values
that are instances of `CloseableResource` are notified by an invocation of their `close()`
method in the inverse order they were added in.
An example implementation of `CloseableResource` is shown below, using an `HttpServer`
resource.
[source,java,indent=0]
.`HttpServer` resource implementing `CloseableResource`
Using an example with AutoCloseable
while explaining Closeable
might confuse the reader.
@marcphilipp WDYT? 🤔
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 it should be used to explain AutoCloseable
instead and we should revamp that section to mention that older releases used CloseableResource
instead which is still supported but no longer recommended etc.
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 it should be used to explain
AutoCloseable
instead and we should revamp that section to mention that older releases usedCloseableResource
instead which is still supported but no longer recommended etc.
Done in 3a96c24 !
…scriptor/AbstractExtensionContext.java Co-authored-by: Marc Philipp <[email protected]>
…scriptor/AbstractExtensionContext.java Co-authored-by: Marc Philipp <[email protected]>
…scriptor/AbstractExtensionContext.java Co-authored-by: Marc Philipp <[email protected]>
…scriptor/AbstractExtensionContext.java Co-authored-by: Marc Philipp <[email protected]>
…scriptor/AbstractExtensionContext.java Co-authored-by: Marc Philipp <[email protected]>
…nfig/JupiterConfiguration.java Co-authored-by: Marc Philipp <[email protected]>
…nfig/JupiterConfiguration.java Co-authored-by: Marc Philipp <[email protected]>
Issue junit-team#4434
Overview
fix #4434
I hereby agree to the terms of the JUnit Contributor License Agreement.
Definition of Done
@API
annotations