// Copyright 2018 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 org.junit.Assert.assertThrows;
import static org.junit.Assert.fail;
import static org.mockito.Mockito.mock;

import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Maps;
import com.google.devtools.build.lib.actions.ActionInput;
import com.google.devtools.build.lib.actions.ActionInputHelper;
import com.google.devtools.build.lib.actions.ActionInputMap;
import com.google.devtools.build.lib.actions.Artifact;
import com.google.devtools.build.lib.actions.Artifact.SpecialArtifact;
import com.google.devtools.build.lib.actions.Artifact.TreeFileArtifact;
import com.google.devtools.build.lib.actions.ArtifactPathResolver;
import com.google.devtools.build.lib.actions.ArtifactRoot;
import com.google.devtools.build.lib.actions.ArtifactRoot.RootType;
import com.google.devtools.build.lib.actions.FileArtifactValue;
import com.google.devtools.build.lib.actions.FileArtifactValue.RemoteFileArtifactValue;
import com.google.devtools.build.lib.actions.FilesetOutputSymlink;
import com.google.devtools.build.lib.actions.HasDigest;
import com.google.devtools.build.lib.actions.HasDigest.ByteStringDigest;
import com.google.devtools.build.lib.actions.StaticInputMetadataProvider;
import com.google.devtools.build.lib.actions.util.ActionsTestUtil;
import com.google.devtools.build.lib.actions.util.ActionsTestUtil.NullAction;
import com.google.devtools.build.lib.remote.RemoteActionFileSystem;
import com.google.devtools.build.lib.remote.RemoteActionInputFetcher;
import com.google.devtools.build.lib.testutil.ManualClock;
import com.google.devtools.build.lib.testutil.Scratch;
import com.google.devtools.build.lib.util.io.TimestampGranularityMonitor;
import com.google.devtools.build.lib.vfs.DigestHashFunction;
import com.google.devtools.build.lib.vfs.DigestUtils;
import com.google.devtools.build.lib.vfs.FileSystem;
import com.google.devtools.build.lib.vfs.OutputPermissions;
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.SyscallCache;
import com.google.devtools.build.lib.vfs.inmemoryfs.InMemoryFileSystem;
import com.google.testing.junit.testparameterinjector.TestParameter;
import com.google.testing.junit.testparameterinjector.TestParameterInjector;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.util.Map;
import javax.annotation.Nullable;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;

/** Tests for {@link ActionOutputMetadataStore}. */
@RunWith(TestParameterInjector.class)
public final class ActionOutputMetadataStoreTest {

  private enum MaterializationPathDepth {
    SHALLOW,
    DEEP
  }

  private enum FileLocation {
    LOCAL,
    REMOTE
  }

  private enum TreeComposition {
    EMPTY,
    FULLY_LOCAL,
    FULLY_REMOTE,
    MIXED;
  }

  private final Map<Path, Integer> chmodCalls = Maps.newConcurrentMap();

  private final Scratch scratch =
      new Scratch(
          new InMemoryFileSystem(DigestHashFunction.SHA256) {
            @Override
            public void chmod(PathFragment pathFragment, int mode) throws IOException {
              Path path = getPath(pathFragment);
              if (chmodCalls.containsKey(path)) {
                fail("chmod called on " + path + " twice");
              }
              chmodCalls.put(path, mode);
              super.chmod(pathFragment, mode);
            }
          });

  private final TimestampGranularityMonitor tsgm =
      new TimestampGranularityMonitor(new ManualClock());

  private final Path execRoot = scratch.resolve("/workspace");
  private final ArtifactRoot sourceRoot = ArtifactRoot.asSourceRoot(Root.fromPath(execRoot));
  private final ArtifactRoot outputRoot =
      ArtifactRoot.asDerivedRoot(execRoot, RootType.Output, "out");

  @Before
  public void createRootDirs() throws Exception {
    sourceRoot.getRoot().asPath().createDirectoryAndParents();
    outputRoot.getRoot().asPath().createDirectoryAndParents();
  }

  private ActionOutputMetadataStore createStore(ImmutableSet<Artifact> outputs) {
    return createStore(outputs, /* actionFs= */ null);
  }

  private ActionOutputMetadataStore createStore(
      ImmutableSet<Artifact> outputs, @Nullable FileSystem actionFs) {
    return ActionOutputMetadataStore.create(
        /* archivedTreeArtifactsEnabled= */ false,
        OutputPermissions.READONLY,
        outputs,
        SyscallCache.NO_CACHE,
        tsgm,
        ArtifactPathResolver.createPathResolver(actionFs, execRoot),
        execRoot.asFragment());
  }

