// 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.KeepConstantArguments;
import com.android.tools.r8.TestBase;
import com.android.tools.r8.TestParameters;
import com.android.tools.r8.TestParametersCollection;
import com.android.tools.r8.dex.code.DexInvokeVirtual;
import com.android.tools.r8.dex.code.DexReturnVoid;
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.InternalOptions;
import com.android.tools.r8.utils.codeinspector.ClassSubject;
import com.android.tools.r8.utils.codeinspector.MethodSubject;
import com.google.common.collect.ImmutableList;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.Parameterized;

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

  private final TestParameters parameters;

  @Parameterized.Parameters(name = "{0}")
  public static TestParametersCollection data() {
    return getTestParameters().withAllRuntimesAndApiLevels().build();
  }

  public B77836766(TestParameters parameters) {
    this.parameters = parameters;
  }

  /**
   * 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.addRuntimeInvisibleAnnotation(KeepConstantArguments.class.getTypeName());
    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 cls2Class = jasminBuilder.addClass("Cls2", absCls.name, itf2.name);
    // Mimic Kotlin's "internal" class
    cls2Class.setAccess("");
    cls2Class.addBridgeMethod(
        "foo",
        ImmutableList.of("Ljava/lang/Integer;"),
        "V",
        ".limit stack 2",
        ".limit locals 2",
        "aload_0",
        "aload_1",
        "invokevirtual " + cls2Class.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 " + cls2Class.name,
        "dup",
        "invokespecial " + cls2Class.name + "/<init>()V",
        "astore_0",
        "aload_0",
        "iconst_0",
        "invokestatic java/lang/Integer/valueOf(I)Ljava/lang/Integer;",
        "invokevirtual " + cls2Class.name + "/foo(Ljava/lang/Integer;)V",
        "return");

    testForR8(parameters.getBackend())
        .addProgramClassFileData(jasminBuilder.buildClasses())
        .addKeepMainRule(mainClass.name)
        .addOptionsModification(this::configure)
        .enableConstantArgumentAnnotations()
        .noHorizontalClassMerging(cls2Class.name)
        .noMinification()
        .setMinApi(parameters.getApiLevel())
        .compile()
        .inspect(
            inspector -> {
              ClassSubject absSubject = inspector.clazz(absCls.name);
              assertThat(absSubject, isPresent());
              ClassSubject cls1Subject = inspector.clazz(cls1.name);
              assertThat(cls1Subject, isPresent());
              ClassSubject cls2Subject = inspector.clazz(cls2Class.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());

              // 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());

              if (parameters.isDexRuntime()) {
                DexCode code = fooFromCls2InAbsCls.getMethod().getCode().asDexCode();
                checkInstructions(
                    code, ImmutableList.of(DexInvokeVirtual.class, DexReturnVoid.class));
                DexInvokeVirtual invoke = (DexInvokeVirtual) code.instructions[0];
                assertEquals(absSubject.getDexProgramClass().type, invoke.getMethod().holder);

                code = fooFromCls1InAbsCls.getMethod().getCode().asDexCode();
                checkInstructions(
                    code, ImmutableList.of(DexInvokeVirtual.class, DexReturnVoid.class));
                invoke = (DexInvokeVirtual) code.instructions[0];
                assertEquals(absSubject.getDexProgramClass().type, invoke.getMethod().holder);
              }
            })
        .run(parameters.getRuntime(), mainClass.name)
        .assertSuccessWithOutput("Hello0");
  }

  /**
   * 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 derivedIntegerClass =
        jasminBuilder.addClass("DerivedInteger", baseCls.name, itf.name);
    derivedIntegerClass.addBridgeMethod(
        "foo",
        ImmutableList.of("Ljava/lang/Integer;"),
        "V",
        ".limit stack 2",
        ".limit locals 2",
        "aload_0",
        "aload_1",
        "invokevirtual " + derivedIntegerClass.name + "/foo(Ljava/lang/Object;)V",
        "return");

    ClassBuilder cls2 = jasminBuilder.addClass("DerivedString", baseCls.name);
    cls2.addRuntimeInvisibleAnnotation(KeepConstantArguments.class.getTypeName());
    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 " + derivedIntegerClass.name,
        "dup",
        "invokespecial " + derivedIntegerClass.name + "/<init>()V",
        "astore_0",
        "aload_0",
        "iconst_0",
        "invokestatic java/lang/Integer/valueOf(I)Ljava/lang/Integer;",
        "invokevirtual " + derivedIntegerClass.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");

    testForR8(parameters.getBackend())
        .addProgramClassFileData(jasminBuilder.buildClasses())
        .addKeepMainRule(mainClass.name)
        .addOptionsModification(this::configure)
        .enableConstantArgumentAnnotations()
        .noHorizontalClassMerging(derivedIntegerClass.name)
        .noMinification()
        .setMinApi(parameters.getApiLevel())
        .compile()
        .inspect(
            inspector -> {
              ClassSubject baseSubject = inspector.clazz(baseCls.name);
              assertThat(baseSubject, isPresent());
              ClassSubject cls1Subject = inspector.clazz(derivedIntegerClass.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());

              // 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());

              if (parameters.isDexRuntime()) {
                DexCode code = barInCls2.getMethod().getCode().asDexCode();
                checkInstructions(
                    code, ImmutableList.of(DexInvokeVirtual.class, DexReturnVoid.class));
                DexInvokeVirtual invoke = (DexInvokeVirtual) code.instructions[0];
                assertEquals(baseSubject.getDexProgramClass().type, invoke.getMethod().holder);

                code = fooInBase.getMethod().getCode().asDexCode();
                checkInstructions(
                    code, ImmutableList.of(DexInvokeVirtual.class, DexReturnVoid.class));
                invoke = (DexInvokeVirtual) code.instructions[0];
                assertEquals(baseSubject.getDexProgramClass().type, invoke.getMethod().holder);
              }
            })
        .run(parameters.getRuntime(), mainClass.name)
        .assertSuccessWithOutput("0Bar");
  }

  /**
   * 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.addRuntimeInvisibleAnnotation(KeepConstantArguments.class.getTypeName());
    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"
    );

    testForR8(parameters.getBackend())
        .addProgramClassFileData(jasminBuilder.buildClasses())
        .addKeepMainRule(mainClass.name)
        .addOptionsModification(this::configure)
        .enableConstantArgumentAnnotations()
        .noMinification()
        .setMinApi(parameters.getApiLevel())
        .compile()
        .inspect(
            inspector -> {
              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());

              if (parameters.isDexRuntime()) {
                DexCode code = barInSub.getMethod().getCode().asDexCode();
                checkInstructions(
                    code, ImmutableList.of(DexInvokeVirtual.class, DexReturnVoid.class));
                DexInvokeVirtual invoke = (DexInvokeVirtual) code.instructions[0];
                assertEquals(baseSubject.getDexProgramClass().type, invoke.getMethod().holder);
              }
            })
        .run(parameters.getRuntime(), mainClass.name)
        .assertSuccessWithOutput("0Bar");
  }

  /*
   * 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.addRuntimeInvisibleAnnotation(KeepConstantArguments.class.getTypeName());
    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"
    );

    testForR8(parameters.getBackend())
        .addProgramClassFileData(jasminBuilder.buildClasses())
        .addKeepMainRule(mainClass.name)
        .addOptionsModification(this::configure)
        .enableConstantArgumentAnnotations()
        .noMinification()
        .setMinApi(parameters.getApiLevel())
        .compile()
        .inspect(
            inspector -> {
              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());

              if (parameters.isDexRuntime()) {
                DexCode code = barInSub.getMethod().getCode().asDexCode();
                checkInstructions(
                    code, ImmutableList.of(DexInvokeVirtual.class, DexReturnVoid.class));
                DexInvokeVirtual invoke = (DexInvokeVirtual) code.instructions[0];
                assertEquals(baseSubject.getDexProgramClass().type, invoke.getMethod().holder);
              }
            })
        .run(parameters.getRuntime(), mainClass.name)
        .assertSuccessWithOutput("0Bar");
  }

  private void configure(InternalOptions options) {
    options.callSiteOptimizationOptions().setEnableMethodStaticizing(false);
    // 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.
    // Disable inlining to avoid the (short) tested method from being inlined and then removed.
    options.inlinerOptions().enableInlining = false;
  }
}
