blob: 9b2ae8f8f1cc807071230e36eed672d90609df75 [file] [log] [blame]
// Copyright 2015 The Bazel Authors. All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package com.google.devtools.build.lib.runtime;
import static com.google.common.collect.ImmutableList.toImmutableList;
import static com.google.common.truth.Truth.assertThat;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
import com.google.common.collect.ImmutableList;
import com.google.common.eventbus.EventBus;
import com.google.devtools.build.lib.actions.Artifact.DerivedArtifact;
import com.google.devtools.build.lib.analysis.ConfiguredTarget;
import com.google.devtools.build.lib.analysis.config.BuildConfigurationValue;
import com.google.devtools.build.lib.analysis.test.TestProvider;
import com.google.devtools.build.lib.analysis.test.TestProvider.TestParams;
import com.google.devtools.build.lib.analysis.test.TestResult;
import com.google.devtools.build.lib.analysis.test.TestRunnerAction;
import com.google.devtools.build.lib.packages.TestTimeout;
import com.google.devtools.build.lib.runtime.TestResultAggregator.AggregationPolicy;
import com.google.devtools.build.lib.view.test.TestStatus.BlazeTestStatus;
import com.google.devtools.build.lib.view.test.TestStatus.TestResultData;
import java.util.stream.Stream;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.JUnit4;
/** Tests for {@link TestResultAggregator}. */
@RunWith(JUnit4.class)
public final class TestResultAggregatorTest {
private final TestParams mockParams = mock(TestParams.class);
@Before
public void configureMockParams() {
when(mockParams.runsDetectsFlakes()).thenReturn(false);
when(mockParams.getTimeout()).thenReturn(TestTimeout.LONG);
when(mockParams.getShards()).thenReturn(1);
}
@Test
public void nonCachedResult_setsActionRanTrue() {
TestResultAggregator underTest = createAggregatorWithTestRuns(1);
underTest.testEvent(
testResult(TestResultData.newBuilder().setRemotelyCached(false), /*locallyCached=*/ false));
assertThat(underTest.aggregateAndReportSummary(false).actionRan()).isTrue();
}
@Test
public void locallyCachedTest_setsActionRanFalse() {
TestResultAggregator underTest = createAggregatorWithTestRuns(1);
underTest.testEvent(
testResult(TestResultData.newBuilder().setRemotelyCached(false), /*locallyCached=*/ true));
assertThat(underTest.aggregateAndReportSummary(false).actionRan()).isFalse();
}
@Test
public void remotelyCachedTest_setsActionRanFalse() {
TestResultAggregator underTest = createAggregatorWithTestRuns(1);
underTest.testEvent(
testResult(TestResultData.newBuilder().setRemotelyCached(true), /*locallyCached=*/ false));
assertThat(underTest.aggregateAndReportSummary(false).actionRan()).isFalse();
}
@Test
public void newCachedResult_keepsActionRanTrueWhenAlreadyTrue() {
TestResultAggregator underTest = createAggregatorWithTestRuns(2);
underTest.testEvent(
testResult(TestResultData.newBuilder().setRemotelyCached(false), /*locallyCached=*/ false));
underTest.testEvent(
testResult(TestResultData.newBuilder().setRemotelyCached(true), /*locallyCached=*/ true));
assertThat(underTest.aggregateAndReportSummary(false).actionRan()).isTrue();
}
@Test
public void timingAggregation() {
TestResultAggregator underTest = createAggregatorWithTestRuns(2);
underTest.testEvent(
testResult(
TestResultData.newBuilder().setStartTimeMillisEpoch(7).setRunDurationMillis(10),
/*locallyCached=*/ true));
underTest.testEvent(
testResult(
TestResultData.newBuilder().setStartTimeMillisEpoch(12).setRunDurationMillis(1),
/*locallyCached=*/ true));
TestSummary summary = underTest.aggregateAndReportSummary(false);
assertThat(summary.getFirstStartTimeMillis()).isEqualTo(7);
assertThat(summary.getLastStopTimeMillis()).isEqualTo(17);
assertThat(summary.getTotalRunDurationMillis()).isEqualTo(11);
}
@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);
underTest.testEvent(
testResult(
TestResultData.newBuilder().setStatus(BlazeTestStatus.PASSED),
/*locallyCached=*/ true));
underTest.testEvent(
testResult(
TestResultData.newBuilder().setStatus(BlazeTestStatus.INCOMPLETE),
/*locallyCached=*/ true));
assertThat(underTest.aggregateAndReportSummary(false).getStatus())
.isEqualTo(BlazeTestStatus.PASSED);
}
@Test
public void notAllTestRunsReported_skipTargetsOnFailure_noStatus() {
TestResultAggregator underTest = createAggregatorWithTestRuns(2);
underTest.testEvent(
testResult(
TestResultData.newBuilder().setStatus(BlazeTestStatus.PASSED),
/*locallyCached=*/ false));
assertThat(underTest.aggregateAndReportSummary(/*skipTargetsOnFailure=*/ true).getStatus())
.isEqualTo(BlazeTestStatus.NO_STATUS);
}
@Test
public void notAllTestRunsReported_noSkipTargetsOnFailure_incomplete() {
TestResultAggregator underTest = createAggregatorWithTestRuns(2);
underTest.testEvent(
testResult(
TestResultData.newBuilder().setStatus(BlazeTestStatus.PASSED),
/*locallyCached=*/ false));
assertThat(underTest.aggregateAndReportSummary(/*skipTargetsOnFailure=*/ false).getStatus())
.isEqualTo(BlazeTestStatus.INCOMPLETE);
}
private TestResultAggregator createAggregatorWithTestRuns(int testRuns) {
when(mockParams.getTestStatusArtifacts())
.thenReturn(
Stream.generate(() -> mock(DerivedArtifact.class))
.limit(testRuns)
.collect(toImmutableList()));
when(mockParams.getRuns()).thenReturn(testRuns);
ConfiguredTarget mockTarget = mock(ConfiguredTarget.class);
when(mockTarget.getProvider(TestProvider.class)).thenReturn(new TestProvider(mockParams));
return new TestResultAggregator(
mockTarget,
mock(BuildConfigurationValue.class),
new AggregationPolicy(
new EventBus(), /*testCheckUpToDate=*/ false, /*testVerboseTimeoutWarnings=*/ false),
/*skippedThisTest=*/ false);
}
private static TestResult testResult(TestResultData.Builder data, boolean locallyCached) {
TestRunnerAction mockTestAction = mock(TestRunnerAction.class);
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);
}
}