// Copyright (c) 2021, 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.constantdynamic;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assume.assumeTrue;

import com.android.tools.r8.TestBase;
import com.android.tools.r8.TestParameters;
import com.android.tools.r8.TestRuntime.CfVm;
import com.android.tools.r8.ToolHelper;
import com.android.tools.r8.ToolHelper.DexVm;
import com.android.tools.r8.cf.CfVersion;
import com.android.tools.r8.jacoco.JacocoClasses;
import com.android.tools.r8.utils.BooleanUtils;
import com.android.tools.r8.utils.StringUtils;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.List;
import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.Test;
import org.junit.rules.TemporaryFolder;
import org.junit.runner.RunWith;
import org.junit.runners.Parameterized;
import org.junit.runners.Parameterized.Parameter;
import org.junit.runners.Parameterized.Parameters;

@RunWith(Parameterized.class)
public class JacocoConstantDynamicTest extends TestBase {

  @Parameter() public TestParameters parameters;

  @Parameter(1)
  public boolean useConstantDynamic;

  @Parameters(name = "{0}, useConstantDynamic: {1}")
  public static List<Object[]> data() {
    return buildParameters(
        getTestParameters().withAllRuntimes().withAllApiLevelsAlsoForCf().build(),
        BooleanUtils.values());
  }

  public static JacocoClasses testClassesNoConstantDynamic;
  public static JacocoClasses testClassesConstantDynamic;

  public JacocoClasses testClasses;

  private static final String MAIN_CLASS = TestRunner.class.getTypeName();
  private static final String EXPECTED_OUTPUT = StringUtils.lines("Hello, world!");

  @BeforeClass
  public static void setUpInput() throws IOException {
    testClassesNoConstantDynamic = testClasses(getStaticTemp(), CfVersion.V1_8);
    testClassesConstantDynamic = testClasses(getStaticTemp(), CfVersion.V11);
  }

  @Before
  public void setUp() throws IOException {
    testClasses = useConstantDynamic ? testClassesConstantDynamic : testClassesNoConstantDynamic;
  }

  @Test
  public void testJvm() throws Exception {
    assumeTrue(
        parameters.isCfRuntime()
            && (parameters.getRuntime().asCf().isNewerThanOrEqual(CfVm.JDK11)
                || !useConstantDynamic));

    // Run non-instrumented code.
    testForRuntime(parameters)
        .addProgramFiles(testClasses.getOriginal())
        .run(parameters.getRuntime(), MAIN_CLASS)
        .assertSuccessWithOutput(EXPECTED_OUTPUT);

    // Run non-instrumented code with an agent causing on the fly instrumentation on the JVM.
    Path output = temp.newFolder().toPath();
    Path agentOutputOnTheFly = output.resolve("on-the-fly");
    testForJvm()
        .addProgramFiles(testClasses.getOriginal())
        .enableJaCoCoAgent(ToolHelper.JACOCO_AGENT, agentOutputOnTheFly)
        .run(parameters.getRuntime(), MAIN_CLASS)
        .assertSuccessWithOutput(EXPECTED_OUTPUT);
    List<String> onTheFlyReport = testClasses.generateReport(agentOutputOnTheFly);
    assertEquals(2, onTheFlyReport.size());

    // Run the instrumented code.
    Path agentOutputOffline = output.resolve("offline");
    testForJvm()
        .addProgramFiles(testClasses.getInstrumented())
        .configureJaCoCoAgentForOfflineInstrumentedCode(ToolHelper.JACOCO_AGENT, agentOutputOffline)
        .run(parameters.getRuntime(), MAIN_CLASS)
        .assertSuccessWithOutput(EXPECTED_OUTPUT);
    List<String> offlineReport = testClasses.generateReport(agentOutputOffline);
    assertEquals(onTheFlyReport, offlineReport);
  }

  @Test
  public void testD8() throws Exception {
    assumeTrue(parameters.getRuntime().isDex());
    if (!useConstantDynamic) {
      Path output = temp.newFolder().toPath();
      Path agentOutput = output.resolve("jacoco.exec");
      testForD8(parameters.getBackend())
          .addProgramFiles(testClasses.getInstrumented())
          .addProgramFiles(ToolHelper.JACOCO_AGENT)
          .setMinApi(parameters.getApiLevel())
          .compile()
          .runWithJaCoCo(agentOutput, parameters.getRuntime(), MAIN_CLASS)
          .assertSuccessWithOutput(EXPECTED_OUTPUT);
      // TODO(sgjesse): Need to figure out why there is no instrumentation output for newer VMs.
      if (parameters.getRuntime().asDex().getVm().isOlderThanOrEqual(DexVm.ART_4_4_4_HOST)) {
        List<String> report = testClasses.generateReport(agentOutput);
        assertEquals(2, report.size());
      } else {
        assertFalse(Files.exists(agentOutput));
      }
    } else {
      testForD8(parameters.getBackend())
          .addProgramFiles(testClasses.getInstrumented())
          .addProgramFiles(ToolHelper.JACOCO_AGENT)
          .setMinApi(parameters.getApiLevel())
          .compile();
    }
  }

  private static JacocoClasses testClasses(TemporaryFolder temp, CfVersion version)
      throws IOException {
    return new JacocoClasses(
        transformer(TestRunner.class)
            .setVersion(version) /*.setClassDescriptor("LTestRunner;")*/
            .transform(),
        temp);
  }

  static class TestRunner {

    public static void main(String[] args) {
      System.out.println("Hello, world!");
    }
  }
}
