// 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.shaking.ifrule;

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

import com.android.tools.r8.shaking.forceproguardcompatibility.ProguardCompatibilityTestBase;
import com.android.tools.r8.utils.InternalOptions;
import com.android.tools.r8.utils.codeinspector.ClassSubject;
import com.android.tools.r8.utils.codeinspector.CodeInspector;
import com.android.tools.r8.utils.codeinspector.FieldSubject;
import com.android.tools.r8.utils.codeinspector.MethodSubject;
import com.google.common.collect.ImmutableList;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.function.Consumer;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.Parameterized;
import org.junit.runners.Parameterized.Parameters;

@RunWith(Parameterized.class)
public class IfOnClassTest extends ProguardCompatibilityTestBase {
  private final static List<Class> CLASSES = ImmutableList.of(
      EmptyMainClassForIfOnClassTests.class,
      Precondition.class, DependentUser.class, Dependent.class);

  private final Shrinker shrinker;
  private final boolean keepPrecondition;

  public IfOnClassTest(Shrinker shrinker, boolean keepPrecondition) {
    this.shrinker = shrinker;
    this.keepPrecondition = keepPrecondition;
  }

  @Parameters(name = "shrinker: {0} precondition: {1}")
  public static Collection<Object[]> data() {
    return ImmutableList.of(
        new Object[] {Shrinker.PROGUARD6, true},
        new Object[] {Shrinker.PROGUARD6, false},
        new Object[] {Shrinker.R8, true},
        new Object[] {Shrinker.R8, false},
        new Object[] {Shrinker.R8_CF, true},
        new Object[] {Shrinker.R8_CF, false});
  }

  private String adaptConfiguration(String proguardConfig) {
    List<String> configWithPrecondition = new ArrayList<>();
    configWithPrecondition.add(
        keepMainProguardConfiguration(EmptyMainClassForIfOnClassTests.class));
    if (keepPrecondition) {
      configWithPrecondition.add("-keep class **.Precondition");
    }
    configWithPrecondition.add(proguardConfig);
    return String.join(System.lineSeparator(), configWithPrecondition);
  }

  @Override
  protected CodeInspector inspectR8Result(
      List<Class> programClasses,
      String proguardConfig,
      Consumer<InternalOptions> configure,
      Backend backend)
      throws Exception {
    return super.inspectR8Result(
        programClasses, adaptConfiguration(proguardConfig), configure, backend);
  }

  @Override
  protected CodeInspector inspectProguard5Result(List<Class> programClasses, String proguardConfig)
      throws Exception {
    return super.inspectProguard5Result(programClasses, adaptConfiguration(proguardConfig));
  }

  @Override
  protected CodeInspector inspectProguard6Result(List<Class> programClasses, String proguardConfig)
      throws Exception {
    return super.inspectProguard6Result(programClasses, adaptConfiguration(proguardConfig));
  }

  @Test
  public void ifThenKeep_withoutNthWildcard() throws Exception {
    List<String> config = ImmutableList.of(
        "-if class **.Precondition",
        "-keep,allowobfuscation class **.*User",
        "-if class **.DependentUser",
        "-keep,allowobfuscation class **.Dependent"
    );

    CodeInspector codeInspector = inspectAfterShrinking(shrinker, CLASSES, config);
    if (!keepPrecondition) {
      // TODO(b/73708139): Proguard6 kept Dependent (w/o any members), which is not necessary.
      if (shrinker == Shrinker.PROGUARD6) {
        return;
      }
      assertEquals(1, codeInspector.allClasses().size());
      return;
    }

    ClassSubject clazz = codeInspector.clazz(DependentUser.class);
    assertThat(clazz, isRenamed());
    // Members of DependentUser are not used anywhere.
    MethodSubject m = clazz.method("void", "callFoo", ImmutableList.of());
    assertThat(m, not(isPresent()));
    FieldSubject f = clazz.field("int", "canBeShrinked");
    assertThat(f, not(isPresent()));

    // Although DependentUser#callFoo is shrinked, Dependent is kept via -if.
    clazz = codeInspector.clazz(Dependent.class);
    assertThat(clazz, isRenamed());
    // But, its members are gone.
    m = clazz.method("java.lang.String", "foo", ImmutableList.of());
    assertThat(m, not(isPresent()));
    f = clazz.field("int", "intField");
    assertThat(f, not(isPresent()));
  }

