// Copyright 2017 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.rules.objc;

import static com.google.common.truth.Truth.assertThat;
import static org.junit.Assert.fail;

import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.Iterables;
import com.google.common.collect.Sets;
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.ArtifactPathResolver;
import com.google.devtools.build.lib.actions.ExecException;
import com.google.devtools.build.lib.actions.UserExecException;
import com.google.devtools.build.lib.actions.util.ActionsTestUtil;
import com.google.devtools.build.lib.analysis.ConfiguredTarget;
import com.google.devtools.build.lib.analysis.actions.SpawnAction;
import com.google.devtools.build.lib.analysis.util.ScratchAttributeWriter;
import com.google.devtools.build.lib.packages.util.MockObjcSupport;
import com.google.devtools.build.lib.rules.cpp.CppCompileAction;
import com.google.devtools.build.lib.vfs.FileSystemUtils;
import com.google.devtools.build.lib.vfs.PathFragment;
import java.util.List;
import java.util.Map;
import java.util.Set;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.JUnit4;

/** Tests for header thinning. */
@RunWith(JUnit4.class)
public class HeaderThinningTest extends ObjcRuleTestCase {

  private static final String CPP_COMPILE_ACTION_RULE_TYPE = "objc_library";

  @Before
  public void beforeEach() throws Exception {
    MockObjcSupport.createCrosstoolPackage(mockToolsConfig);
    MockObjcSupport.setupAppleSdks(mockToolsConfig);
    useConfiguration(
        "--crosstool_top=" + MockObjcSupport.DEFAULT_OSX_CROSSTOOL,
        "--experimental_objc_header_thinning",
        "--objc_use_dotd_pruning",
        "--xcode_version=" + MockObjcSupport.DEFAULT_XCODE_VERSION,
        "--ios_sdk_version=" + MockObjcSupport.DEFAULT_IOS_SDK_VERSION);
  }

  @Test
  public void testCppCompileActionHeaderThinningCanDetermineAdditionalInputs() throws Exception {
    Artifact sourceFile = getSourceArtifact("objc/a.m");
    CppCompileAction action = createCppCompileAction(sourceFile);
    List<Artifact> expectedHeaders =
        ImmutableList.of(
            getSourceArtifact("objc/a.pch"),
            getSourceArtifact("objc/b.h"),
            getSourceArtifact("objc/c"),
            getSourceArtifact("objc/d.hpp"));
    HeaderThinning headerThinning = new HeaderThinning(getPotentialHeaders(expectedHeaders));
    writeToHeadersListFile(action, "objc/a.pch", "objc/b.h", "objc/c", "objc/d.hpp");

    Iterable<Artifact> headersFound = headerThinning.determineAdditionalInputs(null, action, null);
    assertThat(headersFound).containsExactlyElementsIn(expectedHeaders);
  }

  @Test
  public void testCppCompileActionHeaderThinningThrowsWhenUnknownHeaderFound() throws Exception {
    Artifact sourceFile = getSourceArtifact("objc/a.m");
    CppCompileAction action = createCppCompileAction(sourceFile);
    List<Artifact> expectedHeaders =
        ImmutableList.of(getSourceArtifact("objc/a.h"), getSourceArtifact("objc/b.h"));
    HeaderThinning headerThinning = new HeaderThinning(getPotentialHeaders(expectedHeaders));
    writeToHeadersListFile(action, "objc/a.h", "objc/b.h", "objc/c.h");

    try {
      headerThinning.determineAdditionalInputs(null, action, null);
      fail("Exception was not thrown");
    } catch (ExecException e) {
      assertThat(e).hasMessageThat().containsMatch("(objc/c.h)");
      assertThat(e).isInstanceOf(UserExecException.class);
    }
  }

