// 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.analysis;

import static com.google.common.truth.Truth.assertThat;
import static com.google.devtools.build.lib.actions.CompletionContext.FAILED_COMPLETION_CTX;
import static com.google.devtools.build.lib.analysis.TargetCompleteEvent.newFileFromArtifact;
import static java.nio.charset.StandardCharsets.ISO_8859_1;
import static java.nio.charset.StandardCharsets.UTF_8;

import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableSortedSet;
import com.google.common.collect.Iterables;
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.CompletionContext;
import com.google.devtools.build.lib.actions.EventReportingArtifacts.ReportedArtifacts;
import com.google.devtools.build.lib.actions.FileArtifactValue;
import com.google.devtools.build.lib.analysis.TopLevelArtifactHelper.ArtifactsToBuild;
import com.google.devtools.build.lib.analysis.config.BuildConfigurationValue;
import com.google.devtools.build.lib.analysis.util.AnalysisTestCase;
import com.google.devtools.build.lib.buildeventstream.BuildEvent.LocalFile;
import com.google.devtools.build.lib.buildeventstream.BuildEvent.LocalFile.LocalFileType;
import com.google.devtools.build.lib.buildeventstream.BuildEventStreamProtos.File;
import com.google.devtools.build.lib.collect.nestedset.NestedSet;
import com.google.devtools.build.lib.skyframe.ConfiguredTargetAndData;
import com.google.devtools.build.lib.skyframe.TreeArtifactValue;
import com.google.devtools.build.lib.testutil.TestConstants;
import com.google.devtools.build.lib.util.OS;
import com.google.devtools.build.lib.vfs.PathFragment;
import java.util.ArrayList;
import java.util.Map;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.JUnit4;

/** Tests for {@link TargetCompleteEvent}. */
@RunWith(JUnit4.class)
public class TargetCompleteEventTest extends AnalysisTestCase {

  @Test
  public void testReferencedSourceFile() throws Exception {
    scratch.file("BUILD", "filegroup(name = 'files', srcs = ['file'])");
    scratch.file("file", "content does not matter");
    ConfiguredTargetAndData ctAndData = getCtAndData("//:files");
    ArtifactsToBuild artifactsToBuild = getArtifactsToBuild(ctAndData);
    Artifact artifact = Iterables.getOnlyElement(artifactsToBuild.getAllArtifacts().toList());
    FileArtifactValue metadata =
        FileArtifactValue.createForNormalFile(new byte[] {1, 2, 3}, null, 10);
    CompletionContext completionContext =
        getCompletionContext(ImmutableMap.of(artifact, metadata), ImmutableMap.of());

    TargetCompleteEvent event =
        TargetCompleteEvent.successfulBuild(
            ctAndData,
            completionContext,
            artifactsToBuild.getAllArtifactsByOutputGroup(),
            /* announceTargetSummary= */ false);

    assertThat(event.referencedLocalFiles())
        .containsExactly(
            new LocalFile(artifact.getPath(), LocalFileType.OUTPUT_FILE, artifact, metadata));
  }

  @Test
  public void testReferencedSourceDirectory() throws Exception {
    scratch.file("BUILD", "filegroup(name = 'files', srcs = ['dir'])");
    scratch.file("dir/file", "content does not matter");
    ConfiguredTargetAndData ctAndData = getCtAndData("//:files");
    ArtifactsToBuild artifactsToBuild = getArtifactsToBuild(ctAndData);
    Artifact artifact = Iterables.getOnlyElement(artifactsToBuild.getAllArtifacts().toList());
    FileArtifactValue metadata = FileArtifactValue.createForDirectoryWithMtime(0);
    CompletionContext completionContext =
        getCompletionContext(ImmutableMap.of(artifact, metadata), ImmutableMap.of());

    TargetCompleteEvent event =
        TargetCompleteEvent.successfulBuild(
            ctAndData,
            completionContext,
            artifactsToBuild.getAllArtifactsByOutputGroup(),
            /* announceTargetSummary= */ false);

    assertThat(event.referencedLocalFiles())
        .containsExactly(
            new LocalFile(artifact.getPath(), LocalFileType.OUTPUT_DIRECTORY, artifact, metadata));
  }

