Skip to content

Commit

Permalink
ensure that bash v3 tests run with bash v3
Browse files Browse the repository at this point in the history
this fixes our ability to catch the error from 3b85eb1
this is necessary as the movement from sourcing to commands causes `env` to be used, which will reset to the preferred bash rather than the active bash.

other changes:

- confirm: tests no longer hang indefinitely on macos sonoma
- read-key: fix timeouts for bash v3
- read-key: fix special character detection on bash v3
- is-number: it now works on decimal numbers, and supports bash v3
- is-integer: it now supports bash v3
- bash.bash: fix `get_read_decimal_timeout` always returning 1
- bash.bash: fix uppercase_first_letter and lowercase_string on bash v3
- stdinargs: fix empty timeouts causing error
  • Loading branch information
balupton committed Oct 25, 2023
1 parent 3b85eb1 commit 5dfccec
Show file tree
Hide file tree
Showing 9 changed files with 229 additions and 74 deletions.
67 changes: 65 additions & 2 deletions commands.beta/is-integer
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,76 @@

# https://stackoverflow.com/a/29234612/130638

# a much more complicated version of this is:
# if test -z "$1"; then
# return 1
# elif test "$1" = '0'; then
# return 0
# else
# # hide stdout and stderr
# (let "$1") &>/dev/null || return 1
# return 0
# fi

function is_integer_test() (
source "$DOROTHY/sources/bash.bash"
echo-segment --h1="TEST: $0"

eval-tester --name='zero' --status=0 \
-- is-integer 0

eval-tester --name='one' --status=0 \
-- is-integer 1

eval-tester --name='ten' --status=0 \
-- is-integer 10

eval-tester --name='decimal' --status=1 \
-- is-integer 0.1

eval-tester --name='triple decimal' --status=1 \
-- is-integer 1.1.1

eval-tester --name='negative' --status=0 \
-- is-integer -1

eval-tester --name='negative 10' --status=0 \
-- is-integer -10

eval-tester --name='negative decimal' --status=1 \
-- is-integer -1.1

eval-tester --name='negative triple decimal' --status=1 \
-- is-integer -1.1.1

eval-tester --name='empty' --status=1 \
-- is-integer ''

eval-tester --name='letter' --status=1 \
-- is-integer 'a'

eval-tester --name='combo' --status=1 \
-- is-integer '-0a'

echo-segment --g1="TEST: $0"
return 0
)
function is_integer() (
source "$DOROTHY/sources/bash.bash"

[[ $1 == ?(-)+([0-9]) ]]
# if [[ $1 == ?(-)+([0-9]) ]]; then # does not work in bash v3
if [[ $1 =~ ^[-]?[0-9]+$ ]]; then
return 0
else
return 1
fi
)

# fire if invoked standalone
if test "$0" = "${BASH_SOURCE[0]}"; then
is_integer "$@"
if test "$*" = '--test'; then
is_integer_test
else
is_integer "$@"
fi
fi
6 changes: 4 additions & 2 deletions commands/confirm
Original file line number Diff line number Diff line change
Expand Up @@ -259,9 +259,11 @@ function confirm_() (
print_string "$prompt " >"$tty_target"
# send an ansi query to fetch the cursor row and column, returns [^[[24;80R] where 24 is row, 80 is column
# use _ to discard, the first read var is garbage, the second read var is the column, the final read var is the column
# don't use a timeout, as we already in a TTY so can guarantee an answer, and the read will complete immediately upon a response thanks to [-d R] which completes reading when the R is read, which is the final character of the response query
# use a 2 second timeout, as otherwise [confirm --test] on macos sonoma will wait forever
# shorter timeouts aren't suitable as slower machines take a while for the response
# we are already in a TTY, so can usually guarantee an answer, and the read will complete immediately upon a response thanks to [-d R] which completes reading when the R is read, which is the final character of the response query
local _
IFS='[;' read -srd R -p $'\e[6n' _ _ CURSOR_COLUMN <"$tty_target" || :
IFS='[;' read -t 2 -srd R -p $'\e[6n' _ _ CURSOR_COLUMN <"$tty_target" || :

# output the body if it exists
if test -n "$body"; then
Expand Down
29 changes: 25 additions & 4 deletions commands/debug-bash
Original file line number Diff line number Diff line change
Expand Up @@ -15,20 +15,24 @@ function debug_bash() (
debug-bash [...options] -- <command> [...args]
OPTIONS:
--bash=<bash path>
If you want to invoke the command through a custom bash binary, then provide it here.
-v
Pass the -v flag to bash: Print shell input lines as they are read.
EOF
return 22 # EINVAL 22 Invalid argument
}

# process
local item cmd=() args=('-x')
local item option_bash='' bash_args=('-x') cmd=()
while test "$#" -ne 0; do
item="$1"
shift
case "$item" in
'--help' | '-h') help ;;
'-v') args+=('-v') ;;
'--bash='*) option_bash="${item#*--bash=}" ;;
'-v') bash_args+=('-v') ;;
'--')
cmd+=("$@")
shift "$#"
Expand All @@ -46,11 +50,28 @@ function debug_bash() (
help 'No <command> was provided.'
fi

# fallback
if test -z "$option_bash"; then
option_bash="$(type -P bash)"
fi

# =====================================
# Act

bash "${args[@]}" "$(type -P "${cmd[0]}")" "${cmd[@]:1}"
return
# invoke the command or function
local cmd_path
cmd_path="$(type -P "${cmd[0]}" 2>/dev/null || :)"
if test -n "$cmd_path" && [[ $cmd_path == "$DOROTHY"* ]]; then
# command
cmd[0]="$cmd_path"
"$option_bash" "${bash_args[@]}" "${cmd[@]}"
return
else
# function/builtin
set "${bash_args[@]}"
"${cmd[@]}"
return
fi
)

