// 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.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;

import com.android.tools.r8.AsmTestBase;
import com.android.tools.r8.TestParameters;
import com.android.tools.r8.TestParametersCollection;
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.MethodResolutionResult;
import com.android.tools.r8.graph.ProgramMethod;
import com.android.tools.r8.shaking.AppInfoWithLiveness;
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);
    MethodResolutionResult 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() {
    MethodResolutionResult resolutionResult =
        appInfo.resolveMethodOnInterface(methodOnBReference.holder, methodOnBReference);
    DexEncodedMethod resolved = resolutionResult.getSingleTarget();
    assertEquals(methodOnBReference, resolved.getReference());
    assertFalse(resolutionResult.isVirtualTarget());
  }

  @Test
  public void runJvmAndD8() throws Exception {
    testForRuntime(parameters)
        .addProgramClasses(CLASSES)
        .addProgramClassFileData(DUMP)
        .run(parameters.getRuntime(), Main.class)
        .assertFailureWithErrorThatThrows(IncompatibleClassChangeError.class);
  }

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

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

  public void runR8(boolean enableVerticalClassMerging) throws Exception {
    testForR8(parameters.getBackend())
        .addProgramClasses(CLASSES)
        .addProgramClassFileData(DUMP)
        .addKeepMainRule(Main.class)
        .setMinApi(parameters.getApiLevel())
        .addOptionsModification(o -> o.enableVerticalClassMerging = enableVerticalClassMerging)
        .run(parameters.getRuntime(), Main.class)
        .assertFailureWithErrorThatThrows(IncompatibleClassChangeError.class);
  }
}
