// Copyright 2018 The Bazel Authors. All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//    http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package com.google.devtools.build.lib.query2.cquery;

import static com.google.common.collect.ImmutableSet.toImmutableSet;
import static com.google.common.truth.Truth.assertThat;
import static com.google.common.truth.extensions.proto.ProtoTruth.assertThat;
import static com.google.devtools.build.lib.packages.Attribute.attr;
import static com.google.devtools.build.lib.packages.BuildType.LABEL_LIST;
import static java.nio.charset.StandardCharsets.UTF_8;

import com.google.common.collect.ImmutableList;
import com.google.common.collect.Iterables;
import com.google.common.eventbus.EventBus;
import com.google.devtools.build.lib.analysis.AnalysisProtosV2;
import com.google.devtools.build.lib.analysis.AnalysisProtosV2.Configuration;
import com.google.devtools.build.lib.analysis.AnalysisProtosV2.Fragment;
import com.google.devtools.build.lib.analysis.AnalysisProtosV2.FragmentOptions;
import com.google.devtools.build.lib.analysis.AnalysisProtosV2.Option;
import com.google.devtools.build.lib.analysis.ConfiguredRuleClassProvider;
import com.google.devtools.build.lib.analysis.config.ExecutionTransitionFactory;
import com.google.devtools.build.lib.analysis.util.MockRule;
import com.google.devtools.build.lib.events.Event;
import com.google.devtools.build.lib.events.NullEventHandler;
import com.google.devtools.build.lib.events.Reporter;
import com.google.devtools.build.lib.packages.LabelPrinter;
import com.google.devtools.build.lib.query2.PostAnalysisQueryEnvironment;
import com.google.devtools.build.lib.query2.common.CqueryNode;
import com.google.devtools.build.lib.query2.cquery.CqueryOptions.Transitions;
import com.google.devtools.build.lib.query2.cquery.ProtoOutputFormatterCallback.OutputType;
import com.google.devtools.build.lib.query2.engine.QueryEnvironment.Setting;
import com.google.devtools.build.lib.query2.engine.QueryExpression;
import com.google.devtools.build.lib.query2.engine.QueryParser;
import com.google.devtools.build.lib.query2.proto.proto2api.Build;
import com.google.devtools.build.lib.query2.proto.proto2api.Build.ConfiguredRuleInput;
import com.google.devtools.build.lib.query2.query.aspectresolvers.AspectResolver.Mode;
import com.google.devtools.build.lib.util.FileTypeSet;
import com.google.protobuf.ExtensionRegistry;
import com.google.protobuf.Message;
import com.google.protobuf.Parser;
import com.google.protobuf.TextFormat;
import com.google.protobuf.util.JsonFormat;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Set;
import org.junit.Before;
import org.junit.Test;

/**
 * Test for cquery's proto output format.
 *
 * <p>TODO(blaze-configurability): refactor all cquery output format tests to consolidate duplicate
 * infrastructure.
 */
public class ProtoOutputFormatterCallbackTest extends ConfiguredTargetQueryTest {

  private CqueryOptions options;
  private Reporter reporter;
  private final List<Event> events = new ArrayList<>();

  @Before
  public final void setUpCqueryOptions() {
    this.options = new CqueryOptions();
    // TODO(bazel-team): reduce the confusion about these two seemingly similar settings.
    // options.aspectDeps impacts how proto and similar output formatters output aspect results.
    // Setting.INCLUDE_ASPECTS impacts whether or not aspect dependencies are included when
    // following target deps. See CommonQueryOptions for further flag details.
    options.aspectDeps = Mode.OFF;
    helper.setQuerySettings(Setting.INCLUDE_ASPECTS);
    options.protoIncludeConfigurations = true;
    options.protoIncludeRuleInputsAndOutputs = true;
    this.reporter = new Reporter(new EventBus(), events::add);
  }

