// 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.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.ResolutionResult;
import com.android.tools.r8.shaking.AppInfoWithLiveness;
import com.android.tools.r8.shaking.ProguardConfigurationRule;
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 computeAppViewWithLiveness(
        buildClasses(I.class, J.class, K.class, L.class, A.class, Main.class)
            .addLibraryFile(ToolHelper.getJava8RuntimeJar())
            .build(),
        factory ->
            buildConfigForRules(
                factory,
                ImmutableList.<ProguardConfigurationRule>builder()
                    .addAll(buildKeepRuleForClassAndMethods(methodToBeKept, factory))
                    .addAll(buildKeepRuleForClass(classToBeKept, factory))
                    .addAll(buildKeepRuleForClassAndMethods(Main.class, factory))
                    .build()));
  }

  @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());
    ResolutionResult 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());
    ResolutionResult 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());
    ResolutionResult 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());
    ResolutionResult 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());
    ResolutionResult 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();
    }
  }
}
