mirror of
https://github.com/sstephenson/bats.git
synced 2025-03-03 15:29:52 +01:00
Merge pull request #8 from bats-core/mbland-optimized
Fix macOS/Bash 3.2 breakage; eliminate subshells from exec-test, preprocess
This commit is contained in:
commit
8538868563
63
libexec/bats
63
libexec/bats
|
@ -26,35 +26,58 @@ help() {
|
|||
echo
|
||||
}
|
||||
|
||||
BATS_READLINK=
|
||||
|
||||
resolve_link() {
|
||||
$(type -p greadlink readlink | head -1) "$1"
|
||||
if [[ -z "$BATS_READLINK" ]]; then
|
||||
if command -v 'greadlink' >/dev/null; then
|
||||
BATS_READLINK='greadlink'
|
||||
elif command -v 'readlink' >/dev/null; then
|
||||
BATS_READLINK='readlink'
|
||||
else
|
||||
BATS_READLINK='true'
|
||||
fi
|
||||
fi
|
||||
"$BATS_READLINK" "$1" || return 0
|
||||
}
|
||||
|
||||
abs_dirname() {
|
||||
local cwd="$(pwd)"
|
||||
local cwd="$PWD"
|
||||
local path="$1"
|
||||
|
||||
while [ -n "$path" ]; do
|
||||
cd "${path%/*}"
|
||||
local name="${path##*/}"
|
||||
path="$(resolve_link "$name" || true)"
|
||||
path="$(resolve_link "$name")"
|
||||
done
|
||||
|
||||
pwd
|
||||
printf -v "$2" -- '%s' "$PWD"
|
||||
cd "$cwd"
|
||||
}
|
||||
|
||||
expand_path() {
|
||||
{ cd "$(dirname "$1")" 2>/dev/null
|
||||
local dirname="$PWD"
|
||||
local path="${1%/}"
|
||||
local dirname="${path%/*}"
|
||||
|
||||
if [[ "$dirname" == "$path" ]]; then
|
||||
dirname="$PWD"
|
||||
elif cd "$dirname" 2>/dev/null; then
|
||||
dirname="$PWD"
|
||||
cd "$OLDPWD"
|
||||
echo "$dirname/$(basename "$1")"
|
||||
} || echo "$1"
|
||||
else
|
||||
printf '%s' "$path"
|
||||
return
|
||||
fi
|
||||
printf -v "$2" '%s/%s' "$dirname" "${path##*/}"
|
||||
}
|
||||
|
||||
BATS_LIBEXEC="$(abs_dirname "$0")"
|
||||
export BATS_PREFIX="$(abs_dirname "$BATS_LIBEXEC")"
|
||||
export BATS_CWD="$(abs_dirname .)"
|
||||
abs_dirname "$0" 'BATS_LIBEXEC'
|
||||
abs_dirname "$BATS_LIBEXEC" 'BATS_PREFIX'
|
||||
abs_dirname '.' 'BATS_CWD'
|
||||
|
||||
export BATS_PREFIX
|
||||
export BATS_CWD
|
||||
export BATS_TEST_PATTERN='^ *@test +(.+) +\{ *(.*)$'
|
||||
export PATH="$BATS_LIBEXEC:$PATH"
|
||||
|
||||
options=()
|
||||
|
@ -113,14 +136,16 @@ fi
|
|||
|
||||
filenames=()
|
||||
for filename in "${arguments[@]}"; do
|
||||
expand_path "$filename" 'filename'
|
||||
|
||||
if [ -d "$filename" ]; then
|
||||
shopt -s nullglob
|
||||
for suite_filename in "$(expand_path "$filename")"/*.bats; do
|
||||
for suite_filename in "$filename"/*.bats; do
|
||||
filenames["${#filenames[@]}"]="$suite_filename"
|
||||
done
|
||||
shopt -u nullglob
|
||||
else
|
||||
filenames["${#filenames[@]}"]="$(expand_path "$filename")"
|
||||
filenames["${#filenames[@]}"]="$filename"
|
||||
fi
|
||||
done
|
||||
|
||||
|
@ -130,13 +155,11 @@ else
|
|||
command="bats-exec-suite"
|
||||
fi
|
||||
|
||||
if [ -n "$pretty" ]; then
|
||||
set -o pipefail execfail
|
||||
if [ -z "$pretty" ]; then
|
||||
exec "$command" $count_flag "${filenames[@]}"
|
||||
else
|
||||
extended_syntax_flag="-x"
|
||||
formatter="bats-format-tap-stream"
|
||||
else
|
||||
extended_syntax_flag=""
|
||||
formatter="cat"
|
||||
exec "$command" $count_flag $extended_syntax_flag "${filenames[@]}" | "$formatter"
|
||||
fi
|
||||
|
||||
set -o pipefail execfail
|
||||
exec "$command" $count_flag $extended_syntax_flag "${filenames[@]}" | "$formatter"
|
||||
|
|
|
@ -17,7 +17,11 @@ trap "kill 0; exit 1" int
|
|||
|
||||
count=0
|
||||
for filename in "$@"; do
|
||||
let count+="$(bats-exec-test -c "$filename")"
|
||||
while IFS= read -r line; do
|
||||
if [[ "$line" =~ $BATS_TEST_PATTERN ]]; then
|
||||
let count+=1
|
||||
fi
|
||||
done <"$filename"
|
||||
done
|
||||
|
||||
if [ -n "$count_only_flag" ]; then
|
||||
|
|
|
@ -26,7 +26,7 @@ else
|
|||
shift
|
||||
fi
|
||||
|
||||
BATS_TEST_DIRNAME="$(dirname "$BATS_TEST_FILENAME")"
|
||||
BATS_TEST_DIRNAME="${BATS_TEST_FILENAME%/*}"
|
||||
BATS_TEST_NAMES=()
|
||||
|
||||
load() {
|
||||
|
@ -39,10 +39,10 @@ load() {
|
|||
filename="$BATS_TEST_DIRNAME/${name}.bash"
|
||||
fi
|
||||
|
||||
[ -f "$filename" ] || {
|
||||
if [[ ! -f "$filename" ]]; then
|
||||
echo "bats: $filename does not exist" >&2
|
||||
exit 1
|
||||
}
|
||||
fi
|
||||
|
||||
source "${filename}"
|
||||
}
|
||||
|
@ -101,31 +101,33 @@ bats_capture_stack_trace() {
|
|||
local teardown_pattern=" teardown $BATS_TEST_SOURCE"
|
||||
|
||||
local frame
|
||||
local index=1
|
||||
local i
|
||||
|
||||
while frame="$(caller "$index")"; do
|
||||
for ((i=2; i != ${#FUNCNAME[@]}; ++i)); do
|
||||
frame="${BASH_LINENO[$((i-1))]} ${FUNCNAME[$i]} ${BASH_SOURCE[$i]}"
|
||||
BATS_CURRENT_STACK_TRACE["${#BATS_CURRENT_STACK_TRACE[@]}"]="$frame"
|
||||
if [[ "$frame" = *"$test_pattern" || \
|
||||
"$frame" = *"$setup_pattern" || \
|
||||
"$frame" = *"$teardown_pattern" ]]; then
|
||||
break
|
||||
else
|
||||
let index+=1
|
||||
fi
|
||||
done
|
||||
|
||||
BATS_SOURCE="$(bats_frame_filename "${BATS_CURRENT_STACK_TRACE[0]}")"
|
||||
BATS_LINENO="$(bats_frame_lineno "${BATS_CURRENT_STACK_TRACE[0]}")"
|
||||
bats_frame_filename "${BATS_CURRENT_STACK_TRACE[0]}" 'BATS_SOURCE'
|
||||
bats_frame_lineno "${BATS_CURRENT_STACK_TRACE[0]}" 'BATS_LINENO'
|
||||
}
|
||||
|
||||
bats_print_stack_trace() {
|
||||
local frame
|
||||
local index=1
|
||||
local count="${#@}"
|
||||
local filename
|
||||
local lineno
|
||||
|
||||
for frame in "$@"; do
|
||||
local filename="$(bats_trim_filename "$(bats_frame_filename "$frame")")"
|
||||
local lineno="$(bats_frame_lineno "$frame")"
|
||||
bats_frame_filename "$frame" 'filename'
|
||||
bats_trim_filename "$filename" 'filename'
|
||||
bats_frame_lineno "$frame" 'lineno'
|
||||
|
||||
if [ $index -eq 1 ]; then
|
||||
echo -n "# ("
|
||||
|
@ -133,7 +135,8 @@ bats_print_stack_trace() {
|
|||
echo -n "# "
|
||||
fi
|
||||
|
||||
local fn="$(bats_frame_function "$frame")"
|
||||
local fn
|
||||
bats_frame_function "$frame" 'fn'
|
||||
if [ "$fn" != "$BATS_TEST_NAME" ]; then
|
||||
echo -n "from function \`$fn' "
|
||||
fi
|
||||
|
@ -151,12 +154,16 @@ bats_print_stack_trace() {
|
|||
bats_print_failed_command() {
|
||||
local frame="$1"
|
||||
local status="$2"
|
||||
local filename="$(bats_frame_filename "$frame")"
|
||||
local lineno="$(bats_frame_lineno "$frame")"
|
||||
local filename
|
||||
local lineno
|
||||
local failed_line
|
||||
local failed_command
|
||||
|
||||
local failed_line="$(bats_extract_line "$filename" "$lineno")"
|
||||
local failed_command="$(bats_strip_string "$failed_line")"
|
||||
echo -n "# \`${failed_command}' "
|
||||
bats_frame_filename "$frame" 'filename'
|
||||
bats_frame_lineno "$frame" 'lineno'
|
||||
bats_extract_line "$filename" "$lineno" 'failed_line'
|
||||
bats_strip_string "$failed_line" 'failed_command'
|
||||
printf '%s' "# \`${failed_command}' "
|
||||
|
||||
if [ $status -eq 1 ]; then
|
||||
echo "failed"
|
||||
|
@ -166,49 +173,46 @@ bats_print_failed_command() {
|
|||
}
|
||||
|
||||
bats_frame_lineno() {
|
||||
local frame="$1"
|
||||
local lineno="${frame%% *}"
|
||||
echo "$lineno"
|
||||
printf -v "$2" '%s' "${1%% *}"
|
||||
}
|
||||
|
||||
bats_frame_function() {
|
||||
local frame="$1"
|
||||
local rest="${frame#* }"
|
||||
local fn="${rest%% *}"
|
||||
echo "$fn"
|
||||
local __bff_function="${1#* }"
|
||||
printf -v "$2" '%s' "${__bff_function%% *}"
|
||||
}
|
||||
|
||||
bats_frame_filename() {
|
||||
local frame="$1"
|
||||
local rest="${frame#* }"
|
||||
local filename="${rest#* }"
|
||||
local __bff_filename="${1#* }"
|
||||
__bff_filename="${__bff_filename#* }"
|
||||
|
||||
if [ "$filename" = "$BATS_TEST_SOURCE" ]; then
|
||||
echo "$BATS_TEST_FILENAME"
|
||||
else
|
||||
echo "$filename"
|
||||
if [ "$__bff_filename" = "$BATS_TEST_SOURCE" ]; then
|
||||
__bff_filename="$BATS_TEST_FILENAME"
|
||||
fi
|
||||
printf -v "$2" '%s' "$__bff_filename"
|
||||
}
|
||||
|
||||
bats_extract_line() {
|
||||
local filename="$1"
|
||||
local lineno="$2"
|
||||
sed -n "${lineno}p" "$filename"
|
||||
local __bats_extract_line_line
|
||||
local __bats_extract_line_index='0'
|
||||
|
||||
while IFS= read -r __bats_extract_line_line; do
|
||||
if [[ "$((++__bats_extract_line_index))" -eq "$2" ]]; then
|
||||
printf -v "$3" '%s' "${__bats_extract_line_line%$'\r'}"
|
||||
break
|
||||
fi
|
||||
done <"$1"
|
||||
}
|
||||
|
||||
bats_strip_string() {
|
||||
local string="$1"
|
||||
printf "%s" "$string" | sed -e "s/^[ "$'\t'"]*//" -e "s/[ "$'\t'"]*$//"
|
||||
[[ "$1" =~ ^[[:space:]]*(.*)[[:space:]]*$ ]]
|
||||
printf -v "$2" '%s' "${BASH_REMATCH[1]}"
|
||||
}
|
||||
|
||||
bats_trim_filename() {
|
||||
local filename="$1"
|
||||
local length="${#BATS_CWD}"
|
||||
|
||||
if [ "${filename:0:length+1}" = "${BATS_CWD}/" ]; then
|
||||
echo "${filename:length+1}"
|
||||
if [[ "$1" =~ ^${BATS_CWD}/ ]]; then
|
||||
printf -v "$2" '%s' "${1#$BATS_CWD/}"
|
||||
else
|
||||
echo "$filename"
|
||||
printf -v "$2" '%s' "$1"
|
||||
fi
|
||||
}
|
||||
|
||||
|
@ -289,7 +293,7 @@ bats_perform_tests() {
|
|||
|
||||
bats_perform_test() {
|
||||
BATS_TEST_NAME="$1"
|
||||
if [ "$(type -t "$BATS_TEST_NAME" || true)" = "function" ]; then
|
||||
if declare -F "$BATS_TEST_NAME" >/dev/null; then
|
||||
BATS_TEST_NUMBER="$2"
|
||||
if [ -z "$BATS_TEST_NUMBER" ]; then
|
||||
echo "1..1"
|
||||
|
@ -322,7 +326,7 @@ BATS_OUT="${BATS_TMPNAME}.out"
|
|||
|
||||
bats_preprocess_source() {
|
||||
BATS_TEST_SOURCE="${BATS_TMPNAME}.src"
|
||||
{ tr -d '\r' < "$BATS_TEST_FILENAME"; echo; } | bats-preprocess > "$BATS_TEST_SOURCE"
|
||||
. bats-preprocess <<< "$(< "$BATS_TEST_FILENAME")"$'\n' > "$BATS_TEST_SOURCE"
|
||||
trap "bats_cleanup_preprocessed_source" err exit
|
||||
trap "bats_cleanup_preprocessed_source; exit 1" int
|
||||
}
|
||||
|
|
|
@ -65,9 +65,15 @@ log() {
|
|||
}
|
||||
|
||||
summary() {
|
||||
printf "\n%d test%s" "$count" "$(plural "$count")"
|
||||
printf "\n%d test" "$count"
|
||||
if [[ "$count" -ne '1' ]]; then
|
||||
printf 's'
|
||||
fi
|
||||
|
||||
printf ", %d failure%s" "$failures" "$(plural "$failures")"
|
||||
printf ", %d failure" "$failures"
|
||||
if [[ "$failures" -ne '1' ]]; then
|
||||
printf 's'
|
||||
fi
|
||||
|
||||
if [ "$skipped" -gt 0 ]; then
|
||||
printf ", %d skipped" "$skipped"
|
||||
|
@ -79,7 +85,9 @@ summary() {
|
|||
printf_with_truncation() {
|
||||
local width="$1"
|
||||
shift
|
||||
local string="$(printf "$@")"
|
||||
local string
|
||||
|
||||
printf -v 'string' -- "$@"
|
||||
|
||||
if [ "${#string}" -gt "$width" ]; then
|
||||
printf "%s..." "${string:0:$(( $width - 4 ))}"
|
||||
|
@ -105,18 +113,18 @@ advance() {
|
|||
|
||||
set_color() {
|
||||
local color="$1"
|
||||
local weight="$2"
|
||||
printf "\x1B[%d;%dm" $(( 30 + $color )) "$( [ "$weight" = "bold" ] && echo 1 || echo 22 )"
|
||||
local weight='22'
|
||||
|
||||
if [[ "$2" == 'bold' ]]; then
|
||||
weight='1'
|
||||
fi
|
||||
printf "\x1B[%d;%dm" $(( 30 + $color )) "$weight"
|
||||
}
|
||||
|
||||
clear_color() {
|
||||
printf "\x1B[0m"
|
||||
}
|
||||
|
||||
plural() {
|
||||
[ "$1" -eq 1 ] || echo "s"
|
||||
}
|
||||
|
||||
_buffer=""
|
||||
|
||||
buffer() {
|
||||
|
|
|
@ -4,6 +4,7 @@ set -e
|
|||
encode_name() {
|
||||
local name="$1"
|
||||
local result="test_"
|
||||
local hex_code
|
||||
|
||||
if [[ ! "$name" =~ [^[:alnum:]\ _-] ]]; then
|
||||
name="${name//_/-5f}"
|
||||
|
@ -21,27 +22,28 @@ encode_name() {
|
|||
elif [[ "$char" =~ [[:alnum:]] ]]; then
|
||||
result+="$char"
|
||||
else
|
||||
result+="$(printf -- "-%02x" \'"$char")"
|
||||
printf -v 'hex_code' -- "-%02x" \'"$char"
|
||||
result+="$hex_code"
|
||||
fi
|
||||
done
|
||||
fi
|
||||
|
||||
echo "$result"
|
||||
printf -v "$2" '%s' "$result"
|
||||
}
|
||||
|
||||
tests=()
|
||||
index=0
|
||||
pattern='^ *@test *([^ ].*) *\{ *(.*)$'
|
||||
|
||||
while IFS= read -r line; do
|
||||
line="${line//$'\r'}"
|
||||
let index+=1
|
||||
if [[ "$line" =~ $pattern ]]; then
|
||||
quoted_name="${BASH_REMATCH[1]}"
|
||||
if [[ "$line" =~ $BATS_TEST_PATTERN ]]; then
|
||||
name="${BASH_REMATCH[1]#[\'\"]}"
|
||||
name="${name%[\'\"]}"
|
||||
body="${BASH_REMATCH[2]}"
|
||||
name="$(eval echo "$quoted_name")"
|
||||
encoded_name="$(encode_name "$name")"
|
||||
encode_name "$name" 'encoded_name'
|
||||
tests["${#tests[@]}"]="$encoded_name"
|
||||
echo "${encoded_name}() { bats_test_begin ${quoted_name} ${index}; ${body}"
|
||||
echo "${encoded_name}() { bats_test_begin \"${name}\" ${index}; ${body}"
|
||||
else
|
||||
printf "%s\n" "$line"
|
||||
fi
|
||||
|
|
|
@ -41,25 +41,25 @@ fixtures bats
|
|||
}
|
||||
|
||||
@test "summary passing tests" {
|
||||
run filter_control_sequences bats -p $FIXTURE_ROOT/passing.bats
|
||||
run filter_control_sequences bats -p "$FIXTURE_ROOT/passing.bats"
|
||||
[ $status -eq 0 ]
|
||||
[ "${lines[1]}" = "1 test, 0 failures" ]
|
||||
}
|
||||
|
||||
@test "summary passing and skipping tests" {
|
||||
run filter_control_sequences bats -p $FIXTURE_ROOT/passing_and_skipping.bats
|
||||
run filter_control_sequences bats -p "$FIXTURE_ROOT/passing_and_skipping.bats"
|
||||
[ $status -eq 0 ]
|
||||
[ "${lines[2]}" = "2 tests, 0 failures, 1 skipped" ]
|
||||
}
|
||||
|
||||
@test "summary passing and failing tests" {
|
||||
run filter_control_sequences bats -p $FIXTURE_ROOT/failing_and_passing.bats
|
||||
run filter_control_sequences bats -p "$FIXTURE_ROOT/failing_and_passing.bats"
|
||||
[ $status -eq 0 ]
|
||||
[ "${lines[4]}" = "2 tests, 1 failure" ]
|
||||
}
|
||||
|
||||
@test "summary passing, failing and skipping tests" {
|
||||
run filter_control_sequences bats -p $FIXTURE_ROOT/passing_failing_and_skipping.bats
|
||||
run filter_control_sequences bats -p "$FIXTURE_ROOT/passing_failing_and_skipping.bats"
|
||||
[ $status -eq 0 ]
|
||||
[ "${lines[5]}" = "3 tests, 1 failure, 1 skipped" ]
|
||||
}
|
||||
|
@ -268,3 +268,17 @@ fixtures bats
|
|||
[ $status -eq 0 ]
|
||||
[ "${lines[1]}" = "ok 1 loop_func" ]
|
||||
}
|
||||
|
||||
@test "expand variables in test name" {
|
||||
SUITE='test/suite' run bats "$FIXTURE_ROOT/expand_var_in_test_name.bats"
|
||||
[ $status -eq 0 ]
|
||||
[ "${lines[1]}" = "ok 1 test/suite: test with variable in name" ]
|
||||
}
|
||||
|
||||
@test "handle quoted and unquoted test names" {
|
||||
run bats "$FIXTURE_ROOT/quoted_and_unquoted_test_names.bats"
|
||||
[ $status -eq 0 ]
|
||||
[ "${lines[1]}" = "ok 1 single-quoted name" ]
|
||||
[ "${lines[2]}" = "ok 2 double-quoted name" ]
|
||||
[ "${lines[3]}" = "ok 3 unquoted name" ]
|
||||
}
|
||||
|
|
3
test/fixtures/bats/expand_var_in_test_name.bats
vendored
Normal file
3
test/fixtures/bats/expand_var_in_test_name.bats
vendored
Normal file
|
@ -0,0 +1,3 @@
|
|||
@test "$SUITE: test with variable in name" {
|
||||
true
|
||||
}
|
11
test/fixtures/bats/quoted_and_unquoted_test_names.bats
vendored
Normal file
11
test/fixtures/bats/quoted_and_unquoted_test_names.bats
vendored
Normal file
|
@ -0,0 +1,11 @@
|
|||
@test 'single-quoted name' {
|
||||
true
|
||||
}
|
||||
|
||||
@test "double-quoted name" {
|
||||
true
|
||||
}
|
||||
|
||||
@test unquoted name {
|
||||
true
|
||||
}
|
|
@ -1,6 +1,6 @@
|
|||
fixtures() {
|
||||
FIXTURE_ROOT="$BATS_TEST_DIRNAME/fixtures/$1"
|
||||
RELATIVE_FIXTURE_ROOT="$(bats_trim_filename "$FIXTURE_ROOT")"
|
||||
bats_trim_filename "$FIXTURE_ROOT" 'RELATIVE_FIXTURE_ROOT'
|
||||
}
|
||||
|
||||
setup() {
|
||||
|
|
Loading…
Reference in New Issue
Block a user