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

import static org.junit.Assume.assumeFalse;

import com.android.tools.r8.R8FullTestBuilder;
import com.android.tools.r8.R8TestCompileResult;
import com.android.tools.r8.TestBase;
import com.android.tools.r8.TestCompilerBuilder.DiagnosticsConsumer;
import com.android.tools.r8.TestParameters;
import com.android.tools.r8.TestRuntime.CfRuntime;
import com.android.tools.r8.ThrowableConsumer;
import com.android.tools.r8.ToolHelper;
import com.android.tools.r8.ToolHelper.ArtCommandBuilder;
import com.android.tools.r8.ToolHelper.DexVm;
import com.android.tools.r8.ToolHelper.ProcessResult;
import com.android.tools.r8.naming.MemberNaming.FieldSignature;
import com.android.tools.r8.naming.MemberNaming.MethodSignature;
import com.android.tools.r8.utils.InternalOptions;
import com.android.tools.r8.utils.ListUtils;
import com.android.tools.r8.utils.ThrowingConsumer;
import com.android.tools.r8.utils.codeinspector.ClassSubject;
import com.android.tools.r8.utils.codeinspector.CodeInspector;
import com.android.tools.r8.utils.codeinspector.FoundFieldSubject;
import com.android.tools.r8.utils.codeinspector.FoundMethodSubject;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.function.BiConsumer;
import java.util.function.Consumer;
import org.junit.Assert;
import org.junit.runners.Parameterized.Parameters;

/**
 * Base class of individual tree shaking tests in com.android.tools.r8.shaking.examples.
 * <p>
 * To add a new test, add Java files and keep rules to a new subdirectory of src/test/examples and
 * add a new subclass of TreeShakingTest. To run with multiple minification modes and
 * frontend/backend combinations, copy the Parameterized setup from one of the existing subclasses,
 * e.g. {@link com.android.tools.r8.shaking.examples.TreeShaking1Test}. Then create a test method
 * that calls {@link TreeShakingTest::runTest}, passing in the path to your keep rule file and
 * lambdas to determine if the right bits of the application are kept or discarded.
 */
public abstract class TreeShakingTest extends TestBase {

  @Parameters(name = "mode:{0}-{1} minify:{2}")
  public static List<Object[]> defaultTreeShakingParameters() {
    return data(Frontend.values(), MinifyMode.values());
  }

  public static List<Object[]> data(MinifyMode[] minifyModes) {
    return data(Frontend.values(), minifyModes);
  }

  public static List<Object[]> data(Frontend[] frontends, MinifyMode[] minifyModes) {
    return buildParameters(
        frontends, getTestParameters().withAllRuntimesAndApiLevels().build(), minifyModes);
  }

  protected abstract String getName();

  protected abstract String getMainClass();

  protected enum Frontend {
    DEX, JAR
  }

  private final Frontend frontend;
  private final TestParameters parameters;
  private final MinifyMode minify;

  public Frontend getFrontend() {
    return frontend;
  }

  public TestParameters getParameters() {
    return parameters;
  }

  public MinifyMode getMinify() {
    return minify;
  }

  public TreeShakingTest(Frontend frontend, TestParameters parameters, MinifyMode minify) {
    this.frontend = frontend;
    this.parameters = parameters;
    this.minify = minify;
  }

  protected static void checkSameStructure(CodeInspector ref, CodeInspector inspector) {
    ref.forAllClasses(
        refClazz ->
            checkSameStructure(
                refClazz, inspector.clazz(refClazz.getDexProgramClass().toSourceString())));
  }

  private static void checkSameStructure(ClassSubject refClazz, ClassSubject clazz) {
    Assert.assertTrue(clazz.isPresent());
    refClazz.forAllFields(refField -> checkSameStructure(refField, clazz));
    refClazz.forAllMethods(refMethod -> checkSameStructure(refMethod, clazz));
  }

  private static void checkSameStructure(FoundMethodSubject refMethod, ClassSubject clazz) {
    MethodSignature signature = refMethod.getOriginalSignature();
    // Don't check for existence of class initializers, as the code optimization can remove them.
    if (!refMethod.isClassInitializer()) {
      Assert.assertTrue(
          "Missing Method: "
              + clazz.getDexProgramClass().toSourceString()
              + "."
              + signature.toString(),
          clazz.method(signature).isPresent());
    }
  }

  private static void checkSameStructure(FoundFieldSubject refField, ClassSubject clazz) {
    FieldSignature signature = refField.getOriginalSignature();
    Assert.assertTrue(
        "Missing field: " + signature.type + " " + clazz.getOriginalDescriptor()
            + "." + signature.name,
        clazz.field(signature.type, signature.name).isPresent());
  }

  protected void runTest(
      ThrowingConsumer<CodeInspector, Exception> inspection,
      BiConsumer<String, String> outputComparator,
      BiConsumer<CodeInspector, CodeInspector> dexComparator,
      List<String> keepRulesFiles)
      throws Exception {
    runTest(inspection, outputComparator, dexComparator, keepRulesFiles, null, null, null);
  }

  protected void runTest(
      ThrowingConsumer<CodeInspector, Exception> inspection,
      BiConsumer<String, String> outputComparator,
      BiConsumer<CodeInspector, CodeInspector> dexComparator,
      List<String> keepRulesFiles,
      Consumer<InternalOptions> optionsConsumer)
      throws Exception {
    runTest(
        inspection, outputComparator, dexComparator, keepRulesFiles, optionsConsumer, null, null);
  }

