1717import java .util .ArrayList ;
1818import java .util .Collection ;
1919import java .util .List ;
20+ import java .util .Map ;
21+ import java .util .concurrent .ConcurrentHashMap ;
22+ import java .util .concurrent .locks .ReentrantLock ;
2023
2124import static java .util .Collections .emptyList ;
2225import static java .util .Collections .synchronizedList ;
2629import org .junit .platform .commons .PreconditionViolationException ;
2730import org .junit .platform .engine .Filter ;
2831import org .junit .platform .engine .TestExecutionResult ;
32+ import org .junit .platform .engine .UniqueId ;
2933import org .junit .platform .engine .discovery .DiscoverySelectors ;
3034import org .junit .platform .engine .support .descriptor .MethodSource ;
3135import org .junit .platform .launcher .Launcher ;
3539import org .junit .platform .launcher .core .LauncherDiscoveryRequestBuilder ;
3640import org .junit .platform .launcher .core .LauncherFactory ;
3741import org .pitest .testapi .Description ;
42+ import org .pitest .testapi .NullExecutionListener ;
3843import org .pitest .testapi .TestGroupConfig ;
3944import org .pitest .testapi .TestUnit ;
4045import org .pitest .testapi .TestUnitExecutionListener ;
@@ -97,10 +102,14 @@ private class TestIdentifierListener implements TestExecutionListener {
97102 private final Class <?> testClass ;
98103 private final TestUnitExecutionListener l ;
99104 private final List <TestIdentifier > identifiers = synchronizedList (new ArrayList <>());
105+ private final boolean serializeExecution ;
106+ private final Map <UniqueId , ReentrantLock > coverageSerializers = new ConcurrentHashMap <>();
107+ private final ReentrantLock rootCoverageSerializer = new ReentrantLock ();
100108
101109 public TestIdentifierListener (Class <?> testClass , TestUnitExecutionListener l ) {
102110 this .testClass = testClass ;
103111 this .l = l ;
112+ serializeExecution = !(l instanceof NullExecutionListener );
104113 }
105114
106115 List <TestIdentifier > getIdentifiers () {
@@ -117,12 +126,21 @@ public void executionStarted(TestIdentifier testIdentifier) {
117126 && !includedTestMethods .contains (((MethodSource )testIdentifier .getSource ().get ()).getMethodName ())) {
118127 return ;
119128 }
129+
130+ if (serializeExecution ) {
131+ testIdentifier
132+ .getParentIdObject ()
133+ .map (coverageSerializers ::get )
134+ .orElse (rootCoverageSerializer )
135+ .lock ();
136+ coverageSerializers .put (testIdentifier .getUniqueIdObject (), new ReentrantLock ());
137+ }
138+
120139 l .executionStarted (new Description (testIdentifier .getUniqueId (), testClass ));
121140 identifiers .add (testIdentifier );
122141 }
123142 }
124143
125-
126144 @ Override
127145 public void executionFinished (TestIdentifier testIdentifier , TestExecutionResult testExecutionResult ) {
128146 // Classes with failing BeforeAlls never start execution and identify as 'containers' not 'tests'
@@ -133,6 +151,15 @@ public void executionFinished(TestIdentifier testIdentifier, TestExecutionResult
133151 l .executionFinished (new Description (testIdentifier .getUniqueId (), testClass ), false );
134152 } else if (testIdentifier .isTest ()) {
135153 l .executionFinished (new Description (testIdentifier .getUniqueId (), testClass ), true );
154+
155+ if (serializeExecution ) {
156+ coverageSerializers .remove (testIdentifier .getUniqueIdObject ());
157+ testIdentifier
158+ .getParentIdObject ()
159+ .map (coverageSerializers ::get )
160+ .orElse (rootCoverageSerializer )
161+ .unlock ();
162+ }
136163 }
137164 }
138165
0 commit comments