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

import static org.junit.Assume.assumeTrue;

import com.android.tools.r8.R8TestCompileResult;
import com.android.tools.r8.TestParameters;
import com.android.tools.r8.TestParametersBuilder;
import com.android.tools.r8.debug.DebugTestBase.JUnit3Wrapper.Command;
import com.android.tools.r8.naming.ClassNameMapper.MissingFileAction;
import com.android.tools.r8.utils.BooleanUtils;
import com.android.tools.r8.utils.InternalOptions.LineNumberOptimization;
import com.google.common.collect.ImmutableList;
import java.util.ArrayList;
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 source file and line numbers on inlined methods. */
@RunWith(Parameterized.class)
public class DebugInfoWhenInliningTest extends DebugTestBase {

  private static final String CLASS_NAME = "Inlining1";
  private static final String SOURCE_FILE = "Inlining1.java";

  private DebugTestConfig makeConfig(
      LineNumberOptimization lineNumberOptimization, boolean writeProguardMap) throws Exception {
    R8TestCompileResult result =
        testForR8(parameters.getBackend())
            .addProgramFiles(DEBUGGEE_JAR)
            .addKeepMainRule(CLASS_NAME)
            .noMinification()
            .addKeepAttributeSourceFile()
            .addKeepAttributeLineNumberTable()
            .setMinApi(parameters.getApiLevel())
            .addOptionsModification(
                options -> {
                  options.lineNumberOptimization = lineNumberOptimization;
                  options.testing.forceJumboStringProcessing = forceJumboStringProcessing;
                  // TODO(b/117848700): Can we make these tests neutral to inlining threshold?
                  // Also CF needs improvements here.
                  options.inlinerOptions().simpleInliningInstructionLimit =
                      parameters.isCfRuntime() ? 5 : 4;
                })
            .compile();
    DebugTestConfig config = result.debugConfig();
    if (writeProguardMap) {
      config.setProguardMap(result.writeProguardMap(), MissingFileAction.MISSING_FILE_IS_EMPTY_MAP);
    }
    return config;
  }

  private final TestParameters parameters;
  private final boolean forceJumboStringProcessing;

  @Parameters(name = "{0}, force-jumbo: {1}")
  public static List<Object[]> data() {
    return buildParameters(
        TestParametersBuilder.builder().withAllRuntimesAndApiLevels().build(),
        BooleanUtils.values());
  }

  public DebugInfoWhenInliningTest(TestParameters parameters, boolean forceJumboString) {
    assumeTrue(!parameters.isCfRuntime() || !forceJumboString);
    this.parameters = parameters;
    this.forceJumboStringProcessing = forceJumboString;
  }

  private void assumeMappingIsNotToPCs() {
    assumeTrue(
        "Ignoring test when the line number table is removed.",
        parameters.isCfRuntime()
            || parameters.getApiLevel().isLessThan(apiLevelWithPcAsLineNumberSupport()));
  }

  @Test
  public void testEachLineNotOptimized() throws Throwable {
    assumeMappingIsNotToPCs();
    // The reason why the not-optimized test contains half as many line numbers as the optimized
    // one:
    //
    // In the Java source (Inlining1) each call is duplicated. Since they end up on the same line
    // (innermost callee) the line numbers are actually 7, 7, 32, 32, ... but even if the positions
    // are emitted duplicated in the dex code, the debugger stops only when there's a change.
    int[] lineNumbers = {7, 32, 11, 7};
    testEachLine(makeConfig(LineNumberOptimization.OFF, false), lineNumbers);
  }

  @Test
  public void testEachLineNotOptimizedWithMap() throws Throwable {
    assumeMappingIsNotToPCs();
    // The reason why the not-optimized test contains half as many line numbers as the optimized
    // one:
    //
    // In the Java source (Inlining1) each call is duplicated. Since they end up on the same line
    // (innermost callee) the line numbers are actually 7, 7, 32, 32, ... but even if the positions
    // are emitted duplicated in the dex code, the debugger stops only when there's a change.
    int[] lineNumbers = {7, 32, 11, 7};
    testEachLine(makeConfig(LineNumberOptimization.OFF, true), lineNumbers);
  }

