From 5bce925b57cc62d7173320521dbffb48eb36cff8 Mon Sep 17 00:00:00 2001 From: brandjon Date: Fri, 18 Jan 2019 15:12:58 -0800 Subject: [PATCH] Replace BazelPythonStarlarkApiTest with PythonStarlarkApiTest The rewritten test is non-Bazel specific and directly checks the sandwich use case. There's a slight loss in coverage that will be addressed with #7054. Work towards #1446. RELNOTES: None PiperOrigin-RevId: 230002328 --- .../python/BazelPythonStarlarkApiTest.java | 96 ---------------- .../devtools/build/lib/rules/python/BUILD | 13 +++ .../rules/python/PythonStarlarkApiTest.java | 105 ++++++++++++++++++ 3 files changed, 118 insertions(+), 96 deletions(-) delete mode 100644 src/test/java/com/google/devtools/build/lib/bazel/rules/python/BazelPythonStarlarkApiTest.java create mode 100644 src/test/java/com/google/devtools/build/lib/rules/python/PythonStarlarkApiTest.java diff --git a/src/test/java/com/google/devtools/build/lib/bazel/rules/python/BazelPythonStarlarkApiTest.java b/src/test/java/com/google/devtools/build/lib/bazel/rules/python/BazelPythonStarlarkApiTest.java deleted file mode 100644 index cd0262903534f7..00000000000000 --- a/src/test/java/com/google/devtools/build/lib/bazel/rules/python/BazelPythonStarlarkApiTest.java +++ /dev/null @@ -1,96 +0,0 @@ -// Copyright 2018 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.rules.python; - -import static com.google.common.truth.Truth.assertThat; -import static com.google.devtools.build.lib.actions.util.ActionsTestUtil.prettyArtifactNames; - -import com.google.devtools.build.lib.actions.Artifact; -import com.google.devtools.build.lib.analysis.ConfiguredTarget; -import com.google.devtools.build.lib.analysis.util.BuildViewTestCase; -import com.google.devtools.build.lib.packages.StructImpl; -import com.google.devtools.build.lib.rules.python.PyProvider; -import com.google.devtools.build.lib.syntax.SkylarkNestedSet; -import java.io.IOException; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.junit.runners.JUnit4; - -/** Python Starlark API test */ -@RunWith(JUnit4.class) -public class BazelPythonStarlarkApiTest extends BuildViewTestCase { - @Test - public void pythonProviderWithFields() throws Exception { - simpleSources(); - assertNoEvents(); - - ConfiguredTarget helloTarget = getConfiguredTarget("//py:hello"); - StructImpl provider = PyProvider.getProvider(helloTarget); - - assertThat(provider.hasField(PyProvider.TRANSITIVE_SOURCES)).isTrue(); - assertThat(provider.hasField(PyProvider.USES_SHARED_LIBRARIES)).isTrue(); - assertThat(provider.hasField(PyProvider.IMPORTS)).isTrue(); - assertThat(provider.hasField("srcs")).isFalse(); - } - - @Test - public void simpleFieldsValues() throws Exception { - simpleSources(); - assertNoEvents(); - - ConfiguredTarget helloTarget = getConfiguredTarget("//py:hello"); - StructImpl provider = PyProvider.getProvider(helloTarget); - - SkylarkNestedSet sources = (SkylarkNestedSet) provider.getValue(PyProvider.TRANSITIVE_SOURCES); - assertThat(prettyArtifactNames(sources.getSet(Artifact.class))).containsExactly("py/hello.py"); - - assertThat((Boolean) provider.getValue(PyProvider.USES_SHARED_LIBRARIES)).isFalse(); - - SkylarkNestedSet imports = (SkylarkNestedSet) provider.getValue(PyProvider.IMPORTS); - assertThat(imports.getSet(String.class)).containsExactly("__main__/py"); - } - - @Test - public void transitiveFieldsValues() throws Exception { - simpleSources(); - assertNoEvents(); - - ConfiguredTarget helloTarget = getConfiguredTarget("//py:sayHello"); - StructImpl provider = PyProvider.getProvider(helloTarget); - - SkylarkNestedSet sources = (SkylarkNestedSet) provider.getValue(PyProvider.TRANSITIVE_SOURCES); - assertThat(prettyArtifactNames(sources.getSet(Artifact.class))) - .containsExactly("py/hello.py", "py/sayHello.py"); - - assertThat((Boolean) provider.getValue(PyProvider.USES_SHARED_LIBRARIES)).isFalse(); - - SkylarkNestedSet imports = (SkylarkNestedSet) provider.getValue(PyProvider.IMPORTS); - assertThat(imports.getSet(String.class)).containsExactly("__main__/py"); - } - - private void simpleSources() throws IOException { - scratch.file( - "py/hello.py", - "import os", - "def Hello():", - " print(\"Hello, World!\")", - " print(\"Hello, \" + os.getcwd() + \"!\")"); - scratch.file("py/sayHello.py", "from py import hello", "hello.Hello()"); - scratch.file( - "py/BUILD", - "py_binary(name=\"sayHello\", srcs=[\"sayHello.py\"], deps=[\":hello\"])", - "py_library(name=\"hello\", srcs=[\"hello.py\"], imports= [\".\"])"); - } -} diff --git a/src/test/java/com/google/devtools/build/lib/rules/python/BUILD b/src/test/java/com/google/devtools/build/lib/rules/python/BUILD index 18b32986863573..2c9c572a2c2861 100644 --- a/src/test/java/com/google/devtools/build/lib/rules/python/BUILD +++ b/src/test/java/com/google/devtools/build/lib/rules/python/BUILD @@ -18,6 +18,7 @@ test_suite( ":PyProviderTest", ":PyTestConfiguredTargetTest", ":PythonConfigurationTest", + ":PythonStarlarkApiTest", ":PythonVersionSelectTest", ":PythonVersionTest", ], @@ -171,3 +172,15 @@ java_test( "//third_party:truth", ], ) + +java_test( + name = "PythonStarlarkApiTest", + srcs = ["PythonStarlarkApiTest.java"], + deps = [ + "//src/main/java/com/google/devtools/build/lib:packages-internal", + "//src/main/java/com/google/devtools/build/lib:python-rules", + "//src/test/java/com/google/devtools/build/lib:analysis_testutil", + "//third_party:junit4", + "//third_party:truth", + ], +) diff --git a/src/test/java/com/google/devtools/build/lib/rules/python/PythonStarlarkApiTest.java b/src/test/java/com/google/devtools/build/lib/rules/python/PythonStarlarkApiTest.java new file mode 100644 index 00000000000000..6e9f63af9b5002 --- /dev/null +++ b/src/test/java/com/google/devtools/build/lib/rules/python/PythonStarlarkApiTest.java @@ -0,0 +1,105 @@ +// 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.analysis.util.BuildViewTestCase; +import com.google.devtools.build.lib.packages.StructImpl; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.JUnit4; + +/** Tests the ability of Starlark code to interact with the Python rules via the py provider. */ +@RunWith(JUnit4.class) +public class PythonStarlarkApiTest extends BuildViewTestCase { + + // TODO(#7054): Imports aren't propagated correctly. When we fix that, add it to the fields + // tested here. + + /** Defines userlib in //pkg:rules.bzl, which acts as a Starlark-defined version of py_library. */ + private void defineUserlibRule() throws Exception { + scratch.file( + "pkg/rules.bzl", + "def _userlib_impl(ctx):", + " dep_infos = [dep.py for dep in ctx.attr.deps]", + " transitive_sources = depset(", + " direct=ctx.files.srcs,", + " transitive=[py.transitive_sources for py in dep_infos],", + " order='postorder')", + " uses_shared_libraries = \\", + " any([py.uses_shared_libraries for py in dep_infos]) or \\", + " ctx.attr.uses_shared_libraries", + " has_py2_only_sources = \\", + " any([py.has_py2_only_sources for py in dep_infos]) or \\", + " ctx.attr.has_py2_only_sources", + " has_py3_only_sources = \\", + " any([py.has_py3_only_sources for py in dep_infos]) or \\", + " ctx.attr.has_py3_only_sources", + " info = struct(", + " transitive_sources = transitive_sources,", + " uses_shared_libraries = uses_shared_libraries,", + " has_py2_only_sources = has_py2_only_sources,", + " has_py3_only_sources = has_py3_only_sources)", + " return struct(py=info)", + "", + "userlib = rule(", + " implementation = _userlib_impl,", + " attrs = {", + " 'srcs': attr.label_list(allow_files=True),", + " 'deps': attr.label_list(providers=['py']),", + " 'uses_shared_libraries': attr.bool(),", + " 'has_py2_only_sources': attr.bool(),", + " 'has_py3_only_sources': attr.bool(),", + " },", + ")"); + } + + @Test + public void librarySandwich() throws Exception { + // Use new version semantics so we don't validate source versions in py_library. + useConfiguration("--experimental_allow_python_version_transitions=true"); + defineUserlibRule(); + scratch.file( + "pkg/BUILD", + "load(':rules.bzl', 'userlib')", + "userlib(", + " name = 'loweruserlib',", + " srcs = ['loweruserlib.py'],", + " uses_shared_libraries = True,", + " has_py2_only_sources = True,", + ")", + "py_library(", + " name = 'pylib',", + " srcs = ['pylib.py'],", + " deps = [':loweruserlib'],", + " srcs_version = 'PY3ONLY'", + ")", + "userlib(", + " name = 'upperuserlib',", + " srcs = ['upperuserlib.py'],", + " deps = [':pylib'],", + ")"); + StructImpl info = PyProvider.getProvider(getConfiguredTarget("//pkg:upperuserlib")); + assertThat(PyProvider.getTransitiveSources(info)) + .containsExactly( + getSourceArtifact("pkg/loweruserlib.py"), + getSourceArtifact("pkg/pylib.py"), + getSourceArtifact("pkg/upperuserlib.py")); + assertThat(PyProvider.getUsesSharedLibraries(info)).isTrue(); + assertThat(PyProvider.getHasPy2OnlySources(info)).isTrue(); + assertThat(PyProvider.getHasPy3OnlySources(info)).isTrue(); + } +}