// 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.internal.proto;

import static com.android.tools.r8.utils.codeinspector.Matchers.isPresent;
import static com.android.tools.r8.utils.codeinspector.Matchers.notIf;
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 com.android.tools.r8.R8TestRunResult;
import com.android.tools.r8.TestParameters;
import com.android.tools.r8.ToolHelper;
import com.android.tools.r8.graph.DexItemFactory;
import com.android.tools.r8.utils.BooleanUtils;
import com.android.tools.r8.utils.codeinspector.ClassSubject;
import com.android.tools.r8.utils.codeinspector.CodeInspector;
import com.android.tools.r8.utils.codeinspector.analysis.ProtoApplicationStats;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableSet;
import java.nio.file.Path;
import java.util.List;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.Parameterized;

@RunWith(Parameterized.class)
public class Proto2ShrinkingTest extends ProtoShrinkingTestBase {

  private static final String CONTAINS_FLAGGED_OFF_FIELD =
      "com.android.tools.r8.proto2.Shrinking$ContainsFlaggedOffField";
  private static final String EXT_B =
      "com.android.tools.r8.proto2.Shrinking$PartiallyUsedWithExtension$ExtB";
  private static final String EXT_C =
      "com.android.tools.r8.proto2.Shrinking$PartiallyUsedWithExtension$ExtC";
  private static final String FLAGGED_OFF_EXTENSION =
      "com.android.tools.r8.proto2.Shrinking$HasFlaggedOffExtension$Ext";
  private static final String HAS_NO_USED_EXTENSIONS =
      "com.android.tools.r8.proto2.Shrinking$HasNoUsedExtensions";
  private static final String HAS_REQUIRED_FIELD =
      "com.android.tools.r8.proto2.Graph$HasRequiredField";
  private static final String PARTIALLY_USED =
      "com.android.tools.r8.proto2.Shrinking$PartiallyUsed";
  private static final String USED_ROOT = "com.android.tools.r8.proto2.Graph$UsedRoot";
  private static final String USED_VIA_HAZZER =
      "com.android.tools.r8.proto2.Shrinking$UsedViaHazzer";
  private static final String USES_ONLY_REPEATED_FIELDS =
      "com.android.tools.r8.proto2.Shrinking$UsesOnlyRepeatedFields";

  private static List<Path> PROGRAM_FILES =
      ImmutableList.of(PROTO2_EXAMPLES_JAR, PROTO2_PROTO_JAR, PROTOBUF_LITE_JAR);

  private final boolean allowAccessModification;
  private final boolean enableMinification;
  private final TestParameters parameters;

  @Parameterized.Parameters(name = "{2}, allow access modification: {0}, enable minification: {1}")
  public static List<Object[]> data() {
    return buildParameters(
        BooleanUtils.values(),
        BooleanUtils.values(),
        getTestParameters().withDefaultDexRuntime().withAllApiLevels().build());
  }

  public Proto2ShrinkingTest(
      boolean allowAccessModification, boolean enableMinification, TestParameters parameters) {
    this.allowAccessModification = allowAccessModification;
    this.enableMinification = enableMinification;
    this.parameters = parameters;
  }

