// Copyright (c) 2017, the R8 project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.

package com.android.tools.r8.naming;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotEquals;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;

import com.android.tools.r8.DiagnosticsHandler;
import com.android.tools.r8.OutputMode;
import com.android.tools.r8.R8Command;
import com.android.tools.r8.StringConsumer;
import com.android.tools.r8.TestBase;
import com.android.tools.r8.ToolHelper;
import com.android.tools.r8.code.Instruction;
import com.android.tools.r8.code.NewInstance;
import com.android.tools.r8.graph.DexMethod;
import com.android.tools.r8.graph.DexType;
import com.android.tools.r8.shaking.ProguardRuleParserException;
import com.android.tools.r8.utils.AndroidApp;
import com.android.tools.r8.utils.DexInspector;
import com.android.tools.r8.utils.DexInspector.InstructionSubject;
import com.android.tools.r8.utils.DexInspector.InvokeInstructionSubject;
import com.android.tools.r8.utils.DexInspector.MethodSubject;
import com.android.tools.r8.utils.FileUtils;
import java.io.IOException;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.Iterator;
import java.util.concurrent.ExecutionException;
import org.junit.Before;
import org.junit.Test;

public class ApplyMappingTest extends TestBase {

  private static final String MAPPING = "test-mapping.txt";

  private static final Path MINIFICATION_JAR =
      Paths.get(ToolHelper.EXAMPLES_BUILD_DIR, "minification" + FileUtils.JAR_EXTENSION);

  private static final Path NAMING001_JAR =
      Paths.get(ToolHelper.EXAMPLES_BUILD_DIR, "naming001" + FileUtils.JAR_EXTENSION);

  private static final Path NAMING044_JAR =
      Paths.get(ToolHelper.EXAMPLES_BUILD_DIR, "naming044" + FileUtils.JAR_EXTENSION);

  private static final Path APPLYMAPPING044_JAR =
      Paths.get(ToolHelper.EXAMPLES_BUILD_DIR, "applymapping044" + FileUtils.JAR_EXTENSION);

  private Path out;

  @Before
  public void setup() throws IOException {
    out = temp.newFolder("outdex").toPath();
  }

  @Test
  public void test044_obfuscate_and_apply() throws Exception {
    // keep rules that allow obfuscations while keeping everything.
    Path flagForObfuscation =
        Paths.get(ToolHelper.EXAMPLES_DIR, "naming044", "keep-rules-005.txt");
    Path proguardMap = out.resolve(MAPPING);
    class ProguardMapConsumer implements StringConsumer {
      String map;

      @Override
      public void accept(String string, DiagnosticsHandler handler) {
        map = string;
      }
    }
    ProguardMapConsumer mapConsumer = new ProguardMapConsumer();
    runR8(
        ToolHelper.addProguardConfigurationConsumer(
                getCommandForApps(out, flagForObfuscation, NAMING044_JAR)
                    .setProguardMapConsumer(mapConsumer),
                pgConfig -> {
                  pgConfig.setPrintMapping(true);
                  pgConfig.setPrintMappingFile(proguardMap);
                })
            .build());

    // Obviously, dumped map and resource inside the app should be *identical*.
    ClassNameMapper mapperFromFile = ClassNameMapper.mapperFromFile(proguardMap);
    ClassNameMapper mapperFromApp = ClassNameMapper.mapperFromString(mapConsumer.map);
    assertEquals(mapperFromFile, mapperFromApp);

    Path instrOut = temp.newFolder("instr").toPath();
    Path flag = Paths.get(ToolHelper.EXAMPLES_DIR, "applymapping044", "keep-rules.txt");
    AndroidApp instrApp =
        runR8(
            ToolHelper.addProguardConfigurationConsumer(
                    getCommandForInstrumentation(instrOut, flag, NAMING044_JAR, APPLYMAPPING044_JAR)
                        .setDisableMinification(true),
                    pgConfig -> pgConfig.setApplyMappingFile(proguardMap))
                .build());

    DexInspector inspector = new DexInspector(instrApp);
    MethodSubject main = inspector.clazz("applymapping044.Main").method(DexInspector.MAIN);
    Iterator<InvokeInstructionSubject> iterator =
        main.iterateInstructions(InstructionSubject::isInvoke);
    // B#m()
    String b = iterator.next().holder().toString();
    assertEquals("naming044.B", mapperFromApp.deobfuscateClassName(b));
    // sub.SubB#n()
    String subB = iterator.next().holder().toString();
    assertEquals("naming044.sub.SubB", mapperFromApp.deobfuscateClassName(subB));
    // Skip A#<init>
    iterator.next();
    // Skip B#<init>
    iterator.next();
    // B#f(A)
    InvokeInstructionSubject f = iterator.next();
    DexType a1 = f.invokedMethod().proto.parameters.values[0];
    assertNotEquals("naming044.A", a1.toString());
    assertEquals("naming044.A", mapperFromApp.deobfuscateClassName(a1.toString()));
    assertNotEquals("f", f.invokedMethod().name.toString());
    // Skip AsubB#<init>
    iterator.next();
    // AsubB#f(A)
    InvokeInstructionSubject overloaded_f = iterator.next();
    DexMethod aSubB_f = overloaded_f.invokedMethod();
    DexType a2 = aSubB_f.proto.parameters.values[0];
    assertNotEquals("naming044.A", a2.toString());
    assertEquals("naming044.A", mapperFromApp.deobfuscateClassName(a2.toString()));
    assertNotEquals("f", aSubB_f.name.toString());
    // B#f == AsubB#f
    assertEquals(f.invokedMethod().name.toString(), aSubB_f.name.toString());
    // sub.SubB#<init>(int)
    InvokeInstructionSubject subBinit = iterator.next();
    assertNotEquals("naming044.sub.SubB", subBinit.holder().toString());
    assertEquals("naming044.sub.SubB",
        mapperFromApp.deobfuscateClassName(subBinit.holder().toString()));
    // sub.SubB#f(A)
    InvokeInstructionSubject original_f = iterator.next();
    DexMethod subB_f = original_f.invokedMethod();
    DexType a3 = subB_f.proto.parameters.values[0];
    assertEquals(a2, a3);
    assertNotEquals("f", original_f.invokedMethod().name.toString());
  }

