// 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.ir.analysis.escape;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertTrue;

import com.android.tools.r8.TestParameters;
import com.android.tools.r8.TestParametersCollection;
import com.android.tools.r8.graph.AppView;
import com.android.tools.r8.graph.DexMethod;
import com.android.tools.r8.ir.analysis.AnalysisTestBase;
import com.android.tools.r8.ir.code.IRCode;
import com.android.tools.r8.ir.code.Instruction;
import com.android.tools.r8.ir.code.InvokeVirtual;
import com.android.tools.r8.ir.code.NewInstance;
import com.android.tools.r8.ir.code.Value;
import java.util.ArrayList;
import java.util.List;
import java.util.Random;
import java.util.Set;
import java.util.function.Consumer;
import java.util.function.Predicate;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.Parameterized;

@RunWith(Parameterized.class)
public class EscapeAnalysisForNameReflectionTest extends AnalysisTestBase {

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

  public EscapeAnalysisForNameReflectionTest(TestParameters parameters) throws Exception {
    super(
        parameters,
        TestClass.class.getTypeName(), TestClass.class, Helper.class, NamingInterface.class);
  }

  private static Predicate<Instruction> invokesMethodWithName(String name) {
    return instruction ->
        instruction.isInvokeMethod()
            && instruction.asInvokeMethod().getInvokedMethod().name.toString().equals(name);
  }

  @Test
  public void testEscapeViaReturn() throws Exception {
    buildAndCheckIR("escapeViaReturn", checkEscapingName(true, Instruction::isReturn));
  }

  @Test
  public void testEscapeViaThrow() throws Exception {
    buildAndCheckIR(
        "escapeViaThrow",
        code -> {
          NewInstance e = getMatchingInstruction(code, Instruction::isNewInstance);
          assertNotNull(e);
          Value v = e.outValue();
          assertNotNull(v);
          EscapeAnalysis escapeAnalysis =
              new EscapeAnalysis(
                  appView,
                  StringOptimizerEscapeAnalysisConfigurationForTesting.getInstance());
          Set<Instruction> escapeRoutes = escapeAnalysis.computeEscapeRoutes(code, v);
          assertEquals(2, escapeRoutes.size());
          assertTrue(
              escapeRoutes.stream().allMatch(
                  instr ->
                      instr.isThrow()
                          || (instr.isInvokeDirect()
                              && invokesMethodWithName("<init>").test(instr))));
        });
  }

  @Test
  public void testEscapeViaStaticPut() throws Exception {
    buildAndCheckIR("escapeViaStaticPut", checkEscapingName(true, Instruction::isStaticPut));
  }

  @Test
  public void testEscapeViaInstancePut_local() throws Exception {
    buildAndCheckIR(
        "escapeViaInstancePut_local",
        checkEscapingName(true, invokesMethodWithName("namingInterfaceConsumer")));
  }

  @Test
  public void testEscapeViaArrayPut_local() throws Exception {
    buildAndCheckIR(
        "escapeViaArrayPut_local",
        checkEscapingName(true, invokesMethodWithName("namingInterfacesConsumer")));
  }

  @Test
  public void testEscapeViaArrayPut_heap() throws Exception {
    buildAndCheckIR(
        "escapeViaArrayPut_heap",
        checkEscapingName(
            true,
            i -> i.isArrayPut() || invokesMethodWithName("namingInterfacesConsumer").test(i)));
  }

  @Test
  public void testEscapeViaArrayPut_argument() throws Exception {
    buildAndCheckIR(
        "escapeViaArrayPut_argument",
        checkEscapingName(
            true,
            i -> i.isArrayPut() || invokesMethodWithName("namingInterfacesConsumer").test(i)));
  }

  @Test
  public void testEscapeViaListPut() throws Exception {
    buildAndCheckIR(
        "escapeViaListPut",
        checkEscapingName(true, invokesMethodWithName("add")));
  }

  @Test
  public void testEscapeViaListArgumentPut() throws Exception {
    buildAndCheckIR(
        "escapeViaListArgumentPut",
        checkEscapingName(true, invokesMethodWithName("add")));
  }

