Import Upstream version 1.10.0

This commit is contained in:
luoyaoming 2024-05-07 15:14:04 +08:00
parent b482c346be
commit 3271c62133
48 changed files with 2166 additions and 785 deletions

View File

@ -7,7 +7,9 @@ FROM bash:${bashver}
RUN echo "@edgecomm http://dl-cdn.alpinelinux.org/alpine/edge/community" >> /etc/apk/repositories && \
apk update && \
apk add --no-cache parallel ncurses shellcheck@edgecomm && \
mkdir -p ~/.parallel && touch ~/.parallel/will-cite
mkdir -p ~/.parallel && touch ~/.parallel/will-cite && \
curl -sSfL https://github.com/shenwei356/rush/releases/download/v0.5.0/rush_linux_amd64.tar.gz | tar xzf - -C /usr/local/bin && \
chmod +x /usr/local/bin/rush
RUN ln -s /opt/bats/bin/bats /usr/sbin/bats
COPY . /opt/bats/

View File

@ -12,18 +12,19 @@ A clear and concise description of what the bug is.
**To Reproduce**
Steps to reproduce the behavior:
1. Go to '...'
2. Click on '....'
3. Scroll down to '....'
4. See error
1. Create example `file.bats` with following contents
2. run `bats --foo file.bats`
3. ...
**Expected behavior**
A clear and concise description of what you expected to happen.
**Environment (please complete the following information):**
- Bats Version [e.g. 1.4.0 or commit hash]
- OS: [e.g. Linux, FreeBSD, MacOS]
- Bash version: [e.g. 5.1]
- Bats version [e.g. 1.4.0 or commit hash if applicable]
- operating system (including version): [e.g. Linux (please name your distribution!), FreeBSD, MacOS]
- `bash --version`: [e.g. 5.1]
- Install method: [e.g. git submodule, distribution package manager, npm, homebrew, ...]
**Additional context**
Add any other context about the problem here.

View File

@ -29,6 +29,13 @@ jobs:
username: ${{ secrets.DOCKER_USERNAME }}
password: ${{ secrets.DOCKER_PASSWORD }}
- name: Log in to the GitHub Container registry
uses: docker/login-action@65b78e6e13532edd9afa3aa52ac7964289d1a9c1
with:
registry: ghcr.io
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: Set up Docker Buildx
id: buildx
uses: docker/setup-buildx-action@v1

72
.github/workflows/scorecard.yml vendored Normal file
View File

@ -0,0 +1,72 @@
# This workflow uses actions that are not certified by GitHub. They are provided
# by a third-party and are governed by separate terms of service, privacy
# policy, and support documentation.
name: Scorecard supply-chain security
on:
# For Branch-Protection check. Only the default branch is supported. See
# https://github.com/ossf/scorecard/blob/main/docs/checks.md#branch-protection
branch_protection_rule:
# To guarantee Maintained check is occasionally updated. See
# https://github.com/ossf/scorecard/blob/main/docs/checks.md#maintained
schedule:
- cron: '44 10 * * 6'
push:
branches: [ "master" ]
# Declare default permissions as read only.
permissions: read-all
jobs:
analysis:
name: Scorecard analysis
runs-on: ubuntu-latest
permissions:
# Needed to upload the results to code-scanning dashboard.
security-events: write
# Needed to publish results and get a badge (see publish_results below).
id-token: write
# Uncomment the permissions below if installing in a private repository.
# contents: read
# actions: read
steps:
- name: "Checkout code"
uses: actions/checkout@93ea575cb5d8a053eaa0ac8fa3b40d7e05a33cc8 # v3.1.0
with:
persist-credentials: false
- name: "Run analysis"
uses: ossf/scorecard-action@e38b1902ae4f44df626f11ba0734b14fb91f8f86 # v2.1.2
with:
results_file: results.sarif
results_format: sarif
# (Optional) "write" PAT token. Uncomment the `repo_token` line below if:
# - you want to enable the Branch-Protection check on a *public* repository, or
# - you are installing Scorecard on a *private* repository
# To create the PAT, follow the steps in https://github.com/ossf/scorecard-action#authentication-with-pat.
# repo_token: ${{ secrets.SCORECARD_TOKEN }}
# Public repositories:
# - Publish results to OpenSSF REST API for easy access by consumers
# - Allows the repository to include the Scorecard badge.
# - See https://github.com/ossf/scorecard-action#publishing-results.
# For private repositories:
# - `publish_results` will always be set to `false`, regardless
# of the value entered here.
publish_results: true
# Upload the results as artifacts (optional). Commenting out will disable uploads of run results in SARIF
# format to the repository Actions tab.
- name: "Upload artifact"
uses: actions/upload-artifact@3cea5372237819ed00197afe530f5a7ea3e805c8 # v3.1.0
with:
name: SARIF file
path: results.sarif
retention-days: 5
# Upload the results to GitHub's code scanning dashboard.
- name: "Upload to code-scanning"
uses: github/codeql-action/upload-sarif@17573ee1cc1b9d061760f3a006fc4aac4f944fd5 # v2.2.4
with:
sarif_file: results.sarif

View File

@ -1,13 +1,13 @@
name: Tests
# Controls when the action will run.
# Controls when the action will run.
on: [push, pull_request, workflow_dispatch]
jobs:
changelog:
runs-on: ubuntu-20.04
steps:
- uses: actions/checkout@v2
- uses: actions/checkout@v3
- name: Check that PR is mentioned in Changelog
run: |
if ! ./.github/workflows/check_pr_label.sh "${{github.event.pull_request.number}}" "no changelog"; then
@ -18,7 +18,7 @@ jobs:
shfmt:
runs-on: ubuntu-20.04
steps:
- uses: actions/checkout@v2
- uses: actions/checkout@v3
- run: |
curl https://github.com/mvdan/sh/releases/download/v3.5.1/shfmt_v3.5.1_linux_amd64 -o shfmt
chmod a+x shfmt
@ -27,7 +27,7 @@ jobs:
shellcheck:
runs-on: ubuntu-20.04
steps:
- uses: actions/checkout@v2
- uses: actions/checkout@v3
- name: Run shellcheck
run: |
sudo apt-get update -y
@ -42,9 +42,14 @@ jobs:
- ''
# allow for some parallelity without GNU parallel, since it is not installed by default
- 'BATS_NO_PARALLELIZE_ACROSS_FILES=1 BATS_NUMBER_OF_PARALLEL_JOBS=2'
- 'BATS_PARALLEL_BINARY_NAME=rush'
runs-on: ${{ matrix.os }}
steps:
- uses: actions/checkout@v2
- uses: actions/checkout@v3
- name: Install rush
run: |
curl -sSfL https://github.com/shenwei356/rush/releases/download/v0.5.0/rush_linux_amd64.tar.gz | sudo tar xzf - -C /usr/local/bin
if: contains(matrix.env_vars, 'rush')
- name: Run test on OS ${{ matrix.os }}
shell: 'script -q -e -c "bash {0}"' # work around tty issues
env:
@ -56,7 +61,7 @@ jobs:
unset_variables:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- uses: actions/checkout@v3
- name: Check unset variables
shell: 'script -q -e -c "bash {0}"' # work around tty issues
env:
@ -70,8 +75,8 @@ jobs:
os: ['ubuntu-20.04', 'ubuntu-22.04']
runs-on: ${{ matrix.os }}
steps:
- uses: actions/checkout@v2
- uses: actions/setup-node@v2
- uses: actions/checkout@v3
- uses: actions/setup-node@v3
- name: Run test on OS ${{ matrix.os }}
shell: 'script -q -e -c "bash {0}"' # work around tty issues
env:
@ -84,7 +89,7 @@ jobs:
windows:
runs-on: windows-2019
steps:
- uses: actions/checkout@v2
- uses: actions/checkout@v3
- run: |
bash --version
bash -c "time bin/bats --print-output-on-failure --formatter tap test"
@ -95,11 +100,11 @@ jobs:
os: ['windows-2019']
runs-on: ${{ matrix.os }}
steps:
- uses: actions/checkout@v2
- uses: actions/setup-node@v2
- uses: actions/checkout@v3
- uses: actions/setup-node@v3
- run: npm pack ./
- run: npm install -g (get-item .\bats-*.tgz).FullName
- run: bats -T --print-output-on-failure test
- run: bats -T --print-output-on-failure test
macos:
strategy:
@ -109,11 +114,16 @@ jobs:
- ''
# allow for some parallelity without GNU parallel, since it is not installed by default
- 'BATS_NO_PARALLELIZE_ACROSS_FILES=1 BATS_NUMBER_OF_PARALLEL_JOBS=2'
- 'BATS_PARALLEL_BINARY_NAME=rush'
runs-on: ${{ matrix.os }}
steps:
- uses: actions/checkout@v2
- uses: actions/checkout@v3
- name: Install unbuffer via expect
run: brew install expect
- name: Install rush
run: |
curl -sSfL https://github.com/shenwei356/rush/releases/download/v0.5.0/rush_darwin_amd64.tar.gz | sudo tar xzf - -C /usr/local/bin
if: contains(matrix.env_vars, 'rush')
- name: Run test on OS ${{ matrix.os }}
shell: 'unbuffer bash {0}' # work around tty issues
env:
@ -128,8 +138,8 @@ jobs:
os: ['macos-11', 'macos-12']
runs-on: ${{ matrix.os }}
steps:
- uses: actions/checkout@v2
- uses: actions/setup-node@v2
- uses: actions/checkout@v3
- uses: actions/setup-node@v3
- name: Install unbuffer via expect
run: brew install expect
- name: Run test on OS ${{ matrix.os }}
@ -140,7 +150,7 @@ jobs:
npm pack ./
# somehow there is already an installed bats version around
npm install --force -g ./bats-*.tgz
bats --print-output-on-failure test
bats --print-output-on-failure test
bash-version:
strategy:
@ -152,7 +162,7 @@ jobs:
- '-e BATS_NUMBER_OF_PARALLEL_JOBS=2'
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- uses: actions/checkout@v3
- name: Run test on bash version ${{ matrix.version }}
shell: 'script -q -e -c "bash {0}"' # work around tty issues
run: |
@ -160,12 +170,12 @@ jobs:
docker build --build-arg bashver="${{ matrix.version }}" --tag "bats/bats:bash-${{ matrix.version }}" .
docker run -it "bash:${{ matrix.version }}" --version
time docker run -it ${{ matrix.env_vars }} "bats/bats:bash-${{ matrix.version }}" --print-output-on-failure --tap /opt/bats/test
alpine:
runs-on: ubuntu-latest
container: alpine:latest
steps:
- uses: actions/checkout@v2
- uses: actions/checkout@v3
- name: Install dependencies
run: apk add bash ncurses util-linux
- name: Run test on bash version ${{ matrix.version }}
@ -183,7 +193,7 @@ jobs:
- flock
- ""
steps:
- uses: actions/checkout@v2
- uses: actions/checkout@v3
- uses: vmactions/freebsd-vm@v0
with:
prepare: pkg install -y bash parallel ${{ matrix.packages }}
@ -193,15 +203,15 @@ jobs:
find_broken_symlinks:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- uses: actions/checkout@v3
# list symlinks that are broken and force non-zero exit if there are any
- run: "! find . -xtype l | grep ."
rpm:
runs-on: ubuntu-latest
container: almalinux:8
steps:
- uses: actions/checkout@v2
- uses: actions/checkout@v3
- run: dnf install -y rpm-build rpmdevtools
- name: Build and install RPM and dependencies
run: |
@ -221,13 +231,13 @@ jobs:
dockerfile:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- uses: actions/checkout@v3
- name: Set up Docker Buildx
id: buildx
uses: docker/setup-buildx-action@v1
uses: docker/setup-buildx-action@v2
- uses: docker/build-push-action@v2
- uses: docker/build-push-action@v4
with:
platforms: linux/amd64
tags: bats:test
@ -238,17 +248,17 @@ jobs:
env:
TERM: linux # fix tput for tty issue work around
- uses: actions/checkout@v2
- uses: actions/checkout@v3
with:
repository: bats-core/bats-assert
path: bats-assert
- uses: actions/checkout@v2
- uses: actions/checkout@v3
with:
repository: bats-core/bats-support
path: bats-support
- uses: actions/checkout@v2
- uses: actions/checkout@v3
with:
repository: bats-core/bats-file
path: bats-file
@ -262,4 +272,44 @@ jobs:
docker run -itv "$PWD":/code --entrypoint bash bats:test test.sh
shell: 'script -q -e -c "bash {0}"' # work around tty issues
env:
TERM: linux # fix tput for tty issue work around
TERM: linux # fix tput for tty issue work around
coverage:
runs-on: ubuntu-20.04
permissions:
pull-requests: write
issues: write
steps:
- uses: actions/checkout@v3
- run: |
wget https://github.com/SimonKagstrom/kcov/releases/download/v40/kcov-amd64.tar.gz
tar -xf kcov-amd64.tar.gz
- run: |
./usr/local/bin/kcov --exclude-path=/tmp $PWD/coverage ./bin/bats --filter-tags '!no-kcov' test/
shell: 'script -q -e -c "bash {0}"' # work around tty issues
env:
TERM: linux # fix tput for tty issue work around
- name: Archive code coverage results
uses: actions/upload-artifact@v3
with:
name: code-coverage-report
path: coverage/*
- name: Print the Total Coverage
id: coverage-percent
shell: bash
env:
minimum_coverage: 86.39
run: |
value=$(jq '.percent_covered' <coverage/bats/coverage.json)
fixd_point() { # <float val>
int=${value%.*}
decimals=${value#*.}
echo $int${decimals::2}
}
echo "Coverage: $value%" | tee "$GITHUB_STEP_SUMMARY"
if (( $(fixed_point $value) < $(fixed_point $expected) )); then
echo " is below required minimum coverage ($minimum_coverage%)." | tee -a "$GITHUB_STEP_SUMMARY"
exit 1
fi

View File

@ -54,6 +54,7 @@ if ! BATS_PATH=$(bats_readlinkf "${BASH_SOURCE[0]}" 2>/dev/null); then
BATS_PATH=$(bats_readlinkf "${BASH_SOURCE[0]}")
fi
export BATS_SAVED_PATH=$PATH
export BATS_ROOT=${BATS_PATH%/*/*}
export -f bats_readlinkf
exec env BATS_ROOT="$BATS_ROOT" "$BATS_ROOT/libexec/bats-core/bats" "$@"

