// 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.aquery;

import static com.google.common.truth.Truth.assertThat;
import static org.junit.Assert.fail;

import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.Iterables;
import com.google.common.eventbus.EventBus;
import com.google.devtools.build.lib.analysis.AnalysisProtos;
import com.google.devtools.build.lib.analysis.AnalysisProtos.Action;
import com.google.devtools.build.lib.analysis.AnalysisProtos.ActionGraphContainer;
import com.google.devtools.build.lib.analysis.AnalysisProtos.Artifact;
import com.google.devtools.build.lib.analysis.AnalysisProtos.AspectDescriptor;
import com.google.devtools.build.lib.analysis.AnalysisProtos.DepSetOfFiles;
import com.google.devtools.build.lib.analysis.AnalysisProtos.KeyValuePair;
import com.google.devtools.build.lib.analysis.AnalysisProtos.ParamFile;
import com.google.devtools.build.lib.analysis.AnalysisProtos.Target;
import com.google.devtools.build.lib.events.Event;
import com.google.devtools.build.lib.events.Reporter;
import com.google.devtools.build.lib.query2.PostAnalysisQueryEnvironment;
import com.google.devtools.build.lib.query2.aquery.ActionGraphProtoOutputFormatterCallback.OutputType;
import com.google.devtools.build.lib.query2.engine.ActionGraphQueryHelper;
import com.google.devtools.build.lib.query2.engine.ActionGraphQueryTest;
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.query.aspectresolvers.AspectResolver.Mode;
import com.google.devtools.build.lib.skyframe.ConfiguredTargetValue;
import com.google.devtools.build.lib.util.OS;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Map.Entry;
import java.util.Set;
import java.util.regex.Pattern;
import java.util.stream.Collectors;
import org.junit.Before;
import org.junit.Test;

/** Tests for aquery's proto output format */
public class ActionGraphProtoOutputFormatterCallbackTest extends ActionGraphQueryTest {
  private AqueryOptions options;
  private Reporter reporter;
  private final List<Event> events = new ArrayList<>();

  @Before
  public final void setUpAqueryOptions() {
    this.options = new AqueryOptions();
    options.aspectDeps = Mode.OFF;
    options.includeArtifacts = true;
    this.reporter = new Reporter(new EventBus(), events::add);
  }

  @Test
  public void testBasicFunctionality() throws Exception {
    writeFile(
        "test/BUILD",
        "genrule(name='foo', srcs=['in'], outs=['out'], tags=['requires-x'],",
        "        cmd='cat $(SRCS) > $(OUTS)')");
    ActionGraphContainer actionGraphContainer = getOutput("//test:foo");
    Action action = Iterables.getOnlyElement(actionGraphContainer.getActionsList());
    assertThat(action.getMnemonic()).isEqualTo("Genrule");
    String inputId = null;
    for (Artifact artifact : actionGraphContainer.getArtifactsList()) {
      if (artifact.getExecPath().equals("test/in")) {
        inputId = artifact.getId();
        break;
      }
    }
    assertThat(inputId).isNotNull();
    String inputDepSetId = Iterables.getOnlyElement(action.getInputDepSetIdsList());
    DepSetOfFiles depSetOfFiles =
        Iterables.getOnlyElement(actionGraphContainer.getDepSetOfFilesList());
    assertThat(depSetOfFiles.getId()).isEqualTo(inputDepSetId);
    assertThat(depSetOfFiles.getDirectArtifactIdsList()).contains(inputId);
    KeyValuePair infoItem = Iterables.getOnlyElement(action.getExecutionInfoList());
    assertThat(infoItem).isEqualTo(KeyValuePair.newBuilder().setKey("requires-x").build());
  }

  @Test
  public void testAqueryFilters_allFunctions_matchingOnlyFooAction() throws Exception {
    writeFile(
        "test/BUILD",
        "genrule(name='foo', srcs=['foo_matching_in.java'], outs=['foo_matching_out'],",
        "        cmd='cat $(SRCS) > $(OUTS)')",
        "genrule(name='wrong_inputs', srcs=['wrong_in'], outs=['matching_out'],",
        "        cmd='cat $(SRCS) > $(OUTS)')",
        "genrule(name='wrong_outputs', srcs=['matching_in.java'], outs=['wrong_out'],",
        "        cmd='cat $(SRCS) > $(OUTS)')",
        "java_library(name='wrong_mnemonic', srcs=['in_bar.java'])");

    String inputs = ".*\\.java";
    String outputs = ".*matching_out";
    String mnemonic = "Genrule";
    AqueryActionFilter actionFilters =
        constructActionFilter(
            ImmutableMap.of("inputs", inputs, "outputs", outputs, "mnemonic", mnemonic));

    ActionGraphContainer actionGraphContainer =
        getOutput(
            String.format(
                "inputs('%s', outputs('%s', mnemonic('%s', deps(//test:all))))",
                inputs, outputs, mnemonic),
            actionFilters);

    assertMatchingOnlyActionFromFoo(actionGraphContainer);
  }

