// 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 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) {
    // Empty to satisfy construction of none-runtime.
  }

  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),
        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).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).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();
    }
  }
}
