@bats-hardened/bats 1.14.1-alpha02
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE.md +53 -0
- package/README.md +135 -0
- package/bin/bats +75 -0
- package/install.sh +29 -0
- package/lib/bats-core/common.bash +278 -0
- package/lib/bats-core/formatter.bash +151 -0
- package/lib/bats-core/preprocessing.bash +19 -0
- package/lib/bats-core/semaphore.bash +113 -0
- package/lib/bats-core/test_functions.bash +539 -0
- package/lib/bats-core/tracing.bash +425 -0
- package/lib/bats-core/validator.bash +37 -0
- package/lib/bats-core/warnings.bash +44 -0
- package/libexec/bats-core/bats +555 -0
- package/libexec/bats-core/bats-exec-file +402 -0
- package/libexec/bats-core/bats-exec-suite +346 -0
- package/libexec/bats-core/bats-exec-test +383 -0
- package/libexec/bats-core/bats-format-cat +6 -0
- package/libexec/bats-core/bats-format-junit +293 -0
- package/libexec/bats-core/bats-format-pretty +360 -0
- package/libexec/bats-core/bats-format-tap +55 -0
- package/libexec/bats-core/bats-format-tap13 +89 -0
- package/libexec/bats-core/bats-gather-tests +402 -0
- package/libexec/bats-core/bats-preprocess +118 -0
- package/man/Makefile +23 -0
- package/man/README.md +5 -0
- package/man/bats.1 +143 -0
- package/man/bats.1.ronn +201 -0
- package/man/bats.7 +300 -0
- package/man/bats.7.ronn +404 -0
- package/package.json +36 -0
- package/uninstall.sh +63 -0
|
@@ -0,0 +1,346 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
set -e
|
|
3
|
+
|
|
4
|
+
count_only_flag=''
|
|
5
|
+
filter=''
|
|
6
|
+
nfilter=''
|
|
7
|
+
num_jobs=${BATS_NUMBER_OF_PARALLEL_JOBS:-1}
|
|
8
|
+
parallel_binary_name=${BATS_PARALLEL_BINARY_NAME:-"parallel"}
|
|
9
|
+
BATS_ABORT_ON_FAILURE=
|
|
10
|
+
bats_no_parallelize_across_files=${BATS_NO_PARALLELIZE_ACROSS_FILES-}
|
|
11
|
+
bats_no_parallelize_within_files=
|
|
12
|
+
filter_status=''
|
|
13
|
+
gather_tests_flags=('--dummy-flag')
|
|
14
|
+
flags=('--dummy-flag') # add a dummy flag to prevent unset variable errors on empty array expansion in old bash versions
|
|
15
|
+
setup_suite_file=''
|
|
16
|
+
BATS_TRACE_LEVEL="${BATS_TRACE_LEVEL:-0}"
|
|
17
|
+
BATS_SHOW_OUTPUT_OF_SUCCEEDING_TESTS=
|
|
18
|
+
if [[ -n "${BATS_ALLOW_EMPTY_SUITE:-}" ]]; then
|
|
19
|
+
BATS_EMPTY_SUITE_STATUS=0
|
|
20
|
+
else
|
|
21
|
+
BATS_EMPTY_SUITE_STATUS=1
|
|
22
|
+
fi
|
|
23
|
+
|
|
24
|
+
abort() {
|
|
25
|
+
printf 'Error: %s\n' "$1" >&2
|
|
26
|
+
exit 1
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
# shellcheck source=lib/bats-core/common.bash disable=SC2153
|
|
30
|
+
source "$BATS_ROOT/$BATS_LIBDIR/bats-core/common.bash"
|
|
31
|
+
|
|
32
|
+
while [[ "$#" -ne 0 ]]; do
|
|
33
|
+
case "$1" in
|
|
34
|
+
-c)
|
|
35
|
+
count_only_flag=1
|
|
36
|
+
;;
|
|
37
|
+
-f)
|
|
38
|
+
shift
|
|
39
|
+
filter="$1"
|
|
40
|
+
;;
|
|
41
|
+
-j)
|
|
42
|
+
shift
|
|
43
|
+
num_jobs="$1"
|
|
44
|
+
flags+=('-j' "$num_jobs")
|
|
45
|
+
;;
|
|
46
|
+
--parallel-binary-name)
|
|
47
|
+
shift
|
|
48
|
+
parallel_binary_name="$1"
|
|
49
|
+
;;
|
|
50
|
+
-T)
|
|
51
|
+
flags+=('-T')
|
|
52
|
+
;;
|
|
53
|
+
-x)
|
|
54
|
+
flags+=('-x')
|
|
55
|
+
;;
|
|
56
|
+
--abort)
|
|
57
|
+
flags+=('--abort')
|
|
58
|
+
BATS_ABORT_ON_FAILURE=1
|
|
59
|
+
;;
|
|
60
|
+
--no-parallelize-across-files)
|
|
61
|
+
bats_no_parallelize_across_files=1
|
|
62
|
+
;;
|
|
63
|
+
--no-parallelize-within-files)
|
|
64
|
+
bats_no_parallelize_within_files=1
|
|
65
|
+
flags+=("--no-parallelize-within-files")
|
|
66
|
+
;;
|
|
67
|
+
--filter-status)
|
|
68
|
+
shift
|
|
69
|
+
filter_status="$1"
|
|
70
|
+
;;
|
|
71
|
+
--filter-tags)
|
|
72
|
+
shift
|
|
73
|
+
gather_tests_flags+=("--filter-tags" "$1")
|
|
74
|
+
;;
|
|
75
|
+
--negative-filter)
|
|
76
|
+
shift
|
|
77
|
+
nfilter="$1"
|
|
78
|
+
;;
|
|
79
|
+
--dummy-flag) ;;
|
|
80
|
+
|
|
81
|
+
--trace)
|
|
82
|
+
flags+=('--trace')
|
|
83
|
+
((++BATS_TRACE_LEVEL)) # avoid returning 0
|
|
84
|
+
;;
|
|
85
|
+
--print-output-on-failure)
|
|
86
|
+
flags+=(--print-output-on-failure)
|
|
87
|
+
;;
|
|
88
|
+
--show-output-of-passing-tests)
|
|
89
|
+
flags+=(--show-output-of-passing-tests)
|
|
90
|
+
BATS_SHOW_OUTPUT_OF_SUCCEEDING_TESTS=1
|
|
91
|
+
;;
|
|
92
|
+
--verbose-run)
|
|
93
|
+
flags+=(--verbose-run)
|
|
94
|
+
;;
|
|
95
|
+
--gather-test-outputs-in)
|
|
96
|
+
shift
|
|
97
|
+
flags+=(--gather-test-outputs-in "$1")
|
|
98
|
+
;;
|
|
99
|
+
--setup-suite-file)
|
|
100
|
+
shift
|
|
101
|
+
setup_suite_file="$1"
|
|
102
|
+
;;
|
|
103
|
+
--allow-empty-suite)
|
|
104
|
+
BATS_EMPTY_SUITE_STATUS=0
|
|
105
|
+
;;
|
|
106
|
+
*)
|
|
107
|
+
break
|
|
108
|
+
;;
|
|
109
|
+
esac
|
|
110
|
+
shift
|
|
111
|
+
done
|
|
112
|
+
|
|
113
|
+
if [[ "$num_jobs" != 1 ]]; then
|
|
114
|
+
if ! type -p "${parallel_binary_name}" >/dev/null && "${parallel_binary_name}" --version &>/dev/null && [[ -z "$bats_no_parallelize_across_files" ]]; then
|
|
115
|
+
abort "Cannot execute \"${num_jobs}\" jobs without GNU parallel"
|
|
116
|
+
fi
|
|
117
|
+
# shellcheck source=lib/bats-core/semaphore.bash
|
|
118
|
+
source "${BATS_ROOT}/$BATS_LIBDIR/bats-core/semaphore.bash"
|
|
119
|
+
bats_semaphore_setup
|
|
120
|
+
fi
|
|
121
|
+
|
|
122
|
+
# create a file that contains all (filtered) tests to run from all files
|
|
123
|
+
TESTS_LIST_FILE="${BATS_RUN_TMPDIR}/test_list_file.txt"
|
|
124
|
+
|
|
125
|
+
TEST_ROOT=${1-}
|
|
126
|
+
TEST_ROOT=${TEST_ROOT%/*}
|
|
127
|
+
export BATS_RUN_LOGS_DIRECTORY="$TEST_ROOT/.bats/run-logs"
|
|
128
|
+
if [[ ! -d "$BATS_RUN_LOGS_DIRECTORY" ]]; then
|
|
129
|
+
if [[ -n "$filter_status" ]]; then
|
|
130
|
+
printf "Error: --filter-status needs '%s/' to save failed tests. Please create this folder, add it to .gitignore and try again.\n" "$BATS_RUN_LOGS_DIRECTORY"
|
|
131
|
+
exit 1
|
|
132
|
+
else
|
|
133
|
+
BATS_RUN_LOGS_DIRECTORY=
|
|
134
|
+
fi
|
|
135
|
+
# discard via sink instead of having a conditional later
|
|
136
|
+
export BATS_RUNLOG_FILE='/dev/null'
|
|
137
|
+
else
|
|
138
|
+
# use UTC (-u) to avoid problems with TZ changes
|
|
139
|
+
BATS_RUNLOG_DATE=$(date -u '+%Y-%m-%d %H:%M:%S UTC')
|
|
140
|
+
export BATS_RUNLOG_FILE="$BATS_RUN_LOGS_DIRECTORY/${BATS_RUNLOG_DATE}.log" BATS_RUNLOG_DATE
|
|
141
|
+
if [[ ! -w "$BATS_RUN_LOGS_DIRECTORY" ]]; then
|
|
142
|
+
printf "WARNING: Cannot write in %s. This run will not write a log!\n" "$BATS_RUN_LOGS_DIRECTORY" >&2
|
|
143
|
+
BATS_RUNLOG_FILE='/dev/null' # disable runlog file
|
|
144
|
+
fi
|
|
145
|
+
fi
|
|
146
|
+
|
|
147
|
+
# create file even if no tests are found so the `read` below won't fail
|
|
148
|
+
touch "$TESTS_LIST_FILE"
|
|
149
|
+
|
|
150
|
+
gather_tests_output=$(TESTS_LIST_FILE="$TESTS_LIST_FILE" filter="$filter" nfilter="$nfilter" filter_status="$filter_status" bats-gather-tests "${gather_tests_flags[@]}" -- "$@")
|
|
151
|
+
test_count=$(grep -c ^ "$TESTS_LIST_FILE" || true) # don't fail here when there are no tests
|
|
152
|
+
if [[ $gather_tests_output == focus_mode ]]; then
|
|
153
|
+
focus_mode=1
|
|
154
|
+
else
|
|
155
|
+
focus_mode=
|
|
156
|
+
fi
|
|
157
|
+
|
|
158
|
+
if [[ -n "$count_only_flag" ]]; then
|
|
159
|
+
printf '%d\n' "${test_count}"
|
|
160
|
+
# we don't want to pollute the runlog files, as no tests would have been run
|
|
161
|
+
[[ $BATS_RUNLOG_FILE != /dev/null ]] && rm "$BATS_RUNLOG_FILE"
|
|
162
|
+
exit 0
|
|
163
|
+
fi
|
|
164
|
+
|
|
165
|
+
if [[ -n "$bats_no_parallelize_across_files" ]] && [[ ! "$num_jobs" -gt 1 ]]; then
|
|
166
|
+
abort "The flag --no-parallelize-across-files requires at least --jobs 2"
|
|
167
|
+
fi
|
|
168
|
+
|
|
169
|
+
if [[ -n "$bats_no_parallelize_within_files" ]] && [[ ! "$num_jobs" -gt 1 ]]; then
|
|
170
|
+
abort "The flag --no-parallelize-across-files requires at least --jobs 2"
|
|
171
|
+
fi
|
|
172
|
+
|
|
173
|
+
# only abort on the lowest levels
|
|
174
|
+
trap 'BATS_INTERRUPTED=true' INT
|
|
175
|
+
|
|
176
|
+
if [[ -n "$focus_mode" ]]; then
|
|
177
|
+
printf "WARNING: This test run only contains tests tagged \`bats:focus\`!\n" >&2
|
|
178
|
+
fi
|
|
179
|
+
|
|
180
|
+
bats_exit_suite() {
|
|
181
|
+
if [[ "$focus_mode" == 1 && $bats_exec_suite_status -eq 0 ]]; then
|
|
182
|
+
if [[ ${BATS_NO_FAIL_FOCUS_RUN-} == 1 ]]; then
|
|
183
|
+
printf "WARNING: This test run only contains tests tagged \`bats:focus\`!\n" >&2
|
|
184
|
+
else
|
|
185
|
+
printf "Marking test run as failed due to \`bats:focus\` tag. (Set \`BATS_NO_FAIL_FOCUS_RUN=1\` to disable.)\n" >&2
|
|
186
|
+
bats_exec_suite_status=1
|
|
187
|
+
fi
|
|
188
|
+
fi
|
|
189
|
+
|
|
190
|
+
exit "$bats_exec_suite_status" # the actual exit code will be set by the exit trap using bats_exec_suite_status
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
bats_exec_suite_status=0
|
|
194
|
+
printf '1..%d\n' "${test_count}"
|
|
195
|
+
|
|
196
|
+
# No point on continuing if there's no tests.
|
|
197
|
+
if [[ "${test_count}" == 0 ]]; then
|
|
198
|
+
bats_exec_suite_status=$BATS_EMPTY_SUITE_STATUS
|
|
199
|
+
if (( bats_exec_suite_status != 0)); then
|
|
200
|
+
printf "ERROR: Found no tests. Use \`--allow-empty-suite\` or \`BATS_ALLOW_EMPTY_SUITE=1\` to suppress this error." >&2
|
|
201
|
+
fi
|
|
202
|
+
bats_exit_suite
|
|
203
|
+
fi
|
|
204
|
+
|
|
205
|
+
export BATS_SUITE_TMPDIR="${BATS_RUN_TMPDIR}/suite"
|
|
206
|
+
if ! mkdir "$BATS_SUITE_TMPDIR"; then
|
|
207
|
+
printf '%s\n' "Failed to create BATS_SUITE_TMPDIR" >&2
|
|
208
|
+
exit 1
|
|
209
|
+
fi
|
|
210
|
+
|
|
211
|
+
# Deduplicate filenames (without reordering) to avoid running duplicate tests n by n times.
|
|
212
|
+
# (see https://github.com/bats-core/bats-core/issues/329)
|
|
213
|
+
# If a file was specified multiple times, we already got it repeatedly in our TESTS_LIST_FILE.
|
|
214
|
+
# Thus, it suffices to bats-exec-file it once to run all repeated tests on it.
|
|
215
|
+
IFS=$'\n' read -d '' -r -a BATS_UNIQUE_TEST_FILENAMES < <(printf "%s\n" "$@" | nl | sort -k 2 | uniq -f 1 | sort -n | cut -f 2-) || true
|
|
216
|
+
|
|
217
|
+
# shellcheck source=lib/bats-core/tracing.bash
|
|
218
|
+
source "$BATS_ROOT/$BATS_LIBDIR/bats-core/tracing.bash"
|
|
219
|
+
bats_setup_tracing
|
|
220
|
+
|
|
221
|
+
trap bats_suite_exit_trap EXIT
|
|
222
|
+
|
|
223
|
+
exec 3<&1
|
|
224
|
+
|
|
225
|
+
# shellcheck disable=SC2317,SC2329
|
|
226
|
+
bats_suite_exit_trap() {
|
|
227
|
+
local print_bats_out="${BATS_SHOW_OUTPUT_OF_SUCCEEDING_TESTS}"
|
|
228
|
+
if [[ -z "${BATS_SETUP_SUITE_COMPLETED}" || -z "${BATS_TEARDOWN_SUITE_COMPLETED}" ]]; then
|
|
229
|
+
if [[ -z "${BATS_SETUP_SUITE_COMPLETED}" ]]; then
|
|
230
|
+
printf "not ok 1 setup_suite\n"
|
|
231
|
+
elif [[ -z "${BATS_TEARDOWN_SUITE_COMPLETED}" ]]; then
|
|
232
|
+
printf "not ok %d teardown_suite\n" $((test_count + 1))
|
|
233
|
+
fi
|
|
234
|
+
local stack_trace
|
|
235
|
+
bats_get_failure_stack_trace stack_trace
|
|
236
|
+
bats_print_stack_trace "${stack_trace[@]}"
|
|
237
|
+
bats_print_failed_command "${stack_trace[@]}"
|
|
238
|
+
print_bats_out=1
|
|
239
|
+
bats_exec_suite_status=1
|
|
240
|
+
fi
|
|
241
|
+
|
|
242
|
+
if [[ -n "$print_bats_out" ]]; then
|
|
243
|
+
bats_prefix_lines_for_tap_output <"$BATS_OUT"
|
|
244
|
+
fi
|
|
245
|
+
|
|
246
|
+
if [[ ${BATS_INTERRUPTED-NOTSET} != NOTSET ]]; then
|
|
247
|
+
printf "\n# Received SIGINT, aborting ...\n\n"
|
|
248
|
+
fi
|
|
249
|
+
|
|
250
|
+
if [[ -d "$BATS_RUN_LOGS_DIRECTORY" && -n "${BATS_INTERRUPTED:-}" ]]; then
|
|
251
|
+
# aborting a test run with CTRL+C does not save the runlog file
|
|
252
|
+
[[ "$BATS_RUNLOG_FILE" != /dev/null ]] && rm "$BATS_RUNLOG_FILE"
|
|
253
|
+
fi
|
|
254
|
+
exit "$bats_exec_suite_status"
|
|
255
|
+
} >&3
|
|
256
|
+
|
|
257
|
+
bats_run_teardown_suite() {
|
|
258
|
+
local bats_teardown_suite_status=0
|
|
259
|
+
# avoid being called twice, in case this is not called through bats_teardown_suite_trap
|
|
260
|
+
# but from the end of file
|
|
261
|
+
trap bats_suite_exit_trap EXIT
|
|
262
|
+
|
|
263
|
+
bats_set_stacktrace_limit
|
|
264
|
+
|
|
265
|
+
BATS_TEARDOWN_SUITE_COMPLETED=
|
|
266
|
+
teardown_suite >>"$BATS_OUT" 2>&1 || bats_teardown_suite_status=$?
|
|
267
|
+
if ((bats_teardown_suite_status == 0)); then
|
|
268
|
+
BATS_TEARDOWN_SUITE_COMPLETED=1
|
|
269
|
+
elif [[ -n "${BATS_SETUP_SUITE_COMPLETED:-}" ]]; then
|
|
270
|
+
# shellcheck disable=SC2034
|
|
271
|
+
BATS_DEBUG_LAST_STACK_TRACE_IS_VALID=1
|
|
272
|
+
BATS_ERROR_STATUS=$bats_teardown_suite_status
|
|
273
|
+
return $BATS_ERROR_STATUS
|
|
274
|
+
fi
|
|
275
|
+
}
|
|
276
|
+
|
|
277
|
+
# shellcheck disable=SC2317,SC2329
|
|
278
|
+
bats_teardown_suite_trap() {
|
|
279
|
+
bats_run_teardown_suite
|
|
280
|
+
bats_suite_exit_trap
|
|
281
|
+
}
|
|
282
|
+
|
|
283
|
+
teardown_suite() {
|
|
284
|
+
:
|
|
285
|
+
}
|
|
286
|
+
|
|
287
|
+
trap bats_teardown_suite_trap EXIT
|
|
288
|
+
|
|
289
|
+
BATS_OUT="$BATS_RUN_TMPDIR/suite.out"
|
|
290
|
+
if [[ -n "$setup_suite_file" ]]; then
|
|
291
|
+
setup_suite() {
|
|
292
|
+
printf "%s does not define \`setup_suite()\`\n" "$setup_suite_file" >&2
|
|
293
|
+
return 1
|
|
294
|
+
}
|
|
295
|
+
|
|
296
|
+
# shellcheck disable=SC2034 # will be used in the sourced file below
|
|
297
|
+
BATS_TEST_FILENAME="$setup_suite_file"
|
|
298
|
+
# shellcheck source=lib/bats-core/test_functions.bash
|
|
299
|
+
source "$BATS_ROOT/$BATS_LIBDIR/bats-core/test_functions.bash"
|
|
300
|
+
_bats_test_functions_setup -1 # invalid TEST_NUMBER, as this is not a test
|
|
301
|
+
|
|
302
|
+
# shellcheck disable=SC1090
|
|
303
|
+
source "$setup_suite_file"
|
|
304
|
+
|
|
305
|
+
bats_set_stacktrace_limit
|
|
306
|
+
|
|
307
|
+
set -eET
|
|
308
|
+
export BATS_SETUP_SUITE_COMPLETED=
|
|
309
|
+
setup_suite >>"$BATS_OUT" 2>&1
|
|
310
|
+
BATS_SETUP_SUITE_COMPLETED=1
|
|
311
|
+
set +ET
|
|
312
|
+
else
|
|
313
|
+
# prevent exit trap from printing an error because of incomplete setup_suite,
|
|
314
|
+
# when there was none to execute
|
|
315
|
+
BATS_SETUP_SUITE_COMPLETED=1
|
|
316
|
+
fi
|
|
317
|
+
|
|
318
|
+
if [[ "$num_jobs" -gt 1 ]] && [[ -z "$bats_no_parallelize_across_files" ]]; then
|
|
319
|
+
parallel_flags=(--keep-order --jobs "$num_jobs")
|
|
320
|
+
if (( BATS_ABORT_ON_FAILURE )); then
|
|
321
|
+
parallel_flags+=('--halt' 'now,fail=1')
|
|
322
|
+
fi
|
|
323
|
+
# run files in parallel to get the maximum pool of parallel tasks
|
|
324
|
+
# shellcheck disable=SC2086,SC2068
|
|
325
|
+
# we need to handle the quoting of ${flags[@]} ourselves,
|
|
326
|
+
# because parallel can only quote it as one
|
|
327
|
+
"${parallel_binary_name}" "${parallel_flags[@]}" -- "bats-exec-file" "$(printf "%q " "${flags[@]}")" "{#}" "{}" "$TESTS_LIST_FILE" <<< "$(printf "%s\n" "${BATS_UNIQUE_TEST_FILENAMES[@]}")" 2>&1 || bats_exec_suite_status=1
|
|
328
|
+
else
|
|
329
|
+
file_index=0
|
|
330
|
+
for filename in "${BATS_UNIQUE_TEST_FILENAMES[@]}"; do
|
|
331
|
+
(( ++file_index ))
|
|
332
|
+
if [[ "${BATS_INTERRUPTED-NOTSET}" != NOTSET ]]; then
|
|
333
|
+
bats_exec_suite_status=130 # bash's code for SIGINT exits
|
|
334
|
+
break
|
|
335
|
+
fi
|
|
336
|
+
bats-exec-file "${flags[@]}" "$file_index" "$filename" "${TESTS_LIST_FILE}" || bats_exec_suite_status=1
|
|
337
|
+
if (( BATS_ABORT_ON_FAILURE && bats_exec_suite_status > 0 )); then
|
|
338
|
+
break
|
|
339
|
+
fi
|
|
340
|
+
done
|
|
341
|
+
fi
|
|
342
|
+
|
|
343
|
+
set -eET
|
|
344
|
+
bats_run_teardown_suite
|
|
345
|
+
|
|
346
|
+
bats_exit_suite
|