aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/test/shell/integration/execution_phase_tests.sh
diff options
context:
space:
mode:
Diffstat (limited to 'src/test/shell/integration/execution_phase_tests.sh')
-rwxr-xr-xsrc/test/shell/integration/execution_phase_tests.sh211
1 files changed, 211 insertions, 0 deletions
diff --git a/src/test/shell/integration/execution_phase_tests.sh b/src/test/shell/integration/execution_phase_tests.sh
new file mode 100755
index 0000000000..baf2433cd0
--- /dev/null
+++ b/src/test/shell/integration/execution_phase_tests.sh
@@ -0,0 +1,211 @@
+#!/bin/bash
+#
+# 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.
+#
+# execution_phase_tests.sh: miscellaneous integration tests of Bazel for
+# behaviors that affect the execution phase.
+#
+
+# Load the test setup defined in the parent directory
+CURRENT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
+source "${CURRENT_DIR}/../integration_test_setup.sh" \
+ || { echo "integration_test_setup.sh not found!" >&2; exit 1; }
+
+#### HELPER FUNCTIONS ##################################################
+
+function set_up() {
+ cd ${WORKSPACE_DIR}
+}
+
+function tear_down() {
+ bazel shutdown
+}
+
+# Looks for the last occurrence of a log message in a log file.
+#
+# This assumes the use of java.util.logging.SimpleFormatter, which splits
+# the context of a log entry and the log message itself in two lines.
+#
+# TODO(jmmv): We should have functionality in unittest.bash to check the
+# contents of the Bazel's client log in a way that allows us to test for
+# only the messages printed by the last-run command.
+function assert_last_log() {
+ local context="${1}"; shift
+ local message="${1}"; shift
+ local log="${1}"; shift
+ local fail_message="${1}"; shift
+
+ if ! grep -A1 "${context}" "${log}" | tail -n1 | grep -q "${message}" ; then
+ cat "${log}" >>"${TEST_log}" # Help debugging when we fail.
+ fail "${fail_message}"
+ fi
+}
+
+# Asserts that the last dump of cache stats in the log matches the given
+# metric and value.
+function assert_cache_stats() {
+ local metric="${1}"; shift
+ local exp_value="${1}"; shift
+
+ local java_log="$(bazel info output_base 2>/dev/null)/java.log"
+ local last="$(grep -A1 "CacheFileDigestsModule" "${java_log}" | tail -n1)"
+ [ -n "${last}" ] || fail "Could not find cache stats in log"
+ if ! echo "${last}" | grep -q "${metric}=${exp_value}"; then
+ echo "Last cache stats: ${last}" >>"${TEST_log}"
+ fail "${metric} was not ${exp_value}"
+ fi
+}
+
+#### TESTS #############################################################
+
+function test_cache_computed_file_digests_behavior() {
+ mkdir -p package || fail "mkdir failed"
+ cat >package/BUILD <<EOF
+genrule(
+ name = "foo",
+ srcs = ["foo.in"],
+ outs = ["foo.out"],
+ cmd = "cat \$(location foo.in) >\$@",
+)
+
+genrule(
+ name = "bar",
+ srcs = ["bar.in", ":foo"],
+ outs = ["bar.out"],
+ cmd = "cat \$(location bar.in) \$(location :foo) >\$@",
+)
+EOF
+ touch package/foo.in package/bar.in
+
+ bazel build package:bar >>"${TEST_log}" 2>&1 || fail "Should build"
+ # We cannot make any robust assertions on the first run because of implicit
+ # dependencies we have no control about.
+
+ # Rebuilding without changes should yield hits for everything. Run this
+ # multiple times to ensure the reported statistics are not accumulated.
+ for run in 1 2 3; do
+ bazel build package:bar >>"${TEST_log}" 2>&1 || fail "Should build"
+ assert_cache_stats "hit count" 1 # stable-status.txt
+ assert_cache_stats "miss count" 1 # volatile-status.txt
+ done
+
+ # Throw away the in-memory Skyframe state by flipping a flag. We expect hits
+ # for the previous outputs, which are used to query the action cache.
+ bazel build --nocheck_visibility package:bar >>"${TEST_log}" 2>&1 \
+ || fail "Should build"
+ assert_cache_stats "hit count" 3 # stable-status.txt foo.out bar.out
+ assert_cache_stats "miss count" 1 # volatile-status.txt
+
+ # Change the size of the cache and retry the same build. We expect no hits
+ # because resizing the cache invalidates all of its contents.
+ bazel build --cache_computed_file_digests=100 package:bar \
+ >>"${TEST_log}" 2>&1 || fail "Should build"
+ assert_cache_stats "hit count" 0
+ assert_cache_stats "miss count" 4 # {stable,volatile}-status* {foo,bar}.out
+
+ # Run a non-build command, which should not interfere with the cache.
+ bazel info >>"${TEST_log}" 2>&1 || fail "Should run"
+ assert_cache_stats "hit count" 0 # Same as previous command; unmodified.
+ assert_cache_stats "miss count" 4 # Same as previous command; unmodified.
+
+ # Rebuild without changes one more time with the new size of the cache to
+ # ensure the cache is not reset across runs with the flag override.
+ bazel build --nocheck_visibility --cache_computed_file_digests=100 \
+ package:bar >>"${TEST_log}" 2>&1 || fail "Should build"
+ assert_cache_stats "hit count" 3 # stable-status.txt foo.out bar.out
+ assert_cache_stats "miss count" 1 # volatile-status.txt
+}
+
+function test_cache_computed_file_digests_uncaught_changes() {
+ local timestamp=201703151112.13 # Fixed timestamp to mark our file with.
+
+ mkdir -p package || fail "mkdir failed"
+ cat >package/BUILD <<EOF
+genrule(
+ name = "foo",
+ srcs = ["foo.in"],
+ outs = ["foo.out"],
+ cmd = "echo foo >\$@ && touch -t ${timestamp} \$@",
+)
+EOF
+ touch package/foo.in
+
+ # Build the target once to populate the action cache, then update a file to a
+ # known timestamp, and rebuild the target to recompute our internal digests
+ # cache.
+ bazel build package:foo >>"${TEST_log}" 2>&1 || fail "Should build"
+ local output_file="$(find bazel-out/ -name foo.out)"
+ touch -t "${timestamp}" "${output_file}"
+ bazel build package:foo >>"${TEST_log}" 2>&1 || fail "Should build"
+
+ # Modify the content of a file in the action cache in a way that bypasses the
+ # logic to cache file digests: replace the file's content with new contents of
+ # the same length; avoid modifying the inode number; and respect the previous
+ # timestamp.
+ function log_metadata_for_test_debugging() {
+ echo "${1} ${2} modifying it in place:"
+ stat "${output_file}"
+ if which md5sum >/dev/null; then # macOS and possibly others.
+ md5sum "${output_file}"
+ elif which md5 >/dev/null; then # Linux and possibly others.
+ md5 "${output_file}"
+ fi
+ }
+ log_metadata_for_test_debugging "${output_file}" before >>"${TEST_log}"
+ chmod +w "${output_file}"
+ echo bar >"${output_file}" # Contents must match length in genrule.
+ chmod -w "${output_file}"
+ touch -t "${timestamp}" "${output_file}"
+ log_metadata_for_test_debugging "${output_file}" after >>"${TEST_log}"
+
+ # Assert all hits after discarding the in-memory Skyframe state while
+ # modifying the on-disk state in a way that bypasses the digests cache
+ # functionality.
+ bazel build --nocheck_visibility package:foo >>"${TEST_log}" 2>&1 \
+ || fail "Should build"
+ [[ "$(cat "${output_file}")" == bar ]] \
+ || fail "External change to action cache misdetected"
+
+ # For completeness, make the changes to the same output file visibile and
+ # ensure Blaze notices them. This is to sanity-check that we actually
+ # modified the right output file above.
+ touch "${output_file}"
+ bazel build package:foo >>"${TEST_log}" 2>&1 || fail "Should build"
+ [[ "$(cat "${output_file}")" == foo ]] \
+ || fail "External change to action cache not detected"
+}
+
+function test_cache_computed_file_digests_ui() {
+ mkdir -p package || fail "mkdir failed"
+ echo "cc_library(name = 'foo', srcs = ['foo.cc'])" >package/BUILD
+ echo "int foo(void) { return 0; }" >package/foo.cc
+
+ local java_log="$(bazel info output_base 2>/dev/null)/java.log"
+
+ bazel build package:foo >>"${TEST_log}" 2>&1 || fail "Should build"
+ assert_last_log "CacheFileDigestsModule" "Cache stats" "${java_log}" \
+ "Digests cache not enabled by default"
+
+ bazel build --cache_computed_file_digests=0 package:foo >>"${TEST_log}" 2>&1 \
+ || fail "Should build"
+ assert_last_log "CacheFileDigestsModule" "Disabled cache" "${java_log}" \
+ "Digests cache not disabled as requested"
+
+ bazel build package:foo >>"${TEST_log}" 2>&1 || fail "Should build"
+ assert_last_log "CacheFileDigestsModule" "Cache stats" "${java_log}" \
+ "Digests cache not reenabled"
+}
+
+run_suite "Integration tests of ${PRODUCT_NAME} using the execution phase."