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

import static com.android.tools.r8.utils.codeinspector.Matchers.containsLinePositions;
import static com.android.tools.r8.utils.codeinspector.Matchers.isPresent;
import static junit.framework.TestCase.assertEquals;
import static org.hamcrest.CoreMatchers.containsString;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.junit.Assert.assertNull;

import com.android.tools.r8.CompilationFailedException;
import com.android.tools.r8.R8TestBuilder;
import com.android.tools.r8.TestBase;
import com.android.tools.r8.TestParameters;
import com.android.tools.r8.graph.DexClass;
import com.android.tools.r8.naming.retrace.StackTrace;
import com.android.tools.r8.naming.testclasses.ClassToBeMinified;
import com.android.tools.r8.naming.testclasses.Main;
import com.android.tools.r8.references.MethodReference;
import com.android.tools.r8.references.Reference;
import com.android.tools.r8.shaking.ProguardKeepAttributes;
import com.android.tools.r8.utils.BooleanUtils;
import com.android.tools.r8.utils.codeinspector.ClassSubject;
import com.android.tools.r8.utils.codeinspector.CodeInspector;
import com.android.tools.r8.utils.codeinspector.Matchers.LinePosition;
import java.io.IOException;
import java.util.List;
import java.util.concurrent.ExecutionException;
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 RenameSourceFileRetraceTest extends TestBase {

  private static final String FILENAME_RENAME = "FOO";
  private static final String FILENAME_MAIN = "Main.java";
  private static final String FILENAME_CLASS_TO_BE_MINIFIED = "ClassToBeMinified.java";

  private final TestParameters parameters;
  private final boolean isCompat;
  private final boolean keepSourceFile;

  @Parameters(name = "{0}, is compat: {1}, keep source file attribute: {2}")
  public static List<Object[]> data() {
    return buildParameters(
        getTestParameters().withAllRuntimesAndApiLevels().build(),
        BooleanUtils.values(),
        BooleanUtils.values());
  }

  public RenameSourceFileRetraceTest(
      TestParameters parameters, Boolean isCompat, Boolean keepSourceFile) {
    this.parameters = parameters;
    this.isCompat = isCompat;
    this.keepSourceFile = keepSourceFile;
  }

  @Test
  public void testR8()
      throws ExecutionException, CompilationFailedException, IOException, NoSuchMethodException {
    R8TestBuilder<? extends R8TestBuilder<?>> r8TestBuilder =
        isCompat ? testForR8Compat(parameters.getBackend()) : testForR8(parameters.getBackend());
    if (keepSourceFile) {
      r8TestBuilder.addKeepAttributes(ProguardKeepAttributes.SOURCE_FILE);
    }
    String minifiedFileName =
        (keepSourceFile && isCompat)
            ? FILENAME_CLASS_TO_BE_MINIFIED
            : (parameters.getBackend() == Backend.CF ? "SourceFile" : "");
    r8TestBuilder
        .addProgramClasses(ClassToBeMinified.class, Main.class)
        .addKeepAttributes(ProguardKeepAttributes.LINE_NUMBER_TABLE)
        .addKeepMainRule(Main.class)
        .setMinApi(parameters.getApiLevel())
        .enableInliningAnnotations()
        .run(parameters.getRuntime(), Main.class)
        .assertFailureWithErrorThatMatches(containsString("ClassToBeMinified.foo()"))
        .inspectFailure(inspector -> inspectOutput(inspector, minifiedFileName, FILENAME_MAIN))
        .inspectStackTrace(stackTrace -> inspectStackTrace(stackTrace, FILENAME_MAIN));
  }

  @Test
  public void testRenameSourceFileR8()
      throws ExecutionException, CompilationFailedException, IOException, NoSuchMethodException {
    R8TestBuilder<? extends R8TestBuilder<?>> r8TestBuilder =
        isCompat ? testForR8Compat(parameters.getBackend()) : testForR8(parameters.getBackend());
    if (keepSourceFile) {
      r8TestBuilder.addKeepAttributes(ProguardKeepAttributes.SOURCE_FILE);
    }
    r8TestBuilder
        .addProgramClasses(ClassToBeMinified.class, Main.class)
        .addKeepAttributes(ProguardKeepAttributes.LINE_NUMBER_TABLE)
        .addKeepRules("-renamesourcefileattribute " + FILENAME_RENAME)
        .addKeepMainRule(Main.class)
        .setMinApi(parameters.getApiLevel())
        .enableInliningAnnotations()
        .run(parameters.getRuntime(), Main.class)
        .assertFailureWithErrorThatMatches(containsString("ClassToBeMinified.foo()"))
        .inspectFailure(inspector -> inspectOutput(inspector, FILENAME_RENAME, FILENAME_RENAME))
        .inspectStackTrace(stackTrace -> inspectStackTrace(stackTrace, FILENAME_RENAME));
  }

  private void inspectOutput(
      CodeInspector inspector, String classToBeMinifiedFilename, String mainClassFilename) {
    ClassSubject mainSubject = inspector.clazz(Main.class);
    assertThat(mainSubject, isPresent());
    DexClass mainClazz = mainSubject.getDexClass();
    ClassSubject classToBeMinifiedSubject = inspector.clazz(ClassToBeMinified.class);
    assertThat(classToBeMinifiedSubject, isPresent());
    DexClass minifiedClazz = classToBeMinifiedSubject.getDexClass();
    if (keepSourceFile) {
      assertEquals(mainClassFilename, mainClazz.sourceFile.toString());
      assertEquals(classToBeMinifiedFilename, minifiedClazz.sourceFile.toString());
    } else {
      assertNull(mainClazz.sourceFile);
      assertNull(minifiedClazz.sourceFile);
    }
  }

  private void inspectStackTrace(StackTrace stackTrace, String mainFileName)
      throws NoSuchMethodException {
    if (!keepSourceFile) {
      return;
    }
    assertEquals(2, stackTrace.getStackTraceLines().size());
    MethodReference classToBeMinifiedFoo =
        Reference.methodFromMethod(ClassToBeMinified.class.getDeclaredMethod("foo"));
    MethodReference mainMain =
        Reference.methodFromMethod(Main.class.getDeclaredMethod("main", String[].class));
    LinePosition expectedStack =
        LinePosition.stack(
            LinePosition.create(classToBeMinifiedFoo, 1, 13, FILENAME_CLASS_TO_BE_MINIFIED),
            LinePosition.create(mainMain, 1, 10, mainFileName));
    assertThat(stackTrace, containsLinePositions(expectedStack));
  }
}
