// 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.bridgeremoval;

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

import com.android.tools.r8.TestBase;
import com.android.tools.r8.ToolHelper;
import com.android.tools.r8.ToolHelper.ProcessResult;
import com.android.tools.r8.code.InvokeVirtual;
import com.android.tools.r8.code.ReturnVoid;
import com.android.tools.r8.graph.DexCode;
import com.android.tools.r8.jasmin.JasminBuilder;
import com.android.tools.r8.jasmin.JasminBuilder.ClassBuilder;
import com.android.tools.r8.utils.AndroidApp;
import com.android.tools.r8.utils.InternalOptions;
import com.android.tools.r8.utils.codeinspector.ClassSubject;
import com.android.tools.r8.utils.codeinspector.CodeInspector;
import com.android.tools.r8.utils.codeinspector.MethodSubject;
import com.google.common.collect.ImmutableList;
import java.nio.file.Path;
import org.junit.Test;

public class B77836766 extends TestBase {

  /**
   * The below Jasmin code mimics the following Kotlin code:
   *
   * package java_pkg;
   *
   * public interface Itf1 {
   *   void foo(String arg);
   * }
   *
   * public interface Itf2 {
   *   void foo(Integer arg);
   * }
   *
   * package kt_pkg;
   *
   * internal abstract class AbsCls<T> {
   *   void foo(T obj) { ... }
   * }
   *
   * internal class Cls1() : AbsCls<String>(), Itf1
   *
   * internal class Cls2() : AbsCls<Integer>(), Itf2
   *
   *
   * kotlinc introduced bridge methods Cls?#foo to AbsCls#foo:
   *
   * class Cls1 extends AbsCls implements Itf1 {
   *   public bridge synthetic void foo(String arg) {
   *     invoke-virtual Cls1#foo(Object)V
   *   }
   * }
   *
   * Note that we can't write such code in Java because javac requires Itf?#foo, which are
   * technically abstract methods, to be explicitly overridden.
   */
  @Test
  public void test_bridgeTargetInBase_differentBridges() throws Exception {
    JasminBuilder jasminBuilder = new JasminBuilder();

    ClassBuilder absCls = jasminBuilder.addClass("AbsCls");
    absCls.setAccess("public abstract");
    absCls.addFinalMethod("foo", ImmutableList.of("Ljava/lang/Object;"), "V",
        ".limit stack 3",
        ".limit locals 2",
        "getstatic java/lang/System/out Ljava/io/PrintStream;",
        "aload_1",
        "invokevirtual java/io/PrintStream/print(Ljava/lang/Object;)V",
        "return");

    ClassBuilder itf1 = jasminBuilder.addInterface("Itf1");
    itf1.addAbstractMethod("foo", ImmutableList.of("Ljava/lang/String;"), "V");

    ClassBuilder cls1 = jasminBuilder.addClass("Cls1", absCls.name, itf1.name);
    // Mimic Kotlin's "internal" class
    cls1.setAccess("");
    cls1.addBridgeMethod("foo", ImmutableList.of("Ljava/lang/String;"), "V",
        ".limit stack 2",
        ".limit locals 2",
        "aload_0",
        "aload_1",
        "invokevirtual " + cls1.name + "/foo(Ljava/lang/Object;)V",
        "return");

    ClassBuilder itf2 = jasminBuilder.addInterface("Itf2");
    itf2.addAbstractMethod("foo", ImmutableList.of("Ljava/lang/Integer;"), "V");

    ClassBuilder cls2 = jasminBuilder.addClass("Cls2", absCls.name, itf2.name);
    // Mimic Kotlin's "internal" class
    cls2.setAccess("");
    cls2.addBridgeMethod("foo", ImmutableList.of("Ljava/lang/Integer;"), "V",
        ".limit stack 2",
        ".limit locals 2",
        "aload_0",
        "aload_1",
        "invokevirtual " + cls2.name + "/foo(Ljava/lang/Object;)V",
        "return");

    ClassBuilder mainClass = jasminBuilder.addClass("Main");
    mainClass.addMainMethod(
        ".limit stack 5",
        ".limit locals 2",
        "new " + cls1.name,
        "dup",
        "invokespecial " + cls1.name + "/<init>()V",
        "astore_0",
        "aload_0",
        "ldc \"Hello\"",
        "invokevirtual " + cls1.name + "/foo(Ljava/lang/String;)V",
        "new " + cls2.name,
        "dup",
        "invokespecial " + cls2.name + "/<init>()V",
        "astore_0",
        "aload_0",
        "iconst_0",
        "invokestatic java/lang/Integer/valueOf(I)Ljava/lang/Integer;",
        "invokevirtual " + cls2.name + "/foo(Ljava/lang/Integer;)V",
        "return"
    );

    final String mainClassName = mainClass.name;
    String proguardConfig = keepMainProguardConfiguration(mainClass.name, false, false);

    AndroidApp processedApp = runAndVerifyOnJvmAndArt(jasminBuilder, mainClassName, proguardConfig);

    CodeInspector inspector = new CodeInspector(processedApp);
    ClassSubject absSubject = inspector.clazz(absCls.name);
    assertThat(absSubject, isPresent());
    ClassSubject cls1Subject = inspector.clazz(cls1.name);
    assertThat(cls1Subject, isPresent());
    ClassSubject cls2Subject = inspector.clazz(cls2.name);
    assertThat(cls2Subject, isPresent());

    // Cls1#foo and Cls2#foo should not refer to each other.
    // They can invoke their own bridge method or AbsCls#foo (via member rebinding).

    // Cls2#foo has been moved to AbsCls#foo as a result of bridge hoisting.
    MethodSubject fooInCls2 = cls2Subject.method("void", "foo", "java.lang.Integer");
    assertThat(fooInCls2, not(isPresent()));

    MethodSubject fooFromCls2InAbsCls = absSubject.method("void", "foo", "java.lang.Integer");
    assertThat(fooFromCls2InAbsCls, isPresent());
    DexCode code = fooFromCls2InAbsCls.getMethod().getCode().asDexCode();
    checkInstructions(code, ImmutableList.of(InvokeVirtual.class, ReturnVoid.class));
    InvokeVirtual invoke = (InvokeVirtual) code.instructions[0];
    assertEquals(absSubject.getDexProgramClass().type, invoke.getMethod().holder);

    // Cls1#foo has been moved to AbsCls#foo as a result of bridge hoisting.
    MethodSubject fooInCls1 = cls1Subject.method("void", "foo", "java.lang.String");
    assertThat(fooInCls1, not(isPresent()));

    MethodSubject fooFromCls1InAbsCls = absSubject.method("void", "foo", "java.lang.String");
    assertThat(fooFromCls1InAbsCls, isPresent());
    code = fooFromCls1InAbsCls.getMethod().getCode().asDexCode();
    checkInstructions(code, ImmutableList.of(InvokeVirtual.class, ReturnVoid.class));
    invoke = (InvokeVirtual) code.instructions[0];
    assertEquals(absSubject.getDexProgramClass().type, invoke.getMethod().holder);
  }

