// 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 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, ToolHelper.getJava8RuntimeJar(), 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);
  }
}
