// 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 static com.google.devtools.build.skyframe.EvaluationResultSubjectFactory.assertThatEvaluationResult;
import static org.junit.Assert.assertThrows;
import static org.junit.Assert.fail;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.doAnswer;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;

import com.google.common.base.Predicates;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.Maps;
import com.google.common.collect.Sets;
import com.google.devtools.build.lib.actions.FileStateValue;
import com.google.devtools.build.lib.analysis.ConfiguredRuleClassProvider;
import com.google.devtools.build.lib.analysis.util.BuildViewTestCase;
import com.google.devtools.build.lib.clock.BlazeClock;
import com.google.devtools.build.lib.cmdline.Label;
import com.google.devtools.build.lib.cmdline.PackageIdentifier;
import com.google.devtools.build.lib.events.Event;
import com.google.devtools.build.lib.events.ExtendedEventHandler;
import com.google.devtools.build.lib.packages.BazelModuleContext;
import com.google.devtools.build.lib.packages.BuildFileNotFoundException;
import com.google.devtools.build.lib.packages.ConstantRuleVisibility;
import com.google.devtools.build.lib.packages.NoSuchPackageException;
import com.google.devtools.build.lib.packages.NoSuchTargetException;
import com.google.devtools.build.lib.packages.Package;
import com.google.devtools.build.lib.packages.PackageOverheadEstimator;
import com.google.devtools.build.lib.packages.PackageValidator;
import com.google.devtools.build.lib.packages.PackageValidator.InvalidPackageException;
import com.google.devtools.build.lib.packages.semantics.BuildLanguageOptions;
import com.google.devtools.build.lib.pkgcache.PackageOptions;
import com.google.devtools.build.lib.pkgcache.PathPackageLocator;
import com.google.devtools.build.lib.rules.repository.RepositoryDelegatorFunction;
import com.google.devtools.build.lib.server.FailureDetails.PackageLoading;
import com.google.devtools.build.lib.skyframe.util.SkyframeExecutorTestUtils;
import com.google.devtools.build.lib.testutil.ManualClock;
import com.google.devtools.build.lib.testutil.TestRuleClassProvider;
import com.google.devtools.build.lib.util.DetailedExitCode;
import com.google.devtools.build.lib.util.ExitCode;
import com.google.devtools.build.lib.util.Pair;
import com.google.devtools.build.lib.util.io.TimestampGranularityMonitor;
import com.google.devtools.build.lib.vfs.DigestHashFunction;
import com.google.devtools.build.lib.vfs.Dirent;
import com.google.devtools.build.lib.vfs.FileStatus;
import com.google.devtools.build.lib.vfs.FileSystem;
import com.google.devtools.build.lib.vfs.FileSystemUtils;
import com.google.devtools.build.lib.vfs.ModifiedFileSet;
import com.google.devtools.build.lib.vfs.Path;
import com.google.devtools.build.lib.vfs.PathFragment;
import com.google.devtools.build.lib.vfs.Root;
import com.google.devtools.build.lib.vfs.RootedPath;
import com.google.devtools.build.lib.vfs.Symlinks;
import com.google.devtools.build.lib.vfs.SyscallCache;
import com.google.devtools.build.lib.vfs.inmemoryfs.InMemoryFileSystem;
import com.google.devtools.build.skyframe.EvaluationResult;
import com.google.devtools.build.skyframe.RecordingDifferencer;
import com.google.devtools.build.skyframe.SkyKey;
import com.google.devtools.build.skyframe.SkyValue;
import com.google.devtools.common.options.Options;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.OptionalLong;
import java.util.Set;
import java.util.UUID;
import java.util.concurrent.atomic.AtomicInteger;
import javax.annotation.Nullable;
import net.starlark.java.eval.Module;
import net.starlark.java.eval.StarlarkInt;
import org.junit.Rule;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.JUnit4;
import org.mockito.Mock;
import org.mockito.junit.MockitoJUnit;
import org.mockito.junit.MockitoRule;

/**
 * Unit tests of specific functionality of PackageFunction. Note that it's already tested indirectly
 * in several other places.
 */
@RunWith(JUnit4.class)
public class PackageFunctionTest extends BuildViewTestCase {

  @Rule public final MockitoRule mockito = MockitoJUnit.rule();

  @Mock private PackageValidator mockPackageValidator;

  @Mock private PackageOverheadEstimator mockPackageOverheadEstimator;

  private CustomInMemoryFs fs = new CustomInMemoryFs(new ManualClock());

  private void preparePackageLoading(Path... roots) {
    preparePackageLoadingWithCustomStarklarkSemanticsOptions(
        Options.getDefaults(BuildLanguageOptions.class), roots);
  }

  private void preparePackageLoadingWithCustomStarklarkSemanticsOptions(
      BuildLanguageOptions buildLanguageOptions, Path... roots) {
    PackageOptions packageOptions = Options.getDefaults(PackageOptions.class);
    packageOptions.defaultVisibility = ConstantRuleVisibility.PUBLIC;
    packageOptions.showLoadingProgress = true;
    packageOptions.globbingThreads = 7;
    getSkyframeExecutor()
        .preparePackageLoading(
            new PathPackageLocator(
                outputBase,
                Arrays.stream(roots).map(Root::fromPath).collect(ImmutableList.toImmutableList()),
                BazelSkyframeExecutorConstants.BUILD_FILES_BY_PRIORITY),
            packageOptions,
            buildLanguageOptions,
            UUID.randomUUID(),
            ImmutableMap.<String, String>of(),
            new TimestampGranularityMonitor(BlazeClock.instance()));
    skyframeExecutor.setActionEnv(ImmutableMap.<String, String>of());
  }

  @Override
  protected FileSystem createFileSystem() {
    return fs;
  }

  @Override
  protected PackageValidator getPackageValidator() {
    return mockPackageValidator;
  }

  @Override
  protected PackageOverheadEstimator getPackageOverheadEstimator() {
    return mockPackageOverheadEstimator;
  }

  private Package validPackageWithoutErrors(SkyKey skyKey) throws InterruptedException {
    return validPackageInternal(skyKey, /*checkPackageError=*/ true);
  }

  private Package validPackage(SkyKey skyKey) throws InterruptedException {
    return validPackageInternal(skyKey, /*checkPackageError=*/ false);
  }

  private Package validPackageInternal(SkyKey skyKey, boolean checkPackageError)
      throws InterruptedException {
    SkyframeExecutor skyframeExecutor = getSkyframeExecutor();
    skyframeExecutor.injectExtraPrecomputedValues(
        ImmutableList.of(
            PrecomputedValue.injected(
                RepositoryDelegatorFunction.RESOLVED_FILE_INSTEAD_OF_WORKSPACE, Optional.empty()),
            PrecomputedValue.injected(RepositoryDelegatorFunction.ENABLE_BZLMOD, false)));
    EvaluationResult<PackageValue> result =
        SkyframeExecutorTestUtils.evaluate(
            skyframeExecutor, skyKey, /*keepGoing=*/ false, reporter);
    if (result.hasError()) {
      fail(result.getError(skyKey).getException().getMessage());
    }
    PackageValue value = result.get(skyKey);
    if (checkPackageError) {
      assertThat(value.getPackage().containsErrors()).isFalse();
    }
    return value.getPackage();
  }

  private Exception evaluatePackageToException(String pkg) throws Exception {
    return evaluatePackageToException(pkg, /*keepGoing=*/ false);
  }

  /**
   * Helper that evaluates the given package and returns the expected exception.
   *
   * <p>Disables the failFastHandler as a side-effect.
   */
  private Exception evaluatePackageToException(String pkg, boolean keepGoing) throws Exception {
    reporter.removeHandler(failFastHandler);

    SkyKey skyKey = PackageValue.key(PackageIdentifier.parse(pkg));
    EvaluationResult<PackageValue> result =
        SkyframeExecutorTestUtils.evaluate(getSkyframeExecutor(), skyKey, keepGoing, reporter);
    assertThat(result.hasError()).isTrue();
    return result.getError(skyKey).getException();
  }

  @Test
  public void testValidPackage() throws Exception {
    scratch.file("pkg/BUILD");
    validPackageWithoutErrors(PackageValue.key(PackageIdentifier.parse("@//pkg")));
  }

  @Test
  public void testInvalidPackage() throws Exception {
    scratch.file("pkg/BUILD", "sh_library(name='foo', srcs=['foo.sh'])");
    scratch.file("pkg/foo.sh");

    doAnswer(
            inv -> {
              Package pkg = inv.getArgument(0, Package.class);
              if (pkg.getName().equals("pkg")) {
                inv.getArgument(2, ExtendedEventHandler.class).handle(Event.warn("warning event"));
                throw new InvalidPackageException(pkg.getPackageIdentifier(), "no good");
              }
              return null;
            })
        .when(mockPackageValidator)
        .validate(any(Package.class), any(OptionalLong.class), any(ExtendedEventHandler.class));

    invalidatePackages();

    Exception ex = evaluatePackageToException("@//pkg");
    assertThat(ex).isInstanceOf(InvalidPackageException.class);
    assertThat(ex).hasMessageThat().contains("no such package 'pkg': no good");
    assertContainsEvent("warning event");
  }

