// Copyright (c) 2019, 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.shaking;

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

import com.android.tools.r8.TestParameters;
import com.android.tools.r8.TestParametersCollection;
import com.android.tools.r8.jasmin.JasminBuilder;
import com.android.tools.r8.jasmin.JasminBuilder.ClassBuilder;
import com.android.tools.r8.jasmin.JasminTestBase;
import com.android.tools.r8.naming.MemberNaming.MethodSignature;
import com.android.tools.r8.utils.ThrowingConsumer;
import com.android.tools.r8.utils.codeinspector.ClassSubject;
import com.android.tools.r8.utils.codeinspector.CodeInspector;
import com.android.tools.r8.utils.codeinspector.FieldSubject;
import com.android.tools.r8.utils.codeinspector.InstructionSubject;
import com.android.tools.r8.utils.codeinspector.MethodSubject;
import com.google.common.collect.ImmutableList;
import java.util.Iterator;
import java.util.List;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.Parameterized;

@RunWith(Parameterized.class)
public class FieldReadsJasminTest extends JasminTestBase {
  private static final String CLS = "Empty";
  private static final String MAIN = "Main";
  private final TestParameters parameters;

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

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

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

    ClassBuilder main = builder.addClass(MAIN);
    main.addField("protected", "aField", "I", null);
    main.addMainMethod(
        ".limit stack 2",
        ".limit locals 1",
        "  new Main",
        "  dup",
        "  invokespecial Main/<init>()V",
        "  getfield Main/aField I",
        "  return");