View File

@ -3,7 +3,7 @@
%global repo bats-core
Name: bats
Version: 1.9.0
Version: 1.10.0
Release: 1%{?dist}
Summary: Bash Automated Testing System

5
debian/changelog vendored
View File

@ -1,5 +0,0 @@
bats (1.8.2-ok1) yangtze; urgency=medium
* Build for openKylin.
-- denghao <denghao@kylinos.cn> Wed, 22 Feb 2023 10:50:15 +0800

21
debian/control vendored
View File

@ -1,21 +0,0 @@
Source: bats
Section: devel
Priority: optional
Maintainer: Openkylin Developers <packaging@lists.openkylin.top>
Build-Depends: debhelper-compat (= 12), parallel
Standards-Version: 4.6.1
Homepage: https://github.com/bats-core/bats-core
Vcs-Git: https://gitee.com/openkylin/bats.git
Vcs-Browser: https://gitee.com/openkylin/bats
Rules-Requires-Root: no
Package: bats
Architecture: all
Depends: ${misc:Depends}
Recommends: parallel
Multi-Arch: foreign
Description: bash automated testing system
Bats is a TAP-compliant testing framework for Bash. It provides a
simple way to verify that the UNIX programs you write behave as
expected. Bats is most useful when testing software written in Bash,
but you can use it to test any UNIX program.

423
debian/copyright vendored
View File