  @Test
  public void testPackageOverheadPassedToValidationLogic() throws Exception {
    scratch.file("pkg/BUILD", "# Contents doesn't matter, it's all fake");

    when(mockPackageOverheadEstimator.estimatePackageOverhead(any(Package.class)))
        .thenReturn(OptionalLong.of(42));

    invalidatePackages();

    SkyframeExecutorTestUtils.evaluate(
        getSkyframeExecutor(),
        PackageValue.key(PackageIdentifier.parse("@//pkg")),
        /*keepGoing=*/ false,
        reporter);

    verify(mockPackageValidator)
        .validate(any(Package.class), eq(OptionalLong.of(42)), any(ExtendedEventHandler.class));
  }

  @Test
  public void testSkyframeExecutorClearedPackagesResultsInReload() throws Exception {
    scratch.file("pkg/BUILD", "sh_library(name='foo', srcs=['foo.sh'])");
    scratch.file("pkg/foo.sh");

    invalidatePackages();

    // Use number of times the package was validated as a proxy for number of times it was loaded.
    AtomicInteger validationCount = new AtomicInteger();
    doAnswer(
            inv -> {
              if (inv.getArgument(0, Package.class).getName().equals("pkg")) {
                validationCount.incrementAndGet();
              }
              return null;
            })
        .when(mockPackageValidator)
        .validate(any(Package.class), any(OptionalLong.class), any(ExtendedEventHandler.class));

    SkyKey skyKey = PackageValue.key(PackageIdentifier.parse("@//pkg"));
    EvaluationResult<PackageValue> result1 =
        SkyframeExecutorTestUtils.evaluate(
            getSkyframeExecutor(), skyKey, /*keepGoing=*/ false, reporter);
    assertThatEvaluationResult(result1).hasNoError();

    skyframeExecutor.clearLoadedPackages();

    EvaluationResult<PackageValue> result2 =
        SkyframeExecutorTestUtils.evaluate(
            getSkyframeExecutor(), skyKey, /*keepGoing=*/ false, reporter);
    assertThatEvaluationResult(result2).hasNoError();

    assertThat(validationCount.get()).isEqualTo(2);
  }

  @Test
  public void testPropagatesFilesystemInconsistencies() throws Exception {
    RecordingDifferencer differencer = getSkyframeExecutor().getDifferencerForTesting();
    Root pkgRoot = getSkyframeExecutor().getPathEntries().get(0);
    Path fooBuildFile = scratch.file("foo/BUILD");
    Path fooDir = fooBuildFile.getParentDirectory();

    // Our custom filesystem says that fooDir is neither a file nor directory nor symlink
    FileStatus inconsistentFileStatus =
        new FileStatus() {
          @Override
          public boolean isFile() {
            return false;
          }

          @Override
          public boolean isDirectory() {
            return false;
          }

          @Override
          public boolean isSymbolicLink() {
            return false;
          }

          @Override
          public boolean isSpecialFile() {
            return false;
          }

          @Override
          public long getSize() throws IOException {
            return 0;
          }

          @Override
          public long getLastModifiedTime() throws IOException {
            return 0;
          }

          @Override
          public long getLastChangeTime() throws IOException {
            return 0;
          }

          @Override
          public long getNodeId() throws IOException {
            return 0;
          }
        };

    fs.stubStat(fooBuildFile, inconsistentFileStatus);
    RootedPath pkgRootedPath = RootedPath.toRootedPath(pkgRoot, fooDir);
    SkyValue fooDirValue = FileStateValue.create(pkgRootedPath, SyscallCache.NO_CACHE, tsgm);
    differencer.inject(ImmutableMap.of(FileStateValue.key(pkgRootedPath), fooDirValue));

    Exception ex = evaluatePackageToException("@//foo");
    String msg = ex.getMessage();
    assertThat(msg).contains("Inconsistent filesystem operations");
    assertThat(msg)
        .contains(
            "according to stat, existing path /workspace/foo/BUILD is neither"
                + " a file nor directory nor symlink.");
    assertDetailedExitCode(
        ex,
        PackageLoading.Code.PERSISTENT_INCONSISTENT_FILESYSTEM_ERROR,
        ExitCode.LOCAL_ENVIRONMENTAL_ERROR);
  }

  @Test
  public void testPropagatesFilesystemInconsistencies_globbing() throws Exception {
    RecordingDifferencer differencer = getSkyframeExecutor().getDifferencerForTesting();
    Root pkgRoot = getSkyframeExecutor().getPathEntries().get(0);
    scratch.file(
        "foo/BUILD",
        "sh_library(name = 'foo', srcs = glob(['bar/**/baz.sh']))",
        "x = 1//0" // causes 'foo' to be marked in error
        );
    Path bazFile = scratch.file("foo/bar/baz/baz.sh");
    Path bazDir = bazFile.getParentDirectory();
    Path barDir = bazDir.getParentDirectory();

    // Our custom filesystem says "foo/bar/baz" does not exist but it also says that "foo/bar"
    // has a child directory "baz".
    fs.stubStat(bazDir, null);
    RootedPath barDirRootedPath = RootedPath.toRootedPath(pkgRoot, barDir);
    differencer.inject(
        ImmutableMap.of(
            DirectoryListingStateValue.key(barDirRootedPath),
            DirectoryListingStateValue.create(
                ImmutableList.of(new Dirent("baz", Dirent.Type.DIRECTORY)))));

    Exception ex = evaluatePackageToException("@//foo");
    String msg = ex.getMessage();
    assertThat(msg).contains("Inconsistent filesystem operations");
    assertThat(msg).contains("/workspace/foo/bar/baz is no longer an existing directory");
    assertDetailedExitCode(
        ex,
        PackageLoading.Code.PERSISTENT_INCONSISTENT_FILESYSTEM_ERROR,
        ExitCode.LOCAL_ENVIRONMENTAL_ERROR);
  }

  /** Regression test for unexpected exception type from PackageValue. */
  @Test
  public void testDiscrepancyBetweenGlobbingErrors() throws Exception {
    Path fooBuildFile =
        scratch.file("foo/BUILD", "sh_library(name = 'foo', srcs = glob(['bar/*.sh']))");
    Path fooDir = fooBuildFile.getParentDirectory();
    Path barDir = fooDir.getRelative("bar");
    scratch.file("foo/bar/baz.sh");
    fs.scheduleMakeUnreadableAfterReaddir(barDir);

    Exception ex =
        evaluatePackageToException(
            "@//foo",
            // Use --keep_going, not --nokeep_going, semantics so as to exercise the situation we
            // want to exercise.
            //
            // In --nokeep_going semantics, the GlobValue node's error would halt normal evaluation
            // and trigger error bubbling. Then, during error bubbling we would freshly compute the
            // PackageValue node again, meaning we would do non-Skyframe globbing except this time
            // non-Skyframe globbing would encounter the io error, meaning there actually wouldn't
            // be a discrepancy.
            /*keepGoing=*/ true);
    String msg = ex.getMessage();
    assertThat(msg).contains("Inconsistent filesystem operations");
    assertThat(msg).contains("Encountered error '/workspace/foo/bar (Permission denied)'");
    assertDetailedExitCode(
        ex,
        PackageLoading.Code.TRANSIENT_INCONSISTENT_FILESYSTEM_ERROR,
        ExitCode.LOCAL_ENVIRONMENTAL_ERROR);
  }

  @SuppressWarnings("unchecked") // Cast of srcs attribute to Iterable<Label>.
  @Test
  public void testGlobOrderStable() throws Exception {
    scratch.file("foo/BUILD", "sh_library(name = 'foo', srcs = glob(['**/*.txt']))");
    scratch.file("foo/b.txt");
    scratch.file("foo/c/c.txt");
    preparePackageLoading(rootDirectory);
    SkyKey skyKey = PackageValue.key(PackageIdentifier.parse("@//foo"));
    Package pkg = validPackageWithoutErrors(skyKey);
    assertThat((Iterable<Label>) pkg.getTarget("foo").getAssociatedRule().getAttr("srcs"))
        .containsExactly(
            Label.parseAbsoluteUnchecked("//foo:b.txt"),
            Label.parseAbsoluteUnchecked("//foo:c/c.txt"))
        .inOrder();
    scratch.file("foo/d.txt");
    getSkyframeExecutor()
        .invalidateFilesUnderPathForTesting(
            reporter,
            ModifiedFileSet.builder().modify(PathFragment.create("foo/d.txt")).build(),
            Root.fromPath(rootDirectory));
    pkg = validPackageWithoutErrors(skyKey);
    assertThat((Iterable<Label>) pkg.getTarget("foo").getAssociatedRule().getAttr("srcs"))
        .containsExactly(
            Label.parseAbsoluteUnchecked("//foo:b.txt"),
            Label.parseAbsoluteUnchecked("//foo:c/c.txt"),
            Label.parseAbsoluteUnchecked("//foo:d.txt"))
        .inOrder();
  }

