// 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.ir.optimize;

import com.android.tools.r8.NeverClassInline;
import com.android.tools.r8.NeverInline;
import com.android.tools.r8.NoVerticalClassMerging;
import com.android.tools.r8.TestBase;
import com.android.tools.r8.TestParameters;
import com.android.tools.r8.TestParametersCollection;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.Parameterized;

/**
 * Reproduction for issue b/143628636.
 *
 * <p>There are a lot of conditions that need to be in place to trigger this issue. The root issue
 * is resolution incorrectly pruning out a valid candidate. However, mostly code will not even get
 * to that place as a single target is typically found prior to it, and then, if the incorrect
 * pruning of the lookup targets takes place, that needs to further cause invalid call site
 * information to be propagated, which in turn will cause inlining to inline a method where it
 * should not. It is exceedingly unlikely that this test will continue to be a regression test as
 * any one of the above aspects could and likely will be changed in the code base.
 */
@RunWith(Parameterized.class)
public class DefaultInterfaceIssue143628636Test extends TestBase {

  private final TestParameters parameters;

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

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

  @Test
  public void test() throws Exception {
    testForR8(parameters.getBackend())
        .enableInliningAnnotations()
        .enableNeverClassInliningAnnotations()
        .enableNoVerticalClassMergingAnnotations()
        .addInnerClasses(DefaultInterfaceIssue143628636Test.class)
        .addKeepMainRule(TestClass.class)
        .addKeepClassRules(I.class)
        .setMinApi(parameters.getApiLevel())
        .run(parameters.getRuntime(), TestClass.class)
        .assertSuccessWithOutputLines("2", "5");
  }

  @NoVerticalClassMerging
  @NeverClassInline
  public interface A {

    @NeverInline
    default void f(
        // This parameter is needed otherwise the info recording bails out. (See b/143684659).
        int z) {
      // In the end the issue will manifest as a class-cast exception because B.g() is inlined here
      // due to the incorrect conclusion that the only possible receiver type is B.
      System.out.println(g() + z);
    }

    int g();
  }

  // This intermediate interface is needed to cause lookupInterfaceTargets to return null as I
  // is pinned (why does it return null for a pinned holder is questionable, filed b/143686005).
  // The return of null, will cause the outer lookup to hit a different lookup case where the
  // refined receiver (here I) will cause the non-subtype method A.f to be pruned.
  public interface I extends A {}

  // Make sure this class and the call to h() are never eliminated. It is the *partial* info
  // propagated from h() to f() that results in incorrect call-site optimization info.
  @NoVerticalClassMerging
  @NeverClassInline
  public static class B implements A {
    public final int x;

    public B(int x) {
      this.x = x;
    }

    @Override
    public int g() {
      return x;
    }

    @NeverInline
    public void h() {
      // This will lookup A.f and propagate that the receiver is known to be B.
      f(x);
    }
  }

  // Make sure this class and the call to h() are never eliminated. It is the *missing* info
  // propagated from h() to f() that results in incorrect call-site optimization info.
  @NoVerticalClassMerging
  @NeverClassInline
  public static class C implements I {
    public final I i;
    public final int y;

    public C(I i, int y) {
      this.i = i;
      this.y = y;
    }

    @Override
    public int g() {
      return y;
    }

    @NeverInline
    public void h() {
      // Due to the refined receiver type I used here, the lookup targets will omit A.f !
      // Thus the info propagation does not propagate that I (and thus C) may be a receiver type.
      i.f(y);
    }
  }

  static class TestClass {

    public static void main(String[] args) {
      new B(args.length + 1).h();
      new C(args.length == 42 ? null : new C(null, args.length + 2), args.length + 3).h();
    }
  }
}
