// 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.cf.bootstrap;

import static com.android.tools.r8.utils.FileUtils.JAR_EXTENSION;
import static org.junit.Assert.assertEquals;

import com.android.tools.r8.ClassFileConsumer;
import com.android.tools.r8.CompilationMode;
import com.android.tools.r8.R8Command;
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.ToolHelper.ProcessResult;
import com.android.tools.r8.utils.FileUtils;
import com.google.common.base.Charsets;
import java.nio.file.Path;
import java.nio.file.Paths;
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 BootstrapTest extends TestBase {

  private static final Path R8_STABLE_JAR = Paths.get("third_party/r8/r8.jar");

  private static final String R8_NAME = "com.android.tools.r8.R8";
  private static final String[] KEEP_R8 = {
    "-keep public class " + R8_NAME + " {", "  public static void main(...);", "}",
  };
  private static final Path DONTWARN_R8 = Paths.get("src/main/dontwarn.txt");

  private static final String HELLO_NAME = "hello.Hello";
  private static final String[] KEEP_HELLO = {
    "-keep class " + HELLO_NAME + " {", "  public static void main(...);", "}",
  };

  private static class R8Result {

    final ProcessResult processResult;
    final Path outputJar;
    final String pgMap;

    R8Result(ProcessResult processResult, Path outputJar, String pgMap) {
      this.processResult = processResult;
      this.outputJar = outputJar;
      this.pgMap = pgMap;
    }

    @Override
    public String toString() {
      return processResult.toString() + "\n\n" + pgMap;
    }
  }

  @Parameters(name = "{0}")
  public static TestParametersCollection data() {
    return getTestParameters().withNoneRuntime().build();
  }

  public BootstrapTest(TestParameters parameters) {
    // TODO: use parameters to fork the right Java.
    parameters.assertNoneRuntime();
  }

  @Test
  public void test() throws Exception {
    // Run hello.jar to ensure it exists and is valid.
    Path hello = Paths.get(ToolHelper.EXAMPLES_BUILD_DIR, "hello" + JAR_EXTENSION);
    ProcessResult runHello = ToolHelper.runJava(hello, "hello.Hello");
    assertEquals(0, runHello.exitCode);

    // Run r8.jar on hello.jar to ensure that r8.jar is a working compiler.
    R8Result runInputR8 = runExternalR8(R8_STABLE_JAR, hello, "input", KEEP_HELLO, "--debug");
    ProcessResult runHelloR8 = ToolHelper.runJava(runInputR8.outputJar, "hello.Hello");
    assertEquals(runHello.toString(), runHelloR8.toString());

    compareR8(hello, runInputR8, CompilationMode.RELEASE, "r8-r8-rel", "--release", "output-rel");
    compareR8(hello, runInputR8, CompilationMode.DEBUG, "r8-r8", "--debug", "output");
  }

  private void compareR8(
      Path hello,
      R8Result runInputR8,
      CompilationMode internalMode,
      String internalOutput,
      String externalMode,
      String externalOutput)
      throws Exception {
    // Run R8 on r8.jar.
    Path output = runR8(internalOutput, internalMode);
    // Run the resulting compiler on hello.jar.
    R8Result runR8R8 = runExternalR8(output, hello, externalOutput, KEEP_HELLO, externalMode);
    // Check that the process outputs (exit code, stdout, stderr) are the same.
    assertEquals(runInputR8.toString(), runR8R8.toString());
    // Check that the output jars are the same.
    assertProgramsEqual(runInputR8.outputJar, runR8R8.outputJar);
  }

  private Path runR8(String outputFolder, CompilationMode mode) throws Exception {
    Path outputPath = temp.newFolder(outputFolder).toPath();
    Path outputJar = outputPath.resolve("output.jar");
    Path pgConfigFile = outputPath.resolve("keep.rules");
    FileUtils.writeTextFile(pgConfigFile, BootstrapTest.KEEP_R8);
    ToolHelper.runR8(
        R8Command.builder()
            .setMode(mode)
            .addLibraryFiles(ToolHelper.getJava8RuntimeJar())
            .setProgramConsumer(new ClassFileConsumer.ArchiveConsumer(outputJar, true))
            .addProgramFiles(R8_STABLE_JAR)
            .addProguardConfigurationFiles(pgConfigFile, DONTWARN_R8)
            .build());
    return outputJar;
  }

  private R8Result runExternalR8(
      Path r8Jar, Path inputJar, String outputFolder, String[] keepRules, String mode)
      throws Exception {
    Path outputPath = temp.newFolder(outputFolder).toPath();
    Path pgConfigFile = outputPath.resolve("keep.rules");
    Path outputJar = outputPath.resolve("output.jar");
    Path pgMapFile = outputPath.resolve("map.txt");
    FileUtils.writeTextFile(pgConfigFile, keepRules);
    ProcessResult processResult =
        ToolHelper.runJava(
            r8Jar,
            R8_NAME,
            "--lib",
            ToolHelper.JAVA_8_RUNTIME,
            "--classfile",
            inputJar.toString(),
            "--output",
            outputJar.toString(),
            "--pg-conf",
            pgConfigFile.toString(),
            mode,
            "--pg-map-output",
            pgMapFile.toString());
    if (processResult.exitCode != 0) {
      System.out.println(processResult);
    }
    assertEquals(processResult.stderr, 0, processResult.exitCode);
    String pgMap = FileUtils.readTextFile(pgMapFile, Charsets.UTF_8);
    return new R8Result(processResult, outputJar, pgMap);
  }
}
