// Copyright (c) 2020, 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.relocator;

import static com.android.tools.r8.utils.codeinspector.Matchers.isPresent;
import static junit.framework.TestCase.assertFalse;
import static org.hamcrest.CoreMatchers.containsString;
import static org.hamcrest.CoreMatchers.not;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertThrows;

import com.android.tools.r8.CompilationFailedException;
import com.android.tools.r8.TestBase;
import com.android.tools.r8.TestParameters;
import com.android.tools.r8.ToolHelper;
import com.android.tools.r8.ToolHelper.ProcessResult;
import com.android.tools.r8.graph.DexClass;
import com.android.tools.r8.references.Reference;
import com.android.tools.r8.utils.BooleanUtils;
import com.android.tools.r8.utils.DescriptorUtils;
import com.android.tools.r8.utils.Pair;
import com.android.tools.r8.utils.codeinspector.ClassSubject;
import com.android.tools.r8.utils.codeinspector.CodeInspector;
import com.android.tools.r8.utils.codeinspector.FoundClassSubject;
import com.android.tools.r8.utils.codeinspector.FoundFieldSubject;
import com.android.tools.r8.utils.codeinspector.FoundMethodSubject;
import com.android.tools.r8.utils.codeinspector.LocalVariableTable;
import com.android.tools.r8.utils.codeinspector.LocalVariableTable.LocalVariableTableEntry;
import com.android.tools.r8.utils.codeinspector.MethodSubject;
import java.io.IOException;
import java.nio.file.Path;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ExecutionException;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.Parameterized;
import org.junit.runners.Parameterized.Parameters;

@RunWith(Parameterized.class)
public class RelocatorTest extends TestBase {

  private final boolean external;

  @Parameters(name = "{0}, external: {1}")
  public static List<Object[]> data() {
    return buildParameters(getTestParameters().withNoneRuntime().build(), BooleanUtils.values());
  }

  public RelocatorTest(TestParameters parameters, boolean external) {
    this.external = external;
  }

  @Test
  public void testRelocatorIdentity()
      throws IOException, CompilationFailedException, ExecutionException {
    Path output = temp.newFile("output.jar").toPath();
    runRelocator(ToolHelper.R8_WITH_DEPS_JAR, new HashMap<>(), output);
    inspectAllClassesRelocated(ToolHelper.R8_WITH_DEPS_JAR, output, "", "");
  }

  @Test
  public void testRelocatorEmptyToSomething() throws Exception {
    String originalPrefix = "";
    String newPrefix = "foo.bar.baz";
    Path output = temp.newFile("output.jar").toPath();
    Map<String, String> mapping = new HashMap<>();
    mapping.put(originalPrefix, newPrefix);
    runRelocator(ToolHelper.R8_WITH_DEPS_JAR, mapping, output);
    // TODO(b/155618698): Extend relocator with a richer language such that java.lang.Object is not
    //   relocated.
    RuntimeException compilationError =
        assertThrows(
            RuntimeException.class,
            () ->
                inspectAllClassesRelocated(
                    ToolHelper.R8_WITH_DEPS_JAR, output, originalPrefix, newPrefix + "."));
    assertThat(compilationError.getMessage(), containsString("must extend class java.lang.Object"));
  }

  @Test
  public void testRelocatorSomethingToEmpty() throws IOException {
    String originalPrefix = "com.android.tools.r8";
    String newPrefix = "";
    Path output = temp.newFile("output.jar").toPath();
    Map<String, String> mapping = new HashMap<>();
    mapping.put(originalPrefix, newPrefix);
    // TODO(b/155047618): Fixup the type after rewriting.
    CompilationFailedException compilationFailedException =
        assertThrows(
            CompilationFailedException.class,
            () -> {
              runRelocator(ToolHelper.R8_WITH_DEPS_JAR, mapping, output);
            });
  }

