// Copyright 2020 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.collect.ImmutableList.toImmutableList;
import static com.google.common.truth.Truth.assertThat;

import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
import com.google.devtools.build.lib.actions.ActionLookupData;
import com.google.devtools.build.lib.actions.Artifact.ArchivedTreeArtifact;
import com.google.devtools.build.lib.actions.Artifact.SpecialArtifact;
import com.google.devtools.build.lib.actions.Artifact.TreeFileArtifact;
import com.google.devtools.build.lib.vfs.ModifiedFileSet;
import com.google.devtools.build.skyframe.SkyKey;
import com.google.devtools.build.skyframe.SkyValue;
import java.io.IOException;
import java.util.Arrays;
import java.util.Collection;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.Parameterized;
import org.junit.runners.Parameterized.Parameter;
import org.junit.runners.Parameterized.Parameters;

/** {@link FilesystemValueChecker} checker parameterized on {@link BatchStatMode}. */
// TODO(b/207545453): Merge with FilesystemValueCheckerTest{,Base}.
@RunWith(Parameterized.class)
public final class FilesystemValueCheckerParameterizedTest extends FilesystemValueCheckerTestBase {

  private static final ActionLookupData ACTION_LOOKUP_DATA = actionLookupData(0);

  @Parameter public BatchStatMode batchStat;

  @Parameters(name = "batchStat={0}")
  public static ImmutableList<Object[]> batchStatModes() {
    return Arrays.stream(BatchStatMode.values())
        .map(mode -> new BatchStatMode[] {mode})
        .collect(toImmutableList());
  }

  @Test
  public void getDirtyActionValues_unchangedEmptyTreeArtifactWithArchivedFile_noDirtyKeys()
      throws Exception {
    SpecialArtifact treeArtifact = createTreeArtifact("dir");
    treeArtifact.getPath().createDirectoryAndParents();
    ActionExecutionValue actionExecutionValue =
        actionValueWithTreeArtifacts(
            ImmutableList.of(),
            ImmutableList.of(createArchivedTreeArtifactWithContent(treeArtifact)));

    assertThat(getDirtyActionValues(actionExecutionValue)).isEmpty();
  }

  @Test
  public void getDirtyActionValues_unchangedTreeArtifactWithArchivedFile_noDirtyKeys()
      throws Exception {
    SpecialArtifact treeArtifact = createTreeArtifact("dir");
    ActionExecutionValue actionExecutionValue =
        actionValueWithTreeArtifacts(
            ImmutableList.of(
                createTreeFileArtifactWithContent(treeArtifact, "file1", "content"),
                createTreeFileArtifactWithContent(treeArtifact, "file2", "content2")),
            ImmutableList.of(createArchivedTreeArtifactWithContent(treeArtifact)));

    assertThat(getDirtyActionValues(actionExecutionValue)).isEmpty();
  }

  @Test
  public void getDirtyActionValues_editedArchivedFileForEmptyTreeArtifact_reportsChange()
      throws Exception {
    SpecialArtifact treeArtifact = createTreeArtifact("dir");
    treeArtifact.getPath().createDirectoryAndParents();
    ArchivedTreeArtifact archivedTreeArtifact =
        createArchivedTreeArtifactWithContent(treeArtifact, "old content");
    ActionExecutionValue actionExecutionValue =
        actionValueWithTreeArtifacts(ImmutableList.of(), ImmutableList.of(archivedTreeArtifact));

    writeFile(archivedTreeArtifact.getPath(), "new content");
    assertThat(getDirtyActionValues(actionExecutionValue)).containsExactly(ACTION_LOOKUP_DATA);
  }

  @Test
  public void getDirtyActionValues_editedArchivedFileForTreeArtifact_reportsChange()
      throws Exception {
    SpecialArtifact treeArtifact = createTreeArtifact("dir");
    ArchivedTreeArtifact archivedTreeArtifact =
        createArchivedTreeArtifactWithContent(treeArtifact, "old content");
    ActionExecutionValue actionExecutionValue =
        actionValueWithTreeArtifacts(
            ImmutableList.of(
                createTreeFileArtifactWithContent(
                    treeArtifact, /*parentRelativePath=*/ "file1", "content"),
                createTreeFileArtifactWithContent(
                    treeArtifact, /*parentRelativePath=*/ "file2", "content2")),
            ImmutableList.of(archivedTreeArtifact));

    writeFile(archivedTreeArtifact.getPath(), "new content");
    assertThat(getDirtyActionValues(actionExecutionValue)).containsExactly(ACTION_LOOKUP_DATA);
  }

  @Test
  public void getDirtyActionValues_deletedArchivedFileForTreeArtifact_reportsChange()
      throws Exception {
    SpecialArtifact treeArtifact = createTreeArtifact("dir");
    ArchivedTreeArtifact archivedTreeArtifact = createArchivedTreeArtifactWithContent(treeArtifact);
    ActionExecutionValue actionExecutionValue =
        actionValueWithTreeArtifacts(
            ImmutableList.of(
                createTreeFileArtifactWithContent(
                    treeArtifact, /*parentRelativePath=*/ "file1", "content"),
                createTreeFileArtifactWithContent(
                    treeArtifact, /*parentRelativePath=*/ "file2", "content2")),
            ImmutableList.of(archivedTreeArtifact));

    archivedTreeArtifact.getPath().delete();
    assertThat(getDirtyActionValues(actionExecutionValue)).containsExactly(ACTION_LOOKUP_DATA);
  }

