| // 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.devtools.build.lib.testutil.MoreAsserts.assertThrows; |
| |
| 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.packages.SkylarkProvider.SkylarkKey; |
| import com.google.devtools.build.lib.syntax.Mutability; |
| import com.google.devtools.build.lib.syntax.Starlark; |
| import com.google.devtools.build.lib.syntax.StarlarkThread; |
| import org.junit.Test; |
| import org.junit.runner.RunWith; |
| import org.junit.runners.JUnit4; |
| |
| /** Tests for {@link SkylarkProvider}. */ |
| @RunWith(JUnit4.class) |
| public final class SkylarkProviderTest { |
| |
| @Test |
| public void unexportedProvider_Accessors() { |
| SkylarkProvider provider = SkylarkProvider.createUnexportedSchemaless(/*location=*/ null); |
| assertThat(provider.isExported()).isFalse(); |
| assertThat(provider.getName()).isEqualTo("<no name>"); |
| assertThat(provider.getPrintableName()).isEqualTo("<no name>"); |
| assertThat(provider.getErrorMessageFormatForUnknownField()) |
| .isEqualTo("Object has no '%s' attribute."); |
| assertThat(provider.isImmutable()).isFalse(); |
| assertThat(Starlark.repr(provider)).isEqualTo("<provider>"); |
| assertThrows( |
| IllegalStateException.class, |
| () -> provider.getKey()); |
| } |
| |
| @Test |
| public void exportedProvider_Accessors() throws Exception { |
| SkylarkKey key = |
| new SkylarkKey(Label.parseAbsolute("//foo:bar.bzl", ImmutableMap.of()), "prov"); |
| SkylarkProvider provider = SkylarkProvider.createExportedSchemaless(key, /*location=*/ null); |
| assertThat(provider.isExported()).isTrue(); |
| assertThat(provider.getName()).isEqualTo("prov"); |
| assertThat(provider.getPrintableName()).isEqualTo("prov"); |
| assertThat(provider.getErrorMessageFormatForUnknownField()) |
| .isEqualTo("'prov' value has no field or method '%s'"); |
| assertThat(provider.isImmutable()).isTrue(); |
| assertThat(Starlark.repr(provider)).isEqualTo("<provider>"); |
| assertThat(provider.getKey()).isEqualTo(key); |
| } |
| |
| @Test |
| public void schemalessProvider_Instantiation() throws Exception { |
| SkylarkProvider provider = SkylarkProvider.createUnexportedSchemaless(/*location=*/ null); |
| SkylarkInfo info = instantiateWithA1B2C3(provider); |
| assertHasExactlyValuesA1B2C3(info); |
| } |
| |
| @Test |
| public void schemafulProvider_Instantiation() throws Exception { |
| SkylarkProvider provider = SkylarkProvider.createUnexportedSchemaful( |
| ImmutableList.of("a", "b", "c"), /*location=*/ null); |
| SkylarkInfo info = instantiateWithA1B2C3(provider); |
| assertHasExactlyValuesA1B2C3(info); |
| } |
| |
| @Test |
| public void schemalessProvider_GetFields() throws Exception { |
| SkylarkProvider provider = SkylarkProvider.createUnexportedSchemaless(/*location=*/ null); |
| assertThat(provider.getFields()).isNull(); |
| } |
| |
| @Test |
| public void schemafulProvider_GetFields() throws Exception { |
| SkylarkProvider provider = SkylarkProvider.createUnexportedSchemaful( |
| ImmutableList.of("a", "b", "c"), /*location=*/ null); |
| assertThat(provider.getFields()).containsExactly("a", "b", "c").inOrder(); |
| } |
| |
| @Test |
| public void providerEquals() throws Exception { |
| // All permutations of differing label and differing name. |
| SkylarkKey keyFooA = |
| new SkylarkKey(Label.parseAbsolute("//foo.bzl", ImmutableMap.of()), "provA"); |
| SkylarkKey keyFooB = |
| new SkylarkKey(Label.parseAbsolute("//foo.bzl", ImmutableMap.of()), "provB"); |
| SkylarkKey keyBarA = |
| new SkylarkKey(Label.parseAbsolute("//bar.bzl", ImmutableMap.of()), "provA"); |
| SkylarkKey keyBarB = |
| new SkylarkKey(Label.parseAbsolute("//bar.bzl", ImmutableMap.of()), "provB"); |
| |
| // 1 for each key, plus a duplicate for one of the keys, plus 2 that have no key. |
| SkylarkProvider provFooA1 = |
| SkylarkProvider.createExportedSchemaless(keyFooA, /*location=*/ null); |
| SkylarkProvider provFooA2 = |
| SkylarkProvider.createExportedSchemaless(keyFooA, /*location=*/ null); |
| SkylarkProvider provFooB = |
| SkylarkProvider.createExportedSchemaless(keyFooB, /*location=*/ null); |
| SkylarkProvider provBarA = |
| SkylarkProvider.createExportedSchemaless(keyBarA, /*location=*/ null); |
| SkylarkProvider provBarB = |
| SkylarkProvider.createExportedSchemaless(keyBarB, /*location=*/ null); |
| SkylarkProvider provUnexported1 = |
| SkylarkProvider.createUnexportedSchemaless(/*location=*/ null); |
| SkylarkProvider provUnexported2 = |
| SkylarkProvider.createUnexportedSchemaless(/*location=*/ null); |
| |
| // 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(); |
| } |
| |
| /** Instantiates a {@link SkylarkInfo} with fields a=1, b=2, c=3 (and nothing else). */ |
| private static SkylarkInfo instantiateWithA1B2C3(SkylarkProvider provider) throws Exception{ |
| // Code under test begins with the entry point in BaseFunction. |
| StarlarkThread thread = |
| StarlarkThread.builder(Mutability.create("test")).useDefaultSemantics().build(); |
| Object result = |
| Starlark.call( |
| thread, |
| provider, |
| /*args=*/ ImmutableList.of(), |
| /*kwargs=*/ ImmutableMap.of("a", 1, "b", 2, "c", 3)); |
| assertThat(result).isInstanceOf(SkylarkInfo.class); |
| return (SkylarkInfo) result; |
| } |
| |
| /** Asserts that a {@link SkylarkInfo} has fields a=1, b=2, c=3 (and nothing else). */ |
| private static void assertHasExactlyValuesA1B2C3(SkylarkInfo info) throws Exception { |
| assertThat(info.getFieldNames()).containsExactly("a", "b", "c"); |
| assertThat(info.getValue("a")).isEqualTo(1); |
| assertThat(info.getValue("b")).isEqualTo(2); |
| assertThat(info.getValue("c")).isEqualTo(3); |
| } |
| } |