  @Test
  public void testReferencedTreeArtifact() throws Exception {
    scratch.file(
        "defs.bzl",
        """
        def _impl(ctx):
            d = ctx.actions.declare_directory(ctx.label.name)
            ctx.actions.run_shell(outputs = [d], command = "does not matter")
            return DefaultInfo(files = depset([d]))

        dir = rule(_impl)
        """);
    scratch.file(
        "BUILD",
        "load(':defs.bzl', 'dir')",
        "dir(name = 'dir')",
        "filegroup(name = 'files', srcs = ['dir'])");
    ConfiguredTargetAndData ctAndData = getCtAndData("//:files");
    ArtifactsToBuild artifactsToBuild = getArtifactsToBuild(ctAndData);
    SpecialArtifact tree =
        (SpecialArtifact) Iterables.getOnlyElement(artifactsToBuild.getAllArtifacts().toList());
    TreeFileArtifact fileChild =
        TreeFileArtifact.createTreeOutput(tree, PathFragment.create("dir/file.txt"));
    FileArtifactValue fileMetadata =
        FileArtifactValue.createForNormalFile(new byte[] {1, 2, 3}, null, 10);
    // A TreeFileArtifact can be a directory, when materialized by a symlink.
    // See https://github.com/bazelbuild/bazel/issues/20418.
    TreeFileArtifact dirChild = TreeFileArtifact.createTreeOutput(tree, PathFragment.create("sym"));
    FileArtifactValue dirMetadata = FileArtifactValue.createForDirectoryWithMtime(123456789);
    TreeArtifactValue metadata =
        TreeArtifactValue.newBuilder(tree)
            .putChild(fileChild, fileMetadata)
            .putChild(dirChild, dirMetadata)
            .build();
    CompletionContext completionContext =
        getCompletionContext(ImmutableMap.of(), ImmutableMap.of(tree, metadata));

    TargetCompleteEvent event =
        TargetCompleteEvent.successfulBuild(
            ctAndData,
            completionContext,
            artifactsToBuild.getAllArtifactsByOutputGroup(),
            /* announceTargetSummary= */ false);

    assertThat(event.referencedLocalFiles())
        .containsExactly(
            new LocalFile(fileChild.getPath(), LocalFileType.OUTPUT_FILE, fileChild, fileMetadata),
            new LocalFile(
                dirChild.getPath(), LocalFileType.OUTPUT_DIRECTORY, dirChild, dirMetadata));
  }

  @Test
  public void testReferencedUnresolvedSymlink() throws Exception {
    scratch.file(
        "defs.bzl",
        """
        def _impl(ctx):
            s = ctx.actions.declare_symlink(ctx.label.name)
            ctx.actions.symlink(output = s, target_path = "does not matter")
            return DefaultInfo(files = depset([s]))

        sym = rule(_impl)
        """);
    scratch.file(
        "BUILD",
        "load(':defs.bzl', 'sym')",
        "sym(name = 'sym')",
        "filegroup(name = 'files', srcs = ['sym'])");
    ConfiguredTargetAndData ctAndData = getCtAndData("//:files");
    ArtifactsToBuild artifactsToBuild = getArtifactsToBuild(ctAndData);
    Artifact artifact = Iterables.getOnlyElement(artifactsToBuild.getAllArtifacts().toList());
    artifact.getPath().getParentDirectory().createDirectoryAndParents();
    artifact.getPath().createSymbolicLink(fileSystem.getPath("/some/path"));
    FileArtifactValue metadata = FileArtifactValue.createForUnresolvedSymlink(artifact.getPath());
    CompletionContext completionContext =
        getCompletionContext(ImmutableMap.of(artifact, metadata), ImmutableMap.of());

    TargetCompleteEvent event =
        TargetCompleteEvent.successfulBuild(
            ctAndData,
            completionContext,
            artifactsToBuild.getAllArtifactsByOutputGroup(),
            /* announceTargetSummary= */ false);

    assertThat(event.referencedLocalFiles())
        .containsExactly(
            new LocalFile(artifact.getPath(), LocalFileType.OUTPUT_SYMLINK, artifact, metadata));
  }

