# Copyright 2020 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. # Support for unittest.bash #### Set up the test environment. set -euo pipefail cat_jvm_log () { if [[ "$log_content" =~ \ "(error code:".*", error message: '".*"', log file: '"(.*)"')" ]]; then echo >&2 echo "Content of ${BASH_REMATCH[1]}:" >&2 cat "${BASH_REMATCH[1]}" >&2 fi } # Print message in "$1" then exit with status "$2" die () { # second argument is optional, defaulting to 1 local status_code=${2:-1} # Stop capturing stdout/stderr, and dump captured output if [[ "$CAPTURED_STD_ERR" -ne 0 || "$CAPTURED_STD_OUT" -ne 0 ]]; then restore_outputs if [[ "$CAPTURED_STD_OUT" -ne 0 ]]; then cat "${TEST_TMPDIR}/captured.out" CAPTURED_STD_OUT=0 fi if [[ "$CAPTURED_STD_ERR" -ne 0 ]]; then cat "${TEST_TMPDIR}/captured.err" 1>&2 cat_jvm_log "$(cat "${TEST_TMPDIR}/captured.err")" CAPTURED_STD_ERR=0 fi fi if [[ -n "${1-}" ]] ; then echo "$1" 1>&2 fi if [[ -n "${BASH-}" ]]; then local caller_n=0 while [[ $caller_n -lt 4 ]] && \ caller_out=$(caller $caller_n 2>/dev/null); do test $caller_n -eq 0 && echo "CALLER stack (max 4):" echo " $caller_out" let caller_n=caller_n+1 done 1>&2 fi if [[ -n "${status_code}" && "${status_code}" -ne 0 ]]; then exit "$status_code" else exit 1 fi } # Print message in "$1" then record that a non-fatal error occurred in # ERROR_COUNT ERROR_COUNT="${ERROR_COUNT:-0}" error () { if [[ -n "$1" ]] ; then echo "$1" 1>&2 fi ERROR_COUNT=$(($ERROR_COUNT + 1)) } # Die if "$1" != "$2", print $3 as death reason check_eq () { [[ "$1" = "$2" ]] || die "Check failed: '$1' == '$2' ${3:+ ($3)}" } # Die if "$1" == "$2", print $3 as death reason check_ne () { [[ "$1" != "$2" ]] || die "Check failed: '$1' != '$2' ${3:+ ($3)}" } # The structure of the following if statements is such that if '[[' fails # (e.g., a non-number was passed in) then the check will fail. # Die if "$1" > "$2", print $3 as death reason check_le () { [[ "$1" -gt "$2" ]] || die "Check failed: '$1' <= '$2' ${3:+ ($3)}" } # Die if "$1" >= "$2", print $3 as death reason check_lt () { [[ "$1" -lt "$2" ]] || die "Check failed: '$1' < '$2' ${3:+ ($3)}" } # Die if "$1" < "$2", print $3 as death reason check_ge () { [[ "$1" -ge "$2" ]] || die "Check failed: '$1' >= '$2' ${3:+ ($3)}" } # Die if "$1" <= "$2", print $3 as death reason check_gt () { [[ "$1" -gt "$2" ]] || die "Check failed: '$1' > '$2' ${3:+ ($3)}" } # Die if $2 !~ $1; print $3 as death reason check_match () { expr match "$2" "$1" >/dev/null || \ die "Check failed: '$2' does not match regex '$1' ${3:+ ($3)}" } # Run command "$1" at exit. Like "trap" but multiple atexits don't # overwrite each other. Will break if someone does call trap # directly. So, don't do that. ATEXIT="${ATEXIT-}" atexit () { if [[ -z "$ATEXIT" ]]; then ATEXIT="$1" else ATEXIT="$1 ; $ATEXIT" fi trap "$ATEXIT" EXIT } ## TEST_TMPDIR if [[ -z "${TEST_TMPDIR:-}" ]]; then export TEST_TMPDIR="$(mktemp -d ${TMPDIR:-/tmp}/bazel-test.XXXXXXXX)" fi if [[ ! -e "${TEST_TMPDIR}" ]]; then mkdir -p -m 0700 "${TEST_TMPDIR}" # Clean TEST_TMPDIR on exit atexit "rm -fr ${TEST_TMPDIR}" fi # Functions to compare the actual output of a test to the expected # (golden) output. # # Usage: # capture_test_stdout # ... do something ... # diff_test_stdout "$TEST_SRCDIR/path/to/golden.out" # Redirect a file descriptor to a file. CAPTURED_STD_OUT="${CAPTURED_STD_OUT:-0}" CAPTURED_STD_ERR="${CAPTURED_STD_ERR:-0}" capture_test_stdout () { exec 3>&1 # Save stdout as fd 3 exec 4>"${TEST_TMPDIR}/captured.out" exec 1>&4 CAPTURED_STD_OUT=1 } capture_test_stderr () { exec 6>&2 # Save stderr as fd 6 exec 7>"${TEST_TMPDIR}/captured.err" exec 2>&7 CAPTURED_STD_ERR=1 } # Force XML_OUTPUT_FILE to an existing path if [[ -z "${XML_OUTPUT_FILE:-}" ]]; then XML_OUTPUT_FILE=${TEST_TMPDIR}/output.xml fi # Functions to provide easy access to external repository outputs in the sibling # repository layout. # # Usage: # bin_dir # genfiles_dir # testlogs_dir testlogs_dir() { echo $(bazel info bazel-testlogs | sed "s|bazel-out|bazel-out/$1|") }