| #! /bin/sh |
| # vim:et:ft=sh:sts=2:sw=2 |
| # |
| # shFlags unit test for the flag definition methods |
| # |
| # Copyright 2008-2020 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() |
| |
| # These variables will be overridden by the test helpers. |
| stdoutF="${TMPDIR:-/tmp}/STDOUT" |
| stderrF="${TMPDIR:-/tmp}/STDERR" |
| |
| # Load test helpers. |
| . ./shflags_test_helpers |
| |
| testGetoptStandard() { |
| if ! _flags_getoptStandard '-b' >"${stdoutF}" 2>"${stderrF}"; then |
| fail "error parsing -b flag" |
| _showTestOutput |
| fi |
| |
| if _flags_getoptStandard '-x' >"${stdoutF}" 2>"${stderrF}"; then |
| fail "expected error parsing invalid -x flag" |
| _showTestOutput |
| fi |
| } |
| |
| testGetoptEnhanced() { |
| if ! flags_getoptIsEnh; then |
| return |
| fi |
| |
| 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 |
| |
| 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() { |
| 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 |
| 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 |
| testValidBoolsLong() { |
| flags_getoptIsEnh |
| [ $? -eq "${FLAGS_FALSE}" ] && return |
| |
| # Note: the default value of bool is 'false'. |
| |
| # Leave flag false. |
| FLAGS --nobool >"${stdoutF}" 2>"${stderrF}" |
| r3turn=$? |
| assertTrue "FLAGS returned a non-zero result (${r3turn})" ${r3turn} |
| assertFalse '--noXX flag resulted in true value.' "${FLAGS_bool:-}" |
| assertFalse 'expected no output to STDERR' "[ -s '${stderrF}' ]" |
| th_showOutput ${r3turn} "${stdoutF}" "${stderrF}" |
| |
| # Flip flag true. |
| FLAGS --bool >"${stdoutF}" 2>"${stderrF}" |
| r3turn=$? |
| assertTrue "FLAGS returned a non-zero result (${r3turn})" ${r3turn} |
| assertTrue '--XX flag resulted in false value.' "${FLAGS_bool:-}" |
| assertFalse 'expected no output to STDERR' "[ -s '${stderrF}' ]" |
| th_showOutput ${r3turn} "${stdoutF}" "${stderrF}" |
| |
| # Flip flag back false. |
| FLAGS --nobool >"${stdoutF}" 2>"${stderrF}" |
| r3turn=$? |
| assertTrue "FLAGS returned a non-zero result (${r3turn})" ${r3turn} |
| assertFalse '--noXX flag resulted in true value.' "${FLAGS_bool:-}" |
| assertFalse 'expected no output to STDERR' "[ -s '${stderrF}' ]" |
| th_showOutput ${r3turn} "${stdoutF}" "${stderrF}" |
| } |
| |
| testFloats() { |
| _testFloats '-f' |
| if flags_getoptIsEnh; then |
| _testFloats '--float' |
| fi |
| } |
| |
| _testFloats() { |
| flag=$1 |
| |
| for value in ${TH_FLOAT_VALID}; do |
| 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 |
| |
| for value in ${TH_FLOAT_INVALID}; do |
| # 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 |
| } |
| |
| testIntegers() { |
| _testIntegers '-i' |
| if flags_getoptIsEnh; then |
| _testIntegers '--int' |
| fi |
| } |
| |
| _testIntegers() { |
| flag=$1 |
| |
| for value in ${TH_INT_VALID}; do |
| 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 |
| |
| for value in ${TH_INT_INVALID}; do |
| # 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 |
| } |
| |
| testStrings() { |
| _testStrings 'std_single_word' -s single_word |
| if flags_getoptIsEnh; then |
| _testStrings 'enh_single_word' --str single_word |
| _testStrings 'enh_multi_word' --str 'string with spaces' |
| fi |
| } |
| |
| _testStrings() { |
| desc=$1 |
| flag=$2 |
| value=$3 |
| |
| 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 |
| } |
| |
| testMultipleFlags() { |
| _testMultipleFlags '-b' '-i' '-f' '-s' |
| flags_getoptIsEnh |
| [ $? -eq "${FLAGS_FALSE}" ] && return |
| _testMultipleFlags '--bool' '--int' '--float' '--str' |
| } |
| |
| _testMultipleFlags() { |
| boolFlag=$1 |
| intFlag=$2 |
| floatFlag=$3 |
| strFlag=$4 |
| |
| FLAGS \ |
| "${boolFlag}" \ |
| "${intFlag}" 567 \ |
| "${floatFlag}" 123.45678 \ |
| "${strFlag}" 'some_string' \ |
| >"${stdoutF}" 2>"${stderrF}" |
| r3turn=$? |
| assertTrue "use of multiple flags returned a non-zero result" ${r3turn} |
| assertTrue 'boolean test failed.' "${FLAGS_bool}" |
| assertNotSame 'float test failed.' 0 "${FLAGS_float}" |
| assertNotSame 'integer test failed.' 0 "${FLAGS_int}" |
| assertNotSame 'string test failed.' '' "${FLAGS_str}" |
| assertFalse 'expected no output to STDERR' "[ -s '${stderrF}' ]" |
| th_showOutput ${r3turn} "${stdoutF}" "${stderrF}" |
| } |
| |
| _testNonFlagArgs() { |
| argc=$1 |
| shift |
| |
| FLAGS "$@" >"${stdoutF}" 2>"${stderrF}" |
| r3turn=$? |
| assertTrue 'parse returned non-zero value.' ${r3turn} |
| th_showOutput ${r3turn} "${stdoutF}" "${stderrF}" |
| |
| eval set -- "${FLAGS_ARGV}" |
| assertEquals 'wrong count of argv arguments returned.' "${argc}" $# |
| } |
| |
| testSingleNonFlagArg() { _testNonFlagArgs 1 argOne; } |
| testMultipleNonFlagArgs() { _testNonFlagArgs 3 argOne argTwo arg3; } |
| |
| testMultipleNonFlagStringArgsWithSpaces() { |
| if flags_getoptIsEnh; then |
| _testNonFlagArgs 3 argOne 'arg two' arg3 |
| fi |
| } |
| |
| testFlagsWithEquals() { |
| if ! flags_getoptIsEnh; then |
| return |
| fi |
| |
| FLAGS --str='str_flag' 'non_flag' >"${stdoutF}" 2>"${stderrF}" |
| assertTrue 'FLAGS returned a non-zero result' $? |
| assertEquals 'string flag not set properly' 'str_flag' "${FLAGS_str}" |
| th_showOutput ${r3turn} "${stdoutF}" "${stderrF}" |
| |
| eval set -- "${FLAGS_ARGV}" |
| assertEquals 'wrong count of argv arguments returned.' 1 $# |
| } |
| |
| testComplicatedCommandLineStandard() { |
| 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. |
| FLAGS -i 1 non_flag_1 -s 'two' non_flag_2 -f 3 non_flag_3 \ |
| >"${stdoutF}" 2>"${stderrF}" |
| r3turn=$? |
| assertTrue 'FLAGS returned a non-zero result' ${r3turn} |
| assertEquals 'failed int test' 1 "${FLAGS_int}" |
| th_showOutput ${r3turn} "${stdoutF}" "${stderrF}" |
| |
| eval set -- "${FLAGS_ARGV}" |
| assertEquals 'incorrect number of argv values' 7 $# |
| } |
| |
| testComplicatedCommandLineEnhanced() { |
| 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}" |
| r3turn=$? |
| assertTrue 'FLAGS returned a non-zero result' ${r3turn} |
| assertEquals 'failed int test' 1 "${FLAGS_int}" |
| assertEquals 'failed str test' 'two' "${FLAGS_str}" |
| assertEquals 'failed float test' 3 "${FLAGS_float}" |
| th_showOutput ${r3turn} "${stdoutF}" "${stderrF}" |
| |
| eval set -- "${FLAGS_ARGV}" |
| assertEquals 'incorrect number of argv values' 3 $# |
| } |
| |
| 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 |
| } |
| |
| # 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 |
| . "${TH_SHUNIT}" |