Prevent NPE on missing TEST_LOG due to cancel
Tests added that exhibit this failure reported in #11468 without the
correction.
Closes #11494.
PiperOrigin-RevId: 314687670
diff --git a/src/main/java/com/google/devtools/build/lib/exec/StandaloneTestStrategy.java b/src/main/java/com/google/devtools/build/lib/exec/StandaloneTestStrategy.java
index 4881a46..75d7e41 100644
--- a/src/main/java/com/google/devtools/build/lib/exec/StandaloneTestStrategy.java
+++ b/src/main/java/com/google/devtools/build/lib/exec/StandaloneTestStrategy.java
@@ -14,6 +14,7 @@
package com.google.devtools.build.lib.exec;
+import com.google.common.annotations.VisibleForTesting;
import com.google.common.base.Preconditions;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
@@ -244,11 +245,17 @@
Path renamedTestLog = null;
for (Pair<String, Path> pair : testOutputs) {
if (TestFileNameConstants.TEST_LOG.equals(pair.getFirst())) {
+ Preconditions.checkState(renamedTestLog == null, "multiple test_log matches");
renamedTestLog = pair.getSecond();
}
}
TestResultData.Builder dataBuilder = result.testResultDataBuilder();
+ // If the test log path does not exist, mark the test as incomplete
+ if (renamedTestLog == null) {
+ dataBuilder.setStatus(BlazeTestStatus.INCOMPLETE);
+ }
+
if (dataBuilder.getStatus() == BlazeTestStatus.PASSED) {
dataBuilder.setPassedLog(renamedTestLog.toString());
} else if (dataBuilder.getStatus() == BlazeTestStatus.INCOMPLETE) {
@@ -400,12 +407,17 @@
return new TestResult(action, data, /*cached*/ true, execRoot);
}
- private static final class StandaloneFailedAttemptResult implements FailedAttemptResult {
+ @VisibleForTesting
+ static final class StandaloneFailedAttemptResult implements FailedAttemptResult {
private final TestResultData testResultData;
StandaloneFailedAttemptResult(TestResultData testResultData) {
this.testResultData = testResultData;
}
+
+ TestResultData testResultData() {
+ return testResultData;
+ }
}
private final class StandaloneTestRunnerSpawn implements TestRunnerSpawn {
diff --git a/src/test/java/com/google/devtools/build/lib/exec/BUILD b/src/test/java/com/google/devtools/build/lib/exec/BUILD
index 1d9f628..89cef69 100644
--- a/src/test/java/com/google/devtools/build/lib/exec/BUILD
+++ b/src/test/java/com/google/devtools/build/lib/exec/BUILD
@@ -45,6 +45,7 @@
"//src/main/java/com/google/devtools/build/lib/exec:spawn_log_context",
"//src/main/java/com/google/devtools/build/lib/exec:spawn_runner",
"//src/main/java/com/google/devtools/build/lib/exec:spawn_strategy_registry",
+ "//src/main/java/com/google/devtools/build/lib/exec:standalone_test_result",
"//src/main/java/com/google/devtools/build/lib/exec:standalone_test_strategy",
"//src/main/java/com/google/devtools/build/lib/exec:streamed_test_output",
"//src/main/java/com/google/devtools/build/lib/exec:symlink_tree_helper",
diff --git a/src/test/java/com/google/devtools/build/lib/exec/StandaloneTestStrategyTest.java b/src/test/java/com/google/devtools/build/lib/exec/StandaloneTestStrategyTest.java
index 028d5cf..b8cb751 100644
--- a/src/test/java/com/google/devtools/build/lib/exec/StandaloneTestStrategyTest.java
+++ b/src/test/java/com/google/devtools/build/lib/exec/StandaloneTestStrategyTest.java
@@ -40,12 +40,15 @@
import com.google.devtools.build.lib.analysis.BlazeDirectories;
import com.google.devtools.build.lib.analysis.ConfiguredTarget;
import com.google.devtools.build.lib.analysis.test.TestActionContext;
+import com.google.devtools.build.lib.analysis.test.TestActionContext.FailedAttemptResult;
+import com.google.devtools.build.lib.analysis.test.TestActionContext.TestRunnerSpawn;
import com.google.devtools.build.lib.analysis.test.TestAttempt;
import com.google.devtools.build.lib.analysis.test.TestProvider;
import com.google.devtools.build.lib.analysis.test.TestResult;
import com.google.devtools.build.lib.analysis.test.TestRunnerAction;
import com.google.devtools.build.lib.analysis.test.TestStrategy;
import com.google.devtools.build.lib.analysis.util.BuildViewTestCase;
+import com.google.devtools.build.lib.buildeventstream.BuildEventStreamProtos.TestResult.ExecutionInfo;
import com.google.devtools.build.lib.buildeventstream.BuildEventStreamProtos.TestStatus;
import com.google.devtools.build.lib.clock.BlazeClock;
import com.google.devtools.build.lib.clock.Clock;
@@ -54,6 +57,7 @@
import com.google.devtools.build.lib.events.EventKind;
import com.google.devtools.build.lib.events.ExtendedEventHandler;
import com.google.devtools.build.lib.events.StoredEventHandler;
+import com.google.devtools.build.lib.exec.StandaloneTestStrategy.StandaloneFailedAttemptResult;
import com.google.devtools.build.lib.exec.util.TestExecutorBuilder;
import com.google.devtools.build.lib.util.AbruptExitException;
import com.google.devtools.build.lib.util.OS;
@@ -62,6 +66,7 @@
import com.google.devtools.build.lib.vfs.FileSystemUtils;
import com.google.devtools.build.lib.vfs.Path;
import com.google.devtools.build.lib.view.test.TestStatus.BlazeTestStatus;
+import com.google.devtools.build.lib.view.test.TestStatus.TestResultData;
import com.google.devtools.common.options.Options;
import java.io.IOException;
import java.io.OutputStream;
@@ -1022,4 +1027,42 @@
storedEvents.getEvents(),
Event.of(EventKind.FAIL, null, "//standalone:empty_test (run 2 of 2)"));
}
+
+ @Test
+ public void missingTestLogSpawnTestResultIsIncomplete() throws Exception {
+ ExecutionOptions executionOptions = ExecutionOptions.DEFAULTS;
+ Path tmpDirRoot = TestStrategy.getTmpRoot(rootDirectory, outputBase, executionOptions);
+ BinTools binTools = BinTools.forUnitTesting(directories, analysisMock.getEmbeddedTools());
+ TestedStandaloneTestStrategy standaloneTestStrategy =
+ new TestedStandaloneTestStrategy(executionOptions, binTools, tmpDirRoot);
+ ActionExecutionContext actionExecutionContext =
+ new FakeActionExecutionContext(createTempOutErr(tmpDirRoot), spawnStrategy, binTools);
+
+ // setup a test action
+ scratch.file("standalone/simple_test.sh", "this does not get executed, it is mocked out");
+ scratch.file(
+ "standalone/BUILD",
+ "sh_test(",
+ " name = \"simple_test\",",
+ " size = \"small\",",
+ " srcs = [\"simple_test.sh\"],",
+ ")");
+ TestRunnerAction testRunnerAction = getTestAction("//standalone:simple_test");
+ TestRunnerSpawn spawn =
+ standaloneTestStrategy.createTestRunnerSpawn(testRunnerAction, actionExecutionContext);
+
+ TestResultData.Builder builder =
+ TestResultData.newBuilder().setTestPassed(true).setStatus(BlazeTestStatus.PASSED);
+ StandaloneTestResult result =
+ StandaloneTestResult.builder()
+ .setSpawnResults(ImmutableList.of())
+ .setTestResultDataBuilder(builder)
+ .setExecutionInfo(ExecutionInfo.getDefaultInstance())
+ .build();
+ FailedAttemptResult failedResult = spawn.finalizeFailedTestAttempt(result, 0);
+
+ assertThat(failedResult).isInstanceOf(StandaloneFailedAttemptResult.class);
+ TestResultData data = ((StandaloneFailedAttemptResult) failedResult).testResultData();
+ assertThat(data.getStatus()).isEqualTo(BlazeTestStatus.INCOMPLETE);
+ }
}