  @Test
  public void testInputsFilter_regex_matchingOnlyFooAction() throws Exception {
    writeFile(
        "test/BUILD",
        "genrule(name='foo', srcs=['foo_matching_in.java'], outs=['foo_matching_out'],",
        "        cmd='cat $(SRCS) > $(OUTS)')",
        "java_library(name='bar', srcs=['in_bar.java'])");

    String inputs = ".*matching_in.java";
    AqueryActionFilter actionFilters = constructActionFilter(ImmutableMap.of("inputs", inputs));

    ActionGraphContainer actionGraphContainer =
        getOutput(String.format("inputs('%s', deps(//test:all))", inputs), actionFilters);

    assertMatchingOnlyActionFromFoo(actionGraphContainer);
  }

  @Test
  public void testOutputsFilter_regex_matchingOnlyFooAction() throws Exception {
    writeFile(
        "test/BUILD",
        "genrule(name='foo', srcs=['foo_matching_in.java'], outs=['foo_matching_out'],",
        "        cmd='cat $(SRCS) > $(OUTS)')",
        "genrule(name='wrong_outputs', srcs=['matching_in'], outs=['wrong_out'],",
        "        cmd='cat $(SRCS) > $(OUTS)')");

    String outputs = ".*matching_out";
    AqueryActionFilter actionFilters = constructActionFilter(ImmutableMap.of("outputs", outputs));

    ActionGraphContainer actionGraphContainer =
        getOutput(String.format("outputs('%s', deps(//test:all))", outputs), actionFilters);

    assertMatchingOnlyActionFromFoo(actionGraphContainer);
  }

  @Test
  public void testMnemonicFilter_regex_matchingOnlyFooAction() throws Exception {
    writeFile(
        "test/BUILD",
        "genrule(name='foo', srcs=['foo_matching_in.java'], outs=['foo_matching_out'],",
        "        cmd='cat $(SRCS) > $(OUTS)')",
        "java_library(name='bar', srcs=['in_bar.java'])");

    String mnemonic = ".*rule";
    AqueryActionFilter actionFilters = constructActionFilter(ImmutableMap.of("mnemonic", mnemonic));

    ActionGraphContainer actionGraphContainer =
        getOutput(String.format("mnemonic('%s', deps(//test:all))", mnemonic), actionFilters);

    assertMatchingOnlyActionFromFoo(actionGraphContainer);
  }

  @Test
  public void testInputsFilter_exactFileName_matchingOnlyFooAction() throws Exception {
    writeFile(
        "test/BUILD",
        "genrule(name='foo', srcs=['foo_matching_in.java'], outs=['foo_matching_out'],",
        "        cmd='cat $(SRCS) > $(OUTS)')",
        "java_library(name='bar', srcs=['in_bar.java'])");

    String inputs = "test/foo_matching_in.java";
    AqueryActionFilter actionFilters = constructActionFilter(ImmutableMap.of("inputs", inputs));

    ActionGraphContainer actionGraphContainer =
        getOutput(String.format("inputs('%s', deps(//test:all))", inputs), actionFilters);

    assertMatchingOnlyActionFromFoo(actionGraphContainer);
  }

  @Test
  public void testOutputsFilter_exactFileName_matchingOnlyFooAction() throws Exception {
    writeFile(
        "test/BUILD",
        "genrule(name='foo', srcs=['foo_matching_in.java'], outs=['foo_matching_out'],",
        "        cmd='cat $(SRCS) > $(OUTS)')",
        "genrule(name='wrong_outputs', srcs=['matching_in'], outs=['wrong_out'],",
        "        cmd='cat $(SRCS) > $(OUTS)')");

    String outputs = ".*/bin/test/foo_matching_out";
    AqueryActionFilter actionFilters = constructActionFilter(ImmutableMap.of("outputs", outputs));

    ActionGraphContainer actionGraphContainer =
        getOutput(String.format("outputs('%s', deps(//test:all))", outputs), actionFilters);

    assertMatchingOnlyActionFromFoo(actionGraphContainer);
  }

  @Test
  public void testMnemonicFilter_exactMnemonicValue_matchingOnlyFooAction() throws Exception {
    writeFile(
        "test/BUILD",
        "genrule(name='foo', srcs=['foo_matching_in.java'], outs=['foo_matching_out'],",
        "        cmd='cat $(SRCS) > $(OUTS)')",
        "java_library(name='bar', srcs=['in_bar.java'])");

    String mnemonic = "Genrule";
    AqueryActionFilter actionFilters = constructActionFilter(ImmutableMap.of("mnemonic", mnemonic));

    ActionGraphContainer actionGraphContainer =
        getOutput(String.format("mnemonic('%s', deps(//test:all))", mnemonic), actionFilters);

    assertMatchingOnlyActionFromFoo(actionGraphContainer);
  }

  @Test
  public void testInputsFilter_chainInputs_noMatchingAction() throws Exception {
    writeFile(
        "test/BUILD",
        "genrule(name='foo', srcs=['in'], outs=['out'], tags=['requires-x'], ",
        "        cmd='cat $(SRCS) > $(OUTS)')");
    AqueryActionFilter actionFilters =
        constructActionFilterChainSameFunction("inputs", ImmutableList.of("in", "something"));
    ActionGraphContainer actionGraphContainer =
        getOutput("inputs('in', inputs('something', //test:foo))", actionFilters);
    assertThat(actionGraphContainer.getActionsCount()).isEqualTo(0);
  }

