// Copyright (c) 2018, 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.naming.b72391662;

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

import com.android.tools.r8.NeverPropagateValue;
import com.android.tools.r8.ToolHelper;
import com.android.tools.r8.ToolHelper.DexVm.Version;
import com.android.tools.r8.errors.Unreachable;
import com.android.tools.r8.naming.b72391662.subpackage.OtherPackageSuper;
import com.android.tools.r8.naming.b72391662.subpackage.OtherPackageTestClass;
import com.android.tools.r8.shaking.forceproguardcompatibility.ProguardCompatibilityTestBase;
import com.android.tools.r8.utils.AndroidApp;
import com.android.tools.r8.utils.StringUtils;
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 com.google.common.collect.ImmutableList;
import com.google.common.collect.Iterables;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import org.junit.Assume;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.Parameterized;

@RunWith(Parameterized.class)
public class B72391662 extends ProguardCompatibilityTestBase {

  private static final List<Class<?>> CLASSES =
      ImmutableList.of(
          TestMain.class,
          Interface.class,
          Super.class,
          TestClass.class,
          OtherPackageSuper.class,
          OtherPackageTestClass.class,
          NeverPropagateValue.class);

  private final Shrinker shrinker;
  private final String repackagePrefix;
  private final boolean allowAccessModification;
  private final boolean minify;

  @Parameterized.Parameters(name = "Shrinker: {0}, Prefix: {1}, AllowAccessMod: {2}, Minify: {3}")
  public static Collection<Object[]> data() {
    List<Object[]> result = new ArrayList<>();
    for (Shrinker shrinker :
        new Shrinker[] {
          Shrinker.R8,
          Shrinker.R8_COMPAT,
          Shrinker.PROGUARD6_THEN_D8,
          Shrinker.R8_CF,
          Shrinker.R8_COMPAT_CF
        }) {
      for (boolean useRepackagePrefix : new boolean[] {false, true}) {
        String repackagePrefix;
        if (useRepackagePrefix) {
          switch (shrinker) {
            case R8:
              repackagePrefix = "r8";
              break;
            case R8_COMPAT:
              repackagePrefix = "rc";
              break;
            case PROGUARD6_THEN_D8:
              repackagePrefix = "pg";
              break;
            case R8_CF:
              repackagePrefix = "r8cf";
              break;
            case R8_COMPAT_CF:
              repackagePrefix = "rccf";
              break;
            default:
              assert false;
              throw new Unreachable();
          }
        } else {
          repackagePrefix = null;
        }
        for (boolean allowAccessModification : new boolean[] {false, true}) {
          for (boolean minify : new boolean[] {false, true}) {
            result.add(new Object[] {shrinker, repackagePrefix, allowAccessModification, minify});
          }
        }
      }
    }
    return result;
  }

  public B72391662(
      Shrinker shrinker, String repackagePrefix, boolean allowAccessModification, boolean minify) {
    this.shrinker = shrinker;
    this.repackagePrefix = repackagePrefix;
    this.allowAccessModification = allowAccessModification;
    this.minify = minify;
  }

  private static boolean vmVersionIgnored() {
    return !ToolHelper.getDexVm().getVersion().isNewerThanOrEqual(Version.V7_0_0);
  }

  @Test
  public void test_keepAll() throws Exception {
    Assume.assumeFalse(shrinker.generatesDex() && vmVersionIgnored());
    Class mainClass = TestMain.class;
    String keep = !minify ? "-keep" : "-keep,allowobfuscation";
    List<String> config = ImmutableList.of(
        "-printmapping",
        repackagePrefix != null ? "-repackageclasses '" + repackagePrefix + "'" : "",
        allowAccessModification ? "-allowaccessmodification" : "",
        !minify ? "-dontobfuscate" : "",
        "-keep class " + mainClass.getCanonicalName() + " {",
        "  public static void main(java.lang.String[]);",
        "}",
        keep + " class " + TestClass.class.getCanonicalName() + " {",
        "  *;",
        "}",
        keep + " class " + OtherPackageTestClass.class.getCanonicalName() + " {",
        "  *;",
        "}",
        "-dontwarn java.lang.invoke.*"
    );

    AndroidApp app = runShrinker(shrinker, CLASSES, config);
    assertEquals(
        StringUtils.withNativeLineSeparator("123451234567\nABC\n"),
        runOnVM(app, mainClass.getCanonicalName(), shrinker.toBackend()));

    CodeInspector codeInspector =
        shrinker.isR8() ? new CodeInspector(app) : new CodeInspector(app, proguardMap);
    ClassSubject testClass = codeInspector.clazz(TestClass.class);
    assertThat(testClass, isPresent());

    // Test the totally unused method.
    MethodSubject staticMethod = testClass.uniqueMethodWithName("unused");
    assertThat(staticMethod, isPresent());
    assertEquals(minify, staticMethod.isRenamed());
    if (shrinker.isR8()) {
      assertEquals(allowAccessModification, staticMethod.getMethod().accessFlags.isPublic());
    } else {
      assertFalse(staticMethod.getMethod().accessFlags.isPublic());
    }

    // Test an indirectly referred method.
    staticMethod = testClass.uniqueMethodWithName("staticMethod");
    assertThat(staticMethod, isPresent());
    assertEquals(minify, staticMethod.isRenamed());
    boolean publicizeCondition = shrinker.isR8() ? allowAccessModification
        : minify && repackagePrefix != null && allowAccessModification;
    assertEquals(publicizeCondition, staticMethod.getMethod().accessFlags.isPublic());
  }