  private RemoteActionFileSystem createRemoteActionFileSystem(
      ActionInputMap inputMap, ImmutableSet<Artifact> outputs) {
    return new RemoteActionFileSystem(
        scratch.getFileSystem(),
        execRoot.asFragment(),
        outputRoot.getExecPathString(),
        inputMap,
        outputs,
        StaticInputMetadataProvider.empty(),
        mock(RemoteActionInputFetcher.class));
  }

  @Test
  public void withNonArtifactInput() throws Exception {
    ActionInput input = ActionInputHelper.fromPath("foo/bar");
    FileArtifactValue metadata =
        FileArtifactValue.createForNormalFile(
            new byte[] {1, 2, 3}, /* proxy= */ null, /* size= */ 10L);
    ActionInputMap map = new ActionInputMap(1);
    map.putWithNoDepOwner(input, metadata);
    assertThat(map.getInputMetadata(input)).isEqualTo(metadata);
    ActionInputMetadataProvider inputMetadataProvider =
        new ActionInputMetadataProvider(execRoot.asFragment(), map, ImmutableMap.of());
    assertThat(inputMetadataProvider.getInputMetadata(input)).isNull();
    assertThat(chmodCalls).isEmpty();
  }

  @Test
  public void withArtifactInput() throws Exception {
    PathFragment path = PathFragment.create("src/a");
    Artifact artifact = ActionsTestUtil.createArtifactWithRootRelativePath(sourceRoot, path);
    FileArtifactValue metadata =
        FileArtifactValue.createForNormalFile(
            new byte[] {1, 2, 3}, /* proxy= */ null, /* size= */ 10L);
    ActionInputMap map = new ActionInputMap(1);
    map.putWithNoDepOwner(artifact, metadata);
    ActionInputMetadataProvider inputMetadataProvider =
        new ActionInputMetadataProvider(execRoot.asFragment(), map, ImmutableMap.of());
    assertThat(inputMetadataProvider.getInputMetadata(artifact)).isEqualTo(metadata);
    assertThat(chmodCalls).isEmpty();
  }

  @Test
  public void unknownSourceArtifactPermittedDuringInputDiscovery() throws Exception {
    PathFragment path = PathFragment.create("src/a");
    Artifact artifact = ActionsTestUtil.createArtifactWithRootRelativePath(sourceRoot, path);
    ActionInputMap inputMap = new ActionInputMap(0);
    ActionInputMetadataProvider inputMetadataProvider =
        new ActionInputMetadataProvider(execRoot.asFragment(), inputMap, ImmutableMap.of());
    assertThat(inputMetadataProvider.getInputMetadata(artifact)).isNull();
    assertThat(chmodCalls).isEmpty();
  }

  @Test
  public void unknownArtifactPermittedDuringInputDiscovery() throws Exception {
    PathFragment path = PathFragment.create("foo/bar");
    Artifact artifact = ActionsTestUtil.createArtifactWithRootRelativePath(outputRoot, path);
    ActionInputMap inputMap = new ActionInputMap(0);
    ActionInputMetadataProvider inputMetadataProvider =
        new ActionInputMetadataProvider(execRoot.asFragment(), inputMap, ImmutableMap.of());
    assertThat(inputMetadataProvider.getInputMetadata(artifact)).isNull();
    assertThat(chmodCalls).isEmpty();
  }

  @Test
  public void withKnownOutputArtifactStatsFile() throws Exception {
    Artifact artifact = ActionsTestUtil.createArtifact(outputRoot, "foo/bar");
    scratch.file(artifact.getPath().getPathString(), "not empty");
    ActionOutputMetadataStore store = createStore(/* outputs= */ ImmutableSet.of(artifact));
    assertThat(store.getOutputMetadata(artifact)).isNotNull();
    assertThat(chmodCalls).isEmpty();
  }

  @Test
  public void withMissingOutputArtifactStatsFileFailsWithException() {
    Artifact artifact = ActionsTestUtil.createArtifact(outputRoot, "foo/bar");
    assertThat(artifact.getPath().exists()).isFalse();
    ActionOutputMetadataStore store = createStore(/* outputs= */ ImmutableSet.of(artifact));
    assertThrows(FileNotFoundException.class, () -> store.getOutputMetadata(artifact));
    assertThat(chmodCalls).isEmpty();
  }

  @Test
  public void unknownTreeArtifactPermittedDuringInputDiscovery() throws Exception {
    SpecialArtifact treeArtifact =
        ActionsTestUtil.createTreeArtifactWithGeneratingAction(outputRoot, "foo/bar");
    Artifact artifact = TreeFileArtifact.createTreeOutput(treeArtifact, "baz");
    ActionInputMap inputMap = new ActionInputMap(0);
    ActionInputMetadataProvider inputMetadataProvider =
        new ActionInputMetadataProvider(execRoot.asFragment(), inputMap, ImmutableMap.of());
    assertThat(inputMetadataProvider.getInputMetadata(artifact)).isNull();
    assertThat(chmodCalls).isEmpty();
  }

