Cleanups for nested test_suite or java_test under trim_test_configuration

For test_suite, no longer make TestConfiguration a hard requirement (similar to https://github.com/bazelbuild/bazel/commit/215a0f70c81a7574d5d9fe5f771446aaf622f21e). Also, split out the older 'temporary hack' of TestTags in TestProvider (used in test_suite filtering) to its own provider, TestTagsProvider, that is now always provided by tests.

For java_test, change [Bazel]JavaSemantics to more gracefully handle a missing TestConfiguration. For persistent test runner related functions, returns false when missing the TestConfiguration (as it is assumed to be irrelevant). For legacy java_test matters, assumes test_arg is empty (as again assumed to be irrelevant).

RELNOTES: NONE
PiperOrigin-RevId: 334547057
diff --git a/src/main/java/com/google/devtools/build/lib/analysis/BUILD b/src/main/java/com/google/devtools/build/lib/analysis/BUILD
index 8e99574..e36237b 100644
--- a/src/main/java/com/google/devtools/build/lib/analysis/BUILD
+++ b/src/main/java/com/google/devtools/build/lib/analysis/BUILD
@@ -270,6 +270,7 @@
         "test/TestResult.java",
         "test/TestRunnerAction.java",
         "test/TestStrategy.java",
+        "test/TestTagsProvider.java",
         "test/TestTargetExecutionSettings.java",
         "test/TestTargetProperties.java",
     ],
diff --git a/src/main/java/com/google/devtools/build/lib/analysis/RuleConfiguredTargetBuilder.java b/src/main/java/com/google/devtools/build/lib/analysis/RuleConfiguredTargetBuilder.java
index 59595f3..e8ec586 100644
--- a/src/main/java/com/google/devtools/build/lib/analysis/RuleConfiguredTargetBuilder.java
+++ b/src/main/java/com/google/devtools/build/lib/analysis/RuleConfiguredTargetBuilder.java
@@ -42,6 +42,7 @@
 import com.google.devtools.build.lib.analysis.test.TestEnvironmentInfo;
 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.TestTagsProvider;
 import com.google.devtools.build.lib.cmdline.Label;
 import com.google.devtools.build.lib.collect.nestedset.NestedSet;
 import com.google.devtools.build.lib.collect.nestedset.NestedSetBuilder;
@@ -161,13 +162,16 @@
     // Create test action and artifacts if target was successfully initialized
     // and is a test. Also, as an extreme hack, only bother doing this if the TestConfiguration
     // is actually present.
