// Copyright (c) 2018, 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 com.android.tools.r8.ClassFileConsumer;
import com.android.tools.r8.ClassFileConsumer.ArchiveConsumer;
import com.android.tools.r8.CompilationMode;
import com.android.tools.r8.DexIndexedConsumer;
import com.android.tools.r8.ProgramConsumer;
import com.android.tools.r8.R8Command;
import com.android.tools.r8.R8Command.Builder;
import com.android.tools.r8.TestBase;
import com.android.tools.r8.ToolHelper;
import com.android.tools.r8.ToolHelper.ProcessResult;
import com.android.tools.r8.VmTestRunner;
import com.android.tools.r8.utils.DescriptorUtils;
import com.android.tools.r8.utils.FileUtils;
import java.io.IOException;
import java.nio.file.Path;
import java.nio.file.Paths;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;

@RunWith(VmTestRunner.class)
public class LambdaRenamingTestRunner extends TestBase {
  static final Class CLASS = LambdaRenamingTest.class;
  static final Class[] CLASSES = LambdaRenamingTest.CLASSES;

  private Path inputJar;
  private ProcessResult runInput;

  @Before
  public void writeAndRunInputJar() throws IOException {
    inputJar = temp.getRoot().toPath().resolve("input.jar");
    ArchiveConsumer buildInput = new ArchiveConsumer(inputJar);
    for (Class clazz : CLASSES) {
      buildInput.accept(
          ToolHelper.getClassAsBytes(clazz),
          DescriptorUtils.javaTypeToDescriptor(clazz.getName()),
          null);
    }
    buildInput.finished(null);
    runInput = ToolHelper.runJava(inputJar, CLASS.getCanonicalName());
    assertEquals(0, runInput.exitCode);
  }

  private Path writeProguardRules(boolean aggressive) throws IOException {
    Path pgConfig = temp.getRoot().toPath().resolve("keep.txt");
    FileUtils.writeTextFile(
        pgConfig,
        "-keep public class " + CLASS.getCanonicalName() + " {",
        "  public static void main(...);",
        "}",
        "-keep interface " + CLASS.getCanonicalName() + "$ReservedNameObjectInterface1 {",
        "  public java.lang.Object reservedMethod1();",
        "}",
        "-keep interface " + CLASS.getCanonicalName() + "$ReservedNameIntegerInterface2 {",
        "  public java.lang.Integer reservedMethod2();",
        "}",
        aggressive ? "-overloadaggressively" : "# Not overloading aggressively");
    return pgConfig;
  }

  @Test
  public void testProguard() throws Exception {
    buildAndRunProguard("pg.jar", false);
  }

  @Test
  public void testProguardAggressive() throws Exception {
    buildAndRunProguard("pg-aggressive.jar", true);
  }

  @Test
  public void testCf() throws Exception {
    buildAndRunCf("cf.zip", false);
  }

  @Test
  public void testCfAggressive() throws Exception {
    buildAndRunCf("cf-aggressive.zip", true);
  }

  @Test
  public void testDex() throws Exception {
    buildAndRunDex("dex.zip", false);
  }

  @Test
  public void testDexAggressive() throws Exception {
    buildAndRunDex("dex-aggressive.zip", true);
  }

  private void buildAndRunCf(String outName, boolean aggressive) throws Exception {
    Path outCf = temp.getRoot().toPath().resolve(outName);
    build(new ClassFileConsumer.ArchiveConsumer(outCf), aggressive);
    ProcessResult runCf = ToolHelper.runJava(outCf, CLASS.getCanonicalName());
    assertEquals(runInput.toString(), runCf.toString());
  }

  private void buildAndRunDex(String outName, boolean aggressive) throws Exception {
    Path outDex = temp.getRoot().toPath().resolve(outName);
    build(new DexIndexedConsumer.ArchiveConsumer(outDex), aggressive);
    ProcessResult runDex =
        ToolHelper.runArtNoVerificationErrorsRaw(outDex.toString(), CLASS.getCanonicalName());
    assertEquals(runInput.stdout, runDex.stdout);
    assertEquals(runInput.exitCode, runDex.exitCode);
  }

  private void build(ProgramConsumer consumer, boolean aggressive) throws Exception {
    Builder builder =
        ToolHelper.addProguardConfigurationConsumer(
                R8Command.builder(), configuration -> configuration.setPrintMapping(true))
            .setMode(CompilationMode.DEBUG)
            .addLibraryFiles(ToolHelper.getAndroidJar(ToolHelper.getMinApiLevelForDexVm()))
            .addProgramFiles(inputJar)
            .setProgramConsumer(consumer)
            .addProguardConfigurationFiles(writeProguardRules(aggressive));
    if (!(consumer instanceof ClassFileConsumer)) {
      builder.setMinApiLevel(ToolHelper.getMinApiLevelForDexVm().getLevel());
    }
    ToolHelper.runR8(builder.build());
  }

  private void buildAndRunProguard(String outName, boolean aggressive) throws Exception {
    Path pgConfig = writeProguardRules(aggressive);
    Path outPg = temp.getRoot().toPath().resolve(outName);
    ProcessResult proguardResult =
        ToolHelper.runProguard6Raw(
            inputJar, outPg, Paths.get(ToolHelper.JAVA_8_RUNTIME), pgConfig, null);
    System.out.println(proguardResult.stdout);
    if (proguardResult.exitCode != 0) {
      System.out.println(proguardResult.stderr);
    }
    assertEquals(0, proguardResult.exitCode);
    ProcessResult runPg = ToolHelper.runJava(outPg, CLASS.getCanonicalName());
    // Proguard renames IntegerInterface.inexactMethod() and ObjectInterface.inexactMethod()
    // to different names, which causes AbstractMethodError.
    assertNotEquals(-1, runPg.stderr.indexOf("AbstractMethodError"));
    assertNotEquals(0, runPg.exitCode);
  }
}