  @Test
  public void withUnknownOutputArtifactStatsFileTreeArtifact() throws Exception {
    SpecialArtifact treeArtifact =
        ActionsTestUtil.createTreeArtifactWithGeneratingAction(outputRoot, "foo/bar");
    Artifact artifact = TreeFileArtifact.createTreeOutput(treeArtifact, "baz");
    scratch.file(artifact.getPath().getPathString(), "not empty");
    ActionOutputMetadataStore store = createStore(/* outputs= */ ImmutableSet.of(treeArtifact));
    assertThat(store.getOutputMetadata(artifact)).isNotNull();
    assertThat(chmodCalls).isEmpty();
  }

  @Test
  public void createsTreeArtifactValueFromFilesystem() throws Exception {
    SpecialArtifact treeArtifact =
        ActionsTestUtil.createTreeArtifactWithGeneratingAction(outputRoot, "foo/bar");
    TreeFileArtifact child1 = TreeFileArtifact.createTreeOutput(treeArtifact, "child1");
    TreeFileArtifact child2 = TreeFileArtifact.createTreeOutput(treeArtifact, "child2");
    scratch.file(child1.getPath().getPathString(), "child1");
    scratch.file(child2.getPath().getPathString(), "child2");

    ActionOutputMetadataStore store = createStore(/* outputs= */ ImmutableSet.of(treeArtifact));

    FileArtifactValue treeMetadata = store.getOutputMetadata(treeArtifact);
    FileArtifactValue child1Metadata = store.getOutputMetadata(child1);
    FileArtifactValue child2Metadata = store.getOutputMetadata(child2);
    TreeArtifactValue tree = store.getAllTreeArtifactData().get(treeArtifact);

    assertThat(tree.getMetadata()).isEqualTo(treeMetadata);
    assertThat(tree.getChildValues())
        .containsExactly(child1, child1Metadata, child2, child2Metadata);
    assertThat(store.getTreeArtifactChildren(treeArtifact)).isEqualTo(tree.getChildren());
    assertThat(store.getAllArtifactData()).isEmpty();
    assertThat(chmodCalls).isEmpty();
  }

  @Test
  public void resettingOutputs() throws Exception {
    PathFragment path = PathFragment.create("foo/bar");
    Artifact artifact = ActionsTestUtil.createArtifactWithRootRelativePath(outputRoot, path);
    Path outputPath = scratch.file(artifact.getPath().getPathString(), "not empty");
    ActionOutputMetadataStore store = createStore(/* outputs= */ ImmutableSet.of(artifact));
    store.prepareForActionExecution();

    // The store doesn't have any info. It'll stat the file and discover that it's 10 bytes long.
    assertThat(store.getOutputMetadata(artifact).getSize()).isEqualTo(10);
    assertThat(chmodCalls).containsExactly(outputPath, 0555);

    // Inject a remote file of size 42.
    store.injectFile(
        artifact,
        RemoteFileArtifactValue.create(new byte[] {1, 2, 3}, 42, 0, /* expireAtEpochMilli= */ -1));
    assertThat(store.getOutputMetadata(artifact).getSize()).isEqualTo(42);

    // Reset this output, which will make the store stat the file again.
    store.resetOutputs(ImmutableList.of(artifact));
    chmodCalls.clear();
    assertThat(store.getOutputMetadata(artifact).getSize()).isEqualTo(10);
    // The store should not have chmodded the file as it already has the correct permission.
    assertThat(chmodCalls).isEmpty();
  }

  @Test
  public void injectRemoteArtifactMetadata() throws Exception {
    PathFragment path = PathFragment.create("foo/bar");
    Artifact artifact = ActionsTestUtil.createArtifactWithRootRelativePath(outputRoot, path);
    ActionOutputMetadataStore store = createStore(/* outputs= */ ImmutableSet.of(artifact));
    store.prepareForActionExecution();

    byte[] digest = new byte[] {1, 2, 3};
    int size = 10;
    store.injectFile(
        artifact,
        RemoteFileArtifactValue.create(
            digest, size, /* locationIndex= */ 1, /* expireAtEpochMilli= */ -1));

    FileArtifactValue v = store.getOutputMetadata(artifact);
    assertThat(v).isNotNull();
    assertThat(v.getDigest()).isEqualTo(digest);
    assertThat(v.getSize()).isEqualTo(size);
    assertThat(chmodCalls).isEmpty();
  }

