// Copyright (c) 2023, 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.profile.art.completeness;

import static com.android.tools.r8.ir.desugar.records.RecordDesugaring.EQUALS_RECORD_METHOD_NAME;
import static com.android.tools.r8.ir.desugar.records.RecordDesugaring.GET_FIELDS_AS_OBJECTS_METHOD_NAME;
import static com.android.tools.r8.utils.codeinspector.CodeMatchers.invokesMethod;
import static com.android.tools.r8.utils.codeinspector.Matchers.ifThen;
import static com.android.tools.r8.utils.codeinspector.Matchers.isPresent;
import static com.android.tools.r8.utils.codeinspector.Matchers.notIf;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.junit.Assert.assertEquals;
import static org.junit.Assume.assumeTrue;

import com.android.tools.r8.D8TestCompileResult;
import com.android.tools.r8.R8TestCompileResult;
import com.android.tools.r8.TestBase;
import com.android.tools.r8.TestParameters;
import com.android.tools.r8.TestParametersCollection;
import com.android.tools.r8.desugar.records.RecordTestUtils;
import com.android.tools.r8.profile.art.model.ExternalArtProfile;
import com.android.tools.r8.profile.art.utils.ArtProfileInspector;
import com.android.tools.r8.references.ClassReference;
import com.android.tools.r8.references.Reference;
import com.android.tools.r8.synthesis.SyntheticItemsTestUtils;
import com.android.tools.r8.utils.InternalOptions.InlinerOptions;
import com.android.tools.r8.utils.MethodReferenceUtils;
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.MethodSubject;
import com.google.common.collect.ImmutableList;
import java.util.Collections;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.Parameterized;
import org.junit.runners.Parameterized.Parameter;
import org.junit.runners.Parameterized.Parameters;

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

  private static final String RECORD_NAME = "SimpleRecord";
  private static final byte[][] PROGRAM_DATA = RecordTestUtils.getProgramData(RECORD_NAME);
  private static final String EXPECTED_RESULT =
      StringUtils.lines("Jane Doe", "42", "Jane Doe", "42");

  private static final ClassReference MAIN_REFERENCE =
      Reference.classFromTypeName(RecordTestUtils.getMainType(RECORD_NAME));
  private static final ClassReference PERSON_REFERENCE =
      Reference.classFromTypeName(MAIN_REFERENCE.getTypeName() + "$Person");
  private static final ClassReference RECORD_REFERENCE =
      Reference.classFromTypeName("java.lang.Record");
  private static final ClassReference OBJECT_REFERENCE = Reference.classFromClass(Object.class);
  private static final ClassReference STRING_REFERENCE = Reference.classFromClass(String.class);

  @Parameter(0)
  public TestParameters parameters;

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

  @Test
  public void testReference() throws Exception {
    parameters.assumeJvmTestParameters();
    assumeTrue(parameters.canUseRecords());
    testForJvm()
        .addProgramClassFileData(PROGRAM_DATA)
        .run(parameters.getRuntime(), MAIN_REFERENCE.getTypeName())
        .assertSuccessWithOutput(EXPECTED_RESULT);
  }

  @Test
  public void testD8() throws Exception {
    D8TestCompileResult compileResult =
        testForD8(parameters.getBackend())
            .addProgramClassFileData(PROGRAM_DATA)
            .addArtProfileForRewriting(getArtProfile())
            .setMinApi(parameters.getApiLevel())
            .compile();
    compileResult
        .inspectResidualArtProfile(
            profileInspector ->
                compileResult.inspectWithOptions(
                    inspector -> inspectD8(profileInspector, inspector),
                    options -> options.testing.disableRecordApplicationReaderMap = true))
        .run(parameters.getRuntime(), MAIN_REFERENCE.getTypeName())
        .assertSuccessWithOutput(EXPECTED_RESULT);
  }

  @Test
  public void testR8() throws Exception {
    parameters.assumeR8TestParameters();
    assumeTrue(parameters.canUseRecords() || parameters.isDexRuntime());
    R8TestCompileResult compileResult =
        testForR8(parameters.getBackend())
            .addProgramClassFileData(PROGRAM_DATA)
            .addKeepMainRule(MAIN_REFERENCE.getTypeName())
            .addKeepRules(
                "-neverpropagatevalue class " + PERSON_REFERENCE.getTypeName() + " { <fields>; }")
            .addArtProfileForRewriting(getArtProfile())
            .addOptionsModification(InlinerOptions::disableInlining)
            .applyIf(
                parameters.isCfRuntime(),
                testBuilder ->
                    testBuilder.addLibraryFiles(RecordTestUtils.getJdk15LibraryFiles(temp)))
            .enableProguardTestOptions()
            .noHorizontalClassMergingOfSynthetics()
            .setMinApi(parameters.getApiLevel())
            .compile();
    compileResult
        .inspectResidualArtProfile(
            profileInspector ->
                compileResult.inspectWithOptions(
                    inspector -> inspectR8(profileInspector, inspector),
                    options -> options.testing.disableRecordApplicationReaderMap = true))
        .run(parameters.getRuntime(), MAIN_REFERENCE.getTypeName())
        .assertSuccessWithOutput(EXPECTED_RESULT);
  }

  private ExternalArtProfile getArtProfile() {
    return ExternalArtProfile.builder()
        .addMethodRule(MethodReferenceUtils.mainMethod(MAIN_REFERENCE))
        .addClassRule(PERSON_REFERENCE)
        .addMethodRule(
            MethodReferenceUtils.instanceConstructor(
                PERSON_REFERENCE, STRING_REFERENCE, Reference.INT))
        .addMethodRule(
            Reference.method(PERSON_REFERENCE, "name", Collections.emptyList(), STRING_REFERENCE))
        .addMethodRule(
            Reference.method(PERSON_REFERENCE, "age", Collections.emptyList(), Reference.INT))
        .addMethodRule(
            Reference.method(
                PERSON_REFERENCE, "equals", ImmutableList.of(OBJECT_REFERENCE), Reference.BOOL))
        .addMethodRule(
            Reference.method(PERSON_REFERENCE, "hashCode", Collections.emptyList(), Reference.INT))
        .addMethodRule(
            Reference.method(
                PERSON_REFERENCE, "toString", Collections.emptyList(), STRING_REFERENCE))
        .build();
  }

  private void inspectD8(ArtProfileInspector profileInspector, CodeInspector inspector) {
    inspect(
        profileInspector,
        inspector,
        SyntheticItemsTestUtils.syntheticRecordTagClass(),
        parameters.canUseNestBasedAccessesWhenDesugaring(),
        parameters.canUseRecordsWhenDesugaring());
  }

  private void inspectR8(ArtProfileInspector profileInspector, CodeInspector inspector) {
    inspect(
        profileInspector,
        inspector,
        RECORD_REFERENCE,
        parameters.canUseNestBasedAccesses(),
        parameters.canUseRecords());
  }

  private void inspect(
      ArtProfileInspector profileInspector,
      CodeInspector inspector,
      ClassReference recordClassReference,
      boolean canUseNestBasedAccesses,
      boolean canUseRecords) {
    ClassSubject mainClassSubject = inspector.clazz(MAIN_REFERENCE);
    assertThat(mainClassSubject, isPresent());

    MethodSubject mainMethodSubject = mainClassSubject.mainMethod();
    assertThat(mainMethodSubject, isPresent());

    ClassSubject recordTagClassSubject = inspector.clazz(recordClassReference);
    assertThat(recordTagClassSubject, notIf(isPresent(), canUseRecords));
    if (!canUseRecords) {
      assertEquals(1, recordTagClassSubject.allMethods().size());
    }

    MethodSubject recordTagInstanceInitializerSubject = recordTagClassSubject.init();
    assertThat(recordTagInstanceInitializerSubject, notIf(isPresent(), canUseRecords));

    ClassSubject personRecordClassSubject = inspector.clazz(PERSON_REFERENCE);
    assertThat(personRecordClassSubject, isPresent());
    assertEquals(
        canUseRecords
            ? inspector.getTypeSubject(RECORD_REFERENCE.getTypeName())
            : recordTagClassSubject.asTypeSubject(),
        personRecordClassSubject.getSuperType());
    assertEquals(canUseRecords ? 6 : 10, personRecordClassSubject.allMethods().size());

    MethodSubject personInstanceInitializerSubject =
        personRecordClassSubject.uniqueInstanceInitializer();
    assertThat(personInstanceInitializerSubject, isPresent());

    // Name getters.
    MethodSubject nameMethodSubject = personRecordClassSubject.uniqueMethodWithOriginalName("name");
    assertThat(nameMethodSubject, isPresent());

    MethodSubject nameNestAccessorMethodSubject =
        personRecordClassSubject.uniqueMethodWithOriginalName(
            SyntheticItemsTestUtils.syntheticNestInstanceFieldGetter(
                    Reference.field(PERSON_REFERENCE, "name", STRING_REFERENCE))
                .getMethodName());
    assertThat(nameNestAccessorMethodSubject, notIf(isPresent(), canUseNestBasedAccesses));

    // Age getters.
    MethodSubject ageMethodSubject = personRecordClassSubject.uniqueMethodWithOriginalName("age");
    assertThat(ageMethodSubject, isPresent());

    MethodSubject ageNestAccessorMethodSubject =
        personRecordClassSubject.uniqueMethodWithOriginalName(
            SyntheticItemsTestUtils.syntheticNestInstanceFieldGetter(
                    Reference.field(PERSON_REFERENCE, "age", Reference.INT))
                .getMethodName());
    assertThat(ageNestAccessorMethodSubject, notIf(isPresent(), canUseNestBasedAccesses));

    // boolean equals(Object)
    MethodSubject getFieldsAsObjectsMethodSubject =
        personRecordClassSubject.uniqueMethodWithOriginalName(GET_FIELDS_AS_OBJECTS_METHOD_NAME);
    assertThat(getFieldsAsObjectsMethodSubject, notIf(isPresent(), canUseRecords));

    MethodSubject equalsHelperMethodSubject =
        personRecordClassSubject.uniqueMethodWithOriginalName(EQUALS_RECORD_METHOD_NAME);
    assertThat(equalsHelperMethodSubject, notIf(isPresent(), canUseRecords));

    MethodSubject equalsMethodSubject =
        personRecordClassSubject.uniqueMethodWithOriginalName("equals");
    assertThat(equalsMethodSubject, isPresent());
    assertThat(
        equalsMethodSubject, ifThen(!canUseRecords, invokesMethod(equalsHelperMethodSubject)));

    // int hashCode()
    ClassSubject hashCodeHelperClassSubject =
        inspector.clazz(SyntheticItemsTestUtils.syntheticRecordHelperClass(PERSON_REFERENCE, 0));
    assertThat(hashCodeHelperClassSubject, notIf(isPresent(), canUseRecords));

    MethodSubject hashCodeHelperMethodSubject = hashCodeHelperClassSubject.uniqueMethod();
    assertThat(hashCodeHelperMethodSubject, notIf(isPresent(), canUseRecords));

    MethodSubject hashCodeMethodSubject =
        personRecordClassSubject.uniqueMethodWithOriginalName("hashCode");
    assertThat(hashCodeMethodSubject, isPresent());
    assertThat(
        hashCodeMethodSubject,
        ifThen(!canUseRecords, invokesMethod(getFieldsAsObjectsMethodSubject)));
    assertThat(
        hashCodeMethodSubject, ifThen(!canUseRecords, invokesMethod(hashCodeHelperMethodSubject)));

    // String toString()
    ClassSubject toStringHelperClassSubject =
        inspector.clazz(SyntheticItemsTestUtils.syntheticRecordHelperClass(PERSON_REFERENCE, 1));
    assertThat(toStringHelperClassSubject, notIf(isPresent(), canUseRecords));

    MethodSubject toStringHelperMethodSubject = toStringHelperClassSubject.uniqueMethod();
    assertThat(toStringHelperMethodSubject, notIf(isPresent(), canUseRecords));

    MethodSubject toStringMethodSubject =
        personRecordClassSubject.uniqueMethodWithOriginalName("toString");
    assertThat(toStringMethodSubject, isPresent());
    assertThat(
        toStringMethodSubject,
        ifThen(!canUseRecords, invokesMethod(getFieldsAsObjectsMethodSubject)));
    assertThat(
        toStringMethodSubject, ifThen(!canUseRecords, invokesMethod(toStringHelperMethodSubject)));

    profileInspector
        .assertContainsClassRule(personRecordClassSubject)
        .assertContainsMethodRules(
            mainMethodSubject,
            personInstanceInitializerSubject,
            nameMethodSubject,
            ageMethodSubject,
            equalsMethodSubject,
            hashCodeMethodSubject,
            toStringMethodSubject)
        .applyIf(
            !canUseNestBasedAccesses,
            i ->
                i.assertContainsMethodRules(
                    nameNestAccessorMethodSubject, ageNestAccessorMethodSubject))
        .applyIf(
            !canUseRecords,
            i ->
                i.assertContainsClassRules(
                        recordTagClassSubject,
                        hashCodeHelperClassSubject,
                        toStringHelperClassSubject)
                    .assertContainsMethodRules(
                        recordTagInstanceInitializerSubject,
                        equalsHelperMethodSubject,
                        getFieldsAsObjectsMethodSubject,
                        hashCodeHelperMethodSubject,
                        toStringHelperMethodSubject))
        .assertContainsNoOtherRules();
  }
}
