@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
package/LICENSE.md
ADDED
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
Copyright (c) 2017 bats-core contributors
|
|
2
|
+
|
|
3
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
|
4
|
+
a copy of this software and associated documentation files (the
|
|
5
|
+
"Software"), to deal in the Software without restriction, including
|
|
6
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
|
7
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
|
8
|
+
permit persons to whom the Software is furnished to do so, subject to
|
|
9
|
+
the following conditions:
|
|
10
|
+
|
|
11
|
+
The above copyright notice and this permission notice shall be
|
|
12
|
+
included in all copies or substantial portions of the Software.
|
|
13
|
+
|
|
14
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
|
15
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
|
16
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
|
17
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
|
18
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
|
19
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
|
20
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|
21
|
+
|
|
22
|
+
---
|
|
23
|
+
|
|
24
|
+
* [bats-core] is a continuation of [bats]. Copyright for portions of the
|
|
25
|
+
bats-core project are held by Sam Stephenson, 2014 as part of the project
|
|
26
|
+
[bats], licensed under MIT:
|
|
27
|
+
|
|
28
|
+
Copyright (c) 2014 Sam Stephenson
|
|
29
|
+
|
|
30
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
|
31
|
+
a copy of this software and associated documentation files (the
|
|
32
|
+
"Software"), to deal in the Software without restriction, including
|
|
33
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
|
34
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
|
35
|
+
permit persons to whom the Software is furnished to do so, subject to
|
|
36
|
+
the following conditions:
|
|
37
|
+
|
|
38
|
+
The above copyright notice and this permission notice shall be
|
|
39
|
+
included in all copies or substantial portions of the Software.
|
|
40
|
+
|
|
41
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
|
42
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
|
43
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
|
44
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
|
45
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
|
46
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
|
47
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|
48
|
+
|
|
49
|
+
For details, please see the [version control history][commits].
|
|
50
|
+
|
|
51
|
+
[bats-core]: https://github.com/bats-core/bats-core
|
|
52
|
+
[bats]:https://github.com/sstephenson/bats
|
|
53
|
+
[commits]:https://github.com/bats-core/bats-core/commits/master
|
package/README.md
ADDED
|
@@ -0,0 +1,135 @@
|
|
|
1
|
+
[](https://github.com/bats-core/bats-core/releases/latest)
|
|
2
|
+
[](https://www.npmjs.com/package/bats)
|
|
3
|
+
[](https://github.com/bats-core/bats-core/blob/master/LICENSE.md)
|
|
4
|
+
[](https://github.com/bats-core/bats-core/actions?query=workflow%3ATests)
|
|
5
|
+
[](https://bats-core.readthedocs.io)
|
|
6
|
+
|
|
7
|
+
[][gitter]
|
|
8
|
+
|
|
9
|
+
<div align="center">
|
|
10
|
+
<picture>
|
|
11
|
+
<source media="(prefers-color-scheme: dark)" srcset="docs/source/assets/dark_mode_cube.svg">
|
|
12
|
+
<img alt="" src="docs/source/assets/light_mode_cube.svg">
|
|
13
|
+
</picture>
|
|
14
|
+
</div>
|
|
15
|
+
|
|
16
|
+
# Bats-core: Bash Automated Testing System
|
|
17
|
+
|
|
18
|
+
Bats is a [TAP](https://testanything.org/)-compliant testing framework for Bash
|
|
19
|
+
3.2 or above. It provides a simple way to verify that the UNIX programs you
|
|
20
|
+
write behave as expected.
|
|
21
|
+
|
|
22
|
+
A Bats test file is a Bash script with special syntax for defining test cases.
|
|
23
|
+
Under the hood, each test case is just a function with a description.
|
|
24
|
+
|
|
25
|
+
```bash
|
|
26
|
+
#!/usr/bin/env bats
|
|
27
|
+
|
|
28
|
+
@test "addition using bc" {
|
|
29
|
+
result="$(echo 2+2 | bc)"
|
|
30
|
+
[ "$result" -eq 4 ]
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
@test "addition using dc" {
|
|
34
|
+
result="$(echo 2 2+p | dc)"
|
|
35
|
+
[ "$result" -eq 4 ]
|
|
36
|
+
}
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
Bats is most useful when testing software written in Bash, but you can use it to
|
|
40
|
+
test any UNIX program.
|
|
41
|
+
|
|
42
|
+
Test cases consist of standard shell commands. Bats makes use of Bash's
|
|
43
|
+
`errexit` (`set -e`) option when running test cases. If every command in the
|
|
44
|
+
test case exits with a `0` status code (success), the test passes. In this way,
|
|
45
|
+
each line is an assertion of truth.
|
|
46
|
+
|
|
47
|
+
## Table of contents
|
|
48
|
+
|
|
49
|
+
**NOTE** The documentation has moved to <https://bats-core.readthedocs.io>
|
|
50
|
+
|
|
51
|
+
<!-- toc -->
|
|
52
|
+
|
|
53
|
+
- [Testing](#testing)
|
|
54
|
+
- [Support](#support)
|
|
55
|
+
- [Contributing](#contributing)
|
|
56
|
+
- [Contact](#contact)
|
|
57
|
+
- [Version history](#version-history)
|
|
58
|
+
- [Background](#background)
|
|
59
|
+
* [What's the plan and why?](#whats-the-plan-and-why)
|
|
60
|
+
* [Why was this fork created?](#why-was-this-fork-created)
|
|
61
|
+
- [Copyright](#copyright)
|
|
62
|
+
|
|
63
|
+
<!-- tocstop -->
|
|
64
|
+
|
|
65
|
+
## Testing
|
|
66
|
+
|
|
67
|
+
```sh
|
|
68
|
+
bin/bats --tap test
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
See also the [CI](./.github/workflows/tests.yml) settings for the current test environment and
|
|
72
|
+
scripts.
|
|
73
|
+
|
|
74
|
+
## Support
|
|
75
|
+
|
|
76
|
+
The Bats source code repository is [hosted on
|
|
77
|
+
GitHub](https://github.com/bats-core/bats-core). There you can file bugs on the
|
|
78
|
+
issue tracker or submit tested pull requests for review.
|
|
79
|
+
|
|
80
|
+
For real-world examples from open-source projects using Bats, see [Projects
|
|
81
|
+
Using Bats](https://github.com/bats-core/bats-core/wiki/Projects-Using-Bats) on
|
|
82
|
+
the wiki.
|
|
83
|
+
|
|
84
|
+
To learn how to set up your editor for Bats syntax highlighting, see [Syntax
|
|
85
|
+
Highlighting](https://github.com/bats-core/bats-core/wiki/Syntax-Highlighting)
|
|
86
|
+
on the wiki.
|
|
87
|
+
|
|
88
|
+
## Contributing
|
|
89
|
+
|
|
90
|
+
For now see the [`docs`](docs) folder for project guides, work with us on the wiki
|
|
91
|
+
or look at the other communication channels.
|
|
92
|
+
|
|
93
|
+
## Contact
|
|
94
|
+
|
|
95
|
+
- You can find and chat with us on our [Gitter].
|
|
96
|
+
|
|
97
|
+
## Version history
|
|
98
|
+
|
|
99
|
+
See `docs/CHANGELOG.md`.
|
|
100
|
+
|
|
101
|
+
## Background
|
|
102
|
+
|
|
103
|
+
<!-- markdownlint-disable MD026 -->
|
|
104
|
+
### Why was this fork created?
|
|
105
|
+
<!-- markdownlint-enable MD026 -->
|
|
106
|
+
|
|
107
|
+
There was an initial [call for maintainers][call-maintain] for the original Bats repository, but write access to it could not be obtained. With development activity stalled, this fork allowed ongoing maintenance and forward progress for Bats.
|
|
108
|
+
|
|
109
|
+
**Tuesday, September 19, 2017:** This was forked from [Bats][bats-orig] at
|
|
110
|
+
commit [0360811][]. It was created via `git clone --bare` and `git push
|
|
111
|
+
--mirror`.
|
|
112
|
+
|
|
113
|
+
As of **Thursday, April 29, 2021:** the original [Bats][bats-orig] has been
|
|
114
|
+
archived by the owner and is now read-only.
|
|
115
|
+
|
|
116
|
+
This [bats-core](https://github.com/bats-core/bats-core) repo is now the community-maintained Bats project.
|
|
117
|
+
|
|
118
|
+
[call-maintain]: https://github.com/sstephenson/bats/issues/150
|
|
119
|
+
[bats-orig]: https://github.com/sstephenson/bats
|
|
120
|
+
[0360811]: https://github.com/sstephenson/bats/commit/03608115df2071fff4eaaff1605768c275e5f81f
|
|
121
|
+
|
|
122
|
+
## Copyright
|
|
123
|
+
|
|
124
|
+
The Bats Logo was created by [Vukory](https://www.artstation.com/vukory) ([Github](https://github.com/vukory)) and sponsored by [SethFalco](https://github.com/SethFalco). If you want to use our logo, have a look at our [guidelines](./docs/source/assets/README.md#Usage-Guide-for-Third-Parties).
|
|
125
|
+
|
|
126
|
+
© 2017-2024 bats-core organization
|
|
127
|
+
|
|
128
|
+
© 2011-2016 Sam Stephenson
|
|
129
|
+
|
|
130
|
+
Bats is released under an MIT-style license; see `LICENSE.md` for details.
|
|
131
|
+
|
|
132
|
+
See the [parent project](https://github.com/bats-core) at GitHub or the
|
|
133
|
+
[AUTHORS](AUTHORS) file for the current project maintainer team.
|
|
134
|
+
|
|
135
|
+
[gitter]: https://gitter.im/bats-core/bats-core
|
package/bin/bats
ADDED
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
|
|
3
|
+
set -euo pipefail
|
|
4
|
+
|
|
5
|
+
# Note: We first need to use POSIX's `[ ... ]' instead of Bash's `[[ ... ]]'
|
|
6
|
+
# because this is the check for Bash, where the shell may not be Bash. Once we
|
|
7
|
+
# confirm that we are in Bash, we can use [[ ... ]] and (( ... )). Note that
|
|
8
|
+
# these [[ ... ]] and (( ... )) do not cause syntax errors in POSIX shells,
|
|
9
|
+
# though they can be parsed differently.
|
|
10
|
+
if [ -z "${BASH_VERSION-}" ] ||
|
|
11
|
+
[[ -z "${BASH_VERSINFO-}" ]] ||
|
|
12
|
+
((BASH_VERSINFO[0] < 3 || (BASH_VERSINFO[0] == 3 && BASH_VERSINFO[1] < 2)))
|
|
13
|
+
then
|
|
14
|
+
printf 'bats: this program needs to be run by Bash >= 3.2\n' >&2
|
|
15
|
+
exit 1
|
|
16
|
+
fi
|
|
17
|
+
|
|
18
|
+
if command -v greadlink >/dev/null; then
|
|
19
|
+
bats_readlinkf() {
|
|
20
|
+
greadlink -f "$1"
|
|
21
|
+
}
|
|
22
|
+
else
|
|
23
|
+
bats_readlinkf() {
|
|
24
|
+
readlink -f "$1"
|
|
25
|
+
}
|
|
26
|
+
fi
|
|
27
|
+
|
|
28
|
+
fallback_to_readlinkf_posix() {
|
|
29
|
+
bats_readlinkf() {
|
|
30
|
+
[ "${1:-}" ] || return 1
|
|
31
|
+
max_symlinks=40
|
|
32
|
+
CDPATH='' # to avoid changing to an unexpected directory
|
|
33
|
+
|
|
34
|
+
target=$1
|
|
35
|
+
[ -e "${target%/}" ] || target=${1%"${1##*[!/]}"} # trim trailing slashes
|
|
36
|
+
[ -d "${target:-/}" ] && target="$target/"
|
|
37
|
+
|
|
38
|
+
cd -P . 2>/dev/null || return 1
|
|
39
|
+
while [ "$max_symlinks" -ge 0 ] && max_symlinks=$((max_symlinks - 1)); do
|
|
40
|
+
if [ ! "$target" = "${target%/*}" ]; then
|
|
41
|
+
case $target in
|
|
42
|
+
/*) cd -P "${target%/*}/" 2>/dev/null || break ;;
|
|
43
|
+
*) cd -P "./${target%/*}" 2>/dev/null || break ;;
|
|
44
|
+
esac
|
|
45
|
+
target=${target##*/}
|
|
46
|
+
fi
|
|
47
|
+
|
|
48
|
+
if [ ! -L "$target" ]; then
|
|
49
|
+
target="${PWD%/}${target:+/}${target}"
|
|
50
|
+
printf '%s\n' "${target:-/}"
|
|
51
|
+
return 0
|
|
52
|
+
fi
|
|
53
|
+
|
|
54
|
+
# `ls -dl` format: "%s %u %s %s %u %s %s -> %s\n",
|
|
55
|
+
# <file mode>, <number of links>, <owner name>, <group name>,
|
|
56
|
+
# <size>, <date and time>, <pathname of link>, <contents of link>
|
|
57
|
+
# https://pubs.opengroup.org/onlinepubs/9699919799/utilities/ls.html
|
|
58
|
+
link=$(ls -dl -- "$target" 2>/dev/null) || break
|
|
59
|
+
target=${link#*" $target -> "}
|
|
60
|
+
done
|
|
61
|
+
return 1
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
if ! BATS_PATH=$(bats_readlinkf "${BASH_SOURCE[0]}" 2>/dev/null); then
|
|
66
|
+
fallback_to_readlinkf_posix
|
|
67
|
+
BATS_PATH=$(bats_readlinkf "${BASH_SOURCE[0]}")
|
|
68
|
+
fi
|
|
69
|
+
|
|
70
|
+
export BATS_SAVED_PATH=$PATH
|
|
71
|
+
BATS_BASE_LIBDIR=lib # this will be patched with the true value in install.sh
|
|
72
|
+
|
|
73
|
+
export BATS_ROOT=${BATS_PATH%/*/*}
|
|
74
|
+
export -f bats_readlinkf
|
|
75
|
+
exec env BATS_ROOT="$BATS_ROOT" BATS_LIBDIR="${BATS_BASE_LIBDIR:-lib}" "$BATS_ROOT/libexec/bats-core/bats" "$@"
|
package/install.sh
ADDED
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
|
|
3
|
+
set -e
|
|
4
|
+
|
|
5
|
+
BATS_ROOT="${0%/*}"
|
|
6
|
+
PREFIX="${1%/}"
|
|
7
|
+
LIBDIR="${2:-lib}"
|
|
8
|
+
|
|
9
|
+
if [[ -z "$PREFIX" ]]; then
|
|
10
|
+
printf '%s\n' \
|
|
11
|
+
"usage: $0 <prefix> [base_libdir]" \
|
|
12
|
+
" e.g. $0 /usr/local" \
|
|
13
|
+
" $0 /usr/local lib64" >&2
|
|
14
|
+
exit 1
|
|
15
|
+
fi
|
|
16
|
+
|
|
17
|
+
install -d -m 755 "$PREFIX"/{bin,libexec/bats-core,"${LIBDIR}"/bats-core,share/man/man{1,7}}
|
|
18
|
+
|
|
19
|
+
install -m 755 "$BATS_ROOT/bin"/* "$PREFIX/bin"
|
|
20
|
+
install -m 755 "$BATS_ROOT/libexec/bats-core"/* "$PREFIX/libexec/bats-core"
|
|
21
|
+
install -m 755 "$BATS_ROOT/lib/bats-core"/* "$PREFIX/${LIBDIR}/bats-core"
|
|
22
|
+
install -m 644 "$BATS_ROOT/man/bats.1" "$PREFIX/share/man/man1"
|
|
23
|
+
install -m 644 "$BATS_ROOT/man/bats.7" "$PREFIX/share/man/man7"
|
|
24
|
+
|
|
25
|
+
read -rd '' BATS_EXE_CONTENTS <"$PREFIX/bin/bats" || true
|
|
26
|
+
BATS_EXE_CONTENTS=${BATS_EXE_CONTENTS/"BATS_BASE_LIBDIR=lib"/"BATS_BASE_LIBDIR=${LIBDIR}"}
|
|
27
|
+
printf "%s" "$BATS_EXE_CONTENTS" >| "$PREFIX/bin/bats"
|
|
28
|
+
|
|
29
|
+
echo "Installed Bats to $PREFIX/bin/bats"
|
|
@@ -0,0 +1,278 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
|
|
3
|
+
bats_prefix_lines_for_tap_output() {
|
|
4
|
+
while IFS= read -r line; do
|
|
5
|
+
printf '# %s\n' "$line" || break # avoid feedback loop when errors are redirected into BATS_OUT (see #353)
|
|
6
|
+
done
|
|
7
|
+
if [[ -n "$line" ]]; then
|
|
8
|
+
printf '# %s\n' "$line"
|
|
9
|
+
fi
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
function bats_replace_filename() {
|
|
13
|
+
local line
|
|
14
|
+
while read -r line; do
|
|
15
|
+
printf "%s\n" "${line//$BATS_TEST_SOURCE/$BATS_TEST_FILENAME}"
|
|
16
|
+
done
|
|
17
|
+
if [[ -n "$line" ]]; then
|
|
18
|
+
printf "%s\n" "${line//$BATS_TEST_SOURCE/$BATS_TEST_FILENAME}"
|
|
19
|
+
fi
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
bats_quote_code() { # <var> <code>
|
|
23
|
+
printf -v "$1" -- "%s%s%s" "$BATS_BEGIN_CODE_QUOTE" "$2" "$BATS_END_CODE_QUOTE"
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
bats_check_valid_version() {
|
|
27
|
+
if [[ ! $1 =~ [0-9]+.[0-9]+.[0-9]+ ]]; then
|
|
28
|
+
printf "ERROR: version '%s' must be of format <major>.<minor>.<patch>!\n" "$1" >&2
|
|
29
|
+
exit 1
|
|
30
|
+
fi
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
# compares two versions. Return 0 when version1 < version2
|
|
34
|
+
bats_version_lt() { # <version1> <version2>
|
|
35
|
+
bats_check_valid_version "$1"
|
|
36
|
+
bats_check_valid_version "$2"
|
|
37
|
+
|
|
38
|
+
local -a version1_parts version2_parts
|
|
39
|
+
IFS=. read -ra version1_parts <<<"$1"
|
|
40
|
+
IFS=. read -ra version2_parts <<<"$2"
|
|
41
|
+
|
|
42
|
+
local -i i
|
|
43
|
+
for i in {0..2}; do
|
|
44
|
+
if ((version1_parts[i] < version2_parts[i])); then
|
|
45
|
+
return 0
|
|
46
|
+
elif ((version1_parts[i] > version2_parts[i])); then
|
|
47
|
+
return 1
|
|
48
|
+
fi
|
|
49
|
+
done
|
|
50
|
+
# if we made it this far, they are equal -> also not less then
|
|
51
|
+
return 2 # use other failing return code to distinguish equal from gt
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
# ensure a minimum version of bats is running or exit with failure
|
|
55
|
+
bats_require_minimum_version() { # <required version>
|
|
56
|
+
local required_minimum_version=$1
|
|
57
|
+
|
|
58
|
+
if bats_version_lt "$BATS_VERSION" "$required_minimum_version"; then
|
|
59
|
+
printf "BATS_VERSION=%s does not meet required minimum %s\n" "$BATS_VERSION" "$required_minimum_version"
|
|
60
|
+
exit 1
|
|
61
|
+
fi
|
|
62
|
+
|
|
63
|
+
if bats_version_lt "$BATS_GUARANTEED_MINIMUM_VERSION" "$required_minimum_version"; then
|
|
64
|
+
BATS_GUARANTEED_MINIMUM_VERSION="$required_minimum_version"
|
|
65
|
+
fi
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
# returns 0 when search-value is found in array
|
|
69
|
+
bats_linear_reverse_search() { # <search-value> <array-name>
|
|
70
|
+
local -r search_value=$1 array_name=$2
|
|
71
|
+
eval "local -ri array_length=\${#${array_name}[@]}"
|
|
72
|
+
# shellcheck disable=SC2154
|
|
73
|
+
for ((i=array_length - 1; i >=0; --i)); do
|
|
74
|
+
eval "local value=\"\${${array_name}[i]}\""
|
|
75
|
+
# shellcheck disable=SC2154
|
|
76
|
+
if [[ $value == "$search_value" ]]; then
|
|
77
|
+
return 0
|
|
78
|
+
fi
|
|
79
|
+
done
|
|
80
|
+
return 1
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
# returns 0 when search-value is found in array
|
|
84
|
+
bats_binary_search() { # <search-value> <array-name>
|
|
85
|
+
if [[ $# -ne 2 ]]; then
|
|
86
|
+
printf "ERROR: bats_binary_search requires exactly 2 arguments: <search value> <array name>\n" >&2
|
|
87
|
+
return 2
|
|
88
|
+
fi
|
|
89
|
+
|
|
90
|
+
local -r search_value=$1 array_name=$2
|
|
91
|
+
|
|
92
|
+
# we'd like to test if array is set but we cannot distinguish unset from empty arrays, so we need to skip that
|
|
93
|
+
|
|
94
|
+
local start=0 mid end mid_value
|
|
95
|
+
# start is inclusive, end is exclusive ...
|
|
96
|
+
eval "end=\${#${array_name}[@]}"
|
|
97
|
+
|
|
98
|
+
# so start == end means empty search space
|
|
99
|
+
while ((start < end)); do
|
|
100
|
+
mid=$(((start + end) / 2))
|
|
101
|
+
eval "mid_value=\${${array_name}[$mid]}"
|
|
102
|
+
if [[ "$mid_value" == "$search_value" ]]; then
|
|
103
|
+
return 0
|
|
104
|
+
elif [[ "$mid_value" < "$search_value" ]]; then
|
|
105
|
+
# This branch excludes equality -> +1 to skip the mid element.
|
|
106
|
+
# This +1 also avoids endless recursion on odd sized search ranges.
|
|
107
|
+
start=$((mid + 1))
|
|
108
|
+
else
|
|
109
|
+
end=$mid
|
|
110
|
+
fi
|
|
111
|
+
done
|
|
112
|
+
|
|
113
|
+
# did not find it -> its not there
|
|
114
|
+
return 1
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
# store the values in ascending (string!) order in result array
|
|
118
|
+
# Intended for short lists! (uses insertion sort)
|
|
119
|
+
bats_sort() { # <result-array-name> <values to sort...>
|
|
120
|
+
local -r result_name=$1
|
|
121
|
+
shift
|
|
122
|
+
|
|
123
|
+
if (($# == 1)) && [[ $1 == "" ]]; then
|
|
124
|
+
shift # remove leading "" to deal with bash 3 expanding "${empty_array[@]}" to one ""
|
|
125
|
+
fi
|
|
126
|
+
|
|
127
|
+
if (($# == 0)); then
|
|
128
|
+
eval "$result_name=()"
|
|
129
|
+
return 0
|
|
130
|
+
fi
|
|
131
|
+
|
|
132
|
+
local -a sorted_array=()
|
|
133
|
+
local -i i
|
|
134
|
+
while (( $# > 0 )); do # loop over input values
|
|
135
|
+
local current_value="$1"
|
|
136
|
+
shift
|
|
137
|
+
for ((i = ${#sorted_array[@]}; i >= 0; --i)); do # loop over output array from end
|
|
138
|
+
if (( i == 0 )) || [[ ${sorted_array[i - 1]} < $current_value ]]; then
|
|
139
|
+
# insert new element at (freed) desired location
|
|
140
|
+
sorted_array[i]=$current_value
|
|
141
|
+
break
|
|
142
|
+
else
|
|
143
|
+
# shift bigger elements one position to the end
|
|
144
|
+
sorted_array[i]=${sorted_array[i - 1]}
|
|
145
|
+
fi
|
|
146
|
+
done
|
|
147
|
+
done
|
|
148
|
+
|
|
149
|
+
eval "$result_name=(\"\${sorted_array[@]}\")"
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
# check if all search values (must be sorted!) are in the (sorted!) array
|
|
153
|
+
# Intended for short lists/arrays!
|
|
154
|
+
bats_all_in() { # <sorted-array> <sorted search values...>
|
|
155
|
+
local -r haystack_array=$1
|
|
156
|
+
shift
|
|
157
|
+
|
|
158
|
+
local -i haystack_length # just to appease shellcheck
|
|
159
|
+
eval "local -r haystack_length=\${#${haystack_array}[@]}"
|
|
160
|
+
|
|
161
|
+
local -i haystack_index=0 # initialize only here to continue from last search position
|
|
162
|
+
local search_value haystack_value # just to appease shellcheck
|
|
163
|
+
local -i i
|
|
164
|
+
for ((i = 1; i <= $#; ++i)); do
|
|
165
|
+
eval "local search_value=${!i}"
|
|
166
|
+
for (( ; haystack_index < haystack_length; ++haystack_index)); do
|
|
167
|
+
eval "local haystack_value=\${${haystack_array}[$haystack_index]}"
|
|
168
|
+
if [[ $haystack_value > "$search_value" ]]; then
|
|
169
|
+
# we passed the location this value would have been at -> not found
|
|
170
|
+
return 1
|
|
171
|
+
elif [[ $haystack_value == "$search_value" ]]; then
|
|
172
|
+
continue 2 # search value found -> try the next one
|
|
173
|
+
fi
|
|
174
|
+
done
|
|
175
|
+
return 1 # we ran of the end of the haystack without finding the value!
|
|
176
|
+
done
|
|
177
|
+
|
|
178
|
+
# did not return from loop above -> all search values were found
|
|
179
|
+
return 0
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
# check if any search value (must be sorted!) is in the (sorted!) array
|
|
183
|
+
# intended for short lists/arrays
|
|
184
|
+
bats_any_in() { # <sorted-array> <sorted search values>
|
|
185
|
+
local -r haystack_array=$1
|
|
186
|
+
shift
|
|
187
|
+
|
|
188
|
+
local -i haystack_length # just to appease shellcheck
|
|
189
|
+
eval "local -r haystack_length=\${#${haystack_array}[@]}"
|
|
190
|
+
|
|
191
|
+
local -i haystack_index=0 # initialize only here to continue from last search position
|
|
192
|
+
local search_value haystack_value # just to appease shellcheck
|
|
193
|
+
local -i i
|
|
194
|
+
for ((i = 1; i <= $#; ++i)); do
|
|
195
|
+
eval "local search_value=${!i}"
|
|
196
|
+
for (( ; haystack_index < haystack_length; ++haystack_index)); do
|
|
197
|
+
eval "local haystack_value=\${${haystack_array}[$haystack_index]}"
|
|
198
|
+
if [[ $haystack_value > "$search_value" ]]; then
|
|
199
|
+
continue 2 # search value not in array! -> try next
|
|
200
|
+
elif [[ $haystack_value == "$search_value" ]]; then
|
|
201
|
+
return 0 # search value found
|
|
202
|
+
fi
|
|
203
|
+
done
|
|
204
|
+
done
|
|
205
|
+
|
|
206
|
+
# did not return from loop above -> no search value was found
|
|
207
|
+
return 1
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
bats_trim() { # <output-variable> <string>
|
|
211
|
+
local -r bats_trim_ltrimmed=${2#"${2%%[![:space:]]*}"} # cut off leading whitespace
|
|
212
|
+
# shellcheck disable=SC2034 # used in eval!
|
|
213
|
+
local -r bats_trim_trimmed=${bats_trim_ltrimmed%"${bats_trim_ltrimmed##*[![:space:]]}"} # cut off trailing whitespace
|
|
214
|
+
eval "$1=\$bats_trim_trimmed"
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
# a helper function to work around unbound variable errors with ${arr[@]} on Bash 3
|
|
218
|
+
bats_append_arrays_as_args() { # <array...> -- <command ...>
|
|
219
|
+
local -a trailing_args=()
|
|
220
|
+
while (($# > 0)) && [[ $1 != -- ]]; do
|
|
221
|
+
local array=$1
|
|
222
|
+
shift
|
|
223
|
+
|
|
224
|
+
if eval "(( \${#${array}[@]} > 0 ))"; then
|
|
225
|
+
eval "trailing_args+=(\"\${${array}[@]}\")"
|
|
226
|
+
fi
|
|
227
|
+
done
|
|
228
|
+
shift # remove -- separator
|
|
229
|
+
|
|
230
|
+
if (($# == 0)); then
|
|
231
|
+
printf "Error: append_arrays_as_args is missing a command or -- separator\n" >&2
|
|
232
|
+
return 1
|
|
233
|
+
fi
|
|
234
|
+
|
|
235
|
+
if ((${#trailing_args[@]} > 0)); then
|
|
236
|
+
"$@" "${trailing_args[@]}"
|
|
237
|
+
else
|
|
238
|
+
"$@"
|
|
239
|
+
fi
|
|
240
|
+
}
|
|
241
|
+
|
|
242
|
+
bats_format_file_line_reference() { # <output> <file> <line>
|
|
243
|
+
# shellcheck disable=SC2034 # will be used in subimplementation
|
|
244
|
+
local output="${1?}"
|
|
245
|
+
shift
|
|
246
|
+
"bats_format_file_line_reference_${BATS_LINE_REFERENCE_FORMAT?}" "$@"
|
|
247
|
+
}
|
|
248
|
+
|
|
249
|
+
bats_format_file_line_reference_comma_line() {
|
|
250
|
+
printf -v "$output" "%s, line %d" "$@"
|
|
251
|
+
}
|
|
252
|
+
|
|
253
|
+
bats_format_file_line_reference_colon() {
|
|
254
|
+
printf -v "$output" "%s:%d" "$@"
|
|
255
|
+
}
|
|
256
|
+
|
|
257
|
+
# approximate realpath without subshell
|
|
258
|
+
bats_approx_realpath() { # <output-variable> <path>
|
|
259
|
+
local output=$1 path=$2
|
|
260
|
+
if [[ $path != /* ]]; then
|
|
261
|
+
path="$PWD/$path"
|
|
262
|
+
fi
|
|
263
|
+
# x/./y -> x/y
|
|
264
|
+
path=${path//\/.\//\/}
|
|
265
|
+
printf -v "$output" "%s" "$path"
|
|
266
|
+
}
|
|
267
|
+
|
|
268
|
+
bats_format_file_line_reference_uri() {
|
|
269
|
+
local filename=${1?} line=${2?}
|
|
270
|
+
bats_approx_realpath filename "$filename"
|
|
271
|
+
printf -v "$output" "file://%s:%d" "$filename" "$line"
|
|
272
|
+
}
|
|
273
|
+
|
|
274
|
+
# execute command with backed up path
|
|
275
|
+
# to prevent path mocks from interfering with our internals
|
|
276
|
+
bats_execute() { # <command...>
|
|
277
|
+
PATH="${BATS_SAVED_PATH?}" "$@"
|
|
278
|
+
}
|