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

import static com.android.tools.r8.DiagnosticsMatcher.diagnosticMessage;
import static org.hamcrest.CoreMatchers.containsString;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotEquals;
import static org.junit.Assert.assertTrue;

import com.android.tools.r8.TestBase;
import com.android.tools.r8.TestDiagnosticMessagesImpl;
import com.android.tools.r8.ToolHelper;
import com.android.tools.r8.naming.ProguardMapReader.ParseException;
import com.android.tools.r8.position.Position;
import com.android.tools.r8.utils.StringUtils;
import com.google.common.collect.ImmutableList;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.List;
import org.junit.Assert;
import org.junit.Test;

public class ProguardMapReaderTest extends TestBase {

  private static final String ROOT = ToolHelper.EXAMPLES_BUILD_DIR;
  private static final String EXAMPLE_MAP = "throwing/throwing.map";
  private static final String EXAMPLE_MAP_WITH_PACKAGE_INFO =
      "dagger.android.package-info -> dagger.android.package-info:\n";

  @Test
  public void parseThrowingMap() throws IOException {
    ClassNameMapper.mapperFromFile(Paths.get(ROOT, EXAMPLE_MAP));
  }

  @Test
  public void parseQuestionMarkMethod() throws IOException {
    // Regression test for b/120856784
    String mapping =
        "com.c.c.b -> com.c.c.b:\n" +
            "    1287:1287:int ?(int,int) -> ?";
    ClassNameMapper.mapperFromString(mapping);

    // From some other proguard generated map
    mapping = "com.moat.analytics.mobile.cha.b -> com.moat.analytics.mobile.cha.b:\n"
        + "    com.moat.analytics.mobile.cha.MoatAdEventType[] ? -> ?\n"
        + "    java.util.HashMap ? -> ?\n"
        + "    java.util.HashSet ?? -> ??\n";
    ClassNameMapper.mapperFromString(mapping);
  }


  @Test
  public void roundTripTest() throws IOException {
    ClassNameMapper firstMapper = ClassNameMapper.mapperFromFile(Paths.get(ROOT, EXAMPLE_MAP));
    ClassNameMapper secondMapper = ClassNameMapper.mapperFromString(firstMapper.toString());
    Assert.assertEquals(firstMapper, secondMapper);
  }

  @Test
  public void roundTripTestWithLeadingBOM() throws IOException {
    ClassNameMapper firstMapper = ClassNameMapper.mapperFromFile(Paths.get(ROOT, EXAMPLE_MAP));
    assertTrue(firstMapper.toString().charAt(0) != StringUtils.BOM);
    ClassNameMapper secondMapper =
        ClassNameMapper.mapperFromString(StringUtils.BOM + firstMapper.toString());
    assertTrue(secondMapper.toString().charAt(0) != StringUtils.BOM);
    Assert.assertEquals(firstMapper, secondMapper);
    byte[] bytes = Files.readAllBytes(Paths.get(ROOT, EXAMPLE_MAP));
    assertNotEquals(0xef, Byte.toUnsignedLong(bytes[0]));
    Path mapFileWithBOM = writeTextToTempFile(StringUtils.BOM + firstMapper.toString());
    bytes = Files.readAllBytes(mapFileWithBOM);
    assertEquals(0xef, Byte.toUnsignedLong(bytes[0]));
    assertEquals(0xbb, Byte.toUnsignedLong(bytes[1]));
    assertEquals(0xbf, Byte.toUnsignedLong(bytes[2]));
    ClassNameMapper thirdMapper = ClassNameMapper.mapperFromFile(mapFileWithBOM);
    assertTrue(thirdMapper.toString().charAt(0) != StringUtils.BOM);
    Assert.assertEquals(firstMapper, thirdMapper);
  }