  @Test
  public void cannotInjectTreeArtifactChildIndividually() {
    SpecialArtifact treeArtifact =
        ActionsTestUtil.createTreeArtifactWithGeneratingAction(outputRoot, "foo/bar");
    TreeFileArtifact child = TreeFileArtifact.createTreeOutput(treeArtifact, "child");

    ActionOutputMetadataStore store = createStore(/* outputs= */ ImmutableSet.of(treeArtifact));
    store.prepareForActionExecution();

    RemoteFileArtifactValue childValue =
        RemoteFileArtifactValue.create(new byte[] {1, 2, 3}, 5, 1, /* expireAtEpochMilli= */ -1);

    assertThrows(IllegalArgumentException.class, () -> store.injectFile(child, childValue));
    assertThat(store.getAllArtifactData()).isEmpty();
    assertThat(store.getAllTreeArtifactData()).isEmpty();
    assertThat(chmodCalls).isEmpty();
  }

  @Test
  public void canInjectTemplateExpansionOutput() {
    SpecialArtifact treeArtifact =
        ActionsTestUtil.createTreeArtifactWithGeneratingAction(outputRoot, "foo/bar");
    TreeFileArtifact output =
        TreeFileArtifact.createTemplateExpansionOutput(
            treeArtifact, "output", ActionsTestUtil.NULL_TEMPLATE_EXPANSION_ARTIFACT_OWNER);

    ActionOutputMetadataStore store = createStore(/* outputs= */ ImmutableSet.of(treeArtifact));
    store.prepareForActionExecution();

    RemoteFileArtifactValue value =
        RemoteFileArtifactValue.create(new byte[] {1, 2, 3}, 5, 1, /* expireAtEpochMilli= */ -1);
    store.injectFile(output, value);

    assertThat(store.getAllArtifactData()).containsExactly(output, value);
    assertThat(store.getAllTreeArtifactData()).isEmpty();
    assertThat(chmodCalls).isEmpty();
  }

  @Test
  public void injectRemoteTreeArtifactMetadata() throws Exception {
    SpecialArtifact treeArtifact =
        ActionsTestUtil.createTreeArtifactWithGeneratingAction(outputRoot, "dir");
    ActionOutputMetadataStore store = createStore(/* outputs= */ ImmutableSet.of(treeArtifact));
    store.prepareForActionExecution();

    TreeArtifactValue tree =
        TreeArtifactValue.newBuilder(treeArtifact)
            .putChild(
                TreeFileArtifact.createTreeOutput(treeArtifact, "foo"),
                RemoteFileArtifactValue.create(
                    new byte[] {1, 2, 3}, 5, 1, /* expireAtEpochMilli= */ -1))
            .putChild(
                TreeFileArtifact.createTreeOutput(treeArtifact, "bar"),
                RemoteFileArtifactValue.create(
                    new byte[] {4, 5, 6}, 10, 1, /* expireAtEpochMilli= */ -1))
            .build();

    store.injectTree(treeArtifact, tree);

    FileArtifactValue value = store.getOutputMetadata(treeArtifact);
    assertThat(value).isNotNull();
    assertThat(value.getDigest()).isEqualTo(tree.getDigest());
    assertThat(store.getAllTreeArtifactData().get(treeArtifact)).isEqualTo(tree);
    assertThat(chmodCalls).isEmpty();

    assertThat(store.getTreeArtifactChildren(treeArtifact)).isEqualTo(tree.getChildren());

    // Make sure that all children are transferred properly into the ActionExecutionValue. If any
    // child is missing, getExistingFileArtifactValue will throw.
    ActionExecutionValue actionExecutionValue =
        ActionExecutionValue.createFromOutputMetadataStore(
            store, /* outputSymlinks= */ ImmutableList.of(), new NullAction());
    tree.getChildren().forEach(actionExecutionValue::getExistingFileArtifactValue);
  }

  @Test
  public void fileArtifactMaterializedAsSymlink(
      @TestParameter MaterializationPathDepth depth, @TestParameter FileLocation location)
      throws Exception {
    Artifact targetArtifact =
        ActionsTestUtil.createArtifactWithRootRelativePath(
            outputRoot, PathFragment.create("target"));

    Artifact outputArtifact =
        ActionsTestUtil.createArtifactWithRootRelativePath(
            outputRoot, PathFragment.create("output"));

    PathFragment preexistingPath =
        depth.equals(MaterializationPathDepth.DEEP)
            ? outputRoot.getExecPath().getRelative("preexisting")
            : null;

    FileArtifactValue targetMetadata = createFileMetadataForSymlinkTest(location, preexistingPath);

    ActionInputMap inputMap = new ActionInputMap(0);
    inputMap.putWithNoDepOwner(targetArtifact, targetMetadata);

    RemoteActionFileSystem actionFs =
        createRemoteActionFileSystem(inputMap, ImmutableSet.of(outputArtifact));

    ActionOutputMetadataStore store = createStore(ImmutableSet.of(outputArtifact), actionFs);
    store.prepareForActionExecution();

    // In a realistic scenario, files with local metadata should also exist on disk.
    // However, the action filesystem is expected to obtain their metadata from the input map.
    actionFs
        .getPath(outputArtifact.getPath().getParentDirectory().getPathString())
        .createDirectoryAndParents();
    actionFs
        .getPath(outputArtifact.getPath().getPathString())
        .createSymbolicLink(targetArtifact.getPath().asFragment());

    PathFragment expectedMaterializationExecPath =
        location == FileLocation.REMOTE && preexistingPath != null
            ? preexistingPath
            : targetArtifact.getExecPath();

    assertThat(store.getOutputMetadata(outputArtifact))
        .isEqualTo(createFileMetadataForSymlinkTest(location, expectedMaterializationExecPath));
  }

