// 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.truth.Truth.assertThat;
import static com.google.devtools.build.lib.packages.Attribute.attr;
import static com.google.devtools.build.lib.packages.BuildType.LABEL;
import static com.google.devtools.build.lib.packages.BuildType.LABEL_LIST;
import static com.google.devtools.build.lib.packages.Type.STRING;
import static org.junit.Assert.assertThrows;

import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Iterables;
import com.google.devtools.build.lib.analysis.config.BuildConfigurationValue;
import com.google.devtools.build.lib.analysis.config.BuildOptions;
import com.google.devtools.build.lib.analysis.config.BuildOptionsView;
import com.google.devtools.build.lib.analysis.config.ExecutionTransitionFactory;
import com.google.devtools.build.lib.analysis.config.FragmentOptions;
import com.google.devtools.build.lib.analysis.config.TransitionFactories;
import com.google.devtools.build.lib.analysis.config.transitions.PatchTransition;
import com.google.devtools.build.lib.analysis.test.TestConfiguration.TestOptions;
import com.google.devtools.build.lib.analysis.util.DummyTestFragment.DummyTestOptions;
import com.google.devtools.build.lib.analysis.util.MockRule;
import com.google.devtools.build.lib.cmdline.Label;
import com.google.devtools.build.lib.cmdline.TargetParsingException;
import com.google.devtools.build.lib.events.EventHandler;
import com.google.devtools.build.lib.packages.BuildType;
import com.google.devtools.build.lib.query2.engine.QueryEnvironment.Setting;
import com.google.devtools.build.lib.query2.engine.QueryException;
import com.google.devtools.build.lib.server.FailureDetails;
import com.google.devtools.build.lib.server.FailureDetails.ConfigurableQuery;
import com.google.devtools.build.lib.server.FailureDetails.Query;
import com.google.devtools.build.lib.server.FailureDetails.Query.Code;
import com.google.devtools.build.lib.util.FileTypeSet;
import com.google.devtools.build.lib.vfs.Path;
import java.util.Collection;
import java.util.Iterator;
import java.util.Set;
import java.util.stream.Collectors;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.JUnit4;

/**
 * Tests for {@link ConfiguredTargetQueryEnvironment}.
 *
 * <p>This tests core cquery behavior (behavior that doesn't depend on <code>--output</code>).
 * Output format-specific behavior is covered in dedicated test classes.
 */
@RunWith(JUnit4.class)
public class ConfiguredTargetQuerySemanticsTest extends ConfiguredTargetQueryTest {
  @Test
  public void testConfigurationRespected() throws Exception {
    writeBuildFilesWithConfigurableAttributesUnconditionally();
    assertThat(eval("deps(//configurable:main) ^ //configurable:adep")).isEmpty();
    assertThat(eval("deps(//configurable:main) ^ //configurable:defaultdep")).hasSize(1);
  }

  private void setUpLabelsFunctionTests() throws Exception {
    MockRule ruleWithTransitions =
        () ->
            MockRule.define(
                "rule_with_transitions",
                attr("patch_dep", LABEL)
                    .allowedFileTypes(FileTypeSet.ANY_FILE)
                    .cfg(TransitionFactories.of(new FooPatchTransition("SET BY PATCH"))),
                attr("string_dep", STRING),
                attr("split_dep", LABEL)
                    .allowedFileTypes(FileTypeSet.ANY_FILE)
                    .cfg(
                        TransitionFactories.of(
                            new FooSplitTransition("SET BY SPLIT 1", "SET BY SPLIT 2"))),
                attr("patch_dep_list", LABEL_LIST)
                    .allowedFileTypes(FileTypeSet.ANY_FILE)
                    .cfg(TransitionFactories.of(new FooPatchTransition("SET BY PATCH 2"))));
    MockRule noAttributeRule = () -> MockRule.define("no_attribute_rule");

    helper.useRuleClassProvider(
        setRuleClassProviders(ruleWithTransitions, noAttributeRule).build());

    writeFile(
        "test/BUILD",
        "rule_with_transitions(name = 'my_rule',",
        "  patch_dep = ':dep-1',",
        "  split_dep = ':dep-2',",
        "  string_dep = 'some string',",
        "  patch_dep_list = [':dep-3', ':dep-4']",
        ")",
        "no_attribute_rule(name = 'dep-1')",
        "no_attribute_rule(name = 'dep-2')",
        "no_attribute_rule(name = 'dep-3')",
        "no_attribute_rule(name = 'dep-4')");

    helper.setUniverseScope("//test:*");
  }

