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

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;

import com.android.tools.r8.TestAppViewBuilder;
import com.android.tools.r8.TestBase;
import com.android.tools.r8.TestParameters;
import com.android.tools.r8.TestParametersCollection;
import com.android.tools.r8.ToolHelper;
import com.android.tools.r8.graph.AppView;
import com.android.tools.r8.graph.DexMethod;
import com.android.tools.r8.graph.DexProgramClass;
import com.android.tools.r8.graph.DexType;
import com.android.tools.r8.graph.LookupResult;
import com.android.tools.r8.graph.LookupResult.LookupResultSuccess;
import com.android.tools.r8.graph.MethodResolutionResult;
import com.android.tools.r8.shaking.AppInfoWithLiveness;
import com.android.tools.r8.shaking.ProguardConfigurationRule;
import com.android.tools.r8.utils.AndroidApiLevel;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableSet;
import java.util.HashSet;
import java.util.Set;
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 KeptTargetsIncompleteDiamondTest extends TestBase {

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

  public KeptTargetsIncompleteDiamondTest(TestParameters parameters) {
    parameters.assertNoneRuntime();
  }

  private AppView<AppInfoWithLiveness> computeAppViewWithLiveness(
      Class<?> methodToBeKept, Class<?> classToBeKept) throws Exception {
    return TestAppViewBuilder.builder()
        .addProgramClasses(I.class, J.class, K.class, L.class, A.class, Main.class)
        .addLibraryFiles(ToolHelper.getJava8RuntimeJar())
        .addKeepRuleBuilder(
            factory ->
                ImmutableList.<ProguardConfigurationRule>builder()
                    .addAll(buildKeepRuleForClassAndMethods(methodToBeKept, factory))
                    .addAll(buildKeepRuleForClass(classToBeKept, factory))
                    .addAll(buildKeepRuleForClassAndMethods(Main.class, factory))
                    .build())
        .setMinApi(AndroidApiLevel.N)
        .buildWithLiveness();
  }

  @Test
  public void testRefinedReceiverOnStaticTarget() throws Exception {
    // I { <-- kept
    //   foo() <-- kept, initial
    // }
    //
    // J {
    //   default foo() { ... } <-- kept, resolved
    // }
    //
    // K {  }
    //
    // L extends I, K { } <-- upperbound
    //
    // A implements L { <-- lowerbound
    //
    // }
    AppView<AppInfoWithLiveness> appView = computeAppViewWithLiveness(I.class, I.class);
    DexMethod method = buildNullaryVoidMethod(I.class, "foo", appView.dexItemFactory());
    MethodResolutionResult resolutionResult = appView.appInfo().resolveMethodOnInterface(method);
    DexType typeI = buildType(I.class, appView.dexItemFactory());
    DexType typeL = buildType(L.class, appView.dexItemFactory());
    DexType typeA = buildType(A.class, appView.dexItemFactory());
    DexProgramClass classI = appView.definitionForProgramType(typeI);
    DexProgramClass classL = appView.definitionForProgramType(typeL);
    DexProgramClass classA = appView.definitionForProgramType(typeA);
    LookupResult lookupResult =
        resolutionResult.lookupVirtualDispatchTargets(classI, appView.appInfo(), classL, classA);
    assertTrue(lookupResult.isLookupResultSuccess());
    LookupResultSuccess lookupResultSuccess = lookupResult.asLookupResultSuccess();
    Set<String> targets = new HashSet<>();
    lookupResultSuccess.forEach(
        methodTarget -> targets.add(methodTarget.asMethodTarget().getDefinition().qualifiedName()),
        lambdaTarget -> {
          assert false;
        });
    Set<String> expected = ImmutableSet.of(J.class.getTypeName() + ".foo");
    assertEquals(expected, targets);
    assertTrue(lookupResultSuccess.isComplete());
  }

  @Test
  public void testRefinedReceiverOnStaticTargetInRange() throws Exception {
    // I { <-- kept
    //   foo() <-- kept, initial, upperbound
    // }
    //
    // J {
    //   default foo() { ... } <-- kept, resolved
    // }
    //
    // K {  }
    //
    // L extends I, K { }
    //
    // A implements L { <-- lowerbound
    //
    // }
    AppView<AppInfoWithLiveness> appView = computeAppViewWithLiveness(I.class, I.class);
    DexMethod method = buildNullaryVoidMethod(I.class, "foo", appView.dexItemFactory());
    MethodResolutionResult resolutionResult = appView.appInfo().resolveMethodOnInterface(method);
    DexType typeI = buildType(I.class, appView.dexItemFactory());
    DexType typeL = buildType(L.class, appView.dexItemFactory());
    DexType typeA = buildType(A.class, appView.dexItemFactory());
    DexProgramClass classI = appView.definitionForProgramType(typeI);
    DexProgramClass classA = appView.definitionForProgramType(typeA);
    LookupResult lookupResult =
        resolutionResult.lookupVirtualDispatchTargets(classI, appView.appInfo(), classI, classA);
    assertTrue(lookupResult.isLookupResultSuccess());
    LookupResultSuccess lookupResultSuccess = lookupResult.asLookupResultSuccess();
    Set<String> targets = new HashSet<>();
    lookupResultSuccess.forEach(
        methodTarget -> targets.add(methodTarget.asMethodTarget().getDefinition().qualifiedName()),
        lambdaTarget -> {
          assert false;
        });
    Set<String> expected = ImmutableSet.of(J.class.getTypeName() + ".foo");
    assertEquals(expected, targets);
    assertTrue(lookupResultSuccess.isComplete());
  }

  @Test
  public void testRefinedReceiverWithKeptDispatchTarget() throws Exception {
    // I {
    //   foo() <-- initial
    // }
    //
    // J { <-- kept
    //   default foo() { ... } <-- kept, resolved
    // }
    //
    // K {  }
    //
    // L extends I, K { }
    //
    // A implements L { <-- lowerbound, upperbound
    //
    // }
    AppView<AppInfoWithLiveness> appView = computeAppViewWithLiveness(J.class, J.class);
    DexMethod method = buildNullaryVoidMethod(I.class, "foo", appView.dexItemFactory());
    MethodResolutionResult resolutionResult = appView.appInfo().resolveMethodOnInterface(method);
    DexType typeI = buildType(I.class, appView.dexItemFactory());
    DexType typeB = buildType(A.class, appView.dexItemFactory());
    DexProgramClass classI = appView.definitionForProgramType(typeI);
    DexProgramClass classA = appView.definitionForProgramType(typeB);
    LookupResult lookupResult =
        resolutionResult.lookupVirtualDispatchTargets(classI, appView.appInfo(), classA, classA);
    assertTrue(lookupResult.isLookupResultSuccess());
    LookupResultSuccess lookupResultSuccess = lookupResult.asLookupResultSuccess();
    Set<String> targets = new HashSet<>();
    lookupResultSuccess.forEach(
        methodTarget -> targets.add(methodTarget.asMethodTarget().getDefinition().qualifiedName()),
        lambdaTarget -> {
          assert false;
        });
    Set<String> expected = ImmutableSet.of(J.class.getTypeName() + ".foo");
    assertEquals(expected, targets);
    assertTrue(lookupResultSuccess.isIncomplete());
  }

  @Test
  public void testRefinedReceiverWithKeptRefinedReceiver() throws Exception {
    // I {
    //   foo() <-- initial
    // }
    //
    // J {
    //   default foo() { ... } <-- kept, resolved
    // }
    //
    // K {  }
    //
    // A implements I, K { <-- kept, lowerbound, upperbound
    //
    // }
    AppView<AppInfoWithLiveness> appView = computeAppViewWithLiveness(J.class, A.class);
    DexMethod method = buildNullaryVoidMethod(I.class, "foo", appView.dexItemFactory());
    MethodResolutionResult resolutionResult = appView.appInfo().resolveMethodOnInterface(method);
    DexType typeI = buildType(I.class, appView.dexItemFactory());
    DexType typeB = buildType(A.class, appView.dexItemFactory());
    DexProgramClass classI = appView.definitionForProgramType(typeI);
    DexProgramClass classA = appView.definitionForProgramType(typeB);
    LookupResult lookupResult =
        resolutionResult.lookupVirtualDispatchTargets(classI, appView.appInfo(), classA, classA);
    assertTrue(lookupResult.isLookupResultSuccess());
    LookupResultSuccess lookupResultSuccess = lookupResult.asLookupResultSuccess();
    Set<String> targets = new HashSet<>();
    lookupResultSuccess.forEach(
        methodTarget -> targets.add(methodTarget.asMethodTarget().getDefinition().qualifiedName()),
        lambdaTarget -> {
          assert false;
        });
    Set<String> expected = ImmutableSet.of(J.class.getTypeName() + ".foo");
    assertEquals(expected, targets);
    assertTrue(lookupResultSuccess.isIncomplete());
  }

  @Test
  public void testRefinedReceiverWithKeptClassOnInitial() throws Exception {
    // I { <-- kept
    //   foo() <-- kept, initial
    // }
    //
    // J {
    //   default foo() { ... } <-- resolved
    // }
    //
    // K {  }
    //
    // L extends I, K { }
    //
    // A implements L { <-- lowerbound, upperbound
    //
    // }
    AppView<AppInfoWithLiveness> appView = computeAppViewWithLiveness(I.class, I.class);
    DexMethod method = buildNullaryVoidMethod(I.class, "foo", appView.dexItemFactory());
    MethodResolutionResult resolutionResult = appView.appInfo().resolveMethodOnInterface(method);
    DexType typeI = buildType(I.class, appView.dexItemFactory());
    DexType typeB = buildType(A.class, appView.dexItemFactory());
    DexProgramClass classI = appView.definitionForProgramType(typeI);
    DexProgramClass classA = appView.definitionForProgramType(typeB);
    LookupResult lookupResult =
        resolutionResult.lookupVirtualDispatchTargets(classI, appView.appInfo(), classA, classA);
    assertTrue(lookupResult.isLookupResultSuccess());
    LookupResultSuccess lookupResultSuccess = lookupResult.asLookupResultSuccess();
    Set<String> targets = new HashSet<>();
    lookupResultSuccess.forEach(
        methodTarget -> targets.add(methodTarget.asMethodTarget().getDefinition().qualifiedName()),
        lambdaTarget -> {
          assert false;
        });
    Set<String> expected = ImmutableSet.of(J.class.getTypeName() + ".foo");
    assertEquals(expected, targets);
    assertTrue(lookupResultSuccess.isComplete());
  }

  public interface I {
    void foo();
  }

  public interface J extends I {
    @Override
    default void foo() {
      System.out.println("K.foo");
    }
  }

  public interface K extends J {}

  public interface L extends I, K {}

  public static class A implements L {}

  public static class Main {

    public static void main(String[] args) {
      new A();
    }
  }
}
