| // Copyright 2019 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.rules.python; |
| |
| import static com.google.common.truth.Truth.assertThat; |
| |
| import com.google.devtools.build.lib.actions.Artifact; |
| import com.google.devtools.build.lib.collect.nestedset.NestedSet; |
| import com.google.devtools.build.lib.collect.nestedset.NestedSetBuilder; |
| import com.google.devtools.build.lib.collect.nestedset.Order; |
| import com.google.devtools.build.lib.events.Location; |
| import com.google.devtools.build.lib.skylark.util.SkylarkTestCase; |
| import org.junit.Before; |
| import org.junit.Test; |
| import org.junit.runner.RunWith; |
| import org.junit.runners.JUnit4; |
| |
| /** Tests for {@link PyInfo}. */ |
| @RunWith(JUnit4.class) |
| public class PyInfoTest extends SkylarkTestCase { |
| |
| private Artifact dummyArtifact; |
| |
| @Before |
| public void setUp() throws Exception { |
| dummyArtifact = getSourceArtifact("dummy"); |
| update("PyInfo", PyInfo.PROVIDER); |
| update("dummy_file", dummyArtifact); |
| } |
| |
| /** We need this because {@code NestedSet}s don't have value equality. */ |
| private static void assertHasOrderAndContainsExactly( |
| NestedSet<?> set, Order order, Object... values) { |
| assertThat(set.getOrder()).isEqualTo(order); |
| assertThat(set.toList()).containsExactly(values); |
| } |
| |
| /** Checks values set by the builder. */ |
| @Test |
| public void builderExplicit() throws Exception { |
| NestedSet<Artifact> sources = NestedSetBuilder.create(Order.COMPILE_ORDER, dummyArtifact); |
| NestedSet<String> imports = NestedSetBuilder.create(Order.COMPILE_ORDER, "abc"); |
| Location loc = Location.fromFileLineColumn("foo", 1, 2); |
| PyInfo info = |
| PyInfo.builder() |
| .setLocation(loc) |
| .setTransitiveSources(sources) |
| .setUsesSharedLibraries(true) |
| .setImports(imports) |
| .setHasPy2OnlySources(true) |
| .setHasPy3OnlySources(true) |
| .build(); |
| assertThat(info.getCreationLoc()).isEqualTo(loc); |
| assertHasOrderAndContainsExactly( |
| info.getTransitiveSources().getSet(Artifact.class), Order.COMPILE_ORDER, dummyArtifact); |
| assertThat(info.getUsesSharedLibraries()).isTrue(); |
| assertHasOrderAndContainsExactly( |
| info.getImports().getSet(String.class), Order.COMPILE_ORDER, "abc"); |
| assertThat(info.getHasPy2OnlySources()).isTrue(); |
| assertThat(info.getHasPy3OnlySources()).isTrue(); |
| } |
| |
| /** Checks the defaults set by the builder. */ |
| @Test |
| public void builderDefaults() throws Exception { |
| // transitive_sources is mandatory, so create a dummy value but no need to assert on it. |
| NestedSet<Artifact> sources = NestedSetBuilder.create(Order.COMPILE_ORDER, dummyArtifact); |
| PyInfo info = PyInfo.builder().setTransitiveSources(sources).build(); |
| assertThat(info.getCreationLoc()).isEqualTo(Location.BUILTIN); |
| assertThat(info.getUsesSharedLibraries()).isFalse(); |
| assertHasOrderAndContainsExactly(info.getImports().getSet(String.class), Order.COMPILE_ORDER); |
| assertThat(info.getHasPy2OnlySources()).isFalse(); |
| assertThat(info.getHasPy3OnlySources()).isFalse(); |
| } |
| |
| @Test |
| public void starlarkConstructor() throws Exception { |
| exec( |
| "info = PyInfo(", |
| " transitive_sources = depset(direct=[dummy_file]),", |
| " uses_shared_libraries = True,", |
| " imports = depset(direct=['abc']),", |
| " has_py2_only_sources = True,", |
| " has_py3_only_sources = True,", |
| ")"); |
| PyInfo info = (PyInfo) lookup("info"); |
| assertThat(info.getCreationLoc().toString()).isEqualTo(":1:8"); |
| assertHasOrderAndContainsExactly( |
| info.getTransitiveSources().getSet(Artifact.class), Order.STABLE_ORDER, dummyArtifact); |
| assertThat(info.getUsesSharedLibraries()).isTrue(); |
| assertHasOrderAndContainsExactly( |
| info.getImports().getSet(String.class), Order.STABLE_ORDER, "abc"); |
| assertThat(info.getHasPy2OnlySources()).isTrue(); |
| assertThat(info.getHasPy3OnlySources()).isTrue(); |
| } |
| |
| @Test |
| public void starlarkConstructorDefaults() throws Exception { |
| exec("info = PyInfo(transitive_sources = depset(direct=[dummy_file]))"); |
| PyInfo info = (PyInfo) lookup("info"); |
| assertThat(info.getCreationLoc().toString()).isEqualTo(":1:8"); |
| assertHasOrderAndContainsExactly( |
| info.getTransitiveSources().getSet(Artifact.class), Order.STABLE_ORDER, dummyArtifact); |
| assertThat(info.getUsesSharedLibraries()).isFalse(); |
| assertHasOrderAndContainsExactly(info.getImports().getSet(String.class), Order.COMPILE_ORDER); |
| assertThat(info.getHasPy2OnlySources()).isFalse(); |
| assertThat(info.getHasPy3OnlySources()).isFalse(); |
| } |
| |
| @Test |
| public void starlarkConstructorErrors_TransitiveSources() throws Exception { |
| checkEvalErrorContains( |
| "missing 1 required named argument: transitive_sources", // |
| "PyInfo()"); |
| checkEvalErrorContains( |
| "got value of type 'string', want 'depset of Files'", "PyInfo(transitive_sources = 'abc')"); |
| checkEvalErrorContains( |
| "got value of type 'depset', want 'depset of Files'", |
| "PyInfo(transitive_sources = depset(direct=['abc']))"); |
| checkEvalErrorContains( |
| "'transitive_sources' field should be a postorder-compatible depset of Files", |
| "PyInfo(transitive_sources = depset(direct=[dummy_file], order='preorder'))"); |
| } |
| |
| @Test |
| public void starlarkConstructorErrors_UsesSharedLibraries() throws Exception { |
| checkEvalErrorContains( |
| "got value of type 'string', want 'bool'", |
| "PyInfo(transitive_sources = depset([]), uses_shared_libraries = 'abc')"); |
| } |
| |
| @Test |
| public void starlarkConstructorErrors_Imports() throws Exception { |
| checkEvalErrorContains( |
| "got value of type 'string', want 'depset of strings'", |
| "PyInfo(transitive_sources = depset([]), imports = 'abc')"); |
| checkEvalErrorContains( |
| "got value of type 'depset', want 'depset of strings'", |
| "PyInfo(transitive_sources = depset([]), imports = depset(direct=[123]))"); |
| } |
| |
| @Test |
| public void starlarkConstructorErrors_HasPy2OnlySources() throws Exception { |
| checkEvalErrorContains( |
| "got value of type 'string', want 'bool'", |
| "PyInfo(transitive_sources = depset([]), has_py2_only_sources = 'abc')"); |
| } |
| |
| @Test |
| public void starlarkConstructorErrors_HasPy3OnlySources() throws Exception { |
| checkEvalErrorContains( |
| "got value of type 'string', want 'bool'", |
| "PyInfo(transitive_sources = depset([]), has_py3_only_sources = 'abc')"); |
| } |
| } |