# fire if invoked standalone
Expand Down
10 changes: 5 additions & 5 deletions commands/dorothy
Original file line number Diff line number Diff line change
Expand Up @@ -1725,10 +1725,10 @@ function dorothy() (
source "$DOROTHY/sources/ripgrep.bash"

# able to test on bash v3?
local bash bashv3=''
local bash has_macos_bashv3='no'
bash="$(type -P bash)"
if is_mac && test "$bash" != '/bin/bash' && [[ "$(/bin/bash --version || :)" == 'GNU bash, version 3.'* ]]; then
bashv3='/bin/bash'
has_macos_bashv3=yes
fi

# prepre scan paths
Expand Down Expand Up @@ -1759,9 +1759,9 @@ function dorothy() (
fi

# run the bash v3 test
if test -n "$bashv3"; then
eval-helper --no-quiet --wrap -- "$bashv3" "$filepath" --test || {
failures+=("$bashv3 $filepath --test")
if test "$has_macos_bashv3" = 'yes'; then
eval-helper --no-quiet --wrap -- env EVAL_TESTER_BASH=/bin/bash PATH="/bin:$PATH" /bin/bash "$filepath" --test || {
failures+=("env EVAL_TESTER_BASH=/bin/bash PATH='/bin:$PATH' /bin/bash '$filepath' --test")
}
fi
done
Expand Down
32 changes: 24 additions & 8 deletions commands/eval-tester
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,8 @@ function eval_tester() (
--stderr=<expected stderr> (defaults to empty)
--ignore-stderr
--debug (implies --ignore-stderr)
--bash=<bash path>
Used to ensure that the command is invoked through a specific bash binary. Defaults to the env var EVAL_TESTER_BASH.
EOF
if test "$#" -ne 0; then
echo-error "$@"
Expand All @@ -29,13 +31,14 @@ function eval_tester() (
}

# process
local item cmd=() ignore_option=$'\e' option_name='' option_status='0' option_stdout='' option_stderr='' option_debug='no'
local item cmd=() ignore_option=$'\e' option_name='' option_status='0' option_stdout='' option_stderr='' option_debug='no' option_bash="${EVAL_TESTER_BASH-}"
while test "$#" -ne 0; do
item="$1"
shift
case "$item" in
'--help' | '-h') help ;;
'--name='*) option_name="${item#*--name=}" ;;
'--bash='*) option_bash="${item#*--bash=}" ;;
'--ignore-status') option_status="$ignore_option" ;;
'--ignore-stdout') option_stdout="$ignore_option" ;;
'--ignore-stderr') option_stderr="$ignore_option" ;;
Expand All @@ -55,13 +58,26 @@ function eval_tester() (
esac
done

# overrides
if test "$option_debug" = 'yes'; then
cmd=(
'debug-bash'
'--'
"${cmd[@]}"
)
# if invoking a dorothy command (not a function, nor things like cat), then support debug and custom bash
# otherwise, custom bash not necessary as already inherited
# and debug-bash not possible
local cmd_path
cmd_path="$(type -P "${cmd[0]}" 2>/dev/null || :)"
if test -n "$cmd_path" && [[ $cmd_path == "$DOROTHY"* ]]; then
cmd[0]="$cmd_path"
if test "$option_debug" = 'yes'; then
cmd=(
'debug-bash'
"--bash=$option_bash"
'--'
"${cmd[@]}"
)
elif test -n "$option_bash"; then
cmd=(
"$option_bash"
"${cmd[@]}"
)
fi
fi

# =====================================
Expand Down
58 changes: 54 additions & 4 deletions commands/is-number
Original file line number Diff line number Diff line change
@@ -1,14 +1,64 @@
#!/usr/bin/env bash

function is_number_test() (
source "$DOROTHY/sources/bash.bash"
echo-segment --h1="TEST: $0"

eval-tester --name='zero' --status=0 \
-- is-number 0

eval-tester --name='one' --status=0 \
-- is-number 1

eval-tester --name='ten' --status=0 \
-- is-number 10

eval-tester --name='decimal' --status=0 \
-- is-number 0.1

eval-tester --name='triple decimal' --status=1 \
-- is-number 1.1.1

eval-tester --name='negative' --status=0 \
-- is-number -1

eval-tester --name='negative 10' --status=0 \
-- is-number -10

eval-tester --name='negative decimal' --status=0 \
-- is-number -1.1

eval-tester --name='negative triple decimal' --status=1 \
-- is-number -1.1.1

eval-tester --name='empty' --status=1 \
-- is-number ''

eval-tester --name='letter' --status=1 \
-- is-number 'a'

eval-tester --name='combo' --status=1 \
-- is-number '-0a'

echo-segment --g1="TEST: $0"
return 0
)
function is_number() (
source "$DOROTHY/sources/bash.bash"

# hide stdout and stderr
# trunk-ignore(shellcheck/SC2219)
(test "$1" = '0' || let "$1") &>/dev/null
# if [[ $1 == ?(-)+([0-9])?([.]+([0-9])) ]]; then # does not work in bash v3
if [[ $1 =~ ^[-]?[0-9]+(\.[0-9]+)?$ ]]; then # does not work in bash v3
return 0
else
return 1
fi
)

# fire if invoked standalone
if test "$0" = "${BASH_SOURCE[0]}"; then
is_number "$@"
if test "$*" = '--test'; then
is_number_test
else
is_number "$@"
fi
fi
Loading

0 comments on commit 5dfccec

Please sign in to comment.