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

import static com.android.tools.r8.ir.desugar.LambdaRewriter.LAMBDA_CLASS_NAME_PREFIX;
import static com.android.tools.r8.utils.codeinspector.Matchers.isPresent;
import static org.hamcrest.CoreMatchers.containsString;
import static org.hamcrest.CoreMatchers.not;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;

import com.android.tools.r8.NeverInline;
import com.android.tools.r8.TestBase;
import com.android.tools.r8.TestRunResult;
import com.android.tools.r8.ToolHelper;
import com.android.tools.r8.ToolHelper.ProcessResult;
import com.android.tools.r8.ir.optimize.classinliner.builders.BuildersTestClass;
import com.android.tools.r8.ir.optimize.classinliner.builders.ControlFlow;
import com.android.tools.r8.ir.optimize.classinliner.builders.Pair;
import com.android.tools.r8.ir.optimize.classinliner.builders.PairBuilder;
import com.android.tools.r8.ir.optimize.classinliner.builders.Tuple;
import com.android.tools.r8.ir.optimize.classinliner.code.C;
import com.android.tools.r8.ir.optimize.classinliner.code.CodeTestClass;
import com.android.tools.r8.ir.optimize.classinliner.invalidroot.InvalidRootsTestClass;
import com.android.tools.r8.ir.optimize.classinliner.lambdas.LambdasTestClass;
import com.android.tools.r8.ir.optimize.classinliner.trivial.ClassWithFinal;
import com.android.tools.r8.ir.optimize.classinliner.trivial.CycleReferenceAB;
import com.android.tools.r8.ir.optimize.classinliner.trivial.CycleReferenceBA;
import com.android.tools.r8.ir.optimize.classinliner.trivial.EmptyClass;
import com.android.tools.r8.ir.optimize.classinliner.trivial.EmptyClassWithInitializer;
import com.android.tools.r8.ir.optimize.classinliner.trivial.Iface1;
import com.android.tools.r8.ir.optimize.classinliner.trivial.Iface1Impl;
import com.android.tools.r8.ir.optimize.classinliner.trivial.Iface2;
import com.android.tools.r8.ir.optimize.classinliner.trivial.Iface2Impl;
import com.android.tools.r8.ir.optimize.classinliner.trivial.ReferencedFields;
import com.android.tools.r8.ir.optimize.classinliner.trivial.TrivialTestClass;
import com.android.tools.r8.jasmin.JasminBuilder;
import com.android.tools.r8.jasmin.JasminBuilder.ClassBuilder;
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.StringUtils;
import com.android.tools.r8.utils.codeinspector.ClassSubject;
import com.android.tools.r8.utils.codeinspector.CodeInspector;
import com.android.tools.r8.utils.codeinspector.FieldAccessInstructionSubject;
import com.android.tools.r8.utils.codeinspector.FoundClassSubject;
import com.android.tools.r8.utils.codeinspector.InstructionSubject;
import com.android.tools.r8.utils.codeinspector.NewInstanceInstructionSubject;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Sets;
import com.google.common.collect.Streams;
import java.util.Collections;
import java.util.Iterator;
import java.util.Set;
import java.util.stream.Collectors;
import java.util.stream.Stream;
import org.junit.Assume;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.Parameterized;

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

  private final Backend backend;

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

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

  @Test
  public void testTrivial() throws Exception {
    Class<?> main = TrivialTestClass.class;
    Class<?>[] classes = {
        TrivialTestClass.class,
        TrivialTestClass.Inner.class,
        ReferencedFields.class,
        EmptyClass.class,
        EmptyClassWithInitializer.class,
        Iface1.class,
        Iface1Impl.class,
        Iface2.class,
        Iface2Impl.class,
        CycleReferenceAB.class,
        CycleReferenceBA.class,
        ClassWithFinal.class
    };
    String javaOutput = runOnJava(main);
    TestRunResult result =
        testForR8(backend)
            .addProgramClasses(classes)
            .enableInliningAnnotations()
            .addKeepMainRule(main)
            .addKeepAttributes("LineNumberTable")
            .addOptionsModification(this::configure)
            .allowAccessModification()
            .noMinification()
            .run(main)
            .assertSuccessWithOutput(javaOutput);

    CodeInspector inspector = result.inspector();
    ClassSubject clazz = inspector.clazz(main);

    assertEquals(
        Collections.singleton("java.lang.StringBuilder"),
        collectTypes(clazz, "testInner", "void"));

    assertEquals(
        Collections.emptySet(),
        collectTypes(clazz, "testConstructorMapping1", "void"));

    assertEquals(
        Collections.emptySet(),
        collectTypes(clazz, "testConstructorMapping2", "void"));

    assertEquals(
        Collections.singleton("java.lang.StringBuilder"),
        collectTypes(clazz, "testConstructorMapping3", "void"));

    assertEquals(
        Collections.emptySet(),
        collectTypes(clazz, "testEmptyClass", "void"));

    assertEquals(
        Collections.singleton(
            "com.android.tools.r8.ir.optimize.classinliner.trivial.EmptyClassWithInitializer"),
        collectTypes(clazz, "testEmptyClassWithInitializer", "void"));

    assertEquals(
        Collections.singleton(
            "com.android.tools.r8.ir.optimize.classinliner.trivial.ClassWithFinal"),
        collectTypes(clazz, "testClassWithFinalizer", "void"));

    assertEquals(
        Collections.emptySet(),
        collectTypes(clazz, "testCallOnIface1", "void"));

    assertEquals(
        Collections.singleton(
            "com.android.tools.r8.ir.optimize.classinliner.trivial.Iface2Impl"),
        collectTypes(clazz, "testCallOnIface2", "void"));

    assertEquals(
        Sets.newHashSet(
            "com.android.tools.r8.ir.optimize.classinliner.trivial.CycleReferenceAB",
            "java.lang.StringBuilder"),
        collectTypes(clazz, "testCycles", "void"));

    assertEquals(
        Sets.newHashSet("java.lang.StringBuilder",
            "com.android.tools.r8.ir.optimize.classinliner.trivial.CycleReferenceAB"),
        collectTypes(inspector.clazz(CycleReferenceAB.class), "foo", "void", "int"));

    assertFalse(inspector.clazz(CycleReferenceBA.class).isPresent());
  }

  @Test
  public void testBuilders() throws Exception {
    Class<?> main = BuildersTestClass.class;
    Class<?>[] classes = {
        NeverInline.class,
        BuildersTestClass.class,
        BuildersTestClass.Pos.class,
        Tuple.class,
        Pair.class,
        PairBuilder.class,
        ControlFlow.class,
    };
    String javaOutput = runOnJava(main);
    TestRunResult result =
        testForR8(backend)
            .addProgramClasses(classes)
            .enableInliningAnnotations()
            .addKeepMainRule(main)
            .addKeepAttributes("LineNumberTable")
            .addOptionsModification(
                o -> {
                  o.inliningInstructionLimit = 6;
                  configure(o);
                })
            .allowAccessModification()
            .noMinification()
            .run(main)
            .assertSuccessWithOutput(javaOutput);

    CodeInspector inspector = result.inspector();
    ClassSubject clazz = inspector.clazz(main);

    for (int i = 1; i <= 3; i++) {
      Set<String> expected =
          backend == Backend.CF
              // const-string canonicalization is disabled in CF, which helps ClassInliner identify
              // PairBuilder as candidate.
              ? ImmutableSet.of(
                  "java.lang.StringBuilder",
                  "com.android.tools.r8.ir.optimize.classinliner.builders.PairBuilder")
              : ImmutableSet.of("java.lang.StringBuilder");
      assertEquals(expected, collectTypes(clazz, "testSimpleBuilder" + i, "void"));
    }

    // Note that Pair created instances were also inlined in the following method since
    // we use 'System.out.println(pX.toString())', if we used 'System.out.println(pX)'
    // as in the above method, the instance of pair would be passed to println() which
    // would make it not eligible for inlining.
    // TODO(b/143129517): This relies on PairBuilder::build being inlined, thus the limit of 6.
    assertEquals(
        Collections.singleton("java.lang.StringBuilder"),
        collectTypes(clazz, "testSimpleBuilderWithMultipleBuilds", "void"));

    if (backend == Backend.DEX) {
      assertFalse(inspector.clazz(PairBuilder.class).isPresent());
    }

    assertEquals(
        Collections.singleton("java.lang.StringBuilder"),
        collectTypes(clazz, "testBuilderConstructors", "void"));

    assertFalse(inspector.clazz(Tuple.class).isPresent());

    assertEquals(
        Collections.singleton("java.lang.StringBuilder"),
        collectTypes(clazz, "testWithControlFlow", "void"));

    assertFalse(inspector.clazz(ControlFlow.class).isPresent());

    assertEquals(Collections.emptySet(), collectTypes(clazz, "testWithMoreControlFlow", "void"));

    assertFalse(inspector.clazz(BuildersTestClass.Pos.class).isPresent());
  }

  @Test
  public void testErroneousInput() throws Exception {
    JasminBuilder builder = new JasminBuilder();

    ClassBuilder testClass = builder.addClass("A");
    testClass.addStaticFinalField("f", "I", "123");
    testClass.addDefaultConstructor();

    ClassBuilder mainClass = builder.addClass("Main");
    mainClass.addMainMethod(
        ".limit stack 3",
        ".limit locals 1",
        "  getstatic java/lang/System/out Ljava/io/PrintStream;",
        "  new A",
        "  dup",
        "  invokespecial A/<init>()V",
        "  getfield A/f I",
        "  invokevirtual java/io/PrintStream/print(I)V",
        "  return");

    AndroidApp compiled =
        compileWithR8(builder.build(), getProguardConfig(mainClass.name), this::configure, backend);

    // Check that the code fails with an IncompatibleClassChangeError with Java.
    ProcessResult javaResult =
        runOnJavaRaw(mainClass.name, builder.buildClasses().toArray(new byte[2][]));
    assertThat(javaResult.stderr, containsString("IncompatibleClassChangeError"));

    // Check that the code fails with an IncompatibleClassChangeError with ART.
    ProcessResult result =
        backend == Backend.DEX
            ? runOnArtRaw(compiled, mainClass.name)
            : runOnJavaRaw(compiled, mainClass.name, Collections.emptyList());
    assertThat(result.stderr, containsString("IncompatibleClassChangeError"));
  }

  @Test
  public void testCodeSample() throws Exception {
    Class<?> main = CodeTestClass.class;
    Class<?>[] classes = {
        C.class,
        C.L.class,
        C.F.class,
        CodeTestClass.class
    };
    String javaOutput = runOnJava(main);
    TestRunResult result =
        testForR8(backend)
            .addProgramClasses(classes)
            .enableInliningAnnotations()
            .addKeepMainRule(main)
            .addKeepAttributes("LineNumberTable")
            .addOptionsModification(this::configure)
            .allowAccessModification()
            .noMinification()
            .run(main)
            .assertSuccessWithOutput(javaOutput);

    CodeInspector inspector = result.inspector();
    ClassSubject clazz = inspector.clazz(C.class);

    assertEquals(
        Collections.emptySet(),
        collectTypes(clazz, "method1", "int"));

    assertEquals(
        Collections.emptySet(),
        collectTypes(clazz, "method2", "int"));

    assertEquals(
        Collections.emptySet(),
        collectTypes(clazz, "method3", "int"));

    assertFalse(inspector.clazz(C.L.class).isPresent());
    assertFalse(inspector.clazz(C.F.class).isPresent());
  }

  @Test
  public void testInvalidatedRoot() throws Exception {
    Class<?> main = InvalidRootsTestClass.class;
    Class<?>[] classes = {
        InvalidRootsTestClass.class,
        InvalidRootsTestClass.A.class,
        InvalidRootsTestClass.B.class,
        InvalidRootsTestClass.NeverReturnsNormally.class,
        InvalidRootsTestClass.InitNeverReturnsNormally.class
    };
    String javaOutput = runOnJava(main);
    TestRunResult result =
        testForR8(backend)
            .addProgramClasses(classes)
            .enableProguardTestOptions()
            .enableInliningAnnotations()
            .addKeepMainRule(main)
            .addKeepAttributes("LineNumberTable")
            .addOptionsModification(
                o -> {
                  // TODO(b/143129517, 141719453): The limit seems to only be needed for DEX...
                  o.classInliningInstructionLimit = 100;
                  o.classInliningInstructionAllowance = 1000;
                  configure(o);
                })
            .allowAccessModification()
            .noMinification()
            .run(main)
            .assertSuccessWithOutput(javaOutput);

    CodeInspector inspector = result.inspector();
    ClassSubject clazz = inspector.clazz(main);

    // TODO(b/143129517, 141719453): This expectation relies on the class inlining limits.
    assertEquals(
        Sets.newHashSet("java.lang.StringBuilder", "java.lang.RuntimeException"),
        collectTypes(clazz, "testExtraNeverReturnsNormally", "void"));

    assertEquals(
        Sets.newHashSet("java.lang.StringBuilder", "java.lang.RuntimeException"),
        collectTypes(clazz, "testDirectNeverReturnsNormally", "void"));

    assertEquals(
        Sets.newHashSet("java.lang.StringBuilder", "java.lang.RuntimeException"),
        collectTypes(clazz, "testInitNeverReturnsNormally", "void"));

    assertThat(inspector.clazz(InvalidRootsTestClass.NeverReturnsNormally.class), isPresent());
    assertThat(
        inspector.clazz(InvalidRootsTestClass.InitNeverReturnsNormally.class), not(isPresent()));

    // TODO(b/143129517, b/141719453): This expectation relies on the class inlining limits.
    assertEquals(
        Sets.newHashSet("java.lang.StringBuilder", "java.lang.RuntimeException"),
        collectTypes(clazz, "testRootInvalidatesAfterInlining", "void"));

    assertThat(inspector.clazz(InvalidRootsTestClass.A.class), not(isPresent()));
    assertThat(inspector.clazz(InvalidRootsTestClass.B.class), not(isPresent()));
  }

  @Test
  public void testDesugaredLambdas() throws Exception {
    Assume.assumeFalse("No desugaring with CF backend", backend == Backend.CF);
    Class<?> main = LambdasTestClass.class;
    Class<?>[] classes = {
        LambdasTestClass.class,
        LambdasTestClass.Iface.class,
        LambdasTestClass.IfaceUtil.class
    };
    String javaOutput = runOnJava(main);
    TestRunResult result =
        testForR8(backend)
            .addProgramClasses(classes)
            .addKeepMainRule(main)
            .addKeepAttributes("LineNumberTable")
            .addOptionsModification(
                o -> {
                  // TODO(b/141719453): Identify single instances instead of increasing the limit.
                  o.classInliningInstructionLimit = 20;
                  configure(o);
                })
            .allowAccessModification()
            .enableInliningAnnotations()
            .noMinification()
            .run(main)
            .assertSuccessWithOutput(javaOutput);

    CodeInspector inspector = result.inspector();
    ClassSubject clazz = inspector.clazz(main);

    assertEquals(
        Sets.newHashSet(
            "java.lang.StringBuilder"),
        collectTypes(clazz, "testStatelessLambda", "void"));

    // TODO(b/120814598): Should only be "java.lang.StringBuilder". Lambdas are not class inlined
    // because parameter usage is not available for each lambda constructor.
    Set<String> expectedTypes = Sets.newHashSet("java.lang.StringBuilder");
    expectedTypes.addAll(
        inspector.allClasses().stream()
            .map(FoundClassSubject::getFinalName)
            .filter(name -> name.contains(LAMBDA_CLASS_NAME_PREFIX))
            .collect(Collectors.toList()));
    assertEquals(
        expectedTypes,
        collectTypes(clazz, "testStatefulLambda", "void", "java.lang.String", "java.lang.String"));

    // TODO(b/120814598): Should be 0. Lambdas are not class inlined because parameter usage is not
    // available for each lambda constructor.
    assertEquals(
        3,
        inspector.allClasses().stream().filter(ClassSubject::isSynthesizedJavaLambdaClass).count());
  }

  private Set<String> collectTypes(
      ClassSubject clazz, String methodName, String retValue, String... params) {
    return Stream.concat(
        collectNewInstanceTypesWithRetValue(clazz, methodName, retValue, params),
        collectStaticGetTypesWithRetValue(clazz, methodName, retValue, params)
    ).collect(Collectors.toSet());
  }

  private Stream<String> collectNewInstanceTypesWithRetValue(
      ClassSubject clazz, String methodName, String retValue, String... params) {
    assertNotNull(clazz);
    MethodSignature signature = new MethodSignature(methodName, retValue, params);
    Iterator<InstructionSubject> iterator = clazz.method(signature).iterateInstructions();
    return Streams.stream(iterator)
        .filter(InstructionSubject::isNewInstance)
        .map(is -> ((NewInstanceInstructionSubject) is).getType().toSourceString());
  }

  private Stream<String> collectStaticGetTypesWithRetValue(
      ClassSubject clazz, String methodName, String retValue, String... params) {
    assertNotNull(clazz);
    MethodSignature signature = new MethodSignature(methodName, retValue, params);
    Iterator<InstructionSubject> iterator = clazz.method(signature).iterateInstructions();
    return Streams.stream(iterator)
        .filter(InstructionSubject::isStaticGet)
        .map(is -> (FieldAccessInstructionSubject) is)
        .filter(fais -> fais.holder().is(fais.type()))
        .map(fais -> fais.holder().toString());
  }

  private String getProguardConfig(String main) {
    return StringUtils.joinLines(
        keepMainProguardConfiguration(main),
        "-dontobfuscate",
        "-allowaccessmodification",
        "-keepattributes LineNumberTable");
  }

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