  @Test
  public void testSelectInAttribute() throws Exception {
    MockRule depsRule =
        () ->
            MockRule.define(
                "my_rule",
                (builder, env) ->
                    builder
                        .add(attr("deps", LABEL_LIST).allowedFileTypes(FileTypeSet.ANY_FILE)));
    ConfiguredRuleClassProvider ruleClassProvider = setRuleClassProviders(depsRule).build();
    helper.useRuleClassProvider(ruleClassProvider);

    writeFile(
        "test/BUILD",
        """
        my_rule(
            name = "my_rule",
            deps = select({
                ":garfield": [
                    "lasagna.java",
                    "naps.java",
                ],
                "//conditions:default": ["mondays.java"],
            }),
        )

        config_setting(
            name = "garfield",
            values = {"foo": "cat"},
        )
        """);

    helper.setQuerySettings(Setting.NO_IMPLICIT_DEPS);
    AnalysisProtosV2.ConfiguredTarget myRuleProto =
        Iterables.getOnlyElement(
            getProtoOutput("//test:my_rule", AnalysisProtosV2.CqueryResult.parser())
                .getResultsList());
    List<Build.Attribute> attributes = myRuleProto.getTarget().getRule().getAttributeList();
    for (Build.Attribute attribute : attributes) {
      if (!attribute.getName().equals("deps")) {
        continue;
      }
      assertThat(attribute.getStringListValueCount()).isEqualTo(1);
      assertThat(attribute.getStringListValue(0)).isEqualTo("//test:mondays.java");
      break;
    }

    getHelper().useConfiguration("--foo=cat");
    myRuleProto =
        Iterables.getOnlyElement(
            getProtoOutput("//test:my_rule", AnalysisProtosV2.CqueryResult.parser())
                .getResultsList());
    attributes = myRuleProto.getTarget().getRule().getAttributeList();
    for (Build.Attribute attribute : attributes) {
      if (!attribute.getName().equals("deps")) {
        continue;
      }
      assertThat(attribute.getStringListValueCount()).isEqualTo(2);
      assertThat(attribute.getStringListValue(0)).isEqualTo("//test:lasagna.java");
      assertThat(attribute.getStringListValue(1)).isEqualTo("//test:naps.java");
      break;
    }
  }

