// 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 com.google.common.truth.Truth.assertWithMessage;
import static com.google.devtools.build.lib.analysis.testing.ExecGroupSubject.assertThat;
import static com.google.devtools.build.lib.analysis.testing.RuleClassSubject.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.BuildType.NODEP_LABEL;
import static com.google.devtools.build.lib.packages.BuildType.OUTPUT_LIST;
import static com.google.devtools.build.lib.packages.ImplicitOutputsFunction.substitutePlaceholderIntoTemplate;
import static com.google.devtools.build.lib.packages.RuleClass.Builder.STARLARK_BUILD_SETTING_DEFAULT_ATTR_NAME;
import static com.google.devtools.build.lib.packages.RuleClass.NO_EXTERNAL_BINDINGS;
import static com.google.devtools.build.lib.packages.RuleClass.NO_TOOLCHAINS_TO_REGISTER;
import static com.google.devtools.build.lib.packages.Type.BOOLEAN;
import static com.google.devtools.build.lib.packages.Type.INTEGER;
import static com.google.devtools.build.lib.packages.Type.STRING;
import static com.google.devtools.build.lib.packages.Types.STRING_LIST;
import static org.junit.Assert.assertThrows;
import static org.junit.Assert.fail;

import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Iterables;
import com.google.common.collect.Lists;
import com.google.devtools.build.lib.analysis.config.Fragment;
import com.google.devtools.build.lib.analysis.config.ToolchainTypeRequirement;
import com.google.devtools.build.lib.analysis.config.transitions.TransitionFactory;
import com.google.devtools.build.lib.cmdline.Label;
import com.google.devtools.build.lib.cmdline.LabelSyntaxException;
import com.google.devtools.build.lib.cmdline.PackageIdentifier;
import com.google.devtools.build.lib.cmdline.RepositoryMapping;
import com.google.devtools.build.lib.events.Event;
import com.google.devtools.build.lib.events.EventCollector;
import com.google.devtools.build.lib.events.EventKind;
import com.google.devtools.build.lib.packages.Attribute.StarlarkComputedDefaultTemplate.CannotPrecomputeDefaultsException;
import com.google.devtools.build.lib.packages.Attribute.ValidityPredicate;
import com.google.devtools.build.lib.packages.ImplicitOutputsFunction.SafeImplicitOutputsFunction;
import com.google.devtools.build.lib.packages.RuleClass.Builder.RuleClassType;
import com.google.devtools.build.lib.packages.RuleClass.ConfiguredTargetFactory;
import com.google.devtools.build.lib.packages.RuleClass.ToolchainResolutionMode;
import com.google.devtools.build.lib.packages.RuleFactory.BuildLangTypedAttributeValuesMap;
import com.google.devtools.build.lib.packages.util.PackageLoadingTestCase;
import com.google.devtools.build.lib.vfs.Path;
import com.google.devtools.build.lib.vfs.RootedPath;
import com.google.errorprone.annotations.CanIgnoreReturnValue;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.Set;
import javax.annotation.Nullable;
import net.starlark.java.eval.StarlarkFunction;
import net.starlark.java.eval.StarlarkInt;
import net.starlark.java.eval.StarlarkSemantics;
import net.starlark.java.eval.StarlarkThread;
import net.starlark.java.syntax.Location;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.JUnit4;

/** Tests for {@link RuleClass}. */
@RunWith(JUnit4.class)
public final class RuleClassTest extends PackageLoadingTestCase {
  private static final RuleClass.ConfiguredTargetFactory<Object, Object, Exception>
      DUMMY_CONFIGURED_TARGET_FACTORY =
          ruleContext -> {
            throw new IllegalStateException();
          };

  private static final ImmutableList<StarlarkThread.CallStackEntry> DUMMY_STACK =
      ImmutableList.of(
          StarlarkThread.callStackEntry(
              StarlarkThread.TOP_LEVEL, Location.fromFileLineColumn("BUILD", 10, 1)),
          StarlarkThread.callStackEntry("bar", Location.fromFileLineColumn("bar.bzl", 42, 1)),
          StarlarkThread.callStackEntry("rule", Location.BUILTIN));

  private static final class DummyFragment extends Fragment {}

  private static RuleClass createRuleClassA() throws LabelSyntaxException {
    return newRuleClass(
        "ruleA",
        false,
        false,
        false,
        false,
        false,
        false,
        SafeImplicitOutputsFunction.NONE,
        null,
        DUMMY_CONFIGURED_TARGET_FACTORY,
        PredicatesWithMessage.alwaysTrue(),
        AdvertisedProviderSet.EMPTY,
        null,
        ImmutableSet.of(),
        true,
        attr("my-string-attr", STRING).mandatory().build(),
        attr("my-label-attr", LABEL)
            .mandatory()
            .legacyAllowAnyFileType()
            .value(Label.parseCanonical("//default:label"))
            .build(),
        attr("my-labellist-attr", LABEL_LIST).mandatory().legacyAllowAnyFileType().build(),
        attr("my-integer-attr", INTEGER).value(StarlarkInt.of(42)).build(),
        attr("my-string-attr2", STRING).mandatory().value((String) null).build(),
        attr("my-stringlist-attr", STRING_LIST).build(),
        attr("my-sorted-stringlist-attr", STRING_LIST).orderIndependent().build());
  }

  private static RuleClass createRuleClassB(RuleClass ruleClassA) {
    // emulates attribute inheritance
    List<Attribute> attributes = new ArrayList<>(ruleClassA.getAttributes());
    attributes.add(attr("another-string-attr", STRING).mandatory().build());
    return newRuleClass(
        "ruleB",
        false,
        false,
        false,
        false,
        false,
        false,
        SafeImplicitOutputsFunction.NONE,
        null,
        DUMMY_CONFIGURED_TARGET_FACTORY,
        PredicatesWithMessage.alwaysTrue(),
        AdvertisedProviderSet.EMPTY,
        null,
        ImmutableSet.of(),
        true,
        attributes.toArray(new Attribute[0]));
  }

  // Helper method to paper over how some test cases don't supply the mandatory name attribute for
  // historic reasons.
  private static ImmutableMap<String, Object> ensureNameAttrValuePresent(
      Map<String, Object> attrValues) {
    if (attrValues.containsKey("name")) {
      return ImmutableMap.copyOf(attrValues);
    } else {
      return ImmutableMap.<String, Object>builder()
          .putAll(attrValues)
          .put("name", "my-name")
          .buildOrThrow();
    }
  }

