// 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 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.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,
        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,
        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,
            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,
            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,
            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,
            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,
            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,
            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' \
                of 'ruleA', 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,
            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,
            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,
        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,
            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,
            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,
      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,
        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,
        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 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")));
  }
}
