blob: 37ceb837fdcbb63dd09eb324b937e0d2cef69b52 [file] [log] [blame]
// Copyright 2017 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.Truth8.assertThat;
import static com.google.devtools.build.lib.collect.nestedset.Order.STABLE_ORDER;
import static org.junit.Assert.assertThrows;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.verifyNoInteractions;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
import com.google.common.testing.EqualsTester;
import com.google.devtools.build.lib.cmdline.Label;
import com.google.devtools.build.lib.collect.nestedset.Depset;
import com.google.devtools.build.lib.collect.nestedset.NestedSetBuilder;
import java.util.Optional;
import net.starlark.java.eval.Dict;
import net.starlark.java.eval.EvalException;
import net.starlark.java.eval.Mutability;
import net.starlark.java.eval.Starlark;
import net.starlark.java.eval.StarlarkCallable;
import net.starlark.java.eval.StarlarkInt;
import net.starlark.java.eval.StarlarkList;
import net.starlark.java.eval.StarlarkSemantics;
import net.starlark.java.eval.StarlarkThread;
import net.starlark.java.eval.Tuple;
import net.starlark.java.syntax.Location;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.JUnit4;
/** Tests for {@link StarlarkProvider}. */
@RunWith(JUnit4.class)
public final class StarlarkProviderTest {
@Test
public void unexportedProvider_accessors() {
StarlarkProvider provider = StarlarkProvider.builder(Location.BUILTIN).build();
assertThat(provider.isExported()).isFalse();
assertThat(provider.getName()).isEqualTo("<no name>");
assertThat(provider.getPrintableName()).isEqualTo("<no name>");
assertThat(provider.createRawConstructor().getName()).isEqualTo("<raw constructor>");
assertThat(provider.getErrorMessageForUnknownField("foo"))
.isEqualTo("'struct' value has no field or method 'foo'");
assertThat(provider.isImmutable()).isFalse();
assertThat(Starlark.repr(provider)).isEqualTo("<provider>");
assertThrows(IllegalStateException.class, provider::getKey);
}
@Test
public void exportedProvider_accessors() throws Exception {
StarlarkProvider.Key key =
new StarlarkProvider.Key(Label.parseCanonical("//foo:bar.bzl"), "prov");
StarlarkProvider provider = StarlarkProvider.builder(Location.BUILTIN).setExported(key).build();
assertThat(provider.isExported()).isTrue();
assertThat(provider.getName()).isEqualTo("prov");
assertThat(provider.getPrintableName()).isEqualTo("prov");
assertThat(provider.createRawConstructor().getName()).isEqualTo("<raw constructor for prov>");
assertThat(provider.getErrorMessageForUnknownField("foo"))
.isEqualTo("'prov' value has no field or method 'foo'");
assertThat(provider.isImmutable()).isTrue();
assertThat(Starlark.repr(provider)).isEqualTo("<provider>");
assertThat(provider.getKey()).isEqualTo(key);
}
@Test
public void basicInstantiation() throws Exception {
StarlarkProvider provider = StarlarkProvider.builder(Location.BUILTIN).build();
StarlarkInfo infoFromNormalConstructor = instantiateWithA1B2C3(provider);
assertHasExactlyValuesA1B2C3(infoFromNormalConstructor);
assertThat(infoFromNormalConstructor.getProvider()).isEqualTo(provider);
StarlarkInfo infoFromRawConstructor = instantiateWithA1B2C3(provider.createRawConstructor());
assertHasExactlyValuesA1B2C3(infoFromRawConstructor);
assertThat(infoFromRawConstructor.getProvider()).isEqualTo(provider);
assertThat(infoFromNormalConstructor).isEqualTo(infoFromRawConstructor);
}
@Test
public void instantiationWithInit() throws Exception {
StarlarkProvider provider = StarlarkProvider.builder(Location.BUILTIN).setInit(initBC).build();
StarlarkInfo infoFromNormalConstructor = instantiateWithA1(provider);
assertHasExactlyValuesA1B2C3(infoFromNormalConstructor);
assertThat(infoFromNormalConstructor.getProvider()).isEqualTo(provider);
}
@Test
public void instantiationWithInitSignatureMismatch_fails() throws Exception {
StarlarkProvider provider = StarlarkProvider.builder(Location.BUILTIN).setInit(initBC).build();
EvalException e = assertThrows(EvalException.class, () -> instantiateWithA1B2C3(provider));
assertThat(e).hasMessageThat().contains("expected a single `a` argument");
}
@Test
public void instantiationWithInitReturnTypeMismatch_fails() throws Exception {
StarlarkCallable initWithInvalidReturnType =
new StarlarkCallable() {
@Override
public Object call(StarlarkThread thread, Tuple args, Dict<String, Object> kwargs) {
return "invalid";
}
@Override
public String getName() {
return "initWithInvalidReturnType";
}
@Override
public Location getLocation() {
return Location.BUILTIN;
}
};
StarlarkProvider provider =
StarlarkProvider.builder(Location.BUILTIN).setInit(initWithInvalidReturnType).build();
EvalException e = assertThrows(EvalException.class, () -> instantiateWithA1B2C3(provider));
assertThat(e)
.hasMessageThat()
.contains("got string for 'return value of provider init()', want dict");
}
@Test
public void instantiationWithFailingInit_fails() throws Exception {
StarlarkCallable failingInit =
new StarlarkCallable() {
@Override
public Object call(StarlarkThread thread, Tuple args, Dict<String, Object> kwargs)
throws EvalException {
throw Starlark.errorf("failingInit fails");
}
@Override
public String getName() {
return "failingInit";
}
@Override
public Location getLocation() {
return Location.BUILTIN;
}
};
StarlarkProvider provider =
StarlarkProvider.builder(Location.BUILTIN).setInit(failingInit).build();
EvalException e = assertThrows(EvalException.class, () -> instantiateWithA1B2C3(provider));
assertThat(e).hasMessageThat().contains("failingInit fails");
}
@Test
public void rawConstructorBypassesInit() throws Exception {
StarlarkCallable init = mock(StarlarkCallable.class, "init");
StarlarkProvider provider = StarlarkProvider.builder(Location.BUILTIN).setInit(init).build();
StarlarkInfo infoFromRawConstructor = instantiateWithA1B2C3(provider.createRawConstructor());
assertHasExactlyValuesA1B2C3(infoFromRawConstructor);
assertThat(infoFromRawConstructor.getProvider()).isEqualTo(provider);
verifyNoInteractions(init);
}
@Test
public void basicInstantiationWithSchemaWithSomeFieldsUnset() throws Exception {
StarlarkProvider provider =
StarlarkProvider.builder(Location.BUILTIN)
.setSchema(ImmutableList.of("a", "b", "c"))
.build();
StarlarkInfo infoFromNormalConstructor = instantiateWithA1(provider);
assertHasExactlyValuesA1(infoFromNormalConstructor);
StarlarkInfo infoFromRawConstructor = instantiateWithA1(provider.createRawConstructor());
assertHasExactlyValuesA1(infoFromRawConstructor);
}
@Test
public void basicInstantiationWithSchemaWithAllFieldsSet() throws Exception {
StarlarkProvider provider =
StarlarkProvider.builder(Location.BUILTIN)
.setSchema(ImmutableList.of("a", "b", "c"))
.build();
StarlarkInfo infoFromNormalConstructor = instantiateWithA1B2C3(provider);
assertHasExactlyValuesA1B2C3(infoFromNormalConstructor);
StarlarkInfo infoFromRawConstructor = instantiateWithA1B2C3(provider.createRawConstructor());
assertHasExactlyValuesA1B2C3(infoFromRawConstructor);
}
@Test
public void basicInstantiationWithDocumentedSchema() throws Exception {
StarlarkProvider provider =
StarlarkProvider.builder(Location.BUILTIN)
.setSchema(ImmutableMap.of("a", "Parameter a", "b", "Parameter b", "c", "Parameter c"))
.build();
StarlarkInfo infoFromNormalConstructor = instantiateWithA1(provider);
assertHasExactlyValuesA1(infoFromNormalConstructor);
StarlarkInfo infoFromRawConstructor = instantiateWithA1B2C3(provider.createRawConstructor());
assertHasExactlyValuesA1B2C3(infoFromRawConstructor);
}
@Test
public void schemaDisallowsUnexpectedFields() throws Exception {
StarlarkProvider provider =
StarlarkProvider.builder(Location.BUILTIN).setSchema(ImmutableList.of("a", "b")).build();
EvalException e = assertThrows(EvalException.class, () -> instantiateWithA1B2C3(provider));
assertThat(e)
.hasMessageThat()
.contains("got unexpected field 'c' in call to instantiate provider");
}
@Test
public void documentedSchemaDisallowsUnexpectedFields() throws Exception {
StarlarkProvider provider =
StarlarkProvider.builder(Location.BUILTIN)
.setSchema(ImmutableMap.of("a", "Parameter a", "b", "Parameter b"))
.build();
EvalException e = assertThrows(EvalException.class, () -> instantiateWithA1B2C3(provider));
assertThat(e)
.hasMessageThat()
.contains("got unexpected field 'c' in call to instantiate provider");
}
@Test
public void schemaEnforcedOnRawConstructor() throws Exception {
StarlarkProvider provider =
StarlarkProvider.builder(Location.BUILTIN).setSchema(ImmutableList.of("a", "b")).build();
EvalException e =
assertThrows(
EvalException.class, () -> instantiateWithA1B2C3(provider.createRawConstructor()));
assertThat(e)
.hasMessageThat()
.contains("got unexpected field 'c' in call to instantiate provider");
}
@Test
public void schemaEnforcedOnInit() throws Exception {
StarlarkProvider provider =
StarlarkProvider.builder(Location.BUILTIN)
.setSchema(ImmutableList.of("a", "b"))
.setInit(initBC)
.build();
EvalException e = assertThrows(EvalException.class, () -> instantiateWithA1(provider));
assertThat(e)
.hasMessageThat()
.contains("got unexpected field 'c' in call to instantiate provider");
}
@Test
public void documentedProvider_getDocumentation() throws Exception {
StarlarkProvider provider =
StarlarkProvider.builder(Location.BUILTIN).setDocumentation("My doc string").build();
assertThat(provider.getDocumentation()).hasValue("My doc string");
}
@Test
public void undocumentedProvider_getDocumentation() throws Exception {
StarlarkProvider provider = StarlarkProvider.builder(Location.BUILTIN).build();
assertThat(provider.getDocumentation()).isEmpty();
}
@Test
public void schemalessProvider_getFields() throws Exception {
StarlarkProvider provider = StarlarkProvider.builder(Location.BUILTIN).build();
assertThat(provider.getFields()).isNull();
}
@Test
public void schemalessProvider_getSchema() throws Exception {
StarlarkProvider provider = StarlarkProvider.builder(Location.BUILTIN).build();
assertThat(provider.getSchema()).isNull();
}
@Test
public void providerWithUndocumentedSchema_getFields() throws Exception {
StarlarkProvider provider =
StarlarkProvider.builder(Location.BUILTIN)
// Note fields in setSchema() call below are not alphabetized to simulate
// non-alphabetized field order in a provider declaration in Starlark code.
.setSchema(ImmutableList.of("c", "a", "b"))
.build();
assertThat(provider.getFields()).containsExactly("a", "b", "c").inOrder();
}
@Test
public void providerWithUndocumentedSchema_getSchema() throws Exception {
StarlarkProvider provider =
StarlarkProvider.builder(Location.BUILTIN)
// Note fields in setSchema() call below are not alphabetized to simulate
// non-alphabetized field order in a provider declaration in Starlark code.
.setSchema(ImmutableList.of("c", "a", "b"))
.build();
assertThat(provider.getSchema())
.containsExactly("c", Optional.empty(), "a", Optional.empty(), "b", Optional.empty())
.inOrder();
}
@Test
public void providerWithDocumentedSchema_getFields() throws Exception {
StarlarkProvider provider =
StarlarkProvider.builder(Location.BUILTIN)
// Note fields in setSchema() call below are not alphabetized to simulate
// non-alphabetized field order in a provider declaration in Starlark code.
.setSchema(ImmutableMap.of("c", "Parameter c", "a", "Parameter a", "b", "Parameter b"))
.build();
assertThat(provider.getFields()).containsExactly("a", "b", "c").inOrder();
}
@Test
public void providerWithDocumentedSchema_getSchema() throws Exception {
StarlarkProvider provider =
StarlarkProvider.builder(Location.BUILTIN)
// Note fields in setSchema() call below are not alphabetized to simulate
// non-alphabetized field order in a provider declaration in Starlark code.
.setSchema(ImmutableMap.of("c", "Parameter c", "a", "Parameter a", "b", "Parameter b"))
.build();
assertThat(provider.getSchema())
.containsExactly(
"c",
Optional.of("Parameter c"),
"a",
Optional.of("Parameter a"),
"b",
Optional.of("Parameter b"))
.inOrder();
}
/**
* Tests the safe storage and retrieval of depsets, which may be optimized to nested sets in the
* internal representation.
*/
@Test
public void schemafulProvider_withDepset() throws Exception {
StarlarkProvider provider =
StarlarkProvider.builder(Location.BUILTIN).setSchema(ImmutableList.of("field")).build();
StarlarkInfo instance1;
StarlarkInfo instance2;
StarlarkInfo instance3;
StarlarkInfo instance4;
StarlarkInfo instance5;
StarlarkInfo instance6;
try (Mutability mu = Mutability.create()) {
StarlarkThread thread = new StarlarkThread(mu, StarlarkSemantics.DEFAULT);
// Instantiates provider with values of different types all in the same field.
// Instance with an empty depset of string
instance1 =
(StarlarkInfo)
Starlark.call(
thread,
provider,
/* args= */ ImmutableList.of(),
/* kwargs= */ ImmutableMap.of(
"field", Depset.of(String.class, NestedSetBuilder.emptySet(STABLE_ORDER))));
// Instance with a non-empty depset of string
instance2 =
(StarlarkInfo)
Starlark.call(
thread,
provider,
/* args= */ ImmutableList.of(),
/* kwargs= */ ImmutableMap.of(
"field",
Depset.of(String.class, NestedSetBuilder.create(STABLE_ORDER, "foo"))));
// Instance with a non-empty depset of int
instance3 =
(StarlarkInfo)
Starlark.call(
thread,
provider,
/* args= */ ImmutableList.of(),
/* kwargs= */ ImmutableMap.of(
"field",
Depset.of(
StarlarkInt.class,
NestedSetBuilder.create(STABLE_ORDER, StarlarkInt.of(1)))));
// Instance with a string (not a depset)
instance4 =
(StarlarkInfo)
Starlark.call(
thread,
provider,
/* args= */ ImmutableList.of(),
/* kwargs= */ ImmutableMap.of("field", "foo"));
// Instance with a None
instance5 =
(StarlarkInfo)
Starlark.call(
thread,
provider,
/* args= */ ImmutableList.of(),
/* kwargs= */ ImmutableMap.of("field", Starlark.NONE));
// Instance with the field not set
instance6 =
(StarlarkInfo)
Starlark.call(
thread,
provider,
/* args= */ ImmutableList.of(),
/* kwargs= */ ImmutableMap.of());
}
assertThat(instance1.getValue("field")).isInstanceOf(Depset.class);
assertThat(((Depset) instance1.getValue("field")).isEmpty()).isTrue();
assertThat(instance2.getValue("field")).isInstanceOf(Depset.class);
assertThat(((Depset) instance2.getValue("field")).getElementClass()).isEqualTo(String.class);
assertThat(((Depset) instance2.getValue("field")).toList()).containsExactly("foo");
assertThat(instance3.getValue("field")).isInstanceOf(Depset.class);
assertThat(((Depset) instance3.getValue("field")).getElementClass())
.isEqualTo(StarlarkInt.class);
assertThat(((Depset) instance3.getValue("field")).toList()).containsExactly(StarlarkInt.of(1));
assertThat(instance4.getValue("field")).isEqualTo("foo");
assertThat(instance5.getValue("field")).isEqualTo(Starlark.NONE);
assertThat(instance6.getValue("field")).isNull();
}
@Test
public void schemafulProvider_mutable() throws Exception {
StarlarkProvider.Key key =
new StarlarkProvider.Key(Label.parseCanonical("//foo:bar.bzl"), "prov");
StarlarkProvider provider =
StarlarkProvider.builder(Location.BUILTIN)
.setSchema(ImmutableList.of("a"))
.setExported(key)
.build();
StarlarkInfo instance;
try (Mutability mu = Mutability.create()) {
StarlarkThread thread = new StarlarkThread(mu, StarlarkSemantics.DEFAULT);
instance =
(StarlarkInfo)
Starlark.call(
thread,
provider,
/* args= */ ImmutableList.of(),
/* kwargs= */ ImmutableMap.of("a", StarlarkList.of(mu, "x")));
@SuppressWarnings("unchecked")
StarlarkList<String> list = (StarlarkList<String>) instance.getValue("a");
list.addElement("y"); // verifies the fields of the provider instance are mutable
assertThat(instance.isImmutable()).isFalse();
}
@SuppressWarnings("unchecked")
StarlarkList<String> list = (StarlarkList<String>) instance.getValue("a");
assertThat((Iterable<?>) list).containsExactly("x", "y");
}
@Test
public void schemafulProvider_immutable() throws Exception {
StarlarkProvider.Key key =
new StarlarkProvider.Key(Label.parseCanonical("//foo:bar.bzl"), "prov");
StarlarkProvider provider =
StarlarkProvider.builder(Location.BUILTIN)
.setSchema(ImmutableList.of("a"))
.setExported(key)
.build();
StarlarkInfo instance;
try (Mutability mu = Mutability.create()) {
StarlarkThread thread = new StarlarkThread(mu, StarlarkSemantics.DEFAULT);
instance =
(StarlarkInfo)
Starlark.call(
thread,
provider,
/* args= */ ImmutableList.of(),
/* kwargs= */ ImmutableMap.of("a", StarlarkList.of(mu, "x")));
}
assertThat(instance.isImmutable()).isTrue();
@SuppressWarnings("unchecked")
StarlarkList<String> list = (StarlarkList<String>) instance.getValue("a");
assertThat((Iterable<?>) list).containsExactly("x");
// verifies the fields of the frozen provider instance are immutable
EvalException e = assertThrows(EvalException.class, () -> list.addElement("y"));
assertThat(e).hasMessageThat().contains("trying to mutate a frozen list value");
}
@Test
public void schemafulProviderWithDepset_isImmutable() throws Exception {
StarlarkProvider.Key key =
new StarlarkProvider.Key(Label.parseCanonical("//foo:bar.bzl"), "prov");
StarlarkProvider provider =
StarlarkProvider.builder(Location.BUILTIN)
.setSchema(ImmutableList.of("a"))
.setExported(key)
.build();
StarlarkInfo instance;
try (Mutability mu = Mutability.create()) {
StarlarkThread thread = new StarlarkThread(mu, StarlarkSemantics.DEFAULT);
instance =
(StarlarkInfo)
Starlark.call(
thread,
provider,
/* args= */ ImmutableList.of(),
/* kwargs= */ ImmutableMap.of(
"a", Depset.of(String.class, NestedSetBuilder.create(STABLE_ORDER, "foo"))));
assertThat(instance.isImmutable()).isTrue();
}
}
@Test
public void schemafulProviderWithDepset_becomesImmutable() throws Exception {
StarlarkProvider.Key key =
new StarlarkProvider.Key(Label.parseCanonical("//foo:bar.bzl"), "prov");
StarlarkProvider provider =
StarlarkProvider.builder(Location.BUILTIN)
.setSchema(ImmutableList.of("a", "b"))
.setExported(key)
.build();
StarlarkInfo instance;
try (Mutability mu = Mutability.create()) {
StarlarkThread thread = new StarlarkThread(mu, StarlarkSemantics.DEFAULT);
instance =
(StarlarkInfo)
Starlark.call(
thread,
provider,
/* args= */ ImmutableList.of(),
/* kwargs= */ ImmutableMap.of(
"a",
Depset.of(String.class, NestedSetBuilder.create(STABLE_ORDER, "foo")),
"b",
StarlarkList.of(mu, "x")));
assertThat(instance.isImmutable()).isFalse();
}
assertThat(instance.isImmutable()).isTrue();
}
@Test
public void schemafulProvider_optimisedImmutable() throws Exception {
StarlarkProvider.Key key =
new StarlarkProvider.Key(Label.parseCanonical("//foo:bar.bzl"), "prov");
StarlarkProvider provider =
StarlarkProvider.builder(Location.BUILTIN)
.setSchema(ImmutableList.of("a"))
.setExported(key)
.build();
StarlarkInfo instance;
try (Mutability mu = Mutability.create()) {
StarlarkThread thread = new StarlarkThread(mu, StarlarkSemantics.DEFAULT);
instance =
(StarlarkInfo)
Starlark.call(
thread,
provider,
/* args= */ ImmutableList.of(),
/* kwargs= */ ImmutableMap.of("a", StarlarkList.of(mu, "x")));
}
instance = instance.unsafeOptimizeMemoryLayout();
assertThat(instance.isImmutable()).isTrue();
@SuppressWarnings("unchecked")
StarlarkList<String> list = (StarlarkList<String>) instance.getValue("a");
assertThat((Iterable<?>) list).containsExactly("x");
// verifies the fields of the frozen and optimised provider instance are immutable
EvalException e = assertThrows(EvalException.class, () -> list.addElement("y"));
assertThat(e).hasMessageThat().contains("trying to mutate a frozen list value");
}
@Test
public void providerEquals() throws Exception {
// All permutations of differing label and differing name.
StarlarkProvider.Key keyFooA =
new StarlarkProvider.Key(Label.parseCanonical("//foo.bzl"), "provA");
StarlarkProvider.Key keyFooB =
new StarlarkProvider.Key(Label.parseCanonical("//foo.bzl"), "provB");
StarlarkProvider.Key keyBarA =
new StarlarkProvider.Key(Label.parseCanonical("//bar.bzl"), "provA");
StarlarkProvider.Key keyBarB =
new StarlarkProvider.Key(Label.parseCanonical("//bar.bzl"), "provB");
// 1 for each key, plus a duplicate for one of the keys, plus 2 that have no key.
StarlarkProvider provFooA1 =
StarlarkProvider.builder(Location.BUILTIN).setExported(keyFooA).build();
StarlarkProvider provFooA2 =
StarlarkProvider.builder(Location.BUILTIN).setExported(keyFooA).build();
StarlarkProvider provFooB =
StarlarkProvider.builder(Location.BUILTIN).setExported(keyFooB).build();
StarlarkProvider provBarA =
StarlarkProvider.builder(Location.BUILTIN).setExported(keyBarA).build();
StarlarkProvider provBarB =
StarlarkProvider.builder(Location.BUILTIN).setExported(keyBarB).build();
StarlarkProvider provUnexported1 = StarlarkProvider.builder(Location.BUILTIN).build();
StarlarkProvider provUnexported2 = StarlarkProvider.builder(Location.BUILTIN).build();
// For exported providers, different keys -> unequal, same key -> equal. For unexported
// providers it comes down to object identity.
new EqualsTester()
.addEqualityGroup(provFooA1, provFooA2)
.addEqualityGroup(provFooB)
.addEqualityGroup(provBarA, provBarA) // reflexive equality (exported)
.addEqualityGroup(provBarB)
.addEqualityGroup(provUnexported1, provUnexported1) // reflexive equality (unexported)
.addEqualityGroup(provUnexported2)
.testEquals();
}
/** Custom init equivalent to `def initBC(a): return {a:a, b:a*2, c:a*3}` */
private static final StarlarkCallable initBC =
new StarlarkCallable() {
@Override
public Object call(StarlarkThread thread, Tuple args, Dict<String, Object> kwargs)
throws EvalException {
if (!args.isEmpty()) {
throw Starlark.errorf("unexpected positional arguments");
}
if (kwargs.size() != 1 || !kwargs.containsKey("a")) {
throw Starlark.errorf("expected a single `a` argument");
}
StarlarkInt a = (StarlarkInt) kwargs.get("a");
return Dict.builder()
.put("a", a)
.put("b", StarlarkInt.of(a.toIntUnchecked() * 2))
.put("c", StarlarkInt.of(a.toIntUnchecked() * 3))
.build(Mutability.IMMUTABLE);
}
@Override
public String getName() {
return "initBC";
}
@Override
public Location getLocation() {
return Location.BUILTIN;
}
};
/** Instantiates a {@link StarlarkInfo} with fields a=1 (and nothing else). */
private static StarlarkInfo instantiateWithA1(StarlarkCallable provider) throws Exception {
try (Mutability mu = Mutability.create()) {
StarlarkThread thread = new StarlarkThread(mu, StarlarkSemantics.DEFAULT);
Object result =
Starlark.call(
thread,
provider,
/*args=*/ ImmutableList.of(),
/*kwargs=*/ ImmutableMap.of("a", StarlarkInt.of(1)));
assertThat(result).isInstanceOf(StarlarkInfo.class);
return (StarlarkInfo) result;
}
}
/** Instantiates a {@link StarlarkInfo} with fields a=1, b=2, c=3 (and nothing else). */
private static StarlarkInfo instantiateWithA1B2C3(StarlarkCallable provider) throws Exception {
try (Mutability mu = Mutability.create()) {
StarlarkThread thread = new StarlarkThread(mu, StarlarkSemantics.DEFAULT);
Object result =
Starlark.call(
thread,
provider,
/*args=*/ ImmutableList.of(),
/*kwargs=*/ ImmutableMap.of(
"a", StarlarkInt.of(1), "b", StarlarkInt.of(2), "c", StarlarkInt.of(3)));
assertThat(result).isInstanceOf(StarlarkInfo.class);
return (StarlarkInfo) result;
}
}
/** Asserts that a {@link StarlarkInfo} has field a=1 (and nothing else). */
private static void assertHasExactlyValuesA1(StarlarkInfo info) throws Exception {
assertThat(info.getFieldNames()).containsExactly("a");
assertThat(info.getValue("a")).isEqualTo(StarlarkInt.of(1));
}
/** Asserts that a {@link StarlarkInfo} has fields a=1, b=2, c=3 (and nothing else). */
private static void assertHasExactlyValuesA1B2C3(StarlarkInfo info) throws Exception {
assertThat(info.getFieldNames()).containsExactly("a", "b", "c");
assertThat(info.getValue("a")).isEqualTo(StarlarkInt.of(1));
assertThat(info.getValue("b")).isEqualTo(StarlarkInt.of(2));
assertThat(info.getValue("c")).isEqualTo(StarlarkInt.of(3));
}
}