    ensureNoFieldsRead(builder, main);
  }

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

    ClassBuilder main = builder.addClass(MAIN);
    main.addStaticField("sField", "I");
    main.addMainMethod(
        ".limit stack 2",
        ".limit locals 1",
        "  getstatic Main/sField I",
        "  return");

    ensureNoFieldsRead(builder, main);
  }

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

    ClassBuilder main = builder.addClass(MAIN);
    main.addDefaultConstructor();
    main.addStaticField("sField", "Ljava/lang/String;", "\"8\"");
    main.addMainMethod(
        ".limit stack 2",
        ".limit locals 1",
        "  getstatic Main/sField Ljava/lang/String;",
        "  return");

    ensureNoFieldsRead(builder, main);
  }

  private void ensureNoFieldsRead(JasminBuilder app, ClassBuilder clazz) throws Exception {
    List<byte[]> classes = app.buildClasses();

    if (parameters.isDexRuntime()) {
      testForD8()
          .addProgramClassFileData(classes)
          .setMinApi(parameters.getApiLevel())
          .compile()
          .inspect(inspector -> ensureNoFieldsRead(inspector, clazz.name, false));
    }

    testForR8(parameters.getBackend())
        .addProgramClassFileData(classes)
        .addKeepRules("-keep class * { <methods>; }")
        .setMinApi(parameters.getApiLevel())
        .compile()
        .inspect(inspector -> ensureNoFieldsRead(inspector, clazz.name, true));
  }

  private void ensureNoFieldsRead(CodeInspector inspector, String name, boolean isR8) {
    ClassSubject classSubject = inspector.clazz(name);
    assertThat(classSubject, isPresent());
    if (isR8) {
      classSubject.forAllFields(foundFieldSubject -> {
        fail("Expect not to see any fields.");
      });
    }
    MethodSubject mainMethod = classSubject.mainMethod();
    assertThat(mainMethod, isPresent());
    Iterator<InstructionSubject> it =
        mainMethod.iterateInstructions(InstructionSubject::isFieldAccess);
    assertFalse(it.hasNext());
  }

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

    ClassBuilder main = builder.addClass(MAIN);
    // static int sField = System.currentTimeMillis() >=0 ? 42 : 0;
    main.addStaticField("sField", "I", null);
    main.addClassInitializer(
        ".limit stack 4",
        ".limit locals 0",
        "  invokestatic java/lang/System/currentTimeMillis()J",
        "  lconst_0",
        "  lcmp",
        "  iflt l",
        "  bipush 42",
        "  goto p",
        "l:",
        "  iconst_0",
        "p:",
        "  putstatic Main/sField I",
        "  return");
    MethodSignature mainMethod = main.addMainMethod(
        ".limit stack 2",
        ".limit locals 1",
        "  getstatic Main/sField I",
        "  return");

    ensureFieldExistsButNoRead(builder, main, mainMethod, main, "sField");
  }

  private void ensureFieldExistsButNoRead(
      JasminBuilder app,
      ClassBuilder clazz,
      MethodSignature method,
      ClassBuilder fieldHolder,
      String fieldName)
      throws Exception {
    testForR8(parameters.getBackend())
        .addProgramClassFileData(app.buildClasses())
        .addKeepRules("-keep class * { <methods>; }")
        .setMinApi(parameters.getApiLevel())
        .compile()
        .inspect(
            inspector -> {
              FieldSubject fld = inspector.clazz(fieldHolder.name).uniqueFieldWithName(fieldName);
              assertThat(fld, isPresentAndRenamed());

              ClassSubject classSubject = inspector.clazz(clazz.name);
              assertThat(classSubject, isPresent());
              MethodSubject methodSubject = classSubject.uniqueMethodWithName(method.name);
              assertThat(methodSubject, isPresent());
              Iterator<InstructionSubject> it =
                  methodSubject.iterateInstructions(InstructionSubject::isFieldAccess);
              assertFalse(it.hasNext());
            });
  }

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

    ClassBuilder empty = builder.addClass(CLS);
    empty.addDefaultConstructor();
    empty.addField("protected", "aField", "I", null);
    MethodSignature foo = empty.addStaticMethod("foo", ImmutableList.of("L" + CLS + ";"), "V",
        ".limit stack 2",
        ".limit locals 1",
        "  aload 0",
        "  getfield Empty/aField I",
        "  return");

    ClassBuilder main = builder.addClass(MAIN);
    main.addMainMethod(
        ".limit stack 2",
        ".limit locals 1",
        "  aconst_null",
        "  invokestatic Empty/foo(L" + CLS + ";)V",
        "  return");

    inspect(
        builder,
        inspector ->
            ensureFieldExistsAndReadOnlyOnce(
                inspector, empty.name, foo.name, empty, "aField", false),
        inspector -> {
          ClassSubject emptyClassSubject = inspector.clazz(CLS);
          assertThat(emptyClassSubject, isPresent());
          assertTrue(emptyClassSubject.allFields().isEmpty());

          MethodSubject fooMethodSubject = emptyClassSubject.uniqueMethodWithName("foo");
          assertThat(fooMethodSubject, isPresent());
          assertTrue(
              fooMethodSubject
                  .streamInstructions()
                  .filter(InstructionSubject::isInvoke)
                  .anyMatch(
                      invoke ->
                          invoke.getMethod().toSourceString().contains("requireNonNull")
                              || invoke.getMethod().toSourceString().contains("getClass")));
        });
  }

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

    ClassBuilder empty = builder.addClass(CLS);
    empty.addDefaultConstructor();
    empty.addStaticField("sField", "I");
    empty.addClassInitializer(
        ".limit stack 3",
        ".limit locals 1",
        "  getstatic java/lang/System/out Ljava/io/PrintStream;",
        "  ldc \"hello\"",
        "  invokevirtual java/io/PrintStream/print(Ljava/lang/String;)V",
        "  return");

    ClassBuilder main = builder.addClass(MAIN);
    MethodSignature mainMethod = main.addMainMethod(
        ".limit stack 2",
        ".limit locals 1",
        "  getstatic Empty/sField I",
        "  return");

    inspect(
        builder,
        inspector ->
            ensureFieldExistsAndReadOnlyOnce(
                inspector, main.name, mainMethod.name, empty, "sField", false),
        inspector -> {
          ClassSubject emptyClassSubject = inspector.clazz(empty.name);
          assertThat(emptyClassSubject, isPresent());
          assertEquals(1, emptyClassSubject.allStaticFields().size());

          FieldSubject clinitFieldSubject = emptyClassSubject.allStaticFields().get(0);
          assertEquals("$r8$clinit", clinitFieldSubject.getOriginalName());

          ClassSubject mainClassSubject = inspector.clazz(main.name);
          assertThat(mainClassSubject, isPresent());
          assertThat(mainClassSubject.mainMethod(), isPresent());
          assertTrue(
              mainClassSubject
                  .mainMethod()
                  .streamInstructions()
                  .filter(InstructionSubject::isStaticGet)
                  .anyMatch(
                      instruction ->
                          instruction.getField().equals(clinitFieldSubject.getField().field)));
        });
  }

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

    ClassBuilder empty = builder.addClass(CLS);
    empty.addDefaultConstructor();
    empty.addClassInitializer(
        ".limit stack 2",
        ".limit locals 0",
        "  getstatic Main/sField I",
        "  iconst_1",
        "  iadd",
        "  putstatic Main/sField I",
        "  return");

    ClassBuilder main = builder.addClass(MAIN);
    main.addDefaultConstructor();
    main.addStaticField("sField", "I", null);
    main.addClassInitializer(
        ".limit stack 2",
        ".limit locals 0",
        "  bipush 1",
        "  putstatic Main/sField I",
        "  return");
    MethodSignature mainMethod = main.addMainMethod(
        ".limit stack 3",
        ".limit locals 2",
        "  getstatic Main/sField I",
        "  new Empty",
        "  dup",
        "  invokespecial Empty/<init>()V",
        "  getstatic Main/sField I",
        "  bipush 2",
        "  if_icmpeq r",
        "  aconst_null",
        "  athrow",
        "r:",
        "  return");

    ensureFieldExistsAndReadOnlyOnce(builder, main, mainMethod, main, "sField");
  }

  private void inspect(
      JasminBuilder app,
      ThrowingConsumer<CodeInspector, RuntimeException> d8Inspector,
      ThrowingConsumer<CodeInspector, RuntimeException> r8Inspector)
      throws Exception {
    List<byte[]> classes = app.buildClasses();

    if (parameters.isDexRuntime()) {
      testForD8()
          .addProgramClassFileData(classes)
          .setMinApi(parameters.getApiLevel())
          .compile()
          .inspect(d8Inspector);
    }

    testForR8(parameters.getBackend())
        .addProgramClassFileData(classes)
        .addKeepRules("-keep class * { <methods>; }")
        .setMinApi(parameters.getApiLevel())
        .compile()
        .inspect(r8Inspector);
  }

  private void ensureFieldExistsAndReadOnlyOnce(
      JasminBuilder app,
      ClassBuilder clazz,
      MethodSignature method,
      ClassBuilder fieldHolder,
      String fieldName)
      throws Exception {
    inspect(
        app,
        inspector ->
            ensureFieldExistsAndReadOnlyOnce(
                inspector, clazz.name, method.name, fieldHolder, fieldName, false),
        inspector ->
            ensureFieldExistsAndReadOnlyOnce(
                inspector, clazz.name, method.name, fieldHolder, fieldName, true));
  }

  private void ensureFieldExistsAndReadOnlyOnce(
      CodeInspector inspector,
      String className,
      String methodName,
      ClassBuilder fieldHolder,
      String fieldName,
      boolean isR8) {
    FieldSubject fld = inspector.clazz(fieldHolder.name).uniqueFieldWithName(fieldName);
    if (isR8) {
      assertThat(fld, isPresentAndRenamed());
    } else {
      assertThat(fld, isPresent());
    }

    ClassSubject classSubject = inspector.clazz(className);
    assertThat(classSubject, isPresent());
    MethodSubject methodSubject = classSubject.uniqueMethodWithName(methodName);
    assertThat(methodSubject, isPresent());
    Iterator<InstructionSubject> it =
        methodSubject.iterateInstructions(InstructionSubject::isFieldAccess);
    assertTrue(it.hasNext());
    assertEquals(fld.getFinalName(), it.next().getField().name.toString());
    assertFalse(it.hasNext());
  }
}
