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

import static com.android.tools.r8.utils.codeinspector.Matchers.isPresent;
import static com.android.tools.r8.utils.codeinspector.Matchers.isPresentAndNotRenamed;
import static com.android.tools.r8.utils.codeinspector.Matchers.isPresentAndRenamed;
import static org.hamcrest.CoreMatchers.hasItem;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.core.IsNot.not;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
import static org.junit.Assume.assumeTrue;

import com.android.tools.r8.NeverClassInline;
import com.android.tools.r8.NeverInline;
import com.android.tools.r8.NoVerticalClassMerging;
import com.android.tools.r8.R8FullTestBuilder;
import com.android.tools.r8.TestBase;
import com.android.tools.r8.TestParameters;
import com.android.tools.r8.TestParametersCollection;
import com.android.tools.r8.ThrowableConsumer;
import com.android.tools.r8.ToolHelper;
import com.android.tools.r8.utils.Box;
import com.android.tools.r8.utils.StringUtils;
import com.android.tools.r8.utils.codeinspector.CheckCastInstructionSubject;
import com.android.tools.r8.utils.codeinspector.ClassSubject;
import com.android.tools.r8.utils.codeinspector.CodeInspector;
import com.android.tools.r8.utils.codeinspector.InstructionSubject;
import com.android.tools.r8.utils.codeinspector.MethodSubject;
import java.util.ArrayList;
import java.util.List;
import java.util.function.BiConsumer;
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 MainDexDevirtualizerTest extends TestBase {

  private final TestParameters parameters;

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

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

  @Test
  public void testR8() throws Exception {
    assumeTrue(parameters.isCfRuntime() || !parameters.getDexRuntimeVersion().isDalvik());
    runTest(
        testBuilder -> {},
        (inspector, mainDexClasses) -> {
          assertTrue(mainDexClasses.isEmpty());
          // Verify that the call to I.foo in Main.class has been changed to A.foo by checking for a
          // cast.
          ClassSubject clazz = inspector.clazz(Main.class);
          assertThat(clazz, isPresentAndNotRenamed());
          MethodSubject main = clazz.uniqueMethodWithName("main");
          assertThat(main, isPresent());
          List<CheckCastInstructionSubject> checkCasts =
              main.streamInstructions()
                  .filter(InstructionSubject::isCheckCast)
                  .map(InstructionSubject::asCheckCast)
                  .collect(Collectors.toList());
          assertEquals(1, checkCasts.size());
          ClassSubject a = inspector.clazz(A.class);
          assertThat(a, isPresentAndRenamed());
          assertEquals(
              a.getFinalDescriptor(), checkCasts.get(0).getType().getDescriptor().toString());
        });
  }

  // TODO(b/181858113): This test is likely obsolete once main-dex-list support is removed.
  @Test
  public void testMainDexClasses() throws Exception {
    assumeTrue(parameters.isDexRuntime());
    assumeTrue(parameters.getDexRuntimeVersion().isDalvik());
    runTest(
        r8FullTestBuilder ->
            r8FullTestBuilder
                .addMainDexListClasses(I.class, Provider.class, Main.class)
                .allowDiagnosticWarningMessages(),
        this::inspect);
  }

  @Test
  public void testMainDexTracing() throws Exception {
    assumeTrue(parameters.isDexRuntime());
    assumeTrue(parameters.getDexRuntimeVersion().isDalvik());
    runTest(
        r8FullTestBuilder -> r8FullTestBuilder.addMainDexKeepClassRules(Main.class, I.class),
        this::inspect);
  }

  private void runTest(
      ThrowableConsumer<R8FullTestBuilder> setMainDexConsumer,
      BiConsumer<CodeInspector, List<String>> resultConsumer)
      throws Exception {
    Box<String> mainDexStringList = new Box<>("");
    testForR8(parameters.getBackend())
        .addProgramClasses(I.class, Provider.class, A.class, Main.class)
        .enableNoVerticalClassMergingAnnotations()
        .enableInliningAnnotations()
        .enableNeverClassInliningAnnotations()
        .addKeepMainRule(Main.class)
        .addKeepClassRulesWithAllowObfuscation(I.class)
        .setMinApi(parameters.getApiLevel())
        .applyIf(
            parameters.isDexRuntime() && parameters.getDexRuntimeVersion().isDalvik(),
            builder ->
                builder.setMainDexListConsumer(ToolHelper.consumeString(mainDexStringList::set)))
        .apply(setMainDexConsumer)
        .run(parameters.getRuntime(), Main.class)
        .apply(
            result ->
                resultConsumer.accept(
                    result.inspector(),
                    mainDexStringList.get().equals("")
                        ? new ArrayList<>()
                        : StringUtils.splitLines(mainDexStringList.get())));
  }

  private void inspect(CodeInspector inspector, List<String> mainDexClasses) {
    assertEquals(4, inspector.allClasses().size());
    assertEquals(3, mainDexClasses.size());
    inspectClassInMainDex(Main.class, inspector, mainDexClasses);
    inspectClassInMainDex(I.class, inspector, mainDexClasses);
    inspectClassInMainDex(Provider.class, inspector, mainDexClasses);
    ClassSubject aClass = inspector.clazz(A.class);
    assertThat(aClass, isPresentAndRenamed());
    assertThat(mainDexClasses, not(hasItem(aClass.getFinalBinaryName() + ".class")));
  }

  private void inspectClassInMainDex(
      Class<?> clazz, CodeInspector inspector, List<String> mainDexClasses) {
    ClassSubject classSubject = inspector.clazz(clazz);
    assertThat(classSubject, isPresent());
    assertThat(mainDexClasses, hasItem(classSubject.getFinalBinaryName() + ".class"));
  }

  @NoVerticalClassMerging
  public interface I {

    @NeverInline
    void foo();
  }

  public static class Provider {
    @NeverInline
    public static I getImpl() {
      return new A(); // <-- We will call-site optimize getImpl() to always return A.
    }
  }

  @NeverClassInline
  public static class A implements I {

    @Override
    @NeverInline
    public void foo() {
      System.out.println("A::foo");
    }
  }

  public static class Main {

    public static void main(String[] args) {
      // The de-virtualizer will try and rebind from I.foo to A.foo.
      Provider.getImpl().foo();
    }
  }
}
