// Copyright (c) 2018, 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.shaking.proxy;

import static org.junit.Assert.assertEquals;

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.naming.MemberNaming.MethodSignature;
import com.android.tools.r8.shaking.proxy.testclasses.BaseInterface;
import com.android.tools.r8.shaking.proxy.testclasses.Main;
import com.android.tools.r8.shaking.proxy.testclasses.SubClass;
import com.android.tools.r8.shaking.proxy.testclasses.SubInterface;
import com.android.tools.r8.shaking.proxy.testclasses.TestClass;
import com.android.tools.r8.utils.StringUtils;
import com.android.tools.r8.utils.ThrowingConsumer;
import com.android.tools.r8.utils.codeinspector.CodeInspector;
import com.android.tools.r8.utils.codeinspector.FoundMethodSubject;
import com.android.tools.r8.utils.codeinspector.InstructionSubject;
import com.android.tools.r8.utils.codeinspector.InvokeInstructionSubject;
import com.android.tools.r8.utils.codeinspector.MethodSubject;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.Streams;
import java.util.List;
import java.util.function.Predicate;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.Parameterized;

@RunWith(Parameterized.class)
public class ProxiesTest extends TestBase {

  private final TestParameters parameters;

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

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

  private void runTest(
      List<String> additionalKeepRules,
      ThrowingConsumer<CodeInspector, RuntimeException> inspection,
      String expectedResult)
      throws Exception {
    testForR8(parameters.getBackend())
        .addProgramFiles(ToolHelper.getClassFilesForTestPackage(Main.class.getPackage()))
        .addKeepMainRule(Main.class)
        .addKeepRules(
            "-keep class " + Main.class.getCanonicalName() + " {",
            // Keep x, y and z to avoid them being inlined into main.
            "  private void x(com.android.tools.r8.shaking.proxy.testclasses.BaseInterface);",
            "  private void y(com.android.tools.r8.shaking.proxy.testclasses.SubInterface);",
            "  private void z(com.android.tools.r8.shaking.proxy.testclasses.TestClass);",
            "  private void z(com.android.tools.r8.shaking.proxy.testclasses.SubClass);",
            "}")
        .addKeepRules(additionalKeepRules)
        .addOptionsModification(
            o -> {
              o.enableDevirtualization = false;
              o.enableInliningOfInvokesWithNullableReceivers = false;
              // Tests indirectly check if a certain method is inlined or not, where the target
              // method has at least 4 instructions.
              o.inliningInstructionLimit = 4;
            })
        .noMinification()
        .setMinApi(parameters.getApiLevel())
        .compile()
        .inspect(inspection)
        .run(parameters.getRuntime(), Main.class)
        .assertSuccessWithOutput(StringUtils.withNativeLineSeparator(expectedResult));
  }

  private int countInstructionInX(CodeInspector inspector, Predicate<InstructionSubject> invoke) {
    MethodSignature signatureForX =
        new MethodSignature("x", "void", ImmutableList.of(BaseInterface.class.getCanonicalName()));
    MethodSubject method = inspector.clazz(Main.class).method(signatureForX);
    assert method instanceof FoundMethodSubject;
    FoundMethodSubject foundMethod = (FoundMethodSubject) method;
    return (int) Streams.stream(foundMethod.iterateInstructions(invoke)).count();
  }

  private int countInstructionInY(CodeInspector inspector, Predicate<InstructionSubject> invoke) {
    MethodSignature signatureForY =
        new MethodSignature("y", "void", ImmutableList.of(SubInterface.class.getCanonicalName()));
    MethodSubject method = inspector.clazz(Main.class).method(signatureForY);
    assert method instanceof FoundMethodSubject;
    FoundMethodSubject foundMethod = (FoundMethodSubject) method;
    return (int)
        Streams.stream(foundMethod.iterateInstructions(invoke))
            .filter(
                instruction -> {
                  InvokeInstructionSubject invokeInstruction =
                      (InvokeInstructionSubject) instruction;
                  return invokeInstruction.invokedMethod().qualifiedName().endsWith("method");
                })
            .count();
  }

  private int countInstructionInZ(CodeInspector inspector, Predicate<InstructionSubject> invoke) {
    MethodSignature signatureForZ =
        new MethodSignature("z", "void", ImmutableList.of(TestClass.class.getCanonicalName()));
    MethodSubject method = inspector.clazz(Main.class).method(signatureForZ);
    assert method instanceof FoundMethodSubject;
    FoundMethodSubject foundMethod = (FoundMethodSubject) method;
    return (int)
        Streams.stream(foundMethod.iterateInstructions(invoke))
            .filter(
                instruction -> {
                  InvokeInstructionSubject invokeInstruction =
                      (InvokeInstructionSubject) instruction;
                  return invokeInstruction.invokedMethod().qualifiedName().endsWith("method");
                })
            .count();
  }

