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

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.assertNotNull;
import static org.junit.Assert.assertTrue;

import com.android.tools.r8.R8TestRunResult;
import com.android.tools.r8.TestParameters;
import com.android.tools.r8.TestParametersCollection;
import com.android.tools.r8.ToolHelper.DexVm.Version;
import com.android.tools.r8.code.InvokeDirect;
import com.android.tools.r8.code.InvokeVirtual;
import com.android.tools.r8.graph.DexCode;
import com.android.tools.r8.graph.DexEncodedMethod;
import com.android.tools.r8.smali.SmaliBuilder;
import com.android.tools.r8.smali.SmaliBuilder.MethodSignature;
import com.android.tools.r8.smali.SmaliTestBase;
import com.android.tools.r8.utils.codeinspector.ClassSubject;
import com.android.tools.r8.utils.codeinspector.CodeInspector;
import com.google.common.collect.ImmutableList;
import java.util.function.Consumer;
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 InvokeTypeConversionTest extends SmaliTestBase {

  @Parameters(name = "{0}")
  public static TestParametersCollection data() {
    return getTestParameters().withDexRuntimes().withAllApiLevels().build();
  }

  private final String CLASS_NAME = "Example";
  private MethodSignature main;

  private final TestParameters parameters;

  public InvokeTypeConversionTest(TestParameters parameters) {
    this.parameters = parameters;
  }

  private SmaliBuilder buildTestClass(String invokeLine) {
    SmaliBuilder builder = new SmaliBuilder(CLASS_NAME);
    builder.addDefaultConstructor();
    builder.addPrivateInstanceMethod("int", "foo", ImmutableList.of(), 1,
        "  const/4 v0, 0",
        "  return v0");
    builder.addPrivateStaticMethod("int", "bar", ImmutableList.of(), 1,
        "  const/4 v0, 0",
        "  return v0");
    main = builder.addMainMethod(2,
        "new-instance v1, L" + CLASS_NAME + ";",
        "invoke-direct { v1 }, L" + CLASS_NAME + ";-><init>()V",
        invokeLine,
        "move-result v1",
        "invoke-static { v1 }, Ljava/lang/Integer;->valueOf(I)Ljava/lang/Integer;",
        "move-result-object v1",
        "sget-object v0, Ljava/lang/System;->out:Ljava/io/PrintStream;",
        "invoke-virtual { v0, v1 }, Ljava/io/PrintStream;->print(Ljava/lang/Object;)V",
        "return-void");
    return builder;
  }

  private void run(
      SmaliBuilder builder,
      String expectedException,
      Consumer<CodeInspector> inspectorConsumer) throws Exception {
    R8TestRunResult result =
        testForR8(parameters.getBackend())
            .addProgramDexFileData(builder.compile())
            .addKeepMainRule(CLASS_NAME)
            .addKeepRules(
                // We're testing lens-based invocation type conversions.
                "-dontoptimize", "-dontobfuscate", "-allowaccessmodification")
            .addOptionsModification(o -> o.enableInlining = false)
            .setMinApi(parameters.getApiLevel())
            .run(parameters.getRuntime(), CLASS_NAME);
    if (expectedException == null) {
      result.assertSuccessWithOutput("0");
      result.inspect(inspectorConsumer::accept);
    } else {
      result.assertFailureWithErrorThatMatches(containsString(expectedException));
      result.inspectFailure(inspectorConsumer::accept);
    }
  }

  // The following test checks invoke-direct, which refers to the private static method, is *not*
  // rewritten by publicizer lens, resulting in IncompatibleClassChangeError, which is expected.
  //
  // class Example {
  //   private int foo() { return 0; }
  //   private static int bar() { return 0; }
  //   public static void main(String[] args) {
  //     Example instance = new Example();
  //     "invoke-direct instance, Example->bar()"  <- should yield IncompatibleClassChangeError
  //     ...
  //   }
  // }
  @Test
  public void invokeDirectToAlreadyStaticMethod() throws Exception {
    SmaliBuilder builder = buildTestClass(
        "invoke-direct { v1 }, L" + CLASS_NAME + ";->bar()I");
    String expectedError =
        parameters.getRuntime().asDex().getVm().getVersion().isOlderThanOrEqual(Version.V4_4_4)
            ? "VerifyError"
            : "IncompatibleClassChangeError";
    run(builder, expectedError, dexInspector -> {
      ClassSubject clazz = dexInspector.clazz(CLASS_NAME);
      assertThat(clazz, isPresent());
      DexEncodedMethod method = getMethod(dexInspector, main);
      assertNotNull(method);
      DexCode code = method.getCode().asDexCode();
      // The given invoke line is remained as-is.
      assertTrue(code.instructions[2] instanceof InvokeDirect);
    });
  }

  // The following test checks invoke-direct, which refers to the private instance method, *is*
  // rewritten by publicizer lens, as the target method will be publicized.
  //
  // class Example {
  //   private int foo() { return 0; }
  //   private static int bar() { return 0; }
  //   public static void main(String[] args) {
  //     Example instance = new Example();
  //     instance.foo();  // which was "invoke-direct instance, Example->foo()"
  //                      // will be "invoke-virtual instance, Example->foo()"
  //     ...
  //   }
  // }
  @Test
  public void invokeDirectToPublicizedMethod() throws Exception {
    SmaliBuilder builder = buildTestClass(
        "invoke-direct { v1 }, L" + CLASS_NAME + ";->foo()I");
    run(builder, null, dexInspector -> {
      ClassSubject clazz = dexInspector.clazz(CLASS_NAME);
      assertThat(clazz, isPresent());
      DexEncodedMethod method = getMethod(dexInspector, main);
      assertNotNull(method);
      DexCode code = method.getCode().asDexCode();
      // The given invoke line is changed to invoke-virtual
      assertTrue(code.instructions[2] instanceof InvokeVirtual);
    });
  }

}