// Copyright (c) 2022, 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.apimodel;

import static com.android.tools.r8.DiagnosticsMatcher.diagnosticMessage;
import static com.android.tools.r8.utils.codeinspector.Matchers.isAbsent;
import static com.android.tools.r8.utils.codeinspector.Matchers.isPresent;
import static org.hamcrest.CoreMatchers.containsString;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.junit.Assume.assumeTrue;

import com.android.tools.r8.ProguardVersion;
import com.android.tools.r8.TestBase;
import com.android.tools.r8.TestParameters;
import com.android.tools.r8.TestParametersCollection;
import com.android.tools.r8.TestRuntime.CfVm;
import com.android.tools.r8.ToolHelper;
import com.android.tools.r8.utils.AndroidApiLevel;
import com.android.tools.r8.utils.StringUtils;
import com.android.tools.r8.utils.codeinspector.CodeInspector;
import com.google.common.collect.ImmutableList;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.Parameterized;
import org.junit.runners.Parameterized.Parameter;
import org.junit.runners.Parameterized.Parameters;

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

  @Parameter() public TestParameters parameters;

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

  private static final String EXPECTED_OUTPUT = StringUtils.lines(TestClass.class.getTypeName());

  private void computeValuePresent(CodeInspector inspector) {
    assertThat(
        inspector.clazz(ClassValueSub.class).uniqueMethodWithOriginalName("computeValue"),
        isPresent());
  }

  private void computeValueAbsent(CodeInspector inspector) {
    assertThat(
        inspector.clazz(ClassValueSub.class).uniqueMethodWithOriginalName("computeValue"),
        isAbsent());
  }

  @Test
  public void testReference() throws Exception {
    assumeTrue(parameters.isCfRuntime());
    testForRuntime(parameters)
        .addInnerClasses(getClass())
        .run(parameters.getRuntime(), TestClass.class)
        .assertSuccessWithOutput(EXPECTED_OUTPUT);
  }

  @Test
  public void testD8() throws Exception {
    parameters.assumeDexRuntime();
    testForD8()
        .addInnerClasses(getClass())
        .setMinApi(parameters)
        .compile()
        .inspect(this::computeValuePresent)
        .run(parameters.getRuntime(), TestClass.class)
        .assertFailureWithErrorThatThrows(NoClassDefFoundError.class);
  }

  @Test
  public void testR8() throws Exception {
    testForR8(parameters.getBackend())
        .addLibraryFiles(ToolHelper.getAndroidJar(AndroidApiLevel.T))
        .addInnerClasses(getClass())
        .addKeepMainRule(TestClass.class)
        .setMinApi(parameters)
        .addDontWarn(ClassValue.class)
        .compile()
        .inspect(this::computeValueAbsent)
        .run(parameters.getRuntime(), TestClass.class)
        .applyIf(
            parameters.isCfRuntime(),
            r -> r.assertFailureWithErrorThatThrows(AbstractMethodError.class),
            r -> r.assertFailureWithErrorThatThrows(NoClassDefFoundError.class));
  }

  @Test
  public void testProguard() throws Exception {
    assumeTrue(parameters.isCfRuntime());
    testForProguard(ProguardVersion.V7_0_0)
        .addLibraryFiles(ToolHelper.getAndroidJar(AndroidApiLevel.T))
        .addInnerClasses(getClass())
        .addKeepMainRule(TestClass.class)
        .setMinApi(parameters)
        // ProGuard warns about the inner class attributes referring to this outer class.
        .addDontWarn(this.getClass().getTypeName())
        // ProGuard also warns about ClassValueSub not having method get.
        .addDontWarn(ClassValueSub.class.getTypeName())
        .compile()
        .inspect(this::computeValueAbsent)
        .run(parameters.getRuntime(), TestClass.class)
        .applyIf(
            parameters.isCfRuntime(),
            r -> r.assertFailureWithErrorThatThrows(AbstractMethodError.class),
            r -> r.assertFailureWithErrorThatThrows(NoClassDefFoundError.class));
  }

  @Test
  public void testR8KeepExtendsMissingType() throws Exception {
    testForR8(parameters.getBackend())
        .addLibraryFiles(ToolHelper.getAndroidJar(AndroidApiLevel.T))
        .addInnerClasses(getClass())
        .addKeepMainRule(TestClass.class)
        .setMinApi(parameters)
        .addDontWarn(ClassValue.class)
        // Try to keep computeValue on classes extending unknown type.
        .addKeepRules("-keep class * extends " + ClassValue.class.getTypeName() + " { *; }")
        .allowUnusedProguardConfigurationRules()
        .compileWithExpectedDiagnostics(
            diagnostics ->
                diagnostics.assertInfoThatMatches(
                    diagnosticMessage(
                        containsString(
                            "Proguard configuration rule does not match anything: "
                                + "`-keep class * extends "
                                + ClassValue.class.getTypeName()
                                + " {"))))
        .inspect(this::computeValueAbsent)
        .run(parameters.getRuntime(), TestClass.class)
        .applyIf(
            parameters.isCfRuntime(),
            r -> r.assertFailureWithErrorThatThrows(AbstractMethodError.class),
            r -> r.assertFailureWithErrorThatThrows(NoClassDefFoundError.class));
  }

  @Test
  public void testProguardKeepExtendsMissingTypeProguard() throws Exception {
    assumeTrue(parameters.isCfRuntime() && parameters.asCfRuntime().getVm() == CfVm.JDK11);
    testForProguard(ProguardVersion.V7_0_0)
        .addLibraryFiles(ToolHelper.getAndroidJar(AndroidApiLevel.T))
        .addInnerClasses(getClass())
        .addKeepMainRule(TestClass.class)
        .setMinApi(parameters)
        // ProGuard warns about the inner class attributes referring to this outer class.
        .addDontWarn(this.getClass().getTypeName())
        // Just -dontwarn on ClassValue is not sufficient. ProGuard also warns about ClassValueSub
        // not having method get.
        .addDontWarn(ClassValueSub.class.getTypeName())
        // Try to keep computeValue on classes extending unknown type.
        .addKeepRules("-keep class * extends " + ClassValue.class.getTypeName() + " { *; }")
        // TODO(b/261971620): Support extends matching names of missing classes.
        .compile()
        .inspect(this::computeValueAbsent)
        .run(parameters.getRuntime(), TestClass.class)
        .assertFailureWithErrorThatThrows(AbstractMethodError.class);
  }

  @Test
  public void testR8KeepConcreteMethod() throws Exception {
    for (String dontWarn :
        ImmutableList.of(ClassValue.class.getTypeName(), ClassValueSub.class.getTypeName())) {
      testForR8(parameters.getBackend())
          .addLibraryFiles(ToolHelper.getAndroidJar(AndroidApiLevel.T))
          .addInnerClasses(getClass())
          .addKeepMainRule(TestClass.class)
          .setMinApi(parameters)
          .addDontWarn(dontWarn)
          .addKeepRules(
              "-keep class "
                  + ClassValueSub.class.getTypeName()
                  + " { ** computeValue(java.lang.Class); }")
          .compile()
          .inspect(this::computeValuePresent)
          .run(parameters.getRuntime(), TestClass.class)
          .applyIf(
              parameters.isCfRuntime(),
              r -> r.assertSuccessWithOutput(EXPECTED_OUTPUT),
              r -> r.assertFailureWithErrorThatThrows(NoClassDefFoundError.class));
    }
  }

  @Test
  public void testProguardKeepConcreteMethod() throws Exception {
    assumeTrue(parameters.isCfRuntime() && parameters.asCfRuntime().getVm() == CfVm.JDK11);
    testForProguard(ProguardVersion.V7_0_0)
        .addInnerClasses(getClass())
        .addKeepMainRule(TestClass.class)
        // ProGuard warns about the inner class attributes referring to this outer class.
        .addDontWarn(this.getClass().getTypeName())
        // Just -dontwarn on ClassValue is not sufficient. ProGuard also warns about ClassValueSub
        // not having method get.
        .addDontWarn(ClassValueSub.class.getTypeName())
        .addKeepRules(
            "-keep class "
                + ClassValueSub.class.getTypeName()
                + " { ** computeValue(java.lang.Class); }")
        .compile()
        .inspect(this::computeValuePresent)
        .run(parameters.getRuntime(), TestClass.class)
        .applyIf(
            parameters.isCfRuntime(),
            r -> r.assertSuccessWithOutput(EXPECTED_OUTPUT),
            r -> r.assertFailureWithErrorThatThrows(NoClassDefFoundError.class));
  }

  static class ClassValueSub extends ClassValue<Object> {
    @Override
    protected Object computeValue(Class<?> clazz) {
      return clazz.getTypeName();
    }
  }

  static class TestClass {
    static ClassValueSub classValueSub = new ClassValueSub();

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