// 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.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 com.android.tools.r8.CompilationMode;
import com.android.tools.r8.ToolHelper;
import com.android.tools.r8.naming.retrace.StackTrace.StackTraceLine;
import com.google.common.collect.ImmutableList;
import java.util.Collection;
import org.junit.Ignore;
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 = "Backend: {0}, mode: {1}")
  public static Collection<Object[]> data() {
    return buildParameters(ToolHelper.getBackends(), CompilationMode.values());
  }

  public DesugarLambdaRetraceTest(Backend backend, CompilationMode mode) {
    super(backend, mode);
  }

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

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

  private int expectedActualStackTraceHeight() {
    // In debug mode the expected stack trace height differs since there is no lambda desugaring
    // for CF.
    return mode == CompilationMode.RELEASE ? 2 : (backend == Backend.CF ? 4 : 5);
  }

  private boolean isSynthesizedLambdaFrame(StackTraceLine line) {
    return line.className.contains("-$$Lambda$");
  }

  private void checkLambdaFrame(StackTrace retracedStackTrace) {
    StackTrace lambdaFrames = retracedStackTrace.filter(this::isSynthesizedLambdaFrame);
    assertEquals(1, lambdaFrames.size());
    if (lambdaFrames.get(0).hasLineNumber()) {
      assertEquals(mode == CompilationMode.RELEASE ? 0 : 2, lambdaFrames.get(0).lineNumber);
    }
    // Proguard retrace will take the class name until the first $ to construct the file
    // name, so for "-$$Lambda$...", the file name becomes "-.java".
    assertEquals("-.java", lambdaFrames.get(0).fileName);
  }

  private void checkIsSameExceptForFileName(
      StackTrace actualStackTrace, StackTrace retracedStackTrace) {
    // Even when SourceFile is present retrace replaces the file name in the stack trace.
    if (backend == Backend.CF) {
      // TODO(122440196): Additional code to locate issue.
      if (!isSameExceptForFileName(expectedStackTrace).matches(retracedStackTrace)) {
        System.out.println("Expected original:");
        System.out.println(expectedStackTrace.getOriginalStderr());
        System.out.println("Actual original:");
        System.out.println(retracedStackTrace.getOriginalStderr());
        System.out.println("Parsed original:");
        System.out.println(expectedStackTrace);
        System.out.println("Parsed retraced:");
        System.out.println(retracedStackTrace);
      }
      assertThat(retracedStackTrace, isSameExceptForFileName(expectedStackTrace));
    } else {
      // TODO(122440196): Additional code to locate issue.
      if (!isSameExceptForFileName(expectedStackTrace)
          .matches(retracedStackTrace.filter(line -> !isSynthesizedLambdaFrame(line)))) {
        System.out.println("Expected original:");
        System.out.println(expectedStackTrace.getOriginalStderr());
        System.out.println("Actual original:");
        System.out.println(retracedStackTrace.getOriginalStderr());
        System.out.println("Parsed original:");
        System.out.println(expectedStackTrace);
        System.out.println("Parsed retraced:");
        System.out.println(retracedStackTrace);
      }
      // With the frame 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.
      checkLambdaFrame(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 (backend == Backend.CF) {
      // TODO(122440196): Additional code to locate issue.
      if (!isSameExceptForFileNameAndLineNumber(expectedStackTrace).matches(retracedStackTrace)) {
        System.out.println("Expected original:");
        System.out.println(expectedStackTrace.getOriginalStderr());
        System.out.println("Actual original:");
        System.out.println(retracedStackTrace.getOriginalStderr());
        System.out.println("Parsed original:");
        System.out.println(expectedStackTrace);
        System.out.println("Parsed retraced:");
        System.out.println(retracedStackTrace);
      }
      assertThat(retracedStackTrace, isSameExceptForFileNameAndLineNumber(expectedStackTrace));
    } else {
      // TODO(122440196): Additional code to locate issue.
      if (!isSameExceptForFileNameAndLineNumber(expectedStackTrace)
          .matches(retracedStackTrace.filter(line -> !isSynthesizedLambdaFrame(line)))) {
        System.out.println("Expected original:");
        System.out.println(expectedStackTrace.getOriginalStderr());
        System.out.println("Actual original:");
        System.out.println(retracedStackTrace.getOriginalStderr());
        System.out.println("Parsed original:");
        System.out.println(expectedStackTrace);
        System.out.println("Parsed retraced:");
        System.out.println(retracedStackTrace);
      }
      // 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.
      checkLambdaFrame(retracedStackTrace);
    }
    assertEquals(expectedActualStackTraceHeight(), actualStackTrace.size());
  }

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

  @Test
  @Ignore("b/122440196")
  public void testLineNumberTableOnly() throws Exception {
    runTest(
        ImmutableList.of("-keepattributes LineNumberTable"),
        this::checkIsSameExceptForFileName);
  }

  @Test
  @Ignore("b/122440196")
  public void testNoLineNumberTable() throws Exception {
    runTest(
        ImmutableList.of(),
        this::checkIsSameExceptForFileNameAndLineNumber);
  }
}

// Custom consumer functional interface, as java.util.function.Consumer is not present on Android.
@FunctionalInterface
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)));
  }
}
