// 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.lib.actions.FileArtifactValue.create;
import static org.junit.Assert.fail;

import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Iterables;
import com.google.devtools.build.lib.actions.Action;
import com.google.devtools.build.lib.actions.ActionAnalysisMetadata.MiddlemanType;
import com.google.devtools.build.lib.actions.ActionInputHelper;
import com.google.devtools.build.lib.actions.ActionLookupData;
import com.google.devtools.build.lib.actions.ActionLookupValue;
import com.google.devtools.build.lib.actions.Actions;
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.SpecialArtifactType;
import com.google.devtools.build.lib.actions.Artifact.TreeFileArtifact;
import com.google.devtools.build.lib.actions.ArtifactFileMetadata;
import com.google.devtools.build.lib.actions.ArtifactOwner;
import com.google.devtools.build.lib.actions.ArtifactRoot;
import com.google.devtools.build.lib.actions.ArtifactSkyKey;
import com.google.devtools.build.lib.actions.BasicActionLookupValue;
import com.google.devtools.build.lib.actions.FileArtifactValue;
import com.google.devtools.build.lib.actions.FilesetOutputSymlink;
import com.google.devtools.build.lib.actions.MissingInputFileException;
import com.google.devtools.build.lib.actions.MutableActionGraph.ActionConflictException;
import com.google.devtools.build.lib.actions.util.ActionsTestUtil;
import com.google.devtools.build.lib.actions.util.TestAction.DummyAction;
import com.google.devtools.build.lib.events.NullEventHandler;
import com.google.devtools.build.lib.skyframe.serialization.testutils.SerializationTester;
import com.google.devtools.build.lib.util.Pair;
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.Path;
import com.google.devtools.build.lib.vfs.PathFragment;
import com.google.devtools.build.lib.vfs.Root;
import com.google.devtools.build.skyframe.EvaluationContext;
import com.google.devtools.build.skyframe.EvaluationResult;
import com.google.devtools.build.skyframe.SkyFunction;
import com.google.devtools.build.skyframe.SkyKey;
import com.google.devtools.build.skyframe.SkyValue;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.security.MessageDigest;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.JUnit4;

/**
 * Tests for {@link ArtifactFunction}.
 */
// Doesn't actually need any particular Skyframe, but is only relevant to Skyframe full mode.
@RunWith(JUnit4.class)
public class ArtifactFunctionTest extends ArtifactFunctionTestCase {

  @Before
  public final void setUp() throws Exception  {
    delegateActionExecutionFunction = new SimpleActionExecutionFunction();
  }

  private void assertFileArtifactValueMatches(boolean expectDigest) throws Throwable {
    Artifact output = createDerivedArtifact("output");
    Path path = output.getPath();
    file(path, "contents");
    assertValueMatches(path.stat(), expectDigest ? path.getDigest() : null, evaluateFAN(output));
  }

  @Test
  public void testBasicArtifact() throws Throwable {
    fastDigest = false;
    assertFileArtifactValueMatches(/*expectDigest=*/ true);
  }

  @Test
  public void testBasicArtifactWithXattr() throws Throwable {
    fastDigest = true;
    assertFileArtifactValueMatches(/*expectDigest=*/ true);
  }

  @Test
  public void testMissingNonMandatoryArtifact() throws Throwable {
    Artifact input = createSourceArtifact("input1");
    assertThat(evaluateArtifactValue(input, /*mandatory=*/ false)).isNotNull();
  }

  @Test
  public void testUnreadableInputWithFsWithAvailableDigest() throws Throwable {
    final byte[] expectedDigest = MessageDigest.getInstance("md5").digest(
        "someunreadablecontent".getBytes(StandardCharsets.UTF_8));
    setupRoot(
        new CustomInMemoryFs() {
          @Override
          public byte[] getDigest(Path path) throws IOException {
            return path.getBaseName().equals("unreadable") ? expectedDigest : super.getDigest(path);
          }
        });

    Artifact input = createSourceArtifact("unreadable");
    Path inputPath = input.getPath();
    file(inputPath, "dummynotused");
    inputPath.chmod(0);

    FileArtifactValue value =
        (FileArtifactValue) evaluateArtifactValue(input, /*mandatory=*/ true);

    FileStatus stat = inputPath.stat();
    assertThat(value.getSize()).isEqualTo(stat.getSize());
    assertThat(value.getDigest()).isEqualTo(expectedDigest);
  }