@ -1,423 +0,0 @@
Format: https://www.debian.org/doc/packaging-manuals/copyright-format/1.0/
Upstream-Name: bats
Source: <url://example.com>
#
# Please double check copyright with the licensecheck(1) command.
Files: .devcontainer/Dockerfile
.devcontainer/devcontainer.json
.editorconfig
.gitattributes
.github/ISSUE_TEMPLATE/bug_report.md
.github/ISSUE_TEMPLATE/feature_request.md
.github/workflows/check_pr_label.sh
.github/workflows/release.yml
.github/workflows/release_dockerhub.yml
.github/workflows/set_nounset.bash
.github/workflows/tests.yml
.gitignore
.readthedocs.yml
AUTHORS
Dockerfile
bin/bats
contrib/release.sh
contrib/rpm/bats.spec
contrib/semver
docker-compose.override.dist
docker-compose.yml
docker/install_libs.sh
docker/install_tini.sh
docker/tini.pubkey.gpg
docs/.markdownlint.json
docs/CHANGELOG.md
docs/CODEOWNERS
docs/CODE_OF_CONDUCT.md
docs/CONTRIBUTING.md
docs/Makefile
docs/PULL_REQUEST_TEMPLATE.md
docs/examples/README.md
docs/examples/package-tarball
docs/examples/package-tarball.bats
docs/make.bat
docs/releasing.md
docs/source/_static/.gitkeep
docs/source/_templates/.gitkeep
docs/source/docker-usage.md
docs/source/faq.rst
docs/source/gotchas.rst
docs/source/index.rst
docs/source/installation.rst
docs/source/requirements.txt
docs/source/support-matrix.rst
docs/source/tutorial.rst
docs/source/usage.md
docs/source/warnings/BW01.rst
docs/source/warnings/BW02.rst
docs/source/warnings/BW03.rst
docs/source/warnings/index.rst
docs/source/writing-tests.md
docs/versions.md
install.sh
lib/bats-core/common.bash
lib/bats-core/formatter.bash
lib/bats-core/preprocessing.bash
lib/bats-core/semaphore.bash
lib/bats-core/test_functions.bash
lib/bats-core/tracing.bash
lib/bats-core/validator.bash
lib/bats-core/warnings.bash
libexec/bats-core/bats
libexec/bats-core/bats-exec-file
libexec/bats-core/bats-exec-suite
libexec/bats-core/bats-exec-test
libexec/bats-core/bats-format-cat
libexec/bats-core/bats-format-junit
libexec/bats-core/bats-format-pretty
libexec/bats-core/bats-format-tap
libexec/bats-core/bats-format-tap13
libexec/bats-core/bats-preprocess
man/Makefile
man/README.md
man/bats.7
man/bats.7.ronn
package.json
shellcheck.sh
test/.bats/run-logs/.gitkeep
test/bats.bats
test/common.bats
test/concurrent-coordination.bash
test/file_setup_teardown.bats
test/fixtures/bats/BATS_TMPDIR.bats
test/fixtures/bats/BATS_variables_dont_contain_double_slashes.bats
test/fixtures/bats/cmd_using_stdin.bash
test/fixtures/bats/comment_style.bats
test/fixtures/bats/dos_line_no_shellcheck.bats
test/fixtures/bats/duplicate-tests_no_shellcheck.bats
test/fixtures/bats/empty.bats
test/fixtures/bats/environment.bats
test/fixtures/bats/evaluation_count/file1.bats
test/fixtures/bats/evaluation_count/file2.bats
test/fixtures/bats/exit_11.bash
test/fixtures/bats/expand_var_in_test_name.bats
test/fixtures/bats/exported_function.bats
test/fixtures/bats/external_function_calls.bats
test/fixtures/bats/external_functions.bash
test/fixtures/bats/external_functions.bats
test/fixtures/bats/failing.bats
test/fixtures/bats/failing_and_passing.bats
test/fixtures/bats/failing_helper.bats
test/fixtures/bats/failing_setup.bats
test/fixtures/bats/failing_teardown.bats
test/fixtures/bats/failing_with_bash_cond.bats
test/fixtures/bats/failing_with_bash_expression.bats
test/fixtures/bats/failing_with_negated_command.bats
test/fixtures/bats/failure_in_free_code.bats
test/fixtures/bats/focus.bats
test/fixtures/bats/gobble_up_stdin_sleep_and_print_finish.bash
test/fixtures/bats/hang_after_run.bats
test/fixtures/bats/hang_in_run.bats
test/fixtures/bats/hang_in_setup_file.bats
test/fixtures/bats/hang_in_teardown.bats
test/fixtures/bats/hang_in_teardown_file.bats
test/fixtures/bats/hang_in_test.bats
test/fixtures/bats/intact.bats
test/fixtures/bats/issue-205.bats
test/fixtures/bats/issue-433/repro1.bats
test/fixtures/bats/issue-433/repro2.bats
test/fixtures/bats/issue-519.bats
test/fixtures/bats/load.bats
test/fixtures/bats/loop_keep_IFS.bats
test/fixtures/bats/many_passing_and_one_failing.bats
test/fixtures/bats/no-final-newline.bats
test/fixtures/bats/output.bats
test/fixtures/bats/parallel.bats
test/fixtures/bats/passing.bats
test/fixtures/bats/passing_and_failing.bats
test/fixtures/bats/passing_and_skipping.bats
test/fixtures/bats/passing_failing_and_skipping.bats
test/fixtures/bats/print_output_on_failure.bats
test/fixtures/bats/print_output_on_failure_with_stderr.bats
test/fixtures/bats/quoted_and_unquoted_test_names_no_shellcheck.bats
test/fixtures/bats/read_from_stdin.bats
test/fixtures/bats/reference_unset_parameter.bats
test/fixtures/bats/reference_unset_parameter_in_setup.bats
test/fixtures/bats/reference_unset_parameter_in_teardown.bats
test/fixtures/bats/retry.bats
test/fixtures/bats/retry_success.bats
test/fixtures/bats/run_long_command.bats
test/fixtures/bats/set_-eu_in_setup_and_teardown.bats
test/fixtures/bats/setup.bats
test/fixtures/bats/show-output-of-passing-tests.bats
test/fixtures/bats/sigint_in_failing_test.bats
test/fixtures/bats/single_line_no_shellcheck.bats
test/fixtures/bats/skipped.bats
test/fixtures/bats/skipped_with_parens.bats
test/fixtures/bats/source_nonexistent_file.bats
test/fixtures/bats/source_nonexistent_file_in_setup.bats
test/fixtures/bats/source_nonexistent_file_in_teardown.bats
test/fixtures/bats/tab in filename.bats
test/fixtures/bats/teardown.bats
test/fixtures/bats/teardown_file_override_status.bats
test/fixtures/bats/teardown_override_status.bats
test/fixtures/bats/teardown_suite_override_status/setup_suite.bash
test/fixtures/bats/teardown_suite_override_status/test.bats
test/fixtures/bats/test_helper.bash
test/fixtures/bats/unbound_variable.bats
test/fixtures/bats/unofficial_bash_strict_mode.bash
test/fixtures/bats/unofficial_bash_strict_mode.bats
test/fixtures/bats/update_path_env.bats
test/fixtures/bats/verbose-run.bats
test/fixtures/bats/whitespace_no_shellcheck.bats
test/fixtures/bats/without_trailing_newline.bats
test/fixtures/file_setup_teardown/error_in_setup_and_teardown_file.bats
test/fixtures/file_setup_teardown/no_setup_file.bats
test/fixtures/file_setup_teardown/no_teardown_file.bats
test/fixtures/file_setup_teardown/setup_file.bats
test/fixtures/file_setup_teardown/setup_file2.bats
test/fixtures/file_setup_teardown/setup_file_does_not_leak_env.bats
test/fixtures/file_setup_teardown/setup_file_does_not_leak_env2.bats
test/fixtures/file_setup_teardown/setup_file_even_if_all_tests_are_skipped.bats
test/fixtures/file_setup_teardown/setup_file_failed.bats
test/fixtures/file_setup_teardown/setup_file_halfway_error.bats
test/fixtures/file_setup_teardown/teardown_file.bats
test/fixtures/file_setup_teardown/teardown_file2.bats
test/fixtures/file_setup_teardown/teardown_file_after_failing_test.bats
test/fixtures/file_setup_teardown/teardown_file_after_long_test.bats
test/fixtures/file_setup_teardown/teardown_file_does_not_leak.bats
test/fixtures/file_setup_teardown/teardown_file_does_not_leak2.bats
test/fixtures/file_setup_teardown/teardown_file_even_if_all_tests_are_skipped.bats
test/fixtures/file_setup_teardown/teardown_file_failed.bats
test/fixtures/file_setup_teardown/teardown_file_halfway_error.bats
test/fixtures/formatter/dummy-formatter
test/fixtures/formatter/failing.bats
test/fixtures/formatter/passing.bats
test/fixtures/formatter/passing_and_skipping.bats
test/fixtures/formatter/passing_failing_and_skipping.bats
test/fixtures/formatter/skipped_with_parens.bats
test/fixtures/junit-formatter/duplicate/first/file1.bats
test/fixtures/junit-formatter/duplicate/second/file1.bats
test/fixtures/junit-formatter/issue_360.bats
test/fixtures/junit-formatter/issue_531.bats
test/fixtures/junit-formatter/skipped.bats
test/fixtures/junit-formatter/suite/file1.bats
test/fixtures/junit-formatter/suite/file2.bats
test/fixtures/junit-formatter/xml-escape.bats
test/fixtures/load/ambiguous
test/fixtures/load/ambiguous.bash
test/fixtures/load/bats_load_library.bats
test/fixtures/load/exit1.bash
test/fixtures/load/failing_bats_load_library.bats
test/fixtures/load/failing_load.bats
test/fixtures/load/find_library_helper.bats
test/fixtures/load/find_library_helper_err.bats
test/fixtures/load/load.bats
test/fixtures/load/load_in_teardown_after_failure.bats
test/fixtures/load/return1.bash
test/fixtures/load/test_helper.bash
test/fixtures/parallel/must_not_parallelize_across_files/file1.bats
test/fixtures/parallel/must_not_parallelize_across_files/file2.bats
test/fixtures/parallel/must_not_parallelize_within_file.bats
test/fixtures/parallel/parallel-preserve-environment.bats
test/fixtures/parallel/parallel.bats
test/fixtures/parallel/parallel_factor.bats
test/fixtures/parallel/setup_file/setup_file.bats
test/fixtures/parallel/suite/parallel1.bats
test/fixtures/run/failing.bats
test/fixtures/run/invalid.bats
test/fixtures/suite/empty/.gitkeep
test/fixtures/suite/filter/a.bats
test/fixtures/suite/filter/b.bats
test/fixtures/suite/filter/c.bats
test/fixtures/suite/multiple/a.bats
test/fixtures/suite/multiple/b.bats
test/fixtures/suite/override_BATS_FILE_EXTENSION/subfolder/test.other_extension
test/fixtures/suite/override_BATS_FILE_EXTENSION/test.bats
test/fixtures/suite/override_BATS_FILE_EXTENSION/test.test
test/fixtures/suite/recursive/subsuite/test2.bats
test/fixtures/suite/recursive/test.bats
test/fixtures/suite/single/test.bats
test/fixtures/suite/skip/skip-in-setup-and-teardown.bats
test/fixtures/suite/skip/skip-in-setup.bats
test/fixtures/suite/skip/skip-in-teardown.bats
test/fixtures/suite/skip/skip-in-test-and-teardown.bats
test/fixtures/suite/skip/skip-in-test.bats
test/fixtures/suite/test_number/file1.bats
test/fixtures/suite/test_number/file2.bats
test/fixtures/suite_setup_teardown/call_load/setup_suite.bash
test/fixtures/suite_setup_teardown/call_load/test.bats
test/fixtures/suite_setup_teardown/call_load/test_helper.bash
test/fixtures/suite_setup_teardown/default_name/setup_suite.bash
test/fixtures/suite_setup_teardown/default_name/test.bats
test/fixtures/suite_setup_teardown/error_in_free_code/setup_suite.bash
test/fixtures/suite_setup_teardown/error_in_free_code/test.bats
test/fixtures/suite_setup_teardown/error_in_setup_suite/setup_suite.bash
test/fixtures/suite_setup_teardown/error_in_setup_suite/test.bats
test/fixtures/suite_setup_teardown/error_in_teardown_suite/setup_suite.bash
test/fixtures/suite_setup_teardown/error_in_teardown_suite/test.bats
test/fixtures/suite_setup_teardown/exported_vars/setup_suite.bash
test/fixtures/suite_setup_teardown/exported_vars/test.bats
test/fixtures/suite_setup_teardown/failure_in_setup_suite/setup_suite.bash
test/fixtures/suite_setup_teardown/failure_in_setup_suite/test.bats
test/fixtures/suite_setup_teardown/failure_in_teardown_suite/setup_suite.bash
test/fixtures/suite_setup_teardown/failure_in_teardown_suite/test.bats
test/fixtures/suite_setup_teardown/no_failure_no_output/setup_suite.bash
test/fixtures/suite_setup_teardown/no_failure_no_output/test.bats
test/fixtures/suite_setup_teardown/no_setup_suite_function/setup_suite.bash
test/fixtures/suite_setup_teardown/no_setup_suite_function/test.bats
test/fixtures/suite_setup_teardown/non_default_name/setup_suite_non_default.bash
test/fixtures/suite_setup_teardown/non_default_name/test.bats
test/fixtures/suite_setup_teardown/output_with_failure/setup_suite.bash
test/fixtures/suite_setup_teardown/output_with_failure/test.bats
test/fixtures/suite_setup_teardown/pick_up_toplevel/folder1/test.bats
test/fixtures/suite_setup_teardown/pick_up_toplevel/folder2/test.bats
test/fixtures/suite_setup_teardown/pick_up_toplevel/setup_suite.bash
test/fixtures/suite_setup_teardown/pick_up_toplevel/test.bats
test/fixtures/suite_setup_teardown/return_nonzero_in_teardown_suite/setup_suite.bash
test/fixtures/suite_setup_teardown/return_nonzero_in_teardown_suite/test.bats
test/fixtures/suite_setup_teardown/skip_in_setup_file.bats
test/fixtures/suite_setup_teardown/stderr_in_setup_teardown_suite/setup_suite.bash
test/fixtures/suite_setup_teardown/stderr_in_setup_teardown_suite/test.bats
test/fixtures/suite_setup_teardown/syntax_error/setup_suite_no_shellcheck
test/fixtures/suite_setup_teardown/syntax_error/test.bats
test/fixtures/tagging/invalid_tags.bats
test/fixtures/tagging/tagged.bats
test/fixtures/tagging/trimming.bats
test/fixtures/timeout/sleep2.bats
test/fixtures/trace/failing_complex.bats
test/fixtures/trace/failing_recursive.bats
test/fixtures/warnings/BW01.bats
test/fixtures/warnings/BW01_check_exit_code_is_127.bats
test/fixtures/warnings/BW01_no_exit_code_check_no_exit_code_127.bats
test/fixtures/warnings/BW02.bats
test/fixtures/warnings/BW03/define_setup_suite_in_wrong_file.bats
test/fixtures/warnings/BW03/non_default_setup_suite.bash
test/fixtures/warnings/BW03/suppress_warning.bats
test/formatter.bats
test/install.bats
test/junit-formatter.bats
test/load.bats
test/parallel.bats
test/pretty-formatter.bats
test/root.bats
test/run.bats
test/suite.bats
test/suite_setup_teardown.bats
test/tagging.bats
test/tap13-formatter.bats
test/test_helper.bash
test/timeout.bats
test/trace.bats
test/warnings.bats
uninstall.sh
Copyright: __NO_COPYRIGHT_NOR_LICENSE__
License: __NO_COPYRIGHT_NOR_LICENSE__
Files: LICENSE.md
Copyright: 2017 bats-core contributors
License: Expat
Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the
"Software"), to deal in the Software without restriction, including
without limitation the rights to use, copy, modify, merge, publish,
distribute, sublicense, and/or sell copies of the Software, and to
permit persons to whom the Software is furnished to do so, subject to
the following conditions:
.
The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software.
.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
Files: man/bats.1.ronn
Copyright: 2011-2016 Sam Stephenson
2017-2022 bats-core organization<br/>
License: __UNKNOWN__
Bats is released under the terms of an MIT-style license.
Files: README.md
Copyright: 2011-2016 Sam Stephenson
2017-2022 bats-core organization
License: __UNKNOWN__
Bats is released under an MIT-style license; see `LICENSE.md` for details.
.
See the [parent project](https://github.com/bats-core) at GitHub or the
[AUTHORS](AUTHORS) file for the current project maintainer team.
.
[gitter]: https://gitter.im/bats-core/bats-core
Files: man/bats.1
Copyright: 2011 \-2016 Sam Stephenson .P
2017 \-2022 bats\-core organization .br
License: __UNKNOWN__
Bats is released under the terms of an MIT\-style license\.
Files: docs/source/conf.py
Copyright: __NO_COPYRIGHT__ in: docs/source/conf.py
License: __UNKNOWN__
# The full version, including alpha/beta/rc tags
#----------------------------------------------------------------------------
# Files marked as NO_LICENSE_TEXT_FOUND may be covered by the following
# license/copyright files.
#----------------------------------------------------------------------------
# License file: LICENSE.md
Copyright (c) 2017 bats-core contributors
.
Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the
"Software"), to deal in the Software without restriction, including
without limitation the rights to use, copy, modify, merge, publish,
distribute, sublicense, and/or sell copies of the Software, and to
permit persons to whom the Software is furnished to do so, subject to
the following conditions:
.
The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software.
.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
.
---
.
* [bats-core] is a continuation of [bats]. Copyright for portions of the
bats-core project are held by Sam Stephenson, 2014 as part of the project
[bats], licensed under MIT:
.
Copyright (c) 2014 Sam Stephenson
.
Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the
"Software"), to deal in the Software without restriction, including
without limitation the rights to use, copy, modify, merge, publish,
distribute, sublicense, and/or sell copies of the Software, and to
permit persons to whom the Software is furnished to do so, subject to
the following conditions:
.
The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software.
.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
.
For details, please see the [version control history][commits].
.
[bats-core]: https://github.com/bats-core/bats-core
[bats]:https://github.com/sstephenson/bats
[commits]:https://github.com/bats-core/bats-core/commits/master