  @Test
  public void testGlobOrderStableWithNonSkyframeAndSkyframeComponents() throws Exception {
    scratch.file("foo/BUILD", "sh_library(name = 'foo', srcs = glob(['*.txt']))");
    scratch.file("foo/b.txt");
    scratch.file("foo/a.config");
    preparePackageLoading(rootDirectory);
    SkyKey skyKey = PackageValue.key(PackageIdentifier.parse("@//foo"));
    assertSrcs(validPackageWithoutErrors(skyKey), "foo", "//foo:b.txt");
    scratch.overwriteFile(
        "foo/BUILD", "sh_library(name = 'foo', srcs = glob(['*.txt', '*.config']))");
    getSkyframeExecutor()
        .invalidateFilesUnderPathForTesting(
            reporter,
            ModifiedFileSet.builder().modify(PathFragment.create("foo/BUILD")).build(),
            Root.fromPath(rootDirectory));
    assertSrcs(validPackageWithoutErrors(skyKey), "foo", "//foo:a.config", "//foo:b.txt");
    scratch.overwriteFile(
        "foo/BUILD", "sh_library(name = 'foo', srcs = glob(['*.txt', '*.config'])) # comment");
    getSkyframeExecutor()
        .invalidateFilesUnderPathForTesting(
            reporter,
            ModifiedFileSet.builder().modify(PathFragment.create("foo/BUILD")).build(),
            Root.fromPath(rootDirectory));
    assertSrcs(validPackageWithoutErrors(skyKey), "foo", "//foo:a.config", "//foo:b.txt");
    getSkyframeExecutor().resetEvaluator();
    PackageOptions packageOptions = Options.getDefaults(PackageOptions.class);
    packageOptions.defaultVisibility = ConstantRuleVisibility.PUBLIC;
    packageOptions.showLoadingProgress = true;
    packageOptions.globbingThreads = 7;
    getSkyframeExecutor()
        .preparePackageLoading(
            new PathPackageLocator(
                outputBase,
                ImmutableList.of(Root.fromPath(rootDirectory)),
                BazelSkyframeExecutorConstants.BUILD_FILES_BY_PRIORITY),
            packageOptions,
            Options.getDefaults(BuildLanguageOptions.class),
            UUID.randomUUID(),
            ImmutableMap.<String, String>of(),
            tsgm);
    getSkyframeExecutor().setActionEnv(ImmutableMap.<String, String>of());
    assertSrcs(validPackageWithoutErrors(skyKey), "foo", "//foo:a.config", "//foo:b.txt");
  }

  @Test
  public void globEscapesAt() throws Exception {
    scratch.file("foo/BUILD", "filegroup(name = 'foo', srcs = glob(['*.txt']))");
    scratch.file("foo/@f.txt");
    preparePackageLoading(rootDirectory);
    SkyKey skyKey = PackageValue.key(PackageIdentifier.parse("@//foo"));
    assertSrcs(validPackageWithoutErrors(skyKey), "foo", "//foo:@f.txt");

    scratch.overwriteFile("foo/BUILD", "filegroup(name = 'foo', srcs = glob(['*.txt'])) # comment");
    getSkyframeExecutor()
        .invalidateFilesUnderPathForTesting(
            reporter,
            ModifiedFileSet.builder().modify(PathFragment.create("foo/BUILD")).build(),
            Root.fromPath(rootDirectory));
    assertSrcs(validPackageWithoutErrors(skyKey), "foo", "//foo:@f.txt");
  }

  /**
   * Tests that a symlink to a file outside of the package root is handled consistently. If the
   * default behavior of Bazel was changed from {@code
   * ExternalFileAction#DEPEND_ON_EXTERNAL_PKG_FOR_EXTERNAL_REPO_PATHS} to {@code
   * ExternalFileAction#ASSUME_NON_EXISTENT_AND_IMMUTABLE_FOR_EXTERNAL_PATHS} then foo/link.sh
   * should no longer appear in the srcs of //foo:foo. However, either way the srcs should be the
   * same independent of the evaluation being incremental or clean.
   */
  @Test
  public void testGlobWithExternalSymlink() throws Exception {
    scratch.file(
        "foo/BUILD",
        "sh_library(name = 'foo', srcs = glob(['*.sh']))",
        "sh_library(name = 'bar', srcs = glob(['link.sh']))",
        "sh_library(name = 'baz', srcs = glob(['subdir_link/*.txt']))");
    scratch.file("foo/ordinary.sh");
    Path externalTarget = scratch.file("../ops/target.txt");
    FileSystemUtils.ensureSymbolicLink(scratch.resolve("foo/link.sh"), externalTarget);
    FileSystemUtils.ensureSymbolicLink(
        scratch.resolve("foo/subdir_link"), externalTarget.getParentDirectory());
    preparePackageLoading(rootDirectory);
    SkyKey fooKey = PackageValue.key(PackageIdentifier.parse("@//foo"));
    Package fooPkg = validPackageWithoutErrors(fooKey);
    assertSrcs(fooPkg, "foo", "//foo:link.sh", "//foo:ordinary.sh");
    assertSrcs(fooPkg, "bar", "//foo:link.sh");
    assertSrcs(fooPkg, "baz", "//foo:subdir_link/target.txt");
    scratch.overwriteFile(
        "foo/BUILD",
        "sh_library(name = 'foo', srcs = glob(['*.sh'])) #comment",
        "sh_library(name = 'bar', srcs = glob(['link.sh']))",
        "sh_library(name = 'baz', srcs = glob(['subdir_link/*.txt']))");
    getSkyframeExecutor()
        .invalidateFilesUnderPathForTesting(
            reporter,
            ModifiedFileSet.builder().modify(PathFragment.create("foo/BUILD")).build(),
            Root.fromPath(rootDirectory));
    Package fooPkg2 = validPackageWithoutErrors(fooKey);
    assertThat(fooPkg2).isNotEqualTo(fooPkg);
    assertSrcs(fooPkg2, "foo", "//foo:link.sh", "//foo:ordinary.sh");
    assertSrcs(fooPkg2, "bar", "//foo:link.sh");
    assertSrcs(fooPkg2, "baz", "//foo:subdir_link/target.txt");
  }

  private static void assertSrcs(Package pkg, String targetName, String... expected)
      throws NoSuchTargetException {
    List<Label> expectedLabels = new ArrayList<>();
    for (String item : expected) {
      expectedLabels.add(Label.parseAbsoluteUnchecked(item));
    }
    assertThat(getSrcs(pkg, targetName)).containsExactlyElementsIn(expectedLabels).inOrder();
  }

  @SuppressWarnings("unchecked")
  private static Iterable<Label> getSrcs(Package pkg, String targetName)
      throws NoSuchTargetException {
    return (Iterable<Label>) pkg.getTarget(targetName).getAssociatedRule().getAttr("srcs");
  }

  @Test
  public void testOneNewElementInMultipleGlob() throws Exception {
    scratch.file(
        "foo/BUILD",
        "sh_library(name = 'foo', srcs = glob(['*.sh']))",
        "sh_library(name = 'bar', srcs = glob(['*.sh', '*.txt']))");
    preparePackageLoading(rootDirectory);
    SkyKey skyKey = PackageValue.key(PackageIdentifier.parse("@//foo"));
    Package pkg = validPackageWithoutErrors(skyKey);
    scratch.file("foo/irrelevant");
    getSkyframeExecutor()
        .invalidateFilesUnderPathForTesting(
            reporter,
            ModifiedFileSet.builder().modify(PathFragment.create("foo/irrelevant")).build(),
            Root.fromPath(rootDirectory));
    assertThat(validPackageWithoutErrors(skyKey)).isSameInstanceAs(pkg);
  }

  @Test
  public void testNoNewElementInMultipleGlob() throws Exception {
    scratch.file(
        "foo/BUILD",
        "sh_library(name = 'foo', srcs = glob(['*.sh', '*.txt']))",
        "sh_library(name = 'bar', srcs = glob(['*.sh', '*.txt']))");
    preparePackageLoading(rootDirectory);
    SkyKey skyKey = PackageValue.key(PackageIdentifier.parse("@//foo"));
    Package pkg = validPackageWithoutErrors(skyKey);
    scratch.file("foo/irrelevant");
    getSkyframeExecutor()
        .invalidateFilesUnderPathForTesting(
            reporter,
            ModifiedFileSet.builder().modify(PathFragment.create("foo/irrelevant")).build(),
            Root.fromPath(rootDirectory));
    assertThat(validPackageWithoutErrors(skyKey)).isSameInstanceAs(pkg);
  }

  @Test
  public void testTransitiveStarlarkDepsStoredInPackage() throws Exception {
    scratch.file("foo/BUILD", "load('//bar:ext.bzl', 'a')");
    scratch.file("bar/BUILD");
    scratch.file("bar/ext.bzl", "load('//baz:ext.bzl', 'b')", "a = b");
    scratch.file("baz/BUILD");
    scratch.file("baz/ext.bzl", "b = 1");
    scratch.file("qux/BUILD");
    scratch.file("qux/ext.bzl", "c = 1");

    preparePackageLoading(rootDirectory);

    SkyKey skyKey = PackageValue.key(PackageIdentifier.parse("@//foo"));
    Package pkg = validPackageWithoutErrors(skyKey);
    assertThat(pkg.getStarlarkFileDependencies())
        .containsExactly(
            Label.parseAbsolute("//bar:ext.bzl", ImmutableMap.of()),
            Label.parseAbsolute("//baz:ext.bzl", ImmutableMap.of()));

    scratch.overwriteFile("bar/ext.bzl", "load('//qux:ext.bzl', 'c')", "a = c");
    getSkyframeExecutor()
        .invalidateFilesUnderPathForTesting(
            reporter,
            ModifiedFileSet.builder().modify(PathFragment.create("bar/ext.bzl")).build(),
            Root.fromPath(rootDirectory));

    pkg = validPackageWithoutErrors(skyKey);
    assertThat(pkg.getStarlarkFileDependencies())
        .containsExactly(
            Label.parseAbsolute("//bar:ext.bzl", ImmutableMap.of()),
            Label.parseAbsolute("//qux:ext.bzl", ImmutableMap.of()));
  }

