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


import static com.google.common.truth.Truth.assertThat;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertSame;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;

import com.google.common.collect.ImmutableList;
import com.google.common.collect.Iterables;
import com.google.common.collect.Lists;
import com.google.devtools.build.lib.actions.ActionAnalysisMetadata.MiddlemanType;
import com.google.devtools.build.lib.actions.util.ActionsTestUtil;
import com.google.devtools.build.lib.actions.util.LabelArtifactOwner;
import com.google.devtools.build.lib.cmdline.Label;
import com.google.devtools.build.lib.rules.cpp.CppFileTypes;
import com.google.devtools.build.lib.rules.java.JavaSemantics;
import com.google.devtools.build.lib.testutil.Scratch;
import com.google.devtools.build.lib.vfs.Path;
import com.google.devtools.build.lib.vfs.PathFragment;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.JUnit4;

@RunWith(JUnit4.class)
public class ArtifactTest {
  private Scratch scratch;
  private Path execDir;
  private Root rootDir;

  @Before
  public final void setRootDir() throws Exception  {
    scratch = new Scratch();
    execDir = scratch.dir("/exec");
    rootDir = Root.asDerivedRoot(scratch.dir("/exec/root"));
  }

  @Test
  public void testConstruction_badRootDir() throws IOException {
    Path f1 = scratch.file("/exec/dir/file.ext");
    Path bogusDir = scratch.file("/exec/dir/bogus");
    try {
      new Artifact(f1, Root.asDerivedRoot(bogusDir), f1.relativeTo(execDir));
      fail("Expected IllegalArgumentException constructing artifact with a bad root dir");
    } catch (IllegalArgumentException expected) {}
  }

  @Test
  public void testEquivalenceRelation() throws Exception {
    PathFragment aPath = new PathFragment("src/a");
    PathFragment bPath = new PathFragment("src/b");
    assertEquals(new Artifact(aPath, rootDir),
                 new Artifact(aPath, rootDir));
    assertEquals(new Artifact(bPath, rootDir),
                 new Artifact(bPath, rootDir));
    assertFalse(new Artifact(aPath, rootDir).equals(
                new Artifact(bPath, rootDir)));
  }

  @Test
  public void testEmptyLabelIsNone() throws Exception {
    Artifact artifact = new Artifact(new PathFragment("src/a"), rootDir);
    assertThat(artifact.getOwnerLabel()).isNull();
  }

  @Test
  public void testComparison() throws Exception {
    PathFragment aPath = new PathFragment("src/a");
    PathFragment bPath = new PathFragment("src/b");
    Artifact aArtifact = new Artifact(aPath, rootDir);
    Artifact bArtifact = new Artifact(bPath, rootDir);
    assertEquals(-1, Artifact.EXEC_PATH_COMPARATOR.compare(aArtifact, bArtifact));
    assertEquals(0, Artifact.EXEC_PATH_COMPARATOR.compare(aArtifact, aArtifact));
    assertEquals(0, Artifact.EXEC_PATH_COMPARATOR.compare(bArtifact, bArtifact));
    assertEquals(1, Artifact.EXEC_PATH_COMPARATOR.compare(bArtifact, aArtifact));
  }

  @Test
  public void testRootPrefixedExecPath_normal() throws IOException {
    Path f1 = scratch.file("/exec/root/dir/file.ext");
    Artifact a1 = new Artifact(f1, rootDir, f1.relativeTo(execDir));
    assertEquals("root:dir/file.ext", Artifact.asRootPrefixedExecPath(a1));
  }

  @Test
  public void testRootPrefixedExecPath_noRoot() throws IOException {
    Path f1 = scratch.file("/exec/dir/file.ext");
    Artifact a1 = new Artifact(f1.relativeTo(execDir), Root.asDerivedRoot(execDir));
    assertEquals(":dir/file.ext", Artifact.asRootPrefixedExecPath(a1));
  }

  @Test
  public void testRootPrefixedExecPath_nullRootDir() throws IOException {
    Path f1 = scratch.file("/exec/dir/file.ext");
    try {
      new Artifact(f1, null, f1.relativeTo(execDir));
      fail("Expected IllegalArgumentException creating artifact with null root");
    } catch (IllegalArgumentException expected) {}
  }