  @Test
  public void test044_apply() throws Exception {
    Path flag =
        Paths.get(ToolHelper.EXAMPLES_DIR, "applymapping044", "keep-rules-apply-mapping.txt");
    AndroidApp outputApp =
        runR8(
            getCommandForInstrumentation(out, flag, NAMING044_JAR, APPLYMAPPING044_JAR)
                .setDisableMinification(true)
                .build());

    // Make sure the given proguard map is indeed applied.
    DexInspector inspector = new DexInspector(outputApp);
    MethodSubject main = inspector.clazz("applymapping044.Main").method(DexInspector.MAIN);
    Iterator<InvokeInstructionSubject> iterator =
        main.iterateInstructions(InstructionSubject::isInvoke);
    // B#m() -> y#n()
    InvokeInstructionSubject m = iterator.next();
    assertEquals("naming044.y", m.holder().toString());
    assertEquals("n", m.invokedMethod().name.toString());
    // sub.SubB#n() -> z.y#m()
    InvokeInstructionSubject n = iterator.next();
    assertEquals("naming044.z.y", n.holder().toString());
    assertEquals("m", n.invokedMethod().name.toString());
    // Skip A#<init>
    iterator.next();
    // Skip B#<init>
    iterator.next();
    // B#f(A) -> y#p(x)
    InvokeInstructionSubject f = iterator.next();
    DexType a1 = f.invokedMethod().proto.parameters.values[0];
    assertEquals("naming044.x", a1.toString());
    assertEquals("p", f.invokedMethod().name.toString());
    // Skip AsubB#<init>
    iterator.next();
    // AsubB#f(A) -> AsubB#p(x)
    InvokeInstructionSubject overloaded_f = iterator.next();
    DexMethod aSubB_f = overloaded_f.invokedMethod();
    DexType a2 = aSubB_f.proto.parameters.values[0];
    assertEquals("naming044.x", a2.toString());
    assertEquals("p", aSubB_f.name.toString());
    // B#f == AsubB#f
    assertEquals(f.invokedMethod().name.toString(), aSubB_f.name.toString());
    // sub.SubB#<init>(int) -> z.y<init>(int)
    InvokeInstructionSubject subBinit = iterator.next();
    assertEquals("naming044.z.y", subBinit.holder().toString());
    // sub.SubB#f(A) -> SubB#p(x)
    InvokeInstructionSubject original_f = iterator.next();
    DexMethod subB_f = original_f.invokedMethod();
    DexType a3 = subB_f.proto.parameters.values[0];
    assertEquals(a2, a3);
    assertEquals("p", original_f.invokedMethod().name.toString());
  }