  @Test
  public void testLabelFunction_getsCorrectConfigurations() throws Exception {
    setUpLabelsFunctionTests();

    // (Test that you can use the labels function without an error (b/112593112)).
    // Note - 'labels' as a command for cquery is a slight misnomer since it always prints
    // labels AND configurations. But still a helpful function so oh well.
    assertThat(Iterables.getOnlyElement(eval("labels('patch_dep', //test:my_rule)"))).isNotNull();
  }

  @Test
  public void testLabelFunction_getCorrectlyConfiguredDeps() throws Exception {
    setUpLabelsFunctionTests();

    // Test that this retrieves the correctly configured version(s) of the dep(s).
    KeyedConfiguredTarget patchDep =
        Iterables.getOnlyElement(eval("labels('patch_dep', //test:my_rule)"));
    KeyedConfiguredTarget myRule = Iterables.getOnlyElement(eval("//test:my_rule"));
    String targetConfiguration = myRule.getConfigurationChecksum();
    assertThat(patchDep.getConfigurationChecksum()).doesNotMatch(targetConfiguration);
  }

  @Test
  public void testLabelsFunction_splitTransitionAttribute() throws Exception {
    setUpLabelsFunctionTests();

    KeyedConfiguredTarget myRule = Iterables.getOnlyElement(eval("//test:my_rule"));
    String targetConfiguration = myRule.getConfigurationChecksum();

    Collection<KeyedConfiguredTarget> splitDeps = eval("labels('split_dep', //test:my_rule)");
    assertThat(splitDeps).hasSize(2);
    for (KeyedConfiguredTarget kct : splitDeps) {
      assertThat(kct.getConfigurationChecksum()).doesNotMatch(targetConfiguration);
    }
  }

  @Test
  public void testLabelsFunction_labelListAttribute() throws Exception {
    setUpLabelsFunctionTests();

    KeyedConfiguredTarget myRule = Iterables.getOnlyElement(eval("//test:my_rule"));
    String targetConfiguration = myRule.getConfigurationChecksum();

    // Test that this works for label_lists as well.
    Set<KeyedConfiguredTarget> deps = eval("labels('patch_dep_list', //test:my_rule)");
    assertThat(deps).hasSize(2);
    for (KeyedConfiguredTarget kct : deps) {
      assertThat(kct.getConfigurationChecksum()).doesNotMatch(targetConfiguration);
    }
  }

  @Test
  public void testLabelsFunction_errorsOnBadAttribute() throws Exception {
    setUpLabelsFunctionTests();

    // Test that the proper error is thrown when requesting an attribute that doesn't exist.
    EvalThrowsResult evalThrowsResult = evalThrows("labels('fake_attr', //test:my_rule)", true);
    assertConfigurableQueryCode(
        evalThrowsResult.getFailureDetail(), ConfigurableQuery.Code.ATTRIBUTE_MISSING);
    assertThat(evalThrowsResult.getMessage())
        .isEqualTo(
            "in 'fake_attr' of rule //test:my_rule: configured target of type"
                + " rule_with_transitions does not have attribute 'fake_attr'");
  }

  @Test
  public void testLabelsFunction_nonLabelAttribute() throws Exception {
    setUpLabelsFunctionTests();
    assertThat(eval("labels('string_dep', //test:my_rule)")).isEmpty();
  }

  /**
   * Regression test for b/162431514. the {@code labels} query operator uses {@link
   * ConfiguredTargetAccessor#getPrerequisites} which is the actual logic being tested here.
   */
  @Test
  public void testGetPrerequisitesFromAliasReturnsActualPrerequisites() throws Exception {
    MockRule ruleWithDep =
        () ->
            MockRule.define(
                "rule_with_dep", attr("dep", LABEL).allowedFileTypes(FileTypeSet.ANY_FILE));

    helper.useRuleClassProvider(setRuleClassProviders(ruleWithDep).build());
    writeFile(
        "test/BUILD",
        "alias(name = 'alias', actual = ':actual')",
        "rule_with_dep(name = 'actual', dep = ':dep')",
        "rule_with_dep(name = 'dep')");

    KeyedConfiguredTarget dep = Iterables.getOnlyElement(eval("labels('dep', '//test:alias')"));
    assertThat(dep.getLabel()).isEqualTo(Label.parseAbsoluteUnchecked("//test:dep"));
  }