  private FileArtifactValue createFileMetadataForSymlinkTest(
      FileLocation location, @Nullable PathFragment materializationExecPath) {
    switch (location) {
      case LOCAL:
        FileArtifactValue target =
            FileArtifactValue.createForNormalFile(new byte[] {1, 2, 3}, /* proxy= */ null, 10);
        return materializationExecPath == null
            ? target
            : FileArtifactValue.createForResolvedSymlink(
                materializationExecPath, target, target.getDigest());
      case REMOTE:
        return RemoteFileArtifactValue.create(
            new byte[] {1, 2, 3}, 10, 1, -1, materializationExecPath);
    }
    throw new AssertionError();
  }

  @Test
  public void treeArtifactMaterializedAsSymlink(
      @TestParameter MaterializationPathDepth depth, @TestParameter TreeComposition composition)
      throws Exception {
    SpecialArtifact targetArtifact =
        ActionsTestUtil.createTreeArtifactWithGeneratingAction(outputRoot, "target");

    SpecialArtifact outputArtifact =
        ActionsTestUtil.createTreeArtifactWithGeneratingAction(outputRoot, "output");

    PathFragment preexistingPath =
        depth.equals(MaterializationPathDepth.DEEP)
            ? outputRoot.getExecPath().getRelative("preexisting")
            : null;

    TreeArtifactValue targetMetadata =
        createTreeMetadataForSymlinkTest(targetArtifact, composition, preexistingPath);

    ActionInputMap inputMap = new ActionInputMap(0);
    inputMap.putTreeArtifact(targetArtifact, targetMetadata, /* depOwner= */ null);

    RemoteActionFileSystem actionFs =
        createRemoteActionFileSystem(inputMap, ImmutableSet.of(outputArtifact));

    ActionOutputMetadataStore store = createStore(ImmutableSet.of(outputArtifact), actionFs);
    store.prepareForActionExecution();

    // In a realistic scenario, files with local metadata should also exist on disk.
    // However, the action filesystem is expected to obtain their metadata from the input map.
    actionFs
        .getPath(outputArtifact.getPath().getParentDirectory().getPathString())
        .createDirectoryAndParents();
    actionFs.getPath(targetArtifact.getPath().getPathString()).createDirectoryAndParents();
    actionFs
        .getPath(outputArtifact.getPath().getPathString())
        .createSymbolicLink(targetArtifact.getPath().asFragment());

    PathFragment expectedMaterializationExecPath =
        preexistingPath != null ? preexistingPath : targetArtifact.getExecPath();

    assertThat(store.getTreeArtifactValue(outputArtifact))
        .isEqualTo(
            createTreeMetadataForSymlinkTest(
                outputArtifact, composition, expectedMaterializationExecPath));
  }

  private TreeArtifactValue createTreeMetadataForSymlinkTest(
      SpecialArtifact parent,
      TreeComposition composition,
      @Nullable PathFragment materializationExecPath) {
    TreeArtifactValue.Builder builder = TreeArtifactValue.newBuilder(parent);

    TreeFileArtifact child1 = TreeFileArtifact.createTreeOutput(parent, "child1");
    TreeFileArtifact child2 = TreeFileArtifact.createTreeOutput(parent, "child2");

    FileArtifactValue localMetadata1 =
        FileArtifactValue.createForNormalFile(new byte[] {1, 2, 3}, /* proxy= */ null, 10);
    FileArtifactValue localMetadata2 =
        FileArtifactValue.createForNormalFile(new byte[] {1, 2, 3}, /* proxy= */ null, 20);

    RemoteFileArtifactValue remoteMetadata1 =
        RemoteFileArtifactValue.create(new byte[] {1, 2, 3}, 10, 1, -1);
    RemoteFileArtifactValue remoteMetadata2 =
        RemoteFileArtifactValue.create(new byte[] {4, 5, 6}, 20, 1, -1);

    switch (composition) {
      case EMPTY:
        break;
      case FULLY_LOCAL:
        builder.putChild(child1, localMetadata1);
        builder.putChild(child2, localMetadata2);
        break;
      case FULLY_REMOTE:
        builder.putChild(child1, remoteMetadata1);
        builder.putChild(child2, remoteMetadata2);
        break;
      case MIXED:
        builder.putChild(child1, localMetadata1);
        builder.putChild(child2, remoteMetadata2);
        break;
    }

    if (materializationExecPath != null) {
      builder.setMaterializationExecPath(materializationExecPath);
    }

    return builder.build();
  }

