// Copyright 2015 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.packages;

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

import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
import com.google.devtools.build.lib.cmdline.Label;
import com.google.devtools.build.lib.cmdline.PackageIdentifier;
import com.google.devtools.build.lib.cmdline.RepositoryMapping;
import com.google.devtools.build.lib.packages.BuildType.Selector;
import com.google.devtools.build.lib.packages.Type.ConversionException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import net.starlark.java.eval.Dict;
import net.starlark.java.eval.EvalException;
import net.starlark.java.eval.Starlark;
import net.starlark.java.eval.StarlarkInt;
import net.starlark.java.eval.StarlarkList;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.JUnit4;

/** Test of type-conversions for build-specific types. */
@RunWith(JUnit4.class)
public final class BuildTypeTest {

  private final LabelConverter labelConverter =
      new LabelConverter(
          PackageIdentifier.createInMainRepo("quux"), RepositoryMapping.ALWAYS_FALLBACK);

  @Test
  public void testKeepsDictOrdering() throws Exception {
    Map<Object, String> input = new ImmutableMap.Builder<Object, String>()
        .put("c", "//c")
        .put("b", "//b")
        .put("a", "//a")
        .put("f", "//f")
        .put("e", "//e")
        .put("d", "//d")
        .build();

    assertThat(BuildType.LABEL_DICT_UNARY.convert(input, null, labelConverter).keySet())
        .containsExactly("c", "b", "a", "f", "e", "d")
        .inOrder();
  }

  @Test
  public void testLabelKeyedStringDictConvertsToMapFromLabelToString() throws Exception {
    Map<Object, String> input =
        new ImmutableMap.Builder<Object, String>()
            .put("//absolute:label", "absolute value")
            .put(":relative", "theory of relativity")
            .put("nocolon", "colonial times")
            .put("//current/package:explicit", "explicit content")
            .put(Label.parseCanonical("//i/was/already/a/label"), "and that's okay")
            .build();
    LabelConverter converter =
        new LabelConverter(
            PackageIdentifier.parse("//current/package"), RepositoryMapping.ALWAYS_FALLBACK);

    Map<Label, String> expected =
        new ImmutableMap.Builder<Label, String>()
            .put(Label.parseCanonical("//absolute:label"), "absolute value")
            .put(Label.parseCanonical("//current/package:relative"), "theory of relativity")
            .put(Label.parseCanonical("//current/package:nocolon"), "colonial times")
            .put(Label.parseCanonical("//current/package:explicit"), "explicit content")
            .put(Label.parseCanonical("//i/was/already/a/label"), "and that's okay")
            .build();

    assertThat(BuildType.LABEL_KEYED_STRING_DICT.convert(input, null, converter))
        .containsExactlyEntriesIn(expected);
  }

  @Test
  public void testLabelKeyedStringDictConvertingStringShouldFail() throws Exception {
    ConversionException expected =
        assertThrows(
            ConversionException.class,
            () ->
                BuildType.LABEL_KEYED_STRING_DICT.convert(
                    "//actually/a:label", null, labelConverter));
    assertThat(expected)
        .hasMessageThat()
        .isEqualTo(
            "expected value of type 'dict(label, string)', "
                + "but got \"//actually/a:label\" (string)");
  }

  @Test
  public void testLabelKeyedStringDictConvertingListShouldFail() throws Exception {
    ConversionException expected =
        assertThrows(
            ConversionException.class,
            () ->
                BuildType.LABEL_KEYED_STRING_DICT.convert(
                    ImmutableList.of("//actually/a:label"), null, labelConverter));
    assertThat(expected)
        .hasMessageThat()
        .isEqualTo(
            "expected value of type 'dict(label, string)', "
                + "but got [\"//actually/a:label\"] (List)");
  }

  @Test
  public void testLabelKeyedStringDictConvertingMapWithNonStringKeyShouldFail() {
    ConversionException expected =
        assertThrows(
            ConversionException.class,
            () ->
                BuildType.LABEL_KEYED_STRING_DICT.convert(
                    ImmutableMap.of(StarlarkInt.of(1), "OK"), null, labelConverter));
    assertThat(expected)
        .hasMessageThat()
        .isEqualTo("expected value of type 'string' for dict key element, but got 1 (int)");
  }