  @Test
  public void testRootPrefixedExecPaths() throws IOException {
    Path f1 = scratch.file("/exec/root/dir/file1.ext");
    Path f2 = scratch.file("/exec/root/dir/dir/file2.ext");
    Path f3 = scratch.file("/exec/root/dir/dir/dir/file3.ext");
    Artifact a1 = new Artifact(f1, rootDir, f1.relativeTo(execDir));
    Artifact a2 = new Artifact(f2, rootDir, f2.relativeTo(execDir));
    Artifact a3 = new Artifact(f3, rootDir, f3.relativeTo(execDir));
    List<String> strings = new ArrayList<>();
    Artifact.addRootPrefixedExecPaths(Lists.newArrayList(a1, a2, a3), strings);
    assertThat(strings).containsExactly(
        "root:dir/file1.ext",
        "root:dir/dir/file2.ext",
        "root:dir/dir/dir/file3.ext").inOrder();
  }

  @Test
  public void testGetFilename() throws Exception {
    Root root = Root.asSourceRoot(scratch.dir("/foo"));
    Artifact javaFile = new Artifact(scratch.file("/foo/Bar.java"), root);
    Artifact generatedHeader = new Artifact(scratch.file("/foo/bar.proto.h"), root);
    Artifact generatedCc = new Artifact(scratch.file("/foo/bar.proto.cc"), root);
    Artifact aCPlusPlusFile = new Artifact(scratch.file("/foo/bar.cc"), root);
    assertTrue(JavaSemantics.JAVA_SOURCE.matches(javaFile.getFilename()));
    assertTrue(CppFileTypes.CPP_HEADER.matches(generatedHeader.getFilename()));
    assertTrue(CppFileTypes.CPP_SOURCE.matches(generatedCc.getFilename()));
    assertTrue(CppFileTypes.CPP_SOURCE.matches(aCPlusPlusFile.getFilename()));
  }

  @Test
  public void testGetExtension() throws Exception {
    Root root = Root.asSourceRoot(scratch.dir("/foo"));
    Artifact javaFile = new Artifact(scratch.file("/foo/Bar.java"), root);
    assertThat(javaFile.getExtension()).isEqualTo("java");
  }

  @Test
  public void testMangledPath() {
    String path = "dir/sub_dir/name:end";
    assertEquals("dir_Ssub_Udir_Sname_Cend", Actions.escapedPath(path));
  }

  private List<Artifact> getFooBarArtifacts(MutableActionGraph actionGraph, boolean collapsedList)
      throws Exception {
    Root root = Root.asSourceRoot(scratch.dir("/foo"));
    Artifact aHeader1 = new Artifact(scratch.file("/foo/bar1.h"), root);
    Artifact aHeader2 = new Artifact(scratch.file("/foo/bar2.h"), root);
    Artifact aHeader3 = new Artifact(scratch.file("/foo/bar3.h"), root);
    Artifact middleman = new Artifact(new PathFragment("middleman"),
        Root.middlemanRoot(scratch.dir("/foo"), scratch.dir("/foo/out")));
    actionGraph.registerAction(new MiddlemanAction(ActionsTestUtil.NULL_ACTION_OWNER,
        ImmutableList.of(aHeader1, aHeader2, aHeader3), middleman, "desc",
        MiddlemanType.AGGREGATING_MIDDLEMAN));
    return collapsedList ? Lists.newArrayList(aHeader1, middleman) :
        Lists.newArrayList(aHeader1, aHeader2, middleman);
  }

  @Test
  public void testAddExecPaths() throws Exception {
    List<String> paths = new ArrayList<>();
    MutableActionGraph actionGraph = new MapBasedActionGraph();
    Artifact.addExecPaths(getFooBarArtifacts(actionGraph, false), paths);
    assertThat(paths).containsExactlyElementsIn(ImmutableList.of("bar1.h", "bar2.h"));
  }

