Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

add when/unless #72

Merged
merged 5 commits into from
Mar 21, 2024
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
21 changes: 21 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,27 @@ A cukinia config file supports the following statements:
* ``verbose``: Can prefix any test to preserve stdout/stderr
* ``as <string>``: Can prefix any test to change its textual description

### Condition statements

* `when <condition>`: Can prefix any test to `<condition>` it
* `unless <condition>`: Just like `when`, but the opposite

If the condition is not met, the test status will be reported as SKIP.

A few examples using `when` and `unless`:
``` bash
on_eval_board() { grep -q EVK /sys/firmware/devicetree/base/model; }
arch_is_arm64() { test "$(uname -m)" = "aarch64"; }

unless "on_eval_board" \
as "Custom LED controller was detected" \
cukinia_test -d /sys/class/leds/superled

when "arch_is_arm64" \
unless "on_eval_board" \
cukinia_kmod some_driver
```

### Utility statements

* ``cukinia_conf_include <files>``: Includes files as additional config files
Expand Down
126 changes: 82 additions & 44 deletions cukinia
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ usage()
cat <<EOF
NAME:
Cukinia - portable firmware validation framework.
Copyright (C) 2017-2023 Savoir-faire Linux Inc.
Copyright (C) 2017-2024 Savoir-faire Linux Inc.

The name means "zucchini" in Polish. It is a nod to Cucumber,
another neat test framework.
Expand All @@ -78,6 +78,7 @@ OPTIONS:
-f <format> set output format to <format>, currently supported:
csv junitxml
--no-header do not print headers in concerned output formats
--trace trace execution (for debugging)
EOF
}

Expand Down Expand Up @@ -108,6 +109,9 @@ while getopts ":o:f:hv-:" opt; do
no-header)
__no_header=1
;;
trace)
set -x
;;
version)
echo "Cukinia version $CUKINIA_VERSION"
exit 0
Expand Down Expand Up @@ -225,16 +229,23 @@ cukinia_log()
local message="$1"
local result="$2"

_should_log() {
case "$result" in
PASS|FAIL|SKIP) return 0 ;;
esac
return 1
}

case "$__log_format" in
csv)
if [ "$result" = "PASS" ] || [ "$result" = "FAIL" ]; then
if _should_log; then
message=$(echo $message | sed -e "s/'/\\'/g") # ' -> \'
echo "'$message',$result,$__log_class,$__suite_name" >>"$__logfile_tmp"
fi
;;

junitxml)
if [ "$result" = "PASS" ] || [ "$result" = "FAIL" ]; then
if _should_log; then
_junitxml_add_case "$message" "$result"
fi
;;
Expand Down Expand Up @@ -264,6 +275,9 @@ cukinia_runner()

if [ -n "$CUKINIA_ALWAYS_PASS" ]; then
__not="pass"
elif [ -n "$__skip_condition" ]; then
_cukinia_result SKIP
return
fi

case "$__not..$ret" in
Expand Down Expand Up @@ -330,6 +344,7 @@ not()
}

# verbose: the output of what follows will not be muted
# arg1..: command
verbose()
{
local ret=0
Expand All @@ -341,6 +356,40 @@ verbose()
return $ret
}

# _condition_run: run $@ if condition
# arg1: the condition
# arg2..: commands and arguments
_condition_run()
{
local ret=0

eval "$1" >/dev/null || __skip_condition=1
shift

"$@" || ret=1
unset __skip_condition

return $ret
}

# unless: condition test with a negative condition
# arg1: the condition expression
# arg2..: command
unless()
{
local condition="$1"; shift
_condition_run "! $condition" "$@"
}

# when: condition test when condition is true
# arg1: the condition expression
# arg2..: command
when()
{
local condition="$1"; shift
_condition_run "$condition" "$@"
}

# _cukinia_python_pkg: try to import the python package
# arg1: the python package
_cukinia_python_pkg()
Expand Down Expand Up @@ -376,25 +425,24 @@ _cukinia_result()
{
local result="$1"

case "$result" in
PASS)
result=$(_colorize green "PASS")
;;
FAIL)
result=$(_colorize red "FAIL")
;;
*)
;;
esac

case "$__log_format" in
csv|junitxml)
cukinia_log "$__cukinia_cur_test" "$result"
return
;;
*)
cukinia_log "[$result] $__cukinia_cur_test"
;;
esac

case "$result" in
PASS) result=$(_colorize green "PASS") ;;
FAIL) result=$(_colorize red "FAIL") ;;
SKIP) result=$(_colorize yellow2 "SKIP") ;;
esac

if [ "$__skip_condition" ]; then
local suffix=" [$(_colorize yellow2 "unmet condition")]"
fi

cukinia_log "[$result] ${__cukinia_cur_test}${suffix}"
}

# _cukinia_cmd: wrapper to any command
Expand Down Expand Up @@ -1154,36 +1202,26 @@ _colorize()

# Only colorize a few terminal types
case "$TERM" in
linux*|xterm*|vt102)
;;
*)
echo "$@"
return
;;
linux*|xterm*|screen*|tmux*|vt102) ;;
*) echo "$@"; return ;;
esac

case "$color" in
gray)
c='\033[1;30m'
;;
red)
c='\033[1;31m'
;;
green)
c='\033[1;32m'
;;
yellow)
c='\033[1;33m'
;;
blue)
c='\033[1;34m'
;;
purple)
c='\033[1;35m'
;;
cyan)
c='\033[1;36m'
;;
gray) c='\033[1;30m' ;;
red) c='\033[1;31m' ;;
green) c='\033[1;32m' ;;
yellow) c='\033[1;33m' ;;
blue) c='\033[1;34m' ;;
purple) c='\033[1;35m' ;;
cyan) c='\033[1;36m' ;;

red2) c='\033[1;91m' ;;
green2) c='\033[1;92m' ;;
yellow2) c='\033[1;93m' ;;
blue2) c='\033[1;94m' ;;
purple2) c='\033[1;95m' ;;
cyan2) c='\033[1;96m' ;;
white2) c='\033[1;97m' ;;
esac

printf "${c}${text}${nc}"
Expand Down
23 changes: 23 additions & 0 deletions tests/testcases.conf
Original file line number Diff line number Diff line change
Expand Up @@ -146,10 +146,33 @@ section "cukinia_run_dir"

cukinia_run_dir ./exec.pass.d

section "when/unless"

machine_is() { test "$(uname -m)" = "$1"; }
on_eval_board() { grep -q EVK /sys/firmware/devicetree/base/model 2>/dev/null; }

when "machine_is x86_64" \
unless "[ $(( $(date +%d) % 2)) -eq 0 ]" \
as "Should PASS on x86_64 PC only or skip on even days" \
cukinia_cmd /bin/true

when "machine_is arm64" \
as "Should PASS on arm64 only or skip" \
cukinia_cmd /bin/true

unless "machine_is arm64" \
as "Should PASS on PC only or skip" \
cukinia_cmd /bin/true

unless "machine_is x86_64" \
joufellasfl marked this conversation as resolved.
Show resolved Hide resolved
as "Should SKIP on PC only" \
cukinia_cmd /bin/true

section "color tests"

for color in red green blue cyan yellow gray purple; do
cukinia_log "* _colorize $(_colorize $color $color)"
cukinia_log "* _colorize $(_colorize ${color}2 ${color}2)"
done

section "failure detection (must all FAIL)"
Expand Down