  @Test
  public void testLabelKeyedStringDictConvertingMapWithNonStringValueShouldFail() {
    ConversionException expected =
        assertThrows(
            ConversionException.class,
            () ->
                BuildType.LABEL_KEYED_STRING_DICT.convert(
                    ImmutableMap.of("//actually/a:label", StarlarkInt.of(3)),
                    null,
                    labelConverter));
    assertThat(expected)
        .hasMessageThat()
        .isEqualTo("expected value of type 'string' for dict value element, but got 3 (int)");
  }

  @Test
  public void testLabelKeyedStringDictConvertingMapWithInvalidLabelKeyShouldFail() {
    ConversionException expected =
        assertThrows(
            ConversionException.class,
            () ->
                BuildType.LABEL_KEYED_STRING_DICT.convert(
                    ImmutableMap.of("//uplevel/references/are:../../forbidden", "OK"),
                    null,
                    labelConverter));
    assertThat(expected)
        .hasMessageThat()
        .isEqualTo(
            "invalid label '//uplevel/references/are:../../forbidden' in "
                + "dict key element: invalid target name '../../forbidden': "
                + "target names may not contain up-level references '..'");
  }

  @Test
  public void testLabelKeyedStringDictConvertingMapWithMultipleEquivalentKeysShouldFail()
      throws Exception {
    LabelConverter converter =
        new LabelConverter(
            PackageIdentifier.parse("//current/package"), RepositoryMapping.ALWAYS_FALLBACK);
    Map<String, String> input = new ImmutableMap.Builder<String, String>()
        .put(":reference", "value1")
        .put("//current/package:reference", "value2")
        .build();
    ConversionException expected =
        assertThrows(
            ConversionException.class,
            () -> BuildType.LABEL_KEYED_STRING_DICT.convert(input, null, converter));
    assertThat(expected)
        .hasMessageThat()
        .isEqualTo(
            "duplicate labels: //current/package:reference "
                + "(as [\":reference\", \"//current/package:reference\"])");
  }

  @Test
  public void testLabelKeyedStringDictConvertingMapWithMultipleSetsOfEquivalentKeysShouldFail()
      throws Exception {
    LabelConverter converter =
        new LabelConverter(
            PackageIdentifier.parse("//current/rule"), RepositoryMapping.ALWAYS_FALLBACK);
    Map<String, String> input = new ImmutableMap.Builder<String, String>()
        .put(":rule", "first set")
        .put("//current/rule:rule", "also first set")
        .put("//other/package:package", "interrupting rule")
        .put("//other/package", "interrupting rule's friend")
        .put("//current/rule", "part of first set but non-contiguous in iteration order")
        .put("//not/involved/in/any:collisions", "same value")
        .put("//also/not/involved/in/any:collisions", "same value")
        .build();
    ConversionException expected =
        assertThrows(
            ConversionException.class,
            () -> BuildType.LABEL_KEYED_STRING_DICT.convert(input, null, converter));
    assertThat(expected)
        .hasMessageThat()
        .isEqualTo(
            "duplicate labels: //current/rule:rule "
                + "(as [\":rule\", \"//current/rule:rule\", \"//current/rule\"]), "
                + "//other/package:package "
                + "(as [\"//other/package:package\", \"//other/package\"])");
  }

  @Test
  public void testLabelKeyedStringDictErrorConvertingMapWithMultipleEquivalentKeysIncludesContext()
      throws Exception {
    LabelConverter converter =
        new LabelConverter(
            PackageIdentifier.parse("//current/package"), RepositoryMapping.ALWAYS_FALLBACK);
    Map<String, String> input = new ImmutableMap.Builder<String, String>()
        .put(":reference", "value1")
        .put("//current/package:reference", "value2")
        .build();
    ConversionException expected =
        assertThrows(
            ConversionException.class,
            () -> BuildType.LABEL_KEYED_STRING_DICT.convert(input, "flag map", converter));
    assertThat(expected)
        .hasMessageThat()
        .isEqualTo(
            "duplicate labels in flag map: //current/package:reference "
                + "(as [\":reference\", \"//current/package:reference\"])");
  }

