// 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.
            .noMinification()
            .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 {}
}
