// Copyright (c) 2018, 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.isPresent;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotEquals;
import static org.junit.Assert.assertTrue;

import com.android.tools.r8.CompilationFailedException;
import com.android.tools.r8.DataDirectoryResource;
import com.android.tools.r8.DataEntryResource;
import com.android.tools.r8.DataResourceConsumer;
import com.android.tools.r8.DataResourceProvider.Visitor;
import com.android.tools.r8.TestCompileResult;
import com.android.tools.r8.ToolHelper;
import com.android.tools.r8.origin.Origin;
import com.android.tools.r8.shaking.forceproguardcompatibility.ProguardCompatibilityTestBase;
import com.android.tools.r8.utils.ArchiveResourceProvider;
import com.android.tools.r8.utils.DataResourceConsumerForTesting;
import com.android.tools.r8.utils.FileUtils;
import com.android.tools.r8.utils.codeinspector.CodeInspector;
import com.google.common.collect.ImmutableList;
import com.google.common.io.ByteStreams;
import java.io.File;
import java.nio.charset.Charset;
import java.nio.file.Path;
import java.util.Arrays;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.Parameterized;

@RunWith(Parameterized.class)
public class AdaptResourceFileContentsTest extends ProguardCompatibilityTestBase {

  private static final List<Class<?>> CLASSES =
      ImmutableList.of(
          AdaptResourceFileContentsTestClass.class,
          AdaptResourceFileContentsTestClass.A.class,
          AdaptResourceFileContentsTestClass.B.class);

  private Backend backend;

  @Parameterized.Parameters(name = "Backend: {0}")
  public static Backend[] data() {
    return ToolHelper.getBackends();
  }

  public AdaptResourceFileContentsTest(Backend backend) {
    this.backend = backend;
  }

  private static final ImmutableList<String> originalAllChangedResource =
      ImmutableList.of(
          "com.android.tools.r8.naming.AdaptResourceFileContentsTestClass$A",
          "com.android.tools.r8.naming.AdaptResourceFileContentsTestClass$A<java.lang.String>",
          "com.android.tools.r8.naming.AdaptResourceFileContentsTestClass$A<"
              + "com.android.tools.r8.naming.AdaptResourceFileContentsTestClass$A>",
          "com.android.tools.r8.naming.AdaptResourceFileContentsTestClass$B",
          // Test property values are rewritten.
          "property=com.android.tools.r8.naming.AdaptResourceFileContentsTestClass$A",
          // Test XML content is rewritten.
          "<tag>com.android.tools.r8.naming.AdaptResourceFileContentsTestClass$A</tag>",
          "<tag attr=\"com.android.tools.r8.naming.AdaptResourceFileContentsTestClass$A\"></tag>",
          // Test single-quote literals are rewritten.
          "'com.android.tools.r8.naming.AdaptResourceFileContentsTestClass$A'");

  private static final ImmutableList<String> originalAllPresentResource =
      ImmutableList.of(
          "com.android.tools.r8.naming.AdaptResourceFileContentsTestClass",
          "com.android.tools.r8.naming.AdaptResourceFileContentsTestClass$A",
          "com.android.tools.r8.naming.AdaptResourceFileContentsTestClass$B");