  @Test
  public void testLabelKeyedStringDictCollectLabels() throws Exception {
    Map<Label, String> input =
        new ImmutableMap.Builder<Label, String>()
            .put(Label.parseCanonical("//absolute:label"), "absolute value")
            .put(Label.parseCanonical("//current/package:relative"), "theory of relativity")
            .put(Label.parseCanonical("//current/package:nocolon"), "colonial times")
            .put(Label.parseCanonical("//current/package:explicit"), "explicit content")
            .put(Label.parseCanonical("//i/was/already/a/label"), "and that's okay")
            .build();

    ImmutableList<Label> expected =
        ImmutableList.of(
            Label.parseCanonical("//absolute:label"),
            Label.parseCanonical("//current/package:relative"),
            Label.parseCanonical("//current/package:nocolon"),
            Label.parseCanonical("//current/package:explicit"),
            Label.parseCanonical("//i/was/already/a/label"));

    assertThat(collectLabels(BuildType.LABEL_KEYED_STRING_DICT, input))
        .containsExactlyElementsIn(expected);
  }


  /**
   * Tests basic {@link Selector} functionality.
   */
  @Test
  public void testSelector() throws Exception {
    ImmutableMap<String, String> input = ImmutableMap.of(
        "//conditions:a", "//a:a",
        "//conditions:b", "//b:b",
        Selector.DEFAULT_CONDITION_KEY, "//d:d");
    Selector<Label> selector = new Selector<>(input, null, labelConverter, BuildType.LABEL);
    assertThat(selector.getOriginalType()).isEqualTo(BuildType.LABEL);

    Map<Label, Label> expectedMap =
        ImmutableMap.of(
            Label.parseCanonical("//conditions:a"),
            Label.create("@//a", "a"),
            Label.parseCanonical("//conditions:b"),
            Label.create("@//b", "b"),
            Label.parseCanonical(Selector.DEFAULT_CONDITION_KEY),
            Label.create("@//d", "d"));
    assertThat(selector.mapCopy()).isEqualTo(expectedMap);
  }

  /**
   * Tests that creating a {@link Selector} over a mismatching native type triggers an
   * exception.
   */
  @Test
  public void testSelectorWrongType() throws Exception {
    ImmutableMap<String, String> input = ImmutableMap.of(
        "//conditions:a", "not a/../label", "//conditions:b", "also not a/../label",
        BuildType.Selector.DEFAULT_CONDITION_KEY, "whatever");
    ConversionException e =
        assertThrows(
            ConversionException.class,
            () -> new Selector<>(input, null, labelConverter, BuildType.LABEL));
    assertThat(e).hasMessageThat().contains("invalid label 'not a/../label'");
  }

  /** Tests that non-label selector keys trigger an exception. */
  @Test
  public void testSelectorKeyIsNotALabel() {
    ImmutableMap<String, String> input = ImmutableMap.of(
        "not a/../label", "//a:a",
        BuildType.Selector.DEFAULT_CONDITION_KEY, "whatever");
    ConversionException e =
        assertThrows(
            ConversionException.class,
            () -> new Selector<>(input, null, labelConverter, BuildType.LABEL));
    assertThat(e).hasMessageThat().contains("invalid label 'not a/../label'");
  }

  /**
   * Tests that {@link Selector} correctly references its default value.
   */
  @Test
  public void testSelectorDefault() throws Exception {
    ImmutableMap<String, String> input = ImmutableMap.of(
        "//conditions:a", "//a:a",
        "//conditions:b", "//b:b",
        BuildType.Selector.DEFAULT_CONDITION_KEY, "//d:d");
    Selector<Label> selector = new Selector<>(input, null, labelConverter, BuildType.LABEL);
    assertThat(selector.hasDefault()).isTrue();
    assertThat(selector.getDefault()).isEqualTo(Label.create("@//d", "d"));
  }

  @Test
  public void testSelectorDefault_null() throws Exception {
    ImmutableMap<String, Object> input =
        ImmutableMap.of(
            "//conditions:a", "//a:a", BuildType.Selector.DEFAULT_CONDITION_KEY, Starlark.NONE);
    Selector<Label> selector = new Selector<>(input, null, labelConverter, BuildType.LABEL);
    assertThat(selector.hasDefault()).isTrue();
    assertThat(selector.isUnconditional()).isFalse();
    assertThat(selector.getDefault()).isNull();
  }

