// Copyright (c) 2016, 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;

import static org.junit.Assert.assertEquals;

import com.android.tools.r8.ToolHelper.DexVm;
import com.android.tools.r8.ToolHelper.DexVm.Version;
import com.android.tools.r8.utils.StringUtils;
import com.android.tools.r8.utils.TestDescriptionWatcher;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableSet;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.Set;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.ExpectedException;
import org.junit.runner.RunWith;
import org.junit.runners.Parameterized;
import org.junit.runners.Parameterized.Parameters;

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

  @Rule
  public ExpectedException thrown = ExpectedException.none();

  @Parameters(name = "{0}: {1}")
  public static Collection<Object[]> data() {
    return buildParameters(
        getTestParameters().withDexRuntimesAndAllApiLevels().build(), tests.keySet());
  }

  private static final String SMALI_DIR = ToolHelper.SMALI_BUILD_DIR;

  private static Map<String, String> tests;

  static {
    ImmutableMap.Builder<String, String> testsBuilder = ImmutableMap.builder();
    testsBuilder
        .put(
            "arithmetic",
            StringUtils.lines(
                "-1", "3", "2", "3", "3.0", "1", "0", "-131580", "-131580", "2", "4", "-2"))
        .put(
            "controlflow",
            StringUtils.lines("2", "1", "2", "1", "2", "1", "2", "1", "2", "1", "2", "1", "2"))
        .put("fibonacci", StringUtils.lines("55", "55", "55", "55"))
        .put("fill-array-data", "[1, 2, 3][4, 5, 6]")
        .put("filled-new-array", "[1, 2, 3][4, 5, 6][1, 2, 3, 4, 5, 6][6, 5, 4, 3, 2, 1]")
        .put("packed-switch", "12345")
        .put("sparse-switch", "12345")
        .put("unreachable-code-1", "777")
        .put(
            "multiple-returns",
            StringUtils.lines("TFtf", "1", "4611686018427387904", "true", "false"))
        .put("try-catch", "")
        .put("phi-removal-regression", StringUtils.lines("returnBoolean"))
        .put(
            "overlapping-long-registers",
            StringUtils.lines("-9151314442816847872", "-9151314442816319488"))
        .put(
            "type-confusion-regression",
            StringUtils.lines("java.lang.RuntimeException: Test.<init>()"))
        .put(
            "type-confusion-regression2",
            StringUtils.lines("java.lang.NullPointerException: Attempt to read from null array"))
        .put(
            "type-confusion-regression3",
            StringUtils.lines(
                "java.lang.NullPointerException: Attempt to read from field 'byte[] Test.a'"
                    + " on a null object reference"))
        .put("type-confusion-regression4", "")
        .put(
            "type-confusion-regression5", StringUtils.lines("java.lang.RuntimeException: getId()I"))
        .put("chain-of-loops", StringUtils.lines("java.lang.RuntimeException: f(II)"))
        .put("new-instance-and-init", StringUtils.lines("Test(0)", "Test(0)", "Test(0)"))
        .put(
            "bad-codegen",
            StringUtils.lines(
                "java.lang.NullPointerException: Attempt to read from field "
                    + "'Test Test.a' on a null object reference"))
        .put(
            "merge-blocks-regression",
            StringUtils.lines(
                "java.lang.NullPointerException: Attempt to invoke virtual"
                    + " method 'Test Test.bW_()' on a null object reference"))
        .put("self-is-catch-block", StringUtils.lines("100", "-1"))
        .put("infinite-loop", "")
        .put(
            "regression/33336471",
            StringUtils.lines(
                "START", "0", "2", "LOOP", "1", "2", "LOOP", "2", "2", "DONE", "START", "0", "2",
                "LOOP", "1", "2", "LOOP", "2", "2", "DONE"))
        .put("regression/33846227", "")
        .put("illegal-invokes", StringUtils.lines("ICCE", "ICCE"))
        .build();
    tests = testsBuilder.build();
  }

  private static Set<String> invokeErrors = ImmutableSet.of("bad-codegen", "illegal-invokes");

  private static Map<String, Set<String>> missingClasses =
      ImmutableMap.of(
          "try-catch", ImmutableSet.of("test.X"),
          "type-confusion-regression5", ImmutableSet.of("jok", "jol"),
          "bad-codegen", ImmutableSet.of("java.util.LTest"));

  // Tests where the original smali code fails on Art, but runs after R8 processing.
  private static final Map<DexVm.Version, List<String>> originalFailingOnArtVersions =
      ImmutableMap.of(
          Version.V5_1_1,
              ImmutableList.of(
                  // Smali code contains an empty switch payload.
                  "sparse-switch", "regression/33846227"),
          Version.V4_4_4,
              ImmutableList.of(
                  // Smali code contains an empty switch payload.
                  "sparse-switch", "regression/33846227"),
          Version.V4_0_4,
              ImmutableList.of(
                  // Smali code contains an empty switch payload.
                  "sparse-switch", "regression/33846227"));

  // Tests where the output has a different output than the original on certain VMs.
  private static final Map<DexVm.Version, Map<String, String>> customProcessedOutputExpectation =
      ImmutableMap.of(
          Version.V4_4_4,
          ImmutableMap.of(
              "bad-codegen", "java.lang.NullPointerException\n",
              "type-confusion-regression2", "java.lang.NullPointerException\n",
              "type-confusion-regression3", "java.lang.NullPointerException\n",
              "merge-blocks-regression", "java.lang.NullPointerException\n"),
          Version.V4_0_4,
          ImmutableMap.of(
              "bad-codegen", "java.lang.NullPointerException\n",
              "type-confusion-regression2", "java.lang.NullPointerException\n",
              "type-confusion-regression3", "java.lang.NullPointerException\n",
              "merge-blocks-regression", "java.lang.NullPointerException\n"),
          Version.V13_0_0,
          ImmutableMap.of(
              "bad-codegen",
              StringUtils.lines(
                  "java.lang.NullPointerException: Attempt to read from field 'Test Test.a'"
                      + " on a null object reference in method 'Test TestObject.a(Test,"
                      + " Test, Test, Test, boolean)'"),
              "type-confusion-regression3",
              StringUtils.lines(
                  "java.lang.NullPointerException: Attempt to read from field 'byte[]"
                      + " Test.a' on a null object reference in method 'int"
                      + " TestObject.a(Test, Test)'")),
          Version.V14_0_0,
          ImmutableMap.of(
              "bad-codegen",
                  StringUtils.lines(
                      "java.lang.NullPointerException: Attempt to read from field 'Test Test.a'"
                          + " on a null object reference in method 'Test TestObject.a(Test,"
                          + " Test, Test, Test, boolean)'"),
              "type-confusion-regression3",
                  StringUtils.lines(
                      "java.lang.NullPointerException: Attempt to read from field 'byte[]"
                          + " Test.a' on a null object reference in method 'int"
                          + " TestObject.a(Test, Test)'")),
          Version.V15_0_0,
          ImmutableMap.of(
              "bad-codegen",
              StringUtils.lines(
                  "java.lang.NullPointerException: Attempt to read from field 'Test Test.a'"
                      + " on a null object reference in method 'Test TestObject.a(Test,"
                      + " Test, Test, Test, boolean)'"),
              "type-confusion-regression3",
              StringUtils.lines(
                  "java.lang.NullPointerException: Attempt to read from field 'byte[]"
                      + " Test.a' on a null object reference in method 'int"
                      + " TestObject.a(Test, Test)'")));

  // Tests where the input fails with a verification error on Dalvik instead of the
  // expected runtime exception.
  private static final Map<DexVm.Version, List<String>> dalvikVerificationErrors =
      ImmutableMap.of(
          Version.V4_4_4,
              ImmutableList.of(
                  // The invokes are in fact invalid, but the test expects the current Art behavior
                  // of throwing an IncompatibleClassChange exception. Dalvik fails to verify.
                  "illegal-invokes"),
          Version.V4_0_4,
              ImmutableList.of(
                  // The invokes are in fact invalid, but the test expects the current Art behavior
                  // of throwing an IncompatibleClassChange exception. Dalvik fails to verify.
                  "illegal-invokes"));

  private Set<String> failingOnX8 = ImmutableSet.of(
      // Contains use of register as both an int and a float.
      "regression/33336471"
  );

  @Rule
  public TestDescriptionWatcher watcher = new TestDescriptionWatcher();

  private final TestParameters parameters;
  private final String directoryName;
  private final String dexFileName;
  private final String expectedOutput;

  public R8RunSmaliTestsTest(TestParameters parameters, String name) {
    this.parameters = parameters;
    String expectedOutput = tests.get(name);
    if (customProcessedOutputExpectation.containsKey(parameters.asDexRuntime().getVersion())
        && customProcessedOutputExpectation
            .get(parameters.asDexRuntime().getVersion())
            .containsKey(name)) {
      // If the original and the processed code have different expected output, only run
      // the code produced by R8.
      expectedOutput =
          customProcessedOutputExpectation.get(parameters.asDexRuntime().getVersion()).get(name);
    }
    this.directoryName = name;
    this.dexFileName = name.substring(name.lastIndexOf('/') + 1) + ".dex";
    this.expectedOutput = expectedOutput;
  }

  @Test
  public void SmaliTest() throws Exception {
    Path originalDexFile = Paths.get(SMALI_DIR, directoryName, dexFileName);

    if (failingOnX8.contains(directoryName)) {
      thrown.expect(CompilationFailedException.class);
    }

    Version version = parameters.asDexRuntime().getVersion();
    boolean dalvikVerificationError =
        dalvikVerificationErrors.containsKey(version)
            && dalvikVerificationErrors.get(version).contains(directoryName);
    boolean originalFailing =
        (originalFailingOnArtVersions.containsKey(version)
            && originalFailingOnArtVersions.get(version).contains(directoryName));
    Path testJar = Paths.get(SMALI_DIR, directoryName, "Test.jar");
    boolean testJarExists = testJar.toFile().exists();
    Path testJarDex = null;
    if (testJarExists) {
      testJarDex =
          testForD8(Backend.DEX)
              .setMinApi(parameters)
              .addProgramFiles(testJar)
              .compile()
              .writeToZip();
    }
    testForR8(parameters.getBackend())
        .addKeepAllClassesRule()
        .addProgramDexFileData(Files.readAllBytes(originalDexFile))
        .applyIf(testJarExists, p -> p.addProgramFiles(testJar))
        .addDontWarn(missingClasses.getOrDefault(directoryName, Collections.emptySet()))
        .addOptionsModification(
            options ->
                options.getTestingOptions().allowInvokeErrors =
                    invokeErrors.contains(directoryName))
        .setMinApi(parameters)
        .compile()
        .run(parameters.getRuntime(), "Test")
        .applyIf(
            dalvikVerificationError,
            r -> r.assertFailureWithErrorThatThrows(VerifyError.class),
            r -> r.assertSuccessWithOutput(expectedOutput));

    // Also run the original DEX if possible.
    if (!dalvikVerificationError && !originalFailing) {
      ImmutableList.Builder<String> dexListBuilder = ImmutableList.builder();
      dexListBuilder.add(originalDexFile.toString());
      if (testJarExists) {
        dexListBuilder.add(testJarDex.toString());
      }
      String originalOutput =
          ToolHelper.runArtNoVerificationErrors(
              dexListBuilder.build(), "Test", null, parameters.getRuntime().asDex().getVm());
      assertEquals(expectedOutput, originalOutput);
    }
  }
}