  private static final ImmutableList<String> originalAllUnchangedResource =
      ImmutableList.of(
          "com.android.tools.r8.naming.AdaptResourceFileContentsTestClass",
          // Test there is no renaming for the method on A.
          "com.android.tools.r8.naming.AdaptResourceFileContentsTestClass$A.method",
          "com.android.tools.r8.naming.AdaptResourceFileContentsTestClass$A.method()",
          // Test there is no renaming for the methods on B.
          "com.android.tools.r8.naming.AdaptResourceFileContentsTestClass$B.method",
          "com.android.tools.r8.naming.AdaptResourceFileContentsTestClass$B.method()",
          // Test various prefixes.
          "42com.android.tools.r8.naming.AdaptResourceFileContentsTestClass$B",
          "WithIdentifierPrefixcom.android.tools.r8.naming.AdaptResourceFileContentsTestClass$B",
          "-com.android.tools.r8.naming.AdaptResourceFileContentsTestClass$B",
          "WithDashPrefix-com.android.tools.r8.naming.AdaptResourceFileContentsTestClass$B",
          "$com.android.tools.r8.naming.AdaptResourceFileContentsTestClass$B",
          "WithDollarPrefix$com.android.tools.r8.naming.AdaptResourceFileContentsTestClass$B",
          ".com.android.tools.r8.naming.AdaptResourceFileContentsTestClass$B",
          "WithDotPrefix.com.android.tools.r8.naming.AdaptResourceFileContentsTestClass$B",
          // Test various suffixes.
          "com.android.tools.r8.naming.AdaptResourceFileContentsTestClass$B42",
          "com.android.tools.r8.naming.AdaptResourceFileContentsTestClass$BWithIdentifierSuffix",
          "com.android.tools.r8.naming.AdaptResourceFileContentsTestClass$B-",
          "com.android.tools.r8.naming.AdaptResourceFileContentsTestClass$B-WithDashSuffix",
          "com.android.tools.r8.naming.AdaptResourceFileContentsTestClass$B$",
          "com.android.tools.r8.naming.AdaptResourceFileContentsTestClass$B$WithDollarSuffix",
          "com.android.tools.r8.naming.AdaptResourceFileContentsTestClass$B.",
          "com.android.tools.r8.naming.AdaptResourceFileContentsTestClass$B.WithDotSuffix");

  private static String getProguardConfig(
      boolean enableAdaptResourceFileContents, String adaptResourceFileContentsPathFilter) {
    String adaptResourceFileContentsRule;
    if (enableAdaptResourceFileContents) {
      adaptResourceFileContentsRule = "-adaptresourcefilecontents";
      if (adaptResourceFileContentsPathFilter != null) {
        adaptResourceFileContentsRule += " " + adaptResourceFileContentsPathFilter;
      }
    } else {
      adaptResourceFileContentsRule = "";
    }
    return String.join(
        System.lineSeparator(),
        adaptResourceFileContentsRule,
        "-keep class " + AdaptResourceFileContentsTestClass.class.getName() + " {",
        "  public static void main(...);",
        "}");
  }

  private static String getProguardConfigWithNeverInline(
      boolean enableAdaptResourceFileContents, String adaptResourceFileContentsPathFilter) {
    return String.join(
        System.lineSeparator(),
        getProguardConfig(enableAdaptResourceFileContents, adaptResourceFileContentsPathFilter),
        "-neverinline class com.android.tools.r8.naming.AdaptResourceFileContentsTestClass$B {",
        "  public void method();",
        "}",
        "-neverclassinline class com.android.tools.r8.naming.AdaptResourceFileContentsTestClass$B");
  }

  @Test
  public void testEnabled() throws Exception {
    String pgConf = getProguardConfigWithNeverInline(true, null);
    DataResourceConsumerForTesting dataResourceConsumer = new DataResourceConsumerForTesting();
    CodeInspector inspector = compileWithR8(pgConf, dataResourceConsumer).inspector();

    // Check that the data resources have changed as expected.
    checkAllAreChanged(
        dataResourceConsumer.get("resource-all-changed.md"), originalAllChangedResource);
    checkAllAreChanged(
        dataResourceConsumer.get("resource-all-changed.txt"), originalAllChangedResource);

    // Check that the new names are consistent with the actual application code.
    checkAllArePresent(dataResourceConsumer.get("resource-all-present.txt"), inspector);

    // Check that the data resources have not changed unexpectedly.
    checkAllAreUnchanged(
        dataResourceConsumer.get("resource-all-changed.class"), originalAllChangedResource);
    checkAllAreUnchanged(
        dataResourceConsumer.get("resource-all-changed.cLaSs"), originalAllChangedResource);
    checkAllAreUnchanged(
        dataResourceConsumer.get("resource-all-unchanged.txt"), originalAllUnchangedResource);
  }