  /** Regression test for b/165671166. */
  @Test
  public void testFileProtoFromArtifactReencodesAsUtf8() throws Exception {
    if (OS.getCurrent() == OS.WINDOWS) {
      // Windows filesystems return paths with wide characters and don't suffer from the current
      // workaround where arbitrary bytes are represented to Java as Latin-1.
      return;
    }
    scratch.file("sh/BUILD", "filegroup(name = 'globby', srcs = glob(['dir/*']))");
    // Bytes are UTF-8 encoding of: sh/dir/圖片
    byte[] filenameBytes = {
      0x73, 0x68, 0x2f, 0x64, 0x69, 0x72, 0x2f, -27, -100, -106, -25, -119, -121
    };
    String utf8InLatin1FileName = new String(filenameBytes, ISO_8859_1);
    scratch.file(utf8InLatin1FileName, "content does not matter");
    ConfiguredTargetAndData ctAndData = getCtAndData("//sh:globby");
    ArtifactsToBuild artifactsToBuild = getArtifactsToBuild(ctAndData);

    TargetCompleteEvent event =
        TargetCompleteEvent.successfulBuild(
            ctAndData,
            FAILED_COMPLETION_CTX,
            artifactsToBuild.getAllArtifactsByOutputGroup(),
            /*announceTargetSummary=*/ false);

    ArrayList<File> fileProtos = new ArrayList<>();
    ReportedArtifacts reportedArtifacts = event.reportedArtifacts();
    for (NestedSet<Artifact> artifactSet : reportedArtifacts.artifacts) {
      for (Artifact a : artifactSet.toListInterruptibly()) {
        fileProtos.add(
            newFileFromArtifact(
                /* name= */ null,
                a,
                PathFragment.EMPTY_FRAGMENT,
                FAILED_COMPLETION_CTX,
                /* uri= */ null));
      }
    }
    // Bytes are the same but the encoding is actually UTF-8 as required of a protobuf string.
    String utf8FileName = new String(filenameBytes, UTF_8);
    assertThat(fileProtos).hasSize(1);
    assertThat(fileProtos.get(0).getName()).isEqualTo(utf8FileName);
  }

  private ConfiguredTargetAndData getCtAndData(String target) throws Exception {
    AnalysisResult result = update(target);
    ConfiguredTarget ct = Iterables.getOnlyElement(result.getTargetsToBuild());
    TargetAndConfiguration tac = Iterables.getOnlyElement(result.getTopLevelTargetsWithConfigs());
    var configuredTargetConfiguration =
        (BuildConfigurationValue)
            skyframeExecutor.getEvaluator().getExistingValue(ct.getConfigurationKey());
    return new ConfiguredTargetAndData(ct, tac.getTarget(), configuredTargetConfiguration, null);
  }

  private ArtifactsToBuild getArtifactsToBuild(ConfiguredTargetAndData ctAndData) {
    TopLevelArtifactContext context =
        new TopLevelArtifactContext(false, false, false, OutputGroupInfo.DEFAULT_GROUPS);
    return TopLevelArtifactHelper.getAllArtifactsToBuild(ctAndData.getConfiguredTarget(), context);
  }

  private CompletionContext getCompletionContext(
      Map<Artifact, FileArtifactValue> metadata,
      Map<SpecialArtifact, TreeArtifactValue> treeMetadata) {
    ImmutableMap.Builder<Artifact, ImmutableSortedSet<TreeFileArtifact>> expandedArtifacts =
        ImmutableMap.builder();
    ActionInputMap inputMap = new ActionInputMap(0);

    for (Map.Entry<Artifact, FileArtifactValue> entry : metadata.entrySet()) {
      inputMap.put(entry.getKey(), entry.getValue(), /* depOwner= */ null);
    }

    for (Map.Entry<SpecialArtifact, TreeArtifactValue> entry : treeMetadata.entrySet()) {
      expandedArtifacts.put(entry.getKey(), entry.getValue().getChildren());
      inputMap.putTreeArtifact(entry.getKey(), entry.getValue(), /* depOwner= */ null);
    }

    return new CompletionContext(
        directories.getExecRoot(TestConstants.WORKSPACE_NAME),
        expandedArtifacts.buildOrThrow(),
        /* expandedFilesets= */ ImmutableMap.of(),
        ArtifactPathResolver.IDENTITY,
        inputMap,
        /* expandFilesets= */ false,
        /* fullyResolveFilesetLinks= */ false);
  }
}
