pax_global_header00006660000000000000000000000064137006302230014506gustar00rootroot0000000000000052 comment=dcaec03e32e0b152f8ef9cf14b75296cf5caeaff bats-core-1.2.1/000077500000000000000000000000001370063022300133665ustar00rootroot00000000000000bats-core-1.2.1/.appveyor.yml000066400000000000000000000010421370063022300160310ustar00rootroot00000000000000version: 'v1.2.1+appveyor.{build}' build: off # This presumes that Git bash is installed at `C:\Program Files\Git` and the # bash we're using is `C:\Program Files\Git\bin\bash.exe`. # # If instead it finds the Windows Subsystem for Linux bash at # `C:\Windows\System32\bash.exe`, it will fail with an error like: # /mnt/c/.../bats-core/test/test_helper.bash: line 1: # syntax error near unexpected token `$'{\r'' test_script: - where bash - bash --version - bash -c 'export' - bash -c 'time PATH="/usr/bin:${PATH}" bin/bats test' bats-core-1.2.1/.devcontainer/000077500000000000000000000000001370063022300161255ustar00rootroot00000000000000bats-core-1.2.1/.devcontainer/Dockerfile000066400000000000000000000010071370063022300201150ustar00rootroot00000000000000ARG bashver=latest FROM bash:${bashver} # Install parallel and accept the citation notice (we aren't using this in a # context where it make sense to cite GNU Parallel). 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 RUN ln -s /opt/bats/bin/bats /usr/sbin/bats COPY . /opt/bats/ ENTRYPOINT ["bash", "/usr/sbin/bats"] bats-core-1.2.1/.devcontainer/devcontainer.json000066400000000000000000000001231370063022300214750ustar00rootroot00000000000000{ "name": "Bats core development environment", "dockerFile": "Dockerfile" }bats-core-1.2.1/.editorconfig000066400000000000000000000012571370063022300160500ustar00rootroot00000000000000root = true [*] end_of_line = lf indent_style = space indent_size = 2 insert_final_newline = true max_line_length = 80 trim_trailing_whitespace = true # The JSON files contain newlines inconsistently [*.json] indent_size = 2 insert_final_newline = ignore # YAML [*.{yml,yaml}] indent_style = space indent_size = 2 # Makefiles always use tabs for recipe indentation [{Makefile,*.mak}] indent_style = tab # Markdown [*.{md,rmd,mkd,mkdn,mdwn,mdown,markdown,litcoffee}] max_line_length = 80 # tabs behave as if they were replaced by spaces with a tab stop of 4 characters tab_width = 4 # trailing spaces indicates word wrap trim_trailing_spaces = false trim_trailing_whitespace = false bats-core-1.2.1/.gitattributes000077500000000000000000000000511370063022300162600ustar00rootroot00000000000000* text=auto *.sh eol=lf libexec/* eol=lf bats-core-1.2.1/.gitignore000066400000000000000000000000341370063022300153530ustar00rootroot00000000000000docker-compose.override.yml bats-core-1.2.1/.travis.yml000066400000000000000000000014401370063022300154760ustar00rootroot00000000000000language: bash os: - linux env: - BASHVER= - BASHVER=3.2 - BASHVER=4.0 - BASHVER=4.1 - BASHVER=4.2 - BASHVER=4.3 - BASHVER=4.4 - BASHVER=5 matrix: include: - os: osx services: - docker before_script: - | if [[ "${TRAVIS_OS_NAME:-}" == 'linux' ]]; then sudo apt-get install shellcheck fi script: - | if [[ "${TRAVIS_OS_NAME:-}" == 'linux' ]]; then ./shellcheck.sh fi if [[ "${TRAVIS_OS_NAME:-}" == 'linux' && -n "${BASHVER}" ]]; then docker build --build-arg bashver="${BASHVER}" --tag "bats/bats:bash-${BASHVER}" . && docker run -it "bash:${BASHVER}" --version && time docker run -it "bats/bats:bash-${BASHVER}" --tap /opt/bats/test else time bin/bats --formatter tap test fi notifications: email: on_success: never bats-core-1.2.1/AUTHORS000066400000000000000000000003331370063022300144350ustar00rootroot00000000000000Andrew Martin (https://control-plane.io/) Bianca Tamayo (https://biancatamayo.me/) Jason Karns (http://jasonkarns.com/) Mike Bland (https://mike-bland.com/) bats-core-1.2.1/Dockerfile000066400000000000000000000006021370063022300153560ustar00rootroot00000000000000ARG bashver=latest FROM bash:${bashver} # Install parallel and accept the citation notice (we aren't using this in a # context where it make sense to cite GNU Parallel). RUN apk add --no-cache parallel ncurses && \ mkdir -p ~/.parallel && touch ~/.parallel/will-cite RUN ln -s /opt/bats/bin/bats /usr/local/bin/bats COPY . /opt/bats/ WORKDIR /code/ ENTRYPOINT ["bash", "bats"] bats-core-1.2.1/LICENSE.md000066400000000000000000000047471370063022300150060ustar00rootroot00000000000000Copyright (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 bats-core-1.2.1/README.md000066400000000000000000000556501370063022300146600ustar00rootroot00000000000000> # :warning: WARNING: documentation of unreleased features ahead > > This is the current development version. You can find the documentation for v1.2.0 [here](../v1.2.0/README.md). > Please refer to [this list](docs/versions.md) for older versions. # Bats-core: Bash Automated Testing System (2018) [![Latest release](https://img.shields.io/github/release/bats-core/bats-core.svg)](https://github.com/bats-core/bats-core/releases/latest) [![npm package](https://img.shields.io/npm/v/bats.svg)](https://www.npmjs.com/package/bats) [![License](https://img.shields.io/github/license/bats-core/bats-core.svg)](https://github.com/bats-core/bats-core/blob/master/LICENSE.md) [![Continuous integration status for Linux and macOS](https://img.shields.io/travis/bats-core/bats-core/master.svg?label=travis%20build)](https://travis-ci.org/bats-core/bats-core) [![Continuous integration status for Windows](https://img.shields.io/appveyor/ci/bats-core/bats-core/master.svg?label=appveyor%20build)](https://ci.appveyor.com/project/bats-core/bats-core) [![Join the chat in bats-core/bats-core on gitter](https://badges.gitter.im/bats-core/bats-core.svg)][gitter] 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. [TAP]: https://testanything.org A Bats test file is a Bash script with special syntax for defining test cases. Under the hood, each test case is just a function with a description. ```bash #!/usr/bin/env bats @test "addition using bc" { result="$(echo 2+2 | bc)" [ "$result" -eq 4 ] } @test "addition using dc" { result="$(echo 2 2+p | dc)" [ "$result" -eq 4 ] } ``` Bats is most useful when testing software written in Bash, but you can use it to test any UNIX program. Test cases consist of standard shell commands. Bats makes use of Bash's `errexit` (`set -e`) option when running test cases. If every command in the test case exits with a `0` status code (success), the test passes. In this way, each line is an assertion of truth. ## Table of contents - [Installation](#installation) * [Supported Bash versions](#supported-bash-versions) * [Homebrew](#homebrew) * [npm](#npm) * [Installing Bats from source](#installing-bats-from-source) * [Installing Bats from source onto Windows Git Bash](#installing-bats-from-source-onto-windows-git-bash) * [Running Bats in Docker](#running-bats-in-docker) + [Building a Docker image](#building-a-docker-image) - [Usage](#usage) * [Parallel Execution](#parallel-execution) - [Writing tests](#writing-tests) * [`run`: Test other commands](#run-test-other-commands) * [`load`: Share common code](#load-share-common-code) * [`skip`: Easily skip tests](#skip-easily-skip-tests) * [`setup` and `teardown`: Pre- and post-test hooks](#setup-and-teardown-pre--and-post-test-hooks) * [Code outside of test cases](#code-outside-of-test-cases) * [File descriptor 3 (read this if Bats hangs)](#file-descriptor-3-read-this-if-bats-hangs) * [Printing to the terminal](#printing-to-the-terminal) * [Special variables](#special-variables) * [Libraries and Add-ons](#libraries-and-add-ons) - [Testing](#testing) - [Support](#support) - [Contributing](#contributing) - [Contact](#contact) - [Version history](#version-history) - [Background](#background) * [What's the plan and why?](#whats-the-plan-and-why) * [Why was this fork created?](#why-was-this-fork-created) - [Copyright](#copyright) ## Installation ### Supported Bash versions The following is a list of Bash versions that are currently supported by Bats. This list is composed of platforms that Bats has been tested on and is known to work on without issues. - Bash versions: - Everything from `3.2.57(1)` and higher (macOS's highest version) - Operating systems: - Arch Linux - Alpine Linux - Ubuntu Linux - FreeBSD `10.x` and `11.x` - macOS - Windows 10 - Latest version for the following Windows platforms: - Git for Windows Bash (MSYS2 based) - Windows Subsystem for Linux - MSYS2 - Cygwin ### Homebrew On macOS, you can install [Homebrew](https://brew.sh/) if you haven't already, then run: ```bash $ brew install bats-core ``` ### npm You can install the [Bats npm package](https://www.npmjs.com/package/bats) via: ``` # To install globally: $ npm install -g bats # To install into your project and save it as one of the "devDependencies" in # your package.json: $ npm install --save-dev bats ``` ### Installing Bats from source Check out a copy of the Bats repository. Then, either add the Bats `bin` directory to your `$PATH`, or run the provided `install.sh` command with the location to the prefix in which you want to install Bats. For example, to install Bats into `/usr/local`, $ git clone https://github.com/bats-core/bats-core.git $ cd bats-core $ ./install.sh /usr/local __Note:__ You may need to run `install.sh` with `sudo` if you do not have permission to write to the installation prefix. ### Installing Bats from source onto Windows Git Bash Check out a copy of the Bats repository and install it to `$HOME`. This will place the `bats` executable in `$HOME/bin`, which should already be in `$PATH`. $ git clone https://github.com/bats-core/bats-core.git $ cd bats-core $ ./install.sh $HOME ### Running Bats in Docker There is an official image on the Docker Hub: $ docker run -it bats/bats:latest --version #### Building a Docker image Check out a copy of the Bats repository, then build a container image: $ git clone https://github.com/bats-core/bats-core.git $ cd bats-core $ docker build --tag bats/bats:latest . This creates a local Docker image called `bats/bats:latest` based on [Alpine Linux](https://github.com/gliderlabs/docker-alpine/blob/master/docs/usage.md) (to push to private registries, tag it with another organisation, e.g. `my-org/bats:latest`). To run Bats' internal test suite (which is in the container image at `/opt/bats/test`): $ docker run -it bats/bats:latest /opt/bats/test To run a test suite from a directory called `test` in the current directory of your local machine, mount in a volume and direct Bats to its path inside the container: $ docker run -it -v "${PWD}:/code" bats/bats:latest test > `/code` is the working directory of the Docker image. "${PWD}/test" is the > location of the test directory on the local machine. This is a minimal Docker image. If more tools are required this can be used as a base image in a Dockerfile using `FROM `. In the future there may be images based on Debian, and/or with more tools installed (`curl` and `openssl`, for example). If you require a specific configuration please search and +1 an issue or [raise a new issue](https://github.com/bats-core/bats-core/issues). Further usage examples are in [the wiki](https://github.com/bats-core/bats-core/wiki/Docker-Usage-Examples). ## Usage Bats comes with two manual pages. After installation you can view them with `man 1 bats` (usage manual) and `man 7 bats` (writing test files manual). Also, you can view the available command line options that Bats supports by calling Bats with the `-h` or `--help` options. These are the options that Bats currently supports: ``` Bats x.y.z Usage: bats [OPTIONS] bats [-h | -v] is the path to a Bats test file, or the path to a directory containing Bats test files (ending with ".bats") -c, --count Count test cases without running any tests -f, --filter Only run tests that match the regular expression -F, --formatter Switch between formatters: pretty (default), tap (default w/o term), junit -h, --help Display this help message -j, --jobs Number of parallel jobs (requires GNU parallel) --parallel-preserve-environment Preserve the current environment for "--jobs" (run `parallel --record-env` before) --no-tempdir-cleanup Preserve test output temporary directory -o, --output Directory to write report files -p, --pretty Shorthand for "--formatter pretty" -r, --recursive Include tests in subdirectories -t, --tap Shorthand for "--formatter tap" -T, --timing Add timing information to tests -v, --version Display the version number For more information, see https://github.com/bats-core/bats-core ``` To run your tests, invoke the `bats` interpreter with one or more paths to test files ending with the `.bats` extension, or paths to directories containing test files. (`bats` will only execute `.bats` files at the top level of each directory; it will not recurse unless you specify the `-r` flag.) Test cases from each file are run sequentially and in isolation. If all the test cases pass, `bats` exits with a `0` status code. If there are any failures, `bats` exits with a `1` status code. When you run Bats from a terminal, you'll see output as each test is performed, with a check-mark next to the test's name if it passes or an "X" if it fails. $ bats addition.bats ✓ addition using bc ✓ addition using dc 2 tests, 0 failures If Bats is not connected to a terminal—in other words, if you run it from a continuous integration system, or redirect its output to a file—the results are displayed in human-readable, machine-parsable [TAP format][TAP]. You can force TAP output from a terminal by invoking Bats with the `--formatter tap` option. $ bats --formatter tap addition.bats 1..2 ok 1 addition using bc ok 2 addition using dc By combining `-T` and `--formatter junit`, it is possible to output junit-compatible report files. $ bats --formatter junit -T addition.bats 1..2 ok 1 addition using bc ok 2 addition using dc Test reports will be output in the executing directory, but may be placed elsewhere by specifying the `--output` flag. $ bats --formatter junit -T addition.bats --output /tmp 1..2 ok 1 addition using bc ok 2 addition using dc ### Parallel Execution By default, Bats will execute your tests serially. However, Bats supports parallel execution of tests (provided you have [GNU parallel][gnu-parallel] or a compatible replacement installed) using the `--jobs` parameter. This can result in your tests completing faster (depending on your tests and the testing hardware). Ordering of parallised tests is not guaranteed, so this mode may break suites with dependencies between tests (or tests that write to shared locations). When enabling `--jobs` for the first time be sure to re-run bats multiple times to identify any inter-test dependencies or non-deterministic test behaviour. If your code relies on variables from the environment, or from `setup_file()`, you need to specify `--parallel-preserve-environment` as well. Note that this requires running `parallel --record-env` first as a setup step as GNU Parallel will refuse to run without. Only environment variables that were **not** set during this setup step will be preserved! [gnu-parallel]: https://www.gnu.org/software/parallel/ ## Writing tests Each Bats test file is evaluated _n+1_ times, where _n_ is the number of test cases in the file. The first run counts the number of test cases, then iterates over the test cases and executes each one in its own process. For more details about how Bats evaluates test files, see [Bats Evaluation Process][bats-eval] on the wiki. For sample test files, see [examples](/docs/examples). [bats-eval]: https://github.com/bats-core/bats-core/wiki/Bats-Evaluation-Process ### `run`: Test other commands Many Bats tests need to run a command and then make assertions about its exit status and output. Bats includes a `run` helper that invokes its arguments as a command, saves the exit status and output into special global variables, and then returns with a `0` status code so you can continue to make assertions in your test case. For example, let's say you're testing that the `foo` command, when passed a nonexistent filename, exits with a `1` status code and prints an error message. ```bash @test "invoking foo with a nonexistent file prints an error" { run foo nonexistent_filename [ "$status" -eq 1 ] [ "$output" = "foo: no such file 'nonexistent_filename'" ] } ``` The `$status` variable contains the status code of the command, and the `$output` variable contains the combined contents of the command's standard output and standard error streams. A third special variable, the `$lines` array, is available for easily accessing individual lines of output. For example, if you want to test that invoking `foo` without any arguments prints usage information on the first line: ```bash @test "invoking foo without arguments prints usage" { run foo [ "$status" -eq 1 ] [ "${lines[0]}" = "usage: foo " ] } ``` __Note:__ The `run` helper executes its argument(s) in a subshell, so if writing tests against environmental side-effects like a variable's value being changed, these changes will not persist after `run` completes. ### `load`: Share common code You may want to share common code across multiple test files. Bats includes a convenient `load` command for sourcing a Bash source file relative to the location of the current test file. For example, if you have a Bats test in `test/foo.bats`, the command ```bash load test_helper.bash ``` will source the script `test/test_helper.bash` in your test file. This can be useful for sharing functions to set up your environment or load fixtures. `load` delegates to Bash's `source` command after resolving relative paths. > For backwards compatibility `load` first searches for a file ending in > `.bash` (e.g. `load test_helper` searches for `test_helper.bash` before > it looks for `test_helper`). This behaviour is deprecated and subject to > change, please use exact filenames instead. ### `skip`: Easily skip tests Tests can be skipped by using the `skip` command at the point in a test you wish to skip. ```bash @test "A test I don't want to execute for now" { skip run foo [ "$status" -eq 0 ] } ``` Optionally, you may include a reason for skipping: ```bash @test "A test I don't want to execute for now" { skip "This command will return zero soon, but not now" run foo [ "$status" -eq 0 ] } ``` Or you can skip conditionally: ```bash @test "A test which should run" { if [ foo != bar ]; then skip "foo isn't bar" fi run foo [ "$status" -eq 0 ] } ``` __Note:__ `setup` and `teardown` hooks still run for skipped tests. ### `setup` and `teardown`: Pre- and post-test hooks You can define special `setup` and `teardown` functions, which run before and after each test case, respectively. Use these to load fixtures, set up your environment, and clean up when you're done. You can also define `setup_file` and `teardown_file`, which will run once before the first test's `setup` and after the last test's `teardown` for the containing file. Variables that are defined in `setup_file` will be visible to all following functions (`setup`, the test itself, `teardown`, `teardown_file`).
Example of setup/setup_file/teardown/teardown_file call order For example the following call order would result from two files (file 1 with tests 1 and 2, and file 2 with test3) beeing tested: ``` setup_file # from file 1, on entering file 1 setup test1 teardown setup test2 teardown teardown_file # from file 1, on leaving file 1 setup_file # from file 2, on enter file 2 setup test3 teardown teardown_file # from file 2, on leaving file 2 ```
### Code outside of test cases You can include code in your test file outside of `@test` functions. For example, this may be useful if you want to check for dependencies and fail immediately if they're not present. However, any output that you print in code outside of `@test`, `setup` or `teardown` functions must be redirected to `stderr` (`>&2`). Otherwise, the output may cause Bats to fail by polluting the TAP stream on `stdout`. ### File descriptor 3 (read this if Bats hangs) Bats makes a separation between output from the code under test and output that forms the TAP stream (which is produced by Bats internals). This is done in order to produce TAP-compliant output. In the [Printing to the terminal](#printing-to-the-terminal) section, there are details on how to use file descriptor 3 to print custom text properly. A side effect of using file descriptor 3 is that, under some circumstances, it can cause Bats to block and execution to seem dead without reason. This can happen if a child process is spawned in the background from a test. In this case, the child process will inherit file descriptor 3. Bats, as the parent process, will wait for the file descriptor to be closed by the child process before continuing execution. If the child process takes a lot of time to complete (eg if the child process is a `sleep 100` command or a background service that will run indefinitely), Bats will be similarly blocked for the same amount of time. **To prevent this from happening, close FD 3 explicitly when running any command that may launch long-running child processes**, e.g. `command_name 3>&-` . ### Printing to the terminal Bats produces output compliant with [version 12 of the TAP protocol][TAP]. The produced TAP stream is by default piped to a pretty formatter for human consumption, but if Bats is called with the `-t` flag, then the TAP stream is directly printed to the console. This has implications if you try to print custom text to the terminal. As mentioned in [File descriptor 3](#file-descriptor-3), bats provides a special file descriptor, `&3`, that you should use to print your custom text. Here are some detailed guidelines to refer to: - Printing **from within a test function**: - To have text printed from within a test function you need to redirect the output to file descriptor 3, eg `echo 'text' >&3`. This output will become part of the TAP stream. You are encouraged to prepend text printed this way with a hash (eg `echo '# text' >&3`) in order to produce 100% TAP compliant output. Otherwise, depending on the 3rd-party tools you use to analyze the TAP stream, you can encounter unexpected behavior or errors. - The pretty formatter that Bats uses by default to process the TAP stream will filter out and not print text output to file descriptor 3. - Text that is output directly to stdout or stderr (file descriptor 1 or 2), ie `echo 'text'` is considered part of the test function output and is printed only on test failures for diagnostic purposes, regardless of the formatter used (TAP or pretty). - Printing **from within the `setup` or `teardown` functions**: The same hold true as for printing with test functions. - Printing **outside test or `setup`/`teardown` functions**: - Regardless of where text is redirected to (stdout, stderr or file descriptor 3) text is immediately visible in the terminal. - Text printed in such a way, will disable pretty formatting. Also, it will make output non-compliant with the TAP spec. The reason for this is that each test file is evaluated n+1 times (as mentioned [earlier](#writing-tests)). The first run will cause such output to be produced before the [_plan line_][tap-plan] is printed, contrary to the spec that requires the _plan line_ to be either the first or the last line of the output. - Due to internal pipes/redirects, output to stderr is always printed first. [tap-plan]: https://testanything.org/tap-specification.html#the-plan ### Special variables There are several global variables you can use to introspect on Bats tests: * `$BATS_TEST_FILENAME` is the fully expanded path to the Bats test file. * `$BATS_TEST_DIRNAME` is the directory in which the Bats test file is located. * `$BATS_TEST_NAMES` is an array of function names for each test case. * `$BATS_TEST_NAME` is the name of the function containing the current test case. * `$BATS_TEST_DESCRIPTION` is the description of the current test case. * `$BATS_TEST_NUMBER` is the (1-based) index of the current test case in the test file. * `$BATS_TMPDIR` is the location to a directory that may be used to store temporary files. ### Libraries and Add-ons Bats supports loading external assertion libraries and helpers. Those under `bats-core` are officially supported libraries (integration tests welcome!): - https://github.com/bats-core/bats-assert - common assertions for Bats - https://github.com/bats-core/bats-support - supporting library for Bats test helpers - https://github.com/bats-core/bats-file - common filesystem assertions for Bats - https://github.com/bats-core/bats-detik - e2e tests of applications in K8s environments and some external libraries, supported on a "best-effort" basis: - https://github.com/ztombol/bats-docs (still relevant? Requires review) - https://github.com/grayhemp/bats-mock (as per #147) - https://github.com/jasonkarns/bats-mock (how is this different from grayhemp/bats-mock?) ## Testing ```sh bin/bats --tap test ``` See also the [CI](.travis.yml) settings for the current test environment and scripts. ## Support The Bats source code repository is [hosted on GitHub](https://github.com/bats-core/bats-core). There you can file bugs on the issue tracker or submit tested pull requests for review. For real-world examples from open-source projects using Bats, see [Projects Using Bats](https://github.com/bats-core/bats-core/wiki/Projects-Using-Bats) on the wiki. To learn how to set up your editor for Bats syntax highlighting, see [Syntax Highlighting](https://github.com/bats-core/bats-core/wiki/Syntax-Highlighting) on the wiki. ## Contributing For now see the ``docs`` folder for project guides, work with us on the wiki or look at the other communication channels. ## Contact - We are `#bats` on freenode; - Or leave a message on [gitter]. ## Version history See `docs/CHANGELOG.md`. ## Background ### What's the plan and why? **Tuesday, September 19, 2017:** This was forked from [Bats][bats-orig] at commit [0360811][]. It was created via `git clone --bare` and `git push --mirror`. [bats-orig]: https://github.com/sstephenson/bats [0360811]: https://github.com/sstephenson/bats/commit/03608115df2071fff4eaaff1605768c275e5f81f This [bats-core repo](https://github.com/bats-core/bats-core) is the community-maintained Bats project. ### Why was this fork created? 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. [call-maintain]: https://github.com/sstephenson/bats/issues/150 ## Copyright © 2017-2020 bats-core organization © 2011-2016 Sam Stephenson 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?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge bats-core-1.2.1/bin/000077500000000000000000000000001370063022300141365ustar00rootroot00000000000000bats-core-1.2.1/bin/bats000077500000000000000000000032131370063022300150140ustar00rootroot00000000000000#!/usr/bin/env bash set -euo pipefail if command -v greadlink >/dev/null; then bats_readlinkf() { greadlink -f "$1" } else bats_readlinkf() { readlink -f "$1" } fi fallback_to_readlinkf_posix() { bats_readlinkf() { [ "${1:-}" ] || return 1 max_symlinks=40 CDPATH='' # to avoid changing to an unexpected directory target=$1 [ -e "${target%/}" ] || target=${1%"${1##*[!/]}"} # trim trailing slashes [ -d "${target:-/}" ] && target="$target/" cd -P . 2>/dev/null || return 1 while [ "$max_symlinks" -ge 0 ] && max_symlinks=$((max_symlinks - 1)); do if [ ! "$target" = "${target%/*}" ]; then case $target in /*) cd -P "${target%/*}/" 2>/dev/null || break ;; *) cd -P "./${target%/*}" 2>/dev/null || break ;; esac target=${target##*/} fi if [ ! -L "$target" ]; then target="${PWD%/}${target:+/}${target}" printf '%s\n' "${target:-/}" return 0 fi # `ls -dl` format: "%s %u %s %s %u %s %s -> %s\n", # , , , , # , , , # https://pubs.opengroup.org/onlinepubs/9699919799/utilities/ls.html link=$(ls -dl -- "$target" 2>/dev/null) || break target=${link#*" $target -> "} done return 1 } } if ! BATS_PATH=$(bats_readlinkf "${BASH_SOURCE[0]}" 2>/dev/null); then fallback_to_readlinkf_posix BATS_PATH=$(bats_readlinkf "${BASH_SOURCE[0]}") fi export BATS_ROOT=${BATS_PATH%/*/*} export -f bats_readlinkf exec env BATS_ROOT="$BATS_ROOT" "$BATS_ROOT/libexec/bats-core/bats" "$@" bats-core-1.2.1/contrib/000077500000000000000000000000001370063022300150265ustar00rootroot00000000000000bats-core-1.2.1/contrib/release.sh000077500000000000000000000073231370063022300170120ustar00rootroot00000000000000#!/usr/bin/env bash # # bats-core git releaser # ## Usage: %SCRIPT_NAME% [options] ## ## Options: ## --major Major version bump ## --minor Minor version bump ## --patch Patch version bump ## ## -v, --version Print version ## --debug Enable debug mode ## -h, --help Display this message ## set -Eeuo pipefail DIR=$(cd "$(dirname "${0}")" && pwd) THIS_SCRIPT="${DIR}/$(basename "${0}")" BATS_VERSION=$( # shellcheck disable=SC1090 source <(grep '^export BATS_VERSION=' libexec/bats-core/bats) echo "${BATS_VERSION}" ) declare -r DIR declare -r THIS_SCRIPT declare -r BATS_VERSION BUMP_INTERVAL="" NEW_BATS_VERSION="" main() { handle_arguments "${@}" if [[ "${BUMP_INTERVAL:-}" == "" ]]; then echo "${BATS_VERSION}" exit 0 fi local NEW_BATS_VERSION NEW_BATS_VERSION=$(semver bump "${BUMP_INTERVAL}" "${BATS_VERSION}") declare -r NEW_BATS_VERSION local BATS_RELEASE_NOTES="/tmp/bats-release-${NEW_BATS_VERSION}" echo "Releasing: ${BATS_VERSION} to ${NEW_BATS_VERSION}" echo echo "Ensure docs/CHANGELOG.md is correctly updated" replace_in_files write_changelog git diff --staged cat </dev/null get_version() { echo "${THIS_SCRIPT_VERSION:-0.1}" } main "${@}" bats-core-1.2.1/contrib/rpm/000077500000000000000000000000001370063022300156245ustar00rootroot00000000000000bats-core-1.2.1/contrib/rpm/bats.spec000066400000000000000000000030471370063022300174350ustar00rootroot00000000000000%global provider github.com %global project bats-core %global repo bats-core Name: bats Version: 1.2.1 Release: 1%{?dist} Summary: Bash Automated Testing System Group: Development/Libraries License: MIT URL: https://%{provider}/%{project}/%{repo} Source0: https://%{provider}/%{project}/%{repo}/archive/v%{version}.tar.gz BuildArch: noarch Requires: bash %description 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. %prep %setup -q -n %{repo}-%{version} %install mkdir -p ${RPM_BUILD_ROOT}%{_prefix} ${RPM_BUILD_ROOT}%{_libexecdir} ${RPM_BUILD_ROOT}%{_mandir} ./install.sh ${RPM_BUILD_ROOT}%{_prefix} %clean rm -rf $RPM_BUILD_ROOT %check %files %doc README.md LICENSE.md %{_bindir}/%{name} %{_libexecdir}/%{repo} %{_mandir}/man1/%{name}.1.gz %{_mandir}/man7/%{name}.7.gz %changelog * Tue Jul 08 2018 mbland - 1.1.0-1 - Increase version to match upstream release * Mon Jun 18 2018 pixdrift - 1.0.2-1 - Increase version to match upstream release - Relocate libraries to bats-core subdirectory * Sat Jun 09 2018 pixdrift - 1.0.1-1 - Increase version to match upstream release * Fri Jun 08 2018 pixdrift - 1.0.0-1 - Initial package build of forked (bats-core) github project bats-core-1.2.1/contrib/semver000077500000000000000000000174451370063022300162700ustar00rootroot00000000000000#!/usr/bin/env bash # v3.0.0 # https://github.com/fsaintjacques/semver-tool set -o errexit -o nounset -o pipefail NAT='0|[1-9][0-9]*' ALPHANUM='[0-9]*[A-Za-z-][0-9A-Za-z-]*' IDENT="$NAT|$ALPHANUM" FIELD='[0-9A-Za-z-]+' SEMVER_REGEX="\ ^[vV]?\ ($NAT)\\.($NAT)\\.($NAT)\ (\\-(${IDENT})(\\.(${IDENT}))*)?\ (\\+${FIELD}(\\.${FIELD})*)?$" PROG=semver PROG_VERSION="3.0.0" USAGE="\ Usage: $PROG bump (major|minor|patch|release|prerel |build ) $PROG compare $PROG get (major|minor|patch|release|prerel|build) $PROG --help $PROG --version Arguments: A version must match the following regular expression: \"${SEMVER_REGEX}\" In English: -- The version must match X.Y.Z[-PRERELEASE][+BUILD] where X, Y and Z are non-negative integers. -- PRERELEASE is a dot separated sequence of non-negative integers and/or identifiers composed of alphanumeric characters and hyphens (with at least one non-digit). Numeric identifiers must not have leading zeros. A hyphen (\"-\") introduces this optional part. -- BUILD is a dot separated sequence of identifiers composed of alphanumeric characters and hyphens. A plus (\"+\") introduces this optional part. See definition. A string as defined by PRERELEASE above. A string as defined by BUILD above. Options: -v, --version Print the version of this tool. -h, --help Print this help message. Commands: bump Bump by one of major, minor, patch; zeroing or removing subsequent parts. \"bump prerel\" sets the PRERELEASE part and removes any BUILD part. \"bump build\" sets the BUILD part. \"bump release\" removes any PRERELEASE or BUILD parts. The bumped version is written to stdout. compare Compare with , output to stdout the following values: -1 if is newer, 0 if equal, 1 if older. The BUILD part is not used in comparisons. get Extract given part of , where part is one of major, minor, patch, prerel, build, or release. See also: https://semver.org -- Semantic Versioning 2.0.0" function error { echo -e "$1" >&2 exit 1 } function usage-help { error "$USAGE" } function usage-version { echo -e "${PROG}: $PROG_VERSION" exit 0 } function validate-version { local version=$1 if [[ "$version" =~ $SEMVER_REGEX ]]; then # if a second argument is passed, store the result in var named by $2 if [ "$#" -eq "2" ]; then local major=${BASH_REMATCH[1]} local minor=${BASH_REMATCH[2]} local patch=${BASH_REMATCH[3]} local prere=${BASH_REMATCH[4]} local build=${BASH_REMATCH[8]} eval "$2=(\"$major\" \"$minor\" \"$patch\" \"$prere\" \"$build\")" else echo "$version" fi else error "version $version does not match the semver scheme 'X.Y.Z(-PRERELEASE)(+BUILD)'. See help for more information." fi } function is-nat { [[ "$1" =~ ^($NAT)$ ]] } function is-null { [ -z "$1" ] } function order-nat { [ "$1" -lt "$2" ] && { echo -1 ; return ; } [ "$1" -gt "$2" ] && { echo 1 ; return ; } echo 0 } function order-string { [[ $1 < $2 ]] && { echo -1 ; return ; } [[ $1 > $2 ]] && { echo 1 ; return ; } echo 0 } # given two (named) arrays containing NAT and/or ALPHANUM fields, compare them # one by one according to semver 2.0.0 spec. Return -1, 0, 1 if left array ($1) # is less-than, equal, or greater-than the right array ($2). The longer array # is considered greater-than the shorter if the shorter is a prefix of the longer. # function compare-fields { local l="$1[@]" local r="$2[@]" local leftfield=( "${!l}" ) local rightfield=( "${!r}" ) local left local right local i=$(( -1 )) local order=$(( 0 )) while true do [ $order -ne 0 ] && { echo $order ; return ; } : $(( i++ )) left="${leftfield[$i]}" right="${rightfield[$i]}" is-null "$left" && is-null "$right" && { echo 0 ; return ; } is-null "$left" && { echo -1 ; return ; } is-null "$right" && { echo 1 ; return ; } is-nat "$left" && is-nat "$right" && { order=$(order-nat "$left" "$right") ; continue ; } is-nat "$left" && { echo -1 ; return ; } is-nat "$right" && { echo 1 ; return ; } { order=$(order-string "$left" "$right") ; continue ; } done } # shellcheck disable=SC2206 # checked by "validate"; ok to expand prerel id's into array function compare-version { local order validate-version "$1" V validate-version "$2" V_ # compare major, minor, patch local left=( "${V[0]}" "${V[1]}" "${V[2]}" ) local right=( "${V_[0]}" "${V_[1]}" "${V_[2]}" ) order=$(compare-fields left right) [ "$order" -ne 0 ] && { echo "$order" ; return ; } # compare pre-release ids when M.m.p are equal local prerel="${V[3]:1}" local prerel_="${V_[3]:1}" local left=( ${prerel//./ } ) local right=( ${prerel_//./ } ) # if left and right have no pre-release part, then left equals right # if only one of left/right has pre-release part, that one is less than simple M.m.p [ -z "$prerel" ] && [ -z "$prerel_" ] && { echo 0 ; return ; } [ -z "$prerel" ] && { echo 1 ; return ; } [ -z "$prerel_" ] && { echo -1 ; return ; } # otherwise, compare the pre-release id's compare-fields left right } function command-bump { local new; local version; local sub_version; local command; case $# in 2) case $1 in major|minor|patch|release) command=$1; version=$2;; *) usage-help;; esac ;; 3) case $1 in prerel|build) command=$1; sub_version=$2 version=$3 ;; *) usage-help;; esac ;; *) usage-help;; esac validate-version "$version" parts # shellcheck disable=SC2154 local major="${parts[0]}" local minor="${parts[1]}" local patch="${parts[2]}" local prere="${parts[3]}" local build="${parts[4]}" case "$command" in major) new="$((major + 1)).0.0";; minor) new="${major}.$((minor + 1)).0";; patch) new="${major}.${minor}.$((patch + 1))";; release) new="${major}.${minor}.${patch}";; prerel) new=$(validate-version "${major}.${minor}.${patch}-${sub_version}");; build) new=$(validate-version "${major}.${minor}.${patch}${prere}+${sub_version}");; *) usage-help ;; esac echo "$new" exit 0 } function command-compare { local v; local v_; case $# in 2) v=$(validate-version "$1"); v_=$(validate-version "$2") ;; *) usage-help ;; esac set +u # need unset array element to evaluate to null compare-version "$v" "$v_" exit 0 } # shellcheck disable=SC2034 function command-get { local part version if [[ "$#" -ne "2" ]] || [[ -z "$1" ]] || [[ -z "$2" ]]; then usage-help exit 0 fi part="$1" version="$2" validate-version "$version" parts local major="${parts[0]}" local minor="${parts[1]}" local patch="${parts[2]}" local prerel="${parts[3]:1}" local build="${parts[4]:1}" local release="${major}.${minor}.${patch}" case "$part" in major|minor|patch|release|prerel|build) echo "${!part}" ;; *) usage-help ;; esac exit 0 } case $# in 0) echo "Unknown command: $*"; usage-help;; esac case $1 in --help|-h) echo -e "$USAGE"; exit 0;; --version|-v) usage-version ;; bump) shift; command-bump "$@";; get) shift; command-get "$@";; compare) shift; command-compare "$@";; *) echo "Unknown arguments: $*"; usage-help;; esac bats-core-1.2.1/docker-compose.override.dist000066400000000000000000000002231370063022300210000ustar00rootroot00000000000000# Copy this file to docker-compose.override.yml version: '3.6' services: bats: entrypoint: - "bash" networks: default: bats-core-1.2.1/docker-compose.yml000066400000000000000000000003641370063022300170260ustar00rootroot00000000000000version: '3.6' services: bats: build: context: "." dockerfile: "Dockerfile" networks: - "default" user: "root" volumes: - "./:/opt/bats" networks: default: bats-core-1.2.1/docs/000077500000000000000000000000001370063022300143165ustar00rootroot00000000000000bats-core-1.2.1/docs/CHANGELOG.md000066400000000000000000000156021370063022300161330ustar00rootroot00000000000000# Changelog All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog][kac] and this project adheres to [Semantic Versioning][semver]. [kac]: https://keepachangelog.com/en/1.0.0/ [semver]: https://semver.org/ ## [1.2.1] - 2020-07-06 ### Added * JUnit output and extensible formatter rewrite (#246) * `load` function now reads from absolute and relative paths, and $PATH (#282) * Beginner-friendly examples in /docs/examples (#243) * @peshay's `bats-file` fork contributed to `bats-core/bats-file` (#276) ### Changed * Duplicate test names now error (previous behaviour was to issue a warning) (#286) * Changed default formatter in Docker to pretty by adding `ncurses` to Dockerfile, override with `--tap` (#239) * Replace "readlink -f" dependency with Bash solution (#217) ## [1.2.0] - 2020-04-25 Support parallel suite execution and filtering by test name. ### Added * docs/CHANGELOG.md and docs/releasing.md (#122) * The `-f, --filter` flag to run only the tests matching a regular expression (#126) * Optimize stack trace capture (#138) * `--jobs n` flag to support parallel execution of tests with GNU parallel (#172) ### Changed * AppVeyor builds are now semver-compliant (#123) * Add Bash 5 as test target (#181) * Always use upper case signal names to avoid locale dependent err… (#215) * Fix for tests reading from stdin (#227) * Fix wrong line numbers of errors in bash < 4.4 (#229) * Remove preprocessed source after test run (#232) ## [1.1.0] - 2018-07-08 This is the first release with new features relative to the original Bats 0.4.0. ### Added * The `-r, --recursive` flag to scan directory arguments recursively for `*.bats` files (#109) * The `contrib/rpm/bats.spec` file to build RPMs (#111) ### Changed * Travis exercises latest versions of Bash from 3.2 through 4.4 (#116, #117) * Error output highlights invalid command line options (#45, #46, #118) * Replaced `echo` with `printf` (#120) ### Fixed * Fixed `BATS_ERROR_STATUS` getting lost when `bats_error_trap` fired multiple times under Bash 4.2.x (#110) * Updated `bin/bats` symlink resolution, handling the case on CentOS where `/bin` is a symlink to `/usr/bin` (#113, #115) ## [1.0.2] - 2018-06-18 * Fixed sstephenson/bats#240, whereby `skip` messages containing parentheses were truncated (#48) * Doc improvements: * Docker usage (#94) * Better README badges (#101) * Better installation instructions (#102, #104) * Packaging/installation improvements: * package.json update (#100) * Moved `libexec/` files to `libexec/bats-core/`, improved `install.sh` (#105) ## [1.0.1] - 2018-06-09 * Fixed a `BATS_CWD` bug introduced in #91 whereby it was set to the parent of `PWD`, when it should've been set to `PWD` itself (#98). This caused file names in stack traces to contain the basename of `PWD` as a prefix, when the names should've been purely relative to `PWD`. * Ensure the last line of test output prints when it doesn't end with a newline (#99). This was a quasi-bug introduced by replacing `sed` with `while` in #88. ## [1.0.0] - 2018-06-08 `1.0.0` generally preserves compatibility with `0.4.0`, but with some Bash compatibility improvements and a massive performance boost. In other words: - all existing tests should remain compatible - tests that might've failed or exhibited unexpected behavior on earlier versions of Bash should now also pass or behave as expected Changes: * Added support for Docker. * Added support for test scripts that have the [unofficial strict mode](http://redsymbol.net/articles/unofficial-bash-strict-mode/) enabled. * Improved stability on Windows and macOS platforms. * Massive performance improvements, especially on Windows (#8) * Workarounds for inconsistent behavior between Bash versions (#82) * Workaround for preserving stack info after calling an exported function under Bash < 4.4 (#87) * Fixed TAP compliance for skipped tests * Added support for tabs in test names. * `bin/bats` and `install.sh` now work reliably on Windows (#91) ## [0.4.0] - 2014-08-13 * Improved the display of failing test cases. Bats now shows the source code of failing test lines, along with full stack traces including function names, filenames, and line numbers. * Improved the display of the pretty-printed test summary line to include the number of skipped tests, if any. * Improved the speed of the preprocessor, dramatically shortening test and suite startup times. * Added support for absolute pathnames to the `load` helper. * Added support for single-line `@test` definitions. * Added bats(1) and bats(7) manual pages. * Modified the `bats` command to default to TAP output when the `$CI` variable is set, to better support environments such as Travis CI. ## [0.3.1] - 2013-10-28 * Fixed an incompatibility with the pretty formatter in certain environments such as tmux. * Fixed a bug where the pretty formatter would crash if the first line of a test file's output was invalid TAP. ## [0.3.0] - 2013-10-21 * Improved formatting for tests run from a terminal. Failing tests are now colored in red, and the total number of failing tests is displayed at the end of the test run. When Bats is not connected to a terminal (e.g. in CI runs), or when invoked with the `--tap` flag, output is displayed in standard TAP format. * Added the ability to skip tests using the `skip` command. * Added a message to failing test case output indicating the file and line number of the statement that caused the test to fail. * Added "ad-hoc" test suite support. You can now invoke `bats` with multiple filename or directory arguments to run all the specified tests in aggregate. * Added support for test files with Windows line endings. * Fixed regular expression warnings from certain versions of Bash. * Fixed a bug running tests containing lines that begin with `-e`. ## [0.2.0] - 2012-11-16 * Added test suite support. The `bats` command accepts a directory name containing multiple test files to be run in aggregate. * Added the ability to count the number of test cases in a file or suite by passing the `-c` flag to `bats`. * Preprocessed sources are cached between test case runs in the same file for better performance. ## [0.1.0] - 2011-12-30 * Initial public release. [Unreleased]: https://github.com/bats-core/bats-core/compare/v1.1.0...HEAD [1.1.0]: https://github.com/bats-core/bats-core/compare/v1.0.2...v1.1.0 [1.0.2]: https://github.com/bats-core/bats-core/compare/v1.0.1...v1.0.2 [1.0.1]: https://github.com/bats-core/bats-core/compare/v1.0.0...v1.0.1 [1.0.0]: https://github.com/bats-core/bats-core/compare/v0.4.0...v1.0.0 [0.4.0]: https://github.com/bats-core/bats-core/compare/v0.3.1...v0.4.0 [0.3.1]: https://github.com/bats-core/bats-core/compare/v0.3.0...v0.3.1 [0.3.0]: https://github.com/bats-core/bats-core/compare/v0.2.0...v0.3.0 [0.2.0]: https://github.com/bats-core/bats-core/compare/v0.1.0...v0.2.0 [0.1.0]: https://github.com/bats-core/bats-core/commits/v0.1.0 bats-core-1.2.1/docs/CODEOWNERS000066400000000000000000000003231370063022300157070ustar00rootroot00000000000000# This enables automatic code review requests per: # - https://help.github.com/articles/about-codeowners/ # - https://help.github.com/articles/enabling-required-reviews-for-pull-requests/ * @bats-core/bats-core bats-core-1.2.1/docs/CODE_OF_CONDUCT.md000066400000000000000000000070731370063022300171240ustar00rootroot00000000000000# Contributor Covenant Code of Conduct ## Our Pledge In the interest of fostering an open and welcoming environment, we as contributors and maintainers pledge to making participation in our project and our community a harassment-free experience for everyone, regardless of age, body size, disability, ethnicity, gender identity and expression, level of experience, nationality, personal appearance, race, religion, or sexual identity and orientation. ## Our Standards Examples of behavior that contributes to creating a positive environment include: * Using welcoming and inclusive language * Being respectful of differing viewpoints and experiences * Gracefully accepting constructive criticism * Focusing on what is best for the community * Showing empathy towards other community members Examples of unacceptable behavior by participants include: * The use of sexualized language or imagery and unwelcome sexual attention or advances * Trolling, insulting/derogatory comments, and personal or political attacks * Public or private harassment * Publishing others' private information, such as a physical or electronic address, without explicit permission * Other conduct which could reasonably be considered inappropriate in a professional setting ## Our Responsibilities Project maintainers are responsible for clarifying the standards of acceptable behavior and are expected to take appropriate and fair corrective action in response to any instances of unacceptable behavior. Project maintainers have the right and responsibility to remove, edit, or reject comments, commits, code, wiki edits, issues, and other contributions that are not aligned to this Code of Conduct, or to ban temporarily or permanently any contributor for other behaviors that they deem inappropriate, threatening, offensive, or harmful. ## Scope This Code of Conduct applies both within project spaces and in public spaces when an individual is representing the project or its community. Examples of representing a project or community include using an official project e-mail address, posting via an official social media account, or acting as an appointed representative at an online or offline event. Representation of a project may be further defined and clarified by project maintainers. ## Enforcement Instances of abusive, harassing, or otherwise unacceptable behavior may be reported by contacting one of the current [project maintainers](#project-maintainers) listed below. All complaints will be reviewed and investigated and will result in a response that is deemed necessary and appropriate to the circumstances. The project team is obligated to maintain confidentiality with regard to the reporter of an incident. Further details of specific enforcement policies may be posted separately. Project maintainers who do not follow or enforce the Code of Conduct in good faith may face temporary or permanent repercussions as determined by other members of the project's leadership. ## Project Maintainers ### Current Maintainers * [Bianca Tamayo][bt-gh] * [Mike Bland][mb-gh] * [Jason Karns][jk-gh] * [Andrew Martin][am-gh] ### Past Maintainers * Sam Stephenson <> (Original author) ## Attribution This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4, available at [http://contributor-covenant.org/version/1/4][version] [bt-gh]: https://github.com/btamayo [mb-gh]: https://github.com/mbland [jk-gh]: https://github.com/jasonkarns [am-gh]: https://github.com/sublimino [homepage]: https://contributor-covenant.org [version]: https://contributor-covenant.org/version/1/4/ bats-core-1.2.1/docs/CONTRIBUTING.md000066400000000000000000000422251370063022300165540ustar00rootroot00000000000000# Contributing Guidelines ## Welcome! Thank you for considering contributing to the development of 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: - [help wanted][helpwantedlabel] - [docs][docslabel] - [good first issue][goodfirstissuelabel] [docslabel]: https://github.com/bats-core/bats-core/labels/docs [helpwantedlabel]: https://github.com/bats-core/bats-core/labels/help%20wanted [goodfirstissuelabel]: https://github.com/bats-core/bats-core/labels/good%20first%20issue 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 * [Contributing Guidelines](#contributing-guidelines) * [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) * [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) * [Gotchas](#gotchas) * [Open Source License](#open-source-license) * [Credits](#credits) ## Quick links 🔗 - [Gitter channel →][gitterurl]: These messages sync with the IRC channel - [IRC Channel (#bats on freenode) →][ircurl]: These messages sync with Gitter - [README →][README] - [Code of conduct →][CODE_OF_CONDUCT] - [License information →][LICENSE] - [Original repository →][repohome] - [Issues →][repoissues] - [Pull requests →][repoprs] - [Milestones →][repomilestones] - [Projects →][repoprojects] [README]: https://github.com/bats-core/bats-core/blob/master/README.md [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 Harrassment 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 Please check the [README][] or existing [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?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge) or [via IRC (#bats on freenode)][ircurl]. ### 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! If you love writing clear, accessible docs, please don't be shy about pull 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 for Linux and macOS: [![Build Status on Travis](https://travis-ci.org/bats-core/bats-core.svg?branch=ci-configs)](https://travis-ci.org/bats-core/bats-core) - Continuous integration status for Windows: [![Build status on AppVeyor](https://ci.appveyor.com/api/projects/status/tokwm9t9jp5fe7af?svg=true)](https://ci.appveyor.com/project/bats-core/bats-core) ## 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) ### 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. ### Function declarations - Declare functions without the `function` keyword. - Strive to always use `return`, never `exit`, unless an error condition is severe enough to warrant it. - Calling `exit` makes it difficult for the caller to recover from an error, or to compose new commands from existing ones. ### 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. - Don't use `local -r`, as a readonly local variable in one scope can cause a conflict when it calls a function that declares a `local` variable of the same name. - Don't use type flags with `declare` or `local`. Assignments to integer variables in particular may behave differently, and it has no effect on array variables. - For most functions, the first lines should use `local` declarations to assign the original positional parameters to more meaningful names, e.g.: ```bash format_summary() { local cmd_name="$1" local summary="$2" local longest_name_len="$3" ``` For very short functions, this _may not_ be necessary, e.g.: ```bash has_spaces() { [[ "$1" != "${1//[[:space:]]/}" ]] } ``` ### Command substitution - If possible, don't. While this capability is one of Bash's core strengths, every new process created by Bats makes the framework slower, and speed is critical to encouraging the practice of automated testing. (This is especially true on Windows, [where process creation is one or two orders of magnitude slower][win-slow]. See [bats-core/bats-core#8][pr-8] for an illustration of the difference avoiding subshells makes.) Bash is quite powerful; see if you can do what you need in pure Bash first. - If you need to capture the output from a function, store the output using `printf -v` instead if possible. `-v` specfies the name of the variable into which to write the result; the caller can supply this name as a parameter. - If you must use command substituion, use `$()` instead of backticks, as it's more robust, more searchable, and can be nested. [win-slow]: https://rufflewind.com/2014-08-23/windows-bash-slow [pr-8]: https://github.com/bats-core/bats-core/pull/8 ### Process substitution - If possible, don't use it. See the advice on avoiding subprocesses and using `printf -v` in the **Command substitution** section above. - Use wherever necessary and possible, such as when piping input into a `while` loop (which avoids having the loop body execute in a subshell) or running a command taking multiple filename arguments based on output from a function or pipeline (e.g. `diff`). - *Warning*: It is impossible to directly determine the exit status of a process substitution; emitting an exit status as the last line of output is a possible workaround. ### Conditionals and loops - Always use `[[` and `]]` for evaluating variables. Per the guideline under **Formatting**, quote variables and strings within the brackets, but not regular expressions (or variables containing regular expressions) appearing on the right side of the `=~` operator. ### Generating output - Use `printf` instead of `echo`. Both are Bash builtins, and there's no perceptible performance difference when running Bats under the `time` builtin. However, `printf` provides a more consistent experience in general, as `echo` has limitations to the arguments it accepts, and even the same version of Bash may produce different results for `echo` based on how the binary was compiled. See [Stack Overflow: Why is printf better than echo?][printf-vs-echo] for excruciating details. [printf-vs-echo]: https://unix.stackexchange.com/a/65819 ### Signal names Always use upper case signal names (e.g. `trap - INT EXIT`) to avoid locale dependent errors. In some locales (for example Turkish, see [Turkish dotless i](https://en.wikipedia.org/wiki/Dotted_and_dotless_I)) lower case signal names cause Bash to error. An example of the problem: ```bash $ echo "tr_TR.UTF-8 UTF-8" >> /etc/locale.gen && locale-gen tr_TR.UTF-8 # Ubuntu derivatives $ LC_CTYPE=tr_TR.UTF-8 LC_MESSAGES=C bash -c 'trap - int && echo success' bash: line 0: trap: int: invalid signal specification $ 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 by the [Free Software Foundation](https://www.fsf.org/), 2016 under the [Free Art License](http://artlibre.org/licence/lal/en/) [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 [repoissues]: https://github.com/bats-core/bats-core/issues [repohome]: https://github.com/bats-core/bats-core [osmit]: https://opensource.org/licenses/MIT [gitterurl]: https://gitter.im/bats-core/bats-core [ircurl]: https://kiwiirc.com/client/irc.freenode.net:+6697/#bats bats-core-1.2.1/docs/PULL_REQUEST_TEMPLATE.md000066400000000000000000000004751370063022300201250ustar00rootroot00000000000000- [ ] I have reviewed the [Contributor Guidelines][contributor]. - [ ] I have reviewed the [Code of Conduct][coc] and agree to abide by it [contributor]: https://github.com/bats-core/bats-core/blob/master/docs/CONTRIBUTING.md [coc]: https://github.com/bats-core/bats-core/blob/master/docs/CODE_OF_CONDUCT.md bats-core-1.2.1/docs/examples/000077500000000000000000000000001370063022300161345ustar00rootroot00000000000000bats-core-1.2.1/docs/examples/README.md000066400000000000000000000002401370063022300174070ustar00rootroot00000000000000# Examples This directory contains example .bats files. See the [bats-core wiki][examples] for more details. [examples]: (/bats-core/bats-core/wiki/Examples) bats-core-1.2.1/docs/examples/package-tarball000066400000000000000000000011341370063022300210700ustar00rootroot00000000000000#!/usr/bin/env bash # "unofficial" bash strict mode # See: http://redsymbol.net/articles/unofficial-bash-strict-mode set -o errexit # Exit when simple command fails 'set -e' set -o errtrace # Exit on error inside any functions or subshells. set -o nounset # Trigger error when expanding unset variables 'set -u' set -o pipefail # Do not hide errors within pipes 'set -o pipefail' set -o xtrace # Display expanded command and arguments 'set -x' IFS=$'\n\t' # Split words on \n\t rather than spaces main() { tar -czf "$dst_tarball" -C "$src_dir" . } main "$@" bats-core-1.2.1/docs/examples/package-tarball.bats000077500000000000000000000015451370063022300220310ustar00rootroot00000000000000#!/usr/bin/env bats setup() { export dst_tarball="${BATS_TMPDIR}/dst.tar.gz" export src_dir="${BATS_TMPDIR}/src_dir" rm -rf "${dst_tarball}" "${src_dir}" mkdir "${src_dir}" touch "${src_dir}"/{a,b,c} } main() { bash "${BATS_TEST_DIRNAME}"/package-tarball } @test 'fail when \$src_dir and \$dst_tarball are unbound' { unset src_dir dst_tarball run main [ "${status}" -ne 0 ] } @test 'fail when \$src_dir is a non-existent directory' { src_dir='not-a-dir' run main [ "${status}" -ne 0 ] } @test 'pass when \$src_dir directory is empty' { rm -rf "${src_dir:?}/*" run main echo "$output" [ "${status}" -eq 0 ] } @test 'files in \$src_dir are added to tar archive' { run main [ "${status}" -eq 0 ] run tar tf "$dst_tarball" [ "${status}" -eq 0 ] [[ "${output}" =~ a ]] [[ "${output}" =~ b ]] [[ "${output}" =~ c ]] } bats-core-1.2.1/docs/releasing.md000066400000000000000000000076131370063022300166200ustar00rootroot00000000000000# Releasing a new Bats version These notes reflect the current process. There's a lot more we could do, in terms of automation and expanding the number of platforms to which we formally release (see #103). ## Update docs/CHANGELOG.md Create a new entry at the top of `docs/CHANGELOG.md` that enumerates the significant updates to the new version. ## Bumping the version number Bump the version numbers in the following files: - .appveyor.yml - contrib/rpm/bats.spec - libexec/bats-core/bats - package.json Commit these changes (including the `docs/CHANGELOG.md` changes) in a commit with the message `Bats `, where `` is the new version number. Create a new signed, annotated tag with: ```bash $ git tag -a -s ``` Include the `docs/CHANGELOG.md` notes corresponding to the new version as the tag annotation, except the first line should be: `Bats - YYYY-MM-DD` and any Markdown headings should become plain text, e.g.: ```md ### Added ``` should become: ```md Added: ``` ## Create a GitHub release Push the new version commit and tag to GitHub via the following: ```bash $ git push --follow-tags ``` Then visit https://github.com/bats-core/bats-core/releases, and: * Click **Draft a new release**. * Select the new version tag. * Name the release: `Bats `. * Paste the same notes from the version tag annotation as the description, except change the first line to read: `Released: YYYY-MM-DD`. * Click **Publish release**. For more on `git push --follow-tags`, see: * [git push --follow-tags in the online manual][ft-man] * [Stack Overflow: How to push a tag to a remote repository using Git?][ft-so] [ft-man]: https://git-scm.com/docs/git-push#git-push---follow-tags [ft-so]: https://stackoverflow.com/a/26438076 ## NPM `npm publish`. Pretty easy! For the paranoid, use `npm pack` and install the resulting tarball locally with `npm install` before publishing. ## Homebrew The basic instructions are in the [Submit a new version of an existing formula][brew] section of the Homebrew docs. [brew]: https://github.com/Homebrew/brew/blob/master/docs/How-To-Open-a-Homebrew-Pull-Request.md#submit-a-new-version-of-an-existing-formula An example using v1.1.0 (notice that this uses the sha256 sum of the tarball): ```bash $ curl -LOv https://github.com/bats-core/bats-core/archive/v1.1.0.tar.gz $ openssl sha256 v1.1.0.tar.gz SHA256(v1.1.0.tar.gz)=855d8b8bed466bc505e61123d12885500ef6fcdb317ace1b668087364717ea82 # Add the --dry-run flag to see the individual steps without executing. $ brew bump-formula-pr \ --url=https://github.com/bats-core/bats-core/archive/v1.1.0.tar.gz \ --sha256=855d8b8bed466bc505e61123d12885500ef6fcdb317ace1b668087364717ea82 ``` This resulted in https://github.com/Homebrew/homebrew-core/pull/29864, which was automatically merged once the build passed. ## Alpine Linux An example using v1.1.0 (notice that this uses the sha512 sum of the Zip file): ```bash $ curl -LOv https://github.com/bats-core/bats-core/archive/v1.1.0.zip $ openssl sha512 v1.1.0.zip SHA512(v1.1.0.zip)=accd83cfec0025a2be40982b3f9a314c2bbf72f5c85daffa9e9419611904a8d34e376919a5d53e378382e0f3794d2bd781046d810225e2a77812474e427bed9e ``` After cloning alpinelinux/aports, I used the above information to create: https://github.com/alpinelinux/aports/pull/4696 **Note:** Currently users must enable the `edge` branch of the `community` repo by adding/uncommenting the corresponding entry in `/etc/apk/repositories`. ## Announce It's worth making a brief announcement like [the v1.1.0 announcement via Gitter][gitter]: [gitter]: https://gitter.im/bats-core/bats-core?at=5b42c9a57b811a6d63daacb5 ``` v1.1.0 is now available via Homebrew and npm: https://github.com/bats-core/bats-core/releases/tag/v1.1.0 It'll eventually be available in Alpine via the edge branch of the community repo once alpinelinux/aports#4696 gets merged. (Check /etc/apk/repositories to ensure this repo is enabled.) ``` bats-core-1.2.1/docs/usage.md000066400000000000000000000044421370063022300157500ustar00rootroot00000000000000# Docker Usage Guide - [Docker Usage Guide](#docker-usage-guide) * [Basic Usage](#basic-usage) * [Docker Gotchas](#docker-gotchas) * [Extending from the base image](#extending-from-the-base-image) ## Basic Usage To build and run `bats`' own tests: ```bash $ git clone https://github.com/bats-core/bats-core.git Cloning into 'bats-core'... remote: Counting objects: 1222, done. remote: Compressing objects: 100% (53/53), done. remote: Total 1222 (delta 34), reused 55 (delta 21), pack-reused 1146 Receiving objects: 100% (1222/1222), 327.28 KiB | 1.70 MiB/s, done. Resolving deltas: 100% (661/661), done. $ cd bats-core/ $ docker build --tag bats:latest . ... $ docker run -it bats:latest --formatter tap /opt/bats/test ``` To mount your tests into the container, first build the image as above. Then, for example with `bats`: ```bash $ docker run -it -v "$PWD:/opt/bats" bats:latest /opt/bats/test ``` This runs the `test/` directory from the bats-core repository inside the bats Docker container. For test suites that are intended to run in isolation from the project (i.e. the tests do not depend on project files outside of the test directory), you can mount the test directory by itself and execute the tests like so: ```bash $ docker run -it -v "$PWD/test:/test" bats:latest /test ``` ## Docker Gotchas Relying on functionality provided by your environment (ssh keys or agent, installed binaries, fixtures outside the mounted test directory) will fail when running inside Docker. `--interactive`/`-i` attaches an interactive terminal and is useful to kill hanging processes (otherwise has to be done via docker stop command). `--tty`/`-t` simulates a tty (often not used, but most similar to test runs from a Bash prompt). Interactivity is important to a user, but not a build, and TTYs are probably more important to a headless build. Everything's least-surprising to a new Docker use if both are used. ## Extending from the base image Docker operates on a principle of isolation, and bundles all dependencies required into the Docker image. These can be mounted in at runtime (for test files, configuration, etc). For binary dependencies it may be better to extend the base Docker image with further tools and files. ```dockerfile FROM bats RUN \ apk \ --no-cache \ --update \ add \ openssh ``` bats-core-1.2.1/docs/versions.md000066400000000000000000000004371370063022300165140ustar00rootroot00000000000000Here are the docs of following versions: * [v1.2.0](../../v1.2.0/README.md) * [v1.1.0](../../v1.1.0/README.md) * [v1.0.2](../../v1.0.2/README.md) * [v0.4.0](../../v0.4.0/README.md) * [v0.3.1](../../v0.3.1/README.md) * [v0.2.0](../../v0.2.0/README.md) * [v0.1.0](../../v0.1.0/README.md) bats-core-1.2.1/install.sh000077500000000000000000000011631370063022300153740ustar00rootroot00000000000000#!/usr/bin/env bash set -e BATS_ROOT="${0%/*}" PREFIX="$1" if [[ -z "$PREFIX" ]]; then printf '%s\n' \ "usage: $0 " \ " e.g. $0 /usr/local" >&2 exit 1 fi install -d -m 755 "$PREFIX"/{bin,libexec/bats-core,lib/bats-core,share/man/man{1,7}} install -m 755 "$BATS_ROOT/bin"/* "$PREFIX/bin" install -m 755 "$BATS_ROOT/libexec/bats-core"/* "$PREFIX/libexec/bats-core" install -m 755 "$BATS_ROOT/lib/bats-core"/* "$PREFIX/lib/bats-core" install -m 644 "$BATS_ROOT/man/bats.1" "$PREFIX/share/man/man1" install -m 644 "$BATS_ROOT/man/bats.7" "$PREFIX/share/man/man7" echo "Installed Bats to $PREFIX/bin/bats" bats-core-1.2.1/lib/000077500000000000000000000000001370063022300141345ustar00rootroot00000000000000bats-core-1.2.1/lib/bats-core/000077500000000000000000000000001370063022300160135ustar00rootroot00000000000000bats-core-1.2.1/lib/bats-core/preprocessing.bash000066400000000000000000000014731370063022300215420ustar00rootroot00000000000000#!/usr/bin/env bash if [[ -z "$TMPDIR" ]]; then BATS_TMPDIR='/tmp' else BATS_TMPDIR="${TMPDIR%/}" fi BATS_TMPNAME="$BATS_RUN_TMPDIR/bats.$$" BATS_PARENT_TMPNAME="$BATS_RUN_TMPDIR/bats.$PPID" # shellcheck disable=SC2034 BATS_OUT="${BATS_TMPNAME}.out" # used in bats-exec-file bats_preprocess_source() { BATS_TEST_SOURCE="${BATS_TMPNAME}.src" bats-preprocess "$BATS_TEST_FILENAME" >"$BATS_TEST_SOURCE" trap 'bats_cleanup_preprocessed_source' ERR EXIT trap 'bats_cleanup_preprocessed_source; exit 1' INT } bats_cleanup_preprocessed_source() { rm -f "$BATS_TEST_SOURCE" } bats_evaluate_preprocessed_source() { if [[ -z "$BATS_TEST_SOURCE" ]]; then BATS_TEST_SOURCE="${BATS_PARENT_TMPNAME}.src" fi # Dynamically loaded user files provided outside of Bats. # shellcheck disable=SC1090 source "$BATS_TEST_SOURCE" } bats-core-1.2.1/lib/bats-core/test_functions.bash000066400000000000000000000051261370063022300217250ustar00rootroot00000000000000#!/usr/bin/env bash BATS_TEST_DIRNAME="${BATS_TEST_FILENAME%/*}" BATS_TEST_NAMES=() # Shorthand for source-ing files relative to the BATS_TEST_DIRNAME, # optionally with a .bash suffix appended. If the argument doesn't # resolve relative to BATS_TEST_DIRNAME it is sourced as-is. load() { local file="${1:?}" # For backwards-compatibility first look for a .bash-suffixed file. # TODO consider flipping the order here; it would be more consistent # and less surprising to look for an exact-match first. if [[ -f "${BATS_TEST_DIRNAME}/${file}.bash" ]]; then file="${BATS_TEST_DIRNAME}/${file}.bash" elif [[ -f "${BATS_TEST_DIRNAME}/${file}" ]]; then file="${BATS_TEST_DIRNAME}/${file}" fi if [[ ! -f "$file" ]] && ! type -P "$file" >/dev/null; then printf 'bats: %s does not exist\n' "$file" >&2 exit 1 fi # Dynamically loaded user file provided outside of Bats. # Note: 'source "$file" || exit' doesn't work on bash3.2. # shellcheck disable=SC1090 source "${file}" } run() { local origFlags="$-" set +eET local origIFS="$IFS" # 'output', 'status', 'lines' are global variables available to tests. # shellcheck disable=SC2034 output="$("$@" 2>&1)" # shellcheck disable=SC2034 status="$?" # shellcheck disable=SC2034,SC2206 IFS=$'\n' lines=($output) IFS="$origIFS" set "-$origFlags" } setup() { return 0 } teardown() { return 0 } skip() { # if this is a skip in teardown ... if [[ -n "$BATS_TEARDOWN_STARTED" ]]; then # ... we want to skip the rest of teardown. # communicate to bats_exit_trap that the teardown was completed without error # shellcheck disable=SC2034 BATS_TEARDOWN_COMPLETED=1 # if we are already in the exit trap (e.g. due to previous skip) ... if [[ "$BATS_TEARDOWN_STARTED" == as-exit-trap ]]; then # ... we need to do the rest of the tear_down_trap that would otherwise be skipped after the next call to exit bats_exit_trap # and then do the exit (at the end of this function) fi # if we aren't in exit trap, the normal exit handling should suffice else # ... this is either skip in test or skip in setup. # Following variables are used in bats-exec-test which sources this file # shellcheck disable=SC2034 BATS_TEST_SKIPPED="${1:-1}" # shellcheck disable=SC2034 BATS_TEST_COMPLETED=1 fi exit 0 } bats_test_begin() { BATS_TEST_DESCRIPTION="$1" if [[ -n "$BATS_EXTENDED_SYNTAX" ]]; then printf 'begin %d %s\n' "$BATS_TEST_NUMBER" "$BATS_TEST_DESCRIPTION" >&3 fi setup } bats_test_function() { local test_name="$1" BATS_TEST_NAMES+=("$test_name") } bats-core-1.2.1/lib/bats-core/tracing.bash000066400000000000000000000101451370063022300203020ustar00rootroot00000000000000#!/usr/bin/env bash bats_capture_stack_trace() { local test_file local funcname local i BATS_STACK_TRACE=() for ((i = 2; i != ${#FUNCNAME[@]}; ++i)); do # Use BATS_TEST_SOURCE if necessary to work around Bash < 4.4 bug whereby # calling an exported function erases the test file's BASH_SOURCE entry. test_file="${BASH_SOURCE[$i]:-$BATS_TEST_SOURCE}" funcname="${FUNCNAME[$i]}" BATS_STACK_TRACE+=("${BASH_LINENO[$((i - 1))]} $funcname $test_file") if [[ "$test_file" == "$BATS_TEST_SOURCE" ]]; then case "$funcname" in "$BATS_TEST_NAME" | setup | teardown | setup_file | teardown_file) break ;; esac fi done } bats_print_stack_trace() { local frame local index=1 local count="${#@}" local filename local lineno for frame in "$@"; do bats_frame_filename "$frame" 'filename' bats_trim_filename "$filename" 'filename' bats_frame_lineno "$frame" 'lineno' if [[ $index -eq 1 ]]; then printf '# (' else printf '# ' fi local fn bats_frame_function "$frame" 'fn' if [[ "$fn" != "$BATS_TEST_NAME" ]]; then printf "from function \`%s' " "$fn" fi if [[ $index -eq $count ]]; then printf 'in test file %s, line %d)\n' "$filename" "$lineno" else printf 'in file %s, line %d,\n' "$filename" "$lineno" fi ((++index)) done } bats_print_failed_command() { local frame="${BATS_STACK_TRACE[${#BATS_STACK_TRACE[@]} - 1]}" local filename local lineno local failed_line local failed_command bats_frame_filename "$frame" 'filename' bats_frame_lineno "$frame" 'lineno' bats_extract_line "$filename" "$lineno" 'failed_line' bats_strip_string "$failed_line" 'failed_command' printf '%s' "# \`${failed_command}' " if [[ "$BATS_ERROR_STATUS" -eq 1 ]]; then printf 'failed\n' else printf 'failed with status %d\n' "$BATS_ERROR_STATUS" fi } bats_frame_lineno() { printf -v "$2" '%s' "${1%% *}" } bats_frame_function() { local __bff_function="${1#* }" printf -v "$2" '%s' "${__bff_function%% *}" } bats_frame_filename() { local __bff_filename="${1#* }" __bff_filename="${__bff_filename#* }" if [[ "$__bff_filename" == "$BATS_TEST_SOURCE" ]]; then __bff_filename="$BATS_TEST_FILENAME" fi printf -v "$2" '%s' "$__bff_filename" } bats_extract_line() { local __bats_extract_line_line local __bats_extract_line_index=0 while IFS= read -r __bats_extract_line_line; do if [[ "$((++__bats_extract_line_index))" -eq "$2" ]]; then printf -v "$3" '%s' "${__bats_extract_line_line%$'\r'}" break fi done <"$1" } bats_strip_string() { [[ "$1" =~ ^[[:space:]]*(.*)[[:space:]]*$ ]] printf -v "$2" '%s' "${BASH_REMATCH[1]}" } bats_trim_filename() { printf -v "$2" '%s' "${1#$BATS_CWD/}" } bats_debug_trap() { # don't update the trace within library functions or we get backtraces from inside traps if [[ "$1" != $BATS_ROOT/lib/* && "$1" != $BATS_ROOT/libexec/* ]]; then # The last entry in the stack trace is not useful when en error occured: # It is either duplicated (kinda correct) or has wrong line number (Bash < 4.4) # Therefore we capture the stacktrace but use it only after the next debug # trap fired. # Expansion is required for empty arrays which otherwise error BATS_CURRENT_STACK_TRACE=("${BATS_STACK_TRACE[@]+"${BATS_STACK_TRACE[@]}"}") bats_capture_stack_trace fi } # For some versions of Bash, the `ERR` trap may not always fire for every # command failure, but the `EXIT` trap will. Also, some command failures may not # set `$?` properly. See #72 and #81 for details. # # For this reason, we call `bats_error_trap` at the very beginning of # `bats_teardown_trap` (the `DEBUG` trap for the call will fix the stack trace) # and check the value of `$BATS_TEST_COMPLETED` before taking other actions. # We also adjust the exit status value if needed. # # See `bats_exit_trap` for an additional EXIT error handling case when `$?` # isn't set properly during `teardown()` errors. bats_error_trap() { local status="$?" if [[ -z "$BATS_TEST_COMPLETED" ]]; then BATS_ERROR_STATUS="${BATS_ERROR_STATUS:-$status}" if [[ "$BATS_ERROR_STATUS" -eq 0 ]]; then BATS_ERROR_STATUS=1 fi BATS_STACK_TRACE=("${BATS_CURRENT_STACK_TRACE[@]}") trap - DEBUG fi } bats-core-1.2.1/lib/bats-core/validator.bash000066400000000000000000000017521370063022300206440ustar00rootroot00000000000000#!/usr/bin/env bash bats_test_count_validator() { header_pattern='[0-9]+\.\.[0-9]+' IFS= read -r header # repeat the header printf "%s\n" "$header" # if we detect a TAP plan if [[ "$header" =~ $header_pattern ]]; then # extract the number of tests ... local expected_number_of_tests="${header:3}" # ... count the actual number of [not ] oks... local actual_number_of_tests=0 while IFS= read -r line; do # forward line printf "%s\n" "$line" case "$line" in 'ok '*) (( ++actual_number_of_tests )) ;; 'not ok'*) (( ++actual_number_of_tests )) ;; esac done # ... and error if they are not the same if [[ "${actual_number_of_tests}" != "${expected_number_of_tests}" ]]; then printf '# bats warning: Executed %s instead of expected %s tests\n' "$actual_number_of_tests" "$expected_number_of_tests" return 1 fi else # forward output unchanged cat fi }bats-core-1.2.1/libexec/000077500000000000000000000000001370063022300150015ustar00rootroot00000000000000bats-core-1.2.1/libexec/bats-core/000077500000000000000000000000001370063022300166605ustar00rootroot00000000000000bats-core-1.2.1/libexec/bats-core/bats000077500000000000000000000126771370063022300175540ustar00rootroot00000000000000#!/usr/bin/env bash set -e export BATS_VERSION='1.2.1' version() { printf 'Bats %s\n' "$BATS_VERSION" } abort() { printf 'Error: %s\n' "$1" >&2 usage >&2 exit 1 } usage() { local cmd="${0##*/}" local line cat < ${cmd} [-h | -v] HELP_TEXT_HEADER cat <<'HELP_TEXT_BODY' is the path to a Bats test file, or the path to a directory containing Bats test files (ending with ".bats") -c, --count Count test cases without running any tests -f, --filter Only run tests that match the regular expression -F, --formatter Switch between formatters: pretty (default), tap (default w/o term), junit -h, --help Display this help message -j, --jobs Number of parallel jobs (requires GNU parallel) --parallel-preserve-environment Preserve the current environment for "--jobs" (run `parallel --record-env` before) --no-tempdir-cleanup Preserve test output temporary directory -o, --output Directory to write report files -p, --pretty Shorthand for "--formatter pretty" -r, --recursive Include tests in subdirectories -t, --tap Shorthand for "--formatter tap" -T, --timing Add timing information to tests -v, --version Display the version number For more information, see https://github.com/bats-core/bats-core HELP_TEXT_BODY } expand_path() { local path="${1%/}" local dirname="${path%/*}" local result="$2" if [[ "$dirname" == "$path" ]]; then dirname="$PWD" else cd "$dirname" dirname="$PWD" cd "$OLDPWD" fi printf -v "$result" '%s/%s' "$dirname" "${path##*/}" } BATS_LIBEXEC="$(dirname "$(bats_readlinkf "${BASH_SOURCE[0]}")")" export BATS_CWD="$PWD" export BATS_TEST_PATTERN="^[[:blank:]]*@test[[:blank:]]+(.*[^[:blank:]])[[:blank:]]+\{(.*)\$" export BATS_TEST_FILTER= export PATH="$BATS_LIBEXEC:$PATH" export BATS_ROOT_PID=$$ if [[ -z "$TMPDIR" ]]; then export BATS_TMPDIR="/tmp" else export BATS_TMPDIR="${TMPDIR%/}" fi export BATS_RUN_TMPDIR="$BATS_TMPDIR/bats-run-$BATS_ROOT_PID" arguments=() # Unpack single-character options bundled together, e.g. -cr, -pr. for arg in "$@"; do if [[ "$arg" =~ ^-[^-]. ]]; then index=1 while option="${arg:$((index++)):1}"; do if [[ -z "$option" ]]; then break fi arguments+=("-$option") done else arguments+=("$arg") fi shift done set -- "${arguments[@]}" arguments=() unset flags recursive formatter_flags flags=() formatter_flags=() formatter='tap' recursive= tempdir_cleanup=1 output= if [[ -z "${CI:-}" && -t 0 && -t 1 ]] && command -v tput >/dev/null; then formatter='pretty' fi while [[ "$#" -ne 0 ]]; do case "$1" in -h | --help) version usage exit 0 ;; -v | --version) version exit 0 ;; -c | --count) flags+=('-c') ;; -f | --filter) shift flags+=('-f' "$1") ;; -F | --formatter) shift if [[ $1 =~ ^(pretty|junit|tap)$ ]]; then formatter="$1" else printf "Unknown formatter '%s', valid options are pretty, junit, tap\n" "$1" exit 1 fi ;; -o | --output) shift output="$1" ;; -p | --pretty) formatter='pretty' ;; -j | --jobs) shift flags+=('-j' "$1") ;; -r | --recursive) recursive=1 ;; -t | --tap) formatter='tap' ;; -T | --timing) flags+=('-T') formatter_flags+=('-T') ;; --parallel-preserve-environment) flags+=("--parallel-preserve-environment") # check if parallel's env setup was run before # will print on stderr and return 255 on failure # suppress stdout (on success) parallel --env _ echo ::: 1 >/dev/null || exit 1 ;; --no-tempdir-cleanup) tempdir_cleanup='' ;; -*) abort "Bad command line option '$1'" ;; *) arguments+=("$1") ;; esac shift done if [[ -d "$BATS_RUN_TMPDIR" ]]; then printf "Error: BATS_RUN_TMPDIR (%s) already exists\n" "$BATS_RUN_TMPDIR" >&2 printf "Reusing old run directories can lead to unexpected results ... aborting!\n" >&2 exit 1 fi mkdir -p "$BATS_RUN_TMPDIR" if [[ -n "$tempdir_cleanup" ]]; then trap 'rm -rf "$BATS_RUN_TMPDIR"' ERR EXIT fi if [[ "$formatter" != "tap" ]]; then flags+=('-x') fi if [[ "$formatter" == "junit" ]]; then flags+=('-T') formatter_flags+=('-T') fi if [[ "${#arguments[@]}" -eq 0 ]]; then abort 'Must specify at least one ' fi if [[ -n "$output" ]]; then if [[ ! -w "${output}" ]]; then abort "Output path ${output} is not writeable" fi export BATS_REPORT_OUTPUT_PATH="$output" fi filenames=() for filename in "${arguments[@]}"; do expand_path "$filename" 'filename' if [[ -d "$filename" ]]; then shopt -s nullglob if [[ "$recursive" -eq 1 ]]; then while IFS= read -r -d $'\0' file; do filenames+=("$file") done < <(find "$filename" -type f -name '*.bats' -print0 | sort -z) else for suite_filename in "$filename"/*.bats; do filenames+=("$suite_filename") done fi shopt -u nullglob else filenames+=("$filename") fi done # shellcheck source=lib/bats-core/validator.bash source "$BATS_ROOT/lib/bats-core/validator.bash" set -o pipefail execfail exec bats-exec-suite "${flags[@]}" "${filenames[@]}" | bats_test_count_validator | "bats-format-${formatter}" "${formatter_flags[@]}" bats-core-1.2.1/libexec/bats-core/bats-exec-file000077500000000000000000000130261370063022300214000ustar00rootroot00000000000000#!/usr/bin/env bash set -eET export flags=() num_jobs=1 filter='' extended_syntax='' while [[ "$#" -ne 0 ]]; do case "$1" in -c) ;; -f) shift filter="$1" flags+=('-f' "$filter") ;; -j) shift num_jobs="$1" ;; -T) flags+=('-T') ;; -x) flags+=('-x') extended_syntax=1 ;; *) break ;; esac shift done filename=$1 TESTS_FILE="$2" if [[ ! -f "$filename" ]]; then printf 'Testfile "%s" not found\n' "$filename" >&2 exit 1 fi BATS_TEST_FILENAME="$filename" # shellcheck source=lib/bats-core/preprocessing.bash # shellcheck disable=SC2153 source "$BATS_ROOT/lib/bats-core/preprocessing.bash" bats_run_setup_file() { # shellcheck source=lib/bats-core/tracing.bash # shellcheck disable=SC2153 source "$BATS_ROOT/lib/bats-core/tracing.bash" # shellcheck source=lib/bats-core/test_functions.bash # shellcheck disable=SC2153 source "$BATS_ROOT/lib/bats-core/test_functions.bash" exec 3<&1 BATS_STACK_TRACE=() # shellcheck disable=2034 BATS_CURRENT_STACK_TRACE=() # used in tracing.bash # these are defined only to avoid errors when referencing undefined variables down the line # shellcheck disable=2034 BATS_TEST_NAME= # used in tracing.bash # shellcheck disable=2034 BATS_TEST_COMPLETED= # used in tracing.bash BATS_SETUP_FILE_COMPLETED= BATS_TEARDOWN_FILE_COMPLETED= # shellcheck disable=2034 BATS_ERROR_STATUS= # used in tracing.bash trap 'bats_debug_trap "$BASH_SOURCE"' DEBUG trap 'bats_error_trap' ERR trap 'bats_file_teardown_trap' EXIT touch "$BATS_OUT" # get the setup_file/teardown_file functions for this file (if it has them) # shellcheck disable=SC1090 source "$BATS_TEST_SOURCE" setup_file >>"$BATS_OUT" 2>&1 BATS_SETUP_FILE_COMPLETED=1 } bats_run_teardown_file() { # avoid running the therdown trap due to errors in teardown_file trap 'bats_file_exit_trap' EXIT local status=0 # rely on bats_error_trap to catch failures teardown_file >>"$BATS_OUT" 2>&1 BATS_TEARDOWN_FILE_COMPLETED=1 } bats_file_teardown_trap() { bats_error_trap local status=0 bats_run_teardown_file bats_file_exit_trap } bats_file_exit_trap() { trap - ERR EXIT if [[ -z "$BATS_SETUP_FILE_COMPLETED" || -z "$BATS_TEARDOWN_FILE_COMPLETED" ]]; then if [[ -z "$BATS_SETUP_FILE_COMPLETED" ]]; then FAILURE_REASON='setup_file' else FAILURE_REASON='teardown_file' fi printf "not ok %d %s\n" "$((test_number + 1))" "$FAILURE_REASON failed" >&3 bats_print_stack_trace "${BATS_STACK_TRACE[@]}" >&3 bats_print_failed_command >&3 while IFS= read -r line; do printf "# %s\n" "$line" done <"$BATS_OUT" >&3 if [[ -n "$line" ]]; then printf '# %s\n' "$line" fi rm -rf "$BATS_OUT" status=1 fi bats_cleanup_preprocessed_source exit $status } function setup_file() { return 0 } function teardown_file() { return 0 } bats_run_tests() { status=0 tests_to_run=() local line_number=0 test_number='' while read -r test_line; do test_file=${test_line%%$'\t'*} test_name=${test_line##*$'\t'} if [[ "$test_file" == "$filename" ]]; then tests_to_run+=("$test_name") # save the first test's number for later iteration # this assumes that tests for a file are stored consecutive in the file! if [[ -z $test_number ]]; then test_number=$line_number fi fi ((++line_number)) done <"$TESTS_FILE" if [[ "$num_jobs" != 1 ]]; then test_pids_and_numbers=() output_folder="$BATS_RUN_TMPDIR/parallel_output" parallel_log_file="$BATS_RUN_TMPDIR/parallel.log" for test_name in "${tests_to_run[@]}"; do # Only handle non-empty lines if [[ $test_name ]]; then ((++test_number)) test_output_dir="$output_folder/$test_number" mkdir -p "$test_output_dir" # parallelize across files using parallel's semaphore mode # use --results to gather output in separate files # use --fg mode to retrieve exit codes (all non zero exit codes seem to mapped to 1), but which requires us to suppress its output # shellcheck disable=SC2154 #bats_parallel_args is inherited from exec-suite parallel --semaphore -j "$num_jobs" "${bats_parallel_args[@]}" --fg -- bats-exec-test "${flags[@]}" "$filename" "$test_name" "$test_number" >"$test_output_dir/stdout" 2>"$test_output_dir/stderr" & pid=$! test_pids_and_numbers+=("$pid,$test_number") fi done for test_pid_and_number in "${test_pids_and_numbers[@]}"; do test_pid=${test_pid_and_number%,*} test_number=${test_pid_and_number##*,} test_output_dir="$output_folder/$test_number" # fetch the return code wait "$test_pid" || status=1 # wait for tests to finish in the order they were started and output their results as they come in cat "$test_output_dir/stdout" # additionally output stderr as parallel does by default cat "$test_output_dir/stderr" >&2 done else for test_name in "${tests_to_run[@]}"; do # Only handle non-empty lines if [[ $test_name ]]; then ((++test_number)) if [[ "${#flags[@]}" -gt 0 ]]; then bats-exec-test "${flags[@]}" "$filename" "$test_name" "$test_number" || status=1 else bats-exec-test "$filename" "$test_name" "$test_number" || status=1 fi fi done fi export status } if [[ -n "$extended_syntax" ]]; then printf "suite %s\n" "$(basename "$filename")" fi bats_preprocess_source "$filename" bats_run_setup_file bats_run_tests bats_run_teardown_file exit $status bats-core-1.2.1/libexec/bats-core/bats-exec-suite000077500000000000000000000045221370063022300216130ustar00rootroot00000000000000#!/usr/bin/env bash set -e count_only_flag='' filter='' num_jobs=1 have_gnu_parallel= bats_parallel_args=() flags=() abort() { printf 'Error: %s\n' "$1" >&2 exit 1 } while [[ "$#" -ne 0 ]]; do case "$1" in -c) count_only_flag=1 ;; -f) shift filter="$1" flags+=('-f' "$filter") ;; -j) shift num_jobs="$1" flags+=('-j' "$num_jobs") ;; -T) flags+=('-T') ;; -x) flags+=('-x') ;; --parallel-preserve-environment) bats_parallel_args=("--env" "_") ;; *) break ;; esac shift done if (type -p parallel &>/dev/null); then # shellcheck disable=SC2034 have_gnu_parallel=1 elif [[ "$num_jobs" != 1 ]]; then abort "Cannot execute \"${num_jobs}\" jobs without GNU parallel" exit 1 fi trap 'kill 0; exit 1' INT # create a file that contains all (filtered) tests to run from all files TESTS_LIST_FILE="${BATS_RUN_TMPDIR}/test_list_file.txt" all_tests=() for filename in "$@"; do if [[ ! -f "$filename" ]]; then abort "Test file \"${filename}\" does not exist" fi test_names=() test_dupes=() while read -r line; do if [[ ! "$line" =~ ^bats_test_function\ ]]; then continue fi line="${line%$'\r'}" line="${line#* }" test_line=$(printf "%s\t%s" "$filename" "$line") all_tests+=("$test_line") printf "%s\n" "$test_line" >>"$TESTS_LIST_FILE" if [[ " ${test_names[*]} " == *" $line "* ]]; then test_dupes+=("$line") continue fi test_names+=("$line") done < <(BATS_TEST_FILTER="$filter" bats-preprocess "$filename") if [[ "${#test_dupes[@]}" -ne 0 ]]; then abort "Duplicate test name(s) in file \"${filename}\": ${test_dupes[*]}" fi done test_count="${#all_tests[@]}" if [[ -n "$count_only_flag" ]]; then printf '%d\n' "${test_count}" exit fi status=0 printf '1..%d\n' "${test_count}" # No point on continuing if there's no tests. if [[ "${test_count}" == 0 ]]; then exit fi if [[ "$num_jobs" -gt 1 ]]; then # run files in parallel to get the maximum pool of parallel tasks # shellcheck disable=SC2086,SC2068 printf "%s\n" "$@" | parallel "${bats_parallel_args[@]}" --keep-order --jobs "$num_jobs" bats-exec-file "${flags[@]}" {} "$TESTS_LIST_FILE" || status=1 else for filename in "$@"; do bats-exec-file "${flags[@]}" "$filename" "${TESTS_LIST_FILE}" || status=1 done fi exit "$status" bats-core-1.2.1/libexec/bats-core/bats-exec-test000077500000000000000000000112321370063022300214350ustar00rootroot00000000000000#!/usr/bin/env bash set -eET # Variables used in other scripts. BATS_COUNT_ONLY='' BATS_TEST_FILTER='' BATS_ENABLE_TIMING='' BATS_EXTENDED_SYNTAX='' while [[ "$#" -ne 0 ]]; do case "$1" in -c) # shellcheck disable=SC2034 BATS_COUNT_ONLY=1 ;; -f) shift # shellcheck disable=SC2034 BATS_TEST_FILTER="$1" ;; -T) BATS_ENABLE_TIMING='-T' BATS_PERFORM_TEST_CMD+=('-T') ;; -x) # shellcheck disable=SC2034 BATS_EXTENDED_SYNTAX='-x' ;; *) break ;; esac shift done BATS_TEST_FILENAME="$1" shift if [[ -z "$BATS_TEST_FILENAME" ]]; then printf 'usage: bats-exec-test \n' >&2 exit 1 elif [[ ! -f "$BATS_TEST_FILENAME" ]]; then printf 'bats: %s does not exist\n' "$BATS_TEST_FILENAME" >&2 exit 1 fi # load the test helper functions like `load` or `run` that are needed to run a (preprocessed) .bats file without bash errors # shellcheck source=lib/bats-core/test_functions.bash disable=SC2153 source "$BATS_ROOT/lib/bats-core/test_functions.bash" # shellcheck source=lib/bats-core/tracing.bash disable=SC2153 source "$BATS_ROOT/lib/bats-core/tracing.bash" bats_teardown_trap() { bats_error_trap local status=0 # mark the start of this function to distinguish where skip is called # parameter 1 will signify the reason why this function was called # this is used to identify when this is called as exit trap function BATS_TEARDOWN_STARTED=${1:-1} teardown >>"$BATS_OUT" 2>&1 || status="$?" if [[ $status -eq 0 ]]; then BATS_TEARDOWN_COMPLETED=1 elif [[ -n "$BATS_TEST_COMPLETED" ]]; then BATS_ERROR_STATUS="$status" fi bats_exit_trap } bats_exit_trap() { local line local status local skipped='' trap - ERR EXIT if [[ -n "$BATS_TEST_SKIPPED" ]]; then skipped=' # skip' if [[ "$BATS_TEST_SKIPPED" != '1' ]]; then skipped+=" $BATS_TEST_SKIPPED" fi fi BATS_TEST_TIME="" if [[ -z "${skipped}" && -n "$BATS_ENABLE_TIMING" ]]; then BATS_TEST_TIME=" in "$((SECONDS - BATS_TEST_START_TIME))"sec" fi if [[ -z "$BATS_TEST_COMPLETED" || -z "$BATS_TEARDOWN_COMPLETED" ]]; then if [[ "$BATS_ERROR_STATUS" -eq 0 ]]; then # For some versions of bash, `$?` may not be set properly for some error # conditions before triggering the EXIT trap directly (see #72 and #81). # Thanks to the `BATS_TEARDOWN_COMPLETED` signal, this will pinpoint such # errors if they happen during `teardown()` when `bats_perform_test` calls # `bats_teardown_trap` directly after the test itself passes. # # If instead the test fails, and the `teardown()` error happens while # `bats_teardown_trap` runs as the EXIT trap, the test will fail with no # output, since there's no way to reach the `bats_exit_trap` call. BATS_STACK_TRACE=("${BATS_CURRENT_STACK_TRACE[@]}") BATS_ERROR_STATUS=1 fi printf 'not ok %d %s\n' "$BATS_TEST_NUMBER" "${BATS_TEST_DESCRIPTION}${BATS_TEST_TIME}" >&3 bats_print_stack_trace "${BATS_STACK_TRACE[@]}" >&3 bats_print_failed_command >&3 while IFS= read -r line; do printf '# %s\n' "$line" done <"$BATS_OUT" >&3 if [[ -n "$line" ]]; then printf '# %s\n' "$line" fi status=1 else printf 'ok %d %s%s\n' "$BATS_TEST_NUMBER" "${BATS_TEST_DESCRIPTION}${BATS_TEST_TIME}" \ "$skipped" >&3 status=0 fi rm -f "$BATS_OUT" bats_cleanup_preprocessed_source exit "$status" } bats_perform_test() { BATS_TEST_NAME="$1" BATS_TEST_NUMBER="$2" if ! declare -F "$BATS_TEST_NAME" &>/dev/null; then printf "bats: unknown test name \`%s'\n" "$BATS_TEST_NAME" >&2 exit 1 fi # Some versions of Bash will reset BASH_LINENO to the first line of the # function when the ERR trap fires. All versions of Bash appear to reset it # on an unbound variable access error. bats_debug_trap will fire both before # the offending line is executed, and when the error is triggered. # Consequently, we use `BATS_CURRENT_STACK_TRACE` recorded by the # first call to bats_debug_trap, _before_ the ERR trap or unbound variable # access fires. BATS_STACK_TRACE=() BATS_CURRENT_STACK_TRACE=() BATS_TEST_COMPLETED= BATS_TEST_SKIPPED= BATS_TEARDOWN_COMPLETED= BATS_ERROR_STATUS= trap 'bats_debug_trap "$BASH_SOURCE"' DEBUG trap 'bats_error_trap' ERR # mark this call as trap call trap 'bats_teardown_trap as-exit-trap' EXIT "$BATS_TEST_NAME" >>"$BATS_OUT" 2>&1 BATS_TEST_COMPLETED=1 trap 'bats_exit_trap' EXIT bats_teardown_trap } # shellcheck source=lib/bats-core/preprocessing.bash source "$BATS_ROOT/lib/bats-core/preprocessing.bash" exec 3<&1 # Run the given test. bats_preprocess_source bats_evaluate_preprocessed_source bats_perform_test "$@" bats-core-1.2.1/libexec/bats-core/bats-format-junit000077500000000000000000000065541370063022300221660ustar00rootroot00000000000000#!/usr/bin/env bash set -euo pipefail index=0 init_suite() { count=0 failures=0 skipped=0 suitetest_exec_time=0 name="" _buffer="" _buffer_log="" } init_suite host() { local hostname="${HOST:-}" [[ -z "$hostname" ]] && hostname="${HOSTNAME:-}" [[ -z "$hostname" ]] && hostname="$(uname -n)" [[ -z "$hostname" ]] && hostname="$(hostname -f)" echo "$hostname" } header() { timestamp=$(date -u +"%Y-%m-%dT%H:%M:%S") printf "\ " "${class}" "${count}" "${failures}" "${skipped}" "${suitetest_exec_time}" "${timestamp}" "$(host)" while IFS= read -r line; do name="$(echo "$line" | cut -d'=' -f1)" value="$(echo "$line" | cut -d'=' -f2-)" printf "\n " "${name}" "${value}" done < <(env | grep "^BATS_") printf "\n " } footer() { printf " \n" printf " \n" printf "\n" } pass() { printf "\n " "${class}" "${name}" "${test_exec_time}" } fail() { printf "\n \n" } skip() { # shellcheck disable=SC2183 printf "\n %s \n" "${class}" "${name}" "${test_exec_time}" "$1" } buffer() { _buffer="${_buffer}$("$@")" } flush() { echo "${_buffer}" _buffer="" } log() { _buffer_log="${_buffer_log} $1" } flush_log() { if [[ -n "${_buffer_log}" ]]; then buffer fail "${_buffer_log}" _buffer_log="" fi } finish_suite() { [[ ${count} -gt 0 ]] && { ( flush_log header flush footer ) >"$(output_path)" } init_suite } output_path() { path="TestReport-${class}.xml" if [[ -n "${BATS_REPORT_OUTPUT_PATH:-}" ]]; then path="${BATS_REPORT_OUTPUT_PATH%/}/${path}" fi echo "$path" } trap finish_suite EXIT while IFS= read -r line; do case "$line" in "suite "*) flush_log finish_suite suite_expr="suite (.*)" if [[ "$line" =~ $suite_expr ]]; then class="${BASH_REMATCH[1]}" fi ;; "begin "*) flush_log ((index += 1)) name="${line#* $index }" ;; "ok "*) echo "$line" ((count += 1)) expr_ok="ok $index .* in ([0-9]+)sec" expr_skip="ok $index .* # skip[ ]?(.*)" if [[ "$line" =~ $expr_skip ]]; then ((skipped += 1)) test_exec_time=0 buffer skip "${BASH_REMATCH[1]}" elif [[ "$line" =~ $expr_ok ]]; then test_exec_time="${BASH_REMATCH[1]}" suitetest_exec_time=$((suitetest_exec_time + test_exec_time)) buffer pass else log "Wrong output format: ${line}" ((failures += 1)) fi ;; "not ok "*) echo "$line" ((count += 1)) ((failures += 1)) expr_notok="not ok $index .* in ([0-9]+)sec" if [[ "$line" =~ $expr_notok ]]; then test_exec_time="${BASH_REMATCH[1]}" suitetest_exec_time=$((suitetest_exec_time + test_exec_time)) fi ;; "# "*) log "${line:2}" ;; *) echo "$line" ;; esac done bats-core-1.2.1/libexec/bats-core/bats-format-pretty000077500000000000000000000105051370063022300223530ustar00rootroot00000000000000#!/usr/bin/env bash set -e while [[ "$#" -ne 0 ]]; do case "$1" in -T) BATS_ENABLE_TIMING="-T" ;; esac shift done header_pattern='[0-9]+\.\.[0-9]+' IFS= read -r header update_count_column_width() { count_column_width=$((${#count} * 2 + 2)) if [[ -n "$BATS_ENABLE_TIMING" ]]; then # additional space for ' in %s sec' count_column_width=$((count_column_width + ${#SECONDS} + 8)) fi # also update dependent value update_count_column_left } update_screen_width() { screen_width="$(tput cols)" # also update dependent value update_count_column_left } update_count_column_left() { count_column_left=$((screen_width - count_column_width)) } if [[ "$header" =~ $header_pattern ]]; then count="${header:3}" index=0 passed=0 failures=0 skipped=0 name= update_count_column_width else # If the first line isn't a TAP plan, print it and pass the rest through printf '%s\n' "$header" exec cat fi trap update_screen_width WINCH update_screen_width begin() { go_to_column 0 update_count_column_width buffer_with_truncation $((count_column_left - 1)) ' %s' "$name" clear_to_end_of_line go_to_column $count_column_left if [[ -n "$BATS_ENABLE_TIMING" ]]; then buffer "%${#count}s/${count} in %s sec" "$index" "$SECONDS" else buffer "%${#count}s/${count}" "$index" fi go_to_column 1 } pass() { go_to_column 0 if [[ -n "$BATS_ENABLE_TIMING" ]]; then buffer ' ✓ %s [%s]' "$name" "$1" else buffer ' ✓ %s ' "$name" fi advance } skip() { local reason="$1" if [[ -n "$reason" ]]; then reason=": $reason" fi go_to_column 0 buffer ' - %s (skipped%s)' "$name" "$reason" advance } fail() { go_to_column 0 set_color 1 bold if [[ -n "$BATS_ENABLE_TIMING" ]]; then buffer ' ✗ %s [%s]' "$name" "$1" else buffer ' ✗ %s' "$name" fi advance } log() { set_color 1 buffer ' %s\n' "$1" clear_color } summary() { buffer '\n%d test' "$count" if [[ "$count" -ne 1 ]]; then buffer 's' fi buffer ', %d failure' "$failures" if [[ "$failures" -ne 1 ]]; then buffer 's' fi if [[ "$skipped" -gt 0 ]]; then buffer ', %d skipped' "$skipped" fi not_run=$((count - passed - failures - skipped)) if [[ "$not_run" -gt 0 ]]; then buffer ', %d not run' "$not_run" fi if [[ -n "$BATS_ENABLE_TIMING" ]]; then buffer " in $SECONDS seconds" fi buffer '\n' } buffer_with_truncation() { local width="$1" shift local string # shellcheck disable=SC2059 printf -v 'string' -- "$@" if [[ "${#string}" -gt "$width" ]]; then buffer '%s...' "${string:0:$((width - 4))}" else buffer '%s' "$string" fi } go_to_column() { local column="$1" buffer '\x1B[%dG' $((column + 1)) } clear_to_end_of_line() { buffer '\x1B[K' } advance() { clear_to_end_of_line buffer '\n' clear_color } set_color() { local color="$1" local weight=22 if [[ "$2" == 'bold' ]]; then weight=1 fi buffer '\x1B[%d;%dm' "$((30 + color))" "$weight" } clear_color() { buffer '\x1B[0m' } _buffer= buffer() { local content # shellcheck disable=SC2059 printf -v content -- "$@" _buffer+="$content" } flush() { printf '%s' "$_buffer" [[ -n "$BATS_REPORT_OUTPUT_PATH" ]] && printf '%s' "$_buffer" | tee "$BATS_REPORT_OUTPUT_PATH/report.tap" >/dev/null _buffer= } finish() { flush printf '\n' } trap finish EXIT timing_expr="in (([0-9]+sec))$" while IFS= read -r line; do case "$line" in 'begin '*) ((++index)) name="${line#* $index }" begin flush ;; 'ok '*) skip_expr="ok $index (.*) # skip ?(([[:print:]]*))?" if [[ "$line" =~ $skip_expr ]]; then ((++skipped)) skip "${BASH_REMATCH[2]}" else ((++passed)) if [[ -n "$BATS_ENABLE_TIMING" ]]; then if [[ "$line" =~ $timing_expr ]]; then pass "${BASH_REMATCH[2]}" else echo "Could not match output line to timing regex: $line" >&2 exit 1 fi else pass fi fi ;; 'not ok '*) ((++failures)) if [[ -n "$BATS_ENABLE_TIMING" ]]; then if [[ "$line" =~ $timing_expr ]]; then fail "${BASH_REMATCH[2]}" else echo "Could not match failure line to timing regex: $line" >&2 exit 1 fi else fail fi ;; '# '*) log "${line:2}" ;; 'suite '*) ;; esac done summary bats-core-1.2.1/libexec/bats-core/bats-format-tap000077500000000000000000000000401370063022300216010ustar00rootroot00000000000000#!/usr/bin/env bash set -e cat bats-core-1.2.1/libexec/bats-core/bats-preprocess000077500000000000000000000024341370063022300217250ustar00rootroot00000000000000#!/usr/bin/env bash set -e bats_encode_test_name() { local name="$1" local result='test_' local hex_code if [[ ! "$name" =~ [^[:alnum:]\ _-] ]]; then name="${name//_/-5f}" name="${name//-/-2d}" name="${name// /_}" result+="$name" else local length="${#name}" local char i for ((i = 0; i < length; i++)); do char="${name:$i:1}" if [[ "$char" == ' ' ]]; then result+='_' elif [[ "$char" =~ [[:alnum:]] ]]; then result+="$char" else printf -v 'hex_code' -- '-%02x' \'"$char" result+="$hex_code" fi done fi printf -v "$2" '%s' "$result" } test_file="$1" tests=() { while IFS= read -r line; do line="${line//$'\r'/}" if [[ "$line" =~ $BATS_TEST_PATTERN ]]; then name="${BASH_REMATCH[1]#[\'\"]}" name="${name%[\'\"]}" body="${BASH_REMATCH[2]}" bats_encode_test_name "$name" 'encoded_name' printf '%s() { bats_test_begin "%s"; %s\n' "${encoded_name:?}" "$name" "$body" || : if [[ -z "$BATS_TEST_FILTER" || "$name" =~ $BATS_TEST_FILTER ]]; then tests+=("$encoded_name") fi else printf '%s\n' "$line" fi done } <<<"$(<"$test_file")"$'\n' for test_name in "${tests[@]}"; do printf 'bats_test_function %s\n' "$test_name" done bats-core-1.2.1/man/000077500000000000000000000000001370063022300141415ustar00rootroot00000000000000bats-core-1.2.1/man/Makefile000066400000000000000000000006531370063022300156050ustar00rootroot00000000000000# Makefile # # bats-core manpages # RONN := ronn -W PAGES := bats.1 bats.7 ORG := bats-core MANUAL := 'Bash Automated Testing System' ISOFMT := $(shell date -I) RM := rm -f .PHONY: all clean all: $(PAGES) bats.1: bats.1.ronn $(RONN) --date=$(ISOFMT) --manual=$(MANUAL) --organization=$(ORG) --roff $< bats.7: bats.7.ronn $(RONN) --date=$(ISOFMT) --manual=$(MANUAL) --organization=$(ORG) --roff $< clean: $(RM) $(PAGES) bats-core-1.2.1/man/README.md000066400000000000000000000003751370063022300154250ustar00rootroot00000000000000Bats man pages are generated with [Ronn](http://rtomayko.github.io/ronn/). After making changes to `bats.1.ronn` or `bats.7.ronn`, run `make` in this directory to generate `bats.1` and `bats.7`. **Do not edit the `bats.1` or `bats.7` files directly.** bats-core-1.2.1/man/bats.1000066400000000000000000000073741370063022300151670ustar00rootroot00000000000000.\" generated with Ronn-NG/v0.9.0 .\" http://github.com/apjanke/ronn-ng/tree/0.9.0 .TH "BATS" "1" "April 2020" "bats-core" "Bash Automated Testing System" .SH "NAME" \fBbats\fR \- Bash Automated Testing System .SH "SYNOPSIS" Usage: bats [OPTIONS] \fItests\fR bats [\-h | \-v] .P \fItests\fR is the path to a Bats test file, or the path to a directory containing Bats test files (ending with "\.bats") .SH "DESCRIPTION" 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\. .P A Bats test file is a Bash script with special syntax for defining test cases\. Under the hood, each test case is just a function with a description\. .P Test cases consist of standard shell commands\. Bats makes use of Bash\'s \fBerrexit\fR (\fBset \-e\fR) option when running test cases\. If every command in the test case exits with a \fB0\fR status code (success), the test passes\. In this way, each line is an assertion of truth\. .P See \fBbats\fR(7) for more information on writing Bats tests\. .SH "RUNNING TESTS" To run your tests, invoke the \fBbats\fR interpreter with a path to a test file\. The file\'s test cases are run sequentially and in isolation\. If all the test cases pass, \fBbats\fR exits with a \fB0\fR status code\. If there are any failures, \fBbats\fR exits with a \fB1\fR status code\. .P You can invoke the \fBbats\fR interpreter with multiple test file arguments, or with a path to a directory containing multiple \fB\.bats\fR files\. Bats will run each test file individually and aggregate the results\. If any test case fails, \fBbats\fR exits with a \fB1\fR status code\. .SH "OPTIONS" .TP \fB\-c\fR, \fB\-\-count\fR Count the number of test cases without running any tests .TP \fB\-f\fR, \fB\-\-filter \fR Filter test cases by names matching the regular expression .TP \fB\-F\fR, \fB\-\-formatter \fR Switch between formatters: pretty (default), tap (default w/o term), junit .TP \fB\-h\fR, \fB\-\-help\fR Display this help message .TP \fB\-j\fR, \fB\-\-jobs \fR Display this help message .TP \fB\-\-parallel\-preserve\-environment\fR Preserve the current environment for "\-\-jobs" (run \fBparallel \-\-record\-env\fR before) .TP \fB\-\-no\-tempdir\-cleanup\fR Preserve test output temporary directory .TP \fB\-o\fR, \fB\-\-output \fR Directory to write report files .TP \fB\-p\fR, \fB\-\-pretty\fR Shorthand for "\-\-formatter pretty" .TP \fB\-r\fR, \fB\-\-recursive\fR Include tests in subdirectories .TP \fB\-t\fR, \fB\-\-tap\fR Shorthand for "\-\-formatter tap" .TP \fB\-T\fR, \fB\-\-timing\fR Add timing information to tests .TP \fB\-v\fR, \fB\-\-version\fR Display the version number .SH "OUTPUT" When you run Bats from a terminal, you\'ll see output as each test is performed, with a check\-mark next to the test\'s name if it passes or an "X" if it fails\. .IP "" 4 .nf $ bats addition\.bats ✓ addition using bc ✓ addition using dc 2 tests, 0 failures .fi .IP "" 0 .P If Bats is not connected to a terminal\-\-in other words, if you run it from a continuous integration system or redirect its output to a file\-\-the results are displayed in human\-readable, machine\-parsable TAP format\. You can force TAP output from a terminal by invoking Bats with the \fB\-\-tap\fR option\. .IP "" 4 .nf $ bats \-\-tap addition\.bats 1\.\.2 ok 1 addition using bc ok 2 addition using dc .fi .IP "" 0 .SH "EXIT STATUS" The \fBbats\fR interpreter exits with a value of \fB0\fR if all test cases pass, or \fB1\fR if one or more test cases fail\. .SH "SEE ALSO" Bats wiki: \fIhttps://github\.com/bats\-core/bats\-core/wiki/\fR .P \fBbash\fR(1), \fBbats\fR(7) .SH "COPYRIGHT" (c) 2017\-2018 bats\-core organization .br (c) 2011\-2016 Sam Stephenson .P Bats is released under the terms of an MIT\-style license\. bats-core-1.2.1/man/bats.1.ronn000066400000000000000000000067301370063022300161350ustar00rootroot00000000000000bats(1) -- Bash Automated Testing System ======================================== SYNOPSIS -------- Usage: bats [OPTIONS] bats [-h | -v] is the path to a Bats test file, or the path to a directory containing Bats test files (ending with ".bats") DESCRIPTION ----------- 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. A Bats test file is a Bash script with special syntax for defining test cases. Under the hood, each test case is just a function with a description. Test cases consist of standard shell commands. Bats makes use of Bash's `errexit` (`set -e`) option when running test cases. If every command in the test case exits with a `0` status code (success), the test passes. In this way, each line is an assertion of truth. See `bats`(7) for more information on writing Bats tests. RUNNING TESTS ------------- To run your tests, invoke the `bats` interpreter with a path to a test file. The file's test cases are run sequentially and in isolation. If all the test cases pass, `bats` exits with a `0` status code. If there are any failures, `bats` exits with a `1` status code. You can invoke the `bats` interpreter with multiple test file arguments, or with a path to a directory containing multiple `.bats` files. Bats will run each test file individually and aggregate the results. If any test case fails, `bats` exits with a `1` status code. OPTIONS ------- * `-c`, `--count`: Count the number of test cases without running any tests * `-f`, `--filter `: Filter test cases by names matching the regular expression * `-F`, `--formatter `: Switch between formatters: pretty (default), tap (default w/o term), junit * `-h`, `--help`: Display this help message * `-j`, `--jobs `: Number of parallel jobs (requires GNU parallel) * `--parallel-preserve-environment`: Preserve the current environment for "--jobs" (run `parallel --record-env` before) * `--no-tempdir-cleanup`: Preserve test output temporary directory * `-o`, `--output `: Directory to write report files * `-p`, `--pretty`: Shorthand for "--formatter pretty" * `-r`, `--recursive`: Include tests in subdirectories * `-t`, `--tap`: Shorthand for "--formatter tap" * `-T`, `--timing`: Add timing information to tests * `-v`, `--version`: Display the version number OUTPUT ------ When you run Bats from a terminal, you'll see output as each test is performed, with a check-mark next to the test's name if it passes or an "X" if it fails. $ bats addition.bats ✓ addition using bc ✓ addition using dc 2 tests, 0 failures If Bats is not connected to a terminal--in other words, if you run it from a continuous integration system or redirect its output to a file--the results are displayed in human-readable, machine-parsable TAP format. You can force TAP output from a terminal by invoking Bats with the `--tap` option. $ bats --tap addition.bats 1..2 ok 1 addition using bc ok 2 addition using dc EXIT STATUS ----------- The `bats` interpreter exits with a value of `0` if all test cases pass, or `1` if one or more test cases fail. SEE ALSO -------- Bats wiki: _https://github.com/bats\-core/bats\-core/wiki/_ `bash`(1), `bats`(7) COPYRIGHT --------- (c) 2017-2018 bats-core organization
(c) 2011-2016 Sam Stephenson Bats is released under the terms of an MIT-style license. bats-core-1.2.1/man/bats.7000066400000000000000000000115001370063022300151570ustar00rootroot00000000000000.\" generated with Ronn/v0.7.3 .\" http://github.com/rtomayko/ronn/tree/0.7.3 . .TH "BATS" "7" "May 2019" "bats-core" "Bash Automated Testing System" . .SH "NAME" \fBbats\fR \- Bats test file format . .SH "DESCRIPTION" A Bats test file is a Bash script with special syntax for defining test cases\. Under the hood, each test case is just a function with a description\. . .IP "" 4 . .nf #!/usr/bin/env bats @test "addition using bc" { result="$(echo 2+2 | bc)" [ "$result" \-eq 4 ] } @test "addition using dc" { result="$(echo 2 2+p | dc)" [ "$result" \-eq 4 ] } . .fi . .IP "" 0 . .P Each Bats test file is evaluated n+1 times, where \fIn\fR is the number of test cases in the file\. The first run counts the number of test cases, then iterates over the test cases and executes each one in its own process\. . .SH "THE RUN HELPER" Many Bats tests need to run a command and then make assertions about its exit status and output\. Bats includes a \fBrun\fR helper that invokes its arguments as a command, saves the exit status and output into special global variables, and then returns with a \fB0\fR status code so you can continue to make assertions in your test case\. . .P For example, let\'s say you\'re testing that the \fBfoo\fR command, when passed a nonexistent filename, exits with a \fB1\fR status code and prints an error message\. . .IP "" 4 . .nf @test "invoking foo with a nonexistent file prints an error" { run foo nonexistent_filename [ "$status" \-eq 1 ] [ "$output" = "foo: no such file \'nonexistent_filename\'" ] } . .fi . .IP "" 0 . .P The \fB$status\fR variable contains the status code of the command, and the \fB$output\fR variable contains the combined contents of the command\'s standard output and standard error streams\. . .P A third special variable, the \fB$lines\fR array, is available for easily accessing individual lines of output\. For example, if you want to test that invoking \fBfoo\fR without any arguments prints usage information on the first line: . .IP "" 4 . .nf @test "invoking foo without arguments prints usage" { run foo [ "$status" \-eq 1 ] [ "${lines[0]}" = "usage: foo " ] } . .fi . .IP "" 0 . .SH "THE LOAD COMMAND" You may want to share common code across multiple test files\. Bats includes a convenient \fBload\fR command for sourcing a Bash source file relative to the location of the current test file\. For example, if you have a Bats test in \fBtest/foo\.bats\fR, the command . .IP "" 4 . .nf load test_helper . .fi . .IP "" 0 . .P will source the script \fBtest/test_helper\.bash\fR in your test file\. This can be useful for sharing functions to set up your environment or load fixtures\. . .SH "THE SKIP COMMAND" Tests can be skipped by using the \fBskip\fR command at the point in a test you wish to skip\. . .IP "" 4 . .nf @test "A test I don\'t want to execute for now" { skip run foo [ "$status" \-eq 0 ] } . .fi . .IP "" 0 . .P Optionally, you may include a reason for skipping: . .IP "" 4 . .nf @test "A test I don\'t want to execute for now" { skip "This command will return zero soon, but not now" run foo [ "$status" \-eq 0 ] } . .fi . .IP "" 0 . .P Or you can skip conditionally: . .IP "" 4 . .nf @test "A test which should run" { if [ foo != bar ]; then skip "foo isn\'t bar" fi run foo [ "$status" \-eq 0 ] } . .fi . .IP "" 0 . .SH "SETUP AND TEARDOWN FUNCTIONS" You can define special \fBsetup\fR and \fBteardown\fR functions which run before and after each test case, respectively\. Use these to load fixtures, set up your environment, and clean up when you\'re done\. . .SH "CODE OUTSIDE OF TEST CASES" You can include code in your test file outside of \fB@test\fR functions\. For example, this may be useful if you want to check for dependencies and fail immediately if they\'re not present\. However, any output that you print in code outside of \fB@test\fR, \fBsetup\fR or \fBteardown\fR functions must be redirected to \fBstderr\fR (\fB>&2\fR)\. Otherwise, the output may cause Bats to fail by polluting the TAP stream on \fBstdout\fR\. . .SH "SPECIAL VARIABLES" There are several global variables you can use to introspect on Bats tests: . .IP "\(bu" 4 \fB$BATS_TEST_FILENAME\fR is the fully expanded path to the Bats test file\. . .IP "\(bu" 4 \fB$BATS_TEST_DIRNAME\fR is the directory in which the Bats test file is located\. . .IP "\(bu" 4 \fB$BATS_TEST_NAMES\fR is an array of function names for each test case\. . .IP "\(bu" 4 \fB$BATS_TEST_NAME\fR is the name of the function containing the current test case\. . .IP "\(bu" 4 \fB$BATS_TEST_DESCRIPTION\fR is the description of the current test case\. . .IP "\(bu" 4 \fB$BATS_TEST_NUMBER\fR is the (1\-based) index of the current test case in the test file\. . .IP "\(bu" 4 \fB$BATS_TMPDIR\fR is the location to a directory that may be used to store temporary files\. . .IP "" 0 . .SH "SEE ALSO" \fBbash\fR(1), \fBbats\fR(1) bats-core-1.2.1/man/bats.7.ronn000066400000000000000000000106361370063022300161430ustar00rootroot00000000000000bats(7) -- Bats test file format ================================ DESCRIPTION ----------- A Bats test file is a Bash script with special syntax for defining test cases. Under the hood, each test case is just a function with a description. #!/usr/bin/env bats @test "addition using bc" { result="$(echo 2+2 | bc)" [ "$result" -eq 4 ] } @test "addition using dc" { result="$(echo 2 2+p | dc)" [ "$result" -eq 4 ] } Each Bats test file is evaluated n+1 times, where _n_ is the number of test cases in the file. The first run counts the number of test cases, then iterates over the test cases and executes each one in its own process. THE RUN HELPER -------------- Many Bats tests need to run a command and then make assertions about its exit status and output. Bats includes a `run` helper that invokes its arguments as a command, saves the exit status and output into special global variables, and then returns with a `0` status code so you can continue to make assertions in your test case. For example, let's say you're testing that the `foo` command, when passed a nonexistent filename, exits with a `1` status code and prints an error message. @test "invoking foo with a nonexistent file prints an error" { run foo nonexistent_filename [ "$status" -eq 1 ] [ "$output" = "foo: no such file 'nonexistent_filename'" ] } The `$status` variable contains the status code of the command, and the `$output` variable contains the combined contents of the command's standard output and standard error streams. A third special variable, the `$lines` array, is available for easily accessing individual lines of output. For example, if you want to test that invoking `foo` without any arguments prints usage information on the first line: @test "invoking foo without arguments prints usage" { run foo [ "$status" -eq 1 ] [ "${lines[0]}" = "usage: foo " ] } THE LOAD COMMAND ---------------- You may want to share common code across multiple test files. Bats includes a convenient `load` command for sourcing a Bash source file relative to the location of the current test file. For example, if you have a Bats test in `test/foo.bats`, the command load test_helper will source the script `test/test_helper.bash` in your test file. This can be useful for sharing functions to set up your environment or load fixtures. THE SKIP COMMAND ---------------- Tests can be skipped by using the `skip` command at the point in a test you wish to skip. @test "A test I don't want to execute for now" { skip run foo [ "$status" -eq 0 ] } Optionally, you may include a reason for skipping: @test "A test I don't want to execute for now" { skip "This command will return zero soon, but not now" run foo [ "$status" -eq 0 ] } Or you can skip conditionally: @test "A test which should run" { if [ foo != bar ]; then skip "foo isn't bar" fi run foo [ "$status" -eq 0 ] } SETUP AND TEARDOWN FUNCTIONS ---------------------------- You can define special `setup` and `teardown` functions which run before and after each test case, respectively. Use these to load fixtures, set up your environment, and clean up when you're done. CODE OUTSIDE OF TEST CASES -------------------------- You can include code in your test file outside of `@test` functions. For example, this may be useful if you want to check for dependencies and fail immediately if they're not present. However, any output that you print in code outside of `@test`, `setup` or `teardown` functions must be redirected to `stderr` (`>&2`). Otherwise, the output may cause Bats to fail by polluting the TAP stream on `stdout`. SPECIAL VARIABLES ----------------- There are several global variables you can use to introspect on Bats tests: * `$BATS_TEST_FILENAME` is the fully expanded path to the Bats test file. * `$BATS_TEST_DIRNAME` is the directory in which the Bats test file is located. * `$BATS_TEST_NAMES` is an array of function names for each test case. * `$BATS_TEST_NAME` is the name of the function containing the current test case. * `$BATS_TEST_DESCRIPTION` is the description of the current test case. * `$BATS_TEST_NUMBER` is the (1-based) index of the current test case in the test file. * `$BATS_TMPDIR` is the location to a directory that may be used to store temporary files. SEE ALSO -------- `bash`(1), `bats`(1) bats-core-1.2.1/package.json000066400000000000000000000012011370063022300156460ustar00rootroot00000000000000{ "name": "bats", "version": "1.2.1", "description": "Bash Automated Testing System", "homepage": "https://github.com/bats-core/bats-core#readme", "license": "MIT", "author": "Sam Stephenson (http://sstephenson.us/)", "repository": "github:bats-core/bats-core", "bugs": "https://github.com/bats-core/bats-core/issues", "files": [ "bin", "libexec", "man" ], "directories": { "bin": "bin", "doc": "docs", "man": "man", "test": "test" }, "scripts": { "test": "bin/bats test" }, "keywords": [ "bats", "bash", "shell", "test", "unit" ] } bats-core-1.2.1/shellcheck.sh000077500000000000000000000004251370063022300160330ustar00rootroot00000000000000#!/usr/bin/env bash set -e targets=() while IFS= read -r -d $'\0'; do targets+=("$REPLY") done < <( find \ bin/bats \ libexec/bats-core \ lib/bats-core \ shellcheck.sh \ -type f \ -print0 ) LC_ALL=C.UTF-8 shellcheck "${targets[@]}" exit $? bats-core-1.2.1/test/000077500000000000000000000000001370063022300143455ustar00rootroot00000000000000bats-core-1.2.1/test/bats.bats000077500000000000000000000475231370063022300161670ustar00rootroot00000000000000#!/usr/bin/env bats load test_helper fixtures bats @test "no arguments prints message and usage instructions" { run bats [ $status -eq 1 ] [ "${lines[0]}" == 'Error: Must specify at least one ' ] [ "${lines[1]%% *}" == 'Usage:' ] } @test "invalid option prints message and usage instructions" { run bats --invalid-option [ $status -eq 1 ] [ "${lines[0]}" == "Error: Bad command line option '--invalid-option'" ] [ "${lines[1]%% *}" == 'Usage:' ] } @test "-v and --version print version number" { run bats -v [ $status -eq 0 ] [ $(expr "$output" : "Bats [0-9][0-9.]*") -ne 0 ] } @test "-h and --help print help" { run bats -h [ $status -eq 0 ] [ "${#lines[@]}" -gt 3 ] } @test "invalid filename prints an error" { run bats nonexistent [ $status -eq 1 ] [ $(expr "$output" : ".*does not exist") -ne 0 ] } @test "empty test file runs zero tests" { run bats "$FIXTURE_ROOT/empty.bats" [ $status -eq 0 ] [ "$output" = "1..0" ] } @test "one passing test" { run bats "$FIXTURE_ROOT/passing.bats" [ $status -eq 0 ] [ "${lines[0]}" = "1..1" ] [ "${lines[1]}" = "ok 1 a passing test" ] } @test "summary passing tests" { run filter_control_sequences bats -p "$FIXTURE_ROOT/passing.bats" [ $status -eq 0 ] [ "${lines[1]}" = "1 test, 0 failures" ] } @test "summary passing and skipping tests" { run filter_control_sequences bats -p "$FIXTURE_ROOT/passing_and_skipping.bats" [ $status -eq 0 ] [ "${lines[3]}" = "3 tests, 0 failures, 2 skipped" ] } @test "tap passing and skipping tests" { run filter_control_sequences bats --formatter tap "$FIXTURE_ROOT/passing_and_skipping.bats" [ $status -eq 0 ] [ "${lines[0]}" = "1..3" ] [ "${lines[1]}" = "ok 1 a passing test" ] [ "${lines[2]}" = "ok 2 a skipped test with no reason # skip" ] [ "${lines[3]}" = "ok 3 a skipped test with a reason # skip for a really good reason" ] } @test "summary passing and failing tests" { run filter_control_sequences bats -p "$FIXTURE_ROOT/failing_and_passing.bats" [ $status -eq 0 ] [ "${lines[4]}" = "2 tests, 1 failure" ] } @test "summary passing, failing and skipping tests" { run filter_control_sequences bats -p "$FIXTURE_ROOT/passing_failing_and_skipping.bats" [ $status -eq 0 ] [ "${lines[5]}" = "3 tests, 1 failure, 1 skipped" ] } @test "tap passing, failing and skipping tests" { run filter_control_sequences bats --formatter tap "$FIXTURE_ROOT/passing_failing_and_skipping.bats" [ $status -eq 0 ] [ "${lines[0]}" = "1..3" ] [ "${lines[1]}" = "ok 1 a passing test" ] [ "${lines[2]}" = "ok 2 a skipping test # skip" ] [ "${lines[3]}" = "not ok 3 a failing test" ] } @test "BATS_CWD is correctly set to PWD as validated by bats_trim_filename" { local trimmed bats_trim_filename "$PWD/foo/bar" 'trimmed' printf 'ACTUAL: %s\n' "$trimmed" >&2 [ "$trimmed" = 'foo/bar' ] } @test "one failing test" { run bats "$FIXTURE_ROOT/failing.bats" [ $status -eq 1 ] [ "${lines[0]}" = '1..1' ] [ "${lines[1]}" = 'not ok 1 a failing test' ] [ "${lines[2]}" = "# (in test file $RELATIVE_FIXTURE_ROOT/failing.bats, line 4)" ] [ "${lines[3]}" = "# \`eval \"( exit \${STATUS:-1} )\"' failed" ] } @test "one failing and one passing test" { run bats "$FIXTURE_ROOT/failing_and_passing.bats" [ $status -eq 1 ] [ "${lines[0]}" = '1..2' ] [ "${lines[1]}" = 'not ok 1 a failing test' ] [ "${lines[2]}" = "# (in test file $RELATIVE_FIXTURE_ROOT/failing_and_passing.bats, line 2)" ] [ "${lines[3]}" = "# \`false' failed" ] [ "${lines[4]}" = 'ok 2 a passing test' ] } @test "failing test with significant status" { STATUS=2 run bats "$FIXTURE_ROOT/failing.bats" [ $status -eq 1 ] [ "${lines[3]}" = "# \`eval \"( exit \${STATUS:-1} )\"' failed with status 2" ] } @test "failing helper function logs the test case's line number" { run bats "$FIXTURE_ROOT/failing_helper.bats" [ $status -eq 1 ] [ "${lines[1]}" = 'not ok 1 failing helper function' ] [ "${lines[2]}" = "# (from function \`failing_helper' in file $RELATIVE_FIXTURE_ROOT/test_helper.bash, line 6," ] [ "${lines[3]}" = "# in test file $RELATIVE_FIXTURE_ROOT/failing_helper.bats, line 5)" ] [ "${lines[4]}" = "# \`failing_helper' failed" ] } @test "test environments are isolated" { run bats "$FIXTURE_ROOT/environment.bats" [ $status -eq 0 ] } @test "setup is run once before each test" { make_bats_test_suite_tmpdir run bats "$FIXTURE_ROOT/setup.bats" [ $status -eq 0 ] run cat "$BATS_TEST_SUITE_TMPDIR/setup.log" [ ${#lines[@]} -eq 3 ] } @test "teardown is run once after each test, even if it fails" { make_bats_test_suite_tmpdir run bats "$FIXTURE_ROOT/teardown.bats" [ $status -eq 1 ] run cat "$BATS_TEST_SUITE_TMPDIR/teardown.log" [ ${#lines[@]} -eq 3 ] } @test "setup failure" { run bats "$FIXTURE_ROOT/failing_setup.bats" [ $status -eq 1 ] [ "${lines[1]}" = 'not ok 1 truth' ] [ "${lines[2]}" = "# (from function \`setup' in test file $RELATIVE_FIXTURE_ROOT/failing_setup.bats, line 2)" ] [ "${lines[3]}" = "# \`false' failed" ] } @test "passing test with teardown failure" { PASS=1 run bats "$FIXTURE_ROOT/failing_teardown.bats" [ $status -eq 1 ] echo "$output" [ "${lines[1]}" = 'not ok 1 truth' ] [ "${lines[2]}" = "# (from function \`teardown' in test file $RELATIVE_FIXTURE_ROOT/failing_teardown.bats, line 2)" ] [ "${lines[3]}" = "# \`eval \"( exit \${STATUS:-1} )\"' failed" ] } @test "failing test with teardown failure" { PASS=0 run bats "$FIXTURE_ROOT/failing_teardown.bats" [ $status -eq 1 ] [ "${lines[1]}" = 'not ok 1 truth' ] [ "${lines[2]}" = "# (in test file $RELATIVE_FIXTURE_ROOT/failing_teardown.bats, line 6)" ] [ "${lines[3]}" = $'# `[ "$PASS" = 1 ]\' failed' ] } @test "teardown failure with significant status" { PASS=1 STATUS=2 run bats "$FIXTURE_ROOT/failing_teardown.bats" [ $status -eq 1 ] [ "${lines[3]}" = "# \`eval \"( exit \${STATUS:-1} )\"' failed with status 2" ] } @test "failing test file outside of BATS_CWD" { make_bats_test_suite_tmpdir cd "$BATS_TEST_SUITE_TMPDIR" run bats "$FIXTURE_ROOT/failing.bats" [ $status -eq 1 ] [ "${lines[2]}" = "# (in test file $FIXTURE_ROOT/failing.bats, line 4)" ] } @test "load sources scripts relative to the current test file" { run bats "$FIXTURE_ROOT/load.bats" [ $status -eq 0 ] } @test "load sources relative scripts with filename extension" { HELPER_NAME="test_helper.bash" run bats "$FIXTURE_ROOT/load.bats" [ $status -eq 0 ] } @test "load aborts if the specified script does not exist" { HELPER_NAME="nonexistent" run bats "$FIXTURE_ROOT/load.bats" [ $status -eq 1 ] } @test "load sources scripts by absolute path" { HELPER_NAME="${FIXTURE_ROOT}/test_helper.bash" run bats "$FIXTURE_ROOT/load.bats" [ $status -eq 0 ] } @test "load aborts if the script, specified by an absolute path, does not exist" { HELPER_NAME="${FIXTURE_ROOT}/nonexistent" run bats "$FIXTURE_ROOT/load.bats" [ $status -eq 1 ] } @test "load relative script with ambiguous name" { HELPER_NAME="ambiguous" run bats "$FIXTURE_ROOT/load.bats" [ $status -eq 0 ] } @test "load supports scripts on the PATH" { path_dir="$BATS_TMPNAME/path" mkdir -p "$path_dir" cp "${FIXTURE_ROOT}/test_helper.bash" "${path_dir}/on_path" PATH="${path_dir}:$PATH" HELPER_NAME="on_path" run bats "$FIXTURE_ROOT/load.bats" [ $status -eq 0 ] } @test "output is discarded for passing tests and printed for failing tests" { run bats "$FIXTURE_ROOT/output.bats" [ $status -eq 1 ] [ "${lines[6]}" = '# failure stdout 1' ] [ "${lines[7]}" = '# failure stdout 2' ] [ "${lines[11]}" = '# failure stderr' ] } @test "-c prints the number of tests" { run bats -c "$FIXTURE_ROOT/empty.bats" [ $status -eq 0 ] [ "$output" = 0 ] run bats -c "$FIXTURE_ROOT/output.bats" [ $status -eq 0 ] [ "$output" = 4 ] } @test "dash-e is not mangled on beginning of line" { run bats "$FIXTURE_ROOT/intact.bats" [ $status -eq 0 ] [ "${lines[1]}" = "ok 1 dash-e on beginning of line" ] } @test "dos line endings are stripped before testing" { run bats "$FIXTURE_ROOT/dos_line.bats" [ $status -eq 0 ] } @test "test file without trailing newline" { run bats "$FIXTURE_ROOT/without_trailing_newline.bats" [ $status -eq 0 ] [ "${lines[1]}" = "ok 1 truth" ] } @test "skipped tests" { run bats "$FIXTURE_ROOT/skipped.bats" [ $status -eq 0 ] [ "${lines[1]}" = "ok 1 a skipped test # skip" ] [ "${lines[2]}" = "ok 2 a skipped test with a reason # skip a reason" ] } @test "skipped test with parens (pretty formatter)" { run bats --pretty "$FIXTURE_ROOT/skipped_with_parens.bats" [ $status -eq 0 ] # Some systems (Alpine, for example) seem to emit an extra whitespace into # entries in the 'lines' array when a carriage return is present from the # pretty formatter. This is why a '+' is used after the 'skipped' note. [[ "${lines[@]}" =~ "- a skipped test with parentheses in the reason (skipped: "+"a reason (with parentheses))" ]] } @test "extended syntax" { emulate_bats_env run bats-exec-suite -x "$FIXTURE_ROOT/failing_and_passing.bats" echo "$output" [ $status -eq 1 ] [ "${lines[1]}" = 'suite failing_and_passing.bats' ] [ "${lines[2]}" = 'begin 1 a failing test' ] [ "${lines[3]}" = 'not ok 1 a failing test' ] [ "${lines[6]}" = 'begin 2 a passing test' ] [ "${lines[7]}" = 'ok 2 a passing test' ] } @test "timing syntax" { run bats -T "$FIXTURE_ROOT/failing_and_passing.bats" echo "$output" [ $status -eq 1 ] regex='not ok 1 a failing test in [0-1]sec' [[ "${lines[1]}" =~ $regex ]] regex='ok 2 a passing test in [0-1]sec' [[ "${lines[4]}" =~ $regex ]] } @test "extended timing syntax" { emulate_bats_env run bats-exec-suite -x -T "$FIXTURE_ROOT/failing_and_passing.bats" echo "$output" [ $status -eq 1 ] regex="not ok 1 a failing test in [0-1]sec" [ "${lines[2]}" = 'begin 1 a failing test' ] [[ "${lines[3]}" =~ $regex ]] [ "${lines[6]}" = 'begin 2 a passing test' ] regex="ok 2 a passing test in [0-1]sec" [[ "${lines[7]}" =~ $regex ]] } @test "pretty and tap formats" { run bats --formatter tap "$FIXTURE_ROOT/passing.bats" tap_output="$output" [ $status -eq 0 ] run bats --pretty "$FIXTURE_ROOT/passing.bats" pretty_output="$output" [ $status -eq 0 ] [ "$tap_output" != "$pretty_output" ] } @test "pretty formatter bails on invalid tap" { run bats-format-pretty < <(printf "This isn't TAP!\nGood day to you\n") [ $status -eq 0 ] [ "${lines[0]}" = "This isn't TAP!" ] [ "${lines[1]}" = "Good day to you" ] } @test "single-line tests" { run bats "$FIXTURE_ROOT/single_line.bats" [ $status -eq 1 ] [ "${lines[1]}" = 'ok 1 empty' ] [ "${lines[2]}" = 'ok 2 passing' ] [ "${lines[3]}" = 'ok 3 input redirection' ] [ "${lines[4]}" = 'not ok 4 failing' ] [ "${lines[5]}" = "# (in test file $RELATIVE_FIXTURE_ROOT/single_line.bats, line 9)" ] [ "${lines[6]}" = $'# `@test "failing" { false; }\' failed' ] } @test "testing IFS not modified by run" { run bats "$FIXTURE_ROOT/loop_keep_IFS.bats" [ $status -eq 0 ] [ "${lines[1]}" = "ok 1 loop_func" ] } @test "expand variables in test name" { SUITE='test/suite' run bats "$FIXTURE_ROOT/expand_var_in_test_name.bats" [ $status -eq 0 ] [ "${lines[1]}" = "ok 1 test/suite: test with variable in name" ] } @test "handle quoted and unquoted test names" { run bats "$FIXTURE_ROOT/quoted_and_unquoted_test_names.bats" [ $status -eq 0 ] [ "${lines[1]}" = "ok 1 single-quoted name" ] [ "${lines[2]}" = "ok 2 double-quoted name" ] [ "${lines[3]}" = "ok 3 unquoted name" ] } @test 'ensure compatibility with unofficial Bash strict mode' { local expected='ok 1 unofficial Bash strict mode conditions met' # Run Bats under `set -u` to catch as many unset variable accesses as # possible. run bash -u "${BATS_TEST_DIRNAME%/*}/bin/bats" \ "$FIXTURE_ROOT/unofficial_bash_strict_mode.bats" if [[ "$status" -ne 0 || "${lines[1]}" != "$expected" ]]; then cat <&2 printf 'actual: "%s"\n' "${lines[0]}" >&2 [ "${lines[0]}" = "$expected" ] printf 'num lines: %d\n' "${#lines[*]}" >&2 [ "${#lines[*]}" = "1" ] } @test "sourcing a nonexistent file in setup produces error output" { run bats "$FIXTURE_ROOT/source_nonexistent_file_in_setup.bats" [ $status -eq 1 ] [ "${lines[1]}" = 'not ok 1 sourcing nonexistent file fails in setup' ] [ "${lines[2]}" = "# (from function \`setup' in test file $RELATIVE_FIXTURE_ROOT/source_nonexistent_file_in_setup.bats, line 2)" ] [ "${lines[3]}" = "# \`source \"nonexistent file\"' failed" ] } @test "referencing unset parameter in setup produces error output" { run bats "$FIXTURE_ROOT/reference_unset_parameter_in_setup.bats" [ $status -eq 1 ] [ "${lines[1]}" = 'not ok 1 referencing unset parameter fails in setup' ] [ "${lines[2]}" = "# (from function \`setup' in test file $RELATIVE_FIXTURE_ROOT/reference_unset_parameter_in_setup.bats, line 3)" ] [ "${lines[3]}" = "# \`echo \"\$unset_parameter\"' failed" ] } @test "sourcing a nonexistent file in test produces error output" { run bats "$FIXTURE_ROOT/source_nonexistent_file.bats" [ $status -eq 1 ] [ "${lines[1]}" = 'not ok 1 sourcing nonexistent file fails' ] [ "${lines[2]}" = "# (in test file $RELATIVE_FIXTURE_ROOT/source_nonexistent_file.bats, line 2)" ] [ "${lines[3]}" = "# \`source \"nonexistent file\"' failed" ] } @test "referencing unset parameter in test produces error output" { run bats "$FIXTURE_ROOT/reference_unset_parameter.bats" [ $status -eq 1 ] [ "${lines[1]}" = 'not ok 1 referencing unset parameter fails' ] [ "${lines[2]}" = "# (in test file $RELATIVE_FIXTURE_ROOT/reference_unset_parameter.bats, line 3)" ] [ "${lines[3]}" = "# \`echo \"\$unset_parameter\"' failed" ] } @test "sourcing a nonexistent file in teardown produces error output" { run bats "$FIXTURE_ROOT/source_nonexistent_file_in_teardown.bats" [ $status -eq 1 ] [ "${lines[1]}" = 'not ok 1 sourcing nonexistent file fails in teardown' ] [ "${lines[2]}" = "# (from function \`teardown' in test file $RELATIVE_FIXTURE_ROOT/source_nonexistent_file_in_teardown.bats, line 2)" ] [ "${lines[3]}" = "# \`source \"nonexistent file\"' failed" ] } @test "referencing unset parameter in teardown produces error output" { run bats "$FIXTURE_ROOT/reference_unset_parameter_in_teardown.bats" [ $status -eq 1 ] [ "${lines[1]}" = 'not ok 1 referencing unset parameter fails in teardown' ] [ "${lines[2]}" = "# (from function \`teardown' in test file $RELATIVE_FIXTURE_ROOT/reference_unset_parameter_in_teardown.bats, line 3)" ] [ "${lines[3]}" = "# \`echo \"\$unset_parameter\"' failed" ] } @test "execute exported function without breaking failing test output" { exported_function() { return 0; } export -f exported_function run bats "$FIXTURE_ROOT/exported_function.bats" [ $status -eq 1 ] [ "${lines[0]}" = "1..1" ] [ "${lines[1]}" = "not ok 1 failing test" ] [ "${lines[2]}" = "# (in test file $RELATIVE_FIXTURE_ROOT/exported_function.bats, line 7)" ] [ "${lines[3]}" = "# \`false' failed" ] [ "${lines[4]}" = "# a='exported_function'" ] } @test "output printed even when no final newline" { run bats "$FIXTURE_ROOT/no-final-newline.bats" printf 'num lines: %d\n' "${#lines[@]}" >&2 printf 'LINE: %s\n' "${lines[@]}" >&2 [ "$status" -eq 1 ] [ "${#lines[@]}" -eq 7 ] [ "${lines[1]}" = 'not ok 1 no final newline' ] [ "${lines[2]}" = "# (in test file $RELATIVE_FIXTURE_ROOT/no-final-newline.bats, line 2)" ] [ "${lines[3]}" = "# \`printf 'foo\nbar\nbaz' >&2 && return 1' failed" ] [ "${lines[4]}" = '# foo' ] [ "${lines[5]}" = '# bar' ] [ "${lines[6]}" = '# baz' ] } @test "run tests which consume stdin (see #197)" { run bats "$FIXTURE_ROOT/read_from_stdin.bats" [ "$status" -eq 0 ] [[ "${lines[0]}" == "1..3" ]] [[ "${lines[1]}" == "ok 1 test 1" ]] [[ "${lines[2]}" == "ok 2 test 2 with TAB in name" ]] [[ "${lines[3]}" == "ok 3 test 3" ]] } @test "report correct line on unset variables" { run bats "$FIXTURE_ROOT/unbound_variable.bats" [ "$status" -eq 1 ] [ "${#lines[@]}" -eq 9 ] [ "${lines[1]}" = 'not ok 1 access unbound variable' ] [ "${lines[2]}" = "# (in test file $RELATIVE_FIXTURE_ROOT/unbound_variable.bats, line 8)" ] [ "${lines[3]}" = "# \`foo=\$unset_variable' failed" ] [[ "${lines[4]}" =~ ".src: line 8:" ]] [ "${lines[5]}" = 'not ok 2 access second unbound variable' ] [ "${lines[6]}" = "# (in test file $RELATIVE_FIXTURE_ROOT/unbound_variable.bats, line 13)" ] [ "${lines[7]}" = "# \`foo=\$second_unset_variable' failed" ] [[ "${lines[8]}" =~ ".src: line 13:" ]] } @test "report correct line on external function calls" { run bats "$FIXTURE_ROOT/external_function_calls.bats" [ "$status" -eq 1 ] expectedNumberOfTests=12 linesOfOutputPerTest=3 [ "${#lines[@]}" -gt $((expectedNumberOfTests * linesOfOutputPerTest + 1)) ] outputOffset=1 currentErrorLine=9 linesPerTest=5 for t in $(seq $expectedNumberOfTests); do [[ "${lines[$outputOffset]}" =~ "not ok $t " ]] # Skip backtrace into external function if set if [[ "${lines[$((outputOffset + 1))]}" =~ "# (from function " ]]; then outputOffset=$((outputOffset + 1)) parenChar=" " else parenChar="(" fi [ "${lines[$((outputOffset + 1))]}" = "# ${parenChar}in test file $RELATIVE_FIXTURE_ROOT/external_function_calls.bats, line $currentErrorLine)" ] [[ "${lines[$((outputOffset + 2))]}" =~ " failed" ]] outputOffset=$((outputOffset + 3)) currentErrorLine=$((currentErrorLine + linesPerTest)) done } @test "test count validator catches mismatch and returns non zero" { source "$BATS_ROOT/lib/bats-core/validator.bash" export -f bats_test_count_validator run bash -c "echo $'1..1\n' | bats_test_count_validator" [[ $status -ne 0 ]] run bash -c "echo $'1..1\nok 1\nok 2' | bats_test_count_validator" [[ $status -ne 0 ]] run bash -c "echo $'1..1\nok 1' | bats_test_count_validator" [[ $status -eq 0 ]] } bats-core-1.2.1/test/file_setup_teardown.bats000066400000000000000000000162741370063022300212740ustar00rootroot00000000000000load 'test_helper' fixtures file_setup_teardown setup_file() { export SETUP_FILE_EXPORT_TEST=true } @test "setup_file is run once per file" { make_bats_test_suite_tmpdir export LOG="$BATS_TEST_SUITE_TMPDIR/setup_file.log" bats "$FIXTURE_ROOT/setup_file.bats" } @test "teardown_file is run once per file" { make_bats_test_suite_tmpdir export LOG="$BATS_TEST_SUITE_TMPDIR/teardown_file.log" run bats "$FIXTURE_ROOT/teardown_file.bats" [[ $status -eq 0 ]] # output the log for faster debugging cat "$LOG" # expect to find an entry for the tested file grep 'teardown_file.bats' "$LOG" # it should be the only entry run wc -l < "$LOG" [[ $output -eq 1 ]] } @test "setup_file is called correctly in multi file suite" { make_bats_test_suite_tmpdir export LOG="$BATS_TEST_SUITE_TMPDIR/setup_file.log" run bats "$FIXTURE_ROOT/setup_file.bats" "$FIXTURE_ROOT/no_setup_file.bats" "$FIXTURE_ROOT/setup_file2.bats" [[ $status -eq 0 ]] run wc -l < "$LOG" # each setup_file[2].bats is in the log exactly once! [[ $output -eq 2 ]] grep setup_file.bats "$LOG" grep setup_file2.bats "$LOG" } @test "teardown_file is called correctly in multi file suite" { make_bats_test_suite_tmpdir export LOG="$BATS_TEST_SUITE_TMPDIR/teardown_file.log" run bats "$FIXTURE_ROOT/teardown_file.bats" "$FIXTURE_ROOT/no_teardown_file.bats" "$FIXTURE_ROOT/teardown_file2.bats" [[ $status -eq 0 ]] run wc -l < "$LOG" # each teardown_file[2].bats is in the log exactly once! [[ $output -eq 2 ]] grep teardown_file.bats "$LOG" grep teardown_file2.bats "$LOG" } @test "setup_file failure aborts tests for this file" { # this might need to mark them as skipped as the test count is already determined at this point run bats "$FIXTURE_ROOT/setup_file_failed.bats" echo "$output" [[ "${lines[0]}" == "1..2" ]] [[ "${lines[1]}" == "not ok 1 setup_file failed" ]] [[ "${lines[2]}" == "# (from function \`setup_file' in test file $RELATIVE_FIXTURE_ROOT/setup_file_failed.bats, line 2)" ]] [[ "${lines[3]}" == "# \`false' failed" ]] [[ "${lines[4]}" == "# bats warning: Executed 1 instead of expected 2 tests" ]] # this warning is expected # to appease the count validator, we would have to reduce the expected number of tests (retroactively?) or # output even those tests that should be skipped due to a failed setup_file. # Since we are already in a failure mode, the additional error does not hurt and is less verbose than # printing all the failed/skipped tests due to the setup failure. } @test "teardown_file failure fails at least one test from the file" { run bats "$FIXTURE_ROOT/teardown_file_failed.bats" [[ $status -ne 0 ]] echo "$output" [[ "${lines[0]}" == "1..1" ]] [[ "${lines[1]}" == "ok 1 test" ]] [[ "${lines[2]}" == "not ok 2 teardown_file failed" ]] [[ "${lines[3]}" == "# (from function \`teardown_file' in test file $RELATIVE_FIXTURE_ROOT/teardown_file_failed.bats, line 3)" ]] [[ "${lines[4]}" == "# \`false' failed" ]] [[ "${lines[5]}" == "# bats warning: Executed 2 instead of expected 1 tests" ]] # for now this warning is expected # for a failed teardown_file not to change the number of tests being reported, we would have to alter at least one provious test result report # this would require arbitrary amounts of buffering so we simply add our own line with a fake test number # tripping the count validator won't change the overall result, as we already are in a failure mode } @test "teardown_file runs even if any test in the file failed" { make_bats_test_suite_tmpdir export LOG="$BATS_TEST_SUITE_TMPDIR/teardown_file.log" run bats "$FIXTURE_ROOT/teardown_file_after_failing_test.bats" [[ $status -ne 0 ]] grep teardown_file_after_failing_test.bats "$LOG" echo "$output" [[ $output == "1..1 not ok 1 failing test # (in test file $RELATIVE_FIXTURE_ROOT/teardown_file_after_failing_test.bats, line 6) # \`false' failed" ]] } @test "teardown_file should run even after user abort via CTRL-C" { make_bats_test_suite_tmpdir export LOG="$BATS_TEST_SUITE_TMPDIR/teardown_file.log" STARTTIME=$SECONDS # guarantee that background processes get their own process group -> pid=pgid set -m # run testsubprocess in background to not avoid blocking this test bats "$FIXTURE_ROOT/teardown_file_after_long_test.bats"& SUBPROCESS_PID=$! # wait until we enter the test sleep 2 # fake sending SIGINT (CTRL-C) to the process group of the background subprocess kill -SIGINT -- -$SUBPROCESS_PID wait # for the test to finish either way (SIGINT or normal execution) # check that teardown_file ran and created the log file [[ -f "$LOG" ]] grep teardown_file_after_long_test.bats "$LOG" # but the test must not have run to the end! ! grep "test finished successfully" "$LOG" } @test "setup_file runs even if all tests in the file are skipped" { make_bats_test_suite_tmpdir export LOG="$BATS_TEST_SUITE_TMPDIR/setup_file.log" run bats "$FIXTURE_ROOT/setup_file_even_if_all_tests_are_skipped.bats" [[ -f "$LOG" ]] grep setup_file_even_if_all_tests_are_skipped.bats "$LOG" } @test "teardown_file runs even if all tests in the file are skipped" { make_bats_test_suite_tmpdir export LOG="$BATS_TEST_SUITE_TMPDIR/teardown_file.log" run bats "$FIXTURE_ROOT/teardown_file_even_if_all_tests_are_skipped.bats" [[ $status -eq 0 ]] [[ -f "$LOG" ]] grep teardown_file_even_if_all_tests_are_skipped.bats "$LOG" } @test "setup_file must not leak context between tests in the same suite" { # example: BATS_ROOT was unset in one test but used in others, therefore, the suite failed # Simulate leaking env var from first to second test by: export SETUP_FILE_VAR="LEAK!" run bats "$FIXTURE_ROOT/setup_file_does_not_leak_env.bats" "$FIXTURE_ROOT/setup_file_does_not_leak_env2.bats" [[ $status -eq 0 ]] || (echo $output; return 1) } @test "teardown_file must not leak context between tests in the same suite" { # example: BATS_ROOT was unset in one test but used in others, therefore, the suite failed run bats "$FIXTURE_ROOT/teardown_file_does_not_leak.bats" "$FIXTURE_ROOT/teardown_file_does_not_leak2.bats" echo "$output" [[ $status -eq 0 ]] [[ $output == "1..2 ok 1 test ok 2 must not see variable from first run" ]] } @test "halfway setup_file errors are caught and reported" { run bats "$FIXTURE_ROOT/setup_file_halfway_error.bats" [[ $status -ne 0 ]] echo "$output" [[ "$output" == "1..1 not ok 1 setup_file failed # (from function \`setup_file' in test file $RELATIVE_FIXTURE_ROOT/setup_file_halfway_error.bats, line 3) # \`false' failed" ]] } @test "halfway teardown_file errors are caught and reported" { run bats "$FIXTURE_ROOT/teardown_file_halfway_error.bats" echo "$output" [[ $status -ne 0 ]] [[ "${lines[0]}" == "1..1" ]] [[ "${lines[1]}" == "ok 1 empty" ]] [[ "${lines[2]}" == "not ok 2 teardown_file failed" ]] [[ "${lines[3]}" == "# (from function \`teardown_file' in test file $RELATIVE_FIXTURE_ROOT/teardown_file_halfway_error.bats, line 3)" ]] [[ "${lines[4]}" == "# \`false' failed" ]] [[ "${lines[5]}" == "# bats warning: Executed 2 instead of expected 1 tests" ]] # for now this warning is expected } @test "variables exported in setup_file are visible in tests" { [[ $SETUP_FILE_EXPORT_TEST == "true" ]] }bats-core-1.2.1/test/fixtures/000077500000000000000000000000001370063022300162165ustar00rootroot00000000000000bats-core-1.2.1/test/fixtures/bats/000077500000000000000000000000001370063022300171475ustar00rootroot00000000000000bats-core-1.2.1/test/fixtures/bats/ambiguous000066400000000000000000000002531370063022300210650ustar00rootroot00000000000000# Helper to detect regressions in load's lookup ordering. # An exact name match should be prioritized over name.bash. echo "Should not have loaded this file!" >&2 exit 1 bats-core-1.2.1/test/fixtures/bats/ambiguous.bash000066400000000000000000000002631370063022300220020ustar00rootroot00000000000000# Helper to detect regressions in load's lookup ordering. # An exact name match should be prioritized over name.bash. echo "This is the expected file to load." help_me() { :; } bats-core-1.2.1/test/fixtures/bats/cmd_using_stdin.bash000077500000000000000000000004471370063022300231670ustar00rootroot00000000000000#!/usr/bin/env bash # Fractional timeout supported in bash 4+ if [ "${BASH_VERSINFO[0]}" -lt 4 ]; then timeout=1 else timeout=0.01 fi # Just reading from stdin while read -r -t $timeout foo; do if [ "$foo" == "EXIT" ]; then echo "Found" exit 0 fi done echo "Not found" exit 1 bats-core-1.2.1/test/fixtures/bats/dos_line.bats000066400000000000000000000000431370063022300216130ustar00rootroot00000000000000@test "foo" { echo "foo" } bats-core-1.2.1/test/fixtures/bats/duplicate-tests.bats000066400000000000000000000003511370063022300231330ustar00rootroot00000000000000# This does not fail as expected @test "gizmo test" { false } @test "gizmo test" "this does fail, as expected" { false } # This overrides any previous test from the suite with the same description @test "gizmo test" { true } bats-core-1.2.1/test/fixtures/bats/empty.bats000066400000000000000000000000001370063022300211460ustar00rootroot00000000000000bats-core-1.2.1/test/fixtures/bats/environment.bats000066400000000000000000000002121370063022300223610ustar00rootroot00000000000000@test "setting a variable" { variable=1 [ $variable -eq 1 ] } @test "variables do not persist across tests" { [ -z "$variable" ] } bats-core-1.2.1/test/fixtures/bats/expand_var_in_test_name.bats000066400000000000000000000000661370063022300247000ustar00rootroot00000000000000@test "$SUITE: test with variable in name" { true } bats-core-1.2.1/test/fixtures/bats/exported_function.bats000066400000000000000000000001501370063022300235550ustar00rootroot00000000000000if exported_function; then a='exported_function' fi @test "failing test" { echo "a='$a'" false } bats-core-1.2.1/test/fixtures/bats/external_function_calls.bats000066400000000000000000000022421370063022300247270ustar00rootroot00000000000000load test_helper # Test various combinations that may fail line number detection in stack trace # Tests are designed so the first statement succeeds and 2nd fails # All tests fail on the same line so checking can be automated @test "Call true function && false" { help_me help_me && false } @test "Call true function && return 1" { help_me help_me && return 1 } @test "Call true function and invert" { help_me ! help_me } @test "Call false function || false" { ! failing_helper failing_helper || false } @test "Call false function && return 1" { ! failing_helper failing_helper || return 1 } @test "Call false function" { ! failing_helper failing_helper } @test "Call return_0 function && false" { return_0 return_0 && false } @test "Call return_0 function && return 1" { return_0 return_0 && return 1 } @test "Call return_0 function and invert" { return_0 ! return_0 } @test "Call return_1 function || false" { ! return_1 return_1 || false } @test "Call return_1 function && return 1" { ! return_1 return_1 || return 1 } @test "Call return_1 function" { ! return_1 return_1 } bats-core-1.2.1/test/fixtures/bats/failing.bats000066400000000000000000000001101370063022300214230ustar00rootroot00000000000000@test "a failing test" { true true eval "( exit ${STATUS:-1} )" } bats-core-1.2.1/test/fixtures/bats/failing_and_passing.bats000066400000000000000000000001061370063022300237760ustar00rootroot00000000000000@test "a failing test" { false } @test "a passing test" { true } bats-core-1.2.1/test/fixtures/bats/failing_helper.bats000066400000000000000000000001201370063022300227630ustar00rootroot00000000000000load "test_helper" @test "failing helper function" { true failing_helper } bats-core-1.2.1/test/fixtures/bats/failing_setup.bats000066400000000000000000000000561370063022300226540ustar00rootroot00000000000000setup() { false } @test "truth" { true } bats-core-1.2.1/test/fixtures/bats/failing_teardown.bats000066400000000000000000000001231370063022300233320ustar00rootroot00000000000000teardown() { eval "( exit ${STATUS:-1} )" } @test "truth" { [ "$PASS" = 1 ] } bats-core-1.2.1/test/fixtures/bats/intact.bats000066400000000000000000000001351370063022300213030ustar00rootroot00000000000000@test "dash-e on beginning of line" { run cat - <&2 && return 1 } bats-core-1.2.1/test/fixtures/bats/output.bats000066400000000000000000000005131370063022300213610ustar00rootroot00000000000000@test "success writing to stdout" { echo "success stdout 1" echo "success stdout 2" } @test "success writing to stderr" { echo "success stderr" >&2 } @test "failure writing to stdout" { echo "failure stdout 1" echo "failure stdout 2" false } @test "failure writing to stderr" { echo "failure stderr" >&2 false } bats-core-1.2.1/test/fixtures/bats/parallel.bats000066400000000000000000000005501370063022300216160ustar00rootroot00000000000000@test "slow test 1" { sleep 3s } @test "slow test 2" { sleep 3s } @test "slow test 3" { sleep 3s } @test "slow test 4" { sleep 3s } @test "slow test 5" { sleep 3s } @test "slow test 6" { sleep 3s } @test "slow test 7" { sleep 3s } @test "slow test 8" { sleep 3s } @test "slow test 9" { sleep 3s } @test "slow test 10" { sleep 3s } bats-core-1.2.1/test/fixtures/bats/passing.bats000066400000000000000000000000421370063022300214620ustar00rootroot00000000000000@test "a passing test" { true } bats-core-1.2.1/test/fixtures/bats/passing_and_failing.bats000066400000000000000000000001061370063022300237760ustar00rootroot00000000000000@test "a passing test" { true } @test "a failing test" { false } bats-core-1.2.1/test/fixtures/bats/passing_and_skipping.bats000066400000000000000000000002401370063022300242100ustar00rootroot00000000000000@test "a passing test" { true } @test "a skipped test with no reason" { skip } @test "a skipped test with a reason" { skip "for a really good reason" } bats-core-1.2.1/test/fixtures/bats/passing_failing_and_skipping.bats000066400000000000000000000001521370063022300257030ustar00rootroot00000000000000@test "a passing test" { true } @test "a skipping test" { skip } @test "a failing test" { false } bats-core-1.2.1/test/fixtures/bats/quoted_and_unquoted_test_names.bats000066400000000000000000000001551370063022300263140ustar00rootroot00000000000000@test 'single-quoted name' { true } @test "double-quoted name" { true } @test unquoted name { true } bats-core-1.2.1/test/fixtures/bats/read_from_stdin.bats000066400000000000000000000007651370063022300231710ustar00rootroot00000000000000#!/usr/bin/env bats @test "test 1" { # Don't print anything run bash -c "$BATS_TEST_DIRNAME/cmd_using_stdin.bash" [ "$status" -eq 1 ] [ "$output" = "Not found" ] } @test "test 2 with TAB in name" { run bash -c "echo EXIT | $BATS_TEST_DIRNAME/cmd_using_stdin.bash" [ "$status" -eq 0 ] echo "$output" [ "$output" = "Found" ] } @test "test 3" { run bash -c "echo EXIT | $BATS_TEST_DIRNAME/cmd_using_stdin.bash" [ "$status" -eq 0 ] [ "$output" = "Found" ] } bats-core-1.2.1/test/fixtures/bats/reference_unset_parameter.bats000066400000000000000000000001211370063022300252300ustar00rootroot00000000000000@test "referencing unset parameter fails" { set -u echo "$unset_parameter" } bats-core-1.2.1/test/fixtures/bats/reference_unset_parameter_in_setup.bats000066400000000000000000000002631370063022300271450ustar00rootroot00000000000000setup() { set -u echo "$unset_parameter" } teardown() { echo "should not capture the next line" [ 1 -eq 2 ] } @test "referencing unset parameter fails in setup" { : } bats-core-1.2.1/test/fixtures/bats/reference_unset_parameter_in_teardown.bats000066400000000000000000000001611370063022300276250ustar00rootroot00000000000000teardown() { set -u echo "$unset_parameter" } @test "referencing unset parameter fails in teardown" { : } bats-core-1.2.1/test/fixtures/bats/setup.bats000066400000000000000000000004121370063022300211570ustar00rootroot00000000000000LOG="$BATS_TEST_SUITE_TMPDIR/setup.log" setup() { echo "$BATS_TEST_NAME" >> "$LOG" } @test "one" { [ "$(tail -n 1 "$LOG")" = "test_one" ] } @test "two" { [ "$(tail -n 1 "$LOG")" = "test_two" ] } @test "three" { [ "$(tail -n 1 "$LOG")" = "test_three" ] } bats-core-1.2.1/test/fixtures/bats/single_line.bats000066400000000000000000000002201370063022300223040ustar00rootroot00000000000000@test "empty" { } @test "passing" { true; } @test "input redirection" { diff - <( echo hello ); } <> "$LOG" } @test "one" { true } @test "two" { false } @test "three" { true } bats-core-1.2.1/test/fixtures/bats/test_helper.bash000066400000000000000000000004131370063022300223220ustar00rootroot00000000000000help_me() { true } failing_helper() { false } return_0() { # Just return 0. Intentional assignment to boost line numbers result=0 return $result } return_1() { # Just return 0. Intentional assignment to boost line numbers result=1 return $result } bats-core-1.2.1/test/fixtures/bats/unbound_variable.bats000066400000000000000000000005131370063022300233400ustar00rootroot00000000000000set -u # This file is used to test line number offsets. Any changes to lines will affect tests @test "access unbound variable" { unset unset_variable # Add a line for checking line number foo=$unset_variable } @test "access second unbound variable" { unset second_unset_variable foo=$second_unset_variable } bats-core-1.2.1/test/fixtures/bats/unofficial_bash_strict_mode.bash000066400000000000000000000000621370063022300255140ustar00rootroot00000000000000#!/usr/bin/env bash set -euo pipefail IFS=$'\n\t' bats-core-1.2.1/test/fixtures/bats/unofficial_bash_strict_mode.bats000066400000000000000000000001341370063022300255300ustar00rootroot00000000000000load unofficial_bash_strict_mode @test "unofficial Bash strict mode conditions met" { : } bats-core-1.2.1/test/fixtures/bats/whitespace.bats000066400000000000000000000011211370063022300221510ustar00rootroot00000000000000@test "no extra whitespace" { : } @test "tab at beginning of line" { : } @test "tab before description" { : } @test "tab before opening brace" { : } @test "tabs at beginning of line and before description" { : } @test "tabs at beginning, before description, before brace" { : } @test "extra whitespace around single-line test" { :; } @test "no extra whitespace around single-line test" {:;} @test parse unquoted name between extra whitespace {:;} @test { {:;} # unquote single brace is a valid description @test ' {:;} # empty name from single quote bats-core-1.2.1/test/fixtures/bats/without_trailing_newline.bats000066400000000000000000000000301370063022300251300ustar00rootroot00000000000000@test "truth" { true }bats-core-1.2.1/test/fixtures/file_setup_teardown/000077500000000000000000000000001370063022300222605ustar00rootroot00000000000000bats-core-1.2.1/test/fixtures/file_setup_teardown/no_setup_file.bats000066400000000000000000000000311370063022300257600ustar00rootroot00000000000000@test "test" { true }bats-core-1.2.1/test/fixtures/file_setup_teardown/no_teardown_file.bats000066400000000000000000000000321370063022300264440ustar00rootroot00000000000000@test "first" { true }bats-core-1.2.1/test/fixtures/file_setup_teardown/setup_file.bats000066400000000000000000000004751370063022300253000ustar00rootroot00000000000000setup_file() { echo "$BATS_TEST_FILENAME" >> "$LOG" } @test "Setup_file" { [[ -f "$LOG" ]] run wc -l < "$LOG" echo $output [[ $output -eq 1 ]] } @test "Second setup_file test" { # still got only one setup! [[ -f "$LOG" ]] run wc -l < "$LOG" echo $output [[ $output -eq 1 ]] }bats-core-1.2.1/test/fixtures/file_setup_teardown/setup_file2.bats000066400000000000000000000001371370063022300253550ustar00rootroot00000000000000setup_file() { echo "$BATS_TEST_FILENAME" >> "$LOG" } @test "test" { [[ -f "$LOG" ]] }bats-core-1.2.1/test/fixtures/file_setup_teardown/setup_file_does_not_leak_env.bats000066400000000000000000000001331370063022300310250ustar00rootroot00000000000000setup_file() { export SETUP_FILE_VAR="$BATS_TEST_FILENAME" } @test "test" { true }bats-core-1.2.1/test/fixtures/file_setup_teardown/setup_file_does_not_leak_env2.bats000066400000000000000000000001051370063022300311060ustar00rootroot00000000000000@test "test" { [[ "${SETUP_FILE_VAR-"NOT_SET"}" == "NOT_SET" ]] }bats-core-1.2.1/test/fixtures/file_setup_teardown/setup_file_even_if_all_tests_are_skipped.bats000066400000000000000000000001751370063022300334100ustar00rootroot00000000000000setup_file() { echo "$BATS_TEST_FILENAME" >> "$LOG" } @test "test" { skip "We only want to see if setup file runs" }bats-core-1.2.1/test/fixtures/file_setup_teardown/setup_file_failed.bats000066400000000000000000000001241370063022300265730ustar00rootroot00000000000000setup_file() { false } @test "test 1" { true } @test "test 2" { true }bats-core-1.2.1/test/fixtures/file_setup_teardown/setup_file_halfway_error.bats000066400000000000000000000001071370063022300302140ustar00rootroot00000000000000setup_file() { true false true } @test "test" { true }bats-core-1.2.1/test/fixtures/file_setup_teardown/teardown_file.bats000066400000000000000000000001651370063022300257570ustar00rootroot00000000000000teardown_file() { echo "$BATS_TEST_FILENAME" >> "$LOG" } @test "first" { true } @test "second" { true }bats-core-1.2.1/test/fixtures/file_setup_teardown/teardown_file2.bats000066400000000000000000000001651370063022300260410ustar00rootroot00000000000000teardown_file() { echo "$BATS_TEST_FILENAME" >> "$LOG" } @test "first" { true } @test "second" { true }bats-core-1.2.1/test/fixtures/file_setup_teardown/teardown_file_after_failing_test.bats000066400000000000000000000001401370063022300316610ustar00rootroot00000000000000teardown_file() { echo "$BATS_TEST_FILENAME" >> "$LOG" } @test "failing test" { false }bats-core-1.2.1/test/fixtures/file_setup_teardown/teardown_file_after_long_test.bats000066400000000000000000000002301370063022300312070ustar00rootroot00000000000000teardown_file() { echo "$BATS_TEST_FILENAME" >> "$LOG" } @test "long running test" { sleep 10 echo "test finished successfully" >> "$LOG" }bats-core-1.2.1/test/fixtures/file_setup_teardown/teardown_file_does_not_leak.bats000066400000000000000000000001541370063022300306430ustar00rootroot00000000000000teardown_file() { export POTENTIALLY_LEAKING_VARIABLE="$BATS_TEST_FILENAME" } @test "test" { true }bats-core-1.2.1/test/fixtures/file_setup_teardown/teardown_file_does_not_leak2.bats000066400000000000000000000001351370063022300307240ustar00rootroot00000000000000@test "must not see variable from first run" { [[ -z "$POTENTIALLY_LEAKING_VARIABLE" ]] }bats-core-1.2.1/test/fixtures/file_setup_teardown/teardown_file_even_if_all_tests_are_skipped.bats000066400000000000000000000002401370063022300340640ustar00rootroot00000000000000teardown_file() { echo "$BATS_TEST_FILENAME" >> "$LOG" } @test "skipped test" { skip 'All tests in this file are skipped! Teardown_file runs anyways' }bats-core-1.2.1/test/fixtures/file_setup_teardown/teardown_file_failed.bats000066400000000000000000000000711370063022300272570ustar00rootroot00000000000000 teardown_file() { false } @test "test" { true }bats-core-1.2.1/test/fixtures/file_setup_teardown/teardown_file_halfway_error.bats000066400000000000000000000001131370063022300306740ustar00rootroot00000000000000teardown_file() { true false true } @test "empty" { true }bats-core-1.2.1/test/fixtures/parallel/000077500000000000000000000000001370063022300200125ustar00rootroot00000000000000bats-core-1.2.1/test/fixtures/parallel/parallel-preserve-environment.bats000066400000000000000000000002771370063022300266620ustar00rootroot00000000000000setup_file() { export OTHER_ENV_VARIABLE='my-value' } @test "check env variables are set" { [[ "$TEST_ENV_VARIABLE" == "test-value" ]] [[ "$OTHER_ENV_VARIABLE" == "my-value" ]] }bats-core-1.2.1/test/fixtures/parallel/parallel.bats000066400000000000000000000005501370063022300224610ustar00rootroot00000000000000@test "slow test 1" { sleep 3s } @test "slow test 2" { sleep 3s } @test "slow test 3" { sleep 3s } @test "slow test 4" { sleep 3s } @test "slow test 5" { sleep 3s } @test "slow test 6" { sleep 3s } @test "slow test 7" { sleep 3s } @test "slow test 8" { sleep 3s } @test "slow test 9" { sleep 3s } @test "slow test 10" { sleep 3s } bats-core-1.2.1/test/fixtures/parallel/setup_file/000077500000000000000000000000001370063022300221515ustar00rootroot00000000000000bats-core-1.2.1/test/fixtures/parallel/setup_file/setup_file.bats000066400000000000000000000000721370063022300251620ustar00rootroot00000000000000setup_file() { sleep 3 } @test "nothing" { true }bats-core-1.2.1/test/fixtures/parallel/setup_file/setup_file1.bats000077700000000000000000000000001370063022300304062./setup_file.batsustar00rootroot00000000000000bats-core-1.2.1/test/fixtures/parallel/setup_file/setup_file2.bats000077700000000000000000000000001370063022300304072./setup_file.batsustar00rootroot00000000000000bats-core-1.2.1/test/fixtures/parallel/setup_file/setup_file3.bats000077700000000000000000000000001370063022300304102./setup_file.batsustar00rootroot00000000000000bats-core-1.2.1/test/fixtures/parallel/suite/000077500000000000000000000000001370063022300211435ustar00rootroot00000000000000bats-core-1.2.1/test/fixtures/parallel/suite/parallel1.bats000077700000000000000000000000001370063022300265502../parallel.batsustar00rootroot00000000000000bats-core-1.2.1/test/fixtures/parallel/suite/parallel2.bats000077700000000000000000000000001370063022300265512../parallel.batsustar00rootroot00000000000000bats-core-1.2.1/test/fixtures/parallel/suite/parallel3.bats000077700000000000000000000000001370063022300265522../parallel.batsustar00rootroot00000000000000bats-core-1.2.1/test/fixtures/parallel/suite/parallel4.bats000077700000000000000000000000001370063022300265532../parallel.batsustar00rootroot00000000000000bats-core-1.2.1/test/fixtures/suite/000077500000000000000000000000001370063022300173475ustar00rootroot00000000000000bats-core-1.2.1/test/fixtures/suite/empty/000077500000000000000000000000001370063022300205055ustar00rootroot00000000000000bats-core-1.2.1/test/fixtures/suite/empty/.gitkeep000066400000000000000000000000001370063022300221240ustar00rootroot00000000000000bats-core-1.2.1/test/fixtures/suite/filter/000077500000000000000000000000001370063022300206345ustar00rootroot00000000000000bats-core-1.2.1/test/fixtures/suite/filter/a.bats000066400000000000000000000001011370063022300217170ustar00rootroot00000000000000@test 'foo in a' { } @test '--bar in a' { } @test 'baz in a' { } bats-core-1.2.1/test/fixtures/suite/filter/b.bats000066400000000000000000000001021370063022300217210ustar00rootroot00000000000000@test 'bar_in_b' { } @test '--baz_in_b' { } @test 'quux_in_b' { } bats-core-1.2.1/test/fixtures/suite/filter/c.bats000066400000000000000000000001041370063022300217240ustar00rootroot00000000000000@test 'quux_in c' { } @test 'xyzzy in c' { } @test 'plugh_in c' { } bats-core-1.2.1/test/fixtures/suite/multiple/000077500000000000000000000000001370063022300212025ustar00rootroot00000000000000bats-core-1.2.1/test/fixtures/suite/multiple/a.bats000066400000000000000000000000311370063022300222670ustar00rootroot00000000000000@test "truth" { true } bats-core-1.2.1/test/fixtures/suite/multiple/b.bats000066400000000000000000000001111370063022300222670ustar00rootroot00000000000000@test "more truth" { true } @test "quasi-truth" { [ -z "$FLUNK" ] } bats-core-1.2.1/test/fixtures/suite/recursive/000077500000000000000000000000001370063022300213565ustar00rootroot00000000000000bats-core-1.2.1/test/fixtures/suite/recursive/subsuite/000077500000000000000000000000001370063022300232215ustar00rootroot00000000000000bats-core-1.2.1/test/fixtures/suite/recursive/subsuite/test2.bats000066400000000000000000000000501370063022300251300ustar00rootroot00000000000000@test "another passing test" { true } bats-core-1.2.1/test/fixtures/suite/recursive/test.bats000066400000000000000000000000421370063022300232040ustar00rootroot00000000000000@test "a passing test" { true } bats-core-1.2.1/test/fixtures/suite/single/000077500000000000000000000000001370063022300206305ustar00rootroot00000000000000bats-core-1.2.1/test/fixtures/suite/single/test.bats000066400000000000000000000000421370063022300224560ustar00rootroot00000000000000@test "a passing test" { true } bats-core-1.2.1/test/fixtures/suite/skip/000077500000000000000000000000001370063022300203155ustar00rootroot00000000000000bats-core-1.2.1/test/fixtures/suite/skip/skip-in-setup-and-teardown.bats000066400000000000000000000004771370063022300262710ustar00rootroot00000000000000#!/usr/bin/env bats setup () { skip "This is not working (https://github.com/kata-containers/runtime/issues/175)" } @test "skip in setup and teardown" { true } @test "skip in setup, test and teardown" { skip } teardown() { skip "This is not working (https://github.com/clearcontainers/runtime/issues/1042)" } bats-core-1.2.1/test/fixtures/suite/skip/skip-in-setup.bats000066400000000000000000000003021370063022300236730ustar00rootroot00000000000000#!/usr/bin/env bats setup() { skip "This is not working (https://github.com/kata-containers/runtime/issues/175)" } @test "skip in setup" { true } @test "skip in setup and test" { skip }bats-core-1.2.1/test/fixtures/suite/skip/skip-in-teardown.bats000066400000000000000000000002361370063022300243640ustar00rootroot00000000000000#!/usr/bin/env bats @test "skip in teardown" { true } teardown() { skip "This is not working (https://github.com/clearcontainers/runtime/issues/1042)" } bats-core-1.2.1/test/fixtures/suite/skip/skip-in-test-and-teardown.bats000066400000000000000000000003651370063022300261040ustar00rootroot00000000000000#!/usr/bin/env bats teardown() { skip "This is not working (https://github.com/clearcontainers/runtime/issues/1042)" } @test "skip in test and teardown" { skip "This is not working (https://github.com/clearcontainers/runtime/issues/1042)" } bats-core-1.2.1/test/fixtures/suite/skip/skip-in-test.bats000066400000000000000000000002031370063022300235120ustar00rootroot00000000000000#!/usr/bin/env bats @test "skip in test" { skip "This is not working (https://github.com/clearcontainers/runtime/issues/1042)" } bats-core-1.2.1/test/install.bats000066400000000000000000000041041370063022300166650ustar00rootroot00000000000000#!/usr/bin/env bats load test_helper INSTALL_DIR= PATH_TO_INSTALL_SHELL= setup() { make_bats_test_suite_tmpdir INSTALL_DIR="$BATS_TEST_SUITE_TMPDIR/bats-core" PATH_TO_INSTALL_SHELL="${BATS_TEST_DIRNAME%/*}/install.sh" } @test "install.sh creates a valid installation" { run "$PATH_TO_INSTALL_SHELL" "$INSTALL_DIR" [ "$status" -eq 0 ] [ "$output" == "Installed Bats to $INSTALL_DIR/bin/bats" ] [ -x "$INSTALL_DIR/bin/bats" ] [ -x "$INSTALL_DIR/libexec/bats-core/bats" ] [ -x "$INSTALL_DIR/libexec/bats-core/bats-exec-suite" ] [ -x "$INSTALL_DIR/libexec/bats-core/bats-exec-test" ] [ -x "$INSTALL_DIR/libexec/bats-core/bats-format-junit" ] [ -x "$INSTALL_DIR/libexec/bats-core/bats-format-pretty" ] [ -x "$INSTALL_DIR/libexec/bats-core/bats-preprocess" ] [ -f "$INSTALL_DIR/share/man/man1/bats.1" ] [ -f "$INSTALL_DIR/share/man/man7/bats.7" ] run "$INSTALL_DIR/bin/bats" -v [ "$status" -eq 0 ] [ "${output%% *}" == 'Bats' ] } @test "install.sh only updates permissions for Bats files" { mkdir -p "$INSTALL_DIR"/{bin,libexec/bats-core} local dummy_bin="$INSTALL_DIR/bin/dummy" printf 'dummy' >"$dummy_bin" local dummy_libexec="$INSTALL_DIR/libexec/bats-core/dummy" printf 'dummy' >"$dummy_libexec" run "$PATH_TO_INSTALL_SHELL" "$INSTALL_DIR" [ "$status" -eq 0 ] [ -f "$dummy_bin" ] [ ! -x "$dummy_bin" ] [ -f "$dummy_libexec" ] [ ! -x "$dummy_libexec" ] } @test "bin/bats is resilient to symbolic links" { run "$PATH_TO_INSTALL_SHELL" "$INSTALL_DIR" [ "$status" -eq 0 ] # Simulate a symlink to bin/bats (without using a symlink, for Windows sake) # by creating a wrapper script that executes bin/bats via a relative path. # # root.bats contains tests that use real symlinks on platforms that support # them, as does the .travis.yml script that exercises the Dockerfile. local bats_symlink="$INSTALL_DIR/bin/bats-link" printf '%s\n' '#! /usr/bin/env bash' \ "cd '$INSTALL_DIR/bin'" \ './bats "$@"' >"$bats_symlink" chmod 700 "$bats_symlink" run "$bats_symlink" -v [ "$status" -eq 0 ] [ "${output%% *}" == 'Bats' ] } bats-core-1.2.1/test/junit-formatter.bats000066400000000000000000000011071370063022300203510ustar00rootroot00000000000000#!/usr/bin/env bats TEST_REPORT_FILE="TestReport-skipped.bats.xml" teardown() { rm "${TEST_REPORT_FILE}" } @test "junit formatter with skipped test does not fail" { bats --formatter junit "$BATS_ROOT/test/fixtures/bats/skipped.bats" run grep -A 1 'name="a skipped test"' "${TEST_REPORT_FILE}" echo "Skipped test without reason: '${lines[1]}'" [[ ${lines[1]} == *""* ]] run grep -A 1 'name="a skipped test with a reason"' "${TEST_REPORT_FILE}" echo "Skipped test with reason: ${lines[1]}" [[ ${lines[1]} == *"a reason"* ]] } bats-core-1.2.1/test/parallell.bats000066400000000000000000000044231370063022300171730ustar00rootroot00000000000000#!/usr/bin/env bats load test_helper fixtures parallel setup() { type -p parallel &>/dev/null || skip "--jobs requires GNU parallel" } @test "parallel test execution with --jobs" { SECONDS=0 run bats --jobs 10 "$FIXTURE_ROOT/parallel.bats" duration="$SECONDS" [ "$status" -eq 0 ] # Make sure the lines are in-order. [[ "${lines[0]}" == "1..10" ]] for t in {1..10}; do [[ "${lines[$t]}" == "ok $t slow test $t" ]] done # In theory it should take 3s, but let's give it bit of extra time instead. [[ "$duration" -lt 20 ]] } @test "parallel can preserve environment variables" { if [[ ! -e ~/.parallel/ignored_vars ]]; then parallel --record-env PARALLEL_WAS_SETUP=1 fi export TEST_ENV_VARIABLE='test-value' run bats --jobs 1 --parallel-preserve-environment "$FIXTURE_ROOT/parallel-preserve-environment.bats" if [[ $PARALLEL_WAS_SETUP ]]; then rm ~/.parallel/ignored_vars fi echo "$output" [[ "$status" -eq 0 ]] } @test "parallel suite execution with --jobs" { SECONDS=0 run bash -c "bats --jobs 40 \"${FIXTURE_ROOT}/suite/\" 2> >(grep -v '^parallel: Warning: ')" duration="$SECONDS" echo "$output" echo "Duration: $duration" [ "$status" -eq 0 ] # Make sure the lines are in-order. [[ "${lines[0]}" == "1..40" ]] i=0 for s in {1..4}; do for t in {1..10}; do ((++i)) [[ "${lines[$i]}" == "ok $i slow test $t" ]] done done # In theory it should take 3s, but let's give it bit of extra time for load tolerance. # (Since there is no limit to load, we cannot totally avoid erroneous failures by limited tolerance.) # Also check that parallelization happens across all files instead of # linearizing between files, which requires at least 12s [[ "$duration" -lt 12 ]] || (echo "If this fails on Travis, make sure the failure is repeatable and not due to heavy load."; false) } @test "setup_file is not over parallelized" { SECONDS=0 # run 4 files with 3s sleeps in setup_file with parallelity of 2 -> serialize 2 run bats --jobs 2 "$FIXTURE_ROOT/setup_file" duration="$SECONDS" echo "Took $duration seconds" [ "$status" -eq 0 ] # the serialization should lead to at least 6s runtime [[ $duration -ge 6 ]] # parallelization should at least get rid of 1/4th the total runtime [[ $duration -lt 9 ]] } bats-core-1.2.1/test/root.bats000066400000000000000000000055031370063022300162060ustar00rootroot00000000000000#!/usr/bin/env bats # # This suite is dedicated to calculating BATS_ROOT when going through various # permutations of symlinks. It was inspired by the report in issue #113 that the # calculation was broken on CentOS, where /bin is symlinked to /usr/bin. # # The basic test environment is (all paths relative to BATS_TEST_SUITE_TMPDIR): # # - /bin is a relative symlink to /usr/bin, exercising the symlink resolution of # the `bats` parent directory (i.e. "${0%/*}") # - /usr/bin/bats is an absolute symlink to /opt/bats-core/bin/bats, exercising # the symlink resolution of the `bats` executable itself (i.e. "${0##*/}") load test_helper # This would make a good candidate for a one-time setup/teardown per #39. setup() { make_bats_test_suite_tmpdir cd "$BATS_TEST_SUITE_TMPDIR" mkdir -p {usr/bin,opt/bats-core} "$BATS_ROOT/install.sh" "opt/bats-core" ln -s "usr/bin" "bin" if [[ ! -L "bin" ]]; then cd - >/dev/null skip "symbolic links aren't functional on OSTYPE=$OSTYPE" fi ln -s "$BATS_TEST_SUITE_TMPDIR/opt/bats-core/bin/bats" \ "$BATS_TEST_SUITE_TMPDIR/usr/bin/bats" cd - >/dev/null } @test "#113: set BATS_ROOT when /bin is a symlink to /usr/bin" { run "$BATS_TEST_SUITE_TMPDIR/bin/bats" -v [ "$status" -eq 0 ] [ "${output%% *}" == 'Bats' ] } # The resolution scheme here is: # # Set in setup # - /bin => /usr/bin (relative directory) @test "set BATS_ROOT with extreme symlink resolution" { cd "$BATS_TEST_SUITE_TMPDIR" mkdir -p "opt/bats/bin2" # - /usr/bin/foo => /usr/bin/bar (relative executable) ln -s bar usr/bin/foo # - /usr/bin/bar => /opt/bats/bin0/bar (absolute executable) ln -s "$BATS_TEST_SUITE_TMPDIR/opt/bats/bin0/bar" usr/bin/bar # - /opt/bats/bin0 => /opt/bats/bin1 (relative directory) ln -s bin1 opt/bats/bin0 # - /opt/bats/bin1 => /opt/bats/bin2 (absolute directory) ln -s "$BATS_TEST_SUITE_TMPDIR/opt/bats/bin2" opt/bats/bin1 # - /opt/bats/bin2/bar => /opt/bats-core/bin/bar (absolute executable) ln -s "$BATS_TEST_SUITE_TMPDIR/opt/bats-core/bin/bar" opt/bats/bin2/bar # - /opt/bats-core/bin/bar => /opt/bats-core/bin/baz (relative executable) ln -s baz opt/bats-core/bin/bar # - /opt/bats-core/bin/baz => /opt/bats-core/bin/bats (relative executable) ln -s bats opt/bats-core/bin/baz cd - >/dev/null run "$BATS_TEST_SUITE_TMPDIR/bin/foo" -v [ "$status" -eq 0 ] [ "${output%% *}" == 'Bats' ] } @test "set BATS_ROOT when calling from same dir" { cd "$BATS_TEST_SUITE_TMPDIR" run ./bin/bats -v [ "$status" -eq 0 ] [ "${output%% *}" == 'Bats' ] } @test "set BATS_ROOT from PATH" { cd /tmp PATH="$PATH:$BATS_TEST_SUITE_TMPDIR/bin" run bats -v [ "$status" -eq 0 ] [ "${output%% *}" == 'Bats' ] } @test "#182 and probably #184 as well" { cd /tmp PATH="$PATH:$BATS_TEST_SUITE_TMPDIR/bin" run bash bats -v [ "$status" -eq 0 ] [ "${output%% *}" == 'Bats' ] } bats-core-1.2.1/test/suite.bats000077500000000000000000000114611370063022300163570ustar00rootroot00000000000000#!/usr/bin/env bats load test_helper fixtures suite @test "running a suite with no test files" { run bats "$FIXTURE_ROOT/empty" [ $status -eq 0 ] [ "$output" = "1..0" ] } @test "running a suite with one test file" { run bats "$FIXTURE_ROOT/single" [ $status -eq 0 ] [ "${lines[0]}" = "1..1" ] [ "${lines[1]}" = "ok 1 a passing test" ] } @test "counting tests in a suite" { run bats -c "$FIXTURE_ROOT/single" [ $status -eq 0 ] [ "$output" -eq 1 ] run bats -c "$FIXTURE_ROOT/multiple" [ $status -eq 0 ] [ "$output" -eq 3 ] } @test "aggregated output of multiple tests in a suite" { run bats "$FIXTURE_ROOT/multiple" [ $status -eq 0 ] [ "${lines[0]}" = "1..3" ] echo "$output" | grep "^ok . truth" echo "$output" | grep "^ok . more truth" echo "$output" | grep "^ok . quasi-truth" } @test "a failing test in a suite results in an error exit code" { FLUNK=1 run bats "$FIXTURE_ROOT/multiple" [ $status -eq 1 ] [ "${lines[0]}" = "1..3" ] echo "$output" | grep "^not ok . quasi-truth" } @test "running an ad-hoc suite by specifying multiple test files" { run bats "$FIXTURE_ROOT/multiple/a.bats" "$FIXTURE_ROOT/multiple/b.bats" [ $status -eq 0 ] [ "${lines[0]}" = "1..3" ] echo "$output" | grep "^ok . truth" echo "$output" | grep "^ok . more truth" echo "$output" | grep "^ok . quasi-truth" } @test "extended syntax in suite" { emulate_bats_env FLUNK=1 run bats-exec-suite -x "$FIXTURE_ROOT/multiple/"*.bats echo "output: $output" [ $status -eq 1 ] [ "${lines[0]}" = "1..3" ] [ "${lines[1]}" = "suite a.bats" ] [ "${lines[2]}" = "begin 1 truth" ] [ "${lines[3]}" = "ok 1 truth" ] [ "${lines[4]}" = "suite b.bats" ] [ "${lines[5]}" = "begin 2 more truth" ] [ "${lines[6]}" = "ok 2 more truth" ] [ "${lines[7]}" = "begin 3 quasi-truth" ] [ "${lines[8]}" = "not ok 3 quasi-truth" ] } @test "timing syntax in suite" { emulate_bats_env FLUNK=1 run bats-exec-suite -T "$FIXTURE_ROOT/multiple/"*.bats echo "$output" [ $status -eq 1 ] [ "${lines[0]}" = "1..3" ] regex="ok 1 truth in [0-1]sec" [[ "${lines[1]}" =~ $regex ]] regex="ok 2 more truth in [0-1]sec" [[ "${lines[2]}" =~ $regex ]] regex="not ok 3 quasi-truth in [0-1]sec" [[ "${lines[3]}" =~ $regex ]] } @test "extended timing syntax in suite" { emulate_bats_env FLUNK=1 run bats-exec-suite -x -T "$FIXTURE_ROOT/multiple/"*.bats echo "$output" [ $status -eq 1 ] [ "${lines[0]}" = "1..3" ] [ "${lines[1]}" = "suite a.bats" ] [ "${lines[2]}" = "begin 1 truth" ] regex="ok 1 truth in [0-1]sec" [[ "${lines[3]}" =~ $regex ]] [ "${lines[4]}" = "suite b.bats" ] [ "${lines[5]}" = "begin 2 more truth" ] regex="ok 2 more truth in [0-1]sec" [[ "${lines[6]}" =~ $regex ]] [ "${lines[7]}" = "begin 3 quasi-truth" ] regex="not ok 3 quasi-truth in [0-1]sec" [[ "${lines[8]}" =~ $regex ]] } @test "recursive support (short option)" { run bats -r "${FIXTURE_ROOT}/recursive" [ $status -eq 0 ] [ "${lines[0]}" = "1..2" ] [ "${lines[1]}" = "ok 1 another passing test" ] [ "${lines[2]}" = "ok 2 a passing test" ] } @test "recursive support (long option)" { run bats --recursive "${FIXTURE_ROOT}/recursive" [ $status -eq 0 ] [ "${lines[0]}" = "1..2" ] [ "${lines[1]}" = "ok 1 another passing test" ] [ "${lines[2]}" = "ok 2 a passing test" ] } @test "run entire suite when --filter isn't set" { run bats "${FIXTURE_ROOT}/filter" [ "$status" -eq 0 ] [ "${lines[0]}" = '1..9' ] [ "${lines[1]}" = 'ok 1 foo in a' ] [ "${lines[2]}" = 'ok 2 --bar in a' ] [ "${lines[3]}" = 'ok 3 baz in a' ] [ "${lines[4]}" = 'ok 4 bar_in_b' ] [ "${lines[5]}" = 'ok 5 --baz_in_b' ] [ "${lines[6]}" = 'ok 6 quux_in_b' ] [ "${lines[7]}" = 'ok 7 quux_in c' ] [ "${lines[8]}" = 'ok 8 xyzzy in c' ] [ "${lines[9]}" = 'ok 9 plugh_in c' ] } @test "use --filter to run subset of test cases from across the suite" { run bats -f 'ba[rz]' "${FIXTURE_ROOT}/filter" [ "$status" -eq 0 ] [ "${lines[0]}" = '1..4' ] [ "${lines[1]}" = 'ok 1 --bar in a' ] [ "${lines[2]}" = 'ok 2 baz in a' ] [ "${lines[3]}" = 'ok 3 bar_in_b' ] [ "${lines[4]}" = 'ok 4 --baz_in_b' ] local prev_output="$output" run bats --filter 'ba[rz]' "${FIXTURE_ROOT}/filter" [ "$status" -eq 0 ] [ "$output" = "$prev_output" ] } @test "--filter can handle regular expressions that contain [_- ]" { run bats -f '--ba[rz][ _]in' "${FIXTURE_ROOT}/filter" [ "$status" -eq 0 ] [ "${lines[0]}" = '1..2' ] [ "${lines[1]}" = 'ok 1 --bar in a' ] [ "${lines[2]}" = 'ok 2 --baz_in_b' ] } @test "--filter can handle regular expressions that start with ^" { run bats -f '^ba[rz]' "${FIXTURE_ROOT}/filter" [ "$status" -eq 0 ] [ "${lines[0]}" = '1..2' ] [ "${lines[1]}" = 'ok 1 baz in a' ] [ "${lines[2]}" = 'ok 2 bar_in_b' ] } @test "skip is handled correctly in setup, test, and teardown" { bats "${FIXTURE_ROOT}/skip" } bats-core-1.2.1/test/test_helper.bash000066400000000000000000000020121370063022300175150ustar00rootroot00000000000000emulate_bats_env() { export BATS_CWD="$PWD" export BATS_TEST_PATTERN="^[[:blank:]]*@test[[:blank:]]+(.*[^[:blank:]])[[:blank:]]+\{(.*)\$" export BATS_TEST_FILTER= export BATS_ROOT_PID=$$ export BATS_EMULATED_RUN_TMPDIR="$BATS_TMPDIR/bats-run-$BATS_ROOT_PID" export BATS_RUN_TMPDIR="$BATS_EMULATED_RUN_TMPDIR" mkdir -p "$BATS_RUN_TMPDIR" } fixtures() { FIXTURE_ROOT="$BATS_TEST_DIRNAME/fixtures/$1" RELATIVE_FIXTURE_ROOT="${FIXTURE_ROOT#$BATS_CWD/}" } make_bats_test_suite_tmpdir() { export BATS_TEST_SUITE_TMPDIR="$BATS_TMPDIR/bats-test-tmp" mkdir -p "$BATS_TEST_SUITE_TMPDIR" } filter_control_sequences() { "$@" | sed $'s,\x1b\\[[0-9;]*[a-zA-Z],,g' } if ! command -v tput >/dev/null; then tput() { printf '1000\n' } export -f tput fi emit_debug_output() { printf '%s\n' 'output:' "$output" >&2 } teardown() { if [[ -n "$BATS_TEST_SUITE_TMPDIR" ]]; then rm -rf "$BATS_TEST_SUITE_TMPDIR" fi if [[ -n "$BATS_EMULATED_RUN_TMPDIR" ]]; then rm -rf "$BATS_EMULATED_RUN_TMPDIR" fi }