Skip to content

Commit

Permalink
Fix for case of inherited from Test tasks with own executers
Browse files Browse the repository at this point in the history
Signed-off-by: Sergey Zhuravlev <[email protected]>
  • Loading branch information
zhurs committed Dec 7, 2022
1 parent 43d7609 commit a7fd65b
Show file tree
Hide file tree
Showing 4 changed files with 62 additions and 35 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -27,12 +27,15 @@
import org.gradle.api.tasks.testing.Test;
import org.gradle.internal.reflect.Instantiator;
import org.gradle.testretry.TestRetryTaskExtension;
import org.gradle.testretry.internal.executer.LastResultHolder;
import org.gradle.testretry.internal.executer.RetryTestExecuter;
import org.gradle.testretry.internal.executer.RoundResult;
import org.gradle.util.GradleVersion;
import org.jetbrains.annotations.NotNull;

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.stream.Collectors;

public final class TestTaskConfigurer {

Expand Down Expand Up @@ -60,8 +63,10 @@ public static void configureTestTask(Test test, ObjectFactory objectFactory, Pro

test.getExtensions().add(TestRetryTaskExtension.class, TestRetryTaskExtension.NAME, extension);

test.doFirst(new ConditionalTaskAction(isDeactivatedByTestDistributionPlugin, new InitTaskAction(adapter, objectFactory)));
test.doLast(new ConditionalTaskAction(isDeactivatedByTestDistributionPlugin, new FinalizeTaskAction()));
LastResultHolder lastResultHolder = new LastResultHolder();

test.doFirst(new ConditionalTaskAction(isDeactivatedByTestDistributionPlugin, new InitTaskAction(adapter, objectFactory, lastResultHolder)));
test.doLast(new ConditionalTaskAction(isDeactivatedByTestDistributionPlugin, new FinalizeTaskAction(adapter, lastResultHolder)));
}

private static void ensureThatNoRetryExtensionIsPresent(Test testTask) {
Expand Down Expand Up @@ -127,10 +132,10 @@ private static boolean callShouldTestRetryPluginBeDeactivated(Test test) {
}
}

private static RetryTestExecuter createRetryTestExecuter(Test task, TestRetryTaskExtensionAdapter extension, ObjectFactory objectFactory) {
private static RetryTestExecuter createRetryTestExecuter(Test task, TestRetryTaskExtensionAdapter extension, ObjectFactory objectFactory, LastResultHolder lastResultHolder) {
TestExecuter<JvmTestExecutionSpec> delegate = getTestExecuter(task);
Instantiator instantiator = invoke(declaredMethod(AbstractTestTask.class, "getInstantiator"), task);
return new RetryTestExecuter(task, extension, delegate, instantiator, objectFactory, task.getTestClassesDirs().getFiles(), task.getClasspath().getFiles());
return new RetryTestExecuter(task, extension, delegate, instantiator, objectFactory, task.getTestClassesDirs().getFiles(), task.getClasspath().getFiles(), lastResultHolder);
}

private static TestExecuter<JvmTestExecutionSpec> getTestExecuter(Test task) {
Expand Down Expand Up @@ -161,32 +166,49 @@ public void execute(@NotNull Task task) {
}
}

private static class FinalizeTaskAction implements Action<Test> {
public static class FinalizeTaskAction implements Action<Test> {

private final TestRetryTaskExtensionAccessor extension;
private final LastResultHolder lastResultHolder;

public FinalizeTaskAction(TestRetryTaskExtensionAccessor extension, LastResultHolder lastResultHolder) {
this.extension = extension;
this.lastResultHolder = lastResultHolder;
}

@Override
public void execute(@NotNull Test task) {
TestExecuter<JvmTestExecutionSpec> testExecuter = getTestExecuter(task);
if (testExecuter instanceof RetryTestExecuter) {
((RetryTestExecuter) testExecuter).failWithNonRetriedTestsIfAny();
} else {
throw new IllegalStateException("Unexpected test executer: " + testExecuter);
RoundResult lastResult = lastResultHolder.get();
boolean hasNonRetriedTests = lastResult != null && !lastResult.nonRetriedTests.isEmpty();
if (extension.getSimulateNotRetryableTest() || hasNonRetriedTests) {
throw new IllegalStateException("org.gradle.test-retry was unable to retry the following test methods, which is unexpected. Please file a bug report at https://github.com/gradle/test-retry-gradle-plugin/issues" +
(
lastResult == null
? ""
: lastResult.nonRetriedTests.stream()
.flatMap(entry -> entry.getValue().stream().map(methodName -> " " + entry.getKey() + "#" + methodName))
.collect(Collectors.joining("\n", "\n", "\n"))
)
);
}
}
}

private static class InitTaskAction implements Action<Test> {
public static class InitTaskAction implements Action<Test> {

private final TestRetryTaskExtensionAdapter adapter;
private final ObjectFactory objectFactory;
private final LastResultHolder lastResultHolder;

public InitTaskAction(TestRetryTaskExtensionAdapter adapter, ObjectFactory objectFactory) {
public InitTaskAction(TestRetryTaskExtensionAdapter adapter, ObjectFactory objectFactory, LastResultHolder lastResultHolder) {
this.adapter = adapter;
this.objectFactory = objectFactory;
this.lastResultHolder = lastResultHolder;
}

@Override
public void execute(@NotNull Test task) {
RetryTestExecuter retryTestExecuter = createRetryTestExecuter(task, adapter, objectFactory);
RetryTestExecuter retryTestExecuter = createRetryTestExecuter(task, adapter, objectFactory, lastResultHolder);
setTestExecuter(task, retryTestExecuter);
}
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
package org.gradle.testretry.internal.executer;

import javax.annotation.Nullable;

public class LastResultHolder {
@Nullable
private RoundResult lastResult;

@Nullable
public RoundResult get() {
return lastResult;
}

public void set(RoundResult lastResult) {
this.lastResult = lastResult;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,6 @@

import java.io.File;
import java.util.Set;
import java.util.stream.Collectors;

import static org.gradle.testretry.internal.executer.JvmTestExecutionSpecFactory.testExecutionSpecFor;

Expand All @@ -44,7 +43,7 @@ public final class RetryTestExecuter implements TestExecuter<JvmTestExecutionSpe
private final Test testTask;
private final TestFrameworkTemplate frameworkTemplate;

private RoundResult lastResult;
private final LastResultHolder lastResultHolder;

public RetryTestExecuter(
Test task,
Expand All @@ -53,11 +52,13 @@ public RetryTestExecuter(
Instantiator instantiator,
ObjectFactory objectFactory,
Set<File> testClassesDir,
Set<File> resolvedClasspath
Set<File> resolvedClasspath,
LastResultHolder lastResultHolder
) {
this.extension = extension;
this.delegate = delegate;
this.testTask = task;
this.lastResultHolder = lastResultHolder;
this.frameworkTemplate = new TestFrameworkTemplate(
testTask,
instantiator,
Expand Down Expand Up @@ -115,7 +116,7 @@ public void execute(JvmTestExecutionSpec spec, TestResultProcessor testResultPro
while (true) {
delegate.execute(testExecutionSpec, retryTestResultProcessor);
RoundResult result = retryTestResultProcessor.getResult();
lastResult = result;
lastResultHolder.set(result);

if (extension.getSimulateNotRetryableTest() || !result.nonRetriedTests.isEmpty()) {
// fall through to our doLast action to fail accordingly
Expand All @@ -136,19 +137,6 @@ public void execute(JvmTestExecutionSpec spec, TestResultProcessor testResultPro
}
}

public void failWithNonRetriedTestsIfAny() {
if (extension.getSimulateNotRetryableTest() || hasNonRetriedTests()) {
throw new IllegalStateException("org.gradle.test-retry was unable to retry the following test methods, which is unexpected. Please file a bug report at https://github.com/gradle/test-retry-gradle-plugin/issues" +
lastResult.nonRetriedTests.stream()
.flatMap(entry -> entry.getValue().stream().map(methodName -> " " + entry.getKey() + "#" + methodName))
.collect(Collectors.joining("\n", "\n", "\n")));
}
}

private boolean hasNonRetriedTests() {
return lastResult != null && !lastResult.nonRetriedTests.isEmpty();
}

@Override
public void stopNow() {
delegate.stopNow();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,12 +15,12 @@
*/
package org.gradle.testretry.internal.executer;

final class RoundResult {
public final class RoundResult {

final TestNames failedTests;
final TestNames nonRetriedTests;
final boolean lastRound;
final boolean hasRetryFilteredFailures;
public final TestNames failedTests;
public final TestNames nonRetriedTests;
public final boolean lastRound;
public final boolean hasRetryFilteredFailures;

RoundResult(
TestNames failedTests,
Expand Down

0 comments on commit a7fd65b

Please sign in to comment.