  @Test
  public void testRuleClassBasics() throws Exception {
    RuleClass ruleClassA = createRuleClassA();

    assertThat(ruleClassA.getName()).isEqualTo("ruleA");
    assertThat(ruleClassA.getAttributeCount()).isEqualTo(8);

    assertThat(ruleClassA.getAttributeIndex("name")).isEqualTo(0);
    assertThat(ruleClassA.getAttributeIndex("my-string-attr")).isEqualTo(1);
    assertThat(ruleClassA.getAttributeIndex("my-label-attr")).isEqualTo(2);
    assertThat(ruleClassA.getAttributeIndex("my-labellist-attr")).isEqualTo(3);
    assertThat(ruleClassA.getAttributeIndex("my-integer-attr")).isEqualTo(4);
    assertThat(ruleClassA.getAttributeIndex("my-string-attr2")).isEqualTo(5);
    assertThat(ruleClassA.getAttributeIndex("my-stringlist-attr")).isEqualTo(6);
    assertThat(ruleClassA.getAttributeIndex("my-sorted-stringlist-attr")).isEqualTo(7);

    assertThat(ruleClassA.getAttributeByName("name")).isEqualTo(ruleClassA.getAttribute(0));
    assertThat(ruleClassA.getAttributeByName("my-string-attr"))
        .isEqualTo(ruleClassA.getAttribute(1));
    assertThat(ruleClassA.getAttributeByName("my-label-attr"))
        .isEqualTo(ruleClassA.getAttribute(2));
    assertThat(ruleClassA.getAttributeByName("my-labellist-attr"))
        .isEqualTo(ruleClassA.getAttribute(3));
    assertThat(ruleClassA.getAttributeByName("my-integer-attr"))
        .isEqualTo(ruleClassA.getAttribute(4));
    assertThat(ruleClassA.getAttributeByName("my-string-attr2"))
        .isEqualTo(ruleClassA.getAttribute(5));
    assertThat(ruleClassA.getAttributeByName("my-stringlist-attr"))
        .isEqualTo(ruleClassA.getAttribute(6));
    assertThat(ruleClassA.getAttributeByName("my-sorted-stringlist-attr"))
        .isEqualTo(ruleClassA.getAttribute(7));

    // default based on type
    assertThat(ruleClassA.getAttribute(0).getDefaultValue(null)).isEqualTo("");
    assertThat(ruleClassA.getAttribute(1).getDefaultValue(null)).isEqualTo("");
    assertThat(ruleClassA.getAttribute(2).getDefaultValue(null))
        .isEqualTo(Label.parseCanonical("//default:label"));
    assertThat(ruleClassA.getAttribute(3).getDefaultValue(null)).isEqualTo(ImmutableList.of());
    assertThat(ruleClassA.getAttribute(4).getDefaultValue(null)).isEqualTo(StarlarkInt.of(42));
    // default explicitly specified
    assertThat(ruleClassA.getAttribute(5).getDefaultValue(null)).isNull();
    assertThat(ruleClassA.getAttribute(6).getDefaultValue(null)).isEqualTo(ImmutableList.of());
    assertThat(ruleClassA.getAttribute(7).getDefaultValue(null)).isEqualTo(ImmutableList.of());
  }

  @Test
  public void testRuleClassInheritance() throws Exception {
    RuleClass ruleClassA = createRuleClassA();
    RuleClass ruleClassB = createRuleClassB(ruleClassA);

    assertThat(ruleClassB.getName()).isEqualTo("ruleB");
    assertThat(ruleClassB.getAttributeCount()).isEqualTo(9);

    assertThat(ruleClassB.getAttributeIndex("name")).isEqualTo(0);
    assertThat(ruleClassB.getAttributeIndex("my-string-attr")).isEqualTo(1);
    assertThat(ruleClassB.getAttributeIndex("my-label-attr")).isEqualTo(2);
    assertThat(ruleClassB.getAttributeIndex("my-labellist-attr")).isEqualTo(3);
    assertThat(ruleClassB.getAttributeIndex("my-integer-attr")).isEqualTo(4);
    assertThat(ruleClassB.getAttributeIndex("my-string-attr2")).isEqualTo(5);
    assertThat(ruleClassB.getAttributeIndex("my-stringlist-attr")).isEqualTo(6);
    assertThat(ruleClassB.getAttributeIndex("my-sorted-stringlist-attr")).isEqualTo(7);
    assertThat(ruleClassB.getAttributeIndex("another-string-attr")).isEqualTo(8);

    assertThat(ruleClassB.getAttributeByName("name")).isEqualTo(ruleClassB.getAttribute(0));
    assertThat(ruleClassB.getAttributeByName("my-string-attr"))
        .isEqualTo(ruleClassB.getAttribute(1));
    assertThat(ruleClassB.getAttributeByName("my-label-attr"))
        .isEqualTo(ruleClassB.getAttribute(2));
    assertThat(ruleClassB.getAttributeByName("my-labellist-attr"))
        .isEqualTo(ruleClassB.getAttribute(3));
    assertThat(ruleClassB.getAttributeByName("my-integer-attr"))
        .isEqualTo(ruleClassB.getAttribute(4));
    assertThat(ruleClassB.getAttributeByName("my-string-attr2"))
        .isEqualTo(ruleClassB.getAttribute(5));
    assertThat(ruleClassB.getAttributeByName("my-stringlist-attr"))
        .isEqualTo(ruleClassB.getAttribute(6));
    assertThat(ruleClassB.getAttributeByName("my-sorted-stringlist-attr"))
        .isEqualTo(ruleClassB.getAttribute(7));
    assertThat(ruleClassB.getAttributeByName("another-string-attr"))
        .isEqualTo(ruleClassB.getAttribute(8));
  }

  private static final String TEST_PACKAGE_NAME = "testpackage";

  private static final String TEST_RULE_NAME = "my-rule-A";

  private static final int TEST_RULE_DEFINED_AT_LINE = 42;

  private static final String TEST_RULE_LABEL = "@//" + TEST_PACKAGE_NAME + ":" + TEST_RULE_NAME;

  private Path testBuildfilePath;
  private Location testRuleLocation;

  @Before
  public void setRuleLocation() {
    testBuildfilePath = root.getRelative("testpackage/BUILD");
    testRuleLocation =
        Location.fromFileLineColumn(testBuildfilePath.toString(), TEST_RULE_DEFINED_AT_LINE, 0);
  }

  private Package.Builder createDummyPackageBuilder() {
    return packageFactory.newPackageBuilder(
        PackageIdentifier.createInMainRepo(TEST_PACKAGE_NAME),
        RootedPath.toRootedPath(root, testBuildfilePath),
        "TESTING",
        Optional.empty(),
        Optional.empty(),
        StarlarkSemantics.DEFAULT,
        /* repositoryMapping= */ RepositoryMapping.ALWAYS_FALLBACK,
        /* cpuBoundSemaphore= */ null,
        /* generatorMap= */ null,
        /* configSettingVisibilityPolicy= */ null,
        /* globber= */ null);
  }