  @Test
  public void testSelectorDefault_null_singleton() throws Exception {
    ImmutableMap<String, Object> input =
        ImmutableMap.of(BuildType.Selector.DEFAULT_CONDITION_KEY, Starlark.NONE);
    Selector<Label> selector = new Selector<>(input, null, labelConverter, BuildType.LABEL);
    assertThat(selector.hasDefault()).isTrue();
    assertThat(selector.isUnconditional()).isTrue();
    assertThat(selector.getDefault()).isNull();
  }

  @Test
  public void testSelectorList() throws Exception {
    Object selector1 = new SelectorValue(ImmutableMap.of("//conditions:a",
        ImmutableList.of("//a:a"), "//conditions:b", ImmutableList.of("//b:b")), "");
    Object selector2 = new SelectorValue(ImmutableMap.of("//conditions:c",
        ImmutableList.of("//c:c"), "//conditions:d", ImmutableList.of("//d:d")), "");
    BuildType.SelectorList<List<Label>> selectorList =
        new BuildType.SelectorList<>(
            ImmutableList.of(selector1, selector2), null, labelConverter, BuildType.LABEL_LIST);

    assertThat(selectorList.getOriginalType()).isEqualTo(BuildType.LABEL_LIST);
    assertThat(selectorList.getKeyLabels())
        .containsExactly(
            Label.parseCanonical("//conditions:a"),
            Label.parseCanonical("//conditions:b"),
            Label.parseCanonical("//conditions:c"),
            Label.parseCanonical("//conditions:d"));

    List<Selector<List<Label>>> selectors = selectorList.getSelectors();
    assertThat(selectors.get(0).mapCopy())
        .containsExactly(
            Label.parseCanonical("//conditions:a"),
            ImmutableList.of(Label.create("@//a", "a")),
            Label.parseCanonical("//conditions:b"),
            ImmutableList.of(Label.create("@//b", "b")));
    assertThat(selectors.get(1).mapCopy())
        .containsExactly(
            Label.parseCanonical("//conditions:c"),
            ImmutableList.of(Label.create("@//c", "c")),
            Label.parseCanonical("//conditions:d"),
            ImmutableList.of(Label.create("@//d", "d")));
  }

  @Test
  public void testSelectorDict() throws Exception {
    Object selector1 =
        new SelectorValue(
            ImmutableMap.of(
                "//conditions:a",
                ImmutableMap.of("//a:a", "a"),
                "//conditions:b",
                ImmutableMap.of("//b:b", "b")),
            "");
    Object selector2 =
        new SelectorValue(
            ImmutableMap.of(
                "//conditions:c",
                ImmutableMap.of("//c:c", "c"),
                "//conditions:d",
                ImmutableMap.of("//d:d", "d")),
            "");
    BuildType.SelectorList<Map<Label, String>> selectorList =
        new BuildType.SelectorList<>(
            ImmutableList.of(selector1, selector2),
            null,
            labelConverter,
            BuildType.LABEL_KEYED_STRING_DICT);

    assertThat(selectorList.getOriginalType()).isEqualTo(BuildType.LABEL_KEYED_STRING_DICT);
    assertThat(selectorList.getKeyLabels())
        .containsExactly(
            Label.parseCanonical("//conditions:a"),
            Label.parseCanonical("//conditions:b"),
            Label.parseCanonical("//conditions:c"),
            Label.parseCanonical("//conditions:d"));

    List<Selector<Map<Label, String>>> selectors = selectorList.getSelectors();
    assertThat(selectors.get(0).mapCopy())
        .containsExactly(
            Label.parseCanonical("//conditions:a"),
            ImmutableMap.of(Label.create("@//a", "a"), "a"),
            Label.parseCanonical("//conditions:b"),
            ImmutableMap.of(Label.create("@//b", "b"), "b"));
  }

  @Test
  public void testSelectorListMixedTypes() throws Exception {
    Object selector1 =
        new SelectorValue(ImmutableMap.of("//conditions:a", ImmutableList.of("//a:a")), "");
    Object selector2 =
        new SelectorValue(ImmutableMap.of("//conditions:b", "//b:b"), "");
    ConversionException e =
        assertThrows(
            ConversionException.class,
            () ->
                new BuildType.SelectorList<>(
                    ImmutableList.of(selector1, selector2),
                    null,
                    labelConverter,
                    BuildType.LABEL_LIST));
    assertThat(e).hasMessageThat().contains("expected value of type 'list(label)'");
  }

