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

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotSame;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;

import com.android.tools.r8.CompilationException;
import com.android.tools.r8.R8Command;
import com.android.tools.r8.ToolHelper;
import com.android.tools.r8.graph.DexCode;
import com.android.tools.r8.graph.DexString;
import com.android.tools.r8.naming.ClassNameMapper;
import com.android.tools.r8.naming.ClassNaming;
import com.android.tools.r8.naming.MemberNaming;
import com.android.tools.r8.naming.MemberNaming.InlineInformation;
import com.android.tools.r8.naming.MemberNaming.MethodSignature;
import com.android.tools.r8.naming.MemberNaming.Signature;
import com.android.tools.r8.naming.ProguardMapReader;
import com.android.tools.r8.shaking.ProguardRuleParserException;
import com.android.tools.r8.utils.AndroidApp;
import com.android.tools.r8.utils.DexInspector;
import com.android.tools.r8.utils.DexInspector.ClassSubject;
import com.google.common.collect.BiMap;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.Maps;
import com.google.common.io.Closer;
import java.io.IOException;
import java.io.InputStream;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
import java.util.concurrent.ExecutionException;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.TemporaryFolder;
import org.junit.runner.RunWith;
import org.junit.runners.Parameterized;
import org.junit.runners.Parameterized.Parameter;
import org.junit.runners.Parameterized.Parameters;

@RunWith(Parameterized.class)
public class R8DebugStrippingTest {

  private static final String ROOT = ToolHelper.EXAMPLES_BUILD_DIR;
  private static final String EXAMPLE_DEX = "throwing/classes.dex";
  private static final String EXAMPLE_MAP = "throwing/throwing.map";
  private static final String EXAMPLE_CLASS = "throwing.Throwing";
  private static final String EXAMPLE_JAVA = "Throwing.java";

  private static final String MAIN_NAME = "main";
  private static final String[] MAIN_PARAMETERS = new String[]{"java.lang.String[]"};
  private static final String VOID_RETURN = "void";

  private static final String OTHER_NAME = "throwInAFunctionThatIsNotInlinedAndCalledTwice";
  private static final String[] NO_PARAMETERS = new String[0];
  private static final String INT_RETURN = "int";

  private static final String THIRD_NAME = "aFunctionThatCallsAnInlinedMethodThatThrows";
  private static final String[] LIST_PARAMETER = new String[]{"java.util.List"};

  private static final String FORTH_NAME = "anotherFunctionThatCallsAnInlinedMethodThatThrows";
  private static final String[] STRING_PARAMETER = new String[]{"java.lang.String"};

  private static final Map<String, Signature> SIGNATURE_MAP = ImmutableMap.of(
      MAIN_NAME, new MethodSignature(MAIN_NAME, VOID_RETURN, MAIN_PARAMETERS),
      OTHER_NAME, new MethodSignature(OTHER_NAME, INT_RETURN, NO_PARAMETERS),
      THIRD_NAME, new MethodSignature(THIRD_NAME, INT_RETURN, LIST_PARAMETER),
      FORTH_NAME, new MethodSignature(FORTH_NAME, INT_RETURN, STRING_PARAMETER)
  );

  private ClassNameMapper mapper;

  @Parameter(0)
  public boolean compressRanges;

  @Rule
  public TemporaryFolder temp = ToolHelper.getTemporaryFolderForTest();

  @Before
  public void loadRangeInformation() throws IOException {
    mapper = ProguardMapReader.mapperFromFile(Paths.get(ROOT, EXAMPLE_MAP));
  }

  @Parameters(name = "compressLineNumers={0}")
  public static Object[] parameters() {
    return new Object[]{true, false};
  }

  @Test
  public void testStackTraces()
      throws IOException, ProguardRuleParserException, ExecutionException, CompilationException {

    // Temporary directory for R8 output.
    Path out = temp.getRoot().toPath();

    R8Command command =
        R8Command.builder()
            .addProgramFiles(Paths.get(ROOT, EXAMPLE_DEX))
            .setOutputPath(out)
            .setProguardMapFile(Paths.get(ROOT, EXAMPLE_MAP))
            .build();

    // Generate R8 processed version.
    AndroidApp result =
        ToolHelper.runR8(command, (options) -> options.skipDebugLineNumberOpt = !compressRanges);

    ClassNameMapper classNameMapper;
    try (InputStream is = result.getProguardMap()) {
      classNameMapper = ProguardMapReader.mapperFromInputStream(is);
    }
    if (compressRanges) {
      classNameMapper.forAllClassNamings(this::ensureRangesAreUniquePerClass);
    }

    if (!ToolHelper.artSupported()) {
      return;
    }
    // Run art on original.
    String originalOutput =
        ToolHelper.runArtNoVerificationErrors(ROOT + EXAMPLE_DEX, EXAMPLE_CLASS);
    // Run art on R8 processed version.
    String otherOutput =
        ToolHelper.runArtNoVerificationErrors(out + "/classes.dex", EXAMPLE_CLASS);
    // Check that exceptions are in same range
    assertStacktracesMatchRanges(originalOutput, otherOutput, classNameMapper);

    // Check that we have debug information in all the places required.
    DexInspector inspector = new DexInspector(out.resolve("classes.dex"));
    BiMap<String, String> obfuscationMap
        = classNameMapper.getObfuscatedToOriginalMapping().inverse();
    ClassSubject overloaded = inspector.clazz(obfuscationMap.get("throwing.Overloaded"));
    assertTrue(overloaded.isPresent());
    ensureDebugInfosExist(overloaded);
  }