  @Test
  public void testDuplicatedDeps() throws Exception {
    RuleClass depsRuleClass =
        newRuleClass(
            "ruleDeps",
            false,
            false,
            false,
            false,
            false,
            false,
            SafeImplicitOutputsFunction.NONE,
            null,
            DUMMY_CONFIGURED_TARGET_FACTORY,
            PredicatesWithMessage.alwaysTrue(),
            AdvertisedProviderSet.EMPTY,
            null,
            ImmutableSet.of(),
            true,
            attr("list1", LABEL_LIST).mandatory().legacyAllowAnyFileType().build(),
            attr("list2", LABEL_LIST).mandatory().legacyAllowAnyFileType().build(),
            attr("list3", LABEL_LIST).mandatory().legacyAllowAnyFileType().build());

    // LinkedHashMap -> predictable iteration order for testing
    Map<String, Object> attributeValues = new LinkedHashMap<>();
    attributeValues.put("list1", Lists.newArrayList("//testpackage:dup1", ":dup1", ":nodup"));
    attributeValues.put("list2", Lists.newArrayList(":nodup1", ":nodup2"));
    attributeValues.put("list3", Lists.newArrayList(":dup1", ":dup1", ":dup2", ":dup2"));

    reporter.removeHandler(failFastHandler);
    createRule(depsRuleClass, "depsRule", attributeValues);

    assertThat(eventCollector.count()).isSameInstanceAs(3);
    assertDupError("//testpackage:dup1", "list1", "depsRule");
    assertDupError("//testpackage:dup1", "list3", "depsRule");
    assertDupError("//testpackage:dup2", "list3", "depsRule");
  }

  private void assertDupError(String label, String attrName, String ruleName) {
    assertContainsEvent(String.format("Label '%s' is duplicated in the '%s' attribute of rule '%s'",
        label, attrName, ruleName));
  }

  @Test
  public void testDuplicatedDepsWithinSingleSelectConditionError() throws Exception {
    RuleClass depsRuleClass =
        newRuleClass(
            "ruleDeps",
            false,
            false,
            false,
            false,
            false,
            false,
            SafeImplicitOutputsFunction.NONE,
            null,
            DUMMY_CONFIGURED_TARGET_FACTORY,
            PredicatesWithMessage.alwaysTrue(),
            AdvertisedProviderSet.EMPTY,
            null,
            ImmutableSet.of(),
            true,
            attr("list1", LABEL_LIST).mandatory().legacyAllowAnyFileType().build());

    SelectorList selectorList1 =
        SelectorList.of(
            new SelectorValue(
                ImmutableMap.of("//conditions:a", ImmutableList.of(":dup1", ":dup1")), ""));

    // expect errors
    reporter.removeHandler(failFastHandler);

    Map<String, Object> attributeValues = new HashMap<>();
    attributeValues.put("list1", selectorList1);
    createRule(depsRuleClass, "depsRule", attributeValues);

    assertThat(eventCollector.count()).isSameInstanceAs(1);
    assertDupError("//testpackage:dup1", "list1", "depsRule");
  }

  @Test
  public void testDuplicatedDepsWithinConditionMultipleSelectsErrors() throws Exception {
    RuleClass depsRuleClass =
        newRuleClass(
            "ruleDeps",
            false,
            false,
            false,
            false,
            false,
            false,
            SafeImplicitOutputsFunction.NONE,
            null,
            DUMMY_CONFIGURED_TARGET_FACTORY,
            PredicatesWithMessage.alwaysTrue(),
            AdvertisedProviderSet.EMPTY,
            null,
            ImmutableSet.of(),
            true,
            attr("list1", LABEL_LIST).mandatory().legacyAllowAnyFileType().build());

    SelectorList selectorList1a =
        SelectorList.of(
            new SelectorValue(
                ImmutableMap.of(
                    "//conditions:a", ImmutableList.of(":dup1", "dup1"),
                    "//conditions:b", ImmutableList.of(":nodup1")),
                ""));
    SelectorList selectorList1b =
        SelectorList.of(
            new SelectorValue(
                ImmutableMap.of(
                    "//conditions:c", ImmutableList.of(":dup2", "dup2"),
                    "//conditions:d", ImmutableList.of(":nodup1")),
                ""));
    SelectorList selectorList1 = SelectorList.concat(selectorList1a, selectorList1b);

    // expect errors
    reporter.removeHandler(failFastHandler);

    Map<String, Object> attributeValues = new HashMap<>();
    attributeValues.put("list1", selectorList1);
    createRule(depsRuleClass, "depsRule", attributeValues);

    assertThat(eventCollector.count()).isSameInstanceAs(2);
    assertDupError("//testpackage:dup1", "list1", "depsRule");
    assertDupError("//testpackage:dup2", "list1", "depsRule");
  }

  @Test
  public void testSameDepAcrossMultipleSelectsNoDuplicateNoError() throws Exception {
    RuleClass depsRuleClass =
        newRuleClass(
            "ruleDeps",
            false,
            false,
            false,
            false,
            false,
            false,
            SafeImplicitOutputsFunction.NONE,
            null,
            DUMMY_CONFIGURED_TARGET_FACTORY,
            PredicatesWithMessage.alwaysTrue(),
            AdvertisedProviderSet.EMPTY,
            null,
            ImmutableSet.of(),
            true,
            attr("list1", LABEL_LIST).mandatory().legacyAllowAnyFileType().build());

    // ignore duplicatess across selects where values appear duplicated but are not
    SelectorList selectorList1a =
        SelectorList.of(
            new SelectorValue(
                ImmutableMap.of(
                    "//conditions:a", ImmutableList.of(":nodup1"),
                    "//conditions:b", ImmutableList.of(":nodup2")),
                ""));
    SelectorList selectorList1b =
        SelectorList.of(
            new SelectorValue(
                ImmutableMap.of(
                    "//conditions:a", ImmutableList.of(":nodup2"),
                    "//conditions:b", ImmutableList.of(":nodup1")),
                ""));
    SelectorList selectorList1 = SelectorList.concat(selectorList1a, selectorList1b);

    Map<String, Object> attributeValues = new HashMap<>();
    attributeValues.put("list1", selectorList1);
    createRule(depsRuleClass, "depsRule", attributeValues);
  }

  @Test
  public void testSameDepAcrossMultipleSelectsIsDuplicateNoError() throws Exception {
    RuleClass depsRuleClass =
        newRuleClass(
            "ruleDeps",
            false,
            false,
            false,
            false,
            false,
            false,
            SafeImplicitOutputsFunction.NONE,
            null,
            DUMMY_CONFIGURED_TARGET_FACTORY,
            PredicatesWithMessage.alwaysTrue(),
            AdvertisedProviderSet.EMPTY,
            null,
            ImmutableSet.of(),
            true,
            attr("list1", LABEL_LIST).mandatory().legacyAllowAnyFileType().build());

    // repetition of dup1 is identified at analysis time, not loading time
    SelectorList selectorList1a =
        SelectorList.of(
            new SelectorValue(
                ImmutableMap.of(
                    "//conditions:a", ImmutableList.of(":dup1"),
                    "//conditions:b", ImmutableList.of(":nodup1")),
                ""));
    SelectorList selectorList1b =
        SelectorList.of(
            new SelectorValue(
                ImmutableMap.of(
                    "//conditions:a", ImmutableList.of(":dup1"),
                    "//conditions:b", ImmutableList.of(":nodup2")),
                ""));
    SelectorList selectorList1 = SelectorList.concat(selectorList1a, selectorList1b);

    Map<String, Object> attributeValues = new HashMap<>();
    attributeValues.put("list1", selectorList1);
    createRule(depsRuleClass, "depsRule", attributeValues);
  }

