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

import static com.android.tools.r8.DiagnosticsMatcher.diagnosticMessage;
import static org.hamcrest.CoreMatchers.containsString;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;

import com.android.tools.r8.TestBase;
import com.android.tools.r8.TestDiagnosticMessages;
import com.android.tools.r8.TestParameters;
import com.android.tools.r8.ToolHelper;
import com.android.tools.r8.jasmin.JasminBuilder.ClassFileVersion;
import com.android.tools.r8.naming.MemberNaming.MethodSignature;
import com.android.tools.r8.utils.BooleanUtils;
import com.android.tools.r8.utils.InternalOptions;
import com.android.tools.r8.utils.StringUtils;
import com.google.common.collect.ImmutableList;
import java.util.List;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.Parameterized;
import org.junit.runners.Parameterized.Parameter;
import org.junit.runners.Parameterized.Parameters;

@RunWith(Parameterized.class)
public class InvalidDebugInfoTests extends TestBase {

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

  @Parameter(0)
  public TestParameters parameters;

  @Parameter(1)
  public boolean strict;

  private void optionsModification(InternalOptions options) {
    options.invalidDebugInfoStrict = strict;
    options.testing.forceIRForCfToCfDesugar = true;
  }

  private void assertInvalidTypeMessage(TestDiagnosticMessages diagnostics) {
    assertInvalidInfoMessages(diagnostics, "Attempt to define local of type");
  }

  private void assertUninitializedLocalMessage(TestDiagnosticMessages diagnostics) {
    assertInvalidInfoMessages(diagnostics, "Local refers to uninitialized register");
  }

  private void assertInvalidInfoMessages(TestDiagnosticMessages diagnostics, String message) {
    // The reporting of invalid debug info issues three info items:
    diagnostics.assertOnlyInfos();
    diagnostics.assertInfosMatch(
        ImmutableList.of(
            diagnosticMessage(containsString("Stripped invalid locals information")),
            diagnosticMessage(containsString(message)),
            diagnosticMessage(containsString("sign of using an outdated Java toolchain"))));
  }

  // This is a regression test for invalid live-ranges of locals generated by some old Java
  // compilers. The issue is that a local slot may have been initialized outside the live-scope of
  // the variable and then the subsequent live-scope of the variable extends beyond its actual
  // liveness. In the example below the variable 'y' is initialized outside its range (it is thus
  // associated with the local 'x' (the SSA value is unaffected by the istore). Finally the 'return'
  // forces a read of all supposedly live variables before exiting. Here the attempt to read 'y'
  // will actually be a read of 'x'.
  @Test
  public void testInvalidInfoThrow() throws Exception {
    JasminBuilder builder = new JasminBuilder(ClassFileVersion.JDK_1_4);
    JasminBuilder.ClassBuilder clazz = builder.addClass("Test");

    clazz.addStaticMethod("foo", ImmutableList.of("I"), "V",
        ".limit stack 3",
        ".limit locals 4",
        ".var 0 is x I from LabelInit to LabelExit",
        ".var 1 is y I from LabelLocalStart to LabelExit",
        ".var 2 is e Ljava/lang/Exception; from LabelCatchStart to LabelCatchEnd",
        // var 3 is the jsr address
        "LabelInit:",
        "LabelTryStart:",
        "  ldc 84",
        "  iload 0",
        "  dup",
        "  istore 1", // init local[1] to value of local[0] (eg, 'x' since 'y' is not live yet).
        "  idiv",
        "  istore 0",
        "LabelLocalStart:",
        "  jsr LabelPrint",
        "  goto LabelExit",
        "LabelTryEnd:",
        "LabelCatchStart:",
        "  astore 2",
        "  jsr LabelPrint",
        "  return", // y is not actually live here.
        "LabelCatchEnd:",
        "LabelPrint:",
        "  astore 3",
        "  getstatic java/lang/System/out Ljava/io/PrintStream;",
        "  iload 0",
        "  invokevirtual java/io/PrintStream/println(I)V",
        "  ret 3",
        "LabelExit:",
        "  return",
        ".catch java/lang/Exception from LabelTryStart to LabelTryEnd using LabelCatchStart"
    );

    clazz.addMainMethod(
        ".limit stack 1",
        ".limit locals 1",
        "  ldc 2",
        "  invokestatic Test/foo(I)V",
        "  ldc 0",
        "  invokestatic Test/foo(I)V",
        "  return");

    String expected = "42" + ToolHelper.LINE_SEPARATOR + "0" + ToolHelper.LINE_SEPARATOR;
    if (parameters.isJvmTestParameters()) {
      testForJvm(parameters)
          .addProgramClassFileData(builder.buildClasses())
          .run(parameters.getRuntime(), clazz.name)
          .assertSuccessWithOutput(expected);
    }
    testForD8(parameters.getBackend())
        .addProgramClassFileData(builder.buildClasses())
        .setMinApi(parameters)
        .addOptionsModification(this::optionsModification)
        .compileWithExpectedDiagnostics(
            diagnostics -> {
              if (strict) {
                assertUninitializedLocalMessage(diagnostics);
              } else {
                diagnostics.assertNoMessages();
              }
            })
        .run(parameters.getRuntime(), clazz.name)
        .assertSuccessWithOutput(expected);
  }