  @Test
  public void testMissingMandatoryArtifact() throws Throwable {
    Artifact input = createSourceArtifact("input1");
    try {
      evaluateArtifactValue(input, /*mandatory=*/ true);
      fail();
    } catch (MissingInputFileException ex) {
      // Expected.
    }
  }

  @Test
  public void testMiddlemanArtifact() throws Throwable {
    Artifact output = createMiddlemanArtifact("output");
    Artifact input1 = createSourceArtifact("input1");
    Artifact input2 = createDerivedArtifact("input2");
    SpecialArtifact tree = createDerivedTreeArtifactWithAction("treeArtifact");
    TreeFileArtifact treeFile1 = createFakeTreeFileArtifact(tree, "child1", "hello1");
    TreeFileArtifact treeFile2 = createFakeTreeFileArtifact(tree, "child2", "hello2");
    file(treeFile1.getPath(), "src1");
    file(treeFile2.getPath(), "src2");
    Action action =
        new DummyAction(
            ImmutableList.of(input1, input2, tree), output, MiddlemanType.AGGREGATING_MIDDLEMAN);
    actions.add(action);
    file(input2.getPath(), "contents");
    file(input1.getPath(), "source contents");
    evaluate(Iterables.toArray(ImmutableSet.of(input2, input1, input2, tree), SkyKey.class));
    SkyValue value = evaluateArtifactValue(output);
    ArrayList<Pair<Artifact, ?>> inputs = new ArrayList<>();
    inputs.addAll(((AggregatingArtifactValue) value).getFileArtifacts());
    inputs.addAll(((AggregatingArtifactValue) value).getTreeArtifacts());
    assertThat(inputs)
        .containsExactly(
            Pair.of(input1, create(input1)),
            Pair.of(input2, create(input2)),
            Pair.of(tree, ((TreeArtifactValue) evaluateArtifactValue(tree))));
  }

  /**
   * Tests that ArtifactFunction rethrows transitive {@link IOException}s as
   * {@link MissingInputFileException}s.
   */
  @Test
  public void testIOException_EndToEnd() throws Throwable {
    final IOException exception = new IOException("beep");
    setupRoot(
        new CustomInMemoryFs() {
          @Override
          public FileStatus statIfFound(Path path, boolean followSymlinks) throws IOException {
            if (path.getBaseName().equals("bad")) {
              throw exception;
            }
            return super.statIfFound(path, followSymlinks);
          }
        });
    try {
      evaluateArtifactValue(createSourceArtifact("bad"));
      fail();
    } catch (MissingInputFileException e) {
      assertThat(e).hasMessageThat().contains(exception.getMessage());
    }
  }

  @Test
  public void testActionTreeArtifactOutput() throws Throwable {
    SpecialArtifact artifact = createDerivedTreeArtifactWithAction("treeArtifact");
    TreeFileArtifact treeFileArtifact1 =
        createFakeTreeFileArtifact(artifact, ALL_OWNER, "child1", "hello1");
    TreeFileArtifact treeFileArtifact2 =
        createFakeTreeFileArtifact(artifact, ALL_OWNER, "child2", "hello2");

    TreeArtifactValue value = (TreeArtifactValue) evaluateArtifactValue(artifact);
    assertThat(value.getChildValues()).containsKey(treeFileArtifact1);
    assertThat(value.getChildValues()).containsKey(treeFileArtifact2);
    assertThat(value.getChildValues().get(treeFileArtifact1).getDigest()).isNotNull();
    assertThat(value.getChildValues().get(treeFileArtifact2).getDigest()).isNotNull();
  }