  @Test
  public void testOutputsFilter_chainOutputs_noMatchingAction() throws Exception {
    writeFile(
        "test/BUILD",
        "genrule(name='foo', srcs=['in'], outs=['out'], tags=['requires-x'], ",
        "        cmd='cat $(SRCS) > $(OUTS)')");
    AqueryActionFilter actionFilters =
        constructActionFilterChainSameFunction("outputs", ImmutableList.of("out", "something"));
    ActionGraphContainer actionGraphContainer =
        getOutput("outputs('out', outputs('something', //test:foo))", actionFilters);
    assertThat(actionGraphContainer.getActionsCount()).isEqualTo(0);
  }

  @Test
  public void testMnemonicFilter_chainMnemonics_noMatchingAction() throws Exception {
    writeFile(
        "test/BUILD",
        "genrule(name='foo', srcs=['in'], outs=['out'], tags=['requires-x'], ",
        "        cmd='cat $(SRCS) > $(OUTS)')");
    AqueryActionFilter actionFilters =
        constructActionFilterChainSameFunction("mnemonic", ImmutableList.of(".*rule", "something"));
    ActionGraphContainer actionGraphContainer =
        getOutput("mnemonic('.*rule', mnemonic('something', //test:foo))", actionFilters);
    assertThat(actionGraphContainer.getActionsCount()).isEqualTo(0);
  }

  @Test
  public void testInputsFilter_chainInputs_matchingOnlyFooAction() throws Exception {
    writeFile(
        "test/BUILD",
        "genrule(name='foo', srcs=['foo_matching_in.java'], outs=['foo_matching_out'],",
        "        cmd='cat $(SRCS) > $(OUTS)')",
        "java_library(name='bar', srcs=['in_bar.java'])",
        "genrule(name='foo2', srcs=['foo_matching_in.java_not'], outs=['foo_matching_out2'],",
        "        cmd='cat $(SRCS) > $(OUTS)')");

    AqueryActionFilter actionFilters =
        constructActionFilterChainSameFunction("inputs", ImmutableList.of(".*java", ".*foo.*"));

    ActionGraphContainer actionGraphContainer =
        getOutput("inputs('.*java', inputs('.*foo.*', deps(//test:all)))", actionFilters);

    assertMatchingOnlyActionFromFoo(actionGraphContainer);
  }

  @Test
  public void testOutputsFilter_chainOutputs_matchingOnlyFooAction() throws Exception {
    writeFile(
        "test/BUILD",
        "genrule(name='foo', srcs=['foo_matching_in.java'], outs=['foo_matching_out'],",
        "        cmd='cat $(SRCS) > $(OUTS)')",
        "genrule(name='foo2', srcs=['foo_matching_in.java'], outs=['foo_matching_out_not'],",
        "        cmd='cat $(SRCS) > $(OUTS)')",
        "genrule(name='foo3', srcs=['foo_matching_in.java'], outs=['not_matching_out'],",
        "        cmd='cat $(SRCS) > $(OUTS)')");

    AqueryActionFilter actionFilters =
        constructActionFilterChainSameFunction("outputs", ImmutableList.of(".*out", ".*foo.*"));

    ActionGraphContainer actionGraphContainer =
        getOutput("outputs('.*out', outputs('.*foo.*', deps(//test:all)))", actionFilters);

    assertMatchingOnlyActionFromFoo(actionGraphContainer);
  }

  @Test
  public void testMnemonicFilter_chainMnemonic_matchingOnlyFooAction() throws Exception {
    // java_library targets generate actions of the following mnemonics:
    // - Javac
    // - JavaSourceJar
    // - Turbine
    writeFile("test/BUILD", "java_library(", "    name = 'foo',", "    srcs = ['Foo.java'],", ")");

    AqueryActionFilter actionFilters =
        constructActionFilterChainSameFunction("mnemonic", ImmutableList.of("Java.*", ".*e.*"));

    ActionGraphContainer actionGraphContainer =
        getOutput("mnemonic('Java.*', mnemonic('.*e.*', deps(//test:all)))", actionFilters);

    assertThat(actionGraphContainer.getActionsCount()).isEqualTo(1);
    Action action = Iterables.getOnlyElement(actionGraphContainer.getActionsList());
    assertThat(action.getMnemonic()).isEqualTo("JavaSourceJar");
  }

  @Test
  public void testInputsFilter_noMatchingAction() throws Exception {
    writeFile(
        "test/BUILD",
        "genrule(name='foo', srcs=['in'], outs=['out'], tags=['requires-x'], ",
        "        cmd='cat $(SRCS) > $(OUTS)')");
    AqueryActionFilter actionFilters =
        constructActionFilter(ImmutableMap.of("inputs", "something"));
    ActionGraphContainer actionGraphContainer =
        getOutput("inputs('something', //test:foo)", actionFilters);
    assertThat(actionGraphContainer.getActionsCount()).isEqualTo(0);
  }

  @Test
  public void testOutputsFilter_noMatchingAction() throws Exception {
    writeFile(
        "test/BUILD",
        "genrule(name='foo', srcs=['in'], outs=['out'], tags=['requires-x'], ",
        "        cmd='cat $(SRCS) > $(OUTS)')");
    AqueryActionFilter actionFilters =
        constructActionFilter(ImmutableMap.of("outputs", "something"));
    ActionGraphContainer actionGraphContainer =
        getOutput("outputs('something', //test:foo)", actionFilters);
    assertThat(actionGraphContainer.getActionsCount()).isEqualTo(0);
  }

