// 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.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.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 final Backend backend;

  @Parameters(name = "{0}")
  public static Backend[] setup() {
    return Backend.values();
  }

  public IndirectSuperInterfaceTest(Backend backend) {
    this.backend = backend;
  }

  @Test
  public void test() throws Exception {
    String expected = StringUtils.joinLines(
        "A::method -> InterfaceA::method",
        "B::method -> InterfaceB::method",
        "C::method -> InterfaceC::method",
        "D::method -> InterfaceD::method");

    testForJvm()
        .addTestClasspath()
        .run(TestClass.class)
        .assertSuccessWithOutput(expected);

    testForR8(backend)
        .addProgramClasses(CLASSES)
        .addKeepPackageRules(TestClass.class.getPackage())
        .addKeepMainRule(TestClass.class)
        .enableInliningAnnotations()
        .run(TestClass.class)
        .assertSuccessWithOutput(expected);
  }
}
