blob: 1da470b119150c7de67a81706a1f5bb399a87ee3 (
plain) (
blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
|
. "${CLOYSTER_SCRIPT_ROOT}/lib/test/output.sh"
cloyster_test_varname() {
if [ -n "${1}" ]; then echo "_cloyster_test_${1}"; else echo "_cloyster_test"; fi
}
cloyster_test_init() {
export _cloyster_test_tests_counter_count=0
export _cloyster_test_tests_counter_success=0
export _cloyster_test_tests_counter_skipped=0
export _cloyster_test_tests_counter_failed=0
export _cloyster_test_tests_counter_ignored=0
export _cloyster_test_tests_failed=
export _cloyster_test_tests_skipped=
export _cloyster_test_tests_success=
export _cloyster_test_tests_ignored=
export _cloyster_test_tests=
export _cloyster_test_groups=
export _cloyster_test_init=y
}
cloyster_test_add_shellcheck() {
ignore=
if ! command -v shellcheck >/dev/null; then ign=".ignore:SHELLCHECK_REQUIRED"; fi
_cloyster__test__shellcheck() {
shellcheck -e SC1008,SC2239 "${CLOYSTER_COMMAND_FILE}"
}
cloyster_test_add -a shellcheck shellcheck "_cloyster__test__shellcheck" "${ignore}"
}
cloyster_test_add() {
append=
while getopts :a _opt; do case "${_opt}" in
a) append=y;;
esac; done; shift $((OPTIND - 1))
id=$1
name=$2
fun=$3
args=$4
if [ -z "${id}" ]; then return 1; fi
if [ -z "${name}" ]; then return 1; fi
list=$(cloyster_test_varname "tests")
var=$(cloyster_test_varname "tests_${id}")
if [ -n "$(readvar "$var")" ]; then
echo "ERROR: A test '${id}' has already been defined"
return 1
fi
if is_true "${append}"; then _cloyster_test_tests="${name} ${_cloyster_test_tests}"; else _cloyster_test_tests="${_cloyster_test_tests} ${name}"; fi
setvar "${var}" "${var}"
setvar "${var}__name" "${name}"
setvar "${var}__fun" "${fun}"
setvar "${var}__args" "${args}"
}
cloyster_test_run() {
cloyster_test_log "${_green}${_bold}⚡⚡⚡ Running cloyster tests for ${_bold}${_yellow}${CLOYSTER_COMMAND}${_rst} ⚡⚡⚡"
cloyster_test_log "${_darkgray} (did you knew that #!/bin/sh is twenty years older than emojis ?)${_rst}\n"
cloyster_test_add_shellcheck #|| s=$?; _error "Failed to lol $s"; exit 1
incr() {
var="_cloyster_test_tests_counter_${1}"
val=$(($(readvar "$var") + 1))
setvar "$var" "$val"
}
_echo_block_init
all_start_us=$(posix_time_microseconds)
for id in ${_cloyster_test_tests}; do
incr "count"
name=$(readvar "_cloyster_test_tests_${id}__name")
args=$(readvar "_cloyster_test_tests_${id}__args")
line=$(readvar "_cloyster_test_tests_${id}__line")
fun=$(readvar "_cloyster_test_tests_${id}__fun")
fun="${fun:-"_test_${id}"}"
testlog="${_tmp_dir}/test_${id}.log"
_debug "Running test '${name}' line=${line} fun=${fun} args=${args}"
refute=; skip=; tags=; status=; precond_status=; ignore=; fatal=;
skip_reason=; ignore_reason= fatal_reason=
for arg in $args; do
tag=$(echo "$arg" | cut -d ":" -f 1)
targ=$(echo "$arg" | sed "s/^${tag}://g")
case $tag in
.refute) refute=y;;
.skip) skip=y; skip_reason=${targ:-.skip};;
.ignore) ignore=y; ignore_reason=${targ:-.ignore};;
.fatal) fatal=y; fatal_reason=${targ:-.fatal};;
.tag) if [ -n "${targ}" ]; then tags="${tags} ${targ}"; fi;;
*) ;;
esac
done
## -- Preconditions
if [ ! "$skip" = "y" ]; then
(
preconds=$(
for arg in $args; do
cond=$(echo "$arg" | cut -d ":" -f 2,100)
case $arg in
.if:*) if $($cond); then miss=y; break; fi;;
.not:*) if ! $($cond); then miss=y; break; fi;;
*) ;;
esac
done
if [ "${miss}" = "y" ]; then
echo "$(tput AF 105)Precondition failed: ${arg}" >> "${testlog}"
exit 2
fi
)
precond_status=$?
exit $precond_status
) 2>> "${testlog}" >> "${testlog}"
precond_status=$?
else
echo "$(tput AF 105)${skip_reason}" >> "${testlog}"
fi
# -- TEST SUBSHELL
if [ "${precond_status}" = "0" ] && [ ! "${skip}" = "y" ]; then
(
. "${CLOYSTER_SCRIPT_ROOT}/lib/test/asserts.sh"
_assert_reset_count
start_us=$(posix_time_microseconds)
(
"$fun"
s=$?
asserts=$(_assert_count)
if [ ! "${asserts}" = "0" ]; then echo "☀️ Passed ${asserts} assertions."; fi
exit $s
)
status=$?
end_us=$(posix_time_microseconds)
duration=$(bc -e "$end_us - $start_us")
if is_true "$refute" && [ "${status}" = "0" ]; then echo "⚠️ Exited with code ${_bold}${status}${_rst} (refuting, expected >0)"; fi
if is_true "$refute" && [ ! "${status}" = "0" ]; then echo "🌗 Exited with code ${status} (refuting)"; fi
if ! is_true "$refute" && [ ! "${status}" = "0" ]; then echo "⚠️ Exited with code ${_bold}${status}${_rst} (expected 0)"; fi
echo "$(tput AF 59)Ran in ${duration}ms${_rst}"
exit $status
) 2>> "${testlog}" >> "${testlog}"
status=$?
fi
## -- TEST FINISHED
cmpstatus="$status"
if is_true "$refute"; then
if [ "$status" = "0" ]; then cmpstatus=1; else cmpstatus=0; fi
fi
if [ "$precond_status" = "0" ] && [ "$cmpstatus" = "0" ]; then
_echo_block success
_cloyster_test_tests_success="${_cloyster_test_tests_success}${id} "
incr "success"
elif [ "$precond_status" = "2" ] || [ "$skip" = "y" ]; then
_echo_block skipped
_cloyster_test_tests_skipped="${_cloyster_test_tests_skipped} ${id}"
incr "skipped"
else
if [ ! "$precond_status" = "0" ]; then
err="precondition_error:${precond_status}"
else
err="${status}"
fi
_action=failed
if is_true "${ignore}"; then _action="ignored"; fi
_echo_block "${_action}"
setvar "_cloyster_test_tests_${id}__status" "$err"
setvar "_cloyster_test_tests_${id}__ignore" "$ignore"
setvar "_cloyster_test_tests_${_action}" "$(readvar "_cloyster_test_tests_${_action}") ${id}"
incr "${_action}"
fi
done
_echo_block_flush
all_end_us=$(posix_time_microseconds)
duration=$(bc -e "$all_end_us - $all_start_us")
_test_output_results
echo ""
_test_output_overview
}
|