// 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.naming.retrace;

import static com.android.tools.r8.ir.desugar.LambdaClass.R8_LAMBDA_ACCESSOR_METHOD_PREFIX;
import static com.android.tools.r8.naming.retrace.StackTrace.isSame;
import static com.android.tools.r8.naming.retrace.StackTrace.isSameExceptForFileName;
import static com.android.tools.r8.naming.retrace.StackTrace.isSameExceptForFileNameAndLineNumber;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.junit.Assert.assertEquals;
import static org.junit.Assume.assumeTrue;

import com.android.tools.r8.CompilationMode;
import com.android.tools.r8.TestParameters;
import com.android.tools.r8.naming.retrace.StackTrace.StackTraceLine;
import com.android.tools.r8.references.Reference;
import com.android.tools.r8.synthesis.SyntheticItemsTestUtils;
import com.android.tools.r8.utils.BooleanUtils;
import com.google.common.collect.ImmutableList;
import java.util.Collection;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.Parameterized;
import org.junit.runners.Parameterized.Parameters;

@RunWith(Parameterized.class)
public class DesugarLambdaRetraceTest extends RetraceTestBase {

  @Parameters(name = "{0}, mode: {1}, compat: {2}")
  public static Collection<Object[]> data() {
    return buildParameters(
        getTestParameters().withAllRuntimesAndApiLevels().build(),
        CompilationMode.values(),
        BooleanUtils.values());
  }

  public DesugarLambdaRetraceTest(TestParameters parameters, CompilationMode mode, boolean compat) {
    super(parameters, mode, compat);
  }

  @Override
  public Collection<Class<?>> getClasses() {
    return ImmutableList.of(getMainClass(), ConsumerDesugarLambdaRetraceTest.class);
  }

  @Override
  public Class<?> getMainClass() {
    return MainDesugarLambdaRetraceTest.class;
  }

  private int expectedActualStackTraceHeight() {
    // In DEX release the entire lambda is inlined.
    if (parameters.isDexRuntime()) {
      return mode == CompilationMode.RELEASE ? 1 : 6;
    }
    // In CF release it is not and in debug there is no lambda desugaring thus the shorter stack.
    return mode == CompilationMode.RELEASE ? 2 : 4;
  }

  private boolean isSynthesizedLambdaFrame(StackTraceLine line) {
    // TODO(141287349): The mapping should not map the external name to the internal name!
    return SyntheticItemsTestUtils.isInternalLambda(Reference.classFromTypeName(line.className))
        || line.methodName.startsWith(R8_LAMBDA_ACCESSOR_METHOD_PREFIX);
  }

  private void checkLambdaFrames(StackTrace retracedStackTrace) {
    StackTrace lambdaFrames = retracedStackTrace.filter(this::isSynthesizedLambdaFrame);
    assertEquals(2, lambdaFrames.size());

    StackTraceLine syntheticLambdaClassFrame = lambdaFrames.get(1);
    if (syntheticLambdaClassFrame.hasLineNumber()) {
      assertEquals(mode == CompilationMode.RELEASE ? 0 : 2, syntheticLambdaClassFrame.lineNumber);
    }
    // Proguard retrace will take the class name until the first $ to construct the file
    // name, so for "-$$Lambda$...", the file name becomes "-.java".
    // TODO(b/141287349): Format the class name of desugared lambda classes.
    // assertEquals("-.java", syntheticLambdaClassFrame.fileName);
  }

  private void checkIsSame(StackTrace actualStackTrace, StackTrace retracedStackTrace) {
    // Even when SourceFile is present retrace replaces the file name in the stack trace.
    if (parameters.isCfRuntime()) {
      assertThat(retracedStackTrace, isSame(expectedStackTrace));
    } else {
      // With the frame from the lambda class filtered out the stack trace is the same.
      assertThat(
          retracedStackTrace.filter(line -> !isSynthesizedLambdaFrame(line)),
          isSame(expectedStackTrace));
      // Check the frame from the lambda class.
      checkLambdaFrames(retracedStackTrace);
    }
    assertEquals(expectedActualStackTraceHeight(), actualStackTrace.size());
  }

  private void checkIsSameExceptForFileName(
      StackTrace actualStackTrace, StackTrace retracedStackTrace) {
    // Even when SourceFile is present retrace replaces the file name in the stack trace.
    if (parameters.isCfRuntime()) {
      assertThat(retracedStackTrace, isSameExceptForFileName(expectedStackTrace));
    } else {
      // With the frames from the lambda class filtered out the stack trace is the same.
      assertThat(
          retracedStackTrace.filter(line -> !isSynthesizedLambdaFrame(line)),
          isSameExceptForFileName(expectedStackTrace));
      // Check the frame from the lambda class.
      checkLambdaFrames(retracedStackTrace);
    }
    assertEquals(expectedActualStackTraceHeight(), actualStackTrace.size());
  }

  private void checkIsSameExceptForFileNameAndLineNumber(
      StackTrace actualStackTrace, StackTrace retracedStackTrace) {
    // Even when SourceFile is present retrace replaces the file name in the stack trace.
    if (parameters.isCfRuntime()) {
      assertThat(retracedStackTrace, isSameExceptForFileNameAndLineNumber(expectedStackTrace));
    } else {
      // With the frame from the lambda class filtered out the stack trace is the same.
      assertThat(
          retracedStackTrace.filter(line -> !isSynthesizedLambdaFrame(line)),
          isSameExceptForFileNameAndLineNumber(expectedStackTrace));
      // Check the frame from the lambda class.
      checkLambdaFrames(retracedStackTrace);
    }
    assertEquals(expectedActualStackTraceHeight(), actualStackTrace.size());
  }

  @Test
  public void testSourceFileAndLineNumberTable() throws Exception {
    runTest(ImmutableList.of("-keepattributes SourceFile,LineNumberTable"), this::checkIsSame);
  }

  @Test
  public void testLineNumberTableOnly() throws Exception {
    assumeTrue(compat);
    assumeTrue(parameters.isDexRuntime());
    runTest(
        ImmutableList.of("-keepattributes LineNumberTable"), this::checkIsSameExceptForFileName);
  }

  @Test
  public void testNoLineNumberTable() throws Exception {
    assumeTrue(compat);
    assumeTrue(parameters.isDexRuntime());
    runTest(ImmutableList.of(), this::checkIsSameExceptForFileNameAndLineNumber);
  }
}

// Custom consumer functional interface, as java.util.function.Consumer is not present on Android.
interface ConsumerDesugarLambdaRetraceTest<T> {
  void accept(T value);
}

class MainDesugarLambdaRetraceTest {

  public static void method2(long j) {
    System.out.println("In method2");
    if (j == 1) throw null;
  }

  public static void method1(String s, ConsumerDesugarLambdaRetraceTest<String> consumer) {
    System.out.println("In method1");
    for (int i = 0; i < 10; i++) {
      consumer.accept(s);
    }
  }

  public static void main(String[] args) {
    System.out.println("In main");
    method1("1", s -> method2(Long.parseLong(s)));
  }
}
