// 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.

// 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.testrules;

import static com.android.tools.r8.utils.codeinspector.Matchers.isPresent;
import static org.hamcrest.CoreMatchers.not;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.junit.Assert.fail;

import com.android.tools.r8.TestBase;
import com.android.tools.r8.ToolHelper;
import com.android.tools.r8.utils.codeinspector.ClassSubject;
import com.android.tools.r8.utils.codeinspector.CodeInspector;
import com.google.common.collect.ImmutableList;
import java.util.List;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.Parameterized;

@RunWith(Parameterized.class)
public class ForceInlineTest extends TestBase {
  private Backend backend;

  @Parameterized.Parameters(name = "Backend: {0}")
  public static Backend[] data() {
    return ToolHelper.getBackends();
  }

  public ForceInlineTest(Backend backend) {
    this.backend = backend;
  }

  private CodeInspector runTest(List<String> proguardConfiguration) throws Exception {
    return testForR8(backend)
        .addProgramClasses(Main.class, A.class, B.class, C.class)
        .addKeepRules(proguardConfiguration)
        .assumeAllMethodsMayHaveSideEffects()
        .compile()
        .inspector();
  }

  @Test
  public void testDefaultInlining() throws Exception {
    CodeInspector inspector =
        runTest(
            ImmutableList.of(
                "-keep class **.Main { *; }",
                "-nevermerge @com.android.tools.r8.NeverMerge class *",
                "-neverinline class *{ @com.android.tools.r8.NeverInline <methods>;}",
                "-dontobfuscate"));

    ClassSubject classA = inspector.clazz(A.class);
    ClassSubject classB = inspector.clazz(B.class);
    ClassSubject classC = inspector.clazz(C.class);
    ClassSubject classMain = inspector.clazz(Main.class);
    assertThat(classA, isPresent());
    assertThat(classB, isPresent());
    assertThat(classC, isPresent());
    assertThat(classMain, isPresent());

    // By default A.m *will not* be inlined (called several times and not small).
    assertThat(classA.method("int", "m", ImmutableList.of("int", "int")), isPresent());
    // By default A.method *will* be inlined (called only once).
    assertThat(classA.method("int", "method", ImmutableList.of()), not(isPresent()));
    // By default B.m *will not* be inlined (called several times and not small).
    assertThat(classB.method("int", "m", ImmutableList.of("int", "int")), isPresent());
    // By default B.method *will* be inlined (called only once).
    assertThat(classB.method("int", "method", ImmutableList.of()), not(isPresent()));
  }

  @Test
  public void testNeverInline() throws Exception {
    CodeInspector inspector =
        runTest(
            ImmutableList.of(
                "-neverinline class **.A { method(); }",
                "-neverinline class **.B { method(); }",
                "-keep class **.Main { *; }",
                "-nevermerge @com.android.tools.r8.NeverMerge class *",
                "-neverinline class *{ @com.android.tools.r8.NeverInline <methods>;}",
                "-dontobfuscate"));

    ClassSubject classA = inspector.clazz(A.class);
    ClassSubject classB = inspector.clazz(B.class);
    ClassSubject classC = inspector.clazz(C.class);
    ClassSubject classMain = inspector.clazz(Main.class);
    assertThat(classA, isPresent());
    assertThat(classB, isPresent());
    assertThat(classC, isPresent());
    assertThat(classMain, isPresent());

    // Compared to the default method is no longer inlined.
    assertThat(classA.method("int", "m", ImmutableList.of("int", "int")), isPresent());
    assertThat(classA.method("int", "method", ImmutableList.of()), isPresent());
    assertThat(classB.method("int", "m", ImmutableList.of("int", "int")), isPresent());
    assertThat(classB.method("int", "method", ImmutableList.of()), isPresent());
  }

  @Test
  public void testForceInline() throws Exception {
    CodeInspector inspector =
        runTest(
            ImmutableList.of(
                "-forceinline class **.A { int m(int, int); }",
                "-forceinline class **.B { int m(int, int); }",
                "-keep class **.Main { *; }",
                "-nevermerge @com.android.tools.r8.NeverMerge class *",
                "-neverinline class *{ @com.android.tools.r8.NeverInline <methods>;}",
                "-dontobfuscate"));

    ClassSubject classA = inspector.clazz(A.class);
    ClassSubject classB = inspector.clazz(B.class);
    ClassSubject classC = inspector.clazz(C.class);
    ClassSubject classMain = inspector.clazz(Main.class);

    // Compared to the default m is now inlined and method still is, so classes A and B are gone.
    assertThat(classA, not(isPresent()));
    assertThat(classB, not(isPresent()));
    assertThat(classC, isPresent());
    assertThat(classMain, isPresent());
  }

  @Test
  public void testForceInlineFails() {
    try {
      runTest(
          ImmutableList.of(
              "-forceinline class **.A { int x(); }",
              "-keep class **.Main { *; }",
              "-nevermerge @com.android.tools.r8.NeverMerge class *",
              "-dontobfuscate"));
      fail("Force inline of non-inlinable method succeeded");
    } catch (Throwable t) {
      // Ignore assertion error.
    }
  }
}