  @Test
  public void testCppCompileActionHeaderThinningFindsHeadersInTreeArtifacts() throws Exception {
    Artifact sourceFile = getSourceArtifact("objc/a.m");
    CppCompileAction action = createCppCompileAction(sourceFile);
    List<Artifact> expectedHeaders =
        ImmutableList.of(getSourceArtifact("objc/a.h"), getTreeArtifact("tree/dir"));
    HeaderThinning headerThinning = new HeaderThinning(getPotentialHeaders(expectedHeaders));
    writeToHeadersListFile(action, "objc/a.h", "tree/dir/c.h");

    Iterable<Artifact> headersFound = headerThinning.determineAdditionalInputs(null, action, null);
    assertThat(headersFound).containsExactlyElementsIn(expectedHeaders);
  }

  @Test
  public void testObjcCompileActionHeaderThinningCanFindRequiredHeaderInputs() throws Exception {
    Artifact sourceFile = getSourceArtifact("objc/a.m");
    Artifact headersListFile = getHeadersListArtifact(sourceFile);
    scratch.file(
        headersListFile.getExecPathString(), "objc/a.pch", "objc/b.h", "objc/c", "objc/d.hpp");
    List<Artifact> expectedHeaders =
        ImmutableList.of(
            getSourceArtifact("objc/a.pch"),
            getSourceArtifact("objc/b.h"),
            getSourceArtifact("objc/c"),
            getSourceArtifact("objc/d.hpp"));

    Iterable<Artifact> headersFound =
        HeaderThinning.findRequiredHeaderInputs(
            sourceFile,
            headersListFile,
            createHeaderFilesMap(getPotentialHeaders(expectedHeaders)),
            ArtifactPathResolver.IDENTITY);
    assertThat(headersFound).containsExactlyElementsIn(expectedHeaders);
  }

  private void writeToHeadersListFile(CppCompileAction action, String... lines) throws Exception {
    Artifact headersListFile = null;
    for (Artifact input : action.getMandatoryInputs()) {
      if (input.getExtension().equals("headers_list")) {
        headersListFile = input;
        break;
      }
    }
    assertThat(headersListFile).isNotNull();
    scratch.file(headersListFile.getPath().getPathString(), lines);
  }

  /**
   * Simple utility to populate some unused header Artifacts along with the ones we expect to find.
   */
  private Iterable<Artifact> getPotentialHeaders(List<Artifact> expectedHeaders) {
    return Iterables.concat(
        ImmutableList.of(
            getSourceArtifact("objc/unused.h"),
            getSourceArtifact("some/other.h"),
            getSourceArtifact("objc/foo.pch")),
        expectedHeaders);
  }

  private CppCompileAction createCppCompileAction(Artifact sourceFile) throws Exception {
    String ownerLabel = "//objc:lib";
    ScratchAttributeWriter.fromLabelString(this, CPP_COMPILE_ACTION_RULE_TYPE, ownerLabel)
        .setList("srcs", sourceFile.getFilename())
        .write();
    ConfiguredTarget target = getConfiguredTarget(ownerLabel);
    List<CppCompileAction> allActions =
        actionsTestUtil()
            .findTransitivePrerequisitesOf(
                ActionsTestUtil.getFirstArtifactEndingWith(getFilesToBuild(target), ".a"),
                CppCompileAction.class);
    for (CppCompileAction action : allActions) {
      if (action.getSourceFile().getExecPath().equals(sourceFile.getExecPath())) {
        return action;
      }
    }
    return null;
  }

  private Artifact getHeadersListArtifact(Artifact sourceFile) {
    return getSourceArtifact(
        FileSystemUtils.replaceExtension(sourceFile.getExecPath(), ".headers_list"),
        sourceFile.getRoot().getRoot());
  }

  private static Map<PathFragment, Artifact> createHeaderFilesMap(Iterable<Artifact> artifacts) {
    ImmutableMap.Builder<PathFragment, Artifact> headerFilesMapBuilder = ImmutableMap.builder();
    for (Artifact artifact : artifacts) {
      headerFilesMapBuilder.put(artifact.getExecPath(), artifact);
    }
    return headerFilesMapBuilder.build();
  }