  @Test
  @SuppressWarnings("deprecation") // only use for tests
  public void testConfigurations() throws Exception {
    options.transitions = Transitions.LITE;

    MockRule ruleWithPatch =
        () ->
            MockRule.define(
                "my_rule",
                (builder, env) ->
                    builder.add(
                        attr("deps", LABEL_LIST)
                            .allowedFileTypes(FileTypeSet.ANY_FILE)
                            .cfg(ExecutionTransitionFactory.createFactory())));
    MockRule parentRuleClass =
        () ->
            MockRule.define(
                "parent_rule",
                (builder, env) ->
                    builder
                        .add(attr("deps", LABEL_LIST).allowedFileTypes(FileTypeSet.ANY_FILE))
                        .add(attr("srcs", LABEL_LIST).allowedFileTypes(FileTypeSet.ANY_FILE)));

    ConfiguredRuleClassProvider ruleClassProvider =
        setRuleClassProviders(ruleWithPatch, parentRuleClass, getSimpleRule()).build();
    helper.useRuleClassProvider(ruleClassProvider);

    writeFile(
        "test/BUILD",
        """
        parent_rule(
            name = "parent_rule",
            srcs = ["parent.source"],
            deps = [":transition_rule"],
        )

        my_rule(
            name = "transition_rule",
            deps = [
                ":dep",
                ":patched",
            ],
        )

        simple_rule(name = "dep")
        """);

    helper.setQuerySettings(Setting.NO_IMPLICIT_DEPS);
    AnalysisProtosV2.CqueryResult cqueryResult =
        getProtoOutput("deps(//test:parent_rule)", AnalysisProtosV2.CqueryResult.parser());
    List<Configuration> configurations = cqueryResult.getConfigurationsList();
    assertThat(configurations).hasSize(2);

    List<AnalysisProtosV2.ConfiguredTarget> resultsList = cqueryResult.getResultsList();

    AnalysisProtosV2.ConfiguredTarget parentRuleProto =
        getRuleProtoByName(resultsList, "//test:parent_rule");
    Set<CqueryNode> keyedTargets = eval("deps(//test:parent_rule)");

    CqueryNode parentRule = getKeyedTargetByLabel(keyedTargets, "//test:parent_rule");
    assertThat(parentRuleProto.getConfiguration().getChecksum())
        .isEqualTo(parentRule.getConfigurationChecksum());

    Configuration parentConfiguration =
        getConfigurationForId(configurations, parentRuleProto.getConfigurationId());
    assertThat(parentConfiguration.getChecksum()).isEqualTo(parentRule.getConfigurationChecksum());
    assertThat(parentConfiguration)
        .ignoringFieldDescriptors(
            Configuration.getDescriptor().findFieldByName("checksum"),
            Configuration.getDescriptor().findFieldByName("id"),
            Configuration.getDescriptor().findFieldByName("fragments"),
            Configuration.getDescriptor().findFieldByName("id"),
            Configuration.getDescriptor().findFieldByName("fragment_options"))
        .isEqualTo(
            Configuration.newBuilder()
                .setMnemonic("k8-fastbuild")
                .setPlatformName("k8")
                .setIsTool(false)
                .build());

    List<Fragment> fragmentsList = parentConfiguration.getFragmentsList();

    assertThat(fragmentsList.stream().map(Fragment::getName)).isInOrder();
    assertThat(fragmentsList)
        .contains(
            Fragment.newBuilder()
                .setName("com.google.devtools.build.lib.rules.cpp.CppConfiguration")
                .addFragmentOptionNames(
                    "com.google.devtools.build.lib.rules.apple.AppleCommandLineOptions")
                .addFragmentOptionNames("com.google.devtools.build.lib.rules.cpp.CppOptions")
                .build());

    List<FragmentOptions> fragmentOptionsList = parentConfiguration.getFragmentOptionsList();
    assertThat(fragmentOptionsList.stream().map(FragmentOptions::getName)).isInOrder();

    FragmentOptions appleFragmentOptions =
        fragmentOptionsList.stream()
            .filter(
                fo ->
                    fo.getName()
                        .equals(
                            "com.google.devtools.build.lib.rules.apple.AppleCommandLineOptions"))
            .findFirst()
            .get();
    assertThat(appleFragmentOptions.getName())
        .isEqualTo("com.google.devtools.build.lib.rules.apple.AppleCommandLineOptions");
    assertThat(appleFragmentOptions.getOptionsList())
        .contains(Option.newBuilder().setName("apple_platform_type").setValue("macos").build());

    assertThat(appleFragmentOptions.getOptionsList().stream().map(Option::getName)).isInOrder();

    FragmentOptions cppFragmentOptions =
        fragmentOptionsList.stream()
            .filter(fo -> fo.getName().equals("com.google.devtools.build.lib.rules.cpp.CppOptions"))
            .findFirst()
            .get();
    assertThat(cppFragmentOptions.getName())
        .isEqualTo("com.google.devtools.build.lib.rules.cpp.CppOptions");
    assertThat(cppFragmentOptions.getOptionsList())
        .contains(Option.newBuilder().setName("dynamic_mode").setValue("DEFAULT").build());

    assertThat(cppFragmentOptions.getOptionsList().stream().map(Option::getName)).isInOrder();

    AnalysisProtosV2.ConfiguredTarget transitionRuleProto =
        getRuleProtoByName(resultsList, "//test:transition_rule");
    CqueryNode transitionRule = getKeyedTargetByLabel(keyedTargets, "//test:transition_rule");
    assertThat(transitionRuleProto.getConfiguration().getChecksum())
        .isEqualTo(transitionRule.getConfigurationChecksum());

    Configuration transitionConfiguration =
        getConfigurationForId(configurations, transitionRuleProto.getConfigurationId());
    assertThat(transitionConfiguration.getChecksum())
        .isEqualTo(transitionRule.getConfigurationChecksum());

    AnalysisProtosV2.ConfiguredTarget depRuleProto = getRuleProtoByName(resultsList, "//test:dep");
    Configuration depRuleConfiguration =
        getConfigurationForId(configurations, depRuleProto.getConfigurationId());
    assertThat(depRuleConfiguration.getPlatformName()).isEqualTo("k8");
    assertThat(depRuleConfiguration.getMnemonic()).matches("k8-opt-exec-.*");
    assertThat(depRuleConfiguration.getIsTool()).isTrue();

    CqueryNode depRule = getKeyedTargetByLabel(keyedTargets, "//test:dep");

    assertThat(depRuleProto.getConfiguration().getChecksum())
        .isEqualTo(depRule.getConfigurationChecksum());

    // Assert the proto checksums for targets in different configurations are not the same.
    assertThat(depRuleConfiguration.getChecksum())
        .isNotEqualTo(transitionConfiguration.getChecksum());
    // Targets without a configuration have a configuration_id of 0.
    AnalysisProtosV2.ConfiguredTarget fileTargetProto =
        resultsList.stream()
            .filter(result -> result.getTarget().getSourceFile().getName().equals("//test:patched"))
            .findAny()
            .orElseThrow();
    assertThat(fileTargetProto.getConfigurationId()).isEqualTo(0);

    assertThat(parentRuleProto.getTarget().getRule().getConfiguredRuleInputList())
        .containsExactly(
            // Targets whose deps have no transitions should appear with identifical configuration
            // information to their parent:
            ConfiguredRuleInput.newBuilder()
                .setLabel("//test:transition_rule")
                .setConfigurationChecksum(parentRuleProto.getConfiguration().getChecksum())
                .setConfigurationId(parentRuleProto.getConfigurationId())
                .build(),
            // Source file deps have no configurations:
            ConfiguredRuleInput.newBuilder().setLabel("//test:parent.source").build());

    // Targets with deps with transitions should show distinct configurations.
    ConfiguredRuleInput patchedConfiguredRuleInput =
        ConfiguredRuleInput.newBuilder().setLabel("//test:patched").build();
    ConfiguredRuleInput depConfiguredRuleInput =
        ConfiguredRuleInput.newBuilder()
            .setLabel("//test:dep")
            .setConfigurationChecksum(depRuleProto.getConfiguration().getChecksum())
            .setConfigurationId(depRuleProto.getConfigurationId())
            .build();
    List<ConfiguredRuleInput> configuredRuleInputs =
        transitionRuleProto.getTarget().getRule().getConfiguredRuleInputList();
    assertThat(configuredRuleInputs)
        .containsExactly(patchedConfiguredRuleInput, depConfiguredRuleInput);
  }

