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

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertSame;

import com.android.tools.r8.CompilationFailedException;
import com.android.tools.r8.DiagnosticsChecker;
import com.android.tools.r8.TestBase;
import com.android.tools.r8.TestParameters;
import com.android.tools.r8.TestParametersCollection;
import com.android.tools.r8.ToolHelper;
import com.android.tools.r8.origin.Origin;
import com.android.tools.r8.tracereferences.TraceReferencesCommandParser.OutputFormat;
import com.android.tools.r8.utils.AndroidApiLevel;
import com.android.tools.r8.utils.DescriptorUtils;
import com.android.tools.r8.utils.FileUtils;
import com.android.tools.r8.utils.StringUtils;
import com.android.tools.r8.utils.ZipUtils;
import com.google.common.collect.ImmutableList;
import java.io.BufferedOutputStream;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.List;
import java.util.stream.Collectors;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;
import kotlin.text.Charsets;
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 TraceReferencesCommandTest extends TestBase {
  @Parameters(name = "{0}")
  public static TestParametersCollection data() {
    return getTestParameters().withNoneRuntime().build();
  }

  public TraceReferencesCommandTest(TestParameters parameters) {}

  @Test
  public void emptyBuilder() throws Throwable {
    verifyEmptyCommand(TraceReferencesCommand.builder().build());
  }

  private void verifyEmptyCommand(TraceReferencesCommand command) {
    assertEquals(0, command.getLibrary().size());
    assertEquals(0, command.getTarget().size());
    assertEquals(0, command.getSource().size());
    assertEquals(TraceReferencesCommandParser.OutputFormat.PRINTUSAGE, command.getOutputFormat());
    assertNull(command.getOutput());
  }

  @Test(expected = CompilationFailedException.class)
  public void emptyRun() throws Throwable {
    DiagnosticsChecker.checkErrorsContains(
        "No library specified",
        handler -> {
          TraceReferences.run(TraceReferencesCommand.builder(handler).build());
        });
  }

  @Test(expected = CompilationFailedException.class)
  public void emptyRunCommandLine() throws Throwable {
    DiagnosticsChecker.checkErrorsContains(
        "No library specified",
        handler -> {
          TraceReferences.run(
              TraceReferencesCommand.parse(new String[] {""}, Origin.unknown(), handler).build());
        });
  }

  @Test(expected = CompilationFailedException.class)
  public void onlyLibrarySpecified() throws Throwable {
    DiagnosticsChecker.checkErrorsContains(
        "No target specified",
        handler -> {
          TraceReferences.run(
              TraceReferencesCommand.builder(handler)
                  .addLibraryFiles(ToolHelper.getAndroidJar(AndroidApiLevel.P))
                  .build());
        });
  }

  @Test(expected = CompilationFailedException.class)
  public void onlyLibrarySpecifiedCommandLine() throws Throwable {
    DiagnosticsChecker.checkErrorsContains(
        "No target specified",
        handler -> {
          TraceReferences.run(
              TraceReferencesCommand.parse(
                      new String[] {
                        "--lib", ToolHelper.getAndroidJar(AndroidApiLevel.P).toString()
                      },
                      Origin.unknown(),
                      handler)
                  .build());
        });
  }

  private String formatName(OutputFormat format) {
    if (format == TraceReferencesCommandParser.OutputFormat.PRINTUSAGE) {
      return "printuses";
    }
    if (format == TraceReferencesCommandParser.OutputFormat.KEEP_RULES) {
      return "keep";
    }
    assertSame(format, TraceReferencesCommandParser.OutputFormat.KEEP_RULES_WITH_ALLOWOBFUSCATION);
    return "keepallowobfuscation";
  }

  public void runAndCheckOutput(
      Path targetJar, Path sourceJar, OutputFormat format, String expected) throws Throwable {
    Path dir = temp.newFolder().toPath();
    Path output = dir.resolve("output.txt");
    TraceReferences.run(
        TraceReferencesCommand.builder()
            .addLibraryFiles(ToolHelper.getAndroidJar(AndroidApiLevel.P))
            .addTargetFiles(targetJar)
            .addSourceFiles(sourceJar)
            .setOutputPath(output)
            .setOutputFormat(format)
            .build());
    assertEquals(expected, FileUtils.readTextFile(output, Charsets.UTF_8));

    TraceReferences.run(
        TraceReferencesCommand.parse(
                new String[] {
                  "--lib", ToolHelper.getAndroidJar(AndroidApiLevel.P).toString(),
                  "--target", targetJar.toString(),
                  "--source", sourceJar.toString(),
                  "--output", output.toString(),
                  "--format", formatName(format)
                },
                Origin.unknown())
            .build());
    assertEquals(expected, FileUtils.readTextFile(output, Charsets.UTF_8));
  }

  public void runAndCheckOutput(
      List<Class<?>> targetClasses,
      List<Class<?>> sourceClasses,
      OutputFormat format,
      String expected)
      throws Throwable {
    Path dir = temp.newFolder().toPath();
    Path targetJar = dir.resolve("target.jar");
    Path sourceJar = dir.resolve("source.jar");
    ZipUtils.zip(
        targetJar,
        ToolHelper.getClassPathForTests(),
        targetClasses.stream()
            .map(ToolHelper::getClassFileForTestClass)
            .collect(Collectors.toList()));
    ZipUtils.zip(
        sourceJar,
        ToolHelper.getClassPathForTests(),
        sourceClasses.stream()
            .map(ToolHelper::getClassFileForTestClass)
            .collect(Collectors.toList()));
    runAndCheckOutput(targetJar, sourceJar, format, expected);
  }

  @Test
  public void test_printUses() throws Throwable {
    runAndCheckOutput(
        ImmutableList.of(Target.class),
        ImmutableList.of(Source.class),
        TraceReferencesCommandParser.OutputFormat.PRINTUSAGE,
        StringUtils.lines(
            ImmutableList.of(
                "com.android.tools.r8.tracereferences.TraceReferencesCommandTest$Target",
                "com.android.tools.r8.tracereferences.TraceReferencesCommandTest$Target: void"
                    + " target(int)",
                "com.android.tools.r8.tracereferences.TraceReferencesCommandTest$Target: int"
                    + " field")));
  }

  @Test
  public void test_keepRules() throws Throwable {
    runAndCheckOutput(
        ImmutableList.of(Target.class),
        ImmutableList.of(Source.class),
        TraceReferencesCommandParser.OutputFormat.KEEP_RULES,
        StringUtils.lines(
            ImmutableList.of(
                "-keep class com.android.tools.r8.tracereferences.TraceReferencesCommandTest$Target"
                    + " {",
                "  public static void target(int);",
                "  int field;",
                "}",
                "-keeppackagenames com.android.tools.r8.tracereferences")));
  }

  @Test
  public void test_keepRulesAllowObfuscation() throws Throwable {
    runAndCheckOutput(
        ImmutableList.of(Target.class),
        ImmutableList.of(Source.class),
        TraceReferencesCommandParser.OutputFormat.KEEP_RULES_WITH_ALLOWOBFUSCATION,
        StringUtils.lines(
            ImmutableList.of(
                "-keep,allowobfuscation class"
                    + " com.android.tools.r8.tracereferences.TraceReferencesCommandTest$Target {",
                "  public static void target(int);",
                "  int field;",
                "}",
                "-keeppackagenames com.android.tools.r8.tracereferences")));
  }

  @Test
  public void testNoReferences_printUses() throws Throwable {
    runAndCheckOutput(
        ImmutableList.of(OtherTarget.class),
        ImmutableList.of(Source.class),
        TraceReferencesCommandParser.OutputFormat.PRINTUSAGE,
        StringUtils.lines(ImmutableList.of()));
  }

  @Test
  public void testMissingReference_keepRules() throws Throwable {
    runAndCheckOutput(
        ImmutableList.of(OtherTarget.class),
        ImmutableList.of(Source.class),
        TraceReferencesCommandParser.OutputFormat.KEEP_RULES,
        StringUtils.lines(ImmutableList.of()));
  }

  @Test
  public void testNoReferences_keepRulesAllowObfuscation() throws Throwable {
    runAndCheckOutput(
        ImmutableList.of(OtherTarget.class),
        ImmutableList.of(Source.class),
        TraceReferencesCommandParser.OutputFormat.KEEP_RULES_WITH_ALLOWOBFUSCATION,
        StringUtils.lines(ImmutableList.of()));
  }

  public static void zip(Path zipFile, String path, byte[] data) throws IOException {
    try (ZipOutputStream stream =
        new ZipOutputStream(new BufferedOutputStream(Files.newOutputStream(zipFile)))) {
      ZipEntry zipEntry = new ZipEntry(path);
      stream.putNextEntry(zipEntry);
      stream.write(data);
      stream.closeEntry();
    }
  }

  @Test
  public void testMissingDefinition_printUses() throws Throwable {
    Path dir = temp.newFolder().toPath();
    Path targetJar = dir.resolve("target.jar");
    Path sourceJar = dir.resolve("source.jar");
    zip(targetJar, DescriptorUtils.getPathFromJavaType(Target.class), getClassWithTargetRemoved());
    ZipUtils.zip(
        sourceJar,
        ToolHelper.getClassPathForTests(),
        ToolHelper.getClassFileForTestClass(Source.class));
    runAndCheckOutput(
        targetJar,
        sourceJar,
        TraceReferencesCommandParser.OutputFormat.PRINTUSAGE,
        StringUtils.lines(
            ImmutableList.of(
                "com.android.tools.r8.tracereferences.TraceReferencesCommandTest$Target",
                "# Error: Could not find definition for method void"
                    + " com.android.tools.r8.tracereferences.TraceReferencesCommandTest$Target"
                    + ".target(int)",
                "# Error: Could not find definition for field int"
                    + " com.android.tools.r8.tracereferences.TraceReferencesCommandTest$Target"
                    + ".field")));
  }

  @Test
  public void testMissingDefinition_keepRules() throws Throwable {
    Path dir = temp.newFolder().toPath();
    Path targetJar = dir.resolve("target.jar");
    Path sourceJar = dir.resolve("source.jar");
    zip(targetJar, DescriptorUtils.getPathFromJavaType(Target.class), getClassWithTargetRemoved());
    ZipUtils.zip(
        sourceJar,
        ToolHelper.getClassPathForTests(),
        ToolHelper.getClassFileForTestClass(Source.class));
    runAndCheckOutput(
        targetJar,
        sourceJar,
        TraceReferencesCommandParser.OutputFormat.KEEP_RULES,
        StringUtils.lines(
            ImmutableList.of(
                "-keep class com.android.tools.r8.tracereferences.TraceReferencesCommandTest$Target"
                    + " {",
                "# Error: Could not find definition for method void"
                    + " com.android.tools.r8.tracereferences.TraceReferencesCommandTest$Target"
                    + ".target(int)",
                "# Error: Could not find definition for field int"
                    + " com.android.tools.r8.tracereferences.TraceReferencesCommandTest$Target"
                    + ".field",
                "}",
                "-keeppackagenames com.android.tools.r8.tracereferences")));
  }

  @Test
  public void testMissingDefinition_keepRulesAllowObfuscation() throws Throwable {
    Path dir = temp.newFolder().toPath();
    Path targetJar = dir.resolve("target.jar");
    Path sourceJar = dir.resolve("source.jar");
    zip(targetJar, DescriptorUtils.getPathFromJavaType(Target.class), getClassWithTargetRemoved());
    ZipUtils.zip(
        sourceJar,
        ToolHelper.getClassPathForTests(),
        ToolHelper.getClassFileForTestClass(Source.class));
    runAndCheckOutput(
        targetJar,
        sourceJar,
        TraceReferencesCommandParser.OutputFormat.KEEP_RULES_WITH_ALLOWOBFUSCATION,
        StringUtils.lines(
            ImmutableList.of(
                "-keep,allowobfuscation class"
                    + " com.android.tools.r8.tracereferences.TraceReferencesCommandTest$Target {",
                "# Error: Could not find definition for method void"
                    + " com.android.tools.r8.tracereferences.TraceReferencesCommandTest$Target.target(int)",
                "# Error: Could not find definition for field int"
                    + " com.android.tools.r8.tracereferences.TraceReferencesCommandTest$Target.field",
                "}",
                "-keeppackagenames com.android.tools.r8.tracereferences")));
  }

  private byte[] getClassWithTargetRemoved() throws IOException {
    return transformer(Target.class)
        .removeMethods((access, name, descriptor, signature, exceptions) -> name.equals("target"))
        .removeFields((access, name, descriptor, signature, value) -> name.equals("field"))
        .transform();
  }

  static class Target {
    public static int field;

    public static void target(int i) {}
  }

  static class OtherTarget {
    public static void target() {}
  }

  static class Source {
    public static void source() {
      Target.target(Target.field);
    }
  }
}