  @Test
  public void testNonExistingStarlarkExtension() throws Exception {
    scratch.file("test/starlark/BUILD", "load('//test/starlark:bad_extension.bzl', 'some_symbol')");
    invalidatePackages();

    Exception ex = evaluatePackageToException("@//test/starlark");
    assertThat(ex)
        .hasMessageThat()
        .isEqualTo(
            "error loading package 'test/starlark': "
                + "cannot load '//test/starlark:bad_extension.bzl': no such file");
    assertDetailedExitCode(
        ex, PackageLoading.Code.IMPORT_STARLARK_FILE_ERROR, ExitCode.BUILD_FAILURE);
  }

  @Test
  public void testNonExistingStarlarkExtensionFromExtension() throws Exception {
    scratch.file(
        "test/starlark/extension.bzl",
        "load('//test/starlark:bad_extension.bzl', 'some_symbol')",
        "a = 'a'");
    scratch.file("test/starlark/BUILD", "load('//test/starlark:extension.bzl', 'a')");
    invalidatePackages();

    Exception ex = evaluatePackageToException("@//test/starlark");
    assertThat(ex)
        .hasMessageThat()
        .isEqualTo(
            "error loading package 'test/starlark': "
                + "at /workspace/test/starlark/extension.bzl:1:6: "
                + "cannot load '//test/starlark:bad_extension.bzl': no such file");
    assertDetailedExitCode(
        ex, PackageLoading.Code.IMPORT_STARLARK_FILE_ERROR, ExitCode.BUILD_FAILURE);
  }

  @Test
  public void testBuiltinsInjectionFailure() throws Exception {
    setBuildLanguageOptions("--experimental_builtins_bzl_path=tools/builtins_staging");
    scratch.file(
        "tools/builtins_staging/exports.bzl",
        "1 // 0  # <-- dynamic error",
        "exported_toplevels = {}",
        "exported_rules = {}",
        "exported_to_java = {}");
    scratch.file("pkg/BUILD");

    Exception ex = evaluatePackageToException("@//pkg");
    assertThat(ex)
        .hasMessageThat()
        .isEqualTo(
            "error loading package 'pkg': Internal error while loading Starlark builtins: Failed"
                + " to load builtins sources: initialization of module 'exports.bzl' (internal)"
                + " failed");
    assertDetailedExitCode(
        ex, PackageLoading.Code.BUILTINS_INJECTION_FAILURE, ExitCode.BUILD_FAILURE);
  }

  @Test
  public void testSymlinkCycleWithStarlarkExtension() throws Exception {
    Path extensionFilePath = scratch.resolve("/workspace/test/starlark/extension.bzl");
    FileSystemUtils.ensureSymbolicLink(extensionFilePath, PathFragment.create("extension.bzl"));
    scratch.file("test/starlark/BUILD", "load('//test/starlark:extension.bzl', 'a')");
    invalidatePackages();

    Exception ex = evaluatePackageToException("@//test/starlark");
    assertThat(ex)
        .hasMessageThat()
        .isEqualTo(
            "error loading package 'test/starlark': Encountered error while reading extension "
                + "file 'test/starlark/extension.bzl': Symlink cycle");
    assertDetailedExitCode(
        ex, PackageLoading.Code.IMPORT_STARLARK_FILE_ERROR, ExitCode.BUILD_FAILURE);
  }

  @Test
  public void testIOErrorLookingForSubpackageForLabelIsHandled() throws Exception {
    scratch.file(
        "foo/BUILD", //
        "sh_library(name = 'foo', srcs = ['bar/baz.sh'])");
    Path barBuildFile = scratch.file("foo/bar/BUILD");
    fs.stubStatError(barBuildFile, new IOException("nope"));

    evaluatePackageToException("@//foo");
    assertContainsEvent("nope");
  }

  @Test
  public void testLoadOK() throws Exception {
    scratch.file("p/a.bzl", "a = 1; b = 1; d = 1");
    scratch.file("p/subdir/a.bzl", "c = 1; e = 1");
    scratch.file(
        "p/BUILD",
        //
        "load(':a.bzl', 'a')",
        "load('a.bzl', 'b')",
        "load('subdir/a.bzl', 'c')",
        "load('//p:a.bzl', 'd')",
        "load('//p:subdir/a.bzl', 'e')");
    validPackageWithoutErrors(PackageValue.key(PackageIdentifier.parse("@//p")));
  }

  // See WorkspaceFileFunctionTest for tests that exercise load('@repo...').

  @Test
  public void testLoadBadLabel() throws Exception {
    scratch.file("p/BUILD", "load('this\tis not a label', 'a')");
    reporter.removeHandler(failFastHandler);
    SkyKey key = PackageValue.key(PackageIdentifier.parse("@//p"));
    SkyframeExecutorTestUtils.evaluate(skyframeExecutor, key, /*keepGoing=*/ false, reporter);
    assertContainsEvent(
        "in load statement: invalid target name 'this<?>is not a label': target names may not"
            + " contain non-printable characters");
  }

  @Test
  public void testLoadFromExternalPackage() throws Exception {
    scratch.file("p/BUILD", "load('//external:file.bzl', 'a')");
    reporter.removeHandler(failFastHandler);
    SkyKey key = PackageValue.key(PackageIdentifier.parse("@//p"));
    SkyframeExecutorTestUtils.evaluate(skyframeExecutor, key, /*keepGoing=*/ false, reporter);
    assertContainsEvent("Starlark files may not be loaded from the //external package");
  }

  @Test
  public void testLoadWithoutBzlSuffix() throws Exception {
    scratch.file("p/BUILD", "load('//p:file.starlark', 'a')");
    reporter.removeHandler(failFastHandler);
    SkyKey key = PackageValue.key(PackageIdentifier.parse("@//p"));
    SkyframeExecutorTestUtils.evaluate(skyframeExecutor, key, /*keepGoing=*/ false, reporter);
    assertContainsEvent("The label must reference a file with extension '.bzl'");
  }

  @Test
  public void testBadWorkspaceFile() throws Exception {
    Path workspacePath = scratch.overwriteFile("WORKSPACE", "junk");
    SkyKey skyKey = PackageValue.key(PackageIdentifier.createInMainRepo("external"));
    getSkyframeExecutor()
        .invalidate(
            Predicates.equalTo(
                FileStateValue.key(
                    RootedPath.toRootedPath(
                        Root.fromPath(workspacePath.getParentDirectory()),
                        PathFragment.create(workspacePath.getBaseName())))));

    reporter.removeHandler(failFastHandler);
    EvaluationResult<PackageValue> result =
        SkyframeExecutorTestUtils.evaluate(
            getSkyframeExecutor(), skyKey, /*keepGoing=*/ false, reporter);
    assertThat(result.hasError()).isFalse();
    assertThat(result.get(skyKey).getPackage().containsErrors()).isTrue();
  }

  // Regression test for the two ugly consequences of a bug where GlobFunction incorrectly matched
  // dangling symlinks.
  @Test
  public void testIncrementalSkyframeHybridGlobbingOnDanglingSymlink() throws Exception {
    Path packageDirPath =
        scratch.file("foo/BUILD", "exports_files(glob(['*.txt']))").getParentDirectory();
    scratch.file("foo/existing.txt");
    FileSystemUtils.ensureSymbolicLink(packageDirPath.getChild("dangling.txt"), "nope");

    preparePackageLoading(rootDirectory);

    SkyKey skyKey = PackageValue.key(PackageIdentifier.parse("@//foo"));
    Package pkg = validPackageWithoutErrors(skyKey);
    assertThat(pkg.containsErrors()).isFalse();
    assertThat(pkg.getTarget("existing.txt").getName()).isEqualTo("existing.txt");
    assertThrows(NoSuchTargetException.class, () -> pkg.getTarget("dangling.txt"));

    scratch.overwriteFile(
        "foo/BUILD", "exports_files(glob(['*.txt']))", "#some-irrelevant-comment");

    getSkyframeExecutor()
        .invalidateFilesUnderPathForTesting(
            reporter,
            ModifiedFileSet.builder().modify(PathFragment.create("foo/BUILD")).build(),
            Root.fromPath(rootDirectory));

    Package pkg2 = validPackageWithoutErrors(skyKey);
    assertThat(pkg2.containsErrors()).isFalse();
    assertThat(pkg2.getTarget("existing.txt").getName()).isEqualTo("existing.txt");
    assertThrows(NoSuchTargetException.class, () -> pkg2.getTarget("dangling.txt"));
    // One consequence of the bug was that dangling symlinks were matched by globs evaluated by
    // Skyframe globbing, meaning there would incorrectly be corresponding targets in packages
    // that had skyframe cache hits during skyframe hybrid globbing.

    scratch.file("foo/nope");
    getSkyframeExecutor()
        .invalidateFilesUnderPathForTesting(
            reporter,
            ModifiedFileSet.builder().modify(PathFragment.create("foo/nope")).build(),
            Root.fromPath(rootDirectory));

    Package newPkg = validPackageWithoutErrors(skyKey);
    assertThat(newPkg.containsErrors()).isFalse();
    assertThat(newPkg.getTarget("existing.txt").getName()).isEqualTo("existing.txt");
    // Another consequence of the bug is that change pruning would incorrectly cut off changes that
    // caused a dangling symlink potentially matched by a glob to come into existence.
    assertThat(newPkg.getTarget("dangling.txt").getName()).isEqualTo("dangling.txt");
    assertThat(newPkg).isNotSameInstanceAs(pkg);
  }