  @Test
  public void testRelocateKeepsDebugInfo()
      throws IOException, CompilationFailedException, ExecutionException {
    String originalPrefix = "com.android.tools.r8";
    String newPrefix = "com.android.tools.r8";
    Path output = temp.newFile("output.jar").toPath();
    Map<String, String> mapping = new HashMap<>();
    mapping.put(originalPrefix, newPrefix);
    runRelocator(ToolHelper.R8_WITH_DEPS_JAR, mapping, output);
    // Assert that all classes are the same, have the same methods and debug info:
    CodeInspector originalInspector = new CodeInspector(ToolHelper.R8_WITH_DEPS_JAR);
    CodeInspector relocatedInspector = new CodeInspector(output);
    for (FoundClassSubject clazz : originalInspector.allClasses()) {
      ClassSubject relocatedClass = relocatedInspector.clazz(clazz.getFinalName());
      assertThat(relocatedClass, isPresent());
      assertEquals(
          clazz.getDexProgramClass().sourceFile, relocatedClass.getDexProgramClass().sourceFile);
      for (FoundMethodSubject originalMethod : clazz.allMethods()) {
        MethodSubject relocatedMethod = relocatedClass.method(originalMethod.asMethodReference());
        assertThat(relocatedMethod, isPresent());
        assertEquals(originalMethod.hasLineNumberTable(), relocatedMethod.hasLineNumberTable());
        if (originalMethod.hasLineNumberTable()) {
          // TODO(b/155303677): Figure out why we cannot assert the same lines.
          // assertEquals(
          //     originalMethod.getLineNumberTable().getLines().size(),
          //     relocatedMethod.getLineNumberTable().getLines().size());
        }
        assertEquals(
            originalMethod.hasLocalVariableTable(), relocatedMethod.hasLocalVariableTable());
        if (originalMethod.hasLocalVariableTable()) {
          LocalVariableTable originalVariableTable = originalMethod.getLocalVariableTable();
          LocalVariableTable relocatedVariableTable = relocatedMethod.getLocalVariableTable();
          assertEquals(originalVariableTable.size(), relocatedVariableTable.size());
          for (int i = 0; i < originalVariableTable.getEntries().size(); i++) {
            LocalVariableTableEntry originalEntry = originalVariableTable.get(i);
            LocalVariableTableEntry relocatedEntry = relocatedVariableTable.get(i);
            assertEquals(originalEntry.name, relocatedEntry.name);
            assertEquals(originalEntry.signature, relocatedEntry.signature);
            assertEquals(originalEntry.type.toString(), relocatedEntry.type.toString());
          }
        }
      }
    }
  }

  @Test
  public void testRelocateAll() throws IOException, CompilationFailedException, ExecutionException {
    String originalPrefix = "com.android.tools.r8";
    String newPrefix = "foo.bar.baz";
    Map<String, String> mapping = new HashMap<>();
    mapping.put("some.package.that.does.not.exist", "foo");
    mapping.put(originalPrefix, newPrefix);
    Path output = temp.newFile("output.jar").toPath();
    runRelocator(ToolHelper.R8_WITH_DEPS_JAR, mapping, output);
    inspectAllClassesRelocated(ToolHelper.R8_WITH_DEPS_JAR, output, originalPrefix, newPrefix);
  }

  @Test
  public void testOrderingOfPrefixes() throws Exception {
    String originalPrefix = "com.android";
    String newPrefix = "foo.bar.baz";
    Path output = temp.newFile("output.jar").toPath();
    Map<String, String> mapping = new LinkedHashMap<>();
    mapping.put(originalPrefix, newPrefix);
    mapping.put("com.android.tools.r8", "qux");
    CompilationFailedException exception =
        assertThrows(
            CompilationFailedException.class,
            () -> runRelocator(ToolHelper.R8_WITH_DEPS_JAR, mapping, output));
    assertThat(
        exception.getCause().getMessage(),
        containsString("can be relocated by multiple mappings."));
  }