  @Test
  public void testAlias_filtering() throws Exception {
    MockRule ruleWithHostDep =
        () ->
            MockRule.define(
                "rule_with_host_dep",
                attr("host_dep", LABEL)
                    .allowedFileTypes(FileTypeSet.ANY_FILE)
                    .cfg(ExecutionTransitionFactory.create()),
                attr("$impl_dep", LABEL)
                    .allowedFileTypes(FileTypeSet.ANY_FILE)
                    .value(Label.parseAbsoluteUnchecked("//test:other")));
    MockRule simpleRule = () -> MockRule.define("simple_rule");

    helper.useRuleClassProvider(setRuleClassProviders(ruleWithHostDep, simpleRule).build());
    writeFile(
        "test/BUILD",
        "alias(name = 'other_my_rule', actual = ':my_rule')",
        "rule_with_host_dep(name = 'my_rule', host_dep = ':host_dep')",
        "alias(name = 'other_host_dep', actual = ':host_dep')",
        "simple_rule(name='host_dep')",
        "alias(name = 'other_impl_dep', actual = 'impl_dep')",
        "simple_rule(name='impl_dep')");

    KeyedConfiguredTarget other = Iterables.getOnlyElement(eval("//test:other_my_rule"));
    KeyedConfiguredTarget myRule = Iterables.getOnlyElement(eval("//test:my_rule"));
    // Note: {@link KeyedConfiguredTarget#getLabel} returns the label of the "actual" value not the
    // label of the alias, so we need to check the underlying label.
    assertThat(other.getConfiguredTarget().getLabel())
        .isEqualTo(myRule.getConfiguredTarget().getLabel());

    // Regression test for b/73496081 in which alias-ed configured targets were skipping filtering.
    helper.setQuerySettings(Setting.ONLY_TARGET_DEPS, Setting.NO_IMPLICIT_DEPS);
    assertThat(evalToListOfStrings("deps(//test:other_my_rule)-//test:other_my_rule"))
        .isEqualTo(evalToListOfStrings("//test:my_rule"));
  }

  @Test
  public void testTopLevelTransition() throws Exception {
    MockRule ruleClassTransition =
        () ->
            MockRule.define(
                "rule_class_transition",
                (builder, env) -> builder.cfg(new FooPatchTransition("SET BY PATCH")).build());

    helper.useRuleClassProvider(setRuleClassProviders(ruleClassTransition).build());
    helper.setUniverseScope("//test:rule_class");

    writeFile("test/BUILD", "rule_class_transition(name='rule_class')");

    Set<KeyedConfiguredTarget> ruleClass = eval("//test:rule_class");
    DummyTestOptions testOptions =
        getConfiguration(Iterables.getOnlyElement(ruleClass))
            .getOptions()
            .get(DummyTestOptions.class);
    assertThat(testOptions.foo).isEqualTo("SET BY PATCH");
  }

  private void createConfigRulesAndBuild() throws Exception {
    MockRule ruleWithTransitions =
        () ->
            MockRule.define(
                "my_rule",
                attr("target", LABEL).allowedFileTypes(FileTypeSet.ANY_FILE),
                attr("host", LABEL)
                    .allowedFileTypes(FileTypeSet.ANY_FILE)
                    .cfg(ExecutionTransitionFactory.create()),
                attr("exec", LABEL)
                    .allowedFileTypes(FileTypeSet.ANY_FILE)
                    .cfg(ExecutionTransitionFactory.create()),
                attr("deps", BuildType.LABEL_LIST).allowedFileTypes(FileTypeSet.ANY_FILE));
    MockRule simpleRule =
        () ->
            MockRule.define(
                "simple_rule", attr("dep", LABEL).allowedFileTypes(FileTypeSet.ANY_FILE));
    helper.useRuleClassProvider(setRuleClassProviders(ruleWithTransitions, simpleRule).build());

    writeFile(
        "test/BUILD",
        "my_rule(",
        "  name = 'my_rule',",
        "  target = ':target_dep',",
        "  host = ':host_dep',",
        "  exec = ':exec_dep',",
        "  deps = [':dep'],",
        ")",
        "simple_rule(name = 'target_dep', dep=':dep')",
        "simple_rule(name = 'host_dep', dep=':dep')",
        "simple_rule(name = 'exec_dep', dep=':dep')",
        "simple_rule(name = 'dep')");
  }