  @Test
  public void roundTripTestWithMultipleBOMsAndWhitespace() throws IOException {
    List<String> ws =
        ImmutableList.of(
            "",
            " ",
            "  ",
            "\t ",
            " \t",
            "" + StringUtils.BOM,
            StringUtils.BOM + " " + StringUtils.BOM);
    for (String whitespace : ws) {
      ClassNameMapper firstMapper = ClassNameMapper.mapperFromFile(Paths.get(ROOT, EXAMPLE_MAP));
      assertTrue(firstMapper.toString().charAt(0) != StringUtils.BOM);
      StringBuilder buildWithWhitespace = new StringBuilder();
      char prevChar = '\0';
      for (char c : firstMapper.toString().toCharArray()) {
        if (c == ':' || c == ' ') {
          buildWithWhitespace.append(whitespace);
          buildWithWhitespace.append(c);
          buildWithWhitespace.append(whitespace);
        } else if (c == '-' || c == '(') {
          buildWithWhitespace.append(whitespace);
          buildWithWhitespace.append(c);
        } else if (c == '>' && prevChar == '-') {
          buildWithWhitespace.append(c);
          buildWithWhitespace.append(whitespace);
        } else {
          buildWithWhitespace.append(c);
        }
        prevChar = c;
      }
      ClassNameMapper secondMapper =
          ClassNameMapper.mapperFromString(buildWithWhitespace.toString());
      assertFalse(firstMapper.toString().contains("" + StringUtils.BOM));
      Assert.assertEquals(firstMapper, secondMapper);
      byte[] bytes = Files.readAllBytes(Paths.get(ROOT, EXAMPLE_MAP));
      assertNotEquals(0xef, Byte.toUnsignedLong(bytes[0]));
      Path mapFileWithBOM = writeTextToTempFile(StringUtils.BOM + firstMapper.toString());
      ClassNameMapper thirdMapper = ClassNameMapper.mapperFromFile(mapFileWithBOM);
      assertTrue(thirdMapper.toString().charAt(0) != StringUtils.BOM);
      Assert.assertEquals(firstMapper, thirdMapper);
    }
  }

  @Test
  public void parseIdentifierArrowAmbiguity1() throws IOException {
    ClassNameMapper mapper = ClassNameMapper.mapperFromString("a->b:");
    ClassNameMapper.Builder builder = ClassNameMapper.builder();
    builder.classNamingBuilder("b", "a", Position.UNKNOWN);
    Assert.assertEquals(builder.build(), mapper);
  }

  @Test
  public void parseIdentifierArrowAmbiguity2() throws IOException {
    ClassNameMapper mapper = ClassNameMapper.mapperFromString("-->b:");
    ClassNameMapper.Builder builder = ClassNameMapper.builder();
    builder.classNamingBuilder("b", "-", Position.UNKNOWN);
    Assert.assertEquals(builder.build(), mapper);
  }

  @Test
  public void parseMapWithPackageInfo() throws IOException {
    ClassNameMapper mapper = ClassNameMapper.mapperFromString(EXAMPLE_MAP_WITH_PACKAGE_INFO);
    assertEquals(1, mapper.getObfuscatedToOriginalMapping().original.size());
  }

  @Test
  public void testSingleCases() throws IOException {
    List<String> ss =
        ImmutableList.of(
            /* */ "a.b.C -> d.e.F:\n" //
                + "    void a() -> b\n",
            /* */ "a.b.C -> d.e.F:\n" //
                + "    1:1:void a() -> b\n",
            /* */ "a.b.C -> d.e.F:\n" //
                + "    1:2:void a() -> b\n",
            /* */ "a.b.C -> d.e.F:\n" //
                + "    1:1:void a():2:2 -> b\n",
            /* */ "a.b.C -> d.e.F:\n" //
                + "    1:2:void a():11:12 -> b\n",
            /* */ "a.b.C -> d.e.F:\n" //
                + "    1:1:void a():11:11 -> b\n" //
                + "    1:1:void c():21 -> b\n",
            /* */ "a.b.C -> d.e.F:\n" //
                + "    1:2:void a():11:12 -> b\n"
                + "    1:2:void c():21 -> b\n",
            /* */ "a.b.C -> d.e.F:\n" //
                + "    1:1:void a(int):11:11 -> b\n" //
                + "    1:1:void c():21 -> b\n",
            /* */ "a.b.C -> d.e.F:\n" //
                + "    1:1:void g.a(int):11:11 -> b\n" //
                + "    1:1:void c():21 -> b\n",
            /* */ "a.b.C -> d.e.F:\n" //
                + "    1:1:void a(int):11:11 -> b\n" //
                + "    2:2:void c():21:21 -> b\n",
            /* */ "a.b.C -> d.e.F:\n" //
                + "    1:1:void a():11:11 -> b\n" //
                + "    1:1:void c():21:21 -> d\n",
            /* */ "a.b.C -> d.e.F:\n" //
                + "    2:2:void f1():11:11 -> b\n" //
                + "    2:2:void f2():21 -> b\n" //
                + "    2:2:void f3():21 -> b\n" //
                + "    2:2:void f4():22 -> b\n" //
                + "    2:2:void f5():21 -> b\n" //
                + "    3:3:void f6():12:34 -> c\n",
            /* */ "a.b.C -> d.e.F:\n" //
                + "    2:2:void f1():11:11 -> b\n" //
                + "    2:2:void f2():21 -> b\n" //
                + "    2:2:void f3() -> b\n" //
                + "    2:2:void f5():21 -> b\n" //
                + "    3:3:void f6() -> c\n");

    for (String s : ss) {
      ClassNameMapper cnm = ClassNameMapper.mapperFromString(s);
      String result = cnm.toString();
      Assert.assertEquals(s, result);
    }
  }

