Open source some skyframe/bazel tests.
--
MOS_MIGRATED_REVID=106308990
diff --git a/src/test/java/com/google/devtools/build/lib/skyframe/RecursivePkgFunctionTest.java b/src/test/java/com/google/devtools/build/lib/skyframe/RecursivePkgFunctionTest.java
new file mode 100644
index 0000000..ce2b84d
--- /dev/null
+++ b/src/test/java/com/google/devtools/build/lib/skyframe/RecursivePkgFunctionTest.java
@@ -0,0 +1,169 @@
+// 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.common.collect.ImmutableSet;
+import com.google.common.collect.Iterables;
+import com.google.devtools.build.lib.analysis.util.BuildViewTestCase;
+import com.google.devtools.build.lib.cmdline.PackageIdentifier;
+import com.google.devtools.build.lib.vfs.Path;
+import com.google.devtools.build.lib.vfs.PathFragment;
+import com.google.devtools.build.lib.vfs.RootedPath;
+import com.google.devtools.build.skyframe.BuildDriver;
+import com.google.devtools.build.skyframe.EvaluationResult;
+import com.google.devtools.build.skyframe.SkyKey;
+import com.google.devtools.build.skyframe.WalkableGraph;
+
+/**
+ * Tests for {@link RecursivePkgFunction}. Unfortunately, we can't directly test
+ * RecursivePkgFunction as it uses PackageValues, and PackageFunction uses legacy stuff that
+ * isn't easily mockable. So our testing strategy is to make hacky calls to
+ * SequencedSkyframeExecutor.
+ *
+ * <p>Target parsing tests already cover most of the behavior of RecursivePkgFunction, but there
+ * are a couple of corner cases we need to test directly.
+ */
+public class RecursivePkgFunctionTest extends BuildViewTestCase {
+
+ private SkyframeExecutor skyframeExecutor;
+
+ @Override
+ protected void setUp() throws Exception {
+ super.setUp();
+ skyframeExecutor = getSkyframeExecutor();
+ }
+
+ private SkyKey buildRecursivePkgKey(
+ Path root, PathFragment rootRelativePath, ImmutableSet<PathFragment> excludedPaths) {
+ RootedPath rootedPath = RootedPath.toRootedPath(root, rootRelativePath);
+ return RecursivePkgValue.key(
+ PackageIdentifier.DEFAULT_REPOSITORY_NAME, rootedPath, excludedPaths);
+ }
+
+ private RecursivePkgValue buildRecursivePkgValue(Path root, PathFragment rootRelativePath)
+ throws Exception {
+ return buildRecursivePkgValue(root, rootRelativePath, ImmutableSet.<PathFragment>of());
+ }
+
+ private RecursivePkgValue buildRecursivePkgValue(
+ Path root, PathFragment rootRelativePath, ImmutableSet<PathFragment> excludedPaths)
+ throws Exception {
+ SkyKey key = buildRecursivePkgKey(root, rootRelativePath, excludedPaths);
+ return getEvaluationResult(key).get(key);
+ }
+
+ private EvaluationResult<RecursivePkgValue> getEvaluationResult(SkyKey key)
+ throws InterruptedException {
+ BuildDriver driver = skyframeExecutor.getDriverForTesting();
+ EvaluationResult<RecursivePkgValue> evaluationResult =
+ driver.evaluate(
+ ImmutableList.of(key),
+ /*keepGoing=*/ false,
+ SequencedSkyframeExecutor.DEFAULT_THREAD_COUNT,
+ reporter);
+ Preconditions.checkState(!evaluationResult.hasError());
+ return evaluationResult;
+ }
+
+ public void testStartingAtBuildFile() throws Exception {
+ scratch.file("a/b/c/BUILD");
+ RecursivePkgValue value =
+ buildRecursivePkgValue(rootDirectory, new PathFragment("a/b/c/BUILD"));
+ assertTrue(value.getPackages().isEmpty());
+ }
+
+ public void testPackagesUnderMultipleRoots() throws Exception {
+ Path root1 = rootDirectory.getRelative("root1");
+ Path root2 = rootDirectory.getRelative("root2");
+ scratch.file(root1 + "/WORKSPACE");
+ scratch.file(root2 + "/WORKSPACE");
+ scratch.file(root1 + "/a/BUILD");
+ scratch.file(root2 + "/a/b/BUILD");
+ setPackageCacheOptions("--package_path=" + "root1" + ":" + "root2");
+
+ RecursivePkgValue valueForRoot1 = buildRecursivePkgValue(root1, new PathFragment("a"));
+ String root1Pkg = Iterables.getOnlyElement(valueForRoot1.getPackages());
+ assertEquals(root1Pkg, "a");
+
+ RecursivePkgValue valueForRoot2 = buildRecursivePkgValue(root2, new PathFragment("a"));
+ String root2Pkg = Iterables.getOnlyElement(valueForRoot2.getPackages());
+ assertEquals(root2Pkg, "a/b");
+ }
+
+ public void testSubdirectoryExclusion() throws Exception {
+ // Given a package "a" with two packages below it, "a/b" and "a/c",
+ scratch.file("a/BUILD");
+ scratch.file("a/b/BUILD");
+ scratch.file("a/c/BUILD");
+
+ // When the top package is evaluated for recursive package values, and "a/b" is excluded,
+ PathFragment excludedPathFragment = new PathFragment("a/b");
+ SkyKey key =
+ buildRecursivePkgKey(
+ rootDirectory, new PathFragment("a"), ImmutableSet.of(excludedPathFragment));
+ EvaluationResult<RecursivePkgValue> evaluationResult = getEvaluationResult(key);
+ RecursivePkgValue value = evaluationResult.get(key);
+
+ // Then the package corresponding to "a/b" is not present in the result,
+ assertThat(value.getPackages()).doesNotContain("a/b");
+
+ // And the "a" package and "a/c" package are.
+ assertThat(value.getPackages()).contains("a");
+ assertThat(value.getPackages()).contains("a/c");
+
+ // Also, the computation graph does not contain a cached value for "a/b".
+ WalkableGraph graph = Preconditions.checkNotNull(evaluationResult.getWalkableGraph());
+ assertFalse(
+ graph.exists(
+ buildRecursivePkgKey(
+ rootDirectory, excludedPathFragment, ImmutableSet.<PathFragment>of())));
+
+ // And the computation graph does contain a cached value for "a/c" with the empty set excluded,
+ // because that key was evaluated.
+ assertTrue(
+ graph.exists(
+ buildRecursivePkgKey(
+ rootDirectory, new PathFragment("a/c"), ImmutableSet.<PathFragment>of())));
+ }
+
+ public void testExcludedSubdirectoryGettingPassedDown() throws Exception {
+ // Given a package "a" with two packages below a directory below it, "a/b/c" and "a/b/d",
+ scratch.file("a/BUILD");
+ scratch.file("a/b/c/BUILD");
+ scratch.file("a/b/d/BUILD");
+
+ // When the top package is evaluated for recursive package values, and "a/b/c" is excluded,
+ ImmutableSet<PathFragment> excludedPaths = ImmutableSet.of(new PathFragment("a/b/c"));
+ SkyKey key = buildRecursivePkgKey(rootDirectory, new PathFragment("a"), excludedPaths);
+ EvaluationResult<RecursivePkgValue> evaluationResult = getEvaluationResult(key);
+ RecursivePkgValue value = evaluationResult.get(key);
+
+ // Then the package corresponding to the excluded subdirectory is not present in the result,
+ assertThat(value.getPackages()).doesNotContain("a/b/c");
+
+ // And the top package and other subsubdirectory package are.
+ assertThat(value.getPackages()).contains("a");
+ assertThat(value.getPackages()).contains("a/b/d");
+
+ // Also, the computation graph contains a cached value for "a/b" with "a/b/c" excluded, because
+ // "a/b/c" does live underneath "a/b".
+ WalkableGraph graph = Preconditions.checkNotNull(evaluationResult.getWalkableGraph());
+ assertTrue(
+ graph.exists(buildRecursivePkgKey(rootDirectory, new PathFragment("a/b"), excludedPaths)));
+ }
+}