| #!/bin/bash |
| # |
| # Copyright 2016 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. |
| # |
| # bazel_query_test.sh: integration tests for bazel query |
| |
| # --- begin runfiles.bash initialization --- |
| # Copy-pasted from Bazel's Bash runfiles library (tools/bash/runfiles/runfiles.bash). |
| set -euo pipefail |
| if [[ ! -d "${RUNFILES_DIR:-/dev/null}" && ! -f "${RUNFILES_MANIFEST_FILE:-/dev/null}" ]]; then |
| if [[ -f "$0.runfiles_manifest" ]]; then |
| export RUNFILES_MANIFEST_FILE="$0.runfiles_manifest" |
| elif [[ -f "$0.runfiles/MANIFEST" ]]; then |
| export RUNFILES_MANIFEST_FILE="$0.runfiles/MANIFEST" |
| elif [[ -f "$0.runfiles/bazel_tools/tools/bash/runfiles/runfiles.bash" ]]; then |
| export RUNFILES_DIR="$0.runfiles" |
| fi |
| fi |
| if [[ -f "${RUNFILES_DIR:-/dev/null}/bazel_tools/tools/bash/runfiles/runfiles.bash" ]]; then |
| source "${RUNFILES_DIR}/bazel_tools/tools/bash/runfiles/runfiles.bash" |
| elif [[ -f "${RUNFILES_MANIFEST_FILE:-/dev/null}" ]]; then |
| source "$(grep -m1 "^bazel_tools/tools/bash/runfiles/runfiles.bash " \ |
| "$RUNFILES_MANIFEST_FILE" | cut -d ' ' -f 2-)" |
| else |
| echo >&2 "ERROR: cannot find @bazel_tools//tools/bash/runfiles:runfiles.bash" |
| exit 1 |
| fi |
| # --- end runfiles.bash initialization --- |
| |
| source "$(rlocation "io_bazel/src/test/shell/integration_test_setup.sh")" \ |
| || { echo "integration_test_setup.sh not found!" >&2; exit 1; } |
| |
| # `uname` returns the current platform, e.g "MSYS_NT-10.0" or "Linux". |
| # `tr` converts all upper case letters to lower case. |
| # `case` matches the result if the `uname | tr` expression to string prefixes |
| # that use the same wildcards as names do in Bash, i.e. "msys*" matches strings |
| # starting with "msys", and "*" matches everything (it's the default case). |
| case "$(uname -s | tr [:upper:] [:lower:])" in |
| msys*) |
| # As of 2018-08-14, Bazel on Windows only supports MSYS Bash. |
| declare -r is_windows=true |
| ;; |
| *) |
| declare -r is_windows=false |
| ;; |
| esac |
| |
| if "$is_windows"; then |
| # Disable MSYS path conversion that converts path-looking command arguments to |
| # Windows paths (even if they arguments are not in fact paths). |
| export MSYS_NO_PATHCONV=1 |
| export MSYS2_ARG_CONV_EXCL="*" |
| fi |
| |
| function set_up() { |
| add_to_bazelrc "build --package_path=%workspace%" |
| setup_skylib_support |
| } |
| |
| function tear_down() { |
| bazel shutdown |
| } |
| |
| #### TESTS ############################################################# |
| |
| function test_does_not_fail_horribly() { |
| rm -rf peach |
| mkdir -p peach |
| cat > peach/BUILD <<EOF |
| sh_library(name='brighton', deps=[':harken']) |
| sh_library(name='harken') |
| EOF |
| |
| bazel query 'deps(//peach:brighton)' > $TEST_log |
| |
| expect_log "//peach:brighton" |
| expect_log "//peach:harken" |
| } |
| |
| function test_invalid_query_fails_parsing() { |
| bazel query 'deps("--bad_target_name_from_bad_script")' >& "$TEST_log" \ |
| && fail "Expected failure" |
| expect_log "target literal must not begin with (-)" |
| } |
| |
| function test_visibility_affects_xml_output() { |
| rm -rf kiwi |
| mkdir -p kiwi |
| |
| cat > kiwi/BUILD <<EOF |
| sh_library(name='kiwi', visibility=['//visibility:private']) |
| EOF |
| bazel query --output=xml '//kiwi:kiwi' > output_private |
| |
| cat > kiwi/BUILD <<EOF |
| sh_library(name='kiwi', visibility=['//visibility:public']) |
| EOF |
| bazel query --output=xml '//kiwi:kiwi' > output_public |
| |
| cat > kiwi/BUILD <<EOF |
| sh_library(name='kiwi') |
| EOF |
| bazel query --output=xml '//kiwi:kiwi' > output_none |
| |
| cmp output_private output_public && fail "visibility does not affect XML output" |
| cmp output_none output_private && fail "visibility does not affect XML output" |
| cmp output_none output_public && fail "visibility does not affect XML output" |
| |
| assert_contains "//kiwi:kiwi" output_private |
| assert_contains "//kiwi:kiwi" output_public |
| assert_contains "//kiwi:kiwi" output_none |
| |
| assert_contains "//visibility:private" output_private |
| assert_contains "//visibility:public" output_public |
| assert_not_contains "//visibility:private" output_none |
| assert_not_contains "//visibility:public" output_none |
| } |
| |
| function test_visibility_affects_proto_output() { |
| rm -rf kiwi |
| mkdir -p kiwi |
| |
| cat > kiwi/BUILD <<EOF |
| sh_library(name='kiwi', visibility=['//visibility:private']) |
| EOF |
| bazel query --output=proto '//kiwi:kiwi' > output_private |
| |
| cat > kiwi/BUILD <<EOF |
| sh_library(name='kiwi', visibility=['//visibility:public']) |
| EOF |
| bazel query --output=proto '//kiwi:kiwi' > output_public |
| |
| # There is no check for unspecified visibility because proto output format |
| # adds every attribute to the output, regardless of whether they are specified |
| # or have the default value |
| |
| cmp output_private output_public && fail "visibility does not affect proto output" |
| |
| assert_contains "//kiwi:kiwi" output_private |
| assert_contains "//kiwi:kiwi" output_public |
| |
| assert_contains "//visibility:private" output_private |
| assert_contains "//visibility:public" output_public |
| } |
| |
| function make_depth_tests() { |
| rm -rf depth |
| rm -rf depth2 |
| mkdir -p depth depth2 || die "Could not create test directory" |
| cat > "depth/BUILD" <<EOF |
| sh_binary(name = 'one', srcs = ['one.sh'], deps = [':two']) |
| sh_library(name = 'two', srcs = ['two.sh'], |
| deps = [':div2', ':three', '//depth2:three']) |
| sh_library(name = 'three', srcs = ['three.sh'], deps = [':four']) |
| sh_library(name = 'four', srcs = ['four.sh'], deps = [':div2', ':five']) |
| sh_library(name = 'five', srcs = ['five.sh']) |
| sh_library(name = 'div2', srcs = ['two.sh']) |
| EOF |
| |
| echo "sh_library(name = 'three', srcs = ['three.sh'])" > depth2/BUILD |
| |
| touch depth/{one,two,three,four,five}.sh depth2/three.sh |
| chmod a+x depth/*.sh depth2/*.sh |
| } |
| |
| # Running a deps query twice should return results in the same order |
| # if output is sorted, otherwise just the same results. |
| function assert_depth_query_idempotence() { |
| order_results="$1" |
| if $order_results ; then |
| order_output_arg=--order_output=auto |
| universe_arg="" |
| else |
| order_output_arg=--order_output=no |
| universe_arg=--universe_scope=//depth:* |
| fi |
| make_depth_tests |
| last_log="$TEST_log.last" |
| for run in {1..5}; do |
| # Only compare the output stream with the query results. |
| mv -f $TEST_log $last_log |
| bazel query 'deps(//depth:one, 4)' $order_output_arg $universe_arg \ |
| > $TEST_log || fail "Expected success" |
| if [ $run -gt 1 ]; then |
| if $order_results ; then |
| diff $TEST_log $last_log || \ |
| fail "Lines differed between query results: $last_log" |
| else |
| diff <(sort $TEST_log) <(sort $last_log) || \ |
| fail "Lines differed between sorted query results" |
| fi |
| fi |
| done |
| rm -f $last_log || die "Could not remove $last_log" |
| } |
| |
| function test_depth_query_idempotence_ordered() { |
| assert_depth_query_idempotence true |
| } |
| |
| function test_depth_query_idempotence_unordered() { |
| assert_depth_query_idempotence false |
| } |
| |
| function test_universe_scope_with_without_star() { |
| rm -rf foo |
| mkdir -p foo || fail "Couldn't mkdir" |
| echo "sh_library(name = 'foo')" > foo/BUILD || fail "Couldn't write BUILD" |
| bazel query --order_output=no \ |
| --universe_scope=//foo/... '//foo:BUILD' >& $TEST_log || |
| fail "Expected success" |
| # This is documenting current behavior, rather than enforcing a contract. For |
| # performance and code simplicity, we return targets if their package was |
| # loaded, so //foo:BUILD exists as a target (although its deps and rdeps are |
| # unknown). |
| expect_log "//foo:BUILD" |
| bazel query --order_output=no \ |
| --universe_scope=//foo/...:* '//foo:BUILD' >& $TEST_log || |
| fail "Expected success" |
| expect_log "//foo:BUILD" |
| } |
| |
| function test_outside_universe_ok() { |
| rm -rf foo |
| rm -rf bar |
| mkdir -p foo bar || fail "Couldn't mkdir" |
| echo "sh_library(name = 'foo', deps = ['//bar:bar'])" > foo/BUILD || |
| fail "Couldn't write BUILD" |
| cat <<'EOF' > bar/BUILD || fail "Couldn't write BUILD" |
| sh_library(name = 'bar') |
| sh_library(name = 'dep') |
| sh_library(name = 'top', deps = [':dep']) |
| EOF |
| bazel query --order_output=no \ |
| --universe_scope=//foo/...:* 'allrdeps(//bar:BUILD)' >& $TEST_log || |
| fail "Expected success" |
| # This is documenting current behavior, rather than enforcing a contract. See |
| # corresponding comment in test_universe_scope_with_without_star. |
| expect_log "//bar:BUILD" |
| bazel query --order_output=no \ |
| --universe_scope=//foo/...:* 'allrdeps(//bar:dep)' >& $TEST_log || |
| fail "Expected success" |
| # This is documenting current behavior, rather than enforcing a contract. See |
| # corresponding comment in test_universe_scope_with_without_star. In this |
| # case, even though we return //bar:dep, we do not see its rdep //bar:top. |
| expect_log "//bar:dep" |
| expect_not_log "//bar:top" |
| } |
| |
| # Since all targets in deps(..., n) are accessible n steps away, none should |
| # have a minrank greater than n. |
| function test_minrank_le_depth_bound() { |
| make_depth_tests |
| for depth in {5..0}; do |
| bazel query "deps(//depth:one, $depth)" --output=minrank > $TEST_log \ |
| || fail "Expected success" |
| for rank in $(cut -d' ' -f 1 $TEST_log); do |
| [ $rank -le $depth ] || fail "Expected max minrank of $depth, was $rank" |
| done |
| done |
| } |
| |
| function test_starlark_dep_in_sky_query() { |
| rm -rf foo |
| rm -rf bar |
| mkdir -p foo bar || fail "Couldn't make directories" |
| echo 'load("//bar:fakerule.bzl", "const")' > foo/BUILD || fail "Couldn't write" |
| touch bar/BUILD || fail "Couldn't touch bar/BUILD" |
| echo 'const = 2' > bar/fakerule.bzl || fail "Couldn't write fakerule" |
| bazel query --universe_scope=//foo/...:* --order_output=no \ |
| 'rbuildfiles(bar/fakerule.bzl)' >& $TEST_log || fail "Expected success" |
| expect_log_once "//foo:BUILD" |
| expect_not_log "//bar:BUILD" |
| expect_not_log "fakerule\.bzl" |
| } |
| |
| function test_starlark_regular_file_not_included_in_rbuildfiles() { |
| rm -rf foo |
| mkdir -p foo || fail "Couldn't make directories" |
| echo "baz" > "foo/baz.bzl" || fail "Couldn't create baz.bzl" |
| echo 'sh_library(name = "foo", srcs = ["baz.bzl"])' > foo/BUILD |
| bazel query --universe_scope=//foo/...:* --order_output=no \ |
| 'rbuildfiles(foo/baz.bzl)' >& $TEST_log || fail "Expected success" |
| expect_not_log "//foo:BUILD" |
| # TODO(bazel-team): Remove this once test clean-up is automated. |
| # Clean up after ourselves. |
| rm -rf foo |
| } |
| |
| function test_starlark_symlink_source_not_included_in_rbuildfiles() { |
| rm -rf foo |
| mkdir -p foo || fail "Couldn't make directories" |
| echo "moo" > "foo/moo" || fail "Couldn't create moo" |
| ln -s "$PWD/foo/moo" "foo/baz.bzl" && [[ -f foo/baz.bzl ]] || fail "Couldn't create baz.bzl symlink" |
| echo 'sh_library(name = "foo", srcs = ["baz.bzl"])' > foo/BUILD |
| bazel query --universe_scope=//foo/...:* --order_output=no \ |
| 'rbuildfiles(foo/baz.bzl)' >& $TEST_log || fail "Expected success" |
| expect_not_log "//foo:BUILD" |
| # TODO(bazel-team): Remove this once test clean-up is automated. |
| # Clean up after ourselves. |
| rm -rf foo |
| } |
| |
| function test_starlark_symlink_target_not_included_in_rbuildfiles() { |
| rm -rf foo |
| mkdir -p foo || fail "Couldn't make directories" |
| echo "baz" > "foo/baz.bzl" || fail "Couldn't create baz.bzl" |
| ln -s "$PWD/foo/baz.bzl" "foo/Moo.java" && [[ -f foo/Moo.java ]] || fail "Couldn't create Moo.java symlink" |
| echo 'sh_library(name = "foo", srcs = ["Moo.java"])' > foo/BUILD |
| bazel query --universe_scope=//foo/...:* --order_output=no \ |
| 'rbuildfiles(foo/baz.bzl)' >& $TEST_log || fail "Expected success" |
| expect_not_log "//foo:BUILD" |
| # TODO(bazel-team): Remove this once test clean-up is automated. |
| # Clean up after ourselves. |
| rm -rf foo |
| } |
| |
| function test_starlark_glob_regular_file_not_included_in_rbuildfiles() { |
| rm -rf foo |
| mkdir -p foo || fail "Couldn't make directories" |
| echo "baz" > "foo/baz.bzl" || fail "Couldn't create baz.bzl" |
| echo 'sh_library(name = "foo", srcs = glob(["*.bzl"]))' > foo/BUILD |
| bazel query --universe_scope=//foo/...:* --order_output=no \ |
| 'rbuildfiles(foo/baz.bzl)' >& $TEST_log || fail "Expected success" |
| expect_not_log "//foo:BUILD" |
| # TODO(bazel-team): Remove this once test clean-up is automated. |
| # Clean up after ourselves. |
| rm -rf foo |
| } |
| |
| function test_starlark_glob_symlink_source_not_included_in_rbuildfiles() { |
| rm -rf foo |
| mkdir -p foo || fail "Couldn't make directories" |
| echo "moo" > "foo/moo" || fail "Couldn't create moo" |
| ln -s "$PWD/foo/moo" "foo/baz.bzl" && [[ -f foo/baz.bzl ]] || fail "Couldn't create baz.bzl symlink" |
| echo 'sh_library(name = "foo", srcs = glob(["*.bzl"]))' > foo/BUILD |
| bazel query --universe_scope=//foo/...:* --order_output=no \ |
| 'rbuildfiles(foo/baz.bzl)' >& $TEST_log || fail "Expected success" |
| expect_not_log "//foo:BUILD" |
| # TODO(bazel-team): Remove this once test clean-up is automated. |
| # Clean up after ourselves. |
| rm -rf foo |
| } |
| |
| function test_starlark_glob_symlink_target_not_included_in_rbuildfiles() { |
| rm -rf foo |
| mkdir -p foo || fail "Couldn't make directories" |
| echo "baz" > "foo/baz.bzl" || fail "Couldn't create baz.bzl" |
| ln -s "$PWD/foo/baz.bzl" "foo/Moo.java" && [[ -f foo/Moo.java ]] || fail "Couldn't create Moo.java symlink" |
| echo 'sh_library(name = "foo", srcs = glob(["*.java"]))' > foo/BUILD |
| bazel query --universe_scope=//foo/...:* --order_output=no \ |
| 'rbuildfiles(foo/baz.bzl)' >& $TEST_log || fail "Expected success" |
| expect_not_log "//foo:BUILD" |
| # TODO(bazel-team): Remove this once test clean-up is automated. |
| # Clean up after ourselves. |
| rm -rf foo |
| } |
| |
| function test_starlark_recursive_glob_regular_file_not_included_in_rbuildfiles() { |
| rm -rf foo |
| mkdir -p foo/bar || fail "Couldn't make directories" |
| echo "baz" > "foo/bar/baz.bzl" || fail "Couldn't create baz.bzl" |
| echo 'sh_library(name = "foo", srcs = glob(["**/*.bzl"]))' > foo/BUILD |
| bazel query --universe_scope=//foo/...:* --order_output=no \ |
| 'rbuildfiles(foo/bar/baz.bzl)' >& $TEST_log || fail "Expected success" |
| expect_not_log "//foo:BUILD" |
| # TODO(bazel-team): Remove this once test clean-up is automated. |
| # Clean up after ourselves. |
| rm -rf foo |
| } |
| |
| function test_starlark_recursive_glob_symlink_source_not_included_in_rbuildfiles() { |
| rm -rf foo |
| mkdir -p foo/bar || fail "Couldn't make directories" |
| echo "moo" > "foo/moo" || fail "Couldn't create moo" |
| ln -s "$PWD/foo/moo" "foo/bar/baz.bzl" && [[ -f foo/bar/baz.bzl ]] || fail "Couldn't create baz.bzl symlink" |
| echo 'sh_library(name = "foo", srcs = glob(["**/*.bzl"]))' > foo/BUILD |
| bazel query --universe_scope=//foo/...:* --order_output=no \ |
| 'rbuildfiles(foo/bar/baz.bzl)' >& $TEST_log || fail "Expected success" |
| expect_not_log "//foo:BUILD" |
| # TODO(bazel-team): Remove this once test clean-up is automated. |
| # Clean up after ourselves. |
| rm -rf foo |
| } |
| |
| function test_starlark_recursive_glob_symlink_target_not_included_in_rbuildfiles() { |
| rm -rf foo |
| mkdir -p foo/bar || fail "Couldn't make directories" |
| echo "baz" > "foo/bar/baz.bzl" || fail "Couldn't create baz.bzl" |
| ln -s "$PWD/foo/bar/baz.bzl" "foo/Moo.java" && [[ -f foo/Moo.java ]] || fail "Couldn't create Moo.java symlink" |
| echo 'sh_library(name = "foo", srcs = glob(["**/*.java"]))' > foo/BUILD |
| bazel query --universe_scope=//foo/...:* --order_output=no \ |
| 'rbuildfiles(foo/bar/baz.bzl)' >& $TEST_log || fail "Expected success" |
| expect_not_log "//foo:BUILD" |
| # TODO(bazel-team): Remove this once test clean-up is automated. |
| # Clean up after ourselves. |
| rm -rf foo |
| } |
| |
| function test_starlark_subdir_dep_in_sky_query() { |
| rm -rf foo |
| mkdir -p foo bar/baz || fail "Couldn't make directories" |
| echo 'load("//bar:baz/fakerule.bzl", "const")' > foo/BUILD || fail "Couldn't write" |
| touch bar/BUILD || fail "Couldn't touch bar/BUILD" |
| echo 'const = 2' > bar/baz/fakerule.bzl || fail "Couldn't write fakerule" |
| bazel query --universe_scope=//foo/...:* --order_output=no \ |
| 'rbuildfiles(bar/baz/fakerule.bzl)' >& $TEST_log || fail "Expected success" |
| expect_log_once "//foo:BUILD" |
| expect_not_log "//bar:BUILD" |
| expect_not_log "fakerule\.bzl" |
| } |
| |
| function test_parent_independent_of_child() { |
| rm -rf foo |
| mkdir -p foo/subdir || fail "Couldn't make directories" |
| echo 'sh_library(name = "sh", data = glob(["**"]))' > foo/BUILD || |
| fail "Couldn't write" |
| touch foo/subdir/BUILD || fail "Couldn't touch foo/subdir/BUILD" |
| bazel query --universe_scope=//foo/...:* --order_output=no \ |
| 'rbuildfiles(foo/subdir/BUILD)' >& $TEST_log || fail "Expected success" |
| expect_log_once "//foo/subdir:BUILD" |
| expect_not_log "//foo:BUILD" |
| } |
| |
| function test_does_not_fail_horribly_with_file() { |
| rm -rf peach |
| mkdir -p peach |
| cat > peach/BUILD <<EOF |
| sh_library(name='brighton', deps=[':harken']) |
| sh_library(name='harken') |
| EOF |
| |
| echo "deps(//peach:brighton)" > query_file |
| bazel query --query_file=query_file > $TEST_log |
| |
| expect_log "//peach:brighton" |
| expect_log "//peach:harken" |
| } |
| |
| function test_location_output_not_allowed_with_buildfiles_or_loadfiles() { |
| rm -rf foo |
| mkdir -p foo |
| cat > foo/bzl.bzl <<EOF |
| x = 2 |
| EOF |
| cat > foo/BUILD <<EOF |
| load('//foo:bzl.bzl', 'x') |
| sh_library(name='foo') |
| EOF |
| |
| bazel query 'buildfiles(//foo)' >& $TEST_log || fail "Expected success" |
| expect_log "//foo:bzl.bzl" |
| bazel query 'loadfiles(//foo)' >& $TEST_log || fail "Expected success" |
| expect_log "//foo:bzl.bzl" |
| bazel query --output=location '//foo' >& $TEST_log || fail "Expected success" |
| expect_log "//foo:foo" |
| |
| local expected_error_msg="Query expressions involving 'buildfiles' or 'loadfiles' cannot be used with --output=location" |
| local expected_exit_code=2 |
| for query_string in 'buildfiles(//foo)' 'loadfiles(//foo)' |
| do |
| bazel query --output=location "$query_string" >& $TEST_log \ |
| && fail "Expected failure" |
| exit_code=$? |
| expect_log "$expected_error_msg" |
| assert_equals "$expected_exit_code" "$exit_code" |
| done |
| } |
| |
| function test_location_output_relative_locations() { |
| rm -rf foo |
| mkdir -p foo |
| cat > foo/BUILD <<EOF |
| sh_library(name='foo') |
| EOF |
| |
| bazel query --output=location '//foo' >& $TEST_log || fail "Expected success" |
| expect_log "${TEST_TMPDIR}/.*/foo/BUILD" |
| expect_log "//foo:foo" |
| |
| bazel query --output=location --relative_locations '//foo' >& $TEST_log || fail "Expected success" |
| # Query with --relative_locations should not show full path |
| expect_not_log "${TEST_TMPDIR}/.*/foo/BUILD" |
| expect_log "^foo/BUILD" |
| expect_log "//foo:foo" |
| } |
| |
| function test_location_output_source_files() { |
| rm -rf foo |
| mkdir -p foo |
| cat > foo/BUILD <<EOF |
| py_binary( |
| name = "main", |
| srcs = ["main.py"], |
| ) |
| EOF |
| touch foo/main.py || fail "Could not touch foo/main.py" |
| |
| # The incompatible_display_source_file_location flag displays the location of |
| # line 1 of the actual source file |
| bazel query \ |
| --output=location \ |
| --incompatible_display_source_file_location \ |
| '//foo:main.py' >& $TEST_log || fail "Expected success" |
| expect_log "source file //foo:main.py" |
| expect_log "^${TEST_TMPDIR}/.*/foo/main.py:1:1" |
| expect_not_log "^${TEST_TMPDIR}/.*/foo/BUILD:[0-9]*:[0-9]*" |
| |
| # The noincompatible_display_source_file_location flag displays its location |
| # in the BUILD file |
| bazel query \ |
| --output=location \ |
| --noincompatible_display_source_file_location \ |
| '//foo:main.py' >& $TEST_log || fail "Expected success" |
| expect_log "source file //foo:main.py" |
| expect_log "^${TEST_TMPDIR}/.*/foo/BUILD:[0-9]*:[0-9]*" |
| expect_not_log "^${TEST_TMPDIR}/.*/foo/main.py:1:1" |
| |
| # The incompatible_display_source_file_location should still be affected by |
| # relative_locations flag to display the relative location of the source file |
| bazel query \ |
| --output=location \ |
| --relative_locations \ |
| --incompatible_display_source_file_location \ |
| '//foo:main.py' >& $TEST_log || fail "Expected success" |
| expect_log "source file //foo:main.py" |
| expect_log "^foo/main.py:1:1" |
| expect_not_log "^${TEST_TMPDIR}/.*/foo/main.py:1:1" |
| |
| # The noincompatible_display_source_file_location flag should still be |
| # affected by relative_locations flag to display the relative location of |
| # the BUILD file. |
| bazel query --output=location \ |
| --relative_locations \ |
| --noincompatible_display_source_file_location \ |
| '//foo:main.py' >& $TEST_log || fail "Expected success" |
| expect_log "source file //foo:main.py" |
| expect_log "^foo/BUILD:[0-9]*:[0-9]*" |
| expect_not_log "^${TEST_TMPDIR}/.*/foo/BUILD:[0-9]*:[0-9]*" |
| } |
| |
| function test_proto_output_source_files() { |
| rm -rf foo |
| mkdir -p foo |
| cat > foo/BUILD <<EOF |
| py_binary( |
| name = "main", |
| srcs = ["main.py"], |
| ) |
| EOF |
| touch foo/main.py || fail "Could not touch foo/main.py" |
| |
| bazel query --output=proto \ |
| --incompatible_display_source_file_location \ |
| '//foo:main.py' >& $TEST_log || fail "Expected success" |
| |
| expect_log "${TEST_TMPDIR}/.*/foo/main.py:1:1" $TEST_log |
| expect_not_log "${TEST_TMPDIR}/.*/foo/BUILD:[0-9]*:[0-9]*" $TEST_log |
| |
| bazel query --output=proto \ |
| --noincompatible_display_source_file_location \ |
| '//foo:main.py' >& $TEST_log || fail "Expected success" |
| expect_log "${TEST_TMPDIR}/.*/foo/BUILD:[0-9]*:[0-9]*" $TEST_log |
| expect_not_log "${TEST_TMPDIR}/.*/foo/main.py:1:1" $TEST_log |
| } |
| |
| function test_xml_output_source_files() { |
| rm -rf foo |
| mkdir -p foo |
| cat > foo/BUILD <<EOF |
| py_binary( |
| name = "main", |
| srcs = ["main.py"], |
| ) |
| EOF |
| touch foo/main.py || fail "Could not touch foo/main.py" |
| |
| bazel query --output=xml \ |
| --incompatible_display_source_file_location \ |
| '//foo:main.py' >& $TEST_log || fail "Expected success" |
| expect_log "location=\"${TEST_TMPDIR}/.*/foo/main.py:1:1" |
| expect_not_log "location=\"${TEST_TMPDIR}/.*/foo/BUILD:[0-9]*:[0-9]*" |
| |
| bazel query --output=xml \ |
| --noincompatible_display_source_file_location \ |
| '//foo:main.py' >& $TEST_log || fail "Expected success" |
| expect_log "location=\"${TEST_TMPDIR}/.*/foo/BUILD:[0-9]*:[0-9]*" |
| expect_not_log "location=\"${TEST_TMPDIR}/.*/foo/main.py:1:1" |
| } |
| |
| function test_subdirectory_named_external() { |
| mkdir -p foo/external foo/bar |
| cat > foo/external/BUILD <<EOF |
| sh_library(name = 't1') |
| EOF |
| cat > foo/bar/BUILD <<EOF |
| sh_library(name = 't2') |
| EOF |
| |
| bazel query foo/... >& $TEST_log || fail "Expected success" |
| expect_log "//foo/external:t1" |
| expect_log "//foo/bar:t2" |
| } |
| |
| function test_buildfiles_with_build_bazel() { |
| if [ "${PRODUCT_NAME}" != "bazel" ]; then |
| return 0 |
| fi |
| rm -rf foo |
| mkdir -p foo |
| cat > foo/bzl.bzl <<EOF |
| x = 2 |
| EOF |
| cat > foo/BUILD.bazel <<EOF |
| load('//foo:bzl.bzl', 'x') |
| sh_library(name='foo') |
| EOF |
| |
| bazel query 'buildfiles(//foo)' >& $TEST_log || fail "Expected success" |
| expect_log "//foo:bzl.bzl$" |
| expect_log "//foo:BUILD.bazel$" |
| expect_not_log "//foo:BUILD$" |
| } |
| |
| function test_buildfile_in_genquery() { |
| mkdir -p papaya |
| cat > papaya/BUILD <<EOF |
| exports_files(['papaya.bzl']) |
| EOF |
| cat > papaya/papaya.bzl <<EOF |
| foo = 1 |
| EOF |
| mkdir -p honeydew |
| cat > honeydew/BUILD <<EOF |
| load('//papaya:papaya.bzl', 'foo') |
| sh_library(name='honeydew', deps=[':pineapple']) |
| sh_library(name='pineapple') |
| genquery(name='q', |
| scope=[':honeydew'], |
| strict=0, |
| expression='buildfiles(//honeydew:all)') |
| EOF |
| |
| bazel build //honeydew:q >& $TEST_log || fail "Expected success" |
| cat bazel-bin/honeydew/q > $TEST_log |
| expect_log_once "^//honeydew:BUILD$" |
| } |
| |
| function test_genquery_bad_output_formatter() { |
| mkdir -p starfruit |
| cat > starfruit/BUILD <<EOF |
| sh_library(name = 'starfruit') |
| genquery(name='q', |
| scope=['//starfruit'], |
| expression='//starfruit', |
| opts = ["--output=blargh"],) |
| EOF |
| |
| local expected_error_msg="in genquery rule //starfruit:q: Invalid output format 'blargh'. Valid values are: label, label_kind, build, minrank, maxrank, package, location, graph, jsonproto, xml, proto" |
| bazel build //starfruit:q >& $TEST_log && fail "Expected failure" |
| expect_log "$expected_error_msg" |
| } |
| |
| function test_graphless_genquery_somepath_output_in_dependency_order() { |
| mkdir -p foo |
| cat > foo/BUILD <<EOF |
| sh_library(name = "c", deps = [":b"]) |
| sh_library(name = "b", deps = [":a"]) |
| sh_library(name = "a") |
| genquery(name = "somepath", |
| scope = ['//foo:c'], |
| expression = "somepath(//foo:c, //foo:a)") |
| genquery(name = "allpaths", |
| scope = ['//foo:c'], |
| expression = "allpaths(//foo:c, //foo:a)") |
| EOF |
| |
| # Somepath in genquery needs to output in dependency order instead of |
| # lexicographical order (which is the default for all other expressions) |
| cat > foo/expected_sp_output <<EOF |
| //foo:c |
| //foo:b |
| //foo:a |
| EOF |
| bazel build //foo:somepath >& $TEST_log || fail "Expected success" |
| assert_equals "$(cat foo/expected_sp_output)" "$(cat bazel-bin/foo/somepath)" |
| |
| # Allpaths in genquery outputs in lexicographical order (just like all other |
| # expressions) as the dependency order is not preserved during computation |
| # in GraphlessBlazeQueryEnvironment |
| cat > foo/expected_ap_output <<EOF |
| //foo:a |
| //foo:b |
| //foo:c |
| EOF |
| bazel build //foo:allpaths >& $TEST_log || fail "Expected success" |
| assert_equals "$(cat foo/expected_ap_output)" "$(cat bazel-bin/foo/allpaths)" |
| } |
| |
| function test_graphless_query_matches_graphless_genquery_output() { |
| rm -rf foo |
| mkdir -p foo |
| cat > foo/BUILD <<EOF |
| sh_library(name = "b", deps = [":c"]) |
| sh_library(name = "c", deps = [":a"]) |
| sh_library(name = "a") |
| genquery( |
| name = "q", |
| expression = "deps(//foo:b)", |
| scope = ["//foo:b"], |
| ) |
| EOF |
| |
| cat > foo/expected_lexicographical_result <<EOF |
| //foo:a |
| //foo:b |
| //foo:c |
| EOF |
| |
| # Genquery uses a graphless blaze environment by default. |
| bazel build --experimental_genquery_use_graphless_query \ |
| //foo:q || fail "Expected success" |
| |
| # The --incompatible_lexicographical_output flag is used to |
| # switch order_output=auto to use graphless query and output in |
| # lexicographical order. |
| bazel query --incompatible_lexicographical_output \ |
| "deps(//foo:b)" | grep foo >& foo/query_output || fail "Expected success" |
| |
| # The outputs of graphless query and graphless genquery should be the same and |
| # should both be in lexicographical order. |
| assert_equals \ |
| "$(cat foo/expected_lexicographical_result)" "$(cat foo/query_output)" |
| assert_equals \ |
| "$(cat foo/expected_lexicographical_result)" "$(cat bazel-bin/foo/q)" |
| } |
| |
| function test_graphless_query_resilient_to_cycles() { |
| rm -rf foo |
| mkdir -p foo |
| cat > foo/BUILD <<EOF |
| sh_library(name = "a", deps = [":b"]) |
| sh_library(name = "b", deps = [":c"]) |
| sh_library(name = "c", deps = [":a"]) |
| sh_library(name = "d") |
| EOF |
| |
| for command in \ |
| "somepath(//foo:a, //foo:c)" \ |
| "somepath(//foo:a, //foo:d)" \ |
| "somepath(//foo:c, //foo:d)" \ |
| "allpaths(//foo:a, //foo:d)" \ |
| "deps(//foo:a)" \ |
| "rdeps(//foo:a, //foo:d)" \ |
| "same_pkg_direct_rdeps(//foo:b)" |
| do |
| bazel query --experimental_graphless_query=true \ |
| "$command" || fail "Expected success" |
| done |
| } |
| |
| function test_lexicographical_output_does_not_affect_order_output_no() { |
| rm -rf foo |
| mkdir -p foo |
| cat > foo/BUILD <<EOF |
| sh_library(name = "b", deps = [":c"]) |
| sh_library(name = "c", deps = [":a"]) |
| sh_library(name = "a") |
| genquery( |
| name = "q", |
| expression = "deps(//foo:b)", |
| scope = ["//foo:b"], |
| ) |
| EOF |
| |
| bazel query --order_output=no \ |
| "deps(//foo:b)" | grep foo >& foo/query_output \ |
| || fail "Expected success" |
| bazel query --order_output=no \ |
| --incompatible_lexicographical_output \ |
| "deps(//foo:b)" | grep foo >& foo/lex_query_output \ |
| || fail "Expected success" |
| |
| # The --incompatible_lexicographical_output flag should not affect query |
| # order_output=no. Note that there is a chance it may output in |
| # lexicographical order since it is unordered. |
| assert_equals \ |
| "$(cat foo/query_output)" "$(cat foo/lex_query_output)" |
| } |
| |
| function test_lexicographical_output_does_not_affect_somepath() { |
| rm -rf foo |
| mkdir -p foo |
| cat > foo/BUILD <<EOF |
| sh_library(name = "b", deps = [":c"]) |
| sh_library(name = "c", deps = [":a"]) |
| sh_library(name = "a") |
| EOF |
| |
| cat > foo/expected_deps_output <<EOF |
| //foo:b |
| //foo:c |
| //foo:a |
| EOF |
| |
| bazel query --incompatible_lexicographical_output \ |
| "somepath(//foo:b, //foo:a)" | grep foo >& foo/query_output |
| |
| assert_equals \ |
| "$(cat foo/expected_deps_output)" "$(cat foo/query_output)" |
| } |
| |
| # Regression test for https://github.com/bazelbuild/bazel/issues/8582. |
| function test_rbuildfiles_can_handle_non_loading_phase_edges() { |
| mkdir -p foo |
| # When we have a package //foo whose BUILD file |
| cat > foo/BUILD <<EOF |
| # Defines a target //foo:foo, with input file foo/foo.sh, |
| sh_library(name = 'foo', srcs = ['foo.sh']) |
| EOF |
| # And foo/foo.sh has some initial contents. |
| echo "bar" > foo/foo.sh |
| |
| # Then `rbuildfiles` correctly thinks //foo "depends" on foo/BUILD, |
| bazel query \ |
| --universe_scope=//foo:foo \ |
| --order_output=no \ |
| "rbuildfiles(foo/BUILD)" >& $TEST_log || fail "Expected success" |
| expect_log //foo:BUILD |
| # And that no package "depends" on foo/foo.sh. |
| bazel query \ |
| --universe_scope=//foo:foo \ |
| --order_output=no \ |
| "rbuildfiles(foo/foo.sh)" >& $TEST_log || fail "Expected success" |
| expect_not_log //foo:BUILD |
| |
| # But then, after we *build* //foo:foo (thus priming the Skyframe graph with |
| # a transitive dep path from the input ArtifactValue for foo/foo.sh to the |
| # FileStateValue for foo/foo.sh), |
| bazel build //foo:foo >& $TEST_log || fail "Expected success" |
| |
| # And we modify the contents of foo/foo.sh, |
| echo "baz" > foo/foo.sh |
| |
| # And we again do a `rbuildfiles(foo/foo.sh)`, Bazel again correctly thinks |
| # no package "depends" on foo/foo.sh. |
| # |
| # Historically, Bazel would crash here because it would first invalidate the |
| # UTC of FileStateValue for foo/foo.sh (invalidating the ArtifactValue for |
| # foo/foo.sh), and then evaluate the DTC of the *skyquery-land* universe of |
| # //foo:foo (*not* evaluating that ArtifactValue), and then observe an rdep |
| # edge on the not-done ArtifactValue, and then crash. |
| bazel query \ |
| --universe_scope=//foo:foo \ |
| --order_output=no \ |
| "rbuildfiles(foo/foo.sh)" >& $TEST_log || fail "Expected success" |
| expect_not_log //foo:BUILD |
| } |
| |
| function test_infer_universe_scope_considers_only_target_patterns() { |
| # When we have three targets //a:a, //b:b, //c:c, with //b:b depending |
| # directly on //a:a, and //c:c depending directly on //b:b. |
| mkdir -p a b c |
| echo "sh_library(name = 'a')" > a/BUILD |
| echo "sh_library(name = 'b', deps = ['//a:a'])" > b/BUILD |
| echo "sh_library(name = 'c', deps = ['//b:b'])" > c/BUILD |
| |
| # And we run 'bazel query' with both --infer_universe_scope and |
| # --order_output=no set (making this invocation eligible for SkyQuery), with |
| # a query expression of "allrdeps(//a)", |
| bazel query \ |
| --infer_universe_scope \ |
| --order_output=no \ |
| "allrdeps(//a)" >& $TEST_log || fail "Expected success" |
| # Then the invocation succeeds (confirming SkyQuery mode was enabled), |
| # And also the result contains //a:a |
| expect_log //a:a |
| # But it does not contain //b:c or //c:c, because they aren't contained in |
| # the inferred universe scope. |
| expect_not_log //b:b |
| expect_not_log //c:c |
| |
| # And also, when we run 'bazel clean' (just to be sure, since the semantics |
| # of SkyQuery depends on the state of the Bazel server) |
| bazel clean >& $TEST_log || fail "Expected success" |
| |
| # And then we run 'bazel query' again, with the same options as last time, |
| # but this time with a query expression that contains target patterns whose |
| # DTC covers //b:b and //c:c too, |
| bazel query \ |
| --infer_universe_scope --order_output=no \ |
| "allrdeps(//a) ^ deps(//c:c)" >& $TEST_log || fail "Expected success" |
| # Then the invocation also succeeds (confirming SkyQuery mode was enabled), |
| # But this time the result contains all three targets. |
| expect_log //a:a |
| expect_log //b:b |
| expect_log //c:c |
| } |
| |
| function test_bogus_visibility() { |
| mkdir -p foo bar || fail "Couldn't make directories" |
| cat <<'EOF' > foo/BUILD || fail "Couldn't write BUILD file" |
| sh_library(name = 'a', visibility = ['//bad:visibility', '//bar:__pkg__']) |
| sh_library(name = 'b', visibility = ['//visibility:public']) |
| sh_library(name = 'c', visibility = ['//bad:visibility']) |
| EOF |
| touch bar/BUILD || fail "Couldn't write BUILD file" |
| ! bazel query --keep_going --output=label_kind \ |
| 'visible(//bar:BUILD, //foo:a + //foo:b + //foo:c)' \ |
| >& "$TEST_log" || fail "Expected failure" |
| expect_log "no such package 'bad'" |
| expect_log "keep_going specified, ignoring errors. Results may be inaccurate" |
| expect_log "sh_library rule //foo:a" |
| expect_log "sh_library rule //foo:b" |
| expect_not_log "sh_library rule //foo:c" |
| } |
| |
| function test_infer_universe_scope_defers_to_universe_scope_value() { |
| # When we have two targets, in two different packages, that do not depend on |
| # each other, |
| mkdir -p a b |
| echo "sh_library(name = 'a')" > a/BUILD |
| echo "sh_library(name = 'b')" > b/BUILD |
| |
| # And we run 'bazel query' with a --universe_scope value that covers only one |
| # of the targets but a query expression that has target patterns for both |
| # targets, but also pass --infer_universe_scope, |
| bazel query \ |
| --universe_scope=//a:a \ |
| --infer_universe_scope \ |
| --order_output=no \ |
| "//a:a + //b:b" >& $TEST_log && fail "Expected failure" |
| # Then the query invocation fails, because of the missing target, thus |
| # verifying that our value of --universe_scope was respected and |
| # --infer_universe_scope was ignored. |
| expect_log "Evaluation of subquery \"//b:b\" failed" |
| |
| # And then, when we run 'bazel clean' (just to be sure, since the semantics |
| # of SkyQuery depends on the state of the Bazel server) |
| bazel clean >& $TEST_log || fail "Expected success" |
| |
| # And we run 'bazel query', this time without setting --universe_scope, but |
| # with --infer_universe_scope and the same query expression, |
| bazel query \ |
| --infer_universe_scope \ |
| --order_output=no \ |
| "//a:a + //b:b" >& $TEST_log || fail "Expected success" |
| # Then the query expression succeeds, because both targets are in the |
| # inferred universe. |
| expect_log //a:a |
| expect_log //b:b |
| } |
| |
| function test_query_failure_exit_code_behavior() { |
| bazel query //targetdoesnotexist >& "$TEST_log" && fail "Expected failure" |
| exit_code="$?" |
| assert_equals 7 "$exit_code" |
| bazel query --keep_going //targetdoesnotexist >& "$TEST_log" \ |
| && fail "Expected failure" |
| exit_code="$?" |
| assert_equals 3 "$exit_code" |
| |
| bazel query '$x' >& "$TEST_log" && fail "Expected failure" |
| exit_code="$?" |
| assert_equals 7 "$exit_code" |
| bazel query --keep_going '$x' >& "$TEST_log" && fail "Expected failure" |
| exit_code="$?" |
| assert_equals 7 "$exit_code" |
| } |
| |
| function test_query_environment_keep_going_does_not_fail() { |
| rm -rf foo |
| mkdir -p foo |
| cat > foo/BUILD <<EOF |
| sh_library(name = "a", deps = [":b", "//other:doesnotexist"]) |
| sh_library(name = "b") |
| EOF |
| |
| # Ensure that --keep_going works for both graphless and non-graphless blaze |
| # query environments for each function. |
| for incompatible in "--incompatible" "--noincompatible" |
| do |
| for command in \ |
| "somepath(//foo:a, //foo:b)" \ |
| "deps(//foo:a)" \ |
| "rdeps(//foo:a, //foo:b)" \ |
| "allpaths(//foo:a, //foo:b)" |
| do |
| bazel query "$incompatible"_lexicographical_output --keep_going \ |
| --output=label_kind "$command" \ |
| >& "$TEST_log" && fail "Expected failure" |
| exit_code="$?" |
| assert_equals 3 $exit_code |
| expect_log "sh_library rule //foo:a" |
| expect_log "sh_library rule //foo:b" |
| expect_log "errors were encountered while computing transitive closure" |
| done |
| done |
| } |
| |
| function test_unnecessary_external_workspaces_not_loaded() { |
| cat > WORKSPACE <<'EOF' |
| local_repository( |
| name = "notthere", |
| path = "/nope", |
| ) |
| EOF |
| cat > BUILD <<'EOF' |
| filegroup( |
| name = "something", |
| srcs = ["@notthere"], |
| ) |
| EOF |
| bazel query '//:*' || fail "Expected success" |
| } |
| |
| function test_query_sees_aspect_hints_deps_on_starlark_rule() { |
| local package="aspect_hints" |
| mkdir -p "${package}" |
| |
| cat > "${package}/custom_rule.bzl" <<EOF |
| |
| def _rule_impl(ctx): |
| return [] |
| |
| custom_rule = rule( |
| implementation = _rule_impl, |
| attrs = { |
| "deps": attr.label_list(), |
| } |
| ) |
| EOF |
| |
| cat > "${package}/BUILD" <<EOF |
| load("//${package}:custom_rule.bzl", "custom_rule") |
| |
| custom_rule(name = "hint") |
| |
| custom_rule( |
| name = "foo", |
| deps = [":bar"], |
| ) |
| custom_rule( |
| name = "bar", |
| aspect_hints = [":hint"], |
| ) |
| EOF |
| |
| bazel query "somepath(//${package}:foo, //${package}:hint)" >& $TEST_log \ |
| || fail "Expected success" |
| |
| expect_log "//${package}:hint" |
| } |
| |
| function test_same_pkg_direct_rdeps_loads_only_inputs_packages() { |
| mkdir -p "pkg1" |
| mkdir -p "pkg2" |
| mkdir -p "pkg3" |
| |
| cat > "pkg1/BUILD" <<EOF |
| sh_library(name = "t1", deps = [":t2", "//pkg2:t3"]) |
| sh_library(name = "t2") |
| EOF |
| |
| cat > "pkg2/BUILD" <<EOF |
| sh_library(name = "t3") |
| EOF |
| |
| cat > "pkg3/BUILD" <<EOF |
| sh_library(name = "t4", deps = [":t5"]) |
| sh_library(name = "t5") |
| EOF |
| |
| bazel query --experimental_ui_debug_all_events \ |
| "same_pkg_direct_rdeps(//pkg1:t2+//pkg3:t5)" >& $TEST_log \ |
| || fail "Expected success" |
| |
| expect_log "Loading package: pkg1" |
| expect_log "Loading package: pkg3" |
| # For graphless query mode, pkg2 should not be loaded because |
| # same_pkg_direct_rdeps only cares about the targets in the same package |
| # as its inputs. |
| expect_not_log "Loading package: pkg2" |
| # the result of "same_pkg_direct_rdeps(//pkg1:t2+//pkg3:t5)" |
| expect_log "//pkg1:t1" |
| expect_log "//pkg3:t4" |
| } |
| |
| function test_basic_query_jsonproto() { |
| local pkg="${FUNCNAME[0]}" |
| mkdir -p "$pkg" || fail "mkdir -p $pkg" |
| cat > "$pkg/BUILD" <<'EOF' |
| genrule( |
| name = "bar", |
| srcs = ["dummy.txt"], |
| outs = ["bar_out.txt"], |
| cmd = "echo unused > $(OUTS)", |
| ) |
| EOF |
| bazel query --output=jsonproto --noimplicit_deps "//$pkg:bar" > output 2> "$TEST_log" \ |
| || fail "Expected success" |
| cat output >> "$TEST_log" |
| |
| # Verify that the appropriate attributes were included. |
| assert_contains "\"ruleClass\": \"genrule\"" output |
| assert_contains "\"name\": \"//$pkg:bar\"" output |
| assert_contains "\"ruleInput\": \[\"//$pkg:dummy.txt\"\]" output |
| assert_contains "\"ruleOutput\": \[\"//$pkg:bar_out.txt\"\]" output |
| assert_contains "echo unused" output |
| } |
| |
| run_suite "${PRODUCT_NAME} query tests" |