  /**
   * class Base {
   *   void foo(Object o) {...}
   * }
   * interface ItfInteger {
   *   void foo(Integer o);
   * }
   * class DerivedInteger extends Base implements ItfInteger {
   *   // Bridge method deferring to Base#foo(Object):
   *   public bridge synthetic void foo(Integer o) {
   *     foo((Object) o);
   *   } }
   * class DerivedString extends Base {
   *   // Regular non-bridge method calling Base#foo(Object):
   *   public void bar(String o) {
   *     foo(o);
   *   } }
   */
  @Test
  public void test_bridgeTargetInBase_bridgeAndNonBridge() throws Exception {
    JasminBuilder jasminBuilder = new JasminBuilder();

    ClassBuilder baseCls = jasminBuilder.addClass("Base");
    baseCls.addVirtualMethod("foo", ImmutableList.of("Ljava/lang/Object;"), "V",
        ".limit stack 3",
        ".limit locals 2",
        "getstatic java/lang/System/out Ljava/io/PrintStream;",
        "aload_1",
        "invokevirtual java/io/PrintStream/print(Ljava/lang/Object;)V",
        "return");

    ClassBuilder itf = jasminBuilder.addInterface("ItfInteger");
    itf.addAbstractMethod("foo", ImmutableList.of("Ljava/lang/Integer;"), "V");

    ClassBuilder cls1 = jasminBuilder.addClass("DerivedInteger", baseCls.name, itf.name);
    cls1.addBridgeMethod("foo", ImmutableList.of("Ljava/lang/Integer;"), "V",
        ".limit stack 2",
        ".limit locals 2",
        "aload_0",
        "aload_1",
        "invokevirtual " + cls1.name + "/foo(Ljava/lang/Object;)V",
        "return");

    ClassBuilder cls2 = jasminBuilder.addClass("DerivedString", baseCls.name);
    cls2.addVirtualMethod("bar", ImmutableList.of("Ljava/lang/String;"), "V",
        ".limit stack 2",
        ".limit locals 2",
        "aload_0",
        "aload_1",
        "invokevirtual " + cls2.name + "/foo(Ljava/lang/Object;)V",
        "return");

    ClassBuilder mainClass = jasminBuilder.addClass("Main");
    mainClass.addMainMethod(
        ".limit stack 5",
        ".limit locals 2",
        "new " + cls1.name,
        "dup",
        "invokespecial " + cls1.name + "/<init>()V",
        "astore_0",
        "aload_0",
        "iconst_0",
        "invokestatic java/lang/Integer/valueOf(I)Ljava/lang/Integer;",
        "invokevirtual " + cls1.name + "/foo(Ljava/lang/Integer;)V",
        "new " + cls2.name,
        "dup",
        "invokespecial " + cls2.name + "/<init>()V",
        "astore_0",
        "aload_0",
        "ldc \"Bar\"",
        "invokevirtual " + cls2.name + "/bar(Ljava/lang/String;)V",
        "return"
    );

    final String mainClassName = mainClass.name;
    String proguardConfig = keepMainProguardConfiguration(mainClass.name, false, false);

    AndroidApp processedApp = runAndVerifyOnJvmAndArt(jasminBuilder, mainClassName, proguardConfig);

    CodeInspector inspector = new CodeInspector(processedApp);
    ClassSubject baseSubject = inspector.clazz(baseCls.name);
    assertThat(baseSubject, isPresent());
    ClassSubject cls1Subject = inspector.clazz(cls1.name);
    assertThat(cls1Subject, isPresent());
    ClassSubject cls2Subject = inspector.clazz(cls2.name);
    assertThat(cls2Subject, isPresent());

    // Cls1#foo and Cls2#bar should refer to Base#foo.

    MethodSubject barInCls2 = cls2Subject.method("void", "bar", "java.lang.String");
    assertThat(barInCls2, isPresent());
    DexCode code = barInCls2.getMethod().getCode().asDexCode();
    checkInstructions(code, ImmutableList.of(InvokeVirtual.class, ReturnVoid.class));
    InvokeVirtual invoke = (InvokeVirtual) code.instructions[0];
    assertEquals(baseSubject.getDexProgramClass().type, invoke.getMethod().holder);

    // Cls1#foo has been moved to Base#foo as a result of bridge hoisting.
    MethodSubject fooInCls1 = cls1Subject.method("void", "foo", "java.lang.Integer");
    assertThat(fooInCls1, not(isPresent()));

    MethodSubject fooInBase = baseSubject.method("void", "foo", "java.lang.Integer");
    assertThat(fooInBase, isPresent());
    code = fooInBase.getMethod().getCode().asDexCode();
    checkInstructions(code, ImmutableList.of(InvokeVirtual.class, ReturnVoid.class));
    invoke = (InvokeVirtual) code.instructions[0];
    assertEquals(baseSubject.getDexProgramClass().type, invoke.getMethod().holder);
  }

