Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 8 additions & 7 deletions lib/bats/helper-function
Original file line number Diff line number Diff line change
Expand Up @@ -52,14 +52,15 @@ restore_bats_shell_options() {
local result="${1:-0}"
local target_stack_item_pattern=" ${FUNCNAME[1]} ${BASH_SOURCE[1]}$"

# After removing our caller from BATS_CURRENT_STACK_TRACE and restoring the
# Bats shell options, the `return` call at the end of the function will fire
# `bats_debug_trap`, which sets BATS_CURRENT_STACK_TRACE to
# BATS_PREVIOUS_STACK_TRACE.
#
# If `result` is nonzero, `bats_error_trap` will fire and set
# BATS_ERROR_STACK_TRACE to BATS_PREVIOUS_STACK_TRACE and fail the test.
if [[ "${BATS_CURRENT_STACK_TRACE[0]}" =~ $target_stack_item_pattern ]]; then
# After removing our caller from BATS_CURRENT_STACK_TRACE and restoring the
# Bats shell options, the `return` call at the end of the function will fire
# `bats_debug_trap`, which sets BATS_CURRENT_STACK_TRACE to
# BATS_PREVIOUS_STACK_TRACE.
#
# Then, if `result` is nonzero, `return` will fire `bats_error_trap`, which
# sets BATS_ERROR_STACK_TRACE to BATS_PREVIOUS_STACK_TRACE, and the error
# response will fail the test.
unset 'BATS_CURRENT_STACK_TRACE[0]'
set -eET
fi
Expand Down
148 changes: 98 additions & 50 deletions lib/bats/helpers
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,8 @@
# This is good practice even if you call `remove_bats_test_dirs` in your
# `environment.bash` file.

. "${BASH_SOURCE%/*}/helper-function"

# A subdirectory of BATS_TMPDIR that contains a space.
#
# Using this path instead of BATS_TMPDIR directly helps ensure that shell
Expand All @@ -61,8 +63,9 @@ BATS_TEST_BINDIR="$BATS_TEST_ROOTDIR/bin"
# Arguments:
# $1: Path to the project's top-level test directory
set_bats_test_suite_name() {
local test_rootdir="$(cd "$1" && echo "$PWD")"
local relative_filename="${BATS_TEST_FILENAME#$test_rootdir/}"
cd "$1"
local relative_filename="${BATS_TEST_FILENAME#$PWD/}"
cd - &>/dev/null
readonly SUITE="${relative_filename%.bats}"
}

Expand All @@ -74,18 +77,9 @@ set_bats_test_suite_name() {
# Arguments:
# $@: Paths of subdirectories relative to BATS_TEST_ROOTDIR
create_bats_test_dirs() {
local dirs_to_create=()
local test_dir

for test_dir in "${@/#/$BATS_TEST_ROOTDIR/}"; do
if [[ ! -d "$test_dir" ]]; then
dirs_to_create+=("$test_dir")
fi
done

if [[ "${#dirs_to_create[@]}" -ne '0' ]]; then
mkdir -p "${dirs_to_create[@]}"
fi
set "$DISABLE_BATS_SHELL_OPTIONS"
__create_bats_test_dirs "$@"
restore_bats_shell_options "$?"
}

# Creates a test script relative to BATS_TEST_ROOTDIR
Expand All @@ -100,26 +94,9 @@ create_bats_test_dirs() {
# $1: Path of the script relative to BATS_TEST_ROOTDIR
# ...: Lines comprising the script
create_bats_test_script() {
local script="$1"
shift
local script_dir="${script%/*}"

if [[ -z "$script" ]]; then
echo "No test script specified" >&2
exit 1
elif [[ "$script_dir" == "$script" ]]; then
script_dir=''
fi

create_bats_test_dirs "$script_dir"
script="$BATS_TEST_ROOTDIR/$script"
rm -f "$script"

if [[ "${1:0:2}" != '#!' ]]; then
echo "#! /usr/bin/env bash" >"$script"
fi
printf '%s\n' "$@" >>"$script"
chmod 700 "$script"
set "$DISABLE_BATS_SHELL_OPTIONS"
__create_bats_test_script "$@"
restore_bats_shell_options "$?"
}

# Recursively removes `BATS_TEST_ROOTDIR` and its subdirectories
Expand Down Expand Up @@ -183,18 +160,15 @@ skip_if_cannot_trigger_file_permission_failure() {
# Arguments:
# ...: System programs that must be present for the test case to proceed
skip_if_system_missing() {
local missing=()
local program
local __missing=()

for program in "$@"; do
if ! command -v "$program" >/dev/null; then
missing+=("$program")
fi
done
set "$DISABLE_BATS_SHELL_OPTIONS"
__search_for_missing_programs "$@"
restore_bats_shell_options "$?"

if [[ "${#missing[@]}" -ne '0' ]]; then
printf -v missing '%s, ' "${missing[@]}"
skip "${missing%, } not installed on the system"
if [[ "${#__missing[@]}" -ne '0' ]]; then
printf -v __missing '%s, ' "${__missing[@]}"
skip "${__missing%, } not installed on the system"
fi
}

Expand Down Expand Up @@ -311,12 +285,9 @@ test_filter() {
# compare the exact lines of `output` using `assert_lines_equal` and other
# `lines`-based assertions.
split_bats_output_into_lines() {
local line
lines=()

while IFS= read -r line; do
lines+=("${line%$'\r'}")
done <<<"$output"
set "$DISABLE_BATS_SHELL_OPTIONS"
__split_bats_output_into_lines
restore_bats_shell_options "$?"
}

# Creates a stub program in PATH for testing purposes
Expand All @@ -335,3 +306,80 @@ stub_program_in_path() {
fi
create_bats_test_script "${BATS_TEST_BINDIR#$BATS_TEST_ROOTDIR/}/$1" "${@:2}"
}

# --------------------------------
# IMPLEMENTATION - HERE BE DRAGONS
#
# None of the functions below this line are part of the public interface.
# --------------------------------

# Implementation for `create_bats_test_dirs`
#
# Arguments:
# $@: Paths of subdirectories relative to BATS_TEST_ROOTDIR
__create_bats_test_dirs() {
local dirs_to_create=()
local test_dir

for test_dir in "${@/#/$BATS_TEST_ROOTDIR/}"; do
if [[ ! -d "$test_dir" ]]; then
dirs_to_create+=("$test_dir")
fi
done

if [[ "${#dirs_to_create[@]}" -ne '0' ]]; then
mkdir -p "${dirs_to_create[@]}"
fi
}

# Implementation for `create_bats_test_script`
#
# Arguments:
# $1: Path of the script relative to BATS_TEST_ROOTDIR
# ...: Lines comprising the script
__create_bats_test_script() {
local script="$1"
shift
local script_dir="${script%/*}"

if [[ -z "$script" ]]; then
echo "No test script specified" >&2
exit 1
elif [[ "$script_dir" == "$script" ]]; then
script_dir=''
fi

create_bats_test_dirs "$script_dir"
script="$BATS_TEST_ROOTDIR/$script"
rm -f "$script"

if [[ "${1:0:2}" != '#!' ]]; then
echo "#! /usr/bin/env bash" >"$script"
fi
printf '%s\n' "$@" >>"$script"
chmod 700 "$script"
}

# Enumerates programs not installed on the system for `skip_if_system_missing`
#
# Arguments:
# ...: System programs that must be present for the test case to proceed
__search_for_missing_programs() {
local program

for program in "$@"; do
if ! command -v "$program" >/dev/null; then
__missing+=("$program")
fi
done
}

# Implementation for `split_bats_output_into_lines`
__split_bats_output_into_lines() {
local line
lines=()

while IFS= read -r line; do
lines+=("${line%$'\r'}")
done <<<"$output"
}
33 changes: 24 additions & 9 deletions lib/testing/environment
Original file line number Diff line number Diff line change
Expand Up @@ -106,15 +106,7 @@ test-go() {
# ...: Names of "child" command scripts
@go.create_parent_and_subcommands() {
set "$DISABLE_BATS_SHELL_OPTIONS"
local parent="$1"
shift
local subcommand

@go.create_test_command_script "$parent"

for subcommand in "$@"; do
@go.create_test_command_script "$parent.d/$subcommand"
done
__@go.create_parent_and_subcommands "$@"
restore_bats_shell_options "$?"
}

Expand All @@ -132,3 +124,26 @@ test-go() {
@go.split $'\n' "$(@go.compgen "${@:2}")" "$1"
restore_bats_shell_options "$?"
}

# --------------------------------
# IMPLEMENTATION - HERE BE DRAGONS
#
# None of the functions below this line are part of the public interface.
# --------------------------------

# Implementation for `@go.create_parent_and_subcommands`
#
# Arguments:
# parent_name: Name of the "parent" command script
# ...: Names of "child" command scripts
__@go.create_parent_and_subcommands() {
local parent="$1"
shift
local subcommand

@go.create_test_command_script "$parent"

for subcommand in "$@"; do
@go.create_test_command_script "$parent.d/$subcommand"
done
}
6 changes: 6 additions & 0 deletions lib/testing/stubbing
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@
# You must import `_GO_CORE_DIR/lib/testing/environment` before importing this
# script, and make sure to call `@go.remove_test_go_rootdir` from `teardown`.

. "$_GO_CORE_DIR/lib/bats/helper-function"

export _GO_INJECT_SEARCH_PATH="$TEST_GO_ROOTDIR/test-bin"
export _GO_INJECT_MODULE_PATH="$TEST_GO_ROOTDIR/test-lib"

Expand All @@ -20,8 +22,10 @@ export _GO_INJECT_MODULE_PATH="$TEST_GO_ROOTDIR/test-lib"
# module_name: Name of the command script to stub
# ...: Lines comprising the stubbed command script implementation
@go.create_command_script_test_stub() {
set "$DISABLE_BATS_SHELL_OPTIONS"
local script_path="$_GO_INJECT_SEARCH_PATH/$1"
create_bats_test_script "${script_path#$BATS_TEST_ROOTDIR/}" "${@:2}"
restore_bats_shell_options "$?"
}

# Creates a stub module implementation in `_GO_INJECT_MODULE_PATH`
Expand All @@ -30,7 +34,9 @@ export _GO_INJECT_MODULE_PATH="$TEST_GO_ROOTDIR/test-lib"
# module_name: Name of the module to stub
# ...: Lines comprising the stubbed module implementation
@go.create_module_test_stub() {
set "$DISABLE_BATS_SHELL_OPTIONS"
local module_path="$_GO_INJECT_MODULE_PATH/$1"
create_bats_test_script "${module_path#$BATS_TEST_ROOTDIR/}" "${@:2}"
chmod 600 "$module_path"
restore_bats_shell_options "$?"
}
16 changes: 13 additions & 3 deletions tests/assertion-test-helpers.bats
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,13 @@ emit_debug_info() {
}

run_assertion_test() {
set "$DISABLE_BATS_SHELL_OPTIONS"
setup_assertion_test "$@"
restore_bats_shell_options
run "$BATS_TEST_ROOTDIR/$EXPECT_ASSERTION_TEST_SCRIPT"
}

setup_assertion_test() {
local expected_output=("${@:2}")
local expected_output_line

Expand All @@ -43,11 +50,15 @@ run_assertion_test() {
"@test \"$BATS_TEST_DESCRIPTION\" {" \
" $ASSERTION" \
'}'
run "$BATS_TEST_ROOTDIR/$EXPECT_ASSERTION_TEST_SCRIPT"
}

check_failure_output() {
set +eET
set "$DISABLE_BATS_SHELL_OPTIONS"
__check_failure_output "$@"
restore_bats_shell_options "$?"
}

__check_failure_output() {
local test_script="$BATS_TEST_ROOTDIR/$EXPECT_ASSERTION_TEST_SCRIPT"
local assertion_line="${ASSERTION%%$'\n'*}"
local expected_output
Expand All @@ -69,7 +80,6 @@ check_failure_output() {
result='1'
fi
unset 'BATS_CURRENT_STACK_TRACE[0]' 'BATS_PREVIOUS_STACK_TRACE[0]'
set -eET
return "$result"
}

Expand Down
Loading