// 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 org.hamcrest.CoreMatchers.allOf;
import static org.hamcrest.CoreMatchers.anyOf;
import static org.hamcrest.CoreMatchers.containsString;
import static org.hamcrest.core.IsNot.not;

import com.android.tools.r8.TestRunResult;
import com.android.tools.r8.errors.Unreachable;
import com.android.tools.r8.jasmin.JasminBuilder;
import com.android.tools.r8.jasmin.JasminBuilder.ClassBuilder;
import com.android.tools.r8.jasmin.JasminTestBase;
import com.android.tools.r8.utils.StringUtils;
import com.google.common.collect.ImmutableList;
import java.nio.file.Path;
import java.util.Collection;
import org.hamcrest.Matcher;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.Parameterized;
import org.junit.runners.Parameterized.Parameters;

@RunWith(Parameterized.class)
public class InvalidTypesTest extends JasminTestBase {

  private enum Mode {
    NO_INVOKE,
    INVOKE_UNVERIFIABLE_METHOD,
    INVOKE_VERIFIABLE_METHOD_ON_UNVERIFIABLE_CLASS;

    public String instruction() {
      switch (this) {
        case NO_INVOKE:
          return "";

        case INVOKE_UNVERIFIABLE_METHOD:
          return "invokestatic UnverifiableClass/unverifiableMethod()V";

        case INVOKE_VERIFIABLE_METHOD_ON_UNVERIFIABLE_CLASS:
          return "invokestatic UnverifiableClass/verifiableMethod()V";

        default:
          throw new Unreachable();
      }
    }
  }

  private final Backend backend;
  private final Mode mode;

  public InvalidTypesTest(Backend backend, Mode mode) {
    this.backend = backend;
    this.mode = mode;
  }

  @Parameters(name = "Backend: {0}, mode: {1}")
  public static Collection<Object[]> parameters() {
    return buildParameters(Backend.values(), Mode.values());
  }

  @Test
  public void test() throws Exception {
    JasminBuilder jasminBuilder = new JasminBuilder();

    ClassBuilder classA = jasminBuilder.addClass("A");
    classA.addDefaultConstructor();

    ClassBuilder classB = jasminBuilder.addClass("B");
    classB.addDefaultConstructor();

    ClassBuilder mainClass = jasminBuilder.addClass("TestClass");
    mainClass.addStaticField("f", "LA;");
    mainClass.addMainMethod(
        ".limit stack 2",
        ".limit locals 1",
        // Print "Hello!".
        "getstatic java/lang/System/out Ljava/io/PrintStream;",
        "ldc \"Hello!\"",
        "invokevirtual java/io/PrintStream/println(Ljava/lang/String;)V",
        // Invoke method on UnverifiableClass, depending on the mode.
        mode.instruction(),
        // Print "Goodbye!".
        "getstatic java/lang/System/out Ljava/io/PrintStream;",
        "ldc \"Goodbye!\"",
        "invokevirtual java/io/PrintStream/println(Ljava/lang/String;)V",
        "return");

    mainClass
        .staticMethodBuilder("m", ImmutableList.of(), "V")
        .setCode(
            "getstatic java/lang/System/out Ljava/io/PrintStream;",
            "getstatic TestClass/f LA;",
            "invokevirtual java/lang/Object/toString()Ljava/lang/String;",
            "invokevirtual java/io/PrintStream/println(Ljava/lang/String;)V",
            "return")
        .build();

    ClassBuilder UnverifiableClass = jasminBuilder.addClass("UnverifiableClass");
    UnverifiableClass.staticMethodBuilder("unverifiableMethod", ImmutableList.of(), "V")
        .setCode(
            "new A",
            "dup",
            "invokespecial A/<init>()V",
            "putstatic TestClass/f LA;",
            "invokestatic TestClass/m()V",
            "new B",
            "dup",
            "invokespecial B/<init>()V",
            "putstatic TestClass/f LA;",
            "invokestatic TestClass/m()V",
            "return")
        .build();
    UnverifiableClass.staticMethodBuilder("verifiableMethod", ImmutableList.of(), "V")
        .setCode(
            "getstatic java/lang/System/out Ljava/io/PrintStream;",
            "ldc \"In verifiable method!\"",
            "invokevirtual java/io/PrintStream/println(Ljava/lang/String;)V",
            "return")
        .build();

    Path inputJar = temp.getRoot().toPath().resolve("input.jar");
    jasminBuilder.writeJar(inputJar);

    if (backend == Backend.CF) {
      TestRunResult<?> jvmResult = testForJvm().addClasspath(inputJar).run(mainClass.name);
      checkTestRunResult(jvmResult, false);
    } else {
      assert backend == Backend.DEX;

      TestRunResult<?> dxResult = testForDX().addProgramFiles(inputJar).run(mainClass.name);
      checkTestRunResult(dxResult, false);

      TestRunResult<?> d8Result = testForD8().addProgramFiles(inputJar).run(mainClass.name);
      checkTestRunResult(d8Result, false);
    }

    TestRunResult r8Result =
        testForR8(backend)
            .addProgramFiles(inputJar)
            .addKeepMainRule(mainClass.name)
            .addOptionsModification(options -> options.testing.allowTypeErrors = true)
            .run(mainClass.name);
    checkTestRunResult(r8Result, true);
  }

  private void checkTestRunResult(TestRunResult<?> result, boolean isR8) {
    switch (mode) {
      case NO_INVOKE:
        result.assertSuccessWithOutput(getExpectedOutput(isR8));
        break;

      case INVOKE_VERIFIABLE_METHOD_ON_UNVERIFIABLE_CLASS:
        if (isR8) {
          result.assertSuccessWithOutput(getExpectedOutput(isR8));
        } else {
          result
              .assertFailureWithOutput(getExpectedOutput(isR8))
              .assertFailureWithErrorThatMatches(getMatcherForExpectedError());
        }
        break;

      case INVOKE_UNVERIFIABLE_METHOD:
        if (isR8) {
          result
              .assertFailureWithOutput(getExpectedOutput(isR8))
              .assertFailureWithErrorThatMatches(
                  allOf(
                      containsString("java.lang.NullPointerException"),
                      not(containsString("java.lang.VerifyError"))));
        } else {
          result
              .assertFailureWithOutput(getExpectedOutput(isR8))
              .assertFailureWithErrorThatMatches(getMatcherForExpectedError());
        }
        break;

      default:
        throw new Unreachable();
    }
  }

  private String getExpectedOutput(boolean isR8) {
    if (mode == Mode.NO_INVOKE) {
      return StringUtils.joinLines("Hello!", "Goodbye!", "");
    }
    if (isR8 && mode == Mode.INVOKE_VERIFIABLE_METHOD_ON_UNVERIFIABLE_CLASS) {
      return StringUtils.joinLines("Hello!", "In verifiable method!", "Goodbye!", "");
    }
    return StringUtils.joinLines("Hello!", "");
  }

  private Matcher<String> getMatcherForExpectedError() {
    if (backend == Backend.CF) {
      return allOf(
          containsString("java.lang.VerifyError"),
          containsString("Bad type in putfield/putstatic"));
    }

    assert backend == Backend.DEX;
    return allOf(
        containsString("java.lang.VerifyError"),
        anyOf(
            containsString("register v0 has type Precise Reference: B but expected Reference: A"),
            containsString("VFY: storing type 'LB;' into field type 'LA;'")));
  }
}