  // Regression test for Skyframe globbing incorrectly matching the package's directory path on
  // 'glob(['**'], exclude_directories = 0)'. We test for this directly by triggering
  // hybrid globbing (gives coverage for both non-skyframe globbing and skyframe globbing).
  @Test
  public void testRecursiveGlobNeverMatchesPackageDirectory() throws Exception {
    scratch.file(
        "foo/BUILD",
        "[sh_library(name = x + '-matched') for x in glob(['**'], exclude_directories = 0)]");
    scratch.file("foo/bar");

    preparePackageLoading(rootDirectory);

    SkyKey skyKey = PackageValue.key(PackageIdentifier.parse("@//foo"));
    Package pkg = validPackageWithoutErrors(skyKey);
    assertThat(pkg.containsErrors()).isFalse();
    assertThat(pkg.getTarget("bar-matched").getName()).isEqualTo("bar-matched");
    assertThrows(NoSuchTargetException.class, () -> pkg.getTarget("-matched"));

    scratch.overwriteFile(
        "foo/BUILD",
        "[sh_library(name = x + '-matched') for x in glob(['**'], exclude_directories = 0)]",
        "#some-irrelevant-comment");
    getSkyframeExecutor()
        .invalidateFilesUnderPathForTesting(
            reporter,
            ModifiedFileSet.builder().modify(PathFragment.create("foo/BUILD")).build(),
            Root.fromPath(rootDirectory));

    Package pkg2 = validPackageWithoutErrors(skyKey);
    assertThat(pkg2.containsErrors()).isFalse();
    assertThat(pkg2.getTarget("bar-matched").getName()).isEqualTo("bar-matched");
    assertThrows(NoSuchTargetException.class, () -> pkg2.getTarget("-matched"));
  }

  @Test
  public void testPackageLoadingErrorOnIOExceptionReadingBuildFile() throws Exception {
    Path fooBuildFilePath = scratch.file("foo/BUILD");
    IOException exn = new IOException("nope");
    fs.throwExceptionOnGetInputStream(fooBuildFilePath, exn);

    Exception ex = evaluatePackageToException("@//foo");
    assertThat(ex).hasMessageThat().contains("nope");
    assertThat(ex).isInstanceOf(NoSuchPackageException.class);
    assertThat(ex).hasCauseThat().isInstanceOf(IOException.class);
    assertDetailedExitCode(ex, PackageLoading.Code.BUILD_FILE_MISSING, ExitCode.BUILD_FAILURE);
  }

  @Test
  public void testPackageLoadingErrorOnIOExceptionReadingBzlFile() throws Exception {
    scratch.file("foo/BUILD", "load('//foo:bzl.bzl', 'x')");
    Path fooBzlFilePath = scratch.file("foo/bzl.bzl");
    IOException exn = new IOException("nope");
    fs.throwExceptionOnGetInputStream(fooBzlFilePath, exn);

    Exception ex = evaluatePackageToException("@//foo");
    assertThat(ex).hasMessageThat().contains("nope");
    assertThat(ex).isInstanceOf(NoSuchPackageException.class);
    assertThat(ex).hasCauseThat().isInstanceOf(IOException.class);
    assertDetailedExitCode(
        ex, PackageLoading.Code.IMPORT_STARLARK_FILE_ERROR, ExitCode.BUILD_FAILURE);
  }

  @Test
  public void testLabelsCrossesSubpackageBoundaries() throws Exception {
    reporter.removeHandler(failFastHandler);

    scratch.file("pkg/BUILD", "exports_files(['sub/blah'])");
    scratch.file("pkg/sub/BUILD");
    invalidatePackages();

    SkyKey skyKey = PackageValue.key(PackageIdentifier.parse("@//pkg"));
    EvaluationResult<PackageValue> result =
        SkyframeExecutorTestUtils.evaluate(
            getSkyframeExecutor(), skyKey, /*keepGoing=*/ false, reporter);
    assertThatEvaluationResult(result).hasNoError();
    assertThat(result.get(skyKey).getPackage().containsErrors()).isTrue();
    assertContainsEvent("Label '//pkg:sub/blah' is invalid because 'pkg/sub' is a subpackage");
  }

  @Test
  public void testSymlinkCycleEncounteredWhileHandlingLabelCrossingSubpackageBoundaries()
      throws Exception {
    scratch.file("pkg/BUILD", "exports_files(['sub/blah'])");
    Path subBuildFilePath = scratch.dir("pkg/sub").getChild("BUILD");
    FileSystemUtils.ensureSymbolicLink(subBuildFilePath, subBuildFilePath);
    invalidatePackages();

    Exception ex = evaluatePackageToException("@//pkg");
    assertThat(ex).isInstanceOf(BuildFileNotFoundException.class);
    assertThat(ex)
        .hasMessageThat()
        .contains(
            "no such package 'pkg/sub': Symlink cycle detected while trying to find BUILD file");
    assertContainsEvent("circular symlinks detected");
  }

  // Regression test for b/206459361.
  @Test
  public void nonSkyframeGlobbingIOException_andLabelCrossingSubpackageBoundaries_withKeepGoing()
      throws Exception {
    reporter.removeHandler(failFastHandler);

    // When a package's BUILD file and the relevant filesystem state is such that non-Skyframe
    // globbing will encounter an IOException due to a directory symlink cycle *and* the BUILD file
    // defines a target with a label that crosses subpackage boundaries,
    Path pkgBUILDPath =
        scratch.file(
            "pkg/BUILD",
            "exports_files(['sub/blah'])  # label crossing subpackage boundaries", //
            "glob(['globcycle/**/foo.txt'])  # triggers non-Skyframe globbing error");
    scratch.file("pkg/sub/BUILD");
    Path pkgGlobcyclePath = pkgBUILDPath.getParentDirectory().getChild("globcycle");
    FileSystemUtils.ensureSymbolicLink(pkgGlobcyclePath, pkgGlobcyclePath);
    assertThrows(IOException.class, () -> pkgGlobcyclePath.statIfFound(Symlinks.FOLLOW));

    invalidatePackages();

    // ... and we evaluate the package with keepGoing == true, we expect the evaluation to fail with
    // the non-Skyframe globbing error, but for the label crossing event to *not* get added (because
    // the globbing IOException would put Package.Builder in a state on which we cannot run
    // handleLabelsCrossingSubpackagesAndPropagateInconsistentFilesystemExceptions).
    SkyKey pkgKey = PackageValue.key(PackageIdentifier.parse("@//pkg"));
    EvaluationResult<PackageValue> result =
        SkyframeExecutorTestUtils.evaluate(
            getSkyframeExecutor(), pkgKey, /*keepGoing=*/ true, reporter);
    assertThatEvaluationResult(result)
        .hasErrorEntryForKeyThat(pkgKey)
        .hasExceptionThat()
        .isInstanceOf(NoSuchPackageException.class);
    assertThatEvaluationResult(result)
        .hasErrorEntryForKeyThat(pkgKey)
        .hasExceptionThat()
        .hasMessageThat()
        .contains("Symlink cycle: /workspace/pkg/globcycle");
    assertDoesNotContainEvent(
        "Label '//pkg:sub/blah' is invalid because 'pkg/sub' is a subpackage");
  }

  @Test
  public void testGlobAllowEmpty_paramValueMustBeBoolean() throws Exception {
    reporter.removeHandler(failFastHandler);

    scratch.file("pkg/BUILD", "x = " + "glob(['*.foo'], allow_empty = 5)");
    invalidatePackages();

    SkyKey skyKey = PackageValue.key(PackageIdentifier.parse("@//pkg"));
    validPackage(skyKey);

    assertContainsEvent("expected boolean for argument `allow_empty`, got `5`");
  }

  @Test
  public void testGlobAllowEmpty_functionParam() throws Exception {
    scratch.file("pkg/BUILD", "x = " + "glob(['*.foo'], allow_empty=True)");
    invalidatePackages();

    SkyKey skyKey = PackageValue.key(PackageIdentifier.parse("@//pkg"));
    Package pkg = validPackage(skyKey);
    assertThat(pkg.containsErrors()).isFalse();
    assertNoEvents();
  }

  @Test
  public void testGlobAllowEmpty_starlarkOption() throws Exception {
    preparePackageLoadingWithCustomStarklarkSemanticsOptions(
        Options.parse(BuildLanguageOptions.class, "--incompatible_disallow_empty_glob=false")
            .getOptions(),
        rootDirectory);

    scratch.file("pkg/BUILD", "x = " + "glob(['*.foo'])");
    invalidatePackages();

    SkyKey skyKey = PackageValue.key(PackageIdentifier.parse("@//pkg"));
    Package pkg = validPackage(skyKey);
    assertThat(pkg.containsErrors()).isFalse();
    assertNoEvents();
  }