  @Test
  public void testMnemonicFilter_noMatchingAction() throws Exception {
    writeFile(
        "test/BUILD",
        "genrule(name='foo', srcs=['in'], outs=['out'], tags=['requires-x'], ",
        "        cmd='cat $(SRCS) > $(OUTS)')");
    AqueryActionFilter actionFilters =
        constructActionFilter(ImmutableMap.of("mnemonic", "something"));
    ActionGraphContainer actionGraphContainer =
        getOutput("mnemonic('something', //test:foo)", actionFilters);
    assertThat(actionGraphContainer.getActionsCount()).isEqualTo(0);
  }

  @Test
  public void test_includeArtifacts_disabled() throws Exception {
    options.includeArtifacts = false;

    writeFile("test/BUILD", "java_library(name='foo', srcs=['foo.java'])");
    ActionGraphContainer actionGraphContainer =
        getOutput("deps(//test:foo)", AqueryActionFilter.emptyInstance());
    Action javaCompileAction =
        Iterables.getOnlyElement(
            actionGraphContainer.getActionsList().stream()
                .filter(x -> x.getMnemonic().equals("Javac"))
                .collect(Collectors.toList()));

    assertThat(javaCompileAction.getInputDepSetIdsList()).isEmpty();
    assertThat(javaCompileAction.getOutputIdsList()).isEmpty();
    assertThat(actionGraphContainer.getDepSetOfFilesList()).isEmpty();
    assertThat(actionGraphContainer.getArtifactsList()).isEmpty();
  }

  @Test
  public void test_includeParamFile_subsetOfCmdlineArgs() throws Exception {
    if (OS.getCurrent() == OS.DARWIN) {
      return;
    }
    options.includeParamFiles = true;
    options.includeCommandline = true;

    writeFile("test/BUILD", "cc_binary(name='foo', srcs=['foo.cc'])");
    ActionGraphContainer actionGraphContainer =
        getOutput("deps(//test:foo)", AqueryActionFilter.emptyInstance());
    Action cppLinkAction =
        Iterables.getOnlyElement(
            actionGraphContainer.getActionsList().stream()
                .filter(x -> x.getMnemonic().equals("CppLink"))
                .collect(Collectors.toList()));

    // Verify that there's exactly 1 param file.
    assertThat(cppLinkAction.getParamFilesCount()).isEqualTo(1);

    // Verify that the set of arguments in the param file
    // is a subset of the set of arguments in the command line.
    ParamFile paramFile = Iterables.getOnlyElement(cppLinkAction.getParamFilesList());
    Set<String> cmdlineArgs = new HashSet<>(cppLinkAction.getArgumentsList());
    Set<String> paramFileArgs = new HashSet<>(paramFile.getArgumentsList());
    assertThat(cmdlineArgs).containsAtLeastElementsIn(paramFileArgs);
  }

  @Test
  public void test_flagTurnedOff_excludeParamFile() throws Exception {
    if (OS.getCurrent() == OS.DARWIN) {
      return;
    }
    writeFile("test/BUILD", "cc_binary(name='foo', srcs=['foo.cc'])");
    ActionGraphContainer actionGraphContainer =
        getOutput("deps(//test:foo)", AqueryActionFilter.emptyInstance());
    Action cppLinkAction =
        Iterables.getOnlyElement(
            actionGraphContainer.getActionsList().stream()
                .filter(x -> x.getMnemonic().equals("CppLink"))
                .collect(Collectors.toList()));

    // Verify that there's no param file field.
    assertThat(cppLinkAction.getParamFilesCount()).isEqualTo(0);
  }

  @Test
  public void test_includeParamFileSpawnActionStarlarkRule_noParamFileExplicitlyWritten()
      throws Exception {
    if (OS.getCurrent() == OS.DARWIN) {
      return;
    }
    options.includeParamFiles = true;
    options.includeCommandline = true;

    writeFile(
        "test/test_rule.bzl",
        "def _impl(ctx):",
        "  args = ctx.actions.args()",
        "  args.add('--param_file_arg')",
        "  args.set_param_file_format('multiline')",
        "  args.use_param_file('--param_file=%s', use_always = True)",
        "  ctx.actions.run(",
        "    inputs = ctx.files.srcs,",
        "    outputs = [ctx.outputs.outfile],",
        "    executable = 'dummy',",
        "    arguments = ['--non-param-file-flag', args],",
        "    mnemonic = 'SkylarkAction'",
        "  )",
        "test_rule = rule(",
        "  implementation = _impl,",
        "  attrs = {",
        "    'srcs': attr.label_list(allow_files=True)",
        "  },",
        "  outputs = {",
        "    'outfile': '{name}.out'",
        "  },",
        ")");

    writeFile(
        "test/BUILD",
        "load('//test:test_rule.bzl', 'test_rule')",
        "test_rule(name='foo', srcs=['foo.java'])");

    ActionGraphContainer actionGraphContainer =
        getOutput("deps(//test:all)", AqueryActionFilter.emptyInstance());

    Action spawnAction = Iterables.getOnlyElement(actionGraphContainer.getActionsList());

    // Verify that there's no param file field.
    assertThat(spawnAction.getParamFilesCount()).isEqualTo(0);

    // Verify that the argument list contains both arguments from param file and otherwise.
    assertThat(spawnAction.getArgumentsList())
        .containsExactly("dummy", "--non-param-file-flag", "--param_file_arg");
  }