  @Test
  public void getMetadataFromFilesetMapping() throws Exception {
    FileArtifactValue directoryFav = FileArtifactValue.createForDirectoryWithMtime(10L);
    FileArtifactValue regularFav =
        FileArtifactValue.createForVirtualActionInput(new byte[] {1, 2, 3, 4}, 10L);
    HasDigest.ByteStringDigest byteStringDigest = new ByteStringDigest(new byte[] {2, 3, 4});

    ImmutableList<FilesetOutputSymlink> symlinks =
        ImmutableList.of(
            createFilesetOutputSymlink(directoryFav, "dir"),
            createFilesetOutputSymlink(regularFav, "file"),
            createFilesetOutputSymlink(byteStringDigest, "bytes"));

    Artifact artifact =
        ActionsTestUtil.createArtifactWithRootRelativePath(
            outputRoot, PathFragment.create("foo/bar"));
    ImmutableMap<Artifact, ImmutableList<FilesetOutputSymlink>> expandedFilesets =
        ImmutableMap.of(artifact, symlinks);

    ActionInputMetadataProvider inputMetadataProvider =
        new ActionInputMetadataProvider(
            execRoot.asFragment(), new ActionInputMap(0), expandedFilesets);

    // Only the regular FileArtifactValue should have its metadata stored.
    assertThat(inputMetadataProvider.getInputMetadata(createInput("dir"))).isNull();
    assertThat(inputMetadataProvider.getInputMetadata(createInput("file"))).isEqualTo(regularFav);
    assertThat(inputMetadataProvider.getInputMetadata(createInput("bytes"))).isNull();
    assertThat(inputMetadataProvider.getInputMetadata(createInput("does_not_exist"))).isNull();
    assertThat(chmodCalls).isEmpty();
  }

  private FilesetOutputSymlink createFilesetOutputSymlink(HasDigest digest, String identifier) {
    return FilesetOutputSymlink.create(
        PathFragment.create(identifier + "_symlink"),
        PathFragment.create(identifier),
        digest,
        execRoot.asFragment());
  }

  private ActionInput createInput(String identifier) {
    return ActionInputHelper.fromPath(execRoot.getRelative(identifier).getPathString());
  }

  @Test
  public void omitRegularArtifact() {
    Artifact omitted =
        ActionsTestUtil.createArtifactWithRootRelativePath(
            outputRoot, PathFragment.create("omitted"));
    Artifact consumed =
        ActionsTestUtil.createArtifactWithRootRelativePath(
            outputRoot, PathFragment.create("consumed"));
    ActionOutputMetadataStore store =
        createStore(/* outputs= */ ImmutableSet.of(omitted, consumed));

    store.prepareForActionExecution();
    store.markOmitted(omitted);

    assertThat(store.artifactOmitted(omitted)).isTrue();
    assertThat(store.artifactOmitted(consumed)).isFalse();
    assertThat(store.getAllArtifactData())
        .containsExactly(omitted, FileArtifactValue.OMITTED_FILE_MARKER);
    assertThat(store.getAllTreeArtifactData()).isEmpty();
    assertThat(chmodCalls).isEmpty();
  }

  @Test
  public void omitTreeArtifact() {
    SpecialArtifact omittedTree =
        ActionsTestUtil.createTreeArtifactWithGeneratingAction(
            outputRoot, PathFragment.create("omitted"));
    SpecialArtifact consumedTree =
        ActionsTestUtil.createTreeArtifactWithGeneratingAction(
            outputRoot, PathFragment.create("consumed"));
    ActionOutputMetadataStore store =
        createStore(/* outputs= */ ImmutableSet.of(omittedTree, consumedTree));

    store.prepareForActionExecution();
    store.markOmitted(omittedTree);
    store.markOmitted(omittedTree); // Marking a tree artifact as omitted twice is tolerated.

    assertThat(store.artifactOmitted(omittedTree)).isTrue();
    assertThat(store.artifactOmitted(consumedTree)).isFalse();
    assertThat(store.getAllTreeArtifactData())
        .containsExactly(omittedTree, TreeArtifactValue.OMITTED_TREE_MARKER);
    assertThat(store.getAllArtifactData()).isEmpty();
    assertThat(chmodCalls).isEmpty();
  }