  @Test
  public void testSameDepAcrossConditionsInSelectNoError() throws Exception {
    RuleClass depsRuleClass =
        newRuleClass(
            "ruleDeps",
            false,
            false,
            false,
            false,
            false,
            false,
            SafeImplicitOutputsFunction.NONE,
            null,
            DUMMY_CONFIGURED_TARGET_FACTORY,
            PredicatesWithMessage.alwaysTrue(),
            AdvertisedProviderSet.EMPTY,
            null,
            ImmutableSet.of(),
            true,
            attr("list1", LABEL_LIST).mandatory().legacyAllowAnyFileType().build());

    SelectorList selectorList1 =
        SelectorList.of(
            new SelectorValue(
                ImmutableMap.of(
                    "//conditions:a", ImmutableList.of(":nodup1"),
                    "//conditions:b", ImmutableList.of(":nodup1")),
                ""));

    Map<String, Object> attributeValues = new HashMap<>();
    attributeValues.put("list1", selectorList1);

    createRule(depsRuleClass, "depsRule", attributeValues);
  }

  @Test
  public void testCreateRule() throws Exception {
    RuleClass ruleClassA = createRuleClassA();

    // LinkedHashMap -> predictable iteration order for testing
    Map<String, Object> attributeValues = new LinkedHashMap<>();
    attributeValues.put("my-labellist-attr", "foobar"); // wrong type
    attributeValues.put("bogus-attr", "foobar"); // no such attr
    attributeValues.put("my-stringlist-attr", Arrays.asList("foo", "bar"));

    reporter.removeHandler(failFastHandler);
    EventCollector collector = new EventCollector(EventKind.ERRORS);
    reporter.addHandler(collector);

    Rule rule = createRule(ruleClassA, TEST_RULE_NAME, attributeValues);

    // TODO(blaze-team): (2009) refactor to use assertContainsEvent
    Iterator<String> expectedMessages = Arrays.asList(
        "expected value of type 'list(label)' for attribute 'my-labellist-attr' "
        + "in 'ruleA' rule, but got \"foobar\" (string)",
        "no such attribute 'bogus-attr' in 'ruleA' rule",
        "missing value for mandatory "
        + "attribute 'my-string-attr' in 'ruleA' rule",
        "missing value for mandatory attribute 'my-label-attr' in 'ruleA' rule",
        "missing value for mandatory "
        + "attribute 'my-labellist-attr' in 'ruleA' rule",
        "missing value for mandatory "
        + "attribute 'my-string-attr2' in 'ruleA' rule"
    ).iterator();

    for (Event event : collector) {
      assertThat(event.getLocation().line()).isEqualTo(TEST_RULE_DEFINED_AT_LINE);
      assertThat(event.getLocation().file()).isEqualTo(testBuildfilePath.toString());
      assertThat(event.getMessage())
          .isEqualTo(TEST_RULE_LABEL.substring(1) + ": " + expectedMessages.next());
    }

    // Test basic rule properties:
    assertThat(rule.getRuleClass()).isEqualTo("ruleA");
    assertThat(rule.getName()).isEqualTo(TEST_RULE_NAME);
    assertThat(rule.getLabel().toString()).isEqualTo(TEST_RULE_LABEL.substring(1));

    // Test attribute access:
    AttributeMap attributes = RawAttributeMapper.of(rule);
    assertThat(attributes.get("my-label-attr", BuildType.LABEL).toString())
        .isEqualTo("//default:label");
    assertThat(attributes.get("my-integer-attr", Type.INTEGER).toIntUnchecked()).isEqualTo(42);
    // missing attribute -> default chosen based on type
    assertThat(attributes.get("my-string-attr", Type.STRING)).isEmpty();
    assertThat(attributes.get("my-labellist-attr", BuildType.LABEL_LIST)).isEmpty();
    assertThat(attributes.get("my-stringlist-attr", Types.STRING_LIST))
        .isEqualTo(Arrays.asList("foo", "bar"));
    IllegalArgumentException e =
        assertThrows(
            IllegalArgumentException.class, () -> attributes.get("my-labellist-attr", Type.STRING));
    assertThat(e)
        .hasMessageThat()
        .isEqualTo(
            "Attribute my-labellist-attr is of type list(label) "
                + "and not of type string in ruleA rule //testpackage:my-rule-A");
  }

  @Test
  public void testImplicitOutputs() throws Exception {
    RuleClass ruleClassC =
        newRuleClass(
            "ruleC",
            false,
            false,
            false,
            false,
            false,
            false,
            ImplicitOutputsFunction.fromTemplates(
                "foo-%{name}.bar", "lib%{name}-wazoo-%{name}.mumble", "stuff-%{outs}-bar"),
            null,
            DUMMY_CONFIGURED_TARGET_FACTORY,
            PredicatesWithMessage.alwaysTrue(),
            AdvertisedProviderSet.EMPTY,
            null,
            ImmutableSet.of(),
            true,
            attr("outs", OUTPUT_LIST).build());

    Map<String, Object> attributeValues = new HashMap<>();
    attributeValues.put("outs", Collections.singletonList("explicit_out"));
    attributeValues.put("name", "myrule");

    Rule rule = createRule(ruleClassC, "myrule", attributeValues);

    Set<String> set = new HashSet<>();
    for (OutputFile outputFile : rule.getOutputFiles()) {
      set.add(outputFile.getName());
      assertThat(outputFile.getGeneratingRule()).isSameInstanceAs(rule);
    }
    assertThat(set).containsExactly("foo-myrule.bar", "libmyrule-wazoo-myrule.mumble",
        "stuff-explicit_out-bar", "explicit_out");
  }

  @Test
  public void testImplicitOutsWithBasenameDirname() throws Exception {
    RuleClass ruleClass =
        newRuleClass(
            "ruleClass",
            false,
            false,
            false,
            false,
            false,
            false,
            ImplicitOutputsFunction.fromTemplates("%{dirname}lib%{basename}.bar"),
            null,
            DUMMY_CONFIGURED_TARGET_FACTORY,
            PredicatesWithMessage.alwaysTrue(),
            AdvertisedProviderSet.EMPTY,
            null,
            ImmutableSet.of(),
            true);

    Rule rule = createRule(ruleClass, "myRule", ImmutableMap.of());
    assertThat(Iterables.getOnlyElement(rule.getOutputFiles()).getName())
        .isEqualTo("libmyRule.bar");

    Rule ruleWithSlash = createRule(ruleClass, "myRule/with/slash", ImmutableMap.of());
    assertThat(Iterables.getOnlyElement(ruleWithSlash.getOutputFiles()).getName())
        .isEqualTo("myRule/with/libslash.bar");
  }

  /**
   * Helper routine that instantiates a rule class with the given computed default and supporting
   * attributes for the default to reference.
   */
  private static RuleClass getRuleClassWithComputedDefault(Attribute computedDefault) {
    return newRuleClass(
        "ruleClass",
        false,
        false,
        false,
        false,
        false,
        false,
        ImplicitOutputsFunction.fromTemplates("empty"),
        null,
        DUMMY_CONFIGURED_TARGET_FACTORY,
        PredicatesWithMessage.alwaysTrue(),
        AdvertisedProviderSet.EMPTY,
        null,
        ImmutableSet.of(),
        true,
        attr("condition", BOOLEAN).value(false).build(),
        attr("declared1", BOOLEAN).value(false).build(),
        attr("declared2", BOOLEAN).value(false).build(),
        attr("nonconfigurable", BOOLEAN).nonconfigurable("test").value(false).build(),
        computedDefault);
  }