  @Test
  public void testSpawnActionTemplate() throws Throwable {
    // artifact1 is a tree artifact generated by normal action.
    SpecialArtifact artifact1 = createDerivedTreeArtifactWithAction("treeArtifact1");
    createFakeTreeFileArtifact(artifact1, "child1", "hello1");
    createFakeTreeFileArtifact(artifact1, "child2", "hello2");

    // artifact2 is a tree artifact generated by action template.
    SpecialArtifact artifact2 = createDerivedTreeArtifactOnly("treeArtifact2");
    TreeFileArtifact treeFileArtifact1 =
        createFakeTreeFileArtifact(
            artifact2,
            ActionTemplateExpansionValue.ActionTemplateExpansionKey.of(
                (ActionLookupValue.ActionLookupKey) artifact2.getArtifactOwner(), 1),
            "child1",
            "hello1");
    TreeFileArtifact treeFileArtifact2 =
        createFakeTreeFileArtifact(
            artifact2,
            ActionTemplateExpansionValue.ActionTemplateExpansionKey.of(
                (ActionLookupValue.ActionLookupKey) artifact2.getArtifactOwner(), 1),
            "child2",
            "hello2");

    actions.add(
        ActionsTestUtil.createDummySpawnActionTemplate(artifact1, artifact2));

    TreeArtifactValue value = (TreeArtifactValue) evaluateArtifactValue(artifact2);
    assertThat(value.getChildValues()).containsKey(treeFileArtifact1);
    assertThat(value.getChildValues()).containsKey(treeFileArtifact2);
    assertThat(value.getChildValues().get(treeFileArtifact1).getDigest()).isNotNull();
    assertThat(value.getChildValues().get(treeFileArtifact2).getDigest()).isNotNull();
  }

  @Test
  public void testConsecutiveSpawnActionTemplates() throws Throwable {
    // artifact1 is a tree artifact generated by normal action.
    SpecialArtifact artifact1 = createDerivedTreeArtifactWithAction("treeArtifact1");
    createFakeTreeFileArtifact(artifact1, "child1", "hello1");
    createFakeTreeFileArtifact(artifact1, "child2", "hello2");

    // artifact2 is a tree artifact generated by action template.
    SpecialArtifact artifact2 = createDerivedTreeArtifactOnly("treeArtifact2");
    createFakeTreeFileArtifact(artifact2, "child1", "hello1");
    createFakeTreeFileArtifact(artifact2, "child2", "hello2");
    actions.add(
        ActionsTestUtil.createDummySpawnActionTemplate(artifact1, artifact2));

    // artifact3 is a tree artifact generated by action template.
    SpecialArtifact artifact3 = createDerivedTreeArtifactOnly("treeArtifact3");
    TreeFileArtifact treeFileArtifact1 =
        createFakeTreeFileArtifact(
            artifact3,
            ActionTemplateExpansionValue.ActionTemplateExpansionKey.of(
                (ActionLookupValue.ActionLookupKey) artifact2.getArtifactOwner(), 2),
            "child1",
            "hello1");
    TreeFileArtifact treeFileArtifact2 =
        createFakeTreeFileArtifact(
            artifact3,
            ActionTemplateExpansionValue.ActionTemplateExpansionKey.of(
                (ActionLookupValue.ActionLookupKey) artifact2.getArtifactOwner(), 2),
            "child2",
            "hello2");
    actions.add(
        ActionsTestUtil.createDummySpawnActionTemplate(artifact2, artifact3));

    TreeArtifactValue value = (TreeArtifactValue) evaluateArtifactValue(artifact3);
    assertThat(value.getChildValues()).containsKey(treeFileArtifact1);
    assertThat(value.getChildValues()).containsKey(treeFileArtifact2);
    assertThat(value.getChildValues().get(treeFileArtifact1).getDigest()).isNotNull();
    assertThat(value.getChildValues().get(treeFileArtifact2).getDigest()).isNotNull();
  }

