// 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 com.android.tools.r8.utils.codeinspector.Matchers.isRenamed;
import static org.hamcrest.CoreMatchers.not;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;

import com.android.tools.r8.TestBase;
import com.android.tools.r8.TestParameters;
import com.android.tools.r8.utils.BooleanUtils;
import com.android.tools.r8.utils.StringUtils;
import com.android.tools.r8.utils.codeinspector.ClassSubject;
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 ConditionalKeepIfKeptTest extends TestBase {

  static final String EXPECTED =
      StringUtils.lines("class " + StaticallyReferenced.class.getTypeName());

  private final TestParameters parameters;
  private final boolean useMarker;

  @Parameterized.Parameters(name = "{0}, marker:{1}")
  public static List<Object[]> data() {
    return buildParameters(
        getTestParameters().withCfRuntimes().withDexRuntimes().withAllApiLevels().build(),
        BooleanUtils.values());
  }

  public ConditionalKeepIfKeptTest(TestParameters parameters, boolean useMarker) {
    this.parameters = parameters;
    this.useMarker = useMarker;
  }

  private String getConditionalRulePrefix() {
    String clazz = StaticallyReferenced.class.getTypeName();
    return useMarker
        ? "-if @" + Marked.class.getTypeName() + " class * -keep class <1>"
        : "-if class " + clazz + " -keep class " + clazz;
  }

  @Test
  public void testIfKeepNoMembers() throws Exception {
    testForR8(parameters.getBackend())
        .addInnerClasses(ConditionalKeepIfKeptTest.class)
        .addKeepRules(getConditionalRulePrefix())
        .addKeepMainRule(TestClass.class)
        .setMinApi(parameters.getApiLevel())
        .run(parameters.getRuntime(), TestClass.class)
        .assertSuccessWithOutput(EXPECTED)
        .inspect(
            inspector -> {
              ClassSubject classSubject = inspector.clazz(StaticallyReferenced.class);
              assertThat(classSubject, isPresent());
              assertEquals(0, classSubject.allFields().size());
              // TODO(b/132318799): Should not keep <init>() when not specified.
              assertEquals(1, classSubject.allMethods().size());
              assertTrue(classSubject.init().isPresent());
            });
  }

  @Test
  public void testIfKeepAllMembers() throws Exception {
    Assume.assumeFalse("b/132318609", useMarker);
    testForR8(parameters.getBackend())
        .addInnerClasses(ConditionalKeepIfKeptTest.class)
        .addKeepRules(getConditionalRulePrefix() + " { *; }")
        .addKeepMainRule(TestClass.class)
        .setMinApi(parameters.getApiLevel())
        .run(parameters.getRuntime(), TestClass.class)
        .assertSuccessWithOutput(EXPECTED)
        .inspect(
            inspector -> {
              ClassSubject classSubject = inspector.clazz(StaticallyReferenced.class);
              assertThat(classSubject, isPresent());
              assertEquals(2, classSubject.allFields().size());
              assertEquals(3, classSubject.allMethods().size());
            });
  }

  @Test
  public void testIfKeepStaticMembers() throws Exception {
    Assume.assumeFalse("b/132318609", useMarker);
    testForR8(parameters.getBackend())
        .addInnerClasses(ConditionalKeepIfKeptTest.class)
        .addKeepRules(getConditionalRulePrefix() + " { static *; }")
        .addKeepMainRule(TestClass.class)
        .setMinApi(parameters.getApiLevel())
        .run(parameters.getRuntime(), TestClass.class)
        .assertSuccessWithOutput(EXPECTED)
        .inspect(
            inspector -> {
              ClassSubject classSubject = inspector.clazz(StaticallyReferenced.class);
              assertThat(classSubject, isPresent());
              assertEquals(1, classSubject.allFields().size());
              assertEquals(1, classSubject.allMethods().size());
            });
  }

  @Test
  public void testIfKeepNonStaticMembers() throws Exception {
    Assume.assumeFalse("b/132318609", useMarker);
    testForR8(parameters.getBackend())
        .addInnerClasses(ConditionalKeepIfKeptTest.class)
        .addKeepRules(getConditionalRulePrefix() + " { !static *; }")
        .addKeepMainRule(TestClass.class)
        .setMinApi(parameters.getApiLevel())
        .run(parameters.getRuntime(), TestClass.class)
        .assertSuccessWithOutput(EXPECTED)
        .inspect(
            inspector -> {
              ClassSubject classSubject = inspector.clazz(StaticallyReferenced.class);
              assertThat(classSubject, isPresent());
              assertEquals(1, classSubject.allFields().size());
              assertEquals(2, classSubject.allMethods().size());
            });
  }

  @Test
  public void testIfKeepFields() throws Exception {
    Assume.assumeFalse("b/132318609", useMarker);
    testForR8(parameters.getBackend())
        .addInnerClasses(ConditionalKeepIfKeptTest.class)
        .addKeepRules(getConditionalRulePrefix() + " { <fields>; }")
        .addKeepMainRule(TestClass.class)
        .setMinApi(parameters.getApiLevel())
        .run(parameters.getRuntime(), TestClass.class)
        .assertSuccessWithOutput(EXPECTED)
        .inspect(
            inspector -> {
              ClassSubject classSubject = inspector.clazz(StaticallyReferenced.class);
              assertThat(classSubject, isPresent());
              assertEquals(2, classSubject.allFields().size());
              assertEquals(0, classSubject.allMethods().size());
            });
  }

  @Test
  public void testIfKeepMethods() throws Exception {
    Assume.assumeFalse("b/132318609", useMarker);
    testForR8(parameters.getBackend())
        .addInnerClasses(ConditionalKeepIfKeptTest.class)
        .addKeepRules(getConditionalRulePrefix() + " { <methods>; }")
        .addKeepMainRule(TestClass.class)
        .setMinApi(parameters.getApiLevel())
        .run(parameters.getRuntime(), TestClass.class)
        .assertSuccessWithOutput(EXPECTED)
        .inspect(
            inspector -> {
              ClassSubject classSubject = inspector.clazz(StaticallyReferenced.class);
              assertThat(classSubject, isPresent());
              assertEquals(3, classSubject.allMethods().size());
              classSubject.allMethods().forEach(m -> assertThat(m, not(isRenamed())));
              // Keeping methods will cause the fields to be kept too (but allow renaming them).
              assertEquals(2, classSubject.allFields().size());
              classSubject.allFields().forEach(f -> assertThat(f, isRenamed()));
            });
  }

  @interface Marked {}

  @Marked
  static class StaticallyReferenced {
    static long staticField;

    static long staticMethod() {
      return staticField += System.nanoTime();
    }

    long nonStaticField;

    StaticallyReferenced() {
      nonStaticField = System.nanoTime();
    }

    long nonStaticMethod() {
      return nonStaticField;
    }
  }

  static class TestClass {

    public static void main(String[] args) {
      System.out.println(StaticallyReferenced.class);
    }
  }
}
