xref: /aosp_15_r20/external/bazelbuild-rules_android/test/bashunit/unittest_utils.sh (revision 9e965d6fece27a77de5377433c2f7e6999b8cc0b)
1*9e965d6fSRomain Jobredeaux# Copyright 2020 The Bazel Authors. All rights reserved.
2*9e965d6fSRomain Jobredeaux#
3*9e965d6fSRomain Jobredeaux# Licensed under the Apache License, Version 2.0 (the "License");
4*9e965d6fSRomain Jobredeaux# you may not use this file except in compliance with the License.
5*9e965d6fSRomain Jobredeaux# You may obtain a copy of the License at
6*9e965d6fSRomain Jobredeaux#
7*9e965d6fSRomain Jobredeaux#    http://www.apache.org/licenses/LICENSE-2.0
8*9e965d6fSRomain Jobredeaux#
9*9e965d6fSRomain Jobredeaux# Unless required by applicable law or agreed to in writing, software
10*9e965d6fSRomain Jobredeaux# distributed under the License is distributed on an "AS IS" BASIS,
11*9e965d6fSRomain Jobredeaux# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12*9e965d6fSRomain Jobredeaux# See the License for the specific language governing permissions and
13*9e965d6fSRomain Jobredeaux# limitations under the License.
14*9e965d6fSRomain Jobredeaux
15*9e965d6fSRomain Jobredeaux# Support for unittest.bash
16*9e965d6fSRomain Jobredeaux
17*9e965d6fSRomain Jobredeaux#### Set up the test environment.
18*9e965d6fSRomain Jobredeaux
19*9e965d6fSRomain Jobredeauxset -euo pipefail
20*9e965d6fSRomain Jobredeaux
21*9e965d6fSRomain Jobredeauxcat_jvm_log () {
22*9e965d6fSRomain Jobredeaux  if [[ "$log_content" =~ \
23*9e965d6fSRomain Jobredeaux      "(error code:".*", error message: '".*"', log file: '"(.*)"')" ]]; then
24*9e965d6fSRomain Jobredeaux    echo >&2
25*9e965d6fSRomain Jobredeaux    echo "Content of ${BASH_REMATCH[1]}:" >&2
26*9e965d6fSRomain Jobredeaux    cat "${BASH_REMATCH[1]}" >&2
27*9e965d6fSRomain Jobredeaux  fi
28*9e965d6fSRomain Jobredeaux}
29*9e965d6fSRomain Jobredeaux
30*9e965d6fSRomain Jobredeaux# Print message in "$1" then exit with status "$2"
31*9e965d6fSRomain Jobredeauxdie () {
32*9e965d6fSRomain Jobredeaux  # second argument is optional, defaulting to 1
33*9e965d6fSRomain Jobredeaux  local status_code=${2:-1}
34*9e965d6fSRomain Jobredeaux  # Stop capturing stdout/stderr, and dump captured output
35*9e965d6fSRomain Jobredeaux  if [[ "$CAPTURED_STD_ERR" -ne 0 || "$CAPTURED_STD_OUT" -ne 0 ]]; then
36*9e965d6fSRomain Jobredeaux    restore_outputs
37*9e965d6fSRomain Jobredeaux    if [[ "$CAPTURED_STD_OUT" -ne 0 ]]; then
38*9e965d6fSRomain Jobredeaux        cat "${TEST_TMPDIR}/captured.out"
39*9e965d6fSRomain Jobredeaux        CAPTURED_STD_OUT=0
40*9e965d6fSRomain Jobredeaux    fi
41*9e965d6fSRomain Jobredeaux    if [[ "$CAPTURED_STD_ERR" -ne 0 ]]; then
42*9e965d6fSRomain Jobredeaux        cat "${TEST_TMPDIR}/captured.err" 1>&2
43*9e965d6fSRomain Jobredeaux        cat_jvm_log "$(cat "${TEST_TMPDIR}/captured.err")"
44*9e965d6fSRomain Jobredeaux        CAPTURED_STD_ERR=0
45*9e965d6fSRomain Jobredeaux    fi
46*9e965d6fSRomain Jobredeaux  fi
47*9e965d6fSRomain Jobredeaux
48*9e965d6fSRomain Jobredeaux  if [[ -n "${1-}" ]] ; then
49*9e965d6fSRomain Jobredeaux      echo "$1" 1>&2
50*9e965d6fSRomain Jobredeaux  fi
51*9e965d6fSRomain Jobredeaux  if [[ -n "${BASH-}" ]]; then
52*9e965d6fSRomain Jobredeaux    local caller_n=0
53*9e965d6fSRomain Jobredeaux    while [[ $caller_n -lt 4 ]] && \
54*9e965d6fSRomain Jobredeaux        caller_out=$(caller $caller_n 2>/dev/null); do
55*9e965d6fSRomain Jobredeaux      test $caller_n -eq 0 && echo "CALLER stack (max 4):"
56*9e965d6fSRomain Jobredeaux      echo "  $caller_out"
57*9e965d6fSRomain Jobredeaux      let caller_n=caller_n+1
58*9e965d6fSRomain Jobredeaux    done 1>&2
59*9e965d6fSRomain Jobredeaux  fi
60*9e965d6fSRomain Jobredeaux  if [[ -n "${status_code}" && "${status_code}" -ne 0 ]]; then
61*9e965d6fSRomain Jobredeaux      exit "$status_code"
62*9e965d6fSRomain Jobredeaux  else
63*9e965d6fSRomain Jobredeaux      exit 1
64*9e965d6fSRomain Jobredeaux  fi
65*9e965d6fSRomain Jobredeaux}
66*9e965d6fSRomain Jobredeaux
67*9e965d6fSRomain Jobredeaux# Print message in "$1" then record that a non-fatal error occurred in
68*9e965d6fSRomain Jobredeaux# ERROR_COUNT
69*9e965d6fSRomain JobredeauxERROR_COUNT="${ERROR_COUNT:-0}"
70*9e965d6fSRomain Jobredeauxerror () {
71*9e965d6fSRomain Jobredeaux  if [[ -n "$1" ]] ; then
72*9e965d6fSRomain Jobredeaux      echo "$1" 1>&2
73*9e965d6fSRomain Jobredeaux  fi
74*9e965d6fSRomain Jobredeaux  ERROR_COUNT=$(($ERROR_COUNT + 1))
75*9e965d6fSRomain Jobredeaux}
76*9e965d6fSRomain Jobredeaux
77*9e965d6fSRomain Jobredeaux# Die if "$1" != "$2", print $3 as death reason
78*9e965d6fSRomain Jobredeauxcheck_eq () {
79*9e965d6fSRomain Jobredeaux  [[ "$1" = "$2" ]] || die "Check failed: '$1' == '$2' ${3:+ ($3)}"
80*9e965d6fSRomain Jobredeaux}
81*9e965d6fSRomain Jobredeaux
82*9e965d6fSRomain Jobredeaux# Die if "$1" == "$2", print $3 as death reason
83*9e965d6fSRomain Jobredeauxcheck_ne () {
84*9e965d6fSRomain Jobredeaux  [[ "$1" != "$2" ]] || die "Check failed: '$1' != '$2' ${3:+ ($3)}"
85*9e965d6fSRomain Jobredeaux}
86*9e965d6fSRomain Jobredeaux
87*9e965d6fSRomain Jobredeaux# The structure of the following if statements is such that if '[[' fails
88*9e965d6fSRomain Jobredeaux# (e.g., a non-number was passed in) then the check will fail.
89*9e965d6fSRomain Jobredeaux
90*9e965d6fSRomain Jobredeaux# Die if "$1" > "$2", print $3 as death reason
91*9e965d6fSRomain Jobredeauxcheck_le () {
92*9e965d6fSRomain Jobredeaux  [[ "$1" -gt "$2" ]] || die "Check failed: '$1' <= '$2' ${3:+ ($3)}"
93*9e965d6fSRomain Jobredeaux}
94*9e965d6fSRomain Jobredeaux
95*9e965d6fSRomain Jobredeaux# Die if "$1" >= "$2", print $3 as death reason
96*9e965d6fSRomain Jobredeauxcheck_lt () {
97*9e965d6fSRomain Jobredeaux  [[ "$1" -lt "$2" ]] || die "Check failed: '$1' < '$2' ${3:+ ($3)}"
98*9e965d6fSRomain Jobredeaux}
99*9e965d6fSRomain Jobredeaux
100*9e965d6fSRomain Jobredeaux# Die if "$1" < "$2", print $3 as death reason
101*9e965d6fSRomain Jobredeauxcheck_ge () {
102*9e965d6fSRomain Jobredeaux  [[ "$1" -ge "$2" ]] || die "Check failed: '$1' >= '$2' ${3:+ ($3)}"
103*9e965d6fSRomain Jobredeaux}
104*9e965d6fSRomain Jobredeaux
105*9e965d6fSRomain Jobredeaux# Die if "$1" <= "$2", print $3 as death reason
106*9e965d6fSRomain Jobredeauxcheck_gt () {
107*9e965d6fSRomain Jobredeaux  [[ "$1" -gt "$2" ]] || die "Check failed: '$1' > '$2' ${3:+ ($3)}"
108*9e965d6fSRomain Jobredeaux}
109*9e965d6fSRomain Jobredeaux
110*9e965d6fSRomain Jobredeaux# Die if $2 !~ $1; print $3 as death reason
111*9e965d6fSRomain Jobredeauxcheck_match ()
112*9e965d6fSRomain Jobredeaux{
113*9e965d6fSRomain Jobredeaux  expr match "$2" "$1" >/dev/null || \
114*9e965d6fSRomain Jobredeaux    die "Check failed: '$2' does not match regex '$1' ${3:+ ($3)}"
115*9e965d6fSRomain Jobredeaux}
116*9e965d6fSRomain Jobredeaux
117*9e965d6fSRomain Jobredeaux# Run command "$1" at exit. Like "trap" but multiple atexits don't
118*9e965d6fSRomain Jobredeaux# overwrite each other. Will break if someone does call trap
119*9e965d6fSRomain Jobredeaux# directly. So, don't do that.
120*9e965d6fSRomain JobredeauxATEXIT="${ATEXIT-}"
121*9e965d6fSRomain Jobredeauxatexit () {
122*9e965d6fSRomain Jobredeaux  if [[ -z "$ATEXIT" ]]; then
123*9e965d6fSRomain Jobredeaux      ATEXIT="$1"
124*9e965d6fSRomain Jobredeaux  else
125*9e965d6fSRomain Jobredeaux      ATEXIT="$1 ; $ATEXIT"
126*9e965d6fSRomain Jobredeaux  fi
127*9e965d6fSRomain Jobredeaux  trap "$ATEXIT" EXIT
128*9e965d6fSRomain Jobredeaux}
129*9e965d6fSRomain Jobredeaux
130*9e965d6fSRomain Jobredeaux## TEST_TMPDIR
131*9e965d6fSRomain Jobredeauxif [[ -z "${TEST_TMPDIR:-}" ]]; then
132*9e965d6fSRomain Jobredeaux  export TEST_TMPDIR="$(mktemp -d ${TMPDIR:-/tmp}/bazel-test.XXXXXXXX)"
133*9e965d6fSRomain Jobredeauxfi
134*9e965d6fSRomain Jobredeauxif [[ ! -e "${TEST_TMPDIR}" ]]; then
135*9e965d6fSRomain Jobredeaux  mkdir -p -m 0700 "${TEST_TMPDIR}"
136*9e965d6fSRomain Jobredeaux  # Clean TEST_TMPDIR on exit
137*9e965d6fSRomain Jobredeaux  atexit "rm -fr ${TEST_TMPDIR}"
138*9e965d6fSRomain Jobredeauxfi
139*9e965d6fSRomain Jobredeaux
140*9e965d6fSRomain Jobredeaux# Functions to compare the actual output of a test to the expected
141*9e965d6fSRomain Jobredeaux# (golden) output.
142*9e965d6fSRomain Jobredeaux#
143*9e965d6fSRomain Jobredeaux# Usage:
144*9e965d6fSRomain Jobredeaux#   capture_test_stdout
145*9e965d6fSRomain Jobredeaux#   ... do something ...
146*9e965d6fSRomain Jobredeaux#   diff_test_stdout "$TEST_SRCDIR/path/to/golden.out"
147*9e965d6fSRomain Jobredeaux
148*9e965d6fSRomain Jobredeaux# Redirect a file descriptor to a file.
149*9e965d6fSRomain JobredeauxCAPTURED_STD_OUT="${CAPTURED_STD_OUT:-0}"
150*9e965d6fSRomain JobredeauxCAPTURED_STD_ERR="${CAPTURED_STD_ERR:-0}"
151*9e965d6fSRomain Jobredeaux
152*9e965d6fSRomain Jobredeauxcapture_test_stdout () {
153*9e965d6fSRomain Jobredeaux  exec 3>&1 # Save stdout as fd 3
154*9e965d6fSRomain Jobredeaux  exec 4>"${TEST_TMPDIR}/captured.out"
155*9e965d6fSRomain Jobredeaux  exec 1>&4
156*9e965d6fSRomain Jobredeaux  CAPTURED_STD_OUT=1
157*9e965d6fSRomain Jobredeaux}
158*9e965d6fSRomain Jobredeaux
159*9e965d6fSRomain Jobredeauxcapture_test_stderr () {
160*9e965d6fSRomain Jobredeaux  exec 6>&2 # Save stderr as fd 6
161*9e965d6fSRomain Jobredeaux  exec 7>"${TEST_TMPDIR}/captured.err"
162*9e965d6fSRomain Jobredeaux  exec 2>&7
163*9e965d6fSRomain Jobredeaux  CAPTURED_STD_ERR=1
164*9e965d6fSRomain Jobredeaux}
165*9e965d6fSRomain Jobredeaux
166*9e965d6fSRomain Jobredeaux# Force XML_OUTPUT_FILE to an existing path
167*9e965d6fSRomain Jobredeauxif [[ -z "${XML_OUTPUT_FILE:-}" ]]; then
168*9e965d6fSRomain Jobredeaux  XML_OUTPUT_FILE=${TEST_TMPDIR}/output.xml
169*9e965d6fSRomain Jobredeauxfi
170*9e965d6fSRomain Jobredeaux
171*9e965d6fSRomain Jobredeaux# Functions to provide easy access to external repository outputs in the sibling
172*9e965d6fSRomain Jobredeaux# repository layout.
173*9e965d6fSRomain Jobredeaux#
174*9e965d6fSRomain Jobredeaux# Usage:
175*9e965d6fSRomain Jobredeaux#   bin_dir <repository name>
176*9e965d6fSRomain Jobredeaux#   genfiles_dir <repository name>
177*9e965d6fSRomain Jobredeaux#   testlogs_dir <repository name>
178*9e965d6fSRomain Jobredeaux
179*9e965d6fSRomain Jobredeauxtestlogs_dir() {
180*9e965d6fSRomain Jobredeaux  echo $(bazel info bazel-testlogs | sed "s|bazel-out|bazel-out/$1|")
181*9e965d6fSRomain Jobredeaux}
182