  @Test
  public void testEscapeViaArrayGet() throws Exception {
    buildAndCheckIR(
        "escapeViaArrayGet",
        checkEscapingName(true, invokesMethodWithName("namingInterfaceConsumer")));
  }

  @Test
  public void testHandlePhiAndAlias() throws Exception {
    buildAndCheckIR(
        "handlePhiAndAlias", checkEscapingName(true, invokesMethodWithName("stringConsumer")));
  }

  @Test
  public void testToString() throws Exception {
    buildAndCheckIR("toString", checkEscapingName(true, Instruction::isReturn));
  }

  @Test
  public void testEscapeViaRecursion() throws Exception {
    buildAndCheckIR("escapeViaRecursion", checkEscapingName(true, Instruction::isReturn));
  }

  @Test
  public void testEscapeViaLoopAndBoxing() throws Exception {
    buildAndCheckIR(
        "escapeViaLoopAndBoxing",
        checkEscapingName(
            true, instr -> instr.isReturn() || invokesMethodWithName("toString").test(instr)));
  }

  static class StringOptimizerEscapeAnalysisConfigurationForTesting
      implements EscapeAnalysisConfiguration {

    private static final StringOptimizerEscapeAnalysisConfigurationForTesting INSTANCE =
        new StringOptimizerEscapeAnalysisConfigurationForTesting();

    private StringOptimizerEscapeAnalysisConfigurationForTesting() {}

    static StringOptimizerEscapeAnalysisConfigurationForTesting getInstance() {
      return INSTANCE;
    }

    @Override
    public boolean isLegitimateEscapeRoute(
        AppView<?> appView,
        EscapeAnalysis escapeAnalysis,
        Instruction escapeRoute,
        DexMethod context) {
      if (escapeRoute.isReturn() || escapeRoute.isThrow() || escapeRoute.isStaticPut()) {
        return false;
      }
      if (escapeRoute.isInvokeMethod()) {
        DexMethod invokedMethod = escapeRoute.asInvokeMethod().getInvokedMethod();
        // Heuristic: if the call target has the same method name, it could be still local.
        if (invokedMethod.name == context.name) {
          return true;
        }
        // It's not legitimate during testing, except for recursion calls.
        return false;
      }
      if (escapeRoute.isArrayPut()) {
        Value array = escapeRoute.asArrayPut().array().getAliasedValue();
        return !array.isPhi() && array.definition.isCreatingArray();
      }
      if (escapeRoute.isInstancePut()) {
        Value instance = escapeRoute.asInstancePut().object().getAliasedValue();
        return !instance.isPhi() && instance.definition.isNewInstance();
      }
      // All other cases are not legitimate.
      return false;
    }
  }

  private Consumer<IRCode> checkEscapingName(
      boolean expectedHeuristicResult, Predicate<Instruction> instructionTester) {
    assert instructionTester != null;
    return code -> {
      InvokeVirtual simpleNameCall = getSimpleNameCall(code);
      assertNotNull(simpleNameCall);
      Value v = simpleNameCall.outValue();
      assertNotNull(v);
      EscapeAnalysis escapeAnalysis =
          new EscapeAnalysis(
              appView, StringOptimizerEscapeAnalysisConfigurationForTesting.getInstance());
      Set<Instruction> escapeRoutes = escapeAnalysis.computeEscapeRoutes(code, v);
      assertNotEquals(expectedHeuristicResult, escapeRoutes.isEmpty());
      assertTrue(escapeRoutes.stream().allMatch(instructionTester));
    };
  }

  private static InvokeVirtual getSimpleNameCall(IRCode code) {
    return getMatchingInstruction(code, instruction -> {
      if (instruction.isInvokeVirtual()) {
        DexMethod invokedMethod = instruction.asInvokeVirtual().getInvokedMethod();
        return invokedMethod.holder.toDescriptorString().equals("Ljava/lang/Class;")
            && invokedMethod.name.toString().equals("getSimpleName");
      }
      return false;
    }).asInvokeVirtual();
  }

