// 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.FileUtils;
import com.android.tools.r8.utils.dexinspector.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 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;
    });
  }
}
