Description
There seems to be a potential race condition in NodeTestTask. The issue appears to be related to concurrent access to the parentContext field.
The race condition appears to be present in the latest release too.
Steps to reproduce
While I am unable to provide consistent steps to reproduce the issue at this time, the problem was identified by ThreadSanitizer (TSAN) and is exercised by the ExampleUnitTest class below.
The test is written in Kotlin but that should not affect the result.
@TestInstance(TestInstance.Lifecycle.PER_CLASS)
@Execution(ExecutionMode.CONCURRENT)
class ExampleUnitTest {
@ParameterizedTest
@MethodSource("numbers")
fun testRaceCondition(n: Int) {
assertTrue { true }
}
companion object {
const val LIMIT = 1000
@JvmStatic
fun numbers(): List<Arguments> = (1..LIMIT).map { Arguments.of(it) }
}
}
TSAN Output
SanitizerError
ThreadSanitizer: data race NodeTestTask.java:144 in org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$prepare$0()V
Details
==================
WARNING: ThreadSanitizer: data race (pid=6275)
Read of size 4 at 0x00008fee0088 by thread T1:
#0 org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$prepare$0()V NodeTestTask.java:144
#1 org.junit.platform.engine.support.hierarchical.NodeTestTask$$Lambda+0x000000010025b728.execute()V ??
#2 org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(Lorg/junit/platform/engine/support/hierarchical/ThrowableCollector$Executable;)V ThrowableCollector.java:74
#3 org.junit.platform.engine.support.hierarchical.NodeTestTask.prepare()V NodeTestTask.java:144
#4 org.junit.platform.engine.support.hierarchical.NodeTestTask.execute()V NodeTestTask.java:110
#5 org.junit.platform.engine.support.hierarchical.ForkJoinPoolHierarchicalTestExecutorService$ExclusiveTask.exec()Z ForkJoinPoolHierarchicalTestExecutorService.java:253
...
Previous write of size 4 at 0x00008fee0088 by thread T2:
#0 org.junit.platform.engine.support.hierarchical.NodeTestTask.setParentContext(Lorg/junit/platform/engine/support/hierarchical/EngineExecutionContext;)V NodeTestTask.java:102
#1 org.junit.platform.engine.support.hierarchical.NodeTestTask$DefaultDynamicTestExecutor.execute(Lorg/junit/platform/engine/TestDescriptor;Lorg/junit/platform/engine/EngineExecutionListener;)Ljava/util/concurrent/Future; NodeTestTask.java:266
#2 org.junit.platform.engine.support.hierarchical.NodeTestTask$DefaultDynamicTestExecutor.execute(Lorg/junit/platform/engine/TestDescriptor;)V NodeTestTask.java:246
#3 org.junit.jupiter.engine.descriptor.TemplateExecutor.execute(Lorg/junit/platform/engine/support/hierarchical/Node$DynamicTestExecutor;Lorg/junit/platform/engine/TestDescriptor;)V TemplateExecutor.java:96
#4 org.junit.jupiter.engine.descriptor.TemplateExecutor.lambda$executeForProvider$1(Lorg/junit/platform/engine/support/hierarchical/Node$DynamicTestExecutor;Lorg/junit/platform/engine/TestDescriptor;)V TemplateExecutor.java:59
#5 org.junit.jupiter.engine.descriptor.TemplateExecutor$$Lambda+0x00000001002a3bf8.accept(Ljava/lang/Object;)V ??
It appears there is a concurrent write in setParentContext with a concurrent read in prepare.
class NodeTestTask {
private @Nullable C parentContext;
private @Nullable C context;
private void prepare() {
requiredThrowableCollector().execute(() -> context = node.prepare(requireNonNull(parentContext)));
parentContext = null;
}
void setParentContext(@Nullable C parentContext) {
this.parentContext = parentContext;
}
}
Potential Solution
Marking the parentContext field volatile within NodeTestTask fixes the warning.
I hope this information is helpful for investigating the issue.
Context
- Used versions (Jupiter/Vintage/Platform):
- Jupiter: 6.0.1
- Platform: 6.0.1
- OS: Linux
Deliverables
Description
There seems to be a potential race condition in
NodeTestTask. The issue appears to be related to concurrent access to theparentContextfield.The race condition appears to be present in the latest release too.
Steps to reproduce
While I am unable to provide consistent steps to reproduce the issue at this time, the problem was identified by ThreadSanitizer (TSAN) and is exercised by the
ExampleUnitTestclass below.The test is written in Kotlin but that should not affect the result.
TSAN Output
It appears there is a concurrent write in
setParentContextwith a concurrent read inprepare.Potential Solution
Marking the
parentContextfieldvolatilewithinNodeTestTaskfixes the warning.I hope this information is helpful for investigating the issue.
Context
Deliverables