Skip to content

Commit

Permalink
Create unit tests for BATS helper functions
Browse files Browse the repository at this point in the history
Signed-off-by: Jan Dubois <jan.dubois@suse.com>
  • Loading branch information
jandubois committed Jul 8, 2023
1 parent 24f14e6 commit b7b89d8
Show file tree
Hide file tree
Showing 2 changed files with 249 additions and 18 deletions.
229 changes: 229 additions & 0 deletions bats/tests/bats/utils.bats
Original file line number Diff line number Diff line change
@@ -0,0 +1,229 @@
# Checks need to be disabled to allow literal JSON in variable assignments
# https://www.shellcheck.net/wiki/SC2089 -- Quotes/backslashes will be treated literally. Use an array.
# https://www.shellcheck.net/wiki/SC2090 -- Quotes/backslashes in this variable will not be respected.
# shellcheck disable=SC2089
# shellcheck disable=SC2090

load '../helpers/load'

local_setup() {
COUNTER="${BATS_FILE_TMPDIR}/counter"
echo 0 >"$COUNTER"
}

# Increment counter file. Return success when counter >= max.
inc_counter() {
local max=${1-9999}
local counter=$(($(cat "$COUNTER") + 1))
echo $counter >"$COUNTER"
((counter >= max))
}

assert_counter_is() {
run cat "${COUNTER}"
assert_output "$1"
}

@test 'true' {
true
}

check_truthiness() {
local predicate=$1
local value

# test true values
for value in true True 1 yes YES any; do
run "$predicate" "$value"
if [[ $predicate == is_true ]]; then
assert_success
else
assert_failure
fi
done

# test false values
for value in false fALSE 0 no No NO ''; do
run "$predicate" "$value"
if [[ $predicate == is_true ]]; then
assert_failure
else
assert_success
fi
done
}

@test 'is_true' {
check_truthiness is_true
}

@test 'is_false' {
check_truthiness is_false
}

@test 'bool' {
run bool true
assert_output true

run bool false
assert_output false
}

@test 'validate_enum OS should pass' {
run validate_enum OS darwin linux windows
assert_success
}

@test 'validate_enum FRUIT should fail' {
FRUIT=apple
run validate_enum FRUIT banana cherry pear
assert_failure
# Can't check output; it is written using "fatal":
# FRUIT=apple is not a valid setting; select from [banana cherry pear]
}

@test 'is_xxx' {
local count=0
# Exactly one of the is_xxx functions should return true
for os in linux macos windows; do
if "is_$os"; then
((++count))
fi
done
((count == 1))
}

@test 'jq_output extracts string value' {
output='{"foo":"bar"}'
run jq_output .foo
assert_success
assert_output bar
}

@test 'jq_output extracts "false" value' {
output='{"foo":false}'
run jq_output .foo
assert_success
assert_output false
}

@test 'jq_output cannot extract "null" value' {
output='{"foo":null}'
run jq_output .foo
assert_failure
assert_output null
}

@test 'jq_output fails when key is not found' {
output='{"foo":"bar"}'
run jq_output .baz
assert_failure
assert_output null
}

@test 'this_function' {
foo() {
this_function
}
run foo
assert_success
assert_output foo
}

@test 'calling_function' {
bar() {
baz
}
baz() {
calling_function
}
run bar
assert_success
assert_output bar
}

@test 'try will run command at least once' {
run try --max 0 --delay 5 inc_counter
assert_failure
assert_counter_is 1
# "try" should not have called "sleep 5" at all
((SECONDS < 2))
}

@test 'try will stop as soon as the command succeeds' {
run try --max 3 --delay 3 inc_counter 2
assert_success
assert_counter_is 2
# "try" should have called "sleep 3" exactly once
((SECONDS >= 3))
((SECONDS < 6))
}

@test 'try will return after max retries' {
run try --max 3 --delay 2 inc_counter
assert_failure
assert_counter_is 3
# "try" should have called "sleep 2" exactly twice
((SECONDS >= 4))
((SECONDS < 6))
}

check_image_without_tag() {
local image=$1
local expect=$2
run image_without_tag "$image"
assert_success
assert_output "$expect"
}

@test 'image_without_tag with busybox' {
check_image_without_tag busybox busybox
}

