// Copyright (c) 2023, 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.diagnosticMessage;
import static org.hamcrest.CoreMatchers.allOf;
import static org.hamcrest.CoreMatchers.containsString;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.fail;

import com.android.tools.r8.TestParameters;
import com.android.tools.r8.Version;
import com.android.tools.r8.utils.AndroidApiLevel;
import com.android.tools.r8.utils.SemanticVersion;
import com.android.tools.r8.utils.StringUtils;
import com.android.tools.r8.utils.ZipUtils.ZipBuilder;
import com.google.common.collect.ImmutableList;
import java.nio.file.Path;
import java.util.List;
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 LibraryProvidedProguardRulesR8SpecificTest
    extends LibraryProvidedProguardRulesTestBase {

  @Parameter(0)
  public TestParameters parameters;

  @Parameter(1)
  public LibraryType libraryType;

  @Parameter(2)
  public ProviderType providerType;

  @Parameters(name = "{0}, AAR: {1}, {2}")
  public static List<Object[]> data() {
    return buildParameters(
        getTestParameters().withNoneRuntime().build(),
        ImmutableList.of(LibraryType.JAR_WITH_RULES),
        ProviderType.values());
  }

  private static final String EXPECTED_A =
      StringUtils.lines(
          "-keep class A1 {", "  <init>();", "}", "-keep class A2 {", "  <init>();", "}");

  private static final String EXPECTED_B =
      StringUtils.lines(
          "-keep class B1 {", "  <init>();", "}", "-keep class B2 {", "  <init>();", "}");

  private static final String EXPECTED_C =
      StringUtils.lines(
          "-keep class C1 {", "  <init>();", "}", "-keep class C2 {", "  <init>();", "}");

  private static final String EXPECTED_D =
      StringUtils.lines(
          "-keep class D1 {", "  <init>();", "}", "-keep class D2 {", "  <init>();", "}");

  private static final String EXPECTED_E =
      StringUtils.lines(
          "-keep class E1 {", "  <init>();", "}", "-keep class E2 {", "  <init>();", "}");

  private static final String EXPECTED_X =
      StringUtils.lines(
          "-keep class X1 {", "  <init>();", "}", "-keep class X2 {", "  <init>();", "}");

  private Path buildLibrary() throws Exception {
    ZipBuilder jarBuilder =
        ZipBuilder.builder(temp.newFile(libraryType.isAar() ? "classes.jar" : "test.jar").toPath());
    if (libraryType.hasRulesInJar()) {
      jarBuilder.addText("META-INF/com.android.tools/r8/test1.pro", "-keep class A1");
      jarBuilder.addText("META-INF/com.android.tools/r8/test2.pro", "-keep class A2");
      jarBuilder.addText("META-INF/com.android.tools/r8-min-4.0.0/test1.pro", "-keep class B1");
      jarBuilder.addText("META-INF/com.android.tools/r8-min-4.0.0/test2.pro", "-keep class B2");
      jarBuilder.addText("META-INF/com.android.tools/r8-max-8.1.0/test1.pro", "-keep class C1");
      jarBuilder.addText("META-INF/com.android.tools/r8-max-8.1.0/test2.pro", "-keep class C2");
      jarBuilder.addText(
          "META-INF/com.android.tools/r8-min-5.0.0-max-8.0.0/test1.pro", "-keep class D1");
      jarBuilder.addText(
          "META-INF/com.android.tools/r8-min-5.0.0-max-8.0.0/test2.pro", "-keep class D2");
      jarBuilder.addText("META-INF/com.android.tools/r8-min-10.5.0/test1.pro", "-keep class E1");
      jarBuilder.addText("META-INF/com.android.tools/r8-min-10.5.0/test2.pro", "-keep class E2");
      jarBuilder.addText("META-INF/proguard/test1.pro", "-keep class X1");
      jarBuilder.addText("META-INF/proguard/test2.pro", "-keep class X2");
    }
    if (libraryType.isAar()) {
      // TODO(b/228319861): Also test AARs.
      fail("Not tested");
      return null;
    } else {
      return jarBuilder.build();
    }
  }

  private Path buildLibraryProguardOnlyRules(String directory) throws Exception {
    ZipBuilder jarBuilder =
        ZipBuilder.builder(
            temp.newFolder().toPath().resolve(libraryType.isAar() ? "classes.jar" : "test.jar"));
    if (libraryType.hasRulesInJar()) {
      jarBuilder.addText("META-INF/" + directory + "/test1.pro", "-keep class X1");
      jarBuilder.addText("META-INF/" + directory + "/test2.pro", "-keep class X2");
    }
    if (libraryType.isAar()) {
      // TODO(b/228319861): Also test AARs.
      fail("Not tested");
      return null;
    } else {
      return jarBuilder.build();
    }
  }

  private Path buildLibraryR8VersionAgnosticOnlyRules() throws Exception {
    ZipBuilder jarBuilder =
        ZipBuilder.builder(
            temp.newFolder().toPath().resolve(libraryType.isAar() ? "classes.jar" : "test.jar"));
    if (libraryType.hasRulesInJar()) {
      jarBuilder.addText("META-INF/com.android.tools/r8/test1.pro", "-keep class A1");
      jarBuilder.addText("META-INF/com.android.tools/r8/test2.pro", "-keep class A2");
    }
    if (libraryType.isAar()) {
      // TODO(b/228319861): Also test AARs.
      fail("Not tested");
      return null;
    } else {
      return jarBuilder.build();
    }
  }

  private Path buildLibraryProguardOnlyRules() throws Exception {
    return buildLibraryProguardOnlyRules("proguard");
  }

  private void runTest(SemanticVersion compilerVersion, String expected) throws Exception {
    Path library = buildLibrary();
    testForR8(Backend.DEX)
        .applyIf(providerType == ProviderType.API, b -> b.addProgramFiles(library))
        .applyIf(providerType == ProviderType.INJARS, b -> b.addKeepRules("-injars " + library))
        .setMinApi(AndroidApiLevel.B)
        .setFakeCompilerVersion(compilerVersion)
        .allowUnusedProguardConfigurationRules()
        .compile()
        .inspectProguardConfiguration(
            configuration -> assertEquals(expected, configuration.toString()));
  }

  @Test
  public void runTestVersion3() throws Exception {
    runTest(
        SemanticVersion.create(3, 0, 0), StringUtils.lines(EXPECTED_A.trim(), EXPECTED_C.trim()));
  }

  @Test
  public void runTestVersion4() throws Exception {
    runTest(
        SemanticVersion.create(4, 0, 0),
        StringUtils.lines(EXPECTED_A.trim(), EXPECTED_B.trim(), EXPECTED_C.trim()));
  }

  @Test
  public void runTestVersion5() throws Exception {
    runTest(
        SemanticVersion.create(5, 0, 0),
        StringUtils.lines(
            EXPECTED_A.trim(), EXPECTED_B.trim(), EXPECTED_C.trim(), EXPECTED_D.trim()));
  }

  @Test
  public void runTestVersion8() throws Exception {
    runTest(
        SemanticVersion.create(8, 0, 0),
        StringUtils.lines(
            EXPECTED_A.trim(), EXPECTED_B.trim(), EXPECTED_C.trim(), EXPECTED_D.trim()));
  }

  @Test
  public void runTestVersion8_1() throws Exception {
    runTest(
        SemanticVersion.create(8, 1, 0),
        StringUtils.lines(EXPECTED_A.trim(), EXPECTED_B.trim(), EXPECTED_C.trim()));
  }

  @Test
  public void runTestVersion8_2() throws Exception {
    runTest(
        SemanticVersion.create(8, 2, 0), StringUtils.lines(EXPECTED_A.trim(), EXPECTED_B.trim()));
  }

  @Test
  public void runTestVersion10() throws Exception {
    runTest(
        SemanticVersion.create(10, 0, 0), StringUtils.lines(EXPECTED_A.trim(), EXPECTED_B.trim()));
  }

  @Test
  public void runTestVersion10_5() throws Exception {
    runTest(
        SemanticVersion.create(10, 5, 0),
        StringUtils.lines(EXPECTED_A.trim(), EXPECTED_B.trim(), EXPECTED_E.trim()));
  }

  @Test
  public void runTestVersionMainR8VersionSpecificRules() throws Exception {
    if (!Version.isMainVersion()) {
      return;
    }
    Path library = buildLibrary();
    testForR8(Backend.DEX)
        .applyIf(
            providerType == ProviderType.API,
            b -> b.addProgramFiles(library).addProgramFiles(library))
        .applyIf(providerType == ProviderType.INJARS, b -> b.addKeepRules("-injars " + library))
        .setMinApi(AndroidApiLevel.B)
        .allowUnusedProguardConfigurationRules()
        .allowDiagnosticMessages()
        .compileWithExpectedDiagnostics(
            diagnostics ->
                assertEquals(
                    1,
                    diagnostics.getWarnings().stream()
                        .filter(
                            allOf(
                                    diagnosticMessage(containsString("Running R8 version main")),
                                    diagnosticMessage(containsString("Using version 8.1.0 for")))
                                ::matches)
                        .count()))
        .inspectProguardConfiguration(
            configuration ->
                assertEquals(
                    StringUtils.lines(EXPECTED_A.trim(), EXPECTED_B.trim(), EXPECTED_C.trim()),
                    configuration.toString()));
  }

  @Test
  public void runTestVersionMainR8VersionAgnosticOnlyRules() throws Exception {
    if (!Version.isMainVersion()) {
      return;
    }
    Path library = buildLibraryR8VersionAgnosticOnlyRules();
    testForR8(Backend.DEX)
        .applyIf(providerType == ProviderType.API, b -> b.addProgramFiles(library))
        .applyIf(providerType == ProviderType.INJARS, b -> b.addKeepRules("-injars " + library))
        .setMinApi(AndroidApiLevel.B)
        .allowUnusedProguardConfigurationRules()
        .compile()
        .inspectProguardConfiguration(
            configuration -> assertEquals(EXPECTED_A, configuration.toString()));
  }

  @Test
  public void testProguardOnlyRules() throws Exception {
    Path library = buildLibraryProguardOnlyRules();
    testForR8(Backend.DEX)
        .applyIf(providerType == ProviderType.API, b -> b.addProgramFiles(library))
        .applyIf(providerType == ProviderType.INJARS, b -> b.addKeepRules("-injars " + library))
        .setMinApi(AndroidApiLevel.B)
        .setFakeCompilerVersion(SemanticVersion.create(1, 2, 3))
        .allowUnusedProguardConfigurationRules()
        .compile()
        .inspectProguardConfiguration(
            configuration -> assertEquals(EXPECTED_X, configuration.toString()));
  }

  @Test
  public void testProguardOnlyRulesVersionMain() throws Exception {
    Path library = buildLibraryProguardOnlyRules();
    testForR8(Backend.DEX)
        .applyIf(providerType == ProviderType.API, b -> b.addProgramFiles(library))
        .applyIf(providerType == ProviderType.INJARS, b -> b.addKeepRules("-injars " + library))
        .setMinApi(AndroidApiLevel.B)
        .allowUnusedProguardConfigurationRules()
        .compile()
        .inspectProguardConfiguration(
            configuration -> assertEquals(EXPECTED_X, configuration.toString()));
  }

  @Test
  public void testUnusedProguardOnlyRules() throws Exception {
    for (String directory :
        ImmutableList.of(
            "proguard-min-6.1.0",
            "proguard-max-7.0.0",
            "proguard-min-6.1.0-max-7.0.0",
            "proguard610",
            "com.android.tools/proguard",
            "com.android.tools/proguard-min-6.1.0",
            "com.android.tools/proguard-max-7.0.0",
            "com.android.tools/proguard-min-6.1.0-max-7.0.0",
            "com.android.tools/proguard610")) {
      Path library = buildLibraryProguardOnlyRules(directory);
      testForR8(Backend.DEX)
          .applyIf(providerType == ProviderType.API, b -> b.addProgramFiles(library))
          .applyIf(providerType == ProviderType.INJARS, b -> b.addKeepRules("-injars " + library))
          .setMinApi(AndroidApiLevel.B)
          .setFakeCompilerVersion(SemanticVersion.create(1, 2, 3))
          .compile()
          .inspectProguardConfiguration(
              configuration -> assertEquals("", configuration.toString()));
    }
  }

  @Test
  public void testUnusedProguardOnlyRulesVersionMain() throws Exception {
    for (String directory :
        ImmutableList.of(
            "proguard-min-6.1.0",
            "proguard-max-7.0.0",
            "proguard-min-6.1.0-max-7.0.0",
            "proguard610",
            "com.android.tools/proguard",
            "com.android.tools/proguard-min-6.1.0",
            "com.android.tools/proguard-max-7.0.0",
            "com.android.tools/proguard-min-6.1.0-max-7.0.0",
            "com.android.tools/proguard610")) {
      Path library = buildLibraryProguardOnlyRules(directory);
      testForR8(Backend.DEX)
          .applyIf(providerType == ProviderType.API, b -> b.addProgramFiles(library))
          .applyIf(providerType == ProviderType.INJARS, b -> b.addKeepRules("-injars " + library))
          .setMinApi(AndroidApiLevel.B)
          .compile()
          .inspectProguardConfiguration(
              configuration -> assertEquals("", configuration.toString()));
    }
  }
}
