Windows: fix tests to work with test wrapper

Fix the shell tests to work with
--experimental_windows_native_test_wrapper (when
using Bazel built at HEAD).

In this change:

- Remove the is_windows function definition from
  testenv.sh, to ensure that tests wanting to
  check the platform will define their own
  is_windows variable (as many tests already do).

- Define the is_windows variable using `uname` in
  every test that needs to know the platform.

- Use the Bash runfiles library in the affected
  tests.

- Every test that calls "bazel shutdown" now uses
  it with try_with_timeout, so tests won't fail
  flakily when bazel cannot immediately be shut
  down.

See https://github.com/bazelbuild/bazel/issues/5508

Closes #7126.

PiperOrigin-RevId: 229539256
diff --git a/src/test/shell/bazel/BUILD b/src/test/shell/bazel/BUILD
index 6c417a6..a7e7f87 100644
--- a/src/test/shell/bazel/BUILD
+++ b/src/test/shell/bazel/BUILD
@@ -91,6 +91,7 @@
     srcs = ["bazel_windows_example_test.sh"],
     data = [
         ":test-deps",
+        "@bazel_tools//tools/bash/runfiles",
     ],
 )
 
@@ -351,7 +352,10 @@
     name = "external_path_test",
     size = "medium",
     srcs = ["external_path_test.sh"],
-    data = [":test-deps"],
+    data = [
+        ":test-deps",
+        "@bazel_tools//tools/bash/runfiles",
+    ],
     shard_count = 6,
     tags = ["no_windows"],
 )
@@ -630,6 +634,7 @@
     data = [
         ":test-deps",
         "//src:bazel",
+        "@bazel_tools//tools/bash/runfiles",
     ],
     tags = ["no_windows"],
 )
@@ -654,6 +659,7 @@
         ":test-deps",
         "//:bazel-distfile",
         "//src:embedded_jdk_allmodules",
+        "@bazel_tools//tools/bash/runfiles",
     ],
     tags = ["block-network"],
 )
diff --git a/src/test/shell/bazel/bazel_bootstrap_distfile_test.sh b/src/test/shell/bazel/bazel_bootstrap_distfile_test.sh
index 9739c0a..0153219 100755
--- a/src/test/shell/bazel/bazel_bootstrap_distfile_test.sh
+++ b/src/test/shell/bazel/bazel_bootstrap_distfile_test.sh
@@ -17,17 +17,60 @@
 # Test that bazel can be compiled out of the distribution artifact.
 #
 
