// Copyright (c) 2017, 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.graph;

import static org.hamcrest.CoreMatchers.containsString;
import static org.junit.Assert.assertTrue;

import com.android.tools.r8.NoMethodStaticizing;
import com.android.tools.r8.TestBase;
import com.android.tools.r8.TestParameters;
import com.android.tools.r8.TestParametersCollection;
import com.android.tools.r8.TestRunResult;
import com.android.tools.r8.ToolHelper.DexVm.Version;
import com.android.tools.r8.transformers.ClassTransformer;
import com.android.tools.r8.utils.DescriptorUtils;
import com.android.tools.r8.utils.StringUtils;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.Parameterized;
import org.junit.runners.Parameterized.Parameters;
import org.objectweb.asm.MethodVisitor;
import org.objectweb.asm.Opcodes;

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

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

  final TestParameters parameters;

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

  static final String EXPECTED =
      StringUtils.lines(
          "superMethod in SubLevel2",
          "superMethod in SubLevel2",
          "superMethod in SubLevel2",
          "java.lang.NoSuchMethodError",
          "subLevel1Method in SubLevel2",
          "subLevel1Method in SubLevel2",
          "subLevel2Method in SubLevel2",
          "From SubLevel1: otherSuperMethod in Super");

  static final String UNEXPECTED_DEX_5_AND_6_OUTPUT =
      StringUtils.lines(
          "superMethod in Super",
          "superMethod in SubLevel1",
          "superMethod in SubLevel2",
          "java.lang.NoSuchMethodError",
          "subLevel1Method in SubLevel1",
          "subLevel1Method in SubLevel2",
          "subLevel2Method in SubLevel2",
          "From SubLevel1: otherSuperMethod in Super");

  String getExpectedOutput() {
    if (parameters.isDexRuntime()) {
      Version version = parameters.getRuntime().asDex().getVm().getVersion();
      if (version.isNewerThanOrEqual(Version.V5_1_1)
          && version.isOlderThanOrEqual(Version.V6_0_1)) {
        return UNEXPECTED_DEX_5_AND_6_OUTPUT;
      }
    }
    return EXPECTED;
  }

  @Test
  public void testReference() throws Exception {
    testForRuntime(parameters)
        .addProgramClasses(
            MainClass.class,
            Consumer.class,
            Super.class,
            SubLevel1.class,
            SubLevel2.class,
            SubClassOfInvokerClass.class)
        .addProgramClassFileData(InvokerClassDump.dumpVerifying())
        .run(parameters.getRuntime(), MainClass.class)
        .assertSuccessWithOutput(getExpectedOutput());
  }

  @Test
  public void testR8() throws Exception {
    testForR8(parameters.getBackend())
        .addProgramClasses(
            MainClass.class,
            Consumer.class,
            Super.class,
            SubLevel1.class,
            SubLevel2.class,
            SubClassOfInvokerClass.class)
        .addProgramClassFileData(InvokerClassDump.dumpVerifying())
        .setMinApi(parameters.getApiLevel())
        .addKeepMainRule(MainClass.class)
        .run(parameters.getRuntime(), MainClass.class)
        .assertSuccessWithOutput(EXPECTED);
  }

  @Test
  public void testReferenceNonVerifying() throws Exception {
    testForRuntime(parameters)
        .addProgramClasses(
            MainClassFailing.class,
            Consumer.class,
            Super.class,
            SubLevel1.class,
            SubLevel2.class,
            SubClassOfInvokerClass.class)
        .addProgramClassFileData(InvokerClassDump.dumpNonVerifying())
        .run(parameters.getRuntime(), MainClassFailing.class)
        .apply(r -> checkNonVerifyingResult(r, false));
  }

  private void checkNonVerifyingResult(TestRunResult<?> result, boolean isR8) {
    // The input is invalid and any JVM will fail at verification time.
    if (parameters.isCfRuntime()) {
      result.assertFailureWithErrorThatThrows(VerifyError.class);
      return;
    }
    // Dex results vary wildly...
    Version version = parameters.getRuntime().asDex().getVm().getVersion();
    if (!isR8 && version.isOlderThanOrEqual(Version.V4_4_4)) {
      result.assertFailureWithErrorThatThrows(VerifyError.class);
    } else if (version == Version.V5_1_1 || version == Version.V6_0_1) {
      result.assertFailure();
    } else {
      result.assertSuccessWithOutputThatMatches(containsString(NoSuchMethodError.class.getName()));
    }
  }

  @Test
  public void testR8NonVerifying() throws Exception {
    testForR8(parameters.getBackend())
        .addProgramClasses(
            MainClassFailing.class,
            Consumer.class,
            Super.class,
            SubLevel1.class,
            SubLevel2.class,
            SubClassOfInvokerClass.class)
        .addProgramClassFileData(InvokerClassDump.dumpNonVerifying())
        .setMinApi(parameters.getApiLevel())
        .addKeepMainRule(MainClassFailing.class)
        .addOptionsModification(o -> o.testing.allowTypeErrors = true)
        .enableNoMethodStaticizingAnnotations()
        .run(parameters.getRuntime(), MainClassFailing.class)
        .apply(r -> checkNonVerifyingResult(r, true));
  }

  /** Copy of {@ref java.util.function.Consumer} to allow tests to run on early versions of art. */
  interface Consumer<T> {

    void accept(T item);
  }

  static class Super {

    public void superMethod() {
      System.out.println("superMethod in Super");
    }

    public void otherSuperMethod() {
      System.out.println("otherSuperMethod in Super");
    }
  }

  static class SubLevel1 extends Super {

    @Override
    public void superMethod() {
      System.out.println("superMethod in SubLevel1");
    }

    public void subLevel1Method() {
      System.out.println("subLevel1Method in SubLevel1");
    }

    public void otherSuperMethod() {
      System.out.println("otherSuperMethod in SubLevel1");
    }

    public void callOtherSuperMethod() {
      System.out.print("From SubLevel1: ");
      super.otherSuperMethod();
    }
  }

  static class SubClassOfInvokerClass extends InvokerClass {

    @NoMethodStaticizing
    public void subLevel2Method() {
      System.out.println("subLevel2Method in SubClassOfInvokerClass");
    }
  }

  static class SubLevel2 extends SubLevel1 {

    @Override
    public void superMethod() {
      System.out.println("superMethod in SubLevel2");
    }

    @Override
    public void subLevel1Method() {
      System.out.println("subLevel1Method in SubLevel2");
    }

    public void subLevel2Method() {
      System.out.println("subLevel2Method in SubLevel2");
    }

    public void otherSuperMethod() {
      System.out.println("otherSuperMethod in SubLevel2");
    }

    public void callOtherSuperMethodIndirect() {
      callOtherSuperMethod();
    }
  }

  static class MainClass {

    private static void tryInvoke(Consumer<InvokerClass> function) {
      InvokerClass invoker = new InvokerClass();
      try {
        function.accept(invoker);
      } catch (Throwable e) {
        System.out.println(e.getClass().getCanonicalName());
      }
    }

    public static void main(String... args) {
      tryInvoke(InvokerClass::invokeSuperMethodOnSuper);
      tryInvoke(InvokerClass::invokeSuperMethodOnSubLevel1);
      tryInvoke(InvokerClass::invokeSuperMethodOnSubLevel2);
      tryInvoke(InvokerClass::invokeSubLevel1MethodOnSuper);
      tryInvoke(InvokerClass::invokeSubLevel1MethodOnSubLevel1);
      tryInvoke(InvokerClass::invokeSubLevel1MethodOnSubLevel2);
      tryInvoke(InvokerClass::invokeSubLevel2MethodOnSubLevel2);
      tryInvoke(InvokerClass::callOtherSuperMethodIndirect);
    }
  }

  static class MainClassFailing {

    private static void tryInvoke(Consumer<InvokerClass> function) {
      InvokerClass invoker = new InvokerClass();
      try {
        function.accept(invoker);
      } catch (Throwable e) {
        System.out.println(e.getClass().getCanonicalName());
      }
    }

    public static void main(String... args) {
      tryInvoke(InvokerClass::invokeSubLevel2MethodOnSubClassOfInvokerClass);
    }
  }

  /**
   * This class is a stub class needed to compile the dependent Java classes. The actual
   * implementation that will be used at runtime is generated by {@link InvokerClassDump}.
   */
  static class InvokerClass extends SubLevel2 {

    public void invokeSuperMethodOnSubLevel2() {
      stubIsUnreachable();
    }

    public void invokeSuperMethodOnSubLevel1() {
      stubIsUnreachable();
    }

    public void invokeSuperMethodOnSuper() {
      stubIsUnreachable();
    }

    public void invokeSubLevel1MethodOnSubLevel2() {
      stubIsUnreachable();
    }

    public void invokeSubLevel1MethodOnSubLevel1() {
      stubIsUnreachable();
    }

    public void invokeSubLevel1MethodOnSuper() {
      stubIsUnreachable();
    }

    public void invokeSubLevel2MethodOnSubLevel2() {
      stubIsUnreachable();
    }

    public void invokeSubLevel2MethodOnSubClassOfInvokerClass() {
      stubIsUnreachable();
    }

    private static void stubIsUnreachable() {
      throw new RuntimeException("Stub should never be called.");
    }
  }

  // This modifies the above {@link InvokerClass} with invoke-special for the corresponding methods.
  static class InvokerClassDump implements Opcodes {

    public static byte[] dumpVerifying() throws Exception {
      return dump(true);
    }

    public static byte[] dumpNonVerifying() throws Exception {
      return dump(false);
    }

    static byte[] dump(boolean verifying) throws Exception {
      return transformer(InvokerClass.class)
          .addClassTransformer(
              new ClassTransformer() {
                @Override
                public MethodVisitor visitMethod(
                    int access,
                    String name,
                    String descriptor,
                    String signature,
                    String[] exceptions) {
                  // Keep the constructor as is.
                  if (name.equals("<init>")) {
                    return super.visitMethod(access, name, descriptor, signature, exceptions);
                  }
                  // Remove all methods not in the form of invokeXonY.
                  if (!name.startsWith("invoke")) {
                    return null;
                  }
                  // If dumping valid methods drop the invoke on a subclass, otherwise drop all
                  // others.
                  if (verifying == name.equals("invokeSubLevel2MethodOnSubClassOfInvokerClass")) {
                    return null;
                  }
                  // Replace the body of invokeXonY methods by invoke of X on class Y.
                  MethodVisitor mv =
                      super.visitMethod(access, name, descriptor, signature, exceptions);
                  int split = name.indexOf("On");
                  assertTrue(split > 0);
                  String targetMethodRaw = name.substring("invoke".length(), split);
                  String targetMethod =
                      targetMethodRaw.substring(0, 1).toLowerCase() + targetMethodRaw.substring(1);
                  String targetHolderRaw = name.substring(split + 2);
                  String targetHolderType =
                      InvokeSuperTest.class.getTypeName() + "$" + targetHolderRaw;
                  String targetHolderName =
                      DescriptorUtils.getBinaryNameFromJavaType(targetHolderType);
                  mv.visitCode();
                  mv.visitVarInsn(ALOAD, 0);
                  mv.visitMethodInsn(INVOKESPECIAL, targetHolderName, targetMethod, "()V", false);
                  mv.visitInsn(RETURN);
                  mv.visitMaxs(1, 1);
                  mv.visitEnd();
                  return null;
                }
              })
          .transform();
    }
  }
}
