├── LICENSE ├── README.md ├── butler ├── butler-base.sh ├── butlerfile ├── complete.bash ├── complete.zsh ├── init.sh ├── shunit ├── shunit2 ├── shunit2_test.sh ├── shunit2_test_asserts.sh ├── shunit2_test_failures.sh ├── shunit2_test_helpers ├── shunit2_test_macros.sh ├── shunit2_test_misc.sh └── shunit2_test_standalone.sh ├── test.sh └── tests ├── butlerfile_test.sh ├── commands_test.sh ├── completion_test.sh ├── example_test.sh ├── helpers.sh ├── initcommand_test.sh └── safety_test.sh /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2014 Michael Allen 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining a copy of 4 | this software and associated documentation files (the "Software"), to deal in 5 | the Software without restriction, including without limitation the rights to 6 | use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies 7 | of the Software, and to permit persons to whom the Software is furnished to do 8 | so, subject to the following conditions: 9 | 10 | The above copyright notice and this permission notice shall be included in all 11 | copies or substantial portions of the Software. 12 | 13 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 19 | SOFTWARE. 20 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | #Butler 2 | Turn: 3 | 4 | `bundle exec rails server` 5 | `foreman run python app.py db upgrade` 6 | `...` 7 | 8 | into: 9 | 10 | `butler run` or `butler build` or `butler test`. 11 | 12 | Basically anything you do every day, let the Butler do it. 13 | 14 | ##Installation 15 | 16 | Butler is easiest installed via homebrew: 17 | 18 | > brew install michaeldfallen/formula/butler 19 | 20 | Then run `butler --init` to create a sample butlerfile and get started. 21 | 22 | ###Bash and Zsh completion 23 | 24 | To enable completion add the following to your `~/.bashrc` or `~/.zshrc`: 25 | 26 | source "$(butler --init-completion)" 27 | 28 | That will load the correct completion files for your shell. 29 | 30 | ##Usage 31 | 32 | Create a butlerfile to define your commands 33 | 34 | [command]: [shell command to run] 35 | 36 | then tell butler to do it 37 | 38 | > butler [command] 39 | Executing [command] 40 | 41 | The first time you ask butler to run a command it will confirm with you that the 42 | command is safe: 43 | 44 | > butler [command] 45 | First time executing [command]: [shell command to run] 46 | Execute [command]? (y)es, (n)o, just this (o)nce 47 | 48 | This way you can happily use other peoples butlerfile commands without worrying 49 | about them sneaking an `rm -rf ~` in to the script. 50 | 51 | ###Setting the shell 52 | 53 | By default butler will look at `$SHELL`, which is set by most shells including 54 | ZSH. This should mean that butler will automatically use your default shell to 55 | execute commands. 56 | 57 | If `$SHELL` is not set it will fall back on Bash. 58 | 59 | If you want to set a specific shell for butler to use just export 60 | `$BUTLER_SHELL`: 61 | 62 | > echo 'BUTLER_SHELL="/bin/dash"' >> ~/.zshrc 63 | 64 | ###Longer scripts - coming soon 65 | 66 | For longer scripts just drop them in a `bin` folder 67 | 68 | project/ 69 | bin/ 70 | complexbuild 71 | .. 72 | 73 | Butler will know what to do 74 | 75 | > butler complexbuild 76 | Aye, sir... 77 | 78 | ##License 79 | 80 | Butler is licensed under the MIT license. 81 | 82 | See [LICENSE] for the full license text. 83 | 84 | ##Credits 85 | 86 | Inspired by 87 | [Foreman] by [David Dollar] [@ddollar] 88 | and 89 | [Shoreman] by [Chris Mytton] [@chrismytton] 90 | 91 | [Foreman]: https://github.com/ddollar/foreman 92 | [David Dollar]: https://github.com/ddollar 93 | [@ddollar]: https://twitter.com/ddollar 94 | [Shoreman]: https://github.com/chrismytton/shoreman 95 | [Chris Mytton]: https://github.com/chrismytton 96 | [@chrismytton]: https://twitter.com/chrismytton 97 | [LICENSE]: https://github.com/michaeldfallen/butler/blob/master/LICENSE 98 | -------------------------------------------------------------------------------- /butler: -------------------------------------------------------------------------------- 1 | #! /usr/bin/env bash 2 | # 3 | # Butler 4 | # 5 | # A task runner to simplify development 6 | # Let the Butler do it. 7 | 8 | if [[ "$OSTYPE" == *darwin* ]]; then 9 | READLINK_CMD='greadlink' 10 | else 11 | READLINK_CMD='readlink' 12 | fi 13 | 14 | dot="$(cd "$(dirname "$([ -L "$0" ] && $READLINK_CMD -f "$0" || echo "$0")")"; pwd)" 15 | 16 | if [[ "$1" == "--init-completion" ]]; then 17 | echo "$dot/init.sh" 18 | exit 1 19 | fi 20 | 21 | source "$dot/butler-base.sh" 22 | 23 | butler_exec "$@" 24 | -------------------------------------------------------------------------------- /butler-base.sh: -------------------------------------------------------------------------------- 1 | #! /usr/bin/env bash 2 | # 3 | # Butler-base 4 | # 5 | # The API for Butler. 6 | # Let the Butler do it. 7 | 8 | if [[ "$OSTYPE" == *darwin* ]]; then 9 | SHA_CMD="gsha256sum" 10 | else 11 | SHA_CMD="sha256sum" 12 | fi 13 | 14 | usage() { 15 | echo "usage:" 16 | echo " butler [COMMAND] # Run a command defined in your butlerfile" 17 | echo " butler # List all known commands" 18 | } 19 | 20 | error() { 21 | echo "error: $@" 22 | } 23 | 24 | list_commands() { 25 | local butlerfile="$1" 26 | echo "commands:" 27 | while read line || [[ -n "$line" ]]; do 28 | echo " $line" 29 | done < "$butlerfile" 30 | } 31 | 32 | complete_command() { 33 | local butlerfile="$1"; shift 34 | local word="$@" 35 | while read line || [[ -n "$line" ]]; do 36 | local name="${line%%:*}" 37 | if [[ "$name" == *"$word"* ]]; then 38 | echo "$name" 39 | fi 40 | done < "$butlerfile" 41 | } 42 | 43 | hash_this() { 44 | echo "$@" | $SHA_CMD | sed 's/ -$//' 45 | } 46 | 47 | record_hash() { 48 | local dot_butler="${DOT_BUTLER:-$HOME/.butler}" 49 | if [ ! -d "$dot_butler" ]; then 50 | mkdir -p "$dot_butler" 51 | fi 52 | touch "$dot_butler/$@" 53 | } 54 | 55 | can_continue() { 56 | local dot_butler="${DOT_BUTLER:-$HOME/.butler}" 57 | local name="$1"; shift; 58 | local command="$1"; shift; 59 | local hash="$(hash_this "$name: $command")" 60 | if [ -f "$dot_butler/$hash" ]; then 61 | return 0 62 | else 63 | echo "First time executing $name: $command" 64 | echo -n "Execute $name? (y)es, (n)o, just this (o)nce: " 65 | read execute_permission 66 | if [[ "$execute_permission" == "y" ]]; then 67 | record_hash "$hash" 68 | return 0 69 | elif [[ "$execute_permission" == "n" ]]; then 70 | exit 1 71 | elif [[ "$execute_permission" == "o" ]]; then 72 | return 0 73 | fi 74 | return 1 75 | fi 76 | } 77 | 78 | execute() { 79 | local name="$1";shift; 80 | local command="$1";shift; 81 | local args=$@ 82 | if can_continue "$name" "$command"; then 83 | echo "Executing $name: $command" 84 | bash -c "$command" -- $args 85 | fi 86 | } 87 | 88 | init_butlerfile() { 89 | echo "Creating an example butlerfile with one command: hello" 90 | echo "Try executing:" 91 | echo "> butler hello" 92 | echo "hello: echo \"Hello, World!\"" >> butlerfile 93 | } 94 | 95 | run_command() { 96 | local targetname="$1"; shift; 97 | local args=$@ 98 | local foundcommand="" 99 | local foundnum=0 100 | 101 | while read line || [[ -n "$line" ]]; do 102 | local name="${line%%:*}" 103 | local command="${line#*:[[:space:]]}" 104 | if [ "$name" == "$targetname" ]; then 105 | foundcommand="$command" 106 | let foundnum+=1 107 | fi 108 | done < "$butlerfile" 109 | 110 | if [[ -z "$foundcommand" ]]; then 111 | error "$targetname doesn't exist in your butlerfile" 112 | exit 1 113 | elif [[ "$foundnum" -ne "1" ]]; then 114 | error "found $foundnum commands named $targetname, please fix your butlerfile" 115 | exit 1 116 | else 117 | execute "$targetname" "$foundcommand" $args 118 | fi 119 | } 120 | 121 | butler_exec() { 122 | local command="$1"; shift; 123 | local butlerfile='butlerfile' 124 | if [[ "$command" == "--init" ]]; then 125 | if [[ -f $butlerfile ]]; then 126 | error "butlerfile already exists" 127 | list_commands $butlerfile 128 | exit 1 129 | else 130 | init_butlerfile 131 | exit 0 132 | fi 133 | fi 134 | 135 | if [[ "$command" == "--cmplt" ]]; then 136 | if [[ -f $butlerfile ]]; then 137 | complete_command $butlerfile "$@" 138 | exit 0 139 | else 140 | exit 1 141 | fi 142 | fi 143 | 144 | if [[ ! -f $butlerfile ]]; then 145 | error "No butlerfile found." 146 | exit 1 147 | fi 148 | 149 | if [[ -z "$command" ]]; then 150 | usage 151 | list_commands $butlerfile 152 | exit 0 153 | fi 154 | 155 | if [[ -n "$command" ]]; then 156 | run_command "$command" $@ 157 | exit 0 158 | fi 159 | exit 1 160 | } 161 | -------------------------------------------------------------------------------- /butlerfile: -------------------------------------------------------------------------------- 1 | test: ./test.sh 2 | -------------------------------------------------------------------------------- /complete.bash: -------------------------------------------------------------------------------- 1 | _butler_complete() { 2 | COMPREPLY=() 3 | local word="${COMP_WORDS[COMP_CWORD]}" 4 | if [ "${#COMP_WORDS[@]}" -eq 2 ]; then 5 | local completions="$(butler --cmplt "$word")" 6 | COMPREPLY=( $(compgen -W "$completions" -- "$word") ) 7 | fi 8 | } 9 | 10 | complete -F _butler_complete butler 11 | -------------------------------------------------------------------------------- /complete.zsh: -------------------------------------------------------------------------------- 1 | _butler_complete() { 2 | local word words completions 3 | read -cA words 4 | word="${words[2]}" 5 | if [ "${#words[@]}" -eq 2 ]; then 6 | completions="$(butler --cmplt "${word}")" 7 | fi 8 | reply=( "${(ps:\n:)completions}" ) 9 | } 10 | 11 | compctl -K _butler_complete butler 12 | -------------------------------------------------------------------------------- /init.sh: -------------------------------------------------------------------------------- 1 | if [[ "$OSTYPE" == *darwin* ]]; then 2 | READLINK_CMD='greadlink' 3 | else 4 | READLINK_CMD='readlink' 5 | fi 6 | 7 | dot="$(cd "$(dirname "$([ -L "$0" ] && $READLINK_CMD -f "$0" || echo "$0")")"; pwd)" 8 | 9 | if [[ -n "$ZSH_VERSION" ]]; then 10 | source "$dot/complete.zsh" 11 | elif [[ -n "$BASH_VERSION" ]]; then 12 | source "$dot/complete.bash" 13 | fi 14 | -------------------------------------------------------------------------------- /shunit/shunit2: -------------------------------------------------------------------------------- 1 | #! /bin/sh 2 | # $Id: shunit2 335 2011-05-01 20:10:33Z kate.ward@forestent.com $ 3 | # vim:et:ft=sh:sts=2:sw=2 4 | # 5 | # Copyright 2008 Kate Ward. All Rights Reserved. 6 | # Released under the LGPL (GNU Lesser General Public License) 7 | # 8 | # shUnit2 -- Unit testing framework for Unix shell scripts. 9 | # http://code.google.com/p/shunit2/ 10 | # 11 | # Author: kate.ward@forestent.com (Kate Ward) 12 | # 13 | # shUnit2 is a xUnit based unit test framework for Bourne shell scripts. It is 14 | # based on the popular JUnit unit testing framework for Java. 15 | 16 | # return if shunit already loaded 17 | [ -n "${SHUNIT_VERSION:-}" ] && exit 0 18 | 19 | SHUNIT_VERSION='2.1.6' 20 | 21 | SHUNIT_TRUE=0 22 | SHUNIT_FALSE=1 23 | SHUNIT_ERROR=2 24 | 25 | # enable strict mode by default 26 | SHUNIT_STRICT=${SHUNIT_STRICT:-${SHUNIT_TRUE}} 27 | 28 | _shunit_warn() { echo "shunit2:WARN $@" >&2; } 29 | _shunit_error() { echo "shunit2:ERROR $@" >&2; } 30 | _shunit_fatal() { echo "shunit2:FATAL $@" >&2; exit ${SHUNIT_ERROR}; } 31 | 32 | # specific shell checks 33 | if [ -n "${ZSH_VERSION:-}" ]; then 34 | setopt |grep "^shwordsplit$" >/dev/null 35 | if [ $? -ne ${SHUNIT_TRUE} ]; then 36 | _shunit_fatal 'zsh shwordsplit option is required for proper operation' 37 | fi 38 | if [ -z "${SHUNIT_PARENT:-}" ]; then 39 | _shunit_fatal "zsh does not pass \$0 through properly. please declare \ 40 | \"SHUNIT_PARENT=\$0\" before calling shUnit2" 41 | fi 42 | fi 43 | 44 | # 45 | # constants 46 | # 47 | 48 | __SHUNIT_ASSERT_MSG_PREFIX='ASSERT:' 49 | __SHUNIT_MODE_SOURCED='sourced' 50 | __SHUNIT_MODE_STANDALONE='standalone' 51 | __SHUNIT_PARENT=${SHUNIT_PARENT:-$0} 52 | 53 | # set the constants readonly 54 | shunit_constants_=`set |grep '^__SHUNIT_' |cut -d= -f1` 55 | echo "${shunit_constants_}" |grep '^Binary file' >/dev/null && \ 56 | shunit_constants_=`set |grep -a '^__SHUNIT_' |cut -d= -f1` 57 | for shunit_constant_ in ${shunit_constants_}; do 58 | shunit_ro_opts_='' 59 | case ${ZSH_VERSION:-} in 60 | '') ;; # this isn't zsh 61 | [123].*) ;; # early versions (1.x, 2.x, 3.x) 62 | *) shunit_ro_opts_='-g' ;; # all later versions. declare readonly globally 63 | esac 64 | readonly ${shunit_ro_opts_} ${shunit_constant_} 65 | done 66 | unset shunit_constant_ shunit_constants_ shunit_ro_opts_ 67 | 68 | # variables 69 | __shunit_lineno='' # line number of executed test 70 | __shunit_mode=${__SHUNIT_MODE_SOURCED} # operating mode 71 | __shunit_reportGenerated=${SHUNIT_FALSE} # is report generated 72 | __shunit_script='' # filename of unittest script (standalone mode) 73 | __shunit_skip=${SHUNIT_FALSE} # is skipping enabled 74 | __shunit_suite='' # suite of tests to execute 75 | 76 | # counts of tests 77 | __shunit_testSuccess=${SHUNIT_TRUE} 78 | __shunit_testsTotal=0 79 | __shunit_testsPassed=0 80 | __shunit_testsFailed=0 81 | 82 | # counts of asserts 83 | __shunit_assertsTotal=0 84 | __shunit_assertsPassed=0 85 | __shunit_assertsFailed=0 86 | __shunit_assertsSkipped=0 87 | 88 | # macros 89 | _SHUNIT_LINENO_='eval __shunit_lineno=""; if [ "${1:-}" = "--lineno" ]; then [ -n "$2" ] && __shunit_lineno="[$2] "; shift 2; fi' 90 | 91 | #----------------------------------------------------------------------------- 92 | # assert functions 93 | # 94 | 95 | # Assert that two values are equal to one another. 96 | # 97 | # Args: 98 | # message: string: failure message [optional] 99 | # expected: string: expected value 100 | # actual: string: actual value 101 | # Returns: 102 | # integer: success (TRUE/FALSE/ERROR constant) 103 | assertEquals() 104 | { 105 | ${_SHUNIT_LINENO_} 106 | if [ $# -lt 2 -o $# -gt 3 ]; then 107 | _shunit_error "assertEquals() requires two or three arguments; $# given" 108 | _shunit_error "1: ${1:+$1} 2: ${2:+$2} 3: ${3:+$3}${4:+ 4: $4}" 109 | return ${SHUNIT_ERROR} 110 | fi 111 | _shunit_shouldSkip && return ${SHUNIT_TRUE} 112 | 113 | shunit_message_=${__shunit_lineno} 114 | if [ $# -eq 3 ]; then 115 | shunit_message_="${shunit_message_}$1" 116 | shift 117 | fi 118 | shunit_expected_=$1 119 | shunit_actual_=$2 120 | 121 | shunit_return=${SHUNIT_TRUE} 122 | if [ "${shunit_expected_}" = "${shunit_actual_}" ]; then 123 | _shunit_assertPass 124 | else 125 | failNotEquals "${shunit_message_}" "${shunit_expected_}" "${shunit_actual_}" 126 | shunit_return=${SHUNIT_FALSE} 127 | fi 128 | 129 | unset shunit_message_ shunit_expected_ shunit_actual_ 130 | return ${shunit_return} 131 | } 132 | _ASSERT_EQUALS_='eval assertEquals --lineno "${LINENO:-}"' 133 | 134 | # Assert that two values are not equal to one another. 135 | # 136 | # Args: 137 | # message: string: failure message [optional] 138 | # expected: string: expected value 139 | # actual: string: actual value 140 | # Returns: 141 | # integer: success (TRUE/FALSE/ERROR constant) 142 | assertNotEquals() 143 | { 144 | ${_SHUNIT_LINENO_} 145 | if [ $# -lt 2 -o $# -gt 3 ]; then 146 | _shunit_error "assertNotEquals() requires two or three arguments; $# given" 147 | return ${SHUNIT_ERROR} 148 | fi 149 | _shunit_shouldSkip && return ${SHUNIT_TRUE} 150 | 151 | shunit_message_=${__shunit_lineno} 152 | if [ $# -eq 3 ]; then 153 | shunit_message_="${shunit_message_}$1" 154 | shift 155 | fi 156 | shunit_expected_=$1 157 | shunit_actual_=$2 158 | 159 | shunit_return=${SHUNIT_TRUE} 160 | if [ "${shunit_expected_}" != "${shunit_actual_}" ]; then 161 | _shunit_assertPass 162 | else 163 | failSame "${shunit_message_}" "$@" 164 | shunit_return=${SHUNIT_FALSE} 165 | fi 166 | 167 | unset shunit_message_ shunit_expected_ shunit_actual_ 168 | return ${shunit_return} 169 | } 170 | _ASSERT_NOT_EQUALS_='eval assertNotEquals --lineno "${LINENO:-}"' 171 | 172 | # Assert that a value is null (i.e. an empty string) 173 | # 174 | # Args: 175 | # message: string: failure message [optional] 176 | # actual: string: actual value 177 | # Returns: 178 | # integer: success (TRUE/FALSE/ERROR constant) 179 | assertNull() 180 | { 181 | ${_SHUNIT_LINENO_} 182 | if [ $# -lt 1 -o $# -gt 2 ]; then 183 | _shunit_error "assertNull() requires one or two arguments; $# given" 184 | return ${SHUNIT_ERROR} 185 | fi 186 | _shunit_shouldSkip && return ${SHUNIT_TRUE} 187 | 188 | shunit_message_=${__shunit_lineno} 189 | if [ $# -eq 2 ]; then 190 | shunit_message_="${shunit_message_}$1" 191 | shift 192 | fi 193 | assertTrue "${shunit_message_}" "[ -z '$1' ]" 194 | shunit_return=$? 195 | 196 | unset shunit_message_ 197 | return ${shunit_return} 198 | } 199 | _ASSERT_NULL_='eval assertNull --lineno "${LINENO:-}"' 200 | 201 | # Assert that a value is not null (i.e. a non-empty string) 202 | # 203 | # Args: 204 | # message: string: failure message [optional] 205 | # actual: string: actual value 206 | # Returns: 207 | # integer: success (TRUE/FALSE/ERROR constant) 208 | assertNotNull() 209 | { 210 | ${_SHUNIT_LINENO_} 211 | if [ $# -gt 2 ]; then # allowing 0 arguments as $1 might actually be null 212 | _shunit_error "assertNotNull() requires one or two arguments; $# given" 213 | return ${SHUNIT_ERROR} 214 | fi 215 | _shunit_shouldSkip && return ${SHUNIT_TRUE} 216 | 217 | shunit_message_=${__shunit_lineno} 218 | if [ $# -eq 2 ]; then 219 | shunit_message_="${shunit_message_}$1" 220 | shift 221 | fi 222 | shunit_actual_=`_shunit_escapeCharactersInString "${1:-}"` 223 | test -n "${shunit_actual_}" 224 | assertTrue "${shunit_message_}" $? 225 | shunit_return=$? 226 | 227 | unset shunit_actual_ shunit_message_ 228 | return ${shunit_return} 229 | } 230 | _ASSERT_NOT_NULL_='eval assertNotNull --lineno "${LINENO:-}"' 231 | 232 | # Assert that two values are the same (i.e. equal to one another). 233 | # 234 | # Args: 235 | # message: string: failure message [optional] 236 | # expected: string: expected value 237 | # actual: string: actual value 238 | # Returns: 239 | # integer: success (TRUE/FALSE/ERROR constant) 240 | assertSame() 241 | { 242 | ${_SHUNIT_LINENO_} 243 | if [ $# -lt 2 -o $# -gt 3 ]; then 244 | _shunit_error "assertSame() requires two or three arguments; $# given" 245 | return ${SHUNIT_ERROR} 246 | fi 247 | _shunit_shouldSkip && return ${SHUNIT_TRUE} 248 | 249 | shunit_message_=${__shunit_lineno} 250 | if [ $# -eq 3 ]; then 251 | shunit_message_="${shunit_message_}$1" 252 | shift 253 | fi 254 | assertEquals "${shunit_message_}" "$1" "$2" 255 | shunit_return=$? 256 | 257 | unset shunit_message_ 258 | return ${shunit_return} 259 | } 260 | _ASSERT_SAME_='eval assertSame --lineno "${LINENO:-}"' 261 | 262 | # Assert that two values are not the same (i.e. not equal to one another). 263 | # 264 | # Args: 265 | # message: string: failure message [optional] 266 | # expected: string: expected value 267 | # actual: string: actual value 268 | # Returns: 269 | # integer: success (TRUE/FALSE/ERROR constant) 270 | assertNotSame() 271 | { 272 | ${_SHUNIT_LINENO_} 273 | if [ $# -lt 2 -o $# -gt 3 ]; then 274 | _shunit_error "assertNotSame() requires two or three arguments; $# given" 275 | return ${SHUNIT_ERROR} 276 | fi 277 | _shunit_shouldSkip && return ${SHUNIT_TRUE} 278 | 279 | shunit_message_=${__shunit_lineno} 280 | if [ $# -eq 3 ]; then 281 | shunit_message_="${shunit_message_:-}$1" 282 | shift 283 | fi 284 | assertNotEquals "${shunit_message_}" "$1" "$2" 285 | shunit_return=$? 286 | 287 | unset shunit_message_ 288 | return ${shunit_return} 289 | } 290 | _ASSERT_NOT_SAME_='eval assertNotSame --lineno "${LINENO:-}"' 291 | 292 | # Assert that a value or shell test condition is true. 293 | # 294 | # In shell, a value of 0 is true and a non-zero value is false. Any integer 295 | # value passed can thereby be tested. 296 | # 297 | # Shell supports much more complicated tests though, and a means to support 298 | # them was needed. As such, this function tests that conditions are true or 299 | # false through evaluation rather than just looking for a true or false. 300 | # 301 | # The following test will succeed: 302 | # assertTrue 0 303 | # assertTrue "[ 34 -gt 23 ]" 304 | # The folloing test will fail with a message: 305 | # assertTrue 123 306 | # assertTrue "test failed" "[ -r '/non/existant/file' ]" 307 | # 308 | # Args: 309 | # message: string: failure message [optional] 310 | # condition: string: integer value or shell conditional statement 311 | # Returns: 312 | # integer: success (TRUE/FALSE/ERROR constant) 313 | assertTrue() 314 | { 315 | ${_SHUNIT_LINENO_} 316 | if [ $# -gt 2 ]; then 317 | _shunit_error "assertTrue() takes one two arguments; $# given" 318 | return ${SHUNIT_ERROR} 319 | fi 320 | _shunit_shouldSkip && return ${SHUNIT_TRUE} 321 | 322 | shunit_message_=${__shunit_lineno} 323 | if [ $# -eq 2 ]; then 324 | shunit_message_="${shunit_message_}$1" 325 | shift 326 | fi 327 | shunit_condition_=$1 328 | 329 | # see if condition is an integer, i.e. a return value 330 | shunit_match_=`expr "${shunit_condition_}" : '\([0-9]*\)'` 331 | shunit_return=${SHUNIT_TRUE} 332 | if [ -z "${shunit_condition_}" ]; then 333 | # null condition 334 | shunit_return=${SHUNIT_FALSE} 335 | elif [ -n "${shunit_match_}" -a "${shunit_condition_}" = "${shunit_match_}" ] 336 | then 337 | # possible return value. treating 0 as true, and non-zero as false. 338 | [ ${shunit_condition_} -ne 0 ] && shunit_return=${SHUNIT_FALSE} 339 | else 340 | # (hopefully) a condition 341 | ( eval ${shunit_condition_} ) >/dev/null 2>&1 342 | [ $? -ne 0 ] && shunit_return=${SHUNIT_FALSE} 343 | fi 344 | 345 | # record the test 346 | if [ ${shunit_return} -eq ${SHUNIT_TRUE} ]; then 347 | _shunit_assertPass 348 | else 349 | _shunit_assertFail "${shunit_message_}" 350 | fi 351 | 352 | unset shunit_message_ shunit_condition_ shunit_match_ 353 | return ${shunit_return} 354 | } 355 | _ASSERT_TRUE_='eval assertTrue --lineno "${LINENO:-}"' 356 | 357 | # Assert that a value or shell test condition is false. 358 | # 359 | # In shell, a value of 0 is true and a non-zero value is false. Any integer 360 | # value passed can thereby be tested. 361 | # 362 | # Shell supports much more complicated tests though, and a means to support 363 | # them was needed. As such, this function tests that conditions are true or 364 | # false through evaluation rather than just looking for a true or false. 365 | # 366 | # The following test will succeed: 367 | # assertFalse 1 368 | # assertFalse "[ 'apples' = 'oranges' ]" 369 | # The folloing test will fail with a message: 370 | # assertFalse 0 371 | # assertFalse "test failed" "[ 1 -eq 1 -a 2 -eq 2 ]" 372 | # 373 | # Args: 374 | # message: string: failure message [optional] 375 | # condition: string: integer value or shell conditional statement 376 | # Returns: 377 | # integer: success (TRUE/FALSE/ERROR constant) 378 | assertFalse() 379 | { 380 | ${_SHUNIT_LINENO_} 381 | if [ $# -lt 1 -o $# -gt 2 ]; then 382 | _shunit_error "assertFalse() quires one or two arguments; $# given" 383 | return ${SHUNIT_ERROR} 384 | fi 385 | _shunit_shouldSkip && return ${SHUNIT_TRUE} 386 | 387 | shunit_message_=${__shunit_lineno} 388 | if [ $# -eq 2 ]; then 389 | shunit_message_="${shunit_message_}$1" 390 | shift 391 | fi 392 | shunit_condition_=$1 393 | 394 | # see if condition is an integer, i.e. a return value 395 | shunit_match_=`expr "${shunit_condition_}" : '\([0-9]*\)'` 396 | shunit_return=${SHUNIT_TRUE} 397 | if [ -z "${shunit_condition_}" ]; then 398 | # null condition 399 | shunit_return=${SHUNIT_FALSE} 400 | elif [ -n "${shunit_match_}" -a "${shunit_condition_}" = "${shunit_match_}" ] 401 | then 402 | # possible return value. treating 0 as true, and non-zero as false. 403 | [ ${shunit_condition_} -eq 0 ] && shunit_return=${SHUNIT_FALSE} 404 | else 405 | # (hopefully) a condition 406 | ( eval ${shunit_condition_} ) >/dev/null 2>&1 407 | [ $? -eq 0 ] && shunit_return=${SHUNIT_FALSE} 408 | fi 409 | 410 | # record the test 411 | if [ ${shunit_return} -eq ${SHUNIT_TRUE} ]; then 412 | _shunit_assertPass 413 | else 414 | _shunit_assertFail "${shunit_message_}" 415 | fi 416 | 417 | unset shunit_message_ shunit_condition_ shunit_match_ 418 | return ${shunit_return} 419 | } 420 | _ASSERT_FALSE_='eval assertFalse --lineno "${LINENO:-}"' 421 | 422 | #----------------------------------------------------------------------------- 423 | # failure functions 424 | # 425 | 426 | # Records a test failure. 427 | # 428 | # Args: 429 | # message: string: failure message [optional] 430 | # Returns: 431 | # integer: success (TRUE/FALSE/ERROR constant) 432 | fail() 433 | { 434 | ${_SHUNIT_LINENO_} 435 | if [ $# -gt 1 ]; then 436 | _shunit_error "fail() requires zero or one arguments; $# given" 437 | return ${SHUNIT_ERROR} 438 | fi 439 | _shunit_shouldSkip && return ${SHUNIT_TRUE} 440 | 441 | shunit_message_=${__shunit_lineno} 442 | if [ $# -eq 1 ]; then 443 | shunit_message_="${shunit_message_}$1" 444 | shift 445 | fi 446 | 447 | _shunit_assertFail "${shunit_message_}" 448 | 449 | unset shunit_message_ 450 | return ${SHUNIT_FALSE} 451 | } 452 | _FAIL_='eval fail --lineno "${LINENO:-}"' 453 | 454 | # Records a test failure, stating two values were not equal. 455 | # 456 | # Args: 457 | # message: string: failure message [optional] 458 | # expected: string: expected value 459 | # actual: string: actual value 460 | # Returns: 461 | # integer: success (TRUE/FALSE/ERROR constant) 462 | failNotEquals() 463 | { 464 | ${_SHUNIT_LINENO_} 465 | if [ $# -lt 2 -o $# -gt 3 ]; then 466 | _shunit_error "failNotEquals() requires one or two arguments; $# given" 467 | return ${SHUNIT_ERROR} 468 | fi 469 | _shunit_shouldSkip && return ${SHUNIT_TRUE} 470 | 471 | shunit_message_=${__shunit_lineno} 472 | if [ $# -eq 3 ]; then 473 | shunit_message_="${shunit_message_}$1" 474 | shift 475 | fi 476 | shunit_expected_=$1 477 | shunit_actual_=$2 478 | 479 | _shunit_assertFail "${shunit_message_:+${shunit_message_} }expected:<${shunit_expected_}> but was:<${shunit_actual_}>" 480 | 481 | unset shunit_message_ shunit_expected_ shunit_actual_ 482 | return ${SHUNIT_FALSE} 483 | } 484 | _FAIL_NOT_EQUALS_='eval failNotEquals --lineno "${LINENO:-}"' 485 | 486 | # Records a test failure, stating two values should have been the same. 487 | # 488 | # Args: 489 | # message: string: failure message [optional] 490 | # expected: string: expected value 491 | # actual: string: actual value 492 | # Returns: 493 | # integer: success (TRUE/FALSE/ERROR constant) 494 | failSame() 495 | { 496 | ${_SHUNIT_LINENO_} 497 | if [ $# -lt 2 -o $# -gt 3 ]; then 498 | _shunit_error "failSame() requires two or three arguments; $# given" 499 | return ${SHUNIT_ERROR} 500 | fi 501 | _shunit_shouldSkip && return ${SHUNIT_TRUE} 502 | 503 | shunit_message_=${__shunit_lineno} 504 | if [ $# -eq 3 ]; then 505 | shunit_message_="${shunit_message_}$1" 506 | shift 507 | fi 508 | 509 | _shunit_assertFail "${shunit_message_:+${shunit_message_} }expected not same" 510 | 511 | unset shunit_message_ 512 | return ${SHUNIT_FALSE} 513 | } 514 | _FAIL_SAME_='eval failSame --lineno "${LINENO:-}"' 515 | 516 | # Records a test failure, stating two values were not equal. 517 | # 518 | # This is functionally equivalent to calling failNotEquals(). 519 | # 520 | # Args: 521 | # message: string: failure message [optional] 522 | # expected: string: expected value 523 | # actual: string: actual value 524 | # Returns: 525 | # integer: success (TRUE/FALSE/ERROR constant) 526 | failNotSame() 527 | { 528 | ${_SHUNIT_LINENO_} 529 | if [ $# -lt 2 -o $# -gt 3 ]; then 530 | _shunit_error "failNotEquals() requires one or two arguments; $# given" 531 | return ${SHUNIT_ERROR} 532 | fi 533 | _shunit_shouldSkip && return ${SHUNIT_TRUE} 534 | 535 | shunit_message_=${__shunit_lineno} 536 | if [ $# -eq 3 ]; then 537 | shunit_message_="${shunit_message_}$1" 538 | shift 539 | fi 540 | failNotEquals "${shunit_message_}" "$1" "$2" 541 | shunit_return=$? 542 | 543 | unset shunit_message_ 544 | return ${shunit_return} 545 | } 546 | _FAIL_NOT_SAME_='eval failNotSame --lineno "${LINENO:-}"' 547 | 548 | #----------------------------------------------------------------------------- 549 | # skipping functions 550 | # 551 | 552 | # Force remaining assert and fail functions to be "skipped". 553 | # 554 | # This function forces the remaining assert and fail functions to be "skipped", 555 | # i.e. they will have no effect. Each function skipped will be recorded so that 556 | # the total of asserts and fails will not be altered. 557 | # 558 | # Args: 559 | # None 560 | startSkipping() 561 | { 562 | __shunit_skip=${SHUNIT_TRUE} 563 | } 564 | 565 | # Resume the normal recording behavior of assert and fail calls. 566 | # 567 | # Args: 568 | # None 569 | endSkipping() 570 | { 571 | __shunit_skip=${SHUNIT_FALSE} 572 | } 573 | 574 | # Returns the state of assert and fail call skipping. 575 | # 576 | # Args: 577 | # None 578 | # Returns: 579 | # boolean: (TRUE/FALSE constant) 580 | isSkipping() 581 | { 582 | return ${__shunit_skip} 583 | } 584 | 585 | #----------------------------------------------------------------------------- 586 | # suite functions 587 | # 588 | 589 | # Stub. This function should contains all unit test calls to be made. 590 | # 591 | # DEPRECATED (as of 2.1.0) 592 | # 593 | # This function can be optionally overridden by the user in their test suite. 594 | # 595 | # If this function exists, it will be called when shunit2 is sourced. If it 596 | # does not exist, shunit2 will search the parent script for all functions 597 | # beginning with the word 'test', and they will be added dynamically to the 598 | # test suite. 599 | # 600 | # This function should be overridden by the user in their unit test suite. 601 | # Note: see _shunit_mktempFunc() for actual implementation 602 | # 603 | # Args: 604 | # None 605 | #suite() { :; } # DO NOT UNCOMMENT THIS FUNCTION 606 | 607 | # Adds a function name to the list of tests schedule for execution. 608 | # 609 | # This function should only be called from within the suite() function. 610 | # 611 | # Args: 612 | # function: string: name of a function to add to current unit test suite 613 | suite_addTest() 614 | { 615 | shunit_func_=${1:-} 616 | 617 | __shunit_suite="${__shunit_suite:+${__shunit_suite} }${shunit_func_}" 618 | __shunit_testsTotal=`expr ${__shunit_testsTotal} + 1` 619 | 620 | unset shunit_func_ 621 | } 622 | 623 | # Stub. This function will be called once before any tests are run. 624 | # 625 | # Common one-time environment preparation tasks shared by all tests can be 626 | # defined here. 627 | # 628 | # This function should be overridden by the user in their unit test suite. 629 | # Note: see _shunit_mktempFunc() for actual implementation 630 | # 631 | # Args: 632 | # None 633 | #oneTimeSetUp() { :; } # DO NOT UNCOMMENT THIS FUNCTION 634 | 635 | # Stub. This function will be called once after all tests are finished. 636 | # 637 | # Common one-time environment cleanup tasks shared by all tests can be defined 638 | # here. 639 | # 640 | # This function should be overridden by the user in their unit test suite. 641 | # Note: see _shunit_mktempFunc() for actual implementation 642 | # 643 | # Args: 644 | # None 645 | #oneTimeTearDown() { :; } # DO NOT UNCOMMENT THIS FUNCTION 646 | 647 | # Stub. This function will be called before each test is run. 648 | # 649 | # Common environment preparation tasks shared by all tests can be defined here. 650 | # 651 | # This function should be overridden by the user in their unit test suite. 652 | # Note: see _shunit_mktempFunc() for actual implementation 653 | # 654 | # Args: 655 | # None 656 | #setUp() { :; } 657 | 658 | # Note: see _shunit_mktempFunc() for actual implementation 659 | # Stub. This function will be called after each test is run. 660 | # 661 | # Common environment cleanup tasks shared by all tests can be defined here. 662 | # 663 | # This function should be overridden by the user in their unit test suite. 664 | # Note: see _shunit_mktempFunc() for actual implementation 665 | # 666 | # Args: 667 | # None 668 | #tearDown() { :; } # DO NOT UNCOMMENT THIS FUNCTION 669 | 670 | #------------------------------------------------------------------------------ 671 | # internal shUnit2 functions 672 | # 673 | 674 | # Create a temporary directory to store various run-time files in. 675 | # 676 | # This function is a cross-platform temporary directory creation tool. Not all 677 | # OSes have the mktemp function, so one is included here. 678 | # 679 | # Args: 680 | # None 681 | # Outputs: 682 | # string: the temporary directory that was created 683 | _shunit_mktempDir() 684 | { 685 | # try the standard mktemp function 686 | ( exec mktemp -dqt shunit.XXXXXX 2>/dev/null ) && return 687 | 688 | # the standard mktemp didn't work. doing our own. 689 | if [ -r '/dev/urandom' -a -x '/usr/bin/od' ]; then 690 | _shunit_random_=`/usr/bin/od -vAn -N4 -tx4 "${_shunit_file_}" 719 | #! /bin/sh 720 | exit ${SHUNIT_TRUE} 721 | EOF 722 | chmod +x "${_shunit_file_}" 723 | done 724 | 725 | unset _shunit_file_ 726 | } 727 | 728 | # Final cleanup function to leave things as we found them. 729 | # 730 | # Besides removing the temporary directory, this function is in charge of the 731 | # final exit code of the unit test. The exit code is based on how the script 732 | # was ended (e.g. normal exit, or via Ctrl-C). 733 | # 734 | # Args: 735 | # name: string: name of the trap called (specified when trap defined) 736 | _shunit_cleanup() 737 | { 738 | _shunit_name_=$1 739 | 740 | case ${_shunit_name_} in 741 | EXIT) _shunit_signal_=0 ;; 742 | INT) _shunit_signal_=2 ;; 743 | TERM) _shunit_signal_=15 ;; 744 | *) 745 | _shunit_warn "unrecognized trap value (${_shunit_name_})" 746 | _shunit_signal_=0 747 | ;; 748 | esac 749 | 750 | # do our work 751 | rm -fr "${__shunit_tmpDir}" 752 | 753 | # exit for all non-EXIT signals 754 | if [ ${_shunit_name_} != 'EXIT' ]; then 755 | _shunit_warn "trapped and now handling the (${_shunit_name_}) signal" 756 | # disable EXIT trap 757 | trap 0 758 | # add 128 to signal and exit 759 | exit `expr ${_shunit_signal_} + 128` 760 | elif [ ${__shunit_reportGenerated} -eq ${SHUNIT_FALSE} ] ; then 761 | _shunit_assertFail 'Unknown failure encountered running a test' 762 | _shunit_generateReport 763 | exit ${SHUNIT_ERROR} 764 | fi 765 | 766 | unset _shunit_name_ _shunit_signal_ 767 | } 768 | 769 | # The actual running of the tests happens here. 770 | # 771 | # Args: 772 | # None 773 | _shunit_execSuite() 774 | { 775 | for _shunit_test_ in ${__shunit_suite}; do 776 | __shunit_testSuccess=${SHUNIT_TRUE} 777 | 778 | # disable skipping 779 | endSkipping 780 | 781 | # execute the per-test setup function 782 | setUp 783 | 784 | # execute the test 785 | echo "${_shunit_test_}" 786 | eval ${_shunit_test_} 787 | 788 | # execute the per-test tear-down function 789 | tearDown 790 | 791 | # update stats 792 | if [ ${__shunit_testSuccess} -eq ${SHUNIT_TRUE} ]; then 793 | __shunit_testsPassed=`expr ${__shunit_testsPassed} + 1` 794 | else 795 | __shunit_testsFailed=`expr ${__shunit_testsFailed} + 1` 796 | fi 797 | done 798 | 799 | unset _shunit_test_ 800 | } 801 | 802 | # Generates the user friendly report with appropriate OK/FAILED message. 803 | # 804 | # Args: 805 | # None 806 | # Output: 807 | # string: the report of successful and failed tests, as well as totals. 808 | _shunit_generateReport() 809 | { 810 | _shunit_ok_=${SHUNIT_TRUE} 811 | 812 | # if no exit code was provided one, determine an appropriate one 813 | [ ${__shunit_testsFailed} -gt 0 \ 814 | -o ${__shunit_testSuccess} -eq ${SHUNIT_FALSE} ] \ 815 | && _shunit_ok_=${SHUNIT_FALSE} 816 | 817 | echo 818 | if [ ${__shunit_testsTotal} -eq 1 ]; then 819 | echo "Ran ${__shunit_testsTotal} test." 820 | else 821 | echo "Ran ${__shunit_testsTotal} tests." 822 | fi 823 | 824 | _shunit_failures_='' 825 | _shunit_skipped_='' 826 | [ ${__shunit_assertsFailed} -gt 0 ] \ 827 | && _shunit_failures_="failures=${__shunit_assertsFailed}" 828 | [ ${__shunit_assertsSkipped} -gt 0 ] \ 829 | && _shunit_skipped_="skipped=${__shunit_assertsSkipped}" 830 | 831 | if [ ${_shunit_ok_} -eq ${SHUNIT_TRUE} ]; then 832 | _shunit_msg_='OK' 833 | [ -n "${_shunit_skipped_}" ] \ 834 | && _shunit_msg_="${_shunit_msg_} (${_shunit_skipped_})" 835 | else 836 | _shunit_msg_="FAILED (${_shunit_failures_}" 837 | [ -n "${_shunit_skipped_}" ] \ 838 | && _shunit_msg_="${_shunit_msg_},${_shunit_skipped_}" 839 | _shunit_msg_="${_shunit_msg_})" 840 | fi 841 | 842 | echo 843 | echo ${_shunit_msg_} 844 | __shunit_reportGenerated=${SHUNIT_TRUE} 845 | 846 | unset _shunit_failures_ _shunit_msg_ _shunit_ok_ _shunit_skipped_ 847 | } 848 | 849 | # Test for whether a function should be skipped. 850 | # 851 | # Args: 852 | # None 853 | # Returns: 854 | # boolean: whether the test should be skipped (TRUE/FALSE constant) 855 | _shunit_shouldSkip() 856 | { 857 | [ ${__shunit_skip} -eq ${SHUNIT_FALSE} ] && return ${SHUNIT_FALSE} 858 | _shunit_assertSkip 859 | } 860 | 861 | # Records a successful test. 862 | # 863 | # Args: 864 | # None 865 | _shunit_assertPass() 866 | { 867 | __shunit_assertsPassed=`expr ${__shunit_assertsPassed} + 1` 868 | __shunit_assertsTotal=`expr ${__shunit_assertsTotal} + 1` 869 | } 870 | 871 | # Records a test failure. 872 | # 873 | # Args: 874 | # message: string: failure message to provide user 875 | _shunit_assertFail() 876 | { 877 | _shunit_msg_=$1 878 | 879 | __shunit_testSuccess=${SHUNIT_FALSE} 880 | __shunit_assertsFailed=`expr ${__shunit_assertsFailed} + 1` 881 | __shunit_assertsTotal=`expr ${__shunit_assertsTotal} + 1` 882 | echo "${__SHUNIT_ASSERT_MSG_PREFIX}${_shunit_msg_}" 883 | 884 | unset _shunit_msg_ 885 | } 886 | 887 | # Records a skipped test. 888 | # 889 | # Args: 890 | # None 891 | _shunit_assertSkip() 892 | { 893 | __shunit_assertsSkipped=`expr ${__shunit_assertsSkipped} + 1` 894 | __shunit_assertsTotal=`expr ${__shunit_assertsTotal} + 1` 895 | } 896 | 897 | # Prepare a script filename for sourcing. 898 | # 899 | # Args: 900 | # script: string: path to a script to source 901 | # Returns: 902 | # string: filename prefixed with ./ (if necessary) 903 | _shunit_prepForSourcing() 904 | { 905 | _shunit_script_=$1 906 | case "${_shunit_script_}" in 907 | /*|./*) echo "${_shunit_script_}" ;; 908 | *) echo "./${_shunit_script_}" ;; 909 | esac 910 | unset _shunit_script_ 911 | } 912 | 913 | # Escape a character in a string. 914 | # 915 | # Args: 916 | # c: string: unescaped character 917 | # s: string: to escape character in 918 | # Returns: 919 | # string: with escaped character(s) 920 | _shunit_escapeCharInStr() 921 | { 922 | [ -n "$2" ] || return # no point in doing work on an empty string 923 | 924 | # Note: using shorter variable names to prevent conflicts with 925 | # _shunit_escapeCharactersInString(). 926 | _shunit_c_=$1 927 | _shunit_s_=$2 928 | 929 | 930 | # escape the character 931 | echo ''${_shunit_s_}'' |sed 's/\'${_shunit_c_}'/\\\'${_shunit_c_}'/g' 932 | 933 | unset _shunit_c_ _shunit_s_ 934 | } 935 | 936 | # Escape a character in a string. 937 | # 938 | # Args: 939 | # str: string: to escape characters in 940 | # Returns: 941 | # string: with escaped character(s) 942 | _shunit_escapeCharactersInString() 943 | { 944 | [ -n "$1" ] || return # no point in doing work on an empty string 945 | 946 | _shunit_str_=$1 947 | 948 | # Note: using longer variable names to prevent conflicts with 949 | # _shunit_escapeCharInStr(). 950 | for _shunit_char_ in '"' '$' "'" '`'; do 951 | _shunit_str_=`_shunit_escapeCharInStr "${_shunit_char_}" "${_shunit_str_}"` 952 | done 953 | 954 | echo "${_shunit_str_}" 955 | unset _shunit_char_ _shunit_str_ 956 | } 957 | 958 | # Extract list of functions to run tests against. 959 | # 960 | # Args: 961 | # script: string: name of script to extract functions from 962 | # Returns: 963 | # string: of function names 964 | _shunit_extractTestFunctions() 965 | { 966 | _shunit_script_=$1 967 | 968 | # extract the lines with test function names, strip of anything besides the 969 | # function name, and output everything on a single line. 970 | _shunit_regex_='^[ ]*(function )*test[A-Za-z0-9_]* *\(\)' 971 | egrep "${_shunit_regex_}" "${_shunit_script_}" \ 972 | |sed 's/^[^A-Za-z0-9_]*//;s/^function //;s/\([A-Za-z0-9_]*\).*/\1/g' \ 973 | |xargs 974 | 975 | unset _shunit_regex_ _shunit_script_ 976 | } 977 | 978 | #------------------------------------------------------------------------------ 979 | # main 980 | # 981 | 982 | # determine the operating mode 983 | if [ $# -eq 0 ]; then 984 | __shunit_script=${__SHUNIT_PARENT} 985 | __shunit_mode=${__SHUNIT_MODE_SOURCED} 986 | else 987 | __shunit_script=$1 988 | [ -r "${__shunit_script}" ] || \ 989 | _shunit_fatal "unable to read from ${__shunit_script}" 990 | __shunit_mode=${__SHUNIT_MODE_STANDALONE} 991 | fi 992 | 993 | # create a temporary storage location 994 | __shunit_tmpDir=`_shunit_mktempDir` 995 | 996 | # provide a public temporary directory for unit test scripts 997 | # TODO(kward): document this 998 | SHUNIT_TMPDIR="${__shunit_tmpDir}/tmp" 999 | mkdir "${SHUNIT_TMPDIR}" 1000 | 1001 | # setup traps to clean up after ourselves 1002 | trap '_shunit_cleanup EXIT' 0 1003 | trap '_shunit_cleanup INT' 2 1004 | trap '_shunit_cleanup TERM' 15 1005 | 1006 | # create phantom functions to work around issues with Cygwin 1007 | _shunit_mktempFunc 1008 | PATH="${__shunit_tmpDir}:${PATH}" 1009 | 1010 | # make sure phantom functions are executable. this will bite if /tmp (or the 1011 | # current $TMPDIR) points to a path on a partition that was mounted with the 1012 | # 'noexec' option. the noexec command was created with _shunit_mktempFunc(). 1013 | noexec 2>/dev/null || _shunit_fatal \ 1014 | 'please declare TMPDIR with path on partition with exec permission' 1015 | 1016 | # we must manually source the tests in standalone mode 1017 | if [ "${__shunit_mode}" = "${__SHUNIT_MODE_STANDALONE}" ]; then 1018 | . "`_shunit_prepForSourcing \"${__shunit_script}\"`" 1019 | fi 1020 | 1021 | # execute the oneTimeSetUp function (if it exists) 1022 | oneTimeSetUp 1023 | 1024 | # execute the suite function defined in the parent test script 1025 | # deprecated as of 2.1.0 1026 | suite 1027 | 1028 | # if no suite function was defined, dynamically build a list of functions 1029 | if [ -z "${__shunit_suite}" ]; then 1030 | shunit_funcs_=`_shunit_extractTestFunctions "${__shunit_script}"` 1031 | for shunit_func_ in ${shunit_funcs_}; do 1032 | suite_addTest ${shunit_func_} 1033 | done 1034 | fi 1035 | unset shunit_func_ shunit_funcs_ 1036 | 1037 | # execute the tests 1038 | _shunit_execSuite 1039 | 1040 | # execute the oneTimeTearDown function (if it exists) 1041 | oneTimeTearDown 1042 | 1043 | # generate the report 1044 | _shunit_generateReport 1045 | 1046 | # that's it folks 1047 | [ ${__shunit_testsFailed} -eq 0 ] 1048 | exit $? 1049 | -------------------------------------------------------------------------------- /shunit/shunit2_test.sh: -------------------------------------------------------------------------------- 1 | #! /bin/sh 2 | # $Id: shunit2_test.sh 322 2011-04-24 00:09:45Z kate.ward@forestent.com $ 3 | # vim:et:ft=sh:sts=2:sw=2 4 | # 5 | # Copyright 2008 Kate Ward. All Rights Reserved. 6 | # Released under the LGPL (GNU Lesser General Public License) 7 | # Author: kate.ward@forestent.com (Kate Ward) 8 | # 9 | # shUnit2 unit test suite runner. 10 | # 11 | # This script runs all the unit tests that can be found, and generates a nice 12 | # report of the tests. 13 | 14 | MY_NAME=`basename $0` 15 | MY_PATH=`dirname $0` 16 | 17 | PREFIX='shunit2_test_' 18 | SHELLS='/bin/sh /bin/bash /bin/dash /bin/ksh /bin/pdksh /bin/zsh' 19 | TESTS='' 20 | for test in ${PREFIX}[a-z]*.sh; do 21 | TESTS="${TESTS} ${test}" 22 | done 23 | 24 | # load common unit test functions 25 | . ../lib/versions 26 | . ./shunit2_test_helpers 27 | 28 | usage() 29 | { 30 | echo "usage: ${MY_NAME} [-e key=val ...] [-s shell(s)] [-t test(s)]" 31 | } 32 | 33 | env='' 34 | 35 | # process command line flags 36 | while getopts 'e:hs:t:' opt; do 37 | case ${opt} in 38 | e) # set an environment variable 39 | key=`expr "${OPTARG}" : '\([^=]*\)='` 40 | val=`expr "${OPTARG}" : '[^=]*=\(.*\)'` 41 | if [ -z "${key}" -o -z "${val}" ]; then 42 | usage 43 | exit 1 44 | fi 45 | eval "${key}='${val}'" 46 | export ${key} 47 | env="${env:+${env} }${key}" 48 | ;; 49 | h) usage; exit 0 ;; # output help 50 | s) shells=${OPTARG} ;; # list of shells to run 51 | t) tests=${OPTARG} ;; # list of tests to run 52 | *) usage; exit 1 ;; 53 | esac 54 | done 55 | shift `expr ${OPTIND} - 1` 56 | 57 | # fill shells and/or tests 58 | shells=${shells:-${SHELLS}} 59 | tests=${tests:-${TESTS}} 60 | 61 | # error checking 62 | if [ -z "${tests}" ]; then 63 | th_error 'no tests found to run; exiting' 64 | exit 1 65 | fi 66 | 67 | cat <&1; ) 123 | done 124 | done 125 | -------------------------------------------------------------------------------- /shunit/shunit2_test_asserts.sh: -------------------------------------------------------------------------------- 1 | #! /bin/sh 2 | # $Id: shunit2_test_asserts.sh 312 2011-03-14 22:41:29Z kate.ward@forestent.com $ 3 | # vim:et:ft=sh:sts=2:sw=2 4 | # 5 | # Copyright 2008 Kate Ward. All Rights Reserved. 6 | # Released under the LGPL (GNU Lesser General Public License) 7 | # 8 | # Author: kate.ward@forestent.com (Kate Ward) 9 | # 10 | # shUnit2 unit test for assert functions 11 | 12 | # load test helpers 13 | . ./shunit2_test_helpers 14 | 15 | #------------------------------------------------------------------------------ 16 | # suite tests 17 | # 18 | 19 | commonEqualsSame() 20 | { 21 | fn=$1 22 | 23 | ( ${fn} 'x' 'x' >"${stdoutF}" 2>"${stderrF}" ) 24 | th_assertTrueWithNoOutput 'equal' $? "${stdoutF}" "${stderrF}" 25 | 26 | ( ${fn} "${MSG}" 'x' 'x' >"${stdoutF}" 2>"${stderrF}" ) 27 | th_assertTrueWithNoOutput 'equal; with msg' $? "${stdoutF}" "${stderrF}" 28 | 29 | ( ${fn} 'abc def' 'abc def' >"${stdoutF}" 2>"${stderrF}" ) 30 | th_assertTrueWithNoOutput 'equal with spaces' $? "${stdoutF}" "${stderrF}" 31 | 32 | ( ${fn} 'x' 'y' >"${stdoutF}" 2>"${stderrF}" ) 33 | th_assertFalseWithOutput 'not equal' $? "${stdoutF}" "${stderrF}" 34 | 35 | ( ${fn} '' '' >"${stdoutF}" 2>"${stderrF}" ) 36 | th_assertTrueWithNoOutput 'null values' $? "${stdoutF}" "${stderrF}" 37 | 38 | ( ${fn} arg1 >"${stdoutF}" 2>"${stderrF}" ) 39 | th_assertFalseWithError 'too few arguments' $? "${stdoutF}" "${stderrF}" 40 | 41 | ( ${fn} arg1 arg2 arg3 arg4 >"${stdoutF}" 2>"${stderrF}" ) 42 | th_assertFalseWithError 'too many arguments' $? "${stdoutF}" "${stderrF}" 43 | } 44 | 45 | commonNotEqualsSame() 46 | { 47 | fn=$1 48 | 49 | ( ${fn} 'x' 'y' >"${stdoutF}" 2>"${stderrF}" ) 50 | th_assertTrueWithNoOutput 'not same' $? "${stdoutF}" "${stderrF}" 51 | 52 | ( ${fn} "${MSG}" 'x' 'y' >"${stdoutF}" 2>"${stderrF}" ) 53 | th_assertTrueWithNoOutput 'not same, with msg' $? "${stdoutF}" "${stderrF}" 54 | 55 | ( ${fn} 'x' 'x' >"${stdoutF}" 2>"${stderrF}" ) 56 | th_assertFalseWithOutput 'same' $? "${stdoutF}" "${stderrF}" 57 | 58 | ( ${fn} '' '' >"${stdoutF}" 2>"${stderrF}" ) 59 | th_assertFalseWithOutput 'null values' $? "${stdoutF}" "${stderrF}" 60 | 61 | ( ${fn} arg1 >"${stdoutF}" 2>"${stderrF}" ) 62 | th_assertFalseWithError 'too few arguments' $? "${stdoutF}" "${stderrF}" 63 | 64 | ( ${fn} arg1 arg2 arg3 arg4 >"${stdoutF}" 2>"${stderrF}" ) 65 | th_assertFalseWithError 'too many arguments' $? "${stdoutF}" "${stderrF}" 66 | } 67 | 68 | testAssertEquals() 69 | { 70 | commonEqualsSame 'assertEquals' 71 | } 72 | 73 | testAssertNotEquals() 74 | { 75 | commonNotEqualsSame 'assertNotEquals' 76 | } 77 | 78 | testAssertSame() 79 | { 80 | commonEqualsSame 'assertSame' 81 | } 82 | 83 | testAssertNotSame() 84 | { 85 | commonNotEqualsSame 'assertNotSame' 86 | } 87 | 88 | testAssertNull() 89 | { 90 | ( assertNull '' >"${stdoutF}" 2>"${stderrF}" ) 91 | th_assertTrueWithNoOutput 'null' $? "${stdoutF}" "${stderrF}" 92 | 93 | ( assertNull "${MSG}" '' >"${stdoutF}" 2>"${stderrF}" ) 94 | th_assertTrueWithNoOutput 'null, with msg' $? "${stdoutF}" "${stderrF}" 95 | 96 | ( assertNull 'x' >"${stdoutF}" 2>"${stderrF}" ) 97 | th_assertFalseWithOutput 'not null' $? "${stdoutF}" "${stderrF}" 98 | 99 | ( assertNull >"${stdoutF}" 2>"${stderrF}" ) 100 | th_assertFalseWithError 'too few arguments' $? "${stdoutF}" "${stderrF}" 101 | 102 | ( assertNull arg1 arg2 arg3 >"${stdoutF}" 2>"${stderrF}" ) 103 | th_assertFalseWithError 'too many arguments' $? "${stdoutF}" "${stderrF}" 104 | } 105 | 106 | testAssertNotNull() 107 | { 108 | ( assertNotNull 'x' >"${stdoutF}" 2>"${stderrF}" ) 109 | th_assertTrueWithNoOutput 'not null' $? "${stdoutF}" "${stderrF}" 110 | 111 | ( assertNotNull "${MSG}" 'x' >"${stdoutF}" 2>"${stderrF}" ) 112 | th_assertTrueWithNoOutput 'not null, with msg' $? "${stdoutF}" "${stderrF}" 113 | 114 | ( assertNotNull 'x"b' >"${stdoutF}" 2>"${stderrF}" ) 115 | th_assertTrueWithNoOutput 'not null, with double-quote' $? \ 116 | "${stdoutF}" "${stderrF}" 117 | 118 | ( assertNotNull "x'b" >"${stdoutF}" 2>"${stderrF}" ) 119 | th_assertTrueWithNoOutput 'not null, with single-quote' $? \ 120 | "${stdoutF}" "${stderrF}" 121 | 122 | ( assertNotNull 'x$b' >"${stdoutF}" 2>"${stderrF}" ) 123 | th_assertTrueWithNoOutput 'not null, with dollar' $? \ 124 | "${stdoutF}" "${stderrF}" 125 | 126 | ( assertNotNull 'x`b' >"${stdoutF}" 2>"${stderrF}" ) 127 | th_assertTrueWithNoOutput 'not null, with backtick' $? \ 128 | "${stdoutF}" "${stderrF}" 129 | 130 | ( assertNotNull '' >"${stdoutF}" 2>"${stderrF}" ) 131 | th_assertFalseWithOutput 'null' $? "${stdoutF}" "${stderrF}" 132 | 133 | # there is no test for too few arguments as $1 might actually be null 134 | 135 | ( assertNotNull arg1 arg2 arg3 >"${stdoutF}" 2>"${stderrF}" ) 136 | th_assertFalseWithError 'too many arguments' $? "${stdoutF}" "${stderrF}" 137 | } 138 | 139 | testAssertTrue() 140 | { 141 | ( assertTrue 0 >"${stdoutF}" 2>"${stderrF}" ) 142 | th_assertTrueWithNoOutput 'true' $? "${stdoutF}" "${stderrF}" 143 | 144 | ( assertTrue "${MSG}" 0 >"${stdoutF}" 2>"${stderrF}" ) 145 | th_assertTrueWithNoOutput 'true, with msg' $? "${stdoutF}" "${stderrF}" 146 | 147 | ( assertTrue '[ 0 -eq 0 ]' >"${stdoutF}" 2>"${stderrF}" ) 148 | th_assertTrueWithNoOutput 'true condition' $? "${stdoutF}" "${stderrF}" 149 | 150 | ( assertTrue 1 >"${stdoutF}" 2>"${stderrF}" ) 151 | th_assertFalseWithOutput 'false' $? "${stdoutF}" "${stderrF}" 152 | 153 | ( assertTrue '[ 0 -eq 1 ]' >"${stdoutF}" 2>"${stderrF}" ) 154 | th_assertFalseWithOutput 'false condition' $? "${stdoutF}" "${stderrF}" 155 | 156 | ( assertTrue '' >"${stdoutF}" 2>"${stderrF}" ) 157 | th_assertFalseWithOutput 'null' $? "${stdoutF}" "${stderrF}" 158 | 159 | ( assertTrue >"${stdoutF}" 2>"${stderrF}" ) 160 | th_assertFalseWithError 'too few arguments' $? "${stdoutF}" "${stderrF}" 161 | 162 | ( assertTrue arg1 arg2 arg3 >"${stdoutF}" 2>"${stderrF}" ) 163 | th_assertFalseWithError 'too many arguments' $? "${stdoutF}" "${stderrF}" 164 | } 165 | 166 | testAssertFalse() 167 | { 168 | ( assertFalse 1 >"${stdoutF}" 2>"${stderrF}" ) 169 | th_assertTrueWithNoOutput 'false' $? "${stdoutF}" "${stderrF}" 170 | 171 | ( assertFalse "${MSG}" 1 >"${stdoutF}" 2>"${stderrF}" ) 172 | th_assertTrueWithNoOutput 'false, with msg' $? "${stdoutF}" "${stderrF}" 173 | 174 | ( assertFalse '[ 0 -eq 1 ]' >"${stdoutF}" 2>"${stderrF}" ) 175 | th_assertTrueWithNoOutput 'false condition' $? "${stdoutF}" "${stderrF}" 176 | 177 | ( assertFalse 0 >"${stdoutF}" 2>"${stderrF}" ) 178 | th_assertFalseWithOutput 'true' $? "${stdoutF}" "${stderrF}" 179 | 180 | ( assertFalse '[ 0 -eq 0 ]' >"${stdoutF}" 2>"${stderrF}" ) 181 | th_assertFalseWithOutput 'true condition' $? "${stdoutF}" "${stderrF}" 182 | 183 | ( assertFalse '' >"${stdoutF}" 2>"${stderrF}" ) 184 | th_assertFalseWithOutput 'true condition' $? "${stdoutF}" "${stderrF}" 185 | 186 | ( assertFalse >"${stdoutF}" 2>"${stderrF}" ) 187 | th_assertFalseWithError 'too few arguments' $? "${stdoutF}" "${stderrF}" 188 | 189 | ( assertFalse arg1 arg2 arg3 >"${stdoutF}" 2>"${stderrF}" ) 190 | th_assertFalseWithError 'too many arguments' $? "${stdoutF}" "${stderrF}" 191 | } 192 | 193 | #------------------------------------------------------------------------------ 194 | # suite functions 195 | # 196 | 197 | oneTimeSetUp() 198 | { 199 | tmpDir="${__shunit_tmpDir}/output" 200 | mkdir "${tmpDir}" 201 | stdoutF="${tmpDir}/stdout" 202 | stderrF="${tmpDir}/stderr" 203 | 204 | MSG='This is a test message' 205 | } 206 | 207 | # load and run shUnit2 208 | [ -n "${ZSH_VERSION:-}" ] && SHUNIT_PARENT=$0 209 | . ${TH_SHUNIT} 210 | -------------------------------------------------------------------------------- /shunit/shunit2_test_failures.sh: -------------------------------------------------------------------------------- 1 | #! /bin/sh 2 | # $Id: shunit2_test_failures.sh 286 2008-11-24 21:42:34Z kate.ward@forestent.com $ 3 | # vim:et:ft=sh:sts=2:sw=2 4 | # 5 | # Copyright 2008 Kate Ward. All Rights Reserved. 6 | # Released under the LGPL (GNU Lesser General Public License) 7 | # 8 | # Author: kate.ward@forestent.com (Kate Ward) 9 | # 10 | # shUnit2 unit test for failure functions 11 | 12 | # load common unit-test functions 13 | . ./shunit2_test_helpers 14 | 15 | #----------------------------------------------------------------------------- 16 | # suite tests 17 | # 18 | 19 | testFail() 20 | { 21 | ( fail >"${stdoutF}" 2>"${stderrF}" ) 22 | th_assertFalseWithOutput 'fail' $? "${stdoutF}" "${stderrF}" 23 | 24 | ( fail "${MSG}" >"${stdoutF}" 2>"${stderrF}" ) 25 | th_assertFalseWithOutput 'fail with msg' $? "${stdoutF}" "${stderrF}" 26 | 27 | ( fail arg1 >"${stdoutF}" 2>"${stderrF}" ) 28 | th_assertFalseWithOutput 'too many arguments' $? "${stdoutF}" "${stderrF}" 29 | } 30 | 31 | testFailNotEquals() 32 | { 33 | ( failNotEquals 'x' 'x' >"${stdoutF}" 2>"${stderrF}" ) 34 | th_assertFalseWithOutput 'same' $? "${stdoutF}" "${stderrF}" 35 | 36 | ( failNotEquals "${MSG}" 'x' 'x' >"${stdoutF}" 2>"${stderrF}" ) 37 | th_assertFalseWithOutput 'same with msg' $? "${stdoutF}" "${stderrF}" 38 | 39 | ( failNotEquals 'x' 'y' >"${stdoutF}" 2>"${stderrF}" ) 40 | th_assertFalseWithOutput 'not same' $? "${stdoutF}" "${stderrF}" 41 | 42 | ( failNotEquals '' '' >"${stdoutF}" 2>"${stderrF}" ) 43 | th_assertFalseWithOutput 'null values' $? "${stdoutF}" "${stderrF}" 44 | 45 | ( failNotEquals >"${stdoutF}" 2>"${stderrF}" ) 46 | th_assertFalseWithError 'too few arguments' $? "${stdoutF}" "${stderrF}" 47 | 48 | ( failNotEquals arg1 arg2 arg3 arg4 >"${stdoutF}" 2>"${stderrF}" ) 49 | th_assertFalseWithError 'too many arguments' $? "${stdoutF}" "${stderrF}" 50 | } 51 | 52 | testFailSame() 53 | { 54 | ( failSame 'x' 'x' >"${stdoutF}" 2>"${stderrF}" ) 55 | th_assertFalseWithOutput 'same' $? "${stdoutF}" "${stderrF}" 56 | 57 | ( failSame "${MSG}" 'x' 'x' >"${stdoutF}" 2>"${stderrF}" ) 58 | th_assertFalseWithOutput 'same with msg' $? "${stdoutF}" "${stderrF}" 59 | 60 | ( failSame 'x' 'y' >"${stdoutF}" 2>"${stderrF}" ) 61 | th_assertFalseWithOutput 'not same' $? "${stdoutF}" "${stderrF}" 62 | 63 | ( failSame '' '' >"${stdoutF}" 2>"${stderrF}" ) 64 | th_assertFalseWithOutput 'null values' $? "${stdoutF}" "${stderrF}" 65 | 66 | ( failSame >"${stdoutF}" 2>"${stderrF}" ) 67 | th_assertFalseWithError 'too few arguments' $? "${stdoutF}" "${stderrF}" 68 | 69 | ( failSame arg1 arg2 arg3 arg4 >"${stdoutF}" 2>"${stderrF}" ) 70 | th_assertFalseWithError 'too many arguments' $? "${stdoutF}" "${stderrF}" 71 | } 72 | 73 | #----------------------------------------------------------------------------- 74 | # suite functions 75 | # 76 | 77 | oneTimeSetUp() 78 | { 79 | tmpDir="${__shunit_tmpDir}/output" 80 | mkdir "${tmpDir}" 81 | stdoutF="${tmpDir}/stdout" 82 | stderrF="${tmpDir}/stderr" 83 | 84 | MSG='This is a test message' 85 | } 86 | 87 | # load and run shUnit2 88 | [ -n "${ZSH_VERSION:-}" ] && SHUNIT_PARENT=$0 89 | . ${TH_SHUNIT} 90 | -------------------------------------------------------------------------------- /shunit/shunit2_test_helpers: -------------------------------------------------------------------------------- 1 | # $Id: shunit2_test_helpers 286 2008-11-24 21:42:34Z kate.ward@forestent.com $ 2 | # vim:et:ft=sh:sts=2:sw=2 3 | # 4 | # Copyright 2008 Kate Ward. All Rights Reserved. 5 | # Released under the LGPL (GNU Lesser General Public License) 6 | # 7 | # Author: kate.ward@forestent.com (Kate Ward) 8 | # 9 | # shUnit2 unit test common functions 10 | 11 | # treat unset variables as an error when performing parameter expansion 12 | set -u 13 | 14 | # set shwordsplit for zsh 15 | [ -n "${ZSH_VERSION:-}" ] && setopt shwordsplit 16 | 17 | # 18 | # constants 19 | # 20 | 21 | # path to shUnit2 library. can be overridden by setting SHUNIT_INC 22 | TH_SHUNIT=${SHUNIT_INC:-./shunit2} 23 | 24 | # configure debugging. set the DEBUG environment variable to any 25 | # non-empty value to enable debug output, or TRACE to enable trace 26 | # output. 27 | TRACE=${TRACE:+'th_trace '} 28 | [ -n "${TRACE}" ] && DEBUG=1 29 | [ -z "${TRACE}" ] && TRACE=':' 30 | 31 | DEBUG=${DEBUG:+'th_debug '} 32 | [ -z "${DEBUG}" ] && DEBUG=':' 33 | 34 | # 35 | # variables 36 | # 37 | 38 | th_RANDOM=0 39 | 40 | # 41 | # functions 42 | # 43 | 44 | # message functions 45 | th_trace() { echo "${MY_NAME}:TRACE $@" >&2; } 46 | th_debug() { echo "${MY_NAME}:DEBUG $@" >&2; } 47 | th_info() { echo "${MY_NAME}:INFO $@" >&2; } 48 | th_warn() { echo "${MY_NAME}:WARN $@" >&2; } 49 | th_error() { echo "${MY_NAME}:ERROR $@" >&2; } 50 | th_fatal() { echo "${MY_NAME}:FATAL $@" >&2; } 51 | 52 | # output subtest name 53 | th_subtest() { echo " $@" >&2; } 54 | 55 | # generate a random number 56 | th_generateRandom() 57 | { 58 | tfgr_random=${th_RANDOM} 59 | 60 | while [ "${tfgr_random}" = "${th_RANDOM}" ]; do 61 | if [ -n "${RANDOM:-}" ]; then 62 | # $RANDOM works 63 | tfgr_random=${RANDOM}${RANDOM}${RANDOM}$$ 64 | elif [ -r '/dev/urandom' ]; then 65 | tfgr_random=`od -vAn -N4 -tu4 "${stdoutF}" 2>"${stderrF}" ) 24 | grep '^ASSERT:\[[0-9]*\] *' "${stdoutF}" >/dev/null 25 | rtrn=$? 26 | assertTrue '_ASSERT_EQUALS_ failure' ${rtrn} 27 | [ ${rtrn} -ne ${SHUNIT_TRUE} ] && cat "${stderrF}" >&2 28 | 29 | ( ${_ASSERT_EQUALS_} '"some msg"' 'x' 'y' >"${stdoutF}" 2>"${stderrF}" ) 30 | grep '^ASSERT:\[[0-9]*\] *' "${stdoutF}" >/dev/null 31 | rtrn=$? 32 | assertTrue '_ASSERT_EQUALS_ w/ msg failure' ${rtrn} 33 | [ ${rtrn} -ne ${SHUNIT_TRUE} ] && cat "${stderrF}" >&2 34 | } 35 | 36 | testAssertNotEquals() 37 | { 38 | # start skipping if LINENO not available 39 | [ -z "${LINENO:-}" ] && startSkipping 40 | 41 | ( ${_ASSERT_NOT_EQUALS_} 'x' 'x' >"${stdoutF}" 2>"${stderrF}" ) 42 | grep '^ASSERT:\[[0-9]*\] *' "${stdoutF}" >/dev/null 43 | rtrn=$? 44 | assertTrue '_ASSERT_NOT_EQUALS_ failure' ${rtrn} 45 | [ ${rtrn} -ne ${SHUNIT_TRUE} ] && cat "${stderrF}" >&2 46 | 47 | ( ${_ASSERT_NOT_EQUALS_} '"some msg"' 'x' 'x' >"${stdoutF}" 2>"${stderrF}" ) 48 | grep '^ASSERT:\[[0-9]*\] *' "${stdoutF}" >/dev/null 49 | rtrn=$? 50 | assertTrue '_ASSERT_NOT_EQUALS_ w/ msg failure' ${rtrn} 51 | [ ${rtrn} -ne ${SHUNIT_TRUE} ] && cat "${stderrF}" >&2 52 | } 53 | 54 | testSame() 55 | { 56 | # start skipping if LINENO not available 57 | [ -z "${LINENO:-}" ] && startSkipping 58 | 59 | ( ${_ASSERT_SAME_} 'x' 'y' >"${stdoutF}" 2>"${stderrF}" ) 60 | grep '^ASSERT:\[[0-9]*\] *' "${stdoutF}" >/dev/null 61 | rtrn=$? 62 | assertTrue '_ASSERT_SAME_ failure' ${rtrn} 63 | [ ${rtrn} -ne ${SHUNIT_TRUE} ] && cat "${stderrF}" >&2 64 | 65 | ( ${_ASSERT_SAME_} '"some msg"' 'x' 'y' >"${stdoutF}" 2>"${stderrF}" ) 66 | grep '^ASSERT:\[[0-9]*\] *' "${stdoutF}" >/dev/null 67 | rtrn=$? 68 | assertTrue '_ASSERT_SAME_ w/ msg failure' ${rtrn} 69 | [ ${rtrn} -ne ${SHUNIT_TRUE} ] && cat "${stderrF}" >&2 70 | } 71 | 72 | testNotSame() 73 | { 74 | # start skipping if LINENO not available 75 | [ -z "${LINENO:-}" ] && startSkipping 76 | 77 | ( ${_ASSERT_NOT_SAME_} 'x' 'x' >"${stdoutF}" 2>"${stderrF}" ) 78 | grep '^ASSERT:\[[0-9]*\] *' "${stdoutF}" >/dev/null 79 | rtrn=$? 80 | assertTrue '_ASSERT_NOT_SAME_ failure' ${rtrn} 81 | [ ${rtrn} -ne ${SHUNIT_TRUE} ] && cat "${stderrF}" >&2 82 | 83 | ( ${_ASSERT_NOT_SAME_} '"some msg"' 'x' 'x' >"${stdoutF}" 2>"${stderrF}" ) 84 | grep '^ASSERT:\[[0-9]*\] *' "${stdoutF}" >/dev/null 85 | rtrn=$? 86 | assertTrue '_ASSERT_NOT_SAME_ w/ msg failure' ${rtrn} 87 | [ ${rtrn} -ne ${SHUNIT_TRUE} ] && cat "${stderrF}" >&2 88 | } 89 | 90 | testNull() 91 | { 92 | # start skipping if LINENO not available 93 | [ -z "${LINENO:-}" ] && startSkipping 94 | 95 | ( ${_ASSERT_NULL_} 'x' >"${stdoutF}" 2>"${stderrF}" ) 96 | grep '^ASSERT:\[[0-9]*\] *' "${stdoutF}" >/dev/null 97 | rtrn=$? 98 | assertTrue '_ASSERT_NULL_ failure' ${rtrn} 99 | [ ${rtrn} -ne ${SHUNIT_TRUE} ] && cat "${stderrF}" >&2 100 | 101 | ( ${_ASSERT_NULL_} '"some msg"' 'x' >"${stdoutF}" 2>"${stderrF}" ) 102 | grep '^ASSERT:\[[0-9]*\] *' "${stdoutF}" >/dev/null 103 | rtrn=$? 104 | assertTrue '_ASSERT_NULL_ w/ msg failure' ${rtrn} 105 | [ ${rtrn} -ne ${SHUNIT_TRUE} ] && cat "${stderrF}" >&2 106 | } 107 | 108 | testNotNull() 109 | { 110 | # start skipping if LINENO not available 111 | [ -z "${LINENO:-}" ] && startSkipping 112 | 113 | ( ${_ASSERT_NOT_NULL_} '' >"${stdoutF}" 2>"${stderrF}" ) 114 | grep '^ASSERT:\[[0-9]*\] *' "${stdoutF}" >/dev/null 115 | rtrn=$? 116 | assertTrue '_ASSERT_NOT_NULL_ failure' ${rtrn} 117 | [ ${rtrn} -ne ${SHUNIT_TRUE} ] && cat "${stderrF}" >&2 118 | 119 | ( ${_ASSERT_NOT_NULL_} '"some msg"' '""' >"${stdoutF}" 2>"${stderrF}" ) 120 | grep '^ASSERT:\[[0-9]*\] *' "${stdoutF}" >/dev/null 121 | rtrn=$? 122 | assertTrue '_ASSERT_NOT_NULL_ w/ msg failure' ${rtrn} 123 | [ ${rtrn} -ne ${SHUNIT_TRUE} ] && cat "${stdoutF}" "${stderrF}" >&2 124 | } 125 | 126 | testAssertTrue() 127 | { 128 | # start skipping if LINENO not available 129 | [ -z "${LINENO:-}" ] && startSkipping 130 | 131 | ( ${_ASSERT_TRUE_} ${SHUNIT_FALSE} >"${stdoutF}" 2>"${stderrF}" ) 132 | grep '^ASSERT:\[[0-9]*\] *' "${stdoutF}" >/dev/null 133 | rtrn=$? 134 | assertTrue '_ASSERT_TRUE_ failure' ${rtrn} 135 | [ ${rtrn} -ne ${SHUNIT_TRUE} ] && cat "${stderrF}" >&2 136 | 137 | 138 | ( ${_ASSERT_TRUE_} '"some msg"' ${SHUNIT_FALSE} >"${stdoutF}" 2>"${stderrF}" ) 139 | grep '^ASSERT:\[[0-9]*\] *' "${stdoutF}" >/dev/null 140 | rtrn=$? 141 | assertTrue '_ASSERT_TRUE_ w/ msg failure' ${rtrn} 142 | [ ${rtrn} -ne ${SHUNIT_TRUE} ] && cat "${stderrF}" >&2 143 | } 144 | 145 | testAssertFalse() 146 | { 147 | # start skipping if LINENO not available 148 | [ -z "${LINENO:-}" ] && startSkipping 149 | 150 | ( ${_ASSERT_FALSE_} ${SHUNIT_TRUE} >"${stdoutF}" 2>"${stderrF}" ) 151 | grep '^ASSERT:\[[0-9]*\] *' "${stdoutF}" >/dev/null 152 | rtrn=$? 153 | assertTrue '_ASSERT_FALSE_ failure' ${rtrn} 154 | [ ${rtrn} -ne ${SHUNIT_TRUE} ] && cat "${stderrF}" >&2 155 | 156 | ( ${_ASSERT_FALSE_} '"some msg"' ${SHUNIT_TRUE} >"${stdoutF}" 2>"${stderrF}" ) 157 | grep '^ASSERT:\[[0-9]*\] *' "${stdoutF}" >/dev/null 158 | rtrn=$? 159 | assertTrue '_ASSERT_FALSE_ w/ msg failure' ${rtrn} 160 | [ ${rtrn} -ne ${SHUNIT_TRUE} ] && cat "${stderrF}" >&2 161 | } 162 | 163 | testFail() 164 | { 165 | # start skipping if LINENO not available 166 | [ -z "${LINENO:-}" ] && startSkipping 167 | 168 | ( ${_FAIL_} >"${stdoutF}" 2>"${stderrF}" ) 169 | grep '^ASSERT:\[[0-9]*\] *' "${stdoutF}" >/dev/null 170 | rtrn=$? 171 | assertTrue '_FAIL_ failure' ${rtrn} 172 | [ ${rtrn} -ne ${SHUNIT_TRUE} ] && cat "${stderrF}" >&2 173 | 174 | ( ${_FAIL_} '"some msg"' >"${stdoutF}" 2>"${stderrF}" ) 175 | grep '^ASSERT:\[[0-9]*\] *' "${stdoutF}" >/dev/null 176 | rtrn=$? 177 | assertTrue '_FAIL_ w/ msg failure' ${rtrn} 178 | [ ${rtrn} -ne ${SHUNIT_TRUE} ] && cat "${stderrF}" >&2 179 | } 180 | 181 | testFailNotEquals() 182 | { 183 | # start skipping if LINENO not available 184 | [ -z "${LINENO:-}" ] && startSkipping 185 | 186 | ( ${_FAIL_NOT_EQUALS_} 'x' 'y' >"${stdoutF}" 2>"${stderrF}" ) 187 | grep '^ASSERT:\[[0-9]*\] *' "${stdoutF}" >/dev/null 188 | rtrn=$? 189 | assertTrue '_FAIL_NOT_EQUALS_ failure' ${rtrn} 190 | [ ${rtrn} -ne ${SHUNIT_TRUE} ] && cat "${stderrF}" >&2 191 | 192 | ( ${_FAIL_NOT_EQUALS_} '"some msg"' 'x' 'y' >"${stdoutF}" 2>"${stderrF}" ) 193 | grep '^ASSERT:\[[0-9]*\] *' "${stdoutF}" >/dev/null 194 | rtrn=$? 195 | assertTrue '_FAIL_NOT_EQUALS_ w/ msg failure' ${rtrn} 196 | [ ${rtrn} -ne ${SHUNIT_TRUE} ] && cat "${stderrF}" >&2 197 | } 198 | 199 | testFailSame() 200 | { 201 | # start skipping if LINENO not available 202 | [ -z "${LINENO:-}" ] && startSkipping 203 | 204 | ( ${_FAIL_SAME_} 'x' 'x' >"${stdoutF}" 2>"${stderrF}" ) 205 | grep '^ASSERT:\[[0-9]*\] *' "${stdoutF}" >/dev/null 206 | rtrn=$? 207 | assertTrue '_FAIL_SAME_ failure' ${rtrn} 208 | [ ${rtrn} -ne ${SHUNIT_TRUE} ] && cat "${stderrF}" >&2 209 | 210 | ( ${_FAIL_SAME_} '"some msg"' 'x' 'x' >"${stdoutF}" 2>"${stderrF}" ) 211 | grep '^ASSERT:\[[0-9]*\] *' "${stdoutF}" >/dev/null 212 | rtrn=$? 213 | assertTrue '_FAIL_SAME_ w/ msg failure' ${rtrn} 214 | [ ${rtrn} -ne ${SHUNIT_TRUE} ] && cat "${stderrF}" >&2 215 | } 216 | 217 | testFailNotSame() 218 | { 219 | # start skipping if LINENO not available 220 | [ -z "${LINENO:-}" ] && startSkipping 221 | 222 | ( ${_FAIL_NOT_SAME_} 'x' 'y' >"${stdoutF}" 2>"${stderrF}" ) 223 | grep '^ASSERT:\[[0-9]*\] *' "${stdoutF}" >/dev/null 224 | rtrn=$? 225 | assertTrue '_FAIL_NOT_SAME_ failure' ${rtrn} 226 | [ ${rtrn} -ne ${SHUNIT_TRUE} ] && cat "${stderrF}" >&2 227 | 228 | ( ${_FAIL_NOT_SAME_} '"some msg"' 'x' 'y' >"${stdoutF}" 2>"${stderrF}" ) 229 | grep '^ASSERT:\[[0-9]*\] *' "${stdoutF}" >/dev/null 230 | rtrn=$? 231 | assertTrue '_FAIL_NOT_SAME_ w/ msg failure' ${rtrn} 232 | [ ${rtrn} -ne ${SHUNIT_TRUE} ] && cat "${stderrF}" >&2 233 | } 234 | 235 | #------------------------------------------------------------------------------ 236 | # suite functions 237 | # 238 | 239 | oneTimeSetUp() 240 | { 241 | tmpDir="${__shunit_tmpDir}/output" 242 | mkdir "${tmpDir}" 243 | stdoutF="${tmpDir}/stdout" 244 | stderrF="${tmpDir}/stderr" 245 | } 246 | 247 | # load and run shUnit2 248 | [ -n "${ZSH_VERSION:-}" ] && SHUNIT_PARENT=$0 249 | . ${TH_SHUNIT} 250 | -------------------------------------------------------------------------------- /shunit/shunit2_test_misc.sh: -------------------------------------------------------------------------------- 1 | #! /bin/sh 2 | # $Id: shunit2_test_misc.sh 322 2011-04-24 00:09:45Z kate.ward@forestent.com $ 3 | # vim:et:ft=sh:sts=2:sw=2 4 | # 5 | # Copyright 2008 Kate Ward. All Rights Reserved. 6 | # Released under the LGPL (GNU Lesser General Public License) 7 | # 8 | # Author: kate.ward@forestent.com (Kate Ward) 9 | # 10 | # shUnit2 unit tests of miscellaneous things 11 | 12 | # load test helpers 13 | . ./shunit2_test_helpers 14 | 15 | #------------------------------------------------------------------------------ 16 | # suite tests 17 | # 18 | 19 | # Note: the test script is prefixed with '#' chars so that shUnit2 does not 20 | # incorrectly interpret the embedded functions as real functions. 21 | testUnboundVariable() 22 | { 23 | sed 's/^#//' >"${unittestF}" <"${stdoutF}" 2>"${stderrF}" ) 37 | assertFalse 'expected a non-zero exit value' $? 38 | grep '^ASSERT:Unknown failure' "${stdoutF}" >/dev/null 39 | assertTrue 'assert message was not generated' $? 40 | grep '^Ran [0-9]* test' "${stdoutF}" >/dev/null 41 | assertTrue 'test count message was not generated' $? 42 | grep '^FAILED' "${stdoutF}" >/dev/null 43 | assertTrue 'failure message was not generated' $? 44 | } 45 | 46 | testIssue7() 47 | { 48 | ( assertEquals 'Some message.' 1 2 >"${stdoutF}" 2>"${stderrF}" ) 49 | diff "${stdoutF}" - >/dev/null < but was:<2> 51 | EOF 52 | rtrn=$? 53 | assertEquals ${SHUNIT_TRUE} ${rtrn} 54 | [ ${rtrn} -ne ${SHUNIT_TRUE} ] && cat "${stderrF}" >&2 55 | } 56 | 57 | testPrepForSourcing() 58 | { 59 | assertEquals '/abc' `_shunit_prepForSourcing '/abc'` 60 | assertEquals './abc' `_shunit_prepForSourcing './abc'` 61 | assertEquals './abc' `_shunit_prepForSourcing 'abc'` 62 | } 63 | 64 | testEscapeCharInStr() 65 | { 66 | actual=`_shunit_escapeCharInStr '\' ''` 67 | assertEquals '' "${actual}" 68 | assertEquals 'abc\\' `_shunit_escapeCharInStr '\' 'abc\'` 69 | assertEquals 'abc\\def' `_shunit_escapeCharInStr '\' 'abc\def'` 70 | assertEquals '\\def' `_shunit_escapeCharInStr '\' '\def'` 71 | 72 | actual=`_shunit_escapeCharInStr '"' ''` 73 | assertEquals '' "${actual}" 74 | assertEquals 'abc\"' `_shunit_escapeCharInStr '"' 'abc"'` 75 | assertEquals 'abc\"def' `_shunit_escapeCharInStr '"' 'abc"def'` 76 | assertEquals '\"def' `_shunit_escapeCharInStr '"' '"def'` 77 | 78 | actual=`_shunit_escapeCharInStr '$' ''` 79 | assertEquals '' "${actual}" 80 | assertEquals 'abc\$' `_shunit_escapeCharInStr '$' 'abc$'` 81 | assertEquals 'abc\$def' `_shunit_escapeCharInStr '$' 'abc$def'` 82 | assertEquals '\$def' `_shunit_escapeCharInStr '$' '$def'` 83 | 84 | # actual=`_shunit_escapeCharInStr "'" ''` 85 | # assertEquals '' "${actual}" 86 | # assertEquals "abc\\'" `_shunit_escapeCharInStr "'" "abc'"` 87 | # assertEquals "abc\\'def" `_shunit_escapeCharInStr "'" "abc'def"` 88 | # assertEquals "\\'def" `_shunit_escapeCharInStr "'" "'def"` 89 | 90 | # # must put the backtick in a variable so the shell doesn't misinterpret it 91 | # # while inside a backticked sequence (e.g. `echo '`'` would fail). 92 | # backtick='`' 93 | # actual=`_shunit_escapeCharInStr ${backtick} ''` 94 | # assertEquals '' "${actual}" 95 | # assertEquals '\`abc' \ 96 | # `_shunit_escapeCharInStr "${backtick}" ${backtick}'abc'` 97 | # assertEquals 'abc\`' \ 98 | # `_shunit_escapeCharInStr "${backtick}" 'abc'${backtick}` 99 | # assertEquals 'abc\`def' \ 100 | # `_shunit_escapeCharInStr "${backtick}" 'abc'${backtick}'def'` 101 | } 102 | 103 | testEscapeCharInStr_specialChars() 104 | { 105 | # make sure our forward slash doesn't upset sed 106 | assertEquals '/' `_shunit_escapeCharInStr '\' '/'` 107 | 108 | # some shells escape these differently 109 | #assertEquals '\\a' `_shunit_escapeCharInStr '\' '\a'` 110 | #assertEquals '\\b' `_shunit_escapeCharInStr '\' '\b'` 111 | } 112 | 113 | # Test the various ways of declaring functions. 114 | # 115 | # Prefixing (then stripping) with comment symbol so these functions aren't 116 | # treated as real functions by shUnit2. 117 | testExtractTestFunctions() 118 | { 119 | f="${tmpD}/extract_test_functions" 120 | sed 's/^#//' <"${f}" 121 | #testABC() { echo 'ABC'; } 122 | #test_def() { 123 | # echo 'def' 124 | #} 125 | #testG3 () 126 | #{ 127 | # echo 'G3' 128 | #} 129 | #function test4() { echo '4'; } 130 | # test5() { echo '5'; } 131 | #some_test_function() { echo 'some func'; } 132 | #func_with_test_vars() { 133 | # testVariable=1234 134 | #} 135 | EOF 136 | 137 | actual=`_shunit_extractTestFunctions "${f}"` 138 | assertEquals 'testABC test_def testG3 test4 test5' "${actual}" 139 | } 140 | 141 | #------------------------------------------------------------------------------ 142 | # suite functions 143 | # 144 | 145 | setUp() 146 | { 147 | for f in ${expectedF} ${stdoutF} ${stderrF}; do 148 | cp /dev/null ${f} 149 | done 150 | rm -fr "${tmpD}" 151 | mkdir "${tmpD}" 152 | } 153 | 154 | oneTimeSetUp() 155 | { 156 | tmpD="${SHUNIT_TMPDIR}/tmp" 157 | expectedF="${SHUNIT_TMPDIR}/expected" 158 | stdoutF="${SHUNIT_TMPDIR}/stdout" 159 | stderrF="${SHUNIT_TMPDIR}/stderr" 160 | unittestF="${SHUNIT_TMPDIR}/unittest" 161 | } 162 | 163 | # load and run shUnit2 164 | [ -n "${ZSH_VERSION:-}" ] && SHUNIT_PARENT=$0 165 | . ${TH_SHUNIT} 166 | -------------------------------------------------------------------------------- /shunit/shunit2_test_standalone.sh: -------------------------------------------------------------------------------- 1 | #! /bin/sh 2 | # $Id: shunit2_test_standalone.sh 303 2010-05-03 13:11:27Z kate.ward@forestent.com $ 3 | # vim:et:ft=sh:sts=2:sw=2 4 | # 5 | # Copyright 2010 Kate Ward. All Rights Reserved. 6 | # Released under the LGPL (GNU Lesser General Public License) 7 | # Author: kate.ward@forestent.com (Kate Ward) 8 | # 9 | # shUnit2 unit test for standalone operation. 10 | # 11 | # This unit test is purely to test that calling shunit2 directly, while passing 12 | # the name of a unit test script, works. When run, this script determines if it 13 | # is running as a standalone program, and calls main() if it is. 14 | 15 | ARGV0=`basename "$0"` 16 | 17 | # load test helpers 18 | . ./shunit2_test_helpers 19 | 20 | #------------------------------------------------------------------------------ 21 | # suite tests 22 | # 23 | 24 | testStandalone() 25 | { 26 | assertTrue ${SHUNIT_TRUE} 27 | } 28 | 29 | #------------------------------------------------------------------------------ 30 | # main 31 | # 32 | 33 | main() 34 | { 35 | ${TH_SHUNIT} "${ARGV0}" 36 | } 37 | 38 | # are we running as a standalone? 39 | if [ "${ARGV0}" = 'shunit2_test_standalone.sh' ]; then 40 | if [ $# -gt 0 ]; then main "$@"; else main; fi 41 | fi 42 | -------------------------------------------------------------------------------- /test.sh: -------------------------------------------------------------------------------- 1 | #! /usr/bin/env bash 2 | 3 | run_tests() { 4 | for t in tests/*_test.sh; do 5 | $t 6 | done 7 | } 8 | 9 | run_tests 10 | -------------------------------------------------------------------------------- /tests/butlerfile_test.sh: -------------------------------------------------------------------------------- 1 | dot="$(cd "$(dirname "$0")"; pwd)" 2 | 3 | source "$dot/helpers.sh" 4 | source "$dot/../butler-base.sh" 5 | 6 | test_no_butlerfile() { 7 | cd_to_tmp 8 | output="$(butler_exec)" 9 | assertEquals "error: No butlerfile found." "$output" 10 | rm_tmp 11 | } 12 | 13 | test_should_list_commands_if_none_given() { 14 | expected="\ 15 | $(usage) 16 | commands: 17 | run: foo" 18 | 19 | cd_to_tmp 20 | echo "run: foo" > butlerfile 21 | output="$(butler_exec)" 22 | assertEquals "$expected" "$output" 23 | rm_tmp 24 | } 25 | 26 | test_should_list_no_commands_for_empty_butlerfile() { 27 | expected="\ 28 | $(usage) 29 | commands:" 30 | cd_to_tmp 31 | touch butlerfile 32 | output="$(butler_exec)" 33 | assertEquals "$expected" "$output" 34 | rm_tmp 35 | } 36 | 37 | test_runs_command_from_butlerfile() { 38 | expected="\ 39 | Executing foo: echo \"Hello, world!\" 40 | Hello, world!" 41 | 42 | cd_to_tmp 43 | prep_command "foo: echo \"Hello, world!\"" 44 | 45 | output="$(butler_exec foo)" 46 | 47 | assertEquals "$expected" "$output" 48 | rm_tmp 49 | } 50 | 51 | test_messages_if_command_not_found_in_butlerfile() { 52 | expected="error: foo doesn't exist in your butlerfile" 53 | 54 | cd_to_tmp 55 | echo "bar: echo \"Hello, world!\"" > butlerfile 56 | 57 | output="$(butler_exec foo)" 58 | 59 | assertEquals "$expected" "$output" 60 | rm_tmp 61 | } 62 | 63 | test_reports_multiple_instance_of_command() { 64 | expected="error: found 3 commands named foo, please fix your butlerfile" 65 | commands="\ 66 | foo: echo \"Hello, 1!\" 67 | foo: echo \"Hello, 2!\" 68 | foo: echo \"Hello, 3!\"" 69 | 70 | cd_to_tmp 71 | echo "$commands" > butlerfile 72 | 73 | output="$(butler_exec foo)" 74 | 75 | assertEquals "$expected" "$output" 76 | 77 | rm_tmp 78 | } 79 | 80 | test_only_execute_the_correct_command() { 81 | expectedFoo="\ 82 | Executing foo: echo \"Hello, Foo!\" 83 | Hello, Foo!" 84 | expectedBar="\ 85 | Executing bar: echo \"Hello, Bar!\" 86 | Hello, Bar!" 87 | 88 | cd_to_tmp 89 | prep_command "foo: echo \"Hello, Foo!\"" 90 | prep_command "bar: echo \"Hello, Bar!\"" 91 | 92 | output="$(butler_exec foo)" 93 | assertEquals "$expectedFoo" "$output" 94 | 95 | output="$(butler_exec bar)" 96 | assertEquals "$expectedBar" "$output" 97 | 98 | rm_tmp 99 | } 100 | 101 | test_passes_args_to_command() { 102 | expectedBar="\ 103 | Executing bar: echo \"Hello, \$1 \$2!\" 104 | Hello," 105 | expectedBaz="\ 106 | Executing baz: echo \"Hello, \$@!\" 107 | Hello," 108 | expectedFoo="\ 109 | Executing foo: echo \"Hello, \$1!\" 110 | Hello," 111 | 112 | cd_to_tmp 113 | prep_command "foo: echo \"Hello, \$1!\"" 114 | prep_command "baz: echo \"Hello, \$@!\"" 115 | prep_command "bar: echo \"Hello, \$1 \$2!\"" 116 | 117 | output="$(butler_exec foo "World")" 118 | assertEquals "$expectedFoo World!" "$output" 119 | output="$(butler_exec foo "Butler")" 120 | assertEquals "$expectedFoo Butler!" "$output" 121 | output="$(butler_exec foo "Michael" "Allen")" 122 | assertEquals "$expectedFoo Michael!" "$output" 123 | output="$(butler_exec bar "Michael" "Allen")" 124 | assertEquals "$expectedBar Michael Allen!" "$output" 125 | output="$(butler_exec baz "Michael" "Allen")" 126 | assertEquals "$expectedBaz Michael Allen!" "$output" 127 | 128 | rm_tmp 129 | } 130 | 131 | source "$dot/../shunit/shunit2" 132 | -------------------------------------------------------------------------------- /tests/commands_test.sh: -------------------------------------------------------------------------------- 1 | dot="$(cd "$(dirname "$0")"; pwd)" 2 | 3 | source "$dot/helpers.sh" 4 | source "$dot/../butler-base.sh" 5 | 6 | test_works_for_symlinks() { 7 | expected="error: No butlerfile found." 8 | 9 | cd_to_tmp 10 | ln -s "$dot/../butler" "butler" 11 | output="$(./butler)" 12 | 13 | assertEquals "$expected" "$output" 14 | rm_tmp 15 | } 16 | 17 | test_record_hash() { 18 | cd_to_tmp 19 | 20 | expected="d3b07384d113edec49eaa6238ad5ff00" 21 | record_test_hash "foo: foo" 22 | 23 | assertEquals "$(can_continue "foo" "foo"; echo "$?")" "0" 24 | 25 | empty_dot_butler 26 | rm_tmp 27 | } 28 | 29 | source "$dot/../shunit/shunit2" 30 | -------------------------------------------------------------------------------- /tests/completion_test.sh: -------------------------------------------------------------------------------- 1 | dot="$(cd "$(dirname "$0")"; pwd)" 2 | 3 | source "$dot/helpers.sh" 4 | source "$dot/../butler-base.sh" 5 | 6 | test_no_butlerfile() { 7 | cd_to_tmp 8 | 9 | output="$(butler_exec "--cmplt")" 10 | assertEquals "$output" "" 11 | 12 | rm_tmp 13 | } 14 | 15 | test_no_butlerfile_with_word() { 16 | cd_to_tmp 17 | 18 | output="$(butler_exec "--cmplt" "fo")" 19 | assertEquals "$output" "" 20 | 21 | rm_tmp 22 | } 23 | 24 | test_completes_single_option() { 25 | cd_to_tmp 26 | 27 | echo "foo: echo \"foo\"" >> butlerfile 28 | output="$(butler_exec "--cmplt" "fo")" 29 | assertEquals "$output" "foo" 30 | 31 | rm_tmp 32 | } 33 | 34 | test_completes_multiple_options() { 35 | cd_to_tmp 36 | 37 | echo "foo: echo \"foo\"" >> butlerfile 38 | echo "foobar: echo \"foobar\"" >> butlerfile 39 | 40 | output="$(butler_exec "--cmplt" "fo")" 41 | assertEquals "$output" "foo 42 | foobar" 43 | rm_tmp 44 | } 45 | 46 | source "$dot/../shunit/shunit2" 47 | -------------------------------------------------------------------------------- /tests/example_test.sh: -------------------------------------------------------------------------------- 1 | dot="$(cd "$(dirname "$0")"; pwd)" 2 | 3 | source "$dot/helpers.sh" 4 | source "$dot/../butler-base.sh" 5 | 6 | test_example() { 7 | cd_to_tmp 8 | touch foo 9 | assertEquals "1" "1" 10 | rm_tmp 11 | } 12 | 13 | source "$dot/../shunit/shunit2" 14 | -------------------------------------------------------------------------------- /tests/helpers.sh: -------------------------------------------------------------------------------- 1 | export scriptDir="$(cd "$(dirname "$0")"; pwd)" 2 | 3 | time_now() { 4 | echo "$(date +%s)" 5 | } 6 | 7 | cd_to_tmp() { 8 | tmpfile="/tmp/git-prompt-tests-$(time_now)" 9 | mkdir -p "$tmpfile" 10 | cd "$tmpfile" 11 | } 12 | 13 | rm_tmp() { 14 | cd $scriptDir 15 | rm -rf /tmp/git-prompt-tests* 16 | } 17 | 18 | empty_dot_butler() { 19 | local dot_butler="${1:-${DOT_BUTLER:-$HOME/.butler}}" 20 | rm -r "$dot_butler" 21 | } 22 | 23 | prep_command() { 24 | local command="$@" 25 | record_test_hash "$command" 26 | echo "$command" >> butlerfile 27 | } 28 | 29 | record_test_hash() { 30 | export DOT_BUTLER="./.butler_test" 31 | hash="$(hash_this "$@")" 32 | record_hash "$hash" 33 | } 34 | -------------------------------------------------------------------------------- /tests/initcommand_test.sh: -------------------------------------------------------------------------------- 1 | dot="$(cd "$(dirname "$0")"; pwd)" 2 | 3 | source "$dot/helpers.sh" 4 | source "$dot/../butler-base.sh" 5 | 6 | test_init_fails_when_butlerfile_exists() { 7 | expected="\ 8 | error: butlerfile already exists 9 | commands: 10 | foo: echo \"Hello, World!\"" 11 | commands="\ 12 | foo: echo \"Hello, World!\"" 13 | 14 | cd_to_tmp 15 | echo "$commands" >> butlerfile 16 | 17 | output="$(butler_exec --init)" 18 | assertEquals "$expected" "$output" 19 | 20 | rm_tmp 21 | } 22 | 23 | test_init_function_creates_butlerfile() { 24 | expectedInit="\ 25 | Creating an example butlerfile with one command: hello 26 | Try executing: 27 | > butler hello" 28 | expectedHello="\ 29 | Executing hello: echo \"Hello, World!\" 30 | Hello, World!" 31 | 32 | cd_to_tmp 33 | output="$(butler_exec --init)" 34 | assertEquals "$expectedInit" "$output" 35 | 36 | record_test_hash "hello: echo \"Hello, World!\"" 37 | output="$(butler_exec hello)" 38 | assertEquals "$expectedHello" "$output" 39 | 40 | rm_tmp 41 | } 42 | 43 | source "$dot/../shunit/shunit2" 44 | -------------------------------------------------------------------------------- /tests/safety_test.sh: -------------------------------------------------------------------------------- 1 | dot="$(cd "$(dirname "$0")"; pwd)" 2 | 3 | source "$dot/helpers.sh" 4 | source "$dot/../butler-base.sh" 5 | 6 | test_no_hash_file_yes() { 7 | cd_to_tmp 8 | 9 | export DOT_BUTLER="./.butler_test" 10 | echo "foo: echo \"foo\"" >> butlerfile 11 | 12 | expected="\ 13 | First time executing foo: echo \"foo\" 14 | Execute foo? (y)es, (n)o, just this (o)nce: " 15 | 16 | command_execution="Executing foo: echo \"foo\" 17 | foo" 18 | 19 | output="$(butler_exec "foo" <<< "y")" 20 | assertEquals "$expected$command_execution" "$output" 21 | 22 | output="$(butler_exec "foo")" 23 | assertEquals "$command_execution" "$output" 24 | 25 | rm_tmp 26 | } 27 | 28 | test_no_hash_file_no() { 29 | cd_to_tmp 30 | 31 | export DOT_BUTLER="./.butler_test" 32 | echo "foo: echo \"foo\"" >> butlerfile 33 | 34 | expected="\ 35 | First time executing foo: echo \"foo\" 36 | Execute foo? (y)es, (n)o, just this (o)nce: " 37 | 38 | command_execution="Executing foo: echo \"foo\" 39 | foo" 40 | 41 | output="$(butler_exec "foo" <<< "n")" 42 | assertEquals "$expected" "$output" 43 | 44 | output="$(butler_exec "foo" <<< "n")" 45 | assertEquals "$expected" "$output" 46 | 47 | rm_tmp 48 | } 49 | 50 | test_no_hash_file_once() { 51 | cd_to_tmp 52 | 53 | export DOT_BUTLER="./.butler_test" 54 | echo "foo: echo \"foo\"" >> butlerfile 55 | 56 | expected="\ 57 | First time executing foo: echo \"foo\" 58 | Execute foo? (y)es, (n)o, just this (o)nce: " 59 | 60 | command_execution="Executing foo: echo \"foo\" 61 | foo" 62 | 63 | output="$(butler_exec "foo" <<< "o")" 64 | assertEquals "$expected$command_execution" "$output" 65 | 66 | output="$(butler_exec "foo" <<< "o")" 67 | assertEquals "$expected$command_execution" "$output" 68 | 69 | rm_tmp 70 | } 71 | 72 | test_with_hash_file() { 73 | cd_to_tmp 74 | 75 | prep_command "foo: echo \"foo\"" 76 | 77 | expected="\ 78 | Executing foo: echo \"foo\" 79 | foo" 80 | 81 | output="$(butler_exec "foo")" 82 | assertEquals "$expected" "$output" 83 | 84 | rm_tmp 85 | } 86 | 87 | source "$dot/../shunit/shunit2" 88 | --------------------------------------------------------------------------------