#! /bin/sh # $Id$ # vim:et:ft=sh:sts=2:sw=2 # # Copyright 2008 Kate Ward. All Rights Reserved. # Released under the LGPL (GNU Lesser General Public License) # # Author: kate.ward@forestent.com (Kate Ward) # # shFlags unit test for the flag definition methods # # 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 # load test helpers . ./shflags_test_helpers #------------------------------------------------------------------------------ # suite tests # testGetoptStandard() { _flags_getoptStandard '-b' >"${stdoutF}" 2>"${stderrF}" rslt=$? assertTrue "didn't parse valid flag 'b'" ${rslt} th_showOutput ${rslt} "${stdoutF}" "${stderrF}" _flags_getoptStandard '-x' >"${stdoutF}" 2>"${stderrF}" assertFalse "parsed invalid flag 'x'" $? } testGetoptEnhanced() { flags_getoptIsEnh || return _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'" $? _flags_getoptEnhanced '-x' >"${stdoutF}" 2>"${stderrF}" assertFalse "parsed invalid flag 'x'" $? _flags_getoptEnhanced '--xyz' >"${stdoutF}" 2>"${stderrF}" assertFalse "parsed invalid flag 'xyz'" $? } 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}" 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}" } # TODO(kate): separate into multiple functions to reflect correct usage testValidBoolsLong() { flags_getoptIsEnh || 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}" } testValidFloats() { _testValidFloats '-f' flags_getoptIsEnh || return _testValidFloats '--float' } _testValidFloats() { 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} assertEquals "float (${flag} ${value}) test failed." ${value} ${FLAGS_float} assertFalse 'expected no output to STDERR' "[ -s '${stderrF}' ]" th_showOutput ${r3turn} "${stdoutF}" "${stderrF}" done } testInvalidFloats() { _testInvalidFloats '-f' flags_getoptIsEnh || return _testInvalidFloats '--float' } _testInvalidFloats() { flag=$1 for value in ${TH_FLOAT_INVALID}; do th_clearReturn ( FLAGS ${flag} ${value} >"${stdoutF}" 2>"${stderrF}" echo $? >"${returnF}" ) th_queryReturn assertFalse "FLAGS (${value}) returned a zero result" ${th_return} assertFalse 'expected no output to STDOUT' "[ -s '${stdoutF}' ]" assertTrue 'expected output to STDERR' "[ -s '${stderrF}' ]" done } testValidIntegers() { _testValidIntegers '-i' flags_getoptIsEnh || return _testValidIntegers '--int' } _testValidIntegers() { 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} assertEquals "integer (${value}) test failed." ${value} ${FLAGS_int} assertFalse 'expected no output to STDERR' "[ -s '${stderrF}' ]" th_showOutput ${r3turn} "${stdoutF}" "${stderrF}" done } testInvalidIntegers() { _testInvalidIntegers '-i' flags_getoptIsEnh || return _testInvalidIntegers '--int' } _testInvalidIntegers() { flag=$1 for value in ${TH_INT_INVALID}; do th_clearReturn ( FLAGS ${flag} ${value} >"${stdoutF}" 2>"${stderrF}" echo $? >"${returnF}" ) th_queryReturn assertFalse "invalid integer (${value}) test returned success." ${th_return} assertFalse 'expected no output to STDOUT' "[ -s '${stdoutF}' ]" assertTrue 'expected output to STDERR' "[ -s '${stderrF}' ]" done } testValidStrings() { _testValidStrings -s single_word if flags_getoptIsEnh; then _testValidStrings --str single_word _testValidStrings --str 'string with spaces' fi } _testValidStrings() { flag=$1 value=$2 FLAGS ${flag} "${value}" >"${stdoutF}" 2>"${stderrF}" r3turn=$? assertTrue "'FLAGS ${flag} ${value}' returned a non-zero result (${r3turn})" \ ${r3turn} 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}" } testMultipleFlags() { _testMultipleFlags '-b' '-i' '-f' '-s' flags_getoptIsEnh || 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 multple 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} $# assertEquals 'wrong count of argc arguments returned.' 0 ${FLAGS_ARGC} } testSingleNonFlagArg() { _testNonFlagArgs 1 argOne } testMultipleNonFlagArgs() { _testNonFlagArgs 3 argOne argTwo arg3 } testMultipleNonFlagStringArgsWithSpaces() { flags_getoptIsEnh || return _testNonFlagArgs 3 argOne 'arg two' arg3 } testFlagsWithEquals() { flags_getoptIsEnh || return 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 $# assertEquals 'wrong count of argc arguments returned.' 1 ${FLAGS_ARGC} } testComplicatedCommandLineStandard() { flags_getoptIsEnh && 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 || 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 $# } #------------------------------------------------------------------------------ # suite functions # 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 [ -n "${ZSH_VERSION:-}" ] && SHUNIT_PARENT=$0 . ${TH_SHUNIT}