  protected void runTest(
      ThrowingConsumer<CodeInspector, Exception> inspection,
      BiConsumer<String, String> outputComparator,
      BiConsumer<CodeInspector, CodeInspector> dexComparator,
      List<String> keepRulesFiles,
      Consumer<InternalOptions> optionsConsumer,
      ThrowableConsumer<R8FullTestBuilder> testBuilderConsumer)
      throws Exception {
    runTest(
        inspection,
        outputComparator,
        dexComparator,
        keepRulesFiles,
        optionsConsumer,
        testBuilderConsumer,
        null);
  }

  protected void runTest(
      ThrowingConsumer<CodeInspector, Exception> inspection,
      BiConsumer<String, String> outputComparator,
      BiConsumer<CodeInspector, CodeInspector> dexComparator,
      List<String> keepRulesFiles,
      Consumer<InternalOptions> optionsConsumer,
      ThrowableConsumer<R8FullTestBuilder> testBuilderConsumer,
      DiagnosticsConsumer diagnosticsConsumer)
      throws Exception {
    assumeFalse(frontend == Frontend.DEX && parameters.isCfRuntime());
    String originalDex = ToolHelper.TESTS_BUILD_DIR + getName() + "/classes.dex";
    String programFile =
        frontend == Frontend.DEX ? originalDex : ToolHelper.TESTS_BUILD_DIR + getName() + ".jar";
    R8FullTestBuilder testBuilder =
        testForR8(parameters.getBackend())
            // Go through app builder to add dex files.
            .apply(
                b ->
                    ToolHelper.getAppBuilder(b.getBuilder())
                        .addProgramFiles(Paths.get(programFile)))
            .enableProguardTestOptions()
            .applyIf(minify.isAggressive(), b -> b.addKeepRules("-overloadaggressively"))
            .minification(minify.isMinify())
            .setMinApi(parameters.getApiLevel())
            .addKeepRuleFiles(ListUtils.map(keepRulesFiles, Paths::get))
            .addLibraryFiles(Paths.get(ToolHelper.EXAMPLES_BUILD_DIR + "shakinglib.jar"))
            .addDefaultRuntimeLibrary(parameters)
            .addOptionsModification(
                options -> {
                  options.enableInlining = programFile.contains("inlining");
                  if (optionsConsumer != null) {
                    optionsConsumer.accept(options);
                  }
                })
            .allowStdoutMessages()
            .applyIf(testBuilderConsumer != null, testBuilderConsumer);
    R8TestCompileResult compileResult =
        diagnosticsConsumer == null
            ? testBuilder.compile()
            : testBuilder.compileWithExpectedDiagnostics(diagnosticsConsumer);
    Path outJar = compileResult.writeToZip();
    if (parameters.isCfRuntime()) {
      Path shakinglib = Paths.get(ToolHelper.EXAMPLES_BUILD_DIR, "shakinglib.jar");
      CfRuntime cfRuntime = parameters.getRuntime().asCf();
      ProcessResult resultInput =
          ToolHelper.runJava(
              cfRuntime, Arrays.asList(Paths.get(programFile), shakinglib), getMainClass());
      Assert.assertEquals(0, resultInput.exitCode);
      ProcessResult resultOutput =
          ToolHelper.runJava(cfRuntime, Arrays.asList(outJar, shakinglib), getMainClass());
      if (outputComparator != null) {
        outputComparator.accept(resultInput.stdout, resultOutput.stdout);
      } else {
        Assert.assertEquals(resultInput.toString(), resultOutput.toString());
      }
      if (inspection != null) {
        compileResult.inspect(inspection);
      }
      return;
    }
    if (!ToolHelper.artSupported() && !ToolHelper.compareAgaintsGoldenFiles()) {
      return;
    }
    Consumer<ArtCommandBuilder> extraArtArgs = builder -> {
      builder.appendClasspath(ToolHelper.EXAMPLES_BUILD_DIR + "shakinglib/classes.dex");
    };
    DexVm dexVm = parameters.getRuntime().asDex().getVm();
    if (Files.exists(Paths.get(originalDex))) {
      if (outputComparator != null) {
        String output1 =
            ToolHelper.runArtNoVerificationErrors(
                Collections.singletonList(originalDex), getMainClass(), extraArtArgs, dexVm);
        String output2 =
            ToolHelper.runArtNoVerificationErrors(
                Collections.singletonList(outJar.toString()), getMainClass(), extraArtArgs, dexVm);
        outputComparator.accept(output1, output2);
      } else {
        ToolHelper.checkArtOutputIdentical(
            Collections.singletonList(originalDex),
            Collections.singletonList(outJar.toString()),
            getMainClass(),
            extraArtArgs,
            null);
      }
      if (dexComparator != null) {
        CodeInspector ref = new CodeInspector(Paths.get(originalDex));
        dexComparator.accept(ref, compileResult.inspector());
      }
    } else {
      Assert.assertNull(outputComparator);
      Assert.assertNull(dexComparator);
      ToolHelper.runArtNoVerificationErrors(
          Collections.singletonList(outJar.toString()), getMainClass(), extraArtArgs, dexVm);
    }
    if (inspection != null) {
      compileResult.inspect(inspection);
    }
  }
}
