// Copyright (c) 2022, 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 twr.twraddsuppressed;

import static org.junit.Assert.assertEquals;

import com.android.tools.r8.DesugarTestConfiguration;
import com.android.tools.r8.TestBase;
import com.android.tools.r8.TestParameters;
import com.android.tools.r8.TestParametersCollection;
import com.android.tools.r8.TestRuntime.CfVm;
import com.android.tools.r8.ToolHelper.DexVm.Version;
import com.android.tools.r8.utils.IntBox;
import com.android.tools.r8.utils.StringUtils;
import com.android.tools.r8.utils.codeinspector.ClassSubject;
import com.android.tools.r8.utils.codeinspector.InstructionSubject;
import com.android.tools.r8.utils.codeinspector.MethodSubject;
import com.google.common.collect.ImmutableList;
import java.util.List;
import java.util.stream.Collectors;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.Parameterized;
import org.junit.runners.Parameterized.Parameter;
import org.junit.runners.Parameterized.Parameters;
import twr.twraddsuppressed.asm.TestClass$MyClosableDump;
import twr.twraddsuppressed.asm.TestClassDump;

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

  private static final String TEST_CLASS = "twr.twraddsuppressed.TestClass";

  @Parameter(0)
  public TestParameters parameters;

  @Parameters(name = "{0}")
  public static TestParametersCollection data() {
    return getTestParameters()
        .withCfRuntimesStartingFromIncluding(CfVm.JDK9)
        .withDexRuntimes()
        .withAllApiLevelsAlsoForCf()
        .build();
  }

  public boolean runtimeHasSuppressedExceptionsSupport() {
    // TODO(b/214239152): Update this if desugaring is changed.
    // Despite 4.0.4 being API level 15 and add suppressed being officially added in 19 it is
    // actually implemented. Thus, the backport implementation will use the functionality and run
    // as expected by RI.
    return parameters.isCfRuntime()
        || parameters.getDexRuntimeVersion().isNewerThanOrEqual(Version.V4_0_4);
  }

  public boolean apiLevelHasSuppressedExceptionsSupport(boolean isDesugaring) {
    return !isDesugaring
        || parameters
            .getApiLevel()
            .isGreaterThanOrEqualTo(apiLevelWithSuppressedExceptionsSupport());
  }

  public boolean apiLevelHasTwrCloseResourceSupport(boolean isDesugaring) {
    return !isDesugaring
        || parameters.getApiLevel().isGreaterThanOrEqualTo(apiLevelWithTwrCloseResourceSupport());
  }

  public List<byte[]> getProgramInputs() throws Exception {
    return ImmutableList.of(TestClassDump.dump(), TestClass$MyClosableDump.dump());
  }

  @Test
  public void testD8() throws Exception {
    testForDesugaring(parameters)
        .addProgramClassFileData(getProgramInputs())
        .run(parameters.getRuntime(), TEST_CLASS)
        .assertSuccessWithOutput(
            runtimeHasSuppressedExceptionsSupport() ? StringUtils.lines("CLOSE") : "NONE")
        .inspectIf(
            DesugarTestConfiguration::isDesugared,
            inspector -> {
              ClassSubject clazz = inspector.clazz(TEST_CLASS);
              hasInvokesTo(
                  clazz.uniqueMethodWithOriginalName("bar"),
                  // NOTE: The $closeResource helper is _only_ generated by the JDK-9 compiler.
                  "$closeResource",
                  apiLevelHasTwrCloseResourceSupport(true) ? 4 : 0);
              if (apiLevelHasSuppressedExceptionsSupport(true)) {
                hasInvokesTo(clazz.mainMethod(), "getSuppressed", 1);
              } else {
                inspector.forAllClasses(
                    c ->
                        c.forAllMethods(
                            m -> {
                              hasInvokesTo(m, "getSuppressed", 0);
                              hasInvokesTo(m, "addSuppressed", 0);
                            }));
              }
            })
        .inspectIf(
            DesugarTestConfiguration::isNotDesugared,
            inspector -> {
              ClassSubject clazz = inspector.clazz(TEST_CLASS);
              // NOTE: The $closeResource helper is _only_ generated by the JDK-9 compiler.
              hasInvokesTo(clazz.uniqueMethodWithOriginalName("bar"), "$closeResource", 4);
              hasInvokesTo(clazz.mainMethod(), "getSuppressed", 1);
            });
  }

  @Test
  public void testR8() throws Exception {
    parameters.assumeR8TestParameters();
    testForR8(parameters.getBackend())
        .addProgramClassFileData(getProgramInputs())
        .setMinApi(parameters)
        .addKeepMainRule(TEST_CLASS)
        // TODO(b/214250388): Don't warn about AutoClosable in synthesized code.
        .apply(
            b -> {
              if (!apiLevelHasTwrCloseResourceSupport(parameters.isDexRuntime())) {
                b.addDontWarn(AutoCloseable.class);
              }
            })
        .run(parameters.getRuntime(), TEST_CLASS)
        .assertSuccessWithOutput(
            runtimeHasSuppressedExceptionsSupport() ? StringUtils.lines("CLOSE") : "NONE")
        .inspect(
            inspector -> {
              IntBox gets = new IntBox(0);
              IntBox adds = new IntBox(0);
              inspector.forAllClasses(
                  c ->
                      c.forAllMethods(
                          m -> {
                            gets.increment(getInvokesTo(m, "getSuppressed").size());
                            adds.increment(getInvokesTo(m, "addSuppressed").size());
                          }));
              if (apiLevelHasSuppressedExceptionsSupport(parameters.isDexRuntime())) {
                hasInvokesTo(inspector.clazz(TEST_CLASS).mainMethod(), "getSuppressed", 1);
                assertEquals(1, gets.get());
                assertEquals(1, adds.get());
              } else {
                assertEquals(0, gets.get());
                assertEquals(0, adds.get());
              }
            });
  }

  public static void hasInvokesTo(MethodSubject method, String callee, int count) {
    List<InstructionSubject> getSuppressedCalls = getInvokesTo(method, callee);
    assertEquals(count, getSuppressedCalls.size());
  }

  public static List<InstructionSubject> getInvokesTo(MethodSubject method, String callee) {
    return method
        .streamInstructions()
        .filter(i -> i.isInvoke() && i.getMethod().getName().toString().equals(callee))
        .collect(Collectors.toList());
  }
}
