From 3e36512a8948584dfe1dd130c435d6da8334c6d1 Mon Sep 17 00:00:00 2001 From: Douglas Brunk Date: Thu, 5 Dec 2019 14:33:03 -0500 Subject: [PATCH 01/57] Fix eval string handling to handle strings containing single and double quotes. see https://stackoverflow.com/a/48590164 --- shflags | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/shflags b/shflags index 38495e1..6bb34d3 100644 --- a/shflags +++ b/shflags @@ -866,7 +866,7 @@ _flags_parseGetopt() { ;; ${__FLAGS_TYPE_STRING}) - eval "FLAGS_${_flags_usName_}='${_flags_arg_}'" + eval "FLAGS_${_flags_usName_}=\${_flags_arg_}" ;; esac From 943308ff83ab4693658cddac7b87383bfb776d0d Mon Sep 17 00:00:00 2001 From: Douglas Brunk Date: Thu, 5 Dec 2019 14:34:58 -0500 Subject: [PATCH 02/57] Add tests for to handling strings containing single and double quotes. --- shflags_parsing_quotes_test.sh | 86 ++++++++++++++++++++++++++++++++++ 1 file changed, 86 insertions(+) create mode 100755 shflags_parsing_quotes_test.sh diff --git a/shflags_parsing_quotes_test.sh b/shflags_parsing_quotes_test.sh new file mode 100755 index 0000000..157d126 --- /dev/null +++ b/shflags_parsing_quotes_test.sh @@ -0,0 +1,86 @@ +#! /bin/sh +# vim:et:ft=sh:sts=2:sw=2 +# +# shFlags unit test for the flag definition methods +# +# Copyright 2008-2017 Kate Ward. All Rights Reserved. +# Released under the Apache 2.0 license. +# +# Author: kate.ward@forestent.com (Kate Ward) +# https://github.com/kward/shflags +# +### ShellCheck (http://www.shellcheck.net/) +# Disable source following. +# shellcheck disable=SC1090,SC1091 + +# TODO(kward): assert on FLAGS errors +# TODO(kward): testNonStandardIFS() + +# Exit immediately if a pipeline or subshell exits with a non-zero status. +#set -e + +# Treat unset variables as an error. +set -u + +# These variables will be overridden by the test helpers. +returnF="${TMPDIR:-/tmp}/return" +stdoutF="${TMPDIR:-/tmp}/STDOUT" +stderrF="${TMPDIR:-/tmp}/STDERR" + +# Load test helpers. +. ./shflags_test_helpers + + +testStringsWithQuotes() { + _testValidStrings -s "Single Quote Flag's Test" + _testValidStrings -s "Double Quote \"Flag\" Test" + _testValidStrings -s "Mixed Quote's \"Flag\" Test" + _testValidStrings -s 'Mixed Quote'\''s "Flag" Test' +} + +_testValidStrings() +{ + flag=$1 + value=$2 + + FLAGS "${flag}" "${value}" >"${stdoutF}" 2>"${stderrF}" + r3turn=$? + assertTrue "'FLAGS ${flag} ${value}' returned a non-zero result (${r3turn})" \ + ${r3turn} + # shellcheck disable=SC2154 + assertEquals "string (${value}) test failed." "${value}" "${FLAGS_str}" + if [ ${r3turn} -eq "${FLAGS_TRUE}" ]; then + assertFalse 'expected no output to STDERR' "[ -s '${stderrF}' ]" + else + # Validate that an error is thrown for unsupported getopt uses. + assertFatalMsg '.* spaces in options' + fi + th_showOutput ${r3turn} "${stdoutF}" "${stderrF}" +} + + +oneTimeSetUp() { + th_oneTimeSetUp + + if flags_getoptIsStd; then + th_warn 'Standard version of getopt found. Enhanced tests will be skipped.' + else + th_warn 'Enhanced version of getopt found. Standard tests will be skipped.' + fi +} + +setUp() { + DEFINE_boolean bool false 'boolean test' 'b' + DEFINE_float float 0.0 'float test' 'f' + DEFINE_integer int 0 'integer test' 'i' + DEFINE_string str '' 'string test' 's' +} + +tearDown() { + flags_reset +} + +# Load and run shUnit2. +# shellcheck disable=SC2034 +[ -n "${ZSH_VERSION:-}" ] && SHUNIT_PARENT=$0 +. "${TH_SHUNIT}" From 2b84e28d96cf61e3208e8e369dca80a1dd3260fe Mon Sep 17 00:00:00 2001 From: Kate Ward Date: Tue, 11 Feb 2020 04:18:45 +0100 Subject: [PATCH 03/57] Fixed recent shellcheck errors. --- shflags | 5 ++++- shflags_issue_28_test.sh | 4 +++- shflags_private_test.sh | 5 +++++ shflags_public_test.sh | 9 ++++++++- 4 files changed, 20 insertions(+), 3 deletions(-) diff --git a/shflags b/shflags index 6bb34d3..ac1506e 100644 --- a/shflags +++ b/shflags @@ -259,7 +259,10 @@ for __flags_const in ${__flags_constants}; do fi case ${ZSH_VERSION} in [123].*) readonly "${__flags_const}" ;; - *) readonly -g "${__flags_const}" ;; # Declare readonly constants globally. + *) + # Declare readonly constants globally. + # shellcheck disable=SC2039 + readonly -g "${__flags_const}" ;; esac done unset __flags_const __flags_constants diff --git a/shflags_issue_28_test.sh b/shflags_issue_28_test.sh index fbb17d9..69043eb 100755 --- a/shflags_issue_28_test.sh +++ b/shflags_issue_28_test.sh @@ -57,8 +57,9 @@ _testHelp() { assertTrue 'setting FLAGS_HELP did not produce expected result' ${grepped} [ ${grepped} -ne "${FLAGS_TRUE}" ] && th_showOutput - # test that "'" chars work in help string + # Test that "'" chars work in help string. ( + # shellcheck disable=SC2034 DEFINE_boolean b false "help string containing a ' char" b FLAGS "${flag}" >"${stdoutF}" 2>"${stderrF}" ) @@ -73,6 +74,7 @@ mock_flags_columns() { } _doDefines() { + # shellcheck disable=SC2034 DEFINE_boolean 'force' false '' f } diff --git a/shflags_private_test.sh b/shflags_private_test.sh index b80c177..6490a20 100755 --- a/shflags_private_test.sh +++ b/shflags_private_test.sh @@ -49,18 +49,23 @@ mock_getopt_enh() { echo ' --foo --'; return 0; } testGenOptStr() { _testGenOptStr '' '' + # shellcheck disable=SC2034 DEFINE_boolean bool false 'boolean value' b _testGenOptStr 'b' 'bool' + # shellcheck disable=SC2034 DEFINE_float float 0.0 'float value' f _testGenOptStr 'bf:' 'bool,float:' + # shellcheck disable=SC2034 DEFINE_integer int 0 'integer value' i _testGenOptStr 'bf:i:' 'bool,float:,int:' + # shellcheck disable=SC2034 DEFINE_string str 0 'string value' s _testGenOptStr 'bf:i:s:' 'bool,float:,int:,str:' + # shellcheck disable=SC2034 DEFINE_boolean help false 'show help' h _testGenOptStr 'bf:i:s:h' 'bool,float:,int:,str:,help' } diff --git a/shflags_public_test.sh b/shflags_public_test.sh index 779187c..3d4ac90 100755 --- a/shflags_public_test.sh +++ b/shflags_public_test.sh @@ -59,8 +59,9 @@ _testHelp() { assertTrue 'setting FLAGS_HELP did not produce expected result' ${grepped} [ ${grepped} -ne "${FLAGS_TRUE}" ] && th_showOutput - # test that "'" chars work in help string + # Test that "'" chars work in help string. ( + # shellcheck disable=SC2034 DEFINE_boolean b false "help string containing a ' char" b FLAGS "${flag}" >"${stdoutF}" 2>"${stderrF}" ) @@ -116,13 +117,19 @@ EOF } testEnhancedHelpOutput() { + flags_getoptIsEnh || startSkipping + # shellcheck disable=SC2034 DEFINE_boolean test_bool false 'test boolean' b + # shellcheck disable=SC2034 DEFINE_integer test_int 0 'test integer' i + # shellcheck disable=SC2034 DEFINE_string test_str '' 'test string' s + # shellcheck disable=SC2034 DEFINE_string long_desc 'blah' \ 'testing of a long description to force wrap of default value' D + # shellcheck disable=SC2034 DEFINE_string long_default \ 'this_is_a_long_default_value_to_force_alternate_indentation' \ 'testing of long default value' F From 73f27f8aad55ceadb14ced97ab6b09275f6d0176 Mon Sep 17 00:00:00 2001 From: Kate Ward Date: Sun, 29 Mar 2020 15:40:17 +0200 Subject: [PATCH 04/57] Updated from upstream. --- lib/shunit2 | 468 ++++++++++++++++++++++++++++++++++++--------------- lib/versions | 45 +++-- test_runner | 22 ++- 3 files changed, 381 insertions(+), 154 deletions(-) diff --git a/lib/shunit2 b/lib/shunit2 index bdd79e8..0d5ade9 100755 --- a/lib/shunit2 +++ b/lib/shunit2 @@ -1,8 +1,9 @@ #! /bin/sh # vim:et:ft=sh:sts=2:sw=2 # -# Copyright 2008-2018 Kate Ward. All Rights Reserved. +# Copyright 2008-2020 Kate Ward. All Rights Reserved. # Released under the Apache 2.0 license. +# http://www.apache.org/licenses/LICENSE-2.0 # # shUnit2 -- Unit testing framework for Unix shell scripts. # https://github.com/kward/shunit2 @@ -16,12 +17,10 @@ # shellcheck disable=SC2006 # expr may be antiquated, but it is the only solution in some cases. # shellcheck disable=SC2003 -# Commands are purposely escaped so they can be mocked outside shUnit2. -# shellcheck disable=SC1001,SC1012 # Return if shunit2 already loaded. -\[ -n "${SHUNIT_VERSION:-}" ] && exit 0 -SHUNIT_VERSION='2.1.7' +(command [ -n "${SHUNIT_VERSION:-}" ]) && exit 0 +SHUNIT_VERSION='2.1.9pre' # Return values that scripts can use. SHUNIT_TRUE=0 @@ -30,40 +29,45 @@ SHUNIT_ERROR=2 # Logging functions. _shunit_warn() { - echo "${__shunit_ansi_yellow}shunit2:WARN${__shunit_ansi_none} $*" >&2 + ${__SHUNIT_CMD_ECHO_ESC} \ + "${__shunit_ansi_yellow}shunit2:WARN${__shunit_ansi_none} $*" >&2 } _shunit_error() { - echo "${__shunit_ansi_red}shunit2:ERROR${__shunit_ansi_none} $*" >&2 + ${__SHUNIT_CMD_ECHO_ESC} \ + "${__shunit_ansi_red}shunit2:ERROR${__shunit_ansi_none} $*" >&2 } _shunit_fatal() { - echo "${__shunit_ansi_red}shunit2:FATAL${__shunit_ansi_none} $*" >&2 + ${__SHUNIT_CMD_ECHO_ESC} \ + "${__shunit_ansi_red}shunit2:FATAL${__shunit_ansi_none} $*" >&2 exit ${SHUNIT_ERROR} } # Determine some reasonable command defaults. +__SHUNIT_CMD_ECHO_ESC='echo -e' +# shellcheck disable=SC2039 +(command [ "`echo -e test`" = '-e test' ]) && __SHUNIT_CMD_ECHO_ESC='echo' + __SHUNIT_UNAME_S=`uname -s` case "${__SHUNIT_UNAME_S}" in BSD) __SHUNIT_CMD_EXPR='gexpr' ;; *) __SHUNIT_CMD_EXPR='expr' ;; esac - -__SHUNIT_CMD_ECHO_ESC='echo -e' -# shellcheck disable=SC2039 -\[ "`echo -e test`" = '-e test' ] && __SHUNIT_CMD_ECHO_ESC='echo' +__SHUNIT_CMD_TPUT='tput' # Commands a user can override if needed. SHUNIT_CMD_EXPR=${SHUNIT_CMD_EXPR:-${__SHUNIT_CMD_EXPR}} +SHUNIT_CMD_TPUT=${SHUNIT_CMD_TPUT:-${__SHUNIT_CMD_TPUT}} # Enable color output. Options are 'never', 'always', or 'auto'. SHUNIT_COLOR=${SHUNIT_COLOR:-auto} # Specific shell checks. -if \[ -n "${ZSH_VERSION:-}" ]; then +if (command [ -n "${ZSH_VERSION:-}" ]); then setopt |grep "^shwordsplit$" >/dev/null - if \[ $? -ne ${SHUNIT_TRUE} ]; then + if (command [ $? -ne ${SHUNIT_TRUE} ]); then _shunit_fatal 'zsh shwordsplit option is required for proper operation' fi - if \[ -z "${SHUNIT_PARENT:-}" ]; then + if (command [ -z "${SHUNIT_PARENT:-}" ]); then _shunit_fatal "zsh does not pass \$0 through properly. please declare \ \"SHUNIT_PARENT=\$0\" before calling shUnit2" fi @@ -77,6 +81,10 @@ __SHUNIT_MODE_SOURCED='sourced' __SHUNIT_MODE_STANDALONE='standalone' __SHUNIT_PARENT=${SHUNIT_PARENT:-$0} +# User provided test prefix to display in front of the name of the test being +# executed. Define by setting the SHUNIT_TEST_PREFIX variable. +__SHUNIT_TEST_PREFIX=${SHUNIT_TEST_PREFIX:-} + # ANSI colors. __SHUNIT_ANSI_NONE='\033[0m' __SHUNIT_ANSI_RED='\033[1;31m' @@ -89,7 +97,7 @@ __shunit_constants=`set |grep '^__SHUNIT_' |cut -d= -f1` echo "${__shunit_constants}" |grep '^Binary file' >/dev/null && \ __shunit_constants=`set |grep -a '^__SHUNIT_' |cut -d= -f1` for __shunit_const in ${__shunit_constants}; do - if \[ -z "${ZSH_VERSION:-}" ]; then + if (command [ -z "${ZSH_VERSION:-}" ]); then readonly "${__shunit_const}" else case ${ZSH_VERSION} in @@ -111,6 +119,7 @@ __shunit_reportGenerated=${SHUNIT_FALSE} # Is report generated. __shunit_script='' # Filename of unittest script (standalone mode). __shunit_skip=${SHUNIT_FALSE} # Is skipping enabled. __shunit_suite='' # Suite of tests to execute. +__shunit_clean=${SHUNIT_FALSE} # _shunit_cleanup() was already called. # ANSI colors (populated by _shunit_configureColor()). __shunit_ansi_none='' @@ -136,7 +145,7 @@ __shunit_assertsSkipped=0 # # shellcheck disable=SC2016,SC2089 -_SHUNIT_LINENO_='eval __shunit_lineno=""; if \[ "${1:-}" = "--lineno" ]; then \[ -n "$2" ] && __shunit_lineno="[$2] "; shift 2; fi' +_SHUNIT_LINENO_='eval __shunit_lineno=""; if (command [ "${1:-}" = "--lineno" ]); then (command [ -n "$2" ]) && __shunit_lineno="[$2] "; shift 2; fi' #----------------------------------------------------------------------------- # Assertion functions. @@ -153,7 +162,7 @@ _SHUNIT_LINENO_='eval __shunit_lineno=""; if \[ "${1:-}" = "--lineno" ]; then \[ assertEquals() { # shellcheck disable=SC2090 ${_SHUNIT_LINENO_} - if \[ $# -lt 2 -o $# -gt 3 ]; then + if (command [ $# -lt 2 -o $# -gt 3 ]); then _shunit_error "assertEquals() requires two or three arguments; $# given" _shunit_assertFail return ${SHUNIT_ERROR} @@ -161,7 +170,7 @@ assertEquals() { _shunit_shouldSkip && return ${SHUNIT_TRUE} shunit_message_=${__shunit_lineno} - if \[ $# -eq 3 ]; then + if (command [ $# -eq 3 ]); then shunit_message_="${shunit_message_}$1" shift fi @@ -169,7 +178,7 @@ assertEquals() { shunit_actual_=$2 shunit_return=${SHUNIT_TRUE} - if \[ "${shunit_expected_}" = "${shunit_actual_}" ]; then + if (command [ "${shunit_expected_}" = "${shunit_actual_}" ]); then _shunit_assertPass else failNotEquals "${shunit_message_}" "${shunit_expected_}" "${shunit_actual_}" @@ -193,7 +202,7 @@ _ASSERT_EQUALS_='eval assertEquals --lineno "${LINENO:-}"' assertNotEquals() { # shellcheck disable=SC2090 ${_SHUNIT_LINENO_} - if \[ $# -lt 2 -o $# -gt 3 ]; then + if (command [ $# -lt 2 -o $# -gt 3 ]); then _shunit_error "assertNotEquals() requires two or three arguments; $# given" _shunit_assertFail return ${SHUNIT_ERROR} @@ -201,7 +210,7 @@ assertNotEquals() { _shunit_shouldSkip && return ${SHUNIT_TRUE} shunit_message_=${__shunit_lineno} - if \[ $# -eq 3 ]; then + if (command [ $# -eq 3 ]); then shunit_message_="${shunit_message_}$1" shift fi @@ -209,10 +218,10 @@ assertNotEquals() { shunit_actual_=$2 shunit_return=${SHUNIT_TRUE} - if \[ "${shunit_expected_}" != "${shunit_actual_}" ]; then + if (command [ "${shunit_expected_}" != "${shunit_actual_}" ]); then _shunit_assertPass else - failSame "${shunit_message_}" "$@" + failSame "${shunit_message_}" "${shunit_expected_}" "${shunit_actual_}" shunit_return=${SHUNIT_FALSE} fi @@ -222,6 +231,86 @@ assertNotEquals() { # shellcheck disable=SC2016,SC2034 _ASSERT_NOT_EQUALS_='eval assertNotEquals --lineno "${LINENO:-}"' +# Assert that a container contains a content. +# +# Args: +# message: string: failure message [optional] +# container: string: container to analyze +# content: string: content to find +# Returns: +# integer: success (TRUE/FALSE/ERROR constant) +assertContains() { + # shellcheck disable=SC2090 + ${_SHUNIT_LINENO_} + if (command [ $# -lt 2 -o $# -gt 3 ]); then + _shunit_error "assertContains() requires two or three arguments; $# given" + _shunit_assertFail + return ${SHUNIT_ERROR} + fi + _shunit_shouldSkip && return ${SHUNIT_TRUE} + + shunit_message_=${__shunit_lineno} + if (command [ $# -eq 3 ]); then + shunit_message_="${shunit_message_}$1" + shift + fi + shunit_container_=$1 + shunit_content_=$2 + + shunit_return=${SHUNIT_TRUE} + if echo "$shunit_container_" | grep -F -- "$shunit_content_" > /dev/null; then + _shunit_assertPass + else + failNotFound "${shunit_message_}" "${shunit_content_}" + shunit_return=${SHUNIT_FALSE} + fi + + unset shunit_message_ shunit_container_ shunit_content_ + return ${shunit_return} +} +# shellcheck disable=SC2016,SC2034 +_ASSERT_CONTAINS_='eval assertContains --lineno "${LINENO:-}"' + +# Assert that a container does not contain a content. +# +# Args: +# message: string: failure message [optional] +# container: string: container to analyze +# content: string: content to look for +# Returns: +# integer: success (TRUE/FALSE/ERROR constant) +assertNotContains() { + # shellcheck disable=SC2090 + ${_SHUNIT_LINENO_} + if (command [ $# -lt 2 -o $# -gt 3 ]); then + _shunit_error "assertNotContains() requires two or three arguments; $# given" + _shunit_assertFail + return ${SHUNIT_ERROR} + fi + _shunit_shouldSkip && return ${SHUNIT_TRUE} + + shunit_message_=${__shunit_lineno} + if (command [ $# -eq 3 ]); then + shunit_message_="${shunit_message_}$1" + shift + fi + shunit_container_=$1 + shunit_content_=$2 + + shunit_return=${SHUNIT_TRUE} + if echo "$shunit_container_" | grep -F -- "$shunit_content_" > /dev/null; then + failFound "${shunit_message_}" "${shunit_content_}" + shunit_return=${SHUNIT_FALSE} + else + _shunit_assertPass + fi + + unset shunit_message_ shunit_container_ shunit_content_ + return ${shunit_return} +} +# shellcheck disable=SC2016,SC2034 +_ASSERT_NOT_CONTAINS_='eval assertNotContains --lineno "${LINENO:-}"' + # Assert that a value is null (i.e. an empty string) # # Args: @@ -232,7 +321,7 @@ _ASSERT_NOT_EQUALS_='eval assertNotEquals --lineno "${LINENO:-}"' assertNull() { # shellcheck disable=SC2090 ${_SHUNIT_LINENO_} - if \[ $# -lt 1 -o $# -gt 2 ]; then + if (command [ $# -lt 1 -o $# -gt 2 ]); then _shunit_error "assertNull() requires one or two arguments; $# given" _shunit_assertFail return ${SHUNIT_ERROR} @@ -240,7 +329,7 @@ assertNull() { _shunit_shouldSkip && return ${SHUNIT_TRUE} shunit_message_=${__shunit_lineno} - if \[ $# -eq 2 ]; then + if (command [ $# -eq 2 ]); then shunit_message_="${shunit_message_}$1" shift fi @@ -263,7 +352,8 @@ _ASSERT_NULL_='eval assertNull --lineno "${LINENO:-}"' assertNotNull() { # shellcheck disable=SC2090 ${_SHUNIT_LINENO_} - if \[ $# -gt 2 ]; then # allowing 0 arguments as $1 might actually be null + if (command [ $# -gt 2 ]); then + # Allowing 0 arguments as $1 might actually be null. _shunit_error "assertNotNull() requires one or two arguments; $# given" _shunit_assertFail return ${SHUNIT_ERROR} @@ -271,7 +361,7 @@ assertNotNull() { _shunit_shouldSkip && return ${SHUNIT_TRUE} shunit_message_=${__shunit_lineno} - if \[ $# -eq 2 ]; then + if (command [ $# -eq 2 ]); then shunit_message_="${shunit_message_}$1" shift fi @@ -297,7 +387,7 @@ _ASSERT_NOT_NULL_='eval assertNotNull --lineno "${LINENO:-}"' assertSame() { # shellcheck disable=SC2090 ${_SHUNIT_LINENO_} - if \[ $# -lt 2 -o $# -gt 3 ]; then + if (command [ $# -lt 2 -o $# -gt 3 ]); then _shunit_error "assertSame() requires two or three arguments; $# given" _shunit_assertFail return ${SHUNIT_ERROR} @@ -305,7 +395,7 @@ assertSame() { _shunit_shouldSkip && return ${SHUNIT_TRUE} shunit_message_=${__shunit_lineno} - if \[ $# -eq 3 ]; then + if (command [ $# -eq 3 ]); then shunit_message_="${shunit_message_}$1" shift fi @@ -329,7 +419,7 @@ _ASSERT_SAME_='eval assertSame --lineno "${LINENO:-}"' assertNotSame() { # shellcheck disable=SC2090 ${_SHUNIT_LINENO_} - if \[ $# -lt 2 -o $# -gt 3 ]; then + if (command [ $# -lt 2 -o $# -gt 3 ]); then _shunit_error "assertNotSame() requires two or three arguments; $# given" _shunit_assertFail return ${SHUNIT_ERROR} @@ -337,7 +427,7 @@ assertNotSame() { _shunit_shouldSkip && return ${SHUNIT_TRUE} shunit_message_=${__shunit_lineno} - if \[ $# -eq 3 ]; then + if (command [ $# -eq 3 ]); then shunit_message_="${shunit_message_:-}$1" shift fi @@ -374,7 +464,7 @@ _ASSERT_NOT_SAME_='eval assertNotSame --lineno "${LINENO:-}"' assertTrue() { # shellcheck disable=SC2090 ${_SHUNIT_LINENO_} - if \[ $# -lt 1 -o $# -gt 2 ]; then + if (command [ $# -lt 1 -o $# -gt 2 ]); then _shunit_error "assertTrue() takes one or two arguments; $# given" _shunit_assertFail return ${SHUNIT_ERROR} @@ -382,30 +472,30 @@ assertTrue() { _shunit_shouldSkip && return ${SHUNIT_TRUE} shunit_message_=${__shunit_lineno} - if \[ $# -eq 2 ]; then + if (command [ $# -eq 2 ]); then shunit_message_="${shunit_message_}$1" shift fi shunit_condition_=$1 # See if condition is an integer, i.e. a return value. - shunit_match_=`expr "${shunit_condition_}" : '\([0-9]*\)'` shunit_return=${SHUNIT_TRUE} - if \[ -z "${shunit_condition_}" ]; then + shunit_match_=`expr "${shunit_condition_}" : '\([0-9]*\)'` + if (command [ -z "${shunit_condition_}" ]); then # Null condition. shunit_return=${SHUNIT_FALSE} - elif \[ -n "${shunit_match_}" -a "${shunit_condition_}" = "${shunit_match_}" ] + elif (command [ -n "${shunit_match_}" -a "${shunit_condition_}" = "${shunit_match_}" ]) then # Possible return value. Treating 0 as true, and non-zero as false. - \[ "${shunit_condition_}" -ne 0 ] && shunit_return=${SHUNIT_FALSE} + (command [ "${shunit_condition_}" -ne 0 ]) && shunit_return=${SHUNIT_FALSE} else # Hopefully... a condition. ( eval "${shunit_condition_}" ) >/dev/null 2>&1 - \[ $? -ne 0 ] && shunit_return=${SHUNIT_FALSE} + (command [ $? -ne 0 ]) && shunit_return=${SHUNIT_FALSE} fi # Record the test. - if \[ ${shunit_return} -eq ${SHUNIT_TRUE} ]; then + if (command [ ${shunit_return} -eq ${SHUNIT_TRUE} ]); then _shunit_assertPass else _shunit_assertFail "${shunit_message_}" @@ -441,15 +531,15 @@ _ASSERT_TRUE_='eval assertTrue --lineno "${LINENO:-}"' assertFalse() { # shellcheck disable=SC2090 ${_SHUNIT_LINENO_} - if \[ $# -lt 1 -o $# -gt 2 ]; then - _shunit_error "assertFalse() quires one or two arguments; $# given" + if (command [ $# -lt 1 -o $# -gt 2 ]); then + _shunit_error "assertFalse() requires one or two arguments; $# given" _shunit_assertFail return ${SHUNIT_ERROR} fi _shunit_shouldSkip && return ${SHUNIT_TRUE} shunit_message_=${__shunit_lineno} - if \[ $# -eq 2 ]; then + if (command [ $# -eq 2 ]); then shunit_message_="${shunit_message_}$1" shift fi @@ -458,21 +548,21 @@ assertFalse() { # See if condition is an integer, i.e. a return value. shunit_match_=`expr "${shunit_condition_}" : '\([0-9]*\)'` shunit_return=${SHUNIT_TRUE} - if \[ -z "${shunit_condition_}" ]; then + if (command [ -z "${shunit_condition_}" ]); then # Null condition. shunit_return=${SHUNIT_FALSE} - elif \[ -n "${shunit_match_}" -a "${shunit_condition_}" = "${shunit_match_}" ] + elif (command [ -n "${shunit_match_}" -a "${shunit_condition_}" = "${shunit_match_}" ]) then # Possible return value. Treating 0 as true, and non-zero as false. - \[ "${shunit_condition_}" -eq 0 ] && shunit_return=${SHUNIT_FALSE} + (command [ "${shunit_condition_}" -eq 0 ]) && shunit_return=${SHUNIT_FALSE} else # Hopefully... a condition. ( eval "${shunit_condition_}" ) >/dev/null 2>&1 - \[ $? -eq 0 ] && shunit_return=${SHUNIT_FALSE} + (command [ $? -eq 0 ]) && shunit_return=${SHUNIT_FALSE} fi # Record the test. - if \[ "${shunit_return}" -eq "${SHUNIT_TRUE}" ]; then + if (command [ "${shunit_return}" -eq "${SHUNIT_TRUE}" ]); then _shunit_assertPass else _shunit_assertFail "${shunit_message_}" @@ -497,14 +587,14 @@ _ASSERT_FALSE_='eval assertFalse --lineno "${LINENO:-}"' fail() { # shellcheck disable=SC2090 ${_SHUNIT_LINENO_} - if \[ $# -gt 1 ]; then + if (command [ $# -gt 1 ]); then _shunit_error "fail() requires zero or one arguments; $# given" return ${SHUNIT_ERROR} fi _shunit_shouldSkip && return ${SHUNIT_TRUE} shunit_message_=${__shunit_lineno} - if \[ $# -eq 1 ]; then + if (command [ $# -eq 1 ]); then shunit_message_="${shunit_message_}$1" shift fi @@ -528,20 +618,21 @@ _FAIL_='eval fail --lineno "${LINENO:-}"' failNotEquals() { # shellcheck disable=SC2090 ${_SHUNIT_LINENO_} - if \[ $# -lt 2 -o $# -gt 3 ]; then + if (command [ $# -lt 2 -o $# -gt 3 ]); then _shunit_error "failNotEquals() requires one or two arguments; $# given" return ${SHUNIT_ERROR} fi _shunit_shouldSkip && return ${SHUNIT_TRUE} shunit_message_=${__shunit_lineno} - if \[ $# -eq 3 ]; then + if (command [ $# -eq 3 ]); then shunit_message_="${shunit_message_}$1" shift fi shunit_expected_=$1 shunit_actual_=$2 + shunit_message_=${shunit_message_%% } _shunit_assertFail "${shunit_message_:+${shunit_message_} }expected:<${shunit_expected_}> but was:<${shunit_actual_}>" unset shunit_message_ shunit_expected_ shunit_actual_ @@ -550,6 +641,69 @@ failNotEquals() { # shellcheck disable=SC2016,SC2034 _FAIL_NOT_EQUALS_='eval failNotEquals --lineno "${LINENO:-}"' +# Records a test failure, stating a value was found. +# +# Args: +# message: string: failure message [optional] +# content: string: found value +# Returns: +# integer: success (TRUE/FALSE/ERROR constant) +failFound() { + # shellcheck disable=SC2090 + ${_SHUNIT_LINENO_} + if (command [ $# -lt 1 -o $# -gt 2 ]); then + _shunit_error "failFound() requires one or two arguments; $# given" + return ${SHUNIT_ERROR} + fi + _shunit_shouldSkip && return ${SHUNIT_TRUE} + + shunit_message_=${__shunit_lineno} + if (command [ $# -eq 2 ]); then + shunit_message_="${shunit_message_}$1" + shift + fi + + shunit_message_=${shunit_message_%% } + _shunit_assertFail "${shunit_message_:+${shunit_message_} }Found" + + unset shunit_message_ + return ${SHUNIT_FALSE} +} +# shellcheck disable=SC2016,SC2034 +_FAIL_FOUND_='eval failFound --lineno "${LINENO:-}"' + +# Records a test failure, stating a content was not found. +# +# Args: +# message: string: failure message [optional] +# content: string: content not found +# Returns: +# integer: success (TRUE/FALSE/ERROR constant) +failNotFound() { + # shellcheck disable=SC2090 + ${_SHUNIT_LINENO_} + if (command [ $# -lt 1 -o $# -gt 2 ]); then + _shunit_error "failNotFound() requires one or two arguments; $# given" + return ${SHUNIT_ERROR} + fi + _shunit_shouldSkip && return ${SHUNIT_TRUE} + + shunit_message_=${__shunit_lineno} + if (command [ $# -eq 2 ]); then + shunit_message_="${shunit_message_}$1" + shift + fi + shunit_content_=$1 + + shunit_message_=${shunit_message_%% } + _shunit_assertFail "${shunit_message_:+${shunit_message_} }Not found:<${shunit_content_}>" + + unset shunit_message_ shunit_content_ + return ${SHUNIT_FALSE} +} +# shellcheck disable=SC2016,SC2034 +_FAIL_NOT_FOUND_='eval failNotFound --lineno "${LINENO:-}"' + # Records a test failure, stating two values should have been the same. # # Args: @@ -562,18 +716,19 @@ failSame() { # shellcheck disable=SC2090 ${_SHUNIT_LINENO_} - if \[ $# -lt 2 -o $# -gt 3 ]; then + if (command [ $# -lt 2 -o $# -gt 3 ]); then _shunit_error "failSame() requires two or three arguments; $# given" return ${SHUNIT_ERROR} fi _shunit_shouldSkip && return ${SHUNIT_TRUE} shunit_message_=${__shunit_lineno} - if \[ $# -eq 3 ]; then + if (command [ $# -eq 3 ]); then shunit_message_="${shunit_message_}$1" shift fi + shunit_message_=${shunit_message_%% } _shunit_assertFail "${shunit_message_:+${shunit_message_} }expected not same" unset shunit_message_ @@ -595,14 +750,14 @@ _FAIL_SAME_='eval failSame --lineno "${LINENO:-}"' failNotSame() { # shellcheck disable=SC2090 ${_SHUNIT_LINENO_} - if \[ $# -lt 2 -o $# -gt 3 ]; then - _shunit_error "failNotEquals() requires one or two arguments; $# given" + if (command [ $# -lt 2 -o $# -gt 3 ]); then + _shunit_error "failNotSame() requires one or two arguments; $# given" return ${SHUNIT_ERROR} fi _shunit_shouldSkip && return ${SHUNIT_TRUE} shunit_message_=${__shunit_lineno} - if \[ $# -eq 3 ]; then + if (command [ $# -eq 3 ]); then shunit_message_="${shunit_message_}$1" shift fi @@ -746,10 +901,10 @@ _shunit_mktempDir() { # The standard `mktemp` didn't work. Use our own. # shellcheck disable=SC2039 - if \[ -r '/dev/urandom' -a -x '/usr/bin/od' ]; then + if (command [ -r '/dev/urandom' -a -x '/usr/bin/od' ]); then _shunit_random_=`/usr/bin/od -vAn -N4 -tx4 "${_shunit_file_}" + command cat <"${_shunit_file_}" #! /bin/sh exit ${SHUNIT_TRUE} EOF - \chmod +x "${_shunit_file_}" + command chmod +x "${_shunit_file_}" done unset _shunit_file_ @@ -795,28 +950,37 @@ EOF _shunit_cleanup() { _shunit_name_=$1 - case ${_shunit_name_} in - EXIT) _shunit_signal_=0 ;; - INT) _shunit_signal_=2 ;; - TERM) _shunit_signal_=15 ;; + case "${_shunit_name_}" in + EXIT) ;; + INT) _shunit_signal_=130 ;; # 2+128 + TERM) _shunit_signal_=143 ;; # 15+128 *) _shunit_error "unrecognized trap value (${_shunit_name_})" _shunit_signal_=0 ;; esac + if (command [ "${_shunit_name_}" != 'EXIT' ]); then + _shunit_warn "trapped and now handling the (${_shunit_name_}) signal" + fi # Do our work. - \rm -fr "${__shunit_tmpDir}" + if (command [ ${__shunit_clean} -eq ${SHUNIT_FALSE} ]); then + # Ensure tear downs are only called once. + __shunit_clean=${SHUNIT_TRUE} - # Exit for all non-EXIT signals. - if \[ "${_shunit_name_}" != 'EXIT' ]; then - _shunit_warn "trapped and now handling the (${_shunit_name_}) signal" - # Disable EXIT trap. - trap 0 - # Add 128 to signal and exit. - exit "`expr "${_shunit_signal_}" + 128`" - elif \[ ${__shunit_reportGenerated} -eq ${SHUNIT_FALSE} ] ; then - _shunit_assertFail 'Unknown failure encountered running a test' + tearDown || _shunit_warn 'tearDown() returned non-zero return code.' + oneTimeTearDown || \ + _shunit_warn 'oneTimeTearDown() returned non-zero return code.' + + command rm -fr "${__shunit_tmpDir}" + fi + + if (command [ "${_shunit_name_}" != 'EXIT' ]); then + # Handle all non-EXIT signals. + trap - 0 # Disable EXIT trap. + exit ${_shunit_signal_} + elif (command [ ${__shunit_reportGenerated} -eq ${SHUNIT_FALSE} ]); then + _shunit_assertFail 'unknown failure encountered running a test' _shunit_generateReport exit ${SHUNIT_ERROR} fi @@ -824,7 +988,7 @@ _shunit_cleanup() { unset _shunit_name_ _shunit_signal_ } -# configureOutput based on user preferences, e.g. color. +# configureColor based on user color preference. # # Args: # color: string: color mode (one of `always`, `auto`, or `none`). @@ -833,15 +997,10 @@ _shunit_configureColor() { case $1 in 'always') _shunit_color_=${SHUNIT_TRUE} ;; 'auto') - ( exec tput >/dev/null 2>&1 ) # Check for existence of tput command. - if [ $? -lt 127 ]; then - _shunit_tput_=`tput colors` - # shellcheck disable=SC2166,SC2181 - [ $? -eq 0 -a "${_shunit_tput_}" -ge 16 ] && _shunit_color_=${SHUNIT_TRUE} - fi + (command [ "`_shunit_colors`" -ge 8 ]) && _shunit_color_=${SHUNIT_TRUE} ;; 'none') ;; - *) _shunit_fatal "unrecognized SHUNIT_COLOR option '${SHUNIT_COLOR}'" ;; + *) _shunit_fatal "unrecognized color option '$1'" ;; esac case ${_shunit_color_} in @@ -864,6 +1023,17 @@ _shunit_configureColor() { unset _shunit_color_ _shunit_tput_ } +# colors returns the number of supported colors for the TERM. +_shunit_colors() { + _shunit_tput_=`${SHUNIT_CMD_TPUT} colors 2>/dev/null` + if (command [ $? -eq 0 ]); then + echo "${_shunit_tput_}" + else + echo 16 + fi + unset _shunit_tput_ +} + # The actual running of the tests happens here. # # Args: @@ -872,21 +1042,26 @@ _shunit_execSuite() { for _shunit_test_ in ${__shunit_suite}; do __shunit_testSuccess=${SHUNIT_TRUE} - # disable skipping + # Disable skipping. endSkipping - # execute the per-test setup function - setUp + # Execute the per-test setup function. + setUp || _shunit_fatal "setup() returned non-zero return code." - # execute the test - echo "${_shunit_test_}" + # Execute the test. + echo "${__SHUNIT_TEST_PREFIX}${_shunit_test_}" eval "${_shunit_test_}" + if (command [ $? -ne ${SHUNIT_TRUE} ]); then + _shunit_error "${_shunit_test_}() returned non-zero return code." + __shunit_testSuccess=${SHUNIT_ERROR} + _shunit_incFailedCount + fi - # execute the per-test tear-down function - tearDown + # Execute the per-test tear-down function. + tearDown || _shunit_fatal "tearDown() returned non-zero return code." - # update stats - if \[ ${__shunit_testSuccess} -eq ${SHUNIT_TRUE} ]; then + # Update stats. + if (command [ ${__shunit_testSuccess} -eq ${SHUNIT_TRUE} ]); then __shunit_testsPassed=`expr ${__shunit_testsPassed} + 1` else __shunit_testsFailed=`expr ${__shunit_testsFailed} + 1` @@ -903,37 +1078,32 @@ _shunit_execSuite() { # Output: # string: the report of successful and failed tests, as well as totals. _shunit_generateReport() { + (command [ "${__shunit_reportGenerated}" -eq ${SHUNIT_TRUE} ]) && return + _shunit_ok_=${SHUNIT_TRUE} - # If no exit code was provided one, determine an appropriate one. - \[ "${__shunit_testsFailed}" -gt 0 \ - -o ${__shunit_testSuccess} -eq ${SHUNIT_FALSE} ] \ + # If no exit code was provided, determine an appropriate one. + (command [ "${__shunit_testsFailed}" -gt 0 \ + -o ${__shunit_testSuccess} -eq ${SHUNIT_FALSE} ]) \ && _shunit_ok_=${SHUNIT_FALSE} echo _shunit_msg_="Ran ${__shunit_ansi_cyan}${__shunit_testsTotal}${__shunit_ansi_none}" - if \[ "${__shunit_testsTotal}" -eq 1 ]; then + if (command [ "${__shunit_testsTotal}" -eq 1 ]); then ${__SHUNIT_CMD_ECHO_ESC} "${_shunit_msg_} test." else ${__SHUNIT_CMD_ECHO_ESC} "${_shunit_msg_} tests." fi - _shunit_failures_='' - _shunit_skipped_='' - \[ ${__shunit_assertsFailed} -gt 0 ] \ - && _shunit_failures_="failures=${__shunit_assertsFailed}" - \[ ${__shunit_assertsSkipped} -gt 0 ] \ - && _shunit_skipped_="skipped=${__shunit_assertsSkipped}" - - if \[ ${_shunit_ok_} -eq ${SHUNIT_TRUE} ]; then + if (command [ ${_shunit_ok_} -eq ${SHUNIT_TRUE} ]); then _shunit_msg_="${__shunit_ansi_green}OK${__shunit_ansi_none}" - \[ -n "${_shunit_skipped_}" ] \ - && _shunit_msg_="${_shunit_msg_} (${__shunit_ansi_yellow}${_shunit_skipped_}${__shunit_ansi_none})" + (command [ "${__shunit_assertsSkipped}" -gt 0 ]) \ + && _shunit_msg_="${_shunit_msg_} (${__shunit_ansi_yellow}skipped=${__shunit_assertsSkipped}${__shunit_ansi_none})" else _shunit_msg_="${__shunit_ansi_red}FAILED${__shunit_ansi_none}" - _shunit_msg_="${_shunit_msg_} (${__shunit_ansi_red}${_shunit_failures_}${__shunit_ansi_none}" - \[ -n "${_shunit_skipped_}" ] \ - && _shunit_msg_="${_shunit_msg_},${__shunit_ansi_yellow}${_shunit_skipped_}${__shunit_ansi_none}" + _shunit_msg_="${_shunit_msg_} (${__shunit_ansi_red}failures=${__shunit_assertsFailed}${__shunit_ansi_none}" + (command [ "${__shunit_assertsSkipped}" -gt 0 ]) \ + && _shunit_msg_="${_shunit_msg_},${__shunit_ansi_yellow}skipped=${__shunit_assertsSkipped}${__shunit_ansi_none}" _shunit_msg_="${_shunit_msg_})" fi @@ -941,7 +1111,7 @@ _shunit_generateReport() { ${__SHUNIT_CMD_ECHO_ESC} "${_shunit_msg_}" __shunit_reportGenerated=${SHUNIT_TRUE} - unset _shunit_failures_ _shunit_msg_ _shunit_ok_ _shunit_skipped_ + unset _shunit_msg_ _shunit_ok_ } # Test for whether a function should be skipped. @@ -951,7 +1121,7 @@ _shunit_generateReport() { # Returns: # boolean: whether the test should be skipped (TRUE/FALSE constant) _shunit_shouldSkip() { - \[ ${__shunit_skip} -eq ${SHUNIT_FALSE} ] && return ${SHUNIT_FALSE} + (command [ ${__shunit_skip} -eq ${SHUNIT_FALSE} ]) && return ${SHUNIT_FALSE} _shunit_assertSkip } @@ -970,13 +1140,22 @@ _shunit_assertPass() { # message: string: failure message to provide user _shunit_assertFail() { __shunit_testSuccess=${SHUNIT_FALSE} - __shunit_assertsFailed=`expr "${__shunit_assertsFailed}" + 1` - __shunit_assertsTotal=`expr "${__shunit_assertsTotal}" + 1` + _shunit_incFailedCount \[ $# -gt 0 ] && ${__SHUNIT_CMD_ECHO_ESC} \ "${__shunit_ansi_red}ASSERT:${__shunit_ansi_none}$*" } +# Increment the count of failed asserts. +# +# Args: +# none +_shunit_incFailedCount() { + __shunit_assertsFailed=`expr "${__shunit_assertsFailed}" + 1` + __shunit_assertsTotal=`expr "${__shunit_assertsTotal}" + 1` +} + + # Records a skipped test. # # Args: @@ -1009,17 +1188,16 @@ _shunit_prepForSourcing() { # Returns: # string: with escaped character(s) _shunit_escapeCharInStr() { - \[ -n "$2" ] || return # No point in doing work on an empty string. + (command [ -n "$2" ]) || return # No point in doing work on an empty string. # Note: using shorter variable names to prevent conflicts with # _shunit_escapeCharactersInString(). _shunit_c_=$1 _shunit_s_=$2 - # Escape the character. # shellcheck disable=SC1003,SC2086 - echo ''${_shunit_s_}'' |sed 's/\'${_shunit_c_}'/\\\'${_shunit_c_}'/g' + echo ''${_shunit_s_}'' |command sed 's/\'${_shunit_c_}'/\\\'${_shunit_c_}'/g' unset _shunit_c_ _shunit_s_ } @@ -1031,7 +1209,7 @@ _shunit_escapeCharInStr() { # Returns: # string: with escaped character(s) _shunit_escapeCharactersInString() { - \[ -n "$1" ] || return # No point in doing work on an empty string. + (command [ -n "$1" ]) || return # No point in doing work on an empty string. _shunit_str_=$1 @@ -1056,10 +1234,10 @@ _shunit_extractTestFunctions() { # Extract the lines with test function names, strip of anything besides the # function name, and output everything on a single line. - _shunit_regex_='^[ ]*(function )*test[A-Za-z0-9_]* *\(\)' + _shunit_regex_='^\s*((function test[A-Za-z0-9_-]*)|(test[A-Za-z0-9_-]* *\(\)))' # shellcheck disable=SC2196 egrep "${_shunit_regex_}" "${_shunit_script_}" \ - |sed 's/^[^A-Za-z0-9_]*//;s/^function //;s/\([A-Za-z0-9_]*\).*/\1/g' \ + |command sed 's/^[^A-Za-z0-9_-]*//;s/^function //;s/\([A-Za-z0-9_-]*\).*/\1/g' \ |xargs unset _shunit_regex_ _shunit_script_ @@ -1070,12 +1248,12 @@ _shunit_extractTestFunctions() { # # Determine the operating mode. -if \[ $# -eq 0 ]; then +if (command [ $# -eq 0 -o "${1:-}" = '--' ]); then __shunit_script=${__SHUNIT_PARENT} __shunit_mode=${__SHUNIT_MODE_SOURCED} else __shunit_script=$1 - \[ -r "${__shunit_script}" ] || \ + (command [ -r "${__shunit_script}" ]) || \ _shunit_fatal "unable to read from ${__shunit_script}" __shunit_mode=${__SHUNIT_MODE_STANDALONE} fi @@ -1086,7 +1264,7 @@ __shunit_tmpDir=`_shunit_mktempDir` # Provide a public temporary directory for unit test scripts. # TODO(kward): document this. SHUNIT_TMPDIR="${__shunit_tmpDir}/tmp" -\mkdir "${SHUNIT_TMPDIR}" +command mkdir "${SHUNIT_TMPDIR}" # Setup traps to clean up after ourselves. trap '_shunit_cleanup EXIT' 0 @@ -1104,23 +1282,37 @@ noexec 2>/dev/null || _shunit_fatal \ 'Please declare TMPDIR with path on partition with exec permission.' # We must manually source the tests in standalone mode. -if \[ "${__shunit_mode}" = "${__SHUNIT_MODE_STANDALONE}" ]; then +if (command [ "${__shunit_mode}" = "${__SHUNIT_MODE_STANDALONE}" ]); then # shellcheck disable=SC1090 - . "`_shunit_prepForSourcing \"${__shunit_script}\"`" + command . "`_shunit_prepForSourcing \"${__shunit_script}\"`" fi # Configure default output coloring behavior. _shunit_configureColor "${SHUNIT_COLOR}" # Execute the oneTimeSetUp function (if it exists). -oneTimeSetUp - -# Execute the suite function defined in the parent test script. -# DEPRECATED as of 2.1.0. -suite +oneTimeSetUp || \ + _shunit_fatal "oneTimeSetUp() returned non-zero return code." + +# Command line selected tests or suite selected tests +if (command [ "$#" -ge 2 ]); then + # Argument $1 is either the filename of tests or '--'; either way, skip it. + shift + # Remaining arguments ($2 .. $#) are assumed to be test function names. + # Interate through all remaining args in "$@" in a POSIX (likely portable) way. + # Helpful tip: https://unix.stackexchange.com/questions/314032/how-to-use-arguments-like-1-2-in-a-for-loop + for _shunit_arg_ do + suite_addTest "${_shunit_arg_}" + done + unset _shunit_arg_ +else + # Execute the suite function defined in the parent test script. + # DEPRECATED as of 2.1.0. + suite +fi -# If no suite function was defined, dynamically build a list of functions. -if \[ -z "${__shunit_suite}" ]; then +# If no tests or suite specified, dynamically build a list of functions. +if (command [ -z "${__shunit_suite}" ]); then shunit_funcs_=`_shunit_extractTestFunctions "${__shunit_script}"` for shunit_func_ in ${shunit_funcs_}; do suite_addTest "${shunit_func_}" @@ -1128,10 +1320,16 @@ if \[ -z "${__shunit_suite}" ]; then fi unset shunit_func_ shunit_funcs_ +# Execute the suite of unit tests. _shunit_execSuite -oneTimeTearDown + +# Execute the oneTimeTearDown function (if it exists). +oneTimeTearDown || \ + _shunit_fatal "oneTimeTearDown() returned non-zero return code." + +# Generate a report summary. _shunit_generateReport # That's it folks. -\[ "${__shunit_testsFailed}" -eq 0 ] +(command [ "${__shunit_testsFailed}" -eq 0 ]) exit $? diff --git a/lib/versions b/lib/versions index 7c3badd..b5533ab 100755 --- a/lib/versions +++ b/lib/versions @@ -3,7 +3,7 @@ # # Versions determines the versions of all installed shells. # -# Copyright 2008-2018 Kate Ward. All Rights Reserved. +# Copyright 2008-2020 Kate Ward. All Rights Reserved. # Released under the Apache 2.0 License. # # Author: kate.ward@forestent.com (Kate Ward) @@ -18,7 +18,7 @@ ARGV0=`basename "$0"` LSB_RELEASE='/etc/lsb-release' -VERSIONS_SHELLS='ash /bin/bash /bin/dash /bin/ksh /bin/pdksh /bin/zsh /bin/sh /usr/xpg4/bin/sh /sbin/sh' +VERSIONS_SHELLS='ash /bin/bash /bin/dash /bin/ksh /bin/mksh /bin/pdksh /bin/zsh /usr/xpg4/bin/sh /bin/sh /sbin/sh' true; TRUE=$? false; FALSE=$? @@ -49,6 +49,8 @@ versions_osName() { 10.11|10.11.[0-9]*) os_name_='Mac OS X El Capitan' ;; 10.12|10.12.[0-9]*) os_name_='macOS Sierra' ;; 10.13|10.13.[0-9]*) os_name_='macOS High Sierra' ;; + 10.14|10.14.[0-9]*) os_name_='macOS Mojave' ;; + 10.15|10.15.[0-9]*) os_name_='macOS Catalina' ;; *) os_name_='macOS' ;; esac ;; @@ -133,10 +135,11 @@ versions_shellVersion() { version_='' case ${shell_} in - /sbin/sh) ;; # SunOS - /usr/xpg4/bin/sh) - version_=`versions_shell_xpg4 "${shell_}"` - ;; # SunOS + # SunOS shells. + /sbin/sh) ;; + /usr/xpg4/bin/sh) version_=`versions_shell_xpg4 "${shell_}"` ;; + + # Generic shell. */sh) # This could be one of any number of shells. Try until one fits. version_='' @@ -147,16 +150,22 @@ versions_shellVersion() { [ -z "${version_}" ] && version_=`versions_shell_xpg4 "${shell_}"` [ -z "${version_}" ] && version_=`versions_shell_zsh "${shell_}"` ;; + + # Specific shells. ash) version_=`versions_shell_ash "${shell_}"` ;; + # bash - Bourne Again SHell (https://www.gnu.org/software/bash/) */bash) version_=`versions_shell_bash "${shell_}"` ;; - */dash) - # Assuming Ubuntu Linux until somebody comes up with a better test. The - # following test will return an empty string if dash is not installed. - version_=`versions_shell_dash` - ;; + */dash) version_=`versions_shell_dash` ;; + # ksh - KornShell (http://www.kornshell.com/) */ksh) version_=`versions_shell_ksh "${shell_}"` ;; + # mksh - MirBSD Korn Shell (http://www.mirbsd.org/mksh.htm) + */mksh) version_=`versions_shell_ksh "${shell_}"` ;; + # pdksh - Public Domain Korn Shell (http://web.cs.mun.ca/~michael/pdksh/) */pdksh) version_=`versions_shell_pdksh "${shell_}"` ;; + # zsh (https://www.zsh.org/) */zsh) version_=`versions_shell_zsh "${shell_}"` ;; + + # Unrecognized shell. *) version_='invalid' esac @@ -173,6 +182,8 @@ versions_shell_bash() { $1 --version : 2>&1 |grep 'GNU bash' |sed 's/.*version \([^ ]*\).*/\1/' } +# Assuming Ubuntu Linux until somebody comes up with a better test. The +# following test will return an empty string if dash is not installed. versions_shell_dash() { eval dpkg >/dev/null 2>&1 [ $? -eq 127 ] && return # Return if dpkg not found. @@ -193,6 +204,10 @@ versions_shell_ksh() { else versions_version_='' fi + if [ -z "${versions_version_}" ]; then + # shellcheck disable=SC2016 + versions_version_=`${versions_shell_} -c 'echo ${KSH_VERSION}'` + fi if [ -z "${versions_version_}" ]; then _versions_have_strings versions_version_=`strings "${versions_shell_}" 2>&1 \ @@ -207,6 +222,14 @@ versions_shell_ksh() { unset versions_shell_ versions_version_ } +# mksh - MirBSD Korn Shell (http://www.mirbsd.org/mksh.htm) +# mksh is a successor to pdksh (Public Domain Korn Shell). +versions_shell_mksh() { + versions_shell_ksh +} + +# pdksh - Public Domain Korn Shell +# pdksh is an obsolete shell, which was replaced by mksh (among others). versions_shell_pdksh() { _versions_have_strings strings "$1" 2>&1 \ diff --git a/test_runner b/test_runner index 415cc8b..ccd717f 100755 --- a/test_runner +++ b/test_runner @@ -3,7 +3,7 @@ # # Unit test suite runner. # -# Copyright 2008-2017 Kate Ward. All Rights Reserved. +# Copyright 2008-2018 Kate Ward. All Rights Reserved. # Released under the Apache 2.0 license. # # Author: kate.ward@forestent.com (Kate Ward) @@ -27,6 +27,8 @@ RUNNER_LOADED=0 RUNNER_ARGV0=`basename "$0"` RUNNER_SHELLS='/bin/sh ash /bin/bash /bin/dash /bin/ksh /bin/pdksh /bin/zsh' RUNNER_TEST_SUFFIX='_test.sh' +true; RUNNER_TRUE=$? +false; RUNNER_FALSE=$? runner_warn() { echo "runner:WARN $*" >&2; } runner_error() { echo "runner:ERROR $*" >&2; } @@ -36,7 +38,7 @@ runner_usage() { echo "usage: ${RUNNER_ARGV0} [-e key=val ...] [-s shell(s)] [-t test(s)]" } -_runner_tests() { echo ./*${RUNNER_TEST_SUFFIX} |sed 's#./##g'; } +_runner_tests() { echo ./*${RUNNER_TEST_SUFFIX} |sed 's#\./##g'; } _runner_testName() { # shellcheck disable=SC1117 _runner_testName_=`expr "${1:-}" : "\(.*\)${RUNNER_TEST_SUFFIX}"` @@ -114,6 +116,7 @@ for key in ${env}; do done # Run tests. +runner_passing_=${RUNNER_TRUE} for shell in ${shells}; do echo @@ -127,20 +130,20 @@ EOF # Check for existence of shell. shell_bin=${shell} shell_name='' - shell_present=${FALSE} + shell_present=${RUNNER_FALSE} case ${shell} in ash) - shell_bin=`which busybox |grep -v '^no busybox'` - [ $? -eq "${TRUE}" -a -n "${shell_bin}" ] && shell_present="${TRUE}" - shell_bin="${shell_bin} ash" + shell_bin=`command -v busybox` + [ $? -eq "${RUNNER_TRUE}" ] && shell_present="${RUNNER_TRUE}" + shell_bin="${shell_bin:+${shell_bin} }ash" shell_name=${shell} ;; *) - [ -x "${shell_bin}" ] && shell_present="${TRUE}" + [ -x "${shell_bin}" ] && shell_present="${RUNNER_TRUE}" shell_name=`basename "${shell}"` ;; esac - if [ "${shell_present}" -eq "${FALSE}" ]; then + if [ "${shell_present}" -eq "${RUNNER_FALSE}" ]; then runner_warn "unable to run tests with the ${shell_name} shell" continue fi @@ -157,8 +160,11 @@ EOF # ${shell_bin} needs word splitting. # shellcheck disable=SC2086 ( exec ${shell_bin} "./${t}" 2>&1; ) + test "${runner_passing_}" -eq ${RUNNER_TRUE} -a $? -eq ${RUNNER_TRUE} + runner_passing_=$? done done + return ${runner_passing_} } # Execute main() if this is run in standalone mode (i.e. not from a unit test). From fe964fe5bd129a4b54bcf93e547efae4c34281bd Mon Sep 17 00:00:00 2001 From: Kate Ward Date: Sun, 29 Mar 2020 15:44:19 +0200 Subject: [PATCH 05/57] Starting a new 1.2.4 release series. --- shflags | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/shflags b/shflags index ac1506e..05c0f80 100644 --- a/shflags +++ b/shflags @@ -1,6 +1,6 @@ # vim:et:ft=sh:sts=2:sw=2 # -# Copyright 2008-2018 Kate Ward. All Rights Reserved. +# Copyright 2008-2020 Kate Ward. All Rights Reserved. # Released under the Apache License 2.0 license. # http://www.apache.org/licenses/LICENSE-2.0 # @@ -92,7 +92,7 @@ # Return if FLAGS already loaded. [ -n "${FLAGS_VERSION:-}" ] && return 0 -FLAGS_VERSION='1.2.3' +FLAGS_VERSION='1.2.4pre' # Return values that scripts can use. FLAGS_TRUE=0 From 5cb3d86220e415ab5f05ea8751745e49637d40dc Mon Sep 17 00:00:00 2001 From: Kate Ward Date: Sun, 29 Mar 2020 15:48:08 +0200 Subject: [PATCH 06/57] Removed blank line. --- shflags_public_test.sh | 1 - 1 file changed, 1 deletion(-) diff --git a/shflags_public_test.sh b/shflags_public_test.sh index 3d4ac90..dbe4aba 100755 --- a/shflags_public_test.sh +++ b/shflags_public_test.sh @@ -117,7 +117,6 @@ EOF } testEnhancedHelpOutput() { - flags_getoptIsEnh || startSkipping # shellcheck disable=SC2034 From 4a449390238baa35946bb30784f67a3664d4281e Mon Sep 17 00:00:00 2001 From: Kate Ward Date: Sun, 29 Mar 2020 17:14:19 +0200 Subject: [PATCH 07/57] Fixed by rebasing on upstream. --- lib/shunit2 | 16 +++++++--------- 1 file changed, 7 insertions(+), 9 deletions(-) diff --git a/lib/shunit2 b/lib/shunit2 index 0d5ade9..a093463 100755 --- a/lib/shunit2 +++ b/lib/shunit2 @@ -480,17 +480,16 @@ assertTrue() { # See if condition is an integer, i.e. a return value. shunit_return=${SHUNIT_TRUE} - shunit_match_=`expr "${shunit_condition_}" : '\([0-9]*\)'` if (command [ -z "${shunit_condition_}" ]); then # Null condition. shunit_return=${SHUNIT_FALSE} - elif (command [ -n "${shunit_match_}" -a "${shunit_condition_}" = "${shunit_match_}" ]) + elif (expr \( "${shunit_condition_}" + '0' \) '=' "${shunit_condition_}" >/dev/null 2>&1) then # Possible return value. Treating 0 as true, and non-zero as false. (command [ "${shunit_condition_}" -ne 0 ]) && shunit_return=${SHUNIT_FALSE} else # Hopefully... a condition. - ( eval "${shunit_condition_}" ) >/dev/null 2>&1 + (eval "${shunit_condition_}" >/dev/null 2>&1) (command [ $? -ne 0 ]) && shunit_return=${SHUNIT_FALSE} fi @@ -501,7 +500,7 @@ assertTrue() { _shunit_assertFail "${shunit_message_}" fi - unset shunit_message_ shunit_condition_ shunit_match_ + unset shunit_message_ shunit_condition_ return ${shunit_return} } # shellcheck disable=SC2016,SC2034 @@ -546,18 +545,17 @@ assertFalse() { shunit_condition_=$1 # See if condition is an integer, i.e. a return value. - shunit_match_=`expr "${shunit_condition_}" : '\([0-9]*\)'` shunit_return=${SHUNIT_TRUE} if (command [ -z "${shunit_condition_}" ]); then # Null condition. - shunit_return=${SHUNIT_FALSE} - elif (command [ -n "${shunit_match_}" -a "${shunit_condition_}" = "${shunit_match_}" ]) + shunit_return=${SHUNIT_TRUE} + elif (expr \( "${shunit_condition_}" + '0' \) '=' "${shunit_condition_}" >/dev/null 2>&1) then # Possible return value. Treating 0 as true, and non-zero as false. (command [ "${shunit_condition_}" -eq 0 ]) && shunit_return=${SHUNIT_FALSE} else # Hopefully... a condition. - ( eval "${shunit_condition_}" ) >/dev/null 2>&1 + (eval "${shunit_condition_}" >/dev/null 2>&1) (command [ $? -eq 0 ]) && shunit_return=${SHUNIT_FALSE} fi @@ -568,7 +566,7 @@ assertFalse() { _shunit_assertFail "${shunit_message_}" fi - unset shunit_message_ shunit_condition_ shunit_match_ + unset shunit_message_ shunit_condition_ return "${shunit_return}" } # shellcheck disable=SC2016,SC2034 From b24adf8aed8e4049e4fb89a0d91a3a9fb2562145 Mon Sep 17 00:00:00 2001 From: Kate Ward Date: Thu, 9 Apr 2020 10:53:53 +0200 Subject: [PATCH 08/57] Fixed expr command determination to work with 'set -e'. --- shflags | 31 +++++++++++++++++++------------ 1 file changed, 19 insertions(+), 12 deletions(-) diff --git a/shflags b/shflags index 05c0f80..1a15627 100644 --- a/shflags +++ b/shflags @@ -108,18 +108,25 @@ FLAGS_LEVEL_FATAL=4 __FLAGS_LEVEL_DEFAULT=${FLAGS_LEVEL_WARN} # Determine some reasonable command defaults. -__FLAGS_EXPR_CMD='expr --' -__FLAGS_UNAME_S=`uname -s` -if [ "${__FLAGS_UNAME_S}" = 'BSD' ]; then - __FLAGS_EXPR_CMD='gexpr --' -else - _flags_output_=`${__FLAGS_EXPR_CMD} 2>&1` - if [ $? -eq ${FLAGS_TRUE} -a "${_flags_output_}" = '--' ]; then - # We are likely running inside BusyBox. - __FLAGS_EXPR_CMD='expr' +_flags_expr_cmd() { + if [ "$(uname -s)" = 'BSD' ]; then + echo 'gexpr --' + return 0 fi - unset _flags_output_ -fi + + _flags_expr_cmd_='expr --' + # shellcheck disable=SC2003 + if _flags_output_=$(expr -- 2>&1); then + if [ "${_flags_output_}" = '--' ]; then + # We are likely running inside BusyBox. + _flags_expr_cmd_='expr' + fi + fi + + echo "${_flags_expr_cmd_}" + unset _flags_expr_cmd_ _flags_output_ +} +__FLAGS_EXPR_CMD=`_flags_expr_cmd` # Commands a user can override if desired. FLAGS_EXPR_CMD=${FLAGS_EXPR_CMD:-${__FLAGS_EXPR_CMD}} @@ -1201,7 +1208,7 @@ flags_reset() { unset flags_name_ flags_type_ flags_strToEval_ flags_usName_ } -# +#----------------------------------------------------------------------------- # Initialization # From ab09d522871810bf0fbc5048d9e30f534973ff3c Mon Sep 17 00:00:00 2001 From: Kate Ward Date: Thu, 9 Apr 2020 16:48:23 +0200 Subject: [PATCH 09/57] Pulled latest from upstream. --- test_runner | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test_runner b/test_runner index 07a423d..0ced69b 100755 --- a/test_runner +++ b/test_runner @@ -168,4 +168,4 @@ EOF } # Execute main() if this is run in standalone mode (i.e. not from a unit test). -[ -z "${SHUNIT_VERSION}" ] && main "$@" +if [ -z "${SHUNIT_VERSION}" ]; then main "$@"; fi From a2027747a02c9698a4b4eb21983490dea9943309 Mon Sep 17 00:00:00 2001 From: Kate Ward Date: Thu, 9 Apr 2020 17:52:50 +0200 Subject: [PATCH 10/57] Refactored logging code and fixed some 'set -e' issues. --- shflags | 73 ++++++++++++++++++++++++++++++--------------------------- 1 file changed, 39 insertions(+), 34 deletions(-) diff --git a/shflags b/shflags index 1a15627..520eda4 100644 --- a/shflags +++ b/shflags @@ -91,7 +91,7 @@ # shellcheck disable=SC2166 # Return if FLAGS already loaded. -[ -n "${FLAGS_VERSION:-}" ] && return 0 +if [ -n "${FLAGS_VERSION:-}" ]; then return 0; fi FLAGS_VERSION='1.2.4pre' # Return values that scripts can use. @@ -99,34 +99,38 @@ FLAGS_TRUE=0 FLAGS_FALSE=1 FLAGS_ERROR=2 -# Logging levels. -FLAGS_LEVEL_DEBUG=0 -FLAGS_LEVEL_INFO=1 -FLAGS_LEVEL_WARN=2 -FLAGS_LEVEL_ERROR=3 -FLAGS_LEVEL_FATAL=4 -__FLAGS_LEVEL_DEFAULT=${FLAGS_LEVEL_WARN} - -# Determine some reasonable command defaults. -_flags_expr_cmd() { +# shlib_expr_cmd determines a reasonable default `expr` command. +# https://github.com/kward/shlib +# +# Use like: +# EXPR_CMD=$(shlib_expr_cmd) +# ${EXPR_CMD} 1 + 1 +# +# Args: +# none +# Output: +# string: expr command +# Return +# int: 0 upon success +shlib_expr_cmd() { if [ "$(uname -s)" = 'BSD' ]; then echo 'gexpr --' return 0 fi - _flags_expr_cmd_='expr --' + _shlib_expr_cmd_='expr --' # shellcheck disable=SC2003 - if _flags_output_=$(expr -- 2>&1); then - if [ "${_flags_output_}" = '--' ]; then + if _shlib_output_=$(${_shlib_expr_cmd_} 2>&1); then + if [ "${_shlib_output_}" = '--' ]; then # We are likely running inside BusyBox. - _flags_expr_cmd_='expr' + _shlib_expr_cmd_='expr' fi fi - echo "${_flags_expr_cmd_}" - unset _flags_expr_cmd_ _flags_output_ + echo "${_shlib_expr_cmd_}" + unset _shlib_expr_cmd_ _shlib_output_ } -__FLAGS_EXPR_CMD=`_flags_expr_cmd` +__FLAGS_EXPR_CMD=`shlib_expr_cmd` # Commands a user can override if desired. FLAGS_EXPR_CMD=${FLAGS_EXPR_CMD:-${__FLAGS_EXPR_CMD}} @@ -136,26 +140,28 @@ FLAGS_GETOPT_CMD=${FLAGS_GETOPT_CMD:-getopt} # Logging functions. # -__flags_level=0 # Default logging level. +# Logging levels. +FLAGS_LEVEL_DEBUG=0 +FLAGS_LEVEL_INFO=1 +FLAGS_LEVEL_WARN=2 +FLAGS_LEVEL_ERROR=3 +FLAGS_LEVEL_FATAL=4 +__FLAGS_LEVEL_DEFAULT=${FLAGS_LEVEL_WARN} +__flags_level=${__FLAGS_LEVEL_DEFAULT} # Current logging level. _flags_debug() { - [ ${__flags_level} -le ${FLAGS_LEVEL_DEBUG} ] || return - echo "flags:DEBUG $*" >&2 + if [ ${__flags_level} -le ${FLAGS_LEVEL_DEBUG} ]; then echo "flags:DEBUG $*" >&2; fi } _flags_info() { - [ ${__flags_level} -le ${FLAGS_LEVEL_INFO} ] || return - echo "flags:INFO $*" >&2 + if [ ${__flags_level} -le ${FLAGS_LEVEL_INFO} ]; then echo "flags:INFO $*" >&2; fi } _flags_warn() { - [ ${__flags_level} -le ${FLAGS_LEVEL_WARN} ] || return - echo "flags:WARN $*" >&2 + if [ ${__flags_level} -le ${FLAGS_LEVEL_WARN} ]; then echo "flags:WARN $*" >&2; fi } _flags_error() { - [ ${__flags_level} -le ${FLAGS_LEVEL_ERROR} ] || return - echo "flags:ERROR $*" >&2 + if [ ${__flags_level} -le ${FLAGS_LEVEL_ERROR} ]; then echo "flags:ERROR $*" >&2; fi } _flags_fatal() { - [ ${__flags_level} -le ${FLAGS_LEVEL_FATAL} ] || return echo "flags:FATAL $*" >&2 exit ${FLAGS_ERROR} } @@ -163,7 +169,7 @@ _flags_fatal() { # Get the logging level. flags_loggingLevel() { echo ${__flags_level}; } -# Set the logging level. +# Set the logging level by overriding the `__flags_level` variable. # # Args: # _flags_level_: integer: new logging level @@ -172,9 +178,9 @@ flags_loggingLevel() { echo ${__flags_level}; } flags_setLoggingLevel() { [ $# -ne 1 ] && _flags_fatal "flags_setLevel(): logging level missing" _flags_level_=$1 - [ "${_flags_level_}" -ge "${FLAGS_LEVEL_DEBUG}" \ - -a "${_flags_level_}" -le "${FLAGS_LEVEL_FATAL}" ] \ - || _flags_fatal "Invalid logging level '${_flags_level_}' specified." + if ! [ "${_flags_level_}" -ge "${FLAGS_LEVEL_DEBUG}" -a "${_flags_level_}" -le "${FLAGS_LEVEL_FATAL}" ]; then + _flags_fatal "Invalid logging level '${_flags_level_}' specified." + fi __flags_level=$1 unset _flags_level_ } @@ -327,8 +333,7 @@ _flags_define() { _flags_usName_="`_flags_underscoreName "${_flags_name_}"`" # Check whether the flag name is reserved. - _flags_itemInList "${_flags_usName_}" "${__FLAGS_RESERVED_LIST}" - if [ $? -eq ${FLAGS_TRUE} ]; then + if _flags_itemInList "${_flags_usName_}" "${__FLAGS_RESERVED_LIST}"; then flags_error="flag name (${_flags_name_}) is reserved" _flags_return_=${FLAGS_ERROR} fi From 59aaaa6a7621c28852d69ad2fc05a24e194ff80d Mon Sep 17 00:00:00 2001 From: Kate Ward Date: Thu, 9 Apr 2020 17:55:20 +0200 Subject: [PATCH 11/57] Removed line limit restrictions. --- CONTRIBUTING.md | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 9915b70..cfc4918 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -16,7 +16,7 @@ doSomething() { } ``` -One-line functions are allowed if they can fit within the 80 char line limit. +One-line functions are allowed if they are for a single command. ```sh doSomething() { echo 'done!'; } @@ -118,10 +118,11 @@ if [ -z 'some string' ]; then fi ``` -Lines of code should be no longer than 80 characters unless absolutely -necessary. When lines are wrapped using the backslash character '\', subsequent -lines should be indented with four (4) spaces so as to differentiate from the -standard spacing of two characters, and tabs may not be used. +Lines of code have no line limit, although the general preference is to wrap +lines at reasonable boundaries (e.g., between if/then/else clauses). When long +lines are wrapped using the backslash character '\', subsequent lines should be +indented with four (4) spaces so as to differentiate from the standard spacing +of two characters, and tabs may not be used. ```sh for x in some set of very long set of arguments that make for a very long \ From 6cda74b24e844152c6af4385788105f84dc495f6 Mon Sep 17 00:00:00 2001 From: Kate Ward Date: Fri, 10 Apr 2020 14:29:35 +0200 Subject: [PATCH 12/57] Setup repo hooks. --- .githooks/pre-commit | 13 ++++++++++ .githooks/pre-commit.shellcheck | 20 ++++++++++++++ init_githooks.sh | 46 +++++++++++++++++++++++++++++++++ 3 files changed, 79 insertions(+) create mode 100755 .githooks/pre-commit create mode 100755 .githooks/pre-commit.shellcheck create mode 100755 init_githooks.sh diff --git a/.githooks/pre-commit b/.githooks/pre-commit new file mode 100755 index 0000000..5ee533a --- /dev/null +++ b/.githooks/pre-commit @@ -0,0 +1,13 @@ +#!/bin/sh +# +# A hook script to verify what is about to be committed. +# Called by "git commit" with no arguments. + +# Redirect output to stderr. +exec 1>&2 + +for f in .githooks/pre-commit.*; do + n=$(echo "${f}" |sed 's/^.*pre-commit\.//') + echo "running ${n} pre-commit" + $(${f}) +done diff --git a/.githooks/pre-commit.shellcheck b/.githooks/pre-commit.shellcheck new file mode 100755 index 0000000..d8f364e --- /dev/null +++ b/.githooks/pre-commit.shellcheck @@ -0,0 +1,20 @@ +#!/bin/sh +# +# Git hook to run ShellCheck. +# +# ShellCheck + +# Treat unset variables as an error when performing parameter expansion. +set -u + +if ! command -v shellcheck >/dev/null; then + echo 'unable to locate shellcheck' >&2 + return 0 +fi + +for f in $(git diff --name-only); do + case "${f}" in + shflags|shflags_test_helpers) shellcheck -s sh "${f}" ;; + *.sh) shellcheck "${f}" ;; + esac +done diff --git a/init_githooks.sh b/init_githooks.sh new file mode 100755 index 0000000..d5a7f50 --- /dev/null +++ b/init_githooks.sh @@ -0,0 +1,46 @@ +#! /bin/sh +# +# Initialize the local git hooks this repository. +# https://git-scm.com/docs/githooks + +topLevel=$(git rev-parse --show-toplevel) && cd "${topLevel}" +hooksDir="${topLevel}/.githooks" +hooksPath=$(git config core.hooksPath) +if [ $? -ne 0 ]; then + hooksPath="${topLevel}/.git/hooks" +fi + +echo "linking hooks..." +for hook in \ + applypatch-msg \ + pre-applypatch \ + post-applypatch \ + pre-commit \ + pre-merge-commit \ + prepare-commit-msg \ + commit-msg \ + post-commit \ + pre-rebase \ + post-checkout \ + post-merge \ + pre-push \ + pre-receive \ + update \ + post-receive \ + post-update \ + push-to-checkout \ + pre-auto-gc \ + post-rewrite \ + sendemail-validate \ + fsmonitor-watchman \ + p4-pre-submit \ + post-index-change +do + src="${hooksDir}/${hook}" + dest="${hooksPath}/${hook}" + + [ -x "${src}" ] || continue + + echo "- ${hook}" + ln -sf "${src}" "${dest}" +done From 3c5fc956859c70dcd768423df7938a1f5340afd1 Mon Sep 17 00:00:00 2001 From: Kate Ward Date: Fri, 10 Apr 2020 14:30:13 +0200 Subject: [PATCH 13/57] Fixed 'set -e' errors. --- shflags | 4 +- shflags_defines_test.sh | 250 ++++++++++++++++++++-------------------- 2 files changed, 125 insertions(+), 129 deletions(-) diff --git a/shflags b/shflags index 520eda4..b2b809b 100644 --- a/shflags +++ b/shflags @@ -357,9 +357,7 @@ _flags_define() { fi # Check for existing short name definition. - if [ ${_flags_return_} -eq ${FLAGS_TRUE} \ - -a "${_flags_short_}" != "${__FLAGS_NULL}" ] - then + if [ ${_flags_return_} -eq ${FLAGS_TRUE} -a "${_flags_short_}" != "${__FLAGS_NULL}" ]; then if _flags_itemInList "${_flags_short_}" "${__flags_shortNames}"; then flags_error="flag short name (${_flags_short_}) already defined" _flags_warn "${flags_error}" diff --git a/shflags_defines_test.sh b/shflags_defines_test.sh index f2e1d71..2c2ad81 100755 --- a/shflags_defines_test.sh +++ b/shflags_defines_test.sh @@ -3,7 +3,7 @@ # # shFlags unit test for the flag definition methods # -# Copyright 2008-2017 Kate Ward. All Rights Reserved. +# Copyright 2008-2020 Kate Ward. All Rights Reserved. # Released under the Apache 2.0 license. # # Author: kate.ward@forestent.com (Kate Ward) @@ -14,7 +14,10 @@ # shellcheck disable=SC1090,SC1091 # Exit immediately if a simple command exits with a non-zero status. -#set -e +set -e + +# Treat unset variables as an error when performing parameter expansion. +set -u # These variables will be overridden by the test helpers. stdoutF="${TMPDIR:-/tmp}/STDOUT" @@ -25,172 +28,165 @@ stderrF="${TMPDIR:-/tmp}/STDERR" testFlagsDefine() { # No arguments. - _flags_define >"${stdoutF}" 2>"${stderrF}" - assertFalse '_flags_define() with no arguments should have failed.' $? + if _flags_define >"${stdoutF}" 2>"${stderrF}" + then :; else + assertEquals '_flags_define() with no arguments should error' ${FLAGS_ERROR} $? + fi assertErrorMsg '' 'no arguments' # One argument. - _flags_define arg1 >"${stdoutF}" 2>"${stderrF}" - assertFalse '_flags_define() call with one argument should fail' $? + if _flags_define arg1 >"${stdoutF}" 2>"${stderrF}" + then :; else + assertEquals '_flags_define() call with one argument should error' ${FLAGS_ERROR} $? + fi assertErrorMsg '' 'one argument' # Two arguments. - _flags_define arg1 arg2 >"${stdoutF}" 2>"${stderrF}" - assertFalse '_flags_define() call with two arguments should fail' $? + if _flags_define arg1 arg2 >"${stdoutF}" 2>"${stderrF}" + then :; else + assertEquals '_flags_define() call with two arguments should error' ${FLAGS_ERROR} $? + fi assertErrorMsg '' 'two arguments' # Three arguments. - _flags_define arg1 arg2 arg3 >"${stdoutF}" 2>"${stderrF}" - assertFalse '_flags_define() call with three arguments should fail' $? + if _flags_define arg1 arg2 arg3 >"${stdoutF}" 2>"${stderrF}" + then :; else + assertEquals '_flags_define() call with three arguments should error' ${FLAGS_ERROR} $? + fi assertErrorMsg '' 'three arguments' # Multiple definition. Assumes working boolean definition (tested elsewhere). - _flags_define "${__FLAGS_TYPE_BOOLEAN}" multiDefBool true 'multi def #1' m - _flags_define "${__FLAGS_TYPE_BOOLEAN}" multiDefBool false 'multi def #2' m \ - >"${stdoutF}" 2>"${stderrF}" - assertFalse '_flags_define() with existing flag name should fail' $? - assertTrue \ - '_flags_define() should not overwrite previously defined default.' \ - "${FLAGS_multiDefBool:-}" + if ! _flags_define "${__FLAGS_TYPE_BOOLEAN}" multiDefBool true 'multi def #1' m; then + fail "didn't expect _flags_define for 'multi def #1' to fail" + fi + if _flags_define "${__FLAGS_TYPE_BOOLEAN}" multiDefBool false 'multi def #2' m >"${stdoutF}" 2>"${stderrF}" + then :; else + assertEquals '_flags_define() with existing flag name should fail' ${FLAGS_FALSE} $? + fi + assertTrue '_flags_define() should not overwrite previously defined default.' "${FLAGS_multiDefBool:-}" assertWarnMsg '' 'existing flag' # Duplicate dashed and underscored definition. - _flags_define "${__FLAGS_TYPE_STRING}" long-name 'foo' 'dashed name' l - _flags_define "${__FLAGS_TYPE_STRING}" long_name 'bar' 'underscored name' l \ - >"${stdoutF}" 2>"${stderrF}" - assertFalse '_flags_define() with existing flag name should fail' $? + if ! _flags_define "${__FLAGS_TYPE_STRING}" long-name 'foo' 'dashed name' l; then + fail "didn't expect _flags_define() for 'dashed name' to fail" + fi + if _flags_define "${__FLAGS_TYPE_STRING}" long_name 'bar' 'underscored name' l >"${stdoutF}" 2>"${stderrF}" + then :; else + assertEquals '_flags_define() with duplicate dashed and underscored definition should fail' ${FLAGS_FALSE} $? + fi # shellcheck disable=SC2154 - assertEquals \ - '_flags_define() should not overwrite previously defined default.' \ - "${FLAGS_long_name}" 'foo' + assertEquals '_flags_define() should not overwrite previously defined default.' "${FLAGS_long_name}" 'foo' assertWarnMsg '' 'already exists' # TODO(kward): test requirement of enhanced getopt. # Invalid type. - _flags_define invalid arg2 arg3 arg4 i >"${stdoutF}" 2>"${stderrF}" - assertFalse '_flags_define() with "invalid" type should have failed.' $? + if _flags_define invalid arg2 arg3 arg4 i >"${stdoutF}" 2>"${stderrF}" + then :; else + assertEquals '_flags_define() with "invalid" type should have failed.' ${FLAGS_ERROR} $? + fi assertErrorMsg 'unrecognized flag type' 'invalid type' } testBoolean() { - # Test true defaults. - for default in 'true' 't' 0; do + while read -r desc ok default want; do flags_reset - DEFINE_boolean boolVal "${default}" 'my boolean' b - rtrn=$? - assertTrue \ - "DEFINE_boolean() call with default of '${default}' failed." \ - "${FLAGS_boolVal:-}" - assertTrue \ - "DEFINE_boolean() call with default of '${default}' returned failure." \ - ${rtrn} - done - # test false defaults - for default in 'false' 'f' 1; do - flags_reset - DEFINE_boolean boolVal "${default}" 'my boolean' b - rtrn=$? - assertFalse \ - "DEFINE_boolean() call with default of '${default}' failed." \ - "${FLAGS_boolVal:-}" - assertTrue \ - "DEFINE_boolean() call with default of '${default}' returned failure." \ - ${rtrn} - done - - # Test invalid default. - flags_reset - DEFINE_boolean boolVal 'invalid' 'my boolean' b >"${stdoutF}" 2>"${stderrF}" - assertFalse 'DEFINE_boolean() call with invalid default did not fail.' $? - assertErrorMsg + if DEFINE_boolean boolVal "${default}" 'my boolean' b >"${stdoutF}" 2>"${stderrF}" + then + assertEquals "${desc}: incorrect FLAGS_boolVal value" "${FLAGS_boolVal:-}" "${want}" + else + got=$? + if [ "${ok}" -eq ${FLAGS_TRUE} ]; then + assertEquals "${desc}: DEFINE_boolean() failed unexpectedly" "${want}" "${got}" + else + assertEquals "${desc}: DEFINE_boolean() expected different return value" "${want}" "${got}" + assertErrorMsg + fi + fi + done <"${stdoutF}" 2>"${stderrF}" - assertFalse 'DEFINE_float() call with string value default did not fail.' $? - assertErrorMsg + # Invalid defaults. + for default in ${TH_FLOAT_INVALID}; do + flags_reset + desc="invalid_float_val='${default}'" + if DEFINE_float floatVal "${default}" 'invalid float' f >"${stdoutF}" 2>"${stderrF}" + then + fail "${desc}: expected DEFINE_float() to fail" + else + assertEquals "${desc}: DEFINE_float() expected error" ${FLAGS_ERROR} $? + assertErrorMsg + fi + done } testInteger() { - # Test valid defaults. + # Valid defaults. for default in ${TH_INT_VALID}; do flags_reset - DEFINE_integer intVal "${default}" "integer: ${default}" i - rtrn=$? - assertSame \ - "DEFINE_integer() call with valid default failed." \ - "${default}" "${FLAGS_intVal:-}" - assertTrue \ - "DEFINE_integer() call with valid default of '${default}' returned failure." \ - ${rtrn} + desc="valid_int_val='${default}'" + if DEFINE_integer intVal "${default}" 'valid integer' i + then + got="${FLAGS_intVal:-}" want="${default}" + assertEquals "${desc}: incorrect FLAGS_intVal value" "${want}" "${got}" + else + assertEquals "${desc}: DEFINE_integer() failed unexpectedly." ${FLAGS_TRUE} $? + fi done - # Test invalid defaults. - flags_reset - DEFINE_integer intVal 1.234 'invalid integer: float' i \ - >"${stdoutF}" 2>"${stderrF}" - assertFalse 'DEFINE_integer() call with float value default did not fail.' $? - assertErrorMsg 'invalid default' 'float default' - - DEFINE_integer intVal -1.234 'invalid integer: negative float' i \ - >"${stdoutF}" 2>"${stderrF}" - assertFalse \ - 'DEFINE_integer() call with negative float value default did not fail.' \ - $? - assertErrorMsg 'invalid default' 'negative float default' - - DEFINE_integer intVal 'invalid' 'invalid integer: string' i \ - >"${stdoutF}" 2>"${stderrF}" - assertFalse \ - 'DEFINE_integer() call with string value default did not fail.' \ - $? - assertErrorMsg 'invalid default' 'string default' + # Invalid defaults. + for default in ${TH_INT_INVALID}; do + flags_reset + desc="invalid_int_val='${default}'" + if DEFINE_integer intVal "${default}" 'invalid integer' i >"${stdoutF}" 2>"${stderrF}" + then + fail "${desc}: expected DEFINE_integer() to fail" + else + assertEquals "${desc}: DEFINE_integer() expected error." ${FLAGS_ERROR} $? + assertErrorMsg + fi + done } -testString() -{ - # test valid defaults - for default in \ - ${TH_BOOL_VALID} \ - ${TH_FLOAT_VALID} \ - ${TH_INT_VALID} \ - 'also valid' +testString() { + # Valid defaults. + for default in ${TH_BOOL_VALID} ${TH_FLOAT_VALID} ${TH_INT_VALID} 'also valid' '' do flags_reset - DEFINE_string strVal "${default}" "string: ${default}" s - rtrn=$? - assertSame \ - "DEFINE_string() call with valid default failed." \ - "${default}" "${FLAGS_strVal:-}" - assertTrue \ - "DEFINE_string() call with valid default of '${default}' returned failure." \ - ${rtrn} + desc="valid_string_val='${default}'" + if DEFINE_string strVal "${default}" "string: ${default}" s + then + got="${FLAGS_strVal:-}" want="${default}" + assertEquals "${desc}: incorrect FLAGS_strVal value" "${want}" "${got}" + else + assertEquals "${desc}: DEFINE_string() failed unexpectedly." ${FLAGS_TRUE} $? + fi done - # test "empty" strings - flags_reset - DEFINE_string str '' "string: empty single quotes" s - rtrn=$? - assertSame \ - "DEFINE_string() call with valid default failed." \ - '' "${FLAGS_str:-}" + # There are no known invalid defaults. } testShortNameLength() { @@ -199,11 +195,13 @@ testShortNameLength() { } testFlagNameIsReserved() { - ( DEFINE_string TRUE '' 'true is a reserved flag name' t \ - >"${stdoutF}" 2>"${stderrF}" ) - rtrn=$? - assertEquals "${FLAGS_ERROR}" "${rtrn}" - assertErrorMsg 'flag name (TRUE) is reserved' + if DEFINE_string TRUE '' 'true is a reserved flag name' t >"${stdoutF}" 2>"${stderrF}" + then + fail "expected DEFINE with reserved flag name to fail" + else + assertEquals "expected error from DEFINE with reserved flag" ${FLAGS_ERROR} $? + assertErrorMsg 'flag name (TRUE) is reserved' + fi } oneTimeSetUp() { From 71db95d1a4952f8e31ca084bed66709da409ce30 Mon Sep 17 00:00:00 2001 From: Kate Ward Date: Fri, 10 Apr 2020 15:17:35 +0200 Subject: [PATCH 14/57] Fixes to hooks. --- .githooks/generic | 28 ++++++++++++++++++++++++++++ .githooks/pre-commit | 13 ------------- .githooks/pre-commit.shellcheck | 2 +- init_githooks.sh | 21 +++++++++++---------- 4 files changed, 40 insertions(+), 24 deletions(-) create mode 100755 .githooks/generic delete mode 100755 .githooks/pre-commit diff --git a/.githooks/generic b/.githooks/generic new file mode 100755 index 0000000..b5f3e4c --- /dev/null +++ b/.githooks/generic @@ -0,0 +1,28 @@ +#!/bin/sh +# +# A generic git hook proxy. +# https://git-scm.com/docs/githooks + +run() { + hook=$1 + file=$2 + + n=$(echo "${file}" |sed "s/^.*${hook}\.//") + echo "running ${n} ${hook}" + ${file} +} + +# Redirect output to stderr. +exec 1>&2 + +githooks='.githooks' +basename=$(basename "$0") + +for f in $(cd ${githooks} && echo *); do + case "${f}" in + pre-commit.*) + # Called by "git commit" with no arguments. + [ "${basename}" = 'pre-commit' ] && run pre-commit "${githooks}/${f}" + ;; + esac +done diff --git a/.githooks/pre-commit b/.githooks/pre-commit deleted file mode 100755 index 5ee533a..0000000 --- a/.githooks/pre-commit +++ /dev/null @@ -1,13 +0,0 @@ -#!/bin/sh -# -# A hook script to verify what is about to be committed. -# Called by "git commit" with no arguments. - -# Redirect output to stderr. -exec 1>&2 - -for f in .githooks/pre-commit.*; do - n=$(echo "${f}" |sed 's/^.*pre-commit\.//') - echo "running ${n} pre-commit" - $(${f}) -done diff --git a/.githooks/pre-commit.shellcheck b/.githooks/pre-commit.shellcheck index d8f364e..034f7b9 100755 --- a/.githooks/pre-commit.shellcheck +++ b/.githooks/pre-commit.shellcheck @@ -12,7 +12,7 @@ if ! command -v shellcheck >/dev/null; then return 0 fi -for f in $(git diff --name-only); do +for f in $(git diff --cached --name-only); do case "${f}" in shflags|shflags_test_helpers) shellcheck -s sh "${f}" ;; *.sh) shellcheck "${f}" ;; diff --git a/init_githooks.sh b/init_githooks.sh index d5a7f50..19a380f 100755 --- a/init_githooks.sh +++ b/init_githooks.sh @@ -3,13 +3,18 @@ # Initialize the local git hooks this repository. # https://git-scm.com/docs/githooks -topLevel=$(git rev-parse --show-toplevel) && cd "${topLevel}" +topLevel=$(git rev-parse --show-toplevel) +if ! cd "${topLevel}"; then + echo "filed to cd into topLevel directory '${topLevel}'" + exit 1 +fi + hooksDir="${topLevel}/.githooks" -hooksPath=$(git config core.hooksPath) -if [ $? -ne 0 ]; then - hooksPath="${topLevel}/.git/hooks" +if ! hooksPath=$(git config core.hooksPath); then + hooksPath="${topLevel}/.git/hooks" fi +src="${hooksDir}/generic" echo "linking hooks..." for hook in \ applypatch-msg \ @@ -36,11 +41,7 @@ for hook in \ p4-pre-submit \ post-index-change do - src="${hooksDir}/${hook}" + echo "- ${hook}" dest="${hooksPath}/${hook}" - - [ -x "${src}" ] || continue - - echo "- ${hook}" - ln -sf "${src}" "${dest}" + ln -sf "${src}" "${dest}" done From 28832e246b5e9ab99cf0af54da4d2dac05f47653 Mon Sep 17 00:00:00 2001 From: Kate Ward Date: Fri, 10 Apr 2020 15:22:15 +0200 Subject: [PATCH 15/57] Fixes to hooks. --- .githooks/generic | 19 ++++++++++--------- .githooks/pre-commit.shellcheck | 8 ++++++-- 2 files changed, 16 insertions(+), 11 deletions(-) diff --git a/.githooks/generic b/.githooks/generic index b5f3e4c..71d0122 100755 --- a/.githooks/generic +++ b/.githooks/generic @@ -4,12 +4,12 @@ # https://git-scm.com/docs/githooks run() { - hook=$1 - file=$2 + hook=$1 + file=$2 n=$(echo "${file}" |sed "s/^.*${hook}\.//") - echo "running ${n} ${hook}" - ${file} + echo "running ${n} ${hook}" + ${file} } # Redirect output to stderr. @@ -19,10 +19,11 @@ githooks='.githooks' basename=$(basename "$0") for f in $(cd ${githooks} && echo *); do - case "${f}" in - pre-commit.*) - # Called by "git commit" with no arguments. - [ "${basename}" = 'pre-commit' ] && run pre-commit "${githooks}/${f}" - ;; + case "${f}" in + pre-commit.*) + # Called by "git commit" with no arguments. + [ "${basename}" = 'pre-commit' ] && run pre-commit "${githooks}/${f}" + ;; + *) ;; esac done diff --git a/.githooks/pre-commit.shellcheck b/.githooks/pre-commit.shellcheck index 034f7b9..999195f 100755 --- a/.githooks/pre-commit.shellcheck +++ b/.githooks/pre-commit.shellcheck @@ -13,8 +13,12 @@ if ! command -v shellcheck >/dev/null; then fi for f in $(git diff --cached --name-only); do + cmd=':' case "${f}" in - shflags|shflags_test_helpers) shellcheck -s sh "${f}" ;; - *.sh) shellcheck "${f}" ;; + shflags|shflags_test_helpers) cmd="shellcheck -s sh ${f}" ;; + *.sh) cmd="shellcheck ${f}" ;; esac + if ! ${cmd}; then + echo "shellcheck error for '${f}'" >&2 + fi done From edc18446eb250f47147b78fb6d1377116d65c4b3 Mon Sep 17 00:00:00 2001 From: Kate Ward Date: Fri, 10 Apr 2020 15:23:35 +0200 Subject: [PATCH 16/57] Fixes to hooks. --- .githooks/generic | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/.githooks/generic b/.githooks/generic index 71d0122..b1b5cd0 100755 --- a/.githooks/generic +++ b/.githooks/generic @@ -12,6 +12,11 @@ run() { ${file} } +die() { + echo 'error: hook did not succeed' >&2 + exit 1 +} + # Redirect output to stderr. exec 1>&2 @@ -22,8 +27,8 @@ for f in $(cd ${githooks} && echo *); do case "${f}" in pre-commit.*) # Called by "git commit" with no arguments. - [ "${basename}" = 'pre-commit' ] && run pre-commit "${githooks}/${f}" + [ "${basename}" = 'pre-commit' ] || continue + run pre-commit "${githooks}/${f}" || die ;; - *) ;; esac done From 81722e3ea011077c51acc6e878506693e82195df Mon Sep 17 00:00:00 2001 From: Kate Ward Date: Sun, 29 Mar 2020 18:20:07 +0200 Subject: [PATCH 17/57] Merged public and issue_28 tests. Fixed test errors. --- shflags_issue_28_test.sh | 145 --------------------------------------- shflags_public_test.sh | 51 ++++++++++---- 2 files changed, 36 insertions(+), 160 deletions(-) delete mode 100755 shflags_issue_28_test.sh diff --git a/shflags_issue_28_test.sh b/shflags_issue_28_test.sh deleted file mode 100755 index 69043eb..0000000 --- a/shflags_issue_28_test.sh +++ /dev/null @@ -1,145 +0,0 @@ -#! /bin/sh -# vim:et:ft=sh:sts=2:sw=2 -# -# shFlags unit test for https://github.com/kward/shflags/issues/28. -# -# Copyright 2008-2017 Kate Ward. All Rights Reserved. -# Released under the Apache 2.0 license. -# -# Author: kate.ward@forestent.com (Kate Ward) -# https://github.com/kward/shflags -# -### ShellCheck (http://www.shellcheck.net/) -# Disable source following. -# shellcheck disable=SC1090,SC1091 - -# These variables will be overridden by the test helpers. -expectedF="${TMPDIR:-/tmp}/expected" -returnF="${TMPDIR:-/tmp}/return" -stdoutF="${TMPDIR:-/tmp}/STDOUT" -stderrF="${TMPDIR:-/tmp}/STDERR" - -# Load test helpers. -. ./shflags_test_helpers - -testHelp() { - _testHelp '-h' - flags_getoptIsEnh || return - _testHelp '--help' -} - -_testHelp() { - flag=$1 - - # Test default help output. - th_clearReturn - ( - FLAGS "${flag}" >"${stdoutF}" 2>"${stderrF}" - echo $? >"${returnF}" - ) - assertFalse \ - 'short help request should have returned a false exit code.' \ - "$(th_queryReturn)" - grep 'show this help' "${stderrF}" >/dev/null - grepped=$? - assertTrue \ - 'short request for help should have produced some help output.' \ - ${grepped} - [ ${grepped} -ne "${FLAGS_TRUE}" ] && th_showOutput - - # Test proper output when FLAGS_HELP set. - ( - FLAGS_HELP='this is a test' - FLAGS "${flag}" >"${stdoutF}" 2>"${stderrF}" - ) - grep 'this is a test' "${stderrF}" >/dev/null - grepped=$? - assertTrue 'setting FLAGS_HELP did not produce expected result' ${grepped} - [ ${grepped} -ne "${FLAGS_TRUE}" ] && th_showOutput - - # Test that "'" chars work in help string. - ( - # shellcheck disable=SC2034 - DEFINE_boolean b false "help string containing a ' char" b - FLAGS "${flag}" >"${stdoutF}" 2>"${stderrF}" - ) - grep "help string containing a ' char" "${stderrF}" >/dev/null - grepped=$? - assertTrue "help strings containing apostrophes don't work" ${grepped} - [ ${grepped} -ne "${FLAGS_TRUE}" ] && th_showOutput -} - -mock_flags_columns() { - echo 80 -} - -_doDefines() { - # shellcheck disable=SC2034 - DEFINE_boolean 'force' false '' f -} - -testStandardHelpOutput() { - flags_getoptIsStd || startSkipping - - _doDefines - help='USAGE: standard [flags] args' - - cat >"${expectedF}" <"${stdoutF}" 2>"${stderrF}" - ) - diff "${expectedF}" "${stderrF}" >/dev/null - r3turn=$? - assertTrue 'unexpected help output' ${r3turn} - th_showOutput ${r3turn} "${stdoutF}" "${stderrF}" -} - -testEnhancedHelpOutput() { - flags_getoptIsEnh || startSkipping - - _doDefines - help='USAGE: enhanced [flags] args' - - cat >"${expectedF}" <"${stdoutF}" 2>"${stderrF}" - ) - diff "${expectedF}" "${stderrF}" >/dev/null - differed=$? - assertTrue 'unexpected help output' ${differed} - th_showOutput ${differed} "${stdoutF}" "${stderrF}" -} - -oneTimeSetUp() { - th_oneTimeSetUp - - if flags_getoptIsStd; then - th_warn 'Standard version of getopt found. Enhanced tests will be skipped.' - return - fi - th_warn 'Enhanced version of getopt found. Standard tests will be skipped.' -} - -setUp() { - flags_reset -} - -# Load and run shUnit2. -# shellcheck disable=SC2034 -[ -n "${ZSH_VERSION:-}" ] && SHUNIT_PARENT=$0 -. "${TH_SHUNIT}" diff --git a/shflags_public_test.sh b/shflags_public_test.sh index dbe4aba..244d2b8 100755 --- a/shflags_public_test.sh +++ b/shflags_public_test.sh @@ -3,7 +3,7 @@ # # shFlags unit test for the public functions. # -# Copyright 2008-2017 Kate Ward. All Rights Reserved. +# Copyright 2008-2020 Kate Ward. All Rights Reserved. # Released under the Apache 2.0 license. # # Author: kate.ward@forestent.com (Kate Ward) @@ -26,7 +26,8 @@ stderrF="${TMPDIR:-/tmp}/STDERR" testHelp() { _testHelp '-h' - flags_getoptIsEnh || return + flags_getoptIsEnh + [ $? -eq ${FLAGS_FALSE} ] && return _testHelp '--help' } @@ -40,24 +41,24 @@ _testHelp() { echo $? >"${returnF}" ) assertFalse \ - 'a call for help should return a non-zero exit code.' \ + 'short help request should have returned a false exit code.' \ "$(th_queryReturn)" - grep 'show this help' "${stderrF}" >/dev/null - grepped=$? + (grep 'show this help' "${stderrF}" >/dev/null) + r3turn=$? assertTrue \ 'short request for help should have produced some help output.' \ - ${grepped} - [ ${grepped} -ne "${FLAGS_TRUE}" ] && th_showOutput + ${r3turn} + [ ${r3turn} -ne ${FLAGS_TRUE} ] && th_showOutput # Test proper output when FLAGS_HELP set. ( FLAGS_HELP='this is a test' FLAGS "${flag}" >"${stdoutF}" 2>"${stderrF}" ) - grep 'this is a test' "${stderrF}" >/dev/null - grepped=$? - assertTrue 'setting FLAGS_HELP did not produce expected result' ${grepped} - [ ${grepped} -ne "${FLAGS_TRUE}" ] && th_showOutput + (grep 'this is a test' "${stderrF}" >/dev/null) + r3turn=$? + assertTrue 'setting FLAGS_HELP did not produce expected result' ${r3turn} + [ ${r3turn} -ne ${FLAGS_TRUE} ] && th_showOutput # Test that "'" chars work in help string. ( @@ -65,10 +66,10 @@ _testHelp() { DEFINE_boolean b false "help string containing a ' char" b FLAGS "${flag}" >"${stdoutF}" 2>"${stderrF}" ) - grep "help string containing a ' char" "${stderrF}" >/dev/null - grepped=$? - assertTrue "help strings containing apostrophes don't work" ${grepped} - [ ${grepped} -ne "${FLAGS_TRUE}" ] && th_showOutput + (grep "help string containing a ' char" "${stderrF}" >/dev/null) + r3turn=$? + assertTrue "help strings containing apostrophes don't work" ${r3turn} + [ ${r3turn} -ne ${FLAGS_TRUE} ] && th_showOutput } mock_flags_columns() { @@ -86,6 +87,10 @@ testStandardHelpOutput() { DEFINE_string long_default \ 'this_is_a_long_default_value_to_force_alternate_indentation' \ 'testing of long default value' F + + # Test for https://github.com/kward/shflags/issues/28. + DEFINE_boolean 'force' false '' f + help='USAGE: standard [flags] args' cat >"${expectedF}" <"${expectedF}" < Date: Fri, 10 Apr 2020 15:24:25 +0200 Subject: [PATCH 18/57] Run with multiple linux distros. --- .travis.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.travis.yml b/.travis.yml index 66a0c25..a1b2c4b 100644 --- a/.travis.yml +++ b/.travis.yml @@ -9,6 +9,8 @@ script: os: - linux + - dist: bionic + - dist: xenial - osx addons: From 32c85b25424ee56997dc26304ca25dc2fd5eb26a Mon Sep 17 00:00:00 2001 From: Kate Ward Date: Sun, 29 Mar 2020 18:27:06 +0200 Subject: [PATCH 19/57] Updated from upstream. --- test_runner | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test_runner b/test_runner index ccd717f..07a423d 100755 --- a/test_runner +++ b/test_runner @@ -3,7 +3,7 @@ # # Unit test suite runner. # -# Copyright 2008-2018 Kate Ward. All Rights Reserved. +# Copyright 2008-2020 Kate Ward. All Rights Reserved. # Released under the Apache 2.0 license. # # Author: kate.ward@forestent.com (Kate Ward) @@ -25,7 +25,7 @@ RUNNER_LOADED=0 RUNNER_ARGV0=`basename "$0"` -RUNNER_SHELLS='/bin/sh ash /bin/bash /bin/dash /bin/ksh /bin/pdksh /bin/zsh' +RUNNER_SHELLS='/bin/sh ash /bin/bash /bin/dash /bin/ksh /bin/mksh /bin/zsh' RUNNER_TEST_SUFFIX='_test.sh' true; RUNNER_TRUE=$? false; RUNNER_FALSE=$? From d031fa8b6e2a86958d94414eb3674c7bb307801e Mon Sep 17 00:00:00 2001 From: Kate Ward Date: Fri, 10 Apr 2020 15:27:52 +0200 Subject: [PATCH 20/57] Fixed shellcheck errors. --- shflags_defines_test.sh | 28 ++++++++++++++-------------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/shflags_defines_test.sh b/shflags_defines_test.sh index 2c2ad81..7f5baf7 100755 --- a/shflags_defines_test.sh +++ b/shflags_defines_test.sh @@ -30,28 +30,28 @@ testFlagsDefine() { # No arguments. if _flags_define >"${stdoutF}" 2>"${stderrF}" then :; else - assertEquals '_flags_define() with no arguments should error' ${FLAGS_ERROR} $? + assertEquals '_flags_define() with no arguments should error' "${FLAGS_ERROR}" $? fi assertErrorMsg '' 'no arguments' # One argument. if _flags_define arg1 >"${stdoutF}" 2>"${stderrF}" then :; else - assertEquals '_flags_define() call with one argument should error' ${FLAGS_ERROR} $? + assertEquals '_flags_define() call with one argument should error' "${FLAGS_ERROR}" $? fi assertErrorMsg '' 'one argument' # Two arguments. if _flags_define arg1 arg2 >"${stdoutF}" 2>"${stderrF}" then :; else - assertEquals '_flags_define() call with two arguments should error' ${FLAGS_ERROR} $? + assertEquals '_flags_define() call with two arguments should error' "${FLAGS_ERROR}" $? fi assertErrorMsg '' 'two arguments' # Three arguments. if _flags_define arg1 arg2 arg3 >"${stdoutF}" 2>"${stderrF}" then :; else - assertEquals '_flags_define() call with three arguments should error' ${FLAGS_ERROR} $? + assertEquals '_flags_define() call with three arguments should error' "${FLAGS_ERROR}" $? fi assertErrorMsg '' 'three arguments' @@ -61,7 +61,7 @@ testFlagsDefine() { fi if _flags_define "${__FLAGS_TYPE_BOOLEAN}" multiDefBool false 'multi def #2' m >"${stdoutF}" 2>"${stderrF}" then :; else - assertEquals '_flags_define() with existing flag name should fail' ${FLAGS_FALSE} $? + assertEquals '_flags_define() with existing flag name should fail' "${FLAGS_FALSE}" $? fi assertTrue '_flags_define() should not overwrite previously defined default.' "${FLAGS_multiDefBool:-}" assertWarnMsg '' 'existing flag' @@ -72,7 +72,7 @@ testFlagsDefine() { fi if _flags_define "${__FLAGS_TYPE_STRING}" long_name 'bar' 'underscored name' l >"${stdoutF}" 2>"${stderrF}" then :; else - assertEquals '_flags_define() with duplicate dashed and underscored definition should fail' ${FLAGS_FALSE} $? + assertEquals '_flags_define() with duplicate dashed and underscored definition should fail' "${FLAGS_FALSE}" $? fi # shellcheck disable=SC2154 assertEquals '_flags_define() should not overwrite previously defined default.' "${FLAGS_long_name}" 'foo' @@ -83,7 +83,7 @@ testFlagsDefine() { # Invalid type. if _flags_define invalid arg2 arg3 arg4 i >"${stdoutF}" 2>"${stderrF}" then :; else - assertEquals '_flags_define() with "invalid" type should have failed.' ${FLAGS_ERROR} $? + assertEquals '_flags_define() with "invalid" type should have failed.' "${FLAGS_ERROR}" $? fi assertErrorMsg 'unrecognized flag type' 'invalid type' } @@ -97,7 +97,7 @@ testBoolean() { assertEquals "${desc}: incorrect FLAGS_boolVal value" "${FLAGS_boolVal:-}" "${want}" else got=$? - if [ "${ok}" -eq ${FLAGS_TRUE} ]; then + if [ "${ok}" -eq "${FLAGS_TRUE}" ]; then assertEquals "${desc}: DEFINE_boolean() failed unexpectedly" "${want}" "${got}" else assertEquals "${desc}: DEFINE_boolean() expected different return value" "${want}" "${got}" @@ -125,7 +125,7 @@ testFloat() { got="${FLAGS_floatVal:-}" want="${default}" assertEquals "${desc}: incorrect FLAGS_floatVal value" "${want}" "${got}" else - assertEquals "${desc}: DEFINE_float() failed unexpectedly." ${FLAGS_TRUE} $? + assertEquals "${desc}: DEFINE_float() failed unexpectedly." "${FLAGS_TRUE}" $? fi done @@ -137,7 +137,7 @@ testFloat() { then fail "${desc}: expected DEFINE_float() to fail" else - assertEquals "${desc}: DEFINE_float() expected error" ${FLAGS_ERROR} $? + assertEquals "${desc}: DEFINE_float() expected error" "${FLAGS_ERROR}" $? assertErrorMsg fi done @@ -153,7 +153,7 @@ testInteger() { got="${FLAGS_intVal:-}" want="${default}" assertEquals "${desc}: incorrect FLAGS_intVal value" "${want}" "${got}" else - assertEquals "${desc}: DEFINE_integer() failed unexpectedly." ${FLAGS_TRUE} $? + assertEquals "${desc}: DEFINE_integer() failed unexpectedly." "${FLAGS_TRUE}" $? fi done @@ -165,7 +165,7 @@ testInteger() { then fail "${desc}: expected DEFINE_integer() to fail" else - assertEquals "${desc}: DEFINE_integer() expected error." ${FLAGS_ERROR} $? + assertEquals "${desc}: DEFINE_integer() expected error." "${FLAGS_ERROR}" $? assertErrorMsg fi done @@ -182,7 +182,7 @@ testString() { got="${FLAGS_strVal:-}" want="${default}" assertEquals "${desc}: incorrect FLAGS_strVal value" "${want}" "${got}" else - assertEquals "${desc}: DEFINE_string() failed unexpectedly." ${FLAGS_TRUE} $? + assertEquals "${desc}: DEFINE_string() failed unexpectedly." "${FLAGS_TRUE}" $? fi done @@ -199,7 +199,7 @@ testFlagNameIsReserved() { then fail "expected DEFINE with reserved flag name to fail" else - assertEquals "expected error from DEFINE with reserved flag" ${FLAGS_ERROR} $? + assertEquals "expected error from DEFINE with reserved flag" "${FLAGS_ERROR}" $? assertErrorMsg 'flag name (TRUE) is reserved' fi } From a9d47d6eb855c1bf7d13cc477271a7ea1a659f5d Mon Sep 17 00:00:00 2001 From: Kate Ward Date: Sun, 29 Mar 2020 18:28:56 +0200 Subject: [PATCH 21/57] Fixed recent test failures, and a shunit2 bug. --- lib/shunit2 | 2 +- shflags_defines_test.sh | 3 +++ shflags_parsing_test.sh | 33 ++++++++++++++++++++++----------- 3 files changed, 26 insertions(+), 12 deletions(-) diff --git a/lib/shunit2 b/lib/shunit2 index a093463..530b2d6 100755 --- a/lib/shunit2 +++ b/lib/shunit2 @@ -948,13 +948,13 @@ EOF _shunit_cleanup() { _shunit_name_=$1 + _shunit_signal_=0 case "${_shunit_name_}" in EXIT) ;; INT) _shunit_signal_=130 ;; # 2+128 TERM) _shunit_signal_=143 ;; # 15+128 *) _shunit_error "unrecognized trap value (${_shunit_name_})" - _shunit_signal_=0 ;; esac if (command [ "${_shunit_name_}" != 'EXIT' ]); then diff --git a/shflags_defines_test.sh b/shflags_defines_test.sh index e4582b5..f2e1d71 100755 --- a/shflags_defines_test.sh +++ b/shflags_defines_test.sh @@ -13,6 +13,9 @@ # Disable source following. # shellcheck disable=SC1090,SC1091 +# Exit immediately if a simple command exits with a non-zero status. +#set -e + # These variables will be overridden by the test helpers. stdoutF="${TMPDIR:-/tmp}/STDOUT" stderrF="${TMPDIR:-/tmp}/STDERR" diff --git a/shflags_parsing_test.sh b/shflags_parsing_test.sh index ce7d151..a972508 100755 --- a/shflags_parsing_test.sh +++ b/shflags_parsing_test.sh @@ -41,7 +41,8 @@ testGetoptStandard() { } testGetoptEnhanced() { - flags_getoptIsEnh || return + flags_getoptIsEnh + [ $? -eq ${FLAGS_FALSE} ] && return _flags_getoptEnhanced '-b' >"${stdoutF}" 2>"${stderrF}" assertTrue "didn't parse valid flag 'b'" $? @@ -87,7 +88,8 @@ testValidBoolsShort() # TODO(kate): separate into multiple functions to reflect correct usage testValidBoolsLong() { - flags_getoptIsEnh || return + flags_getoptIsEnh + [ $? -eq ${FLAGS_FALSE} ] && return # Note: the default value of bool is 'false'. @@ -118,7 +120,8 @@ testValidBoolsLong() { testValidFloats() { _testValidFloats '-f' - flags_getoptIsEnh || return + flags_getoptIsEnh + [ $? -eq ${FLAGS_FALSE} ] && return _testValidFloats '--float' } @@ -139,7 +142,8 @@ _testValidFloats() { testInvalidFloats() { _testInvalidFloats '-f' - flags_getoptIsEnh || return + flags_getoptIsEnh + [ $? -eq ${FLAGS_FALSE} ] && return _testInvalidFloats '--float' } @@ -160,7 +164,8 @@ _testInvalidFloats() testValidIntegers() { _testValidIntegers '-i' - flags_getoptIsEnh || return + flags_getoptIsEnh + [ $? -eq ${FLAGS_FALSE} ] && return _testValidIntegers '--int' } @@ -179,7 +184,8 @@ _testValidIntegers() { testInvalidIntegers() { _testInvalidIntegers '-i' - flags_getoptIsEnh || return + flags_getoptIsEnh + [ $? -eq ${FLAGS_FALSE} ] && return _testInvalidIntegers '--int' } @@ -227,7 +233,8 @@ _testValidStrings() testMultipleFlags() { _testMultipleFlags '-b' '-i' '-f' '-s' - flags_getoptIsEnh || return + flags_getoptIsEnh + [ $? -eq ${FLAGS_FALSE} ] && return _testMultipleFlags '--bool' '--int' '--float' '--str' } @@ -277,13 +284,15 @@ testMultipleNonFlagArgs() { testMultipleNonFlagStringArgsWithSpaces() { - flags_getoptIsEnh || return + flags_getoptIsEnh + [ $? -eq ${FLAGS_FALSE} ] && return _testNonFlagArgs 3 argOne 'arg two' arg3 } testFlagsWithEquals() { - flags_getoptIsEnh || return + flags_getoptIsEnh + [ $? -eq ${FLAGS_FALSE} ] && return FLAGS --str='str_flag' 'non_flag' >"${stdoutF}" 2>"${stderrF}" assertTrue 'FLAGS returned a non-zero result' $? @@ -296,7 +305,8 @@ testFlagsWithEquals() } testComplicatedCommandLineStandard() { - flags_getoptIsEnh && return + flags_getoptIsEnh + [ $? -eq ${FLAGS_TRUE} ] && return # Note: standard getopt stops parsing after first non-flag argument, which # results in the remaining flags being treated as arguments instead. @@ -312,7 +322,8 @@ testComplicatedCommandLineStandard() { } testComplicatedCommandLineEnhanced() { - flags_getoptIsEnh || return + flags_getoptIsEnh + [ $? -eq ${FLAGS_FALSE} ] && return FLAGS -i 1 non_flag_1 --str='two' non_flag_2 --float 3 'non flag 3' \ >"${stdoutF}" 2>"${stderrF}" From b53d9258306fe6b733917ab0f4dba976cd14fb01 Mon Sep 17 00:00:00 2001 From: Kate Ward Date: Fri, 10 Apr 2020 15:30:56 +0200 Subject: [PATCH 22/57] Try testing with multiple linux distros. --- .travis.yml | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/.travis.yml b/.travis.yml index a1b2c4b..19174a9 100644 --- a/.travis.yml +++ b/.travis.yml @@ -9,8 +9,6 @@ script: os: - linux - - dist: bionic - - dist: xenial - osx addons: @@ -21,6 +19,12 @@ addons: matrix: include: + - os: linux + # Ubuntu Bionic 18.04 + dist: bionic + - os: linux + # Ubuntu Xenial 16.04 + dist: xenial - os: linux script: # Run the source through ShellCheck (http://www.shellcheck.net). From e39b814be50be07a78f53408080be80fdd0dabcd Mon Sep 17 00:00:00 2001 From: Kate Ward Date: Sun, 29 Mar 2020 23:59:46 +0200 Subject: [PATCH 23/57] Reworked to fix test failures on both macOS and Linux. --- shflags | 4 ++-- shflags_public_test.sh | 6 ++++-- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/shflags b/shflags index 05c0f80..74d6d9a 100644 --- a/shflags +++ b/shflags @@ -1060,7 +1060,7 @@ flags_getoptInfo() { # Returns: # bool: true if getopt is the enhanced version flags_getoptIsEnh() { - test "${__FLAGS_GETOPT_VERS}" -eq "${__FLAGS_GETOPT_VERS_ENH}" + test ${__FLAGS_GETOPT_VERS} -eq ${__FLAGS_GETOPT_VERS_ENH} } # Returns whether the detected getopt version is the standard version. @@ -1070,7 +1070,7 @@ flags_getoptIsEnh() { # Returns: # bool: true if getopt is the standard version flags_getoptIsStd() { - test "${__FLAGS_GETOPT_VERS}" -eq "${__FLAGS_GETOPT_VERS_STD}" + test ${__FLAGS_GETOPT_VERS} -eq ${__FLAGS_GETOPT_VERS_STD} } # This is effectively a 'usage()' function. It prints usage information and diff --git a/shflags_public_test.sh b/shflags_public_test.sh index 244d2b8..487f6d0 100755 --- a/shflags_public_test.sh +++ b/shflags_public_test.sh @@ -26,12 +26,12 @@ stderrF="${TMPDIR:-/tmp}/STDERR" testHelp() { _testHelp '-h' - flags_getoptIsEnh - [ $? -eq ${FLAGS_FALSE} ] && return _testHelp '--help' } _testHelp() { + flags_getoptIsEnh || return ${SHUNIT_TRUE} + flag=$1 # Test default help output. @@ -70,6 +70,8 @@ _testHelp() { r3turn=$? assertTrue "help strings containing apostrophes don't work" ${r3turn} [ ${r3turn} -ne ${FLAGS_TRUE} ] && th_showOutput + + return ${SHUNIT_TRUE} } mock_flags_columns() { From cf2b33775ffd514f77673344533814e93aba6628 Mon Sep 17 00:00:00 2001 From: Kate Ward Date: Fri, 10 Apr 2020 15:34:41 +0200 Subject: [PATCH 24/57] Don't test 16.04 twice. --- .travis.yml | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/.travis.yml b/.travis.yml index 19174a9..a470697 100644 --- a/.travis.yml +++ b/.travis.yml @@ -7,10 +7,6 @@ script: # Execute the unit tests. - ./test_runner -os: - - linux - - osx - addons: apt: packages: @@ -25,6 +21,7 @@ matrix: - os: linux # Ubuntu Xenial 16.04 dist: xenial + - os: osx - os: linux script: # Run the source through ShellCheck (http://www.shellcheck.net). From 4b9a380003e8cf09e76aa550b9576fed54624e17 Mon Sep 17 00:00:00 2001 From: Kate Ward Date: Mon, 30 Mar 2020 00:09:16 +0200 Subject: [PATCH 25/57] Fixed ShellCheck warnings. --- shflags | 4 ++-- shflags_public_test.sh | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/shflags b/shflags index 74d6d9a..05c0f80 100644 --- a/shflags +++ b/shflags @@ -1060,7 +1060,7 @@ flags_getoptInfo() { # Returns: # bool: true if getopt is the enhanced version flags_getoptIsEnh() { - test ${__FLAGS_GETOPT_VERS} -eq ${__FLAGS_GETOPT_VERS_ENH} + test "${__FLAGS_GETOPT_VERS}" -eq "${__FLAGS_GETOPT_VERS_ENH}" } # Returns whether the detected getopt version is the standard version. @@ -1070,7 +1070,7 @@ flags_getoptIsEnh() { # Returns: # bool: true if getopt is the standard version flags_getoptIsStd() { - test ${__FLAGS_GETOPT_VERS} -eq ${__FLAGS_GETOPT_VERS_STD} + test "${__FLAGS_GETOPT_VERS}" -eq "${__FLAGS_GETOPT_VERS_STD}" } # This is effectively a 'usage()' function. It prints usage information and diff --git a/shflags_public_test.sh b/shflags_public_test.sh index 487f6d0..c08f494 100755 --- a/shflags_public_test.sh +++ b/shflags_public_test.sh @@ -30,7 +30,7 @@ testHelp() { } _testHelp() { - flags_getoptIsEnh || return ${SHUNIT_TRUE} + flags_getoptIsEnh || return "${SHUNIT_TRUE}" flag=$1 @@ -71,7 +71,7 @@ _testHelp() { assertTrue "help strings containing apostrophes don't work" ${r3turn} [ ${r3turn} -ne ${FLAGS_TRUE} ] && th_showOutput - return ${SHUNIT_TRUE} + return "${SHUNIT_TRUE}" } mock_flags_columns() { From 0ac7dff1600e55c25520c0e491c851076fe29cb4 Mon Sep 17 00:00:00 2001 From: Kate Ward Date: Fri, 10 Apr 2020 15:43:13 +0200 Subject: [PATCH 26/57] Trying to figure out where the test_runner is failing. --- test_runner | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/test_runner b/test_runner index 0ced69b..6a87c8b 100755 --- a/test_runner +++ b/test_runner @@ -160,7 +160,9 @@ EOF # ${shell_bin} needs word splitting. # shellcheck disable=SC2086 ( exec ${shell_bin} "./${t}" 2>&1; ) - test "${runner_passing_}" -eq ${RUNNER_TRUE} -a $? -eq ${RUNNER_TRUE} + shell_passing=$? + [ "${shell_passing}" -eq "${RUNNER_TRUE}" ] || echo "${shell_bin} not passing" >&2 + test "${runner_passing_}" -eq ${RUNNER_TRUE} -a ${shell_passing} -eq ${RUNNER_TRUE} runner_passing_=$? done done From 059b27fdb1f49882c28508b847f24dbc0a8a0b65 Mon Sep 17 00:00:00 2001 From: Kate Ward Date: Mon, 30 Mar 2020 00:14:39 +0200 Subject: [PATCH 27/57] Fixed ShellCheck warnings. --- shflags_parsing_test.sh | 22 +++++++++++----------- shflags_public_test.sh | 6 +++--- 2 files changed, 14 insertions(+), 14 deletions(-) diff --git a/shflags_parsing_test.sh b/shflags_parsing_test.sh index a972508..1623434 100755 --- a/shflags_parsing_test.sh +++ b/shflags_parsing_test.sh @@ -42,7 +42,7 @@ testGetoptStandard() { testGetoptEnhanced() { flags_getoptIsEnh - [ $? -eq ${FLAGS_FALSE} ] && return + [ $? -eq "${FLAGS_FALSE}" ] && return _flags_getoptEnhanced '-b' >"${stdoutF}" 2>"${stderrF}" assertTrue "didn't parse valid flag 'b'" $? @@ -89,7 +89,7 @@ testValidBoolsShort() # TODO(kate): separate into multiple functions to reflect correct usage testValidBoolsLong() { flags_getoptIsEnh - [ $? -eq ${FLAGS_FALSE} ] && return + [ $? -eq "${FLAGS_FALSE}" ] && return # Note: the default value of bool is 'false'. @@ -121,7 +121,7 @@ testValidBoolsLong() { testValidFloats() { _testValidFloats '-f' flags_getoptIsEnh - [ $? -eq ${FLAGS_FALSE} ] && return + [ $? -eq "${FLAGS_FALSE}" ] && return _testValidFloats '--float' } @@ -143,7 +143,7 @@ testInvalidFloats() { _testInvalidFloats '-f' flags_getoptIsEnh - [ $? -eq ${FLAGS_FALSE} ] && return + [ $? -eq "${FLAGS_FALSE}" ] && return _testInvalidFloats '--float' } @@ -165,7 +165,7 @@ _testInvalidFloats() testValidIntegers() { _testValidIntegers '-i' flags_getoptIsEnh - [ $? -eq ${FLAGS_FALSE} ] && return + [ $? -eq "${FLAGS_FALSE}" ] && return _testValidIntegers '--int' } @@ -185,7 +185,7 @@ _testValidIntegers() { testInvalidIntegers() { _testInvalidIntegers '-i' flags_getoptIsEnh - [ $? -eq ${FLAGS_FALSE} ] && return + [ $? -eq "${FLAGS_FALSE}" ] && return _testInvalidIntegers '--int' } @@ -234,7 +234,7 @@ _testValidStrings() testMultipleFlags() { _testMultipleFlags '-b' '-i' '-f' '-s' flags_getoptIsEnh - [ $? -eq ${FLAGS_FALSE} ] && return + [ $? -eq "${FLAGS_FALSE}" ] && return _testMultipleFlags '--bool' '--int' '--float' '--str' } @@ -285,14 +285,14 @@ testMultipleNonFlagArgs() { testMultipleNonFlagStringArgsWithSpaces() { flags_getoptIsEnh - [ $? -eq ${FLAGS_FALSE} ] && return + [ $? -eq "${FLAGS_FALSE}" ] && return _testNonFlagArgs 3 argOne 'arg two' arg3 } testFlagsWithEquals() { flags_getoptIsEnh - [ $? -eq ${FLAGS_FALSE} ] && return + [ $? -eq "${FLAGS_FALSE}" ] && return FLAGS --str='str_flag' 'non_flag' >"${stdoutF}" 2>"${stderrF}" assertTrue 'FLAGS returned a non-zero result' $? @@ -306,7 +306,7 @@ testFlagsWithEquals() testComplicatedCommandLineStandard() { flags_getoptIsEnh - [ $? -eq ${FLAGS_TRUE} ] && return + [ $? -eq "${FLAGS_TRUE}" ] && return # Note: standard getopt stops parsing after first non-flag argument, which # results in the remaining flags being treated as arguments instead. @@ -323,7 +323,7 @@ testComplicatedCommandLineStandard() { testComplicatedCommandLineEnhanced() { flags_getoptIsEnh - [ $? -eq ${FLAGS_FALSE} ] && return + [ $? -eq "${FLAGS_FALSE}" ] && return FLAGS -i 1 non_flag_1 --str='two' non_flag_2 --float 3 'non flag 3' \ >"${stdoutF}" 2>"${stderrF}" diff --git a/shflags_public_test.sh b/shflags_public_test.sh index c08f494..683b25a 100755 --- a/shflags_public_test.sh +++ b/shflags_public_test.sh @@ -48,7 +48,7 @@ _testHelp() { assertTrue \ 'short request for help should have produced some help output.' \ ${r3turn} - [ ${r3turn} -ne ${FLAGS_TRUE} ] && th_showOutput + [ ${r3turn} -ne "${FLAGS_TRUE}" ] && th_showOutput # Test proper output when FLAGS_HELP set. ( @@ -58,7 +58,7 @@ _testHelp() { (grep 'this is a test' "${stderrF}" >/dev/null) r3turn=$? assertTrue 'setting FLAGS_HELP did not produce expected result' ${r3turn} - [ ${r3turn} -ne ${FLAGS_TRUE} ] && th_showOutput + [ ${r3turn} -ne "${FLAGS_TRUE}" ] && th_showOutput # Test that "'" chars work in help string. ( @@ -69,7 +69,7 @@ _testHelp() { (grep "help string containing a ' char" "${stderrF}" >/dev/null) r3turn=$? assertTrue "help strings containing apostrophes don't work" ${r3turn} - [ ${r3turn} -ne ${FLAGS_TRUE} ] && th_showOutput + [ ${r3turn} -ne "${FLAGS_TRUE}" ] && th_showOutput return "${SHUNIT_TRUE}" } From 08f31006eaa297ee9819e7e16b5c1322d9c6efb1 Mon Sep 17 00:00:00 2001 From: Kate Ward Date: Fri, 10 Apr 2020 15:49:40 +0200 Subject: [PATCH 28/57] Replaced tabs with spaces. --- .githooks/pre-commit.shellcheck | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.githooks/pre-commit.shellcheck b/.githooks/pre-commit.shellcheck index 999195f..99a318c 100755 --- a/.githooks/pre-commit.shellcheck +++ b/.githooks/pre-commit.shellcheck @@ -13,12 +13,12 @@ if ! command -v shellcheck >/dev/null; then fi for f in $(git diff --cached --name-only); do - cmd=':' + cmd=':' case "${f}" in shflags|shflags_test_helpers) cmd="shellcheck -s sh ${f}" ;; *.sh) cmd="shellcheck ${f}" ;; esac if ! ${cmd}; then - echo "shellcheck error for '${f}'" >&2 + echo "shellcheck error for '${f}'" >&2 fi done From 15fe2c78cbb5bee274f2eff43005d0f006cc456f Mon Sep 17 00:00:00 2001 From: Kate Ward Date: Mon, 30 Mar 2020 00:21:12 +0200 Subject: [PATCH 29/57] Limit which branches and tags will be tested. --- .travis.yml | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/.travis.yml b/.travis.yml index f773ce9..66a0c25 100644 --- a/.travis.yml +++ b/.travis.yml @@ -24,3 +24,10 @@ matrix: # Run the source through ShellCheck (http://www.shellcheck.net). - shellcheck *_test.sh - shellcheck -s sh shflags shflags_test_helpers + +branches: + only: + - master + - 1.0.x + # Tags, e.g. v.1.2.3. + - /^v\d+\.\d+(\.\d+)?(-\S*)?$/ From 94878737ced07f4aef92d1c3ba58e9f7ca3927f9 Mon Sep 17 00:00:00 2001 From: Kate Ward Date: Fri, 10 Apr 2020 15:51:33 +0200 Subject: [PATCH 30/57] Added testing of mksh. --- .travis.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.travis.yml b/.travis.yml index a470697..8d82c6a 100644 --- a/.travis.yml +++ b/.travis.yml @@ -11,6 +11,7 @@ addons: apt: packages: - ksh + - mksh - zsh matrix: From 887af19e97b9e4495885a6675c829a22ca86e307 Mon Sep 17 00:00:00 2001 From: Kate Ward Date: Sat, 11 Apr 2020 13:36:54 +0200 Subject: [PATCH 31/57] Pulled from upstream. --- test_runner | 24 ++++++++++++++++++++++-- 1 file changed, 22 insertions(+), 2 deletions(-) diff --git a/test_runner b/test_runner index 07a423d..22aed9e 100755 --- a/test_runner +++ b/test_runner @@ -12,6 +12,20 @@ # This script runs all the unit tests that can be found, and generates a nice # report of the tests. # +### Sample usage: +# +# Run all tests for all shells. +# $ ./test_runner +# +# Run all tests for single shell. +# $ ./test_runner -s /bin/bash +# +# Run single test for all shells. +# $ ./test_runner -t shunit_asserts_test.sh +# +# Run single test for single shell. +# $ ./test_runner -s /bin/bash -t shunit_asserts_test.sh +# ### ShellCheck (http://www.shellcheck.net/) # Disable source following. # shellcheck disable=SC1090,SC1091 @@ -160,7 +174,11 @@ EOF # ${shell_bin} needs word splitting. # shellcheck disable=SC2086 ( exec ${shell_bin} "./${t}" 2>&1; ) - test "${runner_passing_}" -eq ${RUNNER_TRUE} -a $? -eq ${RUNNER_TRUE} + shell_passing=$? + if [ "${shell_passing}" -ne "${RUNNER_TRUE}" ]; then + runner_warn "${shell_bin} not passing" + fi + test "${runner_passing_}" -eq ${RUNNER_TRUE} -a ${shell_passing} -eq ${RUNNER_TRUE} runner_passing_=$? done done @@ -168,4 +186,6 @@ EOF } # Execute main() if this is run in standalone mode (i.e. not from a unit test). -[ -z "${SHUNIT_VERSION}" ] && main "$@" +if [ -z "${SHUNIT_VERSION}" ]; then + main "$@" +fi From 208aea863ed3433ea13697e17f39a31f698feae8 Mon Sep 17 00:00:00 2001 From: Kate Ward Date: Fri, 10 Apr 2020 16:00:15 +0200 Subject: [PATCH 32/57] Fix warning for shells that aren't passing. --- test_runner | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/test_runner b/test_runner index 6a87c8b..93ca521 100755 --- a/test_runner +++ b/test_runner @@ -161,7 +161,9 @@ EOF # shellcheck disable=SC2086 ( exec ${shell_bin} "./${t}" 2>&1; ) shell_passing=$? - [ "${shell_passing}" -eq "${RUNNER_TRUE}" ] || echo "${shell_bin} not passing" >&2 + if [ "${shell_passing}" -ne "${RUNNER_TRUE}" ]; then + runner_warn "${shell_bin} not passing" + fi test "${runner_passing_}" -eq ${RUNNER_TRUE} -a ${shell_passing} -eq ${RUNNER_TRUE} runner_passing_=$? done From 94bbf55362f89f4cd848d2d17c0776d24f5b177f Mon Sep 17 00:00:00 2001 From: Kate Ward Date: Sat, 11 Apr 2020 13:59:51 +0200 Subject: [PATCH 33/57] Pulled from upstream. --- lib/shunit2 | 357 ++++++++++++++++++++++++++++++++-------------------- 1 file changed, 220 insertions(+), 137 deletions(-) diff --git a/lib/shunit2 b/lib/shunit2 index 530b2d6..26f743e 100755 --- a/lib/shunit2 +++ b/lib/shunit2 @@ -19,7 +19,9 @@ # shellcheck disable=SC2003 # Return if shunit2 already loaded. -(command [ -n "${SHUNIT_VERSION:-}" ]) && exit 0 +if test -n "${SHUNIT_VERSION:-}"; then + exit 0 +fi SHUNIT_VERSION='2.1.9pre' # Return values that scripts can use. @@ -27,25 +29,19 @@ SHUNIT_TRUE=0 SHUNIT_FALSE=1 SHUNIT_ERROR=2 -# Logging functions. -_shunit_warn() { - ${__SHUNIT_CMD_ECHO_ESC} \ - "${__shunit_ansi_yellow}shunit2:WARN${__shunit_ansi_none} $*" >&2 -} -_shunit_error() { - ${__SHUNIT_CMD_ECHO_ESC} \ - "${__shunit_ansi_red}shunit2:ERROR${__shunit_ansi_none} $*" >&2 -} -_shunit_fatal() { - ${__SHUNIT_CMD_ECHO_ESC} \ - "${__shunit_ansi_red}shunit2:FATAL${__shunit_ansi_none} $*" >&2 - exit ${SHUNIT_ERROR} -} +# Determine if `builtin` command exists. +__SHUNIT_BUILTIN='builtin' +# shellcheck disable=2039 +if ! ("${__SHUNIT_BUILTIN}" echo 123 >/dev/null 2>&1); then + __SHUNIT_BUILTIN='' +fi # Determine some reasonable command defaults. __SHUNIT_CMD_ECHO_ESC='echo -e' # shellcheck disable=SC2039 -(command [ "`echo -e test`" = '-e test' ]) && __SHUNIT_CMD_ECHO_ESC='echo' +if ${__SHUNIT_BUILTIN} [ "`echo -e test`" = '-e test' ]; then + __SHUNIT_CMD_ECHO_ESC='echo' +fi __SHUNIT_UNAME_S=`uname -s` case "${__SHUNIT_UNAME_S}" in @@ -61,13 +57,25 @@ SHUNIT_CMD_TPUT=${SHUNIT_CMD_TPUT:-${__SHUNIT_CMD_TPUT}} # Enable color output. Options are 'never', 'always', or 'auto'. SHUNIT_COLOR=${SHUNIT_COLOR:-auto} +# Logging functions. +_shunit_warn() { + ${__SHUNIT_CMD_ECHO_ESC} "${__shunit_ansi_yellow}shunit2:WARN${__shunit_ansi_none} $*" >&2 +} +_shunit_error() { + ${__SHUNIT_CMD_ECHO_ESC} "${__shunit_ansi_red}shunit2:ERROR${__shunit_ansi_none} $*" >&2 +} +_shunit_fatal() { + ${__SHUNIT_CMD_ECHO_ESC} "${__shunit_ansi_red}shunit2:FATAL${__shunit_ansi_none} $*" >&2 + exit ${SHUNIT_ERROR} +} + # Specific shell checks. -if (command [ -n "${ZSH_VERSION:-}" ]); then +if ${__SHUNIT_BUILTIN} [ -n "${ZSH_VERSION:-}" ]; then setopt |grep "^shwordsplit$" >/dev/null - if (command [ $? -ne ${SHUNIT_TRUE} ]); then + if ${__SHUNIT_BUILTIN} [ $? -ne ${SHUNIT_TRUE} ]; then _shunit_fatal 'zsh shwordsplit option is required for proper operation' fi - if (command [ -z "${SHUNIT_PARENT:-}" ]); then + if ${__SHUNIT_BUILTIN} [ -z "${SHUNIT_PARENT:-}" ]; then _shunit_fatal "zsh does not pass \$0 through properly. please declare \ \"SHUNIT_PARENT=\$0\" before calling shUnit2" fi @@ -97,12 +105,15 @@ __shunit_constants=`set |grep '^__SHUNIT_' |cut -d= -f1` echo "${__shunit_constants}" |grep '^Binary file' >/dev/null && \ __shunit_constants=`set |grep -a '^__SHUNIT_' |cut -d= -f1` for __shunit_const in ${__shunit_constants}; do - if (command [ -z "${ZSH_VERSION:-}" ]); then + if ${__SHUNIT_BUILTIN} [ -z "${ZSH_VERSION:-}" ]; then readonly "${__shunit_const}" else case ${ZSH_VERSION} in [123].*) readonly "${__shunit_const}" ;; - *) readonly -g "${__shunit_const}" # Declare readonly constants globally. + *) + # Declare readonly constants globally. + # shellcheck disable=SC2039 + readonly -g "${__shunit_const}" esac fi done @@ -145,7 +156,7 @@ __shunit_assertsSkipped=0 # # shellcheck disable=SC2016,SC2089 -_SHUNIT_LINENO_='eval __shunit_lineno=""; if (command [ "${1:-}" = "--lineno" ]); then (command [ -n "$2" ]) && __shunit_lineno="[$2] "; shift 2; fi' +_SHUNIT_LINENO_='eval __shunit_lineno=""; if ${__SHUNIT_BUILTIN} [ "${1:-}" = "--lineno" ]; then if ${__SHUNIT_BUILTIN} [ -n "$2" ]; then __shunit_lineno="[$2] "; fi; shift 2; fi' #----------------------------------------------------------------------------- # Assertion functions. @@ -162,15 +173,17 @@ _SHUNIT_LINENO_='eval __shunit_lineno=""; if (command [ "${1:-}" = "--lineno" ]) assertEquals() { # shellcheck disable=SC2090 ${_SHUNIT_LINENO_} - if (command [ $# -lt 2 -o $# -gt 3 ]); then + if ${__SHUNIT_BUILTIN} [ $# -lt 2 -o $# -gt 3 ]; then _shunit_error "assertEquals() requires two or three arguments; $# given" _shunit_assertFail return ${SHUNIT_ERROR} fi - _shunit_shouldSkip && return ${SHUNIT_TRUE} + if _shunit_shouldSkip; then + return ${SHUNIT_TRUE} + fi shunit_message_=${__shunit_lineno} - if (command [ $# -eq 3 ]); then + if ${__SHUNIT_BUILTIN} [ $# -eq 3 ]; then shunit_message_="${shunit_message_}$1" shift fi @@ -178,7 +191,7 @@ assertEquals() { shunit_actual_=$2 shunit_return=${SHUNIT_TRUE} - if (command [ "${shunit_expected_}" = "${shunit_actual_}" ]); then + if ${__SHUNIT_BUILTIN} [ "${shunit_expected_}" = "${shunit_actual_}" ]; then _shunit_assertPass else failNotEquals "${shunit_message_}" "${shunit_expected_}" "${shunit_actual_}" @@ -202,15 +215,17 @@ _ASSERT_EQUALS_='eval assertEquals --lineno "${LINENO:-}"' assertNotEquals() { # shellcheck disable=SC2090 ${_SHUNIT_LINENO_} - if (command [ $# -lt 2 -o $# -gt 3 ]); then + if ${__SHUNIT_BUILTIN} [ $# -lt 2 -o $# -gt 3 ]; then _shunit_error "assertNotEquals() requires two or three arguments; $# given" _shunit_assertFail return ${SHUNIT_ERROR} fi - _shunit_shouldSkip && return ${SHUNIT_TRUE} + if _shunit_shouldSkip; then + return ${SHUNIT_TRUE} + fi shunit_message_=${__shunit_lineno} - if (command [ $# -eq 3 ]); then + if ${__SHUNIT_BUILTIN} [ $# -eq 3 ]; then shunit_message_="${shunit_message_}$1" shift fi @@ -218,7 +233,7 @@ assertNotEquals() { shunit_actual_=$2 shunit_return=${SHUNIT_TRUE} - if (command [ "${shunit_expected_}" != "${shunit_actual_}" ]); then + if ${__SHUNIT_BUILTIN} [ "${shunit_expected_}" != "${shunit_actual_}" ]; then _shunit_assertPass else failSame "${shunit_message_}" "${shunit_expected_}" "${shunit_actual_}" @@ -242,23 +257,24 @@ _ASSERT_NOT_EQUALS_='eval assertNotEquals --lineno "${LINENO:-}"' assertContains() { # shellcheck disable=SC2090 ${_SHUNIT_LINENO_} - if (command [ $# -lt 2 -o $# -gt 3 ]); then + if ${__SHUNIT_BUILTIN} [ $# -lt 2 -o $# -gt 3 ]; then _shunit_error "assertContains() requires two or three arguments; $# given" _shunit_assertFail return ${SHUNIT_ERROR} fi - _shunit_shouldSkip && return ${SHUNIT_TRUE} + if _shunit_shouldSkip; then + return ${SHUNIT_TRUE} + fi shunit_message_=${__shunit_lineno} - if (command [ $# -eq 3 ]); then + if ${__SHUNIT_BUILTIN} [ $# -eq 3 ]; then shunit_message_="${shunit_message_}$1" shift fi shunit_container_=$1 shunit_content_=$2 - shunit_return=${SHUNIT_TRUE} - if echo "$shunit_container_" | grep -F -- "$shunit_content_" > /dev/null; then + if echo "${shunit_container_}" |grep -F -- "${shunit_content_}" >/dev/null; then _shunit_assertPass else failNotFound "${shunit_message_}" "${shunit_content_}" @@ -282,15 +298,17 @@ _ASSERT_CONTAINS_='eval assertContains --lineno "${LINENO:-}"' assertNotContains() { # shellcheck disable=SC2090 ${_SHUNIT_LINENO_} - if (command [ $# -lt 2 -o $# -gt 3 ]); then + if ${__SHUNIT_BUILTIN} [ $# -lt 2 -o $# -gt 3 ]; then _shunit_error "assertNotContains() requires two or three arguments; $# given" _shunit_assertFail return ${SHUNIT_ERROR} fi - _shunit_shouldSkip && return ${SHUNIT_TRUE} + if _shunit_shouldSkip; then + return ${SHUNIT_TRUE} + fi shunit_message_=${__shunit_lineno} - if (command [ $# -eq 3 ]); then + if ${__SHUNIT_BUILTIN} [ $# -eq 3 ]; then shunit_message_="${shunit_message_}$1" shift fi @@ -321,15 +339,17 @@ _ASSERT_NOT_CONTAINS_='eval assertNotContains --lineno "${LINENO:-}"' assertNull() { # shellcheck disable=SC2090 ${_SHUNIT_LINENO_} - if (command [ $# -lt 1 -o $# -gt 2 ]); then + if ${__SHUNIT_BUILTIN} [ $# -lt 1 -o $# -gt 2 ]; then _shunit_error "assertNull() requires one or two arguments; $# given" _shunit_assertFail return ${SHUNIT_ERROR} fi - _shunit_shouldSkip && return ${SHUNIT_TRUE} + if _shunit_shouldSkip; then + return ${SHUNIT_TRUE} + fi shunit_message_=${__shunit_lineno} - if (command [ $# -eq 2 ]); then + if ${__SHUNIT_BUILTIN} [ $# -eq 2 ]; then shunit_message_="${shunit_message_}$1" shift fi @@ -352,16 +372,18 @@ _ASSERT_NULL_='eval assertNull --lineno "${LINENO:-}"' assertNotNull() { # shellcheck disable=SC2090 ${_SHUNIT_LINENO_} - if (command [ $# -gt 2 ]); then + if ${__SHUNIT_BUILTIN} [ $# -gt 2 ]; then # Allowing 0 arguments as $1 might actually be null. _shunit_error "assertNotNull() requires one or two arguments; $# given" _shunit_assertFail return ${SHUNIT_ERROR} fi - _shunit_shouldSkip && return ${SHUNIT_TRUE} + if _shunit_shouldSkip; then + return ${SHUNIT_TRUE} + fi shunit_message_=${__shunit_lineno} - if (command [ $# -eq 2 ]); then + if ${__SHUNIT_BUILTIN} [ $# -eq 2 ]; then shunit_message_="${shunit_message_}$1" shift fi @@ -387,15 +409,17 @@ _ASSERT_NOT_NULL_='eval assertNotNull --lineno "${LINENO:-}"' assertSame() { # shellcheck disable=SC2090 ${_SHUNIT_LINENO_} - if (command [ $# -lt 2 -o $# -gt 3 ]); then + if ${__SHUNIT_BUILTIN} [ $# -lt 2 -o $# -gt 3 ]; then _shunit_error "assertSame() requires two or three arguments; $# given" _shunit_assertFail return ${SHUNIT_ERROR} fi - _shunit_shouldSkip && return ${SHUNIT_TRUE} + if _shunit_shouldSkip; then + return ${SHUNIT_TRUE} + fi shunit_message_=${__shunit_lineno} - if (command [ $# -eq 3 ]); then + if ${__SHUNIT_BUILTIN} [ $# -eq 3 ]; then shunit_message_="${shunit_message_}$1" shift fi @@ -419,15 +443,17 @@ _ASSERT_SAME_='eval assertSame --lineno "${LINENO:-}"' assertNotSame() { # shellcheck disable=SC2090 ${_SHUNIT_LINENO_} - if (command [ $# -lt 2 -o $# -gt 3 ]); then + if ${__SHUNIT_BUILTIN} [ $# -lt 2 -o $# -gt 3 ]; then _shunit_error "assertNotSame() requires two or three arguments; $# given" _shunit_assertFail return ${SHUNIT_ERROR} fi - _shunit_shouldSkip && return ${SHUNIT_TRUE} + if _shunit_shouldSkip; then + return ${SHUNIT_TRUE} + fi shunit_message_=${__shunit_lineno} - if (command [ $# -eq 3 ]); then + if ${__SHUNIT_BUILTIN} [ $# -eq 3 ]; then shunit_message_="${shunit_message_:-}$1" shift fi @@ -464,15 +490,17 @@ _ASSERT_NOT_SAME_='eval assertNotSame --lineno "${LINENO:-}"' assertTrue() { # shellcheck disable=SC2090 ${_SHUNIT_LINENO_} - if (command [ $# -lt 1 -o $# -gt 2 ]); then + if ${__SHUNIT_BUILTIN} [ $# -lt 1 -o $# -gt 2 ]; then _shunit_error "assertTrue() takes one or two arguments; $# given" _shunit_assertFail return ${SHUNIT_ERROR} fi - _shunit_shouldSkip && return ${SHUNIT_TRUE} + if _shunit_shouldSkip; then + return ${SHUNIT_TRUE} + fi shunit_message_=${__shunit_lineno} - if (command [ $# -eq 2 ]); then + if ${__SHUNIT_BUILTIN} [ $# -eq 2 ]; then shunit_message_="${shunit_message_}$1" shift fi @@ -480,21 +508,24 @@ assertTrue() { # See if condition is an integer, i.e. a return value. shunit_return=${SHUNIT_TRUE} - if (command [ -z "${shunit_condition_}" ]); then + if ${__SHUNIT_BUILTIN} [ -z "${shunit_condition_}" ]; then # Null condition. shunit_return=${SHUNIT_FALSE} elif (expr \( "${shunit_condition_}" + '0' \) '=' "${shunit_condition_}" >/dev/null 2>&1) then # Possible return value. Treating 0 as true, and non-zero as false. - (command [ "${shunit_condition_}" -ne 0 ]) && shunit_return=${SHUNIT_FALSE} + if ${__SHUNIT_BUILTIN} [ "${shunit_condition_}" -ne 0 ]; then + shunit_return=${SHUNIT_FALSE} + fi else # Hopefully... a condition. - (eval "${shunit_condition_}" >/dev/null 2>&1) - (command [ $? -ne 0 ]) && shunit_return=${SHUNIT_FALSE} + if ! eval "${shunit_condition_}" >/dev/null 2>&1; then + shunit_return=${SHUNIT_FALSE} + fi fi # Record the test. - if (command [ ${shunit_return} -eq ${SHUNIT_TRUE} ]); then + if ${__SHUNIT_BUILTIN} [ ${shunit_return} -eq ${SHUNIT_TRUE} ]; then _shunit_assertPass else _shunit_assertFail "${shunit_message_}" @@ -530,15 +561,17 @@ _ASSERT_TRUE_='eval assertTrue --lineno "${LINENO:-}"' assertFalse() { # shellcheck disable=SC2090 ${_SHUNIT_LINENO_} - if (command [ $# -lt 1 -o $# -gt 2 ]); then + if ${__SHUNIT_BUILTIN} [ $# -lt 1 -o $# -gt 2 ]; then _shunit_error "assertFalse() requires one or two arguments; $# given" _shunit_assertFail return ${SHUNIT_ERROR} fi - _shunit_shouldSkip && return ${SHUNIT_TRUE} + if _shunit_shouldSkip; then + return ${SHUNIT_TRUE} + fi shunit_message_=${__shunit_lineno} - if (command [ $# -eq 2 ]); then + if ${__SHUNIT_BUILTIN} [ $# -eq 2 ]; then shunit_message_="${shunit_message_}$1" shift fi @@ -546,21 +579,24 @@ assertFalse() { # See if condition is an integer, i.e. a return value. shunit_return=${SHUNIT_TRUE} - if (command [ -z "${shunit_condition_}" ]); then + if ${__SHUNIT_BUILTIN} [ -z "${shunit_condition_}" ]; then # Null condition. shunit_return=${SHUNIT_TRUE} - elif (expr \( "${shunit_condition_}" + '0' \) '=' "${shunit_condition_}" >/dev/null 2>&1) - then + elif (expr \( "${shunit_condition_}" + '0' \) '=' "${shunit_condition_}" >/dev/null 2>&1); then # Possible return value. Treating 0 as true, and non-zero as false. - (command [ "${shunit_condition_}" -eq 0 ]) && shunit_return=${SHUNIT_FALSE} + if ${__SHUNIT_BUILTIN} [ "${shunit_condition_}" -eq 0 ]; then + shunit_return=${SHUNIT_FALSE} + fi else # Hopefully... a condition. - (eval "${shunit_condition_}" >/dev/null 2>&1) - (command [ $? -eq 0 ]) && shunit_return=${SHUNIT_FALSE} + # shellcheck disable=SC2086 + if eval ${shunit_condition_} >/dev/null 2>&1; then + shunit_return=${SHUNIT_FALSE} + fi fi # Record the test. - if (command [ "${shunit_return}" -eq "${SHUNIT_TRUE}" ]); then + if ${__SHUNIT_BUILTIN} [ "${shunit_return}" -eq "${SHUNIT_TRUE}" ]; then _shunit_assertPass else _shunit_assertFail "${shunit_message_}" @@ -585,14 +621,16 @@ _ASSERT_FALSE_='eval assertFalse --lineno "${LINENO:-}"' fail() { # shellcheck disable=SC2090 ${_SHUNIT_LINENO_} - if (command [ $# -gt 1 ]); then + if ${__SHUNIT_BUILTIN} [ $# -gt 1 ]; then _shunit_error "fail() requires zero or one arguments; $# given" return ${SHUNIT_ERROR} fi - _shunit_shouldSkip && return ${SHUNIT_TRUE} + if _shunit_shouldSkip; then + return ${SHUNIT_TRUE} + fi shunit_message_=${__shunit_lineno} - if (command [ $# -eq 1 ]); then + if ${__SHUNIT_BUILTIN} [ $# -eq 1 ]; then shunit_message_="${shunit_message_}$1" shift fi @@ -616,14 +654,16 @@ _FAIL_='eval fail --lineno "${LINENO:-}"' failNotEquals() { # shellcheck disable=SC2090 ${_SHUNIT_LINENO_} - if (command [ $# -lt 2 -o $# -gt 3 ]); then + if ${__SHUNIT_BUILTIN} [ $# -lt 2 -o $# -gt 3 ]; then _shunit_error "failNotEquals() requires one or two arguments; $# given" return ${SHUNIT_ERROR} fi - _shunit_shouldSkip && return ${SHUNIT_TRUE} + if _shunit_shouldSkip; then + return ${SHUNIT_TRUE} + fi shunit_message_=${__shunit_lineno} - if (command [ $# -eq 3 ]); then + if ${__SHUNIT_BUILTIN} [ $# -eq 3 ]; then shunit_message_="${shunit_message_}$1" shift fi @@ -649,14 +689,16 @@ _FAIL_NOT_EQUALS_='eval failNotEquals --lineno "${LINENO:-}"' failFound() { # shellcheck disable=SC2090 ${_SHUNIT_LINENO_} - if (command [ $# -lt 1 -o $# -gt 2 ]); then + if ${__SHUNIT_BUILTIN} [ $# -lt 1 -o $# -gt 2 ]; then _shunit_error "failFound() requires one or two arguments; $# given" return ${SHUNIT_ERROR} fi - _shunit_shouldSkip && return ${SHUNIT_TRUE} + if _shunit_shouldSkip; then + return ${SHUNIT_TRUE} + fi shunit_message_=${__shunit_lineno} - if (command [ $# -eq 2 ]); then + if ${__SHUNIT_BUILTIN} [ $# -eq 2 ]; then shunit_message_="${shunit_message_}$1" shift fi @@ -680,14 +722,16 @@ _FAIL_FOUND_='eval failFound --lineno "${LINENO:-}"' failNotFound() { # shellcheck disable=SC2090 ${_SHUNIT_LINENO_} - if (command [ $# -lt 1 -o $# -gt 2 ]); then + if ${__SHUNIT_BUILTIN} [ $# -lt 1 -o $# -gt 2 ]; then _shunit_error "failNotFound() requires one or two arguments; $# given" return ${SHUNIT_ERROR} fi - _shunit_shouldSkip && return ${SHUNIT_TRUE} + if _shunit_shouldSkip; then + return ${SHUNIT_TRUE} + fi shunit_message_=${__shunit_lineno} - if (command [ $# -eq 2 ]); then + if ${__SHUNIT_BUILTIN} [ $# -eq 2 ]; then shunit_message_="${shunit_message_}$1" shift fi @@ -710,18 +754,19 @@ _FAIL_NOT_FOUND_='eval failNotFound --lineno "${LINENO:-}"' # actual: string: actual value # Returns: # integer: success (TRUE/FALSE/ERROR constant) -failSame() -{ +failSame() { # shellcheck disable=SC2090 ${_SHUNIT_LINENO_} - if (command [ $# -lt 2 -o $# -gt 3 ]); then + if ${__SHUNIT_BUILTIN} [ $# -lt 2 -o $# -gt 3 ]; then _shunit_error "failSame() requires two or three arguments; $# given" return ${SHUNIT_ERROR} fi - _shunit_shouldSkip && return ${SHUNIT_TRUE} + if _shunit_shouldSkip; then + return ${SHUNIT_TRUE} + fi shunit_message_=${__shunit_lineno} - if (command [ $# -eq 3 ]); then + if ${__SHUNIT_BUILTIN} [ $# -eq 3 ]; then shunit_message_="${shunit_message_}$1" shift fi @@ -748,14 +793,16 @@ _FAIL_SAME_='eval failSame --lineno "${LINENO:-}"' failNotSame() { # shellcheck disable=SC2090 ${_SHUNIT_LINENO_} - if (command [ $# -lt 2 -o $# -gt 3 ]); then + if ${__SHUNIT_BUILTIN} [ $# -lt 2 -o $# -gt 3 ]; then _shunit_error "failNotSame() requires one or two arguments; $# given" return ${SHUNIT_ERROR} fi - _shunit_shouldSkip && return ${SHUNIT_TRUE} + if _shunit_shouldSkip; then + return ${SHUNIT_TRUE} + fi shunit_message_=${__shunit_lineno} - if (command [ $# -eq 3 ]); then + if ${__SHUNIT_BUILTIN} [ $# -eq 3 ]; then shunit_message_="${shunit_message_}$1" shift fi @@ -895,14 +942,15 @@ suite_addTest() { # string: the temporary directory that was created _shunit_mktempDir() { # Try the standard `mktemp` function. - ( exec mktemp -dqt shunit.XXXXXX 2>/dev/null ) && return + if ( exec mktemp -dqt shunit.XXXXXX 2>/dev/null ); then + return + fi # The standard `mktemp` didn't work. Use our own. # shellcheck disable=SC2039 - if (command [ -r '/dev/urandom' -a -x '/usr/bin/od' ]); then - _shunit_random_=`/usr/bin/od -vAn -N4 -tx4 /dev/null` - if (command [ $? -eq 0 ]); then + if _shunit_tput_=`${SHUNIT_CMD_TPUT} colors 2>/dev/null`; then echo "${_shunit_tput_}" else echo 16 @@ -1044,22 +1094,26 @@ _shunit_execSuite() { endSkipping # Execute the per-test setup function. - setUp || _shunit_fatal "setup() returned non-zero return code." + if ! setUp; then + _shunit_fatal "setup() returned non-zero return code." + fi # Execute the test. echo "${__SHUNIT_TEST_PREFIX}${_shunit_test_}" - eval "${_shunit_test_}" - if (command [ $? -ne ${SHUNIT_TRUE} ]); then + # shellcheck disable=SC2086 + if ! eval ${_shunit_test_}; then _shunit_error "${_shunit_test_}() returned non-zero return code." __shunit_testSuccess=${SHUNIT_ERROR} _shunit_incFailedCount fi # Execute the per-test tear-down function. - tearDown || _shunit_fatal "tearDown() returned non-zero return code." + if ! tearDown; then + _shunit_fatal "tearDown() returned non-zero return code." + fi # Update stats. - if (command [ ${__shunit_testSuccess} -eq ${SHUNIT_TRUE} ]); then + if ${__SHUNIT_BUILTIN} [ ${__shunit_testSuccess} -eq ${SHUNIT_TRUE} ]; then __shunit_testsPassed=`expr ${__shunit_testsPassed} + 1` else __shunit_testsFailed=`expr ${__shunit_testsFailed} + 1` @@ -1076,32 +1130,36 @@ _shunit_execSuite() { # Output: # string: the report of successful and failed tests, as well as totals. _shunit_generateReport() { - (command [ "${__shunit_reportGenerated}" -eq ${SHUNIT_TRUE} ]) && return + if ${__SHUNIT_BUILTIN} [ "${__shunit_reportGenerated}" -eq ${SHUNIT_TRUE} ]; then + return + fi _shunit_ok_=${SHUNIT_TRUE} # If no exit code was provided, determine an appropriate one. - (command [ "${__shunit_testsFailed}" -gt 0 \ - -o ${__shunit_testSuccess} -eq ${SHUNIT_FALSE} ]) \ - && _shunit_ok_=${SHUNIT_FALSE} + if ${__SHUNIT_BUILTIN} [ "${__shunit_testsFailed}" -gt 0 -o ${__shunit_testSuccess} -eq ${SHUNIT_FALSE} ]; then + _shunit_ok_=${SHUNIT_FALSE} + fi echo _shunit_msg_="Ran ${__shunit_ansi_cyan}${__shunit_testsTotal}${__shunit_ansi_none}" - if (command [ "${__shunit_testsTotal}" -eq 1 ]); then + if ${__SHUNIT_BUILTIN} [ "${__shunit_testsTotal}" -eq 1 ]; then ${__SHUNIT_CMD_ECHO_ESC} "${_shunit_msg_} test." else ${__SHUNIT_CMD_ECHO_ESC} "${_shunit_msg_} tests." fi - if (command [ ${_shunit_ok_} -eq ${SHUNIT_TRUE} ]); then + if ${__SHUNIT_BUILTIN} [ ${_shunit_ok_} -eq ${SHUNIT_TRUE} ]; then _shunit_msg_="${__shunit_ansi_green}OK${__shunit_ansi_none}" - (command [ "${__shunit_assertsSkipped}" -gt 0 ]) \ - && _shunit_msg_="${_shunit_msg_} (${__shunit_ansi_yellow}skipped=${__shunit_assertsSkipped}${__shunit_ansi_none})" + if ${__SHUNIT_BUILTIN} [ "${__shunit_assertsSkipped}" -gt 0 ]; then + _shunit_msg_="${_shunit_msg_} (${__shunit_ansi_yellow}skipped=${__shunit_assertsSkipped}${__shunit_ansi_none})" + fi else _shunit_msg_="${__shunit_ansi_red}FAILED${__shunit_ansi_none}" _shunit_msg_="${_shunit_msg_} (${__shunit_ansi_red}failures=${__shunit_assertsFailed}${__shunit_ansi_none}" - (command [ "${__shunit_assertsSkipped}" -gt 0 ]) \ - && _shunit_msg_="${_shunit_msg_},${__shunit_ansi_yellow}skipped=${__shunit_assertsSkipped}${__shunit_ansi_none}" + if ${__SHUNIT_BUILTIN} [ "${__shunit_assertsSkipped}" -gt 0 ]; then + _shunit_msg_="${_shunit_msg_},${__shunit_ansi_yellow}skipped=${__shunit_assertsSkipped}${__shunit_ansi_none}" + fi _shunit_msg_="${_shunit_msg_})" fi @@ -1119,7 +1177,9 @@ _shunit_generateReport() { # Returns: # boolean: whether the test should be skipped (TRUE/FALSE constant) _shunit_shouldSkip() { - (command [ ${__shunit_skip} -eq ${SHUNIT_FALSE} ]) && return ${SHUNIT_FALSE} + if test ${__shunit_skip} -eq ${SHUNIT_FALSE}; then + return ${SHUNIT_FALSE} + fi _shunit_assertSkip } @@ -1140,8 +1200,9 @@ _shunit_assertFail() { __shunit_testSuccess=${SHUNIT_FALSE} _shunit_incFailedCount - \[ $# -gt 0 ] && ${__SHUNIT_CMD_ECHO_ESC} \ - "${__shunit_ansi_red}ASSERT:${__shunit_ansi_none}$*" + if ${__SHUNIT_BUILTIN} [ $# -gt 0 ]; then + ${__SHUNIT_CMD_ECHO_ESC} "${__shunit_ansi_red}ASSERT:${__shunit_ansi_none}$*" + fi } # Increment the count of failed asserts. @@ -1153,7 +1214,6 @@ _shunit_incFailedCount() { __shunit_assertsTotal=`expr "${__shunit_assertsTotal}" + 1` } - # Records a skipped test. # # Args: @@ -1163,6 +1223,19 @@ _shunit_assertSkip() { __shunit_assertsTotal=`expr "${__shunit_assertsTotal}" + 1` } +# Dump the current test metrics. +# +# Args: +# none +_shunit_metrics() { + echo "< \ +total: ${__shunit_assertsTotal} \ +passed: ${__shunit_assertsPassed} \ +failed: ${__shunit_assertsFailed} \ +skipped: ${__shunit_assertsSkipped} \ +>" +} + # Prepare a script filename for sourcing. # # Args: @@ -1186,7 +1259,9 @@ _shunit_prepForSourcing() { # Returns: # string: with escaped character(s) _shunit_escapeCharInStr() { - (command [ -n "$2" ]) || return # No point in doing work on an empty string. + if ${__SHUNIT_BUILTIN} [ -z "$2" ]; then + return # No point in doing work on an empty string. + fi # Note: using shorter variable names to prevent conflicts with # _shunit_escapeCharactersInString(). @@ -1207,7 +1282,9 @@ _shunit_escapeCharInStr() { # Returns: # string: with escaped character(s) _shunit_escapeCharactersInString() { - (command [ -n "$1" ]) || return # No point in doing work on an empty string. + if ${__SHUNIT_BUILTIN} [ -z "$1" ]; then + return # No point in doing work on an empty string. + fi _shunit_str_=$1 @@ -1246,13 +1323,14 @@ _shunit_extractTestFunctions() { # # Determine the operating mode. -if (command [ $# -eq 0 -o "${1:-}" = '--' ]); then +if ${__SHUNIT_BUILTIN} [ $# -eq 0 -o "${1:-}" = '--' ]; then __shunit_script=${__SHUNIT_PARENT} __shunit_mode=${__SHUNIT_MODE_SOURCED} else __shunit_script=$1 - (command [ -r "${__shunit_script}" ]) || \ - _shunit_fatal "unable to read from ${__shunit_script}" + if ! ${__SHUNIT_BUILTIN} [ -r "${__shunit_script}" ]; then + _shunit_fatal "unable to read from ${__shunit_script}" + fi __shunit_mode=${__SHUNIT_MODE_STANDALONE} fi @@ -1262,7 +1340,9 @@ __shunit_tmpDir=`_shunit_mktempDir` # Provide a public temporary directory for unit test scripts. # TODO(kward): document this. SHUNIT_TMPDIR="${__shunit_tmpDir}/tmp" -command mkdir "${SHUNIT_TMPDIR}" +if ! command mkdir "${SHUNIT_TMPDIR}"; then + _shunit_fatal "error creating SHUNIT_TMPDIR '${SHUNIT_TMPDIR}'" +fi # Setup traps to clean up after ourselves. trap '_shunit_cleanup EXIT' 0 @@ -1280,20 +1360,21 @@ noexec 2>/dev/null || _shunit_fatal \ 'Please declare TMPDIR with path on partition with exec permission.' # We must manually source the tests in standalone mode. -if (command [ "${__shunit_mode}" = "${__SHUNIT_MODE_STANDALONE}" ]); then +if ${__SHUNIT_BUILTIN} [ "${__shunit_mode}" = "${__SHUNIT_MODE_STANDALONE}" ]; then # shellcheck disable=SC1090 - command . "`_shunit_prepForSourcing \"${__shunit_script}\"`" + ${__SHUNIT_BUILTIN} . "`_shunit_prepForSourcing \"${__shunit_script}\"`" fi # Configure default output coloring behavior. _shunit_configureColor "${SHUNIT_COLOR}" # Execute the oneTimeSetUp function (if it exists). -oneTimeSetUp || \ - _shunit_fatal "oneTimeSetUp() returned non-zero return code." +if ! oneTimeSetUp; then + _shunit_fatal "oneTimeSetUp() returned non-zero return code." +fi # Command line selected tests or suite selected tests -if (command [ "$#" -ge 2 ]); then +if ${__SHUNIT_BUILTIN} [ "$#" -ge 2 ]; then # Argument $1 is either the filename of tests or '--'; either way, skip it. shift # Remaining arguments ($2 .. $#) are assumed to be test function names. @@ -1310,7 +1391,7 @@ else fi # If no tests or suite specified, dynamically build a list of functions. -if (command [ -z "${__shunit_suite}" ]); then +if ${__SHUNIT_BUILTIN} [ -z "${__shunit_suite}" ]; then shunit_funcs_=`_shunit_extractTestFunctions "${__shunit_script}"` for shunit_func_ in ${shunit_funcs_}; do suite_addTest "${shunit_func_}" @@ -1322,12 +1403,14 @@ unset shunit_func_ shunit_funcs_ _shunit_execSuite # Execute the oneTimeTearDown function (if it exists). -oneTimeTearDown || \ - _shunit_fatal "oneTimeTearDown() returned non-zero return code." +if ! oneTimeTearDown; then + _shunit_fatal "oneTimeTearDown() returned non-zero return code." +fi # Generate a report summary. _shunit_generateReport # That's it folks. -(command [ "${__shunit_testsFailed}" -eq 0 ]) -exit $? +if ! ${__SHUNIT_BUILTIN} [ "${__shunit_testsFailed}" -eq 0 ]; then + return ${SHUNIT_FALSE} +fi From 3eab9429cbd1e6c3f54f4bd9a40fa4593943db64 Mon Sep 17 00:00:00 2001 From: Kate Ward Date: Sat, 11 Apr 2020 14:04:43 +0200 Subject: [PATCH 34/57] Modernized the testGetoptStandard function. --- shflags_parsing_test.sh | 21 ++++++++------------- 1 file changed, 8 insertions(+), 13 deletions(-) diff --git a/shflags_parsing_test.sh b/shflags_parsing_test.sh index 1623434..87846f9 100755 --- a/shflags_parsing_test.sh +++ b/shflags_parsing_test.sh @@ -3,7 +3,7 @@ # # shFlags unit test for the flag definition methods # -# Copyright 2008-2017 Kate Ward. All Rights Reserved. +# Copyright 2008-2020 Kate Ward. All Rights Reserved. # Released under the Apache 2.0 license. # # Author: kate.ward@forestent.com (Kate Ward) @@ -16,12 +16,6 @@ # TODO(kward): assert on FLAGS errors # TODO(kward): testNonStandardIFS() -# Exit immediately if a pipeline or subshell exits with a non-zero status. -#set -e - -# Treat unset variables as an error. -set -u - # These variables will be overridden by the test helpers. returnF="${TMPDIR:-/tmp}/return" stdoutF="${TMPDIR:-/tmp}/STDOUT" @@ -31,13 +25,14 @@ stderrF="${TMPDIR:-/tmp}/STDERR" . ./shflags_test_helpers testGetoptStandard() { - _flags_getoptStandard '-b' >"${stdoutF}" 2>"${stderrF}" - rslt=$? - assertTrue "didn't parse valid flag 'b'" ${rslt} - th_showOutput ${rslt} "${stdoutF}" "${stderrF}" + if ! _flags_getoptStandard '-b' >"${stdoutF}" 2>"${stderrF}"; then + fail "didn't parse valid flag 'b'" + th_showOutput ${rslt} "${stdoutF}" "${stderrF}" + fi - _flags_getoptStandard '-x' >"${stdoutF}" 2>"${stderrF}" - assertFalse "parsed invalid flag 'x'" $? + if _flags_getoptStandard '-x' >"${stdoutF}" 2>"${stderrF}"; then + fail "parsed invalid flag 'x'" + fi } testGetoptEnhanced() { From 757447b68f82acf6d837b60dc9556b04052ebf31 Mon Sep 17 00:00:00 2001 From: Kate Ward Date: Sat, 11 Apr 2020 14:06:10 +0200 Subject: [PATCH 35/57] Modernized the testGetoptStandard function. --- shflags_parsing_test.sh | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/shflags_parsing_test.sh b/shflags_parsing_test.sh index 87846f9..e8bc89d 100755 --- a/shflags_parsing_test.sh +++ b/shflags_parsing_test.sh @@ -27,11 +27,12 @@ stderrF="${TMPDIR:-/tmp}/STDERR" testGetoptStandard() { if ! _flags_getoptStandard '-b' >"${stdoutF}" 2>"${stderrF}"; then fail "didn't parse valid flag 'b'" - th_showOutput ${rslt} "${stdoutF}" "${stderrF}" + _showTestOutput fi if _flags_getoptStandard '-x' >"${stdoutF}" 2>"${stderrF}"; then fail "parsed invalid flag 'x'" + _showTestOutput fi } @@ -354,6 +355,9 @@ tearDown() { flags_reset } +# showTestOutput for the most recently run test. +_showTestOutput() { th_showOutput "${SHUNIT_FALSE}" "${stdoutF}" "${stderrF}"; } + # Load and run shUnit2. # shellcheck disable=SC2034 [ -n "${ZSH_VERSION:-}" ] && SHUNIT_PARENT=$0 From 4379bf271cb951def3b69b8631253bcd476a78f1 Mon Sep 17 00:00:00 2001 From: Kate Ward Date: Sat, 11 Apr 2020 13:38:02 +0200 Subject: [PATCH 36/57] Removed unused TH_MY_NAME variable. --- shflags_test_helpers | 4 ---- 1 file changed, 4 deletions(-) diff --git a/shflags_test_helpers b/shflags_test_helpers index 77dbf28..36f651f 100644 --- a/shflags_test_helpers +++ b/shflags_test_helpers @@ -34,10 +34,6 @@ th_warn() { echo "test:WARN $*" >&2; } th_error() { echo "test:ERROR $*" >&2; } th_fatal() { echo "test:FATAL $*" >&2; exit 1; } -# My name. -TH_MY_NAME=`basename "$0"` || th_fatal 'Error executing basename.' -export TH_MY_NAME - # Path to shFlags library. Can be overridden by setting SHFLAGS_INC. TH_SHFLAGS=${SHFLAGS_INC:-./shflags}; export TH_SHFLAGS From 2ad6555e44864b95e15506b17e59ac739203e7d0 Mon Sep 17 00:00:00 2001 From: Kate Ward Date: Fri, 10 Apr 2020 20:55:18 +0200 Subject: [PATCH 37/57] Fixed minor shell nit. --- init_githooks.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/init_githooks.sh b/init_githooks.sh index 19a380f..3349df4 100755 --- a/init_githooks.sh +++ b/init_githooks.sh @@ -41,7 +41,7 @@ for hook in \ p4-pre-submit \ post-index-change do - echo "- ${hook}" + echo " ${hook}" dest="${hooksPath}/${hook}" ln -sf "${src}" "${dest}" done From f39d1199a2ab917743cc7cf9b10a7279bd23bea2 Mon Sep 17 00:00:00 2001 From: Kate Ward Date: Sat, 11 Apr 2020 14:06:34 +0200 Subject: [PATCH 38/57] Enabled "set -e" by default. --- shflags_test_helpers | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/shflags_test_helpers b/shflags_test_helpers index 36f651f..d808d0f 100644 --- a/shflags_test_helpers +++ b/shflags_test_helpers @@ -20,7 +20,10 @@ # Disagree with [ p ] && [ q ] vs [ p -a -q ] recommendation. # shellcheck disable=SC2166 -# Treat unset variables as an error. +# Exit immediately if a simple command exits with a non-zero status. +set -e + +# Treat unset variables as an error when performing parameter expansion. set -u # Set shwordsplit for zsh. From 800dbce950b77ef20c921fa02c308e2e5f9a156f Mon Sep 17 00:00:00 2001 From: Kate Ward Date: Sat, 11 Apr 2020 20:21:26 +0200 Subject: [PATCH 39/57] Fixes to th_showOutput(). --- shflags_test_helpers | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/shflags_test_helpers b/shflags_test_helpers index d808d0f..9b8e41e 100644 --- a/shflags_test_helpers +++ b/shflags_test_helpers @@ -70,22 +70,26 @@ th_oneTimeSetUp() { } th_showOutput() { - _th_rtrn="${1:-${returnF}}" + if isSkipping; then + return + fi + + _th_return="${1:-${returnF}}" _th_stdout="${2:-${stdoutF}}" _th_stderr="${3:-${stderrF}}" - isSkipping - if [ $? -eq "${SHUNIT_FALSE}" -a "${_th_rtrn}" != "${FLAGS_TRUE}" ]; then + if [ "${_th_return}" != "${FLAGS_TRUE}" ]; then + # shellcheck disable=SC2166 if [ -n "${_th_stdout}" -a -s "${_th_stdout}" ]; then echo '>>> STDOUT' >&2 cat "${_th_stdout}" >&2 + echo '<<< STDOUT' >&2 fi + # shellcheck disable=SC2166 if [ -n "${_th_stderr}" -a -s "${_th_stderr}" ]; then echo '>>> STDERR' >&2 cat "${_th_stderr}" >&2 - fi - if [ -n "${_th_stdout}" -o -n "${_th_stderr}" ]; then - echo '<<< end output' >&2 + echo '<<< STDERR' >&2 fi fi From c2543931181413acebc1b98e12a6a3f69626008c Mon Sep 17 00:00:00 2001 From: Kate Ward Date: Sat, 11 Apr 2020 20:22:47 +0200 Subject: [PATCH 40/57] More set -e fixes. --- shflags | 9 +- shflags_parsing_test.sh | 246 ++++++++++++++++++---------------------- 2 files changed, 115 insertions(+), 140 deletions(-) diff --git a/shflags b/shflags index b2b809b..337c39f 100644 --- a/shflags +++ b/shflags @@ -1002,8 +1002,9 @@ DEFINE_string() { _flags_define ${__FLAGS_TYPE_STRING} "$@"; } # integer: success of operation, or error FLAGS() { # Define a standard 'help' flag if one isn't already defined. - [ -z "${__flags_help_type:-}" ] && \ - DEFINE_boolean 'help' false 'show this help' 'h' + if [ -z "${__flags_help_type:-}" ]; then + DEFINE_boolean 'help' false 'show this help' 'h' + fi # Parse options. if [ $# -gt 0 ]; then @@ -1024,7 +1025,9 @@ FLAGS() { flags_return=$? fi - [ ${flags_return} -eq ${FLAGS_ERROR} ] && _flags_fatal "${flags_error}" + if [ ${flags_return} -eq ${FLAGS_ERROR} ]; then + _flags_fatal "${flags_error}" + fi return ${flags_return} } diff --git a/shflags_parsing_test.sh b/shflags_parsing_test.sh index e8bc89d..46126ed 100755 --- a/shflags_parsing_test.sh +++ b/shflags_parsing_test.sh @@ -26,60 +26,65 @@ stderrF="${TMPDIR:-/tmp}/STDERR" testGetoptStandard() { if ! _flags_getoptStandard '-b' >"${stdoutF}" 2>"${stderrF}"; then - fail "didn't parse valid flag 'b'" + fail "error parsing -b flag" _showTestOutput fi if _flags_getoptStandard '-x' >"${stdoutF}" 2>"${stderrF}"; then - fail "parsed invalid flag 'x'" + fail "expected error parsing invalid -x flag" _showTestOutput fi } testGetoptEnhanced() { - flags_getoptIsEnh - [ $? -eq "${FLAGS_FALSE}" ] && return + if ! flags_getoptIsEnh; then + return + fi - _flags_getoptEnhanced '-b' >"${stdoutF}" 2>"${stderrF}" - assertTrue "didn't parse valid flag 'b'" $? - _flags_getoptEnhanced '--bool' >"${stdoutF}" 2>"${stderrF}" - assertTrue "didn't parse valid flag 'bool'" $? + if ! _flags_getoptEnhanced '-b' >"${stdoutF}" 2>"${stderrF}"; then + fail "error parsing -b flag" + _showTestOutput + fi + if ! _flags_getoptEnhanced '--bool' >"${stdoutF}" 2>"${stderrF}"; then + fail "error parsing --bool flag" + _showTestOutput + fi - _flags_getoptEnhanced '-x' >"${stdoutF}" 2>"${stderrF}" - assertFalse "parsed invalid flag 'x'" $? - _flags_getoptEnhanced '--xyz' >"${stdoutF}" 2>"${stderrF}" - assertFalse "parsed invalid flag 'xyz'" $? + if _flags_getoptEnhanced '-x' >"${stdoutF}" 2>"${stderrF}"; then + fail "expected error parsing invalid -x flag" + _showTestOutput + fi + if _flags_getoptEnhanced '--xyz' >"${stdoutF}" 2>"${stderrF}"; then + fail "expected error parsing invalid --xyz flag" + _showTestOutput + fi } -testValidBoolsShort() -{ - FLAGS -b >"${stdoutF}" 2>"${stderrF}" - r3turn=$? - assertTrue "-b) FLAGS returned a non-zero result (${r3turn})" ${r3turn} - value=${FLAGS_bool:-} - assertTrue "-b) boolean was not true (${value})." "${value}" - assertFalse '-b) expected no output to STDERR' "[ -s '${stderrF}' ]" - test ${r3turn} -eq "${FLAGS_TRUE}" -a ! -s "${stderrF}" - th_showOutput $? "${stdoutF}" "${stderrF}" +testValidBoolsShort() { + desc='bool_true_arg' + if FLAGS -b >"${stdoutF}" 2>"${stderrF}"; then + assertTrue "${desc}: expected true value" "${FLAGS_bool:-}" + else + fail "${desc}: FLAGS returned a non-zero result ($?)" + fi + th_showOutput + desc='bool2_defined' DEFINE_boolean bool2 true '2nd boolean' B - FLAGS >"${stdoutF}" 2>"${stderrF}" - r3turn=$? - assertTrue "-B) FLAGS returned a non-zero result (${r3turn})" ${r3turn} - value=${FLAGS_bool2:-} - assertTrue "-B) boolean was not true (${value})" "${value}" - assertFalse '-B) expected no output to STDERR' "[ -s '${stderrF}' ]" - test ${r3turn} -eq "${FLAGS_TRUE}" -a ! -s "${stderrF}" - th_showOutput $? "${stdoutF}" "${stderrF}" - - FLAGS -B >"${stdoutF}" 2>"${stderrF}" - r3turn=$? - assertTrue "-B) FLAGS returned a non-zero result (${r3turn})" ${r3turn} - value=${FLAGS_bool2:-} - assertFalse "-B) boolean was not false (${value})" "${value}" - assertFalse '-B) expected no output to STDERR' "[ -s '${stderrF}' ]" - test ${r3turn} -eq "${FLAGS_TRUE}" -a ! -s "${stderrF}" - th_showOutput $? "${stdoutF}" "${stderrF}" + if FLAGS >"${stdoutF}" 2>"${stderrF}"; then + assertTrue "${desc}: expected true value" "${FLAGS_bool2:-}" + else + fail "${desc}: FLAGS returned a non-zero result ($?)" + fi + th_showOutput + + desc='bool_false_arg' + if FLAGS -B >"${stdoutF}" 2>"${stderrF}"; then + assertFalse "${desc}: expected false value" "${FLAGS_bool2:-}" + else + fail "${desc}: FLAGS returned a non-zero result ($?)" + fi + th_showOutput } # TODO(kate): separate into multiple functions to reflect correct usage @@ -114,117 +119,90 @@ testValidBoolsLong() { th_showOutput ${r3turn} "${stdoutF}" "${stderrF}" } -testValidFloats() { - _testValidFloats '-f' - flags_getoptIsEnh - [ $? -eq "${FLAGS_FALSE}" ] && return - _testValidFloats '--float' +testFloats() { + _testFloats '-f' + if flags_getoptIsEnh; then + _testFloats '--float' + fi } -_testValidFloats() { +_testFloats() { flag=$1 + for value in ${TH_FLOAT_VALID}; do - FLAGS "${flag}" "${value}" >"${stdoutF}" 2>"${stderrF}" - r3turn=$? - assertTrue "FLAGS ${flag} ${value} returned non-zero result (${r3turn})" \ - ${r3turn} - # shellcheck disable=SC2154 - assertEquals "float (${flag} ${value}) test failed." "${value}" "${FLAGS_float}" - assertFalse 'expected no output to STDERR' "[ -s '${stderrF}' ]" - th_showOutput ${r3turn} "${stdoutF}" "${stderrF}" + if FLAGS "${flag}" "${value}" >"${stdoutF}" 2>"${stderrF}"; then + # shellcheck disable=SC2154 + assertEquals "${flag}: incorrect value" "${value}" "${FLAGS_float}" + else + fail "${flag}: unexpected non-zero result ($?)" + th_showOutput + fi done -} -testInvalidFloats() -{ - _testInvalidFloats '-f' - flags_getoptIsEnh - [ $? -eq "${FLAGS_FALSE}" ] && return - _testInvalidFloats '--float' -} - -_testInvalidFloats() -{ - flag=$1 for value in ${TH_FLOAT_INVALID}; do - th_clearReturn - ( - FLAGS "${flag}" "${value}" >"${stdoutF}" 2>"${stderrF}" - echo $? >"${returnF}" - ) - assertFalse "FLAGS (${value}) returned a zero result" "$(th_queryReturn)" - assertFalse 'expected no output to STDOUT' "[ -s '${stdoutF}' ]" - assertTrue 'expected output to STDERR' "[ -s '${stderrF}' ]" + # Wrap FLAGS in () to catch errors. + if (FLAGS "${flag}" "${value}" >"${stdoutF}" 2>"${stderrF}"); then + fail "${flag}: expected a non-zero result" + th_showOutput + else + assertEquals "${flag}: expected an error" $? "${FLAGS_ERROR}" + fi done } -testValidIntegers() { - _testValidIntegers '-i' - flags_getoptIsEnh - [ $? -eq "${FLAGS_FALSE}" ] && return - _testValidIntegers '--int' +testIntegers() { + _testIntegers '-i' + if flags_getoptIsEnh; then + _testIntegers '--int' + fi } -_testValidIntegers() { +_testIntegers() { flag=$1 + for value in ${TH_INT_VALID}; do - FLAGS "${flag}" "${value}" >"${stdoutF}" 2>"${stderrF}" - r3turn=$? - assertTrue "FLAGS (${value}) returned a non-zero result (${r3turn})" ${r3turn} - # shellcheck disable=SC2154 - assertEquals "integer (${value}) test failed." "${value}" "${FLAGS_int}" - assertFalse 'expected no output to STDERR' "[ -s '${stderrF}' ]" - th_showOutput ${r3turn} "${stdoutF}" "${stderrF}" + if FLAGS "${flag}" "${value}" >"${stdoutF}" 2>"${stderrF}"; then + # shellcheck disable=SC2154 + assertEquals "${flag}: incorrect value" "${value}" "${FLAGS_int}" + else + fail "${flag}: unexpected non-zero result ($?)" + th_showOutput + fi done -} -testInvalidIntegers() { - _testInvalidIntegers '-i' - flags_getoptIsEnh - [ $? -eq "${FLAGS_FALSE}" ] && return - _testInvalidIntegers '--int' -} - -_testInvalidIntegers() { - flag=$1 for value in ${TH_INT_INVALID}; do - th_clearReturn - ( - FLAGS "${flag}" "${value}" >"${stdoutF}" 2>"${stderrF}" - echo $? >"${returnF}" - ) - assertFalse "invalid integer (${value}) test returned success." "$(th_queryReturn)" - assertFalse 'expected no output to STDOUT' "[ -s '${stdoutF}' ]" - assertTrue 'expected output to STDERR' "[ -s '${stderrF}' ]" + # Wrap FLAGS in () to catch errors. + if (FLAGS "${flag}" "${value}" >"${stdoutF}" 2>"${stderrF}"); then + fail "${flag}: expected a non-zero result" + th_showOutput + else + assertEquals "${flag}: expected an error" $? "${FLAGS_ERROR}" + fi done } -testValidStrings() { - _testValidStrings -s single_word +testStrings() { + _testStrings 'std_single_word' -s single_word if flags_getoptIsEnh; then - _testValidStrings --str single_word - _testValidStrings --str 'string with spaces' + _testStrings 'enh_single_word' --str single_word + _testStrings 'enh_multi_word' --str 'string with spaces' fi } -_testValidStrings() -{ - flag=$1 - value=$2 +_testStrings() { + desc=$1 + flag=$2 + value=$3 - FLAGS "${flag}" "${value}" >"${stdoutF}" 2>"${stderrF}" - r3turn=$? - assertTrue "'FLAGS ${flag} ${value}' returned a non-zero result (${r3turn})" \ - ${r3turn} - # shellcheck disable=SC2154 - assertEquals "string (${value}) test failed." "${value}" "${FLAGS_str}" - if [ ${r3turn} -eq "${FLAGS_TRUE}" ]; then - assertFalse 'expected no output to STDERR' "[ -s '${stderrF}' ]" + if FLAGS "${flag}" "${value}" >"${stdoutF}" 2>"${stderrF}"; then + # shellcheck disable=SC2154 + assertEquals "${desc}: incorrect value" "${value}" "${FLAGS_str}" else + fail "${desc}: unexpected non-zero result ($?)" # Validate that an error is thrown for unsupported getopt uses. assertFatalMsg '.* spaces in options' + th_showOutput fi - th_showOutput ${r3turn} "${stdoutF}" "${stderrF}" } testMultipleFlags() { @@ -270,25 +248,19 @@ _testNonFlagArgs() { assertEquals 'wrong count of argc arguments returned.' 0 "${FLAGS_ARGC}" } -testSingleNonFlagArg() { - _testNonFlagArgs 1 argOne -} - -testMultipleNonFlagArgs() { - _testNonFlagArgs 3 argOne argTwo arg3 -} +testSingleNonFlagArg() { _testNonFlagArgs 1 argOne; } +testMultipleNonFlagArgs() { _testNonFlagArgs 3 argOne argTwo arg3; } -testMultipleNonFlagStringArgsWithSpaces() -{ - flags_getoptIsEnh - [ $? -eq "${FLAGS_FALSE}" ] && return - _testNonFlagArgs 3 argOne 'arg two' arg3 +testMultipleNonFlagStringArgsWithSpaces() { + if flags_getoptIsEnh; then + _testNonFlagArgs 3 argOne 'arg two' arg3 + fi } -testFlagsWithEquals() -{ - flags_getoptIsEnh - [ $? -eq "${FLAGS_FALSE}" ] && return +testFlagsWithEquals() { + if ! flags_getoptIsEnh; then + return + fi FLAGS --str='str_flag' 'non_flag' >"${stdoutF}" 2>"${stderrF}" assertTrue 'FLAGS returned a non-zero result' $? From 0c6cef6c0b61d8bf4b819a6b5ccb284cdd064211 Mon Sep 17 00:00:00 2001 From: Kate Ward Date: Sat, 11 Apr 2020 20:24:09 +0200 Subject: [PATCH 41/57] Removed unused variable. --- shflags_parsing_test.sh | 1 - 1 file changed, 1 deletion(-) diff --git a/shflags_parsing_test.sh b/shflags_parsing_test.sh index 46126ed..adef50e 100755 --- a/shflags_parsing_test.sh +++ b/shflags_parsing_test.sh @@ -17,7 +17,6 @@ # TODO(kward): testNonStandardIFS() # These variables will be overridden by the test helpers. -returnF="${TMPDIR:-/tmp}/return" stdoutF="${TMPDIR:-/tmp}/STDOUT" stderrF="${TMPDIR:-/tmp}/STDERR" From 9c82decd18d503562e8545c9550a63d9acdfbfb3 Mon Sep 17 00:00:00 2001 From: Kate Ward Date: Sun, 12 Apr 2020 00:25:04 +0200 Subject: [PATCH 42/57] Fixed more set -e errors. --- shflags_private_test.sh | 145 ++++++++++++++++++++++++++-------------- shflags_test_helpers | 24 ++++--- 2 files changed, 108 insertions(+), 61 deletions(-) diff --git a/shflags_private_test.sh b/shflags_private_test.sh index 6490a20..6435925 100755 --- a/shflags_private_test.sh +++ b/shflags_private_test.sh @@ -3,7 +3,7 @@ # # shFlags unit tests for the internal functions. # -# Copyright 2008-2018 Kate Ward. All Rights Reserved. +# Copyright 2008-2020 Kate Ward. All Rights Reserved. # Released under the Apache 2.0 license. # # Author: kate.ward@forestent.com (Kate Ward) @@ -86,35 +86,49 @@ _testGenOptStr() { testGetFlagInfo() { __flags_blah_foobar='1234' - rslt=`_flags_getFlagInfo 'blah' 'foobar'` - assertTrue 'request for valid flag info failed' $? - assertEquals 'invalid flag info returned' "${__flags_blah_foobar}" "${rslt}" - - rslt=`_flags_getFlagInfo 'blah' 'hubbabubba' >"${stdoutF}" 2>"${stderrF}"` - assertEquals 'invalid flag did not result in an error' "${FLAGS_ERROR}" $? - assertErrorMsg 'missing flag info variable' + desc='valid_flag' + if rslt="`_flags_getFlagInfo 'blah' 'foobar'`"; then + assertEquals "${desc}: invalid flag result" "${__flags_blah_foobar}" "${rslt}" + else + fail "${desc}: request for valid flag info failed" + fi + + desc='invalid_flag' + if rslt="`_flags_getFlagInfo 'blah' 'hubbabubba' >"${stdoutF}" 2>"${stderrF}"`"; then + fail "${desc}: expected invalid flag request to fail" + th_showOutput + else + assertEquals "${desc}: expected an error" "${FLAGS_ERROR}" $? + assertErrorMsg "missing flag info variable" + fi } testItemInList() { list='this is a test' # shellcheck disable=SC2162 while read desc item want; do - _flags_itemInList "${item}" "${list}" - got=$? - assertEquals "${desc}: itemInList(${item})" "${got}" "${want}" + if [ ${want} -eq ${FLAGS_TRUE} ]; then + continue + fi + got=${FLAGS_TRUE} + if ! _flags_itemInList "${item}" "${list}"; then + got=${FLAGS_FALSE} + fi + assertEquals "${desc}: itemInList(${item})" "${want}" "${got}" done </dev/null 2>&1; then + got=${FLAGS_FALSE} + fi + assertFalse 'missing math succeeded' "${got}" } testMathBuiltin() { diff --git a/shflags_test_helpers b/shflags_test_helpers index 9b8e41e..f5d2191 100644 --- a/shflags_test_helpers +++ b/shflags_test_helpers @@ -109,27 +109,29 @@ th_queryReturn() { return "${SHUNIT_ERROR}" } +assertWarnMsg() { _th_assertMsg 'WARN' "${1:-}" "${2:-}"; } +assertErrorMsg() { _th_assertMsg 'ERROR' "${1:-}" "${2:-}"; } +assertFatalMsg() { _th_assertMsg 'FATAL' "${1:-}" "${2:-}"; } + _th_assertMsg() { _th_alert_type_=$1 _th_alert_msg_=$2 _th_msg_=$3 case ${_th_alert_type_} in - WARN) _th_alert_str_='a warning' ;; + WARN) _th_alert_str_='a warning' ;; ERROR) _th_alert_str_='an error' ;; FATAL) _th_alert_str_='a fatal' ;; esac - [ -z "${_th_alert_msg_}" ] && _th_alert_msg_='.*' - [ -n "${_th_msg_}" ] && _th_msg_="(${_th_msg_}) " + if [ -z "${_th_alert_msg_}" ]; then + _th_alert_msg_='.*' + fi + if [ -n "${_th_msg_}" ]; then + _th_msg_="(${_th_msg_}) " + fi - grep -- "^flags:${_th_alert_type_} ${_th_alert_msg_}" "${stderrF}" \ - >/dev/null - assertTrue \ - "FLAGS ${_th_msg_}failure did not generate ${_th_alert_str_} message" $? + (grep -- "^flags:${_th_alert_type_} ${_th_alert_msg_}" "${stderrF}" >/dev/null) + assertEquals "FLAGS ${_th_msg_}failure did not generate ${_th_alert_str_} message" "${FLAGS_TRUE}" $? unset _th_alert_type_ _th_alert_msg_ _th_alert_str_ _th_msg_ } - -assertWarnMsg() { _th_assertMsg 'WARN' "${1:-}" "${2:-}"; } -assertErrorMsg() { _th_assertMsg 'ERROR' "${1:-}" "${2:-}"; } -assertFatalMsg() { _th_assertMsg 'FATAL' "${1:-}" "${2:-}"; } From dcaf009a72a27856e1c5273735d8322fa8379c19 Mon Sep 17 00:00:00 2001 From: Kate Ward Date: Sun, 12 Apr 2020 00:36:03 +0200 Subject: [PATCH 43/57] Fixed shellcheck errors. --- shflags_private_test.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/shflags_private_test.sh b/shflags_private_test.sh index 6435925..86e4fdd 100755 --- a/shflags_private_test.sh +++ b/shflags_private_test.sh @@ -107,7 +107,7 @@ testItemInList() { list='this is a test' # shellcheck disable=SC2162 while read desc item want; do - if [ ${want} -eq ${FLAGS_TRUE} ]; then + if [ "${want}" -eq "${FLAGS_TRUE}" ]; then continue fi got=${FLAGS_TRUE} From 5a8c0d6e1b3724ba799b65a663092ff811768561 Mon Sep 17 00:00:00 2001 From: Kate Ward Date: Sun, 12 Apr 2020 00:36:39 +0200 Subject: [PATCH 44/57] Fixed bug that allowed bad commit to succeed. --- .githooks/generic | 9 ++++----- .githooks/pre-commit.shellcheck | 12 ++++++++++++ 2 files changed, 16 insertions(+), 5 deletions(-) diff --git a/.githooks/generic b/.githooks/generic index b1b5cd0..6f903dc 100755 --- a/.githooks/generic +++ b/.githooks/generic @@ -13,7 +13,8 @@ run() { } die() { - echo 'error: hook did not succeed' >&2 + hook=$1 + echo "${hook} hook did not succeed" >&2 exit 1 } @@ -25,10 +26,8 @@ basename=$(basename "$0") for f in $(cd ${githooks} && echo *); do case "${f}" in - pre-commit.*) - # Called by "git commit" with no arguments. - [ "${basename}" = 'pre-commit' ] || continue - run pre-commit "${githooks}/${f}" || die + ${basename}.*) + run ${basename} "${githooks}/${f}" || die "${f}" ;; esac done diff --git a/.githooks/pre-commit.shellcheck b/.githooks/pre-commit.shellcheck index 99a318c..7615d44 100755 --- a/.githooks/pre-commit.shellcheck +++ b/.githooks/pre-commit.shellcheck @@ -7,11 +7,20 @@ # Treat unset variables as an error when performing parameter expansion. set -u +TRUE=0 +FALSE=1 + +die() { + echo "$@" >&2 + exit 1 +} + if ! command -v shellcheck >/dev/null; then echo 'unable to locate shellcheck' >&2 return 0 fi +success=${TRUE} for f in $(git diff --cached --name-only); do cmd=':' case "${f}" in @@ -19,6 +28,9 @@ for f in $(git diff --cached --name-only); do *.sh) cmd="shellcheck ${f}" ;; esac if ! ${cmd}; then + success=${FALSE} echo "shellcheck error for '${f}'" >&2 fi done + +exit ${success} From 3f7f9c0a40764e3e0e0026c92929b5621b3233c5 Mon Sep 17 00:00:00 2001 From: Kate Ward Date: Sun, 12 Apr 2020 00:52:31 +0200 Subject: [PATCH 45/57] Fixed more set -e issues. --- shflags_public_test.sh | 62 ++++++++++++++++++++++++++---------------- 1 file changed, 38 insertions(+), 24 deletions(-) diff --git a/shflags_public_test.sh b/shflags_public_test.sh index 683b25a..ad6eab1 100755 --- a/shflags_public_test.sh +++ b/shflags_public_test.sh @@ -30,7 +30,9 @@ testHelp() { } _testHelp() { - flags_getoptIsEnh || return "${SHUNIT_TRUE}" + if ! flags_getoptIsEnh; then + return + fi flag=$1 @@ -79,7 +81,9 @@ mock_flags_columns() { } testStandardHelpOutput() { - flags_getoptIsStd || startSkipping + if ! flags_getoptIsStd; then + startSkipping + fi DEFINE_boolean test_bool false 'test boolean' b DEFINE_integer test_int 0 'test integer' i @@ -111,21 +115,26 @@ EOF ( _flags_columns() { mock_flags_columns; } FLAGS_HELP=${help}; - FLAGS -h >"${stdoutF}" 2>"${stderrF}" - echo $? >"${returnF}" + # Wrap FLAGS call in if/then/else so 'set -e' works properly. + if FLAGS -h >"${stdoutF}" 2>"${stderrF}"; then + rtrn=$? + else + rtrn=$? + fi + echo "${rtrn}" >"${returnF}" ) - assertFalse \ - 'a call for help should return a non-zero exit code.' \ - "$(th_queryReturn)" + assertFalse 'a call for help should return a non-zero exit code.' "$(th_queryReturn)" - diff "${expectedF}" "${stderrF}" >/dev/null - r3turn=$? - assertTrue 'unexpected help output' ${r3turn} - th_showOutput ${r3turn} "${stdoutF}" "${stderrF}" + if ! diff "${expectedF}" "${stderrF}" >/dev/null; then + fail 'unexpected help output' + th_showOutput + fi } testEnhancedHelpOutput() { - flags_getoptIsEnh || startSkipping + if ! flags_getoptIsEnh; then + startSkipping + fi # shellcheck disable=SC2034 DEFINE_boolean test_bool false 'test boolean' b @@ -162,22 +171,27 @@ EOF ( _flags_columns() { mock_flags_columns; } # shellcheck disable=SC2034 - FLAGS_HELP=${help}; - FLAGS -h >"${stdoutF}" 2>"${stderrF}" - echo $? >"${returnF}" + FLAGS_HELP=${help} + # Wrap FLAGS call in if/then/else so 'set -e' works properly. + if FLAGS -h >"${stdoutF}" 2>"${stderrF}"; then + rtrn=$? + else + rtrn=$? + fi + echo "${rtrn}" >"${returnF}" ) - assertFalse \ - 'a call for help should return a non-zero exit code.' \ - "$(th_queryReturn)" + assertFalse 'a call for help should return a non-zero exit code.' "$(th_queryReturn)" - diff "${expectedF}" "${stderrF}" >/dev/null - differed=$? - assertTrue 'unexpected help output' ${differed} - th_showOutput ${differed} "${stdoutF}" "${stderrF}" + if ! diff "${expectedF}" "${stderrF}" >/dev/null; then + fail 'unexpected help output' + th_showOutput + fi } testNoHelp() { - flags_getoptIsEnh || startSkipping + if ! flags_getoptIsEnh; then + startSkipping + fi ( FLAGS --nohelp >"${stdoutF}" 2>"${stderrF}" ) r3turn=$? @@ -205,7 +219,7 @@ testIssue28() { # shellcheck disable=SC2034 DEFINE_boolean 'force' false '' f - testHelp + testHelp && return } oneTimeSetUp() { From e598075c665c6bd3d4a7ffc1281c4fd945ebe5a0 Mon Sep 17 00:00:00 2001 From: Kate Ward Date: Sun, 12 Apr 2020 14:02:13 +0200 Subject: [PATCH 46/57] Fixed handling of deleted files. --- .githooks/pre-commit.shellcheck | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/.githooks/pre-commit.shellcheck b/.githooks/pre-commit.shellcheck index 7615d44..f218922 100755 --- a/.githooks/pre-commit.shellcheck +++ b/.githooks/pre-commit.shellcheck @@ -22,6 +22,11 @@ fi success=${TRUE} for f in $(git diff --cached --name-only); do + # Check for file deletion. + if [ ! -r "${f}" ]; then + continue + fi + cmd=':' case "${f}" in shflags|shflags_test_helpers) cmd="shellcheck -s sh ${f}" ;; From aba0a5b0758b1e60517f5aff72937139a0b73418 Mon Sep 17 00:00:00 2001 From: Kate Ward Date: Mon, 13 Apr 2020 22:37:49 +0200 Subject: [PATCH 47/57] Pulled from upstream. --- lib/shunit2 | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/shunit2 b/lib/shunit2 index 26f743e..2850370 100755 --- a/lib/shunit2 +++ b/lib/shunit2 @@ -704,7 +704,7 @@ failFound() { fi shunit_message_=${shunit_message_%% } - _shunit_assertFail "${shunit_message_:+${shunit_message_} }Found" + _shunit_assertFail "${shunit_message_:+${shunit_message_} }found" unset shunit_message_ return ${SHUNIT_FALSE} @@ -738,7 +738,7 @@ failNotFound() { shunit_content_=$1 shunit_message_=${shunit_message_%% } - _shunit_assertFail "${shunit_message_:+${shunit_message_} }Not found:<${shunit_content_}>" + _shunit_assertFail "${shunit_message_:+${shunit_message_} }not found:<${shunit_content_}>" unset shunit_message_ shunit_content_ return ${SHUNIT_FALSE} From 0d478a378f9407e92cf65ea5bf5e0ffac8bfc8d5 Mon Sep 17 00:00:00 2001 From: Kate Ward Date: Mon, 13 Apr 2020 22:56:45 +0200 Subject: [PATCH 48/57] Fixed #50. FLAGS_ARGC is no longer exported. Started 1.4.0pre series. --- doc/CHANGES-1.2.md | 2 +- doc/CHANGES-1.4.md | 199 +++++++++++++++++++++++++++++++++++++++++++++ shflags | 3 +- 3 files changed, 201 insertions(+), 3 deletions(-) create mode 100644 doc/CHANGES-1.4.md diff --git a/doc/CHANGES-1.2.md b/doc/CHANGES-1.2.md index 325a3c5..b128eb9 100644 --- a/doc/CHANGES-1.2.md +++ b/doc/CHANGES-1.2.md @@ -1,6 +1,6 @@ # Changes in shFlags -## Changes with 1.2.3pre +## Changes with 1.2.3 Upgraded shUnit2 to 2.1.7. diff --git a/doc/CHANGES-1.4.md b/doc/CHANGES-1.4.md new file mode 100644 index 0000000..5e8cb88 --- /dev/null +++ b/doc/CHANGES-1.4.md @@ -0,0 +1,199 @@ +# Changes in shFlags + +## Changes with 1.4.0pre + +A new series was started due to the major changes required for 'set -e' support. + +Upgraded shUnit2 to 2.1.9pre, which includes 'set -e' support. + +Fixed #9. shFlags now works properly with 'set -e' enabled. + +Fixed #50. The `FLAGS_ARGC` variable is no longer is no longer exported. The variable was marked obsolete in 1.0.3, and it is finally being removed. + +## Changes with 1.2.3 + +Upgraded shUnit2 to 2.1.7. + +Fixed the examples to work again with the new code structure. + +Removed `gen_test_report.sh` as it isn't used anymore. + +Minor fix for `_flags_underscoreName()` to insure POSIX compliance. + +Cleanup of pre-GitHub cruft. + +Fixed bug in `_flags_columns()` where `stty size` sometimes gave unexpected +output, causing the function to not work. + +Replaced `test_runner` with upstream from https://github.com/kward/shlib. + +## Changes with 1.2.2 + +Ran all scripts through [ShellCheck](http://www.shellcheck.net/). + +Replaced `shflags_test.sh` with `test_runner` from +https://github.com/kward/shlib. + +Fixed issue #45. Empty help string causes `shflags_test_issue_28.sh` to fail. + +Continuous integration testing setup with [Travis +CI](https://travis-ci.org/kward/shflags). + +Restructured code to be more GitHub like. + +## Changes with 1.2.1 + +Fixed issue #43. Added support for BusyBox `ash` shell. + +Fixed issues #26, #27. Re-factored `_flags_itemInList()` to use built-ins. + +Fixed issue #31. Documented newline support in FLAGS_HELP. + +Fixed issue #28. DEFINE_boolean misbehaves when help-string is empty. + +Fixed issue #25. Fix some typos. + +## Changes with 1.2.0 + +Changed from the LGPL v2.1 license to the Apache v2.0 license so that others can +include the library or make changes without needing to release the modified +source code as well. + +Moved documentation to Markdown. + +Migrated the code to GitHub as http://code.google.com/ is turning down. + +Fixed issue #10. Usage of `expr` under FreeBSD 7.2 (FreeNAS 0.7.1) and FreeBSD +8.0 that was causing many unit tests to fail. + +Fixed issue where booleans were sometimes mis-configured to require additional +values like other flags. + +Changed `_flags_fatal()` to exit with `FLAGS_ERROR` immediately. + +Fixed issue #11. When help is requested, the help flag is no longer prefixed +with '[no]'. + +Upgraded shUnit2 to 2.1.6. + +Fixed issue #12. Requesting help shouldn't be considered an error. + +Added the ability to override the use of the OS default `getopt` command by +defining the `FLAGS_GETOPT_CMD` variable. + +Updated `gen_test_results.sh` and versions from shUnit2 source. + +Fixed issues# 13, 14. Added support for dashes '-' in long flag names. The +defined flag will still be declared with underscores '\_' due to shell +limitations, so only one of a dashed flag name or an underscored flag name are +allowed, not both. (Backslash on \_ to prevent Markdown formatting.) + +Issue #20. Updated LGPL v2.1 license from +http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt. + +Issue #15. Use `gexpr` instead of `expr` on BSD variants. + +Minor tweaks to make run on FreeBSD 9.1. + +Fixed issue in `shflags_test_public.sh` where screens >80 columns were causing a +test to fail. + +Issue #22. Fixed broken testGetFlagInfo() test. + +Created alternate `validFloat()` and `validInt()` functions that use shell +built-ins where possible to increase performance and reduce the usage of the +`expr` command. + +Added separate built-in and `expr` functions for doing math. + +## Changes with 1.0.3 + +MAJOR CHANGE! `FLAGS_ARGC` is now obsolete, and is replaced by `FLAGS_ARGV`. See +below for more info. + +Fixed issue# 7 where long flags defined with '=' (e.g. `--abc=123`) made it +impossible for the user to know how many non-flag command-line arguments were +available because the value returned by `FLAGS_ARGC` was wrong. The `FLAGS_ARGC` +value is now obsolete, but will be maintained for backwards compatibility. The +new method of getting the non-flag arguments is by executing `eval set -- +"${FLAGS_ARGV}"` after the `FLAGS` call. The arguments will then be available +using the standard shell $#, $@, $\*, $1, etc. variables. (Backslash on \* to +prevent Markdown formatting.) + +Due to above fix for issue# 7, there is now proper support for mixing flags with +non-flag arguments on the command-line. Previously, all non-flag arguments had +to be at the end of the command-line. + +Renamed `_flags_standardGetopt()` and `_flags_enhancedGetopt()` functions to +`_flags_getoptStandard()` and `_flags_getoptEnhanced()`. + +Took out the setting and restoration of the '-u' shell flag to treat unset +variables as an error. No point in having it in this library as it is verified +in the unit tests, and provides basically no benefit. + +Fixed bug under Solaris where the generated help was adding extra 'x' +characters. + +Added checks for reserved flag variables (e.g. `FLAGS_TRUE`). + +Fixed some unset variable bugs. + +Now report the actual `getopt` error if there is one. + +All tests now properly enable skipping based on whether a standard or enhanced +`getopt` is found. + +Added the OS version to OS release for Solaris. + +Fixed `flags_reset()` so it unsets the default value environment vars. + +## Changes with 1.0.2 + +${FLAGS_PARENT} no longer transforms into a constant so that it can be defined +at run time in scripts. + +Added warning about short flags being unsupported when there are problems +parsing the options with `getopt`. + +Add default values to end of description strings. + +Fixed bug that returned an error instead of success when recalling the default +values for empty strings. + +Added warning when a duplicate flag definition is attempted. + +Improved `assert[Warn|Error]Msg()` test helper grepping. + +Replaced shell_versions.sh with a new versions library and created +`gen_test_results.sh` to make releases easier. + +Copied the coding standards from shUnit2, but haven't fully implemented them in +shFlags yet. + +Issue# 1: When a user defines their own `--help` flag, no more warning is thrown +when `FLAGS()` is called stating that the help flag already defined. + +Issue# 2: Passing the `--nohelp` option no longer gives help output. + +Issue# 3: Added support for screen width detection. + +## Changes with 1.0.1 + +Fixed bug where the help output added '[no]' to all flag names + +Added additional example files that are referenced by the documentation. + +Improved `zsh` version and option checking. + +Upgraded shUnit2 to 2.1.4 + +Added unit testing for the help output. + +When including a library (e.g. shflags) in a script, zsh 3.0.8 doesn't actually +execute the code in-line, but later. As such, variables that are defined in the +library cannot be used until functions are called from the main code. This +required the 'help' flag definition to be moved inside the FLAGS command. + +## Changes with 1.0.0 + +This is the first official release, so everything is new. diff --git a/shflags b/shflags index 337c39f..caf523d 100644 --- a/shflags +++ b/shflags @@ -92,7 +92,7 @@ # Return if FLAGS already loaded. if [ -n "${FLAGS_VERSION:-}" ]; then return 0; fi -FLAGS_VERSION='1.2.4pre' +FLAGS_VERSION='1.4.0pre' # Return values that scripts can use. FLAGS_TRUE=0 @@ -770,7 +770,6 @@ _flags_parseGetopt() { # arguments. Its usage was replaced by FLAGS_ARGV, and it is being kept only # for backwards compatibility reasons. FLAGS_ARGC=`_flags_math "$# - 1 - ${_flags_argc_}"` - export FLAGS_ARGC # Handle options. note options with values must do an additional shift. while true; do From 250800261970edad8a084be80cb4bfcc1f07296c Mon Sep 17 00:00:00 2001 From: Kate Ward Date: Mon, 13 Apr 2020 23:00:19 +0200 Subject: [PATCH 49/57] Fixed a couple of potential set -e stragglers. --- shflags | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/shflags b/shflags index caf523d..fa43085 100644 --- a/shflags +++ b/shflags @@ -466,7 +466,9 @@ _flags_genOptStr() { for _flags_name_ in ${__flags_longNames}; do _flags_usName_="`_flags_underscoreName "${_flags_name_}"`" _flags_type_="`_flags_getFlagInfo "${_flags_usName_}" "${__FLAGS_INFO_TYPE}"`" - [ $? -eq ${FLAGS_TRUE} ] || _flags_fatal 'call to _flags_type_ failed' + if [ $? -ne ${FLAGS_TRUE} ]; then + _flags_fatal 'call to _flags_type_ failed' + fi case ${_flags_optStrType_} in ${__FLAGS_OPTSTR_SHORT}) _flags_shortName_="`_flags_getFlagInfo \ @@ -625,7 +627,9 @@ _flags_validBool() { # bool: true if the value is a valid integer _flags_validFloat() { flags_return=${FLAGS_FALSE} - [ -n "$1" ] || return ${flags_return} + if [ -z "$1" ]; then + return ${flags_return} + fi _flags_float_=$1 if _flags_validInt "${_flags_float_}"; then From 4d4410669e8949e372a69609685449d07fea6a90 Mon Sep 17 00:00:00 2001 From: Kate Ward Date: Mon, 13 Apr 2020 23:26:57 +0200 Subject: [PATCH 50/57] Reformatted. --- CONTRIBUTING.md | 60 ++++++++++++++----------------------------------- 1 file changed, 17 insertions(+), 43 deletions(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index cfc4918..55db597 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -1,10 +1,8 @@ # Coding Standards -shFlags is more than just a simple 20 line shell script. It is a pretty -significant library of shell code that at first glance is not that easy to -understand. To improve code readability and usability, some guidelines have been -set down to make the code more understandable for anyone who wants to read or -modify it. +shFlags is more than just a simple 20 line shell script. It is a significant library of shell code that at first glance might not seam easy to understand. To improve code readability and usability, these guidelines are followed to help make the code more understandable for anyone who wants to read or modify it. + +[TOC] ## Function declaration @@ -28,23 +26,18 @@ Each function should be preceded by a header that provides the following: 1. A one-sentence summary of what the function does. -1. (optional) A longer description of what the function does, and perhaps some - special information that helps convey its usage better. - +1. (optional) A longer description of what the function does, and perhaps some special information that helps convey its usage better. + 1. Args: a one-line summary of each argument of the form: `name: type: description` -1. Output: a one-line summary of the output provided. Only output to STDOUT - must be documented, unless the output to STDERR is of significance (i.e. not - just an error message). The output should be of the form: - +1. Output: a one-line summary of the output provided. Only output to STDOUT must be documented, unless the output to STDERR is of significance (i.e. not just an error message). The output should be of the form: + `type: description` -1. Returns: a one-line summary of the value returned. Returns in shell are - always integers, but if the output is a true/false for success (i.e. a - boolean), it should be noted. The output should be of the form: - +1. Returns: a one-line summary of the value returned. Returns in shell are always integers, but if the output is a true/false for success (i.e. a boolean), it should be noted. The output should be of the form: + `type: description` Here is a sample header: @@ -65,18 +58,11 @@ Here is a sample header: ## Variable and function names -All shFlags specific constants, variables, and functions will be prefixed -appropriately with 'flags'. This is to distinguish usage in the shFlags code -from users own scripts so that the shell name space remains predictable to -users. The exceptions here are the standard `assertEquals`, etc. functions. +All shFlags specific constants, variables, and functions will be prefixed appropriately with `flags`. This is to distinguish usage in the shFlags code from users own scripts so that the shell name space remains predictable to users. The exceptions here are the standard `assertEquals`, etc., functions. -All non built-in constants and variables will be surrounded with squiggle -brackets, e.g. `${flags_someVariable}` to improve code readability. +All non built-in constants and variables will be surrounded with squiggle brackets, e.g. `${flags_someVariable}` to improve code readability. -Due to some shells not supporting local variables in functions, care in the -naming and use of variables, both public and private, is very important. -Accidental overriding of the variables can occur easily if care is not taken as -all variables are technically global variables in some shells. +Due to some shells not supporting local variables in functions, care in the naming and use of variables, both public and private, is very important. Accidental overriding of the variables can occur easily if care is not taken as all variables are technically global variables in some shells. Type | Sample -------------------------------- | --------------------- @@ -90,13 +76,9 @@ public function, local variable | `flags_variable_` private function | `_flags_function` private function, local variable | `_flags_variable_` -Where it makes sense to improve readability, variables can have the first letter -of the second and later words capitalized. For example, the local variable name -for the help string length is `flags_helpStrLen_`. +Where it makes sense to improve readability, variables can have the first letter of the second and later words capitalized. For example, the local variable name for the help string length is `flags_helpStrLen_`. -There are three special-case global public variables used. They are used due to -overcome the limitations of shell scoping or to prevent forking. The three -variables are: +There are three special-case global public variables used. They are used due to overcome the limitations of shell scoping or to prevent forking. The three variables are: - `flags_error` - `flags_output` @@ -104,9 +86,7 @@ variables are: ## Local variable cleanup -As many shells do not support local variables, no support for cleanup of -variables is present either. As such, all variables local to a function must be -cleared up with the `unset` built-in command at the end of each function. +As many shells do not support local variables, no support for cleanup of variables is present either. As such, all variables local to a function must be cleared up with the `unset` built-in command at the end of each function. ## Indentation @@ -118,11 +98,7 @@ if [ -z 'some string' ]; then fi ``` -Lines of code have no line limit, although the general preference is to wrap -lines at reasonable boundaries (e.g., between if/then/else clauses). When long -lines are wrapped using the backslash character '\', subsequent lines should be -indented with four (4) spaces so as to differentiate from the standard spacing -of two characters, and tabs may not be used. +Lines of code have no line limit, although the general preference is to wrap lines at reasonable boundaries (e.g., between if/then/else clauses). When long lines are wrapped using the backslash character '\', subsequent lines should be indented with four (4) spaces so as to differentiate from the standard spacing of two characters, and tabs may not be used. ```sh for x in some set of very long set of arguments that make for a very long \ @@ -132,9 +108,7 @@ do done ``` -When a conditional expression is written using the built-in [ command, and that -line must be wrapped, place the control || or && operators on the same line as -the expression where possible, with the list to be executed on its own line. +When a conditional expression is written using the built-in `[` command, and that line must be wrapped, place the control `||` or `&&` operators on the same line as the expression where possible, with the list to be executed on its own line. ```sh [ -n 'some really long expression' -a -n 'some other long expr' ] && \ From 5fd87fe19714b66cf031cb34929c9218e769a44b Mon Sep 17 00:00:00 2001 From: Kate Ward Date: Mon, 13 Apr 2020 23:27:07 +0200 Subject: [PATCH 51/57] Reformatted. --- README.md | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/README.md b/README.md index a6fac74..d26e6f8 100644 --- a/README.md +++ b/README.md @@ -1,9 +1,6 @@ # shFlags README -shFlags is a port of the Google [gflags](http://gflags.github.io/gflags/) -library for Unix shell. The code is written in a way to be as portable as -possible to work across a wide array of Unix variants. It is also tested with -[shUnit2](https://github.com/kward/shunit2) to maintain code quality. +shFlags is a port of the Google [gflags](http://gflags.github.io/gflags/) library for Unix shell. The code is written in a way to be as portable as possible to work across a wide array of Unix variants. It is also tested with [shUnit2](https://github.com/kward/shunit2) to maintain code quality. If you'd like to use shFlags, feel free to read the documentation. https://github.com/kward/shflags/wiki/Documentation12x From 28a8d152d6f42651a8f86656ddea1302476f687f Mon Sep 17 00:00:00 2001 From: Kate Ward Date: Mon, 13 Apr 2020 23:27:46 +0200 Subject: [PATCH 52/57] Reformatted. --- doc/CHANGES-1.3.md | 171 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 171 insertions(+) create mode 100644 doc/CHANGES-1.3.md diff --git a/doc/CHANGES-1.3.md b/doc/CHANGES-1.3.md new file mode 100644 index 0000000..248afe6 --- /dev/null +++ b/doc/CHANGES-1.3.md @@ -0,0 +1,171 @@ +# Changes in shFlags + +## 1.3.x development series + +### Changes with 1.3.0 + +*A new series was started due to the major changes required for 'set -e' support.* + +Upgraded shUnit2 to 2.1.9pre, which includes 'set -e' support. + +Fixed #9. shFlags now works properly with 'set -e' enabled. + +Fixed #50. The `FLAGS_ARGC` variable is no longer is no longer exported. The variable was marked obsolete in 1.0.3, and it is finally being removed. + +--- + +## 1.2.x stable series + +### Changes with 1.2.3 + +Upgraded shUnit2 to 2.1.7. + +Fixed the examples to work again with the new code structure. + +Removed `gen_test_report.sh` as it isn't used anymore. + +Minor fix for `_flags_underscoreName()` to insure POSIX compliance. + +Cleanup of pre-GitHub cruft. + +Fixed bug in `_flags_columns()` where `stty size` sometimes gave unexpected +output, causing the function to not work. + +Replaced `test_runner` with upstream from https://github.com/kward/shlib. + +### Changes with 1.2.2 + +Ran all scripts through [ShellCheck](http://www.shellcheck.net/). + +Replaced `shflags_test.sh` with `test_runner` from https://github.com/kward/shlib. + +Fixed issue #45. Empty help string causes `shflags_test_issue_28.sh` to fail. + +Continuous integration testing setup with [Travis CI](https://travis-ci.org/kward/shflags). + +Restructured code to be more GitHub like. + +### Changes with 1.2.1 + +Fixed issue #43. Added support for BusyBox `ash` shell. + +Fixed issues #26, #27. Re-factored `_flags_itemInList()` to use built-ins. + +Fixed issue #31. Documented newline support in `FLAGS_HELP`. + +Fixed issue #28. `DEFINE_boolean` misbehaves when help-string is empty. + +Fixed issue #25. Fix some typos. + +### Changes with 1.2.0 + +Changed from the LGPL v2.1 license to the Apache v2.0 license so that others can include the library or make changes without needing to release the modified source code as well. + +Moved documentation to Markdown. + +Migrated the code to GitHub as http://code.google.com/ is turning down. + +Fixed issue #10. Usage of `expr` under FreeBSD 7.2 (FreeNAS 0.7.1) and FreeBSD 8.0 that was causing many unit tests to fail. + +Fixed issue where booleans were sometimes mis-configured to require additional values like other flags. + +Changed `_flags_fatal()` to exit with `FLAGS_ERROR` immediately. + +Fixed issue #11. When help is requested, the help flag is no longer prefixed with '[no]'. + +Upgraded shUnit2 to 2.1.6. + +Fixed issue #12. Requesting help shouldn't be considered an error. + +Added the ability to override the use of the OS default `getopt` command by defining the `FLAGS_GETOPT_CMD` variable. + +Updated `gen_test_results.sh` and versions from shUnit2 source. + +Fixed issues #13, #14. Added support for dashes '-' in long flag names. The defined flag will still be declared with underscores '\_' due to shell limitations, so only one of a dashed flag name or an underscored flag name are allowed, not both. (Backslash on _ to prevent Markdown formatting.) + +Issue #20. Updated LGPL v2.1 license from http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt. + +Issue #15. Use `gexpr` instead of `expr` on BSD variants. + +Minor tweaks to make run on FreeBSD 9.1. + +Fixed issue in `shflags_test_public.sh` where screens >80 columns were causing a test to fail. + +Issue #22. Fixed broken `testGetFlagInfo()` test. + +Created alternate `validFloat()` and `validInt()` functions that use shell built-ins where possible to increase performance and reduce the usage of the `expr` command. + +Added separate built-in and `expr` functions for doing math. + +--- + +## 1.0.x stable series + +### Changes with 1.0.3 + +MAJOR CHANGE! `FLAGS_ARGC` is now obsolete, and is replaced by `FLAGS_ARGV`. See below for more info. + +Fixed issue# 7 where long flags defined with '=' (e.g. `--abc=123`) made it impossible for the user to know how many non-flag command-line arguments were available because the value returned by `FLAGS_ARGC` was wrong. The `FLAGS_ARGC` value is now obsolete, but will be maintained for backwards compatibility. The new method of getting the non-flag arguments is by executing `eval set -- "${FLAGS_ARGV}"` after the `FLAGS` call. The arguments will then be available using the standard shell $#, $@, $\*, $1, etc. variables. (Backslash on \* to prevent Markdown formatting.) + +Due to above fix for issue# 7, there is now proper support for mixing flags with non-flag arguments on the command-line. Previously, all non-flag arguments had to be at the end of the command-line. + +Renamed `_flags_standardGetopt()` and `_flags_enhancedGetopt()` functions to `_flags_getoptStandard()` and `_flags_getoptEnhanced()`. + +Took out the setting and restoration of the '-u' shell flag to treat unset variables as an error. No point in having it in this library as it is verified in the unit tests, and provides basically no benefit. + +Fixed bug under Solaris where the generated help was adding extra 'x' characters. + +Added checks for reserved flag variables (e.g. `FLAGS_TRUE`). + +Fixed some unset variable bugs. + +Now report the actual `getopt` error if there is one. + +All tests now properly enable skipping based on whether a standard or enhanced `getopt` is found. + +Added the OS version to OS release for Solaris. + +Fixed `flags_reset()` so it unsets the default value environment vars. + +### Changes with 1.0.2 + +`${FLAGS_PARENT}` no longer transforms into a constant so that it can be defined at run time in scripts. + +Added warning about short flags being unsupported when there are problems +parsing the options with `getopt`. + +Add default values to end of description strings. + +Fixed bug that returned an error instead of success when recalling the default values for empty strings. + +Added warning when a duplicate flag definition is attempted. + +Improved `assert[Warn|Error]Msg()` test helper grepping. + +Replaced shell_versions.sh with a new versions library and created `gen_test_results.sh` to make releases easier. + +Copied the coding standards from shUnit2, but haven't fully implemented them in shFlags yet. + +Issue# 1: When a user defines their own `--help` flag, no more warning is thrown when `FLAGS()` is called stating that the help flag already defined. + +Issue# 2: Passing the `--nohelp` option no longer gives help output. + +Issue# 3: Added support for screen width detection. + +### Changes with 1.0.1 + +Fixed bug where the help output added '[no]' to all flag names + +Added additional example files that are referenced by the documentation. + +Improved `zsh` version and option checking. + +Upgraded shUnit2 to 2.1.4 + +Added unit testing for the help output. + +When including a library (e.g. shflags) in a script, zsh 3.0.8 doesn't actually execute the code in-line, but later. As such, variables that are defined in the library cannot be used until functions are called from the main code. This required the 'help' flag definition to be moved inside the `FLAGS` command. + +### Changes with 1.0.0 + +This is the first official release, so everything is new. From d7c59713a44c2dcbe764a733132a001356cdce32 Mon Sep 17 00:00:00 2001 From: Kate Ward Date: Mon, 13 Apr 2020 23:48:44 +0200 Subject: [PATCH 53/57] Renamed to CHANGES-1.3.md. --- doc/CHANGES-1.4.md | 199 --------------------------------------------- 1 file changed, 199 deletions(-) delete mode 100644 doc/CHANGES-1.4.md diff --git a/doc/CHANGES-1.4.md b/doc/CHANGES-1.4.md deleted file mode 100644 index 5e8cb88..0000000 --- a/doc/CHANGES-1.4.md +++ /dev/null @@ -1,199 +0,0 @@ -# Changes in shFlags - -## Changes with 1.4.0pre - -A new series was started due to the major changes required for 'set -e' support. - -Upgraded shUnit2 to 2.1.9pre, which includes 'set -e' support. - -Fixed #9. shFlags now works properly with 'set -e' enabled. - -Fixed #50. The `FLAGS_ARGC` variable is no longer is no longer exported. The variable was marked obsolete in 1.0.3, and it is finally being removed. - -## Changes with 1.2.3 - -Upgraded shUnit2 to 2.1.7. - -Fixed the examples to work again with the new code structure. - -Removed `gen_test_report.sh` as it isn't used anymore. - -Minor fix for `_flags_underscoreName()` to insure POSIX compliance. - -Cleanup of pre-GitHub cruft. - -Fixed bug in `_flags_columns()` where `stty size` sometimes gave unexpected -output, causing the function to not work. - -Replaced `test_runner` with upstream from https://github.com/kward/shlib. - -## Changes with 1.2.2 - -Ran all scripts through [ShellCheck](http://www.shellcheck.net/). - -Replaced `shflags_test.sh` with `test_runner` from -https://github.com/kward/shlib. - -Fixed issue #45. Empty help string causes `shflags_test_issue_28.sh` to fail. - -Continuous integration testing setup with [Travis -CI](https://travis-ci.org/kward/shflags). - -Restructured code to be more GitHub like. - -## Changes with 1.2.1 - -Fixed issue #43. Added support for BusyBox `ash` shell. - -Fixed issues #26, #27. Re-factored `_flags_itemInList()` to use built-ins. - -Fixed issue #31. Documented newline support in FLAGS_HELP. - -Fixed issue #28. DEFINE_boolean misbehaves when help-string is empty. - -Fixed issue #25. Fix some typos. - -## Changes with 1.2.0 - -Changed from the LGPL v2.1 license to the Apache v2.0 license so that others can -include the library or make changes without needing to release the modified -source code as well. - -Moved documentation to Markdown. - -Migrated the code to GitHub as http://code.google.com/ is turning down. - -Fixed issue #10. Usage of `expr` under FreeBSD 7.2 (FreeNAS 0.7.1) and FreeBSD -8.0 that was causing many unit tests to fail. - -Fixed issue where booleans were sometimes mis-configured to require additional -values like other flags. - -Changed `_flags_fatal()` to exit with `FLAGS_ERROR` immediately. - -Fixed issue #11. When help is requested, the help flag is no longer prefixed -with '[no]'. - -Upgraded shUnit2 to 2.1.6. - -Fixed issue #12. Requesting help shouldn't be considered an error. - -Added the ability to override the use of the OS default `getopt` command by -defining the `FLAGS_GETOPT_CMD` variable. - -Updated `gen_test_results.sh` and versions from shUnit2 source. - -Fixed issues# 13, 14. Added support for dashes '-' in long flag names. The -defined flag will still be declared with underscores '\_' due to shell -limitations, so only one of a dashed flag name or an underscored flag name are -allowed, not both. (Backslash on \_ to prevent Markdown formatting.) - -Issue #20. Updated LGPL v2.1 license from -http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt. - -Issue #15. Use `gexpr` instead of `expr` on BSD variants. - -Minor tweaks to make run on FreeBSD 9.1. - -Fixed issue in `shflags_test_public.sh` where screens >80 columns were causing a -test to fail. - -Issue #22. Fixed broken testGetFlagInfo() test. - -Created alternate `validFloat()` and `validInt()` functions that use shell -built-ins where possible to increase performance and reduce the usage of the -`expr` command. - -Added separate built-in and `expr` functions for doing math. - -## Changes with 1.0.3 - -MAJOR CHANGE! `FLAGS_ARGC` is now obsolete, and is replaced by `FLAGS_ARGV`. See -below for more info. - -Fixed issue# 7 where long flags defined with '=' (e.g. `--abc=123`) made it -impossible for the user to know how many non-flag command-line arguments were -available because the value returned by `FLAGS_ARGC` was wrong. The `FLAGS_ARGC` -value is now obsolete, but will be maintained for backwards compatibility. The -new method of getting the non-flag arguments is by executing `eval set -- -"${FLAGS_ARGV}"` after the `FLAGS` call. The arguments will then be available -using the standard shell $#, $@, $\*, $1, etc. variables. (Backslash on \* to -prevent Markdown formatting.) - -Due to above fix for issue# 7, there is now proper support for mixing flags with -non-flag arguments on the command-line. Previously, all non-flag arguments had -to be at the end of the command-line. - -Renamed `_flags_standardGetopt()` and `_flags_enhancedGetopt()` functions to -`_flags_getoptStandard()` and `_flags_getoptEnhanced()`. - -Took out the setting and restoration of the '-u' shell flag to treat unset -variables as an error. No point in having it in this library as it is verified -in the unit tests, and provides basically no benefit. - -Fixed bug under Solaris where the generated help was adding extra 'x' -characters. - -Added checks for reserved flag variables (e.g. `FLAGS_TRUE`). - -Fixed some unset variable bugs. - -Now report the actual `getopt` error if there is one. - -All tests now properly enable skipping based on whether a standard or enhanced -`getopt` is found. - -Added the OS version to OS release for Solaris. - -Fixed `flags_reset()` so it unsets the default value environment vars. - -## Changes with 1.0.2 - -${FLAGS_PARENT} no longer transforms into a constant so that it can be defined -at run time in scripts. - -Added warning about short flags being unsupported when there are problems -parsing the options with `getopt`. - -Add default values to end of description strings. - -Fixed bug that returned an error instead of success when recalling the default -values for empty strings. - -Added warning when a duplicate flag definition is attempted. - -Improved `assert[Warn|Error]Msg()` test helper grepping. - -Replaced shell_versions.sh with a new versions library and created -`gen_test_results.sh` to make releases easier. - -Copied the coding standards from shUnit2, but haven't fully implemented them in -shFlags yet. - -Issue# 1: When a user defines their own `--help` flag, no more warning is thrown -when `FLAGS()` is called stating that the help flag already defined. - -Issue# 2: Passing the `--nohelp` option no longer gives help output. - -Issue# 3: Added support for screen width detection. - -## Changes with 1.0.1 - -Fixed bug where the help output added '[no]' to all flag names - -Added additional example files that are referenced by the documentation. - -Improved `zsh` version and option checking. - -Upgraded shUnit2 to 2.1.4 - -Added unit testing for the help output. - -When including a library (e.g. shflags) in a script, zsh 3.0.8 doesn't actually -execute the code in-line, but later. As such, variables that are defined in the -library cannot be used until functions are called from the main code. This -required the 'help' flag definition to be moved inside the FLAGS command. - -## Changes with 1.0.0 - -This is the first official release, so everything is new. From 66427f9eab8d19e2c5fda43fbdc743c4db3abba8 Mon Sep 17 00:00:00 2001 From: Kate Ward Date: Mon, 13 Apr 2020 23:51:43 +0200 Subject: [PATCH 54/57] Removed FLAGS_ARGC harder. --- shflags | 17 +++-------------- 1 file changed, 3 insertions(+), 14 deletions(-) diff --git a/shflags b/shflags index fa43085..b54bf5b 100644 --- a/shflags +++ b/shflags @@ -213,7 +213,7 @@ fi # # Reserved flag names. -__FLAGS_RESERVED_LIST=' ARGC ARGV ERROR FALSE GETOPT_CMD HELP PARENT TRUE ' +__FLAGS_RESERVED_LIST=' ARGV ERROR FALSE GETOPT_CMD HELP PARENT TRUE ' __FLAGS_RESERVED_LIST="${__FLAGS_RESERVED_LIST} VERSION " # Determined getopt version (standard or enhanced). @@ -749,14 +749,10 @@ _flags_getoptEnhanced() { # dynamic to support any number of flags. # # Args: -# argc: int: original command-line argument count # @: varies: output from getopt parsing # Returns: # integer: a FLAGS success condition _flags_parseGetopt() { - _flags_argc_=$1 - shift - flags_return=${FLAGS_TRUE} if [ "${__FLAGS_GETOPT_VERS}" -ne "${__FLAGS_GETOPT_VERS_ENH}" ]; then @@ -764,17 +760,10 @@ _flags_parseGetopt() { # shellcheck disable=SC2068 set -- $@ else - # Note the quotes around the `$@' -- they are essential! + # Note the quotes around the `$@` -- they are essential! eval set -- "$@" fi - # Provide user with the number of arguments to shift by later. - # NOTE: the FLAGS_ARGC variable is obsolete as of 1.0.3 because it does not - # properly give user access to non-flag arguments mixed in between flag - # arguments. Its usage was replaced by FLAGS_ARGV, and it is being kept only - # for backwards compatibility reasons. - FLAGS_ARGC=`_flags_math "$# - 1 - ${_flags_argc_}"` - # Handle options. note options with values must do an additional shift. while true; do _flags_opt_=$1 @@ -1024,7 +1013,7 @@ FLAGS() { fi if [ ${flags_return} -eq ${FLAGS_TRUE} ]; then - _flags_parseGetopt $# "${__flags_opts}" + _flags_parseGetopt "${__flags_opts}" flags_return=$? fi From d3e654507e0331fe41e69f0729390523bf93f335 Mon Sep 17 00:00:00 2001 From: Kate Ward Date: Mon, 13 Apr 2020 23:53:37 +0200 Subject: [PATCH 55/57] Removed FLAGS_ARGC harder. --- shflags_parsing_test.sh | 2 -- 1 file changed, 2 deletions(-) diff --git a/shflags_parsing_test.sh b/shflags_parsing_test.sh index adef50e..606d757 100755 --- a/shflags_parsing_test.sh +++ b/shflags_parsing_test.sh @@ -244,7 +244,6 @@ _testNonFlagArgs() { eval set -- "${FLAGS_ARGV}" assertEquals 'wrong count of argv arguments returned.' "${argc}" $# - assertEquals 'wrong count of argc arguments returned.' 0 "${FLAGS_ARGC}" } testSingleNonFlagArg() { _testNonFlagArgs 1 argOne; } @@ -268,7 +267,6 @@ testFlagsWithEquals() { eval set -- "${FLAGS_ARGV}" assertEquals 'wrong count of argv arguments returned.' 1 $# - assertEquals 'wrong count of argc arguments returned.' 1 "${FLAGS_ARGC}" } testComplicatedCommandLineStandard() { From ca7e8a77e8ae621038b81f717b5a4b7880f14d51 Mon Sep 17 00:00:00 2001 From: Kate Ward Date: Mon, 13 Apr 2020 23:58:06 +0200 Subject: [PATCH 56/57] Test with Ubuntu Trusty as well. --- .travis.yml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/.travis.yml b/.travis.yml index 8d82c6a..3329b77 100644 --- a/.travis.yml +++ b/.travis.yml @@ -17,11 +17,11 @@ addons: matrix: include: - os: linux - # Ubuntu Bionic 18.04 - dist: bionic + dist: bionic # Ubuntu Bionic 18.04 (EoL Apr 2028). - os: linux - # Ubuntu Xenial 16.04 - dist: xenial + dist: xenial # Ubuntu Xenial 16.04 (EoL Apr 2024). + - os: linux + dist: trusty # Ubuntu Trusty 14.04 (EoL Apr 2022). - os: osx - os: linux script: From 5a661c21cb175578357989f4eaf7a22be58e3ad2 Mon Sep 17 00:00:00 2001 From: Douglas Brunk Date: Mon, 27 Apr 2020 11:30:09 -0400 Subject: [PATCH 57/57] Reimplement proper escaping for options and arguments. --- shflags | 9 +++- shflags_parsing_quotes_test.sh | 79 ++++++++++++++++++++-------------- 2 files changed, 54 insertions(+), 34 deletions(-) diff --git a/shflags b/shflags index b54bf5b..1b7748a 100644 --- a/shflags +++ b/shflags @@ -894,7 +894,7 @@ _flags_parseGetopt() { # Give user back non-flag arguments. FLAGS_ARGV='' while [ $# -gt 0 ]; do - FLAGS_ARGV="${FLAGS_ARGV:+${FLAGS_ARGV} }'$1'" + FLAGS_ARGV="${FLAGS_ARGV:+${FLAGS_ARGV} } `_flags_escape "$1"`" shift done @@ -903,6 +903,13 @@ _flags_parseGetopt() { return ${flags_return} } +_flags_escape() { + [ -n "${BASH_VERSION:-}" ] && printf "%q\n" "$1" && return 0 + [ -n "${ZSH_VERSION:-}" ]&& printf "%q\n" "$1" && return 0 + [ -n "${KSH_VERSION:-}" ]&& printf "%q\n" "$1" && return 0 + printf "%s\n" "$1" | sed -e "s/'/'\"'\"'/g" -e "1s/^/'/" -e "\$s/\$/'/" +} + # Perform some path using built-ins. # # Args: diff --git a/shflags_parsing_quotes_test.sh b/shflags_parsing_quotes_test.sh index 157d126..fc017ef 100755 --- a/shflags_parsing_quotes_test.sh +++ b/shflags_parsing_quotes_test.sh @@ -30,54 +30,67 @@ stderrF="${TMPDIR:-/tmp}/STDERR" # Load test helpers. . ./shflags_test_helpers +testOptionStringsWithQuotes() { + _testValidOptionStrings -s "Single Quote Flag's Test" + _testValidOptionStrings -s "Double Quote \"Flag\" Test" + _testValidOptionStrings -s "Mixed Quote's \"Flag\" Test" + _testValidOptionStrings -s 'Mixed Quote'\''s "Flag" Test' +} -testStringsWithQuotes() { - _testValidStrings -s "Single Quote Flag's Test" - _testValidStrings -s "Double Quote \"Flag\" Test" - _testValidStrings -s "Mixed Quote's \"Flag\" Test" - _testValidStrings -s 'Mixed Quote'\''s "Flag" Test' +testArgumentStringsWithQuotes() { + _testValidArgumentStrings "Single Quote Flag's Test" + _testValidArgumentStrings "Double Quote \"Flag\" Test" + _testValidArgumentStrings "Mixed Quote's \"Flag\" Test" } -_testValidStrings() -{ - flag=$1 - value=$2 +_testValidOptionStrings() { + flag=$1 + value=$2 - FLAGS "${flag}" "${value}" >"${stdoutF}" 2>"${stderrF}" - r3turn=$? - assertTrue "'FLAGS ${flag} ${value}' returned a non-zero result (${r3turn})" \ - ${r3turn} - # shellcheck disable=SC2154 - assertEquals "string (${value}) test failed." "${value}" "${FLAGS_str}" - if [ ${r3turn} -eq "${FLAGS_TRUE}" ]; then - assertFalse 'expected no output to STDERR' "[ -s '${stderrF}' ]" - else - # Validate that an error is thrown for unsupported getopt uses. - assertFatalMsg '.* spaces in options' - fi - th_showOutput ${r3turn} "${stdoutF}" "${stderrF}" + FLAGS "${flag}" "${value}" >"${stdoutF}" 2>"${stderrF}" + r3turn=$? + assertTrue "'FLAGS ${flag} ${value}' returned a non-zero result (${r3turn})" \ + ${r3turn} + # shellcheck disable=SC2154 + assertEquals "string (${value}) test failed." "${value}" "${FLAGS_str}" + if [ ${r3turn} -eq "${FLAGS_TRUE}" ]; then + assertFalse 'expected no output to STDERR' "[ -s '${stderrF}' ]" + else + # Validate that an error is thrown for unsupported getopt uses. + assertFatalMsg '.* spaces in options' + fi + th_showOutput ${r3turn} "${stdoutF}" "${stderrF}" } +_testValidArgumentStrings() { + quoted_string="$1" + FLAGS "$quoted_string" >"${stdoutF}" 2>"${stderrF}" + r3turn=$? + assertTrue "'FLAGS $quoted_string' returned a non-zero result (${r3turn})" \ + ${r3turn} + eval set -- "${FLAGS_ARGV}" + assertEquals "$quoted_string" "$1" +} oneTimeSetUp() { - th_oneTimeSetUp + th_oneTimeSetUp - if flags_getoptIsStd; then - th_warn 'Standard version of getopt found. Enhanced tests will be skipped.' - else - th_warn 'Enhanced version of getopt found. Standard tests will be skipped.' - fi + if flags_getoptIsStd; then + th_warn 'Standard version of getopt found. Enhanced tests will be skipped.' + else + th_warn 'Enhanced version of getopt found. Standard tests will be skipped.' + fi } setUp() { - DEFINE_boolean bool false 'boolean test' 'b' - DEFINE_float float 0.0 'float test' 'f' - DEFINE_integer int 0 'integer test' 'i' - DEFINE_string str '' 'string test' 's' + DEFINE_boolean bool false 'boolean test' 'b' + DEFINE_float float 0.0 'float test' 'f' + DEFINE_integer int 0 'integer test' 'i' + DEFINE_string str '' 'string test' 's' } tearDown() { - flags_reset + flags_reset } # Load and run shUnit2.