  private void createConfigTransitioningRuleClass() throws Exception {
    overwriteFile(
        "tools/allowlists/function_transition_allowlist/BUILD",
        "package_group(",
        "    name = 'function_transition_allowlist',",
        "    packages = [",
        "        '//test/...',",
        "    ],",
        ")");
    writeFile(
        "test/rules.bzl",
        "def _rule_impl(ctx):",
        "    return []",
        "string_flag = rule(",
        "    implementation = _rule_impl,",
        "    build_setting = config.string()",
        ")",
        "def _transition_impl(settings, attr):",
        "    return {'//test:my_flag': 'custom string'}",
        "my_transition = transition(",
        "    implementation = _transition_impl,",
        "    inputs = [],",
        "    outputs = ['//test:my_flag'],",
        ")",
        "rule_with_deps_transition = rule(",
        "    implementation = _rule_impl,",
        "    attrs = {",
        "        'deps': attr.label_list(cfg = my_transition),",
        "        '_allowlist_function_transition': attr.label(",
        "            default = '//tools/allowlists/function_transition_allowlist',",
        "        ),",
        "    }",
        ")",
        "simple_rule = rule(",
        "    implementation = _rule_impl,",
        "    attrs = {}",
        ")");
  }

  @Test
  public void testConfig_target() throws Exception {
    createConfigRulesAndBuild();

    assertThat(eval("config(//test:target_dep, target)")).isEqualTo(eval("//test:target_dep"));

    getHelper().setWholeTestUniverseScope("test:my_rule");

    assertThat(eval("config(//test:target_dep, target)")).isEqualTo(eval("//test:target_dep"));
    EvalThrowsResult hostResult = evalThrows("config(//test:host_dep, target)", true);
    assertThat(hostResult.getMessage())
        .isEqualTo("No target (in) //test:host_dep could be found in the 'target' configuration");
    assertConfigurableQueryCode(
        hostResult.getFailureDetail(), ConfigurableQuery.Code.TARGET_MISSING);
    EvalThrowsResult execResult = evalThrows("config(//test:exec_dep, target)", true);
    assertThat(execResult.getMessage())
        .isEqualTo("No target (in) //test:exec_dep could be found in the 'target' configuration");
    assertConfigurableQueryCode(
        execResult.getFailureDetail(), ConfigurableQuery.Code.TARGET_MISSING);

    BuildConfigurationValue configuration =
        getConfiguration(Iterables.getOnlyElement(eval("config(//test:dep, target)")));

    assertThat(configuration).isNotNull();
    assertThat(configuration.isHostConfiguration()).isFalse();
    assertThat(configuration.isExecConfiguration()).isFalse();
    assertThat(configuration.isToolConfiguration()).isFalse();
  }

  @Test
  public void testConfig_noMoreHostTransition() throws Exception {
    createConfigRulesAndBuild();

    getHelper().setWholeTestUniverseScope("test:my_rule");

    EvalThrowsResult targetResult = evalThrows("config(//test:target_dep, host)", true);
    assertThat(targetResult.getMessage())
        .isEqualTo("No target (in) //test:target_dep could be found in the 'host' configuration");
    assertConfigurableQueryCode(
        targetResult.getFailureDetail(), ConfigurableQuery.Code.TARGET_MISSING);
    EvalThrowsResult hostDepResult = evalThrows("config(//test:host_dep, host)", true);
    assertThat(hostDepResult.getMessage())
        .isEqualTo("No target (in) //test:host_dep could be found in the 'host' configuration");
    assertConfigurableQueryCode(
        hostDepResult.getFailureDetail(), ConfigurableQuery.Code.TARGET_MISSING);
    EvalThrowsResult execDepResult = evalThrows("config(//test:exec_dep, host)", true);
    assertThat(execDepResult.getMessage())
        .isEqualTo("No target (in) //test:exec_dep could be found in the 'host' configuration");
    assertConfigurableQueryCode(
        execDepResult.getFailureDetail(), ConfigurableQuery.Code.TARGET_MISSING);
    EvalThrowsResult hostResult = evalThrows("config(//test:dep, host)", true);
    assertThat(hostResult.getMessage())
        .isEqualTo("No target (in) //test:dep could be found in the 'host' configuration");
    assertConfigurableQueryCode(
        hostResult.getFailureDetail(), ConfigurableQuery.Code.TARGET_MISSING);
  }

