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