  private int countInstructionInZSubClass(
      CodeInspector inspector, Predicate<InstructionSubject> invoke) {
    MethodSignature signatureForZ =
        new MethodSignature("z", "void", ImmutableList.of(SubClass.class.getCanonicalName()));
    MethodSubject method = inspector.clazz(Main.class).method(signatureForZ);
    assert method instanceof FoundMethodSubject;
    FoundMethodSubject foundMethod = (FoundMethodSubject) method;
    return (int)
        Streams.stream(foundMethod.iterateInstructions(invoke))
            .filter(
                instruction -> {
                  InvokeInstructionSubject invokeInstruction =
                      (InvokeInstructionSubject) instruction;
                  return invokeInstruction.invokedMethod().qualifiedName().endsWith("method");
                })
            .count();
  }

  private void noInterfaceKept(CodeInspector inspector) {
    // Indirectly assert that method is inlined into x, y and z.
    assertEquals(1, countInstructionInX(inspector, InstructionSubject::isInvokeInterface));
    assertEquals(1, countInstructionInY(inspector, InstructionSubject::isInvokeInterface));
    assertEquals(1, countInstructionInZ(inspector, InstructionSubject::isInvokeVirtual));
  }

  @Test
  public void testNoInterfaceKept() throws Exception {
    runTest(ImmutableList.of(),
        this::noInterfaceKept,
        "TestClass 1\nTestClass 1\nTestClass 1\nProxy\nEXCEPTION\n");
  }

  private void baseInterfaceKept(CodeInspector inspector) {
    // Indirectly assert that method is not inlined into x.
    assertEquals(3, countInstructionInX(inspector, InstructionSubject::isInvokeInterface));
    // Indirectly assert that method is inlined into y and z.
    assertEquals(1, countInstructionInY(inspector, InstructionSubject::isInvokeInterface));
    assertEquals(1, countInstructionInZ(inspector, InstructionSubject::isInvokeVirtual));
    assertEquals(1, countInstructionInZSubClass(inspector, InstructionSubject::isInvokeVirtual));
  }

  @Test
  public void testBaseInterfaceKept() throws Exception {
    runTest(ImmutableList.of(
        "-keep interface " + BaseInterface.class.getCanonicalName() + " {",
        "  <methods>;",
        "}"),
        this::baseInterfaceKept,
        "TestClass 1\nTestClass 1\nTestClass 1\nProxy\nProxy\nProxy\n" +
        "TestClass 2\nTestClass 2\nTestClass 2\nProxy\nEXCEPTION\n");
  }

  private void subInterfaceKept(CodeInspector inspector) {
    // Indirectly assert that method is not inlined into x or y.
    assertEquals(3, countInstructionInX(inspector, InstructionSubject::isInvokeInterface));
    assertEquals(3, countInstructionInY(inspector, InstructionSubject::isInvokeInterface));
    // Indirectly assert that method is inlined into z.
    assertEquals(1, countInstructionInZ(inspector, InstructionSubject::isInvokeVirtual));
    assertEquals(1, countInstructionInZSubClass(inspector, InstructionSubject::isInvokeVirtual));
  }

  @Test
  public void testSubInterfaceKept() throws Exception {
    runTest(ImmutableList.of(
        "-keep interface " + SubInterface.class.getCanonicalName() + " {",
        "  <methods>;",
        "}"),
        this::subInterfaceKept,
        "TestClass 1\nTestClass 1\nTestClass 1\nProxy\nProxy\nProxy\n" +
        "TestClass 2\nTestClass 2\nTestClass 2\nProxy\nProxy\nProxy\n" +
        "TestClass 3\nTestClass 3\nTestClass 3\n" +
        "TestClass 4\nTestClass 4\nTestClass 4\nSUCCESS\n");
  }

  private void classKept(CodeInspector inspector) {
    // Indirectly assert that method is not inlined into x, y or z.
    assertEquals(3, countInstructionInX(inspector, InstructionSubject::isInvokeInterface));
    assertEquals(3, countInstructionInY(inspector, InstructionSubject::isInvokeInterface));
    assertEquals(3, countInstructionInZ(inspector, InstructionSubject::isInvokeVirtual));
    assertEquals(3, countInstructionInZSubClass(inspector, InstructionSubject::isInvokeVirtual));
  }

  @Test
  public void testClassKept() throws Exception {
    runTest(ImmutableList.of(
        "-keep class " + TestClass.class.getCanonicalName() + " {",
        "  <methods>;",
        "}"),
        this::classKept,
        "TestClass 1\nTestClass 1\nTestClass 1\nProxy\nProxy\nProxy\n" +
        "TestClass 2\nTestClass 2\nTestClass 2\nProxy\nProxy\nProxy\n" +
        "TestClass 3\nTestClass 3\nTestClass 3\n" +
        "TestClass 4\nTestClass 4\nTestClass 4\nSUCCESS\n");
  }

  @Test
  public void testSubClassKept() throws Exception {
    runTest(ImmutableList.of(
        "-keep class " + SubClass.class.getCanonicalName() + " {",
        "  <methods>;",
        "}"),
        this::classKept,
        "TestClass 1\nTestClass 1\nTestClass 1\nProxy\nProxy\nProxy\n" +
        "TestClass 2\nTestClass 2\nTestClass 2\nProxy\nProxy\nProxy\n" +
        "TestClass 3\nTestClass 3\nTestClass 3\n" +
        "TestClass 4\nTestClass 4\nTestClass 4\nSUCCESS\n");
  }
}