// 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;

import static org.hamcrest.CoreMatchers.containsString;
import static org.junit.Assume.assumeTrue;

import com.android.tools.r8.DesugarTestConfiguration;
import com.android.tools.r8.TestBase;
import com.android.tools.r8.TestParameters;
import com.android.tools.r8.TestRuntime.CfVm;
import com.android.tools.r8.cf.CfVersion;
import com.android.tools.r8.utils.AndroidApiLevel;
import com.android.tools.r8.utils.StringUtils;
import java.io.IOException;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.Parameterized;
import org.junit.runners.Parameterized.Parameter;
import org.objectweb.asm.Opcodes;

@RunWith(Parameterized.class)
public class InterfaceInvokePrivateTest extends TestBase implements Opcodes {

  @Parameter(0)
  public TestParameters parameters;

  @Parameter(1)
  public CfVersion inputCfVersion;

  @Parameterized.Parameters(name = "{0}, Input CfVersion = {1})")
  public static Iterable<?> data() {
    return buildParameters(
        getTestParameters().withCfRuntimes().withDexRuntimes().withAllApiLevelsAlsoForCf().build(),
        CfVersion.rangeInclusive(CfVersion.V1_8, CfVersion.V15));
  }

  private static final String EXPECTED_OUTPUT = StringUtils.unixLines("Hello, world!", "21", "6");

  private boolean isInputCfVersionSupported() {
    return inputCfVersion.isLessThanOrEqualTo(
        CfVersion.fromRaw(parameters.getRuntime().asCf().getVm().getClassfileVersion()));
  }

  @Test
  public void testReference() throws Exception {
    assumeTrue(parameters.getRuntime().isCf());
    assumeTrue(parameters.getApiLevel().isEqualTo(AndroidApiLevel.B));

    testForJvm(parameters)
        .addProgramClassFileData(transformIToPrivate(inputCfVersion))
        .addProgramClasses(TestRunner.class)
        .run(parameters.getRuntime(), TestRunner.class)
        .applyIf(
            // Fails if input CF version is not supported.
            !isInputCfVersionSupported(),
            r ->
                r.assertFailureWithErrorThatMatches(
                    containsString(
                        "more recent version of the Java Runtime (class file version "
                            + inputCfVersion.toString())),
            // Fails with ICCE on VMs prior to JDK 11.
            parameters.getRuntime().asCf().isOlderThan(CfVm.JDK11),
            r -> r.assertFailureWithErrorThatThrows(IncompatibleClassChangeError.class),
            // Succeeds on VMs from JDK 11 regardless of the CF version of the input.
            r -> r.assertSuccessWithOutput(EXPECTED_OUTPUT));
  }

  @Test
  public void testDesugar() throws Exception {
    testForDesugaring(parameters)
        .addProgramClassFileData(transformIToPrivate(inputCfVersion))
        .addProgramClasses(TestRunner.class)
        .run(parameters.getRuntime(), TestRunner.class)
        .applyIf(
            // Running un-desugared on a JVM with too high a CF version fails.
            c ->
                parameters.getRuntime().isCf()
                    && !isInputCfVersionSupported()
                    && DesugarTestConfiguration.isNotDesugared(c),
            r ->
                r.assertFailureWithErrorThatMatches(
                    containsString(
                        "more recent version of the Java Runtime (class file version "
                            + inputCfVersion.toString())),
            // Running without interface method desugaring on a JVM with a supported CF version
            // fails on pre JVM 11. On JVM 11 and above this succeeds even of the input CF version
            // is below 55.
            c ->
                parameters.getRuntime().isCf()
                    && parameters.getRuntime().asCf().isOlderThan(CfVm.JDK11)
                    && (DesugarTestConfiguration.isNotDesugared(c)
                        || (parameters.getApiLevel().isGreaterThanOrEqualTo(AndroidApiLevel.N)
                            && c == DesugarTestConfiguration.D8_DEX)),
            r -> r.assertFailureWithErrorThatThrows(IncompatibleClassChangeError.class),
            // All other conditions succeed.
            r -> r.assertSuccessWithOutput(EXPECTED_OUTPUT));
  }

  @Test
  public void testR8() throws Exception {
    parameters.assumeR8TestParameters();
    testForR8(parameters.getBackend())
        .addProgramClassFileData(transformIToPrivate(inputCfVersion))
        .addProgramClasses(TestRunner.class)
        .addKeepMainRule(TestRunner.class)
        // TODO(b/185463156): Not keeping I and its members will "fix" the ICCE for all runtimes.
        .addKeepClassAndMembersRules(I.class)
        .setMinApi(parameters)
        .compile()
        .run(parameters.getRuntime(), TestRunner.class)
        .applyIf(
            // Running un-desugared on a JVM with too high a CF version fails.
            parameters.getRuntime().isCf() && !isInputCfVersionSupported(),
            r ->
                r.assertFailureWithErrorThatMatches(
                    containsString(
                        "more recent version of the Java Runtime (class file version "
                            + inputCfVersion.toString())),
            // Running on a JVM with a supported CF version fails on pre JVM 11. On
            // JVM 11 and above this succeeds even of the input CF version is below 55.
            parameters.getRuntime().isCf()
                && parameters.getRuntime().asCf().isOlderThan(CfVm.JDK11),
            r -> r.assertFailureWithErrorThatThrows(IncompatibleClassChangeError.class),
            // All other conditions succeed.
            r -> r.assertSuccessWithOutput(EXPECTED_OUTPUT));
  }

  private byte[] transformIToPrivate(CfVersion version) throws NoSuchMethodException, IOException {
    return transformer(I.class)
        .setVersion(version)
        .setPrivate(I.class.getDeclaredMethod("privateHello"))
        .transformMethodInsnInMethod(
            "hello",
            ((opcode, owner, name, descriptor, isInterface, continuation) -> {
              continuation.visitMethodInsn(
                  name.equals("privateHello") ? Opcodes.INVOKEINTERFACE : opcode,
                  owner,
                  name,
                  descriptor,
                  isInterface);
            }))
        .transform();
  }

  interface I {
    /* private */ default String privateHello() {
      return "Hello, world!";
    }
    /* private */ default String privateHello(int i1, int i2, int i3, int i4, int i5, int i6) {
      return "" + (i1 + i2 + i3 + i4 + i5 + i6);
    }
    /* private */ default String privateHello(long l1, long l2, long l3) {
      return "" + (l1 + l2 + l3);
    }

    default String hello() {
      // The private method "privateHello" is called with invokeinterface.
      return privateHello()
          + "\n"
          + privateHello(1, 2, 3, 4, 5, 6)
          + "\n"
          + privateHello(1L, 2L, 3L)
          + "\n";
    }
  }

  public static class TestRunner implements I {

    public static void main(String[] args) {
      System.out.print(new TestRunner().hello());
    }
  }
}