  /**
   * Helper routine that checks that a computed default is valid and bound to the expected value.
   */
  private void checkValidComputedDefault(Object expectedValue, Attribute computedDefault,
      ImmutableMap<String, Object> attrValueMap) throws Exception {
    assertThat(computedDefault.getDefaultValueUnchecked())
        .isInstanceOf(Attribute.ComputedDefault.class);
    Rule rule =
        createRule(getRuleClassWithComputedDefault(computedDefault), "myRule", attrValueMap);
    AttributeMap attributes = RawAttributeMapper.of(rule);
    assertThat(attributes.get(computedDefault.getName(), computedDefault.getType()))
        .isEqualTo(expectedValue);
  }

  /**
   * Helper routine that checks that a computed default is invalid due to declared dependency issues
   * and fails with the expected message.
   */
  private void checkInvalidComputedDefault(Attribute computedDefault, String expectedMessage) {
    IllegalArgumentException e =
        assertThrows(
            IllegalArgumentException.class,
            () ->
                createRule(
                    getRuleClassWithComputedDefault(computedDefault), "myRule", ImmutableMap.of()));
    assertThat(e).hasMessageThat().isEqualTo(expectedMessage);
  }

  /** Tests computed default values are computed as expected. */
  @Test
  public void testComputedDefault() throws Exception {
    Attribute computedDefault =
        attr("$result", BOOLEAN)
            .value(
                new Attribute.ComputedDefault("condition") {
                  @Override
                  public Object getDefault(AttributeMap rule) {
                    return rule.get("condition", Type.BOOLEAN);
                  }
                })
            .build();

    checkValidComputedDefault(
        Boolean.FALSE, computedDefault, ImmutableMap.of("condition", Boolean.FALSE));
    checkValidComputedDefault(
        Boolean.TRUE, computedDefault, ImmutableMap.of("condition", Boolean.TRUE));
  }

  /**
   * Tests that computed defaults can only read attribute values for configurable attributes that
   * have been explicitly declared.
   */
  @Test
  public void testComputedDefaultDeclarations() throws Exception {
    checkValidComputedDefault(
        Boolean.FALSE,
        attr("$good_default_no_declares", BOOLEAN)
            .value(
                new Attribute.ComputedDefault() {
                  @Override
                  public Object getDefault(AttributeMap rule) {
                    // OK: not a value check:
                    return rule.isAttributeValueExplicitlySpecified("undeclared");
                  }
                })
            .build(),
        ImmutableMap.of());

    checkValidComputedDefault(
        Boolean.FALSE,
        attr("$good_default_one_declare", BOOLEAN)
            .value(
                new Attribute.ComputedDefault("declared1") {
                  @Override
                  public Object getDefault(AttributeMap rule) {
                    return rule.get("declared1", Type.BOOLEAN);
                  }
                })
            .build(),
        ImmutableMap.of());

    checkValidComputedDefault(
        Boolean.FALSE,
        attr("$good_default_two_declares", BOOLEAN)
            .value(
                new Attribute.ComputedDefault("declared1", "declared2") {
                  @Override
                  public Object getDefault(AttributeMap rule) {
                    return rule.get("declared1", Type.BOOLEAN)
                        && rule.get("declared2", Type.BOOLEAN);
                  }
                })
            .build(),
        ImmutableMap.of());

    checkInvalidComputedDefault(
        attr("$bad_default_no_declares", BOOLEAN).value(
            new Attribute.ComputedDefault() {
              @Override public Object getDefault(AttributeMap rule) {
                return rule.get("declared1", Type.BOOLEAN);
              }
        }).build(),
        "attribute \"declared1\" isn't available in this computed default context");

    checkInvalidComputedDefault(
        attr("$bad_default_one_declare", BOOLEAN).value(
            new Attribute.ComputedDefault("declared1") {
              @Override public Object getDefault(AttributeMap rule) {
                return rule.get("declared1", Type.BOOLEAN) || rule.get("declared2", Type.BOOLEAN);
              }
        }).build(),
        "attribute \"declared2\" isn't available in this computed default context");

    checkInvalidComputedDefault(
        attr("$bad_default_two_declares", BOOLEAN).value(
            new Attribute.ComputedDefault("declared1", "declared2") {
              @Override public Object getDefault(AttributeMap rule) {
                return rule.get("condition", Type.BOOLEAN);
              }
        }).build(),
        "attribute \"condition\" isn't available in this computed default context");
  }

  /**
   * Tests that computed defaults *can* read attribute values for non-configurable attributes
   * without needing to explicitly declare them.
   */
  @Test
  public void testComputedDefaultWithNonConfigurableAttributes() throws Exception {
    checkValidComputedDefault(
        Boolean.FALSE,
        attr("$good_default_reading_undeclared_nonconfigurable_attribute", BOOLEAN)
            .value(
                new Attribute.ComputedDefault() {
                  @Override
                  public Object getDefault(AttributeMap rule) {
                    return rule.get("nonconfigurable", Type.BOOLEAN);
                  }
                })
            .build(),
        ImmutableMap.of());
  }

  @Test
  public void testOutputsAreOrdered() throws Exception {
    RuleClass ruleClassC =
        newRuleClass(
            "ruleC",
            false,
            false,
            false,
            false,
            false,
            false,
            ImplicitOutputsFunction.fromTemplates("first-%{name}", "second-%{name}", "out-%{outs}"),
            null,
            DUMMY_CONFIGURED_TARGET_FACTORY,
            PredicatesWithMessage.alwaysTrue(),
            AdvertisedProviderSet.EMPTY,
            null,
            ImmutableSet.of(),
            true,
            attr("outs", OUTPUT_LIST).build());

    Map<String, Object> attributeValues = new HashMap<>();
    attributeValues.put("outs", ImmutableList.of("third", "fourth"));
    attributeValues.put("name", "myrule");

    Rule rule = createRule(ruleClassC, "myrule", attributeValues);

    List<String> actual = new ArrayList<>();
    for (OutputFile outputFile : rule.getOutputFiles()) {
      actual.add(outputFile.getName());
      assertThat(outputFile.getGeneratingRule()).isSameInstanceAs(rule);
    }
    assertWithMessage("unexpected output set").that(actual).containsExactly("first-myrule",
        "second-myrule", "out-third", "out-fourth", "third", "fourth");
    assertWithMessage("invalid output ordering").that(actual).containsExactly("first-myrule",
        "second-myrule", "out-third", "out-fourth", "third", "fourth").inOrder();
  }

