// 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.memberrebinding;

import com.android.tools.r8.NeverInline;
import com.android.tools.r8.TestBase;
import com.android.tools.r8.TestParameters;
import com.android.tools.r8.TestParametersCollection;
import com.android.tools.r8.utils.StringUtils;
import com.google.common.collect.ImmutableList;
import java.util.List;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.Parameterized;
import org.junit.runners.Parameterized.Parameter;
import org.junit.runners.Parameterized.Parameters;

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

  private static final List<Class<?>> CLASSES =
      ImmutableList.of(
          InterfaceA.class, InterfaceASub.class, A.class,
          InterfaceB.class, InterfaceBSub.class, B.class,
          InterfaceC.class, InterfaceCSub.class, C.class,
          InterfaceD.class, InterfaceDSub.class, D.class,
          TestClass.class);

  // Test A: class A extends an empty class that implements a non-empty interface.

  interface InterfaceA {
    @NeverInline
    default String method() {
      return "InterfaceA::method";
    }
  }

  static class InterfaceASub implements InterfaceA {
    // Intentionally empty.
  }

  static class A extends InterfaceASub {
    @Override
    public String method() {
      return "A::method -> " + super.method();
    }
  }

  // Test B: class B implements an empty interface that extends a non-empty interface.

  interface InterfaceB {
    @NeverInline
    default String method() {
      return "InterfaceB::method";
    }
  }

  interface InterfaceBSub extends InterfaceB {
    // Intentionally empty.
  }

  static class B implements InterfaceBSub {
    @Override
    public String method() {
      return "B::method -> " + InterfaceBSub.super.method();
    }
  }

  // Test C: class C extends a non-empty class that implements a non-empty interface.

  interface InterfaceC {
    @NeverInline
    default String method() {
      return "InterfaceC::method";
    }
  }

  static class InterfaceCSub implements InterfaceC {
    // This method is intentionally not annotated with @NeverInline. If we were to inline this
    // method we would risk introducing a super-invocation to InterfaceC.method() in C.method,
    // which would lead to an IncompatibleClassChangeError on the JVM.
    // (See also Art978_virtual_interfaceTest.)
    @Override
    public String method() {
      return InterfaceC.super.method();
    }
  }

  static class C extends InterfaceCSub {
    @Override
    public String method() {
      return "C::method -> " + super.method();
    }
  }

  // Test D: class D implements a non-empty empty interface that extends a non-empty interface.

  interface InterfaceD {
    @NeverInline
    default String method() {
      return "InterfaceD::method";
    }
  }

  interface InterfaceDSub extends InterfaceD {
    // This method is intentionally not annotated with @NeverInline. If we were to inline this
    // method we would risk introducing a super-invocation to InterfaceC.method() in C.method,
    // which would lead to an IncompatibleClassChangeError on the JVM.
    // (See also Art978_virtual_interfaceTest.)
    @Override
    default String method() {
      return InterfaceD.super.method();
    }
  }

  static class D implements InterfaceDSub {
    @Override
    public String method() {
      return "D::method -> " + InterfaceDSub.super.method();
    }
  }

  static class TestClass {

    public static void main(String[] args) {
      System.out.println(new A().method());
      System.out.println(new B().method());
      System.out.println(new C().method());
      System.out.print(new D().method());
    }
  }

  private static final String EXPECTED =
      StringUtils.joinLines(
          "A::method -> InterfaceA::method",
          "B::method -> InterfaceB::method",
          "C::method -> InterfaceC::method",
          "D::method -> InterfaceD::method");

  @Parameter(0)
  public TestParameters parameters;

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

  @Test
  public void testJvm() throws Exception {
    parameters.assumeJvmTestParameters();
    testForJvm(parameters)
        .addTestClasspath()
        .run(parameters.getRuntime(), TestClass.class)
        .assertSuccessWithOutput(EXPECTED);
  }

  @Test
  public void testR8() throws Exception {
    testForR8(parameters.getBackend())
        .addProgramClasses(CLASSES)
        .addKeepPackageRules(TestClass.class.getPackage())
        .addKeepMainRule(TestClass.class)
        .enableInliningAnnotations()
        .setMinApi(parameters)
        .run(parameters.getRuntime(), TestClass.class)
        .assertSuccessWithOutput(EXPECTED);
  }
}