  @Test
  public void testCppActionTemplate_includesActionTemplateMnemonic() throws Exception {
    writeFile(
        "test/a.bzl",
        "def _impl(ctx):",
        "  directory = ctx.actions.declare_directory(ctx.attr.name + \"_artifact.cc\")",
        "  ctx.actions.run_shell(",
        "    inputs = ctx.files.srcs,",
        "    outputs = [directory],",
        "    mnemonic = 'MoveTreeArtifact',",
        "    command = 'echo abc'",
        "  )",
        "  return [DefaultInfo(files = depset([directory]))]",
        "cc_tree_artifact_files = rule(",
        "  implementation = _impl,",
        "  attrs = {",
        "    'srcs': attr.label_list(allow_files=True),",
        "  },",
        ")");

    writeFile(
        "test/BUILD",
        "load(':a.bzl', 'cc_tree_artifact_files')",
        "cc_tree_artifact_files(",
        "    name = 'tree_artifact',",
        "    srcs = ['a1.cc', 'a2.cc'],",
        ")",
        "",
        "cc_binary(",
        "    name = 'bin',",
        "    srcs = ['b1.h', 'b2.cc', ':tree_artifact'],",
        ")");

    ActionGraphContainer actionGraphContainer =
        getOutput("deps(//test:all)", AqueryActionFilter.emptyInstance());

    List<Action> cppCompileActionTemplates =
        actionGraphContainer.getActionsList().stream()
            .filter(action -> action.getMnemonic().equals("CppCompileActionTemplate"))
            .collect(Collectors.toList());

    // Verify that we have the appropriate number of CppCompileActionTemplates.
    assertThat(cppCompileActionTemplates).hasSize(1);
  }

  @Test
  public void testIncludeAspects_AspectOnAspect() throws Exception {
    options.useAspects = true;
    writeFile(
        "test/rule.bzl",
        "MyProvider = provider(",
        "  fields = {",
        "    'dummy_field': 'dummy field'",
        "  }",
        ")",
        "def _my_jpl_aspect_imp(target, ctx):",
        "  if hasattr(ctx.rule.attr, 'srcs'):",
        "    out = ctx.actions.declare_file('out_jpl_{}'.format(target))",
        "    ctx.actions.run(",
        "      inputs = [f for src in ctx.rule.attr.srcs for f in src.files.to_list()],",
        "      outputs = [out],",
        "      executable = 'dummy',",
        "      mnemonic = 'MyJplAspect'",
        "    )",
        "  return [MyProvider(dummy_field = 1)]",
        "my_jpl_aspect = aspect(",
        "  attr_aspects = ['deps', 'exports'],",
        "  required_aspect_providers = [['proto_java']],",
        "  provides = [MyProvider],",
        "  implementation = _my_jpl_aspect_imp,",
        ")",
        "def _jpl_rule_impl(ctx):",
        "  return struct()",
        "my_jpl_rule = rule(",
        "  attrs = {",
        "    'deps': attr.label_list(aspects = [my_jpl_aspect]),",
        "    'srcs': attr.label_list(allow_files = True),",
        "  },",
        "  implementation = _jpl_rule_impl",
        ")",
        "def _aspect_impl(target, ctx):",
        "  if hasattr(ctx.rule.attr, 'srcs'):",
        "    out = ctx.actions.declare_file('out{}'.format(target))",
        "    ctx.actions.run(",
        "      inputs = [f for src in ctx.rule.attr.srcs for f in src.files.to_list()],",
        "      outputs = [out],",
        "      executable = 'dummy',",
        "      mnemonic = 'MyAspect'",
        "    )",
        "  return [struct()]",
        "my_aspect = aspect(",
        "  attr_aspects = ['deps', 'exports'],",
        "  required_aspect_providers = [[MyProvider]],",
        "  attrs = {",
        "    'aspect_param': attr.string(default = 'x', values = ['x', 'y'])",
        "  },",
        "  implementation = _aspect_impl,",
        ")",
        "def _rule_impl(ctx):",
        "  return struct()",
        "my_rule = rule(",
        "  attrs = {",
        "    'deps': attr.label_list(aspects = [my_aspect]),",
        "    'srcs': attr.label_list(allow_files = True),",
        "    'aspect_param': attr.string(default = 'x', values = ['x', 'y'])",
        "  },",
        "  implementation = _rule_impl",
        ")");

    writeFile(
        "test/BUILD",
        "load(':rule.bzl', 'my_rule', 'my_jpl_rule')",
        "proto_library(",
        "  name = 'x',",
        "  srcs = [':x.proto']",
        ")",
        "my_jpl_rule(",
        "  name = 'my_java_proto',",
        "  deps = [':x'],",
        ")",
        "my_rule(",
        "  name = 'my_target',",
        "  deps = [':my_java_proto'],",
        "  srcs = ['foo.java'],",
        "  aspect_param = 'y'",
        ")");

    ActionGraphContainer actionGraphContainer =
        getOutput("deps(//test:my_target)", AqueryActionFilter.emptyInstance());

    Target protoLibraryTarget =
        Iterables.getOnlyElement(
            actionGraphContainer.getTargetsList().stream()
                .filter(target -> target.getLabel().equals("//test:x"))
                .collect(Collectors.toList()));
    Action actionFromMyAspect =
        Iterables.getOnlyElement(
            actionGraphContainer.getActionsList().stream()
                .filter(
                    action ->
                        action.getMnemonic().equals("MyAspect")
                            && action.getTargetId().equals(protoLibraryTarget.getId()))
                .collect(Collectors.toList()));

    // Verify the aspect path of the action.
    assertThat(actionFromMyAspect.getAspectDescriptorIdsCount()).isEqualTo(2);
    List<KeyValuePair> expectedMyAspectParams =
        ImmutableList.of(KeyValuePair.newBuilder().setKey("aspect_param").setValue("y").build());
    assertCorrectAspectDescriptor(
        actionGraphContainer,
        actionFromMyAspect.getAspectDescriptorIds(0),
        "//test:rule.bzl%my_aspect",
        expectedMyAspectParams);
    assertCorrectAspectDescriptor(
        actionGraphContainer,
        actionFromMyAspect.getAspectDescriptorIds(1),
        "//test:rule.bzl%my_jpl_aspect",
        ImmutableList.of());
  }