  @Test()
  public void testCommentLineBeforeAnyClassMappings() throws IOException {
    String mapping =
        StringUtils.lines(
            "# {'id':'some.namespace.here','unknownField':'Hi There'}", "foo.bar.baz -> a:");
    ClassNameMapper.mapperFromString(mapping);
  }

  // TODO(b/179666867): Should not fail.
  @Test(expected = ParseException.class)
  public void testCommentLineOnClassMapping() throws IOException {
    ClassNameMapper.mapperFromString("foo.bar.qux -> b: #  Some comment here");
  }

  // TODO(b/179666867): Should not fail.
  @Test(expected = ParseException.class)
  public void testJsonCommentLineOnClassMapping() throws IOException {
    ClassNameMapper.mapperFromString(
        "foo.bar.baz -> a: # {'id':'same.class.namespace.here','frame':'foo'}");
  }

  // TODO(b/179666867): Should not fail.
  @Test(expected = ParseException.class)
  public void testCommentLinesOnMethodMappingFiles() throws IOException {
    ClassNameMapper.mapperFromString(
        StringUtils.lines(
            "foo.bar.qux -> b:",
            "    1:10:void error(com.android.tools.r8.Diagnostic) -> error # Some comment here"));
  }

  // TODO(b/179666867): Should not fail.
  @Test(expected = ParseException.class)
  public void testJsonCommentLinesOnMethodMappingFiles() throws IOException {
    ClassNameMapper.mapperFromString(
        StringUtils.lines(
            "foo.bar.qux -> b:",
            "    1:10:void error(com.android.tools.r8.Diagnostic) -> error #"
                + " {'id':'same.frame.namespace.here','frame':'bar'}"));
  }

  @Test()
  public void testUnknownNamespaceComments() throws IOException {
    String mappingWithComments =
        StringUtils.lines(
            "foo.bar.baz -> a:",
            "# {'id':'some.other.namespace.here','fileName':'Class.kt'}",
            "    1:10:void error(com.android.tools.r8.Diagnostic) -> error",
            "# {'id':'some.line.namespace.here','fileName':'Class.kt'}",
            "foo.bar.qux -> b:",
            "# {'id':'some.final.namespace.thing','foo':'Hello World'}");
    TestDiagnosticMessagesImpl testDiagnosticMessages = new TestDiagnosticMessagesImpl();
    ClassNameMapper.mapperFromString(mappingWithComments, testDiagnosticMessages);
    testDiagnosticMessages.assertOnlyInfos();
    testDiagnosticMessages.assertInfosMatch(
        ImmutableList.of(
            diagnosticMessage(
                containsString("Could not find a handler for some.other.namespace.here")),
            diagnosticMessage(
                containsString("Could not find a handler for some.line.namespace.here")),
            diagnosticMessage(
                containsString("Could not find a handler for some.final.namespace.thing"))));
  }
}
