// 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.resolution.virtualtargets;

import static com.android.tools.r8.ToolHelper.getMostRecentAndroidJar;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;

import com.android.tools.r8.TestBase;
import com.android.tools.r8.TestParameters;
import com.android.tools.r8.TestParametersCollection;
import com.android.tools.r8.graph.AppInfoWithClassHierarchy;
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.ImmutableSet;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;
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 KeptTargetsIncompleteLookupTest extends TestBase {

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

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

  private LookupResultSuccess testLookup(Class<?> methodToBeKept) throws Exception {
    return testLookup(B.class, methodToBeKept, methodToBeKept, A.class, C.class);
  }

  private LookupResultSuccess testLookup(
      Class<?> initial,
      Class<?> methodToBeKept,
      Class<?> classToBeKept,
      Class<?>... expectedMethodHolders)
      throws Exception {
    return testLookup(
        initial,
        methodToBeKept,
        classToBeKept,
        Arrays.asList(expectedMethodHolders),
        Arrays.asList(I.class, A.class, B.class, C.class, Main.class, Unrelated.class),
        Main.class);
  }

  private LookupResultSuccess testLookup(
      Class<?> initial,
      Class<?> methodToBeKept,
      Class<?> classToBeKept,
      Collection<Class<?>> expectedMethodHolders,
      Collection<Class<?>> classes,
      Class<?> main)
      throws Exception {
    AppView<AppInfoWithLiveness> appView =
        computeAppViewWithLiveness(
            buildClasses(classes).addLibraryFile(getMostRecentAndroidJar()).build(),
            factory -> {
              List<ProguardConfigurationRule> rules = new ArrayList<>();
              rules.addAll(buildKeepRuleForClassAndMethods(methodToBeKept, factory));
              rules.addAll(buildKeepRuleForClass(classToBeKept, factory));
              rules.addAll(buildKeepRuleForClassAndMethods(main, factory));
              return buildConfigForRules(factory, rules);
            });
    AppInfoWithLiveness appInfo = appView.appInfo();
    DexMethod method = buildNullaryVoidMethod(initial, "foo", appInfo.dexItemFactory());
    ResolutionResult resolutionResult = appInfo.resolveMethodOnClass(method);
    DexProgramClass context =
        DexProgramClass.asProgramClassOrNull(
            appView
                .appInfo()
                .definitionForWithoutExistenceAssert(
                    buildType(Unrelated.class, appInfo.dexItemFactory())));
    LookupResult lookupResult = resolutionResult.lookupVirtualDispatchTargets(context, appInfo);
    assertTrue(lookupResult.isLookupResultSuccess());
    LookupResultSuccess lookupResultSuccess = lookupResult.asLookupResultSuccess();
    Set<String> targets = new HashSet<>();
    lookupResult.forEach(
        target -> targets.add(target.getDefinition().qualifiedName()), lambda -> fail());
    Set<String> expected =
        expectedMethodHolders.stream()
            .map(c -> c.getTypeName() + ".foo")
            .collect(Collectors.toSet());
    assertEquals(expected, targets);
    return lookupResultSuccess;
  }

  @Test
  public void testCompleteLookupResultWhenKeepingUnrelated() throws Exception {
    // I {
    //   foo()
    // }
    //
    // A implements I {
    //   foo() <-- resolved
    // }
    //
    // B extends A { } <-- initial
    //
    // C extends B {
    //   foo()
    // }
    assertTrue(
        testLookup(B.class, Unrelated.class, Unrelated.class, A.class, C.class).isComplete());
  }

  @Test
  public void testKeptResolvedAndNoKeepInSubtreeFromInitial() throws Exception {
    // I {
    //   foo()
    // }
    //
    // A implements I {
    //   foo() <-- kept, resolved
    // }
    //
    // B extends A { } <-- initial
    //
    // C extends B {
    //   foo()
    // }
    assertTrue(testLookup(A.class).isIncomplete());
  }

  @Test
  public void testIncompleteLookupResultWhenKeepingStaticReceiver() throws Exception {
    // I {
    //   foo()
    // }
    //
    // A implements I {
    //   foo() <-- resolved
    // }
    //
    // B extends A { } <-- initial, kept
    //
    // C extends B {
    //   foo()
    // }
    assertTrue(testLookup(B.class).isIncomplete());
  }

  @Test
  public void testIncompleteLookupResultWhenKeepingSubTypeMethod() throws Exception {
    // I {
    //   foo()
    // }
    //
    // A implements I {
    //   foo() <-- resolved
    // }
    //
    // B extends A { } <-- initial
    //
    // C extends B {
    //   foo() <-- kept
    // }
    assertTrue(testLookup(C.class).isIncomplete());
  }

  @Test
  public void testIncompleteLookupResultWhenKeepingMethodOnParentToResolveAndKeepClass()
      throws Exception {
    // I {
    //   foo()
    // }
    //
    // A implements I {
    //   foo() <-- kept
    // }
    //
    // B extends A { }
    //
    // C extends B { <-- initial, resolved, kept
    //   foo()
    // }
    assertTrue(testLookup(C.class, A.class, C.class, C.class).isIncomplete());
  }

  @Test
  public void testCompleteLookupResultWhenKeepingMethodOnParentToResolveAndNotKeepClass()
      throws Exception {
    // I {
    //   foo()
    // }
    //
    // A implements I {
    //   foo() <-- kept
    // }
    //
    // B extends A { }
    //
    // C extends B { <-- initial, resolved
    //   foo()
    // }
    assertTrue(testLookup(C.class, A.class, Unrelated.class, C.class).isComplete());
  }

  @Test
  public void testLibraryWithNoOverride() throws Exception {
    // ----- Library -----
    // I {
    //   foo()
    // }
    //
    // A implements I {
    //   foo() <-- resolved
    // }
    //
    // ----- Program -----
    // B extends A { } <-- initial
    AppView<AppInfoWithClassHierarchy> appView =
        computeAppViewWithClassHierachy(
            buildClasses(Collections.singletonList(B.class), Arrays.asList(A.class, I.class))
                .build());
    AppInfoWithClassHierarchy appInfo = appView.appInfo();
    DexMethod method = buildNullaryVoidMethod(B.class, "foo", appInfo.dexItemFactory());
    ResolutionResult resolutionResult = appInfo.resolveMethodOnClass(method);
    DexType typeA = buildType(A.class, appInfo.dexItemFactory());
    DexType typeB = buildType(B.class, appInfo.dexItemFactory());
    DexProgramClass classB = appInfo.definitionForProgramType(typeB);
    LookupResult lookupResult =
        resolutionResult.lookupVirtualDispatchTargets(
            classB,
            appInfo,
            (type, subTypeConsumer, callSiteConsumer) -> {
              if (type == typeB) {
                subTypeConsumer.accept(classB);
              }
            },
            reference -> false);
    assertTrue(lookupResult.isLookupResultSuccess());
    LookupResultSuccess lookupResultSuccess = lookupResult.asLookupResultSuccess();
    Set<String> targets = new HashSet<>();
    lookupResult.forEach(
        target -> targets.add(target.getDefinition().qualifiedName()), lambda -> fail());
    Set<String> expected = ImmutableSet.of(A.class.getTypeName() + ".foo");
    assertEquals(expected, targets);
    assertTrue(lookupResultSuccess.isComplete());
  }

  @Test
  public void testPrivateKeep() throws Exception {
    // Unrelated { <-- kept
    //   private foo() <-- kept
    // }
    AppView<AppInfoWithLiveness> appView =
        computeAppViewWithLiveness(
            buildClasses(Unrelated.class).addLibraryFile(getMostRecentAndroidJar()).build(),
            Unrelated.class);
    AppInfoWithLiveness appInfo = appView.appInfo();
    DexMethod method = buildNullaryVoidMethod(Unrelated.class, "foo", appInfo.dexItemFactory());
    ResolutionResult resolutionResult = appInfo.resolveMethodOnClass(method);
    DexProgramClass context =
        appView.definitionForProgramType(buildType(Unrelated.class, appInfo.dexItemFactory()));
    LookupResult lookupResult = resolutionResult.lookupVirtualDispatchTargets(context, appInfo);
    assertTrue(lookupResult.isLookupResultSuccess());
    LookupResultSuccess lookupResultSuccess = lookupResult.asLookupResultSuccess();
    Set<String> targets = new HashSet<>();
    lookupResult.forEach(
        target -> targets.add(target.getDefinition().qualifiedName()), lambda -> fail());
    Set<String> expected = ImmutableSet.of(Unrelated.class.getTypeName() + ".foo");
    assertEquals(expected, targets);
    assertTrue(lookupResultSuccess.isIncomplete());
  }

  @Test
  public void testInterfaceKept() throws Exception {
    // I {
    //   foo() <-- kept
    // }
    //
    // A implements I {
    //   foo() <-- resolved
    // }
    //
    // B extends A { } <-- initial, kept
    //
    // C extends B {
    //   foo()
    // }
    assertTrue(testLookup(B.class, I.class, B.class, A.class, C.class).isIncomplete());
  }

  @Test
  public void testInterfaceKeptWithoutKeepInLookup() throws Exception {
    // I {
    //   foo() <-- kept
    // }
    //
    // A implements I {
    //   foo() <-- resolved
    // }
    //
    // B extends A { } <-- initial
    //
    // C extends B {
    //   foo()
    // }
    assertTrue(testLookup(B.class, I.class, Unrelated.class, A.class, C.class).isComplete());
  }

  @Test
  public void testInterfaceKeptAndImplementedInSupType() throws Exception {
    // X {
    //   foo() <-- resolved
    // }
    //
    // I {
    //   foo() <-- kept
    // }
    //
    // Y extends X implements I { } <-- initial
    //
    // Z extends Y { } <-- kept
    assertTrue(
        testLookup(
                Y.class,
                I.class,
                Z.class,
                Collections.singleton(X.class),
                Arrays.asList(X.class, I.class, Y.class, Z.class),
                MainXYZ.class)
            .isIncomplete());
  }

  // TODO(b/148769279): We need to look at the call site to see if it overrides
  //   a method that is kept.

  public static class Unrelated {

    private void foo() {
      System.out.println("Unrelated.foo");
    }
  }

  public interface I {
    void foo();
  }

  public static class A implements I {
    @Override
    public void foo() {
      System.out.println("A.foo");
    }
  }

  public static class B extends A {}

  public static class C extends B {
    @Override
    public void foo() {
      System.out.println("C.foo");
    }
  }

  public static class Main {

    public static void main(String[] args) {
      // This is necessary for considering the classes as instantiated.
      new Unrelated();
      new A();
      new B();
      new C();
    }
  }

  public static class X {

    public void foo() {
      System.out.println("X.foo");
    }
  }

  public static class Y extends X implements I {}

  public static class Z extends Y {}

  public static class MainXYZ {

    public static void main(String[] args) {
      // This is necessary for considering the classes as instantiated.
      new X();
      new Y();
      new Z();
    }
  }
}
