// 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.invokesMethod;
import static com.android.tools.r8.utils.codeinspector.Matchers.isPresent;
import static com.android.tools.r8.utils.codeinspector.Matchers.isPresentAndRenamed;
import static org.hamcrest.CoreMatchers.not;
import static org.hamcrest.MatcherAssert.assertThat;

import com.android.tools.r8.NoHorizontalClassMerging;
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.MethodSubject;
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 ConditionalKeepClassMethodsAllowShrinkingCompatibilityTest 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 ConditionalKeepClassMethodsAllowShrinkingCompatibilityTest(
      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",
        // Reflective lookup of A::foo will only work if optimization and obfuscation are disabled.
        Boolean.toString(!allowOptimization && !allowObfuscation),
        "false");
  }

  @Test
  public void test() throws Exception {
    if (shrinker.isR8()) {
      run(testForR8(parameters.getBackend()).enableNoHorizontalClassMergingAnnotations());
    } else {
      run(
          testForProguard(shrinker.getProguardVersion())
              .addDontWarn(getClass())
              .addNoHorizontalClassMergingAnnotations());
    }
  }

  public <T extends TestShrinkerBuilder<?, ?, ?, ?, T>> void run(T builder) throws Exception {
    String keepRule =
        "-if class * -keepclassmembers,allowshrinking"
            + (allowOptimization ? ",allowoptimization" : "")
            + (allowObfuscation ? ",allowobfuscation" : "")
            + " class <1> { java.lang.String foo(); java.lang.String bar(); }";
    builder
        .addInnerClasses(ConditionalKeepClassMethodsAllowShrinkingCompatibilityTest.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 not the methods.
              assertThat(bClass, isPresentAndRenamed());
              assertThat(bClass.uniqueMethodWithName("foo"), not(isPresent()));
              assertThat(bClass.uniqueMethodWithName("bar"), not(isPresent()));

              assertThat(aClass, isPresentAndRenamed());
              // The dependent rule with soft-pinning of bar never causes A::bar to be retained
              // regardless of A and A::foo being retained.
              assertThat(aClass.uniqueMethodWithName("bar"), not(isPresent()));
              MethodSubject aFoo = aClass.uniqueMethodWithName("foo");
              if (allowOptimization) {
                assertThat(aFoo, not(isPresent()));
              } else {
                assertThat(aFoo, isPresentAndRenamed(allowObfuscation));
                assertThat(inspector.clazz(TestClass.class).mainMethod(), invokesMethod(aFoo));
              }
            });
  }

  static class A {
    public String foo() {
      return "A::foo";
    }

    public String bar() {
      return "A::bar";
    }
  }

  @NoHorizontalClassMerging
  static class B {
    public String foo() {
      return "B::foo";
    }

    public String bar() {
      return "B::bar";
    }
  }

  static class TestClass {

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

    public static void main(String[] args) {
      // Direct call to A.foo, if optimization is not allowed it will be kept.
      A a = new A();
      System.out.println(a.foo());
      // Reference to A should not retain A::foo when allowoptimization is set.
      // Note: if using class constant A.class, PG will actually retain A::foo !?
      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()));
    }
  }
}