  static class Helper {
    static String toString(String x, String y) {
      return x + y;
    }

    static void stringConsumer(String str) {
      System.out.println(str);
    }

    static void namingInterfaceConsumer(NamingInterface itf) {
      System.out.println(itf.getName());
    }

    static void namingInterfacesConsumer(NamingInterface[] interfaces) {
      for (NamingInterface itf : interfaces) {
        System.out.println(itf.getName());
      }
    }
  }

  interface NamingInterface {
    default String getName() {
      return getClass().getName();
    }
  }

  static class TestClass implements NamingInterface {
    private static NamingInterface[] ARRAY = new NamingInterface[1];

    static String tag;
    String id;

    TestClass() {
      this(new Random().nextInt());
    }

    TestClass(int id) {
      this(String.valueOf(id));
    }

    TestClass(String id) {
      this.id = id;
    }

    @Override
    public String getName() {
      return getClass().getCanonicalName();
    }

    @Override
    public String toString() {
      String name = getClass().getSimpleName();
      return Helper.toString(name, id);
    }

    public static String escapeViaReturn() {
      return TestClass.class.getSimpleName();
    }

    public static void escapeViaThrow() {
      RuntimeException e = new RuntimeException();
      throw e;
    }

    public static void escapeViaStaticPut() {
      tag = TestClass.class.getSimpleName();
    }

    public static void escapeViaInstancePut_local() {
      TestClass instance = new TestClass();
      instance.id = instance.getClass().getSimpleName();
      Helper.namingInterfaceConsumer(instance);
    }

    public static void escapeViaArrayPut_local() {
      TestClass instance = new TestClass();
      instance.id = instance.getClass().getSimpleName();
      NamingInterface[] array = new NamingInterface[1];
      array[0] = instance;
      Helper.namingInterfacesConsumer(array);
    }

    public static void escapeViaArrayPut_heap() {
      TestClass instance = new TestClass();
      instance.id = instance.getClass().getSimpleName();
      ARRAY[0] = instance;
      Helper.namingInterfacesConsumer(ARRAY);
    }

    public static void escapeViaArrayPut_argument(NamingInterface[] array) {
      TestClass instance = new TestClass();
      instance.id = instance.getClass().getSimpleName();
      array[0] = instance;
    }

    public static void escapeViaListPut() {
      TestClass instance = new TestClass();
      instance.id = instance.getClass().getSimpleName();
      List<NamingInterface> list = new ArrayList<>();
      list.add(instance);
      Helper.namingInterfacesConsumer(list.toArray(new NamingInterface[0]));
    }

    public static void escapeViaListArgumentPut(List<NamingInterface> list) {
      TestClass instance = new TestClass();
      instance.id = instance.getClass().getSimpleName();
      list.add(instance);
    }

    public static void escapeViaArrayGet(boolean flag) {
      TestClass instance = new TestClass();
      instance.id = instance.getClass().getSimpleName();
      NamingInterface[] array = new NamingInterface[2];
      array[0] = instance;
      array[1] = null;
      // At compile-time, we don't know which one will be taken.
      // So, conservatively, we should consider that name can be propagated.
      NamingInterface couldBeNull = flag ? array[0] : array[1];
      Helper.namingInterfaceConsumer(couldBeNull);
    }

    public static void handlePhiAndAlias(String input) {
      TestClass instance = new TestClass();
      String name = System.currentTimeMillis() > 0 ? instance.getClass().getSimpleName() : input;
      String alias = name;
      Helper.stringConsumer(alias);
    }

    public static String escapeViaRecursion(String arg, boolean escape) {
      if (escape) {
        return arg;
      } else {
        String name = TestClass.class.getSimpleName();
        return escapeViaRecursion(name, true);
      }
    }

    public static TestClass escapeViaLoopAndBoxing(String arg) {
      TestClass box = null;
      while (arg != null) {
        box = new TestClass(arg);
        String name = TestClass.class.getSimpleName();
        box.id = name;
        arg = box.toString();
      }
      return box;
    }
  }
}
