Vendoring bats libraries.
Signed-off-by: Chad Metcalf <chad@docker.com>
This commit is contained in:
committed by
Chad Metcalf
parent
5185cedf4e
commit
6565a1f745
42
lib/bats-assert/src/assert.bash
Normal file
42
lib/bats-assert/src/assert.bash
Normal file
@@ -0,0 +1,42 @@
|
||||
# assert
|
||||
# ======
|
||||
#
|
||||
# Summary: Fail if the given expression evaluates to false.
|
||||
#
|
||||
# Usage: assert <expression>
|
||||
|
||||
# Options:
|
||||
# <expression> The expression to evaluate for truthiness.
|
||||
# *__Note:__ The expression must be a simple command.
|
||||
# [Compound commands](https://www.gnu.org/software/bash/manual/bash.html#Compound-Commands),
|
||||
# such as `[[`, can be used only when executed with `bash -c`.*
|
||||
#
|
||||
# IO:
|
||||
# STDERR - the failed expression, on failure
|
||||
# Globals:
|
||||
# none
|
||||
# Returns:
|
||||
# 0 - if expression evaluates to true
|
||||
# 1 - otherwise
|
||||
#
|
||||
# ```bash
|
||||
# @test 'assert()' {
|
||||
# touch '/var/log/test.log'
|
||||
# assert [ -e '/var/log/test.log' ]
|
||||
# }
|
||||
# ```
|
||||
#
|
||||
# On failure, the failed expression is displayed.
|
||||
#
|
||||
# ```
|
||||
# -- assertion failed --
|
||||
# expression : [ -e /var/log/test.log ]
|
||||
# --
|
||||
# ```
|
||||
assert() {
|
||||
if ! "$@"; then
|
||||
batslib_print_kv_single 10 'expression' "$*" \
|
||||
| batslib_decorate 'assertion failed' \
|
||||
| fail
|
||||
fi
|
||||
}
|
42
lib/bats-assert/src/assert_equal.bash
Normal file
42
lib/bats-assert/src/assert_equal.bash
Normal file
@@ -0,0 +1,42 @@
|
||||
# assert_equal
|
||||
# ============
|
||||
#
|
||||
# Summary: Fail if the actual and expected values are not equal.
|
||||
#
|
||||
# Usage: assert_equal <actual> <expected>
|
||||
#
|
||||
# Options:
|
||||
# <actual> The value being compared.
|
||||
# <expected> The value to compare against.
|
||||
#
|
||||
# ```bash
|
||||
# @test 'assert_equal()' {
|
||||
# assert_equal 'have' 'want'
|
||||
# }
|
||||
# ```
|
||||
#
|
||||
# IO:
|
||||
# STDERR - expected and actual values, on failure
|
||||
# Globals:
|
||||
# none
|
||||
# Returns:
|
||||
# 0 - if values equal
|
||||
# 1 - otherwise
|
||||
#
|
||||
# On failure, the expected and actual values are displayed.
|
||||
#
|
||||
# ```
|
||||
# -- values do not equal --
|
||||
# expected : want
|
||||
# actual : have
|
||||
# --
|
||||
# ```
|
||||
assert_equal() {
|
||||
if [[ $1 != "$2" ]]; then
|
||||
batslib_print_kv_single_or_multi 8 \
|
||||
'expected' "$2" \
|
||||
'actual' "$1" \
|
||||
| batslib_decorate 'values do not equal' \
|
||||
| fail
|
||||
fi
|
||||
}
|
78
lib/bats-assert/src/assert_failure.bash
Normal file
78
lib/bats-assert/src/assert_failure.bash
Normal file
@@ -0,0 +1,78 @@
|
||||
# assert_failure
|
||||
# ==============
|
||||
#
|
||||
# Summary: Fail if `$status` is 0; or is not equal to the optionally provided status.
|
||||
#
|
||||
# Usage: assert_failure [<expected_status>]
|
||||
#
|
||||
# Options:
|
||||
# <expected_status> The specific status code to check against.
|
||||
# If not provided, simply asserts status is != 0.
|
||||
#
|
||||
# IO:
|
||||
# STDERR - `$output`, on failure;
|
||||
# - also, `$status` and `expected_status`, if provided
|
||||
# Globals:
|
||||
# status
|
||||
# output
|
||||
# Returns:
|
||||
# 0 - if `$status' is 0,
|
||||
# or if expected_status is provided but does not equal `$status'
|
||||
# 1 - otherwise
|
||||
#
|
||||
# ```bash
|
||||
# @test 'assert_failure() status only' {
|
||||
# run echo 'Success!'
|
||||
# assert_failure
|
||||
# }
|
||||
# ```
|
||||
#
|
||||
# On failure, `$output` is displayed.
|
||||
#
|
||||
# ```
|
||||
# -- command succeeded, but it was expected to fail --
|
||||
# output : Success!
|
||||
# --
|
||||
# ```
|
||||
#
|
||||
# ## Expected status
|
||||
#
|
||||
# When `expected_status` is provided, fail if `$status` does not equal the `expected_status`.
|
||||
#
|
||||
# ```bash
|
||||
# @test 'assert_failure() with expected status' {
|
||||
# run bash -c "echo 'Error!'; exit 1"
|
||||
# assert_failure 2
|
||||
# }
|
||||
# ```
|
||||
#
|
||||
# On failure, both the expected and actual statuses, and `$output` are displayed.
|
||||
#
|
||||
# ```
|
||||
# -- command failed as expected, but status differs --
|
||||
# expected : 2
|
||||
# actual : 1
|
||||
# output : Error!
|
||||
# --
|
||||
# ```
|
||||
assert_failure() {
|
||||
: "${output?}"
|
||||
: "${status?}"
|
||||
|
||||
(( $# > 0 )) && local -r expected="$1"
|
||||
if (( status == 0 )); then
|
||||
batslib_print_kv_single_or_multi 6 'output' "$output" \
|
||||
| batslib_decorate 'command succeeded, but it was expected to fail' \
|
||||
| fail
|
||||
elif (( $# > 0 )) && (( status != expected )); then
|
||||
{ local -ir width=8
|
||||
batslib_print_kv_single "$width" \
|
||||
'expected' "$expected" \
|
||||
'actual' "$status"
|
||||
batslib_print_kv_single_or_multi "$width" \
|
||||
'output' "$output"
|
||||
} \
|
||||
| batslib_decorate 'command failed as expected, but status differs' \
|
||||
| fail
|
||||
fi
|
||||
}
|
248
lib/bats-assert/src/assert_line.bash
Normal file
248
lib/bats-assert/src/assert_line.bash
Normal file
@@ -0,0 +1,248 @@
|
||||
# assert_line
|
||||
# ===========
|
||||
#
|
||||
# Summary: Fail if the expected line is not found in the output (default) or at a specific line number.
|
||||
#
|
||||
# Usage: assert_line [-n index] [-p | -e] [--] <expected>
|
||||
#
|
||||
# Options:
|
||||
# -n, --index <idx> Match the <idx>th line
|
||||
# -p, --partial Match if `expected` is a substring of `$output` or line <idx>
|
||||
# -e, --regexp Treat `expected` as an extended regular expression
|
||||
# <expected> The expected line string, substring, or regular expression
|
||||
#
|
||||
# IO:
|
||||
# STDERR - details, on failure
|
||||
# error message, on error
|
||||
# Globals:
|
||||
# output
|
||||
# lines
|
||||
# Returns:
|
||||
# 0 - if matching line found
|
||||
# 1 - otherwise
|
||||
#
|
||||
# Similarly to `assert_output`, this function verifies that a command or function produces the expected output.
|
||||
# (It is the logical complement of `refute_line`.)
|
||||
# It checks that the expected line appears in the output (default) or at a specific line number.
|
||||
# Matching can be literal (default), partial or regular expression.
|
||||
#
|
||||
# *__Warning:__
|
||||
# Due to a [bug in Bats][bats-93], empty lines are discarded from `${lines[@]}`,
|
||||
# causing line indices to change and preventing testing for empty lines.*
|
||||
#
|
||||
# [bats-93]: https://github.com/sstephenson/bats/pull/93
|
||||
#
|
||||
# ## Looking for a line in the output
|
||||
#
|
||||
# By default, the entire output is searched for the expected line.
|
||||
# The assertion fails if the expected line is not found in `${lines[@]}`.
|
||||
#
|
||||
# ```bash
|
||||
# @test 'assert_line() looking for line' {
|
||||
# run echo $'have-0\nhave-1\nhave-2'
|
||||
# assert_line 'want'
|
||||
# }
|
||||
# ```
|
||||
#
|
||||
# On failure, the expected line and the output are displayed.
|
||||
#
|
||||
# ```
|
||||
# -- output does not contain line --
|
||||
# line : want
|
||||
# output (3 lines):
|
||||
# have-0
|
||||
# have-1
|
||||
# have-2
|
||||
# --
|
||||
# ```
|
||||
#
|
||||
# ## Matching a specific line
|
||||
#
|
||||
# When the `--index <idx>` option is used (`-n <idx>` for short), the expected line is matched only against the line identified by the given index.
|
||||
# The assertion fails if the expected line does not equal `${lines[<idx>]}`.
|
||||
#
|
||||
# ```bash
|
||||
# @test 'assert_line() specific line' {
|
||||
# run echo $'have-0\nhave-1\nhave-2'
|
||||
# assert_line --index 1 'want-1'
|
||||
# }
|
||||
# ```
|
||||
#
|
||||
# On failure, the index and the compared lines are displayed.
|
||||
#
|
||||
# ```
|
||||
# -- line differs --
|
||||
# index : 1
|
||||
# expected : want-1
|
||||
# actual : have-1
|
||||
# --
|
||||
# ```
|
||||
#
|
||||
# ## Partial matching
|
||||
#
|
||||
# Partial matching can be enabled with the `--partial` option (`-p` for short).
|
||||
# When used, a match fails if the expected *substring* is not found in the matched line.
|
||||
#
|
||||
# ```bash
|
||||
# @test 'assert_line() partial matching' {
|
||||
# run echo $'have 1\nhave 2\nhave 3'
|
||||
# assert_line --partial 'want'
|
||||
# }
|
||||
# ```
|
||||
#
|
||||
# On failure, the same details are displayed as for literal matching, except that the substring replaces the expected line.
|
||||
#
|
||||
# ```
|
||||
# -- no output line contains substring --
|
||||
# substring : want
|
||||
# output (3 lines):
|
||||
# have 1
|
||||
# have 2
|
||||
# have 3
|
||||
# --
|
||||
# ```
|
||||
#
|
||||
# ## Regular expression matching
|
||||
#
|
||||
# Regular expression matching can be enabled with the `--regexp` option (`-e` for short).
|
||||
# When used, a match fails if the *extended regular expression* does not match the line being tested.
|
||||
#
|
||||
# *__Note__:
|
||||
# As expected, the anchors `^` and `$` bind to the beginning and the end (respectively) of the matched line.*
|
||||
#
|
||||
# ```bash
|
||||
# @test 'assert_line() regular expression matching' {
|
||||
# run echo $'have-0\nhave-1\nhave-2'
|
||||
# assert_line --index 1 --regexp '^want-[0-9]$'
|
||||
# }
|
||||
# ```
|
||||
#
|
||||
# On failure, the same details are displayed as for literal matching, except that the regular expression replaces the expected line.
|
||||
#
|
||||
# ```
|
||||
# -- regular expression does not match line --
|
||||
# index : 1
|
||||
# regexp : ^want-[0-9]$
|
||||
# line : have-1
|
||||
# --
|
||||
# ```
|
||||
# FIXME(ztombol): Display `${lines[@]}' instead of `$output'!
|
||||
assert_line() {
|
||||
local -i is_match_line=0
|
||||
local -i is_mode_partial=0
|
||||
local -i is_mode_regexp=0
|
||||
: "${lines?}"
|
||||
|
||||
# Handle options.
|
||||
while (( $# > 0 )); do
|
||||
case "$1" in
|
||||
-n|--index)
|
||||
if (( $# < 2 )) || ! [[ $2 =~ ^([0-9]|[1-9][0-9]+)$ ]]; then
|
||||
echo "\`--index' requires an integer argument: \`$2'" \
|
||||
| batslib_decorate 'ERROR: assert_line' \
|
||||
| fail
|
||||
return $?
|
||||
fi
|
||||
is_match_line=1
|
||||
local -ri idx="$2"
|
||||
shift 2
|
||||
;;
|
||||
-p|--partial) is_mode_partial=1; shift ;;
|
||||
-e|--regexp) is_mode_regexp=1; shift ;;
|
||||
--) shift; break ;;
|
||||
*) break ;;
|
||||
esac
|
||||
done
|
||||
|
||||
if (( is_mode_partial )) && (( is_mode_regexp )); then
|
||||
echo "\`--partial' and \`--regexp' are mutually exclusive" \
|
||||
| batslib_decorate 'ERROR: assert_line' \
|
||||
| fail
|
||||
return $?
|
||||
fi
|
||||
|
||||
# Arguments.
|
||||
local -r expected="$1"
|
||||
|
||||
if (( is_mode_regexp == 1 )) && [[ '' =~ $expected ]] || (( $? == 2 )); then
|
||||
echo "Invalid extended regular expression: \`$expected'" \
|
||||
| batslib_decorate 'ERROR: assert_line' \
|
||||
| fail
|
||||
return $?
|
||||
fi
|
||||
|
||||
# Matching.
|
||||
if (( is_match_line )); then
|
||||
# Specific line.
|
||||
if (( is_mode_regexp )); then
|
||||
if ! [[ ${lines[$idx]} =~ $expected ]]; then
|
||||
batslib_print_kv_single 6 \
|
||||
'index' "$idx" \
|
||||
'regexp' "$expected" \
|
||||
'line' "${lines[$idx]}" \
|
||||
| batslib_decorate 'regular expression does not match line' \
|
||||
| fail
|
||||
fi
|
||||
elif (( is_mode_partial )); then
|
||||
if [[ ${lines[$idx]} != *"$expected"* ]]; then
|
||||
batslib_print_kv_single 9 \
|
||||
'index' "$idx" \
|
||||
'substring' "$expected" \
|
||||
'line' "${lines[$idx]}" \
|
||||
| batslib_decorate 'line does not contain substring' \
|
||||
| fail
|
||||
fi
|
||||
else
|
||||
if [[ ${lines[$idx]} != "$expected" ]]; then
|
||||
batslib_print_kv_single 8 \
|
||||
'index' "$idx" \
|
||||
'expected' "$expected" \
|
||||
'actual' "${lines[$idx]}" \
|
||||
| batslib_decorate 'line differs' \
|
||||
| fail
|
||||
fi
|
||||
fi
|
||||
else
|
||||
# Contained in output.
|
||||
if (( is_mode_regexp )); then
|
||||
local -i idx
|
||||
for (( idx = 0; idx < ${#lines[@]}; ++idx )); do
|
||||
[[ ${lines[$idx]} =~ $expected ]] && return 0
|
||||
done
|
||||
{ local -ar single=( 'regexp' "$expected" )
|
||||
local -ar may_be_multi=( 'output' "$output" )
|
||||
local -ir width="$( batslib_get_max_single_line_key_width "${single[@]}" "${may_be_multi[@]}" )"
|
||||
batslib_print_kv_single "$width" "${single[@]}"
|
||||
batslib_print_kv_single_or_multi "$width" "${may_be_multi[@]}"
|
||||
} \
|
||||
| batslib_decorate 'no output line matches regular expression' \
|
||||
| fail
|
||||
elif (( is_mode_partial )); then
|
||||
local -i idx
|
||||
for (( idx = 0; idx < ${#lines[@]}; ++idx )); do
|
||||
[[ ${lines[$idx]} == *"$expected"* ]] && return 0
|
||||
done
|
||||
{ local -ar single=( 'substring' "$expected" )
|
||||
local -ar may_be_multi=( 'output' "$output" )
|
||||
local -ir width="$( batslib_get_max_single_line_key_width "${single[@]}" "${may_be_multi[@]}" )"
|
||||
batslib_print_kv_single "$width" "${single[@]}"
|
||||
batslib_print_kv_single_or_multi "$width" "${may_be_multi[@]}"
|
||||
} \
|
||||
| batslib_decorate 'no output line contains substring' \
|
||||
| fail
|
||||
else
|
||||
local -i idx
|
||||
for (( idx = 0; idx < ${#lines[@]}; ++idx )); do
|
||||
[[ ${lines[$idx]} == "$expected" ]] && return 0
|
||||
done
|
||||
{ local -ar single=( 'line' "$expected" )
|
||||
local -ar may_be_multi=( 'output' "$output" )
|
||||
local -ir width="$( batslib_get_max_single_line_key_width "${single[@]}" "${may_be_multi[@]}" )"
|
||||
batslib_print_kv_single "$width" "${single[@]}"
|
||||
batslib_print_kv_single_or_multi "$width" "${may_be_multi[@]}"
|
||||
} \
|
||||
| batslib_decorate 'output does not contain line' \
|
||||
| fail
|
||||
fi
|
||||
fi
|
||||
}
|
197
lib/bats-assert/src/assert_output.bash
Normal file
197
lib/bats-assert/src/assert_output.bash
Normal file
@@ -0,0 +1,197 @@
|
||||
# assert_output
|
||||
# =============
|
||||
#
|
||||
# Summary: Fail if `$output' does not match the expected output.
|
||||
#
|
||||
# Usage: assert_output [-p | -e] [- | [--] <expected>]
|
||||
#
|
||||
# Options:
|
||||
# -p, --partial Match if `expected` is a substring of `$output`
|
||||
# -e, --regexp Treat `expected` as an extended regular expression
|
||||
# -, --stdin Read `expected` value from STDIN
|
||||
# <expected> The expected value, substring or regular expression
|
||||
#
|
||||
# IO:
|
||||
# STDIN - [=$1] expected output
|
||||
# STDERR - details, on failure
|
||||
# error message, on error
|
||||
# Globals:
|
||||
# output
|
||||
# Returns:
|
||||
# 0 - if output matches the expected value/partial/regexp
|
||||
# 1 - otherwise
|
||||
#
|
||||
# This function verifies that a command or function produces the expected output.
|
||||
# (It is the logical complement of `refute_output`.)
|
||||
# Output matching can be literal (the default), partial or by regular expression.
|
||||
# The expected output can be specified either by positional argument or read from STDIN by passing the `-`/`--stdin` flag.
|
||||
#
|
||||
# ## Literal matching
|
||||
#
|
||||
# By default, literal matching is performed.
|
||||
# The assertion fails if `$output` does not equal the expected output.
|
||||
#
|
||||
# ```bash
|
||||
# @test 'assert_output()' {
|
||||
# run echo 'have'
|
||||
# assert_output 'want'
|
||||
# }
|
||||
#
|
||||
# @test 'assert_output() with pipe' {
|
||||
# run echo 'hello'
|
||||
# echo 'hello' | assert_output -
|
||||
# }
|
||||
#
|
||||
# @test 'assert_output() with herestring' {
|
||||
# run echo 'hello'
|
||||
# assert_output - <<< hello
|
||||
# }
|
||||
# ```
|
||||
#
|
||||
# On failure, the expected and actual output are displayed.
|
||||
#
|
||||
# ```
|
||||
# -- output differs --
|
||||
# expected : want
|
||||
# actual : have
|
||||
# --
|
||||
# ```
|
||||
#
|
||||
# ## Existence
|
||||
#
|
||||
# To assert that any output exists at all, omit the `expected` argument.
|
||||
#
|
||||
# ```bash
|
||||
# @test 'assert_output()' {
|
||||
# run echo 'have'
|
||||
# assert_output
|
||||
# }
|
||||
# ```
|
||||
#
|
||||
# On failure, an error message is displayed.
|
||||
#
|
||||
# ```
|
||||
# -- no output --
|
||||
# expected non-empty output, but output was empty
|
||||
# --
|
||||
# ```
|
||||
#
|
||||
# ## Partial matching
|
||||
#
|
||||
# Partial matching can be enabled with the `--partial` option (`-p` for short).
|
||||
# When used, the assertion fails if the expected _substring_ is not found in `$output`.
|
||||
#
|
||||
# ```bash
|
||||
# @test 'assert_output() partial matching' {
|
||||
# run echo 'ERROR: no such file or directory'
|
||||
# assert_output --partial 'SUCCESS'
|
||||
# }
|
||||
# ```
|
||||
#
|
||||
# On failure, the substring and the output are displayed.
|
||||
#
|
||||
# ```
|
||||
# -- output does not contain substring --
|
||||
# substring : SUCCESS
|
||||
# output : ERROR: no such file or directory
|
||||
# --
|
||||
# ```
|
||||
#
|
||||
# ## Regular expression matching
|
||||
#
|
||||
# Regular expression matching can be enabled with the `--regexp` option (`-e` for short).
|
||||
# When used, the assertion fails if the *extended regular expression* does not match `$output`.
|
||||
#
|
||||
# *__Note__:
|
||||
# The anchors `^` and `$` bind to the beginning and the end (respectively) of the entire output;
|
||||
# not individual lines.*
|
||||
#
|
||||
# ```bash
|
||||
# @test 'assert_output() regular expression matching' {
|
||||
# run echo 'Foobar 0.1.0'
|
||||
# assert_output --regexp '^Foobar v[0-9]+\.[0-9]+\.[0-9]$'
|
||||
# }
|
||||
# ```
|
||||
#
|
||||
# On failure, the regular expression and the output are displayed.
|
||||
#
|
||||
# ```
|
||||
# -- regular expression does not match output --
|
||||
# regexp : ^Foobar v[0-9]+\.[0-9]+\.[0-9]$
|
||||
# output : Foobar 0.1.0
|
||||
# --
|
||||
# ```
|
||||
assert_output() {
|
||||
local -i is_mode_partial=0
|
||||
local -i is_mode_regexp=0
|
||||
local -i is_mode_nonempty=0
|
||||
local -i use_stdin=0
|
||||
: "${output?}"
|
||||
|
||||
# Handle options.
|
||||
if (( $# == 0 )); then
|
||||
is_mode_nonempty=1
|
||||
fi
|
||||
|
||||
while (( $# > 0 )); do
|
||||
case "$1" in
|
||||
-p|--partial) is_mode_partial=1; shift ;;
|
||||
-e|--regexp) is_mode_regexp=1; shift ;;
|
||||
-|--stdin) use_stdin=1; shift ;;
|
||||
--) shift; break ;;
|
||||
*) break ;;
|
||||
esac
|
||||
done
|
||||
|
||||
if (( is_mode_partial )) && (( is_mode_regexp )); then
|
||||
echo "\`--partial' and \`--regexp' are mutually exclusive" \
|
||||
| batslib_decorate 'ERROR: assert_output' \
|
||||
| fail
|
||||
return $?
|
||||
fi
|
||||
|
||||
# Arguments.
|
||||
local expected
|
||||
if (( use_stdin )); then
|
||||
expected="$(cat -)"
|
||||
else
|
||||
expected="${1-}"
|
||||
fi
|
||||
|
||||
# Matching.
|
||||
if (( is_mode_nonempty )); then
|
||||
if [ -z "$output" ]; then
|
||||
echo 'expected non-empty output, but output was empty' \
|
||||
| batslib_decorate 'no output' \
|
||||
| fail
|
||||
fi
|
||||
elif (( is_mode_regexp )); then
|
||||
if [[ '' =~ $expected ]] || (( $? == 2 )); then
|
||||
echo "Invalid extended regular expression: \`$expected'" \
|
||||
| batslib_decorate 'ERROR: assert_output' \
|
||||
| fail
|
||||
elif ! [[ $output =~ $expected ]]; then
|
||||
batslib_print_kv_single_or_multi 6 \
|
||||
'regexp' "$expected" \
|
||||
'output' "$output" \
|
||||
| batslib_decorate 'regular expression does not match output' \
|
||||
| fail
|
||||
fi
|
||||
elif (( is_mode_partial )); then
|
||||
if [[ $output != *"$expected"* ]]; then
|
||||
batslib_print_kv_single_or_multi 9 \
|
||||
'substring' "$expected" \
|
||||
'output' "$output" \
|
||||
| batslib_decorate 'output does not contain substring' \
|
||||
| fail
|
||||
fi
|
||||
else
|
||||
if [[ $output != "$expected" ]]; then
|
||||
batslib_print_kv_single_or_multi 8 \
|
||||
'expected' "$expected" \
|
||||
'actual' "$output" \
|
||||
| batslib_decorate 'output differs' \
|
||||
| fail
|
||||
fi
|
||||
fi
|
||||
}
|
44
lib/bats-assert/src/assert_success.bash
Normal file
44
lib/bats-assert/src/assert_success.bash
Normal file
@@ -0,0 +1,44 @@
|
||||
# assert_success
|
||||
# ==============
|
||||
#
|
||||
# Summary: Fail if `$status` is not 0.
|
||||
#
|
||||
# Usage: assert_success
|
||||
#
|
||||
# IO:
|
||||
# STDERR - `$status` and `$output`, on failure
|
||||
# Globals:
|
||||
# status
|
||||
# output
|
||||
# Returns:
|
||||
# 0 - if `$status' is 0
|
||||
# 1 - otherwise
|
||||
#
|
||||
# ```bash
|
||||
# @test 'assert_success() status only' {
|
||||
# run bash -c "echo 'Error!'; exit 1"
|
||||
# assert_success
|
||||
# }
|
||||
# ```
|
||||
#
|
||||
# On failure, `$status` and `$output` are displayed.
|
||||
#
|
||||
# ```
|
||||
# -- command failed --
|
||||
# status : 1
|
||||
# output : Error!
|
||||
# --
|
||||
# ```
|
||||
assert_success() {
|
||||
: "${output?}"
|
||||
: "${status?}"
|
||||
|
||||
if (( status != 0 )); then
|
||||
{ local -ir width=6
|
||||
batslib_print_kv_single "$width" 'status' "$status"
|
||||
batslib_print_kv_single_or_multi "$width" 'output' "$output"
|
||||
} \
|
||||
| batslib_decorate 'command failed' \
|
||||
| fail
|
||||
fi
|
||||
}
|
42
lib/bats-assert/src/refute.bash
Normal file
42
lib/bats-assert/src/refute.bash
Normal file
@@ -0,0 +1,42 @@
|
||||
# refute
|
||||
# ======
|
||||
#
|
||||
# Summary: Fail if the given expression evaluates to true.
|
||||
#
|
||||
# Usage: refute <expression>
|
||||
#
|
||||
# Options:
|
||||
# <expression> The expression to evaluate for falsiness.
|
||||
# *__Note:__ The expression must be a simple command.
|
||||
# [Compound commands](https://www.gnu.org/software/bash/manual/bash.html#Compound-Commands),
|
||||
# such as `[[`, can be used only when executed with `bash -c`.*
|
||||
#
|
||||
# IO:
|
||||
# STDERR - the successful expression, on failure
|
||||
# Globals:
|
||||
# none
|
||||
# Returns:
|
||||
# 0 - if expression evaluates to false
|
||||
# 1 - otherwise
|
||||
#
|
||||
# ```bash
|
||||
# @test 'refute()' {
|
||||
# rm -f '/var/log/test.log'
|
||||
# refute [ -e '/var/log/test.log' ]
|
||||
# }
|
||||
# ```
|
||||
#
|
||||
# On failure, the successful expression is displayed.
|
||||
#
|
||||
# ```
|
||||
# -- assertion succeeded, but it was expected to fail --
|
||||
# expression : [ -e /var/log/test.log ]
|
||||
# --
|
||||
# ```
|
||||
refute() {
|
||||
if "$@"; then
|
||||
batslib_print_kv_single 10 'expression' "$*" \
|
||||
| batslib_decorate 'assertion succeeded, but it was expected to fail' \
|
||||
| fail
|
||||
fi
|
||||
}
|
271
lib/bats-assert/src/refute_line.bash
Normal file
271
lib/bats-assert/src/refute_line.bash
Normal file
@@ -0,0 +1,271 @@
|
||||
# refute_line
|
||||
# ===========
|
||||
#
|
||||
# Summary: Fail if the unexpected line is found in the output (default) or at a specific line number.
|
||||
#
|
||||
# Usage: refute_line [-n index] [-p | -e] [--] <unexpected>
|
||||
#
|
||||
# Options:
|
||||
# -n, --index <idx> Match the <idx>th line
|
||||
# -p, --partial Match if `unexpected` is a substring of `$output` or line <idx>
|
||||
# -e, --regexp Treat `unexpected` as an extended regular expression
|
||||
# <unexpected> The unexpected line string, substring, or regular expression.
|
||||
#
|
||||
# IO:
|
||||
# STDERR - details, on failure
|
||||
# error message, on error
|
||||
# Globals:
|
||||
# output
|
||||
# lines
|
||||
# Returns:
|
||||
# 0 - if match not found
|
||||
# 1 - otherwise
|
||||
#
|
||||
# Similarly to `refute_output`, this function verifies that a command or function does not produce the unexpected output.
|
||||
# (It is the logical complement of `assert_line`.)
|
||||
# It checks that the unexpected line does not appear in the output (default) or at a specific line number.
|
||||
# Matching can be literal (default), partial or regular expression.
|
||||
#
|
||||
# *__Warning:__
|
||||
# Due to a [bug in Bats][bats-93], empty lines are discarded from `${lines[@]}`,
|
||||
# causing line indices to change and preventing testing for empty lines.*
|
||||
#
|
||||
# [bats-93]: https://github.com/sstephenson/bats/pull/93
|
||||
#
|
||||
# ## Looking for a line in the output
|
||||
#
|
||||
# By default, the entire output is searched for the unexpected line.
|
||||
# The assertion fails if the unexpected line is found in `${lines[@]}`.
|
||||
#
|
||||
# ```bash
|
||||
# @test 'refute_line() looking for line' {
|
||||
# run echo $'have-0\nwant\nhave-2'
|
||||
# refute_line 'want'
|
||||
# }
|
||||
# ```
|
||||
#
|
||||
# On failure, the unexpected line, the index of its first match and the output with the matching line highlighted are displayed.
|
||||
#
|
||||
# ```
|
||||
# -- line should not be in output --
|
||||
# line : want
|
||||
# index : 1
|
||||
# output (3 lines):
|
||||
# have-0
|
||||
# > want
|
||||
# have-2
|
||||
# --
|
||||
# ```
|
||||
#
|
||||
# ## Matching a specific line
|
||||
#
|
||||
# When the `--index <idx>` option is used (`-n <idx>` for short), the unexpected line is matched only against the line identified by the given index.
|
||||
# The assertion fails if the unexpected line equals `${lines[<idx>]}`.
|
||||
#
|
||||
# ```bash
|
||||
# @test 'refute_line() specific line' {
|
||||
# run echo $'have-0\nwant-1\nhave-2'
|
||||
# refute_line --index 1 'want-1'
|
||||
# }
|
||||
# ```
|
||||
#
|
||||
# On failure, the index and the unexpected line are displayed.
|
||||
#
|
||||
# ```
|
||||
# -- line should differ --
|
||||
# index : 1
|
||||
# line : want-1
|
||||
# --
|
||||
# ```
|
||||
#
|
||||
# ## Partial matching
|
||||
#
|
||||
# Partial matching can be enabled with the `--partial` option (`-p` for short).
|
||||
# When used, a match fails if the unexpected *substring* is found in the matched line.
|
||||
#
|
||||
# ```bash
|
||||
# @test 'refute_line() partial matching' {
|
||||
# run echo $'have 1\nwant 2\nhave 3'
|
||||
# refute_line --partial 'want'
|
||||
# }
|
||||
# ```
|
||||
#
|
||||
# On failure, in addition to the details of literal matching, the substring is also displayed.
|
||||
# When used with `--index <idx>` the substring replaces the unexpected line.
|
||||
#
|
||||
# ```
|
||||
# -- no line should contain substring --
|
||||
# substring : want
|
||||
# index : 1
|
||||
# output (3 lines):
|
||||
# have 1
|
||||
# > want 2
|
||||
# have 3
|
||||
# --
|
||||
# ```
|
||||
#
|
||||
# ## Regular expression matching
|
||||
#
|
||||
# Regular expression matching can be enabled with the `--regexp` option (`-e` for short).
|
||||
# When used, a match fails if the *extended regular expression* matches the line being tested.
|
||||
#
|
||||
# *__Note__:
|
||||
# As expected, the anchors `^` and `$` bind to the beginning and the end (respectively) of the matched line.*
|
||||
#
|
||||
# ```bash
|
||||
# @test 'refute_line() regular expression matching' {
|
||||
# run echo $'Foobar v0.1.0\nRelease date: 2015-11-29'
|
||||
# refute_line --index 0 --regexp '^Foobar v[0-9]+\.[0-9]+\.[0-9]$'
|
||||
# }
|
||||
# ```
|
||||
#
|
||||
# On failure, in addition to the details of literal matching, the regular expression is also displayed.
|
||||
# When used with `--index <idx>` the regular expression replaces the unexpected line.
|
||||
#
|
||||
# ```
|
||||
# -- regular expression should not match line --
|
||||
# index : 0
|
||||
# regexp : ^Foobar v[0-9]+\.[0-9]+\.[0-9]$
|
||||
# line : Foobar v0.1.0
|
||||
# --
|
||||
# ```
|
||||
# FIXME(ztombol): Display `${lines[@]}' instead of `$output'!
|
||||
refute_line() {
|
||||
local -i is_match_line=0
|
||||
local -i is_mode_partial=0
|
||||
local -i is_mode_regexp=0
|
||||
: "${lines?}"
|
||||
|
||||
# Handle options.
|
||||
while (( $# > 0 )); do
|
||||
case "$1" in
|
||||
-n|--index)
|
||||
if (( $# < 2 )) || ! [[ $2 =~ ^([0-9]|[1-9][0-9]+)$ ]]; then
|
||||
echo "\`--index' requires an integer argument: \`$2'" \
|
||||
| batslib_decorate 'ERROR: refute_line' \
|
||||
| fail
|
||||
return $?
|
||||
fi
|
||||
is_match_line=1
|
||||
local -ri idx="$2"
|
||||
shift 2
|
||||
;;
|
||||
-p|--partial) is_mode_partial=1; shift ;;
|
||||
-e|--regexp) is_mode_regexp=1; shift ;;
|
||||
--) shift; break ;;
|
||||
*) break ;;
|
||||
esac
|
||||
done
|
||||
|
||||
if (( is_mode_partial )) && (( is_mode_regexp )); then
|
||||
echo "\`--partial' and \`--regexp' are mutually exclusive" \
|
||||
| batslib_decorate 'ERROR: refute_line' \
|
||||
| fail
|
||||
return $?
|
||||
fi
|
||||
|
||||
# Arguments.
|
||||
local -r unexpected="$1"
|
||||
|
||||
if (( is_mode_regexp == 1 )) && [[ '' =~ $unexpected ]] || (( $? == 2 )); then
|
||||
echo "Invalid extended regular expression: \`$unexpected'" \
|
||||
| batslib_decorate 'ERROR: refute_line' \
|
||||
| fail
|
||||
return $?
|
||||
fi
|
||||
|
||||
# Matching.
|
||||
if (( is_match_line )); then
|
||||
# Specific line.
|
||||
if (( is_mode_regexp )); then
|
||||
if [[ ${lines[$idx]} =~ $unexpected ]]; then
|
||||
batslib_print_kv_single 6 \
|
||||
'index' "$idx" \
|
||||
'regexp' "$unexpected" \
|
||||
'line' "${lines[$idx]}" \
|
||||
| batslib_decorate 'regular expression should not match line' \
|
||||
| fail
|
||||
fi
|
||||
elif (( is_mode_partial )); then
|
||||
if [[ ${lines[$idx]} == *"$unexpected"* ]]; then
|
||||
batslib_print_kv_single 9 \
|
||||
'index' "$idx" \
|
||||
'substring' "$unexpected" \
|
||||
'line' "${lines[$idx]}" \
|
||||
| batslib_decorate 'line should not contain substring' \
|
||||
| fail
|
||||
fi
|
||||
else
|
||||
if [[ ${lines[$idx]} == "$unexpected" ]]; then
|
||||
batslib_print_kv_single 5 \
|
||||
'index' "$idx" \
|
||||
'line' "${lines[$idx]}" \
|
||||
| batslib_decorate 'line should differ' \
|
||||
| fail
|
||||
fi
|
||||
fi
|
||||
else
|
||||
# Line contained in output.
|
||||
if (( is_mode_regexp )); then
|
||||
local -i idx
|
||||
for (( idx = 0; idx < ${#lines[@]}; ++idx )); do
|
||||
if [[ ${lines[$idx]} =~ $unexpected ]]; then
|
||||
{ local -ar single=( 'regexp' "$unexpected" 'index' "$idx" )
|
||||
local -a may_be_multi=( 'output' "$output" )
|
||||
local -ir width="$( batslib_get_max_single_line_key_width "${single[@]}" "${may_be_multi[@]}" )"
|
||||
batslib_print_kv_single "$width" "${single[@]}"
|
||||
if batslib_is_single_line "${may_be_multi[1]}"; then
|
||||
batslib_print_kv_single "$width" "${may_be_multi[@]}"
|
||||
else
|
||||
may_be_multi[1]="$( printf '%s' "${may_be_multi[1]}" | batslib_prefix | batslib_mark '>' "$idx" )"
|
||||
batslib_print_kv_multi "${may_be_multi[@]}"
|
||||
fi
|
||||
} \
|
||||
| batslib_decorate 'no line should match the regular expression' \
|
||||
| fail
|
||||
return $?
|
||||
fi
|
||||
done
|
||||
elif (( is_mode_partial )); then
|
||||
local -i idx
|
||||
for (( idx = 0; idx < ${#lines[@]}; ++idx )); do
|
||||
if [[ ${lines[$idx]} == *"$unexpected"* ]]; then
|
||||
{ local -ar single=( 'substring' "$unexpected" 'index' "$idx" )
|
||||
local -a may_be_multi=( 'output' "$output" )
|
||||
local -ir width="$( batslib_get_max_single_line_key_width "${single[@]}" "${may_be_multi[@]}" )"
|
||||
batslib_print_kv_single "$width" "${single[@]}"
|
||||
if batslib_is_single_line "${may_be_multi[1]}"; then
|
||||
batslib_print_kv_single "$width" "${may_be_multi[@]}"
|
||||
else
|
||||
may_be_multi[1]="$( printf '%s' "${may_be_multi[1]}" | batslib_prefix | batslib_mark '>' "$idx" )"
|
||||
batslib_print_kv_multi "${may_be_multi[@]}"
|
||||
fi
|
||||
} \
|
||||
| batslib_decorate 'no line should contain substring' \
|
||||
| fail
|
||||
return $?
|
||||
fi
|
||||
done
|
||||
else
|
||||
local -i idx
|
||||
for (( idx = 0; idx < ${#lines[@]}; ++idx )); do
|
||||
if [[ ${lines[$idx]} == "$unexpected" ]]; then
|
||||
{ local -ar single=( 'line' "$unexpected" 'index' "$idx" )
|
||||
local -a may_be_multi=( 'output' "$output" )
|
||||
local -ir width="$( batslib_get_max_single_line_key_width "${single[@]}" "${may_be_multi[@]}" )"
|
||||
batslib_print_kv_single "$width" "${single[@]}"
|
||||
if batslib_is_single_line "${may_be_multi[1]}"; then
|
||||
batslib_print_kv_single "$width" "${may_be_multi[@]}"
|
||||
else
|
||||
may_be_multi[1]="$( printf '%s' "${may_be_multi[1]}" | batslib_prefix | batslib_mark '>' "$idx" )"
|
||||
batslib_print_kv_multi "${may_be_multi[@]}"
|
||||
fi
|
||||
} \
|
||||
| batslib_decorate 'line should not be in output' \
|
||||
| fail
|
||||
return $?
|
||||
fi
|
||||
done
|
||||
fi
|
||||
fi
|
||||
}
|
199
lib/bats-assert/src/refute_output.bash
Normal file
199
lib/bats-assert/src/refute_output.bash
Normal file
@@ -0,0 +1,199 @@
|
||||
# refute_output
|
||||
# =============
|
||||
#
|
||||
# Summary: Fail if `$output' matches the unexpected output.
|
||||
#
|
||||
# Usage: refute_output [-p | -e] [- | [--] <unexpected>]
|
||||
#
|
||||
# Options:
|
||||
# -p, --partial Match if `unexpected` is a substring of `$output`
|
||||
# -e, --regexp Treat `unexpected` as an extended regular expression
|
||||
# -, --stdin Read `unexpected` value from STDIN
|
||||
# <unexpected> The unexpected value, substring, or regular expression
|
||||
#
|
||||
# IO:
|
||||
# STDIN - [=$1] unexpected output
|
||||
# STDERR - details, on failure
|
||||
# error message, on error
|
||||
# Globals:
|
||||
# output
|
||||
# Returns:
|
||||
# 0 - if output matches the unexpected value/partial/regexp
|
||||
# 1 - otherwise
|
||||
#
|
||||
# This function verifies that a command or function does not produce the unexpected output.
|
||||
# (It is the logical complement of `assert_output`.)
|
||||
# Output matching can be literal (the default), partial or by regular expression.
|
||||
# The unexpected output can be specified either by positional argument or read from STDIN by passing the `-`/`--stdin` flag.
|
||||
#
|
||||
# ## Literal matching
|
||||
#
|
||||
# By default, literal matching is performed.
|
||||
# The assertion fails if `$output` equals the unexpected output.
|
||||
#
|
||||
# ```bash
|
||||
# @test 'refute_output()' {
|
||||
# run echo 'want'
|
||||
# refute_output 'want'
|
||||
# }
|
||||
#
|
||||
# @test 'refute_output() with pipe' {
|
||||
# run echo 'hello'
|
||||
# echo 'world' | refute_output -
|
||||
# }
|
||||
#
|
||||
# @test 'refute_output() with herestring' {
|
||||
# run echo 'hello'
|
||||
# refute_output - <<< world
|
||||
# }
|
||||
# ```
|
||||
#
|
||||
# On failure, the output is displayed.
|
||||
#
|
||||
# ```
|
||||
# -- output equals, but it was expected to differ --
|
||||
# output : want
|
||||
# --
|
||||
# ```
|
||||
#
|
||||
# ## Existence
|
||||
#
|
||||
# To assert that there is no output at all, omit the matching argument.
|
||||
#
|
||||
# ```bash
|
||||
# @test 'refute_output()' {
|
||||
# run foo --silent
|
||||
# refute_output
|
||||
# }
|
||||
# ```
|
||||
#
|
||||
# On failure, an error message is displayed.
|
||||
#
|
||||
# ```
|
||||
# -- unexpected output --
|
||||
# expected no output, but output was non-empty
|
||||
# --
|
||||
# ```
|
||||
#
|
||||
# ## Partial matching
|
||||
#
|
||||
# Partial matching can be enabled with the `--partial` option (`-p` for short).
|
||||
# When used, the assertion fails if the unexpected _substring_ is found in `$output`.
|
||||
#
|
||||
# ```bash
|
||||
# @test 'refute_output() partial matching' {
|
||||
# run echo 'ERROR: no such file or directory'
|
||||
# refute_output --partial 'ERROR'
|
||||
# }
|
||||
# ```
|
||||
#
|
||||
# On failure, the substring and the output are displayed.
|
||||
#
|
||||
# ```
|
||||
# -- output should not contain substring --
|
||||
# substring : ERROR
|
||||
# output : ERROR: no such file or directory
|
||||
# --
|
||||
# ```
|
||||
#
|
||||
# ## Regular expression matching
|
||||
#
|
||||
# Regular expression matching can be enabled with the `--regexp` option (`-e` for short).
|
||||
# When used, the assertion fails if the *extended regular expression* matches `$output`.
|
||||
#
|
||||
# *__Note__:
|
||||
# The anchors `^` and `$` bind to the beginning and the end (respectively) of the entire output;
|
||||
# not individual lines.*
|
||||
#
|
||||
# ```bash
|
||||
# @test 'refute_output() regular expression matching' {
|
||||
# run echo 'Foobar v0.1.0'
|
||||
# refute_output --regexp '^Foobar v[0-9]+\.[0-9]+\.[0-9]$'
|
||||
# }
|
||||
# ```
|
||||
#
|
||||
# On failure, the regular expression and the output are displayed.
|
||||
#
|
||||
# ```
|
||||
# -- regular expression should not match output --
|
||||
# regexp : ^Foobar v[0-9]+\.[0-9]+\.[0-9]$
|
||||
# output : Foobar v0.1.0
|
||||
# --
|
||||
# ```
|
||||
refute_output() {
|
||||
local -i is_mode_partial=0
|
||||
local -i is_mode_regexp=0
|
||||
local -i is_mode_empty=0
|
||||
local -i use_stdin=0
|
||||
: "${output?}"
|
||||
|
||||
# Handle options.
|
||||
if (( $# == 0 )); then
|
||||
is_mode_empty=1
|
||||
fi
|
||||
|
||||
while (( $# > 0 )); do
|
||||
case "$1" in
|
||||
-p|--partial) is_mode_partial=1; shift ;;
|
||||
-e|--regexp) is_mode_regexp=1; shift ;;
|
||||
-|--stdin) use_stdin=1; shift ;;
|
||||
--) shift; break ;;
|
||||
*) break ;;
|
||||
esac
|
||||
done
|
||||
|
||||
if (( is_mode_partial )) && (( is_mode_regexp )); then
|
||||
echo "\`--partial' and \`--regexp' are mutually exclusive" \
|
||||
| batslib_decorate 'ERROR: refute_output' \
|
||||
| fail
|
||||
return $?
|
||||
fi
|
||||
|
||||
# Arguments.
|
||||
local unexpected
|
||||
if (( use_stdin )); then
|
||||
unexpected="$(cat -)"
|
||||
else
|
||||
unexpected="${1-}"
|
||||
fi
|
||||
|
||||
if (( is_mode_regexp == 1 )) && [[ '' =~ $unexpected ]] || (( $? == 2 )); then
|
||||
echo "Invalid extended regular expression: \`$unexpected'" \
|
||||
| batslib_decorate 'ERROR: refute_output' \
|
||||
| fail
|
||||
return $?
|
||||
fi
|
||||
|
||||
# Matching.
|
||||
if (( is_mode_empty )); then
|
||||
if [ -n "$output" ]; then
|
||||
batslib_print_kv_single_or_multi 6 \
|
||||
'output' "$output" \
|
||||
| batslib_decorate 'output non-empty, but expected no output' \
|
||||
| fail
|
||||
fi
|
||||
elif (( is_mode_regexp )); then
|
||||
if [[ $output =~ $unexpected ]]; then
|
||||
batslib_print_kv_single_or_multi 6 \
|
||||
'regexp' "$unexpected" \
|
||||
'output' "$output" \
|
||||
| batslib_decorate 'regular expression should not match output' \
|
||||
| fail
|
||||
fi
|
||||
elif (( is_mode_partial )); then
|
||||
if [[ $output == *"$unexpected"* ]]; then
|
||||
batslib_print_kv_single_or_multi 9 \
|
||||
'substring' "$unexpected" \
|
||||
'output' "$output" \
|
||||
| batslib_decorate 'output should not contain substring' \
|
||||
| fail
|
||||
fi
|
||||
else
|
||||
if [[ $output == "$unexpected" ]]; then
|
||||
batslib_print_kv_single_or_multi 6 \
|
||||
'output' "$output" \
|
||||
| batslib_decorate 'output equals, but it was expected to differ' \
|
||||
| fail
|
||||
fi
|
||||
fi
|
||||
}
|
Reference in New Issue
Block a user