1#! /bin/sh 2# vim:et:ft=sh:sts=2:sw=2 3# 4# shUnit2 -- Unit testing framework for Unix shell scripts. 5# 6# Copyright 2008-2021 Kate Ward. All Rights Reserved. 7# Released under the Apache 2.0 license. 8# http://www.apache.org/licenses/LICENSE-2.0 9# 10# Author: [email protected] (Kate Ward) 11# https://github.com/kward/shunit2 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# `expr` may be antiquated, but it is the only solution in some cases. 17# shellcheck disable=SC2003 18# Allow usage of legacy backticked `...` notation instead of $(...). 19# shellcheck disable=SC2006 20 21# Return if shunit2 already loaded. 22if test -n "${SHUNIT_VERSION:-}"; then 23 exit 0 24fi 25SHUNIT_VERSION='2.1.9pre' 26 27# Return values that scripts can use. 28SHUNIT_TRUE=0 29SHUNIT_FALSE=1 30SHUNIT_ERROR=2 31 32# Determine if `builtin` command exists. 33__SHUNIT_BUILTIN='builtin' 34# shellcheck disable=2039 35if ! ("${__SHUNIT_BUILTIN}" echo 123 >/dev/null 2>&1); then 36 __SHUNIT_BUILTIN='' 37fi 38 39# Determine some reasonable command defaults. 40__SHUNIT_CMD_ECHO_ESC='echo -e' 41# shellcheck disable=SC2039,SC3037 42if ${__SHUNIT_BUILTIN} [ "`echo -e test`" = '-e test' ]; then 43 __SHUNIT_CMD_ECHO_ESC='echo' 44fi 45 46# Commands a user can override if needed. 47__SHUNIT_CMD_TPUT='tput' 48SHUNIT_CMD_TPUT=${SHUNIT_CMD_TPUT:-${__SHUNIT_CMD_TPUT}} 49 50# Enable color output. Options are 'auto', 'always', or 'never'. 51SHUNIT_COLOR=${SHUNIT_COLOR:-auto} 52 53# 54# Internal constants. 55# 56 57__SHUNIT_MODE_SOURCED='sourced' 58__SHUNIT_MODE_STANDALONE='standalone' 59__SHUNIT_PARENT=${SHUNIT_PARENT:-$0} 60 61# User provided test prefix to display in front of the name of the test being 62# executed. Define by setting the SHUNIT_TEST_PREFIX variable. 63__SHUNIT_TEST_PREFIX=${SHUNIT_TEST_PREFIX:-} 64 65# ANSI colors. 66__SHUNIT_ANSI_NONE='\033[0m' 67__SHUNIT_ANSI_RED='\033[1;31m' 68__SHUNIT_ANSI_GREEN='\033[1;32m' 69__SHUNIT_ANSI_YELLOW='\033[1;33m' 70__SHUNIT_ANSI_CYAN='\033[1;36m' 71 72# 73# Internal variables. 74# 75 76# Variables. 77__shunit_lineno='' # Line number of executed test. 78__shunit_mode=${__SHUNIT_MODE_SOURCED} # Operating mode. 79__shunit_reportGenerated=${SHUNIT_FALSE} # Is report generated. 80__shunit_script='' # Filename of unittest script (standalone mode). 81__shunit_skip=${SHUNIT_FALSE} # Is skipping enabled. 82__shunit_suite='' # Suite of tests to execute. 83__shunit_clean=${SHUNIT_FALSE} # _shunit_cleanup() was already called. 84 85# ANSI colors (populated by _shunit_configureColor()). 86__shunit_ansi_none='' 87__shunit_ansi_red='' 88__shunit_ansi_green='' 89__shunit_ansi_yellow='' 90__shunit_ansi_cyan='' 91 92# Counts of tests. 93__shunit_testSuccess=${SHUNIT_TRUE} 94__shunit_testsTotal=0 95__shunit_testsPassed=0 96__shunit_testsFailed=0 97 98# Counts of asserts. 99__shunit_assertsTotal=0 100__shunit_assertsPassed=0 101__shunit_assertsFailed=0 102__shunit_assertsSkipped=0 103 104# 105# Internal functions. 106# 107 108# Logging. 109_shunit_warn() { 110 ${__SHUNIT_CMD_ECHO_ESC} "${__shunit_ansi_yellow}shunit2:WARN${__shunit_ansi_none} $*" >&2 111} 112_shunit_error() { 113 ${__SHUNIT_CMD_ECHO_ESC} "${__shunit_ansi_red}shunit2:ERROR${__shunit_ansi_none} $*" >&2 114} 115_shunit_fatal() { 116 ${__SHUNIT_CMD_ECHO_ESC} "${__shunit_ansi_red}shunit2:FATAL${__shunit_ansi_none} $*" >&2 117 exit ${SHUNIT_ERROR} 118} 119 120# 121# Macros. 122# 123 124# shellcheck disable=SC2016,SC2089 125_SHUNIT_LINENO_='eval __shunit_lineno=""; if ${__SHUNIT_BUILTIN} [ "${1:-}" = "--lineno" ] && ${__SHUNIT_BUILTIN} [ -n "${2:-}" ]; then __shunit_lineno="[${2}]"; shift 2; fi;' 126 127# 128# Setup. 129# 130 131# Specific shell checks. 132if ${__SHUNIT_BUILTIN} [ -n "${ZSH_VERSION:-}" ]; then 133 setopt |grep "^shwordsplit$" >/dev/null 134 if ${__SHUNIT_BUILTIN} [ $? -ne ${SHUNIT_TRUE} ]; then 135 _shunit_fatal 'zsh shwordsplit option is required for proper operation' 136 fi 137 if ${__SHUNIT_BUILTIN} [ -z "${SHUNIT_PARENT:-}" ]; then 138 _shunit_fatal "zsh does not pass \$0 through properly. please declare \ 139\"SHUNIT_PARENT=\$0\" before calling shUnit2" 140 fi 141fi 142 143# Set the constants readonly. 144__shunit_constants=`set |grep '^__SHUNIT_' |cut -d= -f1` 145echo "${__shunit_constants}" |grep '^Binary file' >/dev/null && \ 146 __shunit_constants=`set |grep -a '^__SHUNIT_' |cut -d= -f1` 147for __shunit_const in ${__shunit_constants}; do 148 if ${__SHUNIT_BUILTIN} [ -z "${ZSH_VERSION:-}" ]; then 149 readonly "${__shunit_const}" 150 else 151 case ${ZSH_VERSION} in 152 [123].*) readonly "${__shunit_const}" ;; 153 *) 154 # Declare readonly constants globally. 155 # shellcheck disable=SC2039,SC3045 156 readonly -g "${__shunit_const}" 157 esac 158 fi 159done 160unset __shunit_const __shunit_constants 161 162#----------------------------------------------------------------------------- 163# Assertion functions. 164# 165 166# Assert that two values are equal to one another. 167# 168# Args: 169# message: string: failure message [optional] 170# expected: string: expected value 171# actual: string: actual value 172# Returns: 173# integer: success (TRUE/FALSE/ERROR constant) 174assertEquals() { 175 # shellcheck disable=SC2090 176 ${_SHUNIT_LINENO_} 177 if ${__SHUNIT_BUILTIN} [ $# -lt 2 -o $# -gt 3 ]; then 178 _shunit_error "assertEquals() requires two or three arguments; $# given" 179 _shunit_assertFail 180 return ${SHUNIT_ERROR} 181 fi 182 if _shunit_shouldSkip; then 183 return ${SHUNIT_TRUE} 184 fi 185 186 shunit_message_=${__shunit_lineno} 187 if ${__SHUNIT_BUILTIN} [ $# -eq 3 ]; then 188 shunit_message_="${shunit_message_}$1" 189 shift 190 fi 191 shunit_expected_=$1 192 shunit_actual_=$2 193 194 shunit_return=${SHUNIT_TRUE} 195 if ${__SHUNIT_BUILTIN} [ "${shunit_expected_}" = "${shunit_actual_}" ]; then 196 _shunit_assertPass 197 else 198 failNotEquals "${shunit_message_}" "${shunit_expected_}" "${shunit_actual_}" 199 shunit_return=${SHUNIT_FALSE} 200 fi 201 202 unset shunit_message_ shunit_expected_ shunit_actual_ 203 return ${shunit_return} 204} 205# shellcheck disable=SC2016,SC2034 206_ASSERT_EQUALS_='eval assertEquals --lineno "${LINENO:-}"' 207 208# Assert that two values are not equal to one another. 209# 210# Args: 211# message: string: failure message [optional] 212# expected: string: expected value 213# actual: string: actual value 214# Returns: 215# integer: success (TRUE/FALSE/ERROR constant) 216assertNotEquals() { 217 # shellcheck disable=SC2090 218 ${_SHUNIT_LINENO_} 219 if ${__SHUNIT_BUILTIN} [ $# -lt 2 -o $# -gt 3 ]; then 220 _shunit_error "assertNotEquals() requires two or three arguments; $# given" 221 _shunit_assertFail 222 return ${SHUNIT_ERROR} 223 fi 224 if _shunit_shouldSkip; then 225 return ${SHUNIT_TRUE} 226 fi 227 228 shunit_message_=${__shunit_lineno} 229 if ${__SHUNIT_BUILTIN} [ $# -eq 3 ]; then 230 shunit_message_="${shunit_message_}$1" 231 shift 232 fi 233 shunit_expected_=$1 234 shunit_actual_=$2 235 236 shunit_return=${SHUNIT_TRUE} 237 if ${__SHUNIT_BUILTIN} [ "${shunit_expected_}" != "${shunit_actual_}" ]; then 238 _shunit_assertPass 239 else 240 failSame "${shunit_message_}" "${shunit_expected_}" "${shunit_actual_}" 241 shunit_return=${SHUNIT_FALSE} 242 fi 243 244 unset shunit_message_ shunit_expected_ shunit_actual_ 245 return ${shunit_return} 246} 247# shellcheck disable=SC2016,SC2034 248_ASSERT_NOT_EQUALS_='eval assertNotEquals --lineno "${LINENO:-}"' 249 250# Assert that a container contains a content. 251# 252# Args: 253# message: string: failure message [optional] 254# container: string: container to analyze 255# content: string: content to find 256# Returns: 257# integer: success (TRUE/FALSE/ERROR constant) 258assertContains() { 259 # shellcheck disable=SC2090 260 ${_SHUNIT_LINENO_} 261 if ${__SHUNIT_BUILTIN} [ $# -lt 2 -o $# -gt 3 ]; then 262 _shunit_error "assertContains() requires two or three arguments; $# given" 263 _shunit_assertFail 264 return ${SHUNIT_ERROR} 265 fi 266 if _shunit_shouldSkip; then 267 return ${SHUNIT_TRUE} 268 fi 269 270 shunit_message_=${__shunit_lineno} 271 if ${__SHUNIT_BUILTIN} [ $# -eq 3 ]; then 272 shunit_message_="${shunit_message_}$1" 273 shift 274 fi 275 shunit_container_=$1 276 shunit_content_=$2 277 shunit_return=${SHUNIT_TRUE} 278 if echo "${shunit_container_}" |grep -F -- "${shunit_content_}" >/dev/null; then 279 _shunit_assertPass 280 else 281 failNotFound "${shunit_message_}" "${shunit_content_}" 282 shunit_return=${SHUNIT_FALSE} 283 fi 284 285 unset shunit_message_ shunit_container_ shunit_content_ 286 return ${shunit_return} 287} 288# shellcheck disable=SC2016,SC2034 289_ASSERT_CONTAINS_='eval assertContains --lineno "${LINENO:-}"' 290 291# Assert that a container does not contain a content. 292# 293# Args: 294# message: string: failure message [optional] 295# container: string: container to analyze 296# content: string: content to look for 297# Returns: 298# integer: success (TRUE/FALSE/ERROR constant) 299assertNotContains() { 300 # shellcheck disable=SC2090 301 ${_SHUNIT_LINENO_} 302 if ${__SHUNIT_BUILTIN} [ $# -lt 2 -o $# -gt 3 ]; then 303 _shunit_error "assertNotContains() requires two or three arguments; $# given" 304 _shunit_assertFail 305 return ${SHUNIT_ERROR} 306 fi 307 if _shunit_shouldSkip; then 308 return ${SHUNIT_TRUE} 309 fi 310 311 shunit_message_=${__shunit_lineno} 312 if ${__SHUNIT_BUILTIN} [ $# -eq 3 ]; then 313 shunit_message_="${shunit_message_}$1" 314 shift 315 fi 316 shunit_container_=$1 317 shunit_content_=$2 318 319 shunit_return=${SHUNIT_TRUE} 320 if echo "$shunit_container_" | grep -F -- "$shunit_content_" > /dev/null; then 321 failFound "${shunit_message_}" "${shunit_content_}" 322 shunit_return=${SHUNIT_FALSE} 323 else 324 _shunit_assertPass 325 fi 326 327 unset shunit_message_ shunit_container_ shunit_content_ 328 return ${shunit_return} 329} 330# shellcheck disable=SC2016,SC2034 331_ASSERT_NOT_CONTAINS_='eval assertNotContains --lineno "${LINENO:-}"' 332 333# Assert that a value is null (i.e. an empty string). 334# 335# Args: 336# message: string: failure message [optional] 337# actual: string: actual value 338# Returns: 339# integer: success (TRUE/FALSE/ERROR constant) 340assertNull() { 341 # shellcheck disable=SC2090 342 ${_SHUNIT_LINENO_} 343 if ${__SHUNIT_BUILTIN} [ $# -gt 2 ]; then 344 # Allowing 0 arguments as $1 might actually be null. 345 _shunit_error "assertNull() requires one or two arguments; $# given" 346 _shunit_assertFail 347 return ${SHUNIT_ERROR} 348 fi 349 if _shunit_shouldSkip; then 350 return ${SHUNIT_TRUE} 351 fi 352 353 shunit_message_=${__shunit_lineno} 354 if ${__SHUNIT_BUILTIN} [ $# -eq 2 ]; then 355 shunit_message_="${shunit_message_}$1" 356 shift 357 fi 358 359 ${__SHUNIT_BUILTIN} test -z "${1:-}" 360 assertTrue "${shunit_message_}" $? 361 shunit_return=$? 362 363 unset shunit_message_ 364 return ${shunit_return} 365} 366# shellcheck disable=SC2016,SC2034 367_ASSERT_NULL_='eval assertNull --lineno "${LINENO:-}"' 368 369# Assert that a value is not null (i.e. a non-empty string). 370# 371# Args: 372# message: string: failure message [optional] 373# actual: string: actual value 374# Returns: 375# integer: success (TRUE/FALSE/ERROR constant) 376assertNotNull() { 377 # shellcheck disable=SC2090 378 ${_SHUNIT_LINENO_} 379 if ${__SHUNIT_BUILTIN} [ $# -gt 2 ]; then 380 # Allowing 0 arguments as $1 might actually be null. 381 _shunit_error "assertNotNull() requires one or two arguments; $# given" 382 _shunit_assertFail 383 return ${SHUNIT_ERROR} 384 fi 385 if _shunit_shouldSkip; then 386 return ${SHUNIT_TRUE} 387 fi 388 389 shunit_message_=${__shunit_lineno} 390 if ${__SHUNIT_BUILTIN} [ $# -eq 2 ]; then 391 shunit_message_="${shunit_message_}$1" 392 shift 393 fi 394 395 ${__SHUNIT_BUILTIN} test -n "${1:-}" 396 assertTrue "${shunit_message_}" $? 397 shunit_return=$? 398 399 unset shunit_message_ 400 return ${shunit_return} 401} 402# shellcheck disable=SC2016,SC2034 403_ASSERT_NOT_NULL_='eval assertNotNull --lineno "${LINENO:-}"' 404 405# Assert that two values are the same (i.e. equal to one another). 406# 407# Args: 408# message: string: failure message [optional] 409# expected: string: expected value 410# actual: string: actual value 411# Returns: 412# integer: success (TRUE/FALSE/ERROR constant) 413assertSame() { 414 # shellcheck disable=SC2090 415 ${_SHUNIT_LINENO_} 416 if ${__SHUNIT_BUILTIN} [ $# -lt 2 -o $# -gt 3 ]; then 417 _shunit_error "assertSame() requires two or three arguments; $# given" 418 _shunit_assertFail 419 return ${SHUNIT_ERROR} 420 fi 421 if _shunit_shouldSkip; then 422 return ${SHUNIT_TRUE} 423 fi 424 425 shunit_message_=${__shunit_lineno} 426 if ${__SHUNIT_BUILTIN} [ $# -eq 3 ]; then 427 shunit_message_="${shunit_message_}$1" 428 shift 429 fi 430 assertEquals "${shunit_message_}" "$1" "$2" 431 shunit_return=$? 432 433 unset shunit_message_ 434 return ${shunit_return} 435} 436# shellcheck disable=SC2016,SC2034 437_ASSERT_SAME_='eval assertSame --lineno "${LINENO:-}"' 438 439# Assert that two values are not the same (i.e. not equal to one another). 440# 441# Args: 442# message: string: failure message [optional] 443# expected: string: expected value 444# actual: string: actual value 445# Returns: 446# integer: success (TRUE/FALSE/ERROR constant) 447assertNotSame() { 448 # shellcheck disable=SC2090 449 ${_SHUNIT_LINENO_} 450 if ${__SHUNIT_BUILTIN} [ $# -lt 2 -o $# -gt 3 ]; then 451 _shunit_error "assertNotSame() requires two or three arguments; $# given" 452 _shunit_assertFail 453 return ${SHUNIT_ERROR} 454 fi 455 if _shunit_shouldSkip; then 456 return ${SHUNIT_TRUE} 457 fi 458 459 shunit_message_=${__shunit_lineno} 460 if ${__SHUNIT_BUILTIN} [ $# -eq 3 ]; then 461 shunit_message_="${shunit_message_:-}$1" 462 shift 463 fi 464 assertNotEquals "${shunit_message_}" "$1" "$2" 465 shunit_return=$? 466 467 unset shunit_message_ 468 return ${shunit_return} 469} 470# shellcheck disable=SC2016,SC2034 471_ASSERT_NOT_SAME_='eval assertNotSame --lineno "${LINENO:-}"' 472 473# Assert that a value or shell test condition is true. 474# 475# In shell, a value of 0 is true and a non-zero value is false. Any integer 476# value passed can thereby be tested. 477# 478# Shell supports much more complicated tests though, and a means to support 479# them was needed. As such, this function tests that conditions are true or 480# false through evaluation rather than just looking for a true or false. 481# 482# The following test will succeed: 483# assertTrue 0 484# assertTrue "[ 34 -gt 23 ]" 485# The following test will fail with a message: 486# assertTrue 123 487# assertTrue "test failed" "[ -r '/non/existent/file' ]" 488# 489# Args: 490# message: string: failure message [optional] 491# condition: string: integer value or shell conditional statement 492# Returns: 493# integer: success (TRUE/FALSE/ERROR constant) 494assertTrue() { 495 # shellcheck disable=SC2090 496 ${_SHUNIT_LINENO_} 497 if ${__SHUNIT_BUILTIN} [ $# -lt 1 -o $# -gt 2 ]; then 498 _shunit_error "assertTrue() takes one or two arguments; $# given" 499 _shunit_assertFail 500 return ${SHUNIT_ERROR} 501 fi 502 if _shunit_shouldSkip; then 503 return ${SHUNIT_TRUE} 504 fi 505 506 shunit_message_=${__shunit_lineno} 507 if ${__SHUNIT_BUILTIN} [ $# -eq 2 ]; then 508 shunit_message_="${shunit_message_}$1" 509 shift 510 fi 511 shunit_condition_=$1 512 513 # See if condition is an integer, i.e. a return value. 514 shunit_return=${SHUNIT_TRUE} 515 if ${__SHUNIT_BUILTIN} [ -z "${shunit_condition_}" ]; then 516 # Null condition. 517 shunit_return=${SHUNIT_FALSE} 518 elif (expr \( "${shunit_condition_}" + '0' \) '=' "${shunit_condition_}" >/dev/null 2>&1) 519 then 520 # Possible return value. Treating 0 as true, and non-zero as false. 521 if ${__SHUNIT_BUILTIN} [ "${shunit_condition_}" -ne 0 ]; then 522 shunit_return=${SHUNIT_FALSE} 523 fi 524 else 525 # Hopefully... a condition. 526 if ! eval "${shunit_condition_}" >/dev/null 2>&1; then 527 shunit_return=${SHUNIT_FALSE} 528 fi 529 fi 530 531 # Record the test. 532 if ${__SHUNIT_BUILTIN} [ ${shunit_return} -eq ${SHUNIT_TRUE} ]; then 533 _shunit_assertPass 534 else 535 _shunit_assertFail "${shunit_message_}" 536 fi 537 538 unset shunit_message_ shunit_condition_ 539 return ${shunit_return} 540} 541# shellcheck disable=SC2016,SC2034 542_ASSERT_TRUE_='eval assertTrue --lineno "${LINENO:-}"' 543 544# Assert that a value or shell test condition is false. 545# 546# In shell, a value of 0 is true and a non-zero value is false. Any integer 547# value passed can thereby be tested. 548# 549# Shell supports much more complicated tests though, and a means to support 550# them was needed. As such, this function tests that conditions are true or 551# false through evaluation rather than just looking for a true or false. 552# 553# The following test will succeed: 554# assertFalse 1 555# assertFalse "[ 'apples' = 'oranges' ]" 556# The following test will fail with a message: 557# assertFalse 0 558# assertFalse "test failed" "[ 1 -eq 1 -a 2 -eq 2 ]" 559# 560# Args: 561# message: string: failure message [optional] 562# condition: string: integer value or shell conditional statement 563# Returns: 564# integer: success (TRUE/FALSE/ERROR constant) 565assertFalse() { 566 # shellcheck disable=SC2090 567 ${_SHUNIT_LINENO_} 568 if ${__SHUNIT_BUILTIN} [ $# -lt 1 -o $# -gt 2 ]; then 569 _shunit_error "assertFalse() requires one or two arguments; $# given" 570 _shunit_assertFail 571 return ${SHUNIT_ERROR} 572 fi 573 if _shunit_shouldSkip; then 574 return ${SHUNIT_TRUE} 575 fi 576 577 shunit_message_=${__shunit_lineno} 578 if ${__SHUNIT_BUILTIN} [ $# -eq 2 ]; then 579 shunit_message_="${shunit_message_}$1" 580 shift 581 fi 582 shunit_condition_=$1 583 584 # See if condition is an integer, i.e. a return value. 585 shunit_return=${SHUNIT_TRUE} 586 if ${__SHUNIT_BUILTIN} [ -z "${shunit_condition_}" ]; then 587 # Null condition. 588 shunit_return=${SHUNIT_TRUE} 589 elif (expr \( "${shunit_condition_}" + '0' \) '=' "${shunit_condition_}" >/dev/null 2>&1); then 590 # Possible return value. Treating 0 as true, and non-zero as false. 591 if ${__SHUNIT_BUILTIN} [ "${shunit_condition_}" -eq 0 ]; then 592 shunit_return=${SHUNIT_FALSE} 593 fi 594 else 595 # Hopefully... a condition. 596 # shellcheck disable=SC2086 597 if eval ${shunit_condition_} >/dev/null 2>&1; then 598 shunit_return=${SHUNIT_FALSE} 599 fi 600 fi 601 602 # Record the test. 603 if ${__SHUNIT_BUILTIN} [ "${shunit_return}" -eq "${SHUNIT_TRUE}" ]; then 604 _shunit_assertPass 605 else 606 _shunit_assertFail "${shunit_message_}" 607 fi 608 609 unset shunit_message_ shunit_condition_ 610 return "${shunit_return}" 611} 612# shellcheck disable=SC2016,SC2034 613_ASSERT_FALSE_='eval assertFalse --lineno "${LINENO:-}"' 614 615#----------------------------------------------------------------------------- 616# Failure functions. 617# 618 619# Records a test failure. 620# 621# Args: 622# message: string: failure message [optional] 623# Returns: 624# integer: success (TRUE/FALSE/ERROR constant) 625fail() { 626 # shellcheck disable=SC2090 627 ${_SHUNIT_LINENO_} 628 if ${__SHUNIT_BUILTIN} [ $# -gt 1 ]; then 629 _shunit_error "fail() requires zero or one arguments; $# given" 630 return ${SHUNIT_ERROR} 631 fi 632 if _shunit_shouldSkip; then 633 return ${SHUNIT_TRUE} 634 fi 635 636 shunit_message_=${__shunit_lineno} 637 if ${__SHUNIT_BUILTIN} [ $# -eq 1 ]; then 638 shunit_message_="${shunit_message_}$1" 639 shift 640 fi 641 642 _shunit_assertFail "${shunit_message_}" 643 644 unset shunit_message_ 645 return ${SHUNIT_FALSE} 646} 647# shellcheck disable=SC2016,SC2034 648_FAIL_='eval fail --lineno "${LINENO:-}"' 649 650# Records a test failure, stating two values were not equal. 651# 652# Args: 653# message: string: failure message [optional] 654# expected: string: expected value 655# actual: string: actual value 656# Returns: 657# integer: success (TRUE/FALSE/ERROR constant) 658failNotEquals() { 659 # shellcheck disable=SC2090 660 ${_SHUNIT_LINENO_} 661 if ${__SHUNIT_BUILTIN} [ $# -lt 2 -o $# -gt 3 ]; then 662 _shunit_error "failNotEquals() requires one or two arguments; $# given" 663 return ${SHUNIT_ERROR} 664 fi 665 if _shunit_shouldSkip; then 666 return ${SHUNIT_TRUE} 667 fi 668 669 shunit_message_=${__shunit_lineno} 670 if ${__SHUNIT_BUILTIN} [ $# -eq 3 ]; then 671 shunit_message_="${shunit_message_}$1" 672 shift 673 fi 674 shunit_expected_=$1 675 shunit_actual_=$2 676 677 shunit_message_=${shunit_message_%% } 678 _shunit_assertFail "${shunit_message_:+${shunit_message_} }expected:<${shunit_expected_}> but was:<${shunit_actual_}>" 679 680 unset shunit_message_ shunit_expected_ shunit_actual_ 681 return ${SHUNIT_FALSE} 682} 683# shellcheck disable=SC2016,SC2034 684_FAIL_NOT_EQUALS_='eval failNotEquals --lineno "${LINENO:-}"' 685 686# Records a test failure, stating a value was found. 687# 688# Args: 689# message: string: failure message [optional] 690# content: string: found value 691# Returns: 692# integer: success (TRUE/FALSE/ERROR constant) 693failFound() { 694 # shellcheck disable=SC2090 695 ${_SHUNIT_LINENO_} 696 if ${__SHUNIT_BUILTIN} [ $# -lt 1 -o $# -gt 2 ]; then 697 _shunit_error "failFound() requires one or two arguments; $# given" 698 return ${SHUNIT_ERROR} 699 fi 700 if _shunit_shouldSkip; then 701 return ${SHUNIT_TRUE} 702 fi 703 704 shunit_message_=${__shunit_lineno} 705 if ${__SHUNIT_BUILTIN} [ $# -eq 2 ]; then 706 shunit_message_="${shunit_message_}$1" 707 shift 708 fi 709 shunit_content_=$1 710 711 shunit_message_=${shunit_message_%% } 712 _shunit_assertFail "${shunit_message_:+${shunit_message_} }found:<${shunit_content_}>" 713 714 unset shunit_message_ shunit_content_ 715 return ${SHUNIT_FALSE} 716} 717# shellcheck disable=SC2016,SC2034 718_FAIL_FOUND_='eval failFound --lineno "${LINENO:-}"' 719 720# Records a test failure, stating a content was not found. 721# 722# Args: 723# message: string: failure message [optional] 724# content: string: content not found 725# Returns: 726# integer: success (TRUE/FALSE/ERROR constant) 727failNotFound() { 728 # shellcheck disable=SC2090 729 ${_SHUNIT_LINENO_} 730 if ${__SHUNIT_BUILTIN} [ $# -lt 1 -o $# -gt 2 ]; then 731 _shunit_error "failNotFound() requires one or two arguments; $# given" 732 return ${SHUNIT_ERROR} 733 fi 734 if _shunit_shouldSkip; then 735 return ${SHUNIT_TRUE} 736 fi 737 738 shunit_message_=${__shunit_lineno} 739 if ${__SHUNIT_BUILTIN} [ $# -eq 2 ]; then 740 shunit_message_="${shunit_message_}$1" 741 shift 742 fi 743 shunit_content_=$1 744 745 shunit_message_=${shunit_message_%% } 746 _shunit_assertFail "${shunit_message_:+${shunit_message_} }not found:<${shunit_content_}>" 747 748 unset shunit_message_ shunit_content_ 749 return ${SHUNIT_FALSE} 750} 751# shellcheck disable=SC2016,SC2034 752_FAIL_NOT_FOUND_='eval failNotFound --lineno "${LINENO:-}"' 753 754# Records a test failure, stating two values should have been the same. 755# 756# Args: 757# message: string: failure message [optional] 758# expected: string: expected value 759# actual: string: actual value 760# Returns: 761# integer: success (TRUE/FALSE/ERROR constant) 762failSame() { 763 # shellcheck disable=SC2090 764 ${_SHUNIT_LINENO_} 765 if ${__SHUNIT_BUILTIN} [ $# -lt 2 -o $# -gt 3 ]; then 766 _shunit_error "failSame() requires two or three arguments; $# given" 767 return ${SHUNIT_ERROR} 768 fi 769 if _shunit_shouldSkip; then 770 return ${SHUNIT_TRUE} 771 fi 772 773 shunit_message_=${__shunit_lineno} 774 if ${__SHUNIT_BUILTIN} [ $# -eq 3 ]; then 775 shunit_message_="${shunit_message_}$1" 776 shift 777 fi 778 779 shunit_message_=${shunit_message_%% } 780 _shunit_assertFail "${shunit_message_:+${shunit_message_} }expected not same" 781 782 unset shunit_message_ 783 return ${SHUNIT_FALSE} 784} 785# shellcheck disable=SC2016,SC2034 786_FAIL_SAME_='eval failSame --lineno "${LINENO:-}"' 787 788# Records a test failure, stating two values were not equal. 789# 790# This is functionally equivalent to calling failNotEquals(). 791# 792# Args: 793# message: string: failure message [optional] 794# expected: string: expected value 795# actual: string: actual value 796# Returns: 797# integer: success (TRUE/FALSE/ERROR constant) 798failNotSame() { 799 # shellcheck disable=SC2090 800 ${_SHUNIT_LINENO_} 801 if ${__SHUNIT_BUILTIN} [ $# -lt 2 -o $# -gt 3 ]; then 802 _shunit_error "failNotSame() requires one or two arguments; $# given" 803 return ${SHUNIT_ERROR} 804 fi 805 if _shunit_shouldSkip; then 806 return ${SHUNIT_TRUE} 807 fi 808 809 shunit_message_=${__shunit_lineno} 810 if ${__SHUNIT_BUILTIN} [ $# -eq 3 ]; then 811 shunit_message_="${shunit_message_}$1" 812 shift 813 fi 814 failNotEquals "${shunit_message_}" "$1" "$2" 815 shunit_return=$? 816 817 unset shunit_message_ 818 return ${shunit_return} 819} 820# shellcheck disable=SC2016,SC2034 821_FAIL_NOT_SAME_='eval failNotSame --lineno "${LINENO:-}"' 822 823#----------------------------------------------------------------------------- 824# Skipping functions. 825# 826 827# Force remaining assert and fail functions to be "skipped". 828# 829# This function forces the remaining assert and fail functions to be "skipped", 830# i.e. they will have no effect. Each function skipped will be recorded so that 831# the total of asserts and fails will not be altered. 832# 833# Args: 834# message: string: message to provide to user [optional] 835startSkipping() { 836 if ${__SHUNIT_BUILTIN} [ $# -gt 0 ]; then _shunit_warn "[skipping] $*"; fi 837 __shunit_skip=${SHUNIT_TRUE} 838} 839 840# Resume the normal recording behavior of assert and fail calls. 841# 842# Args: 843# None 844endSkipping() { __shunit_skip=${SHUNIT_FALSE}; } 845 846# Returns the state of assert and fail call skipping. 847# 848# Args: 849# None 850# Returns: 851# boolean: (TRUE/FALSE constant) 852isSkipping() { return ${__shunit_skip}; } 853 854#----------------------------------------------------------------------------- 855# Suite functions. 856# 857 858# Stub. This function should contains all unit test calls to be made. 859# 860# DEPRECATED (as of 2.1.0) 861# 862# This function can be optionally overridden by the user in their test suite. 863# 864# If this function exists, it will be called when shunit2 is sourced. If it 865# does not exist, shunit2 will search the parent script for all functions 866# beginning with the word 'test', and they will be added dynamically to the 867# test suite. 868# 869# This function should be overridden by the user in their unit test suite. 870# Note: see _shunit_mktempFunc() for actual implementation 871# 872# Args: 873# None 874#suite() { :; } # DO NOT UNCOMMENT THIS FUNCTION 875 876# Adds a function name to the list of tests schedule for execution. 877# 878# This function should only be called from within the suite() function. 879# 880# Args: 881# function: string: name of a function to add to current unit test suite 882suite_addTest() { 883 shunit_func_=${1:-} 884 885 __shunit_suite="${__shunit_suite:+${__shunit_suite} }${shunit_func_}" 886 __shunit_testsTotal=`expr ${__shunit_testsTotal} + 1` 887 888 unset shunit_func_ 889} 890 891# Stub. This function will be called once before any tests are run. 892# 893# Common one-time environment preparation tasks shared by all tests can be 894# defined here. 895# 896# This function should be overridden by the user in their unit test suite. 897# Note: see _shunit_mktempFunc() for actual implementation 898# 899# Args: 900# None 901#oneTimeSetUp() { :; } # DO NOT UNCOMMENT THIS FUNCTION 902 903# Stub. This function will be called once after all tests are finished. 904# 905# Common one-time environment cleanup tasks shared by all tests can be defined 906# here. 907# 908# This function should be overridden by the user in their unit test suite. 909# Note: see _shunit_mktempFunc() for actual implementation 910# 911# Args: 912# None 913#oneTimeTearDown() { :; } # DO NOT UNCOMMENT THIS FUNCTION 914 915# Stub. This function will be called before each test is run. 916# 917# Common environment preparation tasks shared by all tests can be defined here. 918# 919# This function should be overridden by the user in their unit test suite. 920# Note: see _shunit_mktempFunc() for actual implementation 921# 922# Args: 923# None 924#setUp() { :; } # DO NOT UNCOMMENT THIS FUNCTION 925 926# Note: see _shunit_mktempFunc() for actual implementation 927# Stub. This function will be called after each test is run. 928# 929# Common environment cleanup tasks shared by all tests can be defined here. 930# 931# This function should be overridden by the user in their unit test suite. 932# Note: see _shunit_mktempFunc() for actual implementation 933# 934# Args: 935# None 936#tearDown() { :; } # DO NOT UNCOMMENT THIS FUNCTION 937 938#------------------------------------------------------------------------------ 939# Internal shUnit2 functions. 940# 941 942# Create a temporary directory to store various run-time files in. 943# 944# This function is a cross-platform temporary directory creation tool. Not all 945# OSes have the `mktemp` function, so one is included here. 946# 947# Args: 948# None 949# Outputs: 950# string: the temporary directory that was created 951_shunit_mktempDir() { 952 # Try the standard `mktemp` function. 953 if ( exec mktemp -dqt shunit.XXXXXX 2>/dev/null ); then 954 return 955 fi 956 957 # The standard `mktemp` didn't work. Use our own. 958 # shellcheck disable=SC2039,SC3028 959 if ${__SHUNIT_BUILTIN} [ -r '/dev/urandom' -a -x '/usr/bin/od' ]; then 960 _shunit_random_=`/usr/bin/od -vAn -N4 -tx4 </dev/urandom |command sed 's/^[^0-9a-f]*//'` 961 elif ${__SHUNIT_BUILTIN} [ -n "${RANDOM:-}" ]; then 962 # $RANDOM works 963 _shunit_random_=${RANDOM}${RANDOM}${RANDOM}$$ 964 else 965 # `$RANDOM` doesn't work. 966 _shunit_date_=`date '+%Y%m%d%H%M%S'` 967 _shunit_random_=`expr "${_shunit_date_}" / $$` 968 fi 969 970 _shunit_tmpDir_="${TMPDIR:-/tmp}/shunit.${_shunit_random_}" 971 if ! ( umask 077 && command mkdir "${_shunit_tmpDir_}" ); then 972 _shunit_fatal 'could not create temporary directory! exiting' 973 fi 974 975 echo "${_shunit_tmpDir_}" 976 unset _shunit_date_ _shunit_random_ _shunit_tmpDir_ 977} 978 979# This function is here to work around issues in Cygwin. 980# 981# Args: 982# None 983_shunit_mktempFunc() { 984 for _shunit_func_ in oneTimeSetUp oneTimeTearDown setUp tearDown suite noexec 985 do 986 _shunit_file_="${__shunit_tmpDir}/${_shunit_func_}" 987 command cat <<EOF >"${_shunit_file_}" 988#! /bin/sh 989exit ${SHUNIT_TRUE} 990EOF 991 command chmod +x "${_shunit_file_}" 992 done 993 994 unset _shunit_file_ 995} 996 997# Final cleanup function to leave things as we found them. 998# 999# Besides removing the temporary directory, this function is in charge of the 1000# final exit code of the unit test. The exit code is based on how the script 1001# was ended (e.g. normal exit, or via Ctrl-C). 1002# 1003# Args: 1004# name: string: name of the trap called (specified when trap defined) 1005_shunit_cleanup() { 1006 _shunit_name_=$1 1007 1008 _shunit_signal_=0 1009 case "${_shunit_name_}" in 1010 EXIT) ;; 1011 INT) _shunit_signal_=130 ;; # 2+128 1012 TERM) _shunit_signal_=143 ;; # 15+128 1013 *) 1014 _shunit_error "unrecognized trap value (${_shunit_name_})" 1015 ;; 1016 esac 1017 if ${__SHUNIT_BUILTIN} [ "${_shunit_name_}" != 'EXIT' ]; then 1018 _shunit_warn "trapped and now handling the (${_shunit_name_}) signal" 1019 fi 1020 1021 # Do our work. 1022 if ${__SHUNIT_BUILTIN} [ ${__shunit_clean} -eq ${SHUNIT_FALSE} ]; then 1023 # Ensure tear downs are only called once. 1024 __shunit_clean=${SHUNIT_TRUE} 1025 1026 tearDown || _shunit_warn 'tearDown() returned non-zero return code.' 1027 oneTimeTearDown || \ 1028 _shunit_warn 'oneTimeTearDown() returned non-zero return code.' 1029 1030 command rm -fr "${__shunit_tmpDir}" 1031 fi 1032 1033 if ${__SHUNIT_BUILTIN} [ "${_shunit_name_}" != 'EXIT' ]; then 1034 # Handle all non-EXIT signals. 1035 trap - 0 # Disable EXIT trap. 1036 exit ${_shunit_signal_} 1037 elif ${__SHUNIT_BUILTIN} [ ${__shunit_reportGenerated} -eq ${SHUNIT_FALSE} ]; then 1038 _shunit_assertFail 'unknown failure encountered running a test' 1039 _shunit_generateReport 1040 exit ${SHUNIT_ERROR} 1041 fi 1042 1043 unset _shunit_name_ _shunit_signal_ 1044} 1045 1046# configureColor based on user color preference. 1047# 1048# Args: 1049# color: string: color mode (one of `always`, `auto`, or `never`). 1050_shunit_configureColor() { 1051 _shunit_color_=${SHUNIT_FALSE} # By default, no color. 1052 case $1 in 1053 'always') _shunit_color_=${SHUNIT_TRUE} ;; 1054 'auto') 1055 if ${__SHUNIT_BUILTIN} [ "`_shunit_colors`" -ge 8 ]; then 1056 _shunit_color_=${SHUNIT_TRUE} 1057 fi 1058 ;; 1059 'never'|'none') ;; # Support 'none' to support legacy usage. 1060 *) _shunit_fatal "unrecognized color option '$1'" ;; 1061 esac 1062 1063 # shellcheck disable=SC2254 1064 case ${_shunit_color_} in 1065 ${SHUNIT_TRUE}) 1066 __shunit_ansi_none=${__SHUNIT_ANSI_NONE} 1067 __shunit_ansi_red=${__SHUNIT_ANSI_RED} 1068 __shunit_ansi_green=${__SHUNIT_ANSI_GREEN} 1069 __shunit_ansi_yellow=${__SHUNIT_ANSI_YELLOW} 1070 __shunit_ansi_cyan=${__SHUNIT_ANSI_CYAN} 1071 ;; 1072 ${SHUNIT_FALSE}) 1073 __shunit_ansi_none='' 1074 __shunit_ansi_red='' 1075 __shunit_ansi_green='' 1076 __shunit_ansi_yellow='' 1077 __shunit_ansi_cyan='' 1078 ;; 1079 esac 1080 1081 unset _shunit_color_ _shunit_tput_ 1082} 1083 1084# colors returns the number of supported colors for the TERM. 1085_shunit_colors() { 1086 if _shunit_tput_=`${SHUNIT_CMD_TPUT} colors 2>/dev/null`; then 1087 echo "${_shunit_tput_}" 1088 else 1089 echo 16 1090 fi 1091 unset _shunit_tput_ 1092} 1093 1094# The actual running of the tests happens here. 1095# 1096# Args: 1097# None 1098_shunit_execSuite() { 1099 for _shunit_test_ in ${__shunit_suite}; do 1100 __shunit_testSuccess=${SHUNIT_TRUE} 1101 1102 # Disable skipping. 1103 endSkipping 1104 1105 # Execute the per-test setUp() function. 1106 if ! setUp; then 1107 _shunit_fatal "setUp() returned non-zero return code." 1108 fi 1109 1110 # Execute the test. 1111 echo "${__SHUNIT_TEST_PREFIX}${_shunit_test_}" 1112 # shellcheck disable=SC2086 1113 if ! eval ${_shunit_test_}; then 1114 _shunit_error "${_shunit_test_}() returned non-zero return code." 1115 __shunit_testSuccess=${SHUNIT_ERROR} 1116 fi 1117 1118 # Execute the per-test tearDown() function. 1119 if ! tearDown; then 1120 _shunit_fatal "tearDown() returned non-zero return code." 1121 fi 1122 1123 # Update stats. 1124 if ${__SHUNIT_BUILTIN} [ ${__shunit_testSuccess} -eq ${SHUNIT_TRUE} ]; then 1125 __shunit_testsPassed=`expr ${__shunit_testsPassed} + 1` 1126 else 1127 __shunit_testsFailed=`expr ${__shunit_testsFailed} + 1` 1128 fi 1129 done 1130 1131 unset _shunit_test_ 1132} 1133 1134# Generates the user friendly report with appropriate OK/FAILED message. 1135# 1136# Args: 1137# None 1138# Output: 1139# string: the report of successful and failed tests, as well as totals. 1140_shunit_generateReport() { 1141 if ${__SHUNIT_BUILTIN} [ "${__shunit_reportGenerated}" -eq ${SHUNIT_TRUE} ]; then 1142 return 1143 fi 1144 1145 _shunit_ok_=${SHUNIT_TRUE} 1146 1147 # If no exit code was provided, determine an appropriate one. 1148 if ${__SHUNIT_BUILTIN} [ "${__shunit_testsFailed}" -gt 0 -o ${__shunit_testSuccess} -eq ${SHUNIT_FALSE} ]; then 1149 _shunit_ok_=${SHUNIT_FALSE} 1150 fi 1151 1152 echo 1153 _shunit_msg_="Ran ${__shunit_ansi_cyan}${__shunit_testsTotal}${__shunit_ansi_none}" 1154 if ${__SHUNIT_BUILTIN} [ "${__shunit_testsTotal}" -eq 1 ]; then 1155 ${__SHUNIT_CMD_ECHO_ESC} "${_shunit_msg_} test." 1156 else 1157 ${__SHUNIT_CMD_ECHO_ESC} "${_shunit_msg_} tests." 1158 fi 1159 1160 if ${__SHUNIT_BUILTIN} [ ${_shunit_ok_} -eq ${SHUNIT_TRUE} ]; then 1161 _shunit_msg_="${__shunit_ansi_green}OK${__shunit_ansi_none}" 1162 if ${__SHUNIT_BUILTIN} [ "${__shunit_assertsSkipped}" -gt 0 ]; then 1163 _shunit_msg_="${_shunit_msg_} (${__shunit_ansi_yellow}skipped=${__shunit_assertsSkipped}${__shunit_ansi_none})" 1164 fi 1165 else 1166 _shunit_msg_="${__shunit_ansi_red}FAILED${__shunit_ansi_none}" 1167 _shunit_msg_="${_shunit_msg_} (${__shunit_ansi_red}failures=${__shunit_assertsFailed}${__shunit_ansi_none}" 1168 if ${__SHUNIT_BUILTIN} [ "${__shunit_assertsSkipped}" -gt 0 ]; then 1169 _shunit_msg_="${_shunit_msg_},${__shunit_ansi_yellow}skipped=${__shunit_assertsSkipped}${__shunit_ansi_none}" 1170 fi 1171 _shunit_msg_="${_shunit_msg_})" 1172 fi 1173 1174 echo 1175 ${__SHUNIT_CMD_ECHO_ESC} "${_shunit_msg_}" 1176 __shunit_reportGenerated=${SHUNIT_TRUE} 1177 1178 unset _shunit_msg_ _shunit_ok_ 1179} 1180 1181# Test for whether a function should be skipped. 1182# 1183# Args: 1184# None 1185# Returns: 1186# boolean: whether the test should be skipped (TRUE/FALSE constant) 1187_shunit_shouldSkip() { 1188 if ${__SHUNIT_BUILTIN} test ${__shunit_skip} -eq ${SHUNIT_FALSE}; then 1189 return ${SHUNIT_FALSE} 1190 fi 1191 _shunit_assertSkip 1192} 1193 1194# Records a successful test. 1195# 1196# Args: 1197# None 1198_shunit_assertPass() { 1199 __shunit_assertsPassed=`expr ${__shunit_assertsPassed} + 1` 1200 __shunit_assertsTotal=`expr ${__shunit_assertsTotal} + 1` 1201} 1202 1203# Records a test failure. 1204# 1205# Args: 1206# message: string: failure message to provide user 1207_shunit_assertFail() { 1208 __shunit_testSuccess=${SHUNIT_FALSE} 1209 _shunit_incFailedCount 1210 1211 if ${__SHUNIT_BUILTIN} [ $# -gt 0 ]; then 1212 ${__SHUNIT_CMD_ECHO_ESC} "${__shunit_ansi_red}ASSERT:${__shunit_ansi_none}$*" 1213 fi 1214} 1215 1216# Increment the count of failed asserts. 1217# 1218# Args: 1219# none 1220_shunit_incFailedCount() { 1221 __shunit_assertsFailed=`expr "${__shunit_assertsFailed}" + 1` 1222 __shunit_assertsTotal=`expr "${__shunit_assertsTotal}" + 1` 1223} 1224 1225# Records a skipped test. 1226# 1227# Args: 1228# None 1229_shunit_assertSkip() { 1230 __shunit_assertsSkipped=`expr "${__shunit_assertsSkipped}" + 1` 1231 __shunit_assertsTotal=`expr "${__shunit_assertsTotal}" + 1` 1232} 1233 1234# Dump the current test metrics. 1235# 1236# Args: 1237# none 1238_shunit_metrics() { 1239 echo "< \ 1240total: ${__shunit_assertsTotal} \ 1241passed: ${__shunit_assertsPassed} \ 1242failed: ${__shunit_assertsFailed} \ 1243skipped: ${__shunit_assertsSkipped} \ 1244>" 1245} 1246 1247# Prepare a script filename for sourcing. 1248# 1249# Args: 1250# script: string: path to a script to source 1251# Returns: 1252# string: filename prefixed with ./ (if necessary) 1253_shunit_prepForSourcing() { 1254 _shunit_script_=$1 1255 case "${_shunit_script_}" in 1256 /*|./*) echo "${_shunit_script_}" ;; 1257 *) echo "./${_shunit_script_}" ;; 1258 esac 1259 unset _shunit_script_ 1260} 1261 1262# Extract list of functions to run tests against. 1263# 1264# Args: 1265# script: string: name of script to extract functions from 1266# Returns: 1267# string: of function names 1268_shunit_extractTestFunctions() { 1269 _shunit_script_=$1 1270 1271 # Extract the lines with test function names, strip of anything besides the 1272 # function name, and output everything on a single line. 1273 _shunit_regex_='^\s*((function test[A-Za-z0-9_-]*)|(test[A-Za-z0-9_-]* *\(\)))' 1274 # shellcheck disable=SC2196 1275 egrep "${_shunit_regex_}" "${_shunit_script_}" \ 1276 |command sed 's/^[^A-Za-z0-9_-]*//;s/^function //;s/\([A-Za-z0-9_-]*\).*/\1/g' \ 1277 |xargs 1278 1279 unset _shunit_regex_ _shunit_script_ 1280} 1281 1282#------------------------------------------------------------------------------ 1283# Main. 1284# 1285 1286# Determine the operating mode. 1287if ${__SHUNIT_BUILTIN} [ $# -eq 0 -o "${1:-}" = '--' ]; then 1288 __shunit_script=${__SHUNIT_PARENT} 1289 __shunit_mode=${__SHUNIT_MODE_SOURCED} 1290else 1291 __shunit_script=$1 1292 if ! ${__SHUNIT_BUILTIN} [ -r "${__shunit_script}" ]; then 1293 _shunit_fatal "unable to read from ${__shunit_script}" 1294 fi 1295 __shunit_mode=${__SHUNIT_MODE_STANDALONE} 1296fi 1297 1298# Create a temporary storage location. 1299__shunit_tmpDir=`_shunit_mktempDir` 1300 1301# Provide a public temporary directory for unit test scripts. 1302# TODO(kward): document this. 1303SHUNIT_TMPDIR="${__shunit_tmpDir}/tmp" 1304if ! command mkdir "${SHUNIT_TMPDIR}"; then 1305 _shunit_fatal "error creating SHUNIT_TMPDIR '${SHUNIT_TMPDIR}'" 1306fi 1307 1308# Configure traps to clean up after ourselves. 1309trap '_shunit_cleanup EXIT' 0 1310trap '_shunit_cleanup INT' 2 1311trap '_shunit_cleanup TERM' 15 1312 1313# Create phantom functions to work around issues with Cygwin. 1314_shunit_mktempFunc 1315PATH="${__shunit_tmpDir}:${PATH}" 1316 1317# Make sure phantom functions are executable. This will bite if `/tmp` (or the 1318# current `$TMPDIR`) points to a path on a partition that was mounted with the 1319# 'noexec' option. The noexec command was created with `_shunit_mktempFunc()`. 1320noexec 2>/dev/null || _shunit_fatal \ 1321 'Please declare TMPDIR with path on partition with exec permission.' 1322 1323# We must manually source the tests in standalone mode. 1324if ${__SHUNIT_BUILTIN} [ "${__shunit_mode}" = "${__SHUNIT_MODE_STANDALONE}" ]; then 1325 # shellcheck disable=SC1090 1326 ${__SHUNIT_BUILTIN} . "`_shunit_prepForSourcing \"${__shunit_script}\"`" 1327fi 1328 1329# Configure default output coloring behavior. 1330_shunit_configureColor "${SHUNIT_COLOR}" 1331 1332# Execute the oneTimeSetUp function (if it exists). 1333if ! oneTimeSetUp; then 1334 _shunit_fatal "oneTimeSetUp() returned non-zero return code." 1335fi 1336 1337# Command line selected tests or suite selected tests 1338if ${__SHUNIT_BUILTIN} [ "$#" -ge 2 ]; then 1339 # Argument $1 is either the filename of tests or '--'; either way, skip it. 1340 shift 1341 # Remaining arguments ($2 .. $#) are assumed to be test function names. 1342 # Interate through all remaining args in "$@" in a POSIX (likely portable) way. 1343 # Helpful tip: https://unix.stackexchange.com/questions/314032/how-to-use-arguments-like-1-2-in-a-for-loop 1344 for _shunit_arg_ do 1345 suite_addTest "${_shunit_arg_}" 1346 done 1347 unset _shunit_arg_ 1348else 1349 # Execute the suite function defined in the parent test script. 1350 # DEPRECATED as of 2.1.0. 1351 suite 1352fi 1353 1354# If no tests or suite specified, dynamically build a list of functions. 1355if ${__SHUNIT_BUILTIN} [ -z "${__shunit_suite}" ]; then 1356 shunit_funcs_=`_shunit_extractTestFunctions "${__shunit_script}"` 1357 for shunit_func_ in ${shunit_funcs_}; do 1358 suite_addTest "${shunit_func_}" 1359 done 1360fi 1361unset shunit_func_ shunit_funcs_ 1362 1363# Execute the suite of unit tests. 1364_shunit_execSuite 1365 1366# Execute the oneTimeTearDown function (if it exists). 1367if ! oneTimeTearDown; then 1368 _shunit_fatal "oneTimeTearDown() returned non-zero return code." 1369fi 1370 1371# Generate a report summary. 1372_shunit_generateReport 1373 1374# That's it folks. 1375if ! ${__SHUNIT_BUILTIN} [ "${__shunit_testsFailed}" -eq 0 ]; then 1376 return ${SHUNIT_FALSE} 1377fi 1378