  @Test
  public void testIncludeAspects_SingleAspect() throws Exception {
    options.useAspects = true;
    writeFile(
        "test/rule.bzl",
        "MyProvider = provider(",
        "  fields = {",
        "    'dummy_field': 'dummy field'",
        "  }",
        ")",
        "def _my_jpl_aspect_imp(target, ctx):",
        "  if hasattr(ctx.rule.attr, 'srcs'):",
        "    out = ctx.actions.declare_file('out_jpl_{}'.format(target))",
        "    ctx.actions.run(",
        "      inputs = [f for src in ctx.rule.attr.srcs for f in src.files.to_list()],",
        "      outputs = [out],",
        "      executable = 'dummy',",
        "      mnemonic = 'MyJplAspect'",
        "    )",
        "  return [MyProvider(dummy_field = 1)]",
        "my_jpl_aspect = aspect(",
        "  attr_aspects = ['deps', 'exports'],",
        "  required_aspect_providers = [['proto_java']],",
        "  attrs = {",
        "    'aspect_param': attr.string(default = 'x', values = ['x', 'y'])",
        "  },",
        "  implementation = _my_jpl_aspect_imp,",
        ")",
        "def _jpl_rule_impl(ctx):",
        "  return struct()",
        "my_jpl_rule = rule(",
        "  attrs = {",
        "    'deps': attr.label_list(aspects = [my_jpl_aspect]),",
        "    'srcs': attr.label_list(allow_files = True),",
        "    'aspect_param': attr.string(default = 'x', values = ['x', 'y'])",
        "  },",
        "  implementation = _jpl_rule_impl",
        ")");

    writeFile(
        "test/BUILD",
        "load(':rule.bzl', 'my_jpl_rule')",
        "proto_library(",
        "  name = 'x',",
        "  srcs = [':x.proto']",
        ")",
        "my_jpl_rule(",
        "  name = 'my_java_proto',",
        "  deps = [':x'],",
        "  aspect_param = 'y'",
        ")");

    ActionGraphContainer actionGraphContainer =
        getOutput("deps(//test:my_java_proto)", AqueryActionFilter.emptyInstance());

    Target protoLibraryTarget =
        Iterables.getOnlyElement(
            actionGraphContainer.getTargetsList().stream()
                .filter(target -> target.getLabel().equals("//test:x"))
                .collect(Collectors.toList()));
    Action actionFromMyJplAspect =
        Iterables.getOnlyElement(
            actionGraphContainer.getActionsList().stream()
                .filter(
                    action ->
                        action.getMnemonic().equals("MyJplAspect")
                            && action.getTargetId().equals(protoLibraryTarget.getId()))
                .collect(Collectors.toList()));

    // Verify the aspect of the action.
    assertThat(actionFromMyJplAspect.getAspectDescriptorIdsCount()).isEqualTo(1);
    List<KeyValuePair> expectedMyAspectParams =
        ImmutableList.of(KeyValuePair.newBuilder().setKey("aspect_param").setValue("y").build());
    assertCorrectAspectDescriptor(
        actionGraphContainer,
        Iterables.getOnlyElement(actionFromMyJplAspect.getAspectDescriptorIdsList()),
        "//test:rule.bzl%my_jpl_aspect",
        expectedMyAspectParams);
  }