  @Test
  public void testSelectorList_concatenate_selectorList() throws Exception {
    SelectorList selectorList =
        SelectorList.of(
            new SelectorValue(ImmutableMap.of("//conditions:a", ImmutableList.of("//a:a")), ""));
    List<String> list = ImmutableList.of("//a:a", "//b:b");

    // Creating a SelectorList from a SelectorList and a list should work properly.
    SelectorList result = SelectorList.concat(selectorList, list);
    assertThat(result).isNotNull();
    assertThat(result.getType()).isAssignableTo(List.class);
  }

  @Test
  public void testSelectorList_concatenate_selectorValue() throws Exception {
    SelectorValue selectorValue =
        new SelectorValue(ImmutableMap.of("//conditions:a", ImmutableList.of("//a:a")), "");
    List<String> list = ImmutableList.of("//a:a", "//b:b");

    // Creating a SelectorList from a SelectorValue and a list should work properly.
    SelectorList result = SelectorList.concat(selectorValue, list);
    assertThat(result).isNotNull();
    assertThat(result.getType()).isAssignableTo(List.class);
  }

  @Test
  public void testSelectorList_concatenate_differentListTypes() throws Exception {
    List<String> list = ImmutableList.of("//a:a", "//b:b");
    List<String> arrayList = new ArrayList<>();
    arrayList.add("//a:a");

    // Creating a SelectorList from two lists of different types should work properly.
    SelectorList result = SelectorList.concat(list, arrayList);
    assertThat(result).isNotNull();
    assertThat(result.getType()).isAssignableTo(List.class);
  }

  @Test
  public void testSelectorList_concatenate_invalidType() throws Exception {
    List<String> list = ImmutableList.of("//a:a", "//b:b");

    // Creating a SelectorList from a list and a non-list should fail.
    assertThrows(EvalException.class, () -> SelectorList.concat(list, "A string"));
  }

  /**
   * Tests that {@link BuildType#selectableConvert} returns either the native type or a selector on
   * that type, in accordance with the provided input.
   */
  @SuppressWarnings({"unchecked", "TruthIncompatibleType"})
  @Test
  public void testSelectableConvert() throws Exception {
    Object nativeInput = Arrays.asList("//a:a1", "//a:a2");
    Object selectableInput =
        SelectorList.of(new SelectorValue(ImmutableMap.of(
            "//conditions:a", nativeInput,
            BuildType.Selector.DEFAULT_CONDITION_KEY, nativeInput), ""));
    List<Label> expectedLabels =
        ImmutableList.of(Label.create("@//a", "a1"), Label.create("@//a", "a2"));

    // Conversion to direct type:
    Object converted =
        BuildType.selectableConvert(BuildType.LABEL_LIST, nativeInput, null, labelConverter);
    assertThat(converted instanceof List<?>).isTrue();
    assertThat((List<Label>) converted).containsExactlyElementsIn(expectedLabels);

    // Conversion to selectable type:
    converted =
        BuildType.selectableConvert(BuildType.LABEL_LIST, selectableInput, null, labelConverter);
    BuildType.SelectorList<?> selectorList = (BuildType.SelectorList<?>) converted;
    assertThat(((Selector<Label>) selectorList.getSelectors().get(0)).mapCopy())
        .containsExactly(
            Label.parseCanonical("//conditions:a"),
            expectedLabels,
            Label.parseCanonical(Selector.DEFAULT_CONDITION_KEY),
            expectedLabels);
  }

  @Test
  @SuppressWarnings({"unchecked"})
  public void testCopyAndLiftStarlarkList() throws Exception {
    Object starlarkList = StarlarkList.immutableOf("//a:a1", "//a:a2");
    ImmutableList<Label> expectedLabels =
        ImmutableList.of(Label.create("@//a", "a1"), Label.create("@//a", "a2"));

    Object converted =
        BuildType.copyAndLiftStarlarkValue(
            "ruleClass",
            Attribute.attr("attrName", BuildType.LABEL_LIST).allowedFileTypes().build(),
            starlarkList,
            labelConverter);

    assertThat(converted instanceof StarlarkList<?>).isTrue();
    assertThat((List<Label>) converted).containsExactlyElementsIn(expectedLabels);
  }

