blob: eef19d410146135435654d19ef364f0755db75c1 [file] [log] [blame]
kate.wardf32fb4f2008-07-11 15:20:38 +00001# $Id: shunit2 189 2008-07-11 11:46:54Z kate.ward@forestent.com $
kate.wardf51c6162008-06-17 16:38:35 +00002# vim:et:ft=sh:sts=2:sw=2
3# vim:foldmethod=marker:foldmarker=/**,*/
4#
5#/**
6# <?xml version="1.0" encoding="UTF-8"?>
7# <s:shelldoc xmlns:s="http://www.forestent.com/projects/shelldoc/xsl/2005.0">
8# <s:header>
kate.wardf32fb4f2008-07-11 15:20:38 +00009# shUnit 2.1.4
kate.wardf51c6162008-06-17 16:38:35 +000010# Shell Unit Test Framework
11#
12# http://shunit2.sourceforge.net/
13#
14# written by Kate Ward &lt;kate.ward@forestent.com&gt;
15# released under the LGPL
16#
17# this module implements a xUnit based unit test framework similar to JUnit
18# </s:header>
19#*/
20
kate.wardf32fb4f2008-07-11 15:20:38 +000021SHUNIT_VERSION='2.1.4'
kate.wardf51c6162008-06-17 16:38:35 +000022
23_shunit_warn() { echo "shunit2:WARN $@" >&2; }
24_shunit_error() { echo "shunit2:ERROR $@" >&2; }
25_shunit_fatal() { echo "shunit2:FATAL $@" >&2; }
26
27SHUNIT_TRUE=0
28SHUNIT_FALSE=1
29SHUNIT_ERROR=2
30
31# specific shell checks
32if [ -n "${ZSH_VERSION:-}" ]; then
kate.wardf32fb4f2008-07-11 15:20:38 +000033 setopt |grep "^shwordsplit$" >/dev/null
34 if [ $? -ne ${SHUNIT_TRUE} ]; then
35 _shunit_fatal 'zsh shwordsplit option is required for proper operation'
kate.wardf51c6162008-06-17 16:38:35 +000036 exit ${SHUNIT_ERROR}
37 fi
38 if [ -z "${SHUNIT_PARENT:-}" ]; then
39 _shunit_fatal "zsh does not pass \$0 through properly. please declare \
40\"SHUNIT_PARENT=\$0\" before calling shUnit2"
41 exit ${SHUNIT_ERROR}
42 fi
43fi
44
45# shell flags for shunit2:
46# u - treat unset variables as an error when performing parameter expansion
47__SHUNIT_SHELL_FLAGS='u'
48
49# save the current set of shell flags, and then set some for ourself
kate.wardf32fb4f2008-07-11 15:20:38 +000050shunit_shellFlags_="$-"
51for shunit_shellFlag_ in `echo "${__SHUNIT_SHELL_FLAGS}" |sed 's/\(.\)/\1 /g'`
kate.wardf51c6162008-06-17 16:38:35 +000052do
kate.wardf32fb4f2008-07-11 15:20:38 +000053 set -${shunit_shellFlag_}
kate.wardf51c6162008-06-17 16:38:35 +000054done
55
56#
57# constants
58#
59
60__SHUNIT_ASSERT_MSG_PREFIX='ASSERT:'
61__SHUNIT_PARENT=${SHUNIT_PARENT:-$0}
62
63# set the constants readonly
kate.wardf32fb4f2008-07-11 15:20:38 +000064shunit_constants_=`set |grep "^__SHUNIT_" |cut -d= -f1`
65echo "${shunit_constants_}" |grep "^Binary file" >/dev/null
kate.wardf51c6162008-06-17 16:38:35 +000066if [ $? -eq 0 ]; then
67 # deal with binary junk in 'set' output
kate.wardf32fb4f2008-07-11 15:20:38 +000068 shunit_constants_=`set |grep -a "^__SHUNIT_" |cut -d= -f1`
kate.wardf51c6162008-06-17 16:38:35 +000069fi
kate.wardf32fb4f2008-07-11 15:20:38 +000070for shunit_const_ in ${shunit_constants_}; do
71 shunit_ro_opts_=''
kate.wardf51c6162008-06-17 16:38:35 +000072 if [ -n "${ZSH_VERSION:-}" ]; then
kate.wardf32fb4f2008-07-11 15:20:38 +000073 case ${ZSH_VERSION} in
74 [123].*) ;;
75 *) shunit_ro_opts_='-g' ;; # declare readonly constants globally
76 esac
kate.wardf51c6162008-06-17 16:38:35 +000077 fi
kate.wardf32fb4f2008-07-11 15:20:38 +000078 readonly ${shunit_ro_opts_} ${shunit_const_}
kate.wardf51c6162008-06-17 16:38:35 +000079done
kate.wardf32fb4f2008-07-11 15:20:38 +000080unset shunit_const_ shunit_constants_ shunit_ro_opts_
kate.wardf51c6162008-06-17 16:38:35 +000081
82# variables
83__shunit_skip=${SHUNIT_FALSE}
84__shunit_suite=''
85
86__shunit_testsPassed=0
87__shunit_testsFailed=0
88__shunit_testsSkipped=0
89__shunit_testsTotal=0
90
kate.wardf32fb4f2008-07-11 15:20:38 +000091# macros
92_SHUNIT_LINENO_='eval if [ "${1:-}" = "--lineno" ]; then [ -n "$2" ] && shunit_message_="[$2]"; shift 2; fi'
93
kate.wardf51c6162008-06-17 16:38:35 +000094#-----------------------------------------------------------------------------
95# assert functions
96#
97
98#/**
99# <s:function group="asserts">
100# <entry align="right">
101# <emphasis>void</emphasis>
102# </entry>
103# <entry>
104# <funcsynopsis>
105# <funcprototype>
106# <funcdef><function>assertEquals</function></funcdef>
107# <paramdef>string <parameter>[message]</parameter></paramdef>
108# <paramdef>string <parameter>expected</parameter></paramdef>
109# <paramdef>string <parameter>actual</parameter></paramdef>
110# </funcprototype>
111# </funcsynopsis>
112# <para>Asserts that <emphasis>expected</emphasis> and
113# <emphasis>actual</emphasis> are equal to one another. The message is
114# optional.</para>
115# </entry>
116# </s:function>
117#*/
118assertEquals()
119{
kate.wardf32fb4f2008-07-11 15:20:38 +0000120 ${_SHUNIT_LINENO_}
121 if [ $# -lt 2 -o $# -gt 3 ]; then
122 _shunit_error 'assertEquals() requires one or two arguments'
123 return ${SHUNIT_ERROR}
124 fi
kate.wardf51c6162008-06-17 16:38:35 +0000125 _shunit_shouldSkip && return ${SHUNIT_TRUE}
126
kate.wardf32fb4f2008-07-11 15:20:38 +0000127 [ -z "${shunit_message_:-}" ] && shunit_message_=''
128 if [ $# -eq 3 ]; then
129 shunit_message_="${shunit_message_}$1"
kate.wardf51c6162008-06-17 16:38:35 +0000130 shift
131 fi
kate.wardf32fb4f2008-07-11 15:20:38 +0000132 shunit_expected_=$1
133 shunit_actual_=$2
kate.wardf51c6162008-06-17 16:38:35 +0000134
135 shunit_return=${SHUNIT_TRUE}
kate.wardf32fb4f2008-07-11 15:20:38 +0000136 if [ "${shunit_expected_}" = "${shunit_actual_}" ]; then
kate.wardf51c6162008-06-17 16:38:35 +0000137 _shunit_testPassed
138 else
kate.wardf32fb4f2008-07-11 15:20:38 +0000139 failNotEquals "${shunit_message_}" "${shunit_expected_}" "${shunit_actual_}"
kate.wardf51c6162008-06-17 16:38:35 +0000140 shunit_return=${SHUNIT_FALSE}
141 fi
142
kate.wardf32fb4f2008-07-11 15:20:38 +0000143 unset shunit_message_ shunit_expected_ shunit_actual_ __shunit_lineno
kate.wardf51c6162008-06-17 16:38:35 +0000144 return ${shunit_return}
145}
kate.wardf32fb4f2008-07-11 15:20:38 +0000146_ASSERT_EQUALS_='eval assertEquals --lineno "${LINENO:-}"'
kate.wardf51c6162008-06-17 16:38:35 +0000147
148#/**
149# <s:function group="asserts">
150# <entry align="right">
151# <emphasis>void</emphasis>
152# </entry>
153# <entry>
154# <funcsynopsis>
155# <funcprototype>
156# <funcdef><function>assertNull</function></funcdef>
157# <paramdef>string <parameter>[message]</parameter></paramdef>
158# <paramdef>string <parameter>value</parameter></paramdef>
159# </funcprototype>
160# </funcsynopsis>
161# <para>Asserts that <emphasis>value</emphasis> is <literal>null</literal>,
162# or in shell terms a zero-length string. The message is optional.</para>
163# </entry>
164# </s:function>
165#*/
166assertNull()
167{
kate.wardf32fb4f2008-07-11 15:20:38 +0000168 ${_SHUNIT_LINENO_}
169 if [ $# -lt 1 -o $# -gt 2 ]; then
170 _shunit_error 'assertNull() requires one or two arguments'
171 return ${SHUNIT_ERROR}
172 fi
kate.wardf51c6162008-06-17 16:38:35 +0000173 _shunit_shouldSkip && return ${SHUNIT_TRUE}
174
kate.wardf32fb4f2008-07-11 15:20:38 +0000175 [ -z "${shunit_message_:-}" ] && shunit_message_=''
176 if [ $# -eq 2 ]; then
177 shunit_message_="${shunit_message_}$1"
178 shift
179 fi
180 if [ $# -eq 2 ]; then
181 assertTrue "${shunit_message_}$1" "[ -z '$2' ]"
kate.wardf51c6162008-06-17 16:38:35 +0000182 else
kate.wardf32fb4f2008-07-11 15:20:38 +0000183 assertTrue "[ -z '$1' ]"
kate.wardf51c6162008-06-17 16:38:35 +0000184 fi
185}
kate.wardf32fb4f2008-07-11 15:20:38 +0000186_ASSERT_NULL_='eval assertNull --lineno "${LINENO:-}"'
kate.wardf51c6162008-06-17 16:38:35 +0000187
188#/**
189# <s:function group="asserts">
190# <entry align="right">
191# <emphasis>void</emphasis>
192# </entry>
193# <entry>
194# <funcsynopsis>
195# <funcprototype>
196# <funcdef><function>assertNotNull</function></funcdef>
197# <paramdef>string <parameter>[message]</parameter></paramdef>
198# <paramdef>string <parameter>value</parameter></paramdef>
199# </funcprototype>
200# </funcsynopsis>
201# <para>Asserts that <emphasis>value</emphasis> is <emphasis
202# role="strong">not</emphasis> <literal>null</literal>, or in shell terms not
203# a zero-length string. The message is optional.</para>
204# </entry>
205# </s:function>
206#*/
207assertNotNull()
208{
kate.wardf32fb4f2008-07-11 15:20:38 +0000209 ${_SHUNIT_LINENO_}
210 if [ $# -gt 2 ]; then # allowing 0 arguments as $1 might actually be null
211 _shunit_error 'assertNotNull() requires one or two arguments'
212 return ${SHUNIT_ERROR}
213 fi
kate.wardf51c6162008-06-17 16:38:35 +0000214 _shunit_shouldSkip && return ${SHUNIT_TRUE}
215
216 if [ $# -eq 2 ]; then
217 assertTrue "$1" "[ -n '$2' ]"
218 else
219 assertTrue "[ -n '${1:-}' ]"
220 fi
221}
kate.wardf32fb4f2008-07-11 15:20:38 +0000222_ASSERT_NOT_NULL_='eval assertNotNull --lineno "${LINENO:-}"'
kate.wardf51c6162008-06-17 16:38:35 +0000223
224#/**
225# <s:function group="asserts">
226# <entry align="right">
227# <emphasis>void</emphasis>
228# </entry>
229# <entry>
230# <funcsynopsis>
231# <funcprototype>
232# <funcdef><function>assertSame</function></funcdef>
233# <paramdef>string <parameter>[message]</parameter></paramdef>
234# <paramdef>string <parameter>expected</parameter></paramdef>
235# <paramdef>string <parameter>actual</parameter></paramdef>
236# </funcprototype>
237# </funcsynopsis>
238# <para>This function is functionally equivalent to
239# <function>assertEquals</function>.</para>
240# </entry>
241# </s:function>
242#*/
243assertSame()
244{
kate.wardf32fb4f2008-07-11 15:20:38 +0000245 ${_SHUNIT_LINENO_}
246 if [ $# -lt 2 -o $# -gt 3 ]; then
247 _shunit_error 'assertSame() requires one or two arguments'
248 return ${SHUNIT_ERROR}
249 fi
250 _shunit_shouldSkip && return ${SHUNIT_TRUE}
251
252 if [ $# -eq 2 ]; then
253 assertEquals "$1" "$2"
254 else
255 assertEquals "$1" "$2" "$3"
256 fi
kate.wardf51c6162008-06-17 16:38:35 +0000257}
kate.wardf32fb4f2008-07-11 15:20:38 +0000258_ASSERT_SAME_='eval assertSame --lineno "${LINENO:-}"'
kate.wardf51c6162008-06-17 16:38:35 +0000259
260#/**
261# <s:function group="asserts">
262# <entry align="right">
263# <emphasis>void</emphasis>
264# </entry>
265# <entry>
266# <funcsynopsis>
267# <funcprototype>
268# <funcdef><function>assertNotSame</function></funcdef>
269# <paramdef>string <parameter>[message]</parameter></paramdef>
270# <paramdef>string <parameter>unexpected</parameter></paramdef>
271# <paramdef>string <parameter>actual</parameter></paramdef>
272# </funcprototype>
273# </funcsynopsis>
274# <para>Asserts that <emphasis>unexpected</emphasis> and
275# <emphasis>actual</emphasis> are <emphasis role="strong">not</emphasis>
276# equal to one another. The message is optional.</para>
277# </entry>
278# </s:function>
279#*/
280assertNotSame()
281{
kate.wardf32fb4f2008-07-11 15:20:38 +0000282 ${_SHUNIT_LINENO_}
283 if [ $# -lt 2 -o $# -gt 3 ]; then
284 _shunit_error 'assertNotSame() requires two or three arguments'
285 return ${SHUNIT_ERROR}
286 fi
kate.wardf51c6162008-06-17 16:38:35 +0000287 _shunit_shouldSkip && return ${SHUNIT_TRUE}
288
kate.wardf32fb4f2008-07-11 15:20:38 +0000289 [ -z "${shunit_message_:-}" ] && shunit_message_=''
kate.wardf51c6162008-06-17 16:38:35 +0000290 if [ $# -eq 3 ]; then
kate.wardf32fb4f2008-07-11 15:20:38 +0000291 shunit_message_="${shunit_message_}$1"
kate.wardf51c6162008-06-17 16:38:35 +0000292 shift
293 fi
kate.wardf32fb4f2008-07-11 15:20:38 +0000294 shunit_unexpected_=$1
295 shunit_actual_=$2
kate.wardf51c6162008-06-17 16:38:35 +0000296
297 shunit_return=${SHUNIT_TRUE}
kate.wardf32fb4f2008-07-11 15:20:38 +0000298 if [ "${shunit_unexpected_}" != "${shunit_actual_}" ]; then
kate.wardf51c6162008-06-17 16:38:35 +0000299 _shunit_testPassed
300 else
kate.wardf32fb4f2008-07-11 15:20:38 +0000301 failSame "${shunit_message_}" "$@"
kate.wardf51c6162008-06-17 16:38:35 +0000302 shunit_return=${SHUNIT_FALSE}
303 fi
304
kate.wardf32fb4f2008-07-11 15:20:38 +0000305 unset shunit_message_ shunit_unexpected_ shunit_actual_
kate.wardf51c6162008-06-17 16:38:35 +0000306 return ${shunit_return}
307}
kate.wardf32fb4f2008-07-11 15:20:38 +0000308_ASSERT_NOT_SAME_='eval assertNotSame --lineno "${LINENO:-}"'
kate.wardf51c6162008-06-17 16:38:35 +0000309
310#/**
311# <s:function group="asserts">
312# <entry align="right">
313# <emphasis>void</emphasis>
314# </entry>
315# <entry>
316# <funcsynopsis>
317# <funcprototype>
318# <funcdef><function>assertTrue</function></funcdef>
319# <paramdef>string <parameter>[message]</parameter></paramdef>
320# <paramdef>string <parameter>condition</parameter></paramdef>
321# </funcprototype>
322# </funcsynopsis>
323# <para>Asserts that a given shell test condition is true. The message is
324# optional.</para>
325# <para>Testing whether something is true or false is easy enough by using
326# the assertEquals/assertNotSame functions. Shell supports much more
327# complicated tests though, and a means to support them was needed. As such,
328# this function tests that conditions are true or false through evaluation
329# rather than just looking for a true or false.</para>
330# <funcsynopsis>
331# The following test will succeed: <funcsynopsisinfo>assertTrue "[ 34 -gt 23 ]"</funcsynopsisinfo>
332# The folloing test will fail with a message: <funcsynopsisinfo>assertTrue "test failed" "[ -r '/non/existant/file' ]"</funcsynopsisinfo>
333# </funcsynopsis>
334# </entry>
335# </s:function>
336#*/
337assertTrue()
338{
kate.wardf32fb4f2008-07-11 15:20:38 +0000339 ${_SHUNIT_LINENO_}
340 if [ $# -gt 2 ]; then
341 _shunit_error 'assertTrue() takes one two arguments'
342 return ${SHUNIT_ERROR}
343 fi
kate.wardf51c6162008-06-17 16:38:35 +0000344 _shunit_shouldSkip && return ${SHUNIT_TRUE}
345
kate.wardf32fb4f2008-07-11 15:20:38 +0000346 [ -z "${shunit_message_:-}" ] && shunit_message_=''
kate.wardf51c6162008-06-17 16:38:35 +0000347 if [ $# -eq 2 ]; then
kate.wardf32fb4f2008-07-11 15:20:38 +0000348 shunit_message_="${shunit_message_}$1"
kate.wardf51c6162008-06-17 16:38:35 +0000349 shift
350 fi
kate.wardf32fb4f2008-07-11 15:20:38 +0000351 shunit_condition_=$1
kate.wardf51c6162008-06-17 16:38:35 +0000352
353 # see if condition is an integer, i.e. a return value
kate.wardf32fb4f2008-07-11 15:20:38 +0000354 shunit_match_=`expr "${shunit_condition_}" : '\([0-9]*\)'`
355 shunit_return=${SHUNIT_TRUE}
356 if [ -z "${shunit_condition_}" ]; then
kate.wardf51c6162008-06-17 16:38:35 +0000357 # null condition
358 shunit_return=${SHUNIT_FALSE}
kate.wardf32fb4f2008-07-11 15:20:38 +0000359 elif [ "${shunit_condition_}" = "${shunit_match_}" ]; then
kate.wardf51c6162008-06-17 16:38:35 +0000360 # possible return value. treating 0 as true, and non-zero as false.
kate.wardf32fb4f2008-07-11 15:20:38 +0000361 [ ${shunit_condition_} -ne 0 ] && shunit_return=${SHUNIT_FALSE}
kate.wardf51c6162008-06-17 16:38:35 +0000362 else
363 # (hopefully) a condition
kate.wardf32fb4f2008-07-11 15:20:38 +0000364 ( eval ${shunit_condition_} ) >/dev/null 2>&1
kate.wardf51c6162008-06-17 16:38:35 +0000365 [ $? -ne 0 ] && shunit_return=${SHUNIT_FALSE}
366 fi
367
368 # record the test
369 if [ ${shunit_return} -eq ${SHUNIT_TRUE} ]; then
370 _shunit_testPassed
371 else
kate.wardf32fb4f2008-07-11 15:20:38 +0000372 _shunit_testFailed "${shunit_message_}"
kate.wardf51c6162008-06-17 16:38:35 +0000373 fi
374
kate.wardf32fb4f2008-07-11 15:20:38 +0000375 unset shunit_message_ shunit_condition_ shunit_match_
kate.wardf51c6162008-06-17 16:38:35 +0000376 return ${shunit_return}
377}
kate.wardf32fb4f2008-07-11 15:20:38 +0000378_ASSERT_TRUE_='eval assertTrue --lineno "${LINENO:-}"'
kate.wardf51c6162008-06-17 16:38:35 +0000379
380#/**
381# <s:function group="asserts">
382# <entry align="right">
383# <emphasis>void</emphasis>
384# </entry>
385# <entry>
386# <funcsynopsis>
387# <funcprototype>
388# <funcdef><function>assertFalse</function></funcdef>
389# <paramdef>string <parameter>[message]</parameter></paramdef>
390# <paramdef>string <parameter>condition</parameter></paramdef>
391# </funcprototype>
392# </funcsynopsis>
393# <para>Asserts that a given shell test condition is false. The message is
394# optional.</para>
395# <para>Testing whether something is true or false is easy enough by using
396# the assertEquals/assertNotSame functions. Shell supports much more
397# complicated tests though, and a means to support them was needed. As such,
398# this function tests that conditions are true or false through evaluation
399# rather than just looking for a true or false.</para>
400# <funcsynopsis>
401# The following test will succeed: <funcsynopsisinfo>assertFalse "[ 'apples' = 'oranges' ]"</funcsynopsisinfo>
402# The folloing test will fail with a message: <funcsynopsisinfo>assertFalse "test failed" "[ 1 -eq 1 -a 2 -eq 2 ]"</funcsynopsisinfo>
403# </funcsynopsis>
404# </entry>
405# </s:function>
406#*/
407assertFalse()
408{
kate.wardf32fb4f2008-07-11 15:20:38 +0000409 ${_SHUNIT_LINENO_}
410 if [ $# -lt 1 -o $# -gt 2 ]; then
411 _shunit_error 'assertFalse() quires one or two arguments'
412 return ${SHUNIT_ERROR}
413 fi
kate.wardf51c6162008-06-17 16:38:35 +0000414 _shunit_shouldSkip && return ${SHUNIT_TRUE}
415
kate.wardf32fb4f2008-07-11 15:20:38 +0000416 [ -z "${shunit_message_:-}" ] && shunit_message_=''
kate.wardf51c6162008-06-17 16:38:35 +0000417 if [ $# -eq 2 ]; then
kate.wardf32fb4f2008-07-11 15:20:38 +0000418 shunit_message_="${shunit_message_}$1"
kate.wardf51c6162008-06-17 16:38:35 +0000419 shift
420 fi
kate.wardf32fb4f2008-07-11 15:20:38 +0000421 shunit_condition_=$1
kate.wardf51c6162008-06-17 16:38:35 +0000422
423 # see if condition is an integer, i.e. a return value
kate.wardf32fb4f2008-07-11 15:20:38 +0000424 shunit_match_=`expr "${shunit_condition_}" : '\([0-9]*\)'`
425 shunit_return=${SHUNIT_TRUE}
426 if [ -z "${shunit_condition_}" ]; then
kate.wardf51c6162008-06-17 16:38:35 +0000427 # null condition
428 shunit_return=${SHUNIT_FALSE}
kate.wardf32fb4f2008-07-11 15:20:38 +0000429 elif [ "${shunit_condition_}" = "${shunit_match_}" ]; then
kate.wardf51c6162008-06-17 16:38:35 +0000430 # possible return value. treating 0 as true, and non-zero as false.
kate.wardf32fb4f2008-07-11 15:20:38 +0000431 [ ${shunit_condition_} -eq 0 ] && shunit_return=${SHUNIT_FALSE}
kate.wardf51c6162008-06-17 16:38:35 +0000432 else
433 # (hopefully) a condition
kate.wardf32fb4f2008-07-11 15:20:38 +0000434 ( eval ${shunit_condition_} ) >/dev/null 2>&1
kate.wardf51c6162008-06-17 16:38:35 +0000435 [ $? -eq 0 ] && shunit_return=${SHUNIT_FALSE}
436 fi
437
438 # record the test
439 if [ ${shunit_return} -eq ${SHUNIT_TRUE} ]; then
440 _shunit_testPassed
441 else
kate.wardf32fb4f2008-07-11 15:20:38 +0000442 _shunit_testFailed "${shunit_message_}"
kate.wardf51c6162008-06-17 16:38:35 +0000443 fi
444
kate.wardf32fb4f2008-07-11 15:20:38 +0000445 unset shunit_message_ shunit_condition_ shunit_match_
kate.wardf51c6162008-06-17 16:38:35 +0000446 return ${shunit_return}
447}
kate.wardf32fb4f2008-07-11 15:20:38 +0000448_ASSERT_FALSE_='eval assertFalse --lineno "${LINENO:-}"'
kate.wardf51c6162008-06-17 16:38:35 +0000449
450#-----------------------------------------------------------------------------
451# failure functions
452#
453
454#/**
455# <s:function group="failures">
456# <entry align="right">
457# <emphasis>void</emphasis>
458# </entry>
459# <entry>
460# <funcsynopsis>
461# <funcprototype>
462# <funcdef><function>fail</function></funcdef>
463# <paramdef>string <parameter>[message]</parameter></paramdef>
464# </funcprototype>
465# </funcsynopsis>
466# <para>Fails the test immediately, with the optional message.</para>
467# </entry>
468# </s:function>
469#*/
470fail()
471{
kate.wardf32fb4f2008-07-11 15:20:38 +0000472 ${_SHUNIT_LINENO_}
473 if [ $# -gt 1 ]; then
474 _shunit_error 'fail() requires one or two arguments'
475 return ${SHUNIT_ERROR}
476 fi
kate.wardf51c6162008-06-17 16:38:35 +0000477 _shunit_shouldSkip && return ${SHUNIT_TRUE}
478
kate.wardf32fb4f2008-07-11 15:20:38 +0000479 [ -z "${shunit_message_:-}" ] && shunit_message_=''
480 if [ $# -eq 1 ]; then
481 shunit_message_="${shunit_message_}$1"
482 shift
483 fi
kate.wardf51c6162008-06-17 16:38:35 +0000484
kate.wardf32fb4f2008-07-11 15:20:38 +0000485 _shunit_testFailed "${shunit_message_}"
kate.wardf51c6162008-06-17 16:38:35 +0000486
kate.wardf32fb4f2008-07-11 15:20:38 +0000487 unset shunit_message_
488 return ${SHUNIT_FALSE}
kate.wardf51c6162008-06-17 16:38:35 +0000489}
kate.wardf32fb4f2008-07-11 15:20:38 +0000490_FAIL_='eval fail --lineno "${LINENO:-}"'
kate.wardf51c6162008-06-17 16:38:35 +0000491
492#/**
493# <s:function group="failures">
494# <entry align="right">
495# <emphasis>void</emphasis>
496# </entry>
497# <entry>
498# <funcsynopsis>
499# <funcprototype>
500# <funcdef><function>failNotEquals</function></funcdef>
501# <paramdef>string <parameter>[message]</parameter></paramdef>
502# <paramdef>string <parameter>unexpected</parameter></paramdef>
503# <paramdef>string <parameter>actual</parameter></paramdef>
504# </funcprototype>
505# </funcsynopsis>
506# <para>Fails the test if <emphasis>unexpected</emphasis> and
507# <emphasis>actual</emphasis> are <emphasis role="strong">not</emphasis>
508# equal to one another. The message is optional.</para>
509# </entry>
510# </s:function>
511#*/
512failNotEquals()
513{
kate.wardf32fb4f2008-07-11 15:20:38 +0000514 ${_SHUNIT_LINENO_}
515 if [ $# -lt 2 -o $# -gt 3 ]; then
516 _shunit_error 'failNotEquals() requires one or two arguments'
517 return ${SHUNIT_ERROR}
518 fi
kate.wardf51c6162008-06-17 16:38:35 +0000519 _shunit_shouldSkip && return ${SHUNIT_TRUE}
520
kate.wardf32fb4f2008-07-11 15:20:38 +0000521 [ -z "${shunit_message_:-}" ] && shunit_message_=''
kate.wardf51c6162008-06-17 16:38:35 +0000522 if [ $# -eq 3 ]; then
kate.wardf32fb4f2008-07-11 15:20:38 +0000523 shunit_message_="${shunit_message_}$1"
kate.wardf51c6162008-06-17 16:38:35 +0000524 shift
525 fi
kate.wardf32fb4f2008-07-11 15:20:38 +0000526 shunit_unexpected_=$1
527 shunit_actual_=$2
kate.wardf51c6162008-06-17 16:38:35 +0000528
kate.wardf32fb4f2008-07-11 15:20:38 +0000529 _shunit_testFailed "${shunit_message_:+${shunit_message_} }expected:<${shunit_unexpected_}> but was:<${shunit_actual_}>"
kate.wardf51c6162008-06-17 16:38:35 +0000530
kate.wardf32fb4f2008-07-11 15:20:38 +0000531 unset shunit_message_ shunit_unexpected_ shunit_actual_
532 return ${SHUNIT_FALSE}
kate.wardf51c6162008-06-17 16:38:35 +0000533}
kate.wardf32fb4f2008-07-11 15:20:38 +0000534_FAIL_NOT_EQUALS_='eval failNotEquals --lineno "${LINENO:-}"'
kate.wardf51c6162008-06-17 16:38:35 +0000535
536#/**
537# <s:function group="failures">
538# <entry align="right">
539# <emphasis>void</emphasis>
540# </entry>
541# <entry>
542# <funcsynopsis>
543# <funcprototype>
544# <funcdef><function>failSame</function></funcdef>
545# <paramdef>string <parameter>[message]</parameter></paramdef>
546# </funcprototype>
547# </funcsynopsis>
548# <para>Indicate test failure because arguments were not the same. The
549# message is optional.</para>
550# </entry>
551# </s:function>
552#*/
553failSame()
554{
kate.wardf32fb4f2008-07-11 15:20:38 +0000555 ${_SHUNIT_LINENO_}
556 if [ $# -lt 2 -o $# -gt 3 ]; then
557 _shunit_error 'failSame() requires two or three arguments'
558 return ${SHUNIT_ERROR}
559 fi
kate.wardf51c6162008-06-17 16:38:35 +0000560 _shunit_shouldSkip && return ${SHUNIT_TRUE}
561
kate.wardf32fb4f2008-07-11 15:20:38 +0000562 [ -z "${shunit_message_:-}" ] && shunit_message_=''
563 if [ $# -eq 3 ]; then
564 shunit_message_="${shunit_message_}$1"
565 shift
566 fi
kate.wardf51c6162008-06-17 16:38:35 +0000567
kate.wardf32fb4f2008-07-11 15:20:38 +0000568 _shunit_testFailed "${shunit_message_:+${shunit_message_} }expected not same"
kate.wardf51c6162008-06-17 16:38:35 +0000569
kate.wardf32fb4f2008-07-11 15:20:38 +0000570 unset shunit_message_
571 return ${SHUNIT_FALSE}
kate.wardf51c6162008-06-17 16:38:35 +0000572}
kate.wardf32fb4f2008-07-11 15:20:38 +0000573_FAIL_SAME_='eval failSame --lineno "${LINENO:-}"'
kate.wardf51c6162008-06-17 16:38:35 +0000574
575#/**
576# <s:function group="failures">
577# <entry align="right">
578# <emphasis>void</emphasis>
579# </entry>
580# <entry>
581# <funcsynopsis>
582# <funcprototype>
583# <funcdef><function>failNotSame</function></funcdef>
584# <paramdef>string <parameter>[message]</parameter></paramdef>
585# <paramdef>string <parameter>expected</parameter></paramdef>
586# <paramdef>string <parameter>actual</parameter></paramdef>
587# </funcprototype>
588# </funcsynopsis>
589# <para>Fails the test if <emphasis>expected</emphasis> and
590# <emphasis>actual</emphasis> are equal to one another. The message is
591# optional.</para>
592# </entry>
593# </s:function>
594#*/
595failNotSame()
596{
kate.wardf32fb4f2008-07-11 15:20:38 +0000597 ${_SHUNIT_LINENO_}
598 if [ $# -lt 2 -o $# -gt 3 ]; then
599 _shunit_error 'failNotEquals() requires one or two arguments'
600 return ${SHUNIT_ERROR}
601 fi
602 _shunit_shouldSkip && return ${SHUNIT_TRUE}
603
604 if [ $# -eq 2 ]; then
605 failNotEquals "$1" "$2"
606 else
607 failNotEquals "$1" "$2" "$3"
608 fi
kate.wardf51c6162008-06-17 16:38:35 +0000609}
kate.wardf32fb4f2008-07-11 15:20:38 +0000610_FAIL_NOT_SAME_='eval failNotSame --lineno "${LINENO:-}"'
kate.wardf51c6162008-06-17 16:38:35 +0000611
612#-----------------------------------------------------------------------------
613# skipping functions
614#
615
616#/**
617# <s:function group="skipping">
618# <entry align="right">
619# <emphasis>void</emphasis>
620# </entry>
621# <entry>
622# <funcsynopsis>
623# <funcprototype>
624# <funcdef><function>startSkipping</function></funcdef>
625# <paramdef />
626# </funcprototype>
627# </funcsynopsis>
628# <para>This function forces the remaining assert and fail functions to be
629# "skipped", i.e. they will have no effect. Each function skipped will be
630# recorded so that the total of asserts and fails will not be altered.</para>
631# </entry>
632# </s:function>
633#*/
634startSkipping()
635{
636 __shunit_skip=${SHUNIT_TRUE}
637}
638
639#/**
640# <s:function group="skipping">
641# <entry align="right">
642# <emphasis>void</emphasis>
643# </entry>
644# <entry>
645# <funcsynopsis>
646# <funcprototype>
647# <funcdef><function>endSkipping</function></funcdef>
648# <paramdef />
649# </funcprototype>
650# </funcsynopsis>
651# <para>This function returns calls to the assert and fail functions to their
652# default behavior, i.e. they will be called.</para>
653# </entry>
654# </s:function>
655#*/
656endSkipping()
657{
658 __shunit_skip=${SHUNIT_FALSE}
659}
660
661#/**
662# <s:function group="skipping">
663# <entry align="right">
664# <emphasis>boolean</emphasis>
665# </entry>
666# <entry>
667# <funcsynopsis>
668# <funcprototype>
669# <funcdef><function>isSkipping</function></funcdef>
670# <paramdef />
671# </funcprototype>
672# </funcsynopsis>
673# <para>This function returns the state of skipping.</para>
674# </entry>
675# </s:function>
676#*/
677isSkipping()
678{
679 return ${__shunit_skip}
680}
681
682#-----------------------------------------------------------------------------
683# suite functions
684#
685
686#/**
687# <s:function group="suites">
688# <entry align="right">
689# <emphasis>void</emphasis>
690# </entry>
691# <entry>
692# <funcsynopsis>
693# <funcprototype>
694# <funcdef><function>suite</function></funcdef>
695# <paramdef />
696# </funcprototype>
697# </funcsynopsis>
698# <para>This function can be optionally overridden by the user in their test
699# suite.</para>
700# <para>If this function exists, it will be called when
701# <command>shunit2</command> is sourced. If it does not exist, shUnit2 will
702# search the parent script for all functions beginning with the word
703# <literal>test</literal>, and they will be added dynamically to the test
704# suite.</para>
705# </entry>
706# </s:function>
707#*/
708# Note: see _shunit_mktempFunc() for actual implementation
709# suite() { :; }
710
711#/**
712# <s:function group="suites">
713# <entry align="right">
714# <emphasis>void</emphasis>
715# </entry>
716# <entry>
717# <funcsynopsis>
718# <funcprototype>
719# <funcdef><function>suite_addTest</function></funcdef>
720# <paramdef>string <parameter>function</parameter></paramdef>
721# </funcprototype>
722# </funcsynopsis>
723# <para>This function adds a function name to the list of tests scheduled for
724# execution as part of this test suite. This function should only be called
725# from within the <function>suite()</function> function.</para>
726# </entry>
727# </s:function>
728#*/
729suite_addTest()
730{
731 _su_func=${1:-}
732
733 __shunit_suite="${__shunit_suite:+${__shunit_suite} }${_su_func}"
734
735 unset _su_func
736}
737
738#/**
739# <s:function group="suites">
740# <entry align="right">
741# <emphasis>void</emphasis>
742# </entry>
743# <entry>
744# <funcsynopsis>
745# <funcprototype>
746# <funcdef><function>oneTimeSetUp</function></funcdef>
747# <paramdef />
748# </funcprototype>
749# </funcsynopsis>
750# <para>This function can be be optionally overridden by the user in their
751# test suite.</para>
752# <para>If this function exists, it will be called once before any tests are
753# run. It is useful to prepare a common environment for all tests.</para>
754# </entry>
755# </s:function>
756#*/
757# Note: see _shunit_mktempFunc() for actual implementation
758# oneTimeSetUp() { :; }
759
760#/**
761# <s:function group="suites">
762# <entry align="right">
763# <emphasis>void</emphasis>
764# </entry>
765# <entry>
766# <funcsynopsis>
767# <funcprototype>
768# <funcdef><function>oneTimeTearDown</function></funcdef>
769# <paramdef />
770# </funcprototype>
771# </funcsynopsis>
772# <para>This function can be be optionally overridden by the user in their
773# test suite.</para>
774# <para>If this function exists, it will be called once after all tests are
775# completed. It is useful to clean up the environment after all tests.</para>
776# </entry>
777# </s:function>
778#*/
779# Note: see _shunit_mktempFunc() for actual implementation
780# oneTimeTearDown() { :; }
781
782#/**
783# <s:function group="suites">
784# <entry align="right">
785# <emphasis>void</emphasis>
786# </entry>
787# <entry>
788# <funcsynopsis>
789# <funcprototype>
790# <funcdef><function>setUp</function></funcdef>
791# <paramdef />
792# </funcprototype>
793# </funcsynopsis>
794# <para>This function can be be optionally overridden by the user in their
795# test suite.</para>
796# <para>If this function exists, it will be called before each test is run.
797# It is useful to reset the environment before each test.</para>
798# </entry>
799# </s:function>
800#*/
801# Note: see _shunit_mktempFunc() for actual implementation
802# setUp() { :; }
803
804#/**
805# <s:function group="suites">
806# <entry align="right">
807# <emphasis>void</emphasis>
808# </entry>
809# <entry>
810# <funcsynopsis>
811# <funcprototype>
812# <funcdef><function>tearDown</function></funcdef>
813# <paramdef />
814# </funcprototype>
815# </funcsynopsis>
816# <para>This function can be be optionally overridden by the user in their
817# test suite.</para>
818# <para>If this function exists, it will be called after each test completes.
819# It is useful to clean up the environment after each test.</para>
820# </entry>
821# </s:function>
822#*/
823# Note: see _shunit_mktempFunc() for actual implementation
824# tearDown() { :; }
825
826#------------------------------------------------------------------------------
827# internal shUnit2 functions
828#
829
830_shunit_cleanup()
831{
832 name=$1
833
834 case ${name} in
835 EXIT) signal=0 ;;
836 INT) signal=2 ;;
837 TERM) signal=15 ;;
838 *)
839 _shunit_warn "unrecognized trap value (${name})"
840 signal=0
841 ;;
842 esac
843
844 # do our work
845 rm -fr "${__shunit_tmpDir}"
846
847 # exit for all non-EXIT signals
848 if [ ${name} != 'EXIT' ]; then
849 _shunit_warn "trapped and now handling the (${name}) signal"
850 _shunit_generateReport
851 # disable EXIT trap
852 trap 0
kate.wardf32fb4f2008-07-11 15:20:38 +0000853 # add 128 to signal and exit
854 exit `expr ${signal} + 128`
kate.wardf51c6162008-06-17 16:38:35 +0000855 fi
856}
857
858_shunit_execSuite()
859{
860 echo '#'
861 echo '# Performing tests'
862 echo '#'
863 for _su_func in ${__shunit_suite}; do
864 # disable skipping
865 endSkipping
866
867 # execute the per-test setup function
868 setUp
869
870 # execute the test
871 echo "${_su_func}"
872 eval ${_su_func}
873
874 # execute the per-test tear-down function
875 tearDown
876 done
877
878 unset _su_func
879}
880
kate.wardf51c6162008-06-17 16:38:35 +0000881_shunit_generateReport()
882{
883 _su__awkPercent='{printf("%4d %3.0f%%", $1, $1*100/$2)}'
884 if [ ${__shunit_testsTotal:-0} -gt 0 ]; then
885 _su__passed=`echo ${__shunit_testsPassed} ${__shunit_testsTotal} |\
886 awk "${_su__awkPercent}"`
887 _su__failed=`echo ${__shunit_testsFailed} ${__shunit_testsTotal} |\
888 awk "${_su__awkPercent}"`
889 _su__skipped=`echo ${__shunit_testsSkipped} ${__shunit_testsTotal} |\
890 awk "${_su__awkPercent}"`
891 _su__total=`echo ${__shunit_testsTotal} 100 |\
892 awk '{printf("%4d %3d%%", $1, $2)}'`
893 else
894 _su__passed=`echo 0 0 |awk '{printf("%4d %3d%%", $1, $2)}'`
895 _su__failed=${_su__passed}
896 _su__skipped=${_su__passed}
897 _su__total=${_su__passed}
898 fi
899
900 cat <<EOF
901
902#
903# Test report
904#
905tests passed: ${_su__passed}
906tests failed: ${_su__failed}
907tests skipped: ${_su__skipped}
908tests total: ${_su__total}
909EOF
910
911 unset _su__awkPercent _su__passed _su__failed _su__skipped _su__total
912}
913
914# this function is a cross-platform temporary directory creation tool. not all
915# OSes have the mktemp function, so one is included here.
916_shunit_mktempDir()
917{
918 # try the standard mktemp function
919 ( exec mktemp -dqt shunit.XXXXXX 2>/dev/null ) && return
920
921 # the standard mktemp didn't work. doing our own.
922 if [ -r '/dev/urandom' ]; then
923 _su__random=`od -vAn -N4 -tx4 </dev/urandom |sed 's/^[^0-9a-f]*//'`
924 elif [ -n "${RANDOM:-}" ]; then
925 # $RANDOM works
926 _su__random=${RANDOM}${RANDOM}${RANDOM}$$
927 else
928 # $RANDOM doesn't work
929 _su__date=`date '+%Y%m%d%H%M%S'`
930 _su__random=`expr ${_su__date} / $$`
931 fi
932
kate.wardf32fb4f2008-07-11 15:20:38 +0000933 _su__tmpDir="${TMPDIR:-/tmp}/shunit.${_su__random}"
kate.wardf51c6162008-06-17 16:38:35 +0000934 ( umask 077 && mkdir "${_su__tmpDir}" ) || {
935 echo 'shUnit:FATAL could not create temporary directory! exiting' >&2
936 exit 1
937 }
938
939 echo ${_su__tmpDir}
940 unset _su__date _su__random _su__tmpDir
941}
942
943# this function is here to work around issues in Cygwin
944_shunit_mktempFunc()
945{
946 for _su__func in oneTimeSetUp oneTimeTearDown setUp tearDown suite; do
947 _su__file="${__shunit_tmpDir}/${_su__func}"
948 cat <<EOF >"${_su__file}"
949#! /bin/sh
950exit 0
951EOF
952 chmod +x "${_su__file}"
953 done
954
955 unset _su__file
956}
957
958_shunit_shouldSkip()
959{
960 [ ${__shunit_skip} -eq ${SHUNIT_FALSE} ] && return ${SHUNIT_FALSE}
961 _shunit_testSkipped
962}
963
964_shunit_testPassed()
965{
966 __shunit_testsPassed=`expr ${__shunit_testsPassed} + 1`
967 __shunit_testsTotal=`expr ${__shunit_testsTotal} + 1`
968}
969
970_shunit_testFailed()
971{
972 _su__msg=$1
973
974 __shunit_testsFailed=`expr ${__shunit_testsFailed} + 1`
975 __shunit_testsTotal=`expr ${__shunit_testsTotal} + 1`
976 echo "${__SHUNIT_ASSERT_MSG_PREFIX}${_su__msg}" >&2
977
978 unset _su__msg
979}
980
981_shunit_testSkipped()
982{
983 __shunit_testsSkipped=`expr ${__shunit_testsSkipped} + 1`
984 __shunit_testsTotal=`expr ${__shunit_testsTotal} + 1`
985}
986
987#------------------------------------------------------------------------------
988# main
989#
990
991# create a temporary storage location
992__shunit_tmpDir=`_shunit_mktempDir`
993
994# setup traps to clean up after ourselves
995trap '_shunit_cleanup EXIT' 0
996trap '_shunit_cleanup INT' 2
997trap '_shunit_cleanup TERM' 15
998
999# create phantom functions to work around issues with Cygwin
1000_shunit_mktempFunc
1001PATH="${__shunit_tmpDir}:${PATH}"
1002
1003# execute the oneTimeSetUp function (if it exists)
kate.wardf51c6162008-06-17 16:38:35 +00001004oneTimeSetUp
1005
1006# execute the suite function defined in the parent test script
1007# deprecated as of 2.1.0
1008suite
1009
1010# if no suite function was defined, dynamically build a list of functions
1011if [ -z "${__shunit_suite}" ]; then
kate.wardf32fb4f2008-07-11 15:20:38 +00001012 shunit_funcs_=`grep "^[ \t]*test[A-Za-z0-9_]* *()" ${__SHUNIT_PARENT} \
kate.wardf51c6162008-06-17 16:38:35 +00001013 |sed 's/[^A-Za-z0-9_]//g'`
kate.wardf32fb4f2008-07-11 15:20:38 +00001014 for shunit_func_ in ${shunit_funcs_}; do
1015 suite_addTest ${shunit_func_}
kate.wardf51c6162008-06-17 16:38:35 +00001016 done
1017fi
kate.wardf32fb4f2008-07-11 15:20:38 +00001018unset shunit_func_ shunit_funcs_
kate.wardf51c6162008-06-17 16:38:35 +00001019
1020# execute the tests
1021_shunit_execSuite
1022
1023# execute the oneTimeTearDown function (if it exists)
1024oneTimeTearDown
1025
1026# generate report
1027_shunit_generateReport
1028
1029# restore the previous set of shell flags
kate.wardf32fb4f2008-07-11 15:20:38 +00001030for shunit_shellFlag_ in ${__SHUNIT_SHELL_FLAGS}; do
1031 echo ${shunit_shellFlags_} |grep ${shunit_shellFlag_} >/dev/null \
1032 || set +${shunit_shellFlag_}
kate.wardf51c6162008-06-17 16:38:35 +00001033done
kate.wardf32fb4f2008-07-11 15:20:38 +00001034unset shunit_shellFlag_ shunit_shellFlags_
kate.wardf51c6162008-06-17 16:38:35 +00001035
1036[ ${__shunit_testsFailed} -eq 0 ] || exit 1
1037
1038#/**
1039# </s:shelldoc>
1040#*/