| // Copyright 2021 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.bazel.bzlmod; |
| |
| import static com.google.common.truth.Truth.assertThat; |
| import static com.google.devtools.build.lib.bazel.bzlmod.BzlmodTestUtil.buildTag; |
| import static com.google.devtools.build.lib.bazel.bzlmod.BzlmodTestUtil.createModuleKey; |
| import static com.google.devtools.build.lib.bazel.bzlmod.BzlmodTestUtil.createRepositoryMapping; |
| import static com.google.devtools.build.lib.bazel.bzlmod.BzlmodTestUtil.createTagClass; |
| import static com.google.devtools.build.lib.packages.Attribute.attr; |
| import static org.junit.Assert.assertThrows; |
| |
| import com.google.common.collect.ImmutableList; |
| import com.google.common.collect.ImmutableMap; |
| import com.google.devtools.build.lib.cmdline.Label; |
| import com.google.devtools.build.lib.cmdline.PackageIdentifier; |
| import com.google.devtools.build.lib.packages.Attribute.AllowedValueSet; |
| import com.google.devtools.build.lib.packages.BuildType; |
| import com.google.devtools.build.lib.packages.LabelConverter; |
| import com.google.devtools.build.lib.packages.Type; |
| import com.google.devtools.build.lib.util.FileTypeSet; |
| import net.starlark.java.eval.Dict; |
| import net.starlark.java.eval.Mutability; |
| import net.starlark.java.eval.Starlark; |
| import net.starlark.java.eval.StarlarkInt; |
| import net.starlark.java.eval.StarlarkList; |
| import net.starlark.java.eval.StarlarkSemantics; |
| import net.starlark.java.eval.Structure; |
| import org.junit.Test; |
| import org.junit.runner.RunWith; |
| import org.junit.runners.JUnit4; |
| |
| /** Tests for {@link TypeCheckedTag}. */ |
| @RunWith(JUnit4.class) |
| public class TypeCheckedTagTest { |
| |
| private static Object getattr(Structure structure, String fieldName) throws Exception { |
| return Starlark.getattr( |
| Mutability.IMMUTABLE, |
| StarlarkSemantics.DEFAULT, |
| structure, |
| fieldName, |
| /*defaultValue=*/ null); |
| } |
| |
| @Test |
| public void basic() throws Exception { |
| TypeCheckedTag typeCheckedTag = |
| TypeCheckedTag.create( |
| createTagClass(attr("foo", Type.INTEGER).build()), |
| buildTag("tag_name").addAttr("foo", StarlarkInt.of(3)).setDevDependency().build(), |
| /* labelConverter= */ null); |
| assertThat(typeCheckedTag.getFieldNames()).containsExactly("foo"); |
| assertThat(getattr(typeCheckedTag, "foo")).isEqualTo(StarlarkInt.of(3)); |
| assertThat(typeCheckedTag.isDevDependency()).isTrue(); |
| } |
| |
| @Test |
| public void label() throws Exception { |
| TypeCheckedTag typeCheckedTag = |
| TypeCheckedTag.create( |
| createTagClass( |
| attr("foo", BuildType.LABEL_LIST).allowedFileTypes(FileTypeSet.ANY_FILE).build()), |
| buildTag("tag_name") |
| .addAttr( |
| "foo", StarlarkList.immutableOf(":thing1", "//pkg:thing2", "@repo//pkg:thing3")) |
| .build(), |
| new LabelConverter( |
| PackageIdentifier.parse("@myrepo//mypkg"), |
| createRepositoryMapping(createModuleKey("test", "1.0"), "repo", "other_repo"))); |
| assertThat(typeCheckedTag.getFieldNames()).containsExactly("foo"); |
| assertThat(getattr(typeCheckedTag, "foo")) |
| .isEqualTo( |
| StarlarkList.immutableOf( |
| Label.parseAbsoluteUnchecked("@myrepo//mypkg:thing1"), |
| Label.parseAbsoluteUnchecked("@myrepo//pkg:thing2"), |
| Label.parseAbsoluteUnchecked("@other_repo//pkg:thing3"))); |
| assertThat(typeCheckedTag.isDevDependency()).isFalse(); |
| } |
| |
| @Test |
| public void label_withoutDefaultValue() throws Exception { |
| TypeCheckedTag typeCheckedTag = |
| TypeCheckedTag.create( |
| createTagClass( |
| attr("foo", BuildType.LABEL).allowedFileTypes(FileTypeSet.ANY_FILE).build()), |
| buildTag("tag_name").setDevDependency().build(), |
| new LabelConverter( |
| PackageIdentifier.parse("@myrepo//mypkg"), |
| createRepositoryMapping(createModuleKey("test", "1.0"), "repo", "other_repo"))); |
| assertThat(typeCheckedTag.getFieldNames()).containsExactly("foo"); |
| assertThat(getattr(typeCheckedTag, "foo")).isEqualTo(Starlark.NONE); |
| assertThat(typeCheckedTag.isDevDependency()).isTrue(); |
| } |
| |
| @Test |
| public void stringListDict_default() throws Exception { |
| TypeCheckedTag typeCheckedTag = |
| TypeCheckedTag.create( |
| createTagClass( |
| attr("foo", Type.STRING_LIST_DICT) |
| .value(ImmutableMap.of("key", ImmutableList.of("value1", "value2"))) |
| .build()), |
| buildTag("tag_name").build(), |
| null); |
| assertThat(typeCheckedTag.getFieldNames()).containsExactly("foo"); |
| assertThat(getattr(typeCheckedTag, "foo")) |
| .isEqualTo( |
| Dict.builder() |
| .put("key", StarlarkList.immutableOf("value1", "value2")) |
| .buildImmutable()); |
| assertThat(typeCheckedTag.isDevDependency()).isFalse(); |
| } |
| |
| @Test |
| public void multipleAttributesAndDefaults() throws Exception { |
| TypeCheckedTag typeCheckedTag = |
| TypeCheckedTag.create( |
| createTagClass( |
| attr("foo", Type.STRING).mandatory().build(), |
| attr("bar", Type.INTEGER).value(StarlarkInt.of(3)).build(), |
| attr("quux", Type.STRING_LIST).build()), |
| buildTag("tag_name") |
| .addAttr("foo", "fooValue") |
| .addAttr("quux", StarlarkList.immutableOf("quuxValue1", "quuxValue2")) |
| .build(), |
| /*labelConverter=*/ null); |
| assertThat(typeCheckedTag.getFieldNames()).containsExactly("foo", "bar", "quux"); |
| assertThat(getattr(typeCheckedTag, "foo")).isEqualTo("fooValue"); |
| assertThat(getattr(typeCheckedTag, "bar")).isEqualTo(StarlarkInt.of(3)); |
| assertThat(getattr(typeCheckedTag, "quux")) |
| .isEqualTo(StarlarkList.immutableOf("quuxValue1", "quuxValue2")); |
| assertThat(typeCheckedTag.isDevDependency()).isFalse(); |
| } |
| |
| @Test |
| public void mandatory() throws Exception { |
| ExternalDepsException e = |
| assertThrows( |
| ExternalDepsException.class, |
| () -> |
| TypeCheckedTag.create( |
| createTagClass(attr("foo", Type.STRING).mandatory().build()), |
| buildTag("tag_name").build(), |
| /*labelConverter=*/ null)); |
| assertThat(e).hasMessageThat().contains("mandatory attribute foo isn't being specified"); |
| } |
| |
| @Test |
| public void allowedValues() throws Exception { |
| ExternalDepsException e = |
| assertThrows( |
| ExternalDepsException.class, |
| () -> |
| TypeCheckedTag.create( |
| createTagClass( |
| attr("foo", Type.STRING) |
| .allowedValues(new AllowedValueSet("yes", "no")) |
| .build()), |
| buildTag("tag_name").addAttr("foo", "maybe").build(), |
| /*labelConverter=*/ null)); |
| assertThat(e) |
| .hasMessageThat() |
| .contains("the value for attribute foo has to be one of 'yes' or 'no' instead of 'maybe'"); |
| } |
| |
| @Test |
| public void unknownAttr() throws Exception { |
| ExternalDepsException e = |
| assertThrows( |
| ExternalDepsException.class, |
| () -> |
| TypeCheckedTag.create( |
| createTagClass(attr("foo", Type.STRING).build()), |
| buildTag("tag_name").addAttr("bar", "maybe").build(), |
| /*labelConverter=*/ null)); |
| assertThat(e).hasMessageThat().contains("unknown attribute bar provided"); |
| } |
| } |