Don't publish target_summary events for skipped tests; add e2e tests for target_summary events

Skipped tests don't receive configured, completed, or test_summary BEP events, so don't publish target_summary either

PiperOrigin-RevId: 361576400
diff --git a/src/main/java/com/google/devtools/build/lib/runtime/TargetSummaryPublisher.java b/src/main/java/com/google/devtools/build/lib/runtime/TargetSummaryPublisher.java
index 4822767..38f3339 100644
--- a/src/main/java/com/google/devtools/build/lib/runtime/TargetSummaryPublisher.java
+++ b/src/main/java/com/google/devtools/build/lib/runtime/TargetSummaryPublisher.java
@@ -81,12 +81,17 @@
   public void populateTargets(TestFilteringCompleteEvent event) {
     int expectedCompletions = aspectCount.get() + 1; // + 1 for target itself
     checkState(expectedCompletions > 0, "Haven't received BuildStartingEvent");
-    // Add all target runs to the map, assuming 1:1 status artifact <-> result.
     ImmutableSet<ConfiguredTarget> testTargets =
         event.getTestTargets() != null
             ? ImmutableSet.copyOf(event.getTestTargets())
             : ImmutableSet.of();
+    ImmutableSet<ConfiguredTarget> skippedTests = ImmutableSet.copyOf(event.getSkippedTests());
     for (ConfiguredTarget target : event.getTargets()) {
+      if (skippedTests.contains(target)) {
+        // Skipped tests aren't built, and won't receive completion events, so we ignore them. Note
+        // we'll still get (and ignore) a TestSummary event, but that event isn't published to BEP.
+        continue;
+      }
       // We want target summaries for alias targets, but note they don't receive test summaries.
       TargetSummaryAggregator aggregator =
           new TargetSummaryAggregator(
diff --git a/src/test/shell/integration/build_event_stream_test.sh b/src/test/shell/integration/build_event_stream_test.sh
index 34b0047..1603900 100755
--- a/src/test/shell/integration/build_event_stream_test.sh
+++ b/src/test/shell/integration/build_event_stream_test.sh
@@ -407,6 +407,15 @@
   expect_log 'value.*workspace_status_value'
 }
 
+function test_target_summary() {
+  bazel test --experimental_bep_target_summary \
+      --build_event_text_file=$TEST_log pkg:true \
+    || fail "bazel test failed"
+  expect_log_once '^test_summary '
+  expect_log_once '^target_summary '
+  expect_log_once 'overall_test_status: PASSED'
+}
+
 function test_suite() {
   # ...same true when running a test suite containing that test
   bazel test --build_event_text_file=$TEST_log pkg:suite \
@@ -434,7 +443,19 @@
   expect_not_log 'status.*FLAKY'
 }
 
-function test_test_inidivual_results() {
+function test_target_summary_for_test() {
+  bazel test --experimental_bep_target_summary \
+      --build_event_text_file="$TEST_log" //pkg:true \
+    || fail "bazel test failed"
+  expect_log_once '^test_summary '
+  expect_not_log 'aborted'
+  expect_not_log 'status.*FAILED'
+  expect_not_log 'status.*FLAKY'
+  expect_log_once '^target_summary '
+  expect_log_once 'overall_test_status: PASSED'
+}
+
+function test_test_individual_results() {
   # Requesting a test, we expect
   # - precisely one test summary (for the single test we run)
   # - that is properly chained (no additional progress events)
@@ -456,13 +477,16 @@
   # mentioned in the stream.
   # Moreover, as the test consistently fails, we expect the overall status
   # to be reported as failure.
-  (bazel test --build_event_text_file=$TEST_log pkg:flaky \
-      && fail "test failure expected" ) || true
+  (bazel test --experimental_bep_target_summary \
+      --build_event_text_file=$TEST_log pkg:flaky \
+    && fail "test failure expected" ) || true
   expect_log 'attempt.*1$'
   expect_log 'attempt.*2$'
   expect_log 'attempt.*3$'
   expect_log_once '^test_summary '
   expect_log 'status.*FAILED'
+  expect_log_once '^target_summary '
+  expect_log_once 'overall_test_status.*FAILED'
   expect_not_log 'status.*PASSED'
   expect_not_log 'status.*FLAKY'
   expect_not_log 'aborted'
@@ -556,6 +580,19 @@
   expect_log 'tag2'
 }
 
+function test_target_summary_for_build() {
+  bazel build --experimental_bep_target_summary --verbose_failures \
+      --build_event_text_file=$TEST_log pkg:output_files_and_tags \
+    || fail "bazel build failed"
+  expect_log 'output_group'
+  expect_log 'out1.txt'
+  expect_log 'tag1'
+  expect_log 'tag2'
+  expect_log_once '^target_summary '
+  expect_log_once 'overall_build_success.*true'
+  expect_not_log 'overall_test_status'
+}
+
 function test_test_target_complete() {
     bazel test --build_event_text_file="${TEST_log}" pkg:true \
           || tail "expected success"
@@ -656,6 +693,21 @@
   expect_log_once '^build_tool_logs'
 }
 
+function test_aspect_target_summary() {
+  bazel build --build_event_text_file=$TEST_log \
+    --experimental_bep_target_summary \
+    --aspects=simpleaspect.bzl%simple_aspect \
+    --output_groups=aspect-out \
+    pkg:output_files_and_tags || fail "bazel build failed"
+  expect_not_log 'aborted'
+  expect_log_n '^configured' 2
+  expect_log 'last_message: true'
+  expect_log_once '^build_tool_logs'
+  expect_log_n '^completed' 2
+  expect_log_once '^target_summary '
+  expect_log_once 'overall_build_success.*true'
+}
+
 function test_failing_aspect() {
   bazel build --build_event_text_file=$TEST_log \
     --aspects=failingaspect.bzl%failing_aspect \
@@ -667,6 +719,21 @@
   expect_log_once '^build_tool_logs'
 }
 
+function test_aspect_analysis_failure_no_target_summary() {
+  bazel build -k --build_event_text_file=$TEST_log \
+    --experimental_bep_target_summary \
+    --aspects=failingaspect.bzl%failing_aspect \
+    --output_groups=aspect-out \
+    pkg:output_files_and_tags && fail "expected failure" || true
+  expect_log 'aspect.*failing_aspect'
+  expect_log '^finished'
+  expect_log 'last_message: true'
+  expect_log_once '^build_tool_logs'
+  expect_log_once '^completed '  # target completes due to -k
+  expect_log_once '^aborted '  # aborted due to aspect analysis failure
+  expect_not_log '^target_summary '  # no summary due to analysis failure
+}
+
 function test_failing_aspect_bep_output_groups() {
   # In outputgroups/rules.bzl, the `my_rule` definition defines four output
   # groups with different (successful/failed) action counts:
@@ -708,10 +775,12 @@
   # When building but not testing a test, there won't be a test summary
   # (as nothing was tested), so it should not be announced.
   # Still, no event should only be chained in by progress events.
-  bazel build --build_event_text_file=$TEST_log pkg:true \
+  bazel build --experimental_bep_target_summary \
+      --build_event_text_file=$TEST_log pkg:true \
     || fail "bazel build failed"
   expect_not_log 'aborted'
   expect_not_log 'test_summary '
+  expect_log_once '^target_summary '
   # Build Finished
   expect_log 'build_finished'
   expect_log 'finish_time'
@@ -778,6 +847,29 @@
   expect_log_once '^build_tool_logs'
 }
 
+function test_root_cause_before_target_summary() {
+  (bazel build --experimental_bep_target_summary \
+         --build_event_text_file=$TEST_log \
+         pkg:fails_to_build && fail "build failure expected") || true
+  # We expect precisely one action being reported (the failed one) and
+  # precisely on report on a completed target; moreover, the action has
+  # to be reported first.
+  expect_log_once '^action'
+  expect_log 'type: "Genrule"'
+  expect_log_once '^completed'
+  expect_log_once '^target_summary'
+  expect_not_log 'success: true'
+  local naction=`grep -n '^action' $TEST_log | cut -f 1 -d :`
+  local ncomplete=`grep -n '^completed' $TEST_log | cut -f 1 -d :`
+  local nsummary=`grep -n '^target_summary' $TEST_log | cut -f 1 -d :`
+  [ $naction -lt $ncomplete ] \
+      || fail "failed action not before completed target"
+  [ $ncomplete -lt $nsummary ] \
+      || fail "completed not before target_summary"
+  expect_log 'last_message: true'
+  expect_log_once '^build_tool_logs'
+}
+
 function test_action_conf() {
   # Verify that the expected configurations for actions are reported.
   # The example contains a configuration transition (from building for
@@ -805,18 +897,24 @@
 
 function test_visibility_failure() {
   bazel shutdown
-  (bazel build --build_event_text_file=$TEST_log \
+  (bazel build --experimental_bep_target_summary \
+         --build_event_text_file=$TEST_log \
          //visibility:cannotsee && fail "build failure expected") || true
   expect_log 'reason: ANALYSIS_FAILURE'
   expect_log '^aborted'
+  expect_not_log '^completed'
+  expect_not_log '^target_summary'
 
   # The same should hold true, if the server has already analyzed the target
-  (bazel build --build_event_text_file=$TEST_log \
+  (bazel build --experimental_bep_target_summary \
+         --build_event_text_file=$TEST_log \
          //visibility:cannotsee && fail "build failure expected") || true
   expect_log 'reason: ANALYSIS_FAILURE'
   expect_log '^aborted'
   expect_log 'last_message: true'
   expect_log_once '^build_tool_logs'
+  expect_not_log '^completed'
+  expect_not_log '^target_summary'
 }
 
 function test_visibility_indirect() {
@@ -922,9 +1020,12 @@
 }
 
 function test_test_fails_to_build() {
-  (bazel test --build_event_text_file=$TEST_log \
+  (bazel test --experimental_bep_target_summary \
+         --build_event_text_file=$TEST_log \
          pkg:test_that_fails_to_build && fail "test failure expected") || true
   expect_not_log '^test_summary'
+  expect_log_once '^target_summary '
+  expect_not_log 'overall_build_success'
   expect_log 'last_message: true'
   expect_log 'BUILD_FAILURE'
   expect_log 'last_message: true'
@@ -933,9 +1034,12 @@
 }
 
 function test_no_tests_found() {
-  (bazel test --build_event_text_file=$TEST_log \
+  (bazel test --experimental_bep_target_summary \
+         --build_event_text_file=$TEST_log \
          pkg:not_a_test && fail "failure expected") || true
   expect_not_log '^test_summary'
+  expect_log_once '^target_summary '
+  expect_log 'overall_build_success: true'
   expect_log 'last_message: true'
   expect_log 'NO_TESTS_FOUND'
   expect_log 'last_message: true'
@@ -1049,19 +1153,23 @@
 }
 
 function test_noanalyze() {
-  bazel build --noanalyze --build_event_text_file="${TEST_log}" pkg:true \
+  bazel build --noanalyze  --experimental_bep_target_summary \
+      --build_event_text_file="${TEST_log}" pkg:true \
     || fail "build failed"
   expect_log_once '^aborted'
   expect_log 'reason: NO_ANALYZE'
   expect_log 'last_message: true'
   expect_log_once '^build_tool_logs'
+  expect_not_log '^target_summary'
 }
 
 function test_nobuild() {
-  bazel build --nobuild --build_event_text_file="${TEST_log}" pkg:true \
+  bazel build --nobuild  --experimental_bep_target_summary \
+      --build_event_text_file="${TEST_log}" pkg:true \
     || fail "build failed"
   expect_log_once '^aborted'
   expect_log 'reason: NO_BUILD'
+  expect_not_log '^target_summary'
 }
 
 function test_server_pid() {