  @Test
  public void testNoReEntry() throws IOException, CompilationFailedException, ExecutionException {
    // TODO(b/154909222): Check if this is the behavior we would like.
    String originalPrefix = "com.android";
    String newPrefix = "foo.bar.baz";
    Map<String, String> mapping = new LinkedHashMap<>();
    mapping.put(originalPrefix, newPrefix);
    mapping.put(newPrefix, "qux");
    Path output = temp.newFile("output.jar").toPath();
    runRelocator(ToolHelper.R8_WITH_DEPS_JAR, mapping, output);
    inspectAllClassesRelocated(ToolHelper.R8_WITH_DEPS_JAR, output, originalPrefix, newPrefix);
    // Assert that no mappings of com.android.tools.r8 -> qux exists.
    CodeInspector inspector = new CodeInspector(output);
    assertFalse(
        inspector.allClasses().stream().anyMatch(clazz -> clazz.getFinalName().startsWith("qux")));
  }

  @Test
  public void testMultiplePackages()
      throws IOException, ExecutionException, CompilationFailedException {
    Set<String> seenPackages = new HashSet<>();
    List<Pair<String, String>> packageMappings = new ArrayList<>();
    Map<String, String> mapping = new LinkedHashMap<>();
    CodeInspector inspector = new CodeInspector(ToolHelper.R8_WITH_DEPS_JAR);
    int packageNameCounter = 0;
    // Generate a mapping for each package name directly below com.android.tools.r8.
    for (FoundClassSubject clazz : inspector.allClasses()) {
      String packageName = clazz.getDexProgramClass().getType().getPackageName();
      String prefix = "com.android.tools.r8.";
      if (!packageName.startsWith(prefix)) {
        continue;
      }
      int nextPackageNameIndex = packageName.indexOf('.', prefix.length());
      if (nextPackageNameIndex > prefix.length()) {
        String mappedPackageName =
            prefix + packageName.substring(prefix.length(), nextPackageNameIndex);
        if (seenPackages.add(mappedPackageName)) {
          String relocatedPackageName = "number" + packageNameCounter++;
          packageMappings.add(new Pair<>(mappedPackageName, relocatedPackageName));
          mapping.put(mappedPackageName, relocatedPackageName);
        }
      }
    }
    Path output = temp.newFile("output.jar").toPath();
    runRelocator(ToolHelper.R8_WITH_DEPS_JAR, mapping, output);
    for (Pair<String, String> packageMapping : packageMappings) {
      inspectAllClassesRelocated(
          ToolHelper.R8_WITH_DEPS_JAR,
          output,
          packageMapping.getFirst(),
          packageMapping.getSecond());
    }
  }

  @Test
  public void testPartialPrefix()
      throws CompilationFailedException, IOException, ExecutionException {
    String originalPrefix = "com.android.tools.r";
    String newPrefix = "i_cannot_w";
    Map<String, String> mapping = new LinkedHashMap<>();
    mapping.put(originalPrefix, newPrefix);
    Path output = temp.newFile("output.jar").toPath();
    runRelocator(ToolHelper.R8_WITH_DEPS_JAR, mapping, output);
    inspectAllClassesRelocated(ToolHelper.R8_WITH_DEPS_JAR, output, originalPrefix, originalPrefix);
  }

  @Test
  public void testBootstrap() throws IOException, CompilationFailedException, ExecutionException {
    String originalPrefix = "com.android.tools.r8";
    String newPrefix = "relocated_r8";
    Map<String, String> mapping = new LinkedHashMap<>();
    mapping.put(originalPrefix, newPrefix);
    Path output = temp.newFile("output.jar").toPath();
    runRelocator(ToolHelper.R8_WITH_DEPS_JAR, mapping, output);
    // Check that all classes has been remapped.
    inspectAllClassesRelocated(ToolHelper.R8_WITH_DEPS_JAR, output, originalPrefix, newPrefix);
    inspectAllSignaturesNotContainingString(output, originalPrefix);
    // We should be able to call the relocated relocator.
    Path bootstrapOutput = temp.newFile("bootstrap.jar").toPath();
    ProcessResult processResult =
        ToolHelper.runJava(
            output,
            newPrefix + ".SwissArmyKnife",
            "relocator",
            "--input",
            output.toString(),
            "--output",
            bootstrapOutput.toString(),
            "--map",
            newPrefix + "->" + originalPrefix);
    System.out.println(processResult.stderr);
    assertEquals(0, processResult.exitCode);
    inspectAllClassesRelocated(output, bootstrapOutput, newPrefix, originalPrefix);
    inspectAllSignaturesNotContainingString(bootstrapOutput, newPrefix);
    // Assert that this is infact an identity transformation.
    inspectAllClassesRelocated(ToolHelper.R8_WITH_DEPS_JAR, bootstrapOutput, "", "");
  }