  /**
   * class Base {
   *   protected void foo(Object o) { ... }
   *   // Bridge method deferring to Base#foo(Object):
   *   public bridge synthetic void foo(Integer o) {
   *     foo((Object) o);
   *   } }
   * class DerivedString extends Base {
   *   // Regular non-bridge method calling Base#foo(Object):
   *   public void bar(String o) {
   *     foo(o);
   *   } }
   */
  @Test
  public void test_nonBridgeInSubType() throws Exception {
    JasminBuilder jasminBuilder = new JasminBuilder();

    ClassBuilder baseCls = jasminBuilder.addClass("Base");
    baseCls.addVirtualMethod("foo", ImmutableList.of("Ljava/lang/Object;"), "V",
        ".limit stack 3",
        ".limit locals 2",
        "getstatic java/lang/System/out Ljava/io/PrintStream;",
        "aload_1",
        "invokevirtual java/io/PrintStream/print(Ljava/lang/Object;)V",
        "return");
    baseCls.addBridgeMethod("foo", ImmutableList.of("Ljava/lang/Integer;"), "V",
        ".limit stack 2",
        ".limit locals 2",
        "aload_0",
        "aload_1",
        "invokevirtual " + baseCls.name + "/foo(Ljava/lang/Object;)V",
        "return");

    ClassBuilder subCls = jasminBuilder.addClass("DerivedString", baseCls.name);
    subCls.addVirtualMethod("bar", ImmutableList.of("Ljava/lang/String;"), "V",
        ".limit stack 2",
        ".limit locals 2",
        "aload_0",
        "aload_1",
        "invokevirtual " + subCls.name + "/foo(Ljava/lang/Object;)V",
        "return");

    ClassBuilder mainClass = jasminBuilder.addClass("Main");
    mainClass.addMainMethod(
        ".limit stack 5",
        ".limit locals 2",
        "new " + baseCls.name,
        "dup",
        "invokespecial " + baseCls.name + "/<init>()V",
        "astore_0",
        "aload_0",
        "iconst_0",
        "invokestatic java/lang/Integer/valueOf(I)Ljava/lang/Integer;",
        "invokevirtual " + baseCls.name + "/foo(Ljava/lang/Integer;)V",
        "new " + subCls.name,
        "dup",
        "invokespecial " + subCls.name + "/<init>()V",
        "astore_0",
        "aload_0",
        "ldc \"Bar\"",
        "invokevirtual " + subCls.name + "/bar(Ljava/lang/String;)V",
        "return"
    );

    final String mainClassName = mainClass.name;
    String proguardConfig = keepMainProguardConfiguration(mainClass.name, false, false);

    AndroidApp processedApp = runAndVerifyOnJvmAndArt(jasminBuilder, mainClassName, proguardConfig);

    CodeInspector inspector = new CodeInspector(processedApp);
    ClassSubject baseSubject = inspector.clazz(baseCls.name);
    assertThat(baseSubject, isPresent());
    ClassSubject subSubject = inspector.clazz(subCls.name);
    assertThat(subSubject, isPresent());

    // DerivedString2#bar should refer to Base#foo.

    MethodSubject barInSub = subSubject.method("void", "bar", "java.lang.String");
    assertThat(barInSub, isPresent());
    DexCode code = barInSub.getMethod().getCode().asDexCode();
    checkInstructions(code, ImmutableList.of(InvokeVirtual.class, ReturnVoid.class));
    InvokeVirtual invoke = (InvokeVirtual) code.instructions[0];
    assertEquals(baseSubject.getDexProgramClass().type, invoke.getMethod().holder);
  }

