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

import static com.android.tools.r8.utils.codeinspector.CodeMatchers.accessesField;
import static com.android.tools.r8.utils.codeinspector.Matchers.isPresent;
import static com.android.tools.r8.utils.codeinspector.Matchers.isPresentAndRenamed;
import static com.android.tools.r8.utils.codeinspector.Matchers.notIf;
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.TestShrinkerBuilder;
import com.android.tools.r8.utils.BooleanUtils;
import com.android.tools.r8.utils.StringUtils;
import com.android.tools.r8.utils.codeinspector.ClassSubject;
import com.android.tools.r8.utils.codeinspector.FieldSubject;
import com.google.common.collect.ImmutableList;
import java.util.List;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.Parameterized;

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

  private final TestParameters parameters;
  private final boolean allowOptimization;
  private final boolean allowObfuscation;
  private final Shrinker shrinker;

  @Parameterized.Parameters(name = "{0}, opt:{1}, obf:{2}, {3}")
  public static List<Object[]> data() {
    return buildParameters(
        getTestParameters().withCfRuntimes().build(),
        BooleanUtils.values(),
        BooleanUtils.values(),
        ImmutableList.of(Shrinker.R8, Shrinker.PG));
  }

  public KeepClassFieldsAllowShrinkingCompatibilityTest(
      TestParameters parameters,
      boolean allowOptimization,
      boolean allowObfuscation,
      Shrinker shrinker) {
    this.parameters = parameters;
    this.allowOptimization = allowOptimization;
    this.allowObfuscation = allowObfuscation;
    this.shrinker = shrinker;
  }

  String getExpected() {
    return StringUtils.lines(
        "A.foo",
        // R8 will succeed in removing the field if allowoptimization is set.
        Boolean.toString((shrinker.isPG() || !allowOptimization) && !allowObfuscation),
        // R8 will always remove the unreferenced B.foo field.
        Boolean.toString(shrinker.isPG() && !allowOptimization && !allowObfuscation));
  }

  @Test
  public void test() throws Exception {
    if (shrinker.isR8()) {
      run(
          testForR8(parameters.getBackend())
              // Allowing all of shrinking, optimization and obfuscation will amount to a nop rule.
              .allowUnusedProguardConfigurationRules(allowOptimization && allowObfuscation));
    } else {
      run(testForProguard(shrinker.getProguardVersion()).addDontWarn(getClass()));
    }
  }

  public <T extends TestShrinkerBuilder<?, ?, ?, ?, T>> void run(T builder) throws Exception {
    String keepRule =
        "-keepclassmembers,allowshrinking"
            + (allowOptimization ? ",allowoptimization" : "")
            + (allowObfuscation ? ",allowobfuscation" : "")
            + " class * { java.lang.String foo; java.lang.String bar; }";
    builder
        .addInnerClasses(KeepClassFieldsAllowShrinkingCompatibilityTest.class)
        .addKeepClassAndMembersRules(TestClass.class)
        .addKeepRules(keepRule)
        .setMinApi(parameters.getApiLevel())
        .run(parameters.getRuntime(), TestClass.class, A.class.getTypeName())
        .assertSuccessWithOutput(getExpected())
        .inspect(
            inspector -> {
              ClassSubject aClass = inspector.clazz(A.class);
              ClassSubject bClass = inspector.clazz(B.class);
              // The class constants will force A and B to be retained but renamed.
              assertThat(aClass, isPresentAndRenamed());
              assertThat(bClass, isPresentAndRenamed());

              FieldSubject aFoo = aClass.uniqueFieldWithName("foo");
              FieldSubject aBar = aClass.uniqueFieldWithName("bar");
              FieldSubject bFoo = bClass.uniqueFieldWithName("foo");
              FieldSubject bBar = bClass.uniqueFieldWithName("bar");

              if (allowOptimization) {
                // PG fails to optimize out the referenced field.
                assertThat(aFoo, notIf(isPresent(), shrinker.isR8()));
                assertThat(aBar, not(isPresent()));
                assertThat(bFoo, not(isPresent()));
                assertThat(bBar, not(isPresent()));
              } else {
                assertThat(aFoo, isPresentAndRenamed(allowObfuscation));
                // TODO(b/171459868) It is inconsistent that the unused field A.bar is retained.
                //   This does not match the R8 behavior for an unused method, so there may be an
                //   optimization opportunity here.
                //   (See KeepClassMethodsAllowShrinkingCompatibilityTest regarding methods).
                assertThat(aBar, isPresentAndRenamed(allowObfuscation));
                assertThat(inspector.clazz(TestClass.class).mainMethod(), accessesField(aFoo));
                if (shrinker.isR8()) {
                  assertThat(bFoo, not(isPresent()));
                  assertThat(bBar, not(isPresent()));
                } else {
                  assertThat(bFoo, isPresentAndRenamed(allowObfuscation));
                  assertThat(bBar, isPresentAndRenamed(allowObfuscation));
                }
              }
            });
  }

  static class A {
    // Note: If the fields are final PG actually allows itself to inline the values.
    public String foo = "A.foo";
    public String bar = "A.bar";
  }

  static class B {
    public String foo = "B.foo";
    public String bar = "B.bar";
  }

  static class TestClass {

    public static boolean hasFoo(String name) {
      try {
        return Class.forName(name).getDeclaredField("foo") != null;
      } catch (Exception e) {
        return false;
      }
    }

    public static void main(String[] args) {
      // Conditional instance to prohibit class inlining of A.
      A a = args.length == 42 ? null : new A();
      // Direct use of A.foo, if optimization is not allowed it will be kept.
      System.out.println(a.foo);
      // Reference to A should not retain A.foo when allowoptimization is set.
      System.out.println(hasFoo(a.getClass().getTypeName()));
      // Reference to B should not retain B.foo regardless of allowoptimization.
      System.out.println(hasFoo(B.class.getTypeName()));
    }
  }
}