  @Test
  public void testAddExpandedExecPathStrings() throws Exception {
    List<String> paths = new ArrayList<>();
    MutableActionGraph actionGraph = new MapBasedActionGraph();
    Artifact.addExpandedExecPathStrings(getFooBarArtifacts(actionGraph, true), paths,
        ActionInputHelper.actionGraphArtifactExpander(actionGraph));
    assertThat(paths).containsExactly("bar1.h", "bar1.h", "bar2.h", "bar3.h");
  }

  @Test
  public void testAddExpandedExecPaths() throws Exception {
    List<PathFragment> paths = new ArrayList<>();
    MutableActionGraph actionGraph = new MapBasedActionGraph();
    Artifact.addExpandedExecPaths(getFooBarArtifacts(actionGraph, true), paths,
        ActionInputHelper.actionGraphArtifactExpander(actionGraph));
    assertThat(paths).containsExactly(
        new PathFragment("bar1.h"),
        new PathFragment("bar1.h"),
        new PathFragment("bar2.h"),
        new PathFragment("bar3.h"));
  }

  @Test
  public void testAddExpandedArtifacts() throws Exception {
    List<Artifact> expanded = new ArrayList<>();
    MutableActionGraph actionGraph = new MapBasedActionGraph();
    List<Artifact> original = getFooBarArtifacts(actionGraph, true);
    Artifact.addExpandedArtifacts(original, expanded,
        ActionInputHelper.actionGraphArtifactExpander(actionGraph));

    List<Artifact> manuallyExpanded = new ArrayList<>();
    for (Artifact artifact : original) {
      ActionAnalysisMetadata action = actionGraph.getGeneratingAction(artifact);
      if (artifact.isMiddlemanArtifact()) {
        Iterables.addAll(manuallyExpanded, action.getInputs());
      } else {
        manuallyExpanded.add(artifact);
      }
    }
    assertThat(expanded).containsExactlyElementsIn(manuallyExpanded);
  }

  @Test
  public void testAddExecPathsNewActionGraph() throws Exception {
    List<String> paths = new ArrayList<>();
    MutableActionGraph actionGraph = new MapBasedActionGraph();
    Artifact.addExecPaths(getFooBarArtifacts(actionGraph, false), paths);
    assertThat(paths).containsExactlyElementsIn(ImmutableList.of("bar1.h", "bar2.h"));
  }

  @Test
  public void testAddExpandedExecPathStringsNewActionGraph() throws Exception {
    List<String> paths = new ArrayList<>();
    MutableActionGraph actionGraph = new MapBasedActionGraph();
    Artifact.addExpandedExecPathStrings(getFooBarArtifacts(actionGraph, true), paths,
        ActionInputHelper.actionGraphArtifactExpander(actionGraph));
    assertThat(paths).containsExactly("bar1.h", "bar1.h", "bar2.h", "bar3.h");
  }

  @Test
  public void testAddExpandedExecPathsNewActionGraph() throws Exception {
    List<PathFragment> paths = new ArrayList<>();
    MutableActionGraph actionGraph = new MapBasedActionGraph();
    Artifact.addExpandedExecPaths(getFooBarArtifacts(actionGraph, true), paths,
        ActionInputHelper.actionGraphArtifactExpander(actionGraph));
    assertThat(paths).containsExactly(
        new PathFragment("bar1.h"),
        new PathFragment("bar1.h"),
        new PathFragment("bar2.h"),
        new PathFragment("bar3.h"));
  }

  // TODO consider tests for the future
  @Test
  public void testAddExpandedArtifactsNewActionGraph() throws Exception {
    List<Artifact> expanded = new ArrayList<>();
    MutableActionGraph actionGraph = new MapBasedActionGraph();
    List<Artifact> original = getFooBarArtifacts(actionGraph, true);
    Artifact.addExpandedArtifacts(original, expanded,
        ActionInputHelper.actionGraphArtifactExpander(actionGraph));

    List<Artifact> manuallyExpanded = new ArrayList<>();
    for (Artifact artifact : original) {
      ActionAnalysisMetadata action = actionGraph.getGeneratingAction(artifact);
      if (artifact.isMiddlemanArtifact()) {
        Iterables.addAll(manuallyExpanded, action.getInputs());
      } else {
        manuallyExpanded.add(artifact);
      }
    }
    assertThat(expanded).containsExactlyElementsIn(manuallyExpanded);
  }

