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

import static org.junit.Assert.assertEquals;

import com.android.tools.r8.ClassFileConsumer;
import com.android.tools.r8.CompilationMode;
import com.android.tools.r8.DexIndexedConsumer;
import com.android.tools.r8.ProgramConsumer;
import com.android.tools.r8.R8;
import com.android.tools.r8.R8Command;
import com.android.tools.r8.R8Command.Builder;
import com.android.tools.r8.ToolHelper;
import com.android.tools.r8.ToolHelper.DexVm;
import com.android.tools.r8.ToolHelper.ProcessResult;
import com.android.tools.r8.origin.Origin;
import com.android.tools.r8.utils.AndroidApiLevel;
import com.android.tools.r8.utils.DescriptorUtils;
import java.nio.file.Path;
import java.util.Arrays;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.TemporaryFolder;

public class MethodHandleTestRunner {
  static final Class<?> CLASS = MethodHandleTest.class;

  private boolean ldc = false;
  private boolean minify = false;

  @Rule
  public TemporaryFolder temp = ToolHelper.getTemporaryFolderForTest();

  @Test
  public void testMethodHandlesLookup() throws Exception {
    // Run test with dynamic method lookups, i.e. using MethodHandles.lookup().find*()
    ldc = false;
    test();
  }

  @Test
  public void testLdcMethodHandle() throws Exception {
    // Run test with LDC methods, i.e. without java.lang.invoke.MethodHandles
    ldc = true;
    test();
  }

  @Test
  public void testMinify() throws Exception {
    // Run test with LDC methods, i.e. without java.lang.invoke.MethodHandles
    ldc = true;
    ProcessResult runInput = runInput();
    assertEquals(0, runInput.exitCode);
    Path outCf = temp.getRoot().toPath().resolve("cf.jar");
    build(new ClassFileConsumer.ArchiveConsumer(outCf), true);
    ProcessResult runCf =
        ToolHelper.runJava(outCf, CLASS.getCanonicalName(), ldc ? "error" : "exception");
    assertEquals(runInput.toString(), runCf.toString());
  }

  private final Class[] inputClasses = {
    MethodHandleTest.class,
    MethodHandleTest.C.class,
    MethodHandleTest.I.class,
    MethodHandleTest.Impl.class,
    MethodHandleTest.D.class,
    MethodHandleTest.E.class,
    MethodHandleTest.F.class,
  };

  private void test() throws Exception {
    ProcessResult runInput = runInput();
    Path outCf = temp.getRoot().toPath().resolve("cf.jar");
    build(new ClassFileConsumer.ArchiveConsumer(outCf), false);
    Path outDex = temp.getRoot().toPath().resolve("dex.zip");
    build(new DexIndexedConsumer.ArchiveConsumer(outDex), false);

    ProcessResult runCf =
        ToolHelper.runJava(outCf, CLASS.getCanonicalName(), ldc ? "error" : "exception");
    assertEquals(runInput.toString(), runCf.toString());
    // TODO(mathiasr): Once we include a P runtime, change this to "P and above".
    if (ToolHelper.getDexVm() != DexVm.ART_DEFAULT) {
      return;
    }
    ProcessResult runDex =
        ToolHelper.runArtRaw(
            outDex.toString(),
            CLASS.getCanonicalName(),
            cmd -> cmd.appendProgramArgument(ldc ? "pass" : "exception"));
    // Only compare stdout and exitCode since dex2oat prints to stderr.
    if (runInput.exitCode != runDex.exitCode) {
      System.out.println(runDex.stderr);
    }
    assertEquals(runInput.stdout, runDex.stdout);
    assertEquals(runInput.exitCode, runDex.exitCode);
  }

  private void build(ProgramConsumer programConsumer, boolean minify) throws Exception {
    // MethodHandle.invoke() only supported from Android O
    // ConstMethodHandle only supported from Android P
    AndroidApiLevel apiLevel = AndroidApiLevel.P;
    Builder cfBuilder =
        R8Command.builder()
            .setMode(CompilationMode.DEBUG)
            .addLibraryFiles(ToolHelper.getAndroidJar(apiLevel))
            .setProgramConsumer(programConsumer);
    if (!(programConsumer instanceof ClassFileConsumer)) {
      cfBuilder.setMinApiLevel(apiLevel.getLevel());
    }
    for (Class<?> c : inputClasses) {
      byte[] classAsBytes = getClassAsBytes(c);
      cfBuilder.addClassProgramData(classAsBytes, Origin.unknown());
    }
    if (minify) {
      cfBuilder.addProguardConfiguration(
          Arrays.asList(
              "-keep public class com.android.tools.r8.cf.MethodHandleTest {",
              "  public static void main(...);",
              "}"),
          Origin.unknown());
    }
    R8.run(cfBuilder.build());
  }

  private ProcessResult runInput() throws Exception {
    Path out = temp.getRoot().toPath().resolve("input.jar");
    ClassFileConsumer.ArchiveConsumer archiveConsumer = new ClassFileConsumer.ArchiveConsumer(out);
    for (Class<?> c : inputClasses) {
      archiveConsumer.accept(
          getClassAsBytes(c), DescriptorUtils.javaTypeToDescriptor(c.getName()), null);
    }
    archiveConsumer.finished(null);
    ProcessResult runInput = ToolHelper.runJava(out, CLASS.getName(), ldc ? "error" : "exception");
    if (runInput.exitCode != 0) {
      System.out.println(runInput);
    }
    assertEquals(0, runInput.exitCode);
    return runInput;
  }

  private byte[] getClassAsBytes(Class<?> clazz) throws Exception {
    if (ldc) {
      if (clazz == MethodHandleTest.D.class) {
        return MethodHandleDump.dumpD();
      } else if (clazz == MethodHandleTest.class) {
        return MethodHandleDump.transform(ToolHelper.getClassAsBytes(clazz));
      }
    }
    return ToolHelper.getClassAsBytes(clazz);
  }
}