  @Test
  public void ifThenKeep_withNthWildcard() throws Exception {
    List<String> config = ImmutableList.of(
        "-if class **.Precondition",
        "-keep,allowobfuscation class **.*User",
        "-if class **.*User",
        "-keep,allowobfuscation class <1>.<2>"
    );

    CodeInspector codeInspector = inspectAfterShrinking(shrinker, CLASSES, config);
    if (!keepPrecondition) {
      // TODO(b/73708139): Proguard6 kept Dependent (w/o any members), which is not necessary.
      if (shrinker == Shrinker.PROGUARD6) {
        return;
      }
      assertEquals(1, codeInspector.allClasses().size());
      return;
    }

    ClassSubject clazz = codeInspector.clazz(DependentUser.class);
    assertThat(clazz, isRenamed());
    // Members of DependentUser are not used anywhere.
    MethodSubject m = clazz.method("void", "callFoo", ImmutableList.of());
    assertThat(m, not(isPresent()));
    FieldSubject f = clazz.field("int", "canBeShrinked");
    assertThat(f, not(isPresent()));

    // Although DependentUser#callFoo is shrinked, Dependent is kept via -if.
    clazz = codeInspector.clazz(Dependent.class);
    assertThat(clazz, isRenamed());
    // But, its members are gone.
    m = clazz.method("java.lang.String", "foo", ImmutableList.of());
    assertThat(m, not(isPresent()));
    f = clazz.field("int", "intField");
    assertThat(f, not(isPresent()));
  }

  @Test
  public void ifThenKeepClassesWithMembers() throws Exception {
    List<String> config = ImmutableList.of(
        "-if class **.Precondition",
        "-keepclasseswithmembers,allowobfuscation class **.*User {",
        "  static void callFoo(...);",
        "}"
    );

    CodeInspector codeInspector = inspectAfterShrinking(shrinker, CLASSES, config);
    if (!keepPrecondition) {
      assertEquals(1, codeInspector.allClasses().size());
      return;
    }

    ClassSubject clazz = codeInspector.clazz(DependentUser.class);
    assertThat(clazz, isRenamed());
    MethodSubject m = clazz.method("void", "callFoo", ImmutableList.of());
    assertThat(m, isRenamed());
    FieldSubject f = clazz.field("int", "canBeShrinked");
    assertThat(f, not(isPresent()));

    // Dependent is kept due to DependentUser#callFoo, but renamed.
    clazz = codeInspector.clazz(Dependent.class);
    assertThat(clazz, isRenamed());
    m = clazz.method("java.lang.String", "foo", ImmutableList.of());
    assertThat(m, isRenamed());
    f = clazz.field("int", "intField");
    assertThat(f, isRenamed());
  }

  @Test
  public void ifThenKeepClassMembers_withoutNthWildcard() throws Exception {
    List<String> config = ImmutableList.of(
        "-if class **.Precondition",
        "-keepclassmembers,allowobfuscation class **.*User {",
        "  static void callFoo(...);",
        "}",
        // If the member is kept, keep the enclosing class too.
        "-if class **.*User {",
        "  static void callFoo(...);",
        "}",
        "-keep,allowobfuscation class **.*User"
    );

    CodeInspector codeInspector = inspectAfterShrinking(shrinker, CLASSES, config);
    if (!keepPrecondition) {
      // TODO(b/73708139): Proguard6 kept DependentUser (w/o any members), which is not necessary.
      if (shrinker == Shrinker.PROGUARD6) {
        return;
      }
      assertEquals(1, codeInspector.allClasses().size());
      return;
    }

    ClassSubject clazz = codeInspector.clazz(DependentUser.class);
    assertThat(clazz, isRenamed());
    MethodSubject m = clazz.method("void", "callFoo", ImmutableList.of());
    assertThat(m, isRenamed());
    FieldSubject f = clazz.field("int", "canBeShrinked");
    assertThat(f, not(isPresent()));

    // Dependent is kept due to DependentUser#callFoo, but renamed.
    clazz = codeInspector.clazz(Dependent.class);
    assertThat(clazz, isRenamed());
    m = clazz.method("java.lang.String", "foo", ImmutableList.of());
    assertThat(m, isRenamed());
    f = clazz.field("int", "intField");
    assertThat(f, isRenamed());
  }

