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

import static org.hamcrest.CoreMatchers.containsString;
import static org.junit.Assert.assertEquals;

import com.android.tools.r8.NeverInline;
import com.android.tools.r8.R8FullTestBuilder;
import com.android.tools.r8.R8TestRunResult;
import com.android.tools.r8.TestBase;
import com.android.tools.r8.TestParameters;
import com.android.tools.r8.TestParametersCollection;
import com.android.tools.r8.naming.retrace.StackTrace;
import com.android.tools.r8.retrace.internal.RetraceUtils;
import com.android.tools.r8.utils.codeinspector.CodeInspector;
import java.util.function.BiConsumer;
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 SourceFileTest extends TestBase {

  private final TestParameters parameters;
  private static final String FILE_NAME = "foobarbaz.java";

  @Parameters(name = "{0}")
  public static TestParametersCollection data() {
    return getTestParameters().withAllRuntimesAndApiLevels().build();
  }

  public SourceFileTest(TestParameters parameters) {
    this.parameters = parameters;
  }

  @Test
  public void testRuntime() throws Exception {
    testForRuntime(parameters)
        .addProgramClasses(Main.class, ClassWithoutCustomFileName.class)
        .addProgramClassFileData(
            transformer(ClassWithCustomFileName.class).setSourceFile(FILE_NAME).transform())
        .run(parameters.getRuntime(), Main.class)
        .assertFailureWithErrorThatMatches(containsString("Hello World!"))
        .inspectStackTrace(
            stackTrace -> {
              assertEquals(FILE_NAME, stackTrace.getStackTraceLines().get(0).fileName);
            });
  }

  @Test
  public void testR8WithCustomFileName() throws Exception {
    runTest(
        false,
        ((stackTrace, inspector) -> {
          assertEquals(FILE_NAME, stackTrace.getStackTraceLines().get(0).fileName);
          assertEquals(
              FILE_NAME,
              inspector
                  .clazz(ClassWithCustomFileName.class)
                  .retraceUnique()
                  .getSourceFile()
                  .getSourceFile());
        }));
  }

  @Test
  public void testR8WithoutCustomFileName() throws Exception {
    runTest(
        true,
        ((stackTrace, inspector) -> {
          // Since the type has a mapping, the file is inferred from the class name.
          assertEquals("SourceFileTest.java", stackTrace.getStackTraceLines().get(0).fileName);
          RetraceClassElement retraceClassElement =
              inspector.clazz(ClassWithoutCustomFileName.class).retraceUnique();
          assertEquals(
              "SourceFileTest.java",
              RetraceUtils.inferSourceFile(
                  retraceClassElement.getRetracedClass().getTypeName(), "nofile.java", true));
        }));
  }

  private void runTest(boolean addDummyArg, BiConsumer<StackTrace, CodeInspector> consumer)
      throws Exception {
    R8FullTestBuilder r8FullTestBuilder =
        testForR8(parameters.getBackend())
            .addProgramClasses(Main.class, ClassWithoutCustomFileName.class)
            .addProgramClassFileData(
                transformer(ClassWithCustomFileName.class).setSourceFile(FILE_NAME).transform())
            .addKeepClassRules(ClassWithoutCustomFileName.class)
            .enableInliningAnnotations()
            .addKeepMainRule(Main.class)
            .setMinApi(parameters.getApiLevel())
            .addKeepAttributeSourceFile();
    R8TestRunResult runResult =
        addDummyArg
            ? r8FullTestBuilder.run(parameters.getRuntime(), Main.class, "foo")
            : r8FullTestBuilder.run(parameters.getRuntime(), Main.class);
    runResult.assertFailureWithErrorThatMatches(containsString("Hello World!"));
    StackTrace originalStackTrace = runResult.getOriginalStackTrace();
    StackTrace retracedStackTrace = originalStackTrace.retrace(runResult.proguardMap());
    runResult.inspectFailure(inspector -> consumer.accept(retracedStackTrace, inspector));
  }

  public static class ClassWithoutCustomFileName {

    @NeverInline
    public static void foo() {
      throw new RuntimeException("Hello World!");
    }
  }

  public static class ClassWithCustomFileName {

    @NeverInline
    public static void foo() {
      throw new RuntimeException("Hello World!");
    }
  }

  public static class Main {

    public static void main(String[] args) {
      if (args.length == 0) {
        ClassWithCustomFileName.foo();
      } else {
        ClassWithoutCustomFileName.foo();
      }
    }
  }
}