  @Test
  public void test() throws Exception {
    CodeInspector inputInspector = new CodeInspector(PROGRAM_FILES);
    R8TestRunResult result =
        testForR8(parameters.getBackend())
            .addProgramFiles(PROGRAM_FILES)
            .addKeepMainRule("proto2.TestClass")
            .addKeepRuleFiles(PROTOBUF_LITE_PROGUARD_RULES)
            .addKeepRules(allGeneratedMessageLiteSubtypesAreInstantiatedRule())
            // TODO(b/173340579): This rule should not be needed to allow shrinking of
            //  PartiallyUsed$Enum.
            .addNoHorizontalClassMergingRule(PARTIALLY_USED + "$Enum$1")
            .allowAccessModification(allowAccessModification)
            .allowDiagnosticMessages()
            .allowUnusedDontWarnPatterns()
            .allowUnusedProguardConfigurationRules()
            .enableProguardTestOptions()
            .enableProtoShrinking()
            .minification(enableMinification)
            .setMinApi(parameters.getApiLevel())
            .compile()
            .assertAllInfoMessagesMatch(
                containsString("Proguard configuration rule does not match anything"))
            .apply(this::inspectWarningMessages)
            .inspect(
                outputInspector -> {
                  verifyMapAndRequiredFieldsAreKept(inputInspector, outputInspector);
                  verifyUnusedExtensionsAreRemoved(inputInspector, outputInspector);
                  verifyUnusedFieldsAreRemoved(inputInspector, outputInspector);
                  verifyUnusedHazzerBitFieldsAreRemoved(inputInspector, outputInspector);
                  verifyUnusedTypesAreRemoved(inputInspector, outputInspector);
                })
            .run(parameters.getRuntime(), "proto2.TestClass")
            .assertSuccessWithOutputLines(
                "--- roundtrip ---",
                "true",
                "123",
                "asdf",
                "9223372036854775807",
                "qwerty",
                "--- partiallyUsed_proto2 ---",
                "true",
                "42",
                "--- usedViaHazzer ---",
                "true",
                "--- usedViaOneofCase ---",
                "true",
                "--- usesOnlyRepeatedFields ---",
                "1",
                "--- containsFlaggedOffField ---",
                "0",
                "--- hasFlaggedOffExtension ---",
                "4",
                "--- useOneExtension ---",
                "42",
                "--- keepMapAndRequiredFields ---",
                "true",
                "10",
                "10",
                "10");

    DexItemFactory dexItemFactory = new DexItemFactory();
    ProtoApplicationStats original = new ProtoApplicationStats(dexItemFactory, inputInspector);
    ProtoApplicationStats actual =
        new ProtoApplicationStats(dexItemFactory, result.inspector(), original);

    assertEquals(
        ImmutableSet.of(),
        actual.getGeneratedExtensionRegistryStats().getSpuriouslyRetainedExtensionFields());

    if (ToolHelper.isLocalDevelopment()) {
      System.out.println(actual.getStats());
    }
  }

  private void verifyMapAndRequiredFieldsAreKept(
      CodeInspector inputInspector, CodeInspector outputInspector) {
    // Verify the existence of various fields in the input.
    {
      ClassSubject usedRootClassSubject = inputInspector.clazz(USED_ROOT);
      assertThat(usedRootClassSubject, isPresent());
      assertThat(usedRootClassSubject.uniqueFieldWithName("hasRequiredFieldA_"), isPresent());
      assertThat(usedRootClassSubject.uniqueFieldWithName("hasRequiredFieldB_"), isPresent());
      assertThat(usedRootClassSubject.uniqueFieldWithName("myOneof_"), isPresent());
      assertThat(
          usedRootClassSubject.uniqueFieldWithName("recursiveWithRequiredField_"), isPresent());
      assertThat(usedRootClassSubject.uniqueFieldWithName("isExtendedWithOptional_"), isPresent());
      assertThat(usedRootClassSubject.uniqueFieldWithName("isExtendedWithScalars_"), isPresent());
      assertThat(
          usedRootClassSubject.uniqueFieldWithName("isExtendedWithRequiredField_"), isPresent());
      assertThat(
          usedRootClassSubject.uniqueFieldWithName("isRepeatedlyExtendedWithRequiredField_"),
          isPresent());
      assertThat(usedRootClassSubject.uniqueFieldWithName("hasMapField_"), isPresent());

      ClassSubject hasRequiredFieldClassSubject = inputInspector.clazz(HAS_REQUIRED_FIELD);
      assertThat(hasRequiredFieldClassSubject, isPresent());
      assertThat(hasRequiredFieldClassSubject.uniqueFieldWithName("value_"), isPresent());
    }

    // Verify the existence of various fields in the output.
    {
      ClassSubject usedRootClassSubject = outputInspector.clazz(USED_ROOT);
      assertThat(usedRootClassSubject, isPresent());
      assertThat(usedRootClassSubject.uniqueFieldWithName("hasRequiredFieldA_"), isPresent());
      assertThat(usedRootClassSubject.uniqueFieldWithName("hasRequiredFieldB_"), isPresent());
      assertThat(usedRootClassSubject.uniqueFieldWithName("myOneof_"), isPresent());
      assertThat(
          usedRootClassSubject.uniqueFieldWithName("recursiveWithRequiredField_"), isPresent());
      assertThat(usedRootClassSubject.uniqueFieldWithName("hasMapField_"), isPresent());

      assertThat(
          usedRootClassSubject.uniqueFieldWithName("isExtendedWithRequiredField_"), isPresent());
      assertThat(
          usedRootClassSubject.uniqueFieldWithName("isRepeatedlyExtendedWithRequiredField_"),
          isPresent());

      ClassSubject hasRequiredFieldClassSubject = outputInspector.clazz(HAS_REQUIRED_FIELD);
      assertThat(hasRequiredFieldClassSubject, isPresent());
      assertThat(hasRequiredFieldClassSubject.uniqueFieldWithName("value_"), isPresent());
    }

    // Verify the absence of various fields in the output.
    {
      ClassSubject usedRootClassSubject = outputInspector.clazz(USED_ROOT);
      assertThat(usedRootClassSubject, isPresent());
      assertThat(
          usedRootClassSubject.uniqueFieldWithName("isExtendedWithOptional_"), not(isPresent()));
      assertThat(
          usedRootClassSubject.uniqueFieldWithName("isExtendedWithScalars_"), not(isPresent()));
    }
  }