  @Test
  public void testConfig_nullConfig() throws Exception {
    writeFile("test/BUILD", "java_library(name='my_java',", "  srcs = ['foo.java'],", ")");

    assertThat(getConfiguration(Iterables.getOnlyElement(eval("config(//test:foo.java,null)"))))
        .isNull();
  }

  @Test
  public void testConfig_configHash() throws Exception {
    createConfigTransitioningRuleClass();
    writeFile(
        "test/BUILD",
        "load('//test:rules.bzl', 'rule_with_deps_transition', 'simple_rule', 'string_flag')",
        "string_flag(",
        "    name = 'my_flag',",
        "    build_setting_default = '')",
        "rule_with_deps_transition(",
        "    name = 'buildme',",
        "    deps = [':mydep'])",
        "simple_rule(name = 'mydep')");

    // If we don't set --universe_scope=//test:buildme, cquery builds both //test:buildme and
    // //test:mydep as top-level targets. That means //test:mydep will have two configured targets:
    // one under the transitioned configuration and one under the top-level configuration. By
    // setting --universe_scope we ensure only the transitioned version exists.
    helper.setUniverseScope("//test:buildme");
    helper.setQuerySettings(Setting.ONLY_TARGET_DEPS, Setting.NO_IMPLICIT_DEPS);
    Set<KeyedConfiguredTarget> result = eval("deps(//test:buildme, 1)");
    assertThat(result).hasSize(2);

    ImmutableList<KeyedConfiguredTarget> stableOrderList = ImmutableList.copyOf(result);
    int myDepIndex = stableOrderList.get(0).getLabel().toString().equals("//test:mydep") ? 0 : 1;
    BuildConfigurationValue myDepConfig = getConfiguration(stableOrderList.get(myDepIndex));
    BuildConfigurationValue stringFlagConfig =
        getConfiguration(stableOrderList.get(1 - myDepIndex));

    // Note: eval() resets the universe scope after each call. We have to xplicitly set it again.
    helper.setUniverseScope("//test:buildme");
    assertThat(eval("config(//test:mydep, " + myDepConfig.checksum() + ")")).hasSize(1);

    helper.setUniverseScope("//test:buildme");
    QueryException e =
        assertThrows(
            QueryException.class,
            () -> eval("config(//test:mydep, " + stringFlagConfig.checksum() + ")"));
    assertThat(e)
        .hasMessageThat()
        .contains("No target (in) //test:mydep could be found in the configuration with checksum");
  }

  @Test
  public void testConfig_configHashPrefix() throws Exception {
    createConfigRulesAndBuild();
    writeFile("mytest/BUILD", "simple_rule(name = 'mytarget')");

    Set<KeyedConfiguredTarget> result = eval("//mytest:mytarget");
    String configHash = getConfiguration(Iterables.getOnlyElement(result)).checksum();
    String hashPrefix = configHash.substring(0, configHash.length() / 2);

    Set<KeyedConfiguredTarget> resultFromPrefix =
        eval("config(//mytest:mytarget," + hashPrefix + ")");
    assertThat(resultFromPrefix).containsExactlyElementsIn(result);
  }

  @Test
  public void testConfig_configHashUnknownPrefix() throws Exception {
    createConfigRulesAndBuild();
    writeFile("mytest/BUILD", "simple_rule(name = 'mytarget')");

    Set<KeyedConfiguredTarget> result = eval("//mytest:mytarget");
    String configHash = getConfiguration(Iterables.getOnlyElement(result)).checksum();
    String rightPrefix = configHash.substring(0, configHash.length() / 2);
    char lastChar = rightPrefix.charAt(rightPrefix.length() - 1);
    String wrongPrefix = rightPrefix.substring(0, rightPrefix.length() - 1) + (lastChar + 1);

    QueryException e =
        assertThrows(
            QueryException.class, () -> eval("config(//mytest:mytarget," + wrongPrefix + ")"));
    assertConfigurableQueryCode(
        e.getFailureDetail(), ConfigurableQuery.Code.INCORRECT_CONFIG_ARGUMENT_ERROR);
    assertThat(e)
        .hasMessageThat()
        .contains("config()'s second argument must identify a unique configuration");
  }