  /*
   * public class Base {
   *  public bridge void foo(Integer i) { foo((Object) i); }
   *  public foo(Object o) { print(o); }
   *  public bar(String s) { foo(s); }
   * }
   */
  @Test
  public void test_bridgeTargetInsideTheSameClass() throws Exception {
    JasminBuilder jasminBuilder = new JasminBuilder();

    ClassBuilder cls = jasminBuilder.addClass("Base");
    cls.addBridgeMethod("foo", ImmutableList.of("Ljava/lang/Integer;"), "V",
        ".limit stack 2",
        ".limit locals 2",
        "aload_0",
        "aload_1",
        "invokevirtual " + cls.name + "/foo(Ljava/lang/Object;)V",
        "return");
    cls.addVirtualMethod("foo", ImmutableList.of("Ljava/lang/Object;"), "V",
        ".limit stack 3",
        ".limit locals 2",
        "getstatic java/lang/System/out Ljava/io/PrintStream;",
        "aload_1",
        "invokevirtual java/io/PrintStream/print(Ljava/lang/Object;)V",
        "return");
    cls.addVirtualMethod("bar", ImmutableList.of("Ljava/lang/String;"), "V",
        ".limit stack 2",
        ".limit locals 2",
        "aload_0",
        "aload_1",
        "invokevirtual " + cls.name + "/foo(Ljava/lang/Object;)V",
        "return");

    ClassBuilder mainClass = jasminBuilder.addClass("Main");
    mainClass.addMainMethod(
        ".limit stack 5",
        ".limit locals 2",
        "new " + cls.name,
        "dup",
        "invokespecial " + cls.name + "/<init>()V",
        "astore_0",
        "aload_0",
        "iconst_0",
        "invokestatic java/lang/Integer/valueOf(I)Ljava/lang/Integer;",
        "invokevirtual " + cls.name + "/foo(Ljava/lang/Integer;)V",
        "new " + cls.name,
        "dup",
        "invokespecial " + cls.name + "/<init>()V",
        "astore_0",
        "aload_0",
        "ldc \"Bar\"",
        "invokevirtual " + cls.name + "/bar(Ljava/lang/String;)V",
        "return"
    );
    final String mainClassName = mainClass.name;
    String proguardConfig = keepMainProguardConfiguration(mainClass.name, false, false);
    AndroidApp processedApp = runAndVerifyOnJvmAndArt(jasminBuilder, mainClassName, proguardConfig);

    CodeInspector inspector = new CodeInspector(processedApp);
    ClassSubject baseSubject = inspector.clazz(cls.name);
    assertThat(baseSubject, isPresent());

    // Base#bar should remain as-is, i.e., refer to Base#foo(Object).

    MethodSubject barInSub = baseSubject.method("void", "bar", "java.lang.String");
    assertThat(barInSub, isPresent());
    DexCode code = barInSub.getMethod().getCode().asDexCode();
    checkInstructions(code, ImmutableList.of(InvokeVirtual.class, ReturnVoid.class));
    InvokeVirtual invoke = (InvokeVirtual) code.instructions[0];
    assertEquals(baseSubject.getDexProgramClass().type, invoke.getMethod().holder);
  }

