1
0
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:
Mike Bland 2017-09-30 15:46:12 -04:00 committed by GitHub
commit 8538868563
9 changed files with 156 additions and 87 deletions

View File

@ -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"

View File

@ -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

View File

@ -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
}

View File

@ -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() {

View File

@ -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

View File

@ -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" ]
}

View File

@ -0,0 +1,3 @@
@test "$SUITE: test with variable in name" {
true
}

View File

@ -0,0 +1,11 @@
@test 'single-quoted name' {
true
}
@test "double-quoted name" {
true
}
@test unquoted name {
true
}

View File

@ -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() {