// 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.isRenamed;
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.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().withAllRuntimes().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.getRuntime())
          .compile()
          .inspect(inspector -> ensureNoFieldsRead(inspector, clazz.name, false));
    }

    testForR8(parameters.getBackend())
        .addProgramClassFileData(classes)
        .addKeepRules("-keep class * { <methods>; }")
        .setMinApi(parameters.getRuntime())
        .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.getRuntime())
        .compile()
        .inspect(inspector -> {
          FieldSubject fld = inspector.clazz(fieldHolder.name).uniqueFieldWithName(fieldName);
          assertThat(fld, isRenamed());

          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");

    ensureFieldExistsAndReadOnlyOnce(builder, empty, foo, empty, "aField");
  }

  @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");

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

  @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 ensureFieldExistsAndReadOnlyOnce(
      JasminBuilder app,
      ClassBuilder clazz,
      MethodSignature method,
      ClassBuilder fieldHolder,
      String fieldName)
      throws Exception {
    List<byte[]> classes = app.buildClasses();

    if (parameters.isDexRuntime()) {
      testForD8()
          .addProgramClassFileData(classes)
          .setMinApi(parameters.getRuntime())
          .compile()
          .inspect(inspector -> ensureFieldExistsAndReadOnlyOnce(
              inspector, clazz.name, method.name, fieldHolder, fieldName, false));
    }

    testForR8(parameters.getBackend())
        .addProgramClassFileData(classes)
        .addKeepRules("-keep class * { <methods>; }")
        .setMinApi(parameters.getRuntime())
        .compile()
        .inspect(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, isRenamed());
    } 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());
  }
}