  @Test
  public void testConfig_exprArgumentFailure() throws Exception {
    writeFile("test/BUILD", "java_library(name='my_java',", "  srcs = ['foo.java'],", ")");

    EvalThrowsResult evalThrowsResult =
        evalThrows(
            "config(filter(\"??not-a-valid-regex\", //test:foo.java), null)",
            /*unconditionallyThrows=*/ true);
    assertThat(evalThrowsResult.getMessage())
        .startsWith("illegal 'filter' pattern regexp '??not-a-valid-regex'");
    assertThat(evalThrowsResult.getFailureDetail().hasQuery()).isTrue();
    assertThat(evalThrowsResult.getFailureDetail().getQuery().getCode())
        .isEqualTo(Code.SYNTAX_ERROR);
  }

  @Test
  public void testExecTransitionNotFilteredByNoHostDeps() throws Exception {
    createConfigRulesAndBuild();
    helper.setQuerySettings(Setting.ONLY_TARGET_DEPS, Setting.NO_IMPLICIT_DEPS);
    assertThat(evalToListOfStrings("deps(//test:my_rule)"))
        .containsExactly("//test:my_rule", "//test:target_dep", "//test:dep");
  }

  @Test
  public void testRecursiveTargetPatternNeverThrowsError() throws Exception {
    Path parent =
        getHelper()
            .getScratch()
            .file("parent/BUILD", "sh_library(name = 'parent')")
            .getParentDirectory();
    Path child = parent.getRelative("child");
    child.createDirectory();
    Path badBuild = child.getRelative("BUILD");
    badBuild.createSymbolicLink(badBuild);

    helper.setKeepGoing(true);
    assertThat(eval("//parent:all")).isEqualTo(eval("//parent:parent"));

    helper.setKeepGoing(false);
    getHelper().turnOffFailFast();
    TargetParsingException e =
        assertThrows(TargetParsingException.class, () -> eval("//parent/..."));
    assertThat(e)
        .hasMessageThat()
        .isEqualTo(
            "error loading package under directory 'parent': no such package 'parent/child':"
                + " Symlink cycle detected while trying to find BUILD file"
                + " /workspace/parent/child/BUILD");
    assertThat(e.getDetailedExitCode().getFailureDetail().getPackageLoading().getCode())
        .isEqualTo(FailureDetails.PackageLoading.Code.SYMLINK_CYCLE_OR_INFINITE_EXPANSION);
  }

  // Regression test for b/175739699
  @Test
  public void testRecursiveTargetPatternOutsideOfScopeFailsGracefully() throws Exception {
    writeFile("testA/BUILD", "sh_library(name = 'testA')");
    writeFile("testB/BUILD", "sh_library(name = 'testB')");
    writeFile("testB/testC/BUILD", "sh_library(name = 'testC')");
    helper.setUniverseScope("//testA");
    QueryException e = assertThrows(QueryException.class, () -> eval("//testB/..."));
    assertThat(e.getFailureDetail().getQuery().getCode())
        .isEqualTo(Query.Code.TARGET_NOT_IN_UNIVERSE_SCOPE);
    assertThat(e).hasMessageThat().contains("package is not in scope");
  }

  @Override
  @Test
  public void testMultipleTopLevelConfigurations_nullConfigs() throws Exception {
    writeFile("test/BUILD", "java_library(name='my_java',", "  srcs = ['foo.java'],", ")");

    Set<KeyedConfiguredTarget> result = eval("//test:my_java+//test:foo.java");

    assertThat(result).hasSize(2);

    Iterator<KeyedConfiguredTarget> resultIterator = result.iterator();
    KeyedConfiguredTarget first = resultIterator.next();
    if (first.getLabel().toString().equals("//test:foo.java")) {
      assertThat(getConfiguration(first)).isNull();
      assertThat(getConfiguration(resultIterator.next())).isNotNull();
    } else {
      assertThat(getConfiguration(first)).isNotNull();
      assertThat(getConfiguration(resultIterator.next())).isNull();
    }
  }