  @Test
  public void configuredRuleInputsFromAspects() throws Exception {
    options.transitions = Transitions.LITE;
    writeFile(
        "test/BUILD",
        """
        load(":defs.bzl", "my_rule")
        my_rule(
            name = "parent",
            deps = [":child"],
        )
        my_rule(name = "child")
        my_rule(name = "aspect_exec_config_dep")
        my_rule(name = "aspect_same_config_dep")
        """);
    writeFile(
        "test/defs.bzl",
        """
        my_aspect = aspect(
            implementation = lambda target, ctx: [],
            attr_aspects = ["deps"],
            attrs = {
                "_aspect_exec_deps": attr.label_list(
                    cfg = "exec",
                    default = [":aspect_exec_config_dep"]
                ),
                "_aspect_deps": attr.label_list(default = [":aspect_same_config_dep"]),
            }
        )
        my_rule = rule(
            implementation = lambda ctx: [],
            attrs = { "deps": attr.label_list(aspects = [my_aspect]) }
        )
        """);

    helper.setQuerySettings(Setting.INCLUDE_ASPECTS);
    AnalysisProtosV2.CqueryResult cqueryResult =
        getProtoOutput("deps(//test:parent)", AnalysisProtosV2.CqueryResult.parser());
    List<Configuration> configurations = cqueryResult.getConfigurationsList();
    assertThat(configurations).hasSize(3); // Target config, exec config, host platform config.

    List<AnalysisProtosV2.ConfiguredTarget> resultsList = cqueryResult.getResultsList();
    AnalysisProtosV2.ConfiguredTarget parentRuleProto =
        getRuleProtoByName(resultsList, "//test:parent");
    AnalysisProtosV2.ConfiguredTarget directDepProto =
        getRuleProtoByName(resultsList, "//test:child");
    AnalysisProtosV2.ConfiguredTarget aspectDepSameConfigProto =
        getRuleProtoByName(resultsList, "//test:aspect_same_config_dep");
    AnalysisProtosV2.ConfiguredTarget aspectDepExecConfigProto =
        getRuleProtoByName(resultsList, "//test:aspect_exec_config_dep");

    assertThat(parentRuleProto.getTarget().getRule().getConfiguredRuleInputList())
        .containsAtLeast(
            ConfiguredRuleInput.newBuilder()
                .setLabel("//test:child")
                .setConfigurationChecksum(
                    getConfigurationForId(
                            cqueryResult.getConfigurationsList(),
                            directDepProto.getConfigurationId())
                        .getChecksum())
                .setConfigurationId(directDepProto.getConfigurationId())
                .build(),
            ConfiguredRuleInput.newBuilder()
                .setLabel("//test:aspect_same_config_dep")
                .setConfigurationChecksum(
                    getConfigurationForId(
                            cqueryResult.getConfigurationsList(),
                            aspectDepSameConfigProto.getConfigurationId())
                        .getChecksum())
                .setConfigurationId(aspectDepSameConfigProto.getConfigurationId())
                .build(),
            ConfiguredRuleInput.newBuilder()
                .setLabel("//test:aspect_exec_config_dep")
                .setConfigurationChecksum(
                    getConfigurationForId(
                            cqueryResult.getConfigurationsList(),
                            aspectDepExecConfigProto.getConfigurationId())
                        .getChecksum())
                .setConfigurationId(aspectDepExecConfigProto.getConfigurationId())
                .build());

    assertThat(parentRuleProto.getConfigurationId()).isEqualTo(directDepProto.getConfigurationId());
    assertThat(parentRuleProto.getConfigurationId())
        .isEqualTo(aspectDepSameConfigProto.getConfigurationId());
    assertThat(parentRuleProto.getConfigurationId())
        .isNotEqualTo(aspectDepExecConfigProto.getConfigurationId());
  }