  @Test
  public void testEachLineOptimized() throws Throwable {
    assumeMappingIsNotToPCs();
    int[] lineNumbers = {1, 2, 3, 4, 5, 6, 7, 8};
    testEachLine(makeConfig(LineNumberOptimization.ON, false), lineNumbers);
  }

  @Test
  public void testEachLineOptimizedWithMap() throws Throwable {
    assumeMappingIsNotToPCs();
    int[] lineNumbers = {7, 7, 32, 32, 11, 11, 7, 7};
    List<List<SignatureAndLine>> inlineFramesList =
        ImmutableList.of(
            ImmutableList.of(
                new SignatureAndLine("void inlineThisFromSameFile()", 7),
                new SignatureAndLine("void main(java.lang.String[])", 19)),
            ImmutableList.of(
                new SignatureAndLine("void inlineThisFromSameFile()", 7),
                new SignatureAndLine("void main(java.lang.String[])", 20)),
            ImmutableList.of(
                new SignatureAndLine("void Inlining2.inlineThisFromAnotherFile()", 32),
                new SignatureAndLine("void main(java.lang.String[])", 21)),
            ImmutableList.of(
                new SignatureAndLine("void Inlining2.inlineThisFromAnotherFile()", 32),
                new SignatureAndLine("void main(java.lang.String[])", 22)),
            ImmutableList.of(
                new SignatureAndLine("void sameFileMultilevelInliningLevel2()", 11),
                new SignatureAndLine("void sameFileMultilevelInliningLevel1()", 15),
                new SignatureAndLine("void main(java.lang.String[])", 23)),
            ImmutableList.of(
                new SignatureAndLine("void sameFileMultilevelInliningLevel2()", 11),
                new SignatureAndLine("void sameFileMultilevelInliningLevel1()", 15),
                new SignatureAndLine("void main(java.lang.String[])", 24)),
            ImmutableList.of(
                new SignatureAndLine("void Inlining3.differentFileMultilevelInliningLevel2()", 7),
                new SignatureAndLine("void Inlining2.differentFileMultilevelInliningLevel1()", 36),
                new SignatureAndLine("void main(java.lang.String[])", 25)),
            ImmutableList.of(
                new SignatureAndLine("void Inlining3.differentFileMultilevelInliningLevel2()", 7),
                new SignatureAndLine("void Inlining2.differentFileMultilevelInliningLevel1()", 36),
                new SignatureAndLine("void main(java.lang.String[])", 26)));
    testEachLine(makeConfig(LineNumberOptimization.ON, true), lineNumbers, inlineFramesList);
  }

  private void testEachLine(DebugTestConfig config, int[] lineNumbers) throws Throwable {
    testEachLine(config, lineNumbers, null);
  }

  private void testEachLine(
      DebugTestConfig config, int[] lineNumbers, List<List<SignatureAndLine>> inlineFramesList)
      throws Throwable {
    final String mainSignature = "([Ljava/lang/String;)V";

    List<Command> commands = new ArrayList<Command>();
    commands.add(breakpoint(CLASS_NAME, "main", mainSignature));
    commands.add(run());
    boolean first = true;
    assert inlineFramesList == null || inlineFramesList.size() == lineNumbers.length;
    for (int idx = 0; idx < lineNumbers.length; ++idx) {
      if (first) {
        first = false;
      } else {
        commands.add(stepOver());
      }
      commands.add(checkMethod(CLASS_NAME, "main", mainSignature));
      commands.add(checkLine(SOURCE_FILE, lineNumbers[idx]));
      if (inlineFramesList != null) {
        commands.add(checkInlineFrames(inlineFramesList.get(idx)));
      }
    }
    commands.add(run());
    runDebugTest(config, CLASS_NAME, commands);
  }
}
