Vendoring bats libraries.
Signed-off-by: Chad Metcalf <chad@docker.com>
This commit is contained in:
parent
5185cedf4e
commit
6565a1f745
4
lib/bats-assert/.gitignore
vendored
Normal file
4
lib/bats-assert/.gitignore
vendored
Normal file
@ -0,0 +1,4 @@
|
||||
/node_modules
|
||||
/package-lock.json
|
||||
/yarn.lock
|
||||
/bats-assert-*.tgz
|
3
lib/bats-assert/.travis.yml
Normal file
3
lib/bats-assert/.travis.yml
Normal file
@ -0,0 +1,3 @@
|
||||
language: node_js
|
||||
node_js: node
|
||||
cache: npm
|
116
lib/bats-assert/LICENSE
Normal file
116
lib/bats-assert/LICENSE
Normal file
@ -0,0 +1,116 @@
|
||||
CC0 1.0 Universal
|
||||
|
||||
Statement of Purpose
|
||||
|
||||
The laws of most jurisdictions throughout the world automatically confer
|
||||
exclusive Copyright and Related Rights (defined below) upon the creator and
|
||||
subsequent owner(s) (each and all, an "owner") of an original work of
|
||||
authorship and/or a database (each, a "Work").
|
||||
|
||||
Certain owners wish to permanently relinquish those rights to a Work for the
|
||||
purpose of contributing to a commons of creative, cultural and scientific
|
||||
works ("Commons") that the public can reliably and without fear of later
|
||||
claims of infringement build upon, modify, incorporate in other works, reuse
|
||||
and redistribute as freely as possible in any form whatsoever and for any
|
||||
purposes, including without limitation commercial purposes. These owners may
|
||||
contribute to the Commons to promote the ideal of a free culture and the
|
||||
further production of creative, cultural and scientific works, or to gain
|
||||
reputation or greater distribution for their Work in part through the use and
|
||||
efforts of others.
|
||||
|
||||
For these and/or other purposes and motivations, and without any expectation
|
||||
of additional consideration or compensation, the person associating CC0 with a
|
||||
Work (the "Affirmer"), to the extent that he or she is an owner of Copyright
|
||||
and Related Rights in the Work, voluntarily elects to apply CC0 to the Work
|
||||
and publicly distribute the Work under its terms, with knowledge of his or her
|
||||
Copyright and Related Rights in the Work and the meaning and intended legal
|
||||
effect of CC0 on those rights.
|
||||
|
||||
1. Copyright and Related Rights. A Work made available under CC0 may be
|
||||
protected by copyright and related or neighboring rights ("Copyright and
|
||||
Related Rights"). Copyright and Related Rights include, but are not limited
|
||||
to, the following:
|
||||
|
||||
i. the right to reproduce, adapt, distribute, perform, display, communicate,
|
||||
and translate a Work;
|
||||
|
||||
ii. moral rights retained by the original author(s) and/or performer(s);
|
||||
|
||||
iii. publicity and privacy rights pertaining to a person's image or likeness
|
||||
depicted in a Work;
|
||||
|
||||
iv. rights protecting against unfair competition in regards to a Work,
|
||||
subject to the limitations in paragraph 4(a), below;
|
||||
|
||||
v. rights protecting the extraction, dissemination, use and reuse of data in
|
||||
a Work;
|
||||
|
||||
vi. database rights (such as those arising under Directive 96/9/EC of the
|
||||
European Parliament and of the Council of 11 March 1996 on the legal
|
||||
protection of databases, and under any national implementation thereof,
|
||||
including any amended or successor version of such directive); and
|
||||
|
||||
vii. other similar, equivalent or corresponding rights throughout the world
|
||||
based on applicable law or treaty, and any national implementations thereof.
|
||||
|
||||
2. Waiver. To the greatest extent permitted by, but not in contravention of,
|
||||
applicable law, Affirmer hereby overtly, fully, permanently, irrevocably and
|
||||
unconditionally waives, abandons, and surrenders all of Affirmer's Copyright
|
||||
and Related Rights and associated claims and causes of action, whether now
|
||||
known or unknown (including existing as well as future claims and causes of
|
||||
action), in the Work (i) in all territories worldwide, (ii) for the maximum
|
||||
duration provided by applicable law or treaty (including future time
|
||||
extensions), (iii) in any current or future medium and for any number of
|
||||
copies, and (iv) for any purpose whatsoever, including without limitation
|
||||
commercial, advertising or promotional purposes (the "Waiver"). Affirmer makes
|
||||
the Waiver for the benefit of each member of the public at large and to the
|
||||
detriment of Affirmer's heirs and successors, fully intending that such Waiver
|
||||
shall not be subject to revocation, rescission, cancellation, termination, or
|
||||
any other legal or equitable action to disrupt the quiet enjoyment of the Work
|
||||
by the public as contemplated by Affirmer's express Statement of Purpose.
|
||||
|
||||
3. Public License Fallback. Should any part of the Waiver for any reason be
|
||||
judged legally invalid or ineffective under applicable law, then the Waiver
|
||||
shall be preserved to the maximum extent permitted taking into account
|
||||
Affirmer's express Statement of Purpose. In addition, to the extent the Waiver
|
||||
is so judged Affirmer hereby grants to each affected person a royalty-free,
|
||||
non transferable, non sublicensable, non exclusive, irrevocable and
|
||||
unconditional license to exercise Affirmer's Copyright and Related Rights in
|
||||
the Work (i) in all territories worldwide, (ii) for the maximum duration
|
||||
provided by applicable law or treaty (including future time extensions), (iii)
|
||||
in any current or future medium and for any number of copies, and (iv) for any
|
||||
purpose whatsoever, including without limitation commercial, advertising or
|
||||
promotional purposes (the "License"). The License shall be deemed effective as
|
||||
of the date CC0 was applied by Affirmer to the Work. Should any part of the
|
||||
License for any reason be judged legally invalid or ineffective under
|
||||
applicable law, such partial invalidity or ineffectiveness shall not
|
||||
invalidate the remainder of the License, and in such case Affirmer hereby
|
||||
affirms that he or she will not (i) exercise any of his or her remaining
|
||||
Copyright and Related Rights in the Work or (ii) assert any associated claims
|
||||
and causes of action with respect to the Work, in either case contrary to
|
||||
Affirmer's express Statement of Purpose.
|
||||
|
||||
4. Limitations and Disclaimers.
|
||||
|
||||
a. No trademark or patent rights held by Affirmer are waived, abandoned,
|
||||
surrendered, licensed or otherwise affected by this document.
|
||||
|
||||
b. Affirmer offers the Work as-is and makes no representations or warranties
|
||||
of any kind concerning the Work, express, implied, statutory or otherwise,
|
||||
including without limitation warranties of title, merchantability, fitness
|
||||
for a particular purpose, non infringement, or the absence of latent or
|
||||
other defects, accuracy, or the present or absence of errors, whether or not
|
||||
discoverable, all to the greatest extent permissible under applicable law.
|
||||
|
||||
c. Affirmer disclaims responsibility for clearing rights of other persons
|
||||
that may apply to the Work or any use thereof, including without limitation
|
||||
any person's Copyright and Related Rights in the Work. Further, Affirmer
|
||||
disclaims responsibility for obtaining any necessary consents, permissions
|
||||
or other rights required for any use of the Work.
|
||||
|
||||
d. Affirmer understands and acknowledges that Creative Commons is not a
|
||||
party to this document and has no duty or obligation with respect to this
|
||||
CC0 or use of the Work.
|
||||
|
||||
For more information, please see
|
||||
<http://creativecommons.org/publicdomain/zero/1.0/>
|
661
lib/bats-assert/README.md
Normal file
661
lib/bats-assert/README.md
Normal file
@ -0,0 +1,661 @@
|
||||
# bats-assert
|
||||
|
||||
[](https://github.com/bats-core/bats-assert/blob/master/LICENSE)
|
||||
[](https://github.com/bats-core/bats-assert/releases/latest)
|
||||
[](https://www.npmjs.com/package/bats-assert)
|
||||
[](https://travis-ci.org/bats-core/bats-assert)
|
||||
|
||||
`bats-assert` is a helper library providing common assertions for [Bats][bats].
|
||||
|
||||
Assertions are functions that perform a test and output relevant information on failure to help debugging.
|
||||
They return 1 on failure and 0 otherwise.
|
||||
Output, [formatted][bats-support-output] for readability, is sent to the standard error to make assertions usable outside of `@test` blocks too.
|
||||
|
||||
Assertions testing exit code and output operate on the results of the most recent invocation of `run`.
|
||||
|
||||
Dependencies:
|
||||
- [`bats-support`][bats-support] (formerly `bats-core`) - output formatting
|
||||
|
||||
See the [shared documentation][bats-docs] to learn how to install and load this library.
|
||||
|
||||
|
||||
## Usage
|
||||
|
||||
### `assert`
|
||||
|
||||
Fail if the given expression evaluates to false.
|
||||
|
||||
***Note:***
|
||||
*The expression must be a simple command.
|
||||
[Compound commands][bash-comp-cmd], such as `[[`, can be used only when executed with `bash -c`.*
|
||||
|
||||
```bash
|
||||
@test 'assert()' {
|
||||
touch '/var/log/test.log'
|
||||
assert [ -e '/var/log/test.log' ]
|
||||
}
|
||||
```
|
||||
|
||||
On failure, the failed expression is displayed.
|
||||
|
||||
```
|
||||
-- assertion failed --
|
||||
expression : [ -e /var/log/test.log ]
|
||||
--
|
||||
```
|
||||
|
||||
|
||||
### `refute`
|
||||
|
||||
Fail if the given expression evaluates to true.
|
||||
|
||||
***Note:***
|
||||
*The expression must be a simple command.
|
||||
[Compound commands][bash-comp-cmd], such as `[[`, can be used only when executed with `bash -c`.*
|
||||
|
||||
```bash
|
||||
@test 'refute()' {
|
||||
rm -f '/var/log/test.log'
|
||||
refute [ -e '/var/log/test.log' ]
|
||||
}
|
||||
```
|
||||
|
||||
On failure, the successful expression is displayed.
|
||||
|
||||
```
|
||||
-- assertion succeeded, but it was expected to fail --
|
||||
expression : [ -e /var/log/test.log ]
|
||||
--
|
||||
```
|
||||
|
||||
|
||||
### `assert_equal`
|
||||
|
||||
Fail if the two parameters, actual and expected value respectively, do not equal.
|
||||
|
||||
```bash
|
||||
@test 'assert_equal()' {
|
||||
assert_equal 'have' 'want'
|
||||
}
|
||||
```
|
||||
|
||||
On failure, the expected and actual values are displayed.
|
||||
|
||||
```
|
||||
-- values do not equal --
|
||||
expected : want
|
||||
actual : have
|
||||
--
|
||||
```
|
||||
|
||||
If either value is longer than one line both are displayed in *multi-line* format.
|
||||
|
||||
|
||||
### `assert_success`
|
||||
|
||||
Fail if `$status` is not 0.
|
||||
|
||||
```bash
|
||||
@test 'assert_success() status only' {
|
||||
run bash -c "echo 'Error!'; exit 1"
|
||||
assert_success
|
||||
}
|
||||
```
|
||||
|
||||
On failure, `$status` and `$output` are displayed.
|
||||
|
||||
```
|
||||
-- command failed --
|
||||
status : 1
|
||||
output : Error!
|
||||
--
|
||||
```
|
||||
|
||||
If `$output` is longer than one line, it is displayed in *multi-line* format.
|
||||
|
||||
|
||||
### `assert_failure`
|
||||
|
||||
Fail if `$status` is 0.
|
||||
|
||||
```bash
|
||||
@test 'assert_failure() status only' {
|
||||
run echo 'Success!'
|
||||
assert_failure
|
||||
}
|
||||
```
|
||||
|
||||
On failure, `$output` is displayed.
|
||||
|
||||
```
|
||||
-- command succeeded, but it was expected to fail --
|
||||
output : Success!
|
||||
--
|
||||
```
|
||||
|
||||
If `$output` is longer than one line, it is displayed in *multi-line* format.
|
||||
|
||||
#### Expected status
|
||||
|
||||
When one parameter is specified, fail if `$status` does not equal the expected status specified by the parameter.
|
||||
|
||||
```bash
|
||||
@test 'assert_failure() with expected status' {
|
||||
run bash -c "echo 'Error!'; exit 1"
|
||||
assert_failure 2
|
||||
}
|
||||
```
|
||||
|
||||
On failure, the expected and actual status, and `$output` are displayed.
|
||||
|
||||
```
|
||||
-- command failed as expected, but status differs --
|
||||
expected : 2
|
||||
actual : 1
|
||||
output : Error!
|
||||
--
|
||||
```
|
||||
|
||||
If `$output` is longer than one line, it is displayed in *multi-line* format.
|
||||
|
||||
|
||||
### `assert_output`
|
||||
|
||||
This function helps to verify that a command or function produces the correct output by checking that the specified expected output matches the actual output.
|
||||
Matching can be literal (default), partial or regular expression.
|
||||
This function is the logical complement of `refute_output`.
|
||||
|
||||
#### Literal matching
|
||||
|
||||
By default, literal matching is performed.
|
||||
The assertion fails if `$output` does not equal the expected output.
|
||||
|
||||
```bash
|
||||
@test 'assert_output()' {
|
||||
run echo 'have'
|
||||
assert_output 'want'
|
||||
}
|
||||
```
|
||||
|
||||
On failure, the expected and actual output are displayed.
|
||||
|
||||
```
|
||||
-- output differs --
|
||||
expected : want
|
||||
actual : have
|
||||
--
|
||||
```
|
||||
|
||||
If either value is longer than one line both are displayed in *multi-line* format.
|
||||
|
||||
#### Existence
|
||||
|
||||
To assert that any (non-empty) output exists at all, simply omit the matching argument.
|
||||
|
||||
```bash
|
||||
@test 'assert_output()' {
|
||||
run echo 'have'
|
||||
assert_output
|
||||
}
|
||||
```
|
||||
|
||||
On failure, an error message is displayed.
|
||||
|
||||
```
|
||||
-- no output --
|
||||
expected non-empty output, but output was empty
|
||||
--
|
||||
```
|
||||
|
||||
#### Partial matching
|
||||
|
||||
Partial matching can be enabled with the `--partial` option (`-p` for short).
|
||||
When used, the assertion fails if the expected *substring* is not found in `$output`.
|
||||
|
||||
```bash
|
||||
@test 'assert_output() partial matching' {
|
||||
run echo 'ERROR: no such file or directory'
|
||||
assert_output --partial 'SUCCESS'
|
||||
}
|
||||
```
|
||||
|
||||
On failure, the substring and the output are displayed.
|
||||
|
||||
```
|
||||
-- output does not contain substring --
|
||||
substring : SUCCESS
|
||||
output : ERROR: no such file or directory
|
||||
--
|
||||
```
|
||||
|
||||
This option and regular expression matching (`--regexp` or `-e`) are mutually exclusive.
|
||||
An error is displayed when used simultaneously.
|
||||
|
||||
#### Regular expression matching
|
||||
|
||||
Regular expression matching can be enabled with the `--regexp` option (`-e` for short).
|
||||
When used, the assertion fails if the *extended regular expression* does not match `$output`.
|
||||
|
||||
*Note: The anchors `^` and `$` bind to the beginning and the end of the entire output (not individual lines), respectively.*
|
||||
|
||||
```bash
|
||||
@test 'assert_output() regular expression matching' {
|
||||
run echo 'Foobar 0.1.0'
|
||||
assert_output --regexp '^Foobar v[0-9]+\.[0-9]+\.[0-9]$'
|
||||
}
|
||||
```
|
||||
|
||||
On failure, the regular expression and the output are displayed.
|
||||
|
||||
```
|
||||
-- regular expression does not match output --
|
||||
regexp : ^Foobar v[0-9]+\.[0-9]+\.[0-9]$
|
||||
output : Foobar 0.1.0
|
||||
--
|
||||
```
|
||||
|
||||
An error is displayed if the specified extended regular expression is invalid.
|
||||
|
||||
This option and partial matching (`--partial` or `-p`) are mutually exclusive.
|
||||
An error is displayed when used simultaneously.
|
||||
|
||||
#### Standard Input, HereDocs and HereStrings
|
||||
|
||||
The expected output can be specified via standard input (also heredoc/herestring) with the `-`/`--stdin` option.
|
||||
|
||||
```bash
|
||||
@test 'assert_output() with pipe' {
|
||||
run echo 'hello'
|
||||
echo 'hello' | assert_output -
|
||||
}
|
||||
|
||||
@test 'assert_output() with herestring' {
|
||||
run echo 'hello'
|
||||
assert_output - <<< hello
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
### `refute_output`
|
||||
|
||||
This function helps to verify that a command or function produces the correct output by checking that the specified unexpected output does not match the actual output.
|
||||
Matching can be literal (default), partial or regular expression.
|
||||
This function is the logical complement of `assert_output`.
|
||||
|
||||
#### Literal matching
|
||||
|
||||
By default, literal matching is performed.
|
||||
The assertion fails if `$output` equals the unexpected output.
|
||||
|
||||
```bash
|
||||
@test 'refute_output()' {
|
||||
run echo 'want'
|
||||
refute_output 'want'
|
||||
}
|
||||
```
|
||||
|
||||
On failure, the output is displayed.
|
||||
|
||||
```
|
||||
-- output equals, but it was expected to differ --
|
||||
output : want
|
||||
--
|
||||
```
|
||||
|
||||
If output is longer than one line it is displayed in *multi-line* format.
|
||||
|
||||
#### Existence
|
||||
|
||||
To assert that there is no output at all, simply omit the matching argument.
|
||||
|
||||
```bash
|
||||
@test 'refute_output()' {
|
||||
run foo --silent
|
||||
refute_output
|
||||
}
|
||||
```
|
||||
|
||||
On failure, an error message is displayed.
|
||||
|
||||
```
|
||||
-- unexpected output --
|
||||
expected no output, but output was non-empty
|
||||
--
|
||||
```
|
||||
|
||||
#### Partial matching
|
||||
|
||||
Partial matching can be enabled with the `--partial` option (`-p` for short).
|
||||
When used, the assertion fails if the unexpected *substring* is found in `$output`.
|
||||
|
||||
```bash
|
||||
@test 'refute_output() partial matching' {
|
||||
run echo 'ERROR: no such file or directory'
|
||||
refute_output --partial 'ERROR'
|
||||
}
|
||||
```
|
||||
|
||||
On failure, the substring and the output are displayed.
|
||||
|
||||
```
|
||||
-- output should not contain substring --
|
||||
substring : ERROR
|
||||
output : ERROR: no such file or directory
|
||||
--
|
||||
```
|
||||
|
||||
This option and regular expression matching (`--regexp` or `-e`) are mutually exclusive.
|
||||
An error is displayed when used simultaneously.
|
||||
|
||||
#### Regular expression matching
|
||||
|
||||
Regular expression matching can be enabled with the `--regexp` option (`-e` for short).
|
||||
When used, the assertion fails if the *extended regular expression* matches `$output`.
|
||||
|
||||
*Note: The anchors `^` and `$` bind to the beginning and the end of the entire output (not individual lines), respectively.*
|
||||
|
||||
```bash
|
||||
@test 'refute_output() regular expression matching' {
|
||||
run echo 'Foobar v0.1.0'
|
||||
refute_output --regexp '^Foobar v[0-9]+\.[0-9]+\.[0-9]$'
|
||||
}
|
||||
```
|
||||
|
||||
On failure, the regular expression and the output are displayed.
|
||||
|
||||
```
|
||||
-- regular expression should not match output --
|
||||
regexp : ^Foobar v[0-9]+\.[0-9]+\.[0-9]$
|
||||
output : Foobar v0.1.0
|
||||
--
|
||||
```
|
||||
|
||||
An error is displayed if the specified extended regular expression is invalid.
|
||||
|
||||
This option and partial matching (`--partial` or `-p`) are mutually exclusive.
|
||||
An error is displayed when used simultaneously.
|
||||
|
||||
#### Standard Input, HereDocs and HereStrings
|
||||
|
||||
The unexpected output can be specified via standard input (also heredoc/herestring) with the `-`/`--stdin` option.
|
||||
|
||||
```bash
|
||||
@test 'refute_output() with pipe' {
|
||||
run echo 'hello'
|
||||
echo 'world' | refute_output -
|
||||
}
|
||||
|
||||
@test 'refute_output() with herestring' {
|
||||
run echo 'hello'
|
||||
refute_output - <<< world
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
### `assert_line`
|
||||
|
||||
Similarly to `assert_output`, this function helps to verify that a command or function produces the correct output.
|
||||
It checks that the expected line appears in the output (default) or in a specific line of it.
|
||||
Matching can be literal (default), partial or regular expression.
|
||||
This function is the logical complement of `refute_line`.
|
||||
|
||||
***Warning:***
|
||||
*Due to a [bug in Bats][bats-93], empty lines are discarded from `${lines[@]}`, causing line indices to change and preventing testing for empty lines.*
|
||||
|
||||
[bats-93]: https://github.com/sstephenson/bats/pull/93
|
||||
|
||||
#### Looking for a line in the output
|
||||
|
||||
By default, the entire output is searched for the expected line.
|
||||
The assertion fails if the expected line is not found in `${lines[@]}`.
|
||||
|
||||
```bash
|
||||
@test 'assert_line() looking for line' {
|
||||
run echo $'have-0\nhave-1\nhave-2'
|
||||
assert_line 'want'
|
||||
}
|
||||
```
|
||||
|
||||
On failure, the expected line and the output are displayed.
|
||||
|
||||
***Warning:***
|
||||
*The output displayed does not contain empty lines.
|
||||
See the Warning above for more.*
|
||||
|
||||
```
|
||||
-- output does not contain line --
|
||||
line : want
|
||||
output (3 lines):
|
||||
have-0
|
||||
have-1
|
||||
have-2
|
||||
--
|
||||
```
|
||||
|
||||
If output is not longer than one line, it is displayed in *two-column* format.
|
||||
|
||||
#### Matching a specific line
|
||||
|
||||
When the `--index <idx>` option is used (`-n <idx>` for short), the expected line is matched only against the line identified by the given index.
|
||||
The assertion fails if the expected line does not equal `${lines[<idx>]}`.
|
||||
|
||||
```bash
|
||||
@test 'assert_line() specific line' {
|
||||
run echo $'have-0\nhave-1\nhave-2'
|
||||
assert_line --index 1 'want-1'
|
||||
}
|
||||
```
|
||||
|
||||
On failure, the index and the compared lines are displayed.
|
||||
|
||||
```
|
||||
-- line differs --
|
||||
index : 1
|
||||
expected : want-1
|
||||
actual : have-1
|
||||
--
|
||||
```
|
||||
|
||||
#### Partial matching
|
||||
|
||||
Partial matching can be enabled with the `--partial` option (`-p` for short).
|
||||
When used, a match fails if the expected *substring* is not found in the matched line.
|
||||
|
||||
```bash
|
||||
@test 'assert_line() partial matching' {
|
||||
run echo $'have 1\nhave 2\nhave 3'
|
||||
assert_line --partial 'want'
|
||||
}
|
||||
```
|
||||
|
||||
On failure, the same details are displayed as for literal matching, except that the substring replaces the expected line.
|
||||
|
||||
```
|
||||
-- no output line contains substring --
|
||||
substring : want
|
||||
output (3 lines):
|
||||
have 1
|
||||
have 2
|
||||
have 3
|
||||
--
|
||||
```
|
||||
|
||||
This option and regular expression matching (`--regexp` or `-e`) are mutually exclusive.
|
||||
An error is displayed when used simultaneously.
|
||||
|
||||
#### Regular expression matching
|
||||
|
||||
Regular expression matching can be enabled with the `--regexp` option (`-e` for short).
|
||||
When used, a match fails if the *extended regular expression* does not match the line being tested.
|
||||
|
||||
*Note: As expected, the anchors `^` and `$` bind to the beginning and the end of the matched line, respectively.*
|
||||
|
||||
```bash
|
||||
@test 'assert_line() regular expression matching' {
|
||||
run echo $'have-0\nhave-1\nhave-2'
|
||||
assert_line --index 1 --regexp '^want-[0-9]$'
|
||||
}
|
||||
```
|
||||
|
||||
On failure, the same details are displayed as for literal matching, except that the regular expression replaces the expected line.
|
||||
|
||||
```
|
||||
-- regular expression does not match line --
|
||||
index : 1
|
||||
regexp : ^want-[0-9]$
|
||||
line : have-1
|
||||
--
|
||||
```
|
||||
|
||||
An error is displayed if the specified extended regular expression is invalid.
|
||||
|
||||
This option and partial matching (`--partial` or `-p`) are mutually exclusive.
|
||||
An error is displayed when used simultaneously.
|
||||
|
||||
|
||||
### `refute_line`
|
||||
|
||||
Similarly to `refute_output`, this function helps to verify that a command or function produces the correct output.
|
||||
It checks that the unexpected line does not appear in the output (default) or in a specific line of it.
|
||||
Matching can be literal (default), partial or regular expression.
|
||||
This function is the logical complement of `assert_line`.
|
||||
|
||||
***Warning:***
|
||||
*Due to a [bug in Bats][bats-93], empty lines are discarded from `${lines[@]}`, causing line indices to change and preventing testing for empty lines.*
|
||||
|
||||
[bats-93]: https://github.com/sstephenson/bats/pull/93
|
||||
|
||||
#### Looking for a line in the output
|
||||
|
||||
By default, the entire output is searched for the unexpected line.
|
||||
The assertion fails if the unexpected line is found in `${lines[@]}`.
|
||||
|
||||
```bash
|
||||
@test 'refute_line() looking for line' {
|
||||
run echo $'have-0\nwant\nhave-2'
|
||||
refute_line 'want'
|
||||
}
|
||||
```
|
||||
|
||||
On failure, the unexpected line, the index of its first match and the output with the matching line highlighted are displayed.
|
||||
|
||||
***Warning:***
|
||||
*The output displayed does not contain empty lines.
|
||||
See the Warning above for more.*
|
||||
|
||||
```
|
||||
-- line should not be in output --
|
||||
line : want
|
||||
index : 1
|
||||
output (3 lines):
|
||||
have-0
|
||||
> want
|
||||
have-2
|
||||
--
|
||||
```
|
||||
|
||||
If output is not longer than one line, it is displayed in *two-column* format.
|
||||
|
||||
#### Matching a specific line
|
||||
|
||||
When the `--index <idx>` option is used (`-n <idx>` for short), the unexpected line is matched only against the line identified by the given index.
|
||||
The assertion fails if the unexpected line equals `${lines[<idx>]}`.
|
||||
|
||||
```bash
|
||||
@test 'refute_line() specific line' {
|
||||
run echo $'have-0\nwant-1\nhave-2'
|
||||
refute_line --index 1 'want-1'
|
||||
}
|
||||
```
|
||||
|
||||
On failure, the index and the unexpected line are displayed.
|
||||
|
||||
```
|
||||
-- line should differ --
|
||||
index : 1
|
||||
line : want-1
|
||||
--
|
||||
```
|
||||
|
||||
#### Partial matching
|
||||
|
||||
Partial matching can be enabled with the `--partial` option (`-p` for short).
|
||||
When used, a match fails if the unexpected *substring* is found in the matched line.
|
||||
|
||||
```bash
|
||||
@test 'refute_line() partial matching' {
|
||||
run echo $'have 1\nwant 2\nhave 3'
|
||||
refute_line --partial 'want'
|
||||
}
|
||||
```
|
||||
|
||||
On failure, in addition to the details of literal matching, the substring is also displayed.
|
||||
When used with `--index <idx>` the substring replaces the unexpected line.
|
||||
|
||||
```
|
||||
-- no line should contain substring --
|
||||
substring : want
|
||||
index : 1
|
||||
output (3 lines):
|
||||
have 1
|
||||
> want 2
|
||||
have 3
|
||||
--
|
||||
```
|
||||
|
||||
This option and regular expression matching (`--regexp` or `-e`) are mutually exclusive.
|
||||
An error is displayed when used simultaneously.
|
||||
|
||||
#### Regular expression matching
|
||||
|
||||
Regular expression matching can be enabled with the `--regexp` option (`-e` for short).
|
||||
When used, a match fails if the *extended regular expression* matches the line being tested.
|
||||
|
||||
*Note: As expected, the anchors `^` and `$` bind to the beginning and the end of the matched line, respectively.*
|
||||
|
||||
```bash
|
||||
@test 'refute_line() regular expression matching' {
|
||||
run echo $'Foobar v0.1.0\nRelease date: 2015-11-29'
|
||||
refute_line --index 0 --regexp '^Foobar v[0-9]+\.[0-9]+\.[0-9]$'
|
||||
}
|
||||
```
|
||||
|
||||
On failure, in addition to the details of literal matching, the regular expression is also displayed.
|
||||
When used with `--index <idx>` the regular expression replaces the unexpected line.
|
||||
|
||||
```
|
||||
-- regular expression should not match line --
|
||||
index : 0
|
||||
regexp : ^Foobar v[0-9]+\.[0-9]+\.[0-9]$
|
||||
line : Foobar v0.1.0
|
||||
--
|
||||
```
|
||||
|
||||
An error is displayed if the specified extended regular expression is invalid.
|
||||
|
||||
This option and partial matching (`--partial` or `-p`) are mutually exclusive.
|
||||
An error is displayed when used simultaneously.
|
||||
|
||||
|
||||
## Options
|
||||
|
||||
For functions that have options, `--` disables option parsing for the remaining arguments to allow using arguments identical to one of the allowed options.
|
||||
|
||||
```bash
|
||||
assert_output -- '-p'
|
||||
```
|
||||
|
||||
Specifying `--` as an argument is similarly simple.
|
||||
|
||||
```bash
|
||||
refute_line -- '--'
|
||||
```
|
||||
|
||||
|
||||
<!-- REFERENCES -->
|
||||
|
||||
[bats]: https://github.com/sstephenson/bats
|
||||
[bats-support-output]: https://github.com/ztombol/bats-support#output-formatting
|
||||
[bats-support]: https://github.com/ztombol/bats-support
|
||||
[bats-docs]: https://github.com/ztombol/bats-docs
|
||||
[bash-comp-cmd]: https://www.gnu.org/software/bash/manual/bash.html#Compound-Commands
|
30
lib/bats-assert/load.bash
Normal file
30
lib/bats-assert/load.bash
Normal file
@ -0,0 +1,30 @@
|
||||
# bats-assert - Common assertions for Bats
|
||||
#
|
||||
# Written in 2016 by Zoltan Tombol <zoltan dot tombol at gmail dot com>
|
||||
#
|
||||
# To the extent possible under law, the author(s) have dedicated all
|
||||
# copyright and related and neighboring rights to this software to the
|
||||
# public domain worldwide. This software is distributed without any
|
||||
# warranty.
|
||||
#
|
||||
# You should have received a copy of the CC0 Public Domain Dedication
|
||||
# along with this software. If not, see
|
||||
# <http://creativecommons.org/publicdomain/zero/1.0/>.
|
||||
#
|
||||
# Assertions are functions that perform a test and output relevant
|
||||
# information on failure to help debugging. They return 1 on failure
|
||||
# and 0 otherwise.
|
||||
#
|
||||
# All output is formatted for readability using the functions of
|
||||
# `output.bash' and sent to the standard error.
|
||||
|
||||
# shellcheck disable=1090
|
||||
source "$(dirname "${BASH_SOURCE[0]}")/src/assert.bash"
|
||||
source "$(dirname "${BASH_SOURCE[0]}")/src/refute.bash"
|
||||
source "$(dirname "${BASH_SOURCE[0]}")/src/assert_equal.bash"
|
||||
source "$(dirname "${BASH_SOURCE[0]}")/src/assert_success.bash"
|
||||
source "$(dirname "${BASH_SOURCE[0]}")/src/assert_failure.bash"
|
||||
source "$(dirname "${BASH_SOURCE[0]}")/src/assert_output.bash"
|
||||
source "$(dirname "${BASH_SOURCE[0]}")/src/refute_output.bash"
|
||||
source "$(dirname "${BASH_SOURCE[0]}")/src/assert_line.bash"
|
||||
source "$(dirname "${BASH_SOURCE[0]}")/src/refute_line.bash"
|
48
lib/bats-assert/package.json
Normal file
48
lib/bats-assert/package.json
Normal file
@ -0,0 +1,48 @@
|
||||
{
|
||||
"name": "bats-assert",
|
||||
"version": "2.0.0",
|
||||
"description": "Common assertions for Bats",
|
||||
"homepage": "https://github.com/jasonkarns/bats-assert-1",
|
||||
"license": "CC0-1.0",
|
||||
"author": "Zoltán Tömböl (https://github.com/ztombol)",
|
||||
"contributors": [
|
||||
"Sam Stephenson <sstephenson@gmail.com> (http://sstephenson.us/)",
|
||||
"Jason Karns <jason.karns@gmail.com> (http://jason.karns.name)",
|
||||
"Mislav Marohnić <mislav.marohnic@gmail.com> (http://mislav.net/)",
|
||||
"Tim Pope (https://github.com/tpope)"
|
||||
],
|
||||
"repository": "github:jasonkarns/bats-assert-1",
|
||||
"bugs": "https://github.com/jasonkarns/bats-assert-1/issues",
|
||||
"directories": {
|
||||
"lib": "src",
|
||||
"test": "test"
|
||||
},
|
||||
"files": [
|
||||
"load.bash",
|
||||
"src"
|
||||
],
|
||||
"scripts": {
|
||||
"test": "bats ${CI+-t} test",
|
||||
"postversion": "npm publish",
|
||||
"prepublishOnly": "npm run publish:github",
|
||||
"publish:github": "git push --follow-tags"
|
||||
},
|
||||
"devDependencies": {
|
||||
"bats": "^1",
|
||||
"bats-support": "^0.3"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"bats": "0.4 || ^1",
|
||||
"bats-support": "^0.3"
|
||||
},
|
||||
"keywords": [
|
||||
"bats",
|
||||
"bash",
|
||||
"shell",
|
||||
"test",
|
||||
"unit",
|
||||
"assert",
|
||||
"assertion",
|
||||
"helper"
|
||||
]
|
||||
}
|
42
lib/bats-assert/src/assert.bash
Normal file
42
lib/bats-assert/src/assert.bash
Normal file
@ -0,0 +1,42 @@
|
||||
# assert
|
||||
# ======
|
||||
#
|
||||
# Summary: Fail if the given expression evaluates to false.
|
||||
#
|
||||
# Usage: assert <expression>
|
||||
|
||||
# Options:
|
||||
# <expression> The expression to evaluate for truthiness.
|
||||
# *__Note:__ The expression must be a simple command.
|
||||
# [Compound commands](https://www.gnu.org/software/bash/manual/bash.html#Compound-Commands),
|
||||
# such as `[[`, can be used only when executed with `bash -c`.*
|
||||
#
|
||||
# IO:
|
||||
# STDERR - the failed expression, on failure
|
||||
# Globals:
|
||||
# none
|
||||
# Returns:
|
||||
# 0 - if expression evaluates to true
|
||||
# 1 - otherwise
|
||||
#
|
||||
# ```bash
|
||||
# @test 'assert()' {
|
||||
# touch '/var/log/test.log'
|
||||
# assert [ -e '/var/log/test.log' ]
|
||||
# }
|
||||
# ```
|
||||
#
|
||||
# On failure, the failed expression is displayed.
|
||||
#
|
||||
# ```
|
||||
# -- assertion failed --
|
||||
# expression : [ -e /var/log/test.log ]
|
||||
# --
|
||||
# ```
|
||||
assert() {
|
||||
if ! "$@"; then
|
||||
batslib_print_kv_single 10 'expression' "$*" \
|
||||
| batslib_decorate 'assertion failed' \
|
||||
| fail
|
||||
fi
|
||||
}
|
42
lib/bats-assert/src/assert_equal.bash
Normal file
42
lib/bats-assert/src/assert_equal.bash
Normal file
@ -0,0 +1,42 @@
|
||||
# assert_equal
|
||||
# ============
|
||||
#
|
||||
# Summary: Fail if the actual and expected values are not equal.
|
||||
#
|
||||
# Usage: assert_equal <actual> <expected>
|
||||
#
|
||||
# Options:
|
||||
# <actual> The value being compared.
|
||||
# <expected> The value to compare against.
|
||||
#
|
||||
# ```bash
|
||||
# @test 'assert_equal()' {
|
||||
# assert_equal 'have' 'want'
|
||||
# }
|
||||
# ```
|
||||
#
|
||||
# IO:
|
||||
# STDERR - expected and actual values, on failure
|
||||
# Globals:
|
||||
# none
|
||||
# Returns:
|
||||
# 0 - if values equal
|
||||
# 1 - otherwise
|
||||
#
|
||||
# On failure, the expected and actual values are displayed.
|
||||
#
|
||||
# ```
|
||||
# -- values do not equal --
|
||||
# expected : want
|
||||
# actual : have
|
||||
# --
|
||||
# ```
|
||||
assert_equal() {
|
||||
if [[ $1 != "$2" ]]; then
|
||||
batslib_print_kv_single_or_multi 8 \
|
||||
'expected' "$2" \
|
||||
'actual' "$1" \
|
||||
| batslib_decorate 'values do not equal' \
|
||||
| fail
|
||||
fi
|
||||
}
|
78
lib/bats-assert/src/assert_failure.bash
Normal file
78
lib/bats-assert/src/assert_failure.bash
Normal file
@ -0,0 +1,78 @@
|
||||
# assert_failure
|
||||
# ==============
|
||||
#
|
||||
# Summary: Fail if `$status` is 0; or is not equal to the optionally provided status.
|
||||
#
|
||||
# Usage: assert_failure [<expected_status>]
|
||||
#
|
||||
# Options:
|
||||
# <expected_status> The specific status code to check against.
|
||||
# If not provided, simply asserts status is != 0.
|
||||
#
|
||||
# IO:
|
||||
# STDERR - `$output`, on failure;
|
||||
# - also, `$status` and `expected_status`, if provided
|
||||
# Globals:
|
||||
# status
|
||||
# output
|
||||
# Returns:
|
||||
# 0 - if `$status' is 0,
|
||||
# or if expected_status is provided but does not equal `$status'
|
||||
# 1 - otherwise
|
||||
#
|
||||
# ```bash
|
||||
# @test 'assert_failure() status only' {
|
||||
# run echo 'Success!'
|
||||
# assert_failure
|
||||
# }
|
||||
# ```
|
||||
#
|
||||
# On failure, `$output` is displayed.
|
||||
#
|
||||
# ```
|
||||
# -- command succeeded, but it was expected to fail --
|
||||
# output : Success!
|
||||
# --
|
||||
# ```
|
||||
#
|
||||
# ## Expected status
|
||||
#
|
||||
# When `expected_status` is provided, fail if `$status` does not equal the `expected_status`.
|
||||
#
|
||||
# ```bash
|
||||
# @test 'assert_failure() with expected status' {
|
||||
# run bash -c "echo 'Error!'; exit 1"
|
||||
# assert_failure 2
|
||||
# }
|
||||
# ```
|
||||
#
|
||||
# On failure, both the expected and actual statuses, and `$output` are displayed.
|
||||
#
|
||||
# ```
|
||||
# -- command failed as expected, but status differs --
|
||||
# expected : 2
|
||||
# actual : 1
|
||||
# output : Error!
|
||||
# --
|
||||
# ```
|
||||
assert_failure() {
|
||||
: "${output?}"
|
||||
: "${status?}"
|
||||
|
||||
(( $# > 0 )) && local -r expected="$1"
|
||||
if (( status == 0 )); then
|
||||
batslib_print_kv_single_or_multi 6 'output' "$output" \
|
||||
| batslib_decorate 'command succeeded, but it was expected to fail' \
|
||||
| fail
|
||||
elif (( $# > 0 )) && (( status != expected )); then
|
||||
{ local -ir width=8
|
||||
batslib_print_kv_single "$width" \
|
||||
'expected' "$expected" \
|
||||
'actual' "$status"
|
||||
batslib_print_kv_single_or_multi "$width" \
|
||||
'output' "$output"
|
||||
} \
|
||||
| batslib_decorate 'command failed as expected, but status differs' \
|
||||
| fail
|
||||
fi
|
||||
}
|
248
lib/bats-assert/src/assert_line.bash
Normal file
248
lib/bats-assert/src/assert_line.bash
Normal file
@ -0,0 +1,248 @@
|
||||
# assert_line
|
||||
# ===========
|
||||
#
|
||||
# Summary: Fail if the expected line is not found in the output (default) or at a specific line number.
|
||||
#
|
||||
# Usage: assert_line [-n index] [-p | -e] [--] <expected>
|
||||
#
|
||||
# Options:
|
||||
# -n, --index <idx> Match the <idx>th line
|
||||
# -p, --partial Match if `expected` is a substring of `$output` or line <idx>
|
||||
# -e, --regexp Treat `expected` as an extended regular expression
|
||||
# <expected> The expected line string, substring, or regular expression
|
||||
#
|
||||
# IO:
|
||||
# STDERR - details, on failure
|
||||
# error message, on error
|
||||
# Globals:
|
||||
# output
|
||||
# lines
|
||||
# Returns:
|
||||
# 0 - if matching line found
|
||||
# 1 - otherwise
|
||||
#
|
||||
# Similarly to `assert_output`, this function verifies that a command or function produces the expected output.
|
||||
# (It is the logical complement of `refute_line`.)
|
||||
# It checks that the expected line appears in the output (default) or at a specific line number.
|
||||
# Matching can be literal (default), partial or regular expression.
|
||||
#
|
||||
# *__Warning:__
|
||||
# Due to a [bug in Bats][bats-93], empty lines are discarded from `${lines[@]}`,
|
||||
# causing line indices to change and preventing testing for empty lines.*
|
||||
#
|
||||
# [bats-93]: https://github.com/sstephenson/bats/pull/93
|
||||
#
|
||||
# ## Looking for a line in the output
|
||||
#
|
||||
# By default, the entire output is searched for the expected line.
|
||||
# The assertion fails if the expected line is not found in `${lines[@]}`.
|
||||
#
|
||||
# ```bash
|
||||
# @test 'assert_line() looking for line' {
|
||||
# run echo $'have-0\nhave-1\nhave-2'
|
||||
# assert_line 'want'
|
||||
# }
|
||||
# ```
|
||||
#
|
||||
# On failure, the expected line and the output are displayed.
|
||||
#
|
||||
# ```
|
||||
# -- output does not contain line --
|
||||
# line : want
|
||||
# output (3 lines):
|
||||
# have-0
|
||||
# have-1
|
||||
# have-2
|
||||
# --
|
||||
# ```
|
||||
#
|
||||
# ## Matching a specific line
|
||||
#
|
||||
# When the `--index <idx>` option is used (`-n <idx>` for short), the expected line is matched only against the line identified by the given index.
|
||||
# The assertion fails if the expected line does not equal `${lines[<idx>]}`.
|
||||
#
|
||||
# ```bash
|
||||
# @test 'assert_line() specific line' {
|
||||
# run echo $'have-0\nhave-1\nhave-2'
|
||||
# assert_line --index 1 'want-1'
|
||||
# }
|
||||
# ```
|
||||
#
|
||||
# On failure, the index and the compared lines are displayed.
|
||||
#
|
||||
# ```
|
||||
# -- line differs --
|
||||
# index : 1
|
||||
# expected : want-1
|
||||
# actual : have-1
|
||||
# --
|
||||
# ```
|
||||
#
|
||||
# ## Partial matching
|
||||
#
|
||||
# Partial matching can be enabled with the `--partial` option (`-p` for short).
|
||||
# When used, a match fails if the expected *substring* is not found in the matched line.
|
||||
#
|
||||
# ```bash
|
||||
# @test 'assert_line() partial matching' {
|
||||
# run echo $'have 1\nhave 2\nhave 3'
|
||||
# assert_line --partial 'want'
|
||||
# }
|
||||
# ```
|
||||
#
|
||||
# On failure, the same details are displayed as for literal matching, except that the substring replaces the expected line.
|
||||
#
|
||||
# ```
|
||||
# -- no output line contains substring --
|
||||
# substring : want
|
||||
# output (3 lines):
|
||||
# have 1
|
||||
# have 2
|
||||
# have 3
|
||||
# --
|
||||
# ```
|
||||
#
|
||||
# ## Regular expression matching
|
||||
#
|
||||
# Regular expression matching can be enabled with the `--regexp` option (`-e` for short).
|
||||
# When used, a match fails if the *extended regular expression* does not match the line being tested.
|
||||
#
|
||||
# *__Note__:
|
||||
# As expected, the anchors `^` and `$` bind to the beginning and the end (respectively) of the matched line.*
|
||||
#
|
||||
# ```bash
|
||||
# @test 'assert_line() regular expression matching' {
|
||||
# run echo $'have-0\nhave-1\nhave-2'
|
||||
# assert_line --index 1 --regexp '^want-[0-9]$'
|
||||
# }
|
||||
# ```
|
||||
#
|
||||
# On failure, the same details are displayed as for literal matching, except that the regular expression replaces the expected line.
|
||||
#
|
||||
# ```
|
||||
# -- regular expression does not match line --
|
||||
# index : 1
|
||||
# regexp : ^want-[0-9]$
|
||||
# line : have-1
|
||||
# --
|
||||
# ```
|
||||
# FIXME(ztombol): Display `${lines[@]}' instead of `$output'!
|
||||
assert_line() {
|
||||
local -i is_match_line=0
|
||||
local -i is_mode_partial=0
|
||||
local -i is_mode_regexp=0
|
||||
: "${lines?}"
|
||||
|
||||
# Handle options.
|
||||
while (( $# > 0 )); do
|
||||
case "$1" in
|
||||
-n|--index)
|
||||
if (( $# < 2 )) || ! [[ $2 =~ ^([0-9]|[1-9][0-9]+)$ ]]; then
|
||||
echo "\`--index' requires an integer argument: \`$2'" \
|
||||
| batslib_decorate 'ERROR: assert_line' \
|
||||
| fail
|
||||
return $?
|
||||
fi
|
||||
is_match_line=1
|
||||
local -ri idx="$2"
|
||||
shift 2
|
||||
;;
|
||||
-p|--partial) is_mode_partial=1; shift ;;
|
||||
-e|--regexp) is_mode_regexp=1; shift ;;
|
||||
--) shift; break ;;
|
||||
*) break ;;
|
||||
esac
|
||||
done
|
||||
|
||||
if (( is_mode_partial )) && (( is_mode_regexp )); then
|
||||
echo "\`--partial' and \`--regexp' are mutually exclusive" \
|
||||
| batslib_decorate 'ERROR: assert_line' \
|
||||
| fail
|
||||
return $?
|
||||
fi
|
||||
|
||||
# Arguments.
|
||||
local -r expected="$1"
|
||||
|
||||
if (( is_mode_regexp == 1 )) && [[ '' =~ $expected ]] || (( $? == 2 )); then
|
||||
echo "Invalid extended regular expression: \`$expected'" \
|
||||
| batslib_decorate 'ERROR: assert_line' \
|
||||
| fail
|
||||
return $?
|
||||
fi
|
||||
|
||||
# Matching.
|
||||
if (( is_match_line )); then
|
||||
# Specific line.
|
||||
if (( is_mode_regexp )); then
|
||||
if ! [[ ${lines[$idx]} =~ $expected ]]; then
|
||||
batslib_print_kv_single 6 \
|
||||
'index' "$idx" \
|
||||
'regexp' "$expected" \
|
||||
'line' "${lines[$idx]}" \
|
||||
| batslib_decorate 'regular expression does not match line' \
|
||||
| fail
|
||||
fi
|
||||
elif (( is_mode_partial )); then
|
||||
if [[ ${lines[$idx]} != *"$expected"* ]]; then
|
||||
batslib_print_kv_single 9 \
|
||||
'index' "$idx" \
|
||||
'substring' "$expected" \
|
||||
'line' "${lines[$idx]}" \
|
||||
| batslib_decorate 'line does not contain substring' \
|
||||
| fail
|
||||
fi
|
||||
else
|
||||
if [[ ${lines[$idx]} != "$expected" ]]; then
|
||||
batslib_print_kv_single 8 \
|
||||
'index' "$idx" \
|
||||
'expected' "$expected" \
|
||||
'actual' "${lines[$idx]}" \
|
||||
| batslib_decorate 'line differs' \
|
||||
| fail
|
||||
fi
|
||||
fi
|
||||
else
|
||||
# Contained in output.
|
||||
if (( is_mode_regexp )); then
|
||||
local -i idx
|
||||
for (( idx = 0; idx < ${#lines[@]}; ++idx )); do
|
||||
[[ ${lines[$idx]} =~ $expected ]] && return 0
|
||||
done
|
||||
{ local -ar single=( 'regexp' "$expected" )
|
||||
local -ar may_be_multi=( 'output' "$output" )
|
||||
local -ir width="$( batslib_get_max_single_line_key_width "${single[@]}" "${may_be_multi[@]}" )"
|
||||
batslib_print_kv_single "$width" "${single[@]}"
|
||||
batslib_print_kv_single_or_multi "$width" "${may_be_multi[@]}"
|
||||
} \
|
||||
| batslib_decorate 'no output line matches regular expression' \
|
||||
| fail
|
||||
elif (( is_mode_partial )); then
|
||||
local -i idx
|
||||
for (( idx = 0; idx < ${#lines[@]}; ++idx )); do
|
||||
[[ ${lines[$idx]} == *"$expected"* ]] && return 0
|
||||
done
|
||||
{ local -ar single=( 'substring' "$expected" )
|
||||
local -ar may_be_multi=( 'output' "$output" )
|
||||
local -ir width="$( batslib_get_max_single_line_key_width "${single[@]}" "${may_be_multi[@]}" )"
|
||||
batslib_print_kv_single "$width" "${single[@]}"
|
||||
batslib_print_kv_single_or_multi "$width" "${may_be_multi[@]}"
|
||||
} \
|
||||
| batslib_decorate 'no output line contains substring' \
|
||||
| fail
|
||||
else
|
||||
local -i idx
|
||||
for (( idx = 0; idx < ${#lines[@]}; ++idx )); do
|
||||
[[ ${lines[$idx]} == "$expected" ]] && return 0
|
||||
done
|
||||
{ local -ar single=( 'line' "$expected" )
|
||||
local -ar may_be_multi=( 'output' "$output" )
|
||||
local -ir width="$( batslib_get_max_single_line_key_width "${single[@]}" "${may_be_multi[@]}" )"
|
||||
batslib_print_kv_single "$width" "${single[@]}"
|
||||
batslib_print_kv_single_or_multi "$width" "${may_be_multi[@]}"
|
||||
} \
|
||||
| batslib_decorate 'output does not contain line' \
|
||||
| fail
|
||||
fi
|
||||
fi
|
||||
}
|
197
lib/bats-assert/src/assert_output.bash
Normal file
197
lib/bats-assert/src/assert_output.bash
Normal file
@ -0,0 +1,197 @@
|
||||
# assert_output
|
||||
# =============
|
||||
#
|
||||
# Summary: Fail if `$output' does not match the expected output.
|
||||
#
|
||||
# Usage: assert_output [-p | -e] [- | [--] <expected>]
|
||||
#
|
||||
# Options:
|
||||
# -p, --partial Match if `expected` is a substring of `$output`
|
||||
# -e, --regexp Treat `expected` as an extended regular expression
|
||||
# -, --stdin Read `expected` value from STDIN
|
||||
# <expected> The expected value, substring or regular expression
|
||||
#
|
||||
# IO:
|
||||
# STDIN - [=$1] expected output
|
||||
# STDERR - details, on failure
|
||||
# error message, on error
|
||||
# Globals:
|
||||
# output
|
||||
# Returns:
|
||||
# 0 - if output matches the expected value/partial/regexp
|
||||
# 1 - otherwise
|
||||
#
|
||||
# This function verifies that a command or function produces the expected output.
|
||||
# (It is the logical complement of `refute_output`.)
|
||||
# Output matching can be literal (the default), partial or by regular expression.
|
||||
# The expected output can be specified either by positional argument or read from STDIN by passing the `-`/`--stdin` flag.
|
||||
#
|
||||
# ## Literal matching
|
||||
#
|
||||
# By default, literal matching is performed.
|
||||
# The assertion fails if `$output` does not equal the expected output.
|
||||
#
|
||||
# ```bash
|
||||
# @test 'assert_output()' {
|
||||
# run echo 'have'
|
||||
# assert_output 'want'
|
||||
# }
|
||||
#
|
||||
# @test 'assert_output() with pipe' {
|
||||
# run echo 'hello'
|
||||
# echo 'hello' | assert_output -
|
||||
# }
|
||||
#
|
||||
# @test 'assert_output() with herestring' {
|
||||
# run echo 'hello'
|
||||
# assert_output - <<< hello
|
||||
# }
|
||||
# ```
|
||||
#
|
||||
# On failure, the expected and actual output are displayed.
|
||||
#
|
||||
# ```
|
||||
# -- output differs --
|
||||
# expected : want
|
||||
# actual : have
|
||||
# --
|
||||
# ```
|
||||
#
|
||||
# ## Existence
|
||||
#
|
||||
# To assert that any output exists at all, omit the `expected` argument.
|
||||
#
|
||||
# ```bash
|
||||
# @test 'assert_output()' {
|
||||
# run echo 'have'
|
||||
# assert_output
|
||||
# }
|
||||
# ```
|
||||
#
|
||||
# On failure, an error message is displayed.
|
||||
#
|
||||
# ```
|
||||
# -- no output --
|
||||
# expected non-empty output, but output was empty
|
||||
# --
|
||||
# ```
|
||||
#
|
||||
# ## Partial matching
|
||||
#
|
||||
# Partial matching can be enabled with the `--partial` option (`-p` for short).
|
||||
# When used, the assertion fails if the expected _substring_ is not found in `$output`.
|
||||
#
|
||||
# ```bash
|
||||
# @test 'assert_output() partial matching' {
|
||||
# run echo 'ERROR: no such file or directory'
|
||||
# assert_output --partial 'SUCCESS'
|
||||
# }
|
||||
# ```
|
||||
#
|
||||
# On failure, the substring and the output are displayed.
|
||||
#
|
||||
# ```
|
||||
# -- output does not contain substring --
|
||||
# substring : SUCCESS
|
||||
# output : ERROR: no such file or directory
|
||||
# --
|
||||
# ```
|
||||
#
|
||||
# ## Regular expression matching
|
||||
#
|
||||
# Regular expression matching can be enabled with the `--regexp` option (`-e` for short).
|
||||
# When used, the assertion fails if the *extended regular expression* does not match `$output`.
|
||||
#
|
||||
# *__Note__:
|
||||
# The anchors `^` and `$` bind to the beginning and the end (respectively) of the entire output;
|
||||
# not individual lines.*
|
||||
#
|
||||
# ```bash
|
||||
# @test 'assert_output() regular expression matching' {
|
||||
# run echo 'Foobar 0.1.0'
|
||||
# assert_output --regexp '^Foobar v[0-9]+\.[0-9]+\.[0-9]$'
|
||||
# }
|
||||
# ```
|
||||
#
|
||||
# On failure, the regular expression and the output are displayed.
|
||||
#
|
||||
# ```
|
||||
# -- regular expression does not match output --
|
||||
# regexp : ^Foobar v[0-9]+\.[0-9]+\.[0-9]$
|
||||
# output : Foobar 0.1.0
|
||||
# --
|
||||
# ```
|
||||
assert_output() {
|
||||
local -i is_mode_partial=0
|
||||
local -i is_mode_regexp=0
|
||||
local -i is_mode_nonempty=0
|
||||
local -i use_stdin=0
|
||||
: "${output?}"
|
||||
|
||||
# Handle options.
|
||||
if (( $# == 0 )); then
|
||||
is_mode_nonempty=1
|
||||
fi
|
||||
|
||||
while (( $# > 0 )); do
|
||||
case "$1" in
|
||||
-p|--partial) is_mode_partial=1; shift ;;
|
||||
-e|--regexp) is_mode_regexp=1; shift ;;
|
||||
-|--stdin) use_stdin=1; shift ;;
|
||||
--) shift; break ;;
|
||||
*) break ;;
|
||||
esac
|
||||
done
|
||||
|
||||
if (( is_mode_partial )) && (( is_mode_regexp )); then
|
||||
echo "\`--partial' and \`--regexp' are mutually exclusive" \
|
||||
| batslib_decorate 'ERROR: assert_output' \
|
||||
| fail
|
||||
return $?
|
||||
fi
|
||||
|
||||
# Arguments.
|
||||
local expected
|
||||
if (( use_stdin )); then
|
||||
expected="$(cat -)"
|
||||
else
|
||||
expected="${1-}"
|
||||
fi
|
||||
|
||||
# Matching.
|
||||
if (( is_mode_nonempty )); then
|
||||
if [ -z "$output" ]; then
|
||||
echo 'expected non-empty output, but output was empty' \
|
||||
| batslib_decorate 'no output' \
|
||||
| fail
|
||||
fi
|
||||
elif (( is_mode_regexp )); then
|
||||
if [[ '' =~ $expected ]] || (( $? == 2 )); then
|
||||
echo "Invalid extended regular expression: \`$expected'" \
|
||||
| batslib_decorate 'ERROR: assert_output' \
|
||||
| fail
|
||||
elif ! [[ $output =~ $expected ]]; then
|
||||
batslib_print_kv_single_or_multi 6 \
|
||||
'regexp' "$expected" \
|
||||
'output' "$output" \
|
||||
| batslib_decorate 'regular expression does not match output' \
|
||||
| fail
|
||||
fi
|
||||
elif (( is_mode_partial )); then
|
||||
if [[ $output != *"$expected"* ]]; then
|
||||
batslib_print_kv_single_or_multi 9 \
|
||||
'substring' "$expected" \
|
||||
'output' "$output" \
|
||||
| batslib_decorate 'output does not contain substring' \
|
||||
| fail
|
||||
fi
|
||||
else
|
||||
if [[ $output != "$expected" ]]; then
|
||||
batslib_print_kv_single_or_multi 8 \
|
||||
'expected' "$expected" \
|
||||
'actual' "$output" \
|
||||
| batslib_decorate 'output differs' \
|
||||
| fail
|
||||
fi
|
||||
fi
|
||||
}
|
44
lib/bats-assert/src/assert_success.bash
Normal file
44
lib/bats-assert/src/assert_success.bash
Normal file
@ -0,0 +1,44 @@
|
||||
# assert_success
|
||||
# ==============
|
||||
#
|
||||
# Summary: Fail if `$status` is not 0.
|
||||
#
|
||||
# Usage: assert_success
|
||||
#
|
||||
# IO:
|
||||
# STDERR - `$status` and `$output`, on failure
|
||||
# Globals:
|
||||
# status
|
||||
# output
|
||||
# Returns:
|
||||
# 0 - if `$status' is 0
|
||||
# 1 - otherwise
|
||||
#
|
||||
# ```bash
|
||||
# @test 'assert_success() status only' {
|
||||
# run bash -c "echo 'Error!'; exit 1"
|
||||
# assert_success
|
||||
# }
|
||||
# ```
|
||||
#
|
||||
# On failure, `$status` and `$output` are displayed.
|
||||
#
|
||||
# ```
|
||||
# -- command failed --
|
||||
# status : 1
|
||||
# output : Error!
|
||||
# --
|
||||
# ```
|
||||
assert_success() {
|
||||
: "${output?}"
|
||||
: "${status?}"
|
||||
|
||||
if (( status != 0 )); then
|
||||
{ local -ir width=6
|
||||
batslib_print_kv_single "$width" 'status' "$status"
|
||||
batslib_print_kv_single_or_multi "$width" 'output' "$output"
|
||||
} \
|
||||
| batslib_decorate 'command failed' \
|
||||
| fail
|
||||
fi
|
||||
}
|
42
lib/bats-assert/src/refute.bash
Normal file
42
lib/bats-assert/src/refute.bash
Normal file
@ -0,0 +1,42 @@
|
||||
# refute
|
||||
# ======
|
||||
#
|
||||
# Summary: Fail if the given expression evaluates to true.
|
||||
#
|
||||
# Usage: refute <expression>
|
||||
#
|
||||
# Options:
|
||||
# <expression> The expression to evaluate for falsiness.
|
||||
# *__Note:__ The expression must be a simple command.
|
||||
# [Compound commands](https://www.gnu.org/software/bash/manual/bash.html#Compound-Commands),
|
||||
# such as `[[`, can be used only when executed with `bash -c`.*
|
||||
#
|
||||
# IO:
|
||||
# STDERR - the successful expression, on failure
|
||||
# Globals:
|
||||
# none
|
||||
# Returns:
|
||||
# 0 - if expression evaluates to false
|
||||
# 1 - otherwise
|
||||
#
|
||||
# ```bash
|
||||
# @test 'refute()' {
|
||||
# rm -f '/var/log/test.log'
|
||||
# refute [ -e '/var/log/test.log' ]
|
||||
# }
|
||||
# ```
|
||||
#
|
||||
# On failure, the successful expression is displayed.
|
||||
#
|
||||
# ```
|
||||
# -- assertion succeeded, but it was expected to fail --
|
||||
# expression : [ -e /var/log/test.log ]
|
||||
# --
|
||||
# ```
|
||||
refute() {
|
||||
if "$@"; then
|
||||
batslib_print_kv_single 10 'expression' "$*" \
|
||||
| batslib_decorate 'assertion succeeded, but it was expected to fail' \
|
||||
| fail
|
||||
fi
|
||||
}
|
271
lib/bats-assert/src/refute_line.bash
Normal file
271
lib/bats-assert/src/refute_line.bash
Normal file
@ -0,0 +1,271 @@
|
||||
# refute_line
|
||||
# ===========
|
||||
#
|
||||
# Summary: Fail if the unexpected line is found in the output (default) or at a specific line number.
|
||||
#
|
||||
# Usage: refute_line [-n index] [-p | -e] [--] <unexpected>
|
||||
#
|
||||
# Options:
|
||||
# -n, --index <idx> Match the <idx>th line
|
||||
# -p, --partial Match if `unexpected` is a substring of `$output` or line <idx>
|
||||
# -e, --regexp Treat `unexpected` as an extended regular expression
|
||||
# <unexpected> The unexpected line string, substring, or regular expression.
|
||||
#
|
||||
# IO:
|
||||
# STDERR - details, on failure
|
||||
# error message, on error
|
||||
# Globals:
|
||||
# output
|
||||
# lines
|
||||
# Returns:
|
||||
# 0 - if match not found
|
||||
# 1 - otherwise
|
||||
#
|
||||
# Similarly to `refute_output`, this function verifies that a command or function does not produce the unexpected output.
|
||||
# (It is the logical complement of `assert_line`.)
|
||||
# It checks that the unexpected line does not appear in the output (default) or at a specific line number.
|
||||
# Matching can be literal (default), partial or regular expression.
|
||||
#
|
||||
# *__Warning:__
|
||||
# Due to a [bug in Bats][bats-93], empty lines are discarded from `${lines[@]}`,
|
||||
# causing line indices to change and preventing testing for empty lines.*
|
||||
#
|
||||
# [bats-93]: https://github.com/sstephenson/bats/pull/93
|
||||
#
|
||||
# ## Looking for a line in the output
|
||||
#
|
||||
# By default, the entire output is searched for the unexpected line.
|
||||
# The assertion fails if the unexpected line is found in `${lines[@]}`.
|
||||
#
|
||||
# ```bash
|
||||
# @test 'refute_line() looking for line' {
|
||||
# run echo $'have-0\nwant\nhave-2'
|
||||
# refute_line 'want'
|
||||
# }
|
||||
# ```
|
||||
#
|
||||
# On failure, the unexpected line, the index of its first match and the output with the matching line highlighted are displayed.
|
||||
#
|
||||
# ```
|
||||
# -- line should not be in output --
|
||||
# line : want
|
||||
# index : 1
|
||||
# output (3 lines):
|
||||
# have-0
|
||||
# > want
|
||||
# have-2
|
||||
# --
|
||||
# ```
|
||||
#
|
||||
# ## Matching a specific line
|
||||
#
|
||||
# When the `--index <idx>` option is used (`-n <idx>` for short), the unexpected line is matched only against the line identified by the given index.
|
||||
# The assertion fails if the unexpected line equals `${lines[<idx>]}`.
|
||||
#
|
||||
# ```bash
|
||||
# @test 'refute_line() specific line' {
|
||||
# run echo $'have-0\nwant-1\nhave-2'
|
||||
# refute_line --index 1 'want-1'
|
||||
# }
|
||||
# ```
|
||||
#
|
||||
# On failure, the index and the unexpected line are displayed.
|
||||
#
|
||||
# ```
|
||||
# -- line should differ --
|
||||
# index : 1
|
||||
# line : want-1
|
||||
# --
|
||||
# ```
|
||||
#
|
||||
# ## Partial matching
|
||||
#
|
||||
# Partial matching can be enabled with the `--partial` option (`-p` for short).
|
||||
# When used, a match fails if the unexpected *substring* is found in the matched line.
|
||||
#
|
||||
# ```bash
|
||||
# @test 'refute_line() partial matching' {
|
||||
# run echo $'have 1\nwant 2\nhave 3'
|
||||
# refute_line --partial 'want'
|
||||
# }
|
||||
# ```
|
||||
#
|
||||
# On failure, in addition to the details of literal matching, the substring is also displayed.
|
||||
# When used with `--index <idx>` the substring replaces the unexpected line.
|
||||
#
|
||||
# ```
|
||||
# -- no line should contain substring --
|
||||
# substring : want
|
||||
# index : 1
|
||||
# output (3 lines):
|
||||
# have 1
|
||||
# > want 2
|
||||
# have 3
|
||||
# --
|
||||
# ```
|
||||
#
|
||||
# ## Regular expression matching
|
||||
#
|
||||
# Regular expression matching can be enabled with the `--regexp` option (`-e` for short).
|
||||
# When used, a match fails if the *extended regular expression* matches the line being tested.
|
||||
#
|
||||
# *__Note__:
|
||||
# As expected, the anchors `^` and `$` bind to the beginning and the end (respectively) of the matched line.*
|
||||
#
|
||||
# ```bash
|
||||
# @test 'refute_line() regular expression matching' {
|
||||
# run echo $'Foobar v0.1.0\nRelease date: 2015-11-29'
|
||||
# refute_line --index 0 --regexp '^Foobar v[0-9]+\.[0-9]+\.[0-9]$'
|
||||
# }
|
||||
# ```
|
||||
#
|
||||
# On failure, in addition to the details of literal matching, the regular expression is also displayed.
|
||||
# When used with `--index <idx>` the regular expression replaces the unexpected line.
|
||||
#
|
||||
# ```
|
||||
# -- regular expression should not match line --
|
||||
# index : 0
|
||||
# regexp : ^Foobar v[0-9]+\.[0-9]+\.[0-9]$
|
||||
# line : Foobar v0.1.0
|
||||
# --
|
||||
# ```
|
||||
# FIXME(ztombol): Display `${lines[@]}' instead of `$output'!
|
||||
refute_line() {
|
||||
local -i is_match_line=0
|
||||
local -i is_mode_partial=0
|
||||
local -i is_mode_regexp=0
|
||||
: "${lines?}"
|
||||
|
||||
# Handle options.
|
||||
while (( $# > 0 )); do
|
||||
case "$1" in
|
||||
-n|--index)
|
||||
if (( $# < 2 )) || ! [[ $2 =~ ^([0-9]|[1-9][0-9]+)$ ]]; then
|
||||
echo "\`--index' requires an integer argument: \`$2'" \
|
||||
| batslib_decorate 'ERROR: refute_line' \
|
||||
| fail
|
||||
return $?
|
||||
fi
|
||||
is_match_line=1
|
||||
local -ri idx="$2"
|
||||
shift 2
|
||||
;;
|
||||
-p|--partial) is_mode_partial=1; shift ;;
|
||||
-e|--regexp) is_mode_regexp=1; shift ;;
|
||||
--) shift; break ;;
|
||||
*) break ;;
|
||||
esac
|
||||
done
|
||||
|
||||
if (( is_mode_partial )) && (( is_mode_regexp )); then
|
||||
echo "\`--partial' and \`--regexp' are mutually exclusive" \
|
||||
| batslib_decorate 'ERROR: refute_line' \
|
||||
| fail
|
||||
return $?
|
||||
fi
|
||||
|
||||
# Arguments.
|
||||
local -r unexpected="$1"
|
||||
|
||||
if (( is_mode_regexp == 1 )) && [[ '' =~ $unexpected ]] || (( $? == 2 )); then
|
||||
echo "Invalid extended regular expression: \`$unexpected'" \
|
||||
| batslib_decorate 'ERROR: refute_line' \
|
||||
| fail
|
||||
return $?
|
||||
fi
|
||||
|
||||
# Matching.
|
||||
if (( is_match_line )); then
|
||||
# Specific line.
|
||||
if (( is_mode_regexp )); then
|
||||
if [[ ${lines[$idx]} =~ $unexpected ]]; then
|
||||
batslib_print_kv_single 6 \
|
||||
'index' "$idx" \
|
||||
'regexp' "$unexpected" \
|
||||
'line' "${lines[$idx]}" \
|
||||
| batslib_decorate 'regular expression should not match line' \
|
||||
| fail
|
||||
fi
|
||||
elif (( is_mode_partial )); then
|
||||
if [[ ${lines[$idx]} == *"$unexpected"* ]]; then
|
||||
batslib_print_kv_single 9 \
|
||||
'index' "$idx" \
|
||||
'substring' "$unexpected" \
|
||||
'line' "${lines[$idx]}" \
|
||||
| batslib_decorate 'line should not contain substring' \
|
||||
| fail
|
||||
fi
|
||||
else
|
||||
if [[ ${lines[$idx]} == "$unexpected" ]]; then
|
||||
batslib_print_kv_single 5 \
|
||||
'index' "$idx" \
|
||||
'line' "${lines[$idx]}" \
|
||||
| batslib_decorate 'line should differ' \
|
||||
| fail
|
||||
fi
|
||||
fi
|
||||
else
|
||||
# Line contained in output.
|
||||
if (( is_mode_regexp )); then
|
||||
local -i idx
|
||||
for (( idx = 0; idx < ${#lines[@]}; ++idx )); do
|
||||
if [[ ${lines[$idx]} =~ $unexpected ]]; then
|
||||
{ local -ar single=( 'regexp' "$unexpected" 'index' "$idx" )
|
||||
local -a may_be_multi=( 'output' "$output" )
|
||||
local -ir width="$( batslib_get_max_single_line_key_width "${single[@]}" "${may_be_multi[@]}" )"
|
||||
batslib_print_kv_single "$width" "${single[@]}"
|
||||
if batslib_is_single_line "${may_be_multi[1]}"; then
|
||||
batslib_print_kv_single "$width" "${may_be_multi[@]}"
|
||||
else
|
||||
may_be_multi[1]="$( printf '%s' "${may_be_multi[1]}" | batslib_prefix | batslib_mark '>' "$idx" )"
|
||||
batslib_print_kv_multi "${may_be_multi[@]}"
|
||||
fi
|
||||
} \
|
||||
| batslib_decorate 'no line should match the regular expression' \
|
||||
| fail
|
||||
return $?
|
||||
fi
|
||||
done
|
||||
elif (( is_mode_partial )); then
|
||||
local -i idx
|
||||
for (( idx = 0; idx < ${#lines[@]}; ++idx )); do
|
||||
if [[ ${lines[$idx]} == *"$unexpected"* ]]; then
|
||||
{ local -ar single=( 'substring' "$unexpected" 'index' "$idx" )
|
||||
local -a may_be_multi=( 'output' "$output" )
|
||||
local -ir width="$( batslib_get_max_single_line_key_width "${single[@]}" "${may_be_multi[@]}" )"
|
||||
batslib_print_kv_single "$width" "${single[@]}"
|
||||
if batslib_is_single_line "${may_be_multi[1]}"; then
|
||||
batslib_print_kv_single "$width" "${may_be_multi[@]}"
|
||||
else
|
||||
may_be_multi[1]="$( printf '%s' "${may_be_multi[1]}" | batslib_prefix | batslib_mark '>' "$idx" )"
|
||||
batslib_print_kv_multi "${may_be_multi[@]}"
|
||||
fi
|
||||
} \
|
||||
| batslib_decorate 'no line should contain substring' \
|
||||
| fail
|
||||
return $?
|
||||
fi
|
||||
done
|
||||
else
|
||||
local -i idx
|
||||
for (( idx = 0; idx < ${#lines[@]}; ++idx )); do
|
||||
if [[ ${lines[$idx]} == "$unexpected" ]]; then
|
||||
{ local -ar single=( 'line' "$unexpected" 'index' "$idx" )
|
||||
local -a may_be_multi=( 'output' "$output" )
|
||||
local -ir width="$( batslib_get_max_single_line_key_width "${single[@]}" "${may_be_multi[@]}" )"
|
||||
batslib_print_kv_single "$width" "${single[@]}"
|
||||
if batslib_is_single_line "${may_be_multi[1]}"; then
|
||||
batslib_print_kv_single "$width" "${may_be_multi[@]}"
|
||||
else
|
||||
may_be_multi[1]="$( printf '%s' "${may_be_multi[1]}" | batslib_prefix | batslib_mark '>' "$idx" )"
|
||||
batslib_print_kv_multi "${may_be_multi[@]}"
|
||||
fi
|
||||
} \
|
||||
| batslib_decorate 'line should not be in output' \
|
||||
| fail
|
||||
return $?
|
||||
fi
|
||||
done
|
||||
fi
|
||||
fi
|
||||
}
|
199
lib/bats-assert/src/refute_output.bash
Normal file
199
lib/bats-assert/src/refute_output.bash
Normal file
@ -0,0 +1,199 @@
|
||||
# refute_output
|
||||
# =============
|
||||
#
|
||||
# Summary: Fail if `$output' matches the unexpected output.
|
||||
#
|
||||
# Usage: refute_output [-p | -e] [- | [--] <unexpected>]
|
||||
#
|
||||
# Options:
|
||||
# -p, --partial Match if `unexpected` is a substring of `$output`
|
||||
# -e, --regexp Treat `unexpected` as an extended regular expression
|
||||
# -, --stdin Read `unexpected` value from STDIN
|
||||
# <unexpected> The unexpected value, substring, or regular expression
|
||||
#
|
||||
# IO:
|
||||
# STDIN - [=$1] unexpected output
|
||||
# STDERR - details, on failure
|
||||
# error message, on error
|
||||
# Globals:
|
||||
# output
|
||||
# Returns:
|
||||
# 0 - if output matches the unexpected value/partial/regexp
|
||||
# 1 - otherwise
|
||||
#
|
||||
# This function verifies that a command or function does not produce the unexpected output.
|
||||
# (It is the logical complement of `assert_output`.)
|
||||
# Output matching can be literal (the default), partial or by regular expression.
|
||||
# The unexpected output can be specified either by positional argument or read from STDIN by passing the `-`/`--stdin` flag.
|
||||
#
|
||||
# ## Literal matching
|
||||
#
|
||||
# By default, literal matching is performed.
|
||||
# The assertion fails if `$output` equals the unexpected output.
|
||||
#
|
||||
# ```bash
|
||||
# @test 'refute_output()' {
|
||||
# run echo 'want'
|
||||
# refute_output 'want'
|
||||
# }
|
||||
#
|
||||
# @test 'refute_output() with pipe' {
|
||||
# run echo 'hello'
|
||||
# echo 'world' | refute_output -
|
||||
# }
|
||||
#
|
||||
# @test 'refute_output() with herestring' {
|
||||
# run echo 'hello'
|
||||
# refute_output - <<< world
|
||||
# }
|
||||
# ```
|
||||
#
|
||||
# On failure, the output is displayed.
|
||||
#
|
||||
# ```
|
||||
# -- output equals, but it was expected to differ --
|
||||
# output : want
|
||||
# --
|
||||
# ```
|
||||
#
|
||||
# ## Existence
|
||||
#
|
||||
# To assert that there is no output at all, omit the matching argument.
|
||||
#
|
||||
# ```bash
|
||||
# @test 'refute_output()' {
|
||||
# run foo --silent
|
||||
# refute_output
|
||||
# }
|
||||
# ```
|
||||
#
|
||||
# On failure, an error message is displayed.
|
||||
#
|
||||
# ```
|
||||
# -- unexpected output --
|
||||
# expected no output, but output was non-empty
|
||||
# --
|
||||
# ```
|
||||
#
|
||||
# ## Partial matching
|
||||
#
|
||||
# Partial matching can be enabled with the `--partial` option (`-p` for short).
|
||||
# When used, the assertion fails if the unexpected _substring_ is found in `$output`.
|
||||
#
|
||||
# ```bash
|
||||
# @test 'refute_output() partial matching' {
|
||||
# run echo 'ERROR: no such file or directory'
|
||||
# refute_output --partial 'ERROR'
|
||||
# }
|
||||
# ```
|
||||
#
|
||||
# On failure, the substring and the output are displayed.
|
||||
#
|
||||
# ```
|
||||
# -- output should not contain substring --
|
||||
# substring : ERROR
|
||||
# output : ERROR: no such file or directory
|
||||
# --
|
||||
# ```
|
||||
#
|
||||
# ## Regular expression matching
|
||||
#
|
||||
# Regular expression matching can be enabled with the `--regexp` option (`-e` for short).
|
||||
# When used, the assertion fails if the *extended regular expression* matches `$output`.
|
||||
#
|
||||
# *__Note__:
|
||||
# The anchors `^` and `$` bind to the beginning and the end (respectively) of the entire output;
|
||||
# not individual lines.*
|
||||
#
|
||||
# ```bash
|
||||
# @test 'refute_output() regular expression matching' {
|
||||
# run echo 'Foobar v0.1.0'
|
||||
# refute_output --regexp '^Foobar v[0-9]+\.[0-9]+\.[0-9]$'
|
||||
# }
|
||||
# ```
|
||||
#
|
||||
# On failure, the regular expression and the output are displayed.
|
||||
#
|
||||
# ```
|
||||
# -- regular expression should not match output --
|
||||
# regexp : ^Foobar v[0-9]+\.[0-9]+\.[0-9]$
|
||||
# output : Foobar v0.1.0
|
||||
# --
|
||||
# ```
|
||||
refute_output() {
|
||||
local -i is_mode_partial=0
|
||||
local -i is_mode_regexp=0
|
||||
local -i is_mode_empty=0
|
||||
local -i use_stdin=0
|
||||
: "${output?}"
|
||||
|
||||
# Handle options.
|
||||
if (( $# == 0 )); then
|
||||
is_mode_empty=1
|
||||
fi
|
||||
|
||||
while (( $# > 0 )); do
|
||||
case "$1" in
|
||||
-p|--partial) is_mode_partial=1; shift ;;
|
||||
-e|--regexp) is_mode_regexp=1; shift ;;
|
||||
-|--stdin) use_stdin=1; shift ;;
|
||||
--) shift; break ;;
|
||||
*) break ;;
|
||||
esac
|
||||
done
|
||||
|
||||
if (( is_mode_partial )) && (( is_mode_regexp )); then
|
||||
echo "\`--partial' and \`--regexp' are mutually exclusive" \
|
||||
| batslib_decorate 'ERROR: refute_output' \
|
||||
| fail
|
||||
return $?
|
||||
fi
|
||||
|
||||
# Arguments.
|
||||
local unexpected
|
||||
if (( use_stdin )); then
|
||||
unexpected="$(cat -)"
|
||||
else
|
||||
unexpected="${1-}"
|
||||
fi
|
||||
|
||||
if (( is_mode_regexp == 1 )) && [[ '' =~ $unexpected ]] || (( $? == 2 )); then
|
||||
echo "Invalid extended regular expression: \`$unexpected'" \
|
||||
| batslib_decorate 'ERROR: refute_output' \
|
||||
| fail
|
||||
return $?
|
||||
fi
|
||||
|
||||
# Matching.
|
||||
if (( is_mode_empty )); then
|
||||
if [ -n "$output" ]; then
|
||||
batslib_print_kv_single_or_multi 6 \
|
||||
'output' "$output" \
|
||||
| batslib_decorate 'output non-empty, but expected no output' \
|
||||
| fail
|
||||
fi
|
||||
elif (( is_mode_regexp )); then
|
||||
if [[ $output =~ $unexpected ]]; then
|
||||
batslib_print_kv_single_or_multi 6 \
|
||||
'regexp' "$unexpected" \
|
||||
'output' "$output" \
|
||||
| batslib_decorate 'regular expression should not match output' \
|
||||
| fail
|
||||
fi
|
||||
elif (( is_mode_partial )); then
|
||||
if [[ $output == *"$unexpected"* ]]; then
|
||||
batslib_print_kv_single_or_multi 9 \
|
||||
'substring' "$unexpected" \
|
||||
'output' "$output" \
|
||||
| batslib_decorate 'output should not contain substring' \
|
||||
| fail
|
||||
fi
|
||||
else
|
||||
if [[ $output == "$unexpected" ]]; then
|
||||
batslib_print_kv_single_or_multi 6 \
|
||||
'output' "$output" \
|
||||
| batslib_decorate 'output equals, but it was expected to differ' \
|
||||
| fail
|
||||
fi
|
||||
fi
|
||||
}
|
19
lib/bats-assert/test/assert.bats
Executable file
19
lib/bats-assert/test/assert.bats
Executable file
@ -0,0 +1,19 @@
|
||||
#!/usr/bin/env bats
|
||||
|
||||
load test_helper
|
||||
|
||||
@test 'assert() <expression>: returns 0 if <expression> evaluates to TRUE' {
|
||||
run assert true
|
||||
assert_test_pass
|
||||
}
|
||||
|
||||
@test 'assert() <expression>: returns 1 and displays <expression> if it evaluates to FALSE' {
|
||||
run assert false
|
||||
|
||||
assert_test_fail <<'ERR_MSG'
|
||||
|
||||
-- assertion failed --
|
||||
expression : false
|
||||
--
|
||||
ERR_MSG
|
||||
}
|
62
lib/bats-assert/test/assert_equal.bats
Executable file
62
lib/bats-assert/test/assert_equal.bats
Executable file
@ -0,0 +1,62 @@
|
||||
#!/usr/bin/env bats
|
||||
|
||||
load test_helper
|
||||
|
||||
@test 'assert_equal() <actual> <expected>: returns 0 if <actual> equals <expected>' {
|
||||
run assert_equal 'a' 'a'
|
||||
assert_test_pass
|
||||
}
|
||||
|
||||
@test 'assert_equal() <actual> <expected>: returns 1 and displays details if <actual> does not equal <expected>' {
|
||||
run assert_equal 'a' 'b'
|
||||
|
||||
assert_test_fail <<'ERR_MSG'
|
||||
|
||||
-- values do not equal --
|
||||
expected : b
|
||||
actual : a
|
||||
--
|
||||
ERR_MSG
|
||||
}
|
||||
|
||||
@test 'assert_equal() <actual> <expected>: displays details in multi-line format if <actual> is longer than one line' {
|
||||
run assert_equal $'a 0\na 1' 'b'
|
||||
|
||||
assert_test_fail <<'ERR_MSG'
|
||||
|
||||
-- values do not equal --
|
||||
expected (1 lines):
|
||||
b
|
||||
actual (2 lines):
|
||||
a 0
|
||||
a 1
|
||||
--
|
||||
ERR_MSG
|
||||
}
|
||||
|
||||
@test 'assert_equal() <actual> <expected>: displays details in multi-line format if <expected> is longer than one line' {
|
||||
run assert_equal 'a' $'b 0\nb 1'
|
||||
|
||||
assert_test_fail <<'ERR_MSG'
|
||||
|
||||
-- values do not equal --
|
||||
expected (2 lines):
|
||||
b 0
|
||||
b 1
|
||||
actual (1 lines):
|
||||
a
|
||||
--
|
||||
ERR_MSG
|
||||
}
|
||||
|
||||
@test 'assert_equal() <actual> <expected>: performs literal matching' {
|
||||
run assert_equal 'a' '*'
|
||||
|
||||
assert_test_fail <<'ERR_MSG'
|
||||
|
||||
-- values do not equal --
|
||||
expected : *
|
||||
actual : a
|
||||
--
|
||||
ERR_MSG
|
||||
}
|
75
lib/bats-assert/test/assert_failure.bats
Executable file
75
lib/bats-assert/test/assert_failure.bats
Executable file
@ -0,0 +1,75 @@
|
||||
#!/usr/bin/env bats
|
||||
|
||||
load test_helper
|
||||
|
||||
@test "assert_failure(): returns 0 if \`\$status' is not 0" {
|
||||
run false
|
||||
run assert_failure
|
||||
assert_test_pass
|
||||
}
|
||||
|
||||
@test "assert_failure(): returns 1 and displays details if \`\$status' is 0" {
|
||||
run bash -c 'echo "a"
|
||||
exit 0'
|
||||
run assert_failure
|
||||
|
||||
assert_test_fail <<'ERR_MSG'
|
||||
|
||||
-- command succeeded, but it was expected to fail --
|
||||
output : a
|
||||
--
|
||||
ERR_MSG
|
||||
}
|
||||
|
||||
@test "assert_failure(): displays \`\$output' in multi-line format if it is longer then one line" {
|
||||
run bash -c 'printf "a 0\na 1"
|
||||
exit 0'
|
||||
run assert_failure
|
||||
|
||||
assert_test_fail <<'ERR_MSG'
|
||||
|
||||
-- command succeeded, but it was expected to fail --
|
||||
output (2 lines):
|
||||
a 0
|
||||
a 1
|
||||
--
|
||||
ERR_MSG
|
||||
}
|
||||
|
||||
@test "assert_failure() <status>: returns 0 if \`\$status' equals <status>" {
|
||||
run bash -c 'exit 1'
|
||||
run assert_failure 1
|
||||
assert_test_pass
|
||||
}
|
||||
|
||||
@test "assert_failure() <status>: returns 1 and displays details if \`\$status' does not equal <status>" {
|
||||
run bash -c 'echo "a"
|
||||
exit 1'
|
||||
run assert_failure 2
|
||||
|
||||
assert_test_fail <<'ERR_MSG'
|
||||
|
||||
-- command failed as expected, but status differs --
|
||||
expected : 2
|
||||
actual : 1
|
||||
output : a
|
||||
--
|
||||
ERR_MSG
|
||||
}
|
||||
|
||||
@test "assert_failure() <status>: displays \`\$output' in multi-line format if it is longer then one line" {
|
||||
run bash -c 'printf "a 0\na 1"
|
||||
exit 1'
|
||||
run assert_failure 2
|
||||
|
||||
assert_test_fail <<'ERR_MSG'
|
||||
|
||||
-- command failed as expected, but status differs --
|
||||
expected : 2
|
||||
actual : 1
|
||||
output (2 lines):
|
||||
a 0
|
||||
a 1
|
||||
--
|
||||
ERR_MSG
|
||||
}
|
351
lib/bats-assert/test/assert_line.bats
Executable file
351
lib/bats-assert/test/assert_line.bats
Executable file
@ -0,0 +1,351 @@
|
||||
#!/usr/bin/env bats
|
||||
|
||||
load test_helper
|
||||
|
||||
|
||||
###############################################################################
|
||||
# Containing a line
|
||||
###############################################################################
|
||||
|
||||
#
|
||||
# Literal matching
|
||||
#
|
||||
|
||||
# Correctness
|
||||
@test "assert_line() <expected>: returns 0 if <expected> is a line in \`\${lines[@]}'" {
|
||||
run printf 'a\nb\nc'
|
||||
run assert_line 'b'
|
||||
assert_test_pass
|
||||
}
|
||||
|
||||
@test "assert_line() <expected>: returns 1 and displays details if <expected> is not a line in \`\${lines[@]}'" {
|
||||
run echo 'b'
|
||||
run assert_line 'a'
|
||||
|
||||
assert_test_fail <<'ERR_MSG'
|
||||
|
||||
-- output does not contain line --
|
||||
line : a
|
||||
output : b
|
||||
--
|
||||
ERR_MSG
|
||||
}
|
||||
|
||||
# Output formatting
|
||||
@test "assert_line() <expected>: displays \`\$output' in multi-line format if it is longer than one line" {
|
||||
run printf 'b 0\nb 1'
|
||||
run assert_line 'a'
|
||||
|
||||
assert_test_fail <<'ERR_MSG'
|
||||
|
||||
-- output does not contain line --
|
||||
line : a
|
||||
output (2 lines):
|
||||
b 0
|
||||
b 1
|
||||
--
|
||||
ERR_MSG
|
||||
}
|
||||
|
||||
# Options
|
||||
@test 'assert_line() <expected>: performs literal matching by default' {
|
||||
run echo 'a'
|
||||
run assert_line '*'
|
||||
|
||||
assert_test_fail <<'ERR_MSG'
|
||||
|
||||
-- output does not contain line --
|
||||
line : *
|
||||
output : a
|
||||
--
|
||||
ERR_MSG
|
||||
}
|
||||
|
||||
|
||||
#
|
||||
# Partial matching: `-p' and `--partial'
|
||||
#
|
||||
|
||||
# Options
|
||||
@test 'assert_line() -p <partial>: enables partial matching' {
|
||||
run printf 'a\n_b_\nc'
|
||||
run assert_line -p 'b'
|
||||
assert_test_pass
|
||||
}
|
||||
|
||||
@test 'assert_line() --partial <partial>: enables partial matching' {
|
||||
run printf 'a\n_b_\nc'
|
||||
run assert_line --partial 'b'
|
||||
assert_test_pass
|
||||
}
|
||||
|
||||
# Correctness
|
||||
@test "assert_line() --partial <partial>: returns 0 if <partial> is a substring in any line in \`\${lines[@]}'" {
|
||||
run printf 'a\n_b_\nc'
|
||||
run assert_line --partial 'b'
|
||||
assert_test_pass
|
||||
}
|
||||
|
||||
@test "assert_line() --partial <partial>: returns 1 and displays details if <partial> is not a substring in any lines in \`\${lines[@]}'" {
|
||||
run echo 'b'
|
||||
run assert_line --partial 'a'
|
||||
|
||||
assert_test_fail <<'ERR_MSG'
|
||||
|
||||
-- no output line contains substring --
|
||||
substring : a
|
||||
output : b
|
||||
--
|
||||
ERR_MSG
|
||||
}
|
||||
|
||||
# Output formatting
|
||||
@test "assert_line() --partial <partial>: displays \`\$output' in multi-line format if it is longer than one line" {
|
||||
run printf 'b 0\nb 1'
|
||||
run assert_line --partial 'a'
|
||||
|
||||
assert_test_fail <<'ERR_MSG'
|
||||
|
||||
-- no output line contains substring --
|
||||
substring : a
|
||||
output (2 lines):
|
||||
b 0
|
||||
b 1
|
||||
--
|
||||
ERR_MSG
|
||||
}
|
||||
|
||||
|
||||
#
|
||||
# Regular expression matching: `-e' and `--regexp'
|
||||
#
|
||||
|
||||
# Options
|
||||
@test 'assert_line() -e <regexp>: enables regular expression matching' {
|
||||
run printf 'a\n_b_\nc'
|
||||
run assert_line -e '^.b'
|
||||
assert_test_pass
|
||||
}
|
||||
|
||||
@test 'assert_line() --regexp <regexp>: enables regular expression matching' {
|
||||
run printf 'a\n_b_\nc'
|
||||
run assert_line --regexp '^.b'
|
||||
assert_test_pass
|
||||
}
|
||||
|
||||
# Correctness
|
||||
@test "assert_line() --regexp <regexp>: returns 0 if <regexp> matches any line in \`\${lines[@]}'" {
|
||||
run printf 'a\n_b_\nc'
|
||||
run assert_line --regexp '^.b'
|
||||
assert_test_pass
|
||||
}
|
||||
|
||||
@test "assert_line() --regexp <regexp>: returns 1 and displays details if <regexp> does not match any lines in \`\${lines[@]}'" {
|
||||
run echo 'b'
|
||||
run assert_line --regexp '^.a'
|
||||
|
||||
assert_test_fail <<'ERR_MSG'
|
||||
|
||||
-- no output line matches regular expression --
|
||||
regexp : ^.a
|
||||
output : b
|
||||
--
|
||||
ERR_MSG
|
||||
}
|
||||
|
||||
# Output formatting
|
||||
@test "assert_line() --regexp <regexp>: displays \`\$output' in multi-line format if longer than one line" {
|
||||
run printf 'b 0\nb 1'
|
||||
run assert_line --regexp '^.a'
|
||||
|
||||
assert_test_fail <<'ERR_MSG'
|
||||
|
||||
-- no output line matches regular expression --
|
||||
regexp : ^.a
|
||||
output (2 lines):
|
||||
b 0
|
||||
b 1
|
||||
--
|
||||
ERR_MSG
|
||||
}
|
||||
|
||||
|
||||
###############################################################################
|
||||
# Matching single line: `-n' and `--index'
|
||||
###############################################################################
|
||||
|
||||
# Options
|
||||
@test 'assert_line() -n <idx> <expected>: matches against the <idx>-th line only' {
|
||||
run printf 'a\nb\nc'
|
||||
run assert_line -n 1 'b'
|
||||
assert_test_pass
|
||||
}
|
||||
|
||||
@test 'assert_line() --index <idx> <expected>: matches against the <idx>-th line only' {
|
||||
run printf 'a\nb\nc'
|
||||
run assert_line --index 1 'b'
|
||||
assert_test_pass
|
||||
}
|
||||
|
||||
@test 'assert_line() --index <idx>: returns 1 and displays an error message if <idx> is not an integer' {
|
||||
run assert_line --index 1a
|
||||
|
||||
assert_test_fail <<'ERR_MSG'
|
||||
|
||||
-- ERROR: assert_line --
|
||||
`--index' requires an integer argument: `1a'
|
||||
--
|
||||
ERR_MSG
|
||||
}
|
||||
|
||||
|
||||
#
|
||||
# Literal matching
|
||||
#
|
||||
|
||||
# Correctness
|
||||
@test "assert_line() --index <idx> <expected>: returns 0 if <expected> equals \`\${lines[<idx>]}'" {
|
||||
run printf 'a\nb\nc'
|
||||
run assert_line --index 1 'b'
|
||||
assert_test_pass
|
||||
}
|
||||
|
||||
@test "assert_line() --index <idx> <expected>: returns 1 and displays details if <expected> does not equal \`\${lines[<idx>]}'" {
|
||||
run printf 'a\nb\nc'
|
||||
run assert_line --index 1 'a'
|
||||
|
||||
assert_test_fail <<'ERR_MSG'
|
||||
|
||||
-- line differs --
|
||||
index : 1
|
||||
expected : a
|
||||
actual : b
|
||||
--
|
||||
ERR_MSG
|
||||
}
|
||||
|
||||
# Options
|
||||
@test 'assert_line() --index <idx> <expected>: performs literal matching by default' {
|
||||
run printf 'a\nb\nc'
|
||||
run assert_line --index 1 '*'
|
||||
|
||||
assert_test_fail <<'ERR_MSG'
|
||||
|
||||
-- line differs --
|
||||
index : 1
|
||||
expected : *
|
||||
actual : b
|
||||
--
|
||||
ERR_MSG
|
||||
}
|
||||
|
||||
|
||||
#
|
||||
# Partial matching: `-p' and `--partial'
|
||||
#
|
||||
|
||||
# Options
|
||||
@test 'assert_line() --index <idx> -p <partial>: enables partial matching' {
|
||||
run printf 'a\n_b_\nc'
|
||||
run assert_line --index 1 -p 'b'
|
||||
assert_test_pass
|
||||
}
|
||||
|
||||
@test 'assert_line() --index <idx> --partial <partial>: enables partial matching' {
|
||||
run printf 'a\n_b_\nc'
|
||||
run assert_line --index 1 --partial 'b'
|
||||
assert_test_pass
|
||||
}
|
||||
|
||||
# Correctness
|
||||
@test "assert_line() --index <idx> --partial <partial>: returns 0 if <partial> is a substring in \`\${lines[<idx>]}'" {
|
||||
run printf 'a\n_b_\nc'
|
||||
run assert_line --index 1 --partial 'b'
|
||||
assert_test_pass
|
||||
}
|
||||
|
||||
@test "assert_line() --index <idx> --partial <partial>: returns 1 and displays details if <partial> is not a substring in \`\${lines[<idx>]}'" {
|
||||
run printf 'b 0\nb 1'
|
||||
run assert_line --index 1 --partial 'a'
|
||||
|
||||
assert_test_fail <<'ERR_MSG'
|
||||
|
||||
-- line does not contain substring --
|
||||
index : 1
|
||||
substring : a
|
||||
line : b 1
|
||||
--
|
||||
ERR_MSG
|
||||
}
|
||||
|
||||
|
||||
#
|
||||
# Regular expression matching: `-e' and `--regexp'
|
||||
#
|
||||
|
||||
# Options
|
||||
@test 'assert_line() --index <idx> -e <regexp>: enables regular expression matching' {
|
||||
run printf 'a\n_b_\nc'
|
||||
run assert_line --index 1 -e '^.b'
|
||||
assert_test_pass
|
||||
}
|
||||
|
||||
@test 'assert_line() --index <idx> --regexp <regexp>: enables regular expression matching' {
|
||||
run printf 'a\n_b_\nc'
|
||||
run assert_line --index 1 --regexp '^.b'
|
||||
assert_test_pass
|
||||
}
|
||||
|
||||
# Correctness
|
||||
@test "assert_line() --index <idx> --regexp <regexp>: returns 0 if <regexp> matches \`\${lines[<idx>]}'" {
|
||||
run printf 'a\n_b_\nc'
|
||||
run assert_line --index 1 --regexp '^.b'
|
||||
assert_test_pass
|
||||
}
|
||||
|
||||
@test "assert_line() --index <idx> --regexp <regexp>: returns 1 and displays details if <regexp> does not match \`\${lines[<idx>]}'" {
|
||||
run printf 'a\nb\nc'
|
||||
run assert_line --index 1 --regexp '^.a'
|
||||
|
||||
assert_test_fail <<'ERR_MSG'
|
||||
|
||||
-- regular expression does not match line --
|
||||
index : 1
|
||||
regexp : ^.a
|
||||
line : b
|
||||
--
|
||||
ERR_MSG
|
||||
}
|
||||
|
||||
|
||||
###############################################################################
|
||||
# Common
|
||||
###############################################################################
|
||||
|
||||
@test "assert_line(): \`--partial' and \`--regexp' are mutually exclusive" {
|
||||
run assert_line --partial --regexp
|
||||
|
||||
assert_test_fail <<'ERR_MSG'
|
||||
|
||||
-- ERROR: assert_line --
|
||||
`--partial' and `--regexp' are mutually exclusive
|
||||
--
|
||||
ERR_MSG
|
||||
}
|
||||
|
||||
@test 'assert_line() --regexp <regexp>: returns 1 and displays an error message if <regexp> is not a valid extended regular expression' {
|
||||
run assert_line --regexp '[.*'
|
||||
|
||||
assert_test_fail <<'ERR_MSG'
|
||||
|
||||
-- ERROR: assert_line --
|
||||
Invalid extended regular expression: `[.*'
|
||||
--
|
||||
ERR_MSG
|
||||
}
|
||||
|
||||
@test "assert_line(): \`--' stops parsing options" {
|
||||
run printf 'a\n-p\nc'
|
||||
run assert_line -- '-p'
|
||||
assert_test_pass
|
||||
}
|
285
lib/bats-assert/test/assert_output.bats
Executable file
285
lib/bats-assert/test/assert_output.bats
Executable file
@ -0,0 +1,285 @@
|
||||
#!/usr/bin/env bats
|
||||
|
||||
load test_helper
|
||||
|
||||
#
|
||||
# Literal matching
|
||||
#
|
||||
|
||||
# Correctness
|
||||
@test "assert_output() <expected>: returns 0 if <expected> equals \`\$output'" {
|
||||
run echo 'a'
|
||||
run assert_output 'a'
|
||||
assert_test_pass
|
||||
}
|
||||
|
||||
@test "assert_output() <expected>: returns 1 and displays details if <expected> does not equal \`\$output'" {
|
||||
run echo 'b'
|
||||
run assert_output 'a'
|
||||
|
||||
assert_test_fail <<'ERR_MSG'
|
||||
|
||||
-- output differs --
|
||||
expected : a
|
||||
actual : b
|
||||
--
|
||||
ERR_MSG
|
||||
}
|
||||
|
||||
@test 'assert_output(): succeeds if output is non-empty' {
|
||||
run echo 'a'
|
||||
run assert_output
|
||||
|
||||
assert_test_pass
|
||||
}
|
||||
|
||||
@test 'assert_output(): fails if output is empty' {
|
||||
run echo ''
|
||||
run assert_output
|
||||
|
||||
assert_test_fail <<'ERR_MSG'
|
||||
|
||||
-- no output --
|
||||
expected non-empty output, but output was empty
|
||||
--
|
||||
ERR_MSG
|
||||
}
|
||||
|
||||
@test 'assert_output() - : reads <expected> from STDIN' {
|
||||
run echo 'a'
|
||||
run assert_output - <<STDIN
|
||||
a
|
||||
STDIN
|
||||
|
||||
assert_test_pass
|
||||
}
|
||||
|
||||
@test 'assert_output() --stdin : reads <expected> from STDIN' {
|
||||
run echo 'a'
|
||||
run assert_output --stdin <<STDIN
|
||||
a
|
||||
STDIN
|
||||
|
||||
assert_test_pass
|
||||
}
|
||||
|
||||
# Output formatting
|
||||
@test "assert_output() <expected>: displays details in multi-line format if \`\$output' is longer than one line" {
|
||||
run printf 'b 0\nb 1'
|
||||
run assert_output 'a'
|
||||
|
||||
assert_test_fail <<'ERR_MSG'
|
||||
|
||||
-- output differs --
|
||||
expected (1 lines):
|
||||
a
|
||||
actual (2 lines):
|
||||
b 0
|
||||
b 1
|
||||
--
|
||||
ERR_MSG
|
||||
}
|
||||
|
||||
@test 'assert_output() <expected>: displays details in multi-line format if <expected> is longer than one line' {
|
||||
run echo 'b'
|
||||
run assert_output $'a 0\na 1'
|
||||
|
||||
assert_test_fail <<'ERR_MSG'
|
||||
|
||||
-- output differs --
|
||||
expected (2 lines):
|
||||
a 0
|
||||
a 1
|
||||
actual (1 lines):
|
||||
b
|
||||
--
|
||||
ERR_MSG
|
||||
}
|
||||
|
||||
# Options
|
||||
@test 'assert_output() <expected>: performs literal matching by default' {
|
||||
run echo 'a'
|
||||
run assert_output '*'
|
||||
|
||||
assert_test_fail <<'ERR_MSG'
|
||||
|
||||
-- output differs --
|
||||
expected : *
|
||||
actual : a
|
||||
--
|
||||
ERR_MSG
|
||||
}
|
||||
|
||||
|
||||
#
|
||||
# Partial matching: `-p' and `--partial'
|
||||
#
|
||||
|
||||
@test 'assert_output() -p <partial>: enables partial matching' {
|
||||
run echo 'abc'
|
||||
run assert_output -p 'b'
|
||||
assert_test_pass
|
||||
}
|
||||
|
||||
@test 'assert_output() --partial <partial>: enables partial matching' {
|
||||
run echo 'abc'
|
||||
run assert_output --partial 'b'
|
||||
assert_test_pass
|
||||
}
|
||||
|
||||
# Correctness
|
||||
@test "assert_output() --partial <partial>: returns 0 if <partial> is a substring in \`\$output'" {
|
||||
run printf 'a\nb\nc'
|
||||
run assert_output --partial 'b'
|
||||
assert_test_pass
|
||||
}
|
||||
|
||||
@test "assert_output() --partial <partial>: returns 1 and displays details if <partial> is not a substring in \`\$output'" {
|
||||
run echo 'b'
|
||||
run assert_output --partial 'a'
|
||||
|
||||
assert_test_fail <<'ERR_MSG'
|
||||
|
||||
-- output does not contain substring --
|
||||
substring : a
|
||||
output : b
|
||||
--
|
||||
ERR_MSG
|
||||
}
|
||||
|
||||
# Output formatting
|
||||
@test "assert_output() --partial <partial>: displays details in multi-line format if \`\$output' is longer than one line" {
|
||||
run printf 'b 0\nb 1'
|
||||
run assert_output --partial 'a'
|
||||
|
||||
assert_test_fail <<'ERR_MSG'
|
||||
|
||||
-- output does not contain substring --
|
||||
substring (1 lines):
|
||||
a
|
||||
output (2 lines):
|
||||
b 0
|
||||
b 1
|
||||
--
|
||||
ERR_MSG
|
||||
}
|
||||
|
||||
@test 'assert_output() --partial <partial>: displays details in multi-line format if <partial> is longer than one line' {
|
||||
run echo 'b'
|
||||
run assert_output --partial $'a 0\na 1'
|
||||
|
||||
assert_test_fail <<'ERR_MSG'
|
||||
|
||||
-- output does not contain substring --
|
||||
substring (2 lines):
|
||||
a 0
|
||||
a 1
|
||||
output (1 lines):
|
||||
b
|
||||
--
|
||||
ERR_MSG
|
||||
}
|
||||
|
||||
|
||||
#
|
||||
# Regular expression matching: `-e' and `--regexp'
|
||||
#
|
||||
|
||||
@test 'assert_output() -e <regexp>: enables regular expression matching' {
|
||||
run echo 'abc'
|
||||
run assert_output -e '^a'
|
||||
assert_test_pass
|
||||
}
|
||||
|
||||
@test 'assert_output() --regexp <regexp>: enables regular expression matching' {
|
||||
run echo 'abc'
|
||||
run assert_output --regexp '^a'
|
||||
assert_test_pass
|
||||
}
|
||||
|
||||
# Correctness
|
||||
@test "assert_output() --regexp <regexp>: returns 0 if <regexp> matches \`\$output'" {
|
||||
run printf 'a\nb\nc'
|
||||
run assert_output --regexp '.*b.*'
|
||||
assert_test_pass
|
||||
}
|
||||
|
||||
@test "assert_output() --regexp <regexp>: returns 1 and displays details if <regexp> does not match \`\$output'" {
|
||||
run echo 'b'
|
||||
run assert_output --regexp '.*a.*'
|
||||
|
||||
assert_test_fail <<'ERR_MSG'
|
||||
|
||||
-- regular expression does not match output --
|
||||
regexp : .*a.*
|
||||
output : b
|
||||
--
|
||||
ERR_MSG
|
||||
}
|
||||
|
||||
# Output formatting
|
||||
@test "assert_output() --regexp <regexp>: displays details in multi-line format if \`\$output' is longer than one line" {
|
||||
run printf 'b 0\nb 1'
|
||||
run assert_output --regexp '.*a.*'
|
||||
|
||||
assert_test_fail <<'ERR_MSG'
|
||||
|
||||
-- regular expression does not match output --
|
||||
regexp (1 lines):
|
||||
.*a.*
|
||||
output (2 lines):
|
||||
b 0
|
||||
b 1
|
||||
--
|
||||
ERR_MSG
|
||||
}
|
||||
|
||||
@test 'assert_output() --regexp <regexp>: displays details in multi-line format if <regexp> is longer than one line' {
|
||||
run echo 'b'
|
||||
run assert_output --regexp $'.*a\nb.*'
|
||||
|
||||
assert_test_fail <<'ERR_MSG'
|
||||
|
||||
-- regular expression does not match output --
|
||||
regexp (2 lines):
|
||||
.*a
|
||||
b.*
|
||||
output (1 lines):
|
||||
b
|
||||
--
|
||||
ERR_MSG
|
||||
}
|
||||
|
||||
# Error handling
|
||||
@test 'assert_output() --regexp <regexp>: returns 1 and displays an error message if <regexp> is not a valid extended regular expression' {
|
||||
run assert_output --regexp '[.*'
|
||||
|
||||
assert_test_fail <<'ERR_MSG'
|
||||
|
||||
-- ERROR: assert_output --
|
||||
Invalid extended regular expression: `[.*'
|
||||
--
|
||||
ERR_MSG
|
||||
}
|
||||
|
||||
|
||||
#
|
||||
# Common
|
||||
#
|
||||
|
||||
@test "assert_output(): \`--partial' and \`--regexp' are mutually exclusive" {
|
||||
run assert_output --partial --regexp
|
||||
|
||||
assert_test_fail <<'ERR_MSG'
|
||||
|
||||
-- ERROR: assert_output --
|
||||
`--partial' and `--regexp' are mutually exclusive
|
||||
--
|
||||
ERR_MSG
|
||||
}
|
||||
|
||||
@test "assert_output(): \`--' stops parsing options" {
|
||||
run echo '-p'
|
||||
run assert_output -- '-p'
|
||||
assert_test_pass
|
||||
}
|
40
lib/bats-assert/test/assert_success.bats
Executable file
40
lib/bats-assert/test/assert_success.bats
Executable file
@ -0,0 +1,40 @@
|
||||
#!/usr/bin/env bats
|
||||
|
||||
load test_helper
|
||||
|
||||
@test "assert_success(): returns 0 if \`\$status' is 0" {
|
||||
run true
|
||||
run assert_success
|
||||
|
||||
assert_test_pass
|
||||
}
|
||||
|
||||
@test "assert_success(): returns 1 and displays details if \`\$status' is not 0" {
|
||||
run bash -c 'echo "a"
|
||||
exit 1'
|
||||
run assert_success
|
||||
|
||||
assert_test_fail <<'ERR_MSG'
|
||||
|
||||
-- command failed --
|
||||
status : 1
|
||||
output : a
|
||||
--
|
||||
ERR_MSG
|
||||
}
|
||||
|
||||
@test "assert_success(): displays \`\$output' in multi-line format if it is longer than one line" {
|
||||
run bash -c 'printf "a 0\na 1"
|
||||
exit 1'
|
||||
run assert_success
|
||||
|
||||
assert_test_fail <<'ERR_MSG'
|
||||
|
||||
-- command failed --
|
||||
status : 1
|
||||
output (2 lines):
|
||||
a 0
|
||||
a 1
|
||||
--
|
||||
ERR_MSG
|
||||
}
|
18
lib/bats-assert/test/refute.bats
Executable file
18
lib/bats-assert/test/refute.bats
Executable file
@ -0,0 +1,18 @@
|
||||
#!/usr/bin/env bats
|
||||
|
||||
load test_helper
|
||||
|
||||
@test 'refute() <expression>: returns 0 if <expression> evaluates to FALSE' {
|
||||
run refute false
|
||||
assert_test_pass
|
||||
}
|
||||
|
||||
@test 'refute() <expression>: returns 1 and displays <expression> if it evaluates to TRUE' {
|
||||
run refute true
|
||||
assert_test_fail <<'ERR_MSG'
|
||||
|
||||
-- assertion succeeded, but it was expected to fail --
|
||||
expression : true
|
||||
--
|
||||
ERR_MSG
|
||||
}
|
344
lib/bats-assert/test/refute_line.bats
Executable file
344
lib/bats-assert/test/refute_line.bats
Executable file
@ -0,0 +1,344 @@
|
||||
#!/usr/bin/env bats
|
||||
|
||||
load test_helper
|
||||
|
||||
|
||||
###############################################################################
|
||||
# Containing a line
|
||||
###############################################################################
|
||||
|
||||
#
|
||||
# Literal matching
|
||||
#
|
||||
|
||||
# Correctness
|
||||
@test "refute_line() <unexpected>: returns 0 if <unexpected> is not a line in \`\${lines[@]}'" {
|
||||
run printf 'a\nb\nc'
|
||||
run refute_line 'd'
|
||||
assert_test_pass
|
||||
}
|
||||
|
||||
@test "refute_line() <unexpected>: returns 1 and displays details if <unexpected> is not a line in \`\${lines[@]}'" {
|
||||
run echo 'a'
|
||||
run refute_line 'a'
|
||||
|
||||
assert_test_fail <<'ERR_MSG'
|
||||
|
||||
-- line should not be in output --
|
||||
line : a
|
||||
index : 0
|
||||
output : a
|
||||
--
|
||||
ERR_MSG
|
||||
}
|
||||
|
||||
# Output formatting
|
||||
@test "refute_line() <unexpected>: displays \`\$output' in multi-line format if it is longer than one line" {
|
||||
run printf 'a 0\na 1\na 2'
|
||||
run refute_line 'a 1'
|
||||
|
||||
assert_test_fail <<'ERR_MSG'
|
||||
|
||||
-- line should not be in output --
|
||||
line : a 1
|
||||
index : 1
|
||||
output (3 lines):
|
||||
a 0
|
||||
> a 1
|
||||
a 2
|
||||
--
|
||||
ERR_MSG
|
||||
}
|
||||
|
||||
# Options
|
||||
@test 'refute_line() <unexpected>: performs literal matching by default' {
|
||||
run echo 'a'
|
||||
run refute_line '*'
|
||||
assert_test_pass
|
||||
}
|
||||
|
||||
|
||||
#
|
||||
# Partial matching: `-p' and `--partial'
|
||||
#
|
||||
|
||||
# Options
|
||||
@test 'refute_line() -p <partial>: enables partial matching' {
|
||||
run printf 'a\nb\nc'
|
||||
run refute_line -p 'd'
|
||||
assert_test_pass
|
||||
}
|
||||
|
||||
@test 'refute_line() --partial <partial>: enables partial matching' {
|
||||
run printf 'a\nb\nc'
|
||||
run refute_line --partial 'd'
|
||||
assert_test_pass
|
||||
}
|
||||
|
||||
# Correctness
|
||||
@test "refute_line() --partial <partial>: returns 0 if <partial> is not a substring in any line in \`\${lines[@]}'" {
|
||||
run printf 'a\nb\nc'
|
||||
run refute_line --partial 'd'
|
||||
assert_test_pass
|
||||
}
|
||||
|
||||
@test "refute_line() --partial <partial>: returns 1 and displays details if <partial> is a substring in any line in \`\${lines[@]}'" {
|
||||
run echo 'a'
|
||||
run refute_line --partial 'a'
|
||||
|
||||
assert_test_fail <<'ERR_MSG'
|
||||
|
||||
-- no line should contain substring --
|
||||
substring : a
|
||||
index : 0
|
||||
output : a
|
||||
--
|
||||
ERR_MSG
|
||||
}
|
||||
|
||||
# Output formatting
|
||||
@test "refute_line() --partial <partial>: displays \`\$output' in multi-line format if it is longer than one line" {
|
||||
run printf 'a\nabc\nc'
|
||||
run refute_line --partial 'b'
|
||||
|
||||
assert_test_fail <<'ERR_MSG'
|
||||
|
||||
-- no line should contain substring --
|
||||
substring : b
|
||||
index : 1
|
||||
output (3 lines):
|
||||
a
|
||||
> abc
|
||||
c
|
||||
--
|
||||
ERR_MSG
|
||||
}
|
||||
|
||||
|
||||
#
|
||||
# Regular expression matching: `-e' and `--regexp'
|
||||
#
|
||||
|
||||
# Options
|
||||
@test 'refute_line() -e <regexp>: enables regular expression matching' {
|
||||
run printf 'a\nb\nc'
|
||||
run refute_line -e '^.d'
|
||||
assert_test_pass
|
||||
}
|
||||
|
||||
@test 'refute_line() --regexp <regexp>: enables regular expression matching' {
|
||||
run printf 'a\nb\nc'
|
||||
run refute_line --regexp '^.d'
|
||||
assert_test_pass
|
||||
}
|
||||
|
||||
# Correctness
|
||||
@test "refute_line() --regexp <regexp>: returns 0 if <regexp> does not match any line in \`\${lines[@]}'" {
|
||||
run printf 'a\nb\nc'
|
||||
run refute_line --regexp '.*d.*'
|
||||
assert_test_pass
|
||||
}
|
||||
|
||||
@test "refute_line() --regexp <regexp>: returns 1 and displays details if <regexp> matches any lines in \`\${lines[@]}'" {
|
||||
run echo 'a'
|
||||
run refute_line --regexp '.*a.*'
|
||||
|
||||
assert_test_fail <<'ERR_MSG'
|
||||
|
||||
-- no line should match the regular expression --
|
||||
regexp : .*a.*
|
||||
index : 0
|
||||
output : a
|
||||
--
|
||||
ERR_MSG
|
||||
}
|
||||
|
||||
# Output formatting
|
||||
@test "refute_line() --regexp <regexp>: displays \`\$output' in multi-line format if longer than one line" {
|
||||
run printf 'a\nabc\nc'
|
||||
run refute_line --regexp '.*b.*'
|
||||
|
||||
assert_test_fail <<'ERR_MSG'
|
||||
|
||||
-- no line should match the regular expression --
|
||||
regexp : .*b.*
|
||||
index : 1
|
||||
output (3 lines):
|
||||
a
|
||||
> abc
|
||||
c
|
||||
--
|
||||
ERR_MSG
|
||||
}
|
||||
|
||||
|
||||
###############################################################################
|
||||
# Matching single line: `-n' and `--index'
|
||||
###############################################################################
|
||||
|
||||
# Options
|
||||
@test 'refute_line() -n <idx> <expected>: matches against the <idx>-th line only' {
|
||||
run printf 'a\nb\nc'
|
||||
run refute_line -n 1 'd'
|
||||
assert_test_pass
|
||||
}
|
||||
|
||||
@test 'refute_line() --index <idx> <expected>: matches against the <idx>-th line only' {
|
||||
run printf 'a\nb\nc'
|
||||
run refute_line --index 1 'd'
|
||||
assert_test_pass
|
||||
}
|
||||
|
||||
@test 'refute_line() --index <idx>: returns 1 and displays an error message if <idx> is not an integer' {
|
||||
run refute_line --index 1a
|
||||
|
||||
assert_test_fail <<'ERR_MSG'
|
||||
|
||||
-- ERROR: refute_line --
|
||||
`--index' requires an integer argument: `1a'
|
||||
--
|
||||
ERR_MSG
|
||||
}
|
||||
|
||||
|
||||
#
|
||||
# Literal matching
|
||||
#
|
||||
|
||||
# Correctness
|
||||
@test "refute_line() --index <idx> <unexpected>: returns 0 if <unexpected> does not equal \`\${lines[<idx>]}'" {
|
||||
run printf 'a\nb\nc'
|
||||
run refute_line --index 1 'd'
|
||||
assert_test_pass
|
||||
}
|
||||
|
||||
@test "refute_line() --index <idx> <unexpected>: returns 1 and displays details if <unexpected> equals \`\${lines[<idx>]}'" {
|
||||
run printf 'a\nb\nc'
|
||||
run refute_line --index 1 'b'
|
||||
|
||||
assert_test_fail <<'ERR_MSG'
|
||||
|
||||
-- line should differ --
|
||||
index : 1
|
||||
line : b
|
||||
--
|
||||
ERR_MSG
|
||||
}
|
||||
|
||||
# Options
|
||||
@test 'refute_line() --index <idx> <unexpected>: performs literal matching by default' {
|
||||
run printf 'a\nb\nc'
|
||||
run refute_line --index 1 '*'
|
||||
assert_test_pass
|
||||
}
|
||||
|
||||
|
||||
#
|
||||
# Partial matching: `-p' and `--partial'
|
||||
#
|
||||
|
||||
# Options
|
||||
@test 'refute_line() --index <idx> -p <partial>: enables partial matching' {
|
||||
run printf 'a\nb\nc'
|
||||
run refute_line --index 1 -p 'd'
|
||||
assert_test_pass
|
||||
}
|
||||
|
||||
@test 'refute_line() --index <idx> --partial <partial>: enables partial matching' {
|
||||
run printf 'a\nb\nc'
|
||||
run refute_line --index 1 --partial 'd'
|
||||
assert_test_pass
|
||||
}
|
||||
|
||||
# Correctness
|
||||
@test "refute_line() --index <idx> --partial <partial>: returns 0 if <partial> is not a substring in \`\${lines[<idx>]}'" {
|
||||
run printf 'a\nabc\nc'
|
||||
run refute_line --index 1 --partial 'd'
|
||||
assert_test_pass
|
||||
}
|
||||
|
||||
@test "refute_line() --index <idx> --partial <partial>: returns 1 and displays details if <partial> is a substring in \`\${lines[<idx>]}'" {
|
||||
run printf 'a\nabc\nc'
|
||||
run refute_line --index 1 --partial 'b'
|
||||
|
||||
assert_test_fail <<'ERR_MSG'
|
||||
|
||||
-- line should not contain substring --
|
||||
index : 1
|
||||
substring : b
|
||||
line : abc
|
||||
--
|
||||
ERR_MSG
|
||||
}
|
||||
|
||||
|
||||
#
|
||||
# Regular expression matching: `-e' and `--regexp'
|
||||
#
|
||||
|
||||
# Options
|
||||
@test 'refute_line() --index <idx> -e <regexp>: enables regular expression matching' {
|
||||
run printf 'a\nb\nc'
|
||||
run refute_line --index 1 -e '^.b'
|
||||
assert_test_pass
|
||||
}
|
||||
|
||||
@test 'refute_line() --index <idx> --regexp <regexp>: enables regular expression matching' {
|
||||
run printf 'a\nb\nc'
|
||||
run refute_line --index 1 --regexp '^.b'
|
||||
assert_test_pass
|
||||
}
|
||||
|
||||
# Correctness
|
||||
@test "refute_line() --index <idx> --regexp <regexp>: returns 0 if <regexp> does not match \`\${lines[<idx>]}'" {
|
||||
run printf 'a\nabc\nc'
|
||||
run refute_line --index 1 --regexp '.*d.*'
|
||||
assert_test_pass
|
||||
}
|
||||
|
||||
@test "refute_line() --index <idx> --regexp <regexp>: returns 1 and displays details if <regexp> matches \`\${lines[<idx>]}'" {
|
||||
run printf 'a\nabc\nc'
|
||||
run refute_line --index 1 --regexp '.*b.*'
|
||||
|
||||
assert_test_fail <<'ERR_MSG'
|
||||
|
||||
-- regular expression should not match line --
|
||||
index : 1
|
||||
regexp : .*b.*
|
||||
line : abc
|
||||
--
|
||||
ERR_MSG
|
||||
}
|
||||
|
||||
|
||||
###############################################################################
|
||||
# Common
|
||||
###############################################################################
|
||||
|
||||
@test "refute_line(): \`--partial' and \`--regexp' are mutually exclusive" {
|
||||
run refute_line --partial --regexp
|
||||
|
||||
assert_test_fail <<'ERR_MSG'
|
||||
|
||||
-- ERROR: refute_line --
|
||||
`--partial' and `--regexp' are mutually exclusive
|
||||
--
|
||||
ERR_MSG
|
||||
}
|
||||
|
||||
@test 'refute_line() --regexp <regexp>: returns 1 and displays an error message if <regexp> is not a valid extended regular expression' {
|
||||
run refute_line --regexp '[.*'
|
||||
|
||||
assert_test_fail <<'ERR_MSG'
|
||||
|
||||
-- ERROR: refute_line --
|
||||
Invalid extended regular expression: `[.*'
|
||||
--
|
||||
ERR_MSG
|
||||
}
|
||||
|
||||
@test "refute_line(): \`--' stops parsing options" {
|
||||
run printf 'a\n--\nc'
|
||||
run refute_line -- '-p'
|
||||
assert_test_pass
|
||||
}
|
230
lib/bats-assert/test/refute_output.bats
Executable file
230
lib/bats-assert/test/refute_output.bats
Executable file
@ -0,0 +1,230 @@
|
||||
#!/usr/bin/env bats
|
||||
|
||||
load test_helper
|
||||
|
||||
|
||||
#
|
||||
# Literal matching
|
||||
#
|
||||
|
||||
# Correctness
|
||||
@test "refute_output() <unexpected>: returns 0 if <unexpected> does not equal \`\$output'" {
|
||||
run echo 'b'
|
||||
run refute_output 'a'
|
||||
assert_test_pass
|
||||
}
|
||||
|
||||
@test "refute_output() <unexpected>: returns 1 and displays details if <unexpected> equals \`\$output'" {
|
||||
run echo 'a'
|
||||
run refute_output 'a'
|
||||
|
||||
assert_test_fail <<'ERR_MSG'
|
||||
|
||||
-- output equals, but it was expected to differ --
|
||||
output : a
|
||||
--
|
||||
ERR_MSG
|
||||
}
|
||||
|
||||
@test 'refute_output(): succeeds if output is empty' {
|
||||
run echo ''
|
||||
run refute_output
|
||||
|
||||
assert_test_pass
|
||||
}
|
||||
|
||||
@test 'refute_output(): fails if output is non-empty' {
|
||||
run echo 'a'
|
||||
run refute_output
|
||||
|
||||
assert_test_fail <<'ERR_MSG'
|
||||
|
||||
-- output non-empty, but expected no output --
|
||||
output : a
|
||||
--
|
||||
ERR_MSG
|
||||
}
|
||||
|
||||
@test 'refute_output() - : reads <unexpected> from STDIN' {
|
||||
run echo '-'
|
||||
run refute_output - <<INPUT
|
||||
b
|
||||
INPUT
|
||||
|
||||
assert_test_pass
|
||||
}
|
||||
|
||||
@test 'refute_output() --stdin : reads <unexpected> from STDIN' {
|
||||
run echo '--stdin'
|
||||
run refute_output --stdin <<INPUT
|
||||
b
|
||||
INPUT
|
||||
|
||||
assert_test_pass
|
||||
}
|
||||
|
||||
# Output formatting
|
||||
@test 'refute_output() <unexpected>: displays details in multi-line format if necessary' {
|
||||
run printf 'a 0\na 1'
|
||||
run refute_output $'a 0\na 1'
|
||||
|
||||
assert_test_fail <<'ERR_MSG'
|
||||
|
||||
-- output equals, but it was expected to differ --
|
||||
output (2 lines):
|
||||
a 0
|
||||
a 1
|
||||
--
|
||||
ERR_MSG
|
||||
}
|
||||
|
||||
# Options
|
||||
@test 'refute_output() <unexpected>: performs literal matching by default' {
|
||||
run echo 'a'
|
||||
run refute_output '*'
|
||||
assert_test_pass
|
||||
}
|
||||
|
||||
|
||||
#
|
||||
# Partial matching: `-p' and `--partial'
|
||||
#
|
||||
|
||||
# Options
|
||||
@test 'refute_output() -p <partial>: enables partial matching' {
|
||||
run echo 'abc'
|
||||
run refute_output -p 'd'
|
||||
assert_test_pass
|
||||
}
|
||||
|
||||
@test 'refute_output() --partial <partial>: enables partial matching' {
|
||||
run echo 'abc'
|
||||
run refute_output --partial 'd'
|
||||
assert_test_pass
|
||||
}
|
||||
|
||||
# Correctness
|
||||
@test "refute_output() --partial <partial>: returns 0 if <partial> is not a substring in \`\$output'" {
|
||||
run printf 'a\nb\nc'
|
||||
run refute_output --partial 'd'
|
||||
assert_test_pass
|
||||
}
|
||||
|
||||
@test "refute_output() --partial <partial>: returns 1 and displays details if <partial> is a substring in \`\$output'" {
|
||||
run echo 'a'
|
||||
run refute_output --partial 'a'
|
||||
|
||||
assert_test_fail <<'ERR_MSG'
|
||||
|
||||
-- output should not contain substring --
|
||||
substring : a
|
||||
output : a
|
||||
--
|
||||
ERR_MSG
|
||||
}
|
||||
|
||||
# Output formatting
|
||||
@test 'refute_output() --partial <partial>: displays details in multi-line format if necessary' {
|
||||
run printf 'a 0\na 1'
|
||||
run refute_output --partial 'a'
|
||||
|
||||
assert_test_fail <<'ERR_MSG'
|
||||
|
||||
-- output should not contain substring --
|
||||
substring (1 lines):
|
||||
a
|
||||
output (2 lines):
|
||||
a 0
|
||||
a 1
|
||||
--
|
||||
ERR_MSG
|
||||
}
|
||||
|
||||
|
||||
#
|
||||
# Regular expression matching: `-e' and `--regexp'
|
||||
#
|
||||
|
||||
# Options
|
||||
@test 'refute_output() -e <regexp>: enables regular expression matching' {
|
||||
run echo 'abc'
|
||||
run refute_output -e '^d'
|
||||
assert_test_pass
|
||||
}
|
||||
|
||||
@test 'refute_output() --regexp <regexp>: enables regular expression matching' {
|
||||
run echo 'abc'
|
||||
run refute_output --regexp '^d'
|
||||
assert_test_pass
|
||||
}
|
||||
|
||||
# Correctness
|
||||
@test "refute_output() --regexp <regexp>: returns 0 if <regexp> does not match \`\$output'" {
|
||||
run printf 'a\nb\nc'
|
||||
run refute_output --regexp '.*d.*'
|
||||
assert_test_pass
|
||||
}
|
||||
|
||||
@test "refute_output() --regexp <regexp>: returns 1 and displays details if <regexp> matches \`\$output'" {
|
||||
run echo 'a'
|
||||
run refute_output --regexp '.*a.*'
|
||||
|
||||
assert_test_fail <<'ERR_MSG'
|
||||
|
||||
-- regular expression should not match output --
|
||||
regexp : .*a.*
|
||||
output : a
|
||||
--
|
||||
ERR_MSG
|
||||
}
|
||||
|
||||
# Output formatting
|
||||
@test 'refute_output() --regexp <regexp>: displays details in multi-line format if necessary' {
|
||||
run printf 'a 0\na 1'
|
||||
run refute_output --regexp '.*a.*'
|
||||
|
||||
assert_test_fail <<'ERR_MSG'
|
||||
|
||||
-- regular expression should not match output --
|
||||
regexp (1 lines):
|
||||
.*a.*
|
||||
output (2 lines):
|
||||
a 0
|
||||
a 1
|
||||
--
|
||||
ERR_MSG
|
||||
}
|
||||
|
||||
# Error handling
|
||||
@test 'refute_output() --regexp <regexp>: returns 1 and displays an error message if <regexp> is not a valid extended regular expression' {
|
||||
run refute_output --regexp '[.*'
|
||||
|
||||
assert_test_fail <<'ERR_MSG'
|
||||
|
||||
-- ERROR: refute_output --
|
||||
Invalid extended regular expression: `[.*'
|
||||
--
|
||||
ERR_MSG
|
||||
}
|
||||
|
||||
|
||||
#
|
||||
# Common
|
||||
#
|
||||
|
||||
@test "refute_output(): \`--partial' and \`--regexp' are mutually exclusive" {
|
||||
run refute_output --partial --regexp
|
||||
|
||||
assert_test_fail <<'ERR_MSG'
|
||||
|
||||
-- ERROR: refute_output --
|
||||
`--partial' and `--regexp' are mutually exclusive
|
||||
--
|
||||
ERR_MSG
|
||||
}
|
||||
|
||||
@test "refute_output(): \`--' stops parsing options" {
|
||||
run echo '--'
|
||||
run refute_output -- '-p'
|
||||
assert_test_pass
|
||||
}
|
27
lib/bats-assert/test/test_helper.bash
Normal file
27
lib/bats-assert/test/test_helper.bash
Normal file
@ -0,0 +1,27 @@
|
||||
# Load dependencies.
|
||||
load "${BATS_TEST_DIRNAME}/../node_modules/bats-support/load.bash"
|
||||
|
||||
# Load library.
|
||||
load '../load'
|
||||
|
||||
# validate that bats-assert is safe to use under -u
|
||||
set -u
|
||||
|
||||
: "${status:=}"
|
||||
: "${lines:=}"
|
||||
: "${output:=}"
|
||||
|
||||
assert_test_pass() {
|
||||
test "$status" -eq 0
|
||||
test "${#lines[@]}" -eq 0
|
||||
}
|
||||
|
||||
assert_test_fail() {
|
||||
local err_msg="${1-$(cat -)}"
|
||||
local num_lines
|
||||
num_lines="$(printf '%s' "$err_msg" | wc -l)"
|
||||
|
||||
test "$status" -eq 1
|
||||
test "${#lines[@]}" -eq "$num_lines"
|
||||
test "$output" == "$err_msg"
|
||||
}
|
4
lib/bats-support/.gitignore
vendored
Normal file
4
lib/bats-support/.gitignore
vendored
Normal file
@ -0,0 +1,4 @@
|
||||
/node_modules
|
||||
/package-lock.json
|
||||
/yarn.lock
|
||||
/bats-support-*.tgz
|
3
lib/bats-support/.travis.yml
Normal file
3
lib/bats-support/.travis.yml
Normal file
@ -0,0 +1,3 @@
|
||||
language: node_js
|
||||
node_js: node
|
||||
cache: npm
|
46
lib/bats-support/CHANGELOG.md
Normal file
46
lib/bats-support/CHANGELOG.md
Normal file
@ -0,0 +1,46 @@
|
||||
# Change Log
|
||||
|
||||
All notable changes to this project will be documented in this file.
|
||||
This project adheres to [Semantic Versioning](http://semver.org/).
|
||||
|
||||
|
||||
## [0.3.0] - 2016-11-29
|
||||
|
||||
### Added
|
||||
|
||||
- Restricting invocation to specific locations with
|
||||
`batslib_is_caller()`
|
||||
|
||||
|
||||
## [0.2.0] - 2016-03-22
|
||||
|
||||
### Added
|
||||
|
||||
- `npm` support
|
||||
- Reporting arbitrary failures with `fail()` (moved from `bats-assert`)
|
||||
|
||||
### Changed
|
||||
|
||||
- Library renamed to `bats-support`
|
||||
|
||||
|
||||
## 0.1.0 - 2016-02-16
|
||||
|
||||
### Added
|
||||
|
||||
- Two-column key-value formatting with `batslib_print_kv_single()`
|
||||
- Multi-line key-value formatting with `batslib_print_kv_multi()`
|
||||
- Mixed formatting with `batslib_print_kv_single_or_multi()`
|
||||
- Header and footer decoration with `batslib_decorate()`
|
||||
- Prefixing lines with `batslib_prefix()`
|
||||
- Marking lines with `batslib_mark()`
|
||||
- Common output function `batslib_err()`
|
||||
- Line counting with `batslib_count_lines()`
|
||||
- Checking whether a text is one line long with
|
||||
`batslib_is_single_line()`
|
||||
- Determining key width for two-column and mixed formatting with
|
||||
`batslib_get_max_single_line_key_width()`
|
||||
|
||||
|
||||
[0.3.0]: https://github.com/ztombol/bats-support/compare/v0.2.0...v0.3.0
|
||||
[0.2.0]: https://github.com/ztombol/bats-support/compare/v0.1.0...v0.2.0
|
116
lib/bats-support/LICENSE
Normal file
116
lib/bats-support/LICENSE
Normal file
@ -0,0 +1,116 @@
|
||||
CC0 1.0 Universal
|
||||
|
||||
Statement of Purpose
|
||||
|
||||
The laws of most jurisdictions throughout the world automatically confer
|
||||
exclusive Copyright and Related Rights (defined below) upon the creator and
|
||||
subsequent owner(s) (each and all, an "owner") of an original work of
|
||||
authorship and/or a database (each, a "Work").
|
||||
|
||||
Certain owners wish to permanently relinquish those rights to a Work for the
|
||||
purpose of contributing to a commons of creative, cultural and scientific
|
||||
works ("Commons") that the public can reliably and without fear of later
|
||||
claims of infringement build upon, modify, incorporate in other works, reuse
|
||||
and redistribute as freely as possible in any form whatsoever and for any
|
||||
purposes, including without limitation commercial purposes. These owners may
|
||||
contribute to the Commons to promote the ideal of a free culture and the
|
||||
further production of creative, cultural and scientific works, or to gain
|
||||
reputation or greater distribution for their Work in part through the use and
|
||||
efforts of others.
|
||||
|
||||
For these and/or other purposes and motivations, and without any expectation
|
||||
of additional consideration or compensation, the person associating CC0 with a
|
||||
Work (the "Affirmer"), to the extent that he or she is an owner of Copyright
|
||||
and Related Rights in the Work, voluntarily elects to apply CC0 to the Work
|
||||
and publicly distribute the Work under its terms, with knowledge of his or her
|
||||
Copyright and Related Rights in the Work and the meaning and intended legal
|
||||
effect of CC0 on those rights.
|
||||
|
||||
1. Copyright and Related Rights. A Work made available under CC0 may be
|
||||
protected by copyright and related or neighboring rights ("Copyright and
|
||||
Related Rights"). Copyright and Related Rights include, but are not limited
|
||||
to, the following:
|
||||
|
||||
i. the right to reproduce, adapt, distribute, perform, display, communicate,
|
||||
and translate a Work;
|
||||
|
||||
ii. moral rights retained by the original author(s) and/or performer(s);
|
||||
|
||||
iii. publicity and privacy rights pertaining to a person's image or likeness
|
||||
depicted in a Work;
|
||||
|
||||
iv. rights protecting against unfair competition in regards to a Work,
|
||||
subject to the limitations in paragraph 4(a), below;
|
||||
|
||||
v. rights protecting the extraction, dissemination, use and reuse of data in
|
||||
a Work;
|
||||
|
||||
vi. database rights (such as those arising under Directive 96/9/EC of the
|
||||
European Parliament and of the Council of 11 March 1996 on the legal
|
||||
protection of databases, and under any national implementation thereof,
|
||||
including any amended or successor version of such directive); and
|
||||
|
||||
vii. other similar, equivalent or corresponding rights throughout the world
|
||||
based on applicable law or treaty, and any national implementations thereof.
|
||||
|
||||
2. Waiver. To the greatest extent permitted by, but not in contravention of,
|
||||
applicable law, Affirmer hereby overtly, fully, permanently, irrevocably and
|
||||
unconditionally waives, abandons, and surrenders all of Affirmer's Copyright
|
||||
and Related Rights and associated claims and causes of action, whether now
|
||||
known or unknown (including existing as well as future claims and causes of
|
||||
action), in the Work (i) in all territories worldwide, (ii) for the maximum
|
||||
duration provided by applicable law or treaty (including future time
|
||||
extensions), (iii) in any current or future medium and for any number of
|
||||
copies, and (iv) for any purpose whatsoever, including without limitation
|
||||
commercial, advertising or promotional purposes (the "Waiver"). Affirmer makes
|
||||
the Waiver for the benefit of each member of the public at large and to the
|
||||
detriment of Affirmer's heirs and successors, fully intending that such Waiver
|
||||
shall not be subject to revocation, rescission, cancellation, termination, or
|
||||
any other legal or equitable action to disrupt the quiet enjoyment of the Work
|
||||
by the public as contemplated by Affirmer's express Statement of Purpose.
|
||||
|
||||
3. Public License Fallback. Should any part of the Waiver for any reason be
|
||||
judged legally invalid or ineffective under applicable law, then the Waiver
|
||||
shall be preserved to the maximum extent permitted taking into account
|
||||
Affirmer's express Statement of Purpose. In addition, to the extent the Waiver
|
||||
is so judged Affirmer hereby grants to each affected person a royalty-free,
|
||||
non transferable, non sublicensable, non exclusive, irrevocable and
|
||||
unconditional license to exercise Affirmer's Copyright and Related Rights in
|
||||
the Work (i) in all territories worldwide, (ii) for the maximum duration
|
||||
provided by applicable law or treaty (including future time extensions), (iii)
|
||||
in any current or future medium and for any number of copies, and (iv) for any
|
||||
purpose whatsoever, including without limitation commercial, advertising or
|
||||
promotional purposes (the "License"). The License shall be deemed effective as
|
||||
of the date CC0 was applied by Affirmer to the Work. Should any part of the
|
||||
License for any reason be judged legally invalid or ineffective under
|
||||
applicable law, such partial invalidity or ineffectiveness shall not
|
||||
invalidate the remainder of the License, and in such case Affirmer hereby
|
||||
affirms that he or she will not (i) exercise any of his or her remaining
|
||||
Copyright and Related Rights in the Work or (ii) assert any associated claims
|
||||
and causes of action with respect to the Work, in either case contrary to
|
||||
Affirmer's express Statement of Purpose.
|
||||
|
||||
4. Limitations and Disclaimers.
|
||||
|
||||
a. No trademark or patent rights held by Affirmer are waived, abandoned,
|
||||
surrendered, licensed or otherwise affected by this document.
|
||||
|
||||
b. Affirmer offers the Work as-is and makes no representations or warranties
|
||||
of any kind concerning the Work, express, implied, statutory or otherwise,
|
||||
including without limitation warranties of title, merchantability, fitness
|
||||
for a particular purpose, non infringement, or the absence of latent or
|
||||
other defects, accuracy, or the present or absence of errors, whether or not
|
||||
discoverable, all to the greatest extent permissible under applicable law.
|
||||
|
||||
c. Affirmer disclaims responsibility for clearing rights of other persons
|
||||
that may apply to the Work or any use thereof, including without limitation
|
||||
any person's Copyright and Related Rights in the Work. Further, Affirmer
|
||||
disclaims responsibility for obtaining any necessary consents, permissions
|
||||
or other rights required for any use of the Work.
|
||||
|
||||
d. Affirmer understands and acknowledges that Creative Commons is not a
|
||||
party to this document and has no duty or obligation with respect to this
|
||||
CC0 or use of the Work.
|
||||
|
||||
For more information, please see
|
||||
<http://creativecommons.org/publicdomain/zero/1.0/>
|
189
lib/bats-support/README.md
Normal file
189
lib/bats-support/README.md
Normal file
@ -0,0 +1,189 @@
|
||||
*__Important:__ `bats-core` has been renamed to `bats-support`. GitHub
|
||||
automatically redirects all references, e.g. submodules and clones will
|
||||
continue to work, but you are encouraged to [update][github-rename]
|
||||
them. Version numbering continues where `bats-core` left off.*
|
||||
|
||||
[github-rename]: https://help.github.com/articles/renaming-a-repository/
|
||||
|
||||
- - - - -
|
||||
|
||||
# bats-support
|
||||
|
||||
[](https://raw.githubusercontent.com/ztombol/bats-support/master/LICENSE)
|
||||
[](https://github.com/ztombol/bats-support/releases/latest)
|
||||
[](https://travis-ci.org/ztombol/bats-support)
|
||||
|
||||
`bats-support` is a supporting library providing common functions to
|
||||
test helper libraries written for [Bats][bats].
|
||||
|
||||
Features:
|
||||
- [error reporting](#error-reporting)
|
||||
- [output formatting](#output-formatting)
|
||||
- [language tools](#language-and-execution)
|
||||
|
||||
See the [shared documentation][bats-docs] to learn how to install and
|
||||
load this library.
|
||||
|
||||
If you want to use this library in your own helpers or just want to
|
||||
learn about its internals see the developer documentation in the [source
|
||||
files](src).
|
||||
|
||||
|
||||
## Error reporting
|
||||
|
||||
### `fail`
|
||||
|
||||
Display an error message and fail. This function provides a convenient
|
||||
way to report failure in arbitrary situations. You can use it to
|
||||
implement your own helpers when the ones available do not meet your
|
||||
needs. Other functions use it internally as well.
|
||||
|
||||
```bash
|
||||
@test 'fail()' {
|
||||
fail 'this test always fails'
|
||||
}
|
||||
```
|
||||
|
||||
The message can also be specified on the standard input.
|
||||
|
||||
```bash
|
||||
@test 'fail() with pipe' {
|
||||
echo 'this test always fails' | fail
|
||||
}
|
||||
```
|
||||
|
||||
This function always fails and simply outputs the given message.
|
||||
|
||||
```
|
||||
this test always fails
|
||||
```
|
||||
|
||||
|
||||
## Output formatting
|
||||
|
||||
Many test helpers need to produce human readable output. This library
|
||||
provides a simple way to format simple messages and key value pairs, and
|
||||
display them on the standard error.
|
||||
|
||||
|
||||
### Simple message
|
||||
|
||||
Simple messages without structure, e.g. one-line error messages, are
|
||||
simply wrapped in a header and a footer to help them stand out.
|
||||
|
||||
```
|
||||
-- ERROR: assert_output --
|
||||
`--partial' and `--regexp' are mutually exclusive
|
||||
--
|
||||
```
|
||||
|
||||
|
||||
### Key-Value pairs
|
||||
|
||||
Some helpers, e.g. [assertions][bats-assert], structure output as
|
||||
key-value pairs. This library provides two ways to format them.
|
||||
|
||||
When the value is one line long, a pair can be displayed in a columnar
|
||||
fashion called ***two-column*** format.
|
||||
|
||||
```
|
||||
-- output differs --
|
||||
expected : want
|
||||
actual : have
|
||||
--
|
||||
```
|
||||
|
||||
When the value is longer than one line, the key and value must be
|
||||
displayed on separate lines. First, the key is displayed along with the
|
||||
number of lines in the value. Then, the value, indented by two spaces
|
||||
for added readability, starting on the next line. This is called
|
||||
***multi-line*** format.
|
||||
|
||||
```
|
||||
-- command failed --
|
||||
status : 1
|
||||
output (2 lines):
|
||||
Error! Something went terribly wrong!
|
||||
Our engineers are panicing... \`>`;/
|
||||
--
|
||||
```
|
||||
|
||||
Sometimes, for clarity, it is a good idea to display related values also
|
||||
in this format, even if they are just one line long.
|
||||
|
||||
```
|
||||
-- output differs --
|
||||
expected (1 lines):
|
||||
want
|
||||
actual (3 lines):
|
||||
have 1
|
||||
have 2
|
||||
have 3
|
||||
--
|
||||
```
|
||||
|
||||
## Language and Execution
|
||||
|
||||
### Restricting invocation to specific locations
|
||||
|
||||
Sometimes a helper may work properly only when called from a certain
|
||||
location. Because it depends on variables to be set or some other side
|
||||
effect.
|
||||
|
||||
A good example is cleaning up temporary files only if the test has
|
||||
succeeded. The outcome of a test is only available in `teardown`. Thus,
|
||||
to avoid programming mistakes, it makes sense to restrict such a
|
||||
clean-up helper to that function.
|
||||
|
||||
`batslib_is_caller` checks the call stack and returns `0` if the caller
|
||||
was invoked from a given function, and `1` otherwise. This function
|
||||
becomes really useful with the `--indirect` option, which allows calls
|
||||
through intermediate functions, e.g. the calling function may be called
|
||||
from a function that was called from the given function.
|
||||
|
||||
Staying with the example above, the following code snippet implements a
|
||||
helper that is restricted to `teardown` or any function called
|
||||
indirectly from it.
|
||||
|
||||
```shell
|
||||
clean_up() {
|
||||
# Check caller.
|
||||
if batslib_is_caller --indirect 'teardown'; then
|
||||
echo "Must be called from \`teardown'" \
|
||||
| batslib_decorate 'ERROR: clean_up' \
|
||||
| fail
|
||||
return $?
|
||||
fi
|
||||
|
||||
# Body goes here...
|
||||
}
|
||||
```
|
||||
|
||||
In some cases a helper may be called from multiple locations. For
|
||||
example, a logging function that uses the test name, description or
|
||||
number, information only available in `setup`, `@test` or `teardown`, to
|
||||
distinguish entries. The following snippet implements this restriction.
|
||||
|
||||
```shell
|
||||
log_test() {
|
||||
# Check caller.
|
||||
if ! ( batslib_is_caller --indirect 'setup' \
|
||||
|| batslib_is_caller --indirect "$BATS_TEST_NAME" \
|
||||
|| batslib_is_caller --indirect 'teardown' )
|
||||
then
|
||||
echo "Must be called from \`setup', \`@test' or \`teardown'" \
|
||||
| batslib_decorate 'ERROR: log_test' \
|
||||
| fail
|
||||
return $?
|
||||
fi
|
||||
|
||||
# Body goes here...
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
<!-- REFERENCES -->
|
||||
|
||||
[bats]: https://github.com/sstephenson/bats
|
||||
[bats-docs]: https://github.com/ztombol/bats-docs
|
||||
[bats-assert]: https://github.com/ztombol/bats-assert
|
3
lib/bats-support/load.bash
Normal file
3
lib/bats-support/load.bash
Normal file
@ -0,0 +1,3 @@
|
||||
source "$(dirname "${BASH_SOURCE[0]}")/src/output.bash"
|
||||
source "$(dirname "${BASH_SOURCE[0]}")/src/error.bash"
|
||||
source "$(dirname "${BASH_SOURCE[0]}")/src/lang.bash"
|
30
lib/bats-support/package.json
Normal file
30
lib/bats-support/package.json
Normal file
@ -0,0 +1,30 @@
|
||||
{
|
||||
"name": "bats-support",
|
||||
"version": "0.3.0",
|
||||
"description": "Supporting library for Bats test helpers",
|
||||
"homepage": "https://github.com/jasonkarns/bats-support",
|
||||
"license": "CC0-1.0",
|
||||
"author": "Zoltán Tömböl (https://github.com/ztombol)",
|
||||
"contributors": [
|
||||
"Jason Karns <jason.karns@gmail.com> (http://jason.karns.name)"
|
||||
],
|
||||
"repository": "github:jasonkarns/bats-support",
|
||||
"bugs": "https://github.com/jasonkarns/bats-support/issues",
|
||||
"directories": {
|
||||
"lib": "src",
|
||||
"test": "test"
|
||||
},
|
||||
"files": [
|
||||
"load.bash",
|
||||
"src"
|
||||
],
|
||||
"scripts": {
|
||||
"test": "bats ${CI+-t} test"
|
||||
},
|
||||
"devDependencies": {
|
||||
"bats": "^1"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"bats": "0.4 || ^1"
|
||||
}
|
||||
}
|
41
lib/bats-support/src/error.bash
Normal file
41
lib/bats-support/src/error.bash
Normal file
@ -0,0 +1,41 @@
|
||||
#
|
||||
# bats-support - Supporting library for Bats test helpers
|
||||
#
|
||||
# Written in 2016 by Zoltan Tombol <zoltan dot tombol at gmail dot com>
|
||||
#
|
||||
# To the extent possible under law, the author(s) have dedicated all
|
||||
# copyright and related and neighboring rights to this software to the
|
||||
# public domain worldwide. This software is distributed without any
|
||||
# warranty.
|
||||
#
|
||||
# You should have received a copy of the CC0 Public Domain Dedication
|
||||
# along with this software. If not, see
|
||||
# <http://creativecommons.org/publicdomain/zero/1.0/>.
|
||||
#
|
||||
|
||||
#
|
||||
# error.bash
|
||||
# ----------
|
||||
#
|
||||
# Functions implementing error reporting. Used by public helper
|
||||
# functions or test suits directly.
|
||||
#
|
||||
|
||||
# Fail and display a message. When no parameters are specified, the
|
||||
# message is read from the standard input. Other functions use this to
|
||||
# report failure.
|
||||
#
|
||||
# Globals:
|
||||
# none
|
||||
# Arguments:
|
||||
# $@ - [=STDIN] message
|
||||
# Returns:
|
||||
# 1 - always
|
||||
# Inputs:
|
||||
# STDIN - [=$@] message
|
||||
# Outputs:
|
||||
# STDERR - message
|
||||
fail() {
|
||||
(( $# == 0 )) && batslib_err || batslib_err "$@"
|
||||
return 1
|
||||
}
|
73
lib/bats-support/src/lang.bash
Normal file
73
lib/bats-support/src/lang.bash
Normal file
@ -0,0 +1,73 @@
|
||||
#
|
||||
# bats-util - Various auxiliary functions for Bats
|
||||
#
|
||||
# Written in 2016 by Zoltan Tombol <zoltan dot tombol at gmail dot com>
|
||||
#
|
||||
# To the extent possible under law, the author(s) have dedicated all
|
||||
# copyright and related and neighboring rights to this software to the
|
||||
# public domain worldwide. This software is distributed without any
|
||||
# warranty.
|
||||
#
|
||||
# You should have received a copy of the CC0 Public Domain Dedication
|
||||
# along with this software. If not, see
|
||||
# <http://creativecommons.org/publicdomain/zero/1.0/>.
|
||||
#
|
||||
|
||||
#
|
||||
# lang.bash
|
||||
# ---------
|
||||
#
|
||||
# Bash language and execution related functions. Used by public helper
|
||||
# functions.
|
||||
#
|
||||
|
||||
# Check whether the calling function was called from a given function.
|
||||
#
|
||||
# By default, direct invocation is checked. The function succeeds if the
|
||||
# calling function was called directly from the given function. In other
|
||||
# words, if the given function is the next element on the call stack.
|
||||
#
|
||||
# When `--indirect' is specified, indirect invocation is checked. The
|
||||
# function succeeds if the calling function was called from the given
|
||||
# function with any number of intermediate calls. In other words, if the
|
||||
# given function can be found somewhere on the call stack.
|
||||
#
|
||||
# Direct invocation is a form of indirect invocation with zero
|
||||
# intermediate calls.
|
||||
#
|
||||
# Globals:
|
||||
# FUNCNAME
|
||||
# Options:
|
||||
# -i, --indirect - check indirect invocation
|
||||
# Arguments:
|
||||
# $1 - calling function's name
|
||||
# Returns:
|
||||
# 0 - current function was called from the given function
|
||||
# 1 - otherwise
|
||||
batslib_is_caller() {
|
||||
local -i is_mode_direct=1
|
||||
|
||||
# Handle options.
|
||||
while (( $# > 0 )); do
|
||||
case "$1" in
|
||||
-i|--indirect) is_mode_direct=0; shift ;;
|
||||
--) shift; break ;;
|
||||
*) break ;;
|
||||
esac
|
||||
done
|
||||
|
||||
# Arguments.
|
||||
local -r func="$1"
|
||||
|
||||
# Check call stack.
|
||||
if (( is_mode_direct )); then
|
||||
[[ $func == "${FUNCNAME[2]}" ]] && return 0
|
||||
else
|
||||
local -i depth
|
||||
for (( depth=2; depth<${#FUNCNAME[@]}; ++depth )); do
|
||||
[[ $func == "${FUNCNAME[$depth]}" ]] && return 0
|
||||
done
|
||||
fi
|
||||
|
||||
return 1
|
||||
}
|
279
lib/bats-support/src/output.bash
Normal file
279
lib/bats-support/src/output.bash
Normal file
@ -0,0 +1,279 @@
|
||||
#
|
||||
# bats-support - Supporting library for Bats test helpers
|
||||
#
|
||||
# Written in 2016 by Zoltan Tombol <zoltan dot tombol at gmail dot com>
|
||||
#
|
||||
# To the extent possible under law, the author(s) have dedicated all
|
||||
# copyright and related and neighboring rights to this software to the
|
||||
# public domain worldwide. This software is distributed without any
|
||||
# warranty.
|
||||
#
|
||||
# You should have received a copy of the CC0 Public Domain Dedication
|
||||
# along with this software. If not, see
|
||||
# <http://creativecommons.org/publicdomain/zero/1.0/>.
|
||||
#
|
||||
|
||||
#
|
||||
# output.bash
|
||||
# -----------
|
||||
#
|
||||
# Private functions implementing output formatting. Used by public
|
||||
# helper functions.
|
||||
#
|
||||
|
||||
# Print a message to the standard error. When no parameters are
|
||||
# specified, the message is read from the standard input.
|
||||
#
|
||||
# Globals:
|
||||
# none
|
||||
# Arguments:
|
||||
# $@ - [=STDIN] message
|
||||
# Returns:
|
||||
# none
|
||||
# Inputs:
|
||||
# STDIN - [=$@] message
|
||||
# Outputs:
|
||||
# STDERR - message
|
||||
batslib_err() {
|
||||
{ if (( $# > 0 )); then
|
||||
echo "$@"
|
||||
else
|
||||
cat -
|
||||
fi
|
||||
} >&2
|
||||
}
|
||||
|
||||
# Count the number of lines in the given string.
|
||||
#
|
||||
# TODO(ztombol): Fix tests and remove this note after #93 is resolved!
|
||||
# NOTE: Due to a bug in Bats, `batslib_count_lines "$output"' does not
|
||||
# give the same result as `${#lines[@]}' when the output contains
|
||||
# empty lines.
|
||||
# See PR #93 (https://github.com/sstephenson/bats/pull/93).
|
||||
#
|
||||
# Globals:
|
||||
# none
|
||||
# Arguments:
|
||||
# $1 - string
|
||||
# Returns:
|
||||
# none
|
||||
# Outputs:
|
||||
# STDOUT - number of lines
|
||||
batslib_count_lines() {
|
||||
local -i n_lines=0
|
||||
local line
|
||||
while IFS='' read -r line || [[ -n $line ]]; do
|
||||
(( ++n_lines ))
|
||||
done < <(printf '%s' "$1")
|
||||
echo "$n_lines"
|
||||
}
|
||||
|
||||
# Determine whether all strings are single-line.
|
||||
#
|
||||
# Globals:
|
||||
# none
|
||||
# Arguments:
|
||||
# $@ - strings
|
||||
# Returns:
|
||||
# 0 - all strings are single-line
|
||||
# 1 - otherwise
|
||||
batslib_is_single_line() {
|
||||
for string in "$@"; do
|
||||
(( $(batslib_count_lines "$string") > 1 )) && return 1
|
||||
done
|
||||
return 0
|
||||
}
|
||||
|
||||
# Determine the length of the longest key that has a single-line value.
|
||||
#
|
||||
# This function is useful in determining the correct width of the key
|
||||
# column in two-column format when some keys may have multi-line values
|
||||
# and thus should be excluded.
|
||||
#
|
||||
# Globals:
|
||||
# none
|
||||
# Arguments:
|
||||
# $odd - key
|
||||
# $even - value of the previous key
|
||||
# Returns:
|
||||
# none
|
||||
# Outputs:
|
||||
# STDOUT - length of longest key
|
||||
batslib_get_max_single_line_key_width() {
|
||||
local -i max_len=-1
|
||||
while (( $# != 0 )); do
|
||||
local -i key_len="${#1}"
|
||||
batslib_is_single_line "$2" && (( key_len > max_len )) && max_len="$key_len"
|
||||
shift 2
|
||||
done
|
||||
echo "$max_len"
|
||||
}
|
||||
|
||||
# Print key-value pairs in two-column format.
|
||||
#
|
||||
# Keys are displayed in the first column, and their corresponding values
|
||||
# in the second. To evenly line up values, the key column is fixed-width
|
||||
# and its width is specified with the first parameter (possibly computed
|
||||
# using `batslib_get_max_single_line_key_width').
|
||||
#
|
||||
# Globals:
|
||||
# none
|
||||
# Arguments:
|
||||
# $1 - width of key column
|
||||
# $even - key
|
||||
# $odd - value of the previous key
|
||||
# Returns:
|
||||
# none
|
||||
# Outputs:
|
||||
# STDOUT - formatted key-value pairs
|
||||
batslib_print_kv_single() {
|
||||
local -ir col_width="$1"; shift
|
||||
while (( $# != 0 )); do
|
||||
printf '%-*s : %s\n' "$col_width" "$1" "$2"
|
||||
shift 2
|
||||
done
|
||||
}
|
||||
|
||||
# Print key-value pairs in multi-line format.
|
||||
#
|
||||
# The key is displayed first with the number of lines of its
|
||||
# corresponding value in parenthesis. Next, starting on the next line,
|
||||
# the value is displayed. For better readability, it is recommended to
|
||||
# indent values using `batslib_prefix'.
|
||||
#
|
||||
# Globals:
|
||||
# none
|
||||
# Arguments:
|
||||
# $odd - key
|
||||
# $even - value of the previous key
|
||||
# Returns:
|
||||
# none
|
||||
# Outputs:
|
||||
# STDOUT - formatted key-value pairs
|
||||
batslib_print_kv_multi() {
|
||||
while (( $# != 0 )); do
|
||||
printf '%s (%d lines):\n' "$1" "$( batslib_count_lines "$2" )"
|
||||
printf '%s\n' "$2"
|
||||
shift 2
|
||||
done
|
||||
}
|
||||
|
||||
# Print all key-value pairs in either two-column or multi-line format
|
||||
# depending on whether all values are single-line.
|
||||
#
|
||||
# If all values are single-line, print all pairs in two-column format
|
||||
# with the specified key column width (identical to using
|
||||
# `batslib_print_kv_single').
|
||||
#
|
||||
# Otherwise, print all pairs in multi-line format after indenting values
|
||||
# with two spaces for readability (identical to using `batslib_prefix'
|
||||
# and `batslib_print_kv_multi')
|
||||
#
|
||||
# Globals:
|
||||
# none
|
||||
# Arguments:
|
||||
# $1 - width of key column (for two-column format)
|
||||
# $even - key
|
||||
# $odd - value of the previous key
|
||||
# Returns:
|
||||
# none
|
||||
# Outputs:
|
||||
# STDOUT - formatted key-value pairs
|
||||
batslib_print_kv_single_or_multi() {
|
||||
local -ir width="$1"; shift
|
||||
local -a pairs=( "$@" )
|
||||
|
||||
local -a values=()
|
||||
local -i i
|
||||
for (( i=1; i < ${#pairs[@]}; i+=2 )); do
|
||||
values+=( "${pairs[$i]}" )
|
||||
done
|
||||
|
||||
if batslib_is_single_line "${values[@]}"; then
|
||||
batslib_print_kv_single "$width" "${pairs[@]}"
|
||||
else
|
||||
local -i i
|
||||
for (( i=1; i < ${#pairs[@]}; i+=2 )); do
|
||||
pairs[$i]="$( batslib_prefix < <(printf '%s' "${pairs[$i]}") )"
|
||||
done
|
||||
batslib_print_kv_multi "${pairs[@]}"
|
||||
fi
|
||||
}
|
||||
|
||||
# Prefix each line read from the standard input with the given string.
|
||||
#
|
||||
# Globals:
|
||||
# none
|
||||
# Arguments:
|
||||
# $1 - [= ] prefix string
|
||||
# Returns:
|
||||
# none
|
||||
# Inputs:
|
||||
# STDIN - lines
|
||||
# Outputs:
|
||||
# STDOUT - prefixed lines
|
||||
batslib_prefix() {
|
||||
local -r prefix="${1:- }"
|
||||
local line
|
||||
while IFS='' read -r line || [[ -n $line ]]; do
|
||||
printf '%s%s\n' "$prefix" "$line"
|
||||
done
|
||||
}
|
||||
|
||||
# Mark select lines of the text read from the standard input by
|
||||
# overwriting their beginning with the given string.
|
||||
#
|
||||
# Usually the input is indented by a few spaces using `batslib_prefix'
|
||||
# first.
|
||||
#
|
||||
# Globals:
|
||||
# none
|
||||
# Arguments:
|
||||
# $1 - marking string
|
||||
# $@ - indices (zero-based) of lines to mark
|
||||
# Returns:
|
||||
# none
|
||||
# Inputs:
|
||||
# STDIN - lines
|
||||
# Outputs:
|
||||
# STDOUT - lines after marking
|
||||
batslib_mark() {
|
||||
local -r symbol="$1"; shift
|
||||
# Sort line numbers.
|
||||
set -- $( sort -nu <<< "$( printf '%d\n' "$@" )" )
|
||||
|
||||
local line
|
||||
local -i idx=0
|
||||
while IFS='' read -r line || [[ -n $line ]]; do
|
||||
if (( ${1:--1} == idx )); then
|
||||
printf '%s\n' "${symbol}${line:${#symbol}}"
|
||||
shift
|
||||
else
|
||||
printf '%s\n' "$line"
|
||||
fi
|
||||
(( ++idx ))
|
||||
done
|
||||
}
|
||||
|
||||
# Enclose the input text in header and footer lines.
|
||||
#
|
||||
# The header contains the given string as title. The output is preceded
|
||||
# and followed by an additional newline to make it stand out more.
|
||||
#
|
||||
# Globals:
|
||||
# none
|
||||
# Arguments:
|
||||
# $1 - title
|
||||
# Returns:
|
||||
# none
|
||||
# Inputs:
|
||||
# STDIN - text
|
||||
# Outputs:
|
||||
# STDOUT - decorated text
|
||||
batslib_decorate() {
|
||||
echo
|
||||
echo "-- $1 --"
|
||||
cat -
|
||||
echo '--'
|
||||
echo
|
||||
}
|
16
lib/bats-support/test/50-output-10-batslib_err.bats
Executable file
16
lib/bats-support/test/50-output-10-batslib_err.bats
Executable file
@ -0,0 +1,16 @@
|
||||
#!/usr/bin/env bats
|
||||
|
||||
load test_helper
|
||||
|
||||
@test 'batslib_err() <message...>: displays <message...>' {
|
||||
run batslib_err 'm1' 'm2'
|
||||
[ "$status" -eq 0 ]
|
||||
[ "$output" == 'm1 m2' ]
|
||||
}
|
||||
|
||||
@test 'batslib_err(): reads <message...> from STDIN' {
|
||||
run bash -c "source '${TEST_MAIN_DIR}/load.bash'
|
||||
echo 'm1' 'm2' | batslib_err"
|
||||
[ "$status" -eq 0 ]
|
||||
[ "$output" == 'm1 m2' ]
|
||||
}
|
21
lib/bats-support/test/50-output-11-batslib_count_lines.bats
Executable file
21
lib/bats-support/test/50-output-11-batslib_count_lines.bats
Executable file
@ -0,0 +1,21 @@
|
||||
#!/usr/bin/env bats
|
||||
|
||||
load test_helper
|
||||
|
||||
@test 'batslib_count_lines() <string>: displays the number of lines in <string>' {
|
||||
run batslib_count_lines $'a\nb\nc\n'
|
||||
[ "$status" -eq 0 ]
|
||||
[ "$output" == '3' ]
|
||||
}
|
||||
|
||||
@test 'batslib_count_lines() <string>: counts the last line when it is not terminated by a newline' {
|
||||
run batslib_count_lines $'a\nb\nc'
|
||||
[ "$status" -eq 0 ]
|
||||
[ "$output" == '3' ]
|
||||
}
|
||||
|
||||
@test 'batslib_count_lines() <string>: counts empty lines' {
|
||||
run batslib_count_lines $'\n\n\n'
|
||||
[ "$status" -eq 0 ]
|
||||
[ "$output" == '3' ]
|
||||
}
|
13
lib/bats-support/test/50-output-12-batslib_is_single_line.bats
Executable file
13
lib/bats-support/test/50-output-12-batslib_is_single_line.bats
Executable file
@ -0,0 +1,13 @@
|
||||
#!/usr/bin/env bats
|
||||
|
||||
load test_helper
|
||||
|
||||
@test 'batslib_is_single_line() <string...>: returns 0 if all <string...> are single-line' {
|
||||
run batslib_is_single_line 'a' $'b\n' 'c'
|
||||
[ "$status" -eq 0 ]
|
||||
}
|
||||
|
||||
@test 'batslib_is_single_line() <string...>: returns 1 if at least one of <string...> is longer than one line' {
|
||||
run batslib_is_single_line 'a' $'b\nb' 'c'
|
||||
[ "$status" -eq 1 ]
|
||||
}
|
@ -0,0 +1,21 @@
|
||||
#!/usr/bin/env bats
|
||||
|
||||
load test_helper
|
||||
|
||||
@test 'batslib_get_max_single_line_key_width() <pair...>: displays the length of the longest key' {
|
||||
local -ar pairs=( 'k _1' 'v 1'
|
||||
'k 2' 'v 2'
|
||||
'k __3' 'v 3' )
|
||||
run batslib_get_max_single_line_key_width "${pairs[@]}"
|
||||
[ "$status" -eq 0 ]
|
||||
[ "$output" == '5' ]
|
||||
}
|
||||
|
||||
@test 'batslib_get_max_single_line_key_width() <pair...>: only considers keys with single-line values' {
|
||||
local -ar pairs=( 'k _1' 'v 1'
|
||||
'k 2' 'v 2'
|
||||
'k __3' $'v\n3' )
|
||||
run batslib_get_max_single_line_key_width "${pairs[@]}"
|
||||
[ "$status" -eq 0 ]
|
||||
[ "$output" == '4' ]
|
||||
}
|
27
lib/bats-support/test/50-output-14-batslib_print_kv_single.bats
Executable file
27
lib/bats-support/test/50-output-14-batslib_print_kv_single.bats
Executable file
@ -0,0 +1,27 @@
|
||||
#!/usr/bin/env bats
|
||||
|
||||
load test_helper
|
||||
|
||||
@test 'batslib_print_kv_single() <width> <pair...>: displays <pair...> in two-column format with <width> wide key column' {
|
||||
local -ar pairs=( 'k _1' 'v 1'
|
||||
'k 2 ' 'v 2'
|
||||
'k __3' 'v 3' )
|
||||
run batslib_print_kv_single 5 "${pairs[@]}"
|
||||
[ "$status" -eq 0 ]
|
||||
[ "${#lines[@]}" == '3' ]
|
||||
[ "${lines[0]}" == 'k _1 : v 1' ]
|
||||
[ "${lines[1]}" == 'k 2 : v 2' ]
|
||||
[ "${lines[2]}" == 'k __3 : v 3' ]
|
||||
}
|
||||
|
||||
@test 'batslib_print_kv_single() <width> <pair...>: does not truncate keys when the column is too narrow' {
|
||||
local -ar pairs=( 'k _1' 'v 1'
|
||||
'k 2' 'v 2'
|
||||
'k __3' 'v 3' )
|
||||
run batslib_print_kv_single 0 "${pairs[@]}"
|
||||
[ "$status" -eq 0 ]
|
||||
[ "${#lines[@]}" == '3' ]
|
||||
[ "${lines[0]}" == 'k _1 : v 1' ]
|
||||
[ "${lines[1]}" == 'k 2 : v 2' ]
|
||||
[ "${lines[2]}" == 'k __3 : v 3' ]
|
||||
}
|
19
lib/bats-support/test/50-output-15-batslib_print_kv_multi.bats
Executable file
19
lib/bats-support/test/50-output-15-batslib_print_kv_multi.bats
Executable file
@ -0,0 +1,19 @@
|
||||
#!/usr/bin/env bats
|
||||
|
||||
load test_helper
|
||||
|
||||
@test 'batslib_print_kv_multi() <pair...>: displays <pair...> in multi-line format' {
|
||||
local -ar pairs=( 'k _1' 'v 1'
|
||||
'k 2' $'v 2-1\nv 2-2'
|
||||
'k __3' 'v 3' )
|
||||
run batslib_print_kv_multi "${pairs[@]}"
|
||||
[ "$status" -eq 0 ]
|
||||
[ "${#lines[@]}" == '7' ]
|
||||
[ "${lines[0]}" == 'k _1 (1 lines):' ]
|
||||
[ "${lines[1]}" == 'v 1' ]
|
||||
[ "${lines[2]}" == 'k 2 (2 lines):' ]
|
||||
[ "${lines[3]}" == 'v 2-1' ]
|
||||
[ "${lines[4]}" == 'v 2-2' ]
|
||||
[ "${lines[5]}" == 'k __3 (1 lines):' ]
|
||||
[ "${lines[6]}" == 'v 3' ]
|
||||
}
|
31
lib/bats-support/test/50-output-16-batslib_print_kv_single_or_multi.bats
Executable file
31
lib/bats-support/test/50-output-16-batslib_print_kv_single_or_multi.bats
Executable file
@ -0,0 +1,31 @@
|
||||
#!/usr/bin/env bats
|
||||
|
||||
load test_helper
|
||||
|
||||
@test 'batslib_print_kv_single_or_multi() <width> <pair...>: displays <pair...> in two-column format if all values are one line long' {
|
||||
local -ar pairs=( 'k _1' 'v 1'
|
||||
'k 2 ' 'v 2'
|
||||
'k __3' 'v 3' )
|
||||
run batslib_print_kv_single_or_multi 5 "${pairs[@]}"
|
||||
[ "$status" -eq 0 ]
|
||||
[ "${#lines[@]}" == '3' ]
|
||||
[ "${lines[0]}" == 'k _1 : v 1' ]
|
||||
[ "${lines[1]}" == 'k 2 : v 2' ]
|
||||
[ "${lines[2]}" == 'k __3 : v 3' ]
|
||||
}
|
||||
|
||||
@test 'batslib_print_kv_single_or_multi() <width> <pair...>: displays <pair...> in multi-line format if at least one value is longer than one line' {
|
||||
local -ar pairs=( 'k _1' 'v 1'
|
||||
'k 2' $'v 2-1\nv 2-2'
|
||||
'k __3' 'v 3' )
|
||||
run batslib_print_kv_single_or_multi 5 "${pairs[@]}"
|
||||
[ "$status" -eq 0 ]
|
||||
[ "${#lines[@]}" == '7' ]
|
||||
[ "${lines[0]}" == 'k _1 (1 lines):' ]
|
||||
[ "${lines[1]}" == ' v 1' ]
|
||||
[ "${lines[2]}" == 'k 2 (2 lines):' ]
|
||||
[ "${lines[3]}" == ' v 2-1' ]
|
||||
[ "${lines[4]}" == ' v 2-2' ]
|
||||
[ "${lines[5]}" == 'k __3 (1 lines):' ]
|
||||
[ "${lines[6]}" == ' v 3' ]
|
||||
}
|
43
lib/bats-support/test/50-output-17-batslib_prefix.bats
Executable file
43
lib/bats-support/test/50-output-17-batslib_prefix.bats
Executable file
@ -0,0 +1,43 @@
|
||||
#!/usr/bin/env bats
|
||||
|
||||
load test_helper
|
||||
|
||||
@test 'batslib_prefix() <prefix>: prefixes each line of the input with <prefix>' {
|
||||
run bash -c "source '${TEST_MAIN_DIR}/load.bash'
|
||||
printf 'a\nb\nc\n' | batslib_prefix '_'"
|
||||
[ "$status" -eq 0 ]
|
||||
[ "${#lines[@]}" -eq 3 ]
|
||||
[ "${lines[0]}" == '_a' ]
|
||||
[ "${lines[1]}" == '_b' ]
|
||||
[ "${lines[2]}" == '_c' ]
|
||||
}
|
||||
|
||||
@test 'batslib_prefix() <prefix>: prefixes the last line when it is not terminated by a newline' {
|
||||
run bash -c "source '${TEST_MAIN_DIR}/load.bash'
|
||||
printf 'a\nb\nc' | batslib_prefix '_'"
|
||||
[ "$status" -eq 0 ]
|
||||
[ "${#lines[@]}" -eq 3 ]
|
||||
[ "${lines[0]}" == '_a' ]
|
||||
[ "${lines[1]}" == '_b' ]
|
||||
[ "${lines[2]}" == '_c' ]
|
||||
}
|
||||
|
||||
@test 'batslib_prefix() <prefix>: prefixes empty lines' {
|
||||
run bash -c "source '${TEST_MAIN_DIR}/load.bash'
|
||||
printf '\n\n\n' | batslib_prefix '_'"
|
||||
[ "$status" -eq 0 ]
|
||||
[ "${#lines[@]}" -eq 3 ]
|
||||
[ "${lines[0]}" == '_' ]
|
||||
[ "${lines[1]}" == '_' ]
|
||||
[ "${lines[2]}" == '_' ]
|
||||
}
|
||||
|
||||
@test 'batslib_prefix(): <prefix> default to two spaces' {
|
||||
run bash -c "source '${TEST_MAIN_DIR}/load.bash'
|
||||
printf 'a\nb\nc\n' | batslib_prefix"
|
||||
[ "$status" -eq 0 ]
|
||||
[ "${#lines[@]}" -eq 3 ]
|
||||
[ "${lines[0]}" == ' a' ]
|
||||
[ "${lines[1]}" == ' b' ]
|
||||
[ "${lines[2]}" == ' c' ]
|
||||
}
|
72
lib/bats-support/test/50-output-18-batslib_mark.bats
Executable file
72
lib/bats-support/test/50-output-18-batslib_mark.bats
Executable file
@ -0,0 +1,72 @@
|
||||
#!/usr/bin/env bats
|
||||
|
||||
load test_helper
|
||||
|
||||
@test 'batslib_mark() <mark> <index>: marks the <index>-th line of the input with <mark>' {
|
||||
run bash -c "source '${TEST_MAIN_DIR}/load.bash'
|
||||
printf ' a\n b\n c\n' | batslib_mark '>' 0"
|
||||
[ "$status" -eq 0 ]
|
||||
[ "${#lines[@]}" -eq 3 ]
|
||||
[ "${lines[0]}" == '>a' ]
|
||||
[ "${lines[1]}" == ' b' ]
|
||||
[ "${lines[2]}" == ' c' ]
|
||||
}
|
||||
|
||||
@test 'batslib_mark() <mark> <index...>: marks multiple lines when <index...> is in ascending order' {
|
||||
run bash -c "source '${TEST_MAIN_DIR}/load.bash'
|
||||
printf ' a\n b\n c\n' | batslib_mark '>' 1 2"
|
||||
[ "$status" -eq 0 ]
|
||||
[ "${#lines[@]}" -eq 3 ]
|
||||
[ "${lines[0]}" == ' a' ]
|
||||
[ "${lines[1]}" == '>b' ]
|
||||
[ "${lines[2]}" == '>c' ]
|
||||
}
|
||||
|
||||
@test 'batslib_mark() <mark> <index...>: marks multiple lines when <index...> is in random order' {
|
||||
run bash -c "source '${TEST_MAIN_DIR}/load.bash'
|
||||
printf ' a\n b\n c\n d\n' | batslib_mark '>' 2 1 3"
|
||||
[ "$status" -eq 0 ]
|
||||
[ "${#lines[@]}" -eq 4 ]
|
||||
[ "${lines[0]}" == ' a' ]
|
||||
[ "${lines[1]}" == '>b' ]
|
||||
[ "${lines[2]}" == '>c' ]
|
||||
[ "${lines[3]}" == '>d' ]
|
||||
}
|
||||
|
||||
@test 'batslib_mark() <mark> <index...>: ignores duplicate indices' {
|
||||
run bash -c "source '${TEST_MAIN_DIR}/load.bash'
|
||||
printf ' a\n b\n c\n' | batslib_mark '>' 1 2 1"
|
||||
[ "$status" -eq 0 ]
|
||||
[ "${#lines[@]}" -eq 3 ]
|
||||
[ "${lines[0]}" == ' a' ]
|
||||
[ "${lines[1]}" == '>b' ]
|
||||
[ "${lines[2]}" == '>c' ]
|
||||
}
|
||||
|
||||
@test 'batslib_mark() <mark> <index...>: outputs the input untouched if <mark> is the empty string' {
|
||||
run bash -c "source '${TEST_MAIN_DIR}/load.bash'
|
||||
printf ' a\n b\n c\n' | batslib_mark '' 1"
|
||||
[ "$status" -eq 0 ]
|
||||
[ "${#lines[@]}" -eq 3 ]
|
||||
[ "${lines[0]}" == ' a' ]
|
||||
[ "${lines[1]}" == ' b' ]
|
||||
[ "${lines[2]}" == ' c' ]
|
||||
}
|
||||
|
||||
@test 'batslib_mark() <mark> <index>: marks the last line when it is not terminated by a newline' {
|
||||
run bash -c "source '${TEST_MAIN_DIR}/load.bash'
|
||||
printf ' a\n b\n c' | batslib_mark '>' 2"
|
||||
[ "$status" -eq 0 ]
|
||||
[ "${#lines[@]}" -eq 3 ]
|
||||
[ "${lines[0]}" == ' a' ]
|
||||
[ "${lines[1]}" == ' b' ]
|
||||
[ "${lines[2]}" == '>c' ]
|
||||
}
|
||||
|
||||
@test 'batslib_mark() <mark> <index>: does not truncate <mark> if it is longer than the marked line' {
|
||||
run bash -c "source '${TEST_MAIN_DIR}/load.bash'
|
||||
printf '\n' | batslib_mark '>' 0"
|
||||
[ "$status" -eq 0 ]
|
||||
[ "${#lines[@]}" -eq 1 ]
|
||||
[ "${lines[0]}" == '>' ]
|
||||
}
|
13
lib/bats-support/test/50-output-19-batslib_decorate.bats
Executable file
13
lib/bats-support/test/50-output-19-batslib_decorate.bats
Executable file
@ -0,0 +1,13 @@
|
||||
#!/usr/bin/env bats
|
||||
|
||||
load test_helper
|
||||
|
||||
@test 'batslib_decorate() <title>: encloses the input in a footer line and a header line containing <title>' {
|
||||
run bash -c "source '${TEST_MAIN_DIR}/load.bash'
|
||||
echo 'body' | batslib_decorate 'title'"
|
||||
[ "$status" -eq 0 ]
|
||||
[ "${#lines[@]}" -eq 3 ]
|
||||
[ "${lines[0]}" == '-- title --' ]
|
||||
[ "${lines[1]}" == 'body' ]
|
||||
[ "${lines[2]}" == '--' ]
|
||||
}
|
16
lib/bats-support/test/51-error-10-fail.bats
Executable file
16
lib/bats-support/test/51-error-10-fail.bats
Executable file
@ -0,0 +1,16 @@
|
||||
#!/usr/bin/env bats
|
||||
|
||||
load test_helper
|
||||
|
||||
@test 'fail() <message>: returns 1 and displays <message>' {
|
||||
run fail 'message'
|
||||
[ "$status" -eq 1 ]
|
||||
[ "$output" == 'message' ]
|
||||
}
|
||||
|
||||
@test 'fail(): reads <message> from STDIN' {
|
||||
run bash -c "source '${TEST_MAIN_DIR}/load.bash'
|
||||
echo 'message' | fail"
|
||||
[ "$status" -eq 1 ]
|
||||
[ "$output" == 'message' ]
|
||||
}
|
88
lib/bats-support/test/52-lang-10-batslib_is_caller.bats
Executable file
88
lib/bats-support/test/52-lang-10-batslib_is_caller.bats
Executable file
@ -0,0 +1,88 @@
|
||||
#!/usr/bin/env bats
|
||||
|
||||
load 'test_helper'
|
||||
|
||||
|
||||
# Test functions
|
||||
test_func_lvl_2() {
|
||||
test_func_lvl_1 "$@"
|
||||
}
|
||||
|
||||
test_func_lvl_1() {
|
||||
test_func_lvl_0 "$@"
|
||||
}
|
||||
|
||||
test_func_lvl_0() {
|
||||
batslib_is_caller "$@"
|
||||
}
|
||||
|
||||
|
||||
#
|
||||
# Direct invocation
|
||||
#
|
||||
|
||||
# Interface
|
||||
@test 'batslib_is_caller() <function>: returns 0 if the current function was called directly from <function>' {
|
||||
run test_func_lvl_1 test_func_lvl_1
|
||||
[ "$status" -eq 0 ]
|
||||
[ "${#lines[@]}" -eq 0 ]
|
||||
}
|
||||
|
||||
@test 'batslib_is_caller() <function>: returns 1 if the current function was not called directly from <function>' {
|
||||
run test_func_lvl_0 test_func_lvl_1
|
||||
[ "$status" -eq 1 ]
|
||||
[ "${#lines[@]}" -eq 0 ]
|
||||
}
|
||||
|
||||
# Correctness
|
||||
@test 'batslib_is_caller() <function>: the current function does not appear on the call stack' {
|
||||
run test_func_lvl_0 test_func_lvl_0
|
||||
[ "$status" -eq 1 ]
|
||||
[ "${#lines[@]}" -eq 0 ]
|
||||
}
|
||||
|
||||
|
||||
#
|
||||
# Indirect invocation
|
||||
#
|
||||
|
||||
# Options
|
||||
test_i_indirect() {
|
||||
run test_func_lvl_2 "$@"
|
||||
[ "$status" -eq 0 ]
|
||||
[ "${#lines[@]}" -eq 0 ]
|
||||
}
|
||||
|
||||
@test 'batslib_is_caller() -i <function>: enables indirect checking' {
|
||||
test_i_indirect -i test_func_lvl_2
|
||||
}
|
||||
|
||||
@test 'batslib_is_caller() --indirect <function>: enables indirect checking' {
|
||||
test_i_indirect --indirect test_func_lvl_2
|
||||
}
|
||||
|
||||
# Interface
|
||||
@test 'batslib_is_caller() --indirect <function>: returns 0 if the current function was called indirectly from <function>' {
|
||||
run test_func_lvl_2 --indirect test_func_lvl_2
|
||||
[ "$status" -eq 0 ]
|
||||
[ "${#lines[@]}" -eq 0 ]
|
||||
}
|
||||
|
||||
@test 'batslib_is_caller() --indirect <function>: returns 1 if the current function was not called indirectly from <function>' {
|
||||
run test_func_lvl_1 --indirect test_func_lvl_2
|
||||
[ "$status" -eq 1 ]
|
||||
[ "${#lines[@]}" -eq 0 ]
|
||||
}
|
||||
|
||||
# Correctness
|
||||
@test 'batslib_is_caller() --indirect <function>: direct invocation is a special case of indirect invocation with zero intermediate calls' {
|
||||
run test_func_lvl_1 --indirect test_func_lvl_1
|
||||
[ "$status" -eq 0 ]
|
||||
[ "${#lines[@]}" -eq 0 ]
|
||||
}
|
||||
|
||||
@test 'batslib_is_caller() --indirect <function>: the current function does not appear on the call stack' {
|
||||
run test_func_lvl_0 --indirect test_func_lvl_0
|
||||
[ "$status" -eq 1 ]
|
||||
[ "${#lines[@]}" -eq 0 ]
|
||||
}
|
6
lib/bats-support/test/test_helper.bash
Normal file
6
lib/bats-support/test/test_helper.bash
Normal file
@ -0,0 +1,6 @@
|
||||
setup() {
|
||||
export TEST_MAIN_DIR="${BATS_TEST_DIRNAME}/.."
|
||||
|
||||
# Load library.
|
||||
load '../load'
|
||||
}
|
Loading…
Reference in New Issue
Block a user