// 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 com.google.common.collect.ImmutableList;
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!", "Hello from I!");

  @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(3, 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(3, 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(
        ImmutableList.of(
            transformer(TestRunner.class).setVersion(version).transform(),
            transformer(I.class).setVersion(version).transform()),
        temp);
  }

  interface I {
    default void m() {
      System.out.println("Hello from I!");
    }
  }

  static class TestRunner implements I {

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