  // Regression test to check that we properly add UninitializedLocal SSA values for methods that
  // have arguments without local info. To witness this bug, we also need "invalid" debug info, eg,
  // in this test the scope of "y" (local 2) spans the exceptional edge in which it is not live.
  @Test
  public void testInvalidInfoBug37722432() throws Exception {
    JasminBuilder builder = new JasminBuilder(ClassFileVersion.JDK_1_4);
    JasminBuilder.ClassBuilder clazz = builder.addClass("Test");

    clazz.addStaticMethod("foo", ImmutableList.of("I", "I"), "V",
        ".limit stack 2",
        ".limit locals 3",
        ".var 0 is x I from LabelInit to LabelExit",
        // Synthesized arg (no local info)
        ".var 2 is y I from LabelLocalStart to LabelExit",
        ".catch java/lang/Exception from LabelInit to LabelCatch using LabelCatch",
        "LabelInit:", // Start of try block targets catch with a state excluding 'y'.
        "  ldc 84",
        "  iload 0",
        "  idiv",
        "  istore 2",
        "LabelLocalStart:",
        "  getstatic java/lang/System/out Ljava/io/PrintStream;",
        "  iload 2",
        "  invokevirtual java/io/PrintStream/println(I)V",
        "  return",
        "LabelCatch:", // Catch target appears to include 'y' but actually does not.
        "  pop",
        "  return",
        "LabelExit:"
    );

    clazz.addMainMethod(
        ".limit stack 2",
        ".limit locals 1",
        "  ldc 2",
        "  ldc 2",
        "  invokestatic Test/foo(II)V",
        "  ldc 0",
        "  ldc 0",
        "  invokestatic Test/foo(II)V",
        "  return");

    String expected = "42" + ToolHelper.LINE_SEPARATOR;
    if (parameters.isJvmTestParameters()) {
      testForJvm(parameters)
          .addProgramClassFileData(builder.buildClasses())
          .run(parameters.getRuntime(), clazz.name)
          .assertSuccessWithOutput(expected);
    }
    testForD8(parameters.getBackend())
        .addProgramClassFileData(builder.buildClasses())
        .addOptionsModification(this::optionsModification)
        .setMinApi(parameters)
        .compileWithExpectedDiagnostics(
            diagnostics -> {
              if (strict) {
                assertUninitializedLocalMessage(diagnostics);
              } else {
                diagnostics.assertNoMessages();
              }
            })
        .run(parameters.getRuntime(), clazz.name)
        .assertSuccessWithOutput(expected);
  }