-set -u
-DISTFILE=$(rlocation io_bazel/${1#./})
-EMBEDDED_JDK=$(rlocation io_bazel/${2#./})
-shift 1
+set -euo pipefail
+# --- begin runfiles.bash initialization ---
+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 ---
 
-# Load the test setup defined in the parent directory
-source $(rlocation io_bazel/src/test/shell/integration_test_setup.sh) \
+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 2019-01-15, Bazel on Windows only supports MSYS Bash.
+  declare -r is_windows=true
+  ;;
+*)
+  declare -r is_windows=false
+  ;;
+esac
+
+if [[ -n "${1:-}" ]]; then
+  declare -r DISTFILE=$(rlocation io_bazel/${1#./})
+else
+  fail "missing argument for DISTFILE"
+fi
+
+if [[ -n "${2:-}" ]]; then
+  declare -r EMBEDDED_JDK=$(rlocation io_bazel/${2#./})
+else
+  declare -r EMBEDDED_JDK=""
+fi
+
 function _log_progress() {
-  if is_windows; then
+  if $is_windows; then
     log_info "test_bootstrap: $*"
   fi
 }
diff --git a/src/test/shell/bazel/bazel_build_event_stream_test.sh b/src/test/shell/bazel/bazel_build_event_stream_test.sh
index 11f570c..19b558f 100755
--- a/src/test/shell/bazel/bazel_build_event_stream_test.sh
+++ b/src/test/shell/bazel/bazel_build_event_stream_test.sh
@@ -43,13 +43,32 @@
 
 #### SETUP #############################################################
 
-export MSYS_NO_PATHCONV=1
-export MSYS2_ARG_CONV_EXCL="*"
+# `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 2019-01-15, 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() {
   mkdir -p pkg
   touch remote_file
-  if is_windows; then
+  if $is_windows; then
     # Windows needs "file:///c:/foo/bar".
     FILE_URL="file:///$(cygpath -m "$PWD")/remote_file"
   else
diff --git a/src/test/shell/bazel/bazel_experimental_ui_test.sh b/src/test/shell/bazel/bazel_experimental_ui_test.sh
index 2274a9c..0c8c272 100755
--- a/src/test/shell/bazel/bazel_experimental_ui_test.sh
+++ b/src/test/shell/bazel/bazel_experimental_ui_test.sh
@@ -41,9 +41,29 @@
 source "$(rlocation "io_bazel/src/test/shell/integration_test_setup.sh")" \
   || { echo "integration_test_setup.sh not found!" >&2; exit 1; }
 
-#### SETUP #############################################################
+# `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 2019-01-15, Bazel on Windows only supports MSYS Bash.
+  declare -r is_windows=true
+  ;;
+*)
+  declare -r is_windows=false
+  ;;
+esac
 
-set -e
+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
+
+#### SETUP #############################################################
 
 add_to_bazelrc "build --genrule_strategy=local"
 add_to_bazelrc "test --test_strategy=standalone"
@@ -51,7 +71,7 @@
 function set_up() {
   mkdir -p pkg
   touch remote_file
-  if is_windows; then
+  if $is_windows; then
     # The correct syntax for http_file on Windows is "file:///c:/foo/bar.txt"
     local -r cwd="/$(cygpath -m "$PWD")"
   else
diff --git a/src/test/shell/bazel/bazel_rules_test.sh b/src/test/shell/bazel/bazel_rules_test.sh
index bd70148..2490af2 100755
--- a/src/test/shell/bazel/bazel_rules_test.sh
+++ b/src/test/shell/bazel/bazel_rules_test.sh
@@ -42,8 +42,27 @@
 source "$(rlocation "io_bazel/src/test/shell/integration_test_setup.sh")" \
   || { echo "integration_test_setup.sh not found!" >&2; exit 1; }
 
-export MSYS_NO_PATHCONV=1
-export MSYS2_ARG_CONV_EXCL="*"
+# `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 2019-01-15, 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 test_sh_test() {
   mkdir -p a
@@ -290,7 +309,7 @@
   local new_tmpdir="$(mktemp -d "${TEST_TMPDIR}/newfancytmpdirXXXXXX")"
   [ -d "${new_tmpdir}" ] || \
     fail "Could not create new temporary directory ${new_tmpdir}"
-  if is_windows; then
+  if $is_windows; then
     export PATH="$PATH_TO_BAZEL_WRAPPER;/bin;/usr/bin;/random/path;${old_path}"
     local old_tmpdir="${TMP:-}"
     export TMP="${new_tmpdir}"
@@ -301,7 +320,7 @@
   fi
   bazel build //pkg:test --spawn_strategy=standalone --action_env=PATH \
     || fail "Failed to build //pkg:test"
-  if is_windows; then
+  if $is_windows; then
     local -r EXPECTED_PATH="$PATH_TO_BAZEL_WRAPPER:.*/random/path"
     # new_tmpdir is based on $TEST_TMPDIR which is not Unix-style -- convert it.
     local -r EXPECTED_TMP="$(cygpath -u "$new_tmpdir")"
@@ -312,7 +331,7 @@
   assert_contains "PATH=$EXPECTED_PATH" bazel-genfiles/pkg/test.out
   # Bazel respects the client environment's TMPDIR.
   assert_contains "TMPDIR=${EXPECTED_TMP}$" bazel-genfiles/pkg/test.out
-  if is_windows; then
+  if $is_windows; then
     export TMP="${old_tmpdir}"
   else
     export TMPDIR="${old_tmpdir}"
diff --git a/src/test/shell/bazel/bazel_windows_example_test.sh b/src/test/shell/bazel/bazel_windows_example_test.sh
index a8ccb89..5a9736e 100755
--- a/src/test/shell/bazel/bazel_windows_example_test.sh
+++ b/src/test/shell/bazel/bazel_windows_example_test.sh
@@ -17,16 +17,55 @@
 # Tests the examples provided in Bazel with MSVC toolchain
 #
 
-if ! type rlocation &> /dev/null; then
-  # We do not care about this test on old Bazel releases.
-  exit 0
+set -euo pipefail
+# --- begin runfiles.bash initialization ---
+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 ---
 
 # Load the test setup defined in the parent directory
 source $(rlocation io_bazel/src/test/shell/integration_test_setup.sh) \
   || { echo "integration_test_setup.sh not found!" >&2; exit 1; }
 
-if ! is_windows; then
+# `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 2019-01-15, 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
+
+if ! "$is_windows"; then
   echo "This test suite requires running on Windows. But now is ${PLATFORM}" >&2
   exit 0
 fi
diff --git a/src/test/shell/bazel/bazel_with_jdk_test.sh b/src/test/shell/bazel/bazel_with_jdk_test.sh
index ee811c0..7fc5643 100755
--- a/src/test/shell/bazel/bazel_with_jdk_test.sh
+++ b/src/test/shell/bazel/bazel_with_jdk_test.sh
@@ -17,10 +17,53 @@
 # Tests that the version of Bazel with a bundled JDK works.
 #
 
-# Load the test setup defined in the parent directory
-source $(rlocation io_bazel/src/test/shell/integration_test_setup.sh) \
+set -euo pipefail
+# --- begin runfiles.bash initialization ---
+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 2019-01-15, 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 bazel() {
   $(rlocation io_bazel/src/bazel) --bazelrc=$TEST_TMPDIR/bazelrc "$@"
   return $?
@@ -28,7 +71,7 @@
 
 function set_up() {
   # TODO(philwo) remove this when the testenv improvement change is in
-  if is_windows; then
+  if $is_windows; then
     export PATH=/c/python_27_amd64/files:$PATH
     EXTRA_BAZELRC="build --cpu=x64_windows_msvc"
     setup_bazelrc
diff --git a/src/test/shell/bazel/external_patching_test.sh b/src/test/shell/bazel/external_patching_test.sh
index 6ddd024..70003d2 100755
--- a/src/test/shell/bazel/external_patching_test.sh
+++ b/src/test/shell/bazel/external_patching_test.sh
@@ -41,7 +41,30 @@
 source "$(rlocation "io_bazel/src/test/shell/integration_test_setup.sh")" \
   || { echo "integration_test_setup.sh not found!" >&2; exit 1; }
 
-if is_windows; then
+# `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 2019-01-15, 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
+
+
+if $is_windows; then
   export MSYS_NO_PATHCONV=1
   export MSYS2_ARG_CONV_EXCL="*"
 fi
@@ -61,7 +84,7 @@
 }
 
 function get_extrepourl() {
-  if is_windows; then
+  if $is_windows; then
     echo "file:///$(cygpath -m $1)"
   else
     echo "file://$1"
@@ -175,7 +198,7 @@
 
 test_patch_git() {
   EXTREPODIR=`pwd`
-  if is_windows; then
+  if $is_windows; then
     EXTREPODIR="$(cygpath -m ${EXTREPODIR})"
   fi
 
@@ -382,7 +405,7 @@
   ## Verify that the BUILD file of an external repository can be overridden
   ## via the git_repository rule.
   EXTREPODIR=`pwd`
-  if is_windows; then
+  if $is_windows; then
     EXTREPODIR="$(cygpath -m ${EXTREPODIR})"
   fi
 
@@ -450,7 +473,7 @@
   ## Verify that the BUILD file of an external repository can be overridden
   ## via specified content in the git_repository rule.
   EXTREPODIR=`pwd`
-  if is_windows; then
+  if $is_windows; then
     EXTREPODIR="$(cygpath -m ${EXTREPODIR})"
   fi
 
diff --git a/src/test/shell/bazel/git_repository_test.sh b/src/test/shell/bazel/git_repository_test.sh
index 3dc8ab9..59a83ce 100755
--- a/src/test/shell/bazel/git_repository_test.sh
+++ b/src/test/shell/bazel/git_repository_test.sh
@@ -42,7 +42,22 @@
 source "$(rlocation "io_bazel/src/test/shell/integration_test_setup.sh")" \
   || { echo "integration_test_setup.sh not found!" >&2; exit 1; }
 
-if is_windows; then
+# `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 2019-01-15, Bazel on Windows only supports MSYS Bash.
+  declare -r is_windows=true
+  ;;
+*)
+  declare -r is_windows=false
+  ;;
+esac
+
+if $is_windows; then
   export MSYS_NO_PATHCONV=1
   export MSYS2_ARG_CONV_EXCL="*"
   # Enable symlink runfiles tree to make bazel run work
diff --git a/src/test/shell/bazel/skylark_git_repository_test.sh b/src/test/shell/bazel/skylark_git_repository_test.sh
index e0a7a37..c4e1498 100755
--- a/src/test/shell/bazel/skylark_git_repository_test.sh
+++ b/src/test/shell/bazel/skylark_git_repository_test.sh
@@ -42,7 +42,22 @@
 source "$(rlocation "io_bazel/src/test/shell/integration_test_setup.sh")" \
   || { echo "integration_test_setup.sh not found!" >&2; exit 1; }
 
-if is_windows; then
+# `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 2019-01-15, Bazel on Windows only supports MSYS Bash.
+  declare -r is_windows=true
+  ;;
+*)
+  declare -r is_windows=false
+  ;;
+esac
+
+if $is_windows; then
   export MSYS_NO_PATHCONV=1
   export MSYS2_ARG_CONV_EXCL="*"
   # Enable symlink runfiles tree to make bazel run work
diff --git a/src/test/shell/integration/aquery_test.sh b/src/test/shell/integration/aquery_test.sh
index aacf3a3..86efff9 100755
--- a/src/test/shell/integration/aquery_test.sh
+++ b/src/test/shell/integration/aquery_test.sh
@@ -124,7 +124,7 @@
   # their actual contents since that would be too much.
   assert_contains "Inputs: \[" output
   assert_contains "Outputs: \[" output
-  if is_windows; then
+  if $is_windows; then
     assert_contains "Command Line: .*bash\.exe" output
   else
     assert_contains "Command Line: (" output
@@ -806,7 +806,7 @@
 
   # Darwin and Windows only produce 1 CppCompileActionTemplate with PIC,
   # while Linux has both PIC and non-PIC CppCompileActionTemplates
-  if (is_darwin || is_windows); then
+  if (is_darwin || $is_windows); then
     expected_num_actions=1
   else
     expected_num_actions=2
diff --git a/src/test/shell/integration/cpp_test.sh b/src/test/shell/integration/cpp_test.sh
index 7c777e7..0f58c30 100755
--- a/src/test/shell/integration/cpp_test.sh
+++ b/src/test/shell/integration/cpp_test.sh
@@ -54,6 +54,12 @@
   export MSYS2_ARG_CONV_EXCL="*"
 fi
 
+if ! type try_with_timeout >&/dev/null; then
+  # Bazel's testenv.sh defines try_with_timeout but the Google-internal version
+  # uses a different testenv.sh.
+  function try_with_timeout() { $* ; }
+fi
+
 #### TESTS #############################################################
 
 function test_no_rebuild_on_irrelevant_header_change() {
@@ -145,7 +151,7 @@
 
   bazel build -s //$pkg:a >& $TEST_log || fail "build failed"
   expect_log "Compiling $pkg/a.cc"
-  bazel shutdown >& /dev/null || fail "query failed"
+  try_with_timeout bazel shutdown || fail "shutdown failed"
   bazel build -s //$pkg:a >& $TEST_log || fail "build failed"
   expect_not_log "Compiling $pkg/a.cc"
 }
diff --git a/src/test/shell/integration/execution_phase_tests.sh b/src/test/shell/integration/execution_phase_tests.sh
index 9182c3e..7271779 100755
--- a/src/test/shell/integration/execution_phase_tests.sh
+++ b/src/test/shell/integration/execution_phase_tests.sh
@@ -59,12 +59,18 @@
 
 #### HELPER FUNCTIONS ##################################################
 
+if ! type try_with_timeout >&/dev/null; then
+  # Bazel's testenv.sh defines try_with_timeout but the Google-internal version
+  # uses a different testenv.sh.
+  function try_with_timeout() { $* ; }
+fi
+
 function set_up() {
     cd ${WORKSPACE_DIR}
 }
 
 function tear_down() {
-    bazel shutdown
+  try_with_timeout bazel shutdown
 }
 
 # Looks for the last occurrence of a log message in a log file.
diff --git a/src/test/shell/integration/experimental_ui_test.sh b/src/test/shell/integration/experimental_ui_test.sh
index 213a576..60263a8 100755
--- a/src/test/shell/integration/experimental_ui_test.sh
+++ b/src/test/shell/integration/experimental_ui_test.sh
@@ -294,7 +294,7 @@
   BAZEL_QUERY_OUTPUT=`bazel query --experimental_ui 'deps(//pkg:true)'`
   echo "$BAZEL_QUERY_OUTPUT" | grep -q -v '^[@/]' \
    && fail "bazel query output is >$BAZEL_QUERY_OUTPUT<" || true
-  if ! is_windows; then
+  if ! $is_windows; then
     echo "$BAZEL_QUERY_OUTPUT" | grep -q $'\r' \
      && fail "bazel query output is >$BAZEL_QUERY_OUTPUT<" || true
   fi
diff --git a/src/test/shell/integration/loading_phase_test.sh b/src/test/shell/integration/loading_phase_test.sh
index e673a5f..8c7344d 100755
--- a/src/test/shell/integration/loading_phase_test.sh
+++ b/src/test/shell/integration/loading_phase_test.sh
@@ -65,12 +65,18 @@
 
 #### HELPER FUNCTIONS ##################################################
 
+if ! type try_with_timeout >&/dev/null; then
+  # Bazel's testenv.sh defines try_with_timeout but the Google-internal version
+  # uses a different testenv.sh.
+  function try_with_timeout() { $* ; }
+fi
+
 function set_up() {
     cd ${WORKSPACE_DIR}
 }
 
 function tear_down() {
-    bazel shutdown
+  try_with_timeout bazel shutdown
 }
 
 #### TESTS #############################################################
diff --git a/src/test/shell/integration/modify_execution_info_test.sh b/src/test/shell/integration/modify_execution_info_test.sh
index 537f15d..20eb058 100755
--- a/src/test/shell/integration/modify_execution_info_test.sh
+++ b/src/test/shell/integration/modify_execution_info_test.sh
@@ -58,12 +58,18 @@
 
 #### HELPER FUNCTIONS ##################################################
 
+if ! type try_with_timeout >&/dev/null; then
+  # Bazel's testenv.sh defines try_with_timeout but the Google-internal version
+  # uses a different testenv.sh.
+  function try_with_timeout() { $* ; }
+fi
+
 function set_up() {
     cd ${WORKSPACE_DIR}
 }
 
 function tear_down() {
-    bazel shutdown
+  try_with_timeout bazel shutdown
 }
 
 #### TESTS #############################################################
diff --git a/src/test/shell/integration/nonincremental_builds_test.sh b/src/test/shell/integration/nonincremental_builds_test.sh
index 430740f..ca66d3a 100755
--- a/src/test/shell/integration/nonincremental_builds_test.sh
+++ b/src/test/shell/integration/nonincremental_builds_test.sh
@@ -64,9 +64,14 @@
   export MSYS2_ARG_CONV_EXCL="*"
 fi
 
+if ! type try_with_timeout >&/dev/null; then
+  # Bazel's testenv.sh defines try_with_timeout but the Google-internal version
+  # uses a different testenv.sh.
+  function try_with_timeout() { $* ; }
+fi
 
 function tear_down() {
-    bazel shutdown || fail "Failed to shut down bazel"
+  try_with_timeout bazel shutdown || fail "Failed to shut down bazel"
 }
 
 #### TESTS #############################################################
diff --git a/src/test/shell/integration/output_filter_test.sh b/src/test/shell/integration/output_filter_test.sh
index 76def12..d51a828 100755
--- a/src/test/shell/integration/output_filter_test.sh
+++ b/src/test/shell/integration/output_filter_test.sh
@@ -61,7 +61,7 @@
   # "test warning filter for C compilation"
   local -r pkg=$FUNCNAME
 
-  if is_windows; then
+  if $is_windows; then
     local -r copts=\"/W3\"
   else
     local -r copts=""
diff --git a/src/test/shell/testenv.sh b/src/test/shell/testenv.sh
index dd96829..3dce164 100755
--- a/src/test/shell/testenv.sh
+++ b/src/test/shell/testenv.sh
@@ -19,12 +19,7 @@
 # TODO(bazel-team): This file is currently an append of the old testenv.sh and
 # test-setup.sh files. This must be cleaned up eventually.
 
-PLATFORM="$(uname -s | tr 'A-Z' 'a-z')"
-
-function is_windows() {
-  # On windows, the shell test is actually running on msys
-  [[ "${PLATFORM}" =~ msys_nt* ]]
-}
+PLATFORM="$(uname -s | tr [:upper:] [:lower:])"
 
 function is_darwin() {
   [[ "${PLATFORM}" =~ darwin ]]
@@ -50,7 +45,7 @@
 fi
 
 # Set some environment variables needed on Windows.
-if is_windows; then
+if [[ $PLATFORM =~ msys ]]; then
   # TODO(philwo) remove this once we have a Bazel release that includes the CL
   # moving the Windows-specific TEST_TMPDIR into TestStrategy.
   TEST_TMPDIR_BASENAME="$(basename "$TEST_TMPDIR")"
@@ -73,7 +68,7 @@
 # Convert PATH_TO_BAZEL_WRAPPER to Unix path style on Windows, because it will be
 # added into PATH. There's problem if PATH=C:/msys64/usr/bin:/usr/local,
 # because ':' is used as both path separator and in C:/msys64/...
-if is_windows; then
+if [[ $PLATFORM =~ msys ]]; then
   PATH_TO_BAZEL_WRAPPER="$(cygpath -u "$PATH_TO_BAZEL_WRAPPER")"
 fi
 [ ! -f "${PATH_TO_BAZEL_WRAPPER}/bazel" ] \
@@ -91,7 +86,7 @@
 distdir_bzl_file="${BAZEL_RUNFILES}/distdir.bzl"
 
 # Java
-if is_windows; then
+if [[ $PLATFORM =~ msys ]]; then
   jdk_dir="$(cygpath -m $(cd $(rlocation local_jdk/bin/java.exe)/../..; pwd))"
 else
   jdk_dir="${TEST_SRCDIR}/local_jdk"
@@ -424,7 +419,7 @@
   [ "${new_workspace_dir}" = "${WORKSPACE_DIR}" ] \
     || log_fatal "Failed to create workspace"
 
-  if is_windows; then
+  if [[ $PLATFORM =~ msys ]]; then
     export BAZEL_SH="$(cygpath --windows /bin/bash)"
   fi
 }
@@ -462,7 +457,7 @@
     # Try to shutdown Bazel at the end to prevent a "Cannot delete path" error
     # on Windows when the outer Bazel tries to delete $TEST_TMPDIR.
     cd "${WORKSPACE_DIR}"
-    bazel shutdown || true
+    try_with_timeout bazel shutdown || true
   fi
 }
 
@@ -554,7 +549,7 @@
 function use_fake_python_runtimes() {
   # The stub script template automatically appends ".exe" to the Python binary
   # name if it doesn't already end in ".exe", ".com", or ".bat".
-  if is_windows; then
+  if [[ $PLATFORM =~ msys ]]; then
     PYTHON2_FILENAME="python2.bat"
     PYTHON3_FILENAME="python3.bat"
   else
@@ -595,7 +590,7 @@
 EOF
 
   # Windows .bat has uppercase ECHO and no shebang.
-  if is_windows; then
+  if [[ $PLATFORM =~ msys ]]; then
     cat > tools/python/$PYTHON2_FILENAME << EOF
 @ECHO I am Python 2
 EOF