  @Test
  public void testNest() throws IOException, CompilationFailedException, ExecutionException {
    String originalPrefix = "com.android.tools.r8";
    String newPrefix = "com.android.tools.r8";
    Path output = temp.newFile("output.jar").toPath();
    Map<String, String> mapping = new HashMap<>();
    mapping.put(originalPrefix, newPrefix);
    runRelocator(ToolHelper.R8_WITH_DEPS_11_JAR, mapping, output);
    // Assert that all classes are the same, have the same methods and nest info.
    CodeInspector originalInspector = new CodeInspector(ToolHelper.R8_WITH_DEPS_11_JAR);
    CodeInspector relocatedInspector = new CodeInspector(output);
    for (FoundClassSubject originalSubject : originalInspector.allClasses()) {
      ClassSubject relocatedSubject = relocatedInspector.clazz(originalSubject.getFinalName());
      assertThat(relocatedSubject, isPresent());
      DexClass originalClass = originalSubject.getDexProgramClass();
      DexClass relocatedClass = relocatedSubject.getDexProgramClass();
      assertEquals(originalClass.isNestHost(), relocatedClass.isNestHost());
      assertEquals(originalClass.isNestMember(), relocatedClass.isNestMember());
      if (originalClass.isInANest()) {
        assertEquals(
            originalClass.getNestHost().descriptor, relocatedClass.getNestHost().descriptor);
      }
    }
  }

  private void runRelocator(Path input, Map<String, String> mapping, Path output)
      throws CompilationFailedException {
    if (external) {
      List<String> args = new ArrayList<>();
      args.add("--input");
      args.add(input.toString());
      args.add("--output");
      args.add(output.toString());
      mapping.forEach(
          (key, value) -> {
            args.add("--map");
            args.add(key + "->" + value);
          });
      RelocatorCommandLine.run(args.toArray(new String[0]));
    } else {
      RelocatorCommand.Builder builder =
          RelocatorCommand.builder().addProgramFiles(input).setOutputPath(output);
      mapping.forEach(
          (key, value) ->
              builder.addPackageMapping(
                  Reference.packageFromString(key), Reference.packageFromString(value)));
      Relocator.run(builder.build());
    }
  }

  private void inspectAllClassesRelocated(
      Path original, Path relocated, String originalPrefix, String newPrefix)
      throws IOException, ExecutionException {
    CodeInspector originalInspector = new CodeInspector(original);
    CodeInspector relocatedInspector = new CodeInspector(relocated);
    for (FoundClassSubject clazz : originalInspector.allClasses()) {
      if (originalPrefix.isEmpty()
          || clazz
              .getFinalName()
              .startsWith(originalPrefix + DescriptorUtils.JAVA_PACKAGE_SEPARATOR)) {
        String relocatedName = newPrefix + clazz.getFinalName().substring(originalPrefix.length());
        ClassSubject relocatedClass = relocatedInspector.clazz(relocatedName);
        assertThat(relocatedClass, isPresent());
      }
    }
  }

  private void inspectAllSignaturesNotContainingString(Path relocated, String originalPrefix)
      throws IOException, ExecutionException {
    CodeInspector relocatedInspector = new CodeInspector(relocated);
    for (FoundClassSubject clazz : relocatedInspector.allClasses()) {
      assertThat(clazz.getFinalSignatureAttribute(), not(containsString(originalPrefix)));
      for (FoundMethodSubject method : clazz.allMethods()) {
        assertThat(method.getJvmMethodSignatureAsString(), not(containsString(originalPrefix)));
      }
      for (FoundFieldSubject field : clazz.allFields()) {
        assertThat(field.getJvmFieldSignatureAsString(), not(containsString(originalPrefix)));
      }
    }
  }
}
