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

import static com.google.common.truth.Truth.assertThat;
import static com.google.devtools.build.lib.actions.util.ActionsTestUtil.getFirstArtifactEndingWith;

import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
import com.google.devtools.build.lib.actions.Artifact;
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.BuildViewTestCase;
import com.google.devtools.build.lib.cmdline.Label;
import com.google.devtools.build.lib.rules.android.AndroidRuleClasses.MultidexMode;
import java.util.Set;
import org.junit.Before;

/** Base class for testing the multidex code of android_binary and android_test. */
public class AndroidMultidexBaseTest extends BuildViewTestCase {

  @Before
  public final void createFiles() throws Exception {
    scratch.file(
        "java/android/BUILD",
        "android_binary(name = 'app',",
        "               srcs = ['A.java'],",
        "               manifest = 'AndroidManifest.xml',",
        "               resource_files = glob(['res/**']),",
        "              )");
    scratch.file(
        "java/android/res/values/strings.xml",
        "<resources><string name = 'hello'>Hello Android!</string></resources>");
    scratch.file("java/android/A.java", "package android; public class A {};");
  }

  /**
   * Internal helper method: given an android_binary rule label, check that it builds in multidex
   * mode. Three multidex variations are possible: "legacy", "manual_main_dex" and "native".
   *
   * @param ruleLabel the android_binary rule label to test against
   * @param multidexMode the multidex mode used in the rule
   */
  protected void internalTestMultidexBuildStructure(String ruleLabel, MultidexMode multidexMode)
      throws Exception {

    ConfiguredTarget binary = getConfiguredTarget(ruleLabel);
    Set<Artifact> artifacts = actionsTestUtil().artifactClosureOf(getFilesToBuild(binary));

    Artifact finalDexOutput = getFirstArtifactEndingWith(artifacts, "/classes.dex.zip");
    assertThat(finalDexOutput).isNotNull();

    // Only created in legacy mode:
    Artifact strippedJar = getFirstArtifactEndingWith(artifacts, "main_dex_intermediate.jar");
    Artifact mainDexList = getFirstArtifactEndingWith(artifacts, "main_dex_list.txt");
    String ruleName = Label.parseAbsolute(ruleLabel, ImmutableMap.of()).getName();
    Artifact mainDexProguardSpec =
        getFirstArtifactEndingWith(artifacts, "main_dex_" + ruleName + "_proguard.cfg");

    if (multidexMode == MultidexMode.LEGACY) {
      // First action: check that the stripped jar is generated through Proguard.
      assertThat(mainDexProguardSpec).isNotNull();
      AndroidSdkProvider sdk = AndroidSdkProvider.fromRuleContext(getRuleContext(binary));
      assertThat(strippedJar).isNotNull();
      SpawnAction stripAction = getGeneratingSpawnAction(strippedJar);
      assertThat(stripAction.getCommandFilename())
          .isEqualTo(sdk.getProguard().getExecutable().getExecPathString());
      assertThat(stripAction.getInputs().toList()).contains(mainDexProguardSpec);

      // Second action: The dexer consumes the stripped jar to create the main dex class list.
      assertThat(mainDexList).isNotNull();
      SpawnAction mainDexAction = getGeneratingSpawnAction(mainDexList);
      assertThat(mainDexAction.getArguments())
          .containsAtLeast(mainDexList.getExecPathString(), strippedJar.getExecPathString())
          .inOrder();
    } else if (multidexMode == MultidexMode.MANUAL_MAIN_DEX) {
      // Manual main dex mode: strippedJar shouldn't exist and mainDexList should be provided.
      assertThat(strippedJar).isNull();
      assertThat(mainDexList).isNotNull();
    } else {
      // Native mode: these shouldn't exist.
      assertThat(strippedJar).isNull();
      assertThat(mainDexList).isNull();
    }

    Artifact dexMergerInput = getFirstArtifactEndingWith(artifacts, "classes.jar");
    SpawnAction dexMergerAction = getGeneratingSpawnAction(finalDexOutput);
    ImmutableList.Builder<String> argsBuilder =
        ImmutableList.<String>builder()
            .add(
                "--input",
                dexMergerInput.getExecPathString(),
                "--output",
                finalDexOutput.getExecPathString());
    if (multidexMode != MultidexMode.OFF) {
      argsBuilder.add("--multidex=minimal");
    }
    if (multidexMode == MultidexMode.LEGACY || multidexMode == MultidexMode.MANUAL_MAIN_DEX) {
      argsBuilder.add("--main-dex-list", mainDexList.getExecPathString());
    }
    assertThat(dexMergerAction.getRemainingArguments())
        .containsExactlyElementsIn(argsBuilder.build())
        .inOrder();
  }

  /**
   * Internal helper method: given an android_binary rule label, check that the dex merger runs is
   * invoked with {@code --multidex=off}.
   */
  protected void internalTestNonMultidexBuildStructure(String ruleLabel) throws Exception {
    ConfiguredTarget binary = getConfiguredTarget(ruleLabel);
    Set<Artifact> artifacts = actionsTestUtil().artifactClosureOf(getFilesToBuild(binary));
    Artifact dexInput = getFirstArtifactEndingWith(artifacts, "classes.jar");
    Artifact dexOutput = getFirstArtifactEndingWith(artifacts, "classes.dex.zip");
    SpawnAction dexAction = getGeneratingSpawnAction(dexOutput);

    assertThat(dexAction.getRemainingArguments())
        .containsAtLeast(
            "--input",
            dexInput.getExecPathString(),
            "--output",
            dexOutput.getExecPathString(),
            "--multidex=off")
        .inOrder();
  }
}
