Include shunit2 based tests into unit testing pipeline until (eventually) it's converted to cram based unit tests.
Signed-off-by: Petr Štetiar <yn...@true.cz> --- tests/CMakeLists.txt | 1 + tests/shunit2/CMakeLists.txt | 7 + tests/shunit2/shunit2/shunit2 | 1040 +++++++++++++++++++++++++++++++++ tests/shunit2/tests.sh | 287 +++++++++ 4 files changed, 1335 insertions(+) create mode 100644 tests/shunit2/CMakeLists.txt create mode 100644 tests/shunit2/shunit2/shunit2 create mode 100755 tests/shunit2/tests.sh diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index 0cb33427e45a..6258beeb241e 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -1,4 +1,5 @@ ADD_SUBDIRECTORY(cram) +ADD_SUBDIRECTORY(shunit2) MACRO(ADD_UNIT_TEST name) ADD_EXECUTABLE(${name} ${name}.c) diff --git a/tests/shunit2/CMakeLists.txt b/tests/shunit2/CMakeLists.txt new file mode 100644 index 000000000000..74c2134cf3c8 --- /dev/null +++ b/tests/shunit2/CMakeLists.txt @@ -0,0 +1,7 @@ +ADD_TEST( + NAME shunit2 + COMMAND tests.sh + WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} +) + +SET_PROPERTY(TEST shunit2 APPEND PROPERTY ENVIRONMENT "TEST_JSON_SCRIPT=$<TARGET_FILE:test-json-script>") diff --git a/tests/shunit2/shunit2/shunit2 b/tests/shunit2/shunit2/shunit2 new file mode 100644 index 000000000000..eef19d410146 --- /dev/null +++ b/tests/shunit2/shunit2/shunit2 @@ -0,0 +1,1040 @@ +# $Id: shunit2 189 2008-07-11 11:46:54Z kate.w...@forestent.com $ +# vim:et:ft=sh:sts=2:sw=2 +# vim:foldmethod=marker:foldmarker=/**,*/ +# +#/** +# <?xml version="1.0" encoding="UTF-8"?> +# <s:shelldoc xmlns:s="http://www.forestent.com/projects/shelldoc/xsl/2005.0"> +# <s:header> +# shUnit 2.1.4 +# Shell Unit Test Framework +# +# http://shunit2.sourceforge.net/ +# +# written by Kate Ward <kate.w...@forestent.com> +# released under the LGPL +# +# this module implements a xUnit based unit test framework similar to JUnit +# </s:header> +#*/ + +SHUNIT_VERSION='2.1.4' + +_shunit_warn() { echo "shunit2:WARN $@" >&2; } +_shunit_error() { echo "shunit2:ERROR $@" >&2; } +_shunit_fatal() { echo "shunit2:FATAL $@" >&2; } + +SHUNIT_TRUE=0 +SHUNIT_FALSE=1 +SHUNIT_ERROR=2 + +# specific shell checks +if [ -n "${ZSH_VERSION:-}" ]; then + setopt |grep "^shwordsplit$" >/dev/null + if [ $? -ne ${SHUNIT_TRUE} ]; then + _shunit_fatal 'zsh shwordsplit option is required for proper operation' + exit ${SHUNIT_ERROR} + fi + if [ -z "${SHUNIT_PARENT:-}" ]; then + _shunit_fatal "zsh does not pass \$0 through properly. please declare \ +\"SHUNIT_PARENT=\$0\" before calling shUnit2" + exit ${SHUNIT_ERROR} + fi +fi + +# shell flags for shunit2: +# u - treat unset variables as an error when performing parameter expansion +__SHUNIT_SHELL_FLAGS='u' + +# save the current set of shell flags, and then set some for ourself +shunit_shellFlags_="$-" +for shunit_shellFlag_ in `echo "${__SHUNIT_SHELL_FLAGS}" |sed 's/\(.\)/\1 /g'` +do + set -${shunit_shellFlag_} +done + +# +# constants +# + +__SHUNIT_ASSERT_MSG_PREFIX='ASSERT:' +__SHUNIT_PARENT=${SHUNIT_PARENT:-$0} + +# set the constants readonly +shunit_constants_=`set |grep "^__SHUNIT_" |cut -d= -f1` +echo "${shunit_constants_}" |grep "^Binary file" >/dev/null +if [ $? -eq 0 ]; then + # deal with binary junk in 'set' output + shunit_constants_=`set |grep -a "^__SHUNIT_" |cut -d= -f1` +fi +for shunit_const_ in ${shunit_constants_}; do + shunit_ro_opts_='' + if [ -n "${ZSH_VERSION:-}" ]; then + case ${ZSH_VERSION} in + [123].*) ;; + *) shunit_ro_opts_='-g' ;; # declare readonly constants globally + esac + fi + readonly ${shunit_ro_opts_} ${shunit_const_} +done +unset shunit_const_ shunit_constants_ shunit_ro_opts_ + +# variables +__shunit_skip=${SHUNIT_FALSE} +__shunit_suite='' + +__shunit_testsPassed=0 +__shunit_testsFailed=0 +__shunit_testsSkipped=0 +__shunit_testsTotal=0 + +# macros +_SHUNIT_LINENO_='eval if [ "${1:-}" = "--lineno" ]; then [ -n "$2" ] && shunit_message_="[$2]"; shift 2; fi' + +#----------------------------------------------------------------------------- +# assert functions +# + +#/** +# <s:function group="asserts"> +# <entry align="right"> +# <emphasis>void</emphasis> +# </entry> +# <entry> +# <funcsynopsis> +# <funcprototype> +# <funcdef><function>assertEquals</function></funcdef> +# <paramdef>string <parameter>[message]</parameter></paramdef> +# <paramdef>string <parameter>expected</parameter></paramdef> +# <paramdef>string <parameter>actual</parameter></paramdef> +# </funcprototype> +# </funcsynopsis> +# <para>Asserts that <emphasis>expected</emphasis> and +# <emphasis>actual</emphasis> are equal to one another. The message is +# optional.</para> +# </entry> +# </s:function> +#*/ +assertEquals() +{ + ${_SHUNIT_LINENO_} + if [ $# -lt 2 -o $# -gt 3 ]; then + _shunit_error 'assertEquals() requires one or two arguments' + return ${SHUNIT_ERROR} + fi + _shunit_shouldSkip && return ${SHUNIT_TRUE} + + [ -z "${shunit_message_:-}" ] && shunit_message_='' + if [ $# -eq 3 ]; then + shunit_message_="${shunit_message_}$1" + shift + fi + shunit_expected_=$1 + shunit_actual_=$2 + + shunit_return=${SHUNIT_TRUE} + if [ "${shunit_expected_}" = "${shunit_actual_}" ]; then + _shunit_testPassed + else + failNotEquals "${shunit_message_}" "${shunit_expected_}" "${shunit_actual_}" + shunit_return=${SHUNIT_FALSE} + fi + + unset shunit_message_ shunit_expected_ shunit_actual_ __shunit_lineno + return ${shunit_return} +} +_ASSERT_EQUALS_='eval assertEquals --lineno "${LINENO:-}"' + +#/** +# <s:function group="asserts"> +# <entry align="right"> +# <emphasis>void</emphasis> +# </entry> +# <entry> +# <funcsynopsis> +# <funcprototype> +# <funcdef><function>assertNull</function></funcdef> +# <paramdef>string <parameter>[message]</parameter></paramdef> +# <paramdef>string <parameter>value</parameter></paramdef> +# </funcprototype> +# </funcsynopsis> +# <para>Asserts that <emphasis>value</emphasis> is <literal>null</literal>, +# or in shell terms a zero-length string. The message is optional.</para> +# </entry> +# </s:function> +#*/ +assertNull() +{ + ${_SHUNIT_LINENO_} + if [ $# -lt 1 -o $# -gt 2 ]; then + _shunit_error 'assertNull() requires one or two arguments' + return ${SHUNIT_ERROR} + fi + _shunit_shouldSkip && return ${SHUNIT_TRUE} + + [ -z "${shunit_message_:-}" ] && shunit_message_='' + if [ $# -eq 2 ]; then + shunit_message_="${shunit_message_}$1" + shift + fi + if [ $# -eq 2 ]; then + assertTrue "${shunit_message_}$1" "[ -z '$2' ]" + else + assertTrue "[ -z '$1' ]" + fi +} +_ASSERT_NULL_='eval assertNull --lineno "${LINENO:-}"' + +#/** +# <s:function group="asserts"> +# <entry align="right"> +# <emphasis>void</emphasis> +# </entry> +# <entry> +# <funcsynopsis> +# <funcprototype> +# <funcdef><function>assertNotNull</function></funcdef> +# <paramdef>string <parameter>[message]</parameter></paramdef> +# <paramdef>string <parameter>value</parameter></paramdef> +# </funcprototype> +# </funcsynopsis> +# <para>Asserts that <emphasis>value</emphasis> is <emphasis +# role="strong">not</emphasis> <literal>null</literal>, or in shell terms not +# a zero-length string. The message is optional.</para> +# </entry> +# </s:function> +#*/ +assertNotNull() +{ + ${_SHUNIT_LINENO_} + if [ $# -gt 2 ]; then # allowing 0 arguments as $1 might actually be null + _shunit_error 'assertNotNull() requires one or two arguments' + return ${SHUNIT_ERROR} + fi + _shunit_shouldSkip && return ${SHUNIT_TRUE} + + if [ $# -eq 2 ]; then + assertTrue "$1" "[ -n '$2' ]" + else + assertTrue "[ -n '${1:-}' ]" + fi +} +_ASSERT_NOT_NULL_='eval assertNotNull --lineno "${LINENO:-}"' + +#/** +# <s:function group="asserts"> +# <entry align="right"> +# <emphasis>void</emphasis> +# </entry> +# <entry> +# <funcsynopsis> +# <funcprototype> +# <funcdef><function>assertSame</function></funcdef> +# <paramdef>string <parameter>[message]</parameter></paramdef> +# <paramdef>string <parameter>expected</parameter></paramdef> +# <paramdef>string <parameter>actual</parameter></paramdef> +# </funcprototype> +# </funcsynopsis> +# <para>This function is functionally equivalent to +# <function>assertEquals</function>.</para> +# </entry> +# </s:function> +#*/ +assertSame() +{ + ${_SHUNIT_LINENO_} + if [ $# -lt 2 -o $# -gt 3 ]; then + _shunit_error 'assertSame() requires one or two arguments' + return ${SHUNIT_ERROR} + fi + _shunit_shouldSkip && return ${SHUNIT_TRUE} + + if [ $# -eq 2 ]; then + assertEquals "$1" "$2" + else + assertEquals "$1" "$2" "$3" + fi +} +_ASSERT_SAME_='eval assertSame --lineno "${LINENO:-}"' + +#/** +# <s:function group="asserts"> +# <entry align="right"> +# <emphasis>void</emphasis> +# </entry> +# <entry> +# <funcsynopsis> +# <funcprototype> +# <funcdef><function>assertNotSame</function></funcdef> +# <paramdef>string <parameter>[message]</parameter></paramdef> +# <paramdef>string <parameter>unexpected</parameter></paramdef> +# <paramdef>string <parameter>actual</parameter></paramdef> +# </funcprototype> +# </funcsynopsis> +# <para>Asserts that <emphasis>unexpected</emphasis> and +# <emphasis>actual</emphasis> are <emphasis role="strong">not</emphasis> +# equal to one another. The message is optional.</para> +# </entry> +# </s:function> +#*/ +assertNotSame() +{ + ${_SHUNIT_LINENO_} + if [ $# -lt 2 -o $# -gt 3 ]; then + _shunit_error 'assertNotSame() requires two or three arguments' + return ${SHUNIT_ERROR} + fi + _shunit_shouldSkip && return ${SHUNIT_TRUE} + + [ -z "${shunit_message_:-}" ] && shunit_message_='' + if [ $# -eq 3 ]; then + shunit_message_="${shunit_message_}$1" + shift + fi + shunit_unexpected_=$1 + shunit_actual_=$2 + + shunit_return=${SHUNIT_TRUE} + if [ "${shunit_unexpected_}" != "${shunit_actual_}" ]; then + _shunit_testPassed + else + failSame "${shunit_message_}" "$@" + shunit_return=${SHUNIT_FALSE} + fi + + unset shunit_message_ shunit_unexpected_ shunit_actual_ + return ${shunit_return} +} +_ASSERT_NOT_SAME_='eval assertNotSame --lineno "${LINENO:-}"' + +#/** +# <s:function group="asserts"> +# <entry align="right"> +# <emphasis>void</emphasis> +# </entry> +# <entry> +# <funcsynopsis> +# <funcprototype> +# <funcdef><function>assertTrue</function></funcdef> +# <paramdef>string <parameter>[message]</parameter></paramdef> +# <paramdef>string <parameter>condition</parameter></paramdef> +# </funcprototype> +# </funcsynopsis> +# <para>Asserts that a given shell test condition is true. The message is +# optional.</para> +# <para>Testing whether something is true or false is easy enough by using +# the assertEquals/assertNotSame functions. Shell supports much more +# complicated tests though, and a means to support them was needed. As such, +# this function tests that conditions are true or false through evaluation +# rather than just looking for a true or false.</para> +# <funcsynopsis> +# The following test will succeed: <funcsynopsisinfo>assertTrue "[ 34 -gt 23 ]"</funcsynopsisinfo> +# The folloing test will fail with a message: <funcsynopsisinfo>assertTrue "test failed" "[ -r '/non/existant/file' ]"</funcsynopsisinfo> +# </funcsynopsis> +# </entry> +# </s:function> +#*/ +assertTrue() +{ + ${_SHUNIT_LINENO_} + if [ $# -gt 2 ]; then + _shunit_error 'assertTrue() takes one two arguments' + return ${SHUNIT_ERROR} + fi + _shunit_shouldSkip && return ${SHUNIT_TRUE} + + [ -z "${shunit_message_:-}" ] && shunit_message_='' + if [ $# -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 + # null condition + shunit_return=${SHUNIT_FALSE} + elif [ "${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} + else + # (hopefully) a condition + ( eval ${shunit_condition_} ) >/dev/null 2>&1 + [ $? -ne 0 ] && shunit_return=${SHUNIT_FALSE} + fi + + # record the test + if [ ${shunit_return} -eq ${SHUNIT_TRUE} ]; then + _shunit_testPassed + else + _shunit_testFailed "${shunit_message_}" + fi + + unset shunit_message_ shunit_condition_ shunit_match_ + return ${shunit_return} +} +_ASSERT_TRUE_='eval assertTrue --lineno "${LINENO:-}"' + +#/** +# <s:function group="asserts"> +# <entry align="right"> +# <emphasis>void</emphasis> +# </entry> +# <entry> +# <funcsynopsis> +# <funcprototype> +# <funcdef><function>assertFalse</function></funcdef> +# <paramdef>string <parameter>[message]</parameter></paramdef> +# <paramdef>string <parameter>condition</parameter></paramdef> +# </funcprototype> +# </funcsynopsis> +# <para>Asserts that a given shell test condition is false. The message is +# optional.</para> +# <para>Testing whether something is true or false is easy enough by using +# the assertEquals/assertNotSame functions. Shell supports much more +# complicated tests though, and a means to support them was needed. As such, +# this function tests that conditions are true or false through evaluation +# rather than just looking for a true or false.</para> +# <funcsynopsis> +# The following test will succeed: <funcsynopsisinfo>assertFalse "[ 'apples' = 'oranges' ]"</funcsynopsisinfo> +# The folloing test will fail with a message: <funcsynopsisinfo>assertFalse "test failed" "[ 1 -eq 1 -a 2 -eq 2 ]"</funcsynopsisinfo> +# </funcsynopsis> +# </entry> +# </s:function> +#*/ +assertFalse() +{ + ${_SHUNIT_LINENO_} + if [ $# -lt 1 -o $# -gt 2 ]; then + _shunit_error 'assertFalse() quires one or two arguments' + return ${SHUNIT_ERROR} + fi + _shunit_shouldSkip && return ${SHUNIT_TRUE} + + [ -z "${shunit_message_:-}" ] && shunit_message_='' + if [ $# -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 + # null condition + shunit_return=${SHUNIT_FALSE} + elif [ "${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} + else + # (hopefully) a condition + ( eval ${shunit_condition_} ) >/dev/null 2>&1 + [ $? -eq 0 ] && shunit_return=${SHUNIT_FALSE} + fi + + # record the test + if [ ${shunit_return} -eq ${SHUNIT_TRUE} ]; then + _shunit_testPassed + else + _shunit_testFailed "${shunit_message_}" + fi + + unset shunit_message_ shunit_condition_ shunit_match_ + return ${shunit_return} +} +_ASSERT_FALSE_='eval assertFalse --lineno "${LINENO:-}"' + +#----------------------------------------------------------------------------- +# failure functions +# + +#/** +# <s:function group="failures"> +# <entry align="right"> +# <emphasis>void</emphasis> +# </entry> +# <entry> +# <funcsynopsis> +# <funcprototype> +# <funcdef><function>fail</function></funcdef> +# <paramdef>string <parameter>[message]</parameter></paramdef> +# </funcprototype> +# </funcsynopsis> +# <para>Fails the test immediately, with the optional message.</para> +# </entry> +# </s:function> +#*/ +fail() +{ + ${_SHUNIT_LINENO_} + if [ $# -gt 1 ]; then + _shunit_error 'fail() requires one or two arguments' + return ${SHUNIT_ERROR} + fi + _shunit_shouldSkip && return ${SHUNIT_TRUE} + + [ -z "${shunit_message_:-}" ] && shunit_message_='' + if [ $# -eq 1 ]; then + shunit_message_="${shunit_message_}$1" + shift + fi + + _shunit_testFailed "${shunit_message_}" + + unset shunit_message_ + return ${SHUNIT_FALSE} +} +_FAIL_='eval fail --lineno "${LINENO:-}"' + +#/** +# <s:function group="failures"> +# <entry align="right"> +# <emphasis>void</emphasis> +# </entry> +# <entry> +# <funcsynopsis> +# <funcprototype> +# <funcdef><function>failNotEquals</function></funcdef> +# <paramdef>string <parameter>[message]</parameter></paramdef> +# <paramdef>string <parameter>unexpected</parameter></paramdef> +# <paramdef>string <parameter>actual</parameter></paramdef> +# </funcprototype> +# </funcsynopsis> +# <para>Fails the test if <emphasis>unexpected</emphasis> and +# <emphasis>actual</emphasis> are <emphasis role="strong">not</emphasis> +# equal to one another. The message is optional.</para> +# </entry> +# </s:function> +#*/ +failNotEquals() +{ + ${_SHUNIT_LINENO_} + if [ $# -lt 2 -o $# -gt 3 ]; then + _shunit_error 'failNotEquals() requires one or two arguments' + return ${SHUNIT_ERROR} + fi + _shunit_shouldSkip && return ${SHUNIT_TRUE} + + [ -z "${shunit_message_:-}" ] && shunit_message_='' + if [ $# -eq 3 ]; then + shunit_message_="${shunit_message_}$1" + shift + fi + shunit_unexpected_=$1 + shunit_actual_=$2 + + _shunit_testFailed "${shunit_message_:+${shunit_message_} }expected:<${shunit_unexpected_}> but was:<${shunit_actual_}>" + + unset shunit_message_ shunit_unexpected_ shunit_actual_ + return ${SHUNIT_FALSE} +} +_FAIL_NOT_EQUALS_='eval failNotEquals --lineno "${LINENO:-}"' + +#/** +# <s:function group="failures"> +# <entry align="right"> +# <emphasis>void</emphasis> +# </entry> +# <entry> +# <funcsynopsis> +# <funcprototype> +# <funcdef><function>failSame</function></funcdef> +# <paramdef>string <parameter>[message]</parameter></paramdef> +# </funcprototype> +# </funcsynopsis> +# <para>Indicate test failure because arguments were not the same. The +# message is optional.</para> +# </entry> +# </s:function> +#*/ +failSame() +{ + ${_SHUNIT_LINENO_} + if [ $# -lt 2 -o $# -gt 3 ]; then + _shunit_error 'failSame() requires two or three arguments' + return ${SHUNIT_ERROR} + fi + _shunit_shouldSkip && return ${SHUNIT_TRUE} + + [ -z "${shunit_message_:-}" ] && shunit_message_='' + if [ $# -eq 3 ]; then + shunit_message_="${shunit_message_}$1" + shift + fi + + _shunit_testFailed "${shunit_message_:+${shunit_message_} }expected not same" + + unset shunit_message_ + return ${SHUNIT_FALSE} +} +_FAIL_SAME_='eval failSame --lineno "${LINENO:-}"' + +#/** +# <s:function group="failures"> +# <entry align="right"> +# <emphasis>void</emphasis> +# </entry> +# <entry> +# <funcsynopsis> +# <funcprototype> +# <funcdef><function>failNotSame</function></funcdef> +# <paramdef>string <parameter>[message]</parameter></paramdef> +# <paramdef>string <parameter>expected</parameter></paramdef> +# <paramdef>string <parameter>actual</parameter></paramdef> +# </funcprototype> +# </funcsynopsis> +# <para>Fails the test if <emphasis>expected</emphasis> and +# <emphasis>actual</emphasis> are equal to one another. The message is +# optional.</para> +# </entry> +# </s:function> +#*/ +failNotSame() +{ + ${_SHUNIT_LINENO_} + if [ $# -lt 2 -o $# -gt 3 ]; then + _shunit_error 'failNotEquals() requires one or two arguments' + return ${SHUNIT_ERROR} + fi + _shunit_shouldSkip && return ${SHUNIT_TRUE} + + if [ $# -eq 2 ]; then + failNotEquals "$1" "$2" + else + failNotEquals "$1" "$2" "$3" + fi +} +_FAIL_NOT_SAME_='eval failNotSame --lineno "${LINENO:-}"' + +#----------------------------------------------------------------------------- +# skipping functions +# + +#/** +# <s:function group="skipping"> +# <entry align="right"> +# <emphasis>void</emphasis> +# </entry> +# <entry> +# <funcsynopsis> +# <funcprototype> +# <funcdef><function>startSkipping</function></funcdef> +# <paramdef /> +# </funcprototype> +# </funcsynopsis> +# <para>This function forces the remaining assert and fail functions to be +# "skipped", i.e. they will have no effect. Each function skipped will be +# recorded so that the total of asserts and fails will not be altered.</para> +# </entry> +# </s:function> +#*/ +startSkipping() +{ + __shunit_skip=${SHUNIT_TRUE} +} + +#/** +# <s:function group="skipping"> +# <entry align="right"> +# <emphasis>void</emphasis> +# </entry> +# <entry> +# <funcsynopsis> +# <funcprototype> +# <funcdef><function>endSkipping</function></funcdef> +# <paramdef /> +# </funcprototype> +# </funcsynopsis> +# <para>This function returns calls to the assert and fail functions to their +# default behavior, i.e. they will be called.</para> +# </entry> +# </s:function> +#*/ +endSkipping() +{ + __shunit_skip=${SHUNIT_FALSE} +} + +#/** +# <s:function group="skipping"> +# <entry align="right"> +# <emphasis>boolean</emphasis> +# </entry> +# <entry> +# <funcsynopsis> +# <funcprototype> +# <funcdef><function>isSkipping</function></funcdef> +# <paramdef /> +# </funcprototype> +# </funcsynopsis> +# <para>This function returns the state of skipping.</para> +# </entry> +# </s:function> +#*/ +isSkipping() +{ + return ${__shunit_skip} +} + +#----------------------------------------------------------------------------- +# suite functions +# + +#/** +# <s:function group="suites"> +# <entry align="right"> +# <emphasis>void</emphasis> +# </entry> +# <entry> +# <funcsynopsis> +# <funcprototype> +# <funcdef><function>suite</function></funcdef> +# <paramdef /> +# </funcprototype> +# </funcsynopsis> +# <para>This function can be optionally overridden by the user in their test +# suite.</para> +# <para>If this function exists, it will be called when +# <command>shunit2</command> is sourced. If it does not exist, shUnit2 will +# search the parent script for all functions beginning with the word +# <literal>test</literal>, and they will be added dynamically to the test +# suite.</para> +# </entry> +# </s:function> +#*/ +# Note: see _shunit_mktempFunc() for actual implementation +# suite() { :; } + +#/** +# <s:function group="suites"> +# <entry align="right"> +# <emphasis>void</emphasis> +# </entry> +# <entry> +# <funcsynopsis> +# <funcprototype> +# <funcdef><function>suite_addTest</function></funcdef> +# <paramdef>string <parameter>function</parameter></paramdef> +# </funcprototype> +# </funcsynopsis> +# <para>This function adds a function name to the list of tests scheduled for +# execution as part of this test suite. This function should only be called +# from within the <function>suite()</function> function.</para> +# </entry> +# </s:function> +#*/ +suite_addTest() +{ + _su_func=${1:-} + + __shunit_suite="${__shunit_suite:+${__shunit_suite} }${_su_func}" + + unset _su_func +} + +#/** +# <s:function group="suites"> +# <entry align="right"> +# <emphasis>void</emphasis> +# </entry> +# <entry> +# <funcsynopsis> +# <funcprototype> +# <funcdef><function>oneTimeSetUp</function></funcdef> +# <paramdef /> +# </funcprototype> +# </funcsynopsis> +# <para>This function can be be optionally overridden by the user in their +# test suite.</para> +# <para>If this function exists, it will be called once before any tests are +# run. It is useful to prepare a common environment for all tests.</para> +# </entry> +# </s:function> +#*/ +# Note: see _shunit_mktempFunc() for actual implementation +# oneTimeSetUp() { :; } + +#/** +# <s:function group="suites"> +# <entry align="right"> +# <emphasis>void</emphasis> +# </entry> +# <entry> +# <funcsynopsis> +# <funcprototype> +# <funcdef><function>oneTimeTearDown</function></funcdef> +# <paramdef /> +# </funcprototype> +# </funcsynopsis> +# <para>This function can be be optionally overridden by the user in their +# test suite.</para> +# <para>If this function exists, it will be called once after all tests are +# completed. It is useful to clean up the environment after all tests.</para> +# </entry> +# </s:function> +#*/ +# Note: see _shunit_mktempFunc() for actual implementation +# oneTimeTearDown() { :; } + +#/** +# <s:function group="suites"> +# <entry align="right"> +# <emphasis>void</emphasis> +# </entry> +# <entry> +# <funcsynopsis> +# <funcprototype> +# <funcdef><function>setUp</function></funcdef> +# <paramdef /> +# </funcprototype> +# </funcsynopsis> +# <para>This function can be be optionally overridden by the user in their +# test suite.</para> +# <para>If this function exists, it will be called before each test is run. +# It is useful to reset the environment before each test.</para> +# </entry> +# </s:function> +#*/ +# Note: see _shunit_mktempFunc() for actual implementation +# setUp() { :; } + +#/** +# <s:function group="suites"> +# <entry align="right"> +# <emphasis>void</emphasis> +# </entry> +# <entry> +# <funcsynopsis> +# <funcprototype> +# <funcdef><function>tearDown</function></funcdef> +# <paramdef /> +# </funcprototype> +# </funcsynopsis> +# <para>This function can be be optionally overridden by the user in their +# test suite.</para> +# <para>If this function exists, it will be called after each test completes. +# It is useful to clean up the environment after each test.</para> +# </entry> +# </s:function> +#*/ +# Note: see _shunit_mktempFunc() for actual implementation +# tearDown() { :; } + +#------------------------------------------------------------------------------ +# internal shUnit2 functions +# + +_shunit_cleanup() +{ + name=$1 + + case ${name} in + EXIT) signal=0 ;; + INT) signal=2 ;; + TERM) signal=15 ;; + *) + _shunit_warn "unrecognized trap value (${name})" + signal=0 + ;; + esac + + # do our work + rm -fr "${__shunit_tmpDir}" + + # exit for all non-EXIT signals + if [ ${name} != 'EXIT' ]; then + _shunit_warn "trapped and now handling the (${name}) signal" + _shunit_generateReport + # disable EXIT trap + trap 0 + # add 128 to signal and exit + exit `expr ${signal} + 128` + fi +} + +_shunit_execSuite() +{ + echo '#' + echo '# Performing tests' + echo '#' + for _su_func in ${__shunit_suite}; do + # disable skipping + endSkipping + + # execute the per-test setup function + setUp + + # execute the test + echo "${_su_func}" + eval ${_su_func} + + # execute the per-test tear-down function + tearDown + done + + unset _su_func +} + +_shunit_generateReport() +{ + _su__awkPercent='{printf("%4d %3.0f%%", $1, $1*100/$2)}' + if [ ${__shunit_testsTotal:-0} -gt 0 ]; then + _su__passed=`echo ${__shunit_testsPassed} ${__shunit_testsTotal} |\ + awk "${_su__awkPercent}"` + _su__failed=`echo ${__shunit_testsFailed} ${__shunit_testsTotal} |\ + awk "${_su__awkPercent}"` + _su__skipped=`echo ${__shunit_testsSkipped} ${__shunit_testsTotal} |\ + awk "${_su__awkPercent}"` + _su__total=`echo ${__shunit_testsTotal} 100 |\ + awk '{printf("%4d %3d%%", $1, $2)}'` + else + _su__passed=`echo 0 0 |awk '{printf("%4d %3d%%", $1, $2)}'` + _su__failed=${_su__passed} + _su__skipped=${_su__passed} + _su__total=${_su__passed} + fi + + cat <<EOF + +# +# Test report +# +tests passed: ${_su__passed} +tests failed: ${_su__failed} +tests skipped: ${_su__skipped} +tests total: ${_su__total} +EOF + + unset _su__awkPercent _su__passed _su__failed _su__skipped _su__total +} + +# this function is a cross-platform temporary directory creation tool. not all +# OSes have the mktemp function, so one is included here. +_shunit_mktempDir() +{ + # try the standard mktemp function + ( exec mktemp -dqt shunit.XXXXXX 2>/dev/null ) && return + + # the standard mktemp didn't work. doing our own. + if [ -r '/dev/urandom' ]; then + _su__random=`od -vAn -N4 -tx4 </dev/urandom |sed 's/^[^0-9a-f]*//'` + elif [ -n "${RANDOM:-}" ]; then + # $RANDOM works + _su__random=${RANDOM}${RANDOM}${RANDOM}$$ + else + # $RANDOM doesn't work + _su__date=`date '+%Y%m%d%H%M%S'` + _su__random=`expr ${_su__date} / $$` + fi + + _su__tmpDir="${TMPDIR:-/tmp}/shunit.${_su__random}" + ( umask 077 && mkdir "${_su__tmpDir}" ) || { + echo 'shUnit:FATAL could not create temporary directory! exiting' >&2 + exit 1 + } + + echo ${_su__tmpDir} + unset _su__date _su__random _su__tmpDir +} + +# this function is here to work around issues in Cygwin +_shunit_mktempFunc() +{ + for _su__func in oneTimeSetUp oneTimeTearDown setUp tearDown suite; do + _su__file="${__shunit_tmpDir}/${_su__func}" + cat <<EOF >"${_su__file}" +#! /bin/sh +exit 0 +EOF + chmod +x "${_su__file}" + done + + unset _su__file +} + +_shunit_shouldSkip() +{ + [ ${__shunit_skip} -eq ${SHUNIT_FALSE} ] && return ${SHUNIT_FALSE} + _shunit_testSkipped +} + +_shunit_testPassed() +{ + __shunit_testsPassed=`expr ${__shunit_testsPassed} + 1` + __shunit_testsTotal=`expr ${__shunit_testsTotal} + 1` +} + +_shunit_testFailed() +{ + _su__msg=$1 + + __shunit_testsFailed=`expr ${__shunit_testsFailed} + 1` + __shunit_testsTotal=`expr ${__shunit_testsTotal} + 1` + echo "${__SHUNIT_ASSERT_MSG_PREFIX}${_su__msg}" >&2 + + unset _su__msg +} + +_shunit_testSkipped() +{ + __shunit_testsSkipped=`expr ${__shunit_testsSkipped} + 1` + __shunit_testsTotal=`expr ${__shunit_testsTotal} + 1` +} + +#------------------------------------------------------------------------------ +# main +# + +# create a temporary storage location +__shunit_tmpDir=`_shunit_mktempDir` + +# setup traps to clean up after ourselves +trap '_shunit_cleanup EXIT' 0 +trap '_shunit_cleanup INT' 2 +trap '_shunit_cleanup TERM' 15 + +# create phantom functions to work around issues with Cygwin +_shunit_mktempFunc +PATH="${__shunit_tmpDir}:${PATH}" + +# 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 + +# if no suite function was defined, dynamically build a list of functions +if [ -z "${__shunit_suite}" ]; then + shunit_funcs_=`grep "^[ \t]*test[A-Za-z0-9_]* *()" ${__SHUNIT_PARENT} \ + |sed 's/[^A-Za-z0-9_]//g'` + for shunit_func_ in ${shunit_funcs_}; do + suite_addTest ${shunit_func_} + done +fi +unset shunit_func_ shunit_funcs_ + +# execute the tests +_shunit_execSuite + +# execute the oneTimeTearDown function (if it exists) +oneTimeTearDown + +# generate report +_shunit_generateReport + +# restore the previous set of shell flags +for shunit_shellFlag_ in ${__SHUNIT_SHELL_FLAGS}; do + echo ${shunit_shellFlags_} |grep ${shunit_shellFlag_} >/dev/null \ + || set +${shunit_shellFlag_} +done +unset shunit_shellFlag_ shunit_shellFlags_ + +[ ${__shunit_testsFailed} -eq 0 ] || exit 1 + +#/** +# </s:shelldoc> +#*/ diff --git a/tests/shunit2/tests.sh b/tests/shunit2/tests.sh new file mode 100755 index 000000000000..b27775a6b128 --- /dev/null +++ b/tests/shunit2/tests.sh @@ -0,0 +1,287 @@ +JSON_SCRIPT=tests.json +JSON_SCRIPT_BIN=${TEST_JSON_SCRIPT=:-./json_script-example} +FILE_STDOUT=tests.stdout +FILE_STDERR=tests.stderr +FILE_EXPECTED=tests.expected + +call_json_script() { + #export LD_PRELOAD=../libjson_script.so + $JSON_SCRIPT_BIN "$@" "$JSON_SCRIPT" >"$FILE_STDOUT" 2>"$FILE_STDERR" +} + +assertStdioEquals() { + local expected="$1" + local file_stdio="$2" + + echo "$expected" >"$FILE_EXPECTED" + if [ -z "$expected" ]; then + # we are expecting empty output, but we deliberately added a newline + # with echo above, so adding another echo to compensate for that + echo >>"$file_stdio" + fi + diff -up "$FILE_EXPECTED" "$file_stdio" >/dev/null 2>&1 || { + cat >&2 <<EOF +|--- expecting +$expected< +|--- actual +$(cat $file_stdio)< +|--- END +EOF + exit 1 + } +} + +assertStdoutEquals() { + assertStdioEquals "$1" "$FILE_STDOUT" +} + +assertStderrEquals() { + assertStdioEquals "$1" "$FILE_STDERR" +} + +test_bad_json() { + cat >"$JSON_SCRIPT" <<-EOF + [ + [ ] + [ ] + ] + EOF + call_json_script + assertStderrEquals "load JSON data from $JSON_SCRIPT failed." +} + +test_expr_eq() { + cat >"$JSON_SCRIPT" <<-EOF + [ + [ "if", + [ "eq", "VAR", "foo" ], + [ "echo", "bar" ], + [ "echo", "baz" ] + ] + ] + EOF + call_json_script "VAR=foo" + assertStdoutEquals "echo bar" + call_json_script "VAR=xxx" + assertStdoutEquals "echo baz" +} + +test_expr_has() { + cat >"$JSON_SCRIPT" <<-EOF + [ + [ "if", + [ "has", "VAR" ], + [ "echo", "bar" ], + [ "echo", "baz" ] + ] + ] + EOF + call_json_script "VAR=foo" + assertStdoutEquals "echo bar" + call_json_script + assertStdoutEquals "echo baz" +} + +test_expr_regex_single() { + cat >"$JSON_SCRIPT" <<-EOF + [ + [ "if", + [ "regex", "VAR", ".ell." ], + [ "echo", "bar" ], + [ "echo", "baz" ] + ] + ] + EOF + call_json_script "VAR=hello" + assertStdoutEquals "echo bar" + call_json_script "VAR=.ell." + assertStdoutEquals "echo bar" + call_json_script + assertStdoutEquals "echo baz" + call_json_script "VAR=" + assertStdoutEquals "echo baz" + call_json_script "VAR=hell" + assertStdoutEquals "echo baz" +} + +test_expr_regex_multi() { + cat >"$JSON_SCRIPT" <<-EOF + [ + [ "if", + [ "regex", "VAR", [ ".ell.", "w.rld" ] ], + [ "echo", "bar" ], + [ "echo", "baz" ] + ] + ] + EOF + call_json_script "VAR=hello" + assertStdoutEquals "echo bar" + call_json_script "VAR=world" + assertStdoutEquals "echo bar" + call_json_script "VAR=.ell." + assertStdoutEquals "echo bar" + call_json_script "VAR=w.rld" + assertStdoutEquals "echo bar" + call_json_script + assertStdoutEquals "echo baz" + call_json_script "VAR=" + assertStdoutEquals "echo baz" + call_json_script "VAR=hell" + assertStdoutEquals "echo baz" +} + +test_expr_not() { + cat >"$JSON_SCRIPT" <<-EOF + [ + [ "if", + [ "not", [ "has", "VAR" ] ], + [ "echo", "bar" ], + [ "echo", "baz" ] + ] + ] + EOF + call_json_script "VAR=foo" + assertStdoutEquals "echo baz" + call_json_script + assertStdoutEquals "echo bar" +} + +test_expr_and() { + cat >"$JSON_SCRIPT" <<-EOF + [ + [ "if", + [ "and", [ "eq", "EQVAR", "eqval" ], + [ "regex", "REGEXVAR", "regex..." ] + ], + [ "echo", "bar" ], + [ "echo", "baz" ] + ] + ] + EOF + call_json_script "EQVAR=eqval" "REGEXVAR=regexval" + assertStdoutEquals "echo bar" + call_json_script "EQVAR=foo" + assertStdoutEquals "echo baz" + call_json_script "REGEXVAR=regex***" + assertStdoutEquals "echo baz" + call_json_script + assertStdoutEquals "echo baz" +} + +test_expr_or() { + cat >"$JSON_SCRIPT" <<-EOF + [ + [ "if", + [ "or", [ "not", [ "eq", "EQVAR", "eqval" ] ], + [ "regex", "REGEXVAR", [ "regexva.[0-9]", "regexva.[a-z]" ] ] + ], + [ "echo", "bar" ], + [ "echo", "baz" ] + ] + ] + EOF + call_json_script "EQVAR=eqval" "REGEXVAR=regexval1" + assertStdoutEquals "echo bar" + call_json_script "EQVAR=neq" "REGEXVAR=sxc" + assertStdoutEquals "echo bar" + call_json_script "REGEXVAR=sxc" + assertStdoutEquals "echo bar" + call_json_script "EQVAR=foo" + assertStdoutEquals "echo bar" + call_json_script + assertStdoutEquals "echo bar" + call_json_script "EQVAR=eqval" "REGEXVAR=regexval" + assertStdoutEquals "echo baz" +} + +test_expr_isdir() { + cat >"$JSON_SCRIPT" <<-EOF + [ + [ "if", + [ "isdir", "%VAR%" ], + [ "echo", "bar" ], + [ "echo", "baz" ] + ] + ] + EOF + call_json_script "VAR=/" + assertStdoutEquals "echo bar" + call_json_script "VAR=$(mktemp -u)" + assertStdoutEquals "echo baz" + call_json_script + assertStdoutEquals "echo baz" +} + +test_cmd_case() { + cat >"$JSON_SCRIPT" <<-EOF + [ + [ "case", "CASEVAR", { + "0": [ "echo", "foo" ], + "1": [ + [ "echo", "bar" ], + [ "echo", "baz" ] + ], + "%VAR%": [ "echo", "quz" ] + } ] + ] + EOF + call_json_script "CASEVAR=0" + assertStdoutEquals "echo foo" + call_json_script "CASEVAR=1" + assertStdoutEquals "echo bar +echo baz" + call_json_script "CASEVAR=%VAR%" + assertStdoutEquals "echo quz" + call_json_script "CASEVAR=" + assertStdoutEquals "" + call_json_script + assertStdoutEquals "" + call_json_script "CASEVAR=xxx" "VAR=xxx" + assertStdoutEquals "" +} + +test_cmd_if() { + cat >"$JSON_SCRIPT" <<-EOF + [ + [ "if", + [ "eq", "VAR", "foo" ], + [ "echo", "bar" ], + [ "echo", "baz" ] + ] + ] + EOF + call_json_script "VAR=foo" + assertStdoutEquals "echo bar" + call_json_script "VAR=xxx" + assertStdoutEquals "echo baz" +} + +test_cmd_cb() { + cat >"$JSON_SCRIPT" <<-EOF + [ + [ "exec", "%VAR%", "/%VAS%%%/" ] + ] + EOF + call_json_script + assertStdoutEquals "exec /%/" + call_json_script "VAR=" + assertStdoutEquals "exec /%/" + call_json_script "VAR=qux" "VAS=3" + assertStdoutEquals "exec qux /3%/" +} + +test_cmd_return() { + cat >"$JSON_SCRIPT" <<-EOF + [ + [ "heh", "%HEHVAR%" ], + [ "%VAR%", "%VAR%" ], + [ "return" ], + [ "exec_non_reachable", "Arghhh" ] + ] + EOF + call_json_script "HEHVAR=dude" "VAR=ow" + assertStdoutEquals "heh dude +%VAR% ow" +} + +. ./shunit2/shunit2 _______________________________________________ openwrt-devel mailing list openwrt-devel@lists.openwrt.org https://lists.openwrt.org/mailman/listinfo/openwrt-devel