  @Test
  public void invalidInfoBug63412730_onWrite() throws Throwable {
    JasminBuilder builder = new JasminBuilder();
    JasminBuilder.ClassBuilder clazz = builder.addClass("Test");
    MethodSignature method = clazz.addStaticMethod("bar", ImmutableList.of(), "V",
        ".limit stack 3",
        ".limit locals 2",
        ".var 1 is i I from LI to End",
        ".var 0 is f F from LF to End",
        "Init:",
        "  ldc 42",
        "  istore 0",
        ".line 1",
        "LI:",
        "  ldc 7.5",
        "  fstore 1",
        ".line 2",
        "LF:",
        "  getstatic java/lang/System/out Ljava/io/PrintStream;",
        "  dup",
        "  iload 0",
        "  invokevirtual java/io/PrintStream/println(I)V",
        "  fload 1",
        "  invokevirtual java/io/PrintStream/println(F)V",
        ".line 3",
        "  return",
        "End:");

    clazz.addMainMethod(
        ".limit stack 1",
        ".limit locals 1",
        "  invokestatic Test/bar()V",
        "  return");

    String expected = StringUtils.lines("42", "7.5");
    if (parameters.isJvmTestParameters()) {
      testForJvm(parameters)
          .addProgramClassFileData(builder.buildClasses())
          .run(parameters.getRuntime(), clazz.name)
          .assertSuccessWithOutput(expected);
    }
    testForD8(parameters.getBackend())
        .addProgramClassFileData(builder.buildClasses())
        .setMinApi(parameters)
        .addOptionsModification(this::optionsModification)
        .compileWithExpectedDiagnostics(
            diagnostics -> {
              if (strict) {
                assertUninitializedLocalMessage(diagnostics);
              } else {
                assertInvalidTypeMessage(diagnostics);
              }
            })
        .run(parameters.getRuntime(), clazz.name)
        .assertSuccessWithOutput(expected)
        .inspect(
            inspector ->
                assertFalse(inspector.clazz(clazz.name).method(method).hasLocalVariableTable()));
  }

  @Test
  public void invalidInfoBug63412730_onRead() throws Throwable {
    JasminBuilder builder = new JasminBuilder();
    JasminBuilder.ClassBuilder clazz = builder.addClass("Test");
    MethodSignature method = clazz.addStaticMethod("bar", ImmutableList.of(), "V",
        ".limit stack 3",
        ".limit locals 2",
        ".var 1 is i I from Locals to End",
        ".var 0 is f F from Locals to End",
        "Init:",
        "  ldc 42",
        "  istore 0",
        ".line 1",
        "  ldc 7.5",
        "  fstore 1",
        ".line 2",
        "Locals:",
        "  getstatic java/lang/System/out Ljava/io/PrintStream;",
        "  dup",
        "  iload 0",
        "  invokevirtual java/io/PrintStream/println(I)V",
        "  fload 1",
        "  invokevirtual java/io/PrintStream/println(F)V",
        ".line 3",
        "  return",
        "End:");

    clazz.addMainMethod(
        ".limit stack 1",
        ".limit locals 1",
        "  invokestatic Test/bar()V",
        "  return");

    String expected = StringUtils.lines("42", "7.5");
    if (parameters.isJvmTestParameters()) {
      testForJvm(parameters)
          .addProgramClassFileData(builder.buildClasses())
          .run(parameters.getRuntime(), clazz.name)
          .assertSuccessWithOutput(expected);
    }
    testForD8(parameters.getBackend())
        .addProgramClassFileData(builder.buildClasses())
        .addOptionsModification(this::optionsModification)
        .setMinApi(parameters)
        .compileWithExpectedDiagnostics(this::assertInvalidTypeMessage)
        .run(parameters.getRuntime(), clazz.name)
        .assertSuccessWithOutput(expected)
        .inspect(
            inspector ->
                assertFalse(inspector.clazz(clazz.name).method(method).hasLocalVariableTable()));
  }

