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

import static com.android.tools.r8.utils.codeinspector.CodeMatchers.invokesMethod;
import static com.android.tools.r8.utils.codeinspector.Matchers.isPresent;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.core.IsNot.not;

import com.android.tools.r8.KeepConstantArguments;
import com.android.tools.r8.NeverInline;
import com.android.tools.r8.TestBase;
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.MethodSubject;
import org.junit.Test;

public class InliningAfterClassInitializationTest extends TestBase {

  @Test
  public void testClass1() throws Exception {
    Class<TestClass1> mainClass = TestClass1.class;
    CodeInspector inspector =
        buildAndRun(
            mainClass,
            StringUtils.lines("In A.<clinit>()", "In A.notInlineable()", "In A.inlineable()"));

    ClassSubject classA = inspector.clazz(A.class);
    assertThat(classA, isPresent());

    MethodSubject inlineableMethod = classA.uniqueMethodWithName("inlineable");
    assertThat(inlineableMethod, not(isPresent()));

    MethodSubject notInlineableMethod = classA.uniqueMethodWithName("notInlineable");
    assertThat(notInlineableMethod, isPresent());

    MethodSubject testMethod = inspector.clazz(mainClass).mainMethod();
    assertThat(testMethod, isPresent());
    assertThat(testMethod, invokesMethod(notInlineableMethod));
  }

  @Test
  public void testClass2() throws Exception {
    Class<TestClass2> mainClass = TestClass2.class;
    CodeInspector inspector =
        buildAndRun(
            mainClass,
            StringUtils.lines("In A.<clinit>()", "Field A.staticField", "In A.inlineable()"));

    ClassSubject classA = inspector.clazz(A.class);
    assertThat(classA, isPresent());

    MethodSubject inlineableMethod = classA.uniqueMethodWithName("inlineable");
    assertThat(inlineableMethod, not(isPresent()));
  }

  @Test
  public void testClass3() throws Exception {
    Class<TestClass3> mainClass = TestClass3.class;
    CodeInspector inspector =
        buildAndRun(mainClass, StringUtils.lines("In A.<clinit>()", "In A.inlineable()"));

    ClassSubject classA = inspector.clazz(A.class);
    assertThat(classA, isPresent());

    MethodSubject inlineableMethod = classA.uniqueMethodWithName("inlineable");
    assertThat(inlineableMethod, not(isPresent()));
  }

  @Test
  public void testClass4() throws Exception {
    Class<TestClass4> mainClass = TestClass4.class;
    CodeInspector inspector =
        buildAndRun(
            mainClass,
            StringUtils.lines("In A.<clinit>()", "Field A.instanceField", "In A.inlineable()"));

    ClassSubject classA = inspector.clazz(A.class);
    assertThat(classA, isPresent());

    MethodSubject inlineableMethod = classA.uniqueMethodWithName("inlineable");
    assertThat(inlineableMethod, not(isPresent()));
  }

  @Test
  public void testClass5() throws Exception {
    Class<TestClass5> mainClass = TestClass5.class;
    CodeInspector inspector =
        buildAndRun(mainClass, StringUtils.lines("In A.<clinit>()", "In A.inlineable()"));

    ClassSubject classA = inspector.clazz(A.class);
    assertThat(classA, isPresent());

    MethodSubject inlineableMethod = classA.uniqueMethodWithName("inlineable");
    assertThat(inlineableMethod, not(isPresent()));
  }

  @Test
  public void testClass6() throws Exception {
    Class<TestClass6> mainClass = TestClass6.class;
    CodeInspector inspector =
        buildAndRun(mainClass, StringUtils.lines("In A.<clinit>()", "In A.notInlineable()"));

    ClassSubject classA = inspector.clazz(A.class);
    assertThat(classA, isPresent());

    MethodSubject notInlineableMethod = classA.uniqueMethodWithName("notInlineable");
    assertThat(notInlineableMethod, isPresent());

    MethodSubject testMethod = inspector.clazz(mainClass).uniqueMethodWithName("test");
    assertThat(testMethod, isPresent());
    assertThat(testMethod, invokesMethod(notInlineableMethod));
  }

  @Test
  public void testClass7() throws Exception {
    Class<TestClass7> mainClass = TestClass7.class;
    CodeInspector inspector =
        buildAndRun(
            mainClass,
            StringUtils.lines(
                "Caught NullPointerException",
                "In A.<clinit>()",
                "Field A.instanceField",
                "In A.inlineable()"));

    ClassSubject classA = inspector.clazz(A.class);
    assertThat(classA, isPresent());

    MethodSubject inlineableMethod = classA.uniqueMethodWithName("inlineable");
    assertThat(inlineableMethod, not(isPresent()));
  }

  @Test
  public void testClass8() throws Exception {
    Class<TestClass8> mainClass = TestClass8.class;
    CodeInspector inspector =
        buildAndRun(
            mainClass,
            StringUtils.lines(
                "In A.<clinit>()", "In A.notInlineable()", "In A.alsoNotInlineable()"));

    ClassSubject classA = inspector.clazz(A.class);
    assertThat(classA, isPresent());

    MethodSubject notInlineableMethod = classA.uniqueMethodWithName("notInlineable");
    assertThat(notInlineableMethod, isPresent());

    MethodSubject alsoNotInlineableMethod = classA.uniqueMethodWithName("alsoNotInlineable");
    assertThat(alsoNotInlineableMethod, isPresent());

    MethodSubject testMethod = inspector.clazz(mainClass).mainMethod();
    assertThat(testMethod, isPresent());
    assertThat(testMethod, invokesMethod(notInlineableMethod));
    assertThat(testMethod, invokesMethod(alsoNotInlineableMethod));
  }