  @Test
  public void testSomePath_depInCustomConfiguration() throws Exception {
    createConfigTransitioningRuleClass();
    writeFile(
        "test/BUILD",
        "load('//test:rules.bzl', 'rule_with_deps_transition', 'simple_rule', 'string_flag')",
        "string_flag(",
        "    name = 'my_flag',",
        "    build_setting_default = '')",
        "rule_with_deps_transition(",
        "    name = 'buildme',",
        "    deps = [':mydep'])",
        "simple_rule(name = 'mydep')");

    // If we don't set --universe_scope=//test:buildme, then cquery builds both //test:buildme and
    // //test:mydep as top-level targets. That means //test:mydep will have two configured targets:
    // one under the transitioned configuration and one under the top-level configuration. In these
    // cases cquery prefers the top-level configured one, which won't produce a match since that's
    // not the one down this dependency path.
    helper.setUniverseScope("//test:buildme");
    Set<KeyedConfiguredTarget> result = eval("somepath(//test:buildme, //test:mydep)");
    assertThat(result.stream().map(kct -> kct.getLabel().toString()).collect(Collectors.toList()))
        .contains("//test:mydep");
  }

  /** Return an empty BuildOptions for testing fragment dropping. * */
  public static class RemoveTestOptionsTransition implements PatchTransition {
    @Override
    public ImmutableSet<Class<? extends FragmentOptions>> requiresOptionFragments() {
      return ImmutableSet.of(TestOptions.class);
    }

    @Override
    public BuildOptions patch(BuildOptionsView options, EventHandler eventHandler) {
      BuildOptions.Builder builder = BuildOptions.builder();
      for (FragmentOptions option : options.underlying().getNativeOptions()) {
        if (!(option instanceof TestOptions)) {
          builder.addFragmentOptions(option);
        }
      }
      // This does not copy over Starlark options!!
      return builder.build();
    }
  }

  @Test
  public void testQueryHandlesDroppingFragments() throws Exception {
    MockRule ruleDropOptions =
        () ->
            MockRule.define(
                "rule_drop_options",
                attr("dep", LABEL)
                    .allowedFileTypes(FileTypeSet.ANY_FILE)
                    .cfg(TransitionFactories.of(new RemoveTestOptionsTransition())));
    MockRule simpleRule =
        () ->
            MockRule.define(
                "simple_rule", attr("deps", LABEL_LIST).allowedFileTypes(FileTypeSet.ANY_FILE));

    helper.useRuleClassProvider(setRuleClassProviders(ruleDropOptions, simpleRule).build());
    writeFile(
        "test/BUILD",
        "rule_drop_options(name = 'top', dep = ':foo')",
        "simple_rule(name='foo', deps = [':bar'])",
        "simple_rule(name='bar')");

    Set<KeyedConfiguredTarget> result =
        eval("somepath(//test:top, filter(//test:bar, deps(//test:top)))");
    assertThat(result).isNotEmpty();
  }

  @Test
  public void testLabelExpressionsMatchesAllConfiguredTargetsWithLabel() throws Exception {
    createConfigTransitioningRuleClass();
    writeFile(
        "test/BUILD",
        "load('//test:rules.bzl', 'rule_with_deps_transition', 'simple_rule', 'string_flag')",
        "string_flag(",
        "    name = 'my_flag',",
        "    build_setting_default = '')",
        "rule_with_deps_transition(",
        "    name = 'transitioner',",
        "    deps = [':simple'])",
        "simple_rule(name = 'simple')");

    helper.setUniverseScope("//test:transitioner,//test:simple");
    Set<KeyedConfiguredTarget> result = eval("//test:simple");
    assertThat(result.size()).isEqualTo(2);
  }

  @Test
  public void testConfigFunctionRefinesMultipleMatches() throws Exception {
    // Peer to testLabelExpressionsMatchesAllConfiguredTargetsWithLabel. The point of that test is
    // to show "cquery //foo:bar" might return multiple configured targets. The point of this test
    // is to show that config() can refine the same query to a specific one.
    createConfigTransitioningRuleClass();
    writeFile(
        "test/BUILD",
        "load('//test:rules.bzl', 'rule_with_deps_transition', 'simple_rule', 'string_flag')",
        "string_flag(",
        "    name = 'my_flag',",
        "    build_setting_default = '')",
        "rule_with_deps_transition(",
        "    name = 'transitioner',",
        "    deps = [':simple'])",
        "simple_rule(name = 'simple')");

    helper.setUniverseScope("//test:transitioner,//test:simple");
    Set<KeyedConfiguredTarget> result = eval("config(//test:simple, target)");
    assertThat(result.size()).isEqualTo(1);
  }
}