  @Test
  public void test_naming001_rule105() throws Exception {
    // keep rules to reserve D and E, along with a proguard map.
    Path flag = Paths.get(ToolHelper.EXAMPLES_DIR, "naming001", "keep-rules-105.txt");
    Path proguardMap = out.resolve(MAPPING);
    AndroidApp outputApp =
        runR8(
            ToolHelper.addProguardConfigurationConsumer(
                    getCommandForApps(out, flag, NAMING001_JAR).setDisableMinification(true),
                    pgConfig -> {
                      pgConfig.setPrintMapping(true);
                      pgConfig.setPrintMappingFile(proguardMap);
                    })
                .build());

    // Make sure the given proguard map is indeed applied.
    DexInspector inspector = new DexInspector(outputApp);
    MethodSubject main = inspector.clazz("naming001.D").method(DexInspector.MAIN);
    Iterator<InvokeInstructionSubject> iterator =
        main.iterateInstructions(InstructionSubject::isInvoke);
    // mapping-105 simply includes: naming001.D#keep -> peek
    // naming001.E extends D, hence its keep() should be renamed to peek as well.
    // Check E#<init> is not renamed.
    InvokeInstructionSubject init = iterator.next();
    assertEquals("Lnaming001/E;-><init>()V", init.invokedMethod().toSmaliString());
    // E#keep() should be replaced with peek by applying the map.
    InvokeInstructionSubject m = iterator.next();
    assertEquals("peek", m.invokedMethod().name.toSourceString());
    // D must not be renamed
    assertEquals("naming001.D", m.holder().toString());
  }

  @Test
  public void test_naming001_rule106() throws Exception {
    // keep rules just to rename E
    Path flag = Paths.get(ToolHelper.EXAMPLES_DIR, "naming001", "keep-rules-106.txt");
    Path proguardMap = out.resolve(MAPPING);
    AndroidApp outputApp =
        runR8(
            ToolHelper.addProguardConfigurationConsumer(
                getCommandForApps(out, flag, NAMING001_JAR).setDisableMinification(true),
                pgConfig -> {
                  pgConfig.setPrintMapping(true);
                  pgConfig.setPrintMappingFile(proguardMap);
                })
                .build());

    // Make sure the given proguard map is indeed applied.
    DexInspector inspector = new DexInspector(outputApp);
    MethodSubject main = inspector.clazz("naming001.D").method(DexInspector.MAIN);

    // naming001.E is renamed to a.a, so first instruction must be: new-instance La/a;
    Instruction[] instructions = main.getMethod().getCode().asDexCode().instructions;
    assertTrue(instructions[0] instanceof NewInstance);
    NewInstance newInstance = (NewInstance) instructions[0];
    assertEquals( "La/a;", newInstance.getType().toSmaliString());
  }

  @Test
  public void test_minification_conflict_mapping() throws Exception {
    Path flag = Paths.get(
        ToolHelper.EXAMPLES_DIR, "minification", "keep-rules-apply-conflict-mapping.txt");
    try {
      runR8(getCommandForApps(out, flag, MINIFICATION_JAR).build());
      fail("Expect to detect renaming conflict");
    } catch (ProguardMapError e) {
      assertTrue(e.getMessage().contains("functionFromIntToInt"));
    }
  }

  private R8Command.Builder getCommandForInstrumentation(
      Path out, Path flag, Path mainApp, Path instrApp) throws IOException {
    return R8Command.builder()
        .addLibraryFiles(ToolHelper.getDefaultAndroidJar(), mainApp)
        .addProgramFiles(instrApp)
        .setOutput(out, OutputMode.DexIndexed)
        .addProguardConfigurationFiles(flag);
  }

  private R8Command.Builder getCommandForApps(Path out, Path flag, Path... jars)
      throws IOException {
    return R8Command.builder()
        .addLibraryFiles(ToolHelper.getDefaultAndroidJar())
        .addProgramFiles(jars)
        .setOutput(out, OutputMode.DexIndexed)
        .addProguardConfigurationFiles(flag);
  }

  private static AndroidApp runR8(R8Command command)
      throws ProguardRuleParserException, ExecutionException, IOException {
    return ToolHelper.runR8(command, options -> {
      // Disable inlining to make this test not depend on inlining decisions.
      options.enableInlining = false;
    });
  }
}