  @Test
  public void testClass9() throws Exception {
    Class<TestClass9> mainClass = TestClass9.class;
    CodeInspector inspector =
        buildAndRun(
            mainClass,
            StringUtils.lines("In A.<clinit>()", "Field A.staticField", "In A.notInlineable()"));

    ClassSubject classA = inspector.clazz(A.class);
    assertThat(classA, isPresent());

    MethodSubject notInlineableMethod = classA.uniqueMethodWithName("notInlineable");
    assertThat(notInlineableMethod, isPresent());

    MethodSubject testMethod = inspector.clazz(mainClass).mainMethod();
    assertThat(testMethod, isPresent());
    assertThat(testMethod, invokesMethod(notInlineableMethod));
  }

  private CodeInspector buildAndRun(Class<?> mainClass, String expectedOutput) throws Exception {
    testForJvm().addTestClasspath().run(mainClass).assertSuccessWithOutput(expectedOutput);

    return testForR8(Backend.DEX)
        .addInnerClasses(InliningAfterClassInitializationTest.class)
        .addKeepMainRule(mainClass)
        .enableConstantArgumentAnnotations()
        .enableInliningAnnotations()
        .run(mainClass)
        .assertSuccessWithOutput(expectedOutput)
        .inspector();
  }

  static class TestClass1 {

    public static void main(String[] args) {
      A.notInlineable();

      // Since the previous call will cause the initializer of A to run, we can safely inline this
      // call.
      A.inlineable();
    }
  }

  static class TestClass2 {

    public static void main(String[] args) {
      System.out.println(A.staticField);

      // Since the previous instruction will cause the initializer of A to run, we can safely inline
      // this call.
      A.inlineable();
    }
  }

  static class TestClass3 {

    public static void main(String[] args) {
      A.staticField = "Hello world!";

      // Since the previous instruction will cause the initializer of A to run, we can safely inline
      // this call.
      A.inlineable();

      // Make sure the field is read to prevent the static-put instruction from being removed
      // (b/123553485).
      spuriousFieldRead();
    }

    private static void spuriousFieldRead() {
      if (System.currentTimeMillis() < 0) {
        System.out.println(A.staticField);
      }
    }
  }

  static class TestClass4 {

    public static void main(String[] args) {
      test(new A());
    }

    @NeverInline
    private static void test(A obj) {
      System.out.println(obj.instanceField);

      // Since the previous instruction will cause the initializer of A to run, we can safely inline
      // this call.
      A.inlineable();
    }
  }

  static class TestClass5 {

    public static void main(String[] args) {
      test(new A());
    }

    @NeverInline
    private static void test(A obj) {
      obj.instanceField = "Hello world!";

      // Since the previous instruction will cause the initializer of A to run, we can safely inline
      // this call.
      A.inlineable();

      // Make sure the field is read to prevent the instance-put instruction from being removed.
      spuriousFieldRead(obj);
    }

    private static void spuriousFieldRead(A obj) {
      if (System.currentTimeMillis() < 0) {
        System.out.println(obj.instanceField);
      }
    }
  }

  static class TestClass6 {

    public static void main(String[] args) {
      test(null);
    }

    @KeepConstantArguments
    @NeverInline
    private static void test(A obj) {
      try {
        String value = obj.instanceField;
        System.out.println(value);
      } catch (NullPointerException e) {
        // Ignore.
      }

      // This call cannot be inlined because `obj.field` may throw a NullPointerException, in which
      // case A is not guaranteed to be initialized.
      A.notInlineable();
    }
  }

  static class TestClass7 {

    public static void main(String[] args) {
      test(null);
      test(new A());
    }

    @NeverInline
    private static void test(A obj) {
      try {
        String value = obj.instanceField;
        System.out.println(value);
      } catch (NullPointerException e) {
        // Ignore.
        System.out.println("Caught NullPointerException");
        return;
      }

      // Due to the `return` in the catch handler above, A is guaranteed to be initialized if we
      // reach this line.
      A.inlineable();
    }
  }

  static class TestClass8 {

    public static void main(String[] args) {
      try {
        A.notInlineable();
      } catch (ExceptionInInitializerError e) {
        System.out.println("Caught ExceptionInInitializerError");
      }

      A.alsoNotInlineable();
    }
  }

  static class TestClass9 {

    public static void main(String[] args) {
      try {
        String value = A.staticField;
        System.out.println(value);
      } catch (ExceptionInInitializerError e) {
        System.out.println("Caught ExceptionInInitializerError");
      }

      A.notInlineable();
    }
  }

  static class A {

    public String instanceField = "Field A.instanceField";
    public static String staticField =
        System.currentTimeMillis() >= 0 ? "Field A.staticField" : null;

    static {
      System.out.println("In A.<clinit>()");
    }

    static void notInlineable() {
      System.out.println("In A.notInlineable()");
    }

    static void alsoNotInlineable() {
      System.out.println("In A.alsoNotInlineable()");
    }

    static void inlineable() {
      System.out.println("In A.inlineable()");
    }
  }
}
