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

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.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotEquals;
import static org.junit.Assert.assertTrue;

import com.android.tools.r8.DiagnosticsChecker;
import com.android.tools.r8.R8Command;
import com.android.tools.r8.TestBase;
import com.android.tools.r8.ToolHelper;
import com.android.tools.r8.ToolHelper.ProcessResult;
import com.android.tools.r8.origin.Origin;
import com.android.tools.r8.utils.AndroidApp;
import com.android.tools.r8.utils.KeepingDiagnosticHandler;
import com.android.tools.r8.utils.Reporter;
import com.android.tools.r8.utils.codeinspector.ClassSubject;
import com.android.tools.r8.utils.codeinspector.CodeInspector;
import com.google.common.collect.ImmutableList;
import java.nio.file.Path;
import java.util.Collections;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.Parameterized;

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

  // See "Method foo" in WarnReflectiveAccessTestMain.main().
  private static int LINE_NUMBER_OF_MARKED_LINE = 28;

  private KeepingDiagnosticHandler handler;
  private Reporter reporter;

  private Backend backend;

  @Parameterized.Parameters(name = "Backend: {0}")
  public static Backend[] data() {
    return ToolHelper.getBackends();
  }

  public WarnReflectiveAccessTestRunner(Backend backend) {
    this.backend = backend;
  }

  @Before
  public void reset() {
    handler = new KeepingDiagnosticHandler();
    reporter = new Reporter(handler);
  }

  private AndroidApp runR8(
      byte[][] classes,
      Class main,
      Path out,
      boolean explicitRule,
      boolean enableMinification,
      boolean forceProguardCompatibility)
      throws Exception {
    String minificationModifier = enableMinification ? ",allowobfuscation " : " ";
    String reflectionRules =
        explicitRule
            ? "-identifiernamestring class java.lang.Class {\n"
                  + "static java.lang.Class forName(java.lang.String);\n"
                  + "java.lang.reflect.Method getDeclaredMethod(java.lang.String,"
                  + " java.lang.Class[]);\n"
                  + "}\n"
            : "";
    R8Command.Builder commandBuilder =
        R8Command.builder(reporter)
            .addProguardConfiguration(
                ImmutableList.of(
                    "-keep"
                        + minificationModifier
                        + "class "
                        + main.getCanonicalName()
                        + " {"
                        + " <methods>;"
                        + "}",
                    "-printmapping",
                    "-keepattributes LineNumberTable",
                    reflectionRules),
                Origin.unknown())
            .setOutput(out, outputMode(backend));
    for (byte[] clazz : classes) {
      commandBuilder.addClassProgramData(clazz, Origin.unknown());
    }
    commandBuilder.addLibraryFiles(TestBase.runtimeJar(backend));
    return ToolHelper.runR8(
        commandBuilder.build(),
        o -> {
          o.inlinerOptions().enableInlining = false;
          o.forceProguardCompatibility = forceProguardCompatibility;
        });
  }

  private void reflectionWithBuilder(
      boolean explicitRule, boolean enableMinification, boolean forceProguardCompatibility)
      throws Exception {
    byte[][] classes = {ToolHelper.getClassAsBytes(WarnReflectiveAccessTest.class)};
    Path out = temp.getRoot().toPath();
    AndroidApp processedApp =
        runR8(
            classes,
            WarnReflectiveAccessTest.class,
            out,
            explicitRule,
            enableMinification,
            forceProguardCompatibility);

    String main = WarnReflectiveAccessTest.class.getCanonicalName();
    CodeInspector codeInspector = new CodeInspector(processedApp);
    ClassSubject mainSubject = codeInspector.clazz(main);
    assertThat(mainSubject, isPresent());

    ProcessResult javaOutput = runOnJavaRaw(main, classes);
    assertEquals(0, javaOutput.exitCode);
    assertThat(javaOutput.stdout, containsString("TestMain::foo"));

    String mainClassName = enableMinification ? mainSubject.getFinalName() : main;
    ProcessResult output;
    String errorString;
    if (backend == Backend.DEX) {
      output = runOnArtRaw(processedApp, mainClassName);
      errorString = "NoSuchMethodError";
    } else {
      assert backend == Backend.CF;
      output = runOnJavaRaw(processedApp, mainClassName, Collections.emptyList());
      errorString = "method not found";
    }
    if (enableMinification) {
      assertNotEquals(0, output.exitCode);
      assertThat(output.stderr, containsString(errorString));
    } else {
      assertEquals(0, output.exitCode);
      assertThat(output.stdout, containsString("TestMain::foo"));
    }
  }

  @Test
  public void test_explicit_minification_forceProguardCompatibility() throws Exception {
    reflectionWithBuilder(true, true, true);
    assertFalse(handler.warnings.isEmpty());
    DiagnosticsChecker.checkDiagnostic(
        handler.warnings.get(0),
        (Path) null,
        LINE_NUMBER_OF_MARKED_LINE,
        1,
        "Cannot determine",
        "getDeclaredMethod",
        "-identifiernamestring",
        "resolution failure");
  }

  @Test
  public void test_explicit_noMinification_forceProguardCompatibility() throws Exception {
    reflectionWithBuilder(true, false, true);
    assertFalse(handler.warnings.isEmpty());
    DiagnosticsChecker.checkDiagnostic(
        handler.warnings.get(0),
        (Path) null,
        LINE_NUMBER_OF_MARKED_LINE,
        1,
        "Cannot determine",
        "getDeclaredMethod",
        "-identifiernamestring",
        "resolution failure");
  }

  @Test
  public void test_explicit_minification_R8() throws Exception {
    reflectionWithBuilder(true, true, false);
    assertFalse(handler.warnings.isEmpty());
    DiagnosticsChecker.checkDiagnostic(
        handler.warnings.get(0),
        (Path) null,
        LINE_NUMBER_OF_MARKED_LINE,
        1,
        "Cannot determine",
        "getDeclaredMethod",
        "-identifiernamestring",
        "resolution failure");
  }

  @Test
  public void test_explicit_noMinification_R8() throws Exception {
    reflectionWithBuilder(true, false, false);
    assertFalse(handler.warnings.isEmpty());
    DiagnosticsChecker.checkDiagnostic(
        handler.warnings.get(0),
        (Path) null,
        LINE_NUMBER_OF_MARKED_LINE,
        1,
        "Cannot determine",
        "getDeclaredMethod",
        "-identifiernamestring",
        "resolution failure");
  }

  @Test
  public void test_implicit_minification_forceProguardCompatibility() throws Exception {
    reflectionWithBuilder(false, true, true);
    assertTrue(handler.warnings.isEmpty());
  }

  @Test
  public void test_implicit_noMinification_forceProguardCompatibility() throws Exception {
    reflectionWithBuilder(false, false, true);
    assertTrue(handler.warnings.isEmpty());
  }

  @Test
  public void test_implicit_minification_R8() throws Exception {
    reflectionWithBuilder(false, true, false);
    assertTrue(handler.warnings.isEmpty());
  }

  @Test
  public void test_implicit_noMinification_R8() throws Exception {
    reflectionWithBuilder(false, false, false);
    assertTrue(handler.warnings.isEmpty());
  }
}
