Skip to content
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

Fix for case of inherited from Test tasks with own executers #163

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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