  @Test
  public void testGlobDisallowEmpty_functionParam_wasNonEmptyAndBecomesEmpty() throws Exception {
    scratch.file("pkg/BUILD", "x = " + "glob(['*.foo'], allow_empty=False)");
    scratch.file("pkg/blah.foo");
    invalidatePackages();

    SkyKey skyKey = PackageValue.key(PackageIdentifier.parse("@//pkg"));

    Package pkg = validPackage(skyKey);
    assertThat(pkg.containsErrors()).isFalse();
    assertNoEvents();

    scratch.deleteFile("pkg/blah.foo");
    getSkyframeExecutor()
        .invalidateFilesUnderPathForTesting(
            reporter,
            ModifiedFileSet.builder().modify(PathFragment.create("pkg/blah.foo")).build(),
            Root.fromPath(rootDirectory));

    reporter.removeHandler(failFastHandler);
    pkg = validPackage(skyKey);
    assertThat(pkg.containsErrors()).isTrue();
    assertContainsEvent(
        "glob pattern '*.foo' didn't match anything, but allow_empty is set to False (the "
            + "default value of allow_empty can be set with --incompatible_disallow_empty_glob).");
  }

  @Test
  public void testGlobDisallowEmpty_starlarkOption_wasNonEmptyAndBecomesEmpty() throws Exception {
    preparePackageLoadingWithCustomStarklarkSemanticsOptions(
        Options.parse(BuildLanguageOptions.class, "--incompatible_disallow_empty_glob=true")
            .getOptions(),
        rootDirectory);

    scratch.file("pkg/BUILD", "x = " + "glob(['*.foo'])");
    scratch.file("pkg/blah.foo");
    invalidatePackages();

    SkyKey skyKey = PackageValue.key(PackageIdentifier.parse("@//pkg"));

    Package pkg = validPackage(skyKey);
    assertThat(pkg.containsErrors()).isFalse();
    assertNoEvents();

    scratch.deleteFile("pkg/blah.foo");
    getSkyframeExecutor()
        .invalidateFilesUnderPathForTesting(
            reporter,
            ModifiedFileSet.builder().modify(PathFragment.create("pkg/blah.foo")).build(),
            Root.fromPath(rootDirectory));

    reporter.removeHandler(failFastHandler);
    pkg = validPackage(skyKey);
    assertThat(pkg.containsErrors()).isTrue();
    assertContainsEvent(
        "glob pattern '*.foo' didn't match anything, but allow_empty is set to False (the "
            + "default value of allow_empty can be set with --incompatible_disallow_empty_glob).");
  }

  @Test
  public void testGlobDisallowEmpty_functionParam_wasEmptyAndStaysEmpty() throws Exception {
    scratch.file("pkg/BUILD", "x = " + "glob(['*.foo'], allow_empty=False)");
    invalidatePackages();

    SkyKey skyKey = PackageValue.key(PackageIdentifier.parse("@//pkg"));
    reporter.removeHandler(failFastHandler);

    Package pkg = validPackage(skyKey);
    assertThat(pkg.containsErrors()).isTrue();
    String expectedEventString =
        "glob pattern '*.foo' didn't match anything, but allow_empty is set to False (the "
            + "default value of allow_empty can be set with --incompatible_disallow_empty_glob).";
    assertContainsEvent(expectedEventString);

    scratch.overwriteFile("pkg/BUILD", "x = " + "glob(['*.foo'], allow_empty=False) #comment");
    getSkyframeExecutor()
        .invalidateFilesUnderPathForTesting(
            reporter,
            ModifiedFileSet.builder().modify(PathFragment.create("pkg/BUILD")).build(),
            Root.fromPath(rootDirectory));

    pkg = validPackage(skyKey);
    assertThat(pkg.containsErrors()).isTrue();
    assertContainsEvent(expectedEventString);
  }

  @Test
  public void testGlobDisallowEmpty_starlarkOption_wasEmptyAndStaysEmpty() throws Exception {
    preparePackageLoadingWithCustomStarklarkSemanticsOptions(
        Options.parse(BuildLanguageOptions.class, "--incompatible_disallow_empty_glob=true")
            .getOptions(),
        rootDirectory);

    scratch.file("pkg/BUILD", "x = " + "glob(['*.foo'])");
    invalidatePackages();

    SkyKey skyKey = PackageValue.key(PackageIdentifier.parse("@//pkg"));
    reporter.removeHandler(failFastHandler);

    Package pkg = validPackage(skyKey);
    assertThat(pkg.containsErrors()).isTrue();
    String expectedEventString =
        "glob pattern '*.foo' didn't match anything, but allow_empty is set to False (the "
            + "default value of allow_empty can be set with --incompatible_disallow_empty_glob).";
    assertContainsEvent(expectedEventString);

    scratch.overwriteFile("pkg/BUILD", "x = " + "glob(['*.foo']) #comment");
    getSkyframeExecutor()
        .invalidateFilesUnderPathForTesting(
            reporter,
            ModifiedFileSet.builder().modify(PathFragment.create("pkg/BUILD")).build(),
            Root.fromPath(rootDirectory));

    pkg = validPackage(skyKey);
    assertThat(pkg.containsErrors()).isTrue();
    assertContainsEvent(expectedEventString);
  }

  @Test
  public void testGlobDisallowEmpty_functionParam_wasEmptyDueToExcludeAndStaysEmpty()
      throws Exception {
    scratch.file("pkg/BUILD", "x = glob(include=['*.foo'], exclude=['blah.*'], allow_empty=False)");
    scratch.file("pkg/blah.foo");
    invalidatePackages();

    SkyKey skyKey = PackageValue.key(PackageIdentifier.parse("@//pkg"));
    reporter.removeHandler(failFastHandler);

    Package pkg = validPackage(skyKey);
    assertThat(pkg.containsErrors()).isTrue();
    String expectedEventString =
        "all files in the glob have been excluded, but allow_empty is set to False (the "
            + "default value of allow_empty can be set with --incompatible_disallow_empty_glob).";
    assertContainsEvent(expectedEventString);

    scratch.overwriteFile(
        "pkg/BUILD",
        "x = glob(include=['*.foo'], exclude=['blah.*'], allow_empty=False) # comment");
    getSkyframeExecutor()
        .invalidateFilesUnderPathForTesting(
            reporter,
            ModifiedFileSet.builder().modify(PathFragment.create("pkg/BUILD")).build(),
            Root.fromPath(rootDirectory));

    pkg = validPackage(skyKey);
    assertThat(pkg.containsErrors()).isTrue();
    assertContainsEvent(expectedEventString);
  }

  @Test
  public void testGlobDisallowEmpty_starlarkOption_wasEmptyDueToExcludeAndStaysEmpty()
      throws Exception {
    preparePackageLoadingWithCustomStarklarkSemanticsOptions(
        Options.parse(BuildLanguageOptions.class, "--incompatible_disallow_empty_glob=true")
            .getOptions(),
        rootDirectory);

    scratch.file("pkg/BUILD", "x = glob(include=['*.foo'], exclude=['blah.*'])");
    scratch.file("pkg/blah.foo");
    invalidatePackages();

    SkyKey skyKey = PackageValue.key(PackageIdentifier.parse("@//pkg"));
    reporter.removeHandler(failFastHandler);

    Package pkg = validPackage(skyKey);
    assertThat(pkg.containsErrors()).isTrue();
    String expectedEventString =
        "all files in the glob have been excluded, but allow_empty is set to False (the "
            + "default value of allow_empty can be set with --incompatible_disallow_empty_glob).";
    assertContainsEvent(expectedEventString);

    scratch.overwriteFile("pkg/BUILD", "x = glob(include=['*.foo'], exclude=['blah.*']) # comment");
    getSkyframeExecutor()
        .invalidateFilesUnderPathForTesting(
            reporter,
            ModifiedFileSet.builder().modify(PathFragment.create("pkg/BUILD")).build(),
            Root.fromPath(rootDirectory));

    pkg = validPackage(skyKey);
    assertThat(pkg.containsErrors()).isTrue();
    assertContainsEvent(expectedEventString);
  }

  @Test
  public void testGlobDisallowEmpty_functionParam_wasEmptyAndBecomesNonEmpty() throws Exception {
    scratch.file("pkg/BUILD", "x = " + "glob(['*.foo'], allow_empty=False)");
    invalidatePackages();

    SkyKey skyKey = PackageValue.key(PackageIdentifier.parse("@//pkg"));

    reporter.removeHandler(failFastHandler);
    Package pkg = validPackage(skyKey);
    assertThat(pkg.containsErrors()).isTrue();
    assertContainsEvent(
        "glob pattern '*.foo' didn't match anything, but allow_empty is set to False (the "
            + "default value of allow_empty can be set with --incompatible_disallow_empty_glob).");

    scratch.file("pkg/blah.foo");
    getSkyframeExecutor()
        .invalidateFilesUnderPathForTesting(
            reporter,
            ModifiedFileSet.builder().modify(PathFragment.create("pkg/blah.foo")).build(),
            Root.fromPath(rootDirectory));

    reporter.addHandler(failFastHandler);
    eventCollector.clear();
    pkg = validPackage(skyKey);
    assertThat(pkg.containsErrors()).isFalse();
    assertNoEvents();
  }