  @Test
  public void testSubstitutePlaceholderIntoTemplate() throws Exception {
    RuleClass ruleClass =
        newRuleClass(
            "ruleA",
            false,
            false,
            false,
            false,
            false,
            false,
            SafeImplicitOutputsFunction.NONE,
            null,
            DUMMY_CONFIGURED_TARGET_FACTORY,
            PredicatesWithMessage.alwaysTrue(),
            AdvertisedProviderSet.EMPTY,
            null,
            ImmutableSet.of(),
            true,
            attr("a", STRING_LIST).mandatory().build(),
            attr("b", STRING_LIST).mandatory().build(),
            attr("c", STRING_LIST).mandatory().build(),
            attr("baz", STRING_LIST).mandatory().build(),
            attr("empty", STRING_LIST).build());

    Map<String, Object> attributeValues = new LinkedHashMap<>();
    attributeValues.put("a", ImmutableList.of("a", "A"));
    attributeValues.put("b", ImmutableList.of("b", "B"));
    attributeValues.put("c", ImmutableList.of("c", "C"));
    attributeValues.put("baz", ImmutableList.of("baz", "BAZ"));
    attributeValues.put("empty", ImmutableList.<String>of());

    AttributeMap rule = RawAttributeMapper.of(createRule(ruleClass, "testrule", attributeValues));

    assertThat(substitutePlaceholderIntoTemplate("foo", rule)).containsExactly("foo");
    assertThat(substitutePlaceholderIntoTemplate("foo-%{baz}-bar", rule)).containsExactly(
        "foo-baz-bar", "foo-BAZ-bar").inOrder();
    assertThat(substitutePlaceholderIntoTemplate("%{a}-%{b}-%{c}", rule)).containsExactly("a-b-c",
        "a-b-C", "a-B-c", "a-B-C", "A-b-c", "A-b-C", "A-B-c", "A-B-C").inOrder();
    assertThat(substitutePlaceholderIntoTemplate("%{a", rule)).containsExactly("%{a");
    assertThat(substitutePlaceholderIntoTemplate("%{a}}", rule)).containsExactly("a}", "A}")
        .inOrder();
    assertThat(substitutePlaceholderIntoTemplate("x%{a}y%{empty}", rule)).isEmpty();
  }

  @Test
  public void testOrderIndependentAttribute() throws Exception {
    RuleClass ruleClassA = createRuleClassA();

    List<String> list = Arrays.asList("foo", "bar", "baz");
    Map<String, Object> attributeValues = new LinkedHashMap<>();
    // mandatory values
    attributeValues.put("my-string-attr", "");
    attributeValues.put("my-label-attr", "//project");
    attributeValues.put("my-string-attr2", "");
    attributeValues.put("my-labellist-attr", Collections.emptyList());
    // to compare the effect of .orderIndependent()
    attributeValues.put("my-stringlist-attr", list);
    attributeValues.put("my-sorted-stringlist-attr", list);

    Rule rule = createRule(ruleClassA, "testrule", attributeValues);
    AttributeMap attributes = RawAttributeMapper.of(rule);

    assertThat(attributes.get("my-stringlist-attr", Types.STRING_LIST)).isEqualTo(list);
    assertThat(attributes.get("my-sorted-stringlist-attr", Types.STRING_LIST))
        .isEqualTo(Arrays.asList("bar", "baz", "foo"));
  }

  @CanIgnoreReturnValue
  private Rule createRule(RuleClass ruleClass, String name, Map<String, Object> attributeValues)
      throws LabelSyntaxException, InterruptedException, CannotPrecomputeDefaultsException {
    Package.Builder pkgBuilder = createDummyPackageBuilder();
    Label ruleLabel;
    try {
      ruleLabel = pkgBuilder.createLabel(name);
    } catch (LabelSyntaxException e) {
      throw new IllegalArgumentException("Rule has illegal label", e);
    }
    attributeValues = ensureNameAttrValuePresent(attributeValues);
    Rule rule =
        ruleClass.createRule(
            pkgBuilder,
            ruleLabel,
            new BuildLangTypedAttributeValuesMap(attributeValues),
            true,
            ImmutableList.of(
                StarlarkThread.callStackEntry(StarlarkThread.TOP_LEVEL, testRuleLocation)));
    pkgBuilder.getLocalEventHandler().replayOn(reporter);
    return rule;
  }

  @Test
  public void testOverrideWithWrongType() {
    RuleClass parentRuleClass = createParentRuleClass();

    RuleClass.Builder childRuleClassBuilder =
        new RuleClass.Builder("child_rule", RuleClassType.NORMAL, false, parentRuleClass);
    IllegalStateException e =
        assertThrows(
            IllegalStateException.class,
            () -> childRuleClassBuilder.override(attr("attr", INTEGER)));
    assertThat(e)
        .hasMessageThat()
        .isEqualTo(
            "The type of the new attribute 'int' is different from "
                + "the original one 'string'.");
  }

  @Test
  public void testOverrideWithRightType() {
    RuleClass parentRuleClass = createParentRuleClass();

    RuleClass.Builder childRuleClassBuilder = new RuleClass.Builder(
      "child_rule", RuleClassType.NORMAL, false, parentRuleClass);
      childRuleClassBuilder.override(attr("attr", STRING));
  }

  @Test
  public void testCopyAndOverrideAttribute() throws Exception {
    RuleClass parentRuleClass = createParentRuleClass();
    RuleClass childRuleClass = createChildRuleClass(parentRuleClass);

    Map<String, Object> parentValues = new LinkedHashMap<>();
    Map<String, Object> childValues = new LinkedHashMap<>();
    childValues.put("attr", "somevalue");
    createRule(parentRuleClass, "parent_rule", parentValues);
    createRule(childRuleClass, "child_rule", childValues);
  }

  @Test
  public void testCopyAndOverrideAttributeMandatoryMissing() throws Exception {
    RuleClass parentRuleClass = createParentRuleClass();
    RuleClass childRuleClass = createChildRuleClass(parentRuleClass);

    Map<String, Object> childValues = new LinkedHashMap<>();
    reporter.removeHandler(failFastHandler);
    createRule(childRuleClass, "child_rule", childValues);

    assertThat(eventCollector.count()).isSameInstanceAs(1);
    assertContainsEvent("//testpackage:child_rule: missing value for mandatory "
        + "attribute 'attr' in 'child_rule' rule");
  }

  @Test
  public void testRequiredFragmentInheritance() {
    RuleClass parentRuleClass = createParentRuleClass();
    RuleClass childRuleClass = createChildRuleClass(parentRuleClass);
    assertThat(parentRuleClass.getConfigurationFragmentPolicy().getRequiredConfigurationFragments())
        .containsExactly(DummyFragment.class);
    assertThat(childRuleClass.getConfigurationFragmentPolicy().getRequiredConfigurationFragments())
        .containsExactly(DummyFragment.class);
  }