  @Test
  public void outputArtifactNotPreviouslyInjectedInExecutionMode() throws Exception {
    Artifact output =
        ActionsTestUtil.createArtifactWithRootRelativePath(
            outputRoot, PathFragment.create("dir/file.out"));
    Path outputPath = scratch.file(output.getPath().getPathString(), "contents");
    ActionOutputMetadataStore store = createStore(/* outputs= */ ImmutableSet.of(output));
    store.prepareForActionExecution();

    FileArtifactValue metadata = store.getOutputMetadata(output);

    assertThat(metadata.getDigest()).isEqualTo(outputPath.getDigest());
    assertThat(store.getAllArtifactData()).containsExactly(output, metadata);
    assertThat(store.getAllTreeArtifactData()).isEmpty();
    assertThat(chmodCalls).containsExactly(outputPath, 0555);
  }

  @Test
  public void outputArtifactNotPreviouslyInjectedInExecutionMode_writablePermissions()
      throws Exception {
    Artifact output =
        ActionsTestUtil.createArtifactWithRootRelativePath(
            outputRoot, PathFragment.create("dir/file.out"));
    Path outputPath = scratch.file(output.getPath().getPathString(), "contents");
    ActionOutputMetadataStore store =
        ActionOutputMetadataStore.create(
            /* archivedTreeArtifactsEnabled= */ false,
            OutputPermissions.WRITABLE,
            /* outputs= */ ImmutableSet.of(output),
            SyscallCache.NO_CACHE,
            tsgm,
            ArtifactPathResolver.IDENTITY,
            execRoot.asFragment());
    store.prepareForActionExecution();

    FileArtifactValue metadata = store.getOutputMetadata(output);

    assertThat(metadata.getDigest()).isEqualTo(outputPath.getDigest());
    assertThat(store.getAllArtifactData()).containsExactly(output, metadata);
    assertThat(store.getAllTreeArtifactData()).isEmpty();
    // Permissions preserved in store, so chmod calls should be empty.
    assertThat(chmodCalls).containsExactly(outputPath, 0755);
  }

  @Test
  public void outputTreeArtifactNotPreviouslyInjectedInExecutionMode() throws Exception {
    SpecialArtifact treeArtifact =
        ActionsTestUtil.createTreeArtifactWithGeneratingAction(outputRoot, "foo/bar");
    TreeFileArtifact child1 = TreeFileArtifact.createTreeOutput(treeArtifact, "child1");
    TreeFileArtifact child2 = TreeFileArtifact.createTreeOutput(treeArtifact, "subdir/child2");
    Path child1Path = scratch.file(child1.getPath().getPathString(), "contents1");
    Path child2Path = scratch.file(child2.getPath().getPathString(), "contents2");
    ActionOutputMetadataStore store = createStore(/* outputs= */ ImmutableSet.of(treeArtifact));
    store.prepareForActionExecution();

    FileArtifactValue treeMetadata = store.getOutputMetadata(treeArtifact);
    FileArtifactValue child1Metadata = store.getOutputMetadata(child1);
    FileArtifactValue child2Metadata = store.getOutputMetadata(child2);
    TreeArtifactValue tree = store.getAllTreeArtifactData().get(treeArtifact);

    assertThat(tree.getMetadata()).isEqualTo(treeMetadata);
    assertThat(tree.getChildValues())
        .containsExactly(child1, child1Metadata, child2, child2Metadata);
    assertThat(store.getTreeArtifactChildren(treeArtifact)).isEqualTo(tree.getChildren());
    assertThat(store.getAllArtifactData()).isEmpty();
    assertThat(chmodCalls)
        .containsExactly(
            treeArtifact.getPath(),
            0555,
            child1Path,
            0555,
            child2Path,
            0555,
            child2Path.getParentDirectory(),
            0555);
  }

  @Test
  public void getTreeArtifactChildren_noData_returnsEmptySet() {
    SpecialArtifact treeArtifact =
        ActionsTestUtil.createTreeArtifactWithGeneratingAction(
            outputRoot, PathFragment.create("tree"));
    ActionOutputMetadataStore store = createStore(/* outputs= */ ImmutableSet.of(treeArtifact));
    assertThat(store.getTreeArtifactChildren(treeArtifact)).isEmpty();
  }

