// 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.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());
  }
}
