// Copyright (c) 2019, 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.desugar.desugaredlibrary.r8ondex;

import static com.android.tools.r8.utils.FileUtils.JAR_EXTENSION;
import static junit.framework.TestCase.assertEquals;
import static junit.framework.TestCase.assertTrue;
import static org.junit.Assume.assumeTrue;

import com.android.tools.r8.D8;
import com.android.tools.r8.D8TestBuilder;
import com.android.tools.r8.D8TestCompileResult;
import com.android.tools.r8.D8TestRunResult;
import com.android.tools.r8.LibraryDesugaringTestConfiguration;
import com.android.tools.r8.R8;
import com.android.tools.r8.TestDiagnosticMessages;
import com.android.tools.r8.TestParameters;
import com.android.tools.r8.TestParametersCollection;
import com.android.tools.r8.TestRuntime;
import com.android.tools.r8.ToolHelper;
import com.android.tools.r8.ToolHelper.DexVm.Version;
import com.android.tools.r8.ToolHelper.ProcessResult;
import com.android.tools.r8.desugar.desugaredlibrary.DesugaredLibraryTestBase;
import com.android.tools.r8.utils.AndroidApiLevel;
import com.android.tools.r8.utils.StringUtils;
import java.io.IOException;
import java.nio.file.Path;
import java.nio.file.Paths;
import org.junit.BeforeClass;
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 HelloWorldCompiledOnArtTest extends DesugaredLibraryTestBase {

  // TODO(b/142621961): Create an abstraction to easily run tests on External DexR8.
  // Manage pathMock in the abstraction.
  private static Path pathMock;

  @BeforeClass
  public static void compilePathBackport() throws Exception {
    assumeTrue("JDK8 is not checked-in on Windows", !ToolHelper.isWindows());
    pathMock = getStaticTemp().newFolder("PathMock").toPath();
    javac(TestRuntime.getCheckedInJdk8(), getStaticTemp())
        .setOutputPath(pathMock)
        .addSourceFiles(
            getAllFilesWithSuffixInDirectory(Paths.get("src/test/r8OnArtBackport"), "java"))
        .compile();
  }

  public static Path[] getPathBackport() throws Exception {
    return getAllFilesWithSuffixInDirectory(pathMock, "class");
  }

  private final TestParameters parameters;

  @Parameters(name = "{0}")
  public static TestParametersCollection data() {
    return getTestParameters()
        .withDexRuntimesStartingFromIncluding(Version.V7_0_0)
        .withApiLevelsStartingAtIncluding(AndroidApiLevel.L)
        .build();
  }

  public HelloWorldCompiledOnArtTest(TestParameters parameters) {
    this.parameters = parameters;
  }

  private static String commandLinePathFor(String string) {
    return Paths.get(string).toAbsolutePath().toString();
  }

  private static final String HELLO_KEEP =
      commandLinePathFor("src/test/examples/hello/keep-rules.txt");
  private static final String HELLO_PATH =
      commandLinePathFor(ToolHelper.EXAMPLES_BUILD_DIR + "hello" + JAR_EXTENSION);

  @Test
  public void testHelloCompiledWithR8Dex() throws Exception {
    Path helloOutput = temp.newFolder("helloOutput").toPath().resolve("out.zip").toAbsolutePath();
    compileR8ToDexWithD8()
        .run(
            parameters.getRuntime(),
            R8.class,
            "--release",
            "--output",
            helloOutput.toString(),
            "--lib",
            commandLinePathFor(ToolHelper.JAVA_8_RUNTIME),
            "--pg-conf",
            HELLO_KEEP,
            HELLO_PATH)
        .assertSuccess();
    verifyResult(helloOutput);
  }

  @Test
  public void testHelloCompiledWithD8Dex() throws Exception {
    Path helloOutput = temp.newFolder("helloOutput").toPath().resolve("out.zip").toAbsolutePath();
    D8TestRunResult run =
        compileR8ToDexWithD8()
            .run(
                parameters.getRuntime(),
                D8.class,
                "--release",
                "--output",
                helloOutput.toString(),
                "--lib",
                commandLinePathFor(ToolHelper.JAVA_8_RUNTIME),
                HELLO_PATH);
    run.assertSuccess();
    verifyResult(helloOutput);
  }

  private void verifyResult(Path helloOutput) throws IOException {
    ProcessResult processResult = ToolHelper.runArtRaw(helloOutput.toString(), "hello.Hello");
    assertEquals(StringUtils.lines("Hello, world"), processResult.stdout);
  }

  private D8TestCompileResult compileR8ToDexWithD8() throws Exception {
    D8TestBuilder d8TestBuilder =
        testForD8().addProgramFiles(ToolHelper.R8_WITH_RELOCATED_DEPS_JAR);
    if (parameters.getApiLevel().getLevel() < AndroidApiLevel.O.getLevel()) {
      d8TestBuilder.addProgramFiles(getPathBackport());
    }
    D8TestCompileResult compile =
        d8TestBuilder
            .addLibraryFiles(ToolHelper.getAndroidJar(AndroidApiLevel.P))
            .setMinApi(parameters.getApiLevel())
            .enableCoreLibraryDesugaring(
                LibraryDesugaringTestConfiguration.forApiLevel(parameters.getApiLevel()))
            .addOptionsModification(opt -> opt.testing.trackDesugaredAPIConversions = true)
            .compile();
    TestDiagnosticMessages diagnosticMessages = compile.getDiagnosticMessages();
    assertTrue(
        diagnosticMessages.getWarnings().isEmpty()
            || diagnosticMessages.getWarnings().stream()
                .noneMatch(x -> x.getDiagnosticMessage().contains("andThen")));
    return compile
        .withArt6Plus64BitsLib()
        .withArtFrameworks();
  }
}
