Unify internal and external unittest.bash by extracting some setup functions to a separate utils file.

PiperOrigin-RevId: 292216409
diff --git a/src/test/shell/BUILD b/src/test/shell/BUILD
index e654c40..fd9a047 100644
--- a/src/test/shell/BUILD
+++ b/src/test/shell/BUILD
@@ -21,7 +21,10 @@
 
 sh_library(
     name = "bashunit",
-    srcs = ["unittest.bash"],
+    srcs = [
+        "unittest.bash",
+        "unittest_utils.sh",
+    ],
     data = [
         "testenv.sh",
         "//tools:test_sharding_compliant",
diff --git a/src/test/shell/unittest.bash b/src/test/shell/unittest.bash
index ad23fe6..278810f 100644
--- a/src/test/shell/unittest.bash
+++ b/src/test/shell/unittest.bash
@@ -100,157 +100,8 @@
   trap - ERR
 }
 
-#### Set up the test environment, branched from the old shell/testenv.sh
-
-# Enable errexit with pretty stack traces.
-enable_errexit
-
-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 -o "$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 [ x"$status_code" != x -a x"$status_code" != x"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}/ouput.xml
-fi
+# Load the environment support utilities.
+source "${DIR}/unittest_utils.sh" || { echo "unittest_utils.sh not found" >&2; exit 1; }
 
 #### Global variables:
 
diff --git a/src/test/shell/unittest_utils.sh b/src/test/shell/unittest_utils.sh
new file mode 100644
index 0000000..4f7cb63
--- /dev/null
+++ b/src/test/shell/unittest_utils.sh
@@ -0,0 +1,170 @@
+# 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.
+
+# Enable errexit with pretty stack traces.
+enable_errexit
+
+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}/ouput.xml
+fi