  @Test
  public void testIncludeAspects_twoAspectsOneTarget_separateAspectDescriptors() throws Exception {
    options.useAspects = true;
    writeFile(
        "test/rule.bzl",
        "JplProvider = provider(",
        "  fields = {",
        "    'dummy_field': 'dummy field'",
        "  }",
        ")",
        "RandomProvider = provider(",
        "  fields = {",
        "    'dummy_field': 'dummy field'",
        "  }",
        ")",
        "def _common_impl(target, ctx, outfilename, mnemonic, provider):",
        "  if hasattr(ctx.rule.attr, 'srcs'):",
        "    out = ctx.actions.declare_file(outfilename)",
        "    ctx.actions.run(",
        "      inputs = [f for src in ctx.rule.attr.srcs for f in src.files.to_list()],",
        "      outputs = [out],",
        "      executable = 'dummy',",
        "      mnemonic = mnemonic",
        "    )",
        "  return [provider(dummy_field = 1)]",
        "def _my_random_aspect_impl(target, ctx):",
        "  return _common_impl(target, ctx, 'rand_out', 'MyRandomAspect', RandomProvider)",
        "my_random_aspect = aspect(",
        "  attr_aspects = ['deps', 'exports'],",
        "  required_aspect_providers = [['proto_java']],",
        "  provides = [RandomProvider],",
        "  implementation = _my_random_aspect_impl,",
        ")",
        "def _rule_impl(ctx):",
        "  return struct()",
        "my_random_rule = rule(",
        "  attrs = {",
        "    'deps': attr.label_list(aspects = [my_random_aspect]),",
        "    'srcs': attr.label_list(allow_files = True),",
        "  },",
        "  implementation = _rule_impl",
        ")",
        "def _my_jpl_aspect_impl(target, ctx):",
        "  return _common_impl(target, ctx, 'jpl_out', 'MyJplAspect', JplProvider)",
        "my_jpl_aspect = aspect(",
        "  attr_aspects = ['deps', 'exports'],",
        "  required_aspect_providers = [['proto_java']],",
        "  provides = [JplProvider],",
        "  implementation = _my_jpl_aspect_impl,",
        ")",
        "my_jpl_rule = rule(",
        "  attrs = {",
        "    'deps': attr.label_list(aspects = [my_jpl_aspect]),",
        "    'srcs': attr.label_list(allow_files = True),",
        "  },",
        "  implementation = _rule_impl",
        ")");

    writeFile(
        "test/BUILD",
        "load(':rule.bzl', 'my_jpl_rule', 'my_random_rule')",
        "proto_library(",
        "  name = 'x',",
        "  srcs = [':x.proto']",
        ")",
        "my_jpl_rule(",
        "  name = 'target_1',",
        "  deps = [':x'],",
        ")",
        "my_random_rule(",
        "  name = 'target_2',",
        "  deps = [':x'],",
        ")");

    ActionGraphContainer actionGraphContainer =
        getOutput("//test:all", AqueryActionFilter.emptyInstance());

    Target protoLibraryTarget =
        Iterables.getOnlyElement(
            actionGraphContainer.getTargetsList().stream()
                .filter(target -> target.getLabel().equals("//test:x"))
                .collect(Collectors.toList()));
    Action actionFromMyJplAspect =
        Iterables.getOnlyElement(
            actionGraphContainer.getActionsList().stream()
                .filter(
                    action ->
                        action.getMnemonic().equals("MyJplAspect")
                            && action.getTargetId().equals(protoLibraryTarget.getId()))
                .collect(Collectors.toList()));
    Action actionFromMyRandomAspect =
        Iterables.getOnlyElement(
            actionGraphContainer.getActionsList().stream()
                .filter(
                    action ->
                        action.getMnemonic().equals("MyRandomAspect")
                            && action.getTargetId().equals(protoLibraryTarget.getId()))
                .collect(Collectors.toList()));

    // Verify the aspect path of the action contains exactly 1 aspect.
    assertThat(actionFromMyJplAspect.getAspectDescriptorIdsCount()).isEqualTo(1);
    assertCorrectAspectDescriptor(
        actionGraphContainer,
        Iterables.getOnlyElement(actionFromMyJplAspect.getAspectDescriptorIdsList()),
        "//test:rule.bzl%my_jpl_aspect",
        ImmutableList.of());
    assertThat(actionFromMyRandomAspect.getAspectDescriptorIdsCount()).isEqualTo(1);
    assertCorrectAspectDescriptor(
        actionGraphContainer,
        Iterables.getOnlyElement(actionFromMyRandomAspect.getAspectDescriptorIdsList()),
        "//test:rule.bzl%my_random_aspect",
        ImmutableList.of());
  }