  private Artifact getTreeArtifact(String name) {
    Artifact treeArtifactBase = getSourceArtifact(name);
    return new SpecialArtifact(
        treeArtifactBase.getRoot(),
        treeArtifactBase.getExecPath(),
        treeArtifactBase.getArtifactOwner(),
        SpecialArtifactType.TREE);
  }

  @Test
  public void generatesHeaderScanningAction() throws Exception {
    Set<SpawnAction> scanningActions =
        createTargetAndGetHeaderScanningActions(ImmutableList.of("one.m", "two.m"));
    assertThat(scanningActions).hasSize(1);
  }

  @Test
  public void generates2HeaderScanningActionsWhenObjcAndCppSources() throws Exception {
    Set<SpawnAction> scanningActions =
        createTargetAndGetHeaderScanningActions(ImmutableList.of("one.m", "two.cc"));
    assertThat(scanningActions).hasSize(2);
  }

  @Test
  public void generatesMultipleHeaderScanningActionsForLargeTargets2() throws Exception {
    validateGeneratesMultipleHeaderScanningActionsForLargeTargets(
        2, targetConfig.getFragment(ObjcConfiguration.class).objcHeaderThinningPartitionSize());
  }

  @Test
  public void generatesMultipleHeaderScanningActionsForLargeTargets4() throws Exception {
    validateGeneratesMultipleHeaderScanningActionsForLargeTargets(
        4, targetConfig.getFragment(ObjcConfiguration.class).objcHeaderThinningPartitionSize());
  }

  @Test
  public void generatesMultipleHeaderScanningActionsForLargeTargets8() throws Exception {
    validateGeneratesMultipleHeaderScanningActionsForLargeTargets(
        8, targetConfig.getFragment(ObjcConfiguration.class).objcHeaderThinningPartitionSize());
  }

  @Test
  public void generatesMultipleHeaderScanningActionsForLargeTargetsCustomPartition()
      throws Exception {
    int partitionSize = 5;
    useConfiguration(
        "--crosstool_top=" + MockObjcSupport.DEFAULT_OSX_CROSSTOOL,
        "--experimental_objc_header_thinning",
        "--objc_header_thinning_partition_size=" + 5,
        "--objc_use_dotd_pruning",
        "--xcode_version=" + MockObjcSupport.DEFAULT_XCODE_VERSION,
        "--ios_sdk_version=" + MockObjcSupport.DEFAULT_IOS_SDK_VERSION);
    validateGeneratesMultipleHeaderScanningActionsForLargeTargets(12, partitionSize);
  }

  private void validateGeneratesMultipleHeaderScanningActionsForLargeTargets(
      int actionCount, int partitionSize) throws Exception {
    ImmutableList.Builder<String> sourcesBuilder = ImmutableList.builder();
    for (int i = 0; i < partitionSize * actionCount; ++i) {
      sourcesBuilder.add(String.format("source_%d.m", i));
    }
    Set<SpawnAction> scanningActions =
        createTargetAndGetHeaderScanningActions(sourcesBuilder.build());
    assertThat(scanningActions).hasSize(actionCount);
  }

  private Set<SpawnAction> createTargetAndGetHeaderScanningActions(Iterable<String> sources)
      throws Exception {
    String ownerLabel = "//objc:lib";
    ScratchAttributeWriter.fromLabelString(this, CPP_COMPILE_ACTION_RULE_TYPE, ownerLabel)
        .setList("srcs", sources)
        .write();
    ConfiguredTarget target = getConfiguredTarget(ownerLabel);
    List<SpawnAction> spawnActions =
        actionsTestUtil()
            .findTransitivePrerequisitesOf(
                ActionsTestUtil.getFirstArtifactEndingWith(getFilesToBuild(target), ".a"),
                SpawnAction.class);
    return Sets.newHashSet(
        Iterables.filter(spawnActions, a -> a.getMnemonic().equals("ObjcHeaderScanning")));
  }
}
