diff --git a/src/main/java/com/google/devtools/build/lib/analysis/test/TestStrategy.java b/src/main/java/com/google/devtools/build/lib/analysis/test/TestStrategy.java index ef782b5860f53e..d25f74922c6b7d 100644 --- a/src/main/java/com/google/devtools/build/lib/analysis/test/TestStrategy.java +++ b/src/main/java/com/google/devtools/build/lib/analysis/test/TestStrategy.java @@ -42,6 +42,7 @@ import com.google.devtools.build.lib.server.FailureDetails.FailureDetail; import com.google.devtools.build.lib.server.FailureDetails.TestAction; import com.google.devtools.build.lib.server.FailureDetails.TestAction.Code; +import com.google.devtools.build.lib.shell.TerminationStatus; import com.google.devtools.build.lib.util.Fingerprint; import com.google.devtools.build.lib.util.io.OutErr; import com.google.devtools.build.lib.vfs.Path; @@ -393,9 +394,13 @@ protected void processTestOutput( .getEventHandler() .handle(Event.of(EventKind.CANCELLED, null, testName)); } else { - actionExecutionContext - .getEventHandler() - .handle(Event.of(EventKind.FAIL, null, testName + " (see " + testLog + ")")); + TerminationStatus ts = + TerminationStatus.builder() + .setWaitResponse(testResultData.getExitCode()) + .setTimedOut(testResultData.getStatus() == BlazeTestStatus.TIMEOUT) + .build(); + String message = String.format("%s (%s) (see %s)", testName, ts.toShortString(), testLog); + actionExecutionContext.getEventHandler().handle(Event.of(EventKind.FAIL, null, message)); } } } 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 a7000ebbc233b7..a6b74ae6a31755 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 @@ -265,6 +265,10 @@ private StandaloneFailedAttemptResult processTestAttempt( dataBuilder.addFailedLogs(renamedTestLog.toString()); } + if (!result.spawnResults().isEmpty()) { + dataBuilder.setExitCode(result.spawnResults().get(0).exitCode()); + } + // Add the test log to the output TestResultData data = dataBuilder.build(); actionExecutionContext diff --git a/src/main/protobuf/test_status.proto b/src/main/protobuf/test_status.proto index 72cb268607f0c0..e77a19fd41a6b8 100644 --- a/src/main/protobuf/test_status.proto +++ b/src/main/protobuf/test_status.proto @@ -20,15 +20,15 @@ option java_package = "com.google.devtools.build.lib.view.test"; // Status data of test cases which failed (used only for printing test summary) enum FailedTestCasesStatus { - /** Information about every test case is available. */ - FULL = 1; - /** Information about some test cases may be missing. */ - PARTIAL = 2; - /** No information about individual test cases. */ - NOT_AVAILABLE = 3; - /** This is an empty object still without data. */ - EMPTY = 4; -}; + /** Information about every test case is available. */ + FULL = 1; + /** Information about some test cases may be missing. */ + PARTIAL = 2; + /** No information about individual test cases. */ + NOT_AVAILABLE = 3; + /** This is an empty object still without data. */ + EMPTY = 4; +} // Detailed status data for a TestRunnerAction execution. enum BlazeTestStatus { @@ -41,7 +41,7 @@ enum BlazeTestStatus { REMOTE_FAILURE = 6; FAILED_TO_BUILD = 7; BLAZE_HALTED_BEFORE_TESTING = 8; -}; +} // TestCase contains detailed data about all tests (cases/suites/decorators) // ran, structured in a tree. This data will be later used to present the tests @@ -68,7 +68,7 @@ message TestCase { optional Type type = 6; optional Status status = 7; optional bool run = 8 [default = true]; -}; +} // TestResultData holds the outcome data for a single test action (A // single test rule can result in multiple actions due to sharding and @@ -83,6 +83,7 @@ message TestResultData { // Following data is informational. optional BlazeTestStatus status = 3 [default = NO_STATUS]; optional string status_details = 16; + optional int32 exit_code = 17; repeated string failed_logs = 4; repeated string warning = 5; optional bool has_coverage = 6; @@ -111,4 +112,4 @@ message TestResultData { // Additional build info optional TestCase test_case = 13; optional FailedTestCasesStatus failed_status = 14; -}; +} diff --git a/src/test/shell/integration/ui_test.sh b/src/test/shell/integration/ui_test.sh index c9b28d1d3942ab..baa40c334d47cf 100755 --- a/src/test/shell/integration/ui_test.sh +++ b/src/test/shell/integration/ui_test.sh @@ -727,4 +727,14 @@ EOF expect_log_n "INFO: Build completed successfully, [456] total actions" 1 } +function test_exit_code_reported() { + bazel build --curses=yes --color=yes error:failwitherror 2>$TEST_log \ + && fail "${PRODUCT_NAME} build passed" + expect_log '//error:failwitherror failed: (Exit 1): ' + + bazel test --curses=yes --color=yes pkg:false 2>$TEST_log \ + && fail "${PRODUCT_NAME} test passed" + expect_log '//pkg:false (Exit 1) (see' +} + run_suite "Integration tests for ${PRODUCT_NAME}'s UI"