  @Test
  public void testGlobDisallowEmpty_starlarkOption_wasEmptyAndBecomesNonEmpty() throws Exception {
    preparePackageLoadingWithCustomStarklarkSemanticsOptions(
        Options.parse(BuildLanguageOptions.class, "--incompatible_disallow_empty_glob=true")
            .getOptions(),
        rootDirectory);

    scratch.file("pkg/BUILD", "x = " + "glob(['*.foo'])");
    invalidatePackages();

    SkyKey skyKey = PackageValue.key(PackageIdentifier.parse("@//pkg"));

    reporter.removeHandler(failFastHandler);
    Package pkg = validPackage(skyKey);
    assertThat(pkg.containsErrors()).isTrue();

    assertContainsEvent(
        "glob pattern '*.foo' didn't match anything, but allow_empty is set to False (the "
            + "default value of allow_empty can be set with --incompatible_disallow_empty_glob).");

    scratch.file("pkg/blah.foo");
    getSkyframeExecutor()
        .invalidateFilesUnderPathForTesting(
            reporter,
            ModifiedFileSet.builder().modify(PathFragment.create("pkg/blah.foo")).build(),
            Root.fromPath(rootDirectory));

    reporter.addHandler(failFastHandler);
    eventCollector.clear();
    pkg = validPackage(skyKey);
    assertThat(pkg.containsErrors()).isFalse();
    assertNoEvents();
  }

  @Test
  public void testPackageRecordsLoadedModules() throws Exception {
    scratch.file("p/BUILD", "load('a.bzl', 'a'); load(':b.bzl', 'b')");
    scratch.file("p/a.bzl", "load('c.bzl', 'c'); a = c");
    scratch.file("p/b.bzl", "load(':c.bzl', 'c'); b = c");
    scratch.file("p/c.bzl", "c = 0");

    // load p
    preparePackageLoading(rootDirectory);
    SkyKey skyKey = PackageValue.key(PackageIdentifier.parse("@//p"));
    Package p = validPackageWithoutErrors(skyKey);

    // Keys are load strings as they appear in the source (notice ":" in one of them).
    Map<String, Module> pLoads = p.getLoads();
    assertThat(pLoads.keySet().toString()).isEqualTo("[a.bzl, :b.bzl]");

    // subgraph a
    Module a = pLoads.get("a.bzl");
    assertThat(a.toString()).isEqualTo("<module //p:a.bzl>");
    Map<String, Module> aLoads = BazelModuleContext.of(a).loads();
    assertThat(aLoads.keySet().toString()).isEqualTo("[c.bzl]");
    Module cViaA = aLoads.get("c.bzl");
    assertThat(cViaA.toString()).isEqualTo("<module //p:c.bzl>");

    // subgraph b
    Module b = pLoads.get(":b.bzl");
    assertThat(b.toString()).isEqualTo("<module //p:b.bzl>");
    Map<String, Module> bLoads = BazelModuleContext.of(b).loads();
    assertThat(bLoads.keySet().toString()).isEqualTo("[:c.bzl]");
    Module cViaB = bLoads.get(":c.bzl");
    assertThat(cViaB).isSameInstanceAs(cViaA);

    assertThat(cViaA.getGlobal("c")).isEqualTo(StarlarkInt.of(0));
  }

  @Test
  public void veryBrokenPackagePostsDoneToProgressReceiver() throws Exception {
    reporter.removeHandler(failFastHandler);

    // Note: syntax error (recovered), non-existent .bzl file.
    scratch.file("pkg/BUILD", "load('//does_not:exist.bzl', 'broken'");
    SkyKey key = PackageValue.key(PackageIdentifier.parse("@//pkg"));
    EvaluationResult<PackageValue> result =
        SkyframeExecutorTestUtils.evaluate(getSkyframeExecutor(), key, false, reporter);
    assertThatEvaluationResult(result).hasErrorEntryForKeyThat(key);
    assertContainsEvent("syntax error at 'newline': expected ,");
    assertThat(getSkyframeExecutor().getPackageProgressReceiver().progressState())
        .isEqualTo(new Pair<String, String>("1 packages loaded", ""));
  }

  @Test
  public void testNonSkyframeGlobbingEncountersSymlinkCycleAndThrowsIOException() throws Exception {
    reporter.removeHandler(failFastHandler);

    // When a package's BUILD file and the relevant filesystem state is such that non-Skyframe
    // globbing will encounter an IOException due to a directory symlink cycle,
    Path fooBUILDPath = scratch.file("foo/BUILD", "glob(['cycle/**/foo.txt'])");
    Path fooCyclePath = fooBUILDPath.getParentDirectory().getChild("cycle");
    FileSystemUtils.ensureSymbolicLink(fooCyclePath, fooCyclePath);
    IOException ioExnFromFS =
        assertThrows(IOException.class, () -> fooCyclePath.statIfFound(Symlinks.FOLLOW));
    // And it is indeed the case that the FileSystem throws an IOException when the cycle's Path is
    // stat'd (following symlinks, as non-Skyframe globbing does).
    assertThat(ioExnFromFS).hasMessageThat().contains("Too many levels of symbolic links");

    // Then, when we evaluate the PackageValue node for the Package in keepGoing mode,
    SkyKey pkgKey = PackageValue.key(PackageIdentifier.parse("@//foo"));
    EvaluationResult<PackageValue> result =
        SkyframeExecutorTestUtils.evaluate(
            getSkyframeExecutor(), pkgKey, /*keepGoing=*/ true, reporter);
    // The result is a *non-transient* Skyframe error.
    assertThatEvaluationResult(result).hasErrorEntryForKeyThat(pkgKey).isNotTransient();
    // And that error is a NoSuchPackageException
    assertThatEvaluationResult(result)
        .hasErrorEntryForKeyThat(pkgKey)
        .hasExceptionThat()
        .isInstanceOf(NoSuchPackageException.class);
    // With a useful error message,
    assertThatEvaluationResult(result)
        .hasErrorEntryForKeyThat(pkgKey)
        .hasExceptionThat()
        .hasMessageThat()
        .contains("Symlink cycle: /workspace/foo/cycle");
    // And appropriate Skyframe root cause (N.B. since we want PackageFunction to rethrow in
    // situations like this, we want the PackageValue node to be its own root cause).
    assertThatEvaluationResult(result).hasErrorEntryForKeyThat(pkgKey);

    // Then, when we modify the BUILD file so as to force package loading,
    scratch.overwriteFile(
        "foo/BUILD", "glob(['cycle/**/foo.txt']) # dummy comment to force package loading");
    // But we don't make any filesystem changes that would invalidate the GlobValues, meaning that
    // PackageFunction will observe cache hits from Skyframe globbing,
    //
    // And we also have our filesystem blow up if the directory symlink cycle is encountered (thus,
    // the absence of a crash indicates the lack of non-Skyframe globbing),
    fs.stubStatError(
        fooCyclePath,
        new IOException() {
          @Override
          public String getMessage() {
            throw new IllegalStateException("should't get here!");
          }
        });
    // And we evaluate the PackageValue node for the Package in keepGoing mode,
    getSkyframeExecutor()
        .invalidateFilesUnderPathForTesting(
            reporter,
            ModifiedFileSet.builder().modify(PathFragment.create("foo/BUILD")).build(),
            Root.fromPath(rootDirectory));
    // The results are exactly the same as before,
    result =
        SkyframeExecutorTestUtils.evaluate(
            getSkyframeExecutor(), pkgKey, /*keepGoing=*/ true, reporter);
    assertThatEvaluationResult(result).hasErrorEntryForKeyThat(pkgKey).isNotTransient();
    assertThatEvaluationResult(result)
        .hasErrorEntryForKeyThat(pkgKey)
        .hasExceptionThat()
        .isInstanceOf(NoSuchPackageException.class);
    assertThatEvaluationResult(result)
        .hasErrorEntryForKeyThat(pkgKey)
        .hasExceptionThat()
        .hasMessageThat()
        .contains("Symlink cycle: /workspace/foo/cycle");
    // Thus showing that clean and incremental package loading have the same semantics in the
    // presence of a symlink cycle encountered during glob evaluation.
  }

  private static void assertDetailedExitCode(
      Exception exception, PackageLoading.Code expectedPackageLoadingCode, ExitCode exitCode) {
    assertThat(exception).isInstanceOf(DetailedException.class);
    DetailedExitCode detailedExitCode = ((DetailedException) exception).getDetailedExitCode();
    assertThat(detailedExitCode.getExitCode()).isEqualTo(exitCode);
    assertThat(detailedExitCode.getFailureDetail().getPackageLoading().getCode())
        .isEqualTo(expectedPackageLoadingCode);
    assertThat(DetailedExitCode.getExitCode(detailedExitCode.getFailureDetail()))
        .isEqualTo(exitCode);
  }

  /**
   * Tests of the prelude file functionality.
   *
   * <p>This is in a separate BuildViewTestCase because we override the prelude label for the test.
   * (The prelude label is configured differently between Bazel and Blaze.)
   */
  @RunWith(JUnit4.class)
  public static class PreludeTest extends BuildViewTestCase {

    private final CustomInMemoryFs fs = new CustomInMemoryFs(new ManualClock());

    @Override
    protected FileSystem createFileSystem() {
      return fs;
    }

    @Override
    protected ConfiguredRuleClassProvider createRuleClassProvider() {
      ConfiguredRuleClassProvider.Builder builder = new ConfiguredRuleClassProvider.Builder();
      // addStandardRules() may call setPrelude(), so do it first.
      TestRuleClassProvider.addStandardRules(builder);
      builder.setPrelude("//tools/build_rules:test_prelude");
      return builder.build();
    }

