Add new attempt_count field to BES.
PiperOrigin-RevId: 381590740
diff --git a/src/main/java/com/google/devtools/build/lib/buildeventstream/proto/build_event_stream.proto b/src/main/java/com/google/devtools/build/lib/buildeventstream/proto/build_event_stream.proto
index 4b52edb..bd944eb 100644
--- a/src/main/java/com/google/devtools/build/lib/buildeventstream/proto/build_event_stream.proto
+++ b/src/main/java/com/google/devtools/build/lib/buildeventstream/proto/build_event_stream.proto
@@ -713,6 +713,11 @@
// Value of runs_per_test for the test.
int32 run_count = 10;
+ // Number of attempts.
+ // If there are a different number of attempts per shard, the highest attempt
+ // count across all shards for each run is used.
+ int32 attempt_count = 15;
+
// Number of shards.
int32 shard_count = 11;
diff --git a/src/main/java/com/google/devtools/build/lib/runtime/TestResultAggregator.java b/src/main/java/com/google/devtools/build/lib/runtime/TestResultAggregator.java
index 1a120a3..d8c4208 100644
--- a/src/main/java/com/google/devtools/build/lib/runtime/TestResultAggregator.java
+++ b/src/main/java/com/google/devtools/build/lib/runtime/TestResultAggregator.java
@@ -190,10 +190,12 @@
Preconditions.checkNotNull(target, "The existing TestSummary must be associated with a target");
TestParams testParams = target.getProvider(TestProvider.class).getTestParams();
+ int shardNumber = result.getShardNum();
+ summary.addShardAttempts(shardNumber, result.getData().getTestTimesCount());
+
if (!testParams.runsDetectsFlakes()) {
status = aggregateStatus(status, result.getData().getStatus());
} else {
- int shardNumber = result.getShardNum();
int runsPerTestForLabel = testParams.getRuns();
List<BlazeTestStatus> singleShardStatuses =
summary.addShardStatus(shardNumber, result.getData().getStatus());
diff --git a/src/main/java/com/google/devtools/build/lib/runtime/TestSummary.java b/src/main/java/com/google/devtools/build/lib/runtime/TestSummary.java
index 12c393a..000ffdf 100644
--- a/src/main/java/com/google/devtools/build/lib/runtime/TestSummary.java
+++ b/src/main/java/com/google/devtools/build/lib/runtime/TestSummary.java
@@ -44,6 +44,7 @@
import com.google.protobuf.util.Durations;
import com.google.protobuf.util.Timestamps;
import java.util.ArrayList;
+import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
@@ -315,6 +316,13 @@
return ImmutableList.copyOf(statuses);
}
+ /** Records new attempts for the given shard of the target. */
+ public Builder addShardAttempts(int shardNumber, int newAtttempts) {
+ checkMutation();
+ summary.shardAttempts[shardNumber] += newAtttempts;
+ return this;
+ }
+
/**
* Returns the created TestSummary object.
* Any actions following a build() will create another copy of the same values.
@@ -360,6 +368,7 @@
private BuildConfiguration configuration;
private BlazeTestStatus status;
private boolean skipped;
+ private final int[] shardAttempts;
private int numCached;
private int numLocalActionCached;
private boolean actionRan;
@@ -383,9 +392,9 @@
private TestSummary(ConfiguredTarget target) {
this.target = target;
TestParams testParams = getTestParams();
- shardRunStatuses =
- createAndInitialize(
- testParams.runsDetectsFlakes() ? Math.max(testParams.getShards(), 1) : 0);
+ int sz = Math.max(testParams.getShards(), 1);
+ shardAttempts = new int[sz];
+ shardRunStatuses = createAndInitialize(testParams.runsDetectsFlakes() ? sz : 0);
}
private static ImmutableList<ArrayList<BlazeTestStatus>> createAndInitialize(int sz) {
@@ -540,6 +549,10 @@
return testTimes;
}
+ public int getNumAttempts() {
+ return Arrays.stream(this.shardAttempts).max().getAsInt();
+ }
+
public int getNumCached() {
return numCached;
}
@@ -610,6 +623,7 @@
.setOverallStatus(BuildEventStreamerUtils.bepStatus(status))
.setTotalNumCached(getNumCached())
.setTotalRunCount(totalRuns())
+ .setAttemptCount(getNumAttempts())
.setRunCount(testParams.getRuns())
.setShardCount(testParams.getShards())
.setFirstStartTime(Timestamps.fromMillis(firstStartTimeMillis))
diff --git a/src/test/java/com/google/devtools/build/lib/runtime/TestResultAggregatorTest.java b/src/test/java/com/google/devtools/build/lib/runtime/TestResultAggregatorTest.java
index 7211f79..a816bae 100644
--- a/src/test/java/com/google/devtools/build/lib/runtime/TestResultAggregatorTest.java
+++ b/src/test/java/com/google/devtools/build/lib/runtime/TestResultAggregatorTest.java
@@ -113,6 +113,80 @@
}
@Test
+ public void attemptCount_agggregatesSingleShardSingleAttempt() {
+ when(mockParams.runsDetectsFlakes()).thenReturn(true);
+ TestResultAggregator underTest = createAggregatorWithTestRuns(1);
+
+ underTest.testEvent(
+ shardedTestResult(
+ TestResultData.newBuilder().addAllTestTimes(ImmutableList.of(1L, 2L)),
+ /*shardNum=*/ 0));
+
+ assertThat(underTest.aggregateAndReportSummary(false).getNumAttempts()).isEqualTo(2);
+ }
+
+ @Test
+ public void attemptCount_agggregatesSingleShardMultipleAttempts() {
+ when(mockParams.runsDetectsFlakes()).thenReturn(true);
+ TestResultAggregator underTest = createAggregatorWithTestRuns(2);
+
+ underTest.testEvent(
+ shardedTestResult(
+ TestResultData.newBuilder().addAllTestTimes(ImmutableList.of(1L, 2L)),
+ /*shardNum=*/ 0));
+ underTest.testEvent(
+ shardedTestResult(
+ TestResultData.newBuilder().addAllTestTimes(ImmutableList.of(3L, 4L)),
+ /*shardNum=*/ 0));
+
+ assertThat(underTest.aggregateAndReportSummary(false).getNumAttempts()).isEqualTo(4);
+ }
+
+ @Test
+ public void attemptCount_agggregatesMultipleShardsMultipleAttempts() {
+ when(mockParams.runsDetectsFlakes()).thenReturn(true);
+ when(mockParams.getShards()).thenReturn(2);
+ TestResultAggregator underTest = createAggregatorWithTestRuns(3);
+
+ underTest.testEvent(
+ shardedTestResult(
+ TestResultData.newBuilder().addAllTestTimes(ImmutableList.of(1L, 2L, 3L)),
+ /*shardNum=*/ 0));
+ underTest.testEvent(
+ shardedTestResult(
+ TestResultData.newBuilder().addAllTestTimes(ImmutableList.of(3L, 4L)),
+ /*shardNum=*/ 1));
+ underTest.testEvent(
+ shardedTestResult(
+ TestResultData.newBuilder().addAllTestTimes(ImmutableList.of(3L, 4L)),
+ /*shardNum=*/ 1));
+
+ assertThat(underTest.aggregateAndReportSummary(false).getNumAttempts()).isEqualTo(4);
+ }
+
+ @Test
+ public void attemptCount_agggregatesMultipleShardsSingleShardHasMostAttempts() {
+ when(mockParams.runsDetectsFlakes()).thenReturn(true);
+ when(mockParams.getShards()).thenReturn(2);
+ TestResultAggregator underTest = createAggregatorWithTestRuns(3);
+
+ underTest.testEvent(
+ shardedTestResult(
+ TestResultData.newBuilder().addAllTestTimes(ImmutableList.of(1L, 2L, 3L, 4L, 5L)),
+ /*shardNum=*/ 0));
+ underTest.testEvent(
+ shardedTestResult(
+ TestResultData.newBuilder().addAllTestTimes(ImmutableList.of(3L, 4L)),
+ /*shardNum=*/ 1));
+ underTest.testEvent(
+ shardedTestResult(
+ TestResultData.newBuilder().addAllTestTimes(ImmutableList.of(3L, 4L)),
+ /*shardNum=*/ 1));
+
+ assertThat(underTest.aggregateAndReportSummary(false).getNumAttempts()).isEqualTo(5);
+ }
+
+ @Test
public void cancelConcurrentTests_cancellationAfterPassIgnored() {
when(mockParams.runsDetectsFlakes()).thenReturn(true);
TestResultAggregator underTest = createAggregatorWithTestRuns(2);
@@ -180,4 +254,11 @@
when(mockTestAction.getTestOutputsMapping(any(), any())).thenReturn(ImmutableList.of());
return new TestResult(mockTestAction, data.build(), locallyCached, /*systemFailure=*/ null);
}
+
+ private static TestResult shardedTestResult(TestResultData.Builder data, int shardNum) {
+ TestRunnerAction mockTestAction = mock(TestRunnerAction.class);
+ when(mockTestAction.getTestOutputsMapping(any(), any())).thenReturn(ImmutableList.of());
+ when(mockTestAction.getShardNum()).thenReturn(shardNum);
+ return new TestResult(mockTestAction, data.build(), /*cached=*/ false, /*systemFailure=*/ null);
+ }
}