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

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

import com.android.tools.r8.NeverClassInline;
import com.android.tools.r8.NeverInline;
import com.android.tools.r8.NeverMerge;
import com.android.tools.r8.R8TestRunResult;
import com.android.tools.r8.TestBase;
import com.android.tools.r8.TestBuilder;
import com.android.tools.r8.TestParameters;
import com.android.tools.r8.TestParametersCollection;
import com.android.tools.r8.ToolHelper.DexVm.Version;
import com.android.tools.r8.repackage.testclasses.CrossPackageInvokeSuperToPackagePrivateMethodTestClasses;
import java.io.IOException;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.Parameterized;
import org.objectweb.asm.Opcodes;

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

  private final TestParameters parameters;

  @Parameterized.Parameters(name = "{0}")
  public static TestParametersCollection data() {
    return getTestParameters().withAllRuntimesAndApiLevels().build();
  }

  public CrossPackageInvokeSuperToPackagePrivateMethodTest(TestParameters parameters) {
    this.parameters = parameters;
  }

  @Test
  public void testJvm() throws Exception {
    assumeTrue(parameters.isCfRuntime());
    testForJvm()
        .apply(this::addProgramClasses)
        .run(parameters.getRuntime(), TestClass.class)
        .assertSuccessWithOutputLines("A", "B", "A", "C", "D", "C");
  }

  @Test
  public void test() throws Exception {
    testForR8(parameters.getBackend())
        .apply(this::addProgramClasses)
        .addKeepMainRule(TestClass.class)
        .enableInliningAnnotations()
        .enableMergeAnnotations()
        .enableNeverClassInliningAnnotations()
        .setMinApi(parameters.getApiLevel())
        .compile()
        .run(parameters.getRuntime(), TestClass.class)
        .apply(this::inspectRunResult);
  }

  private void addProgramClasses(TestBuilder<?, ?> builder) throws IOException {
    builder
        .addProgramClasses(
            TestClass.class,
            A.class,
            B.class,
            CrossPackageInvokeSuperToPackagePrivateMethodTestClasses.C.class)
        .addProgramClassFileData(
            transformer(D.class)
                .transformMethodInsnInMethod(
                    "packagePrivate",
                    (opcode, owner, name, descriptor, isInterface, continuation) ->
                        continuation.visitMethodInsn(
                            name.equals("packagePrivate") ? Opcodes.INVOKESPECIAL : opcode,
                            name.equals("packagePrivate")
                                ? binaryName(
                                        CrossPackageInvokeSuperToPackagePrivateMethodTest.class)
                                    + "$B"
                                : owner,
                            name,
                            descriptor,
                            isInterface))
                .transform());
  }

  private void inspectRunResult(R8TestRunResult runResult) {
    if (parameters.isCfRuntime()
        || parameters.getRuntime().asDex().getVm().getVersion().isDalvik()) {
      runResult.assertSuccessWithOutputLines("A", "B", "A", "C", "D", "C");
    } else {
      runResult.assertSuccessWithOutputLines("A", "B", "A", "C", "D", "B", "A");
      if (parameters.getRuntime().asDex().getVm().getVersion().isOlderThanOrEqual(Version.V7_0_0)) {
        runResult.assertStderrMatches(
            allOf(
                containsString("Before Android 4.1, method"),
                containsString("would have incorrectly overridden the package-private method")));
      }
    }
  }

  static class TestClass {

    public static void main(String[] args) {
      new A().packagePrivate();
      new B().packagePrivate();
      new CrossPackageInvokeSuperToPackagePrivateMethodTestClasses.C().runPackagePrivate();
      new D().packagePrivate();
    }
  }

  @NeverClassInline
  @NeverMerge
  public static class A {

    @NeverInline
    void packagePrivate() {
      System.out.println("A");
    }
  }

  @NeverClassInline
  @NeverMerge
  public static class B extends A {

    @NeverInline
    void packagePrivate() {
      System.out.println("B");
      super.packagePrivate();
    }
  }

  @NeverClassInline
  public static class D extends CrossPackageInvokeSuperToPackagePrivateMethodTestClasses.C {

    @NeverInline
    void packagePrivate() {
      System.out.println("D");
      /*super.*/packagePrivate();
    }
  }
}