  private void verifyUnusedExtensionsAreRemoved(
      CodeInspector inputInspector, CodeInspector outputInspector) {
    verifyUnusedExtensionsAreRemoved(
        inputInspector,
        outputInspector,
        "com.google.protobuf.proto2_registryGeneratedExtensionRegistryLite");
  }

  private void verifyUnusedExtensionsAreRemoved(
      CodeInspector inputInspector, CodeInspector outputInspector, String extensionRegistryName) {
    // Verify that the registry was split across multiple methods in the input.
    {
      ClassSubject generatedExtensionRegistryLoader = inputInspector.clazz(extensionRegistryName);
      assertThat(generatedExtensionRegistryLoader, isPresent());
      assertThat(
          generatedExtensionRegistryLoader.uniqueMethodWithName("findLiteExtensionByNumber"),
          isPresent());
      assertThat(
          generatedExtensionRegistryLoader.uniqueMethodWithName("findLiteExtensionByNumber1"),
          isPresent());
      assertThat(
          generatedExtensionRegistryLoader.uniqueMethodWithName("findLiteExtensionByNumber2"),
          isPresent());
    }

    // Verify that the registry methods are still present in the output.
    //
    // We expect findLiteExtensionByNumber2() to be inlined into findLiteExtensionByNumber1(). The
    // method findLiteExtensionByNumber1() has two call sites from findLiteExtensionByNumber(),
    // which prevents it from being single-caller inlined.
    {
      ClassSubject generatedExtensionRegistryLoader = outputInspector.clazz(extensionRegistryName);
      assertThat(generatedExtensionRegistryLoader, isPresent());
      assertThat(
          generatedExtensionRegistryLoader.uniqueMethodWithName("findLiteExtensionByNumber"),
          isPresent());
      assertThat(
          generatedExtensionRegistryLoader.uniqueMethodWithName("findLiteExtensionByNumber1"),
          isPresent());
      assertThat(
          generatedExtensionRegistryLoader.uniqueMethodWithName("findLiteExtensionByNumber2"),
          notIf(isPresent(), enableMinification));
    }

    // Verify that unused extensions have been removed with -allowaccessmodification.
    if (allowAccessModification) {
      List<String> unusedExtensionNames =
          ImmutableList.of(FLAGGED_OFF_EXTENSION, HAS_NO_USED_EXTENSIONS, EXT_B, EXT_C);
      for (String unusedExtensionName : unusedExtensionNames) {
        assertThat(inputInspector.clazz(unusedExtensionName), isPresent());
        assertThat(
            unusedExtensionName, outputInspector.clazz(unusedExtensionName), not(isPresent()));
      }
    }
  }