-    if (TargetUtils.isTestRule(ruleContext.getTarget())
-        && ruleContext.getConfiguration().hasFragment(TestConfiguration.class)) {
-      if (runfilesSupport != null) {
-        add(TestProvider.class, initializeTestProvider(filesToRunProvider));
-      } else {
-        if (!allowAnalysisFailures) {
-          throw new IllegalStateException("Test rules must have runfiles");
+    if (TargetUtils.isTestRule(ruleContext.getTarget())) {
+      ImmutableList<String> testTags = ImmutableList.copyOf(ruleContext.getRule().getRuleTags());
+      add(TestTagsProvider.class, new TestTagsProvider(testTags));
+      if (ruleContext.getConfiguration().hasFragment(TestConfiguration.class)) {
+        if (runfilesSupport != null) {
+          add(TestProvider.class, initializeTestProvider(filesToRunProvider));
+        } else {
+          if (!allowAnalysisFailures) {
+            throw new IllegalStateException("Test rules must have runfiles");
+          }
         }
       }
     }
@@ -407,8 +411,7 @@
                 (ExecutionInfo) providersBuilder.getProvider(ExecutionInfo.PROVIDER.getKey()))
             .setShardCount(explicitShardCount)
             .build();
-    ImmutableList<String> testTags = ImmutableList.copyOf(ruleContext.getRule().getRuleTags());
-    return new TestProvider(testParams, testTags);
+    return new TestProvider(testParams);
   }
 
   /**
diff --git a/src/main/java/com/google/devtools/build/lib/analysis/test/TestProvider.java b/src/main/java/com/google/devtools/build/lib/analysis/test/TestProvider.java
index 344633d..d14c16e 100644
--- a/src/main/java/com/google/devtools/build/lib/analysis/test/TestProvider.java
+++ b/src/main/java/com/google/devtools/build/lib/analysis/test/TestProvider.java
@@ -22,17 +22,14 @@
 import com.google.devtools.build.lib.analysis.TransitiveInfoProvider;
 import com.google.devtools.build.lib.concurrent.ThreadSafety.Immutable;
 import com.google.devtools.build.lib.packages.TestTimeout;
-import java.util.List;
 
 /** A {@link TransitiveInfoProvider} for configured targets that implement test rules. */
 @Immutable
 public final class TestProvider implements TransitiveInfoProvider {
   private final TestParams testParams;
-  private final ImmutableList<String> testTags;
 
-  public TestProvider(TestParams testParams, ImmutableList<String> testTags) {
+  public TestProvider(TestParams testParams) {
     this.testParams = testParams;
-    this.testTags = testTags;
   }
 
   /**
@@ -44,14 +41,6 @@
   }
 
   /**
-   * Temporary hack to allow dependencies on test_suite targets to continue to work for the time
-   * being.
-   */
-  public List<String> getTestTags() {
-    return testTags;
-  }
-
-  /**
    * Returns the test status artifacts for a specified configured target
    *
    * @param target the configured target. Should belong to a test rule.
diff --git a/src/main/java/com/google/devtools/build/lib/analysis/test/TestTagsProvider.java b/src/main/java/com/google/devtools/build/lib/analysis/test/TestTagsProvider.java
new file mode 100644
index 0000000..04afe46
--- /dev/null
+++ b/src/main/java/com/google/devtools/build/lib/analysis/test/TestTagsProvider.java
@@ -0,0 +1,38 @@
+// Copyright 2014 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.analysis.test;
+
+import com.google.common.collect.ImmutableList;
+import com.google.devtools.build.lib.analysis.TransitiveInfoProvider;
+import com.google.devtools.build.lib.concurrent.ThreadSafety.Immutable;
+
+/**
+ * A {@link TransitiveInfoProvider} for configured targets to remember tags for test rules.
+ *
+ * <p>Temporary hack to allow dependencies on test_suite targets to continue to work for the time
+ * being.
+ */
+@Immutable
+public final class TestTagsProvider implements TransitiveInfoProvider {
+  private final ImmutableList<String> testTags;
+
+  public TestTagsProvider(ImmutableList<String> testTags) {
+    this.testTags = testTags;
+  }
+
+  public ImmutableList<String> getTestTags() {
+    return testTags;
+  }
+}
diff --git a/src/main/java/com/google/devtools/build/lib/bazel/rules/java/BazelJavaSemantics.java b/src/main/java/com/google/devtools/build/lib/bazel/rules/java/BazelJavaSemantics.java
index b506e3f..2717140 100644
--- a/src/main/java/com/google/devtools/build/lib/bazel/rules/java/BazelJavaSemantics.java
+++ b/src/main/java/com/google/devtools/build/lib/bazel/rules/java/BazelJavaSemantics.java
@@ -711,7 +711,7 @@
       if (JavaSemantics.useLegacyJavaTest(ruleContext)) {
         TestConfiguration testConfiguration =
             ruleContext.getConfiguration().getFragment(TestConfiguration.class);
-        if (testConfiguration.getTestArguments().isEmpty()
+        if ((testConfiguration == null || testConfiguration.getTestArguments().isEmpty())
             && !ruleContext.attributes().isAttributeValueExplicitlySpecified("args")) {
           ImmutableList.Builder<String> builder = ImmutableList.builder();
           for (Artifact artifact : sources) {
diff --git a/src/main/java/com/google/devtools/build/lib/rules/java/JavaSemantics.java b/src/main/java/com/google/devtools/build/lib/rules/java/JavaSemantics.java
index c9b0a1d..b677745 100644
--- a/src/main/java/com/google/devtools/build/lib/rules/java/JavaSemantics.java
+++ b/src/main/java/com/google/devtools/build/lib/rules/java/JavaSemantics.java
@@ -320,9 +320,19 @@
    */
   boolean isJavaExecutableSubstitution();
 
+  /**
+   * Returns true if target is a test target, has TestConfiguration, and persistent test runner set.
+   *
+   * <p>Note that no TestConfiguration implies the TestConfiguration was pruned in some parent of
+   * the rule. Therefore, TestTarget not currently being analyzed as part of top-level and thus
+   * persistent test runner is not especially relevant.
+   */
   static boolean isTestTargetAndPersistentTestRunner(RuleContext ruleContext) {
-    return ruleContext.isTestTarget()
-        && ruleContext.getFragment(TestConfiguration.class).isPersistentTestRunner();
+    if (!ruleContext.isTestTarget()) {
+      return false;
+    }
+    TestConfiguration testConfiguration = ruleContext.getFragment(TestConfiguration.class);
+    return testConfiguration != null && testConfiguration.isPersistentTestRunner();
   }
 
   static Runfiles getTestSupportRunfiles(RuleContext ruleContext) {
diff --git a/src/main/java/com/google/devtools/build/lib/rules/test/TestSuite.java b/src/main/java/com/google/devtools/build/lib/rules/test/TestSuite.java
index 323f0e0..55e9036 100644
--- a/src/main/java/com/google/devtools/build/lib/rules/test/TestSuite.java
+++ b/src/main/java/com/google/devtools/build/lib/rules/test/TestSuite.java
@@ -23,7 +23,7 @@
 import com.google.devtools.build.lib.analysis.Runfiles;
 import com.google.devtools.build.lib.analysis.RunfilesProvider;
 import com.google.devtools.build.lib.analysis.TransitiveInfoCollection;
-import com.google.devtools.build.lib.analysis.test.TestProvider;
+import com.google.devtools.build.lib.analysis.test.TestTagsProvider;
 import com.google.devtools.build.lib.packages.BuildType;
 import com.google.devtools.build.lib.packages.TestTargetUtils;
 import com.google.devtools.build.lib.packages.Type;
@@ -65,9 +65,9 @@
           Iterables.concat(
               getPrerequisites(ruleContext, "tests"),
               getPrerequisites(ruleContext, "$implicit_tests"))) {
-      if (dep.getProvider(TestProvider.class) != null) {
+      if (dep.getProvider(TestTagsProvider.class) != null) {
         // getTestTags maps to Rule.getRuleTags.
-        List<String> tags = dep.getProvider(TestProvider.class).getTestTags();
+        List<String> tags = dep.getProvider(TestTagsProvider.class).getTestTags();
         if (!TestTargetUtils.testMatchesFilters(
             tags, requiredExcluded.first, requiredExcluded.second)) {
           // This test does not match our filter. Ignore it.
@@ -105,8 +105,8 @@
     for (TransitiveInfoCollection dep : ruleContext.getPrerequisites(attributeName)) {
       // TODO(bazel-team): Maybe convert the TransitiveTestsProvider into an inner interface.
       TransitiveTestsProvider provider = dep.getProvider(TransitiveTestsProvider.class);
-      TestProvider testProvider = dep.getProvider(TestProvider.class);
-      if (provider == null && testProvider == null) {
+      TestTagsProvider tagsProvider = dep.getProvider(TestTagsProvider.class);
+      if (provider == null && tagsProvider == null) {
         ruleContext.attributeError(attributeName,
             "expecting a test or a test_suite rule but '" + dep.getLabel() + "' is not one");
       }
diff --git a/src/main/java/com/google/devtools/build/lib/rules/test/TestSuiteRule.java b/src/main/java/com/google/devtools/build/lib/rules/test/TestSuiteRule.java
index adb99f9..5eafdbb 100644
--- a/src/main/java/com/google/devtools/build/lib/rules/test/TestSuiteRule.java
+++ b/src/main/java/com/google/devtools/build/lib/rules/test/TestSuiteRule.java
@@ -21,6 +21,7 @@
 import com.google.devtools.build.lib.analysis.RuleDefinition;
 import com.google.devtools.build.lib.analysis.RuleDefinitionEnvironment;
 import com.google.devtools.build.lib.analysis.test.TestConfiguration;
+import com.google.devtools.build.lib.packages.ConfigurationFragmentPolicy.MissingFragmentPolicy;
 import com.google.devtools.build.lib.packages.RuleClass;
 
 /** Rule object implementing "test_suite". */
@@ -29,8 +30,10 @@
   public RuleClass build(RuleClass.Builder builder, RuleDefinitionEnvironment env) {
     return builder
         // Technically, test_suite does not use TestConfiguration. But the tests it depends on
-        // will always depend on TestConfiguration, so requiring it here simply acknowledges that.
+        // will always depend on TestConfiguration, so requiring it here simply acknowledges that
+        // and prevents pruning by --trim_test_configuration.
         .requiresConfigurationFragments(TestConfiguration.class)
+        .setMissingFragmentPolicy(TestConfiguration.class, MissingFragmentPolicy.IGNORE)
         .override(
             attr("testonly", BOOLEAN)
                 .value(true)
diff --git a/src/test/java/com/google/devtools/build/lib/analysis/test/TrimTestConfigurationTest.java b/src/test/java/com/google/devtools/build/lib/analysis/test/TrimTestConfigurationTest.java
index d6cc9b5..905e7fe 100644
--- a/src/test/java/com/google/devtools/build/lib/analysis/test/TrimTestConfigurationTest.java
+++ b/src/test/java/com/google/devtools/build/lib/analysis/test/TrimTestConfigurationTest.java
@@ -751,6 +751,51 @@
   }
 
   @Test
+  public void flagOnNonTestTargetWithTestSuiteDependencies_IsPermitted() throws Exception {
+    // reporter.removeHandler(failFastHandler);
+    scratch.file(
+        "test/BUILD",
+        "load(':test.bzl', 'starlark_test')",
+        "load(':lib.bzl', 'starlark_lib')",
+        "starlark_lib(",
+        "    name = 'starlark_dep',",
+        "    deps = [':a_test_suite'],",
+        "    testonly = 1,",
+        ")",
+        "starlark_test(",
+        "    name = 'starlark_test',",
+        ")",
+        "test_suite(",
+        "    name = 'a_test_suite',",
+        "    tests = [':starlark_test'],",
+        ")");
+    useConfiguration("--trim_test_configuration", "--noexpand_test_suites", "--test_arg=TypeA");
+    update("//test:starlark_dep");
+    assertThat(getAnalysisResult().getTargetsToBuild()).isNotEmpty();
+  }
+
+  @Test
+  public void flagOnNonTestTargetWithJavaTestDependencies_IsPermitted() throws Exception {
+    // reporter.removeHandler(failFastHandler);
+    scratch.file(
+        "test/BUILD",
+        "load(':lib.bzl', 'starlark_lib')",
+        "starlark_lib(",
+        "    name = 'starlark_dep',",
+        "    deps = [':JavaTest'],",
+        "    testonly = 1,",
+        ")",
+        "java_test(",
+        "    name = 'JavaTest',",
+        "    srcs = ['JavaTest.java'],",
+        "    test_class = 'test.JavaTest',",
+        ")");
+    useConfiguration("--trim_test_configuration", "--noexpand_test_suites", "--test_arg=TypeA");
+    update("//test:starlark_dep");
+    assertThat(getAnalysisResult().getTargetsToBuild()).isNotEmpty();
+  }
+
+  @Test
   public void flagOnTestSuiteWithTestDependencies_CanBeAnalyzed() throws Exception {
     scratch.file(
         "test/BUILD",
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 59627b3..68719d3 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
@@ -51,7 +51,7 @@
     when(mockParams.getTimeout()).thenReturn(TestTimeout.LONG);
     when(mockParams.getTestStatusArtifacts())
         .thenReturn(ImmutableList.<Artifact.DerivedArtifact>of());
-    TestProvider testProvider = new TestProvider(mockParams, ImmutableList.<String>of());
+    TestProvider testProvider = new TestProvider(mockParams);
 
     ConfiguredTarget mockTarget = mock(ConfiguredTarget.class);
     when(mockTarget.getProvider(TestProvider.class)).thenReturn(testProvider);
diff --git a/src/test/java/com/google/devtools/build/lib/runtime/TestSummaryTest.java b/src/test/java/com/google/devtools/build/lib/runtime/TestSummaryTest.java
index 28a38fc..d7cce6c 100644
--- a/src/test/java/com/google/devtools/build/lib/runtime/TestSummaryTest.java
+++ b/src/test/java/com/google/devtools/build/lib/runtime/TestSummaryTest.java
@@ -253,7 +253,7 @@
     when(testParams.getRuns()).thenReturn(2);
     when(testParams.getShards()).thenReturn(3);
 
-    TestProvider testProvider = new TestProvider(testParams, ImmutableList.of());
+    TestProvider testProvider = new TestProvider(testParams);
     when(stubTarget.getProvider(eq(TestProvider.class))).thenReturn(testProvider);
 
     PathConverter pathConverter = mock(PathConverter.class);