// Copyright (c) 2019, 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.isPresent;
import static junit.framework.TestCase.assertEquals;
import static org.hamcrest.MatcherAssert.assertThat;

import com.android.tools.r8.CompilationFailedException;
import com.android.tools.r8.TestBase;
import com.android.tools.r8.TestParameters;
import com.android.tools.r8.TestParametersCollection;
import com.android.tools.r8.utils.InternalOptions.TestingOptions.ProguardIfRuleEvaluationData;
import com.android.tools.r8.utils.codeinspector.ClassSubject;
import java.io.IOException;
import java.util.concurrent.ExecutionException;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.Parameterized;
import org.junit.runners.Parameterized.Parameters;

/**
 * This test specifically tests how many times we evaluate if rules in the enqueuer. Having multiple
 * generated appt2 rules that has same class part and have constant sequential rules can be
 * optimized considerably. The fixed numbers are what was current at the time. Feel free to update
 * these when changing the if-rule evaluator.
 */
@RunWith(Parameterized.class)
public class IfSimilarClassSpecificationBundlingTest extends TestBase {

  public static final String EXPECTED_LINE_OUTPUT = 0xCAFEBABE + "";

  public static class A {
    void a() {}
  }

  public static class B {
    void b() {}
  }

  public static class C {
    void c() {}
  }

  public static class RA {
    static int keepA = 0xCAFEBABE;
  }

  public static class RB {
    static int keepB = 0xCAFEBABE;
  }

  public static class RC {
    static int keepC = 0xCAFEBABE;
  }

  public static class Main {

    public static void main(String[] args) {
      System.out.println(RA.keepA);
      System.out.println(RB.keepB);
      System.out.println(RC.keepC);
    }
  }

  private final TestParameters parameters;

  @Parameters(name = "{0}")
  public static TestParametersCollection data() {
    return getTestParameters().withAllRuntimes().build();
  }

  public IfSimilarClassSpecificationBundlingTest(TestParameters parameters) {
    this.parameters = parameters;
  }

  @Test
  public void testBundlingOfIfRulesWithConstantSequent()
      throws IOException, CompilationFailedException, ExecutionException {
    runTest(
        8,
        12,
        "-if class **$R* { int keepA; }",
        "-keep class " + A.class.getTypeName() + " { void a(); }",
        "-if class **$R* { int keepB; }",
        "-keep class " + B.class.getTypeName() + " { void b(); }",
        "-if class **$R* { int keepC; }",
        "-keep class " + C.class.getTypeName() + " { void c(); }");
  }

  @Test
  public void testBundlingOfIfRulesWithNonConstantSequent()
      throws IOException, CompilationFailedException, ExecutionException {
    runTest(
        22,
        36,
        "-if class **$R* { int keepA; }",
        "-keep class"
            + " com.android.tools.r8.shaking.ifrule.IfSimilarClassSpecificationBundlingTest$<2> {"
            + " void a(); }",
        "-if class **$R* { int keepB; }",
        "-keep class"
            + " com.android.tools.r8.shaking.ifrule.IfSimilarClassSpecificationBundlingTest$<2> {"
            + " void b(); }",
        "-if class **$R* { int keepC; }",
        "-keep class"
            + " com.android.tools.r8.shaking.ifrule.IfSimilarClassSpecificationBundlingTest$<2> {"
            + " void c(); }");
  }

  @Test
  public void testBundlingOfIfRulesWithPositiveList()
      throws IOException, CompilationFailedException, ExecutionException {
    runTest(
        8,
        12,
        "-if class **$R*,**$X { int keepA; }",
        "-keep class " + A.class.getTypeName() + " { void a(); }",
        "-if class **$R*,**$X { int keepB; }",
        "-keep class " + B.class.getTypeName() + " { void b(); }",
        "-if class **$R*,**$X { int keepC; }",
        "-keep class " + C.class.getTypeName() + " { void c(); }");
  }

  private void runTest(
      int expectedClassEvaluations, int expectedMemberEvaluations, String... keepRules)
      throws IOException, CompilationFailedException, ExecutionException {
    class Box {
      private ProguardIfRuleEvaluationData data;
    }
    Box box = new Box();
    testForR8(parameters.getBackend())
        .addInnerClasses(IfSimilarClassSpecificationBundlingTest.class)
        .addKeepMainRule(Main.class)
        .addKeepRules(keepRules)
        .setMinApi(parameters.getRuntime())
        .addOptionsModification(
            options -> {
              options.testing.measureProguardIfRuleEvaluations = true;
              box.data = options.testing.proguardIfRuleEvaluationData;
            })
        .run(parameters.getRuntime(), Main.class)
        .assertSuccessWithOutputLines(
            EXPECTED_LINE_OUTPUT, EXPECTED_LINE_OUTPUT, EXPECTED_LINE_OUTPUT)
        .inspect(
            codeInspector -> {
              ClassSubject aSubject = codeInspector.clazz(A.class);
              assertThat(aSubject, isPresent());
              assertThat(aSubject.uniqueMethodWithName("a"), isPresent());
              ClassSubject bSubject = codeInspector.clazz(B.class);
              assertThat(bSubject, isPresent());
              assertThat(bSubject.uniqueMethodWithName("b"), isPresent());
              ClassSubject cSubject = codeInspector.clazz(C.class);
              assertThat(cSubject, isPresent());
              assertThat(cSubject.uniqueMethodWithName("c"), isPresent());
            });
    assertEquals(expectedClassEvaluations, box.data.numberOfProguardIfRuleClassEvaluations);
    assertEquals(expectedMemberEvaluations, box.data.numberOfProguardIfRuleMemberEvaluations);
  }
}