  private static RuleClass newRuleClass(
      String name,
      boolean starlarkExecutable,
      boolean documented,
      boolean binaryOutput,
      boolean workspaceOnly,
      boolean outputsDefaultExecutable,
      boolean isAnalysisTest,
      ImplicitOutputsFunction implicitOutputsFunction,
      TransitionFactory<RuleTransitionData> transitionFactory,
      ConfiguredTargetFactory<?, ?, ?> configuredTargetFactory,
      PredicateWithMessage<Rule> validityPredicate,
      AdvertisedProviderSet advertisedProviders,
      @Nullable StarlarkFunction configuredTargetFunction,
      Set<Class<? extends Fragment>> allowedConfigurationFragments,
      boolean supportsConstraintChecking,
      Attribute... attributes) {
    return new RuleClass(
        name,
        DUMMY_STACK,
        /* key= */ name,
        RuleClassType.NORMAL,
        /* starlarkParent= */ null,
        /* initializer= */ null,
        /* labelConverterForInitializer= */ null,
        /* isStarlark= */ starlarkExecutable,
        /* extendable= */ false,
        /* extendableAllowlist= */ null,
        /* starlarkTestable= */ false,
        documented,
        binaryOutput,
        workspaceOnly,
        outputsDefaultExecutable,
        isAnalysisTest,
        /* hasAnalysisTestTransition= */ false,
        /* allowlistCheckers= */ ImmutableList.of(),
        /* ignoreLicenses= */ false,
        implicitOutputsFunction,
        transitionFactory,
        configuredTargetFactory,
        validityPredicate,
        advertisedProviders,
        configuredTargetFunction,
        NO_EXTERNAL_BINDINGS,
        NO_TOOLCHAINS_TO_REGISTER,
        /* optionReferenceFunction= */ RuleClass.NO_OPTION_REFERENCE,
        /* ruleDefinitionEnvironmentLabel= */ null,
        /* ruleDefinitionEnvironmentDigest= */ null,
        /* ruleDefinitionEnvironmentRepoMappingEntries= */ null,
        new ConfigurationFragmentPolicy.Builder()
            .requiresConfigurationFragments(allowedConfigurationFragments)
            .build(),
        supportsConstraintChecking,
        /* toolchainTypes= */ ImmutableSet.of(),
        /* useToolchainResolution= */ ToolchainResolutionMode.ENABLED,
        /* executionPlatformConstraints= */ ImmutableSet.of(),
        /* execGroups= */ ImmutableMap.of(),
        OutputFile.Kind.FILE,
        attributes.length > 0 && attributes[0].equals(RuleClass.NAME_ATTRIBUTE)
            ? ImmutableList.copyOf(attributes)
            : ImmutableList.<Attribute>builder()
                .add(RuleClass.NAME_ATTRIBUTE)
                .add(attributes)
                .build(),
        /* buildSetting= */ null,
        /* subrules= */ ImmutableList.of());
  }

  private static RuleClass createParentRuleClass() {
    return newRuleClass(
        "parent_rule",
        false,
        false,
        false,
        false,
        false,
        false,
        SafeImplicitOutputsFunction.NONE,
        null,
        DUMMY_CONFIGURED_TARGET_FACTORY,
        PredicatesWithMessage.alwaysTrue(),
        AdvertisedProviderSet.EMPTY,
        null,
        ImmutableSet.of(DummyFragment.class),
        true,
        attr("attr", STRING).build());
  }

  private static RuleClass createChildRuleClass(RuleClass parentRuleClass) {
    RuleClass.Builder childRuleClassBuilder = new RuleClass.Builder(
        "child_rule", RuleClassType.NORMAL, false, parentRuleClass);
    return childRuleClassBuilder.override(
        childRuleClassBuilder
          .factory(DUMMY_CONFIGURED_TARGET_FACTORY)
          .copy("attr").mandatory())
          .add(attr("tags", STRING_LIST))
          .build();
  }

  @Test
  public void testValidityChecker() throws Exception {
    Rule dep1 =
        createRule(
            new RuleClass.Builder("dep1class", RuleClassType.NORMAL, false)
                .factory(DUMMY_CONFIGURED_TARGET_FACTORY)
                .add(attr("tags", STRING_LIST))
                .build(),
            "dep1",
            ImmutableMap.of());
    Rule dep2 =
        createRule(
            new RuleClass.Builder("dep2class", RuleClassType.NORMAL, false)
                .factory(DUMMY_CONFIGURED_TARGET_FACTORY)
                .add(attr("tags", STRING_LIST))
                .build(),
            "dep2",
            ImmutableMap.of());

    ValidityPredicate checker =
        new ValidityPredicate() {
          @Override
          public String checkValid(Rule from, String toRuleClass) {
            assertThat(from.getName()).isEqualTo("top");
            switch (toRuleClass) {
              case "dep1class":
                return "pear";
              case "dep2class":
                return null;
              default:
                fail("invalid dependency");
                return null;
            }
          }
        };

    RuleClass topClass = new RuleClass.Builder("top", RuleClassType.NORMAL, false)
        .factory(DUMMY_CONFIGURED_TARGET_FACTORY)
        .add(attr("tags", STRING_LIST))
        .add(attr("deps", LABEL_LIST).legacyAllowAnyFileType()
              .validityPredicate(checker))
        .build();

    Rule topRule = createRule(topClass, "top", ImmutableMap.of());

    assertThat(
            topClass
                .getAttributeByName("deps")
                .getValidityPredicate()
                .checkValid(topRule, dep1.getRuleClass()))
        .isEqualTo("pear");
    assertThat(
            topClass
                .getAttributeByName("deps")
                .getValidityPredicate()
                .checkValid(topRule, dep2.getRuleClass()))
        .isNull();
  }

  @Test
  public void testBadRuleClassNames() {
    expectError(RuleClassType.NORMAL, "8abc");
    expectError(RuleClassType.NORMAL, "!abc");
    expectError(RuleClassType.NORMAL, "a b");
  }

  private static void expectError(RuleClassType type, String name) {
    assertThrows(IllegalArgumentException.class, () -> type.checkName(name));
  }

  @Test
  public void testToolchainTypes() throws Exception {
    RuleClass.Builder ruleClassBuilder =
        new RuleClass.Builder("ruleClass", RuleClassType.NORMAL, false)
            .factory(DUMMY_CONFIGURED_TARGET_FACTORY)
            .add(attr("tags", STRING_LIST));

    ruleClassBuilder.addToolchainTypes(
        ToolchainTypeRequirement.create(Label.parseCanonical("//toolchain:tc1")),
        ToolchainTypeRequirement.create(Label.parseCanonical("//toolchain:tc2")));

    RuleClass ruleClass = ruleClassBuilder.build();

    assertThat(ruleClass).hasToolchainType("//toolchain:tc1");
    assertThat(ruleClass).hasToolchainType("//toolchain:tc2");
  }

  @Test
  public void testExecutionPlatformConstraints() throws Exception {
    RuleClass.Builder ruleClassBuilder =
        new RuleClass.Builder("ruleClass", RuleClassType.NORMAL, false)
            .factory(DUMMY_CONFIGURED_TARGET_FACTORY)
            .add(attr("tags", STRING_LIST));

    ruleClassBuilder.addExecutionPlatformConstraints(
        Label.parseCanonical("//constraints:cv1"), Label.parseCanonical("//constraints:cv2"));

    RuleClass ruleClass = ruleClassBuilder.build();

    assertThat(ruleClass.getExecutionPlatformConstraints())
        .containsExactly(
            Label.parseCanonical("//constraints:cv1"), Label.parseCanonical("//constraints:cv2"));
  }