  @Test
  public void testProguardBehavior() throws Exception {
    Path proguardedJar =
        File.createTempFile("proguarded", FileUtils.JAR_EXTENSION, temp.getRoot()).toPath();
    runProguard6Raw(
        proguardedJar,
        ImmutableList.of(
            AdaptResourceFileContentsTestClass.class,
            AdaptResourceFileContentsTestClass.A.class,
            AdaptResourceFileContentsTestClass.B.class),
        getProguardConfig(true, null),
        null,
        getDataResources()
            .stream()
            .filter(x -> !x.getName().toLowerCase().endsWith(FileUtils.CLASS_EXTENSION))
            .collect(Collectors.toList()));

    // Visit each of the resources in the jar and check that their contents are as expected.
    Set<String> filenames = new HashSet<>();
    ArchiveResourceProvider.fromArchive(proguardedJar, true)
        .accept(
            new Visitor() {
              @Override
              public void visit(DataDirectoryResource directory) {}

              @Override
              public void visit(DataEntryResource file) {
                try {
                  byte[] bytes = ByteStreams.toByteArray(file.getByteStream());
                  List<String> lines =
                      Arrays.asList(
                          new String(bytes, Charset.defaultCharset())
                              .split(System.lineSeparator()));
                  if (file.getName().endsWith("resource-all-changed.md")) {
                    checkAllAreChanged(lines, originalAllChangedResource);
                  } else if (file.getName().endsWith("resource-all-changed.txt")) {
                    checkAllAreChanged(lines, originalAllChangedResource);
                  } else if (file.getName().endsWith("resource-all-present.txt")) {
                    checkAllArePresent(lines, new CodeInspector(readJar(proguardedJar)));
                  } else if (file.getName().endsWith("resource-all-unchanged.txt")) {
                    checkAllAreUnchanged(lines, originalAllUnchangedResource);
                  }
                } catch (Exception e) {
                  throw new RuntimeException(e);
                }

                // Record that the jar contains a resource with this name.
                filenames.add(file.getName());
              }
            });

    // Check that the jar contains the four expected resources, and nothing else.
    assertEquals(4, filenames.size());
    assertTrue(filenames.stream().anyMatch(x -> x.endsWith("resource-all-changed.md")));
    assertTrue(filenames.stream().anyMatch(x -> x.endsWith("resource-all-changed.txt")));
    assertTrue(filenames.stream().anyMatch(x -> x.endsWith("resource-all-present.txt")));
    assertTrue(filenames.stream().anyMatch(x -> x.endsWith("resource-all-unchanged.txt")));
  }

  @Test
  public void testEnabledWithFilter() throws Exception {
    DataResourceConsumerForTesting dataResourceConsumer = new DataResourceConsumerForTesting();
    compileWithR8(getProguardConfigWithNeverInline(true, "*.md"), dataResourceConsumer);

    // Check that the file matching the filter has changed as expected.
    checkAllAreChanged(
        dataResourceConsumer.get("resource-all-changed.md"), originalAllChangedResource);

    // Check that all the other data resources are unchanged.
    checkAllAreUnchanged(
        dataResourceConsumer.get("resource-all-changed.class"), originalAllChangedResource);
    checkAllAreUnchanged(
        dataResourceConsumer.get("resource-all-changed.cLaSs"), originalAllChangedResource);
    checkAllAreUnchanged(
        dataResourceConsumer.get("resource-all-changed.txt"), originalAllChangedResource);
    checkAllAreUnchanged(
        dataResourceConsumer.get("resource-all-present.txt"), originalAllPresentResource);
    checkAllAreUnchanged(
        dataResourceConsumer.get("resource-all-unchanged.txt"), originalAllUnchangedResource);
  }

