-
Notifications
You must be signed in to change notification settings - Fork 314
Implement attempt to fix tests #8393
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
Changes from 10 commits
d264232
1743577
981851f
d4c1cc1
e30023c
4c8d511
189e97a
237029a
4e93e3c
99d9749
9693e42
52c3eff
9ecb70d
5548303
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,51 @@ | ||
package datadog.trace.civisibility.config; | ||
|
||
import datadog.trace.civisibility.ipc.serialization.Serializer; | ||
import java.nio.ByteBuffer; | ||
import java.util.Objects; | ||
|
||
public final class ExecutionsByDuration { | ||
public final long durationMillis; | ||
public final int executions; | ||
|
||
public ExecutionsByDuration(long durationMillis, int executions) { | ||
this.durationMillis = durationMillis; | ||
this.executions = executions; | ||
} | ||
|
||
public long getDurationMillis() { | ||
return durationMillis; | ||
} | ||
|
||
public int getExecutions() { | ||
return executions; | ||
} | ||
|
||
@Override | ||
public boolean equals(Object o) { | ||
if (this == o) { | ||
return true; | ||
} | ||
if (o == null || getClass() != o.getClass()) { | ||
return false; | ||
} | ||
ExecutionsByDuration that = (ExecutionsByDuration) o; | ||
return durationMillis == that.durationMillis && executions == that.executions; | ||
} | ||
|
||
@Override | ||
public int hashCode() { | ||
return Objects.hash(durationMillis, executions); | ||
} | ||
|
||
public static class ExecutionsByDurationSerializer { | ||
public static void serialize(Serializer serializer, ExecutionsByDuration executionsByDuration) { | ||
serializer.write(executionsByDuration.durationMillis); | ||
serializer.write(executionsByDuration.executions); | ||
} | ||
|
||
public static ExecutionsByDuration deserialize(ByteBuffer buf) { | ||
return new ExecutionsByDuration(Serializer.readLong(buf), Serializer.readInt(buf)); | ||
} | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -34,7 +34,7 @@ public static boolean isSet(int mask, TestSetting setting) { | |
return (mask & setting.flag) != 0; | ||
} | ||
|
||
public static class TestSettingsSerializer { | ||
public static class TestSettingSerializer { | ||
|
||
public static void serialize(Serializer serializer, TestSetting setting) { | ||
serializer.write(setting.flag); | ||
} | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -2,24 +2,29 @@ | |
|
||
import datadog.trace.api.civisibility.execution.TestExecutionPolicy; | ||
import datadog.trace.api.civisibility.telemetry.tag.RetryReason; | ||
import datadog.trace.civisibility.config.EarlyFlakeDetectionSettings; | ||
import datadog.trace.civisibility.config.ExecutionsByDuration; | ||
import java.util.List; | ||
import org.jetbrains.annotations.Nullable; | ||
|
||
/** Runs a test case N times (N depends on test duration) regardless of success or failure. */ | ||
public class RunNTimes implements TestExecutionPolicy { | ||
|
||
private final EarlyFlakeDetectionSettings earlyFlakeDetectionSettings; | ||
private final boolean suppressFailures; | ||
private int executions; | ||
private final List<ExecutionsByDuration> executionsByDuration; | ||
private int maxExecutions; | ||
private boolean successfulExecutionSeen; | ||
private int successfulExecutionsSeen; | ||
private final RetryReason retryReason; | ||
|
||
public RunNTimes( | ||
EarlyFlakeDetectionSettings earlyFlakeDetectionSettings, boolean suppressFailures) { | ||
this.earlyFlakeDetectionSettings = earlyFlakeDetectionSettings; | ||
List<ExecutionsByDuration> executionsByDuration, | ||
boolean suppressFailures, | ||
RetryReason retryReason) { | ||
this.suppressFailures = suppressFailures; | ||
this.executions = 0; | ||
this.maxExecutions = earlyFlakeDetectionSettings.getExecutions(0); | ||
this.executionsByDuration = executionsByDuration; | ||
this.maxExecutions = getExecutions(0); | ||
this.retryReason = retryReason; | ||
} | ||
|
||
@Override | ||
|
@@ -36,19 +41,29 @@ public boolean suppressFailures() { | |
return suppressFailures; | ||
} | ||
|
||
private int getExecutions(long durationMillis) { | ||
for (ExecutionsByDuration e : executionsByDuration) { | ||
if (durationMillis <= e.getDurationMillis()) { | ||
return e.getExecutions(); | ||
} | ||
} | ||
return 0; | ||
} | ||
|
||
@Override | ||
public boolean retry(boolean successful, long durationMillis) { | ||
successfulExecutionSeen |= successful; | ||
// adjust maximum retries based on the now known test duration | ||
int maxExecutionsForGivenDuration = earlyFlakeDetectionSettings.getExecutions(durationMillis); | ||
if (successful) { | ||
++successfulExecutionsSeen; | ||
} | ||
int maxExecutionsForGivenDuration = getExecutions(durationMillis); | ||
maxExecutions = Math.min(maxExecutions, maxExecutionsForGivenDuration); | ||
return ++executions < maxExecutions; | ||
} | ||
|
||
@Nullable | ||
@Override | ||
public RetryReason currentExecutionRetryReason() { | ||
return currentExecutionIsRetry() ? RetryReason.efd : null; | ||
return currentExecutionIsRetry() ? retryReason : null; | ||
} | ||
|
||
private boolean currentExecutionIsRetry() { | ||
|
@@ -57,6 +72,11 @@ private boolean currentExecutionIsRetry() { | |
|
||
@Override | ||
public boolean hasFailedAllRetries() { | ||
return currentExecutionIsLast() && !successfulExecutionSeen; | ||
return currentExecutionIsLast() && successfulExecutionsSeen == 0; | ||
} | ||
|
||
@Override | ||
public boolean hasSucceededAllRetries() { | ||
return currentExecutionIsLast() && successfulExecutionsSeen == maxExecutions - 1; | ||
|
||
} | ||
} |
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 rename this to something like
getAttemptToFixExecutions
to emphasise that this is relevant only for attempt to fix testsThere 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.
Then, optionally, to promote encapsulation, we could make
TestManagementSettingsSerializer
a nested class in this one, and remove thegetAttemptToFixRetries
method