  private void verifyUnusedFieldsAreRemoved(
      CodeInspector inputInspector, CodeInspector outputInspector) {
    // Verify that various proto fields are present the input.
    {
      ClassSubject cfofClassSubject = inputInspector.clazz(CONTAINS_FLAGGED_OFF_FIELD);
      assertThat(cfofClassSubject, isPresent());
      assertThat(cfofClassSubject.uniqueFieldWithName("conditionallyUsed_"), isPresent());

      ClassSubject puClassSubject = inputInspector.clazz(PARTIALLY_USED);
      assertThat(puClassSubject, isPresent());
      assertEquals(7, puClassSubject.allInstanceFields().size());
      assertThat(puClassSubject.uniqueFieldWithName("bitField0_"), isPresent());
      assertThat(puClassSubject.uniqueFieldWithName("used_"), isPresent());
      assertThat(puClassSubject.uniqueFieldWithName("completelyUnused_"), isPresent());
      assertThat(puClassSubject.uniqueFieldWithName("unusedEnum_"), isPresent());
      assertThat(puClassSubject.uniqueFieldWithName("unusedRepeatedEnum_"), isPresent());
      assertThat(puClassSubject.uniqueFieldWithName("unusedMessage_"), isPresent());
      assertThat(puClassSubject.uniqueFieldWithName("unusedRepeatedMessage_"), isPresent());

      ClassSubject uvhClassSubject = inputInspector.clazz(USED_VIA_HAZZER);
      assertThat(uvhClassSubject, isPresent());
      assertThat(uvhClassSubject.uniqueFieldWithName("used_"), isPresent());
      assertThat(uvhClassSubject.uniqueFieldWithName("unused_"), isPresent());
    }

    // Verify that various proto fields have been removed in the output.
    {
      ClassSubject cfofClassSubject = outputInspector.clazz(CONTAINS_FLAGGED_OFF_FIELD);
      assertThat(cfofClassSubject, isPresent());
      assertThat(cfofClassSubject.uniqueFieldWithName("conditionallyUsed_"), not(isPresent()));

      ClassSubject puClassSubject = outputInspector.clazz(PARTIALLY_USED);
      assertThat(puClassSubject, isPresent());
      assertThat(puClassSubject.uniqueFieldWithName("bitField0_"), isPresent());
      assertThat(puClassSubject.uniqueFieldWithName("used_"), isPresent());
      assertThat(puClassSubject.uniqueFieldWithName("completelyUnused_"), not(isPresent()));
      assertThat(puClassSubject.uniqueFieldWithName("unusedEnum_"), not(isPresent()));
      assertThat(puClassSubject.uniqueFieldWithName("unusedRepeatedEnum_"), not(isPresent()));
      assertThat(puClassSubject.uniqueFieldWithName("unusedMessage_"), not(isPresent()));
      assertThat(puClassSubject.uniqueFieldWithName("unusedRepeatedMessage_"), not(isPresent()));

      ClassSubject uvhClassSubject = outputInspector.clazz(USED_VIA_HAZZER);
      assertThat(uvhClassSubject, isPresent());
      assertThat(uvhClassSubject.uniqueFieldWithName("used_"), isPresent());
      assertThat(uvhClassSubject.uniqueFieldWithName("unused_"), not(isPresent()));
    }
  }

  private void verifyUnusedHazzerBitFieldsAreRemoved(
      CodeInspector inputInspector, CodeInspector outputInspector) {
    // Verify that various proto fields are present the input.
    {
      ClassSubject classSubject = inputInspector.clazz(USES_ONLY_REPEATED_FIELDS);
      assertThat(classSubject, isPresent());
      assertThat(classSubject.uniqueFieldWithName("bitField0_"), isPresent());
      assertThat(classSubject.uniqueFieldWithName("myoneof_"), isPresent());
      assertThat(classSubject.uniqueFieldWithName("myoneofCase_"), isPresent());
    }

    // Verify that various proto fields have been removed in the output.
    {
      ClassSubject classSubject = outputInspector.clazz(USES_ONLY_REPEATED_FIELDS);
      assertThat(classSubject, isPresent());
      assertThat(classSubject.uniqueFieldWithName("bitField0_"), not(isPresent()));
      assertThat(classSubject.uniqueFieldWithName("myoneof_"), not(isPresent()));
      assertThat(classSubject.uniqueFieldWithName("myoneofCase_"), not(isPresent()));
    }
  }