  /** Tests an alias's output. */
  @Test
  public void aliasOutput() throws Exception {
    writeFile(
        "fake_licenses/BUILD",
        """
        load("//test:defs.bzl", "my_rule")
        my_rule(name = "license")
        """);
    writeFile(
        "test/BUILD",
        """
        load(":defs.bzl", "my_rule")
        package(
            default_applicable_licenses = ["//fake_licenses:license"],
        )
        alias(
            name = "my_alias",
            actual = ":my_target",
        )
        my_rule(name = "my_target")
        """);
    writeFile(
        "test/defs.bzl",
        """
        my_rule = rule(
            implementation = lambda ctx: [],
            attrs = {},
        )
        """);

    options.transitions = Transitions.LITE;
    AnalysisProtosV2.CqueryResult cqueryResult =
        getProtoOutput("deps(//test:my_alias)", AnalysisProtosV2.CqueryResult.parser());

    AnalysisProtosV2.ConfiguredTarget aliasProto =
        getRuleProtoByName(cqueryResult.getResultsList(), "//test:my_alias");
    AnalysisProtosV2.ConfiguredTarget actualProto =
        getRuleProtoByName(cqueryResult.getResultsList(), "//test:my_target");

    // Expect the alias's "name" field references the alias's label, not its actual.
    assertThat(aliasProto.getTarget().getRule().getName()).isEqualTo("//test:my_alias");
    assertThat(aliasProto.getTarget().getRule().getRuleInputList())
        .containsExactly("//test:my_target");
    assertThat(aliasProto.getTarget().getRule().getConfiguredRuleInputList())
        .containsAtLeast(
            ConfiguredRuleInput.newBuilder()
                .setLabel("//test:my_target")
                .setConfigurationChecksum(
                    getConfigurationForId(
                            cqueryResult.getConfigurationsList(), actualProto.getConfigurationId())
                        .getChecksum())
                .setConfigurationId(actualProto.getConfigurationId())
                .build(),
            ConfiguredRuleInput.newBuilder()
                .setLabel("//fake_licenses:license")
                // Don't use the aliases' configuration because top-level aliases include test
                // configuration, which all non-test deps trim out.
                .setConfigurationChecksum(
                    getConfigurationForId(
                            cqueryResult.getConfigurationsList(), actualProto.getConfigurationId())
                        .getChecksum())
                .setConfigurationId(actualProto.getConfigurationId())
                .build());
  }