    @Test
    public void testPreludeDefinedSymbolIsUsable() throws Exception {
      scratch.file("tools/build_rules/BUILD");
      scratch.file(
          "tools/build_rules/test_prelude", //
          "foo = 'FOO'");
      scratch.file(
          "pkg/BUILD", //
          "print(foo)");

      getConfiguredTarget("//pkg:BUILD");
      assertContainsEvent("FOO");
    }

    @Test
    public void testPreludeAutomaticallyReexportsLoadedSymbols() throws Exception {
      scratch.file("tools/build_rules/BUILD");
      scratch.file(
          "tools/build_rules/test_prelude", //
          "load('//util:common.bzl', 'foo')");
      scratch.file("util/BUILD");
      scratch.file(
          "util/common.bzl", //
          "foo = 'FOO'");
      scratch.file(
          "pkg/BUILD", //
          "print(foo)");

      getConfiguredTarget("//pkg:BUILD");
      assertContainsEvent("FOO");
    }

    // TODO(brandjon): Invert this test once the prelude is a module instead of a syntactic
    // mutation on BUILD files.
    @Test
    public void testPreludeCanExportUnderscoreSymbols() throws Exception {
      scratch.file("tools/build_rules/BUILD");
      scratch.file(
          "tools/build_rules/test_prelude", //
          "_foo = 'FOO'");
      scratch.file(
          "pkg/BUILD", //
          "print(_foo)");

      getConfiguredTarget("//pkg:BUILD");
      assertContainsEvent("FOO");
    }

    @Test
    public void testPreludeCanShadowUniversal() throws Exception {
      scratch.file("tools/build_rules/BUILD");
      scratch.file(
          "tools/build_rules/test_prelude", //
          "len = 'FOO'");
      scratch.file(
          "pkg/BUILD", //
          "print(len)");

      getConfiguredTarget("//pkg:BUILD");
      assertContainsEvent("FOO");
    }

    @Test
    public void testPreludeCanShadowPredeclareds() throws Exception {
      scratch.file("tools/build_rules/BUILD");
      scratch.file(
          "tools/build_rules/test_prelude", //
          "cc_library = 'FOO'");
      scratch.file(
          "pkg/BUILD", //
          "print(cc_library)");

      getConfiguredTarget("//pkg:BUILD");
      assertContainsEvent("FOO");
    }

    @Test
    public void testPreludeCanShadowInjectedPredeclareds() throws Exception {
      setBuildLanguageOptions("--experimental_builtins_bzl_path=tools/builtins_staging");
      scratch.file(
          "tools/builtins_staging/exports.bzl",
          "exported_toplevels = {}",
          "exported_rules = {'cc_library': 'BAR'}",
          "exported_to_java = {}");
      scratch.file("tools/build_rules/BUILD");
      scratch.file(
          "tools/build_rules/test_prelude", //
          "cc_library = 'FOO'");
      scratch.file(
          "pkg/BUILD", //
          "print(cc_library)");

      getConfiguredTarget("//pkg:BUILD");
      assertContainsEvent("FOO");
    }

    @Test
    public void testPreludeSymbolCannotBeMutated() throws Exception {
      scratch.file("tools/build_rules/BUILD");
      scratch.file(
          "tools/build_rules/test_prelude", //
          "foo = ['FOO']");
      scratch.file(
          "pkg/BUILD", //
          "foo.append('BAR')");

      reporter.removeHandler(failFastHandler);
      getConfiguredTarget("//pkg:BUILD");
      assertContainsEvent("trying to mutate a frozen list value");
    }

    @Test
    public void testPreludeCanAccessBzlDialectFeatures() throws Exception {
      scratch.file("tools/build_rules/BUILD");
      // Test both bzl symbols and syntax (e.g. function defs).
      scratch.file(
          "tools/build_rules/test_prelude", //
          "def foo():",
          "    return native.glob");
      scratch.file(
          "pkg/BUILD", //
          "print(foo())");

      getConfiguredTarget("//pkg:BUILD");
      // Prelude can access native.glob (though only a BUILD thread can call it).
      assertContainsEvent("<built-in method glob of native value>");
    }

    @Test
    public void testPreludeNeedNotBePresent() throws Exception {
      scratch.file(
          "pkg/BUILD", //
          "print('FOO')");

      getConfiguredTarget("//pkg:BUILD");
      assertContainsEvent("FOO");
    }

    @Test
    public void testPreludeNeedNotBePresent_evenWhenPackageIs() throws Exception {
      scratch.file("tools/build_rules/BUILD");
      scratch.file(
          "pkg/BUILD", //
          "print('FOO')");

      getConfiguredTarget("//pkg:BUILD");
      assertContainsEvent("FOO");
    }

    @Test
    public void testPreludeFileNotRecognizedWithoutPackage() throws Exception {
      scratch.file(
          "tools/build_rules/test_prelude", //
          "foo = 'FOO'");
      scratch.file(
          "pkg/BUILD", //
          "print(foo)");

      // The prelude file is not found without a corresponding package to contain it. BUILD files
      // get processed as if no prelude file is present.
      reporter.removeHandler(failFastHandler);
      getConfiguredTarget("//pkg:BUILD");
      assertContainsEvent("name 'foo' is not defined");
    }

    @Test
    public void testPreludeFailsWhenErrorInPreludeFile() throws Exception {
      scratch.file("tools/build_rules/BUILD");
      scratch.file(
          "tools/build_rules/test_prelude", //
          "1//0", // <-- dynamic error
          "foo = 'FOO'");
      scratch.file(
          "pkg/BUILD", //
          "print(foo)");

      reporter.removeHandler(failFastHandler);
      getConfiguredTarget("//pkg:BUILD");
      assertContainsEvent(
          "File \"/workspace/tools/build_rules/test_prelude\", line 1, column 2, in <toplevel>");
      assertContainsEvent("Error: integer division by zero");
    }

    @Test
    public void testPreludeWorksEvenWhenPreludePackageInError() throws Exception {
      scratch.file(
          "tools/build_rules/BUILD", //
          "1//0"); // <-- dynamic error
      scratch.file(
          "tools/build_rules/test_prelude", //
          "foo = 'FOO'");
      scratch.file(
          "pkg/BUILD", //
          "print(foo)");

      // Succeeds because prelude loading is only dependent on the prelude package's existence, not
      // its evaluation.
      getConfiguredTarget("//pkg:BUILD");
      assertContainsEvent("FOO");
    }

    // Another hypothetical test case we could try: Confirm that it's possible to explicitly load
    // the prelude file as a regular .bzl. We don't bother testing this use case because, aside from
    // being arguably pathological, it is currently impossible in practice: The prelude label
    // doesn't end with ".bzl" and isn't configurable by the user. We also want to eliminate the
    // prelude, so there's no intention of adding such a feature.

    // Another possible test case: Verify how prelude applies to WORKSPACE files.
  }

  private static class CustomInMemoryFs extends InMemoryFileSystem {
    private abstract static class FileStatusOrException {
      abstract FileStatus get() throws IOException;

      private static class ExceptionImpl extends FileStatusOrException {
        private final IOException exn;

        private ExceptionImpl(IOException exn) {
          this.exn = exn;
        }

        @Override
        FileStatus get() throws IOException {
          throw exn;
        }
      }

      private static class FileStatusImpl extends FileStatusOrException {

        @Nullable private final FileStatus fileStatus;

        private FileStatusImpl(@Nullable FileStatus fileStatus) {
          this.fileStatus = fileStatus;
        }

        @Override
        @Nullable
        FileStatus get() {
          return fileStatus;
        }
      }
    }

    private final Map<PathFragment, FileStatusOrException> stubbedStats = Maps.newHashMap();
    private final Set<PathFragment> makeUnreadableAfterReaddir = Sets.newHashSet();
    private final Map<PathFragment, IOException> pathsToErrorOnGetInputStream = Maps.newHashMap();

    public CustomInMemoryFs(ManualClock manualClock) {
      super(manualClock, DigestHashFunction.SHA256);
    }

    public void stubStat(Path path, @Nullable FileStatus stubbedResult) {
      stubbedStats.put(path.asFragment(), new FileStatusOrException.FileStatusImpl(stubbedResult));
    }

    public void stubStatError(Path path, IOException stubbedResult) {
      stubbedStats.put(path.asFragment(), new FileStatusOrException.ExceptionImpl(stubbedResult));
    }

    @Override
    public FileStatus statIfFound(PathFragment path, boolean followSymlinks) throws IOException {
      if (stubbedStats.containsKey(path)) {
        return stubbedStats.get(path).get();
      }
      return super.statIfFound(path, followSymlinks);
    }

    public void scheduleMakeUnreadableAfterReaddir(Path path) {
      makeUnreadableAfterReaddir.add(path.asFragment());
    }

    @Override
    public Collection<Dirent> readdir(PathFragment path, boolean followSymlinks)
        throws IOException {
      Collection<Dirent> result = super.readdir(path, followSymlinks);
      if (makeUnreadableAfterReaddir.contains(path)) {
        setReadable(path, false);
      }
      return result;
    }

    public void throwExceptionOnGetInputStream(Path path, IOException exn) {
      pathsToErrorOnGetInputStream.put(path.asFragment(), exn);
    }

    @Override
    protected synchronized InputStream getInputStream(PathFragment path) throws IOException {
      IOException exnToThrow = pathsToErrorOnGetInputStream.get(path);
      if (exnToThrow != null) {
        throw exnToThrow;
      }
      return super.getInputStream(path);
    }
  }
}