  @Test
  public void invalidInfoBug63412730_onMove() throws Throwable {
    JasminBuilder builder = new JasminBuilder(ClassFileVersion.JDK_1_4);
    JasminBuilder.ClassBuilder clazz = builder.addClass("Test");
    MethodSignature method = clazz.addStaticMethod("bar", ImmutableList.of(), "V",
        ".limit stack 3",
        ".limit locals 2",
        ".var 1 is i I from LI to End",
        ".var 0 is j F from LJ to End",
        "Init:",
        "  ldc 42",
        "  istore 0",
        ".line 1",
        "LI:",
        "  ldc 0",
        "  ldc 0",
        "  ifeq LZ",
        "  ldc 75",
        "  istore 1",
        ".line 2",
        "LJ:",
        "  getstatic java/lang/System/out Ljava/io/PrintStream;",
        "  iload 1",
        "  invokevirtual java/io/PrintStream/println(I)V",
        ".line 3",
        "  return",
        "LZ:",
        "  getstatic java/lang/System/out Ljava/io/PrintStream;",
        "  iload 0",
        "  invokevirtual java/io/PrintStream/println(I)V",
        ".line 4",
        "  return",
        "End:");

    clazz.addMainMethod(
        ".limit stack 1",
        ".limit locals 1",
        "  invokestatic Test/bar()V",
        "  return");

    String expected = StringUtils.lines("42");
    if (parameters.isJvmTestParameters()) {
      testForJvm(parameters)
          .addProgramClassFileData(builder.buildClasses())
          .run(parameters.getRuntime(), clazz.name)
          .assertSuccessWithOutput(expected);
    }
    testForD8(parameters.getBackend())
        .addProgramClassFileData(builder.buildClasses())
        .addOptionsModification(this::optionsModification)
        .setMinApi(parameters)
        .compileWithExpectedDiagnostics(
            diagnostics -> {
              if (strict) {
                assertUninitializedLocalMessage(diagnostics);
              } else {
                assertInvalidTypeMessage(diagnostics);
              }
            })
        .run(parameters.getRuntime(), clazz.name)
        .assertSuccessWithOutput(expected)
        .inspect(
            inspector ->
                assertFalse(inspector.clazz(clazz.name).method(method).hasLocalVariableTable()));
  }

  @Test
  public void invalidInfoBug63412730_onPop() throws Throwable {
    JasminBuilder builder = new JasminBuilder();
    JasminBuilder.ClassBuilder clazz = builder.addClass("Test");
    MethodSignature method = clazz.addStaticMethod("bar", ImmutableList.of(), "V",
        ".limit stack 3",
        ".limit locals 2",
        ".var 1 is a [Ljava/lang/Object; from Locals to End",
        ".var 0 is o LObject; from Locals to End",
        "Init:",
        "  ldc 1",
        "  anewarray java/lang/Object",
        "  astore 0",
        ".line 1",
        "  new java/lang/Integer",
        "  dup",
        "  ldc 42",
        "  invokespecial java/lang/Integer/<init>(I)V",
        "  astore 1",
        ".line 2",
        "Locals:",
        "  aload 0",
        "  ldc 0",
        "  aload 1",
        "  aastore",
        ".line 3",
        "  getstatic java/lang/System/out Ljava/io/PrintStream;",
        "  aload 0",
        "  ldc 0",
        "  aaload",
        "  invokevirtual java/io/PrintStream/println(Ljava/lang/Object;)V",
        ".line 4",
        "  return",
        "End:");

    clazz.addMainMethod(
        ".limit stack 1",
        ".limit locals 1",
        "  invokestatic Test/bar()V",
        "  return");

    String expected = StringUtils.lines("42");
    if (parameters.isJvmTestParameters()) {
      testForJvm(parameters)
          .addProgramClassFileData(builder.buildClasses())
          .run(parameters.getRuntime(), clazz.name)
          .assertSuccessWithOutput(expected);
    }
    testForD8(parameters.getBackend())
        .addProgramClassFileData(builder.buildClasses())
        .addOptionsModification(this::optionsModification)
        .setMinApi(parameters)
        .compileWithExpectedDiagnostics(TestDiagnosticMessages::assertNoMessages)
        .run(parameters.getRuntime(), clazz.name)
        .assertSuccessWithOutput(expected)
        .inspect(
            inspector -> {
              // Note: This code is actually invalid debug info, but we do not reject it because
              // both types are reference types. If we change that we should update this test.
              assertTrue(inspector.clazz(clazz.name).method(method).hasLocalVariableTable());
            });
  }
}