  /** Tests output where one of the deps is an alias. */
  @Test
  public void outputOnAliasDep() throws Exception {
    writeFile(
        "test/BUILD",
        """
        load(":defs.bzl", "my_rule")
        my_rule(
            name = "my_target",
            deps = [":my_alias"],
        )
        alias(
            name = "my_alias",
            actual = ":my_child",
        )
        my_rule(name = "my_child")
        """);
    writeFile(
        "test/defs.bzl",
        """
        my_rule = rule(
            implementation = lambda ctx: [],
            attrs = { "deps": attr.label_list() },
        )
        """);

    options.transitions = Transitions.LITE;
    AnalysisProtosV2.CqueryResult cqueryResult =
        getProtoOutput("deps(//test:my_target)", AnalysisProtosV2.CqueryResult.parser());
    Build.Rule targetRule =
        getRuleProtoByName(cqueryResult.getResultsList(), "//test:my_target").getTarget().getRule();

    assertThat(targetRule.getRuleInputList()).contains("//test:my_alias");
    assertThat(targetRule.getRuleInputList()).doesNotContain("//test:my_child");
    assertThat(targetRule.getConfiguredRuleInputList().stream().map(s -> s.getLabel()))
        .contains("//test:my_alias");
    assertThat(targetRule.getConfiguredRuleInputList().stream().map(s -> s.getLabel()))
        .doesNotContain("//test:my_child");
  }

  private CqueryNode getKeyedTargetByLabel(Set<CqueryNode> keyedTargets, String label) {
    return Iterables.getOnlyElement(
        keyedTargets.stream()
            .filter(t -> label.equals(t.getLabel().getCanonicalForm()))
            .collect(toImmutableSet()));
  }

  private Configuration getConfigurationForId(List<Configuration> configurations, int id) {
    return configurations.stream().filter(c -> c.getId() == id).findAny().orElseThrow();
  }

  private AnalysisProtosV2.ConfiguredTarget getRuleProtoByName(
      List<AnalysisProtosV2.ConfiguredTarget> resultsList, String s) {
    return resultsList.stream()
        .filter(result -> s.equals(result.getTarget().getRule().getName()))
        .findAny()
        .orElseThrow();
  }

  @Test
  public void testAlias() throws Exception {
    ConfiguredRuleClassProvider ruleClassProvider = setRuleClassProviders(getSimpleRule()).build();
    helper.useRuleClassProvider(ruleClassProvider);

    writeFile(
        "test/BUILD",
        """
        simple_rule(name = "my_rule")

        alias(
            name = "my_alias",
            actual = ":my_rule",
        )
        """);

    helper.setQuerySettings(Setting.NO_IMPLICIT_DEPS);
    AnalysisProtosV2.ConfiguredTarget alias =
        Iterables.getOnlyElement(
            getProtoOutput("//test:my_alias", AnalysisProtosV2.CqueryResult.parser())
                .getResultsList());

    assertThat(alias.getTarget().getRule().getName()).isEqualTo("//test:my_alias");
    assertThat(alias.getTarget().getRule().getRuleInputCount()).isEqualTo(1);
    assertThat(alias.getTarget().getRule().getRuleInput(0)).isEqualTo("//test:my_rule");
  }