  @Test
  public void testIncludeAspects_flagDisabled_NoAspect() throws Exception {
    // The flag --include_aspects is set to false by default.
    writeFile(
        "test/rule.bzl",
        "MyProvider = provider(",
        "  fields = {",
        "    'dummy_field': 'dummy field'",
        "  }",
        ")",
        "def _my_jpl_aspect_imp(target, ctx):",
        "  if hasattr(ctx.rule.attr, 'srcs'):",
        "    out = ctx.actions.declare_file('out_jpl_{}'.format(target))",
        "    ctx.actions.run(",
        "      inputs = [f for src in ctx.rule.attr.srcs for f in src.files.to_list()],",
        "      outputs = [out],",
        "      executable = 'dummy',",
        "      mnemonic = 'MyJplAspect'",
        "    )",
        "  return [MyProvider(dummy_field = 1)]",
        "my_jpl_aspect = aspect(",
        "  attr_aspects = ['deps', 'exports'],",
        "  required_aspect_providers = [['proto_java']],",
        "  attrs = {",
        "    'aspect_param': attr.string(default = 'x', values = ['x', 'y'])",
        "  },",
        "  implementation = _my_jpl_aspect_imp,",
        ")",
        "def _jpl_rule_impl(ctx):",
        "  return struct()",
        "my_jpl_rule = rule(",
        "  attrs = {",
        "    'deps': attr.label_list(aspects = [my_jpl_aspect]),",
        "    'srcs': attr.label_list(allow_files = True),",
        "    'aspect_param': attr.string(default = 'x', values = ['x', 'y'])",
        "  },",
        "  implementation = _jpl_rule_impl",
        ")");

    writeFile(
        "test/BUILD",
        "load(':rule.bzl', 'my_jpl_rule')",
        "proto_library(",
        "  name = 'x',",
        "  srcs = [':x.proto']",
        ")",
        "my_jpl_rule(",
        "  name = 'my_java_proto',",
        "  deps = [':x'],",
        "  aspect_param = 'y'",
        ")");

    ActionGraphContainer actionGraphContainer =
        getOutput("deps(//test:my_java_proto)", AqueryActionFilter.emptyInstance());

    assertThat(
            actionGraphContainer.getActionsList().stream()
                .filter(action -> !action.getAspectDescriptorIdsList().isEmpty())
                .collect(Collectors.toList()))
        .isEmpty();
  }

  private AnalysisProtos.ActionGraphContainer getOutput(String queryExpression) throws Exception {
    return getOutput(queryExpression, /* actionFilters= */ AqueryActionFilter.emptyInstance());
  }

  private AnalysisProtos.ActionGraphContainer getOutput(
      String queryExpression, AqueryActionFilter actionFilters) throws Exception {
    QueryExpression expression = QueryParser.parse(queryExpression, getDefaultFunctions());
    Set<String> targetPatternSet = new LinkedHashSet<>();
    expression.collectTargetPatterns(targetPatternSet);
    helper.setQuerySettings(Setting.NO_IMPLICIT_DEPS);
    PostAnalysisQueryEnvironment<ConfiguredTargetValue> env =
        ((ActionGraphQueryHelper) helper).getPostAnalysisQueryEnvironment(targetPatternSet);

    ActionGraphProtoOutputFormatterCallback callback =
        new ActionGraphProtoOutputFormatterCallback(
            reporter,
            options,
            /*out=*/ null,
            getHelper().getSkyframeExecutor(),
            env.getAccessor(),
            OutputType.BINARY,
            actionFilters);
    env.evaluateQuery(expression, callback);
    return callback.getProtoResult();
  }

  private void assertMatchingOnlyActionFromFoo(ActionGraphContainer actionGraphContainer) {
    assertMatchingOnlyAction(
        actionGraphContainer, "Genrule", "test/foo_matching_in.java", "/bin/test/foo_matching_out");
  }

  private void assertMatchingOnlyAction(
      ActionGraphContainer actionGraphContainer,
      String mnemonic,
      String onlyInput,
      String onlyOutput) {
    assertThat(actionGraphContainer.getActionsCount()).isEqualTo(1);
    Action action = Iterables.getOnlyElement(actionGraphContainer.getActionsList());

    // Verify mnemonic
    assertThat(action.getMnemonic()).isEqualTo(mnemonic);

    // Verify input
    String inputId = null;
    for (Artifact artifact : actionGraphContainer.getArtifactsList()) {
      if (artifact.getExecPath().endsWith(onlyInput)) {
        inputId = artifact.getId();
        break;
      }
    }
    assertThat(action.getInputDepSetIdsList()).contains(inputId);

    // Verify output
    String outputId = null;
    for (Artifact artifact : actionGraphContainer.getArtifactsList()) {
      if (artifact.getExecPath().endsWith(onlyOutput)) {
        outputId = artifact.getId();
        break;
      }
    }
    assertThat(action.getOutputIdsList()).contains(outputId);
  }

  private void assertCorrectAspectDescriptor(
      ActionGraphContainer actionGraphContainer,
      String aspectDescriptorId,
      String expectedName,
      List<KeyValuePair> expectedParameters) {
    for (AspectDescriptor aspectDescriptor : actionGraphContainer.getAspectDescriptorsList()) {
      if (!aspectDescriptorId.equals(aspectDescriptor.getId())) {
        continue;
      }
      assertThat(aspectDescriptor.getName()).isEqualTo(expectedName);
      assertThat(aspectDescriptor.getParametersList()).isEqualTo(expectedParameters);
      return;
    }
    fail("Should have matched at least one AspectDescriptor.");
  }

  private AqueryActionFilter constructActionFilter(ImmutableMap<String, String> patternStrings) {
    AqueryActionFilter.Builder builder = AqueryActionFilter.builder();
    for (Entry<String, String> e : patternStrings.entrySet()) {
      builder.put(e.getKey(), Pattern.compile(e.getValue()));
    }
    return builder.build();
  }

  private AqueryActionFilter constructActionFilterChainSameFunction(
      String function, List<String> patternStrings) {
    AqueryActionFilter.Builder builder = AqueryActionFilter.builder();
    for (String s : patternStrings) {
      builder.put(function, Pattern.compile(s));
    }
    return builder.build();
  }
}