  @Test
  public void enteringExecutionModeClearsCachedOutputs() throws Exception {
    Artifact artifact =
        ActionsTestUtil.createArtifactWithRootRelativePath(
            outputRoot, PathFragment.create("output"));
    SpecialArtifact treeArtifact =
        ActionsTestUtil.createTreeArtifactWithGeneratingAction(outputRoot, "tree");
    TreeFileArtifact child = TreeFileArtifact.createTreeOutput(treeArtifact, "child");
    scratch.file(artifact.getPath().getPathString(), "1");
    scratch.file(child.getPath().getPathString(), "1");
    ActionOutputMetadataStore store =
        createStore(/* outputs= */ ImmutableSet.of(artifact, treeArtifact));

    FileArtifactValue artifactMetadata1 = store.getOutputMetadata(artifact);
    FileArtifactValue treeArtifactMetadata1 = store.getOutputMetadata(treeArtifact);
    assertThat(artifactMetadata1).isNotNull();
    assertThat(artifactMetadata1).isNotNull();
    assertThat(store.getAllArtifactData().keySet()).containsExactly(artifact);
    assertThat(store.getAllTreeArtifactData().keySet()).containsExactly(treeArtifact);

    // Entering execution mode should clear the cached outputs.
    store.prepareForActionExecution();
    assertThat(store.getAllArtifactData()).isEmpty();
    assertThat(store.getAllTreeArtifactData()).isEmpty();

    // Updated metadata should be read from the filesystem.
    scratch.overwriteFile(artifact.getPath().getPathString(), "2");
    scratch.overwriteFile(child.getPath().getPathString(), "2");
    FileArtifactValue artifactMetadata2 = store.getOutputMetadata(artifact);
    FileArtifactValue treeArtifactMetadata2 = store.getOutputMetadata(treeArtifact);
    assertThat(artifactMetadata2).isNotNull();
    assertThat(treeArtifactMetadata2).isNotNull();
    assertThat(artifactMetadata2).isNotEqualTo(artifactMetadata1);
    assertThat(treeArtifactMetadata2).isNotEqualTo(treeArtifactMetadata1);
  }

  @Test
  public void cannotEnterExecutionModeTwice() {
    ActionOutputMetadataStore store = createStore(/* outputs= */ ImmutableSet.of());
    store.prepareForActionExecution();
    assertThrows(IllegalStateException.class, store::prepareForActionExecution);
  }

  @Test
  public void fileArtifactValueFromArtifactCompatibleWithGetMetadata_changed() throws Exception {
    Artifact artifact =
        ActionsTestUtil.createArtifactWithRootRelativePath(
            outputRoot, PathFragment.create("output"));
    scratch.file(artifact.getPath().getPathString(), "1");
    ActionOutputMetadataStore store = createStore(/* outputs= */ ImmutableSet.of(artifact));

    FileArtifactValue getMetadataResult = store.getOutputMetadata(artifact);
    assertThat(getMetadataResult).isNotNull();

    scratch.overwriteFile(artifact.getPath().getPathString(), "2");
    FileArtifactValue fileArtifactValueFromArtifactResult =
        ActionOutputMetadataStore.fileArtifactValueFromArtifact(
            artifact, /* statNoFollow= */ null, SyscallCache.NO_CACHE, /* tsgm= */ null);
    assertThat(fileArtifactValueFromArtifactResult).isNotNull();

    assertThat(fileArtifactValueFromArtifactResult.couldBeModifiedSince(getMetadataResult))
        .isTrue();
  }

  @Test
  public void fileArtifactValueFromArtifactCompatibleWithGetMetadata_notChanged() throws Exception {
    Artifact artifact =
        ActionsTestUtil.createArtifactWithRootRelativePath(
            outputRoot, PathFragment.create("output"));
    scratch.file(artifact.getPath().getPathString(), "contents");
    ActionOutputMetadataStore store = createStore(/* outputs= */ ImmutableSet.of(artifact));

    FileArtifactValue getMetadataResult = store.getOutputMetadata(artifact);
    assertThat(getMetadataResult).isNotNull();

    FileArtifactValue fileArtifactValueFromArtifactResult =
        ActionOutputMetadataStore.fileArtifactValueFromArtifact(
            artifact, /* statNoFollow= */ null, SyscallCache.NO_CACHE, /* tsgm= */ null);
    assertThat(fileArtifactValueFromArtifactResult).isNotNull();

    assertThat(fileArtifactValueFromArtifactResult.couldBeModifiedSince(getMetadataResult))
        .isFalse();
  }

  @Test
  public void fileArtifactValueForSymlink_readFromCache() throws Exception {
    DigestUtils.configureCache(1);
    Artifact target =
        ActionsTestUtil.createArtifactWithRootRelativePath(
            outputRoot, PathFragment.create("target"));
    scratch.file(target.getPath().getPathString(), "contents");
    Artifact symlink =
        ActionsTestUtil.createArtifactWithRootRelativePath(
            outputRoot, PathFragment.create("symlink"));
    scratch
        .getFileSystem()
        .getPath(symlink.getPath().getPathString())
        .createSymbolicLink(scratch.getFileSystem().getPath(target.getPath().getPathString()));
    ActionOutputMetadataStore store = createStore(/* outputs= */ ImmutableSet.of(target, symlink));
    var targetMetadata = store.getOutputMetadata(target);
    assertThat(DigestUtils.getCacheStats().hitCount()).isEqualTo(0);

    var symlinkMetadata = store.getOutputMetadata(symlink);

    assertThat(symlinkMetadata.getDigest()).isEqualTo(targetMetadata.getDigest());
    assertThat(DigestUtils.getCacheStats().hitCount()).isEqualTo(1);
  }
}