  @Test
  public void testDisabled() throws Exception {
    DataResourceConsumerForTesting dataResourceConsumer = new DataResourceConsumerForTesting();
    compileWithR8(getProguardConfigWithNeverInline(false, null), dataResourceConsumer);

    // Check that all data resources are unchanged.
    checkAllAreUnchanged(
        dataResourceConsumer.get("resource-all-changed.class"), originalAllChangedResource);
    checkAllAreUnchanged(
        dataResourceConsumer.get("resource-all-changed.cLaSs"), originalAllChangedResource);
    checkAllAreUnchanged(
        dataResourceConsumer.get("resource-all-changed.md"), originalAllChangedResource);
    checkAllAreUnchanged(
        dataResourceConsumer.get("resource-all-changed.txt"), originalAllChangedResource);
    checkAllAreUnchanged(
        dataResourceConsumer.get("resource-all-present.txt"), originalAllPresentResource);
    checkAllAreUnchanged(
        dataResourceConsumer.get("resource-all-unchanged.txt"), originalAllUnchangedResource);
  }

  private static void checkAllAreChanged(List<String> adaptedLines, List<String> originalLines) {
    assertEquals(adaptedLines.size(), originalLines.size());
    for (int i = 0; i < originalLines.size(); i++) {
      assertNotEquals(originalLines.get(i), adaptedLines.get(i));
    }
  }

  private static void checkAllArePresent(List<String> lines, CodeInspector inspector) {
    for (String line : lines) {
      assertThat(inspector.clazz(line), isPresent());
    }
  }

  private static void checkAllAreUnchanged(List<String> adaptedLines, List<String> originalLines) {
    assertEquals(adaptedLines.size(), originalLines.size());
    for (int i = 0; i < originalLines.size(); i++) {
      assertEquals(originalLines.get(i), adaptedLines.get(i));
    }
  }

  private TestCompileResult compileWithR8(
      String proguardConfig, DataResourceConsumer dataResourceConsumer)
      throws CompilationFailedException {
    return testForR8(backend)
        .addProgramClasses(CLASSES)
        .addDataResources(getDataResources())
        .enableProguardTestOptions()
        .addKeepRules(proguardConfig)
        .addOptionsModification(o -> o.dataResourceConsumer = dataResourceConsumer)
        .compile();
  }

  private List<DataEntryResource> getDataResources() {
    return ImmutableList.of(
        DataEntryResource.fromBytes(
            String.join(System.lineSeparator(), originalAllChangedResource).getBytes(),
            "resource-all-changed.class",
            Origin.unknown()),
        DataEntryResource.fromBytes(
            String.join(System.lineSeparator(), originalAllChangedResource).getBytes(),
            "resource-all-changed.cLaSs",
            Origin.unknown()),
        DataEntryResource.fromBytes(
            String.join(System.lineSeparator(), originalAllChangedResource).getBytes(),
            "resource-all-changed.md",
            Origin.unknown()),
        DataEntryResource.fromBytes(
            String.join(System.lineSeparator(), originalAllChangedResource).getBytes(),
            "resource-all-changed.txt",
            Origin.unknown()),
        DataEntryResource.fromBytes(
            String.join(System.lineSeparator(), originalAllPresentResource).getBytes(),
            "resource-all-present.txt",
            Origin.unknown()),
        DataEntryResource.fromBytes(
            String.join(System.lineSeparator(), originalAllUnchangedResource).getBytes(),
            "resource-all-unchanged.txt",
            Origin.unknown()));
  }
}

class AdaptResourceFileContentsTestClass {

  public static void main(String[] args) {
    B obj = new B();
    obj.method();
  }

  static class A {

    public void method() {
      System.out.println("In A.method()");
    }
  }

  static class B extends A {

    public void method() {
      System.out.println("In B.method()");
      super.method();
    }
  }
}