  @Test
  public void testExecutionPlatformConstraints_inheritConstraintsFromParent() throws Exception {
    RuleClass parentRuleClass =
        new RuleClass.Builder("$parentRuleClass", RuleClassType.ABSTRACT, false)
            .add(attr("tags", STRING_LIST))
            .addExecutionPlatformConstraints(
                Label.parseCanonical("//constraints:cv1"),
                Label.parseCanonical("//constraints:cv2"))
            .build();

    RuleClass childRuleClass =
        new RuleClass.Builder("childRuleClass", RuleClassType.NORMAL, false, parentRuleClass)
            .factory(DUMMY_CONFIGURED_TARGET_FACTORY)
            .build();

    assertThat(childRuleClass.getExecutionPlatformConstraints())
        .containsExactly(
            Label.parseCanonical("//constraints:cv1"), Label.parseCanonical("//constraints:cv2"));
  }

  @Test
  public void testExecutionPlatformConstraints_inheritAndAddConstraints() throws Exception {
    RuleClass parentRuleClass =
        new RuleClass.Builder("$parentRuleClass", RuleClassType.ABSTRACT, false)
            .add(attr("tags", STRING_LIST))
            .build();

    RuleClass.Builder childRuleClassBuilder =
        new RuleClass.Builder("childRuleClass", RuleClassType.NORMAL, false, parentRuleClass)
            .factory(DUMMY_CONFIGURED_TARGET_FACTORY)
            .addExecutionPlatformConstraints(
                Label.parseCanonical("//constraints:cv1"),
                Label.parseCanonical("//constraints:cv2"));

    RuleClass childRuleClass = childRuleClassBuilder.build();

    assertThat(childRuleClass.getExecutionPlatformConstraints())
        .containsExactly(
            Label.parseCanonical("//constraints:cv1"), Label.parseCanonical("//constraints:cv2"));
  }

  @Test
  public void testExecGroups() {
    RuleClass.Builder ruleClassBuilder =
        new RuleClass.Builder("ruleClass", RuleClassType.NORMAL, false)
            .factory(DUMMY_CONFIGURED_TARGET_FACTORY)
            .add(attr("tags", STRING_LIST));

    Label toolchain = Label.parseCanonicalUnchecked("//toolchain");
    Label constraint = Label.parseCanonicalUnchecked("//constraint");

    // TODO(https://github.com/bazelbuild/bazel/issues/14726): Add tests of optional toolchains.
    ruleClassBuilder.addExecGroups(
        ImmutableMap.of(
            "cherry",
            ExecGroup.builder()
                .addToolchainType(ToolchainTypeRequirement.create(toolchain))
                .execCompatibleWith(ImmutableSet.of(constraint))
                .copyFrom(null)
                .build()));

    RuleClass ruleClass = ruleClassBuilder.build();

    assertThat(ruleClass.getExecGroups()).hasSize(1);
    assertThat(ruleClass.getExecGroups().get("cherry")).hasToolchainType(toolchain);
    assertThat(ruleClass.getExecGroups().get("cherry")).toolchainType(toolchain).isMandatory();
    assertThat(ruleClass.getExecGroups().get("cherry")).hasExecCompatibleWith(constraint);
  }

  @Test
  public void testBuildSetting_createsDefaultAttribute() {
    RuleClass labelFlag =
        new RuleClass.Builder("label_flag", RuleClassType.NORMAL, false)
            .factory(DUMMY_CONFIGURED_TARGET_FACTORY)
            .add(attr("tags", STRING_LIST))
            .setBuildSetting(BuildSetting.create(true, NODEP_LABEL))
            .build();
    RuleClass stringSetting =
        new RuleClass.Builder("string_setting", RuleClassType.NORMAL, false)
            .factory(DUMMY_CONFIGURED_TARGET_FACTORY)
            .add(attr("tags", STRING_LIST))
            .setBuildSetting(BuildSetting.create(false, STRING))
            .build();

    assertThat(labelFlag.hasAttr(STARLARK_BUILD_SETTING_DEFAULT_ATTR_NAME, NODEP_LABEL)).isTrue();
    assertThat(stringSetting.hasAttr(STARLARK_BUILD_SETTING_DEFAULT_ATTR_NAME, STRING)).isTrue();
  }

  @Test
  public void testBuildSetting_doesNotCreateDefaultAttributeIfNotBuildSetting() {
    RuleClass stringSetting =
        new RuleClass.Builder("non_build_setting", RuleClassType.NORMAL, false)
            .factory(DUMMY_CONFIGURED_TARGET_FACTORY)
            .add(attr("tags", STRING_LIST))
            .build();

    assertThat(stringSetting.hasAttr(STARLARK_BUILD_SETTING_DEFAULT_ATTR_NAME, LABEL)).isFalse();
  }

  @Test
  public void testBuildTooManyAttributesRejected() {
    RuleClass.Builder builder =
        new RuleClass.Builder("myclass", RuleClassType.NORMAL, /*starlark=*/ false)
            .factory(DUMMY_CONFIGURED_TARGET_FACTORY)
            .add(attr("tags", STRING_LIST));
    for (int i = 0; i < 200; i++) {
      builder.add(attr("attr" + i, STRING));
    }

    IllegalArgumentException expected =
        assertThrows(IllegalArgumentException.class, builder::build);

    assertThat(expected)
        .hasMessageThat()
        .isEqualTo("Rule class myclass declared too many attributes (202 > 200)");
  }

  @Test
  public void testBuildTooLongAttributeNameRejected() {
    IllegalArgumentException expected =
        assertThrows(
            IllegalArgumentException.class,
            () ->
                new RuleClass.Builder("myclass", RuleClassType.NORMAL, /*starlark=*/ false)
                    .factory(DUMMY_CONFIGURED_TARGET_FACTORY)
                    .add(attr("tags", STRING_LIST))
                    .add(attr("x".repeat(150), STRING))
                    .build());

    assertThat(expected)
        .hasMessageThat()
        .matches("Attribute myclass\\.x{150}'s name is too long \\(150 > 128\\)");
  }

  @Test
  public void testPackageMetadataAlternateName() throws Exception {
    RuleClass noopClass =
        new RuleClass.Builder("noop", RuleClassType.NORMAL, false)
            .factory(DUMMY_CONFIGURED_TARGET_FACTORY)
            .add(attr("tags", STRING_LIST))
            .add(attr(RuleClass.APPLICABLE_METADATA_ATTR, LABEL_LIST).legacyAllowAnyFileType())
            .build();
    Map<String, Object> attributeValues = new LinkedHashMap<>();
    attributeValues.put("applicable_licenses", Lists.newArrayList(":info"));
    Rule noopRule = createRule(noopClass, "noop", attributeValues);

    assertThat(noopRule.getAttr(RuleClass.APPLICABLE_METADATA_ATTR, LABEL_LIST))
        .isEqualTo(Lists.newArrayList(Label.parseCanonical("//testpackage:info")));
  }
}
