// 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.optimize.uninstantiatedtypes;

import static com.android.tools.r8.utils.codeinspector.Matchers.isPresent;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.core.IsNot.not;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotEquals;
import static org.junit.Assert.assertTrue;

import com.android.tools.r8.NeverInline;
import com.android.tools.r8.TestBase;
import com.android.tools.r8.TestParameters;
import com.android.tools.r8.utils.BooleanUtils;
import com.android.tools.r8.utils.StringUtils;
import com.android.tools.r8.utils.codeinspector.ClassSubject;
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.google.common.collect.Streams;
import java.util.List;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.Parameterized;
import org.junit.runners.Parameterized.Parameters;

/**
 * Tests that instance method calls are rewritten to {@code throw null} if the type of the receiver
 * is never instantiated directly or indirectly.
 */
@RunWith(Parameterized.class)
public class InvokeMethodWithReceiverOptimizationTest extends TestBase {

  private final TestParameters parameters;
  private final boolean enableArgumentPropagation;

  @Parameters(name = "{0}, argument propagation: {1}")
  public static List<Object[]> data() {
    return buildParameters(
        getTestParameters().withAllRuntimesAndApiLevels().build(), BooleanUtils.values());
  }

  public InvokeMethodWithReceiverOptimizationTest(
      TestParameters parameters, boolean enableArgumentPropagation) {
    this.parameters = parameters;
    this.enableArgumentPropagation = enableArgumentPropagation;
  }

  @Test
  public void test() throws Exception {
    String expected =
        StringUtils.joinLines(
            "Caught NullPointerException from testRewriteToThrowNull",
            "Caught NullPointerException from testRewriteToThrowNullWithCatchHandlers",
            "Caught NullPointerException from testRewriteToThrowNullWithDeadCatchHandler");

    testForJvm().addTestClasspath().run(TestClass.class).assertSuccessWithOutput(expected);

    CodeInspector inspector =
        testForR8(parameters.getBackend())
            .addInnerClasses(InvokeMethodWithReceiverOptimizationTest.class)
            .addKeepMainRule(TestClass.class)
            .enableInliningAnnotations()
            .addOptionsModification(
                options ->
                    options.callSiteOptimizationOptions().setEnabled(enableArgumentPropagation))
            // TODO(b/120764902): The calls to getOriginalName() below does not work in presence of
            //  argument removal.
            .addDontObfuscate()
            .setMinApi(parameters.getApiLevel())
            .run(parameters.getRuntime(), TestClass.class)
            .assertSuccessWithOutput(expected)
            .inspector();

    ClassSubject testClassSubject = inspector.clazz(TestClass.class);
    assertThat(testClassSubject, isPresent());

    ClassSubject otherClassSubject = inspector.clazz(A.class);
    assertNotEquals(enableArgumentPropagation, otherClassSubject.isPresent());

    // Check that A.method() has been removed.
    assertThat(otherClassSubject.uniqueMethodWithName("method"), not(isPresent()));

    // Check that a throw instruction has been inserted into each of the testRewriteToThrowNull*
    // methods.
    int found = 0;
    for (FoundMethodSubject methodSubject : testClassSubject.allMethods()) {
      if (methodSubject.getOriginalName().startsWith("testRewriteToThrowNull")) {
        assertTrue(
            Streams.stream(methodSubject.iterateInstructions())
                .anyMatch(InstructionSubject::isThrow));
        found++;
      }
    }
    assertEquals(3, found);

    // Check that the method dead() has been removed.
    assertThat(testClassSubject.uniqueMethodWithName("dead"), not(isPresent()));

    // Check that the catch handlers for NullPointerException and RuntimeException have not been
    // removed.
    assertThat(testClassSubject.uniqueMethodWithName("handleNullPointerException"), isPresent());
    assertThat(testClassSubject.uniqueMethodWithName("handleRuntimeException"), isPresent());
  }

  static class TestClass {

    public static void main(String[] args) {
      try {
        testRewriteToThrowNull(null);
      } catch (NullPointerException e) {
        System.out.println("Caught NullPointerException from testRewriteToThrowNull");
      }

      testRewriteToThrowNullWithCatchHandlers(null);

      try {
        testRewriteToThrowNullWithDeadCatchHandler(null);
      } catch (NullPointerException e) {
        System.out.print(
            "Caught NullPointerException from testRewriteToThrowNullWithDeadCatchHandler");
      }
    }

    @NeverInline
    private static void testRewriteToThrowNull(A obj) {
      // Should be rewritten to "throw null".
      String result = obj.method();
      dead(result);
    }

    @NeverInline
    private static void testRewriteToThrowNullWithCatchHandlers(A obj) {
      try {
        // Should be rewritten to "throw null".
        String result = obj.method();
        dead(result);
      } catch (NullPointerException e) {
        // This catch handler cannot be removed.
        handleNullPointerException();
      } catch (RuntimeException e) {
        // This catch handler cannot be removed.
        handleRuntimeException();
      }
    }

    @NeverInline
    private static void handleNullPointerException() {
      System.out.println(
          "Caught NullPointerException from testRewriteToThrowNullWithCatchHandlers");
    }

    @NeverInline
    private static void handleRuntimeException() {
      System.out.println("Caught RuntimeException from testRewriteToThrowNullWithCatchHandlers");
    }

    @NeverInline
    private static void testRewriteToThrowNullWithDeadCatchHandler(A obj) {
      try {
        // Should be rewritten to "throw null".
        String result = obj.method();
        dead(result);
      } catch (CustomException e) {
        // This catch handler should be removed.
        dead("Caught CustomException in testRewriteToThrowNullWithDeadCatchHandler");
      }
    }

    @NeverInline
    private static void dead(String msg) {
      System.out.println("In TestClass.dead(): " + msg);
    }
  }

  static class A {

    @NeverInline
    public String method() {
      return "A.method()";
    }
  }

  static class CustomException extends RuntimeException {}
}
