From 7a230fddd4db33bccc0ae99f46a91b48a668edbb Mon Sep 17 00:00:00 2001 From: Richard Levasseur Date: Fri, 17 Jun 2022 14:19:32 -0700 Subject: [PATCH] Make Bazel tests compatible with Starlark implementation of Python rules Summary of changes: * Remove usage of Python rules where not necessary; the Python rules were/are being used to test features that aren't specific to the Python rules. * Use regex matching for failures instead of exact strings. The Starlark rules have slightly different phrasing or orderings of elements that don't affect behavior. This also makes the tests less brittle overall. * Disable attempting to use the Starlark implementation in all the tests requiring Python 2 (e.g. srcs_version checking etc). The Starlark implementation doesn't currently (and probably never will) support Python 2. https://github.com/bazelbuild/bazel/issues/15684 filed to track removal of it in Bazel. * Disable attempting to use the Starlark implementation where toolchain resolution is required. This will eventually be implemented, but isn't is use at Google and otherwise blocks switching internally. * Tests verifying warnings are printed were removed; Starlark doesn't provide a warning facility. * Stamping is disabled in various tests because, with the Starlark implementation, it requires remote execution of actions, which some tests aren't setup for (they never needed it previously). Rather than set this up, stamping was disabled (affected tests don't require stamping anyways). PiperOrigin-RevId: 455695015 Change-Id: I82822eff05b6c0a66e65f131c9e1c8784b1573ac --- .../build/lib/rules/cpp/CcBinary.java | 5 ++ .../PyBaseConfiguredTargetTestBase.java | 9 ++- .../python/PyBinaryConfiguredTargetTest.java | 18 +++-- .../PyExecutableConfiguredTargetTestBase.java | 28 ++++--- .../python/PyLibraryConfiguredTargetTest.java | 8 -- .../python/PythonSrcsVersionAspectTest.java | 8 ++ .../rules/python/PythonStarlarkApiTest.java | 5 +- .../lib/starlark/StarlarkRuleContextTest.java | 5 -- src/test/shell/integration/aquery_test.sh | 1 - .../integration/modify_execution_info_test.sh | 6 +- .../shell/integration/python_stub_test.sh | 20 ++++- src/test/shell/integration/python_test.sh | 24 ++++-- src/test/shell/integration/runfiles_test.sh | 74 ++++++++++++------- 13 files changed, 132 insertions(+), 79 deletions(-) diff --git a/src/main/java/com/google/devtools/build/lib/rules/cpp/CcBinary.java b/src/main/java/com/google/devtools/build/lib/rules/cpp/CcBinary.java index 228da6740de82c..f826b849de65e5 100644 --- a/src/main/java/com/google/devtools/build/lib/rules/cpp/CcBinary.java +++ b/src/main/java/com/google/devtools/build/lib/rules/cpp/CcBinary.java @@ -170,6 +170,11 @@ public CcCompilationOutputs getCcCompilationOutputs(RuleContext ruleContext) { return ccCompilationOutputs; } + @VisibleForTesting + public CcCompilationOutputs getCcCompilationOutputsForTesting() { + return ccCompilationOutputs; + } + @StarlarkMethod(name = "compilation_outputs", documented = false, useStarlarkThread = true) public CcCompilationOutputs getCcCompilationOutputsStarlark(StarlarkThread thread) throws EvalException { diff --git a/src/test/java/com/google/devtools/build/lib/rules/python/PyBaseConfiguredTargetTestBase.java b/src/test/java/com/google/devtools/build/lib/rules/python/PyBaseConfiguredTargetTestBase.java index 5f1ec405a43cd7..810853d84ee94b 100644 --- a/src/test/java/com/google/devtools/build/lib/rules/python/PyBaseConfiguredTargetTestBase.java +++ b/src/test/java/com/google/devtools/build/lib/rules/python/PyBaseConfiguredTargetTestBase.java @@ -18,6 +18,7 @@ import com.google.devtools.build.lib.analysis.ConfiguredTarget; import com.google.devtools.build.lib.analysis.util.BuildViewTestCase; +import java.util.regex.Pattern; import org.junit.Before; import org.junit.Test; @@ -42,11 +43,11 @@ protected PythonVersion getPythonVersion(ConfiguredTarget ct) { @Test public void badSrcsVersionValue() throws Exception { - checkError("pkg", "foo", + checkError( + "pkg", + "foo", // error: - "invalid value in 'srcs_version' attribute: " - + "has to be one of 'PY2', 'PY3', 'PY2AND3', 'PY2ONLY' " - + "or 'PY3ONLY' instead of 'doesnotexist'", + Pattern.compile(".*invalid value.*srcs_version.*"), // build file: ruleName + "(", " name = 'foo',", diff --git a/src/test/java/com/google/devtools/build/lib/rules/python/PyBinaryConfiguredTargetTest.java b/src/test/java/com/google/devtools/build/lib/rules/python/PyBinaryConfiguredTargetTest.java index 7afa8e11aadbdc..4e2ea704941a51 100644 --- a/src/test/java/com/google/devtools/build/lib/rules/python/PyBinaryConfiguredTargetTest.java +++ b/src/test/java/com/google/devtools/build/lib/rules/python/PyBinaryConfiguredTargetTest.java @@ -19,6 +19,7 @@ import com.google.devtools.build.lib.analysis.ConfiguredTarget; import com.google.devtools.build.lib.analysis.configuredtargets.FileConfiguredTarget; import com.google.devtools.build.lib.testutil.TestConstants; +import java.util.regex.Pattern; import org.junit.Test; import org.junit.runner.RunWith; import org.junit.runners.JUnit4; @@ -50,6 +51,7 @@ private void declareBinDependingOnLibWithVersions(String binVersion, String libS @Test public void python2WithPy3SrcsVersionDependency() throws Exception { + setBuildLanguageOptions("--experimental_builtins_injection_override=-py_test,-py_binary"); declareBinDependingOnLibWithVersions("PY2", "PY3"); assertThat(getPyExecutableDeferredError("//pkg:bin")) .startsWith( @@ -59,6 +61,7 @@ public void python2WithPy3SrcsVersionDependency() throws Exception { @Test public void python2WithPy3OnlySrcsVersionDependency() throws Exception { + setBuildLanguageOptions("--experimental_builtins_injection_override=-py_test,-py_binary"); declareBinDependingOnLibWithVersions("PY2", "PY3ONLY"); assertThat(getPyExecutableDeferredError("//pkg:bin")) .contains("being built for Python 2 but (transitively) includes Python 3-only sources"); @@ -66,6 +69,7 @@ public void python2WithPy3OnlySrcsVersionDependency() throws Exception { @Test public void python3WithPy2OnlySrcsVersionDependency_NewSemantics() throws Exception { + setBuildLanguageOptions("--experimental_builtins_injection_override=-py_test,-py_binary"); declareBinDependingOnLibWithVersions("PY3", "PY2ONLY"); assertThat(getPyExecutableDeferredError("//pkg:bin")) .contains("being built for Python 3 but (transitively) includes Python 2-only sources"); @@ -140,10 +144,11 @@ public void defaultMainCannotBeAmbiguous() throws Exception { "py_binary(", " name = 'foo',", " srcs = ['bar.py'])"); - checkError("pkg2", "bar", + checkError( + "pkg2", + "bar", // error: - "default main file name 'bar.py' matches multiple files. Perhaps specify an explicit file " - + "with 'main' attribute? Matches were: 'pkg2/bar.py' and 'pkg1/bar.py'", + Pattern.compile(".*bar.py.*matches multiple.*"), // build file: "py_binary(", " name = 'bar',", @@ -156,10 +161,11 @@ public void explicitMainCannotBeAmbiguous() throws Exception { "py_binary(", " name = 'foo',", " srcs = ['bar.py'])"); - checkError("pkg2", "foo", + checkError( + "pkg2", + "foo", // error: - "file name 'bar.py' specified by 'main' attribute matches multiple files: e.g., " - + "'pkg2/bar.py' and 'pkg1/bar.py'", + Pattern.compile(".*bar.py.*matches multiple.*"), // build file: "py_binary(", " name = 'foo',", diff --git a/src/test/java/com/google/devtools/build/lib/rules/python/PyExecutableConfiguredTargetTestBase.java b/src/test/java/com/google/devtools/build/lib/rules/python/PyExecutableConfiguredTargetTestBase.java index d52bc388dd4de8..c59bb897db8335 100644 --- a/src/test/java/com/google/devtools/build/lib/rules/python/PyExecutableConfiguredTargetTestBase.java +++ b/src/test/java/com/google/devtools/build/lib/rules/python/PyExecutableConfiguredTargetTestBase.java @@ -16,7 +16,6 @@ import static com.google.common.truth.Truth.assertThat; import static com.google.common.truth.Truth.assertWithMessage; -import static com.google.devtools.build.lib.rules.python.PythonTestUtils.assumesDefaultIsPY2; import com.google.common.base.Joiner; import com.google.common.base.Preconditions; @@ -127,6 +126,8 @@ private String ruleDeclWithPyVersionAttr(String name, String version) { @Test public void pyRuntimeInfoIsPresent() throws Exception { + // Starlark implementation doesn't yet support toolchain resolution. + setBuildLanguageOptions("--experimental_builtins_injection_override=-py_test,-py_binary"); useConfiguration("--incompatible_use_python_toolchains=true"); scratch.file( "pkg/BUILD", // @@ -163,13 +164,14 @@ public void versionAttr_BadValue() throws Exception { @Test public void versionAttr_GoodValue() throws Exception { - scratch.file("pkg/BUILD", ruleDeclWithPyVersionAttr("foo", "PY2")); + scratch.file("pkg/BUILD", ruleDeclWithPyVersionAttr("foo", "PY3")); getOkPyTarget("//pkg:foo"); assertNoEvents(); } @Test public void py3IsDefaultFlag_SetsDefaultPythonVersion() throws Exception { + setBuildLanguageOptions("--experimental_builtins_injection_override=-py_test,-py_binary"); scratch.file( "pkg/BUILD", // ruleName + "(", @@ -190,6 +192,7 @@ public void py3IsDefaultFlag_SetsDefaultPythonVersion() throws Exception { @Test public void py3IsDefaultFlag_DoesntOverrideExplicitVersion() throws Exception { + setBuildLanguageOptions("--experimental_builtins_injection_override=-py_test,-py_binary"); scratch.file("pkg/BUILD", ruleDeclWithPyVersionAttr("foo", "PY2")); assertPythonVersionIs_UnderNewConfig( "//pkg:foo", @@ -203,23 +206,22 @@ public void py3IsDefaultFlag_DoesntOverrideExplicitVersion() throws Exception { @Test public void versionAttrWorks_WhenNotDefaultValue() throws Exception { - assumesDefaultIsPY2(); - scratch.file("pkg/BUILD", ruleDeclWithPyVersionAttr("foo", "PY3")); + setBuildLanguageOptions("--experimental_builtins_injection_override=-py_test,-py_binary"); + scratch.file("pkg/BUILD", ruleDeclWithPyVersionAttr("foo", "PY2")); - assertPythonVersionIs("//pkg:foo", PythonVersion.PY3); + assertPythonVersionIs("//pkg:foo", PythonVersion.PY2); } @Test public void versionAttrWorks_WhenSameAsDefaultValue() throws Exception { - assumesDefaultIsPY2(); - scratch.file("pkg/BUILD", ruleDeclWithPyVersionAttr("foo", "PY2")); + scratch.file("pkg/BUILD", ruleDeclWithPyVersionAttr("foo", "PY3")); - assertPythonVersionIs("//pkg:foo", PythonVersion.PY2); + assertPythonVersionIs("//pkg:foo", PythonVersion.PY3); } @Test public void versionAttrTakesPrecedence_NonDefaultValue() throws Exception { - assumesDefaultIsPY2(); + setBuildLanguageOptions("--experimental_builtins_injection_override=-py_test,-py_binary"); scratch.file("pkg/BUILD", ruleDeclWithPyVersionAttr("foo", "PY3")); assertPythonVersionIs_UnderNewConfig("//pkg:foo", PythonVersion.PY3, "--python_version=PY2"); @@ -227,14 +229,15 @@ public void versionAttrTakesPrecedence_NonDefaultValue() throws Exception { @Test public void versionAttrTakesPrecedence_DefaultValue() throws Exception { - assumesDefaultIsPY2(); - scratch.file("pkg/BUILD", ruleDeclWithPyVersionAttr("foo", "PY2")); + setBuildLanguageOptions("--experimental_builtins_injection_override=-py_test,-py_binary"); + scratch.file("pkg/BUILD", ruleDeclWithPyVersionAttr("foo", "PY3")); - assertPythonVersionIs_UnderNewConfig("//pkg:foo", PythonVersion.PY2, "--python_version=PY3"); + assertPythonVersionIs_UnderNewConfig("//pkg:foo", PythonVersion.PY3, "--python_version=PY2"); } @Test public void canBuildWithDifferentVersionAttrs() throws Exception { + setBuildLanguageOptions("--experimental_builtins_injection_override=-py_test,-py_binary"); scratch.file( "pkg/BUILD", ruleDeclWithPyVersionAttr("foo_v2", "PY2"), @@ -246,6 +249,7 @@ public void canBuildWithDifferentVersionAttrs() throws Exception { @Test public void incompatibleSrcsVersion() throws Exception { + setBuildLanguageOptions("--experimental_builtins_injection_override=-py_test,-py_binary"); reporter.removeHandler(failFastHandler); // We assert below that we don't fail at analysis. scratch.file( "pkg/BUILD", diff --git a/src/test/java/com/google/devtools/build/lib/rules/python/PyLibraryConfiguredTargetTest.java b/src/test/java/com/google/devtools/build/lib/rules/python/PyLibraryConfiguredTargetTest.java index d7ef07e0d32454..4e767a39995326 100644 --- a/src/test/java/com/google/devtools/build/lib/rules/python/PyLibraryConfiguredTargetTest.java +++ b/src/test/java/com/google/devtools/build/lib/rules/python/PyLibraryConfiguredTargetTest.java @@ -120,14 +120,6 @@ public void whatIfSrcsContainsRuleGeneratingNoPyFiles() throws Exception { "'//pkg:bar' does not produce any py_binary srcs files", // build file: lines); - } else { - checkWarning( - "pkg", - "foo", - // warning: - "rule '//pkg:bar' does not produce any Python source files", - // build file: - lines); } } diff --git a/src/test/java/com/google/devtools/build/lib/rules/python/PythonSrcsVersionAspectTest.java b/src/test/java/com/google/devtools/build/lib/rules/python/PythonSrcsVersionAspectTest.java index a80db9474b6b79..3ae0f09dbf8604 100644 --- a/src/test/java/com/google/devtools/build/lib/rules/python/PythonSrcsVersionAspectTest.java +++ b/src/test/java/com/google/devtools/build/lib/rules/python/PythonSrcsVersionAspectTest.java @@ -58,6 +58,7 @@ private String evaluateAspectFor(String label) throws Exception { @Test public void simpleCase() throws Exception { + setBuildLanguageOptions("--experimental_builtins_injection_override=-py_test,-py_binary"); scratch.file( "pkg/BUILD", "py_library(", @@ -115,6 +116,7 @@ public void noRequirements() throws Exception { @Test public void twoContradictoryRequirements() throws Exception { + setBuildLanguageOptions("--experimental_builtins_injection_override=-py_test,-py_binary"); scratch.file( "pkg/BUILD", "py_library(", @@ -150,6 +152,7 @@ public void twoContradictoryRequirements() throws Exception { @Test public void toplevelSelfContradictory() throws Exception { + setBuildLanguageOptions("--experimental_builtins_injection_override=-py_test,-py_binary"); scratch.file( "pkg/BUILD", "py_binary(", @@ -175,6 +178,7 @@ public void toplevelSelfContradictory() throws Exception { @Test public void indirectDependencies() throws Exception { + setBuildLanguageOptions("--experimental_builtins_injection_override=-py_test,-py_binary"); // A <- B <- C <- bin, where only B has the constraint. scratch.file( "pkg/BUILD", @@ -215,6 +219,7 @@ public void indirectDependencies() throws Exception { @Test public void onlyReportTopmost() throws Exception { + setBuildLanguageOptions("--experimental_builtins_injection_override=-py_test,-py_binary"); // A <- B <- C <- bin, where A and C have the constraint. scratch.file( "pkg/BUILD", @@ -256,6 +261,7 @@ public void onlyReportTopmost() throws Exception { @Test public void oneTopmostReachesAnother() throws Exception { + setBuildLanguageOptions("--experimental_builtins_injection_override=-py_test,-py_binary"); // A <- B <- C, where A and C have the constraint. // A <- bin and C <- bin, so both A and C are top-most even though C has a path to A. scratch.file( @@ -300,6 +306,7 @@ public void oneTopmostReachesAnother() throws Exception { @Test public void multiplePathsToRequirement() throws Exception { + setBuildLanguageOptions("--experimental_builtins_injection_override=-py_test,-py_binary"); // Diamond graph A <- B, A <- C, B <- bin, C <- bin, where only A has the constraint. // A is reached through two different paths but reported only once. scratch.file( @@ -341,6 +348,7 @@ public void multiplePathsToRequirement() throws Exception { @Test public void noSrcsVersionButIntroducesRequirement() throws Exception { + setBuildLanguageOptions("--experimental_builtins_injection_override=-py_test,-py_binary"); // A <- B <- C <- bin, B introduces the requirement but not via srcs_version. // dummy_rule propagates sources and sets the py3-only bit. scratch.file( 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 index 8614eb3c3e35dc..d82059f4184ff1 100644 --- 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 @@ -165,7 +165,10 @@ public void runtimeSandwich() throws Exception { " name = 'pybin',", " srcs = ['pybin.py'],", ")"); - useConfiguration("--extra_toolchains=//pkg:usertoolchain"); + useConfiguration( + "--extra_toolchains=//pkg:usertoolchain", "--incompatible_use_python_toolchains=true"); + // Starlark implementation doesn't yet support toolchain resolution + setBuildLanguageOptions("--experimental_builtins_injection_override=-py_test,-py_binary"); ConfiguredTarget target = getConfiguredTarget("//pkg:pybin"); assertThat(collectRunfiles(target).toList()) .containsAtLeast(getSourceArtifact("pkg/data.txt"), getSourceArtifact("pkg/userdata.txt")); diff --git a/src/test/java/com/google/devtools/build/lib/starlark/StarlarkRuleContextTest.java b/src/test/java/com/google/devtools/build/lib/starlark/StarlarkRuleContextTest.java index b8a9b1dcc3b531..0a3d510392ca2b 100644 --- a/src/test/java/com/google/devtools/build/lib/starlark/StarlarkRuleContextTest.java +++ b/src/test/java/com/google/devtools/build/lib/starlark/StarlarkRuleContextTest.java @@ -1675,11 +1675,6 @@ public void testAccessingRunfiles() throws Exception { assertThat(filenames).isInstanceOf(Sequence.class); Sequence filenamesList = (Sequence) filenames; assertThat(filenamesList).containsAtLeast("test/lib.py", "test/lib2.py"); - Object emptyFilenames = - ev.eval("ruleContext.attr.dep.default_runfiles.empty_filenames.to_list()"); - assertThat(emptyFilenames).isInstanceOf(Sequence.class); - Sequence emptyFilenamesList = (Sequence) emptyFilenames; - assertThat(emptyFilenamesList).containsExactly("test/__init__.py"); setRuleContext(createRuleContext("//test:foo_with_init")); Object noEmptyFilenames = diff --git a/src/test/shell/integration/aquery_test.sh b/src/test/shell/integration/aquery_test.sh index eee4a152550b87..ba6f553883d4fc 100755 --- a/src/test/shell/integration/aquery_test.sh +++ b/src/test/shell/integration/aquery_test.sh @@ -1434,7 +1434,6 @@ EOF || fail "Expected success" cat output >> "$TEST_log" - assert_contains "PYTHON_BINARY = '%python_binary%'" output assert_contains "{%python_binary%:" output bazel aquery --output=jsonproto ${QUERY} > output 2> "$TEST_log" \ diff --git a/src/test/shell/integration/modify_execution_info_test.sh b/src/test/shell/integration/modify_execution_info_test.sh index 28e485ef0bb60a..80c1d460be83ce 100755 --- a/src/test/shell/integration/modify_execution_info_test.sh +++ b/src/test/shell/integration/modify_execution_info_test.sh @@ -241,7 +241,7 @@ TestRunner=+requires-test-runner,\ Turbine=+requires-turbine,\ JavaSourceJar=+requires-java-source-jar,\ Javac=+requires-javac,\ -PyTinypar=+requires-py-tinypar,\ +Py.*=+requires-py,\ Action=+requires-action \ > output 2> "$TEST_log" || fail "Expected success" @@ -260,9 +260,7 @@ Action=+requires-action \ assert_contains "requires-java-source-jar: ''" output assert_contains "requires-proto: ''" output # GenProtoDescriptorSet should match if [[ "$PRODUCT_NAME" != "bazel" ]]; then - # Python rules generate some cpp actions and local actions, but py-tinypar - # is the main unique-to-python rule which runs remotely for a py_binary. - assert_contains "requires-py-tinypar: ''" output + assert_contains "requires-py: ''" output fi } diff --git a/src/test/shell/integration/python_stub_test.sh b/src/test/shell/integration/python_stub_test.sh index 734e20ade2c637..42e16bedb2aa70 100755 --- a/src/test/shell/integration/python_stub_test.sh +++ b/src/test/shell/integration/python_stub_test.sh @@ -83,10 +83,18 @@ py_binary(name = "main3", ) EOF - bazel run //test:main2 \ - &> $TEST_log || fail "bazel run failed" - expect_log "I am Python 2" - bazel run //test:main3 \ + # Google builds don't support Python 2 + if [[ "$PRODUCT_NAME" == "bazel" ]]; then + bazel run //test:main2 \ + &> $TEST_log || fail "bazel run failed" + expect_log "I am Python 2" + fi + + # Stamping is disabled so that the invocation doesn't time out. What + # happens is Google has stamping enabled by default, which causes the + # Starlark rule implementation to run an action, which then tries to run + # remotely, but network access is disabled by default, so it times out. + bazel run --nostamp //test:main3 \ &> $TEST_log || fail "bazel run failed" expect_log "I am Python 3" } @@ -117,6 +125,10 @@ EOF # to a value different from the top-level configuration, and then changing it # back again, is able to reuse the top-level configuration. function test_no_action_conflicts_from_version_transition() { + # Requires Python 2 support, which doesn't work for Google-internal builds + if [[ "$PRODUCT_NAME" != "bazel" ]]; then + return 0 + fi mkdir -p test # To repro, we need to build a C++ target in two different ways in the same diff --git a/src/test/shell/integration/python_test.sh b/src/test/shell/integration/python_test.sh index a8538be799969b..34b19b3350d28d 100755 --- a/src/test/shell/integration/python_test.sh +++ b/src/test/shell/integration/python_test.sh @@ -73,6 +73,14 @@ fi # - Otherwise, put your test in //src/test/shell/bazel. That suite can invoke # actual Python 2 and 3 interpreters. +# Python's import system distinguishes between "regular files" and other files +# in some cases (e.g. /dev/null). Here, we are trying to verify that a generated +# __init__.py file passes the isfile() check that the import logic performs and +# would fail for a "character device" (e.g. symlinked to /dev/null). For more +# info, see: +# * https://github.com/bazelbuild/bazel/issues/1458 +# * https://github.com/bazelbuild/bazel/issues/2394 +# * https://bugs.python.org/issue28425 function test_python_binary_empty_files_in_runfiles_are_regular_files() { mkdir -p test/mypackage cat > test/BUILD <<'EOF' @@ -101,11 +109,11 @@ if not os.path.exists(file_to_check): print("mypackage/__init__.py does not exist") sys.exit(1) -if os.path.islink(file_to_check): - print("mypackage/__init__.py is a symlink, expected a regular file") - sys.exit(1) +# Symlinks to regular files are OK. +realpath = os.path.realpath(file_to_check) +print("{} realpath is: {}".format(file_to_check, realpath)) -if not os.path.isfile(file_to_check): +if not os.path.isfile(realpath): print("mypackage/__init__.py is not a regular file") sys.exit(1) @@ -132,10 +140,14 @@ sh_binary( data = [':py-tool'], ) EOF - bazel build --experimental_build_transitive_python_runfiles :sh-tool + # Stamping is disabled so that the invocation doesn't time out. What + # happens is Google has stamping enabled by default, which causes the + # Starlark rule implementation to run an action, which then tries to run + # remotely, but network access is disabled by default, so it times out. + bazel build --experimental_build_transitive_python_runfiles --nostamp :sh-tool [ -d "bazel-bin/py-tool${EXE_EXT}.runfiles" ] || fail "py_binary runfiles tree not built" bazel clean - bazel build --noexperimental_build_transitive_python_runfiles :sh-tool + bazel build --noexperimental_build_transitive_python_runfiles --nostamp :sh-tool [ ! -e "bazel-bin/py-tool${EXE_EXT}.runfiles" ] || fail "py_binary runfiles tree built" } diff --git a/src/test/shell/integration/runfiles_test.sh b/src/test/shell/integration/runfiles_test.sh index 16f2ec683fa698..8138d61ae98b33 100755 --- a/src/test/shell/integration/runfiles_test.sh +++ b/src/test/shell/integration/runfiles_test.sh @@ -77,7 +77,7 @@ function create_pkg() { cd $pkg mkdir -p a/b c/d e/f/g x/y - touch py.py a/b/no_module.py c/d/one_module.py c/__init__.py e/f/g/ignored.py x/y/z.sh + touch py.py a/b/no_module.py c/d/one_module.py c/__init__.py e/f/g/ignored.txt x/y/z.sh chmod +x x/y/z.sh cd .. @@ -99,13 +99,13 @@ function recursive_path_info() { if [[ -f "$path" ]]; then effective_type=file elif [[ -d "$path" ]]; then - effective_type=dir + effective_type="$actual_type dir" else # The various special file types shouldn't occur in practice, so just # call them unknown effective_type=unknown fi - echo "$path $actual_type $effective_type" + echo "$path $effective_type" done } @@ -113,20 +113,37 @@ function recursive_path_info() { function test_hidden() { local -r pkg=$FUNCNAME - create_pkg $pkg + + mkdir -p "$pkg/e/f/g" + touch "$pkg/e/f/g/hidden.txt" + cat > "$pkg/defs.bzl" << EOF +def _obscured_impl(ctx): + executable = ctx.actions.declare_file(ctx.label.name) + ctx.actions.write(executable, "# nop") + return [DefaultInfo( + executable = executable, + runfiles = ctx.runfiles(files = ctx.files.data), + )] + +obscured = rule( + implementation = _obscured_impl, + attrs = {"data": attr.label_list(allow_files = True)}, + # Must be executable to trigger the obscured runfile check + executable = True, +) +EOF + cat > $pkg/BUILD << EOF -py_binary(name = "py", - srcs = [ "py.py" ], - data = [ "e/f", - "e/f/g/hidden.py" ]) +load(":defs.bzl", "obscured") +obscured(name="bin", data=["e/f", "e/f/g/hidden.txt"]) genrule(name = "hidden", - outs = [ "e/f/g/hidden.py" ], + outs = [ "e/f/g/hidden.txt" ], cmd = "touch \$@") EOF - bazel build $pkg:py $EXTRA_BUILD_FLAGS >&$TEST_log 2>&1 || fail "build failed" + bazel build $pkg:bin $EXTRA_BUILD_FLAGS >&$TEST_log 2>&1 || fail "build failed" - # we get a warning that hidden.py is inaccessible - expect_log_once "${pkg}/e/f/g/hidden.py obscured by ${pkg}/e/f " + # we get a warning that hidden.txt is inaccessible + expect_log_once "${pkg}/e/f/g/hidden.txt obscured by ${pkg}/e/f " } function test_foo_runfiles() { @@ -147,7 +164,8 @@ py_binary(name = "py", "a/b/no_module.py", "c/d/one_module.py", "c/__init__.py", - "e/f/g/ignored.py" ], + ], + data = ["e/f/g/ignored.txt"], deps = ["//:root"]) EOF bazel build $pkg:foo $EXTRA_BUILD_FLAGS >&$TEST_log || fail "build failed" @@ -174,30 +192,30 @@ EOF test \! -s __init__.py cd .. - # These are 3-tuples of (path actualFileType effectiveFileType), + # These are basically tuples of (path filetype) expected=" . regular dir -./__init__.py symlink file +./__init__.py file ./test_foo_runfiles regular dir -./test_foo_runfiles/__init__.py regular file +./test_foo_runfiles/__init__.py file ./test_foo_runfiles/a regular dir -./test_foo_runfiles/a/__init__.py regular file +./test_foo_runfiles/a/__init__.py file ./test_foo_runfiles/a/b regular dir -./test_foo_runfiles/a/b/__init__.py regular file -./test_foo_runfiles/a/b/no_module.py symlink file +./test_foo_runfiles/a/b/__init__.py file +./test_foo_runfiles/a/b/no_module.py file ./test_foo_runfiles/c regular dir -./test_foo_runfiles/c/__init__.py symlink file +./test_foo_runfiles/c/__init__.py file ./test_foo_runfiles/c/d regular dir -./test_foo_runfiles/c/d/__init__.py regular file -./test_foo_runfiles/c/d/one_module.py symlink file +./test_foo_runfiles/c/d/__init__.py file +./test_foo_runfiles/c/d/one_module.py file ./test_foo_runfiles/e regular dir ./test_foo_runfiles/e/f symlink dir -./test_foo_runfiles/foo symlink file -./test_foo_runfiles/py symlink file -./test_foo_runfiles/py.py symlink file +./test_foo_runfiles/foo file +./test_foo_runfiles/py file +./test_foo_runfiles/py.py file ./test_foo_runfiles/x regular dir ./test_foo_runfiles/x/y regular dir -./test_foo_runfiles/x/y/z.sh symlink file +./test_foo_runfiles/x/y/z.sh file " expected="$expected$(get_python_runtime_runfiles)" @@ -205,8 +223,8 @@ EOF # but on Linux we only build `bin`. if "$is_windows"; then expected="${expected} -./test_foo_runfiles/py.exe symlink file -./test_foo_runfiles/foo.exe symlink file +./test_foo_runfiles/py.exe file +./test_foo_runfiles/foo.exe file " fi