  @Test
  public void test_keepNonPublic() throws Exception {
    Assume.assumeFalse(shrinker.generatesDex() && vmVersionIgnored());
    Class<?> mainClass = TestMain.class;
    String keep = !minify ? "-keep" : "-keep,allowobfuscation";
    List<String> config = ImmutableList.of(
        "-printmapping",
        repackagePrefix != null ? "-repackageclasses '" + repackagePrefix + "'" : "",
        allowAccessModification ? "-allowaccessmodification" : "",
        !minify ? "-dontobfuscate" : "",
        "-keep class " + mainClass.getCanonicalName() + " {",
        "  public static void main(java.lang.String[]);",
        "}",
        keep + " class " + TestClass.class.getCanonicalName() + " {",
        "  !public <methods>;",
        "}",
        keep + " class " + OtherPackageTestClass.class.getCanonicalName() + " {",
        "  !public <methods>;",
        "}",
        "-dontwarn java.lang.invoke.*"
    );

    AndroidApp app = runShrinker(shrinker, CLASSES, config);
    assertEquals(
        StringUtils.withNativeLineSeparator("123451234567\nABC\n"),
        runOnVM(app, mainClass.getCanonicalName(), shrinker.toBackend()));

    CodeInspector codeInspector =
        shrinker.isR8() ? new CodeInspector(app) : new CodeInspector(app, proguardMap);
    ClassSubject testClass = codeInspector.clazz(TestClass.class);
    assertThat(testClass, isPresent());

    // Test the totally unused method.
    MethodSubject staticMethod = testClass.uniqueMethodWithName("unused");
    assertThat(staticMethod, isPresent());
    assertEquals(minify, staticMethod.isRenamed());
    if (shrinker.isR8()) {
      assertEquals(allowAccessModification, staticMethod.getMethod().accessFlags.isPublic());
    } else {
      assertFalse(staticMethod.getMethod().accessFlags.isPublic());
    }

    // Test an indirectly referred method.
    staticMethod = testClass.uniqueMethodWithName("staticMethod");
    assertThat(staticMethod, isPresent());
    assertEquals(minify, staticMethod.isRenamed());
    boolean publicizeCondition = shrinker.isR8() ? allowAccessModification
        : minify && repackagePrefix != null && allowAccessModification;
    assertEquals(publicizeCondition, staticMethod.getMethod().accessFlags.isPublic());
  }

  @Test
  public void test_keepPublic() throws Exception {
    Assume.assumeFalse(shrinker.generatesDex() && vmVersionIgnored());
    Class<?> mainClass = TestMain.class;
    String keep = !minify ? "-keep" : "-keep,allowobfuscation";
    Iterable<String> config = ImmutableList.of(
        "-printmapping",
        repackagePrefix != null ? "-repackageclasses '" + repackagePrefix + "'" : "",
        allowAccessModification ? "-allowaccessmodification" : "",
        !minify ? "-dontobfuscate" : "",
        "-keep class " + mainClass.getCanonicalName() + " {",
        "  public static void main(java.lang.String[]);",
        "}",
        keep + " class " + TestClass.class.getCanonicalName() + " {",
        "  public <methods>;",
        "}",
        keep + " class " + OtherPackageTestClass.class.getCanonicalName() + " {",
        "  public <methods>;",
        "}",
        "-dontwarn java.lang.invoke.*"
    );
    if (shrinker.isR8()) {
      config =
          Iterables.concat(
              config,
              ImmutableList.of(
                  "-assumemayhavesideeffects class " + TestClass.class.getCanonicalName() + " {",
                  "  * staticMethod();",
                  "}",
                  "-neverpropagatevalue class * {",
                  "  @com.android.tools.r8.NeverPropagateValue <methods>;",
                  "}",
                  "-neverinline class " + TestClass.class.getCanonicalName() + " {",
                  "  * staticMethod();",
                  "}"));
    }

    AndroidApp app = runShrinker(shrinker, CLASSES, config);
    assertEquals(
        StringUtils.withNativeLineSeparator("123451234567\nABC\n"),
        runOnVM(app, mainClass.getCanonicalName(), shrinker.toBackend()));

    CodeInspector codeInspector =
        shrinker.isR8() ? new CodeInspector(app) : new CodeInspector(app, proguardMap);
    ClassSubject testClass = codeInspector.clazz(TestClass.class);
    assertThat(testClass, isPresent());

    // Test the totally unused method.
    MethodSubject staticMethod = testClass.uniqueMethodWithName("unused");
    assertThat(staticMethod, not(isPresent()));

    // Test an indirectly referred method.
    staticMethod = testClass.uniqueMethodWithName("staticMethod");
    assertThat(staticMethod, isPresent());
    assertEquals(minify, staticMethod.isRenamed());
    boolean publicizeCondition = shrinker.isR8() ? allowAccessModification
        : minify && repackagePrefix != null && allowAccessModification;
    assertEquals(publicizeCondition, staticMethod.getMethod().accessFlags.isPublic());
  }
}