  @Test
  public void testCopyAndLiftStarlarkDict() throws Exception {
    Object inputDict = Dict.immutableCopyOf(ImmutableMap.of("a", "b", "c", "d"));

    Object converted =
        BuildType.copyAndLiftStarlarkValue(
            "ruleClass",
            Attribute.attr("attrName", Types.STRING_DICT).build(),
            inputDict,
            labelConverter);

    assertThat(converted instanceof Dict).isTrue();
    assertThat(converted).isEqualTo(inputDict);
    assertThat(converted).isNotSameInstanceAs(inputDict);
  }

  @Test
  public void testCopyAndLiftSelectableStarlarkValue() throws Exception {
    Object starlarkList = StarlarkList.immutableOf("//a:a1", "//a:a2");
    Object selectableInput =
        SelectorList.of(
            new SelectorValue(
                ImmutableMap.of(
                    "//conditions:a",
                    starlarkList,
                    BuildType.Selector.DEFAULT_CONDITION_KEY,
                    starlarkList),
                ""));
    StarlarkList<Label> expectedLabels =
        StarlarkList.immutableOf(Label.create("@//a", "a1"), Label.create("@//a", "a2"));

    Object converted =
        BuildType.copyAndLiftStarlarkValue(
            "ruleClass",
            Attribute.attr("attrName", BuildType.LABEL_LIST).allowedFileTypes().build(),
            selectableInput,
            labelConverter);

    assertThat(converted instanceof SelectorList).isTrue();
    SelectorList selectorList = (SelectorList) converted;
    assertThat(((SelectorValue) selectorList.getElements().get(0)).getDictionary())
        .containsExactly(
            Label.parseCanonical("//conditions:a"),
            expectedLabels,
            Label.parseCanonical(Selector.DEFAULT_CONDITION_KEY),
            expectedLabels);
  }

  /**
   * Tests that {@link com.google.devtools.build.lib.packages.Type#convert} fails on selector
   * inputs.
   */
  @Test
  public void testConvertDoesNotAcceptSelectables() throws Exception {
    Object selectableInput =
        SelectorList.of(
            new SelectorValue(
                ImmutableMap.of("//conditions:a", Arrays.asList("//a:a1", "//a:a2")), ""));
    ConversionException e =
        assertThrows(
            ConversionException.class,
            () -> BuildType.LABEL_LIST.convert(selectableInput, null, labelConverter));
    assertThat(e).hasMessageThat().contains("expected value of type 'list(label)'");
  }

  /** Test for the default condition key label which is not intended to map to an actual target. */
  @Test
  public void testDefaultConditionLabel() throws Exception {
    assertThat(BuildType.Selector.isDefaultConditionLabel(Label.parseCanonical("//condition:a")))
        .isFalse();
    assertThat(
            BuildType.Selector.isDefaultConditionLabel(
                Label.parseCanonical(Selector.DEFAULT_CONDITION_KEY)))
        .isTrue();
  }

  @Test
  public void testUnconditionalSelects() throws Exception {
    assertThat(
            new Selector<>(
                    ImmutableMap.of("//conditions:a", "//a:a"),
                    null,
                    labelConverter,
                    BuildType.LABEL)
                .isUnconditional())
        .isFalse();
    assertThat(
            new Selector<>(
                    ImmutableMap.of(
                        "//conditions:a",
                        "//a:a",
                        BuildType.Selector.DEFAULT_CONDITION_KEY,
                        "//b:b"),
                    null,
                    labelConverter,
                    BuildType.LABEL)
                .isUnconditional())
        .isFalse();
    assertThat(
            new Selector<>(
                    ImmutableMap.of(BuildType.Selector.DEFAULT_CONDITION_KEY, "//b:b"),
                    null,
                    labelConverter,
                    BuildType.LABEL)
                .isUnconditional())
        .isTrue();
  }

  private static <T> ImmutableList<Label> collectLabels(Type<T> type, T value) {
    ImmutableList.Builder<Label> result = ImmutableList.builder();
    type.visitLabels((label, dummy) -> result.add(label), value, /*context=*/ null);
    return result.build();
  }
}