  private void verifyUnusedTypesAreRemoved(
      CodeInspector inputInspector, CodeInspector outputInspector) {
    // Verify that various types are present the input.
    {
      ClassSubject enumClassSubject = inputInspector.clazz(PARTIALLY_USED + "$Enum");
      assertThat(enumClassSubject, isPresent());

      ClassSubject nestedClassSubject = inputInspector.clazz(PARTIALLY_USED + "$Nested");
      assertThat(nestedClassSubject, isPresent());
    }

    // Verify that various types have been removed in the output.
    {
      ClassSubject enumClassSubject = outputInspector.clazz(PARTIALLY_USED + "$Enum");
      assertThat(enumClassSubject, not(isPresent()));

      ClassSubject nestedClassSubject = outputInspector.clazz(PARTIALLY_USED + "$Nested");
      assertThat(nestedClassSubject, not(isPresent()));
    }
  }

  @Test
  public void testNoRewriting() throws Exception {
    testForR8(parameters.getBackend())
        .addProgramFiles(PROGRAM_FILES)
        .addKeepMainRule("proto2.TestClass")
        .addKeepRuleFiles(PROTOBUF_LITE_PROGUARD_RULES)
        // Retain all protos.
        .addKeepRules(keepAllProtosRule())
        // Retain the signature of dynamicMethod() and newMessageInfo().
        .addKeepRules(keepDynamicMethodSignatureRule(), keepNewMessageInfoSignatureRule())
        .allowAccessModification(allowAccessModification)
        .allowDiagnosticMessages()
        .allowUnusedDontWarnPatterns()
        .allowUnusedProguardConfigurationRules()
        .enableProtoShrinking()
        .minification(enableMinification)
        .setMinApi(parameters.getApiLevel())
        .compile()
        .assertAllInfoMessagesMatch(
            containsString("Proguard configuration rule does not match anything"))
        .apply(this::inspectWarningMessages)
        .inspect(
            inspector ->
                assertRewrittenProtoSchemasMatch(new CodeInspector(PROGRAM_FILES), inspector));
  }

  @Test
  public void testTwoExtensionRegistrys() throws Exception {
    CodeInspector inputInspector = new CodeInspector(PROGRAM_FILES);
    testForR8(parameters.getBackend())
        .addProgramFiles(PROGRAM_FILES)
        .addKeepMainRule("proto2.TestClass")
        .addKeepRuleFiles(PROTOBUF_LITE_PROGUARD_RULES)
        .addKeepRules(findLiteExtensionByNumberInDuplicateCalledRule())
        .addKeepRules(allGeneratedMessageLiteSubtypesAreInstantiatedRule())
        // TODO(b/173340579): This rule should not be needed to allow shrinking of
        //  PartiallyUsed$Enum.
        .addNoHorizontalClassMergingRule(PARTIALLY_USED + "$Enum$1")
        .allowAccessModification(allowAccessModification)
        .allowDiagnosticMessages()
        .allowUnusedDontWarnPatterns()
        .allowUnusedProguardConfigurationRules()
        .enableProtoShrinking()
        .minification(enableMinification)
        .setMinApi(parameters.getApiLevel())
        .compile()
        .assertAllInfoMessagesMatch(
            containsString("Proguard configuration rule does not match anything"))
        .apply(this::inspectWarningMessages)
        .inspect(
            outputInspector -> {
              verifyUnusedExtensionsAreRemoved(inputInspector, outputInspector);
              verifyUnusedExtensionsAreRemoved(
                  inputInspector,
                  outputInspector,
                  "com.google.protobuf.proto2_registryGeneratedExtensionRegistryLiteDuplicate");
            });
  }
}