  @Test
  public void actionExecutionValueSerialization() throws Exception {
    Artifact artifact1 = createDerivedArtifact("one");
    Artifact artifact2 = createDerivedArtifact("two");
    ArtifactFileMetadata metadata1 =
        ActionMetadataHandler.fileMetadataFromArtifact(artifact1, null, null);
    SpecialArtifact treeArtifact = createDerivedTreeArtifactOnly("tree");
    TreeFileArtifact treeFileArtifact =
        createFakeTreeFileArtifact(treeArtifact, "subpath", "content");
    TreeArtifactValue treeArtifactValue =
        TreeArtifactValue.create(
            ImmutableMap.of(treeFileArtifact, FileArtifactValue.create(treeFileArtifact)));
    Artifact artifact3 = createDerivedArtifact("three");
    FilesetOutputSymlink filesetOutputSymlink =
        FilesetOutputSymlink.createForTesting(
            PathFragment.EMPTY_FRAGMENT, PathFragment.EMPTY_FRAGMENT, PathFragment.EMPTY_FRAGMENT);
    ActionExecutionValue actionExecutionValue =
        ActionExecutionValue.create(
            ImmutableMap.of(artifact1, metadata1, artifact2, ArtifactFileMetadata.PLACEHOLDER),
            ImmutableMap.of(treeArtifact, treeArtifactValue),
            ImmutableMap.of(artifact3, FileArtifactValue.DEFAULT_MIDDLEMAN),
            ImmutableList.of(filesetOutputSymlink),
            null,
            true);
    ActionExecutionValue valueWithFingerprint =
        ActionExecutionValue.create(
            ImmutableMap.of(artifact1, metadata1, artifact2, ArtifactFileMetadata.PLACEHOLDER),
            ImmutableMap.of(treeArtifact, treeArtifactValue),
            ImmutableMap.of(artifact3, FileArtifactValue.DEFAULT_MIDDLEMAN),
            ImmutableList.of(filesetOutputSymlink),
            null,
            true);
    valueWithFingerprint.getValueFingerprint();
    new SerializationTester(actionExecutionValue, valueWithFingerprint)
        .addDependency(FileSystem.class, root.getFileSystem())
        .runTests();
  }

  private void file(Path path, String contents) throws Exception {
    FileSystemUtils.createDirectoryAndParents(path.getParentDirectory());
    writeFile(path, contents);
  }

  private Artifact createSourceArtifact(String path) {
    return new Artifact.SourceArtifact(
        ArtifactRoot.asSourceRoot(Root.fromPath(root)),
        PathFragment.create(path),
        ArtifactOwner.NullArtifactOwner.INSTANCE);
  }

  private Artifact createDerivedArtifact(String path) {
    PathFragment execPath = PathFragment.create("out").getRelative(path);
    Artifact output =
        new Artifact(
            ArtifactRoot.asDerivedRoot(root, root.getRelative("out")),
            execPath,
            ALL_OWNER);
    actions.add(new DummyAction(ImmutableList.<Artifact>of(), output));
    return output;
  }

  private Artifact createMiddlemanArtifact(String path) {
    ArtifactRoot middlemanRoot =
        ArtifactRoot.middlemanRoot(middlemanPath, middlemanPath.getRelative("out"));
    return new Artifact(middlemanRoot, middlemanRoot.getExecPath().getRelative(path), ALL_OWNER);
  }

  private SpecialArtifact createDerivedTreeArtifactWithAction(String path) {
    SpecialArtifact treeArtifact = createDerivedTreeArtifactOnly(path);
    actions.add(new DummyAction(ImmutableList.<Artifact>of(), treeArtifact));
    return treeArtifact;
  }

  private SpecialArtifact createDerivedTreeArtifactOnly(String path) {
    PathFragment execPath = PathFragment.create("out").getRelative(path);
    return new SpecialArtifact(
        ArtifactRoot.asDerivedRoot(root, root.getRelative("out")),
        execPath,
        ALL_OWNER,
        SpecialArtifactType.TREE);
  }

  private TreeFileArtifact createFakeTreeFileArtifact(
      SpecialArtifact treeArtifact, String parentRelativePath, String content) throws Exception {
    return createFakeTreeFileArtifact(
        treeArtifact,
        ActionTemplateExpansionValue.ActionTemplateExpansionKey.of(
            (ActionLookupValue.ActionLookupKey) treeArtifact.getArtifactOwner(), 0),
        parentRelativePath,
        content);
  }

  private TreeFileArtifact createFakeTreeFileArtifact(
      SpecialArtifact treeArtifact,
      ArtifactOwner artifactOwner,
      String parentRelativePath,
      String content)
      throws Exception {
    TreeFileArtifact treeFileArtifact =
        ActionInputHelper.treeFileArtifact(
            treeArtifact, PathFragment.create(parentRelativePath), artifactOwner);
    Path path = treeFileArtifact.getPath();
    FileSystemUtils.createDirectoryAndParents(path.getParentDirectory());
    writeFile(path, content);
    return treeFileArtifact;
  }

  private void assertValueMatches(FileStatus file, byte[] digest, FileArtifactValue value)
      throws IOException {
    assertThat(value.getSize()).isEqualTo(file.getSize());
    if (digest == null) {
      assertThat(value.getDigest()).isNull();
      assertThat(value.getModifiedTime()).isEqualTo(file.getLastModifiedTime());
    } else {
      assertThat(value.getDigest()).isEqualTo(digest);
    }
  }