  /* See b/209787345 for context. */
  @Test
  public void testAlias_withSelect() throws Exception {
    ConfiguredRuleClassProvider ruleClassProvider = setRuleClassProviders(getSimpleRule()).build();
    helper.useRuleClassProvider(ruleClassProvider);

    writeFile(
        "test/BUILD",
        """
        alias(
            name = "my_alias_rule",
            actual = select({
                ":config1": ":target1",
                "//conditions:default": ":target2",
            }),
        )

        config_setting(
            name = "config1",
            values = {"foo": "woof"},
        )

        simple_rule(name = "target1")

        simple_rule(name = "target2")
        """);
    getHelper().useConfiguration("--foo=woof");
    helper.setQuerySettings(Setting.NO_IMPLICIT_DEPS);

    helper.setQuerySettings(Setting.NO_IMPLICIT_DEPS);
    List<AnalysisProtosV2.ConfiguredTarget> myAliasRuleProto =
        getProtoOutput(
                "deps(//test:my_alias_rule)",
                AnalysisProtosV2.CqueryResult.parser())
            .getResultsList();

    List<String> depNames = new ArrayList<>(myAliasRuleProto.size());
    myAliasRuleProto.forEach(
        configuredTarget -> depNames.add(configuredTarget.getTarget().getRule().getName()));
    assertThat(depNames)
        // The alias also includes platform info since aliases with select() trigger toolchain
        // resolution. We're not interested in those here.
        .containsAtLeast("//test:my_alias_rule", "//test:config1", "//test:target1");
  }

  @Test
  public void testAllOutputFormatsEquivalentToProtoOutput() throws Exception {
    MockRule depsRule =
        () ->
            MockRule.define(
                "my_rule",
                (builder, env) ->
                    builder.add(attr("deps", LABEL_LIST).allowedFileTypes(FileTypeSet.ANY_FILE)));
    ConfiguredRuleClassProvider ruleClassProvider = setRuleClassProviders(depsRule).build();
    helper.useRuleClassProvider(ruleClassProvider);

    writeFile(
        "test/BUILD",
        """
        my_rule(
            name = "my_rule",
            deps = [
                "lasagna.java",
                "naps.java",
            ],
        )
        """);
    AnalysisProtosV2.CqueryResult prototype = AnalysisProtosV2.CqueryResult.getDefaultInstance();
    helper.setQuerySettings(Setting.NO_IMPLICIT_DEPS);
    AnalysisProtosV2.CqueryResult protoOutput =
        getProtoOutput("//test:*", prototype.getParserForType());

    AnalysisProtosV2.CqueryResult textprotoOutput =
        getProtoFromTextprotoOutput("//test:*", prototype);

    AnalysisProtosV2.CqueryResult jsonprotoOutput =
        getProtoFromJsonprotoOutput("//test:*", prototype);

    ImmutableList<AnalysisProtosV2.CqueryResult> streamedProtoOutput =
        getStreamedProtoOutput("//test:*", prototype.getParserForType());
    AnalysisProtosV2.CqueryResult.Builder combinedStreamedProtoBuilder =
        AnalysisProtosV2.CqueryResult.newBuilder();
    for (AnalysisProtosV2.CqueryResult result : streamedProtoOutput) {
      if (!result.getResultsList().isEmpty()) {
        combinedStreamedProtoBuilder.addAllResults(result.getResultsList());
      }
      if (!result.getConfigurationsList().isEmpty()) {
        combinedStreamedProtoBuilder.addAllConfigurations(result.getConfigurationsList());
      }
    }

    assertThat(textprotoOutput).ignoringRepeatedFieldOrder().isEqualTo(protoOutput);
    assertThat(jsonprotoOutput).ignoringRepeatedFieldOrder().isEqualTo(protoOutput);
    assertThat(combinedStreamedProtoBuilder.build())
        .ignoringRepeatedFieldOrder()
        .isEqualTo(protoOutput);
  }

