// 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.ir.optimize.inliner;

import static com.android.tools.r8.utils.codeinspector.Matchers.isAbsent;
import static com.android.tools.r8.utils.codeinspector.Matchers.isPresent;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.fail;

import com.android.tools.r8.TestBase;
import com.android.tools.r8.ToolHelper;
import com.android.tools.r8.ToolHelper.ProcessResult;
import com.android.tools.r8.ir.optimize.inliner.exceptionhandling.ExceptionHandlingTestClass;
import com.android.tools.r8.ir.optimize.inliner.interfaces.InterfaceTargetsTestClass;
import com.android.tools.r8.ir.optimize.inliner.interfaces.InterfaceTargetsTestClass.IfaceA;
import com.android.tools.r8.ir.optimize.inliner.interfaces.InterfaceTargetsTestClass.IfaceB;
import com.android.tools.r8.ir.optimize.inliner.interfaces.InterfaceTargetsTestClass.IfaceC;
import com.android.tools.r8.ir.optimize.inliner.interfaces.InterfaceTargetsTestClass.IfaceD;
import com.android.tools.r8.ir.optimize.inliner.interfaces.InterfaceTargetsTestClass.IfaceNoImpl;
import com.android.tools.r8.naming.MemberNaming.MethodSignature;
import com.android.tools.r8.utils.AndroidApp;
import com.android.tools.r8.utils.InternalOptions;
import com.android.tools.r8.utils.codeinspector.ClassSubject;
import com.android.tools.r8.utils.codeinspector.CodeInspector;
import com.android.tools.r8.utils.codeinspector.MethodSubject;
import java.nio.file.Path;
import java.util.stream.Collectors;
import java.util.stream.Stream;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.Parameterized;

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

  private Backend backend;

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

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

  @Test
  public void testExceptionHandling() throws Exception {
    testForR8(backend)
        .addProgramClasses(ExceptionHandlingTestClass.class)
        .addKeepMainRule(ExceptionHandlingTestClass.class)
        .addOptionsModification(this::configure)
        .enableInliningAnnotations()
        .compile()
        .inspect(
            inspector -> {
              ClassSubject mainClassSubject = inspector.clazz(ExceptionHandlingTestClass.class);
              assertThat(mainClassSubject, isPresent());
              assertThat(
                  mainClassSubject.uniqueMethodWithOriginalName(
                      "inlineeWithNormalExitThatDoesNotThrow"),
                  isAbsent());
              assertThat(
                  mainClassSubject.uniqueMethodWithOriginalName("inlineeWithNormalExitThatThrows"),
                  isAbsent());
              assertThat(
                  mainClassSubject.uniqueMethodWithOriginalName("inlineeWithoutNormalExit"),
                  isAbsent());
            })
        .run(ExceptionHandlingTestClass.class)
        .assertSuccessWithOutputLines(
            "Test succeeded: methodWithoutCatchHandlersTest(1)",
            "Test succeeded: methodWithoutCatchHandlersTest(2)",
            "Test succeeded: methodWithoutCatchHandlersTest(3)",
            "Test succeeded: methodWithCatchHandlersTest(1)",
            "Test succeeded: methodWithCatchHandlersTest(2)",
            "Test succeeded: methodWithCatchHandlersTest(3)");
  }

  @Test
  public void testInterfacesWithoutTargets() throws Exception {
    byte[][] classes = {
        ToolHelper.getClassAsBytes(InterfaceTargetsTestClass.class),
        ToolHelper.getClassAsBytes(InterfaceTargetsTestClass.IfaceNoImpl.class),
        ToolHelper.getClassAsBytes(InterfaceTargetsTestClass.IfaceA.class),
        ToolHelper.getClassAsBytes(InterfaceTargetsTestClass.BaseA.class),
        ToolHelper.getClassAsBytes(InterfaceTargetsTestClass.DerivedA.class),
        ToolHelper.getClassAsBytes(InterfaceTargetsTestClass.IfaceB.class),
        ToolHelper.getClassAsBytes(InterfaceTargetsTestClass.BaseB.class),
        ToolHelper.getClassAsBytes(InterfaceTargetsTestClass.DerivedB.class),
        ToolHelper.getClassAsBytes(InterfaceTargetsTestClass.IfaceC.class),
        ToolHelper.getClassAsBytes(InterfaceTargetsTestClass.IfaceC2.class),
        ToolHelper.getClassAsBytes(InterfaceTargetsTestClass.BaseC.class),
        ToolHelper.getClassAsBytes(InterfaceTargetsTestClass.DerivedC.class),
        ToolHelper.getClassAsBytes(InterfaceTargetsTestClass.IfaceD.class),
        ToolHelper.getClassAsBytes(InterfaceTargetsTestClass.BaseD.class)
    };
    AndroidApp app = runR8(buildAndroidApp(classes), InterfaceTargetsTestClass.class);

    String javaOutput = runOnJava(InterfaceTargetsTestClass.class);
    assert backend == Backend.DEX || backend == Backend.CF;
    String output =
        backend == Backend.DEX
            ? runOnArt(app, InterfaceTargetsTestClass.class)
            : runOnJava(app, InterfaceTargetsTestClass.class);
    assertEquals(javaOutput, output);

    CodeInspector inspector = new CodeInspector(app);
    ClassSubject clazz = inspector.clazz(InterfaceTargetsTestClass.class);

    assertFalse(getMethodSubject(clazz,
        "testInterfaceNoImpl", String.class, IfaceNoImpl.class).isPresent());
    assertFalse(getMethodSubject(clazz,
        "testInterfaceA", String.class, IfaceA.class).isPresent());
    assertFalse(getMethodSubject(clazz,
        "testInterfaceB", String.class, IfaceB.class).isPresent());
    assertFalse(getMethodSubject(clazz,
        "testInterfaceD", String.class, IfaceC.class).isPresent());
    assertFalse(getMethodSubject(clazz,
        "testInterfaceD", String.class, IfaceD.class).isPresent());
  }

  private MethodSubject getMethodSubject(
      ClassSubject clazz, String methodName, Class retValue, Class... params) {
    return clazz.method(new MethodSignature(methodName, retValue.getTypeName(),
        Stream.of(params).map(Class::getTypeName).collect(Collectors.toList())));
  }

  private AndroidApp runR8(AndroidApp app, Class mainClass) throws Exception {
    AndroidApp compiled =
        compileWithR8(
            app, getProguardConfig(mainClass.getCanonicalName()), this::configure, backend);

    // Materialize file for execution.
    Path generatedFile = temp.getRoot().toPath().resolve("classes.jar");
    assert backend == Backend.DEX || backend == Backend.CF;
    compiled.writeToZip(generatedFile, outputMode(backend));

    String output =
        backend == Backend.DEX
            ? ToolHelper.runArtNoVerificationErrors(
                generatedFile.toString(), mainClass.getCanonicalName())
            : ToolHelper.runJava(generatedFile, mainClass.getCanonicalName()).stdout;

    // Compare with Java.
    ProcessResult javaResult = ToolHelper.runJava(
        ToolHelper.getClassPathForTests(), mainClass.getCanonicalName());

    if (javaResult.exitCode != 0) {
      System.out.println(javaResult.stdout);
      System.err.println(javaResult.stderr);
      fail("JVM failed for: " + mainClass);
    }
    assertEquals(
        backend == Backend.DEX
            ? "JVM and ART output differ."
            : "Outputs of source and processed programs running on JVM differ.",
        javaResult.stdout,
        output);

    return compiled;
  }

  private String getProguardConfig(String main) {
    return keepMainProguardConfiguration(main)
        + "\n"
        + "-dontobfuscate\n"
        + "-allowaccessmodification";
  }

  private void configure(InternalOptions options) {
    options.enableClassInlining = false;
  }
}