  private FileArtifactValue evaluateFAN(Artifact artifact) throws Throwable {
    return ((FileArtifactValue) evaluateArtifactValue(artifact));
  }

  private SkyValue evaluateArtifactValue(Artifact artifact) throws Throwable {
    return evaluateArtifactValue(artifact, /* mandatory= */ true);
  }

  private SkyValue evaluateArtifactValue(Artifact artifact, boolean mandatory) throws Throwable {
    SkyKey key = ArtifactSkyKey.key(artifact, mandatory);
    EvaluationResult<SkyValue> result = evaluate(ImmutableList.of(key).toArray(new SkyKey[0]));
    if (result.hasError()) {
      throw result.getError().getException();
    }
    return result.get(key);
  }

  private void setGeneratingActions() throws InterruptedException, ActionConflictException {
    if (evaluator.getExistingValue(ALL_OWNER) == null) {
      differencer.inject(
          ImmutableMap.of(
              ALL_OWNER,
              new BasicActionLookupValue(
                  Actions.filterSharedActionsAndThrowActionConflict(
                      actionKeyContext, ImmutableList.copyOf(actions)),
                  /*nonceVersion=*/ null)));
    }
  }

  private <E extends SkyValue> EvaluationResult<E> evaluate(SkyKey... keys)
      throws InterruptedException, ActionConflictException {
    setGeneratingActions();
    EvaluationContext evaluationContext =
        EvaluationContext.newBuilder()
            .setKeepGoing(false)
            .setNumThreads(SkyframeExecutor.DEFAULT_THREAD_COUNT)
            .setEventHander(NullEventHandler.INSTANCE)
            .build();
    return driver.evaluate(Arrays.asList(keys), evaluationContext);
  }

  /** Value Builder for actions that just stats and stores the output file (which must exist). */
  private static class SimpleActionExecutionFunction implements SkyFunction {
    @Override
    public SkyValue compute(SkyKey skyKey, Environment env) throws InterruptedException {
      Map<Artifact, ArtifactFileMetadata> artifactData = new HashMap<>();
      Map<Artifact, TreeArtifactValue> treeArtifactData = new HashMap<>();
      Map<Artifact, FileArtifactValue> additionalOutputData = new HashMap<>();
      ActionLookupData actionLookupData = (ActionLookupData) skyKey.argument();
      ActionLookupValue actionLookupValue =
          (ActionLookupValue) env.getValue(actionLookupData.getActionLookupKey());
      Action action = actionLookupValue.getAction(actionLookupData.getActionIndex());
      Artifact output = Iterables.getOnlyElement(action.getOutputs());

      try {
        if (output.isTreeArtifact()) {
          TreeFileArtifact treeFileArtifact1 = ActionInputHelper.treeFileArtifact(
              (SpecialArtifact) output, PathFragment.create("child1"));
          TreeFileArtifact treeFileArtifact2 = ActionInputHelper.treeFileArtifact(
              (SpecialArtifact) output, PathFragment.create("child2"));
          TreeArtifactValue treeArtifactValue = TreeArtifactValue.create(ImmutableMap.of(
              treeFileArtifact1, FileArtifactValue.create(treeFileArtifact1),
              treeFileArtifact2, FileArtifactValue.create(treeFileArtifact2)));
          treeArtifactData.put(output, treeArtifactValue);
        } else if (action.getActionType() == MiddlemanType.NORMAL) {
          ArtifactFileMetadata fileValue =
              ActionMetadataHandler.fileMetadataFromArtifact(output, null, null);
          artifactData.put(output, fileValue);
          additionalOutputData.put(output, FileArtifactValue.create(output, fileValue));
       } else {
          additionalOutputData.put(output, FileArtifactValue.DEFAULT_MIDDLEMAN);
        }
      } catch (IOException e) {
        throw new IllegalStateException(e);
      }
      return ActionExecutionValue.create(
          artifactData,
          treeArtifactData,
          additionalOutputData,
          /*outputSymlinks=*/ null,
          /*discoveredModules=*/ null,
          /*actionDependsOnBuildId=*/ false);
    }

    @Override
    public String extractTag(SkyKey skyKey) {
      return null;
    }
  }
}
