diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-19 02:57:58 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-19 02:57:58 +0000 |
commit | be1c7e50e1e8809ea56f2c9d472eccd8ffd73a97 (patch) | |
tree | 9754ff1ca740f6346cf8483ec915d4054bc5da2d /fluent-bit/tests/lib/shunit2/README.md | |
parent | Initial commit. (diff) | |
download | netdata-be1c7e50e1e8809ea56f2c9d472eccd8ffd73a97.tar.xz netdata-be1c7e50e1e8809ea56f2c9d472eccd8ffd73a97.zip |
Adding upstream version 1.44.3.upstream/1.44.3upstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'fluent-bit/tests/lib/shunit2/README.md')
-rw-r--r-- | fluent-bit/tests/lib/shunit2/README.md | 636 |
1 files changed, 636 insertions, 0 deletions
diff --git a/fluent-bit/tests/lib/shunit2/README.md b/fluent-bit/tests/lib/shunit2/README.md new file mode 100644 index 00000000..dd6bba42 --- /dev/null +++ b/fluent-bit/tests/lib/shunit2/README.md @@ -0,0 +1,636 @@ +# shUnit2 + +shUnit2 is a [xUnit](http://en.wikipedia.org/wiki/XUnit) unit test framework for +Bourne based shell scripts, and it is designed to work in a similar manner to +[JUnit](http://www.junit.org), [PyUnit](http://pyunit.sourceforge.net), etc.. If +you have ever had the desire to write a unit test for a shell script, shUnit2 +can do the job. + +[![Travis CI](https://img.shields.io/travis/kward/shunit2.svg)](https://travis-ci.org/kward/shunit2) + +## Table of Contents + +* [Introduction](#introduction) + * [Credits / Contributors](#credits-contributors) + * [Feedback](#feedback) +* [Quickstart](#quickstart) +* [Function Reference](#function-reference) + * [General Info](#general-info) + * [Asserts](#asserts) + * [Failures](#failures) + * [Setup/Teardown](#setup-teardown) + * [Skipping](#skipping) + * [Suites](#suites) +* [Advanced Usage](#advanced-usage) + * [Some constants you can use](#some-constants-you-can-use) + * [Error Handling](#error-handling) + * [Including Line Numbers in Asserts (Macros)](#including-line-numbers-in-asserts-macros) + * [Test Skipping](#test-skipping) + * [Running specific tests from the command line](#cmd-line-args) +* [Appendix](#appendix) + * [Getting help](#getting-help) + * [Zsh](#zsh) + +--- + +## <a name="introduction"></a> Introduction + +shUnit2 was originally developed to provide a consistent testing solution for +[log4sh][log4sh], a shell based logging framework similar to +[log4j](http://logging.apache.org). During the development of that product, a +repeated problem of having things work just fine under one shell (`/bin/bash` on +Linux to be specific), and then not working under another shell (`/bin/sh` on +Solaris) kept coming up. Although several simple tests were run, they were not +adequate and did not catch some corner cases. The decision was finally made to +write a proper unit test framework after multiple brown-bag releases were made. +_Research was done to look for an existing product that met the testing +requirements, but no adequate product was found._ + +### Tested software + +**Tested Operating Systems** (varies over time) + +OS | Support | Verified +----------------------------------- | --------- | -------- +Ubuntu Linux (14.04.05 LTS) | Travis CI | continuous +macOS High Sierra (10.13.3) | Travis CI | continuous +FreeBSD | user | unknown +Solaris 8, 9, 10 (inc. OpenSolaris) | user | unknown +Cygwin | user | unknown + +**Tested Shells** + +* Bourne Shell (__sh__) +* BASH - GNU Bourne Again SHell (__bash__) +* DASH (__dash__) +* Korn Shell (__ksh__) +* pdksh - Public Domain Korn Shell (__pdksh__) +* zsh - Zsh (__zsh__) (since 2.1.2) _please see the Zsh shell errata for more information_ + +See the appropriate Release Notes for this release +(`doc/RELEASE_NOTES-X.X.X.txt`) for the list of actual versions tested. + +### <a name="credits-contributors"></a> Credits / Contributors + +A list of contributors to shUnit2 can be found in `doc/contributors.md`. Many +thanks go out to all those who have contributed to make this a better tool. + +shUnit2 is the original product of many hours of work by Kate Ward, the primary +author of the code. For related software, check out https://github.com/kward. + +### <a name="feedback"></a> Feedback + +Feedback is most certainly welcome for this document. Send your questions, +comments, and criticisms via the +[shunit2-users](https://groups.google.com/a/forestent.com/forum/#!forum/shunit2-users/new) +forum (created 2018-12-09), or file an issue via +https://github.com/kward/shunit2/issues. + +--- + +## <a name="quickstart"></a> Quickstart + +This section will give a very quick start to running unit tests with shUnit2. +More information is located in later sections. + +Here is a quick sample script to show how easy it is to write a unit test in +shell. _Note: the script as it stands expects that you are running it from the +"examples" directory._ + +```sh +#! /bin/sh +# file: examples/equality_test.sh + +testEquality() { + assertEquals 1 1 +} + +# Load shUnit2. +. ./shunit2 +``` + +Running the unit test should give results similar to the following. + +```console +$ cd examples +$ ./equality_test.sh +testEquality + +Ran 1 test. + +OK +``` + +W00t! You've just run your first successful unit test. So, what just happened? +Quite a bit really, and it all happened simply by sourcing the `shunit2` +library. The basic functionality for the script above goes like this: + +* When shUnit2 is sourced, it will walk through any functions defined whose name + starts with the string `test`, and add those to an internal list of tests to + execute. Once a list of test functions to be run has been determined, shunit2 + will go to work. +* Before any tests are executed, shUnit2 again looks for a function, this time + one named `oneTimeSetUp()`. If it exists, it will be run. This function is + normally used to setup the environment for all tests to be run. Things like + creating directories for output or setting environment variables are good to + place here. Just so you know, you can also declare a corresponding function + named `oneTimeTearDown()` function that does the same thing, but once all the + tests have been completed. It is good for removing temporary directories, etc. +* shUnit2 is now ready to run tests. Before doing so though, it again looks for + another function that might be declared, one named `setUp()`. If the function + exists, it will be run before each test. It is good for resetting the + environment so that each test starts with a clean slate. **At this stage, the + first test is finally run.** The success of the test is recorded for a report + that will be generated later. After the test is run, shUnit2 looks for a final + function that might be declared, one named `tearDown()`. If it exists, it will + be run after each test. It is a good place for cleaning up after each test, + maybe doing things like removing files that were created, or removing + directories. This set of steps, `setUp() > test() > tearDown()`, is repeated + for all of the available tests. +* Once all the work is done, shUnit2 will generate the nice report you saw + above. A summary of all the successes and failures will be given so that you + know how well your code is doing. + +We should now try adding a test that fails. Change your unit test to look like +this. + +```sh +#! /bin/sh +# file: examples/party_test.sh + +testEquality() { + assertEquals 1 1 +} + +testPartyLikeItIs1999() { + year=`date '+%Y'` + assertEquals "It's not 1999 :-(" '1999' "${year}" +} + +# Load shUnit2. +. ./shunit2 +``` + +So, what did you get? I guess it told you that this isn't 1999. Bummer, eh? +Hopefully, you noticed a couple of things that were different about the second +test. First, we added an optional message that the user will see if the assert +fails. Second, we did comparisons of strings instead of integers as in the first +test. It doesn't matter whether you are testing for equality of strings or +integers. Both work equally well with shUnit2. + +Hopefully, this is enough to get you started with unit testing. If you want a +ton more examples, take a look at the tests provided with [log4sh][log4sh] or +[shFlags][shflags]. Both provide excellent examples of more advanced usage. +shUnit2 was after all written to meet the unit testing need that +[log4sh][log4sh] had. + +--- + +## <a name="function-reference"></a> Function Reference + +### <a name="general-info"></a> General Info + +Any string values passed should be properly quoted -- they should must be +surrounded by single-quote (`'`) or double-quote (`"`) characters -- so that the +shell will properly parse them. + +### <a name="asserts"></a> Asserts + +`assertEquals [message] expected actual` + +Asserts that _expected_ and _actual_ are equal to one another. The _expected_ +and _actual_ values can be either strings or integer values as both will be +treated as strings. The _message_ is optional, and must be quoted. + +`assertNotEquals [message] unexpected actual` + +Asserts that _unexpected_ and _actual_ are not equal to one another. The +_unexpected_ and _actual_ values can be either strings or integer values as both +will be treaded as strings. The _message_ is optional, and must be quoted. + +`assertSame [message] expected actual` + +This function is functionally equivalent to `assertEquals`. + +`assertNotSame [message] unexpected actual` + +This function is functionally equivalent to `assertNotEquals`. + +`assertContains [message] container content` + +Asserts that _container_ contains _content_. The _container_ and _content_ +values can be either strings or integer values as both will be treated as +strings. The _message_ is optional, and must be quoted. + +`assertNotContains [message] container content` + +Asserts that _container_ does not contain _content_. The _container_ and +_content_ values can be either strings or integer values as both will be treaded +as strings. The _message_ is optional, and must be quoted. + +`assertNull [message] value` + +Asserts that _value_ is _null_, or in shell terms, a zero-length string. The +_value_ must be a string as an integer value does not translate into a zero- +length string. The _message_ is optional, and must be quoted. + +`assertNotNull [message] value` + +Asserts that _value_ is _not null_, or in shell terms, a non-empty string. The +_value_ may be a string or an integer as the later will be parsed as a non-empty +string value. The _message_ is optional, and must be quoted. + +`assertTrue [message] condition` + +Asserts that a given shell test _condition_ is _true_. The condition can be as +simple as a shell _true_ value (the value `0` -- equivalent to +`${SHUNIT_TRUE}`), or a more sophisticated shell conditional expression. The +_message_ is optional, and must be quoted. + +A sophisticated shell conditional expression is equivalent to what the __if__ or +__while__ shell built-ins would use (more specifically, what the __test__ +command would use). Testing for example whether some value is greater than +another value can be done this way. + +`assertTrue "[ 34 -gt 23 ]"` + +Testing for the ability to read a file can also be done. This particular test +will fail. + +`assertTrue 'test failed' "[ -r /some/non-existant/file' ]"` + +As the expressions are standard shell __test__ expressions, it is possible to +string multiple expressions together with `-a` and `-o` in the standard fashion. +This test will succeed as the entire expression evaluates to _true_. + +`assertTrue 'test failed' '[ 1 -eq 1 -a 2 -eq 2 ]'` + +<i>One word of warning: be very careful with your quoting as shell is not the +most forgiving of bad quoting, and things will fail in strange ways.</i> + +`assertFalse [message] condition` + +Asserts that a given shell test _condition_ is _false_. The condition can be as +simple as a shell _false_ value (the value `1` -- equivalent to +`${SHUNIT_FALSE}`), or a more sophisticated shell conditional expression. The +_message_ is optional, and must be quoted. + +_For examples of more sophisticated expressions, see `assertTrue`._ + +### <a name="failures"></a> Failures + +Just to clarify, failures __do not__ test the various arguments against one +another. Failures simply fail, optionally with a message, and that is all they +do. If you need to test arguments against one another, use asserts. + +If all failures do is fail, why might one use them? There are times when you may +have some very complicated logic that you need to test, and the simple asserts +provided are simply not adequate. You can do your own validation of the code, +use an `assertTrue ${SHUNIT_TRUE}` if your own tests succeeded, and use a +failure to record a failure. + +`fail [message]` + +Fails the test immediately. The _message_ is optional, and must be quoted. + +`failNotEquals [message] unexpected actual` + +Fails the test immediately, reporting that the _unexpected_ and _actual_ values +are not equal to one another. The _message_ is optional, and must be quoted. + +_Note: no actual comparison of unexpected and actual is done._ + +`failSame [message] expected actual` + +Fails the test immediately, reporting that the _expected_ and _actual_ values +are the same. The _message_ is optional, and must be quoted. + +_Note: no actual comparison of expected and actual is done._ + +`failNotSame [message] expected actual` + +Fails the test immediately, reporting that the _expected_ and _actual_ values +are not the same. The _message_ is optional, and must be quoted. + +_Note: no actual comparison of expected and actual is done._ + +`failFound [message] content` + +Fails the test immediately, reporting that the _content_ was found. The +_message_ is optional, and must be quoted. + +_Note: no actual search of content is done._ + +`failNotFound [message] content` + +Fails the test immediately, reporting that the _content_ was not found. The +_message_ is optional, and must be quoted. + +_Note: no actual search of content is done._ + +### <a name="setup-teardown"></a> Setup/Teardown + +`oneTimeSetUp` + +This function can be be optionally overridden by the user in their test suite. + +If this function exists, it will be called once before any tests are run. It is +useful to prepare a common environment for all tests. + +`oneTimeTearDown` + +This function can be be optionally overridden by the user in their test suite. + +If this function exists, it will be called once after all tests are completed. +It is useful to clean up the environment after all tests. + +`setUp` + +This function can be be optionally overridden by the user in their test suite. + +If this function exists, it will be called before each test is run. It is useful +to reset the environment before each test. + +`tearDown` + +This function can be be optionally overridden by the user in their test suite. + +If this function exists, it will be called after each test completes. It is +useful to clean up the environment after each test. + +### <a name="skipping"></a> Skipping + +`startSkipping` + +This function forces the remaining _assert_ and _fail_ functions to be +"skipped", i.e. they will have no effect. Each function skipped will be recorded +so that the total of asserts and fails will not be altered. + +`endSkipping` + +This function returns calls to the _assert_ and _fail_ functions to their +default behavior, i.e. they will be called. + +`isSkipping` + +This function returns the current state of skipping. It can be compared against +`${SHUNIT_TRUE}` or `${SHUNIT_FALSE}` if desired. + +### <a name="suites"></a> Suites + +The default behavior of shUnit2 is that all tests will be found dynamically. If +you have a specific set of tests you want to run, or you don't want to use the +standard naming scheme of prefixing your tests with `test`, these functions are +for you. Most users will never use them though. + +`suite` + +This function can be optionally overridden by the user in their test suite. + +If this function exists, it will be called when `shunit2` is sourced. If it does +not exist, shUnit2 will search the parent script for all functions beginning +with the word `test`, and they will be added dynamically to the test suite. + +`suite_addTest name` + +This function adds a function named _name_ to the list of tests scheduled for +execution as part of this test suite. This function should only be called from +within the `suite()` function. + +--- + +## <a name="advanced-usage"></a> Advanced Usage + +### <a name="some-constants-you-can-use"></a> Some constants you can use + +There are several constants provided by shUnit2 as variables that might be of +use to you. + +*Predefined* + +| Constant | Value | +| --------------- | ----- | +| SHUNIT\_TRUE | Standard shell `true` value (the integer value 0). | +| SHUNIT\_FALSE | Standard shell `false` value (the integer value 1). | +| SHUNIT\_ERROR | The integer value 2. | +| SHUNIT\_TMPDIR | Path to temporary directory that will be automatically cleaned up upon exit of shUnit2. | +| SHUNIT\_VERSION | The version of shUnit2 you are running. | + +*User defined* + +| Constant | Value | +| ----------------- | ----- | +| SHUNIT\_CMD\_EXPR | Override which `expr` command is used. By default `expr` is used, except on BSD systems where `gexpr` is used. | +| SHUNIT\_COLOR | Enable colorized output. Options are 'auto', 'always', or 'none', with 'auto' being the default. | +| SHUNIT\_PARENT | The filename of the shell script containing the tests. This is needed specifically for Zsh support. | +| SHUNIT\_TEST\_PREFIX | Define this variable to add a prefix in front of each test name that is output in the test report. | + +### <a name="error-handling"></a> Error handling + +The constants values `SHUNIT_TRUE`, `SHUNIT_FALSE`, and `SHUNIT_ERROR` are +returned from nearly every function to indicate the success or failure of the +function. Additionally the variable `flags_error` is filled with a detailed +error message if any function returns with a `SHUNIT_ERROR` value. + +### <a name="including-line-numbers-in-asserts-macros"></a> Including Line Numbers in Asserts (Macros) + +If you include lots of assert statements in an individual test function, it can +become difficult to determine exactly which assert was thrown unless your +messages are unique. To help somewhat, line numbers can be included in the +assert messages. To enable this, a special shell "macro" must be used rather +than the standard assert calls. _Shell doesn't actually have macros; the name is +used here as the operation is similar to a standard macro._ + +For example, to include line numbers for a `assertEquals()` function call, +replace the `assertEquals()` with `${_ASSERT_EQUALS_}`. + +_**Example** -- Asserts with and without line numbers_ + +```sh +#! /bin/sh +# file: examples/lineno_test.sh + +testLineNo() { + # This assert will have line numbers included (e.g. "ASSERT:[123] ..."). + echo "ae: ${_ASSERT_EQUALS_}" + ${_ASSERT_EQUALS_} 'not equal' 1 2 + + # This assert will not have line numbers included (e.g. "ASSERT: ..."). + assertEquals 'not equal' 1 2 +} + +# Load shUnit2. +. ./shunit2 +``` + +Notes: + +1. Due to how shell parses command-line arguments, all strings used with macros + should be quoted twice. Namely, single-quotes must be converted to single- + double-quotes, and vice-versa. If the string being passed is absolutely for + sure not empty, the extra quoting is not necessary.<br/> + <br/> + Normal `assertEquals` call.<br/> + `assertEquals 'some message' 'x' ''`<br/> + <br/> + Macro `_ASSERT_EQUALS_` call. Note the extra quoting around the _message_ and + the _null_ value.<br/> + `_ASSERT_EQUALS_ '"some message"' 'x' '""'` + +1. Line numbers are not supported in all shells. If a shell does not support + them, no errors will be thrown. Supported shells include: __bash__ (>=3.0), + __ksh__, __pdksh__, and __zsh__. + +### <a name="test-skipping"></a> Test Skipping + +There are times where the test code you have written is just not applicable to +the system you are running on. This section describes how to skip these tests +but maintain the total test count. + +Probably the easiest example would be shell code that is meant to run under the +__bash__ shell, but the unit test is running under the Bourne shell. There are +things that just won't work. The following test code demonstrates two sample +functions, one that will be run under any shell, and the another that will run +only under the __bash__ shell. + +_**Example** -- math include_ +```sh +# file: examples/math.inc. + +add_generic() { + num_a=$1 + num_b=$2 + + expr $1 + $2 +} + +add_bash() { + num_a=$1 + num_b=$2 + + echo $(($1 + $2)) +} +``` + +And here is a corresponding unit test that correctly skips the `add_bash()` function when the unit test is not running under the __bash__ shell. + +_**Example** -- math unit test_ +```sh +#! /bin/sh +# file: examples/math_test.sh + +testAdding() { + result=`add_generic 1 2` + assertEquals \ + "the result of '${result}' was wrong" \ + 3 "${result}" + + # Disable non-generic tests. + [ -z "${BASH_VERSION:-}" ] && startSkipping + + result=`add_bash 1 2` + assertEquals \ + "the result of '${result}' was wrong" \ + 3 "${result}" +} + +oneTimeSetUp() { + # Load include to test. + . ./math.inc +} + +# Load and run shUnit2. +. ./shunit2 +``` + +Running the above test under the __bash__ shell will result in the following +output. + +```console +$ /bin/bash math_test.sh +testAdding + +Ran 1 test. + +OK +``` + +But, running the test under any other Unix shell will result in the following +output. + +```console +$ /bin/ksh math_test.sh +testAdding + +Ran 1 test. + +OK (skipped=1) +``` + +As you can see, the total number of tests has not changed, but the report +indicates that some tests were skipped. + +Skipping can be controlled with the following functions: `startSkipping()`, +`endSkipping()`, and `isSkipping()`. Once skipping is enabled, it will remain +enabled until the end of the current test function call, after which skipping is +disabled. + +### <a name="cmd-line-args"></a> Running specific tests from the command line. + +When running a test script, you may override the default set of tests, or the suite-specified set of tests, by providing additional arguments on the command line. Each additional argument after the `--` marker is assumed to be the name of a test function to be run in the order specified. e.g. + +```console +test-script.sh -- testOne testTwo otherFunction +``` + +or + +```console +shunit2 test-script.sh testOne testTwo otherFunction +``` + +In either case, three functions will be run as tests, `testOne`, `testTwo`, and `otherFunction`. Note that the function `otherFunction` would not normally be run by `shunit2` as part of the implicit collection of tests as it's function name does not match the test function name pattern `test*`. + +If a specified test function does not exist, `shunit2` will still attempt to run that function and thereby cause a failure which `shunit2` will catch and mark as a failed test. All other tests will run normally. + +The specification of tests does not affect how `shunit2` looks for and executes the setup and tear down functions, which will still run as expected. + +--- + +## <a name="appendix"></a> Appendix + +### <a name="getting-help"></a> Getting Help + +For help, please send requests to either the shunit2-users@forestent.com mailing +list (archives available on the web at +https://groups.google.com/a/forestent.com/forum/#!forum/shunit2-users) or +directly to Kate Ward <kate dot ward at forestent dot com>. + +### <a name="zsh"></a> Zsh + +For compatibility with Zsh, there is one requirement that must be met -- the +`shwordsplit` option must be set. There are three ways to accomplish this. + +1. In the unit-test script, add the following shell code snippet before sourcing + the `shunit2` library. + + ```sh + setopt shwordsplit + ``` + +2. When invoking __zsh__ from either the command-line or as a script with `#!`, + add the `-y` parameter. + + ```sh + #! /bin/zsh -y + ``` + +3. When invoking __zsh__ from the command-line, add `-o shwordsplit --` as + parameters before the script name. + + ```console + $ zsh -o shwordsplit -- some_script + ``` + +[log4sh]: https://github.com/kward/log4sh +[shflags]: https://github.com/kward/shflags |