// 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 twr.twrcloseresourceduplication;

import static org.junit.Assert.assertEquals;

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;
import com.android.tools.r8.references.Reference;
import com.android.tools.r8.synthesis.SyntheticItemsTestUtils;
import com.android.tools.r8.utils.AndroidApiLevel;
import com.android.tools.r8.utils.StringUtils;
import com.android.tools.r8.utils.ZipUtils;
import com.android.tools.r8.utils.codeinspector.FoundClassSubject;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableSet;
import java.io.IOException;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
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.twrcloseresourceduplication.asm.TwrCloseResourceDuplication$BarDump;
import twr.twrcloseresourceduplication.asm.TwrCloseResourceDuplication$FooDump;
import twr.twrcloseresourceduplication.asm.TwrCloseResourceDuplicationDump;

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

  protected static final String MAIN =
      "twr.twrcloseresourceduplication.TwrCloseResourceDuplication";
  protected static final String FOO =
      "twr.twrcloseresourceduplication.TwrCloseResourceDuplication$Foo";
  protected static final String BAR =
      "twr.twrcloseresourceduplication.TwrCloseResourceDuplication$Bar";

  static final int INPUT_CLASSES = 3;

  protected static final String EXPECTED =
      StringUtils.lines(
          "foo opened 1",
          "foo post close 1",
          "foo opened 2",
          "foo caught from 2: RuntimeException",
          "foo post close 2",
          "bar opened 1",
          "bar post close 1",
          "bar opened 2",
          "bar caught from 2: RuntimeException",
          "bar post close 2");

  @Parameter(0)
  public TestParameters parameters;

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

  protected boolean hasTwrCloseResourceSupport(boolean isDesugaring) {
    return !isDesugaring
        || parameters.getApiLevel().isGreaterThanOrEqualTo(apiLevelWithTwrCloseResourceSupport());
  }

  protected boolean hasTwrCloseResourceApiOutlines() {
    return parameters.isDexRuntime()
        && parameters.getApiLevel().isLessThan(apiLevelWithTwrCloseResourceSupport());
  }

  protected String getZipFile() throws IOException {
    return ZipUtils.ZipBuilder.builder(temp.newFile("file.zip").toPath())
        // DEX VMs from 4.4 up-to 9.0 including, will fail if no entry is added.
        .addBytes("entry", new byte[1])
        .build()
        .toString();
  }

  protected static List<byte[]> getProgramInputs() throws Exception {
    return ImmutableList.of(
        TwrCloseResourceDuplicationDump.dump(),
        TwrCloseResourceDuplication$FooDump.dump(),
        TwrCloseResourceDuplication$BarDump.dump());
  }

  @Test
  public void testJvm() throws Exception {
    parameters.assumeJvmTestParameters();
    testForJvm(parameters)
        .addProgramClassFileData(getProgramInputs())
        .run(parameters.getRuntime(), MAIN, getZipFile())
        .assertSuccessWithOutput(EXPECTED);
  }

  @Test
  public void testD8() throws Exception {
    testForD8(parameters.getBackend())
        .addProgramClassFileData(getProgramInputs())
        .addLibraryFiles(ToolHelper.getAndroidJar(AndroidApiLevel.LATEST))
        .setMinApi(parameters)
        .run(parameters.getRuntime(), MAIN, getZipFile())
        .assertSuccessWithOutput(EXPECTED)
        .inspect(
            inspector -> {
              // NOTE: The $closeResource helper is _only_ generated by the JDK-9 compiler.
              //
              // There should be two synthetic classes besides the three program classes.
              // One for the desugar version of TWR $closeResource and one for the
              // Throwable.addSuppressed that is still present in the original $closeResource.
              // TODO(b/214329923): If the original $closeResource is pruned this will decrease.
              // TODO(b/168568827): Once we support a nested addSuppressed this will increase.
              int expectedSynthetics = 0;
              if (!hasTwrCloseResourceSupport(true)) {
                expectedSynthetics += 2;
              }
              if (hasTwrCloseResourceApiOutlines()) {
                expectedSynthetics += 1;
              }
              assertEquals(INPUT_CLASSES + expectedSynthetics, inspector.allClasses().size());
            });
  }

  @Test
  public void testR8() throws Exception {
    parameters.assumeDexRuntime();
    testForR8(parameters.getBackend())
        .addProgramClassFileData(getProgramInputs())
        .addLibraryFiles(ToolHelper.getAndroidJar(AndroidApiLevel.LATEST))
        .addKeepMainRule(MAIN)
        .addKeepClassAndMembersRules(FOO, BAR)
        .setMinApi(parameters)
        .addDontObfuscate()
        .run(parameters.getRuntime(), MAIN, getZipFile())
        .assertSuccessWithOutput(EXPECTED)
        .inspect(
            inspector -> {
              List<FoundClassSubject> foundClassSubjects = inspector.allClasses();
              Set<String> foundClasses =
                  foundClassSubjects.stream()
                      .map(FoundClassSubject::getFinalName)
                      .collect(Collectors.toSet());
              // R8 will optimize the generated methods for the two cases below where the thrown
              // exception is known or not, thus the synthetic methods will be 2.
              Set<String> nonSyntheticClassOutput = ImmutableSet.of(FOO, BAR, MAIN);
              if (!hasTwrCloseResourceSupport(parameters.isDexRuntime())) {
                Set<String> classOutputWithSynthetics = new HashSet<>(nonSyntheticClassOutput);
                classOutputWithSynthetics.add(
                    SyntheticItemsTestUtils.syntheticApiOutlineClass(
                            Reference.classFromTypeName(BAR), 0)
                        .getTypeName());
                assertEquals(classOutputWithSynthetics, foundClasses);
              } else {
                assertEquals(nonSyntheticClassOutput, foundClasses);
              }
            });
  }
}