@test 'image_without_tag with busybox:latest' {
check_image_without_tag busybox:latest busybox
}

@test 'image_without_tag with busybox:5000' {
check_image_without_tag busybox:5000 busybox
}

@test 'image_without_tag with registry.io:5000' {
check_image_without_tag registry.io:5000 registry.io:5000
}

@test 'image_without_tag with registry.io:5000/busybox' {
check_image_without_tag registry.io:5000/busybox registry.io:5000/busybox
}

@test 'image_without_tag with registry.io:5000/busybox:8080' {
check_image_without_tag registry.io:5000/busybox:8080 registry.io:5000/busybox
}

@test 'unique_filename without extension' {
run unique_filename "$COUNTER"
assert_success
assert_output "${COUNTER}_2"
touch "$output"

run unique_filename "$COUNTER"
assert_success
assert_output "${COUNTER}_3"
touch "$output"
}

@test 'unique_filename with extension' {
run unique_filename "$COUNTER" .png
assert_success
assert_output "${COUNTER}.png"
touch "$output"

run unique_filename "$COUNTER" .png
assert_success
assert_output "${COUNTER}_2.png"
touch "$output"

run unique_filename "$COUNTER" .png
assert_success
assert_output "${COUNTER}_3.png"
}
38 changes: 20 additions & 18 deletions bats/tests/helpers/utils.bash
Original file line number Diff line number Diff line change
@@ -1,11 +1,7 @@
is_true() {
# case-insensitive check; false values: '', '0', 'no', and 'false'
local value="$(echo "$1" | tr '[:upper:]' '[:lower:]')"
if [[ $value =~ ^(0|no|false)?$ ]]; then
false
else
true
fi
[[ ! $value =~ ^(0|no|false)?$ ]]
}

is_false() {
Expand All @@ -26,7 +22,7 @@ validate_enum() {
local var=$1
shift
for value in "$@"; do
if [ "${!var}" = "$value" ]; then
if [[ ${!var} == "$value" ]]; then
return
fi
done
Expand All @@ -40,7 +36,13 @@ assert_nothing() {
}

jq_output() {
jq -r "$@" <<<"${output}"
# -e sets exit status to 1 when the output is false or null
run jq -e -r "$@" <<<"${output}"
echo "$output"
if [[ $status == 1 && $output == false ]]; then
status=0
fi
return "$status"
}

get_setting() {
Expand Down Expand Up @@ -90,10 +92,10 @@ try() {
shift
done

local count
for ((count = 0; count < max; ++count)); do
local count=0
while true; do
run "$@"
if ((status == 0)); then
if ((status == 0 || ++count >= max)); then
break
fi
sleep "$delay"
Expand All @@ -106,7 +108,7 @@ image_without_tag() {
local image=$1
# If the tag looks like a port number and follows something that looks
# like a domain name, then don't strip the tag (e.g. foo.io:5000).
if [[ ${image##*:} =~ ^[0-9]+$ && ${image%:*} =~ \.[a-z]+$ ]]; then
if [[ ${image##*:} =~ ^[0-9]+(/|$) && ${image%:*} =~ \.[a-z]+$ ]]; then
echo "$image"
else
echo "${image%:*}"
Expand Down Expand Up @@ -156,22 +158,22 @@ unique_filename() {
local suffix=""

while true; do
local filename="$basename$suffix$extension"
if [ ! -e "$filename" ]; then
local filename="${basename}${suffix}${extension}"
if [[ ! -e $filename ]]; then
echo "$filename"
return
fi
index=$((index + 1))
suffix="_$index"
((++index))
suffix="_${index}"
done
}

capture_logs() {
if capturing_logs && [ -d "$PATH_LOGS" ]; then
if capturing_logs && [[ -d $PATH_LOGS ]]; then
local logdir=$(unique_filename "${PATH_BATS_LOGS}/${RD_TEST_FILENAME}")
mkdir -p "$logdir"
cp -LR "$PATH_LOGS/" "$logdir"
echo "${BATS_TEST_DESCRIPTION:-teardown}" >"$logdir/test_description"
cp -LR "${PATH_LOGS}/" "$logdir"
echo "${BATS_TEST_DESCRIPTION:-teardown}" >"${logdir}/test_description"
fi
}

Expand Down

0 comments on commit b7b89d8

Please sign in to comment.