// 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;

import static com.android.tools.r8.DiagnosticsMatcher.diagnosticException;
import static com.android.tools.r8.utils.codeinspector.Matchers.isPresent;
import static org.hamcrest.CoreMatchers.not;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;

import com.android.tools.r8.CompilationFailedException;
import com.android.tools.r8.R8;
import com.android.tools.r8.TestBase;
import com.android.tools.r8.TestParameters;
import com.android.tools.r8.TestParametersCollection;
import com.android.tools.r8.ToolHelper;
import com.android.tools.r8.utils.codeinspector.ClassSubject;
import com.android.tools.r8.utils.codeinspector.CodeInspector;
import com.android.tools.r8.utils.codeinspector.FoundClassSubject;
import com.android.tools.r8.utils.codeinspector.FoundMethodSubject;
import com.android.tools.r8.utils.codeinspector.MethodSubject;
import com.android.tools.r8.utils.graphinspector.GraphInspector;
import com.google.common.collect.Sets;
import com.google.common.collect.Sets.SetView;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.Collections;
import java.util.List;
import java.util.Set;
import java.util.TreeSet;
import java.util.stream.Collectors;
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 KeepAnnotatedMemberTest extends TestBase {

  private static final Path R8_JAR = Paths.get(ToolHelper.THIRD_PARTY_DIR, "r8", "r8.jar");
  private static final String ABSENT_ANNOTATION = "com.android.tools.r8.MissingAnnotation";
  private static final String PRESENT_ANNOTATION =
      "com.android.tools.r8.com.google.common.annotations.VisibleForTesting";

  private static final String CLASS_WITH_ANNOTATED_METHOD =
      "com.android.tools.r8.com.google.common.math.IntMath";

  private static final String ANNOTATED_METHOD = "lessThanBranchFree";

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

  public KeepAnnotatedMemberTest(TestParameters parameters) {
    parameters.assertNoneRuntime();
  }

  @Test
  public void testPresence() throws Exception {
    CodeInspector inspector = new CodeInspector(R8_JAR);
    assertThat(inspector.clazz(ABSENT_ANNOTATION), not(isPresent()));
    assertThat(inspector.clazz(PRESENT_ANNOTATION), isPresent());
    ClassSubject clazz = inspector.clazz(CLASS_WITH_ANNOTATED_METHOD);
    MethodSubject method = clazz.uniqueMethodWithName(ANNOTATED_METHOD);
    assertThat(method, isPresent());
  }

  // TODO(b/159966986): A general keep rule should not cause compiler assertion errors.
  @Test(expected = CompilationFailedException.class)
  public void testPresentAnnotation() throws Exception {
    testForR8(Backend.CF)
        .addProgramFiles(R8_JAR)
        .addKeepRules("-keep class * { @" + PRESENT_ANNOTATION + " *; }")
        .addDontWarnGoogle()
        .addDontWarnJavax()
        .addDontWarn("org.codehaus.mojo.animal_sniffer.IgnoreJRERequirement")
        .compileWithExpectedDiagnostics(
            diagnostics ->
                diagnostics.assertErrorsMatch(diagnosticException(AssertionError.class)));
  }

  @Test
  public void testPresentAnnotationSplit() throws Exception {
    // These rules should be equivalent to the above.
    testForR8(Backend.CF)
        .addProgramFiles(R8_JAR)
        .addKeepRules(
            "-keep class *", "-keepclassmembers class * { @" + PRESENT_ANNOTATION + " *; }")
        .addDontWarnGoogle()
        .addDontWarnJavax()
        .addDontWarn("org.codehaus.mojo.animal_sniffer.IgnoreJRERequirement")
        .compile();
  }

  @Test
  public void testWithMembersAbsentAnnotation() throws Exception {
    testForR8(Backend.CF)
        .addProgramFiles(R8_JAR)
        .allowUnusedProguardConfigurationRules()
        .addKeepRules("-keepclasseswithmembers class * { @" + ABSENT_ANNOTATION + " *; }")
        .compile()
        .inspect(inspector -> assertEquals(0, inspector.allClasses().size()));
  }

  @Test
  public void testWithMembersPresentAnnotation() throws Exception {
    testForR8(Backend.CF)
        .addProgramFiles(R8_JAR)
        .addKeepRules("-keepclasseswithmembers class * { @" + PRESENT_ANNOTATION + " *** *(...); }")
        .addDontWarnGoogle()
        .addDontWarnJavax()
        .addDontWarn("org.codehaus.mojo.animal_sniffer.IgnoreJRERequirement")
        .compile()
        .inspect(
            inspector -> {
              ClassSubject clazz = inspector.clazz(CLASS_WITH_ANNOTATED_METHOD);
              assertThat(clazz, isPresent());
              assertThat(clazz.uniqueMethodWithName(ANNOTATED_METHOD), isPresent());
            });
  }

  @Test
  public void testUnsatisfiedClassMembersPresentAnnotation() throws Exception {
    testForR8(Backend.CF)
        .addProgramFiles(R8_JAR)
        // TODO(b/159971974): Technically this rule does not hit anything and should fail due to
        //  missing allowUnusedProguardConfigurationRules()
        .addKeepRules("-keepclassmembers class * { @" + PRESENT_ANNOTATION + " *** *(...); }")
        .compile()
        .inspect(inspector -> assertEquals(0, inspector.allClasses().size()));
  }

  @Test
  public void testSatisfiedClassMembersPresentAnnotation() throws Exception {
    testForR8(Backend.CF)
        .addProgramFiles(R8_JAR)
        .addKeepClassRules(CLASS_WITH_ANNOTATED_METHOD)
        .addKeepRules("-keepclassmembers class * { @" + PRESENT_ANNOTATION + " *** *(...); }")
        .compile()
        .inspect(
            inspector -> {
              assertEquals(1, inspector.allClasses().size());
              List<FoundMethodSubject> methods =
                  inspector.clazz(CLASS_WITH_ANNOTATED_METHOD).allMethods();
              assertEquals(
                  1, methods.stream().filter(m -> m.getOriginalName().equals("<init>")).count());
              assertEquals(
                  1,
                  methods.stream()
                      .filter(m -> m.getOriginalName().equals(ANNOTATED_METHOD))
                      .count());
              assertEquals(2, methods.size());
            });
  }

  @Test
  public void testUnsatisfiedConditionalPresentAnnotation() throws Exception {
    testForR8(Backend.CF)
        .addProgramFiles(R8_JAR)
        .allowUnusedProguardConfigurationRules()
        .addKeepRules("-if class * -keep class <1> { @" + PRESENT_ANNOTATION + " *** *(...); }")
        .compile()
        .inspect(inspector -> assertEquals(0, inspector.allClasses().size()));
  }

  @Test
  public void testSatisfiedConditionalPresentAnnotation() throws Exception {
    testForR8(Backend.CF)
        .addProgramFiles(R8_JAR)
        .addKeepClassRules(CLASS_WITH_ANNOTATED_METHOD)
        .addKeepRules("-if class * -keep class <1> { @" + PRESENT_ANNOTATION + " *** *(...); }")
        .compile()
        .inspect(
            inspector -> {
              assertEquals(1, inspector.allClasses().size());
              List<FoundMethodSubject> methods =
                  inspector.clazz(CLASS_WITH_ANNOTATED_METHOD).allMethods();
              assertEquals(
                  1, methods.stream().filter(m -> m.getOriginalName().equals("<init>")).count());
              // TODO(b/132318609): This should have the annotated method, but does not due to the
              //  annotation being removed.
              assertEquals(
                  0,
                  methods.stream()
                      .filter(m -> m.getOriginalName().equals(ANNOTATED_METHOD))
                      .count());
              assertEquals(1, methods.size());
            });
  }

  @Test
  public void testConditionalEqualsKeepClassMembers() throws Exception {
    GraphInspector referenceInspector =
        testForR8(Backend.CF)
            .enableGraphInspector()
            .addProgramFiles(R8_JAR)
            .addKeepMainRule(R8.class)
            .addKeepClassRules(CLASS_WITH_ANNOTATED_METHOD)
            // TODO(b/132318609): Remove keep annotation once fixed.
            .addKeepClassRules(PRESENT_ANNOTATION)
            .addKeepRules("-keepclassmembers class * { @" + PRESENT_ANNOTATION + " *** *(...); }")
            .addDontWarnGoogle()
            .addDontWarnJavaxNullableAnnotation()
            .compile()
            .graphInspector();

    GraphInspector ifThenKeepClassMembersInspector =
        testForR8(Backend.CF)
            .enableGraphInspector()
            .addProgramFiles(R8_JAR)
            .addKeepMainRule(R8.class)
            .addKeepClassRules(CLASS_WITH_ANNOTATED_METHOD)
            // TODO(b/132318609): Remove keep annotation once fixed.
            .addKeepClassRules(PRESENT_ANNOTATION)
            .addKeepRules(
                "-if class * "
                    + "-keepclassmembers class <1> { @"
                    + PRESENT_ANNOTATION
                    + " *** *(...); }")
            .addDontWarnGoogle()
            .addDontWarnJavaxNullableAnnotation()
            .compile()
            .graphInspector();
    assertRetainedClassesEqual(referenceInspector, ifThenKeepClassMembersInspector, false, false);

    GraphInspector ifThenKeepClassesWithMembersInspector =
        testForR8(Backend.CF)
            .enableGraphInspector()
            .addProgramFiles(R8_JAR)
            .addKeepMainRule(R8.class)
            .addKeepClassRules(CLASS_WITH_ANNOTATED_METHOD)
            // TODO(b/132318609): Remove keep annotation once fixed.
            .addKeepClassRules(PRESENT_ANNOTATION)
            .addKeepRules(
                "-if class * "
                    + "-keepclasseswithmembers class <1> { @"
                    + PRESENT_ANNOTATION
                    + " *** *(...); }")
            .addDontWarnGoogle()
            .addDontWarnJavaxNullableAnnotation()
            .compile()
            .graphInspector();
    assertRetainedClassesEqual(
        referenceInspector, ifThenKeepClassesWithMembersInspector, false, false);

    GraphInspector ifHasMemberThenKeepClassInspector =
        testForR8(Backend.CF)
            .enableGraphInspector()
            .addProgramFiles(R8_JAR)
            .addKeepMainRule(R8.class)
            .addKeepClassRules(CLASS_WITH_ANNOTATED_METHOD)
            // TODO(b/132318609): Remove keep annotation once fixed.
            .addKeepClassRules(PRESENT_ANNOTATION)
            .addKeepRules(
                "-if class * { @"
                    + PRESENT_ANNOTATION
                    + " *** *(...); } "
                    + "-keep class <1> { @"
                    + PRESENT_ANNOTATION
                    + " *** <2>(...); }")
            .addDontWarnGoogle()
            .addDontWarnJavaxNullableAnnotation()
            .compile()
            .graphInspector();
    // TODO(b/159418523): Should the reference be equal to the result with the conditional rule?
    assertRetainedClassesEqual(referenceInspector, ifHasMemberThenKeepClassInspector, true, true);
  }

  private void assertRetainedClassesEqual(
      GraphInspector referenceResult,
      GraphInspector conditionalResult,
      boolean expectReferenceIsLarger,
      boolean expectConditionalIsLarger) {
    Set<String> referenceClasses =
        new TreeSet<>(
            referenceResult.codeInspector().allClasses().stream()
                .map(FoundClassSubject::getOriginalName)
                .collect(Collectors.toSet()));

    Set<String> conditionalClasses =
        conditionalResult.codeInspector().allClasses().stream()
            .map(FoundClassSubject::getOriginalName)
            .collect(Collectors.toSet());
    {
      SetView<String> notInReference = Sets.difference(conditionalClasses, referenceClasses);
      if (expectConditionalIsLarger) {
        assertFalse("Expected classes in -if rule to retain more.", notInReference.isEmpty());
      } else {
        assertEquals(
            "Classes in -if rule that are not in -keepclassmembers rule",
            Collections.emptySet(),
            notInReference);
      }
    }
    {
      SetView<String> notInConditional = Sets.difference(referenceClasses, conditionalClasses);
      if (expectReferenceIsLarger) {
        assertFalse(
            "Expected classes in -keepclassmembers rule to retain more.",
            notInConditional.isEmpty());
      } else {
        assertEquals(
            "Classes in -keepclassmembers rule that are not in -if rule",
            Collections.emptySet(),
            new TreeSet<>(notInConditional));
      }
    }
  }
}