  @Test
  public void ifThenKeepClassMembers_withNthWildcard() throws Exception {
    List<String> config = ImmutableList.of(
        "-if class **.Precondition",
        "-keepclassmembers,allowobfuscation class **.*User {",
        "  static void callFoo(...);",
        "}",
        // If the member is kept, keep the enclosing class too.
        "-if class **.*User {",
        "  static void callFoo(...);",
        "}",
        "-keep,allowobfuscation class <1>.<2>User"
    );

    CodeInspector codeInspector = inspectAfterShrinking(shrinker, CLASSES, config);
    if (!keepPrecondition) {
      // TODO(b/73708139): Proguard6 kept DependentUser (w/o any members), which is not necessary.
      if (shrinker == Shrinker.PROGUARD6) {
        return;
      }
      assertEquals(1, codeInspector.allClasses().size());
      return;
    }

    ClassSubject clazz = codeInspector.clazz(DependentUser.class);
    assertThat(clazz, isRenamed());
    MethodSubject m = clazz.method("void", "callFoo", ImmutableList.of());
    assertThat(m, isRenamed());
    FieldSubject f = clazz.field("int", "canBeShrinked");
    assertThat(f, not(isPresent()));

    // Dependent is kept due to DependentUser#callFoo, but renamed.
    clazz = codeInspector.clazz(Dependent.class);
    assertThat(clazz, isRenamed());
    m = clazz.method("java.lang.String", "foo", ImmutableList.of());
    assertThat(m, isRenamed());
    f = clazz.field("int", "intField");
    assertThat(f, isRenamed());
  }

  @Test
  public void ifThenKeepNames() throws Exception {
    List<String> config = ImmutableList.of(
        // To keep DependentUser#callFoo, which in turn kept Dependent#<init> as well.
        // We're testing renaming of Dependent itself and members.
        "-keepclasseswithmembers,allowobfuscation class **.*User {",
        "  static void callFoo(...);",
        "}",
        "-if class **.Precondition",
        "-keepnames class **.Dependent"
    );

    CodeInspector codeInspector = inspectAfterShrinking(shrinker, CLASSES, config);

    ClassSubject clazz = codeInspector.clazz(Dependent.class);
    // Only class name is not renamed, if triggered.
    assertThat(clazz, keepPrecondition ? isNotRenamed() : isRenamed());
    MethodSubject m = clazz.method("java.lang.String", "foo", ImmutableList.of());
    assertThat(m, isRenamed());
    FieldSubject f = clazz.field("int", "intField");
    assertThat(f, isRenamed());
  }

  @Test
  public void ifThenKeepClassesWithMemberNames() throws Exception {
    List<String> config = ImmutableList.of(
        // To keep DependentUser#callFoo, which in turn kept Dependent#<init> as well.
        // We're testing renaming of Dependent itself and members.
        "-keepclasseswithmembers,allowobfuscation class **.*User {",
        "  static void callFoo(...);",
        "}",
        "-if class **.Precondition",
        "-keepclasseswithmembernames class **.Dependent {",
        "  <methods>;",
        "}"
    );

    CodeInspector codeInspector = inspectAfterShrinking(shrinker, CLASSES, config);

    ClassSubject clazz = codeInspector.clazz(Dependent.class);
    // Class name is not renamed, if triggered.
    assertThat(clazz, keepPrecondition ? isNotRenamed() : isRenamed());
    MethodSubject m = clazz.method("java.lang.String", "foo", ImmutableList.of());
    // Method name is not renamed either, if triggered.
    assertThat(m, keepPrecondition ? isNotRenamed() : isRenamed());
    FieldSubject f = clazz.field("int", "intField");
    assertThat(f, isRenamed());
  }

  @Test
  public void ifThenKeepClassMemberNames() throws Exception {
    List<String> config = ImmutableList.of(
        // To keep DependentUser#callFoo, which in turn kept Dependent#<init> as well.
        // We're testing renaming of Dependent itself and members.
        "-keepclasseswithmembers,allowobfuscation class **.*User {",
        "  static void callFoo(...);",
        "}",
        "-if class **.Precondition",
        "-keepclassmembernames class **.Dependent {",
        "  <methods>;",
        "}"
    );

    CodeInspector codeInspector = inspectAfterShrinking(shrinker, CLASSES, config);

    ClassSubject clazz = codeInspector.clazz(Dependent.class);
    assertThat(clazz, isRenamed());
    MethodSubject m = clazz.method("java.lang.String", "foo", ImmutableList.of());
    // Only method name is not renamed, if triggered.
    assertThat(m, keepPrecondition ? isNotRenamed() : isRenamed());
    FieldSubject f = clazz.field("int", "intField");
    assertThat(f, isRenamed());
  }

}