1
debian/docs vendored
View File

@ -1 +0,0 @@
README.md

View File

@ -1,4 +0,0 @@
# Reported upstream: https://github.com/bats-core/bats-core/issues/666
bats: acute-accent-in-manual-page [usr/share/man/man1/bats.1.gz:*]
# Reported upstream: https://github.com/bats-core/bats-core/issues/666
bats: acute-accent-in-manual-page [usr/share/man/man7/bats.7.gz:*]

View File

@ -1 +0,0 @@
# You must remove unused comment lines for the released package.

21
debian/rules vendored
View File

@ -1,21 +0,0 @@
#!/usr/bin/make -f
# See debhelper(7) (uncomment to enable)
# output every command that modifies files on the build system.
#DH_VERBOSE = 1
export HOME=$(shell mktemp -d)
# main packaging script based on dh7 syntax
%:
dh $@
override_dh_clean:
dh_clean
rm -f test/.bats/run-logs/*.log
override_dh_auto_install:
./install.sh debian/bats/usr
override_dh_auto_test:
mkdir -p ~/.parallel && touch ~/.parallel/will-cite
LC_ALL=C.UTF-8 LANGUAGE=C.UTF-8 TERM=dumb bin/bats --tap test

3
debian/salsa-ci.yml vendored
View File

@ -1,3 +0,0 @@
---
include:
- https://salsa.debian.org/salsa-ci-team/pipeline/raw/master/recipes/debian.yml

View File

@ -1 +0,0 @@
3.0 (native)

View File

@ -1,3 +0,0 @@
Tests:
test-with-system-bats,
Depends: @, parallel

View File

@ -1,15 +0,0 @@
#!/bin/sh
set -eu
export LC_ALL=C.UTF-8
export LANGUAGE=C.UTF-8
FIXTURE_ROOT="test/fixtures"
export FIXTURE_ROOT
# Exclude `root.bats`: the tests assume being run with the local `bats`.
test_files=$(find test -maxdepth 1 -name '*.bats' | sort | grep -v 'root.bats')
mkdir -p ~/.parallel && touch ~/.parallel/will-cite
TERM=dumb /usr/bin/bats $test_files

4
debian/watch vendored
View File

@ -1,4 +0,0 @@
version=4
opts="filenamemangle=s%(?:.*?)?v?@ANY_VERSION@(@ARCHIVE_EXT@)%@PACKAGE@-$1$2%" \
https://github.com/bats-core/bats-core/tags \
(?:.*?/)v?@ANY_VERSION@@ARCHIVE_EXT@

View File

@ -8,6 +8,38 @@ The format is based on [Keep a Changelog][kac] and this project adheres to
[kac]: https://keepachangelog.com/en/1.0.0/
[semver]: https://semver.org/
## [1.10.0] - 2023-07-15
### Added
* add `${BATS_TEST_TAGS[@]}` for querying the tags during a test (#705)
* print tags on failing tests (#705)
* test for negative arguments to `--jobs` (#693)
* add tests for `--formatter cat` (#710)
* test coverage in CI (#718)
* Support for [rush](https://github.com/shenwei356/rush) as alternative to GNU parallel (#729)
* add `bats_pipe` helper function for `run` that executes `\|` as pipes (#663)
* publish docker images to ghcr.io (additionally to Dockerhub) (#740)
### Documentation
* clarify use cases of `--formatter cat` (#710)
### Fixed
* fix `run` with options overwriting the value of `i` (#726, #727)
* fix `${BATS_TEST_NAMES[@]}` containing only `--tags` instead of test name since Bats v1.8.0 (#705)
* fix `run --keep-empty-lines` counting trailing `\n` as (empty) new line (#711)
* fix short flag unpacker creating bogus command lines with valued flags (#732)
* fix formatter becoming confused with retries (#734)
* fix `--gather-test-outputs-in` fails on tests with `/` (#735)
* fix overriding `date` breaks `--timing` (#736)
#### Documentation
* typos, minor edits (#704)
* simplified contributing.md (#718)
## [1.9.0] - 2023-02-12
### Added

View File

@ -2,7 +2,7 @@
## Welcome!
Thank you for considering contributing to the development of this project's
Thank you for considering contributing to this project's
development and/or documentation. Just a reminder: if you're new to this project
or to OSS and want to find issues to work on, please check the following labels
on issues:
@ -17,16 +17,6 @@ on issues:
To see all labels and their meanings, [check this wiki page][labelswiki].
This guide borrows **heavily** from [@mbland's go-script-bash][gsb] (with some
sections directly quoted), which in turn was
drafted with tips from [Wrangling Web Contributions: How to Build
a CONTRIBUTING.md][moz] and with some inspiration from [the Atom project's
CONTRIBUTING.md file][atom].
[gsb]: https://github.com/mbland/go-script-bash/blob/master/CONTRIBUTING.md
[moz]: https://mozillascience.github.io/working-open-workshop/contributing/
[atom]: https://github.com/atom/atom/blob/master/CONTRIBUTING.md
[labelswiki]: https://github.com/bats-core/bats-core/wiki/GitHub-Issue-Labels
## Table of contents
@ -35,22 +25,18 @@ CONTRIBUTING.md file][atom].
* [Welcome!](#welcome)
* [Table of contents](#table-of-contents)
* [Quick links](#quick-links)
* [Contributor License Agreement](#contributor-license-agreement)
* [Code of conduct](#code-of-conduct)
* [Asking questions and reporting issues](#asking-questions-and-reporting-issues)
* [Asking questions](#asking-questions)
* [Updating documentation](#updating-documentation)
* [Environment setup](#environment-setup)
* [Workflow](#workflow)
* [Testing](#testing)
* [Coding conventions](#coding-conventions)
* [Formatting](#formatting)
* [Naming](#naming)
* [Function declarations](#function-declarations)
* [Variable and parameter declarations](#variable-and-parameter-declarations)
* [Command substitution](#command-substitution)
* [Process substitution](#process-substitution)
* [Conditionals and loops](#conditionals-and-loops)
* [Generating output](#generating-output)
* [Signal names](#signal-names)
* [Gotchas](#gotchas)
* [Open Source License](#open-source-license)
* [Credits](#credits)
@ -71,83 +57,18 @@ CONTRIBUTING.md file][atom].
[CODE_OF_CONDUCT]: https://github.com/bats-core/bats-core/blob/master/docs/CODE_OF_CONDUCT.md
[LICENSE]: https://github.com/bats-core/bats-core/blob/master/LICENSE.md
## Contributor License Agreement
Per the [GitHub Terms of Service][gh-tos], be aware that by making a
contribution to this project, you agree:
* to license your contribution under the same terms as [this project's
license][osmit], and
* that you have the right to license your contribution under those terms.
See also: ["Does my project need an additional contributor agreement? Probably
not."][cla-needed]
[gh-tos]: https://help.github.com/articles/github-terms-of-service/#6-contributions-under-repository-license
[osmit]: #open-source-license
[cla-needed]: https://opensource.guide/legal/#does-my-project-need-an-additional-contributor-agreement
## Code of conduct
Harassment or rudeness of any kind will not be tolerated, period. For
specifics, see the [CODE_OF_CONDUCT][] file.
## Asking questions and reporting issues
## Asking questions
### Asking questions
Please check the [README][] or existing [issues][repoissues] first.
Please check the [documentation][documentation] or existing [discussions][] and [issues][repoissues] first.
If you cannot find an answer to your question, please feel free to hop on our
[Gitter][gitterurl]. [![Gitter](https://badges.gitter.im/bats-core/bats-core.svg)](https://gitter.im/bats-core/bats-core)
### Reporting issues
Before reporting an issue, please use the search feature on the [issues
page][repoissues] to see if an issue matching the one you've observed has already
been filed.
### Updating or filing a new issue
#### Information to include
Try to be as specific as possible about your environment and the problem you're
observing. At a minimum, include:
#### Installation issues
1. State the version of Bash you're using `bash --version`
1. State your operating system and its version
1. If you're installing through homebrew, run `brew doctor`, and attach the
output of `brew info bats-core`
#### Bugs/usage issues
1. State the version of Bash you're using `bash --version`
1. State your operating system and its version
1. Command line steps or code snippets that reproduce the issue
1. Any apparently relevant information from the [Bash changelog][bash-changes]
[bash-changes]: https://tiswww.case.edu/php/chet/bash/CHANGES
Also consider using:
- Bash's `time` builtin to collect running times
- a regression test to add to the suite
- memory usage as reported by a tool such as
[memusg](https://gist.github.com/netj/526585)
### On existing issues
1. DO NOT add a +1 comment: Use the reactions provided instead
1. DO add information if you're facing a similar issue to someone else, but
within a different context (e.g. different steps needed to reproduce the issue
than previous stated, different version of Bash or BATS, different OS, etc.)
You can read on how to do that here: [Information to include](#information-to-include)
1. DO remember that you can use the *Subscribe* button on the right side of the
page to receive notifications of further conversations or a resolution.
## Updating documentation
We love documentation and people who love documentation!
@ -158,95 +79,31 @@ requests. Remember: docs are just as important as code.
Also: _no typo is too small to fix!_ Really. Of course, batches of fixes are
preferred, but even one nit is one nit too many.
## Environment setup
Make sure you have Bash installed per the [Environment setup in the
README][env-setup].
[env-setup]: https://github.com/bats-core/bats-core/blob/master/README.md#environment-setup
## Workflow
The basic workflow for submitting changes resembles that of the [GitHub Git
Flow][github-flow] (a.k.a. GitHub Flow), except that you will be working with
your own fork of the repository and issuing pull requests to the original.
[github-flow]: https://guides.github.com/introduction/flow/
1. Fork the repo on GitHub (look for the "Fork" button)
1. Clone your forked repo to your local machine
1. Create your feature branch (`git checkout -b my-new-feature`)
1. Develop _and [test](#testing)_ your changes as necessary.
1. Commit your changes (`git commit -am 'Add some feature'`)
1. Push to the branch (`git push origin my-new-feature`)
1. Create a new [GitHub pull request][gh-pr] for your feature branch based
against the original repository's `master` branch
1. If your request is accepted, you can [delete your feature branch][rm-branch]
and pull the updated `master` branch from the original repository into your
fork. You may even [delete your fork][rm-fork] if you don't anticipate making
further changes.
[gh-pr]: https://help.github.com/articles/using-pull-requests/
[rm-branch]: https://help.github.com/articles/deleting-unused-branches/
[rm-fork]: https://help.github.com/articles/deleting-a-repository/
## Testing
- Continuous integration status: [![Tests](https://github.com/bats-core/bats-core/workflows/Tests/badge.svg)](https://github.com/bats-core/bats-core/actions?query=workflow%3ATests)
To run all tests:
```sh
bin/bats test
```
To run a single test file:
```sh
bin/bats test/file.bats
```
When running from a teminal, Bats uses the *pretty* formatter by default.
However, to debug Bats you might need to see the raw test output.
The **cat** formatter is intended as an internal debugging tool because
it does not process test outputs.
To use it, run Bats with the `--formatter cat` option.
## Coding conventions
- [Formatting](#formatting)
- [Naming](#naming)
- [Variable and parameter declarations](#variable-and-parameter-declarations)
- [Command substitution](#command-substitution)
- [Conditions and loops](#conditionals-and-loops)
- [Gotchas](#gotchas)
Use (`shfmt`)[https://github.com/mvdan/sh#shfmt] and [ShellCheck](https://www.shellcheck.net/). The CI will enforce this.
### Formatting
- Keep all files 80 characters wide.
- Indent using two spaces.
- Enclose all variables in double quotes when used to avoid having them
interpreted as glob patterns (unless the variable contains a glob pattern)
and to avoid word splitting when the value contains spaces. Both scenarios
can introduce errors that often prove difficult to diagnose.
- **This is especially important when the variable is used to generate a
glob pattern**, since spaces may appear in a path value.
- If the variable itself contains a glob pattern, make sure to set
`IFS=$'\n'` before using it so that the pattern itself and any matching
file names containing spaces are not split apart.
- Exceptions: Quotes are not required within math contexts, i.e. `(( ))` or
`$(( ))`, and must not be used for variables on the right side of the `=~`
operator.
- Enclose all string literals in single quotes.
- Exception: If the string contains an apostrophe, use double quotes.
- Use quotes around variables and literals even inside of `[[ ]]` conditions.
- This is because strings that contain '[' or ']' characters may fail to
compare equally when they should.
- Exception: Do not quote variables that contain regular expression patterns
appearing on the right side of the `=~` operator.
- _Only_ quote arguments to the right of `=~` if the expression is a literal
match without any metacharacters.
The following are intended to prevent too-compact code:
- Declare only one item per `declare`, `local`, `export`, or `readonly` call.
- _Note:_ This also helps avoid subtle bugs, as trying to initialize one
variable using the value of another declared in the same statement will
not do what you may expect. The initialization of the first variable will
not yet be complete when the second variable is declared, so the first
variable will have an empty value.
- Do not use one-line `if`, `for`, `while`, `until`, `case`, or `select`
statements.
- Do not use `&&` or `||` to avoid writing `if` statements.
- Do not write functions entirely on one line.
- For `case` statements: put each pattern on a line by itself; put each command
on a line by itself; put the `;;` terminator on a line by itself.
### Naming
- Use `snake_case` for all identifiers.
Use `snake_case` for all identifiers.
### Function declarations
@ -258,9 +115,6 @@ The following are intended to prevent too-compact code:
### Variable and parameter declarations
- _Gotcha:_ Never initialize an array on the same line as an `export` or
`declare -g` statement. See [the Gotchas section](#gotchas) below for more
details.
- Declare all variables inside functions using `local`.
- Declare temporary file-level variables using `declare`. Use `unset` to remove
them when finished.
@ -349,38 +203,24 @@ $ LC_CTYPE=tr_TR.UTF-8 LC_MESSAGES=C bash -c 'trap - INT && echo success'
success
```
### Gotchas
- If you wish to use command substitution to initialize a `local` variable, and
then check the exit status of the command substitution, you _must_ declare the
variable on one line and perform the substitution on another. If you don't,
the exit status will always indicate success, as it is the status of the
`local` declaration, not the command substitution.
- To work around a bug in some versions of Bash whereby arrays declared with
`declare -g` or `export` and initialized in the same statement eventually go
out of scope, always `export` the array name on one line and initialize it the
next line. See:
- https://lists.gnu.org/archive/html/bug-bash/2012-06/msg00068.html
- ftp://ftp.gnu.org/gnu/bash/bash-4.2-patches/bash42-025
- http://lists.gnu.org/archive/html/help-bash/2012-03/msg00078.html
- [ShellCheck](https://www.shellcheck.net/) can help to identify many of these issues
## Open Source License
This software is made available under the [MIT License][osmit].
For the text of the license, see the [LICENSE][] file.
## Credits
- This guide was heavily written by BATS-core member [@mbland](https://github.com/mbland)
for [go-script-bash](https://github.com/mbland/go-script-bash), tweaked for [BATS-core][repohome]
- Table of Contents created by [gh-md-toc](https://github.com/ekalinin/github-markdown-toc)
- The [official bash logo](https://github.com/odb/official-bash-logo) is copyrighted
The [official bash logo](https://github.com/odb/official-bash-logo) is copyrighted
by the [Free Software Foundation](https://www.fsf.org/), 2016 under the [Free Art License](http://artlibre.org/licence/lal/en/)
This guide borrows **heavily** from [@mbland's go-script-bash][gsb] (with some
sections directly quoted), which in turn was
drafted with tips from [Wrangling Web Contributions: How to Build
a CONTRIBUTING.md][moz] and with some inspiration from [the Atom project's
CONTRIBUTING.md file][atom].
[gsb]: https://github.com/mbland/go-script-bash/blob/master/CONTRIBUTING.md
[moz]: https://mozillascience.github.io/working-open-workshop/contributing/
[atom]: https://github.com/atom/atom/blob/master/CONTRIBUTING.md
[discussions]: https://github.com/bats-core/bats-core/discussions
[documentation]: https://bats-core.readthedocs.io/
[repoprojects]: https://github.com/bats-core/bats-core/projects
[repomilestones]: https://github.com/bats-core/bats-core/milestones
[repoprs]: https://github.com/bats-core/bats-core/pulls

View File

@ -22,7 +22,7 @@ Tags can be defined in two ways. The first being `# bats test_tags=`:
```bash
# bats test_tags=tag:1, tag:2, tag:3
@test "second test" {
@test "first test" {
# ...
}
@ -582,6 +582,7 @@ There are several global variables you can use to introspect on Bats tests:
is `setup_file()`.
- `$BATS_TEST_NUMBER` is the (1-based) index of the current test case in the test file.
- `$BATS_SUITE_TEST_NUMBER` is the (1-based) index of the current test case in the test suite (over all files).
- `$BATS_TEST_TAGS` the tags of the current test.
- `$BATS_TMPDIR` is the base temporary directory used by bats to create its
temporary files / directories.
(default: `$TMPDIR`. If `$TMPDIR` is not set, `/tmp` is used.)

View File

@ -39,6 +39,7 @@ bats_version_lt() { # <version1> <version2>
IFS=. read -ra version1_parts <<<"$1"
IFS=. read -ra version2_parts <<<"$2"
local -i i
for i in {0..2}; do
if ((version1_parts[i] < version2_parts[i])); then
return 0
@ -139,6 +140,7 @@ bats_all_in() { # <sorted-array> <sorted search values...>
local -i haystack_index=0 # initialize only here to continue from last search position
local search_value haystack_value # just to appease shellcheck
local -i i
for ((i = 1; i <= $#; ++i)); do
eval "local search_value=${!i}"
for (( ; haystack_index < haystack_length; ++haystack_index)); do
@ -168,6 +170,7 @@ bats_any_in() { # <sorted-array> <sorted search values>
local -i haystack_index=0 # initialize only here to continue from last search position
local search_value haystack_value # just to appease shellcheck
local -i i
for ((i = 1; i <= $#; ++i)); do
eval "local search_value=${!i}"
for (( ; haystack_index < haystack_length; ++haystack_index)); do
@ -247,3 +250,9 @@ bats_format_file_line_reference_uri() {
bats_approx_realpath filename "$filename"
printf -v "$output" "file://%s:%d" "$filename" "$line"
}
# execute command with backed up path
# to prevent path mocks from interfering with our internals
bats_execute() { # <command...>
PATH="${BATS_SAVED_PATH?}" "$@"
}

View File

@ -41,17 +41,25 @@ function bats_parse_internal_extended_tap() {
not_ok_line_regexpr="not ok ([0-9]+) (.*)"
timing_expr="in ([0-9]+)ms$"
local test_name begin_index ok_index not_ok_index index scope
local test_name begin_index last_begin_index try_index ok_index not_ok_index index scope
begin_index=0
last_begin_index=-1
try_index=0
index=0
scope=plan
while IFS= read -r line; do
unset BATS_FORMATTER_TEST_DURATION BATS_FORMATTER_TEST_TIMEOUT
case "$line" in
'begin '*) # this might only be called in extended tap output
((++begin_index))
scope=begin
test_name="${line#* "$begin_index" }"
begin_index=${line#begin }
begin_index=${begin_index%% *}
if [[ $begin_index == "$last_begin_index" ]]; then
(( ++try_index ))
else
try_index=0
fi
test_name="${line#begin "$begin_index" }"
bats_tap_stream_begin "$begin_index" "$test_name"
;;
'ok '*)

View File

@ -163,14 +163,17 @@ bats_merge_stdout_and_stderr() {
# write separate lines from <input-var> into <output-array>
bats_separate_lines() { # <output-array> <input-var>
local output_array_name="$1"
local input_var_name="$2"
local -r output_array_name="$1"
local -r input_var_name="$2"
local input="${!input_var_name}"
if [[ $keep_empty_lines ]]; then
local bats_separate_lines_lines=()
if [[ -n "${!input_var_name}" ]]; then # avoid getting an empty line for empty input
if [[ -n "$input" ]]; then # avoid getting an empty line for empty input
# remove one trailing \n if it exists to compensate its addition by <<<
input=${input%$'\n'}
while IFS= read -r line; do
bats_separate_lines_lines+=("$line")
done <<<"${!input_var_name}"
done <<<"${input}"
fi
eval "${output_array_name}=(\"\${bats_separate_lines_lines[@]}\")"
else
@ -179,6 +182,127 @@ bats_separate_lines() { # <output-array> <input-var>
fi
}
bats_pipe() { # [-N] [--] command0 [ \| command1 [ \| command2 [...]]]
# This will run each command given, piping them appropriately.
# Meant to be used in combination with `run` helper to allow piped commands
# to be used.
# Note that `\|` must be used, not `|`.
# By default, the exit code of this command will be the last failure in the
# chain of piped commands (similar to `set -o pipefail`).
# Supplying -N (e.g. -0) will instead always use the exit code of the command
# at that position in the chain.
# --returned-status=N could be used as an alternative to -N. This also allows
# for negative values (which count from the end in reverse order).
local pipestatus_position=
# parse options starting with -
while [[ $# -gt 0 ]] && [[ $1 == -* ]]; do
case "$1" in
-[0-9]*)
pipestatus_position="${1#-}"
;;
--returned-status*)
if [ "$1" = "--returned-status" ]; then
pipestatus_position="$2"
shift
elif [[ "$1" =~ ^--returned-status= ]]; then
pipestatus_position="${1#--returned-status=}"
else
printf "Usage error: unknown flag '%s'" "$1" >&2
return 1
fi
;;
--)
shift # eat the -- before breaking away
break
;;
*)
printf "Usage error: unknown flag '%s'" "$1" >&2
return 1
;;
esac
shift
done
# parse and validate arguments, escape as necessary
local -a commands_and_args=("$@")
local -a escaped_args=()
local -i pipe_count=0
local -i previous_pipe_index=-1
local -i index=0
for (( index = 0; index < $#; index++ )); do
local current_command_or_arg="${commands_and_args[$index]}"
local escaped_arg="$current_command_or_arg"
if [[ "$current_command_or_arg" != '|' ]]; then
# escape args to protect them when eval'd (e.g. if they contain whitespace).
printf -v escaped_arg "%q" "$current_command_or_arg"
elif [ "$current_command_or_arg" = "|" ]; then
if [ "$index" -eq 0 ]; then
printf "Usage error: Cannot have leading \`\\|\`.\n" >&2
return 1
fi
if (( (previous_pipe_index + 1) >= index )); then
printf "Usage error: Cannot have consecutive \`\\|\`. Found at argument position '%s'.\n" "$index" >&2
return 1
fi
(( ++pipe_count ))
previous_pipe_index="$index"
fi
escaped_args+=("$escaped_arg")
done
if (( (previous_pipe_index > 0) && (previous_pipe_index == ($# - 1)) )); then
printf "Usage error: Cannot have trailing \`\\|\`.\n" >&2
return 1
fi
if (( pipe_count == 0 )); then
# Don't allow for no pipes. This might be a typo in the test,
# e.g. `run bats_pipe command0 | command1`
# instead of `run bats_pipe command0 \| command1`
# Unfortunately, we can't catch `run bats_pipe command0 \| command1 | command2`.
# But this check is better than just allowing no pipes.
printf "Usage error: No \`\\|\`s found. Is this an error?\n" >&2
return 1
fi
# there will be pipe_count + 1 entries in PIPE_STATUS (pipe_count number of \|'s between each entry).
# valid indices are [-(pipe_count + 1), pipe_count]
if [ -n "$pipestatus_position" ] && (( (pipestatus_position > pipe_count) || (-pipestatus_position > (pipe_count + 1)) )); then
printf "Usage error: Too large of -N argument (or --returned-status) given. Argument value: '%s'.\n" "$pipestatus_position" >&2
return 1
fi
# run commands and return appropriate pipe status
local -a __bats_pipe_eval_pipe_status=()
eval "${escaped_args[@]}" '; __bats_pipe_eval_pipe_status=(${PIPESTATUS[@]})'
local result_status=
if [ -z "$pipestatus_position" ]; then
# if we are performing default "last failure" behavior,
# iterate backwards through pipe_status to find the last error.
result_status=0
for index in "${!__bats_pipe_eval_pipe_status[@]}"; do
# OSX bash doesn't support negative indexing.
local backward_iter_index="$((${#__bats_pipe_eval_pipe_status[@]} - index - 1))"
local status_at_backward_iter_index="${__bats_pipe_eval_pipe_status[$backward_iter_index]}"
if (( status_at_backward_iter_index != 0 )); then
result_status="$status_at_backward_iter_index"
break;
fi
done
elif (( pipestatus_position >= 0 )); then
result_status="${__bats_pipe_eval_pipe_status[$pipestatus_position]}"
else
# Must use positive values for some bash's (like OSX).
local backward_iter_index="$((${#__bats_pipe_eval_pipe_status[@]} + pipestatus_position))"
result_status="${__bats_pipe_eval_pipe_status[$backward_iter_index]}"
fi
return "$result_status"
}
run() { # [!|-N] [--keep-empty-lines] [--separate-stderr] [--] <command to run...>
# This has to be restored on exit from this function to avoid leaking our trap INT into surrounding code.
# Non zero exits won't restore under the assumption that they will fail the test before it can be aborted,
@ -347,8 +471,17 @@ bats_test_begin() {
}
bats_test_function() {
local tags=()
if [[ "$1" == --tags ]]; then
IFS=',' read -ra tags <<<"$2"
shift 2
fi
local test_name="$1"
BATS_TEST_NAMES+=("$test_name")
if [[ "$test_name" == "$BATS_TEST_NAME" ]]; then
# shellcheck disable=SC2034
BATS_TEST_TAGS=("${tags[@]+${tags[@]}}")
fi
}
# decides whether a failed test should be run again

View File

@ -1,7 +1,7 @@
#!/usr/bin/env bash
set -e
export BATS_VERSION='1.9.0'
export BATS_VERSION='1.10.0'
VALID_FORMATTERS="pretty, junit, tap, tap13"
version() {
@ -38,7 +38,7 @@ HELP_TEXT_HEADER
-c, --count Count test cases without running any tests
--code-quote-style <style>
A two character string of code quote delimiters
or 'custom' which requires setting $BATS_BEGIN_CODE_QUOTE and
or 'custom' which requires setting $BATS_BEGIN_CODE_QUOTE and
$BATS_END_CODE_QUOTE. Can also be set via $BATS_CODE_QUOTE_STYLE
--line-reference-format Controls how file/line references e.g. in stack traces are printed:
- comma_line (default): a.bats, line 1
@ -62,7 +62,8 @@ HELP_TEXT_HEADER
Gather the output of failing *and* passing tests
as files in directory (if existing, must be empty)
-h, --help Display this help message
-j, --jobs <jobs> Number of parallel jobs (requires GNU parallel)
-j, --jobs <jobs> Number of parallel jobs (requires GNU parallel or shenwei356/rush)
--parallel-binary-name Name of parallel binary
--no-tempdir-cleanup Preserve test output temporary directory
--no-parallelize-across-files
Serialize test file execution instead of running
@ -133,6 +134,9 @@ fi
arguments=()
# list of single char options that don't expect a value
single_char_flags="hvcprtTx"
# Unpack single-character options bundled together, e.g. -cr, -pr.
for arg in "$@"; do
if [[ "$arg" =~ ^-[^-]. ]]; then
@ -141,6 +145,11 @@ for arg in "$@"; do
if [[ -z "$option" ]]; then
break
fi
if [[ "$single_char_flags" != *$option* && -n "${arg:index}" ]]; then
printf "Error: -%s is not allowed within pack of flags.\n" "$option"
printf " Please put it last (e.g. \`-rF junit\` instead of \`-Fr junit\`), or on its own (\`-r -F junit\`)!\n"
exit 1
fi
arguments+=("-$option")
done
else
@ -212,6 +221,10 @@ while [[ "$#" -ne 0 ]]; do
shift
flags+=('-j' "$1")
;;
--parallel-binary-name)
shift
flags+=('--parallel-binary-name' "$1")
;;
-r | --recursive)
recursive=1
;;

View File

@ -351,10 +351,6 @@ bats_create_file_tempdirs() {
trap 'BATS_INTERRUPTED=true' INT
if [[ -n "$extended_syntax" ]]; then
printf "suite %s\n" "$filename"
fi
BATS_FILE_FIRST_TEST_NUMBER_IN_SUITE=0 # predeclare as Bash 3.2 does not support declare -g
bats_read_tests_list_file
@ -364,6 +360,10 @@ if [[ ${#tests_to_run[@]} -eq 0 ]]; then
exit 0
fi
if [[ -n "$extended_syntax" ]]; then
printf "suite %s\n" "$filename"
fi
# requires the test list to be read but not empty
bats_create_file_tempdirs

View File

@ -4,6 +4,7 @@ set -e
count_only_flag=''
filter=''
num_jobs=${BATS_NUMBER_OF_PARALLEL_JOBS:-1}
parallel_binary_name=${BATS_PARALLEL_BINARY_NAME:-"parallel"}
bats_no_parallelize_across_files=${BATS_NO_PARALLELIZE_ACROSS_FILES-}
bats_no_parallelize_within_files=
filter_status=''
@ -35,6 +36,10 @@ while [[ "$#" -ne 0 ]]; do
num_jobs="$1"
flags+=('-j' "$num_jobs")
;;
--parallel-binary-name)
shift
parallel_binary_name="$1"
;;
-T)
flags+=('-T')
;;
@ -97,7 +102,7 @@ while [[ "$#" -ne 0 ]]; do
done
if [[ "$num_jobs" != 1 ]]; then
if ! type -p parallel >/dev/null && parallel --version &>/dev/null && [[ -z "$bats_no_parallelize_across_files" ]]; then
if ! type -p "${parallel_binary_name}" >/dev/null && "${parallel_binary_name}" --version &>/dev/null && [[ -z "$bats_no_parallelize_across_files" ]]; then
abort "Cannot execute \"${num_jobs}\" jobs without GNU parallel"
fi
# shellcheck source=lib/bats-core/semaphore.bash
@ -441,7 +446,7 @@ if [[ "$num_jobs" -gt 1 ]] && [[ -z "$bats_no_parallelize_across_files" ]]; then
# shellcheck disable=SC2086,SC2068
# we need to handle the quoting of ${flags[@]} ourselves,
# because parallel can only quote it as one
parallel --keep-order --jobs "$num_jobs" bats-exec-file "$(printf "%q " "${flags[@]}")" "{}" "$TESTS_LIST_FILE" ::: "${BATS_UNIQUE_TEST_FILENAMES[@]}" 2>&1 || bats_exec_suite_status=1
"${parallel_binary_name}" --keep-order --jobs "$num_jobs" -- "bats-exec-file" "$(printf "%q " "${flags[@]}")" "{}" "$TESTS_LIST_FILE" <<< "$(printf "%s\n" "${BATS_UNIQUE_TEST_FILENAMES[@]}")" 2>&1 || bats_exec_suite_status=1
else
for filename in "${BATS_UNIQUE_TEST_FILENAMES[@]}"; do
if [[ "${BATS_INTERRUPTED-NOTSET}" != NOTSET ]]; then
@ -455,7 +460,7 @@ fi
set -eET
bats_run_teardown_suite
if [[ "$focus_mode" == 1 && $bats_exec_suite_status -eq 0 ]]; then
if [[ "$focus_mode" == 1 && $bats_exec_suite_status -eq 0 ]]; then
if [[ ${BATS_NO_FAIL_FOCUS_RUN-} == 1 ]]; then
printf "WARNING: This test run only contains tests tagged \`bats:focus\`!\n"
else

View File

@ -132,7 +132,8 @@ bats_exit_trap() {
BATS_TEST_TIME=''
if [[ -n "$BATS_ENABLE_TIMING" ]]; then
BATS_TEST_TIME=" in "$(($(get_mills_since_epoch) - BATS_TEST_START_TIME))"ms"
get_mills_since_epoch BATS_TEST_END_TIME
BATS_TEST_TIME=" in "$((BATS_TEST_END_TIME - BATS_TEST_START_TIME))"ms"
fi
local print_bats_out="${BATS_SHOW_OUTPUT_OF_SUCCEEDING_TESTS}"
@ -157,6 +158,11 @@ bats_exit_trap() {
rm -r "$BATS_TEST_TMPDIR" # clean up for retry
else
printf 'not ok %d %s%s\n' "$BATS_SUITE_TEST_NUMBER" "${BATS_TEST_NAME_PREFIX:-}${BATS_TEST_DESCRIPTION}${BATS_TEST_TIME}" "$exit_metadata" >&3
if (( ${#BATS_TEST_TAGS[@]} > 0 )); then
printf '# tags:'
printf ' %s' "${BATS_TEST_TAGS[@]}"
printf '\n'
fi >&3
local stack_trace
bats_get_failure_stack_trace stack_trace
bats_print_stack_trace "${stack_trace[@]}" >&3
@ -194,7 +200,7 @@ bats_exit_trap() {
if [[ -n "$should_retry" ]]; then
try_suffix="-try$BATS_TEST_TRY_NUMBER"
fi
cp "$BATS_OUT" "$BATS_GATHER_TEST_OUTPUTS_IN/$BATS_SUITE_TEST_NUMBER$try_suffix-$BATS_TEST_DESCRIPTION.log"
cp "$BATS_OUT" "$BATS_GATHER_TEST_OUTPUTS_IN/$BATS_SUITE_TEST_NUMBER$try_suffix-${BATS_TEST_DESCRIPTION/\//%2F}.log"
fi
rm -f "$BATS_OUT"
exit "$status"
@ -280,17 +286,28 @@ bats_abort_timeout_countdown() {
kill -ABRT "$1" &>/dev/null || true
}
get_mills_since_epoch() {
if [[ -n "${EPOCHREALTIME-}" ]]; then
get_mills_since_epoch() { # <output-variable>
local -r output_variable="$1"
local int frac
# allow for different decimal separators
IFS=., read -r int frac <<<"$EPOCHREALTIME"
printf -v "$output_variable" "%d" "${int}${frac::3}"
}
else
get_mills_since_epoch() { # <output-variable>
local -r output_variable="$1"
local ms_since_epoch
ms_since_epoch=$(date +%s%N)
ms_since_epoch=$(bats_execute date +%s%N)
if [[ "$ms_since_epoch" == *N || "${#ms_since_epoch}" -lt 19 ]]; then
ms_since_epoch=$(($(date +%s) * 1000))
ms_since_epoch=$(($(bats_execute date +%s) * 1000))
else
ms_since_epoch=$((ms_since_epoch / 1000000))
fi
printf "%d\n" "$ms_since_epoch"
printf -v "$output_variable" "%d" "$ms_since_epoch"
}
fi
bats_perform_test() {
if ! declare -F "$BATS_TEST_NAME" &>/dev/null; then
@ -323,7 +340,7 @@ bats_perform_test() {
# shellcheck disable=SC2064
trap "bats_teardown_trap as-exit-trap $BATS_killer_pid" EXIT
BATS_TEST_START_TIME=$(get_mills_since_epoch)
get_mills_since_epoch BATS_TEST_START_TIME
"$BATS_TEST_NAME" >>"$BATS_OUT" 2>&1 4>&1
BATS_TEST_COMPLETED=1
@ -342,4 +359,5 @@ exec 3<&1
bats_create_test_tmpdirs
# Run the given test.
bats_evaluate_preprocessed_source
readonly BATS_TEST_TAGS
bats_perform_test

View File

@ -154,6 +154,77 @@ All additional parameters to run should come before the command.
If you want to run a command that starts with `-`, prefix it with `--` to
prevent `run` from parsing it as an option.
THE BATS_PIPE HELPER
--------------
Usage: bats_pipe [OPTIONS] [--] <command0...> [ \| <command1...> [ \| <command2...> [...] ] ]
Options:
-<N> return the exit code from the <N>th command in the chain
of piped commands, instead of default behavior of "the last
non-zero status".
The bats_pipe helper command is meant to handle piping between commands. Its
main purpose is to aide the `run` helper command (which cannot handle pipes,
due to bash parsing priority). `run command0 | command1` will parse `|` before
`run`, which is commonly not intended by test authors.
Running `run bats_pipe command0 \| command1` will have the piped commands run
within the context of the `run` command, and thus have the output and status
variables properly contained within the normal `output` and `status` variables.
Note that this requires the usage of `\|`, not `|`. This is to avoid bash
parsing out `|` first, instead sending `\|` to the bats_pipe command for it to
parse and set up intended piping. Running bats_pipe with no instances of `\|`
will always fail; this is intended to catch typos (accidentally using `|`) by
the test author.
The bats_pipe command will also properly propagate exit status from the piped
commands. The default behavior mimics `set -o pipefail`, returning the status
of the last (rightmost) command that exits with a non-zero status. This ensures
that usage of pipes do not mask the exit statuses of earlier commands.
@test "invoking foo piped to bar" {
run bats_pipe foo \| bar
# asserting foo or bar would return 17 (from foo if bar returns 0).
[ "$status" -eq 17 ]
[ "$output" = "bar output." ]
}
Alternatively, if the test always cares about the status of a specific command,
the -<N> option can be given (e.g. -0) to always return the status of the
command of interest.
@test "invoking foo piped to bar always return foo status" {
run bats_pipe -0 foo \| bar
# status of bar is ignored, status is always from foo.
[ "$status" -eq 2 ]
[ "$output" = "bar output." ]
}
Similarly, --returned-status N (or --returned-status=N) can be used for similar
functionality. This option supports negative values, which always return the
of the command starting from the end and in reverse order.
@test "invoking foo piped to bar always return foo status" {
run bats_pipe --returned-status -2 foo \| bar
# status of bar is ignored, status is always from foo.
[ "$status" -eq 2 ]
[ "$output" = "bar output." ]
}
Piping of command output is especially helpful when the output needs to be
modified in some way (e.g. the command outputs binary data into stdout, which
cannot be stored as-is in an environment variable).
@test "invoking foo that returns binary data" {
run bats_pipe foo \| hexdump -v -e "1/1 \"0x%02X \""
[ "$status" -eq 17 ]
[[ "$output" =~ 0xDE\ 0xAD ]]
}
Any number of pipes can be used in conjunction to chain output between some set
of running commands.
THE LOAD COMMAND
----------------
@ -317,6 +388,7 @@ in the test file.
* `$BATS_FILE_EXTENSION` (default: `bats`) specifies the extension of
test files that should be found when running a suite (via
`bats [-r] suite_folder/`)
* `$BATS_TEST_TAGS` the tags of the current test.
* `$BATS_SUITE_TMPDIR` is a temporary directory common to all tests of a suite.
Could be used to create files required by multiple tests.
* `$BATS_FILE_TMPDIR` is a temporary directory common to all tests of a test file.

View File

@ -1,6 +1,6 @@
{
"name": "bats",
"version": "1.9.0",
"version": "1.10.0",
"description": "Bash Automated Testing System",
"homepage": "https://github.com/bats-core/bats-core#readme",
"license": "MIT",

View File

@ -667,6 +667,7 @@ END_OF_ERR_MSG
[ "${lines[4]}" = "# /usr/local/bin:/usr/bin:/bin" ]
}
# bats test_tags=no-kcov
@test "Test nounset does not trip up bats' internals (see #385)" {
# don't export nounset within this file or we might trip up the testsuite itself,
# getting bad diagnostics
@ -731,7 +732,7 @@ END_OF_ERR_MSG
}
@test "Parallel mode works on MacOS with over subscription (issue #433)" {
type -p parallel &>/dev/null || skip "--jobs requires GNU parallel"
type -p "${BATS_PARALLEL_BINARY_NAME:-"parallel"}" &>/dev/null || skip "--jobs requires GNU parallel"
(type -p flock &>/dev/null || type -p shlock &>/dev/null) || skip "--jobs requires flock/shlock"
reentrant_run bats -j 2 "$FIXTURE_ROOT/issue-433"
@ -788,7 +789,7 @@ END_OF_ERR_MSG
[ "${lines[1]}" == "not ok 1 test" ]
# due to scheduling the exact line will vary but we should exit with 130
[[ "${lines[2]}" == "# (in test file "*")" ]] || false
[[ "${lines[2]}" == "# (in test file "*")" ]] || false
[[ "${lines[3]}" == *"failed with status 130" ]] || false
[ "${lines[4]}" == "# Received SIGINT, aborting ..." ]
[ ${#lines[@]} -eq 5 ]
@ -1134,6 +1135,14 @@ END_OF_ERR_MSG
[ "$(find "$OUTPUT_DIR" -type f | wc -l)" -eq 1 ]
}
@test "--gather-test-output-in works with slashes in test names" {
local OUTPUT_DIR="$BATS_TEST_TMPDIR/logs"
bats_require_minimum_version 1.5.0
reentrant_run -0 bats --gather-test-outputs-in "$OUTPUT_DIR" "$FIXTURE_ROOT/test_with_slash.bats"
[ -e "$OUTPUT_DIR/1-test with %2F in name.log" ]
}
@test "Tell about missing flock and shlock" {
if ! command -v parallel; then
skip "this test requires GNU parallel to be installed"
@ -1525,7 +1534,7 @@ enforce_own_process_group() {
@test "Focus tests filter out other tests and override exit code" {
bats_require_minimum_version 1.5.0
# expect exit 1: focus mode always fails tests
# expect exit 1: focus mode always fails tests
reentrant_run -1 bats "$FIXTURE_ROOT/focus.bats"
[ "${lines[0]}" == "WARNING: This test run only contains tests tagged \`bats:focus\`!" ]
[ "${lines[1]}" == '1..1' ]
@ -1562,3 +1571,15 @@ enforce_own_process_group() {
[[ "${output}" = *"ERROR: command \`$REPORT_FORMATTER\` failed with status 11"* ]] || false
}
@test "Short opt unpacker rejects valued options" {
bats_require_minimum_version 1.5.0
reentrant_run ! bats "$FIXTURE_ROOT/passing.bats" -Fr tap
[[ "${output}" == *"Error: -F is not allowed within pack of flags."* ]] || false
reentrant_run -0 bats "$FIXTURE_ROOT/passing.bats" -rF tap
}
@test "Test timing does not break when overriding date on path" {
bats "$FIXTURE_ROOT/override_date_on_path.bats"
}

1410
test/bats_pipe.bats Normal file

File diff suppressed because it is too large Load Diff

70
test/cat-formatter.bats Normal file
View File

@ -0,0 +1,70 @@
load 'test_helper'
fixtures bats # reuse bats fixtures
@test "passing test" {
reentrant_run bats --formatter cat "${FIXTURE_ROOT}/passing.bats"
[ "${lines[0]}" == '1..1' ]
[ "${lines[1]}" == "suite ${FIXTURE_ROOT}/passing.bats" ]
[ "${lines[2]}" == 'begin 1 a passing test' ]
[ "${lines[3]}" == 'ok 1 a passing test' ]
[ "${#lines[@]}" -eq 4 ]
}
@test "failing test" {
reentrant_run bats --formatter cat "${FIXTURE_ROOT}/failing.bats"
[ "${lines[0]}" == '1..1' ]
[ "${lines[1]}" == "suite ${FIXTURE_ROOT}/failing.bats" ]
[ "${lines[2]}" == 'begin 1 a failing test' ]
[ "${lines[3]}" == 'not ok 1 a failing test' ]
[ "${lines[4]}" == "# (in test file ${RELATIVE_FIXTURE_ROOT}/failing.bats, line 4)" ]
[ "${lines[5]}" == "# \`eval \"( exit \${STATUS:-1} )\"' failed" ]
[ "${#lines[@]}" -eq 6 ]
}
@test "passing test with timing" {
reentrant_run bats --formatter cat --timing "${FIXTURE_ROOT}/passing.bats"
[ "${lines[0]}" == '1..1' ]
[ "${lines[1]}" == "suite ${FIXTURE_ROOT}/passing.bats" ]
[ "${lines[2]}" == 'begin 1 a passing test' ]
[ "${lines[3]::23}" == 'ok 1 a passing test in ' ]
[ "${lines[3]: -2}" == 'ms' ]
[ "${#lines[@]}" -eq 4 ]
}
@test "failing test with timing" {
reentrant_run bats --formatter cat --timing "${FIXTURE_ROOT}/failing.bats"
[ "${lines[0]}" == '1..1' ]
[ "${lines[1]}" == "suite ${FIXTURE_ROOT}/failing.bats" ]
[ "${lines[2]}" == 'begin 1 a failing test' ]
[ "${lines[3]::27}" == 'not ok 1 a failing test in ' ]
[ "${lines[3]: -2}" == 'ms' ]
[ "${lines[4]}" == "# (in test file ${RELATIVE_FIXTURE_ROOT}/failing.bats, line 4)" ]
[ "${lines[5]}" == "# \`eval \"( exit \${STATUS:-1} )\"' failed" ]
[ "${#lines[@]}" -eq 6 ]
}
@test "Cat formatter prints the extended tap stream" {
cd "$BATS_ROOT/libexec/bats-core/"
local formatter="bats-format-cat"
reentrant_run bash -u "$formatter" <<EOF
1..1
suite "$FIXTURE_ROOT/failing.bats"
# output from setup_file
begin 1 test_a_failing_test
# fd3 output from test
not ok 1 a failing test
# (in test file test/fixtures/bats/failing.bats, line 4)
# \`eval "( exit ${STATUS:-1} )"' failed
begin 2 test_a_successful_test
ok 2 a succesful test
unknown line
EOF
[[ "${#lines[@]}" -eq 11 ]]
}

View File

@ -1,6 +1,6 @@
@test "BATS_* variables don't contain double slashes" {
for var_name in ${!BATS_@}; do
local var_value="${!var_name}"
local var_value="${!var_name-}"
if [[ "$var_value" == *'//'* ]]; then
echo "$var_name contains // ${#var_value}: ${var_value}" && false

3
test/fixtures/bats/date vendored Executable file
View File

@ -0,0 +1,3 @@
#!/usr/bin/env bash
echo "dummy date"

View File

@ -0,0 +1,11 @@
setup() {
export PATH
PATH="$(dirname "$BATS_TEST_FILENAME"):$PATH"
}
@test "dummy" {
echo "$PATH"
run -0 date
echo "$output"
[ "${output}" = 'dummy date' ]
}

View File

@ -0,0 +1,3 @@
@test "test with / in name" {
true
}

40
test/fixtures/formatter/echo-formatter vendored Executable file
View File

@ -0,0 +1,40 @@
#!/usr/bin/env bash
set -e
# shellcheck source=lib/bats-core/formatter.bash
source "$BATS_ROOT/lib/bats-core/formatter.bash"
bats_tap_stream_plan() {
echo "STREAM_PLAN: $1"
}
bats_tap_stream_begin() {
echo "STREAM_BEGIN: index: ${1}, name: ${2}"
}
bats_tap_stream_ok() {
echo "STREAM_OK: index ${1}, name: ${2}"
}
bats_tap_stream_skipped() {
echo "STREAM_SKIPPED: index ${1}, name ${2}, reason ${3}"
}
bats_tap_stream_not_ok() {
echo "STREAM_NOT_OK: index ${1}, name ${2}"
}
bats_tap_stream_comment() { # <comment> <scope>
echo "STREAM_COMMENT: comment ${1}, scope ${2}"
}
bats_tap_stream_suite() {
echo "STREAM_SUITE: file ${1}"
}
bats_tap_stream_unknown() { # <full line> <scope>
echo "STREAM_UNKNOWN: ${1}, scope: ${2}"
}
bats_parse_internal_extended_tap

8
test/fixtures/formatter/retry.bats vendored Normal file
View File

@ -0,0 +1,8 @@
#!/usr/bin/env bats
# shellcheck disable=SC2034
BATS_TEST_RETRIES=1
@test "test foobar" {
false
}

View File

@ -2,22 +2,23 @@
@test "first test in file 2" {
echo "BATS_TEST_NUMBER=$BATS_TEST_NUMBER"
[[ "$BATS_TEST_NUMBER" == 1 ]]
[ "$BATS_TEST_NUMBER" -eq 1 ]
echo "BATS_SUITE_TEST_NUMBER=$BATS_SUITE_TEST_NUMBER"
[[ "$BATS_SUITE_TEST_NUMBER" == 4 ]]
[ "$BATS_SUITE_TEST_NUMBER" -eq 4 ]
}
@test "second test in file 2" {
[[ "$BATS_TEST_NUMBER" == 2 ]]
[[ "$BATS_SUITE_TEST_NUMBER" == 5 ]]
[ "$BATS_TEST_NUMBER" -eq 2 ]
[ "$BATS_SUITE_TEST_NUMBER" -eq 5 ]
}
@test "second test in file 3" {
[[ "$BATS_TEST_NUMBER" == 3 ]]
[[ "$BATS_SUITE_TEST_NUMBER" == 6 ]]
[ "$BATS_TEST_NUMBER" -eq 3 ]
[ "$BATS_SUITE_TEST_NUMBER" -eq 6 ]
}
@test "BATS_TEST_NAMES is per file" {
echo "${#BATS_TEST_NAMES[@]}"
[[ "${#BATS_TEST_NAMES[@]}" == 4 ]]
echo "${#BATS_TEST_NAMES[@]} ${BATS_TEST_NAMES[0]}"
[ "${#BATS_TEST_NAMES[@]}" -eq 4 ]
[ "${BATS_TEST_NAMES[0]}" == test_first_test_in_file_2 ]
}

View File

@ -0,0 +1,26 @@
setup() {
declare -p BATS_TEST_TAGS
}
@test "no tags" {
[ ${#BATS_TEST_TAGS[@]} -eq 0 ]
}
# bats test_tags=test_tag
@test "only test tags" {
[ ${#BATS_TEST_TAGS[@]} -eq 1 ]
[ "${BATS_TEST_TAGS[0]}" == test_tag ]
}
# bats file_tags=file_tag
@test "only file tags" {
[ ${#BATS_TEST_TAGS[@]} -eq 1 ]
[ "${BATS_TEST_TAGS[0]}" == file_tag ]
}
# bats test_tags=test_tag
@test "test and file tags" {
[ ${#BATS_TEST_TAGS[@]} -eq 2 ]
[ "${BATS_TEST_TAGS[0]}" == file_tag ]
[ "${BATS_TEST_TAGS[1]}" == test_tag ]
}

View File

@ -0,0 +1,5 @@
# bats file_tags=file_tag
# bats test_tags=test_tag
@test error {
false
}

View File

@ -99,3 +99,16 @@ EOF
reentrant_run -1 bats "$FIXTURE_ROOT/passing.bats" --formatter "$non_executable"
[ "$output" = "ERROR: Formatter '$non_executable' is not executable!" ]
}
@test "retrying tests does not mess up test names" {
bats_require_minimum_version 1.5.0
reentrant_run -1 bats "$FIXTURE_ROOT/retry.bats" --formatter "$FIXTURE_ROOT/echo-formatter"
[ "${lines[0]}" = 'STREAM_PLAN: 1' ]
[ "${lines[1]}" = "STREAM_SUITE: file $FIXTURE_ROOT/retry.bats" ]
[ "${lines[2]}" = 'STREAM_BEGIN: index: 1, name: test foobar' ]
[ "${lines[3]}" = 'STREAM_BEGIN: index: 1, name: test foobar' ]
[ "${lines[4]}" = 'STREAM_NOT_OK: index 1, name test foobar' ]
[ "${lines[5]}" = "STREAM_COMMENT: comment (in test file $RELATIVE_FIXTURE_ROOT/retry.bats, line 7), scope not_ok" ]
[ "${lines[6]}" = "STREAM_COMMENT: comment \`false' failed, scope not_ok" ]
[ "${#lines[@]}" -eq 7 ]
}

View File

@ -9,7 +9,7 @@ fixtures parallel
BATS_TEST_TIMEOUT=10 # only intended for the "short form ..."" test
setup() {
(type -p parallel &>/dev/null && parallel --version &>/dev/null) || skip "--jobs requires GNU parallel"
(type -p "${BATS_PARALLEL_BINARY_NAME:-"parallel"}" &>/dev/null && "${BATS_PARALLEL_BINARY_NAME:-"parallel"}" --version &>/dev/null) || skip "--jobs requires GNU parallel"
(type -p flock &>/dev/null || type -p shlock &>/dev/null) || skip "--jobs requires flock/shlock"
}
@ -212,9 +212,9 @@ check_parallel_tests() { # <expected maximum parallelity>
DISABLE_IN_TEST_FUNCTION=1 reentrant_run ! bats --jobs 2 "$FIXTURE_ROOT/must_not_parallelize_within_file.bats"
}
@test "Short form typo does not run endlessly" {
@test "Negative jobs number does not run endlessly" {
unset BATS_NO_PARALLELIZE_ACROSS_FILES
run bats -j2 "$FIXTURE_ROOT/../bats/passing.bats"
run bats -j -3 "$FIXTURE_ROOT/../bats/passing.bats"
(( SECONDS < 5 ))
[ "${lines[1]}" = 'Invalid number of jobs: -2' ]
[ "${lines[1]}" = 'Invalid number of jobs: -3' ]
}

View File

@ -19,21 +19,19 @@ bats_require_minimum_version 1.5.0
[ ${#lines[@]} -eq 3 ]
}
@test "run --keep-empty-lines preserves trailing empty lines" {
@test "run --keep-empty-lines does not count trailing newline as extra line (see #708)" {
run --keep-empty-lines -- echo -n $'a\n'
printf "'%s'\n" "${lines[@]}"
[ "${lines[0]}" == a ]
[ "${lines[1]}" == '' ]
[ ${#lines[@]} -eq 2 ]
[ ${#lines[@]} -eq 1 ]
}
@test "run --keep-empty-lines preserves multiple trailing empty lines" {
@test "run --keep-empty-lines preserves trailing empty line" {
run --keep-empty-lines -- echo -n $'a\n\n'
printf "'%s'\n" "${lines[@]}"
[ "${lines[0]}" == a ]
[ "${lines[1]}" == '' ]
[ "${lines[2]}" == '' ]
[ ${#lines[@]} -eq 3 ]
[ ${#lines[@]} -eq 2 ]
}
@test "run --keep-empty-lines preserves non-empty trailing line" {

View File

@ -73,3 +73,13 @@ setup() {
[ "${lines[2]}" = 'ok 2 Only test tags' ]
[ "${#lines[@]}" -eq 3 ]
}
@test "BATS_TEST_TAGS are set correctly" {
run -0 bats "$FIXTURE_ROOT/BATS_TEST_TAGS.bats"
}
@test "Print tags on error" {
run -1 bats "$FIXTURE_ROOT/print_tags_on_error.bats"
[ "${lines[2]}" = '# tags: file_tag test_tag' ]
}

View File

@ -45,7 +45,7 @@ execute_with_unset_bats_vars() { # <command to execute...>
"$@"
}
REENTRANT_RUN_PRESERVE+=(BATS_ROOT)
REENTRANT_RUN_PRESERVE+=(BATS_SAVED_PATH BATS_ROOT BATS_TEST_TAGS BATS_PARALLEL_BINARY_NAME)
# call run with all BATS_* variables purged from the environment
reentrant_run() { # <same args as run>