  @Test
  public void testRootRelativePathIsSameAsExecPath() throws Exception {
    Root root = Root.asSourceRoot(scratch.dir("/foo"));
    Artifact a = new Artifact(scratch.file("/foo/bar1.h"), root);
    assertSame(a.getExecPath(), a.getRootRelativePath());
  }

  @Test
  public void testToDetailString() throws Exception {
    Artifact a = new Artifact(scratch.file("/a/b/c"), Root.asDerivedRoot(scratch.dir("/a/b")),
        new PathFragment("b/c"));
    assertEquals("[[/a]b]c", a.toDetailString());
  }

  @Test
  public void testWeirdArtifact() throws Exception {
    try {
      new Artifact(scratch.file("/a/b/c"), Root.asDerivedRoot(scratch.dir("/a")),
          new PathFragment("c"));
      fail();
    } catch (IllegalArgumentException e) {
      assertThat(e).hasMessage(
          "c: illegal execPath doesn't end with b/c at /a/b/c with root /a[derived]");
    }
  }

  @Test
  public void testSerializeToString() throws Exception {
    assertEquals("b/c /3",
        new Artifact(scratch.file("/a/b/c"),
            Root.asDerivedRoot(scratch.dir("/a"))).serializeToString());
  }

  @Test
  public void testSerializeToStringWithExecPath() throws Exception {
    Path path = scratch.file("/aaa/bbb/ccc");
    Root root = Root.asDerivedRoot(scratch.dir("/aaa/bbb"));
    PathFragment execPath = new PathFragment("bbb/ccc");

    assertEquals("bbb/ccc /3", new Artifact(path, root, execPath).serializeToString());
  }

  @Test
  public void testSerializeToStringWithOwner() throws Exception {
    assertEquals("b/c /3 //foo:bar",
        new Artifact(scratch.file("/aa/b/c"), Root.asDerivedRoot(scratch.dir("/aa")),
            new PathFragment("b/c"),
            new LabelArtifactOwner(Label.parseAbsoluteUnchecked("//foo:bar"))).serializeToString());
  }

  @Test
  public void testLongDirname() throws Exception {
    String dirName = createDirNameArtifact().getDirname();

    assertThat(dirName).isEqualTo("aaa/bbb/ccc");
  }

  @Test
  public void testDirnameInExecutionDir() throws Exception {
    Artifact artifact = new Artifact(scratch.file("/foo/bar.txt"),
        Root.asDerivedRoot(scratch.dir("/foo")));

    assertThat(artifact.getDirname()).isEqualTo(".");
  }

  @Test
  public void testCanConstructPathFromDirAndFilename() throws Exception {
    Artifact artifact = createDirNameArtifact();
    String constructed =
        String.format("%s/%s", artifact.getDirname(), artifact.getFilename());

    assertThat(constructed).isEqualTo("aaa/bbb/ccc/ddd");
  }

  @Test
  public void testIsSourceArtifact() throws Exception {
    assertThat(
        new Artifact(scratch.file("/src/foo.cc"), Root.asSourceRoot(scratch.dir("/")),
            new PathFragment("src/foo.cc"))
            .isSourceArtifact())
        .isTrue();
    assertThat(
        new Artifact(scratch.file("/genfiles/aaa/bar.out"),
            Root.asDerivedRoot(scratch.dir("/genfiles"), scratch.dir("/genfiles/aaa")))
            .isSourceArtifact())
        .isFalse();

  }

  @Test
  public void testGetRoot() throws Exception {
    Root root = Root.asDerivedRoot(scratch.dir("/newRoot"));
    assertThat(new Artifact(scratch.file("/newRoot/foo"), root).getRoot()).isEqualTo(root);
  }

  private Artifact createDirNameArtifact() throws Exception {
    return new Artifact(scratch.file("/aaa/bbb/ccc/ddd"), Root.asDerivedRoot(scratch.dir("/")));
  }
}