  private AndroidApp runAndVerifyOnJvmAndArt(
      JasminBuilder jasminBuilder, String mainClassName, String proguardConfig) throws Exception {
    // Run input program on java.
    Path outputDirectory = temp.newFolder().toPath();
    jasminBuilder.writeClassFiles(outputDirectory);
    ProcessResult javaResult = ToolHelper.runJava(outputDirectory, mainClassName);
    assertEquals(0, javaResult.exitCode);

    AndroidApp processedApp = compileWithR8(jasminBuilder.build(), proguardConfig, this::configure);

    // Run processed (output) program on ART
    ProcessResult artResult = runOnArtRaw(processedApp, mainClassName);
    assertEquals(javaResult.stdout, artResult.stdout);
    assertEquals(-1, artResult.stderr.indexOf("VerifyError"));

    return processedApp;
  }

  private void configure(InternalOptions options) {
    // Callees are invoked with a simple constant, e.g., "Bar". Propagating it into the callees
    // bothers what the tests want to check, such as exact instructions in the body that include
    // invocation kinds, like virtual call to a bridge.
    assert !options.callSiteOptimizationOptions().isConstantPropagationEnabled();
    // Disable inlining to avoid the (short) tested method from being inlined and then removed.
    options.enableInlining = false;
  }
}
