From 6cd61bf9da64b99f0b838ebf97493af13a500fcc Mon Sep 17 00:00:00 2001 From: Tim Harsch Date: Wed, 20 Jan 2016 17:14:51 -0800 Subject: [PATCH 01/41] This commit corrects the problem of incorrect TAP format for skipped tests. --- libexec/bats-exec-test | 5 ++-- libexec/bats-format-tap-stream | 2 +- test/bats.bats | 24 +++++++++++++++++--- test/fixtures/bats/passing_and_skipping.bats | 4 ++++ 4 files changed, 29 insertions(+), 6 deletions(-) diff --git a/libexec/bats-exec-test b/libexec/bats-exec-test index 8f3bd510..63fe32f0 100755 --- a/libexec/bats-exec-test +++ b/libexec/bats-exec-test @@ -244,11 +244,12 @@ bats_exit_trap() { local skipped trap - err exit + skipped="" if [ -n "$BATS_TEST_SKIPPED" ]; then skipped=" # skip" if [ "1" != "$BATS_TEST_SKIPPED" ]; then - skipped+=" ($BATS_TEST_SKIPPED)" + skipped+=" $BATS_TEST_SKIPPED" fi fi @@ -259,7 +260,7 @@ bats_exit_trap() { sed -e "s/^/# /" < "$BATS_OUT" >&3 status=1 else - echo "ok ${BATS_TEST_NUMBER}${skipped} ${BATS_TEST_DESCRIPTION}" >&3 + echo "ok ${BATS_TEST_NUMBER} ${BATS_TEST_DESCRIPTION}${skipped}" >&3 status=0 fi diff --git a/libexec/bats-format-tap-stream b/libexec/bats-format-tap-stream index 614768f4..dc23acb9 100755 --- a/libexec/bats-format-tap-stream +++ b/libexec/bats-format-tap-stream @@ -144,7 +144,7 @@ while IFS= read -r line; do flush ;; "ok "* ) - skip_expr="ok $index # skip (\(([^)]*)\))?" + skip_expr="ok $index (.*) # skip ?(([^)]*))?" if [[ "$line" =~ $skip_expr ]]; then let skipped+=1 buffer skip "${BASH_REMATCH[2]}" diff --git a/test/bats.bats b/test/bats.bats index f1aff293..22aa28ee 100755 --- a/test/bats.bats +++ b/test/bats.bats @@ -49,7 +49,16 @@ fixtures bats @test "summary passing and skipping tests" { run filter_control_sequences bats -p $FIXTURE_ROOT/passing_and_skipping.bats [ $status -eq 0 ] - [ "${lines[2]}" = "2 tests, 0 failures, 1 skipped" ] + [ "${lines[3]}" = "3 tests, 0 failures, 2 skipped" ] +} + +@test "tap passing and skipping tests" { + run filter_control_sequences bats --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 skipping test # skip" ] + [ "${lines[3]}" = "ok 3 skip test with a reason # skip for a really good reason" ] } @test "summary passing and failing tests" { @@ -64,6 +73,15 @@ fixtures bats [ "${lines[5]}" = "3 tests, 1 failure, 1 skipped" ] } +@test "tap passing, failing and skipping tests" { + run filter_control_sequences bats --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 "one failing test" { run bats "$FIXTURE_ROOT/failing.bats" [ $status -eq 1 ] @@ -214,8 +232,8 @@ fixtures bats @test "skipped tests" { run bats "$FIXTURE_ROOT/skipped.bats" [ $status -eq 0 ] - [ "${lines[1]}" = "ok 1 # skip a skipped test" ] - [ "${lines[2]}" = "ok 2 # skip (a reason) a skipped test with a reason" ] + [ "${lines[1]}" = "ok 1 a skipped test # skip" ] + [ "${lines[2]}" = "ok 2 a skipped test with a reason # skip a reason" ] } @test "extended syntax" { diff --git a/test/fixtures/bats/passing_and_skipping.bats b/test/fixtures/bats/passing_and_skipping.bats index 88d74bef..a58dc364 100644 --- a/test/fixtures/bats/passing_and_skipping.bats +++ b/test/fixtures/bats/passing_and_skipping.bats @@ -5,3 +5,7 @@ @test "a skipping test" { skip } + +@test "skip test with a reason" { + skip "for a really good reason" +} From adc7ecfe174020a4f69ffe590cc132e6d205cb22 Mon Sep 17 00:00:00 2001 From: Dmitry Rozhkov Date: Mon, 2 May 2016 14:47:48 +0000 Subject: [PATCH 02/41] Avoid undocumented usage of the head utility. Some implementations of head (e.g. the one in Busybox) can't handle options like "-1". Replace them with "-n1". Signed-off-by: Dmitry Rozhkov --- install.sh | 2 +- libexec/bats | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/install.sh b/install.sh index 8bbdd16b..f366815b 100755 --- a/install.sh +++ b/install.sh @@ -2,7 +2,7 @@ set -e resolve_link() { - $(type -p greadlink readlink | head -1) "$1" + $(type -p greadlink readlink | head -n1) "$1" } abs_dirname() { diff --git a/libexec/bats b/libexec/bats index 71f392f7..52ebd910 100755 --- a/libexec/bats +++ b/libexec/bats @@ -27,7 +27,7 @@ help() { } resolve_link() { - $(type -p greadlink readlink | head -1) "$1" + $(type -p greadlink readlink | head -n1) "$1" } abs_dirname() { From d0f06d1f0df1e2bc901b0fac8b34a1b529946ba7 Mon Sep 17 00:00:00 2001 From: Bianca Tamayo Date: Tue, 19 Sep 2017 14:55:18 -0700 Subject: [PATCH 03/41] Added description & info about this repo in README --- README.md | 28 ++++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) diff --git a/README.md b/README.md index 235bf1ee..d193e1c8 100644 --- a/README.md +++ b/README.md @@ -1,3 +1,31 @@ +## BATS: Bash Automated Testing System (2017) + +### What is this repo? +**Tuesday, September 19, 2017:** This is a mirrored fork of [bats](https://github.com/sstephenson/bats), at [0360811](https://github.com/sstephenson/bats/commit/03608115df2071fff4eaaff1605768c275e5f81f). It was created via `git clone --bare` and `git push --mirror`. + +#### Why was it created? +The original bats repository needed new maintainers, and has not been actively maintained since 2013. While there were volunteers for maintainers, attempts to organize issues, and outstanding PRs, the lack of write-access to the repo hindered progress severely. + +## What's the plan and why? +The rough plan, originally [outlined here](https://github.com/sstephenson/bats/issues/150#issuecomment-323845404) is to create a new, mirrored mainline (this repo!). An excerpt: + +> **1. Roadmap 1.0:** +> There are already existing high-quality PRs, and often-requested features and issues, especially here at [#196](https://github.com/sstephenson/bats/issues/196). Leverage these and **consolidate into a single roadmap**. +> +>**2. Create or choose a fork or *mirror* of this repo to use as the new mainline:** +>Repoint existing PRs (whichever ones are possible) to the new mainline, get that repo to a stable 1.0. IMO we should create an organization and grant 2-3 people admin and write access. +> + +Doing it this way accomplishes two things: +1. Removes the dependency on the original maintainer +2. Enables collaboration and contribution flow again +3. Allows the possibility of merging back to original, or merging from original if or when the need arises +4. Prevents lock-out by giving administrative access to more than one person, increases transferability + + +--- +Original README is below: +--- # Bats: Bash Automated Testing System Bats is a [TAP](http://testanything.org)-compliant testing framework From b72cd3545bb0bd71dfc6e5d888a7c8135bc38f9d Mon Sep 17 00:00:00 2001 From: Bianca Tamayo Date: Wed, 20 Sep 2017 15:28:45 -0700 Subject: [PATCH 04/41] Updated repo name in README --- README.md | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index d193e1c8..8bfdf090 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,6 @@ -## BATS: Bash Automated Testing System (2017) +## BATS-core: Bash Automated Testing System (2017) +### Background: ### What is this repo? **Tuesday, September 19, 2017:** This is a mirrored fork of [bats](https://github.com/sstephenson/bats), at [0360811](https://github.com/sstephenson/bats/commit/03608115df2071fff4eaaff1605768c275e5f81f). It was created via `git clone --bare` and `git push --mirror`. @@ -23,8 +24,6 @@ Doing it this way accomplishes two things: 4. Prevents lock-out by giving administrative access to more than one person, increases transferability ---- -Original README is below: --- # Bats: Bash Automated Testing System From e3b37da3a48fb4dfed5c1455986452989224e841 Mon Sep 17 00:00:00 2001 From: Bianca Tamayo Date: Sun, 24 Sep 2017 10:04:14 -0700 Subject: [PATCH 05/41] Added Travis CI Badge to master branch README --- README.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/README.md b/README.md index 8bfdf090..ee524c0a 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,7 @@ ## BATS-core: Bash Automated Testing System (2017) +[![Build Status](https://travis-ci.org/bats-core/bats-core.svg?branch=master)](https://travis-ci.org/bats-core/bats-core) + ### Background: ### What is this repo? **Tuesday, September 19, 2017:** This is a mirrored fork of [bats](https://github.com/sstephenson/bats), at [0360811](https://github.com/sstephenson/bats/commit/03608115df2071fff4eaaff1605768c275e5f81f). It was created via `git clone --bare` and `git push --mirror`. From 8ca0685b853e9a4ced1706f99bab4a4148160f06 Mon Sep 17 00:00:00 2001 From: Bianca Tamayo Date: Sun, 24 Sep 2017 10:26:25 -0700 Subject: [PATCH 06/41] Updating paths #5 FullSemver: 0.4.1+9 Branch: master --- CONDUCT.md | 5 +++++ LICENSE | 21 +++++++++++++++++++++ README.md | 16 ++++++++++------ libexec/bats | 2 +- man/bats.1 | 4 +++- man/bats.1.ronn | 3 ++- 6 files changed, 42 insertions(+), 9 deletions(-) diff --git a/CONDUCT.md b/CONDUCT.md index 43c3dcb5..55343770 100644 --- a/CONDUCT.md +++ b/CONDUCT.md @@ -67,6 +67,11 @@ members of the project's leadership. ## Project Maintainers +### bats-core organization: +* Bianca Tamayo <> + + +## Project Original Author(s) * Sam Stephenson <> ## Attribution diff --git a/LICENSE b/LICENSE index bac4eb29..3ea56075 100644 --- a/LICENSE +++ b/LICENSE @@ -1,3 +1,24 @@ +Copyright (c) 2017 Bianca Tamayo and bats-core organization + +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. + Copyright (c) 2014 Sam Stephenson Permission is hereby granted, free of charge, to any person obtaining diff --git a/README.md b/README.md index ee524c0a..09a6882f 100644 --- a/README.md +++ b/README.md @@ -106,7 +106,7 @@ 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](https://github.com/sstephenson/bats/wiki/Bats-Evaluation-Process) +[Bats Evaluation Process](https://github.com/bats-core/bats-core/wiki/Bats-Evaluation-Process) on the wiki. ### `run`: Test other commands @@ -239,7 +239,7 @@ Check out a copy of the Bats repository. Then, either add the Bats 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/sstephenson/bats.git + $ git clone https://github.com/bats-core/bats-core.git $ cd bats $ ./install.sh /usr/local @@ -250,15 +250,15 @@ have permission to write to the installation prefix. ## Support The Bats source code repository is [hosted on -GitHub](https://github.com/sstephenson/bats). There you can file bugs +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/sstephenson/bats/wiki/Projects-Using-Bats) +[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/sstephenson/bats/wiki/Syntax-Highlighting) +[Syntax Highlighting](https://github.com/bats-core/bats-core/wiki/Syntax-Highlighting) on the wiki. @@ -318,5 +318,9 @@ on the wiki. --- -© 2014 Sam Stephenson. Bats is released under an MIT-style license; +© 2017 Bianca Tamayo (bats-core organization) + +© 2014 Sam Stephenson + +Bats is released under an MIT-style license; see `LICENSE` for details. diff --git a/libexec/bats b/libexec/bats index 71f392f7..06f8faba 100755 --- a/libexec/bats +++ b/libexec/bats @@ -22,7 +22,7 @@ help() { echo " -t, --tap Show results in TAP format" echo " -v, --version Display the version number" echo - echo " For more information, see https://github.com/sstephenson/bats" + echo " For more information, see https://github.com/bats-core/bats-core" echo } diff --git a/man/bats.1 b/man/bats.1 index 82f73016..3d4cb07a 100644 --- a/man/bats.1 +++ b/man/bats.1 @@ -89,12 +89,14 @@ ok 2 addition using dc 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/sstephenson/bats/wiki/\fR +Bats wiki: \fIhttps://github\.com/bats\-core/bats\-core/wiki/\fR . .P \fBbash\fR(1), \fBbats\fR(7) . .SH "COPYRIGHT" + +(c) 2017 Bianca Tamayo (bats-core organization) (c) 2014 Sam Stephenson . .P diff --git a/man/bats.1.ronn b/man/bats.1.ronn index bd8f45b5..90dd62e9 100644 --- a/man/bats.1.ronn +++ b/man/bats.1.ronn @@ -93,7 +93,7 @@ or `1` if one or more test cases fail. SEE ALSO -------- -Bats wiki: _https://github.com/sstephenson/bats/wiki/_ +Bats wiki: _https://github.com/bats\-core/bats\-core/wiki/_ `bash`(1), `bats`(7) @@ -101,6 +101,7 @@ Bats wiki: _https://github.com/sstephenson/bats/wiki/_ COPYRIGHT --------- +(c) 2017 Bianca Tamayo (bats-core organization) (c) 2014 Sam Stephenson Bats is released under the terms of an MIT-style license. From c85f340f1e466b623b39e599692b88c735ade8ea Mon Sep 17 00:00:00 2001 From: Bianca Tamayo Date: Sun, 24 Sep 2017 11:01:48 -0700 Subject: [PATCH 07/41] Added IRC channel info --- README.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/README.md b/README.md index 09a6882f..5867f880 100644 --- a/README.md +++ b/README.md @@ -25,6 +25,8 @@ Doing it this way accomplishes two things: 3. Allows the possibility of merging back to original, or merging from original if or when the need arises 4. Prevents lock-out by giving administrative access to more than one person, increases transferability +## Misc +- We are `#bats` on freenode --- # Bats: Bash Automated Testing System From 3a6efc03cf1f118e3d2f3f6737527e6c7f6273d7 Mon Sep 17 00:00:00 2001 From: Peter Uhnak Date: Mon, 25 Sep 2017 10:07:42 +0200 Subject: [PATCH 08/41] Minor fix in the install command --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 5867f880..15d9a2b9 100644 --- a/README.md +++ b/README.md @@ -242,7 +242,7 @@ 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 + $ cd bats-core $ ./install.sh /usr/local Note that you may need to run `install.sh` with `sudo` if you do not From d9ee4168ed2a63e5599c9cb5547d970dc6bf8508 Mon Sep 17 00:00:00 2001 From: Mike Bland Date: Sat, 30 Sep 2017 10:55:51 -0400 Subject: [PATCH 09/41] Add .appveyor.yml This follows the example from https://www.appveyor.com/docs/lang/ruby/ except that it doesn't need `install` or `before_test` steps. --- .appveyor.yml | 15 +++++++++++++++ 1 file changed, 15 insertions(+) create mode 100644 .appveyor.yml diff --git a/.appveyor.yml b/.appveyor.yml new file mode 100644 index 00000000..fdaa0b82 --- /dev/null +++ b/.appveyor.yml @@ -0,0 +1,15 @@ +version: 'v0.4.0.{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 libexec/bats test From 5e752ee914e97d40c1593be225126ee5054e0814 Mon Sep 17 00:00:00 2001 From: Mike Bland Date: Sat, 30 Sep 2017 11:00:32 -0400 Subject: [PATCH 10/41] .appveyor.yml: Prefix test command with `time` This enables us to get an idea of the performance impact of a change. --- .appveyor.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.appveyor.yml b/.appveyor.yml index fdaa0b82..bc830247 100644 --- a/.appveyor.yml +++ b/.appveyor.yml @@ -12,4 +12,4 @@ build: off test_script: - where bash - bash --version - - bash libexec/bats test + - bash -c 'time libexec/bats test' From bbac787615907ad06214ca2143464396d599ee5a Mon Sep 17 00:00:00 2001 From: Mike Bland Date: Sat, 30 Sep 2017 11:14:48 -0400 Subject: [PATCH 11/41] .travis.yml: Prefix test command with `time` As with the update to .appveyor.yml in the previous commit, this enables us to get an idea of the performance impact of a change. --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index db06d9d7..76848d17 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,5 +1,5 @@ language: c -script: bin/bats --tap test +script: bash -c 'time bin/bats --tap test' notifications: email: on_success: never From d310b259110f51b14871072c252c829994b41432 Mon Sep 17 00:00:00 2001 From: Mike Bland Date: Sat, 30 Sep 2017 11:25:30 -0400 Subject: [PATCH 12/41] .travis.yml: Enable macOS builds Also sets the `language` to `bash`. --- .travis.yml | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/.travis.yml b/.travis.yml index 76848d17..d7c534f6 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,5 +1,11 @@ -language: c -script: bash -c 'time bin/bats --tap test' +language: bash +os: +- linux +- osx + +script: +- bash -c 'time bin/bats --tap test' + notifications: email: on_success: never From 918714dd4d7c4e537dc45f0292b16d559033bde9 Mon Sep 17 00:00:00 2001 From: Mike Bland Date: Sat, 30 Sep 2017 14:51:45 -0400 Subject: [PATCH 13/41] test/bats: Add statements to debug Travis macOS The following build is demonstrating failures I can't reproduce on my own macOS system: https://travis-ci.org/bats-core/bats-core/jobs/281719290 --- test/bats.bats | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/test/bats.bats b/test/bats.bats index f1aff293..9fca64a3 100755 --- a/test/bats.bats +++ b/test/bats.bats @@ -67,6 +67,8 @@ fixtures bats @test "one failing test" { run bats "$FIXTURE_ROOT/failing.bats" [ $status -eq 1 ] + printf 'lines:\n' >&2 + printf '%s\n' "${lines[@]}" >&2 [ "${lines[0]}" = '1..1' ] [ "${lines[1]}" = 'not ok 1 a failing test' ] [ "${lines[2]}" = "# (in test file $RELATIVE_FIXTURE_ROOT/failing.bats, line 4)" ] @@ -86,6 +88,8 @@ fixtures bats @test "failing test with significant status" { STATUS=2 run bats "$FIXTURE_ROOT/failing.bats" [ $status -eq 1 ] + printf 'lines:\n' >&2 + printf '%s\n' "${lines[@]}" >&2 [ "${lines[3]}" = "# \`eval \"( exit \${STATUS:-1} )\"' failed with status 2" ] } @@ -153,6 +157,8 @@ fixtures bats cd "$TMP" run bats "$FIXTURE_ROOT/failing.bats" [ $status -eq 1 ] + printf 'lines:\n' >&2 + printf '%s\n' "${lines[@]}" >&2 [ "${lines[2]}" = "# (in test file $FIXTURE_ROOT/failing.bats, line 4)" ] } From 0f6dde530ee41c36dcb32341ca41af49fb00ad7d Mon Sep 17 00:00:00 2001 From: Mike Bland Date: Tue, 14 Feb 2017 23:06:59 -0500 Subject: [PATCH 14/41] exec-test: Work around Bash 3.2.57 ERR trap bug When running under Bash 3.2.57(1)-release on macOS, the following tests would fail because `BATS_ERROR_STACK_TRACE` would be empty, and hence no information about the actual error would get printed: - one failing test - failing test with significant status - failing test file outside of BATS_CWD This is because each of these cases use `FIXTURE_ROOT/failing.bats`, and the `ERR` trap would not fire for its `eval "( exit ${STATUS:-1} )"` line. Changing it to `exit ${STATUS:-1}` produced the same effect, and changing it to `return ${STATUS:-1}` would cause the output to point to the previous line, which executes `true`. However, the correct status would be reported to the `EXIT` trap, so now we call `bats_error_trap` at the very beginning of `bats_teardown_trap`. All the existing tests now pass under Bash 3.2.57(1)-release, Bash 4.2.25(1)-release (the version from the default Ubuntu 12.04.5/Precise image on Travis CI), and Bash 4.4.12(1)-release. --- libexec/bats-exec-test | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/libexec/bats-exec-test b/libexec/bats-exec-test index 8f3bd510..bdce3c87 100755 --- a/libexec/bats-exec-test +++ b/libexec/bats-exec-test @@ -218,13 +218,22 @@ bats_debug_trap() { fi } +# When running under Bash 3.2.57(1)-release on macOS, the `ERR` trap may not +# always fire, but the `EXIT` trap will. For this reason we call it at the very +# beginning of `bats_teardown_trap` (the `DEBUG` trap for the call will move +# `BATS_CURRENT_STACK_TRACE` to `BATS_PREVIOUS_STACK_TRACE`) and check the value +# of `$?` before taking other actions. bats_error_trap() { - BATS_ERROR_STATUS="$?" - BATS_ERROR_STACK_TRACE=( "${BATS_PREVIOUS_STACK_TRACE[@]}" ) - trap - debug + local status="$?" + if [[ "$status" -ne '0' ]]; then + BATS_ERROR_STATUS="$status" + BATS_ERROR_STACK_TRACE=( "${BATS_PREVIOUS_STACK_TRACE[@]}" ) + trap - debug + fi } bats_teardown_trap() { + bats_error_trap trap "bats_exit_trap" exit local status=0 teardown >>"$BATS_OUT" 2>&1 || status="$?" From a3396cbc891d5f76832cd0cae65bf427c35bfb6c Mon Sep 17 00:00:00 2001 From: Mike Bland Date: Tue, 14 Feb 2017 16:22:02 -0500 Subject: [PATCH 15/41] exec-test: Refactor bats_frame_* functions Preserves existing behavior. Next step will be to take the target variable name as the second argument. --- libexec/bats-exec-test | 22 ++++++++-------------- 1 file changed, 8 insertions(+), 14 deletions(-) diff --git a/libexec/bats-exec-test b/libexec/bats-exec-test index bdce3c87..518c1162 100755 --- a/libexec/bats-exec-test +++ b/libexec/bats-exec-test @@ -166,28 +166,22 @@ bats_print_failed_command() { } bats_frame_lineno() { - local frame="$1" - local lineno="${frame%% *}" - echo "$lineno" + printf '%s\n' "${1%% *}" } bats_frame_function() { - local frame="$1" - local rest="${frame#* }" - local fn="${rest%% *}" - echo "$fn" + local __bff_function="${1#* }" + printf '%s\n' "${__bff_function%% *}" } bats_frame_filename() { - local frame="$1" - local rest="${frame#* }" - local filename="${rest#* }" + local __bff_filename="${1#* }" + __bff_filename="${__bff_filename#* }" - if [ "$filename" = "$BATS_TEST_SOURCE" ]; then - echo "$BATS_TEST_FILENAME" - else - echo "$filename" + if [ "$__bff_filename" = "$BATS_TEST_SOURCE" ]; then + __bff_filename="$BATS_TEST_FILENAME" fi + printf '%s\n' "$__bff_filename" } bats_extract_line() { From 93d3cec96f25ce6171ff25b3c70a0a083712ce13 Mon Sep 17 00:00:00 2001 From: Mike Bland Date: Tue, 14 Feb 2017 16:37:35 -0500 Subject: [PATCH 16/41] exec-test: Use printf -v in bats_frame_* functions This is part of the effort to improve performance by reducing the number of command substitutions/subshells spawned by `bats_debug_trap`. Under Bash 3.2.57(1)-release on a MacBook Pro with a 2.9GHz Intel Core i5 CPU and 8GB 1867MHz DDR3 RAM, this makes `bin/bats test/` go from: 44 tests, 0 failures real 0m7.565s user 0m3.664s sys 0m3.368s to: real 0m6.449s user 0m3.290s sys 0m2.665s --- libexec/bats-exec-test | 27 +++++++++++++++++---------- 1 file changed, 17 insertions(+), 10 deletions(-) diff --git a/libexec/bats-exec-test b/libexec/bats-exec-test index 518c1162..734f8745 100755 --- a/libexec/bats-exec-test +++ b/libexec/bats-exec-test @@ -114,18 +114,21 @@ bats_capture_stack_trace() { fi done - BATS_SOURCE="$(bats_frame_filename "${BATS_CURRENT_STACK_TRACE[0]}")" - BATS_LINENO="$(bats_frame_lineno "${BATS_CURRENT_STACK_TRACE[0]}")" + bats_frame_filename "${BATS_CURRENT_STACK_TRACE[0]}" 'BATS_SOURCE' + bats_frame_lineno "${BATS_CURRENT_STACK_TRACE[0]}" 'BATS_LINENO' } bats_print_stack_trace() { local frame local index=1 local count="${#@}" + local filename + local lineno for frame in "$@"; do - local filename="$(bats_trim_filename "$(bats_frame_filename "$frame")")" - local lineno="$(bats_frame_lineno "$frame")" + bats_frame_filename "$frame" 'filename' + filename="$(bats_trim_filename "$filename")" + bats_frame_lineno "$frame" 'lineno' if [ $index -eq 1 ]; then echo -n "# (" @@ -133,7 +136,8 @@ bats_print_stack_trace() { echo -n "# " fi - local fn="$(bats_frame_function "$frame")" + local fn + bats_frame_function "$frame" 'fn' if [ "$fn" != "$BATS_TEST_NAME" ]; then echo -n "from function \`$fn' " fi @@ -151,8 +155,11 @@ bats_print_stack_trace() { bats_print_failed_command() { local frame="$1" local status="$2" - local filename="$(bats_frame_filename "$frame")" - local lineno="$(bats_frame_lineno "$frame")" + local filename + local lineno + + bats_frame_filename "$frame" 'filename' + bats_frame_lineno "$frame" 'lineno' local failed_line="$(bats_extract_line "$filename" "$lineno")" local failed_command="$(bats_strip_string "$failed_line")" @@ -166,12 +173,12 @@ bats_print_failed_command() { } bats_frame_lineno() { - printf '%s\n' "${1%% *}" + printf -v "$2" '%s' "${1%% *}" } bats_frame_function() { local __bff_function="${1#* }" - printf '%s\n' "${__bff_function%% *}" + printf -v "$2" '%s' "${__bff_function%% *}" } bats_frame_filename() { @@ -181,7 +188,7 @@ bats_frame_filename() { if [ "$__bff_filename" = "$BATS_TEST_SOURCE" ]; then __bff_filename="$BATS_TEST_FILENAME" fi - printf '%s\n' "$__bff_filename" + printf -v "$2" '%s' "$__bff_filename" } bats_extract_line() { From 39440c57824e5fa6eff1c6173f733fe0e481d1fe Mon Sep 17 00:00:00 2001 From: Mike Bland Date: Wed, 15 Feb 2017 09:44:09 -0500 Subject: [PATCH 17/41] exec-test: Replace `dirname` call with `%/*` --- libexec/bats-exec-test | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libexec/bats-exec-test b/libexec/bats-exec-test index 734f8745..c9e0a7e2 100755 --- a/libexec/bats-exec-test +++ b/libexec/bats-exec-test @@ -26,7 +26,7 @@ else shift fi -BATS_TEST_DIRNAME="$(dirname "$BATS_TEST_FILENAME")" +BATS_TEST_DIRNAME="${BATS_TEST_FILENAME%/*}" BATS_TEST_NAMES=() load() { From eaa151fb698f9fdc3c4e29ab9275f9b9529665bd Mon Sep 17 00:00:00 2001 From: Mike Bland Date: Wed, 15 Feb 2017 10:01:32 -0500 Subject: [PATCH 18/41] exec-test: Use printf -v in bats_trim_filename --- libexec/bats-exec-test | 11 ++++------- test/test_helper.bash | 2 +- 2 files changed, 5 insertions(+), 8 deletions(-) diff --git a/libexec/bats-exec-test b/libexec/bats-exec-test index c9e0a7e2..fce77aaa 100755 --- a/libexec/bats-exec-test +++ b/libexec/bats-exec-test @@ -127,7 +127,7 @@ bats_print_stack_trace() { for frame in "$@"; do bats_frame_filename "$frame" 'filename' - filename="$(bats_trim_filename "$filename")" + bats_trim_filename "$filename" 'filename' bats_frame_lineno "$frame" 'lineno' if [ $index -eq 1 ]; then @@ -203,13 +203,10 @@ bats_strip_string() { } bats_trim_filename() { - local filename="$1" - local length="${#BATS_CWD}" - - if [ "${filename:0:length+1}" = "${BATS_CWD}/" ]; then - echo "${filename:length+1}" + if [[ "$1" =~ ^${BATS_CWD}/ ]]; then + printf -v "$2" '%s' "${1#$BATS_CWD/}" else - echo "$filename" + printf -v "$2" '%s' "$1" fi } diff --git a/test/test_helper.bash b/test/test_helper.bash index 84eee8c3..302f743a 100644 --- a/test/test_helper.bash +++ b/test/test_helper.bash @@ -1,6 +1,6 @@ fixtures() { FIXTURE_ROOT="$BATS_TEST_DIRNAME/fixtures/$1" - RELATIVE_FIXTURE_ROOT="$(bats_trim_filename "$FIXTURE_ROOT")" + bats_trim_filename "$FIXTURE_ROOT" 'RELATIVE_FIXTURE_ROOT' } setup() { From 3bc03796e9274e10fe412700e6128d7538ab3046 Mon Sep 17 00:00:00 2001 From: Mike Bland Date: Wed, 15 Feb 2017 10:07:22 -0500 Subject: [PATCH 19/41] exec-test: Use printf -v in bats_strip_string --- libexec/bats-exec-test | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/libexec/bats-exec-test b/libexec/bats-exec-test index fce77aaa..55f32819 100755 --- a/libexec/bats-exec-test +++ b/libexec/bats-exec-test @@ -162,8 +162,10 @@ bats_print_failed_command() { bats_frame_lineno "$frame" 'lineno' local failed_line="$(bats_extract_line "$filename" "$lineno")" - local failed_command="$(bats_strip_string "$failed_line")" - echo -n "# \`${failed_command}' " + local failed_command + + bats_strip_string "$failed_line" 'failed_command' + printf '%s' "# \`${failed_command}' " if [ $status -eq 1 ]; then echo "failed" @@ -198,8 +200,8 @@ bats_extract_line() { } bats_strip_string() { - local string="$1" - printf "%s" "$string" | sed -e "s/^[ "$'\t'"]*//" -e "s/[ "$'\t'"]*$//" + [[ "$1" =~ ^[[:space:]]*(.*)[[:space:]]*$ ]] + printf -v "$2" '%s' "${BASH_REMATCH[1]}" } bats_trim_filename() { From 698fa766a3ee7b62c60c1dd08879347526aa8c7d Mon Sep 17 00:00:00 2001 From: Mike Bland Date: Wed, 15 Feb 2017 10:13:20 -0500 Subject: [PATCH 20/41] exec-test: Replace `type -t` with `command -F` Also eliminates a subshell. --- libexec/bats-exec-test | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libexec/bats-exec-test b/libexec/bats-exec-test index 55f32819..71ca9b06 100755 --- a/libexec/bats-exec-test +++ b/libexec/bats-exec-test @@ -289,7 +289,7 @@ bats_perform_tests() { bats_perform_test() { BATS_TEST_NAME="$1" - if [ "$(type -t "$BATS_TEST_NAME" || true)" = "function" ]; then + if declare -F "$BATS_TEST_NAME" >/dev/null; then BATS_TEST_NUMBER="$2" if [ -z "$BATS_TEST_NUMBER" ]; then echo "1..1" From d294689bdd91049843b05df3680b7ff8c0e8d9c8 Mon Sep 17 00:00:00 2001 From: Mike Bland Date: Wed, 15 Feb 2017 10:26:28 -0500 Subject: [PATCH 21/41] exec-test: Use `printf -v` in bats_extract_line Also replaces `sed` invocation with a `while` loop, saving a subprocess. --- libexec/bats-exec-test | 19 ++++++++++++------- 1 file changed, 12 insertions(+), 7 deletions(-) diff --git a/libexec/bats-exec-test b/libexec/bats-exec-test index 71ca9b06..7e86c16b 100755 --- a/libexec/bats-exec-test +++ b/libexec/bats-exec-test @@ -157,13 +157,12 @@ bats_print_failed_command() { local status="$2" local filename local lineno + local failed_line + local failed_command bats_frame_filename "$frame" 'filename' bats_frame_lineno "$frame" 'lineno' - - local failed_line="$(bats_extract_line "$filename" "$lineno")" - local failed_command - + bats_extract_line "$filename" "$lineno" 'failed_line' bats_strip_string "$failed_line" 'failed_command' printf '%s' "# \`${failed_command}' " @@ -194,9 +193,15 @@ bats_frame_filename() { } bats_extract_line() { - local filename="$1" - local lineno="$2" - sed -n "${lineno}p" "$filename" + 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() { From cf9a3b8af4a8bbb6246e321f687d89e5f654fb57 Mon Sep 17 00:00:00 2001 From: Mike Bland Date: Wed, 15 Feb 2017 10:44:11 -0500 Subject: [PATCH 22/41] exec-test: Invoke bats-preprocess directly Also, `bats-preprocess` now converts DOS/Windows CRLF line endings. --- libexec/bats-exec-test | 2 +- libexec/bats-preprocess | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/libexec/bats-exec-test b/libexec/bats-exec-test index 7e86c16b..09e8a7ff 100755 --- a/libexec/bats-exec-test +++ b/libexec/bats-exec-test @@ -327,7 +327,7 @@ BATS_OUT="${BATS_TMPNAME}.out" bats_preprocess_source() { BATS_TEST_SOURCE="${BATS_TMPNAME}.src" - { tr -d '\r' < "$BATS_TEST_FILENAME"; echo; } | bats-preprocess > "$BATS_TEST_SOURCE" + . bats-preprocess <<< "$(< "$BATS_TEST_FILENAME")"$'\n' > "$BATS_TEST_SOURCE" trap "bats_cleanup_preprocessed_source" err exit trap "bats_cleanup_preprocessed_source; exit 1" int } diff --git a/libexec/bats-preprocess b/libexec/bats-preprocess index 04297ed0..873085e6 100755 --- a/libexec/bats-preprocess +++ b/libexec/bats-preprocess @@ -34,6 +34,7 @@ index=0 pattern='^ *@test *([^ ].*) *\{ *(.*)$' while IFS= read -r line; do + line="${line//$'\r'}" let index+=1 if [[ "$line" =~ $pattern ]]; then quoted_name="${BASH_REMATCH[1]}" From 741c414d6afe9e0c5be5b4435e80676ebc99df54 Mon Sep 17 00:00:00 2001 From: Mike Bland Date: Wed, 15 Feb 2017 11:01:34 -0500 Subject: [PATCH 23/41] preprocess: Use printf -v in encode_name --- libexec/bats-preprocess | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/libexec/bats-preprocess b/libexec/bats-preprocess index 873085e6..6cd90eb4 100755 --- a/libexec/bats-preprocess +++ b/libexec/bats-preprocess @@ -4,6 +4,7 @@ set -e encode_name() { local name="$1" local result="test_" + local hex_code if [[ ! "$name" =~ [^[:alnum:]\ _-] ]]; then name="${name//_/-5f}" @@ -21,12 +22,13 @@ encode_name() { elif [[ "$char" =~ [[:alnum:]] ]]; then result+="$char" else - result+="$(printf -- "-%02x" \'"$char")" + printf -v 'hex_code' -- "-%02x" \'"$char" + result+="$hex_code" fi done fi - echo "$result" + printf -v "$2" '%s' "$result" } tests=() @@ -40,7 +42,7 @@ while IFS= read -r line; do quoted_name="${BASH_REMATCH[1]}" body="${BASH_REMATCH[2]}" name="$(eval echo "$quoted_name")" - encoded_name="$(encode_name "$name")" + encode_name "$name" 'encoded_name' tests["${#tests[@]}"]="$encoded_name" echo "${encoded_name}() { bats_test_begin ${quoted_name} ${index}; ${body}" else From e613b31a1cde947bbe949eaf2fa1d4d99cfc15de Mon Sep 17 00:00:00 2001 From: Mike Bland Date: Wed, 15 Feb 2017 11:10:55 -0500 Subject: [PATCH 24/41] exec-test: Replace `|| { }` with `if [[ ]]; then` Somehow this is ever-so-slightly faster. --- libexec/bats-exec-test | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libexec/bats-exec-test b/libexec/bats-exec-test index 09e8a7ff..1ffc746d 100755 --- a/libexec/bats-exec-test +++ b/libexec/bats-exec-test @@ -39,10 +39,10 @@ load() { filename="$BATS_TEST_DIRNAME/${name}.bash" fi - [ -f "$filename" ] || { + if [[ ! -f "$filename" ]]; then echo "bats: $filename does not exist" >&2 exit 1 - } + fi source "${filename}" } From fac51df957a26d440284b839ffac69cd258cde7b Mon Sep 17 00:00:00 2001 From: Mike Bland Date: Wed, 15 Feb 2017 11:23:28 -0500 Subject: [PATCH 25/41] exec-test: Replace `caller` with `FUNCNAME`, etc. This is part of the effort to improve performance by reducing the number of command substitutions/subshells spawned by `bats_debug_trap`. Under Bash 3.2.57(1)-release on a MacBook Pro with a 2.9GHz Intel Core i5 CPU and 8GB 1867MHz DDR3 RAM, this makes `bin/bats test/` go from the following for the previous commit: 44 tests, 0 failures real 0m5.293s user 0m2.853s sys 0m2.087s to: real 0m4.319s user 0m2.559s sys 0m1.454s --- libexec/bats-exec-test | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/libexec/bats-exec-test b/libexec/bats-exec-test index 1ffc746d..b27a9417 100755 --- a/libexec/bats-exec-test +++ b/libexec/bats-exec-test @@ -101,16 +101,15 @@ bats_capture_stack_trace() { local teardown_pattern=" teardown $BATS_TEST_SOURCE" local frame - local index=1 + local i - while frame="$(caller "$index")"; do + for ((i=2; i != ${#FUNCNAME[@]}; ++i)); do + frame="${BASH_LINENO[$((i-1))]} ${FUNCNAME[$i]} ${BASH_SOURCE[$i]}" BATS_CURRENT_STACK_TRACE["${#BATS_CURRENT_STACK_TRACE[@]}"]="$frame" if [[ "$frame" = *"$test_pattern" || \ "$frame" = *"$setup_pattern" || \ "$frame" = *"$teardown_pattern" ]]; then break - else - let index+=1 fi done From 3ab495fda2e032b869eee86b262e651ff907c9c5 Mon Sep 17 00:00:00 2001 From: Mike Bland Date: Wed, 15 Feb 2017 12:04:03 -0500 Subject: [PATCH 26/41] preprocess: Add tests for vars, quotes in names This is in anticipation of refactoring away the `$(eval echo "$quoted_name")` command substitution. --- test/bats.bats | 14 ++++++++++++++ test/fixtures/bats/expand_var_in_test_name.bats | 3 +++ .../bats/quoted_and_unquoted_test_names.bats | 11 +++++++++++ 3 files changed, 28 insertions(+) create mode 100644 test/fixtures/bats/expand_var_in_test_name.bats create mode 100644 test/fixtures/bats/quoted_and_unquoted_test_names.bats diff --git a/test/bats.bats b/test/bats.bats index 9fca64a3..60fb017a 100755 --- a/test/bats.bats +++ b/test/bats.bats @@ -268,3 +268,17 @@ fixtures 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" ] +} diff --git a/test/fixtures/bats/expand_var_in_test_name.bats b/test/fixtures/bats/expand_var_in_test_name.bats new file mode 100644 index 00000000..8f6dec23 --- /dev/null +++ b/test/fixtures/bats/expand_var_in_test_name.bats @@ -0,0 +1,3 @@ +@test "$SUITE: test with variable in name" { + true +} diff --git a/test/fixtures/bats/quoted_and_unquoted_test_names.bats b/test/fixtures/bats/quoted_and_unquoted_test_names.bats new file mode 100644 index 00000000..706902b3 --- /dev/null +++ b/test/fixtures/bats/quoted_and_unquoted_test_names.bats @@ -0,0 +1,11 @@ +@test 'single-quoted name' { + true +} + +@test "double-quoted name" { + true +} + +@test unquoted { + true +} From 6beea07a0b9b0629b3ddec47899a297f82d9e8b9 Mon Sep 17 00:00:00 2001 From: Mike Bland Date: Wed, 15 Feb 2017 11:53:01 -0500 Subject: [PATCH 27/41] preprocess: Eliminate eval in subshell This is part of the effort to improve performance by reducing the number of command substitutions/subshells. Under Bash 3.2.57(1)-release on a MacBook Pro with a 2.9GHz Intel Core i5 CPU and 8GB 1867MHz DDR3 RAM, this shaves off O(0.15s) from the test suite at the previous commit, but I anticipate this effect being magnified on Windows platforms. --- libexec/bats-preprocess | 8 ++++---- test/bats.bats | 2 +- test/fixtures/bats/quoted_and_unquoted_test_names.bats | 2 +- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/libexec/bats-preprocess b/libexec/bats-preprocess index 6cd90eb4..30392b68 100755 --- a/libexec/bats-preprocess +++ b/libexec/bats-preprocess @@ -33,18 +33,18 @@ encode_name() { tests=() index=0 -pattern='^ *@test *([^ ].*) *\{ *(.*)$' +pattern='^ *@test +(.+) +\{ *(.*)$' while IFS= read -r line; do line="${line//$'\r'}" let index+=1 if [[ "$line" =~ $pattern ]]; then - quoted_name="${BASH_REMATCH[1]}" + name="${BASH_REMATCH[1]#[\'\"]}" + name="${name%[\'\"]}" body="${BASH_REMATCH[2]}" - name="$(eval echo "$quoted_name")" encode_name "$name" 'encoded_name' tests["${#tests[@]}"]="$encoded_name" - echo "${encoded_name}() { bats_test_begin ${quoted_name} ${index}; ${body}" + echo "${encoded_name}() { bats_test_begin \"${name}\" ${index}; ${body}" else printf "%s\n" "$line" fi diff --git a/test/bats.bats b/test/bats.bats index 60fb017a..9bed9983 100755 --- a/test/bats.bats +++ b/test/bats.bats @@ -280,5 +280,5 @@ fixtures bats [ $status -eq 0 ] [ "${lines[1]}" = "ok 1 single-quoted name" ] [ "${lines[2]}" = "ok 2 double-quoted name" ] - [ "${lines[3]}" = "ok 3 unquoted" ] + [ "${lines[3]}" = "ok 3 unquoted name" ] } diff --git a/test/fixtures/bats/quoted_and_unquoted_test_names.bats b/test/fixtures/bats/quoted_and_unquoted_test_names.bats index 706902b3..aa460daa 100644 --- a/test/fixtures/bats/quoted_and_unquoted_test_names.bats +++ b/test/fixtures/bats/quoted_and_unquoted_test_names.bats @@ -6,6 +6,6 @@ true } -@test unquoted { +@test unquoted name { true } From cdc55ad7ea7fd52ad263cda1b635d909208ca09b Mon Sep 17 00:00:00 2001 From: Mike Bland Date: Thu, 16 Mar 2017 12:14:34 -0400 Subject: [PATCH 28/41] bats: Refactor resolve_link, abs_dirname Under Bash 3.2.57(1)-release and 4.4.12(1)-release on a MacBook Pro with a 2.9GHz Intel Core i5 CPU and 8GB 1867MHz DDR3 RAM, this shaves off O(0.4s) from the current test suite. Before the change: 46 tests, 0 failures real 0m4.392s user 0m2.489s sys 0m1.467s After the change: real 0m3.980s user 0m2.312s sys 0m1.233s --- libexec/bats | 17 ++++++++++++++--- 1 file changed, 14 insertions(+), 3 deletions(-) diff --git a/libexec/bats b/libexec/bats index 06f8faba..81290508 100755 --- a/libexec/bats +++ b/libexec/bats @@ -26,18 +26,29 @@ help() { echo } +BATS_READLINK= + resolve_link() { - $(type -p greadlink readlink | head -1) "$1" + if [[ -z "$BATS_READLINK" ]]; then + if command -v 'greadlink' >/dev/null; then + BATS_READLINK='greadlink' + elif command -v 'readlink' >/dev/null; then + BATS_READLINK='readlink' + else + BATS_READLINK='true' + fi + fi + "$BATS_READLINK" "$1" || return 0 } abs_dirname() { - local cwd="$(pwd)" + local cwd="$PWD" local path="$1" while [ -n "$path" ]; do cd "${path%/*}" local name="${path##*/}" - path="$(resolve_link "$name" || true)" + path="$(resolve_link "$name")" done pwd From daf76c27c146598c2deba15694c6cd01b2cd82a6 Mon Sep 17 00:00:00 2001 From: Mike Bland Date: Thu, 16 Mar 2017 12:25:17 -0400 Subject: [PATCH 29/41] bats: Convert abs_dirname to use `printf -v` Under Bash 3.2.57(1)-release and 4.4.12(1)-release on a MacBook Pro with a 2.9GHz Intel Core i5 CPU and 8GB 1867MHz DDR3 RAM, this shaves off O(0.1s) from the current test suite. Before the change: 46 tests, 0 failures real 0m3.983s user 0m2.320s sys 0m1.241s After the change: real 0m3.861s user 0m2.276s sys 0m1.174s --- libexec/bats | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/libexec/bats b/libexec/bats index 81290508..5e90a9e7 100755 --- a/libexec/bats +++ b/libexec/bats @@ -51,7 +51,7 @@ abs_dirname() { path="$(resolve_link "$name")" done - pwd + printf -v "$2" -- '%s' "$PWD" cd "$cwd" } @@ -63,9 +63,12 @@ expand_path() { } || echo "$1" } -BATS_LIBEXEC="$(abs_dirname "$0")" -export BATS_PREFIX="$(abs_dirname "$BATS_LIBEXEC")" -export BATS_CWD="$(abs_dirname .)" +abs_dirname "$0" 'BATS_LIBEXEC' +abs_dirname "$BATS_LIBEXEC" 'BATS_PREFIX' +abs_dirname '.' 'BATS_CWD' + +export BATS_PREFIX +export BATS_CWD export PATH="$BATS_LIBEXEC:$PATH" options=() From d4443adeb790cca11283013fedb28cc2bc12d9cb Mon Sep 17 00:00:00 2001 From: Mike Bland Date: Thu, 16 Mar 2017 13:15:38 -0400 Subject: [PATCH 30/41] bash: Refactor expand_path Under Bash 3.2.57(1)-release and 4.4.12(1)-release on a MacBook Pro with a 2.9GHz Intel Core i5 CPU and 8GB 1867MHz DDR3 RAM, this shaves off O(0.25s) from the current test suite. Before the change: 46 tests, 0 failures real 0m3.851s user 0m2.273s sys 0m1.166s After the change: real 0m3.595s user 0m2.171s sys 0m1.048s --- libexec/bats | 22 ++++++++++++++++------ 1 file changed, 16 insertions(+), 6 deletions(-) diff --git a/libexec/bats b/libexec/bats index 5e90a9e7..5cd95c67 100755 --- a/libexec/bats +++ b/libexec/bats @@ -56,11 +56,19 @@ abs_dirname() { } expand_path() { - { cd "$(dirname "$1")" 2>/dev/null - local dirname="$PWD" + local path="${1%/}" + local dirname="${path%/*}" + + if [[ "$dirname" == "$path" ]]; then + dirname="$PWD" + elif cd "$dirname" 2>/dev/null; then + dirname="$PWD" cd "$OLDPWD" - echo "$dirname/$(basename "$1")" - } || echo "$1" + else + printf '%s' "$path" + return + fi + printf -v "$2" '%s/%s' "$dirname" "${path##*/}" } abs_dirname "$0" 'BATS_LIBEXEC' @@ -127,14 +135,16 @@ fi filenames=() for filename in "${arguments[@]}"; do + expand_path "$filename" 'filename' + if [ -d "$filename" ]; then shopt -s nullglob - for suite_filename in "$(expand_path "$filename")"/*.bats; do + for suite_filename in "$filename"/*.bats; do filenames["${#filenames[@]}"]="$suite_filename" done shopt -u nullglob else - filenames["${#filenames[@]}"]="$(expand_path "$filename")" + filenames["${#filenames[@]}"]="$filename" fi done From 7bcbb2f3e9babf5ab1683c189cdafbed665e6ea9 Mon Sep 17 00:00:00 2001 From: Mike Bland Date: Thu, 16 Mar 2017 13:40:37 -0400 Subject: [PATCH 31/41] bats: Don't pipe to cat for nonpretty output Under Bash 3.2.57(1)-release and 4.4.12(1)-release on a MacBook Pro with a 2.9GHz Intel Core i5 CPU and 8GB 1867MHz DDR3 RAM, this shaves off O(0.04-0.05s) from the current test suite. Very minor, but it's a straightforward change that may provide a minor-yet-noticeable effect on Windows. Before this change: 46 tests, 0 failures real 0m3.588s user 0m2.171s sys 0m1.046s After this change: real 0m3.538s user 0m2.119s sys 0m0.941s --- libexec/bats | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/libexec/bats b/libexec/bats index 5cd95c67..7dc0c14e 100755 --- a/libexec/bats +++ b/libexec/bats @@ -154,13 +154,11 @@ else command="bats-exec-suite" fi -if [ -n "$pretty" ]; then +set -o pipefail execfail +if [ -z "$pretty" ]; then + exec "$command" $count_flag "${filenames[@]}" +else extended_syntax_flag="-x" formatter="bats-format-tap-stream" -else - extended_syntax_flag="" - formatter="cat" + exec "$command" $count_flag $extended_syntax_flag "${filenames[@]}" | "$formatter" fi - -set -o pipefail execfail -exec "$command" $count_flag $extended_syntax_flag "${filenames[@]}" | "$formatter" From f5acd286129e3b68945a33da7d74ece82564ac57 Mon Sep 17 00:00:00 2001 From: Mike Bland Date: Thu, 16 Mar 2017 14:10:19 -0400 Subject: [PATCH 32/41] bats-exec-suite: Count tests w/ BATS_TEST_PATTERN Under Bash 3.2.57(1)-release and 4.4.12(1)-release on a MacBook Pro with a 2.9GHz Intel Core i5 CPU and 8GB 1867MHz DDR3 RAM, this shaves off O(0.16s) from the current test suite. Before this change: 46 tests, 0 failures real 0m3.541s user 0m2.125s sys 0m0.937s After this change: real 0m3.372s user 0m2.031s sys 0m0.894s --- libexec/bats | 1 + libexec/bats-exec-suite | 6 +++++- libexec/bats-preprocess | 3 +-- 3 files changed, 7 insertions(+), 3 deletions(-) diff --git a/libexec/bats b/libexec/bats index 7dc0c14e..e074747d 100755 --- a/libexec/bats +++ b/libexec/bats @@ -77,6 +77,7 @@ abs_dirname '.' 'BATS_CWD' export BATS_PREFIX export BATS_CWD +export BATS_TEST_PATTERN='^ *@test +(.+) +\{ *(.*)$' export PATH="$BATS_LIBEXEC:$PATH" options=() diff --git a/libexec/bats-exec-suite b/libexec/bats-exec-suite index 29ab255d..96021bbd 100755 --- a/libexec/bats-exec-suite +++ b/libexec/bats-exec-suite @@ -17,7 +17,11 @@ trap "kill 0; exit 1" int count=0 for filename in "$@"; do - let count+="$(bats-exec-test -c "$filename")" + while IFS= read -r line; do + if [[ "$line" =~ $BATS_TEST_PATTERN ]]; then + let count+=1 + fi + done <"$filename" done if [ -n "$count_only_flag" ]; then diff --git a/libexec/bats-preprocess b/libexec/bats-preprocess index 30392b68..8307b761 100755 --- a/libexec/bats-preprocess +++ b/libexec/bats-preprocess @@ -33,12 +33,11 @@ encode_name() { tests=() index=0 -pattern='^ *@test +(.+) +\{ *(.*)$' while IFS= read -r line; do line="${line//$'\r'}" let index+=1 - if [[ "$line" =~ $pattern ]]; then + if [[ "$line" =~ $BATS_TEST_PATTERN ]]; then name="${BASH_REMATCH[1]#[\'\"]}" name="${name%[\'\"]}" body="${BASH_REMATCH[2]}" From 8c4a86d53458920db6953d8ab613c3f7149d0e35 Mon Sep 17 00:00:00 2001 From: Mike Bland Date: Thu, 16 Mar 2017 16:04:54 -0400 Subject: [PATCH 33/41] format-tap: Refactor summary to remove subshells While the performance impact of these changes are in the noise under macOS 10.12.3 on a on a MacBook Pro with a 2.9GHz Intel Core i5 CPU and 8GB 1867MHz DDR3 RAM, eliminating these subshells makes the code more consistent. I did try removing `buffer` to eliminate yet more subshells, but the flickering of the output did prove annoying, so I'm not removing it. --- libexec/bats-format-tap-stream | 26 +++++++++++++++++--------- 1 file changed, 17 insertions(+), 9 deletions(-) diff --git a/libexec/bats-format-tap-stream b/libexec/bats-format-tap-stream index 614768f4..b13fe1fc 100755 --- a/libexec/bats-format-tap-stream +++ b/libexec/bats-format-tap-stream @@ -65,9 +65,15 @@ log() { } summary() { - printf "\n%d test%s" "$count" "$(plural "$count")" + printf "\n%d test" "$count" + if [[ "$count" -ne '1' ]]; then + printf 's' + fi - printf ", %d failure%s" "$failures" "$(plural "$failures")" + printf ", %d failure" "$failures" + if [[ "$failures" -ne '1' ]]; then + printf 's' + fi if [ "$skipped" -gt 0 ]; then printf ", %d skipped" "$skipped" @@ -79,7 +85,9 @@ summary() { printf_with_truncation() { local width="$1" shift - local string="$(printf "$@")" + local string + + printf -v 'string' -- "$@" if [ "${#string}" -gt "$width" ]; then printf "%s..." "${string:0:$(( $width - 4 ))}" @@ -105,18 +113,18 @@ advance() { set_color() { local color="$1" - local weight="$2" - printf "\x1B[%d;%dm" $(( 30 + $color )) "$( [ "$weight" = "bold" ] && echo 1 || echo 22 )" + local weight='22' + + if [[ "$2" == 'bold' ]]; then + weight='1' + fi + printf "\x1B[%d;%dm" $(( 30 + $color )) "$weight" } clear_color() { printf "\x1B[0m" } -plural() { - [ "$1" -eq 1 ] || echo "s" -} - _buffer="" buffer() { From ebb192e036284b5006ecac08343c72be6e93e19b Mon Sep 17 00:00:00 2001 From: Mike Bland Date: Thu, 28 Sep 2017 06:34:03 -0400 Subject: [PATCH 34/41] Fix test failures due to unquoted variables The four test cases updated in this commit were failing on my Windows virtual machine because my username contains a space. Quoting the file paths containing "$FIXTURE_ROOT" solved the problem. --- test/bats.bats | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/test/bats.bats b/test/bats.bats index 9bed9983..44b573ce 100755 --- a/test/bats.bats +++ b/test/bats.bats @@ -41,25 +41,25 @@ fixtures bats } @test "summary passing tests" { - run filter_control_sequences bats -p $FIXTURE_ROOT/passing.bats + 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 + run filter_control_sequences bats -p "$FIXTURE_ROOT/passing_and_skipping.bats" [ $status -eq 0 ] [ "${lines[2]}" = "2 tests, 0 failures, 1 skipped" ] } @test "summary passing and failing tests" { - run filter_control_sequences bats -p $FIXTURE_ROOT/failing_and_passing.bats + 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 + run filter_control_sequences bats -p "$FIXTURE_ROOT/passing_failing_and_skipping.bats" [ $status -eq 0 ] [ "${lines[5]}" = "3 tests, 1 failure, 1 skipped" ] } From d1f9165ba0b82d13a6870b2e72f6779ca4576f85 Mon Sep 17 00:00:00 2001 From: Jason Grosz Date: Mon, 2 Oct 2017 14:39:27 -0500 Subject: [PATCH 35/41] Reword skipped test fixtures for clarity Separate "skip" from the test name (description) to be distinct from "skip" as part of the TAP Directive. --- test/bats.bats | 4 ++-- test/fixtures/bats/passing_and_skipping.bats | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/test/bats.bats b/test/bats.bats index 22aa28ee..441916e2 100755 --- a/test/bats.bats +++ b/test/bats.bats @@ -57,8 +57,8 @@ fixtures 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]}" = "ok 3 skip test with a reason # skip for a really good reason" ] + [ "${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" { diff --git a/test/fixtures/bats/passing_and_skipping.bats b/test/fixtures/bats/passing_and_skipping.bats index a58dc364..83fc76bf 100644 --- a/test/fixtures/bats/passing_and_skipping.bats +++ b/test/fixtures/bats/passing_and_skipping.bats @@ -2,10 +2,10 @@ true } -@test "a skipping test" { +@test "a skipped test with no reason" { skip } -@test "skip test with a reason" { +@test "a skipped test with a reason" { skip "for a really good reason" } From adf559ec4014ad504c250b9db06a9e67e847d8f6 Mon Sep 17 00:00:00 2001 From: Jason Grosz Date: Mon, 2 Oct 2017 14:53:47 -0500 Subject: [PATCH 36/41] Remove unnecessary assignment and blank line --- libexec/bats-exec-test | 2 -- 1 file changed, 2 deletions(-) diff --git a/libexec/bats-exec-test b/libexec/bats-exec-test index 63fe32f0..001a8c5d 100755 --- a/libexec/bats-exec-test +++ b/libexec/bats-exec-test @@ -244,8 +244,6 @@ bats_exit_trap() { local skipped trap - err exit - - skipped="" if [ -n "$BATS_TEST_SKIPPED" ]; then skipped=" # skip" if [ "1" != "$BATS_TEST_SKIPPED" ]; then From eed991303b63287c0d75d7cc4d21fd994cd37a40 Mon Sep 17 00:00:00 2001 From: Jason Grosz Date: Tue, 3 Oct 2017 13:30:35 -0500 Subject: [PATCH 37/41] Add double quotes around `$FIXTURE_ROOT` --- test/bats.bats | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/bats.bats b/test/bats.bats index 441916e2..3f48d0df 100755 --- a/test/bats.bats +++ b/test/bats.bats @@ -53,7 +53,7 @@ fixtures bats } @test "tap passing and skipping tests" { - run filter_control_sequences bats --tap $FIXTURE_ROOT/passing_and_skipping.bats + run filter_control_sequences bats --tap "$FIXTURE_ROOT/passing_and_skipping.bats" [ $status -eq 0 ] [ "${lines[0]}" = "1..3" ] [ "${lines[1]}" = "ok 1 a passing test" ] @@ -68,7 +68,7 @@ fixtures bats } @test "summary passing, failing and skipping tests" { - run filter_control_sequences bats -p $FIXTURE_ROOT/passing_failing_and_skipping.bats + run filter_control_sequences bats -p "$FIXTURE_ROOT/passing_failing_and_skipping.bats" [ $status -eq 0 ] [ "${lines[5]}" = "3 tests, 1 failure, 1 skipped" ] } From 1ed87ecb7f0b8f2be4c04aed242f2114975ab8e1 Mon Sep 17 00:00:00 2001 From: Mike Bland Date: Mon, 2 Oct 2017 22:02:00 -0400 Subject: [PATCH 38/41] test/bats: Add fake tput to fix Alpine tests The test cases that use the `-p` or `--pretty` flag would fail if `tput` wasn't available (installed as part of the `ncurses` package). On Alpine, `ncurses` isn't installed by default. This change ensures the tests validate the expected behavior regardless of whether `tput` is available. --- test/test_helper.bash | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/test/test_helper.bash b/test/test_helper.bash index 302f743a..af890034 100644 --- a/test/test_helper.bash +++ b/test/test_helper.bash @@ -11,6 +11,13 @@ 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 + teardown() { [ -d "$TMP" ] && rm -f "$TMP"/* } From 617e086a267ecaf7abfbf74e4189ee83b85a78b9 Mon Sep 17 00:00:00 2001 From: Nelo Wallus Date: Wed, 22 Mar 2017 15:27:15 +0100 Subject: [PATCH 39/41] Allow sourcing of helper files from BATS_LIB_PATH The existing functionality of load() is preserved: 1. Load helper files in the same directory the current testfile resides in 2. Load helper files by absolute path Additionally an environment variable BATS_LIB_PATH can be defined to be source helper files from. If BATS_LIB_PATH is empty the following locations are used: 1. $HOME/.bats/lib Allows users to manage helper libraries themselves, similar to python/ruby/... 2. /usr/lib/bats Allows to install helper libraries via a package manager. --- libexec/bats-exec-test | 38 +++++++++++++++++++++++++++++--------- 1 file changed, 29 insertions(+), 9 deletions(-) diff --git a/libexec/bats-exec-test b/libexec/bats-exec-test index 22b1c714..f5736f16 100755 --- a/libexec/bats-exec-test +++ b/libexec/bats-exec-test @@ -33,18 +33,38 @@ load() { local name="$1" local filename - if [ "${name:0:1}" = "/" ]; then - filename="${name}" - else - filename="$BATS_TEST_DIRNAME/${name}.bash" - fi + # Argument is absolute, verify that the path exists and return after + # sourcing + if [[ "${name:0:1}" == "/" ]]; then + filename=$name + + if [[ ! -f "$filename" ]]; then + echo "bats: $filename does not exist" >&2 + exit 1 + fi - if [[ ! -f "$filename" ]]; then - echo "bats: $filename does not exist" >&2 - exit 1 + source "$filename" + return fi - source "${filename}" + # Set libpath with directory of current test file + # Defaults to BATS_LIB_PATH e.g. for testing + local libpath="${BATS_LIB_PATH:-$HOME/.bats/lib:/usr/lib/bats}" + libpath="$BATS_TEST_DIRNAME:$libpath" + + # Test for library file in each libpath, source and return if it + # exists + for part in ${libpath//:/ }; do + filename="$part/$name.bash" + + if [[ -f "$filename" ]]; then + source "$filename" + return + fi + done + + echo "bats: No file $name in BATS_LIB_PATH found" >&2 + exit 1 } run() { From cb434296c573520ec8b4f999de5f82991c31acfc Mon Sep 17 00:00:00 2001 From: Nelo Wallus Date: Wed, 22 Mar 2017 19:49:36 +0100 Subject: [PATCH 40/41] Add test harness for various library loading methods --- test/fixtures/bats/load.bats | 21 +++++++++++++++++++ .../bats/load_path/no_loader/no_loader.bash | 3 +++ test/fixtures/bats/load_path/single_file.bash | 3 +++ test/fixtures/bats/load_path/with_loader.bash | 1 + .../bats/load_path/with_loader/a-file.bash | 3 +++ 5 files changed, 31 insertions(+) create mode 100644 test/fixtures/bats/load_path/no_loader/no_loader.bash create mode 100644 test/fixtures/bats/load_path/single_file.bash create mode 100644 test/fixtures/bats/load_path/with_loader.bash create mode 100644 test/fixtures/bats/load_path/with_loader/a-file.bash diff --git a/test/fixtures/bats/load.bats b/test/fixtures/bats/load.bats index 975b6b8c..45d6f0af 100644 --- a/test/fixtures/bats/load.bats +++ b/test/fixtures/bats/load.bats @@ -1,6 +1,27 @@ [ -n "$HELPER_NAME" ] || HELPER_NAME="test_helper" load "$HELPER_NAME" +BATS_LIB_PATH="$BATS_TEST_DIRNAME/load_path" \ + load "${HELPER_LIB_SINGLE_FILE:-single_file}" + +BATS_LIB_PATH="$BATS_TEST_DIRNAME/load_path" \ + load "${HELPER_LIB_NO_LOADER:-no_loader}" + +BATS_LIB_PATH="$BATS_TEST_DIRNAME/load_path" \ + load "${HELPER_LIB_WITH_LOADER:-with_loader}" + @test "calling a loaded helper" { help_me } + +@test "calling a library helper" { + lib_func +} + +@test "calling a helper from library without loading file" { + no_loader +} + +@test "calling a helper from library with loading file" { + with_loader +} diff --git a/test/fixtures/bats/load_path/no_loader/no_loader.bash b/test/fixtures/bats/load_path/no_loader/no_loader.bash new file mode 100644 index 00000000..2ee35060 --- /dev/null +++ b/test/fixtures/bats/load_path/no_loader/no_loader.bash @@ -0,0 +1,3 @@ +no_loader() { + true +} diff --git a/test/fixtures/bats/load_path/single_file.bash b/test/fixtures/bats/load_path/single_file.bash new file mode 100644 index 00000000..5a170e13 --- /dev/null +++ b/test/fixtures/bats/load_path/single_file.bash @@ -0,0 +1,3 @@ +lib_func() { + true +} diff --git a/test/fixtures/bats/load_path/with_loader.bash b/test/fixtures/bats/load_path/with_loader.bash new file mode 100644 index 00000000..ba4d78ec --- /dev/null +++ b/test/fixtures/bats/load_path/with_loader.bash @@ -0,0 +1 @@ +source "$(dirname ${BASH_SOURCE[0]})/with_loader/a-file.bash" diff --git a/test/fixtures/bats/load_path/with_loader/a-file.bash b/test/fixtures/bats/load_path/with_loader/a-file.bash new file mode 100644 index 00000000..12fbd141 --- /dev/null +++ b/test/fixtures/bats/load_path/with_loader/a-file.bash @@ -0,0 +1,3 @@ +with_loader() { + true +} From e96502c7ffa3e6652f9408750b40e002111aa3cc Mon Sep 17 00:00:00 2001 From: Nelo Wallus Date: Wed, 22 Mar 2017 19:49:49 +0100 Subject: [PATCH 41/41] Source all files of a library if no loading file exists --- libexec/bats-exec-test | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-) diff --git a/libexec/bats-exec-test b/libexec/bats-exec-test index f5736f16..b88d4609 100755 --- a/libexec/bats-exec-test +++ b/libexec/bats-exec-test @@ -52,15 +52,24 @@ load() { local libpath="${BATS_LIB_PATH:-$HOME/.bats/lib:/usr/lib/bats}" libpath="$BATS_TEST_DIRNAME:$libpath" - # Test for library file in each libpath, source and return if it - # exists - for part in ${libpath//:/ }; do - filename="$part/$name.bash" + # Test for library in each libpath + for libdir in ${libpath//:/ }; do + dirname="$libdir/$name" + filename="$dirname.bash" + # Test for loading file of library if [[ -f "$filename" ]]; then source "$filename" return fi + + # Test for library and source all files within + if [[ -d "$dirname" ]]; then + for libfile in $dirname/*.bash; do + source $libfile + done + return + fi done echo "bats: No file $name in BATS_LIB_PATH found" >&2