| # source this file; set up for tests | |
| # Copyright (C) 2009-2025 Free Software Foundation, Inc. | |
| # This program is free software: you can redistribute it and/or modify | |
| # it under the terms of the GNU General Public License as published by | |
| # the Free Software Foundation, either version 3 of the License, or | |
| # (at your option) any later version. | |
| # This program is distributed in the hope that it will be useful, | |
| # but WITHOUT ANY WARRANTY; without even the implied warranty of | |
| # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
| # GNU General Public License for more details. | |
| # You should have received a copy of the GNU General Public License | |
| # along with this program. If not, see <https://www.gnu.org/licenses/>. | |
| # Using this file in a test | |
| # ========================= | |
| # | |
| # The typical skeleton of a test looks like this: | |
| # | |
| # #!/bin/sh | |
| # . "${srcdir=.}/init.sh"; path_prepend_ . | |
| # Execute some commands. | |
| # Note that these commands are executed in a subdirectory, therefore you | |
| # need to prepend "../" to relative filenames in the build directory. | |
| # Note that the "path_prepend_ ." is useful only if the body of your | |
| # test invokes programs residing in the initial directory. | |
| # For example, if the programs you want to test are in src/, and this test | |
| # script is named tests/test-1, then you would use "path_prepend_ ../src", | |
| # or perhaps export PATH='$(abs_top_builddir)/src$(PATH_SEPARATOR)'"$$PATH" | |
| # to all tests via automake's TESTS_ENVIRONMENT. | |
| # Set the exit code 0 for success, 77 for skipped, or 1 or other for failure. | |
| # Use the skip_ and fail_ functions to print a diagnostic and then exit | |
| # with the corresponding exit code. | |
| # Exit $? | |
| # Executing a test that uses this file | |
| # ==================================== | |
| # | |
| # Running a single test: | |
| # $ make check TESTS=test-foo.sh | |
| # | |
| # Running a single test, with verbose output: | |
| # $ make check TESTS=test-foo.sh VERBOSE=yes | |
| # | |
| # Running a single test, keeping the temporary directory: | |
| # $ make check TESTS=test-foo.sh KEEP=yes | |
| # | |
| # Running a single test, with single-stepping: | |
| # 1. Go into a sub-shell: | |
| # $ bash | |
| # 2. Set relevant environment variables from TESTS_ENVIRONMENT in the | |
| # Makefile: | |
| # $ export srcdir=../../tests # this is an example | |
| # 3. Execute the commands from the test, copy&pasting them one by one: | |
| # $ . "$srcdir/init.sh"; path_prepend_ . | |
| # ... | |
| # 4. Finally | |
| # $ exit | |
| # ============================================================================= | |
| # Elementary diagnostics | |
| ME_=`expr "./$0" : '.*/\(.*\)$'` | |
| # Prepare PATH_SEPARATOR. | |
| # The user is always right. | |
| if test "${PATH_SEPARATOR+set}" != set; then | |
| # Determine PATH_SEPARATOR by trying to find /bin/sh in a PATH which | |
| # contains only /bin. Note that ksh looks also at the FPATH variable, | |
| # so we have to set that as well for the test. | |
| PATH_SEPARATOR=: | |
| (PATH='/bin;/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 \ | |
| && { (PATH='/bin:/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 \ | |
| || PATH_SEPARATOR=';' | |
| } | |
| fi | |
| # We use a trap below for cleanup. This requires us to go through | |
| # hoops to get the right exit status transported through the handler. | |
| # So use 'Exit STATUS' instead of 'exit STATUS' inside of the tests. | |
| # Turn off errexit here so that we don't trip the bug with OSF1/Tru64 | |
| # sh inside this function. | |
| Exit () { set +e; (exit $1); exit $1; } | |
| # Print warnings (e.g., about skipped and failed tests) to this file number. | |
| # Override by defining to say, 9, in init.cfg, and putting say, | |
| # export ...ENVVAR_SETTINGS...; $(SHELL) 9>&2 | |
| # in the definition of TESTS_ENVIRONMENT in your tests/Makefile.am file. | |
| # This is useful when using automake's parallel tests mode, to print | |
| # the reason for skip/failure to console, rather than to the .log files. | |
| : ${stderr_fileno_=2} | |
| # Note that correct expansion of "$*" depends on IFS starting with ' '. | |
| # Always write the full diagnostic to stderr. | |
| # When stderr_fileno_ is not 2, also emit the first line of the | |
| # diagnostic to that file descriptor. | |
| warn_ () | |
| { | |
| # If IFS does not start with ' ', set it and emit the warning in a subshell. | |
| case $IFS in | |
| ' '*) printf '%s\n' "$*" >&2 | |
| test $stderr_fileno_ = 2 \ | |
| || { local args=$* | |
| local firstline=${args%%"$gl_init_sh_nl_"*} | |
| printf '%s\n' "$firstline" >&$stderr_fileno_ | |
| } | |
| ;; | |
| *) (IFS=' '; warn_ "$@");; | |
| esac | |
| } | |
| fail_ () { warn_ "$ME_: failed test: $@"; Exit 1; } | |
| skip_ () { warn_ "$ME_: skipped test: $@"; Exit 77; } | |
| fatal_ () { warn_ "$ME_: hard error: $@"; Exit 99; } | |
| framework_failure_ () { warn_ "$ME_: set-up failure: $@"; Exit 99; } | |
| # ============================================================================= | |
| # Ensure the shell supports modern syntax. | |
| # Sanitize this shell to POSIX mode, if possible. | |
| DUALCASE=1; export DUALCASE | |
| if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then | |
| emulate sh | |
| NULLCMD=: | |
| alias -g '${1+"$@"}'='"$@"' | |
| setopt NO_GLOB_SUBST | |
| else | |
| case `(set -o) 2>/dev/null` in | |
| *posix*) set -o posix ;; | |
| esac | |
| fi | |
| # We require $(...) support unconditionally. | |
| # We require that the printf built-in work correctly regarding octal escapes; | |
| # this eliminates /bin/sh on AIX 7.2. | |
| # We require non-surprising "local" semantics (this eliminates dash). | |
| # This takes the admittedly draconian step of eliminating dash, because the | |
| # assignment tab=$(printf '\t') works fine, yet preceding it with "local " | |
| # transforms it into an assignment that sets the variable to the empty string. | |
| # That is too counter-intuitive, and can lead to subtle run-time malfunction. | |
| # The example below is less subtle in that with dash, it evokes the run-time | |
| # exception "dash: 1: local: 1: bad variable name". | |
| # We require a few additional shell features only when $EXEEXT is nonempty, | |
| # in order to support automatic $EXEEXT emulation: | |
| # - hyphen-containing alias names | |
| # - we prefer to use ${var#...} substitution, rather than having | |
| # to work around lack of support for that feature. | |
| # The following code attempts to find a shell with support for these features. | |
| # If the current shell passes the test, we're done. Otherwise, test other | |
| # shells until we find one that passes. If one is found, re-exec it. | |
| # If no acceptable shell is found, skip the current test. | |
| # | |
| # The "...set -x; P=1 true 2>err..." test is to disqualify any shell that | |
| # emits "P=1" into err, as /bin/sh from SunOS 5.11 and OpenBSD 4.7 do. | |
| # | |
| # Use "9" to indicate success (rather than 0), in case some shell acts | |
| # like Solaris 10's /bin/sh but exits successfully instead of with status 2. | |
| # Eval this code in a subshell to determine a shell's suitability. | |
| # 10 - passes all tests; ok to use | |
| # 9 - ok, but enabling "set -x" corrupts app stderr; prefer higher score | |
| # ? - not ok | |
| gl_shell_test_script_=' | |
| test $(echo y) = y || exit 1 | |
| case $({ LC_ALL=en_US.UTF-8 printf "\\351" | |
| printf "\\351\\n" | |
| } 2>/dev/null | LC_ALL=C tr "\\351" x) in | |
| xx) ;; | |
| *) exit 1;; | |
| esac | |
| f_local_() { local v=1; }; f_local_ || exit 1 | |
| f_dash_local_fail_() { local t=$(printf " 1"); }; f_dash_local_fail_ | |
| score_=10 | |
| if test "$VERBOSE" = yes; then | |
| test -n "$( (exec 3>&1; set -x; P=1 true 2>&3) 2> /dev/null)" && score_=9 | |
| fi | |
| test -z "$EXEEXT" && exit $score_ | |
| shopt -s expand_aliases | |
| alias a-b="echo zoo" | |
| v=abx | |
| test ${v%x} = ab \ | |
| && test ${v#a} = bx \ | |
| && test $(a-b) = zoo \ | |
| && exit $score_ | |
| ' | |
| if test "x$1" = "x--no-reexec"; then | |
| shift | |
| else | |
| # Assume a working shell. Export to subshells (setup_ needs this). | |
| gl_set_x_corrupts_stderr_=false | |
| export gl_set_x_corrupts_stderr_ | |
| # Record the first marginally acceptable shell. | |
| marginal_= | |
| # Search for a shell that meets our requirements. | |
| for re_shell_ in __current__ "${CONFIG_SHELL:-no_shell}" \ | |
| /bin/sh bash dash zsh pdksh fail | |
| do | |
| test "$re_shell_" = no_shell && continue | |
| # If we've made it all the way to the sentinel, "fail" without | |
| # finding even a marginal shell, skip this test. | |
| if test "$re_shell_" = fail; then | |
| test -z "$marginal_" && skip_ failed to find an adequate shell | |
| re_shell_=$marginal_ | |
| break | |
| fi | |
| # When testing the current shell, simply "eval" the test code. | |
| # Otherwise, run it via $re_shell_ -c ... | |
| if test "$re_shell_" = __current__; then | |
| # 'eval'ing this code makes Solaris 10's /bin/sh exit with | |
| # $? set to 2. It does not evaluate any of the code after the | |
| # "unexpected" first '('. Thus, we must run it in a subshell. | |
| ( eval "$gl_shell_test_script_" ) > /dev/null 2>&1 | |
| else | |
| "$re_shell_" -c "$gl_shell_test_script_" 2>/dev/null | |
| fi | |
| st_=$? | |
| # $re_shell_ works just fine. Use it. | |
| if test $st_ = 10; then | |
| gl_set_x_corrupts_stderr_=false | |
| break | |
| fi | |
| # If this is our first marginally acceptable shell, remember it. | |
| if test "$st_:$marginal_" = 9: ; then | |
| marginal_="$re_shell_" | |
| gl_set_x_corrupts_stderr_=true | |
| fi | |
| done | |
| if test "$re_shell_" != __current__; then | |
| # Found a usable shell. Preserve -v and -x. | |
| case $- in | |
| *v*x* | *x*v*) opts_=-vx ;; | |
| *v*) opts_=-v ;; | |
| *x*) opts_=-x ;; | |
| *) opts_= ;; | |
| esac | |
| re_shell=$re_shell_ | |
| export re_shell | |
| exec "$re_shell_" $opts_ "$0" --no-reexec "$@" | |
| echo "$ME_: exec failed" 1>&2 | |
| exit 127 | |
| fi | |
| fi | |
| # ============================================================================= | |
| # Ensure the shell behaves reasonably. | |
| # If this is bash, turn off all aliases. | |
| test -n "$BASH_VERSION" && unalias -a | |
| # Note that when supporting $EXEEXT (transparently mapping from PROG_NAME to | |
| # PROG_NAME.exe), we want to support hyphen-containing names like test-acos. | |
| # That is part of the shell-selection test above. Why use aliases rather | |
| # than functions? Because support for hyphen-containing aliases is more | |
| # widespread than that for hyphen-containing function names. | |
| test -n "$EXEEXT" && test -n "$BASH_VERSION" && shopt -s expand_aliases | |
| # ============================================================================= | |
| # Creating a temporary directory (needed by the core test framework) | |
| # Create a temporary directory, much like mktemp -d does. | |
| # Written by Jim Meyering. | |
| # | |
| # Usage: mktempd_ /tmp template.XXXXXXXXXX | |
| # | |
| # First, try to use the mktemp program. | |
| # Failing that, we'll roll our own mktemp-like function: | |
| # - try to get random bytes from /dev/urandom, mapping them to file-name bytes | |
| # - failing that, generate output from a combination of quickly-varying | |
| # sources and awk. | |
| # - try to create the desired directory. | |
| # - make only $MAX_TRIES_ attempts | |
| # mkdir on msys2 does not support the '-m' option. | |
| case `(uname -o) 2>/dev/null` in | |
| Msys) | |
| mkdir () | |
| { | |
| if test " $1" = " -m"; then | |
| shift; shift | |
| fi | |
| /bin/mkdir "$@" | |
| } | |
| ;; | |
| esac | |
| # Helper function. Print $N pseudo-random bytes from a-zA-Z0-9. | |
| rand_bytes_ () | |
| { | |
| n_=$1 | |
| # Maybe try openssl rand -base64 $n_prime_|tr '+/=\012' abcd first? | |
| # But if they have openssl, they probably have mktemp, too. | |
| chars_=abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789 | |
| dev_rand_=/dev/urandom | |
| if test -r "$dev_rand_"; then | |
| # Note: 256-length($chars_) == 194; 3 copies of $chars_ is 186 + 8 = 194. | |
| dd ibs=$n_ count=1 if=$dev_rand_ 2>/dev/null \ | |
| | LC_ALL=C tr -c $chars_ 01234567$chars_$chars_$chars_ | |
| return | |
| fi | |
| # Fall back on quickly-varying sources + awk. | |
| # Limit awk program to 7th Edition Unix so that it works even on Solaris 10. | |
| (date; date +%N; free; who -a; w; ps auxww; ps -ef) 2>&1 | awk ' | |
| BEGIN { | |
| n = '"$n_"' | |
| for (i = 0; i < 256; i++) | |
| ordinal[sprintf ("%c", i)] = i | |
| } | |
| { | |
| for (i = 1; i <= length; i++) | |
| a[ai++ % n] += ordinal[substr ($0, i, 1)] | |
| } | |
| END { | |
| chars = "'"$chars_"'" | |
| charslen = length (chars) | |
| for (i = 0; i < n; i++) | |
| printf "%s", substr (chars, a[i] % charslen + 1, 1) | |
| printf "\n" | |
| } | |
| ' | |
| } | |
| mktempd_ () | |
| { | |
| case $# in | |
| 2);; | |
| *) fail_ "Usage: mktempd_ DIR TEMPLATE";; | |
| esac | |
| destdir_=$1 | |
| template_=$2 | |
| MAX_TRIES_=4 | |
| # Disallow any trailing slash on specified destdir: | |
| # it would subvert the post-mktemp "case"-based destdir test. | |
| case $destdir_ in | |
| / | //) destdir_slash_=$destdir;; | |
| */) fail_ "invalid destination dir: remove trailing slash(es)";; | |
| *) destdir_slash_=$destdir_/;; | |
| esac | |
| case $template_ in | |
| -*) fail_ \ | |
| "invalid template: $template_ (must not begin with '-')";; | |
| *XXXX) ;; | |
| *) fail_ \ | |
| "invalid template: $template_ (must have a suffix of at least 4 X's)";; | |
| esac | |
| # First, try GNU mktemp, where -t has no option-argument. | |
| # Put -t last, as GNU mktemp allows, so that the incompatible NetBSD mktemp | |
| # (where -t has an option-argument) fails instead of creating a junk dir. | |
| d=`unset TMPDIR; { mktemp -d -p "$destdir_" "$template_" -t; } 2>/dev/null` && | |
| # The resulting name must be in the specified directory. | |
| case $d in "$destdir_slash_"*) :;; *) false;; esac && | |
| # It must have created the directory. | |
| test -d "$d" && | |
| # It must have 0700 permissions. Handle sticky "S" bits. | |
| perms=`ls -dgo "$d" 2>/dev/null` && | |
| case $perms in drwx--[-S]---*) :;; *) false;; esac && { | |
| echo "$d" | |
| return | |
| } | |
| # If we reach this point, we'll have to create a directory manually. | |
| # Get a copy of the template without its suffix of X's. | |
| base_template_=`echo "$template_"|sed 's/XX*$//'` | |
| # Calculate how many X's we've just removed. | |
| template_length_=`echo "$template_" | wc -c` | |
| nx_=`echo "$base_template_" | wc -c` | |
| nx_=`expr $template_length_ - $nx_` | |
| err_= | |
| i_=1 | |
| while :; do | |
| X_=`rand_bytes_ $nx_` | |
| candidate_dir_="$destdir_slash_$base_template_$X_" | |
| err_=`mkdir -m 0700 "$candidate_dir_" 2>&1` \ | |
| && { echo "$candidate_dir_"; return; } | |
| test $MAX_TRIES_ -le $i_ && break; | |
| i_=`expr $i_ + 1` || break | |
| done | |
| fail_ "$err_" | |
| } | |
| # ============================================================================= | |
| # Core test framework | |
| # An arbitrary prefix to help distinguish test directories. | |
| testdir_prefix_ () { printf gt; } | |
| # Set up the environment for the test to run in. | |
| setup_ () | |
| { | |
| if test "$VERBOSE" = yes; then | |
| # Test whether set -x may cause the selected shell to corrupt an | |
| # application's stderr. Many do, including zsh-4.3.10 and the /bin/sh | |
| # from SunOS 5.11 and OpenBSD 4.7. | |
| # If enabling verbose output this way would cause trouble, simply | |
| # issue a warning and refrain. | |
| if $gl_set_x_corrupts_stderr_; then | |
| warn_ "using SHELL=$SHELL with 'set -x' corrupts stderr" | |
| else | |
| set -x | |
| fi | |
| fi | |
| initial_cwd_=$PWD | |
| # Create and enter the temporary directory. | |
| pfx_=`testdir_prefix_` | |
| test_dir_=`mktempd_ "$initial_cwd_" "$pfx_-$ME_.XXXX"` \ | |
| || fail_ "failed to create temporary directory in $initial_cwd_" | |
| cd "$test_dir_" || fail_ "failed to cd to temporary directory" | |
| # Set variables srcdir, builddir, for the convenience of the test. | |
| case $srcdir in | |
| /* | ?:*) ;; | |
| *) srcdir="../$srcdir" ;; | |
| esac | |
| builddir=".." | |
| export srcdir builddir | |
| # As autoconf-generated configure scripts do, ensure that IFS | |
| # is defined initially, so that saving and restoring $IFS works. | |
| gl_init_sh_nl_=' | |
| ' | |
| IFS=" "" $gl_init_sh_nl_" | |
| # This trap statement, along with a trap on 0 below, ensure that the | |
| # temporary directory, $test_dir_, is removed upon exit as well as | |
| # upon receipt of any of the listed signals. | |
| for sig_ in 1 2 3 13 15; do | |
| eval "trap 'Exit $(expr $sig_ + 128)' $sig_" | |
| done | |
| # Remove relative and non-accessible directories from PATH, including '.' | |
| # and Zero-length entries. | |
| saved_IFS="$IFS"; IFS="$PATH_SEPARATOR" | |
| new_PATH= | |
| for dir in $PATH; do | |
| IFS="$saved_IFS" | |
| case "$dir" in | |
| [\\/]* | ?:[\\/]*) | |
| test -d "$dir/." || continue | |
| new_PATH="${new_PATH}${new_PATH:+$PATH_SEPARATOR}${dir}" | |
| ;; | |
| esac | |
| done | |
| IFS="$saved_IFS" | |
| PATH="$new_PATH" | |
| export PATH | |
| } | |
| # This is a stub function that is run upon trap (upon regular exit and | |
| # interrupt). Override it with a per-test function, e.g., to unmount | |
| # a partition, or to undo any other global state changes. | |
| cleanup_ () { :; } | |
| # Run the user-overridable cleanup_ function, remove the temporary | |
| # directory and exit with the incoming value of $?. | |
| remove_tmp_ () | |
| { | |
| __st=$? | |
| cleanup_ | |
| if test "$KEEP" = yes; then | |
| echo "Not removing temporary directory $test_dir_" | |
| else | |
| # cd out of the directory we're about to remove | |
| cd "$initial_cwd_" || cd / || cd /tmp | |
| chmod -R u+rwx "$test_dir_" | |
| # If the first removal fails, wait for subprocesses to exit and try again. | |
| # If that fails and exit status was to be 0, change it to 1. | |
| rm -rf "$test_dir_" 2>/dev/null \ | |
| || { sleep 1 && rm -rf "$test_dir_"; } \ | |
| || { test $__st = 0 && __st=1; } | |
| fi | |
| exit $__st | |
| } | |
| # ============================================================================= | |
| # Prepending directories to PATH | |
| # Given a directory name, DIR, if every entry in it that matches *.exe | |
| # contains only the specified bytes (see the case stmt below), then print | |
| # a space-separated list of those names and return 0. Otherwise, don't | |
| # print anything and return 1. Naming constraints apply also to DIR. | |
| find_exe_basenames_ () | |
| { | |
| feb_dir_=$1 | |
| feb_fail_=0 | |
| feb_result_= | |
| feb_sp_= | |
| for feb_file_ in $feb_dir_/*.exe; do | |
| # If there was no *.exe file, or there existed a file named "*.exe" that | |
| # was deleted between the above glob expansion and the existence test | |
| # below, just skip it. | |
| test "x$feb_file_" = "x$feb_dir_/*.exe" && test ! -f "$feb_file_" \ | |
| && continue | |
| # Exempt [.exe, since we can't create a function by that name, yet | |
| # we can't invoke [ by PATH search anyways due to shell builtins. | |
| test "x$feb_file_" = "x$feb_dir_/[.exe" && continue | |
| case $feb_file_ in | |
| *[!-a-zA-Z/0-9_.+]*) feb_fail_=1; break;; | |
| *) # Remove leading file name components as well as the .exe suffix. | |
| feb_file_=${feb_file_##*/} | |
| feb_file_=${feb_file_%.exe} | |
| feb_result_="$feb_result_$feb_sp_$feb_file_";; | |
| esac | |
| feb_sp_=' ' | |
| done | |
| test $feb_fail_ = 0 && printf %s "$feb_result_" | |
| return $feb_fail_ | |
| } | |
| # Consider the files in directory, $1. | |
| # For each file name of the form PROG.exe, create an alias named | |
| # PROG that simply invokes PROG.exe, then return 0. If any selected | |
| # file name or the directory name, $1, contains an unexpected character, | |
| # define no alias and return 1. | |
| create_exe_shims_ () | |
| { | |
| case $EXEEXT in | |
| '') return 0 ;; | |
| .exe) ;; | |
| *) echo "$0: unexpected \$EXEEXT value: $EXEEXT" 1>&2; return 1 ;; | |
| esac | |
| base_names_=`find_exe_basenames_ $1` \ | |
| || { echo "$0 (exe_shim): skipping directory: $1" 1>&2; return 0; } | |
| if test -n "$base_names_"; then | |
| for base_ in $base_names_; do | |
| alias "$base_"="$base_$EXEEXT" | |
| done | |
| fi | |
| return 0 | |
| } | |
| # Use this function to prepend to PATH an absolute name for each | |
| # specified, possibly-$initial_cwd_-relative, directory. | |
| path_prepend_ () | |
| { | |
| while test $# != 0; do | |
| path_dir_=$1 | |
| case $path_dir_ in | |
| '') fail_ "invalid path dir: '$1'";; | |
| /* | ?:*) abs_path_dir_=$path_dir_;; | |
| *) abs_path_dir_=$initial_cwd_/$path_dir_;; | |
| esac | |
| case $abs_path_dir_ in | |
| *$PATH_SEPARATOR*) fail_ "invalid path dir: '$abs_path_dir_'";; | |
| esac | |
| PATH="$abs_path_dir_$PATH_SEPARATOR$PATH" | |
| # Create an alias, FOO, for each FOO.exe in this directory. | |
| create_exe_shims_ "$abs_path_dir_" \ | |
| || fail_ "something failed (above): $abs_path_dir_" | |
| shift | |
| done | |
| export PATH | |
| } | |
| # ============================================================================= | |
| # Convenience environment variables for the tests | |
| # ----------------------------------------------------------------------------- | |
| # Enable glibc's malloc-perturbing option. | |
| # This is useful for exposing code that depends on the fact that | |
| # malloc-related functions often return memory that is mostly zeroed. | |
| # If you have the time and cycles, use valgrind to do an even better job. | |
| : ${MALLOC_PERTURB_=87} | |
| export MALLOC_PERTURB_ | |
| # ----------------------------------------------------------------------------- | |
| # The interpreter for Bourne-shell scripts. | |
| # No special standards compatibility requirements. | |
| # Some environments, such as Android, don't have /bin/sh. | |
| if test -f /bin/sh$EXEEXT; then | |
| BOURNE_SHELL=/bin/sh | |
| else | |
| BOURNE_SHELL=sh | |
| fi | |
| # ============================================================================= | |
| # Convenience functions for the tests | |
| # ----------------------------------------------------------------------------- | |
| # Return value checking | |
| # This is used to simplify checking of the return value | |
| # which is useful when ensuring a command fails as desired. | |
| # I.e., just doing `command ... &&fail=1` will not catch | |
| # a segfault in command for example. With this helper you | |
| # instead check an explicit exit code like | |
| # returns_ 1 command ... || fail=1 | |
| returns_ () { | |
| # Disable tracing so it doesn't interfere with stderr of the wrapped command | |
| { local is_tracing=`{ :; } 2>&1`; } 2>/dev/null | |
| { set +x; } 2>/dev/null | |
| local exp_exit="$1" | |
| shift | |
| "$@" | |
| test $? -eq $exp_exit && ret_=0 || ret_=1 | |
| # Restore tracing if it was enabled. | |
| if test -n "$is_tracing"; then | |
| set -x | |
| fi | |
| { return $ret_; } 2>/dev/null | |
| } | |
| # ----------------------------------------------------------------------------- | |
| # Text file comparison | |
| # Emit a header similar to that from diff -u; Print the simulated "diff" | |
| # command so that the order of arguments is clear. Don't bother with @@ lines. | |
| emit_diff_u_header_ () | |
| { | |
| printf '%s\n' "diff -u $*" \ | |
| "--- $1 1970-01-01" \ | |
| "+++ $2 1970-01-01" | |
| } | |
| # Arrange not to let diff or cmp operate on /dev/null, | |
| # since on some old systems, that doesn't work. | |
| # When there are not two arguments, or no argument is /dev/null, return 2. | |
| # When one argument is /dev/null and the other is not empty, | |
| # cat the nonempty file to stderr and return 1. | |
| # Otherwise, return 0. | |
| compare_dev_null_ () | |
| { | |
| test $# = 2 || return 2 | |
| if test "x$1" = x/dev/null; then | |
| test -s "$2" || return 0 | |
| emit_diff_u_header_ "$@"; sed 's/^/+/' "$2" | |
| return 1 | |
| fi | |
| if test "x$2" = x/dev/null; then | |
| test -s "$1" || return 0 | |
| emit_diff_u_header_ "$@"; sed 's/^/-/' "$1" | |
| return 1 | |
| fi | |
| return 2 | |
| } | |
| for diff_opt_ in -u -U3 -c '' no; do | |
| test "$diff_opt_" != no && | |
| diff_out_=`exec 2>/dev/null | |
| LC_ALL=C diff $diff_opt_ "$0" "$0" < /dev/null` && | |
| break | |
| done | |
| if test "$diff_opt_" != no; then | |
| if test -z "$diff_out_"; then | |
| # diff on msys2 does not support the '-' argument for denoting stdin. | |
| case `(uname -o) 2>/dev/null` in | |
| Msys) | |
| compare_ () | |
| { | |
| if test " $1" = " -"; then | |
| cat > '(stdin)' | |
| LC_ALL=C diff $diff_opt_ '(stdin)' "$2" | |
| elif test " $2" = " -"; then | |
| cat > '(stdin)' | |
| LC_ALL=C diff $diff_opt_ "$1" '(stdin)' | |
| else | |
| LC_ALL=C diff $diff_opt_ "$@" | |
| fi | |
| } | |
| ;; | |
| *) | |
| compare_ () | |
| { | |
| LC_ALL=C diff $diff_opt_ "$@" | |
| } | |
| esac | |
| else | |
| compare_ () | |
| { | |
| # If no differences were found, AIX and HP-UX 'diff' produce output | |
| # like "No differences encountered". Hide this output. | |
| LC_ALL=C diff $diff_opt_ "$@" > diff.out | |
| diff_status_=$? | |
| test $diff_status_ -eq 0 || cat diff.out || diff_status_=2 | |
| rm -f diff.out || diff_status_=2 | |
| return $diff_status_ | |
| } | |
| fi | |
| elif cmp -s /dev/null /dev/null 2>/dev/null; then | |
| compare_ () { cmp -s "$@"; } | |
| else | |
| compare_ () { cmp "$@"; } | |
| fi | |
| # Usage: compare EXPECTED ACTUAL | |
| # | |
| # Given compare_dev_null_'s preprocessing, defer to compare_ if 2 or more. | |
| # Otherwise, propagate $? to caller: any diffs have already been printed. | |
| compare () | |
| { | |
| # This looks like it can be factored to use a simple "case $?" | |
| # after unchecked compare_dev_null_ invocation, but that would | |
| # fail in a "set -e" environment. | |
| if compare_dev_null_ "$@"; then | |
| return 0 | |
| else | |
| case $? in | |
| 1) return 1;; | |
| *) compare_ "$@";; | |
| esac | |
| fi | |
| } | |
| # ----------------------------------------------------------------------------- | |
| # If you want to override the testdir_prefix_ function, | |
| # or to add more utility functions, use this file. | |
| test -f "$srcdir/init.cfg" \ | |
| && . "$srcdir/init.cfg" | |
| # ============================================================================= | |
| # Set up the environment for the test to run in. | |
| setup_ "$@" | |
| # This trap is here, rather than in the setup_ function, because some | |
| # shells run the exit trap at shell function exit, rather than script exit. | |
| trap remove_tmp_ EXIT | |