Open source some skyframe/bazel tests.

--
MOS_MIGRATED_REVID=106308990
diff --git a/src/test/java/com/google/devtools/build/lib/skyframe/PrepareDepsOfPatternsFunctionTest.java b/src/test/java/com/google/devtools/build/lib/skyframe/PrepareDepsOfPatternsFunctionTest.java
new file mode 100644
index 0000000..d7b9e5f
--- /dev/null
+++ b/src/test/java/com/google/devtools/build/lib/skyframe/PrepareDepsOfPatternsFunctionTest.java
@@ -0,0 +1,273 @@
+// 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.skyframe;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import com.google.common.base.Preconditions;
+import com.google.common.collect.ImmutableList;
+import com.google.devtools.build.lib.analysis.util.BuildViewTestCase;
+import com.google.devtools.build.lib.cmdline.Label;
+import com.google.devtools.build.lib.packages.NoSuchPackageException;
+import com.google.devtools.build.lib.packages.NoSuchTargetException;
+import com.google.devtools.build.skyframe.EvaluationResult;
+import com.google.devtools.build.skyframe.SkyKey;
+import com.google.devtools.build.skyframe.SkyValue;
+import com.google.devtools.build.skyframe.WalkableGraph;
+
+import java.io.IOException;
+
+/** Tests for {@link com.google.devtools.build.lib.skyframe.PrepareDepsOfPatternsFunction}. */
+public class PrepareDepsOfPatternsFunctionTest extends BuildViewTestCase {
+
+  private static SkyKey getKeyForLabel(Label label) {
+    // Note that these tests used to look for TargetMarker SkyKeys before TargetMarker was
+    // inlined in TransitiveTraversalFunction. Because TargetMarker is now inlined, it doesn't
+    // appear in the graph. Instead, these tests now look for TransitiveTraversal keys.
+    return TransitiveTraversalValue.key(label);
+  }
+
+  public void testFunctionLoadsTargetAndNotUnspecifiedTargets() throws Exception {
+    // Given a package "//foo" with independent target rules ":foo" and ":foo2",
+    createFooAndFoo2(/*dependent=*/ false);
+
+    // Given a target pattern sequence consisting of a single-target pattern for "//foo",
+    ImmutableList<String> patternSequence = ImmutableList.of("//foo");
+
+    // When PrepareDepsOfPatternsFunction successfully completes evaluation,
+    WalkableGraph walkableGraph =
+        getGraphFromPatternsEvaluation(patternSequence, /*successExpected=*/ true);
+
+    // Then the graph contains a value for the target "//foo:foo",
+    assertValidValue(walkableGraph, getKeyForLabel(Label.create("foo", "foo")));
+
+    // And the graph does not contain a value for the target "//foo:foo2".
+    assertFalse(walkableGraph.exists(getKeyForLabel(Label.create("foo", "foo2"))));
+  }
+
+  public void testFunctionLoadsTargetDependencies() throws Exception {
+    // Given a package "//foo" with target rules ":foo" and ":foo2",
+    // And given ":foo" depends on ":foo2",
+    createFooAndFoo2(/*dependent=*/ true);
+
+    // Given a target pattern sequence consisting of a single-target pattern for "//foo",
+    ImmutableList<String> patternSequence = ImmutableList.of("//foo");
+
+    // When PrepareDepsOfPatternsFunction successfully completes evaluation,
+    WalkableGraph walkableGraph =
+        getGraphFromPatternsEvaluation(patternSequence, /*successExpected=*/ true);
+
+    // Then the graph contains an entry for ":foo"'s dependency, ":foo2".
+    assertValidValue(walkableGraph, getKeyForLabel(Label.create("foo", "foo2")));
+  }
+
+  public void testFunctionExpandsTargetPatterns() throws Exception {
+    // Given a package "//foo" with independent target rules ":foo" and ":foo2",
+    createFooAndFoo2(/*dependent=*/ false);
+
+    // Given a target pattern sequence consisting of a pattern for "//foo:*",
+    ImmutableList<String> patternSequence = ImmutableList.of("//foo:*");
+
+    // When PrepareDepsOfPatternsFunction successfully completes evaluation,
+    WalkableGraph walkableGraph =
+        getGraphFromPatternsEvaluation(patternSequence, /*successExpected=*/ true);
+
+    // Then the graph contains an entry for ":foo" and ":foo2".
+    assertValidValue(walkableGraph, getKeyForLabel(Label.create("foo", "foo")));
+    assertValidValue(walkableGraph, getKeyForLabel(Label.create("foo", "foo2")));
+  }
+
+  public void testTargetParsingException() throws Exception {
+    // Given no packages, and a target pattern sequence referring to a non-existent target,
+    String nonexistentTarget = "//foo:foo";
+    ImmutableList<String> patternSequence = ImmutableList.of(nonexistentTarget);
+
+    // When PrepareDepsOfPatternsFunction completes evaluation,
+    WalkableGraph walkableGraph =
+        getGraphFromPatternsEvaluation(patternSequence, /*successExpected=*/ false);
+
+    // Then the graph does not contain an entry for ":foo",
+    assertFalse(walkableGraph.exists(getKeyForLabel(Label.create("foo", "foo"))));
+  }
+
+  public void testDependencyTraversalNoSuchPackageException() throws Exception {
+    // Given a package "//foo" with a target ":foo" that has a dependency on a non-existent target
+    // "//bar:bar" in a non-existent package "//bar",
+    createFooWithDependencyOnMissingBarPackage();
+
+    // Given a target pattern sequence consisting of a single-target pattern for "//foo",
+    ImmutableList<String> patternSequence = ImmutableList.of("//foo");
+
+    // When PrepareDepsOfPatternsFunction completes evaluation,
+    WalkableGraph walkableGraph =
+        getGraphFromPatternsEvaluation(patternSequence, /*successExpected=*/ false);
+
+    // Then the graph contains an entry for ":foo",
+    assertValidValue(
+        walkableGraph,
+        getKeyForLabel(Label.create("foo", "foo")),
+        /*expectTransitiveException=*/ true);
+
+    // And an entry with a NoSuchPackageException for "//bar:bar",
+    Exception e = assertException(walkableGraph, getKeyForLabel(Label.create("bar", "bar")));
+    assertThat(e).isInstanceOf(NoSuchPackageException.class);
+  }
+
+  public void testDependencyTraversalNoSuchTargetException() throws Exception {
+    // Given a package "//foo" with a target ":foo" that has a dependency on a non-existent target
+    // "//bar:bar" in an existing package "//bar",
+    createFooWithDependencyOnBarPackageWithMissingTarget();
+
+    // Given a target pattern sequence consisting of a single-target pattern for "//foo",
+    ImmutableList<String> patternSequence = ImmutableList.of("//foo");
+
+    // When PrepareDepsOfPatternsFunction completes evaluation,
+    WalkableGraph walkableGraph =
+        getGraphFromPatternsEvaluation(patternSequence, /*successExpected=*/ false);
+
+    // Then the graph contains an entry for ":foo" which has both a value and an exception,
+    assertValidValue(
+        walkableGraph,
+        getKeyForLabel(Label.create("foo", "foo")),
+        /*expectTransitiveException=*/ true);
+
+    // And an entry with a NoSuchTargetException for "//bar:bar",
+    Exception e = assertException(walkableGraph, getKeyForLabel(Label.create("bar", "bar")));
+    assertThat(e).isInstanceOf(NoSuchTargetException.class);
+  }
+
+  public void testParsingProblemsKeepGoing() throws Exception {
+    parsingProblem(/*keepGoing=*/ true);
+  }
+
+  /**
+   * PrepareDepsOfPatternsFunction always keeps going despite any target pattern parsing errors,
+   * in keeping with the original behavior of {@link SkyframeExecutor#prepareAndGet}, which
+   * always used {@code keepGoing=true} during target pattern parsing because it was responsible
+   * for ensuring that queries had a complete graph to work on.
+   */
+  public void testParsingProblemsNoKeepGoing() throws Exception {
+    parsingProblem(/*keepGoing=*/ false);
+  }
+
+  private void parsingProblem(boolean keepGoing) throws Exception {
+    // Given a package "//foo" with target rule ":foo",
+    createFooAndFoo2(/*dependent=*/ false);
+
+    // Given a target pattern sequence consisting of a pattern with parsing problems followed by
+    // a legit target pattern,
+    String bogusPattern = "//foo/....";
+    ImmutableList<String> patternSequence = ImmutableList.of(bogusPattern, "//foo:foo");
+
+    // When PrepareDepsOfPatternsFunction runs in the selected keep-going mode,
+    WalkableGraph walkableGraph =
+        getGraphFromPatternsEvaluation(
+            patternSequence, /*successExpected=*/ true, /*keepGoing=*/ keepGoing);
+
+    // Then it skips evaluation of the malformed target pattern, but logs about it,
+    assertContainsEvent("Skipping '" + bogusPattern + "': ");
+
+    // And then the graph contains a value for the legit target pattern's target "//foo:foo".
+    assertTrue(walkableGraph.exists(getKeyForLabel(Label.create("foo", "foo"))));
+  }
+
+  // Helpers:
+
+  private WalkableGraph getGraphFromPatternsEvaluation(
+      ImmutableList<String> patternSequence, boolean successExpected) throws InterruptedException {
+    return getGraphFromPatternsEvaluation(patternSequence, successExpected, /*keepGoing=*/ true);
+  }
+
+  private WalkableGraph getGraphFromPatternsEvaluation(
+      ImmutableList<String> patternSequence, boolean successExpected, boolean keepGoing)
+      throws InterruptedException {
+    SkyKey independentTarget = PrepareDepsOfPatternsValue.key(patternSequence, "");
+    ImmutableList<SkyKey> singletonTargetPattern = ImmutableList.of(independentTarget);
+
+    // When PrepareDepsOfPatternsFunction completes evaluation,
+    EvaluationResult<SkyValue> evaluationResult =
+        getSkyframeExecutor()
+            .getDriverForTesting()
+            .evaluate(singletonTargetPattern, keepGoing, LOADING_PHASE_THREADS, eventCollector);
+
+    if (successExpected) {
+      // Then the evaluation completed successfully.
+      assertFalse(evaluationResult.hasError());
+    } else {
+      // Then the evaluation resulted in some errors.
+      assertTrue(evaluationResult.hasError());
+    }
+
+    return Preconditions.checkNotNull(evaluationResult.getWalkableGraph());
+  }
+
+  private void createFooAndFoo2(boolean dependent) throws IOException {
+    String dependencyIfAny = dependent ? "srcs = [':foo2']," : "";
+    scratch.file(
+        "foo/BUILD",
+        "genrule(name = 'foo',",
+        dependencyIfAny,
+        "    outs = ['out.txt'],",
+        "    cmd = 'touch $@')",
+        "genrule(name = 'foo2',",
+        "    outs = ['out2.txt'],",
+        "    cmd = 'touch $@')");
+  }
+
+  private void createFooWithDependencyOnMissingBarPackage() throws IOException {
+    scratch.file(
+        "foo/BUILD",
+        "genrule(name = 'foo',",
+        "    srcs = ['//bar:bar'],",
+        "    outs = ['out.txt'],",
+        "    cmd = 'touch $@')");
+  }
+
+  private void createFooWithDependencyOnBarPackageWithMissingTarget() throws IOException {
+    scratch.file(
+        "foo/BUILD",
+        "genrule(name = 'foo',",
+        "    srcs = ['//bar:bar'],",
+        "    outs = ['out.txt'],",
+        "    cmd = 'touch $@')");
+    scratch.file("bar/BUILD");
+  }
+
+  private void assertValidValue(WalkableGraph graph, SkyKey key) {
+    assertValidValue(graph, key, /*expectTransitiveException=*/ false);
+  }
+
+  /**
+   * A node in the walkable graph may have both a value and an exception. This happens when one
+   * of a node's transitive dependencies throws an exception, but its parent recovers from it.
+   */
+  private void assertValidValue(
+      WalkableGraph graph, SkyKey key, boolean expectTransitiveException) {
+    assertTrue(graph.exists(key));
+    assertNotNull(graph.getValue(key));
+    if (expectTransitiveException) {
+      assertNotNull(graph.getException(key));
+    } else {
+      assertNull(graph.getException(key));
+    }
+  }
+
+  private Exception assertException(WalkableGraph graph, SkyKey key) {
+    assertTrue(graph.exists(key));
+    assertNull(graph.getValue(key));
+    Exception exception = graph.getException(key);
+    assertNotNull(exception);
+    return exception;
+  }
+}