// Copyright (c) 2018, 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 com.android.tools.r8.DiagnosticsMatcher.diagnosticOrigin;
import static com.android.tools.r8.OriginMatcher.hasPart;
import static com.android.tools.r8.utils.codeinspector.Matchers.isPresent;
import static com.android.tools.r8.utils.codeinspector.Matchers.notIf;
import static org.hamcrest.CoreMatchers.allOf;
import static org.hamcrest.CoreMatchers.containsString;
import static org.hamcrest.CoreMatchers.instanceOf;
import static org.hamcrest.CoreMatchers.is;
import static org.hamcrest.CoreMatchers.not;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.junit.Assert.assertThrows;
import static org.junit.Assume.assumeTrue;

import com.android.tools.r8.CompilationFailedException;
import com.android.tools.r8.DataResourceProvider;
import com.android.tools.r8.ProgramResource;
import com.android.tools.r8.ProgramResource.Kind;
import com.android.tools.r8.ProgramResourceProvider;
import com.android.tools.r8.ResourceException;
import com.android.tools.r8.TestBase;
import com.android.tools.r8.TestParameters;
import com.android.tools.r8.origin.ArchiveEntryOrigin;
import com.android.tools.r8.origin.Origin;
import com.android.tools.r8.utils.DescriptorUtils;
import com.android.tools.r8.utils.StringUtils;
import com.android.tools.r8.utils.ZipUtils.ZipBuilder;
import com.android.tools.r8.utils.codeinspector.CodeInspector;
import com.google.common.collect.ImmutableList;
import com.google.common.io.ByteStreams;
import java.io.IOException;
import java.nio.file.Path;
import java.util.Collection;
import java.util.Collections;
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 LibraryProvidedProguardRulesTest extends TestBase {

  static class A {
    private static String buildClassName(String className) {
      return A.class.getPackage().getName() + "." + className;
    }

    public static void main(String[] args) {
      try {
        Class.forName(buildClassName("B"));
        System.out.println("YES");
      } catch (ClassNotFoundException e) {
        System.out.println("NO");
      }
    }
  }

  static class B {}

  enum LibraryType {
    JAR_WITH_RULES,
    AAR_WITH_RULES,
    AAR_WITH_RULES_ONLY_IN_JAR,
    AAR_WITH_RULES_BOTH_IN_JAR_AND_IN_AAR;

    boolean isAar() {
      return this != JAR_WITH_RULES;
    }

    boolean hasRulesInJar() {
      return this != AAR_WITH_RULES;
    }

    boolean hasRulesInAar() {
      return this == AAR_WITH_RULES || this == AAR_WITH_RULES_BOTH_IN_JAR_AND_IN_AAR;
    }
  }

  @Parameter(0)
  public TestParameters parameters;

  @Parameter(1)
  public LibraryType libraryType;

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

  private Path buildLibrary(List<String> rules) throws Exception {
    ZipBuilder jarBuilder =
        ZipBuilder.builder(temp.newFile(libraryType.isAar() ? "classes.jar" : "test.jar").toPath());
    addTestClassesToZip(jarBuilder.getOutputStream(), ImmutableList.of(A.class, B.class));
    if (libraryType.hasRulesInJar()) {
      for (int i = 0; i < rules.size(); i++) {
        String name = "META-INF/proguard/jar" + (i == 0 ? "" : i) + ".rules";
        jarBuilder.addText(name, rules.get(i));
      }
    }
    if (libraryType.isAar()) {
      Path jar = jarBuilder.build();
      String allRules = StringUtils.lines(rules);
      ZipBuilder aarBuilder = ZipBuilder.builder(temp.newFile("test.aar").toPath());
      aarBuilder.addFilesRelative(jar.getParent(), jar);
      if (libraryType.hasRulesInAar()) {
        aarBuilder.addText("proguard.txt", allRules);
      }
      return aarBuilder.build();
    } else {
      return jarBuilder.build();
    }
  }

  private CodeInspector runTest(List<String> rules) throws Exception {
    return testForR8(parameters.getBackend())
        .addProgramFiles(buildLibrary(rules))
        .setMinApi(parameters.getApiLevel())
        .compile()
        .inspector();
  }

  private CodeInspector runTest(String rules) throws Exception {
    return runTest(ImmutableList.of(rules));
  }

  @Test
  public void keepOnlyA() throws Exception {
    CodeInspector inspector = runTest("-keep class " + A.class.getTypeName() + " {}");
    // TODO(b/228319861): Read Proguard rules from AAR's.
    assertThat(inspector.clazz(A.class), notIf(isPresent(), libraryType.isAar()));
    assertThat(inspector.clazz(B.class), not(isPresent()));
  }

  @Test
  public void keepOnlyB() throws Exception {
    CodeInspector inspector = runTest("-keep class **B {}");
    assertThat(inspector.clazz(A.class), not(isPresent()));
    // TODO(b/228319861): Read Proguard rules from AAR's.
    assertThat(inspector.clazz(B.class), notIf(isPresent(), libraryType.isAar()));
  }

  @Test
  public void keepBoth() throws Exception {
    CodeInspector inspector = runTest("-keep class ** {}");
    // TODO(b/228319861): Read Proguard rules from AAR's.
    assertThat(inspector.clazz(A.class), notIf(isPresent(), libraryType.isAar()));
    assertThat(inspector.clazz(B.class), notIf(isPresent(), libraryType.isAar()));
  }

  @Test
  public void multipleFiles() throws Exception {
    CodeInspector inspector = runTest(ImmutableList.of("-keep class **A {}", "-keep class **B {}"));
    // TODO(b/228319861): Read Proguard rules from AAR's.
    assertThat(inspector.clazz(A.class), notIf(isPresent(), libraryType.isAar()));
    assertThat(inspector.clazz(B.class), notIf(isPresent(), libraryType.isAar()));
  }

  @Test
  public void syntaxError() throws Exception {
    // TODO(b/228319861): Read Proguard rules from AAR's.
    assumeTrue(!libraryType.isAar());
    assertThrows(
        CompilationFailedException.class,
        () ->
            testForR8(parameters.getBackend())
                .addProgramFiles(buildLibrary(ImmutableList.of("error")))
                .setMinApi(parameters.getApiLevel())
                .compileWithExpectedDiagnostics(
                    diagnostics ->
                        diagnostics.assertErrorThatMatches(
                            allOf(
                                diagnosticMessage(containsString("Expected char '-'")),
                                diagnosticOrigin(hasPart("META-INF/proguard/jar.rules")),
                                diagnosticOrigin(instanceOf(ArchiveEntryOrigin.class))))));
  }

  @Test
  public void includeError() throws Exception {
    // TODO(b/228319861): Read Proguard rules from AAR's.
    assumeTrue(!libraryType.isAar());
    assertThrows(
        CompilationFailedException.class,
        () ->
            testForR8(parameters.getBackend())
                .addProgramFiles(buildLibrary(ImmutableList.of("-include other.rules")))
                .setMinApi(parameters.getApiLevel())
                .compileWithExpectedDiagnostics(
                    diagnostics ->
                        diagnostics.assertErrorThatMatches(
                            diagnosticMessage(
                                containsString("Options with file names are not supported")))));
  }

  static class TestProvider implements ProgramResourceProvider, DataResourceProvider {

    @Override
    public Collection<ProgramResource> getProgramResources() throws ResourceException {
      byte[] bytes;
      try {
        bytes = ByteStreams.toByteArray(A.class.getResourceAsStream("A.class"));
      } catch (IOException e) {
        throw new ResourceException(Origin.unknown(), "Unexpected");
      }
      return ImmutableList.of(
          ProgramResource.fromBytes(Origin.unknown(), Kind.CF, bytes,
              Collections.singleton(DescriptorUtils.javaTypeToDescriptor(A.class.getTypeName()))));
    }

    @Override
    public DataResourceProvider getDataResourceProvider() {
      return this;
    }

    @Override
    public void accept(Visitor visitor) throws ResourceException {
      throw new ResourceException(Origin.unknown(), "Cannot provide data resources after all");
    }
  }

  @Test
  public void throwingDataResourceProvider() throws Exception {
    // TODO(b/228319861): Read Proguard rules from AAR's.
    assumeTrue(!libraryType.isAar());
    assertThrows(
        CompilationFailedException.class,
        () ->
            testForR8(parameters.getBackend())
                .addProgramResourceProviders(new TestProvider())
                .setMinApi(parameters.getApiLevel())
                .compileWithExpectedDiagnostics(
                    diagnostics ->
                        diagnostics.assertErrorThatMatches(
                            allOf(
                                diagnosticMessage(
                                    containsString("Cannot provide data resources after all")),
                                diagnosticOrigin(is(Origin.unknown()))))));
  }
}
