From patchwork Sun Jan 12 22:55:12 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: =?utf-8?q?Petr_=C5=A0tetiar?= X-Patchwork-Id: 1221903 X-Patchwork-Delegate: ynezz@true.cz Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=lists.openwrt.org (client-ip=2607:7c80:54:e::133; helo=bombadil.infradead.org; envelope-from=openwrt-devel-bounces+incoming=patchwork.ozlabs.org@lists.openwrt.org; receiver=) Authentication-Results: ozlabs.org; dmarc=none (p=none dis=none) header.from=true.cz Authentication-Results: ozlabs.org; dkim=pass (2048-bit key; unprotected) header.d=lists.infradead.org header.i=@lists.infradead.org header.a=rsa-sha256 header.s=bombadil.20170209 header.b=KZ11s4mL; dkim-atps=neutral Received: from bombadil.infradead.org (bombadil.infradead.org [IPv6:2607:7c80:54:e::133]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 47wsXL74QQz9s29 for ; Mon, 13 Jan 2020 09:56:18 +1100 (AEDT) DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.infradead.org; s=bombadil.20170209; h=Sender: Content-Transfer-Encoding:Content-Type:Cc:List-Subscribe:List-Help:List-Post: List-Archive:List-Unsubscribe:List-Id:Subject:MIME-Version:References: In-Reply-To:Message-Id:Date:To:From:Reply-To:Content-ID:Content-Description: Resent-Date:Resent-From:Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID: List-Owner; bh=Tu3W7NE+pGieZ349bIYknTy2k1VtAzygbETpoUNN8YU=; b=KZ11s4mLhL7Eb1 rK4rFOv7w7YPCHu9euHWYuQMgRImk3kGtJ9rFTL4vyZ/cXFcDDEyhLINM0ouG9rjU10UJMy7bscST Ze080liVBoLlHPM18MKeEjx4qtlYKZp8ndKG/u2FJ1WqtzPXccESZv4CeKIq0SIPDRqlfrCP45WoB ot4mawxDFRr4stfDfbsKdMo/JKea/aKYsVMIM1pwVYuF3/Qy3zRxa63stGJ2syfvABBpK32E14oUK ezugpr1KKJponVgpSvIEAmeDEarCCckeMMPP95UjIYthsYo9i4P8EwgkYpLRMHtRk8n5DHiDjYjIO wX4wrRnqgeadialY54jA==; Received: from localhost ([127.0.0.1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.92.3 #3 (Red Hat Linux)) id 1iqm9W-000293-SE; Sun, 12 Jan 2020 22:56:14 +0000 Received: from smtp-out.xnet.cz ([178.217.244.18]) by bombadil.infradead.org with esmtps (Exim 4.92.3 #3 (Red Hat Linux)) id 1iqm8m-0001CX-L9 for openwrt-devel@lists.openwrt.org; Sun, 12 Jan 2020 22:55:34 +0000 Received: from meh.true.cz (meh.true.cz [108.61.167.218]) (Authenticated sender: petr@true.cz) by smtp-out.xnet.cz (Postfix) with ESMTPSA id 03F723789; Sun, 12 Jan 2020 23:55:21 +0100 (CET) Received: by meh.true.cz (OpenSMTPD) with ESMTP id 8f20fcc7; Sun, 12 Jan 2020 23:55:11 +0100 (CET) From: =?utf-8?q?Petr_=C5=A0tetiar?= To: openwrt-devel@lists.openwrt.org Date: Sun, 12 Jan 2020 23:55:12 +0100 Message-Id: <20200112225515.11654-2-ynezz@true.cz> In-Reply-To: <20200112225515.11654-1-ynezz@true.cz> References: <20200112225515.11654-1-ynezz@true.cz> MIME-Version: 1.0 X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20200112_145529_013436_5CC2E291 X-CRM114-Status: GOOD ( 13.97 ) X-Spam-Score: 0.0 (/) X-Spam-Report: SpamAssassin version 3.4.2 on bombadil.infradead.org summary: Content analysis details: (0.0 points) pts rule name description ---- ---------------------- -------------------------------------------------- -0.0 RCVD_IN_DNSWL_NONE RBL: Sender listed at https://www.dnswl.org/, no trust [178.217.244.18 listed in list.dnswl.org] 0.0 SPF_NONE SPF: sender does not publish an SPF Record 0.0 SPF_HELO_NONE SPF: HELO does not publish an SPF Record Subject: [OpenWrt-Devel] [PATCH libubox 1/4] tests: include json script shunit2 based testing X-BeenThere: openwrt-devel@lists.openwrt.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: =?utf-8?q?Petr_=C5=A0tetiar?= Sender: "openwrt-devel" Errors-To: openwrt-devel-bounces+incoming=patchwork.ozlabs.org@lists.openwrt.org Include shunit2 based tests into unit testing pipeline until (eventually) it's converted to cram based unit tests. Signed-off-by: Petr Štetiar --- 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=$") 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.ward@forestent.com $ +# vim:et:ft=sh:sts=2:sw=2 +# vim:foldmethod=marker:foldmarker=/**,*/ +# +#/** +# +# +# +# shUnit 2.1.4 +# Shell Unit Test Framework +# +# http://shunit2.sourceforge.net/ +# +# written by Kate Ward <kate.ward@forestent.com> +# released under the LGPL +# +# this module implements a xUnit based unit test framework similar to JUnit +# +#*/ + +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 +# + +#/** +# +# +# void +# +# +# +# +# assertEquals +# string [message] +# string expected +# string actual +# +# +# Asserts that expected and +# actual are equal to one another. The message is +# optional. +# +# +#*/ +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:-}"' + +#/** +# +# +# void +# +# +# +# +# assertNull +# string [message] +# string value +# +# +# Asserts that value is null, +# or in shell terms a zero-length string. The message is optional. +# +# +#*/ +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:-}"' + +#/** +# +# +# void +# +# +# +# +# assertNotNull +# string [message] +# string value +# +# +# Asserts that value is not null, or in shell terms not +# a zero-length string. The message is optional. +# +# +#*/ +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:-}"' + +#/** +# +# +# void +# +# +# +# +# assertSame +# string [message] +# string expected +# string actual +# +# +# This function is functionally equivalent to +# assertEquals. +# +# +#*/ +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:-}"' + +#/** +# +# +# void +# +# +# +# +# assertNotSame +# string [message] +# string unexpected +# string actual +# +# +# Asserts that unexpected and +# actual are not +# equal to one another. The message is optional. +# +# +#*/ +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:-}"' + +#/** +# +# +# void +# +# +# +# +# assertTrue +# string [message] +# string condition +# +# +# Asserts that a given shell test condition is true. The message is +# optional. +# 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. +# +# The following test will succeed: assertTrue "[ 34 -gt 23 ]" +# The folloing test will fail with a message: assertTrue "test failed" "[ -r '/non/existant/file' ]" +# +# +# +#*/ +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:-}"' + +#/** +# +# +# void +# +# +# +# +# assertFalse +# string [message] +# string condition +# +# +# Asserts that a given shell test condition is false. The message is +# optional. +# 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. +# +# The following test will succeed: assertFalse "[ 'apples' = 'oranges' ]" +# The folloing test will fail with a message: assertFalse "test failed" "[ 1 -eq 1 -a 2 -eq 2 ]" +# +# +# +#*/ +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 +# + +#/** +# +# +# void +# +# +# +# +# fail +# string [message] +# +# +# Fails the test immediately, with the optional message. +# +# +#*/ +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:-}"' + +#/** +# +# +# void +# +# +# +# +# failNotEquals +# string [message] +# string unexpected +# string actual +# +# +# Fails the test if unexpected and +# actual are not +# equal to one another. The message is optional. +# +# +#*/ +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:-}"' + +#/** +# +# +# void +# +# +# +# +# failSame +# string [message] +# +# +# Indicate test failure because arguments were not the same. The +# message is optional. +# +# +#*/ +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:-}"' + +#/** +# +# +# void +# +# +# +# +# failNotSame +# string [message] +# string expected +# string actual +# +# +# Fails the test if expected and +# actual are equal to one another. The message is +# optional. +# +# +#*/ +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 +# + +#/** +# +# +# void +# +# +# +# +# startSkipping +# +# +# +# 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. +# +# +#*/ +startSkipping() +{ + __shunit_skip=${SHUNIT_TRUE} +} + +#/** +# +# +# void +# +# +# +# +# endSkipping +# +# +# +# This function returns calls to the assert and fail functions to their +# default behavior, i.e. they will be called. +# +# +#*/ +endSkipping() +{ + __shunit_skip=${SHUNIT_FALSE} +} + +#/** +# +# +# boolean +# +# +# +# +# isSkipping +# +# +# +# This function returns the state of skipping. +# +# +#*/ +isSkipping() +{ + return ${__shunit_skip} +} + +#----------------------------------------------------------------------------- +# suite functions +# + +#/** +# +# +# void +# +# +# +# +# suite +# +# +# +# This function can be optionally overridden by the user in their test +# suite. +# If this function exists, it will be called when +# shunit2 is sourced. If it does not exist, shUnit2 will +# search the parent script for all functions beginning with the word +# test, and they will be added dynamically to the test +# suite. +# +# +#*/ +# Note: see _shunit_mktempFunc() for actual implementation +# suite() { :; } + +#/** +# +# +# void +# +# +# +# +# suite_addTest +# string function +# +# +# 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 suite() function. +# +# +#*/ +suite_addTest() +{ + _su_func=${1:-} + + __shunit_suite="${__shunit_suite:+${__shunit_suite} }${_su_func}" + + unset _su_func +} + +#/** +# +# +# void +# +# +# +# +# oneTimeSetUp +# +# +# +# This function can be be optionally overridden by the user in their +# test suite. +# 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. +# +# +#*/ +# Note: see _shunit_mktempFunc() for actual implementation +# oneTimeSetUp() { :; } + +#/** +# +# +# void +# +# +# +# +# oneTimeTearDown +# +# +# +# This function can be be optionally overridden by the user in their +# test suite. +# 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. +# +# +#*/ +# Note: see _shunit_mktempFunc() for actual implementation +# oneTimeTearDown() { :; } + +#/** +# +# +# void +# +# +# +# +# setUp +# +# +# +# This function can be be optionally overridden by the user in their +# test suite. +# If this function exists, it will be called before each test is run. +# It is useful to reset the environment before each test. +# +# +#*/ +# Note: see _shunit_mktempFunc() for actual implementation +# setUp() { :; } + +#/** +# +# +# void +# +# +# +# +# tearDown +# +# +# +# This function can be be optionally overridden by the user in their +# test suite. +# If this function exists, it will be called after each test completes. +# It is useful to clean up the environment after each test. +# +# +#*/ +# 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 </dev/null ) && return + + # the standard mktemp didn't work. doing our own. + if [ -r '/dev/urandom' ]; then + _su__random=`od -vAn -N4 -tx4 &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 <"${_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 + +#/** +# +#*/ 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 <"$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