  @Test
  public void testAllOutputFormatsEquivalentToProtoOutput_noIncludeConfigurations()
      throws Exception {
    options.protoIncludeConfigurations = false;
    MockRule depsRule =
        () ->
            MockRule.define(
                "my_rule",
                (builder, env) ->
                    builder.add(attr("deps", LABEL_LIST).allowedFileTypes(FileTypeSet.ANY_FILE)));
    ConfiguredRuleClassProvider ruleClassProvider = setRuleClassProviders(depsRule).build();
    helper.useRuleClassProvider(ruleClassProvider);

    writeFile(
        "test/BUILD",
        """
        my_rule(
            name = "my_rule",
            deps = [
                "lasagna.java",
                "naps.java",
            ],
        )
        """);
    Build.QueryResult prototype = Build.QueryResult.getDefaultInstance();
    helper.setQuerySettings(Setting.NO_IMPLICIT_DEPS);
    Build.QueryResult protoOutput = getProtoOutput("//test:*", prototype.getParserForType());

    Build.QueryResult textprotoOutput = getProtoFromTextprotoOutput("//test:*", prototype);

    Build.QueryResult jsonprotoOutput = getProtoFromJsonprotoOutput("//test:*", prototype);

    ImmutableList<Build.QueryResult> streamedProtoOutput =
        getStreamedProtoOutput("//test:*", prototype.getParserForType());
    Build.QueryResult.Builder combinedStreamedProtoBuilder = Build.QueryResult.newBuilder();
    for (Build.QueryResult result : streamedProtoOutput) {
      if (!result.getTargetList().isEmpty()) {
        combinedStreamedProtoBuilder.addAllTarget(result.getTargetList());
      }
    }

    assertThat(textprotoOutput).ignoringRepeatedFieldOrder().isEqualTo(protoOutput);
    assertThat(jsonprotoOutput).ignoringRepeatedFieldOrder().isEqualTo(protoOutput);
    assertThat(combinedStreamedProtoBuilder.build())
        .ignoringRepeatedFieldOrder()
        .isEqualTo(protoOutput);
  }

  private MockRule getSimpleRule() {
    return () -> MockRule.define("simple_rule");
  }

  private <T extends Message> T getProtoOutput(String queryExpression, Parser<T> parser)
      throws Exception {
    InputStream in = queryAndGetInputStream(queryExpression, OutputType.BINARY);
    return parser.parseFrom(in, ExtensionRegistry.getEmptyRegistry());
  }

  private <T extends Message> ImmutableList<T> getStreamedProtoOutput(
      String queryExpression, Parser<T> parser) throws Exception {
    InputStream in = queryAndGetInputStream(queryExpression, OutputType.DELIMITED_BINARY);
    ImmutableList.Builder<T> builder = new ImmutableList.Builder<>();
    T result;
    while ((result = parser.parseDelimitedFrom(in, ExtensionRegistry.getEmptyRegistry())) != null) {
      builder.add(result);
    }
    return builder.build();
  }

  private <T extends Message> T getProtoFromTextprotoOutput(String queryExpression, T prototype)
      throws Exception {
    InputStream in = queryAndGetInputStream(queryExpression, OutputType.TEXT);
    Message.Builder builder = prototype.newBuilderForType();
    TextFormat.getParser().merge(new InputStreamReader(in, UTF_8), builder);
    @SuppressWarnings("unchecked")
    T message = (T) builder.build();
    return message;
  }

  private <T extends Message> T getProtoFromJsonprotoOutput(String queryExpression, T prototype)
      throws Exception {
    InputStream in = queryAndGetInputStream(queryExpression, OutputType.JSON);
    Message.Builder builder = prototype.newBuilderForType();
    JsonFormat.parser().merge(new InputStreamReader(in, UTF_8), builder);
    @SuppressWarnings("unchecked")
    T message = (T) builder.build();
    return message;
  }

  private InputStream queryAndGetInputStream(String queryExpression, OutputType outputType)
      throws Exception {
    QueryExpression expression = QueryParser.parse(queryExpression, getDefaultFunctions());
    Set<String> targetPatternSet = new LinkedHashSet<>();
    expression.collectTargetPatterns(targetPatternSet);
    PostAnalysisQueryEnvironment<CqueryNode> env =
        ((ConfiguredTargetQueryHelper) helper).getPostAnalysisQueryEnvironment(targetPatternSet);
    ByteArrayOutputStream out = new ByteArrayOutputStream();
    ProtoOutputFormatterCallback callback =
        new ProtoOutputFormatterCallback(
            reporter,
            options,
            out,
            getHelper().getSkyframeExecutor(),
            env.getAccessor(),
            options.aspectDeps.createResolver(
                getHelper().getPackageManager(), NullEventHandler.INSTANCE),
            outputType,
            LabelPrinter.legacy());
    env.evaluateQuery(expression, callback);
    return new ByteArrayInputStream(out.toByteArray());
  }
}