  private void ensureDebugInfosExist(ClassSubject overloaded) {
    final Map<DexString, Boolean> hasDebugInfo = Maps.newIdentityHashMap();
    overloaded.forAllMethods(method -> {
          if (!method.isAbstract()) {
            DexCode code = method.getMethod().getCode().asDexCode();
            DexString name = method.getMethod().method.name;
            Boolean previous = hasDebugInfo.get(name);
            boolean current = code.getDebugInfo() != null;
            // If we have seen one before, it should be the same as now.
            assertTrue(previous == null || (previous == current));
            hasDebugInfo.put(name, current);
          }
        }
    );
  }

  private void ensureRangesAreUniquePerClass(ClassNaming naming) {
    final Map<String, Set<Integer>> rangeMap = new HashMap<>();
    naming.forAllMemberNaming(memberNaming -> {
      if (memberNaming.isMethodNaming()) {
        if (memberNaming.topLevelRange != MemberNaming.fakeZeroRange) {
          int startLine = memberNaming.topLevelRange.from;
          Set<Integer> used = rangeMap
              .computeIfAbsent(memberNaming.getRenamedName(), any -> new HashSet<>());
          assertFalse(used.contains(startLine));
          used.add(startLine);
        }
      }
    });
  }

  private String extractRangeIndex(String line, ClassNameMapper mapper) {
    int position = line.lastIndexOf(EXAMPLE_JAVA);
    assertNotSame("Malformed stackframe: " + line, -1, position);
    String numberPart = line.substring(position + EXAMPLE_JAVA.length() + 1, line.lastIndexOf(')'));
    int number = Integer.parseInt(numberPart);
    // Search the signature map for all signatures that actually match. We do this by first looking
    // up the renamed signature and then checking whether it is contained in the line. We prepend
    // the class name to make sure we do not match random characters in the line.
    for (Entry<String, Signature> entry : SIGNATURE_MAP.entrySet()) {
      MemberNaming naming = mapper.getClassNaming(EXAMPLE_CLASS)
          .lookupByOriginalSignature(entry.getValue());
      if (!line.contains(EXAMPLE_CLASS + "." + naming.getRenamedName())) {
        continue;
      }
      if (naming.topLevelRange.contains(number)) {
        return entry.getKey() + ":" + 0;
      }
      int rangeNo = 1;
      for (InlineInformation inlineInformation : naming.inlineInformation) {
        if (inlineInformation.inlinedRange.contains(number)) {
          return entry.getKey() + ":" + rangeNo;
        }
        rangeNo++;
      }
    }
    fail("Number not in any range " + number);
    return null;
  }

  private MemberNaming selectRanges(String line, ClassNameMapper mapper) {
    Signature signature;
    for (Entry<String, Signature> entry : SIGNATURE_MAP.entrySet()) {
      if (line.contains(entry.getKey())) {
        return mapper.getClassNaming(EXAMPLE_CLASS).lookup(entry.getValue());
      }
    }
    Assert.fail("unknown method in line " + line);
    return null;
  }

  private void assertStacktracesMatchRanges(String before, String after,
      ClassNameMapper newMapper) {
    String[] beforeLines = before.split("\n");
    String[] afterLines = after.split("\n");
    assertEquals("Output length differs", beforeLines.length,
        afterLines.length);
    for (int i = 0; i < beforeLines.length; i++) {
      if (!beforeLines[i].startsWith("FRAME:")) {
        continue;
      }
      String beforeLine = beforeLines[i];
      String expected = extractRangeIndex(beforeLine, mapper);
      String afterLine = afterLines[i];
      String generated = extractRangeIndex(afterLine, newMapper);
      assertEquals("Ranges match", expected, generated);
    }
  }
}
