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

import com.android.tools.r8.R8Command;
import com.android.tools.r8.ToolHelper;
import com.android.tools.r8.ToolHelper.DexVm.Version;
import com.android.tools.r8.ToolHelper.ProcessResult;
import com.android.tools.r8.VmTestRunner;
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.origin.Origin;
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.AndroidApp;
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.List;
import java.util.function.Consumer;
import org.junit.Test;
import org.junit.runner.RunWith;

@RunWith(VmTestRunner.class)
public class InvokeTypeConversionTest extends SmaliTestBase {
  private final String CLASS_NAME = "Example";
  private MethodSignature main;

  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 {
    AndroidApp app = buildApplication(builder);
    List<String> pgConfigs = ImmutableList.of(
        keepMainProguardConfiguration(CLASS_NAME),
        // We're testing lense-based invocation type conversions.
        "-dontoptimize",
        "-dontobfuscate",
        "-allowaccessmodification");
    R8Command.Builder command = ToolHelper.prepareR8CommandBuilder(app);
    command.addProguardConfiguration(pgConfigs, Origin.unknown());
    AndroidApp processedApp = ToolHelper.runR8(command.build(), o -> {
      o.enableInlining = false;
    });
    ProcessResult artResult = runOnArtRaw(processedApp, CLASS_NAME);
    if (expectedException == null) {
      assertEquals(0, artResult.exitCode);
      assertEquals("0", artResult.stdout);
    } else {
      assertEquals(1, artResult.exitCode);
      assertThat(artResult.stderr, containsString(expectedException));
    }
    CodeInspector inspector = new CodeInspector(processedApp);
    inspectorConsumer.accept(inspector);
  }

  // The following test checks invoke-direct, which refers to the private static method, is *not*
  // rewritten by publicizer lense, 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 =
        ToolHelper.getDexVm().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 lense, 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);
    });
  }

}