  @Test
  public void getDirtyActionValues_deletedArchivedFileForEmptyTreeArtifact_reportsChange()
      throws Exception {
    SpecialArtifact treeArtifact = createTreeArtifact("dir");
    ArchivedTreeArtifact archivedTreeArtifact = createArchivedTreeArtifactWithContent(treeArtifact);
    ActionExecutionValue actionExecutionValue =
        actionValueWithTreeArtifacts(ImmutableList.of(), ImmutableList.of(archivedTreeArtifact));

    archivedTreeArtifact.getPath().delete();
    assertThat(getDirtyActionValues(actionExecutionValue)).containsExactly(ACTION_LOOKUP_DATA);
  }

  @Test
  public void getDirtyActionValues_editedFileForTreeArtifactWithArchivedFile_reportsChange()
      throws Exception {
    SpecialArtifact treeArtifact = createTreeArtifact("dir");
    TreeFileArtifact child1 =
        createTreeFileArtifactWithContent(
            treeArtifact, /*parentRelativePath=*/ "file1", "old content");
    ActionExecutionValue actionExecutionValue =
        actionValueWithTreeArtifacts(
            ImmutableList.of(
                child1,
                createTreeFileArtifactWithContent(
                    treeArtifact, /*parentRelativePath=*/ "file2", "content2")),
            ImmutableList.of(createArchivedTreeArtifactWithContent(treeArtifact)));

    writeFile(child1.getPath(), "new content");
    assertThat(getDirtyActionValues(actionExecutionValue)).containsExactly(ACTION_LOOKUP_DATA);
  }

  @Test
  public void getDirtyActionValues_treeArtifactWithArchivedArtifact_reportsOnlyChangedKey()
      throws Exception {
    SpecialArtifact unchangedTreeArtifact = createTreeArtifact("dir1");
    ActionExecutionValue unchangedValue =
        actionValueWithTreeArtifacts(
            ImmutableList.of(createTreeFileArtifactWithContent(unchangedTreeArtifact, "child")),
            ImmutableList.of(createArchivedTreeArtifactWithContent(unchangedTreeArtifact)));
    SpecialArtifact changedTreeArtifact = createTreeArtifact("dir2");
    ArchivedTreeArtifact changedArchivedTreeArtifact =
        createArchivedTreeArtifactWithContent(changedTreeArtifact, "old content");
    ActionExecutionValue changedValue =
        actionValueWithTreeArtifacts(
            ImmutableList.of(
                createTreeFileArtifactWithContent(changedTreeArtifact, "file", "content")),
            ImmutableList.of(changedArchivedTreeArtifact));

    writeFile(changedArchivedTreeArtifact.getPath(), "new content");
    assertThat(
            getDirtyActionValues(
                ImmutableMap.of(
                    actionLookupData(0), unchangedValue, actionLookupData(1), changedValue)))
        .containsExactly(actionLookupData(1));
  }

  private Collection<SkyKey> getDirtyActionValues(ActionExecutionValue actionExecutionValue)
      throws InterruptedException {
    return getDirtyActionValues(ImmutableMap.of(ACTION_LOOKUP_DATA, actionExecutionValue));
  }

  private Collection<SkyKey> getDirtyActionValues(ImmutableMap<SkyKey, SkyValue> valuesMap)
      throws InterruptedException {
    return new FilesystemValueChecker(
            /*tsgm=*/ null, /*lastExecutionTimeRange=*/ null, FSVC_THREADS_FOR_TEST)
        .getDirtyActionValues(
            valuesMap,
            batchStat.getBatchStat(fs),
            ModifiedFileSet.EVERYTHING_MODIFIED,
            /*trustRemoteArtifacts=*/ false);
  }

  private TreeFileArtifact createTreeFileArtifactWithContent(
      SpecialArtifact treeArtifact, String parentRelativePath, String... contentLines)
      throws IOException {
    TreeFileArtifact artifact = TreeFileArtifact.createTreeOutput(treeArtifact, parentRelativePath);
    writeFile(artifact.getPath(), contentLines);
    return artifact;
  }

  private ArchivedTreeArtifact createArchivedTreeArtifactWithContent(
      SpecialArtifact treeArtifact, String... contentLines) throws IOException {
    ArchivedTreeArtifact artifact = ArchivedTreeArtifact.createForTree(treeArtifact);
    writeFile(artifact.getPath(), contentLines);
    return artifact;
  }

  private static ActionLookupData actionLookupData(int actionIndex) {
    return ActionLookupData.create(ACTION_LOOKUP_KEY, actionIndex);
  }
}
