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

import static com.android.tools.r8.ToolHelper.getMostRecentAndroidJar;
import static org.hamcrest.CoreMatchers.containsString;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;

import com.android.tools.r8.AsmTestBase;
import com.android.tools.r8.R8TestRunResult;
import com.android.tools.r8.TestParameters;
import com.android.tools.r8.TestParametersCollection;
import com.android.tools.r8.TestRunResult;
import com.android.tools.r8.graph.DexEncodedMethod;
import com.android.tools.r8.graph.DexMethod;
import com.android.tools.r8.graph.DexProgramClass;
import com.android.tools.r8.graph.ProgramMethod;
import com.android.tools.r8.graph.ResolutionResult;
import com.android.tools.r8.shaking.AppInfoWithLiveness;
import com.android.tools.r8.utils.AndroidApiLevel;
import com.google.common.collect.ImmutableList;
import java.util.List;
import org.junit.Assert;
import org.junit.BeforeClass;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.Parameterized;
import org.junit.runners.Parameterized.Parameters;
import org.objectweb.asm.ClassWriter;
import org.objectweb.asm.MethodVisitor;
import org.objectweb.asm.Opcodes;

@RunWith(Parameterized.class)
public class VirtualOverrideOfStaticMethodWithVirtualParentInterfaceTest extends AsmTestBase {

  public interface A {
    default void f() {}
  }

  public interface B extends A {
    // Made static using ASM.
    /*static*/ default void f() {}
  }

  public static class C implements B {
    public void f() {
      System.out.println("Called C.f");
    }
  }

  public static class Main {

    public static void main(String[] args) {
      B b = new C();
      b.f();
    }
  }

  public static class BDump implements Opcodes {

    static String prefix(String suffix) {
      return VirtualOverrideOfStaticMethodWithVirtualParentInterfaceTest.class
              .getTypeName()
              .replace('.', '/')
          + suffix;
    }

    public static byte[] dump() {
      ClassWriter cw = new ClassWriter(0);
      cw.visit(
          V1_8,
          ACC_PUBLIC | ACC_ABSTRACT | ACC_INTERFACE,
          prefix("$B"),
          null,
          "java/lang/Object",
          null);
      {
        // Added ACC_STATIC
        MethodVisitor mv = cw.visitMethod(ACC_PUBLIC | ACC_STATIC, "f", "()V", null, null);
        mv.visitCode();
        mv.visitInsn(RETURN);
        mv.visitMaxs(0, 1);
        mv.visitEnd();
      }
      cw.visitEnd();
      return cw.toByteArray();
    }
  }

  public static List<Class<?>> CLASSES = ImmutableList.of(A.class, C.class, Main.class);

  public static byte[] DUMP = BDump.dump();

  private static AppInfoWithLiveness appInfo;

  @BeforeClass
  public static void computeAppInfo() throws Exception {
    appInfo =
        computeAppViewWithLiveness(
                buildClasses(CLASSES)
                    .addClassProgramData(DUMP)
                    .addLibraryFile(getMostRecentAndroidJar())
                    .build(),
                Main.class)
            .appInfo();
  }

  private static DexMethod buildMethod(Class clazz, String name) {
    return buildNullaryVoidMethod(clazz, name, appInfo.dexItemFactory());
  }

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

  private final TestParameters parameters;
  private final DexMethod methodOnAReference = buildMethod(A.class, "f");
  private final DexMethod methodOnBReference = buildMethod(B.class, "f");
  private final DexMethod methodOnCReference = buildMethod(C.class, "f");

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

  @Test
  public void lookupSingleTarget() {
    DexProgramClass bClass = appInfo.definitionForProgramType(methodOnBReference.holder);
    ProgramMethod methodOnB = bClass.lookupProgramMethod(methodOnBReference);
    ResolutionResult resolutionResult =
        appInfo.resolveMethodOnInterface(methodOnBReference.holder, methodOnBReference);
    DexEncodedMethod resolved = resolutionResult.getSingleTarget();
    assertEquals(methodOnBReference, resolved.getReference());
    assertFalse(resolutionResult.isVirtualTarget());
    DexEncodedMethod singleVirtualTarget =
        appInfo.lookupSingleVirtualTarget(methodOnBReference, methodOnB, false);
    Assert.assertNull(singleVirtualTarget);
  }

  @Test
  public void lookupVirtualTargets() {
    ResolutionResult resolutionResult =
        appInfo.resolveMethodOnInterface(methodOnBReference.holder, methodOnBReference);
    DexEncodedMethod resolved = resolutionResult.getSingleTarget();
    assertEquals(methodOnBReference, resolved.getReference());
    assertFalse(resolutionResult.isVirtualTarget());
  }

  @Test
  public void runJvmAndD8() throws Exception {
    TestRunResult<?> runResult;
    if (parameters.isCfRuntime()) {
      runResult =
          testForJvm()
              .addProgramClasses(CLASSES)
              .addProgramClassFileData(DUMP)
              .run(parameters.getRuntime(), Main.class);
    } else {
      runResult =
          testForD8()
              .addProgramClasses(CLASSES)
              .addProgramClassFileData(DUMP)
              .setMinApi(parameters.getApiLevel())
              .run(parameters.getRuntime(), Main.class);
    }
    checkResult(runResult);
  }

  @Test
  public void runR8() throws Exception {
    runR8(true);
  }

  @Test
  public void runR8NoMerging() throws Exception {
    runR8(false);
  }

  public void runR8(boolean enableVerticalClassMerging) throws Exception {
    R8TestRunResult runResult =
        testForR8(parameters.getBackend())
            .addProgramClasses(CLASSES)
            .addProgramClassFileData(DUMP)
            .addKeepMainRule(Main.class)
            .setMinApi(parameters.getApiLevel())
            .addOptionsModification(o -> o.enableVerticalClassMerging = enableVerticalClassMerging)
            .run(parameters.getRuntime(), Main.class);
    if (enableVerticalClassMerging) {
      // Vertical class merging will merge B and C and change the instruction to invoke-virtual
      // causing the legacy ART runtime behavior to match the expected error.
      runResult.assertFailureWithErrorThatMatches(containsString("IncompatibleClassChangeError"));
    } else {
      checkResult(runResult);
    }
  }

  private void checkResult(TestRunResult<?> runResult) {
    runResult.assertFailureWithErrorThatMatches(containsString(expectedRuntimeError()));
  }

  private String expectedRuntimeError() {
    if (parameters.isDexRuntime()
        && parameters.getApiLevel().getLevel() < AndroidApiLevel.N.getLevel()) {
      // When desugaring default interface methods the error will be NoSuchMethodError.
      return "NoSuchMethodError";
    }
    return "IncompatibleClassChangeError";
  }
}
