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

import static com.android.tools.r8.utils.codeinspector.Matchers.isPresent;
import static org.hamcrest.CoreMatchers.not;
import static org.hamcrest.MatcherAssert.assertThat;

import com.android.tools.r8.TestBase;
import com.android.tools.r8.TestParameters;
import com.android.tools.r8.jasmin.JasminBuilder;
import com.android.tools.r8.jasmin.JasminBuilder.ClassBuilder;
import com.android.tools.r8.utils.BooleanUtils;
import com.android.tools.r8.utils.codeinspector.ClassSubject;
import com.android.tools.r8.utils.codeinspector.CodeInspector;
import com.android.tools.r8.utils.codeinspector.MethodSubject;
import java.util.Collections;
import java.util.List;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.Parameterized;

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

  private final boolean minification;
  private final TestParameters parameters;

  @Parameterized.Parameters(name = "{1}, minification: {0}")
  public static List<Object[]> data() {
    return buildParameters(
        BooleanUtils.values(), getTestParameters().withAllRuntimesAndApiLevels().build());
  }

  public RemoveVisibilityBridgeMethodsTest(boolean minification, TestParameters parameters) {
    this.minification = minification;
    this.parameters = parameters;
  }

  @Test
  public void test() throws Exception {
    testForR8(parameters.getBackend())
        .addInnerClasses(RemoveVisibilityBridgeMethodsTest.class)
        .addKeepMainRule(Main.class)
        .allowAccessModification()
        .minification(minification)
        .setMinApi(parameters.getApiLevel())
        .compile()
        .inspect(this::inspect)
        .run(parameters.getRuntime(), Main.class)
        .assertSuccess();
  }

  private void inspect(CodeInspector inspector) throws Exception {
    assertThat(inspector.method(Outer.SubClass.class.getMethod("method")), not(isPresent()));
    assertThat(inspector.method(Outer.StaticSubClass.class.getMethod("method")), not(isPresent()));
  }

  /**
   * Regression test for b76383728 to make sure we correctly identify and remove real visibility
   * forward bridge methods synthesized by javac.
   */
  @Test
  public void regressionTest_b76383728() throws Exception {
    JasminBuilder jasminBuilder = new JasminBuilder();

    ClassBuilder superClass = jasminBuilder.addClass("SuperClass");
    superClass.addDefaultConstructor();
    superClass.addVirtualMethod("method", Collections.emptyList(), "Ljava/lang/String;",
        ".limit stack 1",
        "ldc \"Hello World\"",
        "areturn");

    // Generate a subclass with a method with same
    ClassBuilder subclass = jasminBuilder.addClass("SubClass", superClass.name);
    subclass.addBridgeMethod("getMethod", Collections.emptyList(), "Ljava/lang/String;",
        ".limit stack 1",
        "aload_0",
        "invokespecial " + superClass.name + "/method()Ljava/lang/String;",
        "areturn");

    ClassBuilder mainClass = jasminBuilder.addClass("Main");
    mainClass.addMainMethod(
        ".limit stack 3",
        ".limit locals 2",
        "getstatic java/lang/System/out Ljava/io/PrintStream;",
        "new " + subclass.name,
        "dup",
        "invokespecial " + subclass.name + "/<init>()V",
        "invokevirtual " + subclass.name + "/getMethod()Ljava/lang/String;",
        "invokevirtual java/io/PrintStream/println(Ljava/lang/String;)V",
        "return");

    List<byte[]> programClassFileData = jasminBuilder.buildClasses();

    // Run input program on java.
    if (parameters.isCfRuntime()) {
      testForJvm()
          .addProgramClassFileData(programClassFileData)
          .run(parameters.getRuntime(), mainClass.name)
          .assertSuccessWithOutputLines("Hello World");
    }

    testForR8(parameters.getBackend())
        .addProgramClassFileData(programClassFileData)
        .addKeepMainRule(mainClass.name)
        .addOptionsModification(options -> options.enableInlining = false)
        .allowAccessModification()
        .minification(minification)
        .setMinApi(parameters.getApiLevel())
        .compile()
        .inspect(
            inspector -> {
              ClassSubject classSubject = inspector.clazz(superClass.name);
              assertThat(classSubject, isPresent());
              MethodSubject methodSubject =
                  classSubject.method("java.lang.String", "method", Collections.emptyList());
              assertThat(methodSubject, isPresent());

              classSubject = inspector.clazz(subclass.name);
              assertThat(classSubject, isPresent());
              methodSubject =
                  classSubject.method("java.lang.String", "getMethod", Collections.emptyList());
              assertThat(methodSubject, isPresent());
            })
        .run(parameters.getRuntime(), mainClass.name)
        .assertSuccessWithOutputLines("Hello World");
  }

  static class Main {

    public static void main(String[] args) {
      new Outer().create().method();
      new Outer.StaticSubClass().method();
    }
  }

  static class Outer {

    class SuperClass {
      public void method() {}
    }

    // As SuperClass is package private SubClass will have a bridge method for "method".
    public class SubClass extends SuperClass {}

    public SubClass create() {
      return new SubClass();
    }

    static class StaticSuperClass {
      public void method() {}
    }

    // As SuperClass is package private SubClass will have a bridge method for "method".
    public static class StaticSubClass extends StaticSuperClass {}
  }
}
