Initial code checkin
[grml-unittests.git] / autoconfig / unit_tests / shunit2
1 # $Id: shunit2 277 2008-10-29 21:20:22Z kate.ward@forestent.com $
2 # 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>
9 # shUnit 2.1.5
10 # Shell Unit Test Framework
11 #
12 # http://shunit2.googlecode.com/
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
21 SHUNIT_VERSION='2.1.5'
22
23 SHUNIT_TRUE=0
24 SHUNIT_FALSE=1
25 SHUNIT_ERROR=2
26
27 _shunit_warn() { echo "shunit2:WARN $@" >&2; }
28 _shunit_error() { echo "shunit2:ERROR $@" >&2; }
29 _shunit_fatal() { echo "shunit2:FATAL $@" >&2; }
30
31 # specific shell checks
32 if [ -n "${ZSH_VERSION:-}" ]; then
33   setopt |grep "^shwordsplit$" >/dev/null
34   if [ $? -ne ${SHUNIT_TRUE} ]; then
35     _shunit_fatal 'zsh shwordsplit option is required for proper operation'
36     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
43 fi
44
45 #
46 # constants
47 #
48
49 __SHUNIT_ASSERT_MSG_PREFIX='ASSERT:'
50 __SHUNIT_PARENT=${SHUNIT_PARENT:-$0}
51
52 # set the constants readonly
53 shunit_constants_=`set |grep '^__SHUNIT_' |cut -d= -f1`
54 echo "${shunit_constants_}" |grep '^Binary file' >/dev/null \
55     && shunit_constants_=`set |grep -a '^__SHUNIT_' |cut -d= -f1`
56 for shunit_constant_ in ${shunit_constants_}; do
57   shunit_ro_opts_=''
58   case ${ZSH_VERSION:-} in
59     '') ;;  # this isn't zsh
60     [123].*) ;;  # early versions (1.x, 2.x, 3.x)
61     *) shunit_ro_opts_='-g' ;;  # all later versions. declare readonly globally
62   esac
63   readonly ${shunit_ro_opts_} ${shunit_constant_}
64 done
65 unset shunit_constant_ shunit_constants_ shunit_ro_opts_
66
67 # variables
68 __shunit_skip=${SHUNIT_FALSE}
69 __shunit_suite=''
70
71 # counts of tests
72 __shunit_testSuccess=${SHUNIT_TRUE}
73 __shunit_testsTotal=0
74 __shunit_testsPassed=0
75 __shunit_testsFailed=0
76
77 # counts of asserts
78 __shunit_assertsTotal=0
79 __shunit_assertsPassed=0
80 __shunit_assertsFailed=0
81 __shunit_assertsSkipped=0
82
83 __shunit_lineno=''
84 __shunit_reportGenerated=${SHUNIT_FALSE}
85
86 # macros
87 _SHUNIT_LINENO_='eval __shunit_lineno=""; if [ "${1:-}" = "--lineno" ]; then [ -n "$2" ] && __shunit_lineno="[$2] "; shift 2; fi'
88
89 #-----------------------------------------------------------------------------
90 # assert functions
91 #
92
93 #/**
94 # <s:function group="asserts">
95 # <entry align="right">
96 #   <emphasis>void</emphasis>
97 # </entry>
98 # <entry>
99 #   <funcsynopsis>
100 #     <funcprototype>
101 #       <funcdef><function>assertEquals</function></funcdef>
102 #       <paramdef>string <parameter>[message]</parameter></paramdef>
103 #       <paramdef>string <parameter>expected</parameter></paramdef>
104 #       <paramdef>string <parameter>actual</parameter></paramdef>
105 #     </funcprototype>
106 #   </funcsynopsis>
107 #   <para>Asserts that <emphasis>expected</emphasis> and
108 #   <emphasis>actual</emphasis> are equal to one another. The message is
109 #   optional.</para>
110 # </entry>
111 # </s:function>
112 #*/
113 assertEquals()
114 {
115   ${_SHUNIT_LINENO_}
116   if [ $# -lt 2 -o $# -gt 3 ]; then
117     _shunit_error "assertEquals() requires two or three arguments; $# given"
118     _shunit_error "1: ${1:+$1} 2: ${2:+$2} 3: ${3:+$3}"
119     return ${SHUNIT_ERROR}
120   fi
121   _shunit_shouldSkip && return ${SHUNIT_TRUE}
122
123   shunit_message_=${__shunit_lineno}
124   if [ $# -eq 3 ]; then
125     shunit_message_="${shunit_message_}$1"
126     shift
127   fi
128   shunit_expected_=$1
129   shunit_actual_=$2
130
131   shunit_return=${SHUNIT_TRUE}
132   if [ "${shunit_expected_}" = "${shunit_actual_}" ]; then
133     _shunit_assertPass
134   else
135     failNotEquals "${shunit_message_}" "${shunit_expected_}" "${shunit_actual_}"
136     shunit_return=${SHUNIT_FALSE}
137   fi
138
139   unset shunit_message_ shunit_expected_ shunit_actual_
140   return ${shunit_return}
141 }
142 _ASSERT_EQUALS_='eval assertEquals --lineno "${LINENO:-}"'
143
144 #/**
145 # <s:function group="asserts">
146 # <entry align="right">
147 #   <emphasis>void</emphasis>
148 # </entry>
149 # <entry>
150 #   <funcsynopsis>
151 #     <funcprototype>
152 #       <funcdef><function>assertNotEquals</function></funcdef>
153 #       <paramdef>string <parameter>[message]</parameter></paramdef>
154 #       <paramdef>string <parameter>unexpected</parameter></paramdef>
155 #       <paramdef>string <parameter>actual</parameter></paramdef>
156 #     </funcprototype>
157 #   </funcsynopsis>
158 #   <para>Asserts that <emphasis>unexpected</emphasis> and
159 #   <emphasis>actual</emphasis> are <emphasis role="strong">not</emphasis>
160 #   equal to one another. The message is optional.</para>
161 # </entry>
162 # </s:function>
163 #*/
164 assertNotEquals()
165 {
166   ${_SHUNIT_LINENO_}
167   if [ $# -lt 2 -o $# -gt 3 ]; then
168     _shunit_error "assertNotEquals() requires two or three arguments; $# given"
169     return ${SHUNIT_ERROR}
170   fi
171   _shunit_shouldSkip && return ${SHUNIT_TRUE}
172
173   shunit_message_=${__shunit_lineno}
174   if [ $# -eq 3 ]; then
175     shunit_message_="${shunit_message_}$1"
176     shift
177   fi
178   shunit_unexpected_=$1
179   shunit_actual_=$2
180
181   shunit_return=${SHUNIT_TRUE}
182   if [ "${shunit_unexpected_}" != "${shunit_actual_}" ]; then
183     _shunit_assertPass
184   else
185     failSame "${shunit_message_}" "$@"
186     shunit_return=${SHUNIT_FALSE}
187   fi
188
189   unset shunit_message_ shunit_unexpected_ shunit_actual_
190   return ${shunit_return}
191 }
192 _ASSERT_NOT_EQUALS_='eval assertNotEquals --lineno "${LINENO:-}"'
193
194 #/**
195 # <s:function group="asserts">
196 # <entry align="right">
197 #   <emphasis>void</emphasis>
198 # </entry>
199 # <entry>
200 #   <funcsynopsis>
201 #     <funcprototype>
202 #       <funcdef><function>assertNull</function></funcdef>
203 #       <paramdef>string <parameter>[message]</parameter></paramdef>
204 #       <paramdef>string <parameter>value</parameter></paramdef>
205 #     </funcprototype>
206 #   </funcsynopsis>
207 #   <para>Asserts that <emphasis>value</emphasis> is <literal>null</literal>,
208 #   or in shell terms a zero-length string. The message is optional.</para>
209 # </entry>
210 # </s:function>
211 #*/
212 assertNull()
213 {
214   ${_SHUNIT_LINENO_}
215   if [ $# -lt 1 -o $# -gt 2 ]; then
216     _shunit_error "assertNull() requires one or two arguments; $# given"
217     return ${SHUNIT_ERROR}
218   fi
219   _shunit_shouldSkip && return ${SHUNIT_TRUE}
220
221   shunit_message_=${__shunit_lineno}
222   if [ $# -eq 2 ]; then
223     shunit_message_="${shunit_message_}$1"
224     shift
225   fi
226   assertTrue "${shunit_message_}" "[ -z '$1' ]"
227   shunit_return=$?
228
229   unset shunit_message_
230   return ${shunit_return}
231 }
232 _ASSERT_NULL_='eval assertNull --lineno "${LINENO:-}"'
233
234 #/**
235 # <s:function group="asserts">
236 # <entry align="right">
237 #   <emphasis>void</emphasis>
238 # </entry>
239 # <entry>
240 #   <funcsynopsis>
241 #     <funcprototype>
242 #       <funcdef><function>assertNotNull</function></funcdef>
243 #       <paramdef>string <parameter>[message]</parameter></paramdef>
244 #       <paramdef>string <parameter>value</parameter></paramdef>
245 #     </funcprototype>
246 #   </funcsynopsis>
247 #   <para>Asserts that <emphasis>value</emphasis> is <emphasis
248 #   role="strong">not</emphasis> <literal>null</literal>, or in shell terms not
249 #   a zero-length string. The message is optional.</para>
250 # </entry>
251 # </s:function>
252 #*/
253 assertNotNull()
254 {
255   ${_SHUNIT_LINENO_}
256   if [ $# -gt 2 ]; then  # allowing 0 arguments as $1 might actually be null
257     _shunit_error "assertNotNull() requires one or two arguments; $# given"
258     return ${SHUNIT_ERROR}
259   fi
260   _shunit_shouldSkip && return ${SHUNIT_TRUE}
261
262   shunit_message_=${__shunit_lineno}
263   if [ $# -eq 2 ]; then
264     shunit_message_="${shunit_message_}$1"
265     shift
266   fi
267   assertTrue "${shunit_message_}" "[ -n '${1:-}' ]"
268   shunit_return=$?
269
270   unset shunit_message_
271   return ${shunit_return}
272 }
273 _ASSERT_NOT_NULL_='eval assertNotNull --lineno "${LINENO:-}"'
274
275 #/**
276 # <s:function group="asserts">
277 # <entry align="right">
278 #   <emphasis>void</emphasis>
279 # </entry>
280 # <entry>
281 #   <funcsynopsis>
282 #     <funcprototype>
283 #       <funcdef><function>assertSame</function></funcdef>
284 #       <paramdef>string <parameter>[message]</parameter></paramdef>
285 #       <paramdef>string <parameter>expected</parameter></paramdef>
286 #       <paramdef>string <parameter>actual</parameter></paramdef>
287 #     </funcprototype>
288 #   </funcsynopsis>
289 #   <para>This function is functionally equivalent to
290 #   <function>assertEquals</function>.</para>
291 # </entry>
292 # </s:function>
293 #*/
294 assertSame()
295 {
296   ${_SHUNIT_LINENO_}
297   if [ $# -lt 2 -o $# -gt 3 ]; then
298     _shunit_error "assertSame() requires one or two arguments; $# given"
299     return ${SHUNIT_ERROR}
300   fi
301   _shunit_shouldSkip && return ${SHUNIT_TRUE}
302
303   shunit_message_=${__shunit_lineno}
304   if [ $# -eq 3 ]; then
305     shunit_message_="${shunit_message_}$1"
306     shift
307   fi
308   assertEquals "${shunit_message_}" "$1" "$2"
309   shunit_return=$?
310
311   unset shunit_message_
312   return ${shunit_return}
313 }
314 _ASSERT_SAME_='eval assertSame --lineno "${LINENO:-}"'
315
316 #/**
317 # <s:function group="asserts">
318 # <entry align="right">
319 #   <emphasis>void</emphasis>
320 # </entry>
321 # <entry>
322 #   <funcsynopsis>
323 #     <funcprototype>
324 #       <funcdef><function>assertNotSame</function></funcdef>
325 #       <paramdef>string <parameter>[message]</parameter></paramdef>
326 #       <paramdef>string <parameter>unexpected</parameter></paramdef>
327 #       <paramdef>string <parameter>actual</parameter></paramdef>
328 #     </funcprototype>
329 #   </funcsynopsis>
330 #   <para>Asserts that <emphasis>unexpected</emphasis> and
331 #   <emphasis>actual</emphasis> are <emphasis role="strong">not</emphasis>
332 #   equal to one another. The message is optional.</para>
333 # </entry>
334 # </s:function>
335 #*/
336 assertNotSame()
337 {
338   ${_SHUNIT_LINENO_}
339   if [ $# -lt 2 -o $# -gt 3 ]; then
340     _shunit_error "assertNotSame() requires two or three arguments; $# given"
341     return ${SHUNIT_ERROR}
342   fi
343   _shunit_shouldSkip && return ${SHUNIT_TRUE}
344
345   shunit_message_=${__shunit_lineno}
346   if [ $# -eq 3 ]; then
347     shunit_message_="${shunit_message_:-}$1"
348     shift
349   fi
350   assertNotEquals "${shunit_message_}" "$1" "$2"
351   shunit_return=$?
352
353   unset shunit_message_
354   return ${shunit_return}
355 }
356 _ASSERT_NOT_SAME_='eval assertNotSame --lineno "${LINENO:-}"'
357
358 #/**
359 # <s:function group="asserts">
360 # <entry align="right">
361 #   <emphasis>void</emphasis>
362 # </entry>
363 # <entry>
364 #   <funcsynopsis>
365 #     <funcprototype>
366 #       <funcdef><function>assertTrue</function></funcdef>
367 #       <paramdef>string <parameter>[message]</parameter></paramdef>
368 #       <paramdef>string <parameter>condition</parameter></paramdef>
369 #     </funcprototype>
370 #   </funcsynopsis>
371 #   <para>Asserts that a given shell test condition is true. The message is
372 #   optional.</para>
373 #   <para>Testing whether something is true or false is easy enough by using
374 #   the assertEquals/assertNotSame functions. Shell supports much more
375 #   complicated tests though, and a means to support them was needed. As such,
376 #   this function tests that conditions are true or false through evaluation
377 #   rather than just looking for a true or false.</para>
378 #   <funcsynopsis>
379 #     The following test will succeed: <funcsynopsisinfo>assertTrue "[ 34 -gt 23 ]"</funcsynopsisinfo>
380 #     The folloing test will fail with a message: <funcsynopsisinfo>assertTrue "test failed" "[ -r '/non/existant/file' ]"</funcsynopsisinfo>
381 #   </funcsynopsis>
382 # </entry>
383 # </s:function>
384 #*/
385 assertTrue()
386 {
387   ${_SHUNIT_LINENO_}
388   if [ $# -gt 2 ]; then
389     _shunit_error "assertTrue() takes one two arguments; $# given"
390     return ${SHUNIT_ERROR}
391   fi
392   _shunit_shouldSkip && return ${SHUNIT_TRUE}
393
394   shunit_message_=${__shunit_lineno}
395   if [ $# -eq 2 ]; then
396     shunit_message_="${shunit_message_}$1"
397     shift
398   fi
399   shunit_condition_=$1
400
401   # see if condition is an integer, i.e. a return value
402   shunit_match_=`expr "${shunit_condition_}" : '\([0-9]*\)'`
403   shunit_return=${SHUNIT_TRUE}
404   if [ -z "${shunit_condition_}" ]; then
405     # null condition
406     shunit_return=${SHUNIT_FALSE}
407   elif [ "${shunit_condition_}" = "${shunit_match_}" ]; then
408     # possible return value. treating 0 as true, and non-zero as false.
409     [ ${shunit_condition_} -ne 0 ] && shunit_return=${SHUNIT_FALSE}
410   else
411     # (hopefully) a condition
412     ( eval ${shunit_condition_} ) >/dev/null 2>&1
413     [ $? -ne 0 ] && shunit_return=${SHUNIT_FALSE}
414   fi
415
416   # record the test
417   if [ ${shunit_return} -eq ${SHUNIT_TRUE} ]; then
418     _shunit_assertPass
419   else
420     _shunit_assertFail "${shunit_message_}"
421   fi
422
423   unset shunit_message_ shunit_condition_ shunit_match_
424   return ${shunit_return}
425 }
426 _ASSERT_TRUE_='eval assertTrue --lineno "${LINENO:-}"'
427
428 #/**
429 # <s:function group="asserts">
430 # <entry align="right">
431 #   <emphasis>void</emphasis>
432 # </entry>
433 # <entry>
434 #   <funcsynopsis>
435 #     <funcprototype>
436 #       <funcdef><function>assertFalse</function></funcdef>
437 #       <paramdef>string <parameter>[message]</parameter></paramdef>
438 #       <paramdef>string <parameter>condition</parameter></paramdef>
439 #     </funcprototype>
440 #   </funcsynopsis>
441 #   <para>Asserts that a given shell test condition is false. The message is
442 #   optional.</para>
443 #   <para>Testing whether something is true or false is easy enough by using
444 #   the assertEquals/assertNotSame functions. Shell supports much more
445 #   complicated tests though, and a means to support them was needed. As such,
446 #   this function tests that conditions are true or false through evaluation
447 #   rather than just looking for a true or false.</para>
448 #   <funcsynopsis>
449 #     The following test will succeed: <funcsynopsisinfo>assertFalse "[ 'apples' = 'oranges' ]"</funcsynopsisinfo>
450 #     The folloing test will fail with a message: <funcsynopsisinfo>assertFalse "test failed" "[ 1 -eq 1 -a 2 -eq 2 ]"</funcsynopsisinfo>
451 #   </funcsynopsis>
452 # </entry>
453 # </s:function>
454 #*/
455 assertFalse()
456 {
457   ${_SHUNIT_LINENO_}
458   if [ $# -lt 1 -o $# -gt 2 ]; then
459     _shunit_error "assertFalse() quires one or two arguments; $# given"
460     return ${SHUNIT_ERROR}
461   fi
462   _shunit_shouldSkip && return ${SHUNIT_TRUE}
463
464   shunit_message_=${__shunit_lineno}
465   if [ $# -eq 2 ]; then
466     shunit_message_="${shunit_message_}$1"
467     shift
468   fi
469   shunit_condition_=$1
470
471   # see if condition is an integer, i.e. a return value
472   shunit_match_=`expr "${shunit_condition_}" : '\([0-9]*\)'`
473   shunit_return=${SHUNIT_TRUE}
474   if [ -z "${shunit_condition_}" ]; then
475     # null condition
476     shunit_return=${SHUNIT_FALSE}
477   elif [ "${shunit_condition_}" = "${shunit_match_}" ]; then
478     # possible return value. treating 0 as true, and non-zero as false.
479     [ ${shunit_condition_} -eq 0 ] && shunit_return=${SHUNIT_FALSE}
480   else
481     # (hopefully) a condition
482     ( eval ${shunit_condition_} ) >/dev/null 2>&1
483     [ $? -eq 0 ] && shunit_return=${SHUNIT_FALSE}
484   fi
485
486   # record the test
487   if [ ${shunit_return} -eq ${SHUNIT_TRUE} ]; then
488     _shunit_assertPass
489   else
490     _shunit_assertFail "${shunit_message_}"
491   fi
492
493   unset shunit_message_ shunit_condition_ shunit_match_
494   return ${shunit_return}
495 }
496 _ASSERT_FALSE_='eval assertFalse --lineno "${LINENO:-}"'
497
498 #-----------------------------------------------------------------------------
499 # failure functions
500 #
501
502 #/**
503 # <s:function group="failures">
504 # <entry align="right">
505 #   <emphasis>void</emphasis>
506 # </entry>
507 # <entry>
508 #   <funcsynopsis>
509 #     <funcprototype>
510 #       <funcdef><function>fail</function></funcdef>
511 #       <paramdef>string <parameter>[message]</parameter></paramdef>
512 #     </funcprototype>
513 #   </funcsynopsis>
514 #   <para>Fails the test immediately, with the optional message.</para>
515 # </entry>
516 # </s:function>
517 #*/
518 fail()
519 {
520   ${_SHUNIT_LINENO_}
521   if [ $# -gt 1 ]; then
522     _shunit_error "fail() requires one or two arguments; $# given"
523     return ${SHUNIT_ERROR}
524   fi
525   _shunit_shouldSkip && return ${SHUNIT_TRUE}
526
527   shunit_message_=${__shunit_lineno}
528   if [ $# -eq 1 ]; then
529     shunit_message_="${shunit_message_}$1"
530     shift
531   fi
532
533   _shunit_assertFail "${shunit_message_}"
534
535   unset shunit_message_
536   return ${SHUNIT_FALSE}
537 }
538 _FAIL_='eval fail --lineno "${LINENO:-}"'
539
540 #/**
541 # <s:function group="failures">
542 # <entry align="right">
543 #   <emphasis>void</emphasis>
544 # </entry>
545 # <entry>
546 #   <funcsynopsis>
547 #     <funcprototype>
548 #       <funcdef><function>failNotEquals</function></funcdef>
549 #       <paramdef>string <parameter>[message]</parameter></paramdef>
550 #       <paramdef>string <parameter>unexpected</parameter></paramdef>
551 #       <paramdef>string <parameter>actual</parameter></paramdef>
552 #     </funcprototype>
553 #   </funcsynopsis>
554 #   <para>Fails the test if <emphasis>unexpected</emphasis> and
555 #   <emphasis>actual</emphasis> are <emphasis role="strong">not</emphasis>
556 #   equal to one another. The message is optional.</para>
557 # </entry>
558 # </s:function>
559 #*/
560 failNotEquals()
561 {
562   ${_SHUNIT_LINENO_}
563   if [ $# -lt 2 -o $# -gt 3 ]; then
564     _shunit_error "failNotEquals() requires one or two arguments; $# given"
565     return ${SHUNIT_ERROR}
566   fi
567   _shunit_shouldSkip && return ${SHUNIT_TRUE}
568
569   shunit_message_=${__shunit_lineno}
570   if [ $# -eq 3 ]; then
571     shunit_message_="${shunit_message_}$1"
572     shift
573   fi
574   shunit_unexpected_=$1
575   shunit_actual_=$2
576
577   _shunit_assertFail "${shunit_message_:+${shunit_message_} }expected:<${shunit_unexpected_}> but was:<${shunit_actual_}>"
578
579   unset shunit_message_ shunit_unexpected_ shunit_actual_
580   return ${SHUNIT_FALSE}
581 }
582 _FAIL_NOT_EQUALS_='eval failNotEquals --lineno "${LINENO:-}"'
583
584 #/**
585 # <s:function group="failures">
586 # <entry align="right">
587 #   <emphasis>void</emphasis>
588 # </entry>
589 # <entry>
590 #   <funcsynopsis>
591 #     <funcprototype>
592 #       <funcdef><function>failSame</function></funcdef>
593 #       <paramdef>string <parameter>[message]</parameter></paramdef>
594 #     </funcprototype>
595 #   </funcsynopsis>
596 #   <para>Indicate test failure because arguments were the same. The message is
597 #   optional.</para>
598 # </entry>
599 # </s:function>
600 #*/
601 failSame()
602 {
603   ${_SHUNIT_LINENO_}
604   if [ $# -lt 2 -o $# -gt 3 ]; then
605     _shunit_error "failSame() requires two or three arguments; $# given"
606     return ${SHUNIT_ERROR}
607   fi
608   _shunit_shouldSkip && return ${SHUNIT_TRUE}
609
610   shunit_message_=${__shunit_lineno}
611   if [ $# -eq 3 ]; then
612     shunit_message_="${shunit_message_}$1"
613     shift
614   fi
615
616   _shunit_assertFail "${shunit_message_:+${shunit_message_} }expected not same"
617
618   unset shunit_message_
619   return ${SHUNIT_FALSE}
620 }
621 _FAIL_SAME_='eval failSame --lineno "${LINENO:-}"'
622
623 #/**
624 # <s:function group="failures">
625 # <entry align="right">
626 #   <emphasis>void</emphasis>
627 # </entry>
628 # <entry>
629 #   <funcsynopsis>
630 #     <funcprototype>
631 #       <funcdef><function>failNotSame</function></funcdef>
632 #       <paramdef>string <parameter>[message]</parameter></paramdef>
633 #       <paramdef>string <parameter>expected</parameter></paramdef>
634 #       <paramdef>string <parameter>actual</parameter></paramdef>
635 #     </funcprototype>
636 #   </funcsynopsis>
637 #   <para>Indicate test failure because arguments were not the same. The
638 #   message is optional.</para>
639 # </entry>
640 # </s:function>
641 #*/
642 failNotSame()
643 {
644   ${_SHUNIT_LINENO_}
645   if [ $# -lt 2 -o $# -gt 3 ]; then
646     _shunit_error "failNotEquals() requires one or two arguments; $# given"
647     return ${SHUNIT_ERROR}
648   fi
649   _shunit_shouldSkip && return ${SHUNIT_TRUE}
650
651   shunit_message_=${__shunit_lineno}
652   if [ $# -eq 3 ]; then
653     shunit_message_="${shunit_message_}$1"
654     shift
655   fi
656   failNotEquals "${shunit_message_}" "$1" "$2"
657   shunit_return=$?
658
659   unset shunit_message_
660   return ${shunit_return}
661 }
662 _FAIL_NOT_SAME_='eval failNotSame --lineno "${LINENO:-}"'
663
664 #-----------------------------------------------------------------------------
665 # skipping functions
666 #
667
668 #/**
669 # <s:function group="skipping">
670 # <entry align="right">
671 #   <emphasis>void</emphasis>
672 # </entry>
673 # <entry>
674 #   <funcsynopsis>
675 #     <funcprototype>
676 #       <funcdef><function>startSkipping</function></funcdef>
677 #       <paramdef />
678 #     </funcprototype>
679 #   </funcsynopsis>
680 #   <para>This function forces the remaining assert and fail functions to be
681 #   "skipped", i.e. they will have no effect. Each function skipped will be
682 #   recorded so that the total of asserts and fails will not be altered.</para>
683 # </entry>
684 # </s:function>
685 #*/
686 startSkipping()
687 {
688   __shunit_skip=${SHUNIT_TRUE}
689 }
690
691 #/**
692 # <s:function group="skipping">
693 # <entry align="right">
694 #   <emphasis>void</emphasis>
695 # </entry>
696 # <entry>
697 #   <funcsynopsis>
698 #     <funcprototype>
699 #       <funcdef><function>endSkipping</function></funcdef>
700 #       <paramdef />
701 #     </funcprototype>
702 #   </funcsynopsis>
703 #   <para>This function returns calls to the assert and fail functions to their
704 #   default behavior, i.e. they will be called.</para>
705 # </entry>
706 # </s:function>
707 #*/
708 endSkipping()
709 {
710   __shunit_skip=${SHUNIT_FALSE}
711 }
712
713 #/**
714 # <s:function group="skipping">
715 # <entry align="right">
716 #   <emphasis>boolean</emphasis>
717 # </entry>
718 # <entry>
719 #   <funcsynopsis>
720 #     <funcprototype>
721 #       <funcdef><function>isSkipping</function></funcdef>
722 #       <paramdef />
723 #     </funcprototype>
724 #   </funcsynopsis>
725 #   <para>This function returns the state of skipping.</para>
726 # </entry>
727 # </s:function>
728 #*/
729 isSkipping()
730 {
731   return ${__shunit_skip}
732 }
733
734 #-----------------------------------------------------------------------------
735 # suite functions
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>suite</function></funcdef>
747 #       <paramdef />
748 #     </funcprototype>
749 #   </funcsynopsis>
750 #   <para>This function can be optionally overridden by the user in their test
751 #   suite.</para>
752 #   <para>If this function exists, it will be called when
753 #   <command>shunit2</command> is sourced. If it does not exist, shUnit2 will
754 #   search the parent script for all functions beginning with the word
755 #   <literal>test</literal>, and they will be added dynamically to the test
756 #   suite.</para>
757 # </entry>
758 # </s:function>
759 #*/
760 # Note: see _shunit_mktempFunc() for actual implementation
761 # suite() { :; }
762
763 #/**
764 # <s:function group="suites">
765 # <entry align="right">
766 #   <emphasis>void</emphasis>
767 # </entry>
768 # <entry>
769 #   <funcsynopsis>
770 #     <funcprototype>
771 #       <funcdef><function>suite_addTest</function></funcdef>
772 #       <paramdef>string <parameter>function</parameter></paramdef>
773 #     </funcprototype>
774 #   </funcsynopsis>
775 #   <para>This function adds a function name to the list of tests scheduled for
776 #   execution as part of this test suite. This function should only be called
777 #   from within the <function>suite()</function> function.</para>
778 # </entry>
779 # </s:function>
780 #*/
781 suite_addTest()
782 {
783   shunit_func_=${1:-}
784
785   __shunit_suite="${__shunit_suite:+${__shunit_suite} }${shunit_func_}"
786   __shunit_testsTotal=`expr ${__shunit_testsTotal} + 1`
787
788   unset shunit_func_
789 }
790
791 #/**
792 # <s:function group="suites">
793 # <entry align="right">
794 #   <emphasis>void</emphasis>
795 # </entry>
796 # <entry>
797 #   <funcsynopsis>
798 #     <funcprototype>
799 #       <funcdef><function>oneTimeSetUp</function></funcdef>
800 #       <paramdef />
801 #     </funcprototype>
802 #   </funcsynopsis>
803 #   <para>This function can be be optionally overridden by the user in their
804 #   test suite.</para>
805 #   <para>If this function exists, it will be called once before any tests are
806 #   run. It is useful to prepare a common environment for all tests.</para>
807 # </entry>
808 # </s:function>
809 #*/
810 # Note: see _shunit_mktempFunc() for actual implementation
811 # oneTimeSetUp() { :; }
812
813 #/**
814 # <s:function group="suites">
815 # <entry align="right">
816 #   <emphasis>void</emphasis>
817 # </entry>
818 # <entry>
819 #   <funcsynopsis>
820 #     <funcprototype>
821 #       <funcdef><function>oneTimeTearDown</function></funcdef>
822 #       <paramdef />
823 #     </funcprototype>
824 #   </funcsynopsis>
825 #   <para>This function can be be optionally overridden by the user in their
826 #   test suite.</para>
827 #   <para>If this function exists, it will be called once after all tests are
828 #   completed. It is useful to clean up the environment after all tests.</para>
829 # </entry>
830 # </s:function>
831 #*/
832 # Note: see _shunit_mktempFunc() for actual implementation
833 # oneTimeTearDown() { :; }
834
835 #/**
836 # <s:function group="suites">
837 # <entry align="right">
838 #   <emphasis>void</emphasis>
839 # </entry>
840 # <entry>
841 #   <funcsynopsis>
842 #     <funcprototype>
843 #       <funcdef><function>setUp</function></funcdef>
844 #       <paramdef />
845 #     </funcprototype>
846 #   </funcsynopsis>
847 #   <para>This function can be be optionally overridden by the user in their
848 #   test suite.</para>
849 #   <para>If this function exists, it will be called before each test is run.
850 #   It is useful to reset the environment before each test.</para>
851 # </entry>
852 # </s:function>
853 #*/
854 # Note: see _shunit_mktempFunc() for actual implementation
855 # setUp() { :; }
856
857 #/**
858 # <s:function group="suites">
859 # <entry align="right">
860 #   <emphasis>void</emphasis>
861 # </entry>
862 # <entry>
863 #   <funcsynopsis>
864 #     <funcprototype>
865 #       <funcdef><function>tearDown</function></funcdef>
866 #       <paramdef />
867 #     </funcprototype>
868 #   </funcsynopsis>
869 #   <para>This function can be be optionally overridden by the user in their
870 #   test suite.</para>
871 #   <para>If this function exists, it will be called after each test completes.
872 #   It is useful to clean up the environment after each test.</para>
873 # </entry>
874 # </s:function>
875 #*/
876 # Note: see _shunit_mktempFunc() for actual implementation
877 # tearDown() { :; }
878
879 #------------------------------------------------------------------------------
880 # internal shUnit2 functions
881 #
882
883 # this function is a cross-platform temporary directory creation tool. not all
884 # OSes have the mktemp function, so one is included here.
885 _shunit_mktempDir()
886 {
887   # try the standard mktemp function
888   ( exec mktemp -dqt shunit.XXXXXX 2>/dev/null ) && return
889
890   # the standard mktemp didn't work.  doing our own.
891   if [ -r '/dev/urandom' ]; then
892     _shunit_random_=`od -vAn -N4 -tx4 </dev/urandom |sed 's/^[^0-9a-f]*//'`
893   elif [ -n "${RANDOM:-}" ]; then
894     # $RANDOM works
895     _shunit_random_=${RANDOM}${RANDOM}${RANDOM}$$
896   else
897     # $RANDOM doesn't work
898     _shunit_date_=`date '+%Y%m%d%H%M%S'`
899     _shunit_random_=`expr ${_shunit_date_} / $$`
900   fi
901
902   _shunit_tmpDir_="${TMPDIR:-/tmp}/shunit.${_shunit_random_}"
903   ( umask 077 && mkdir "${_shunit_tmpDir_}" ) || {
904     _shunit_fatal 'could not create temporary directory! exiting'
905     exit ${SHUNIT_FALSE}
906   }
907
908   echo ${_shunit_tmpDir_}
909   unset _shunit_date_ _shunit_random_ _shunit_tmpDir_
910 }
911
912 # this function is here to work around issues in Cygwin
913 _shunit_mktempFunc()
914 {
915   for _shunit_func_ in oneTimeSetUp oneTimeTearDown setUp tearDown suite; do
916     _shunit_file_="${__shunit_tmpDir}/${_shunit_func_}"
917     cat <<EOF >"${_shunit_file_}"
918 #! /bin/sh
919 exit ${SHUNIT_TRUE}
920 EOF
921     chmod +x "${_shunit_file_}"
922   done
923
924   unset _shunit_file_
925 }
926
927 _shunit_cleanup()
928 {
929   _shunit_name_=$1
930
931   case ${_shunit_name_} in
932     EXIT) _shunit_signal_=0 ;;
933     INT) _shunit_signal_=2 ;;
934     TERM) _shunit_signal_=15 ;;
935     *)
936       _shunit_warn "unrecognized trap value (${_shunit_name_})"
937       _shunit_signal_=0
938       ;;
939   esac
940
941   # do our work
942   rm -fr "${__shunit_tmpDir}"
943
944   # exit for all non-EXIT signals
945   if [ ${_shunit_name_} != 'EXIT' ]; then
946     _shunit_warn "trapped and now handling the (${_shunit_name_}) signal"
947     # disable EXIT trap
948     trap 0
949     # add 128 to signal and exit
950     exit `expr ${_shunit_signal_} + 128`
951   elif [ ${__shunit_reportGenerated} -eq ${SHUNIT_FALSE} ] ; then
952     _shunit_assertFail 'Unknown failure encountered running a test'
953     _shunit_generateReport
954     exit ${SHUNIT_ERROR}
955   fi
956
957   unset _shunit_name_ _shunit_signal_
958 }
959
960 # The actual running of the tests happens here.
961 _shunit_execSuite()
962 {
963   for _shunit_test_ in ${__shunit_suite}; do
964     __shunit_testSuccess=${SHUNIT_TRUE}
965
966     # disable skipping
967     endSkipping
968
969     # execute the per-test setup function
970     setUp
971
972     # execute the test
973     echo "${_shunit_test_}"
974     eval ${_shunit_test_}
975
976     # execute the per-test tear-down function
977     tearDown
978
979     # update stats
980     if [ ${__shunit_testSuccess} -eq ${SHUNIT_TRUE} ]; then
981       __shunit_testsPassed=`expr ${__shunit_testsPassed} + 1`
982     else
983       __shunit_testsFailed=`expr ${__shunit_testsFailed} + 1`
984     fi
985   done
986
987   unset _shunit_test_
988 }
989
990 # This function exits shUnit2 with the appropriate error code and OK/FAILED
991 # message.
992 _shunit_generateReport()
993 {
994   _shunit_ok_=${SHUNIT_TRUE}
995
996   # if no exit code was provided one, determine an appropriate one
997   [ ${__shunit_testsFailed} -gt 0 \
998       -o ${__shunit_testSuccess} -eq ${SHUNIT_FALSE} ] \
999           && _shunit_ok_=${SHUNIT_FALSE}
1000
1001   echo
1002   if [ ${__shunit_testsTotal} -eq 1 ]; then
1003     echo "Ran ${__shunit_testsTotal} test."
1004   else
1005     echo "Ran ${__shunit_testsTotal} tests."
1006   fi
1007
1008   _shunit_failures_=''
1009   _shunit_skipped_=''
1010   [ ${__shunit_assertsFailed} -gt 0 ] \
1011       && _shunit_failures_="failures=${__shunit_assertsFailed}"
1012   [ ${__shunit_assertsSkipped} -gt 0 ] \
1013       && _shunit_skipped_="skipped=${__shunit_assertsSkipped}"
1014
1015   if [ ${_shunit_ok_} -eq ${SHUNIT_TRUE} ]; then
1016     _shunit_msg_='OK'
1017     [ -n "${_shunit_skipped_}" ] \
1018         && _shunit_msg_="${_shunit_msg_} (${_shunit_skipped_})"
1019   else
1020     _shunit_msg_="FAILED (${_shunit_failures_}"
1021     [ -n "${_shunit_skipped_}" ] \
1022         && _shunit_msg_="${_shunit_msg_},${_shunit_skipped_}"
1023     _shunit_msg_="${_shunit_msg_})"
1024   fi
1025
1026   echo
1027   echo ${_shunit_msg_}
1028   __shunit_reportGenerated=${SHUNIT_TRUE}
1029
1030   unset _shunit_failures_ _shunit_msg_ _shunit_ok_ _shunit_skipped_
1031 }
1032
1033 _shunit_shouldSkip()
1034 {
1035   [ ${__shunit_skip} -eq ${SHUNIT_FALSE} ] && return ${SHUNIT_FALSE}
1036   _shunit_assertSkip
1037 }
1038
1039 _shunit_assertPass()
1040 {
1041   __shunit_assertsPassed=`expr ${__shunit_assertsPassed} + 1`
1042   __shunit_assertsTotal=`expr ${__shunit_assertsTotal} + 1`
1043 }
1044
1045 _shunit_assertFail()
1046 {
1047   _shunit_msg_=$1
1048
1049   __shunit_testSuccess=${SHUNIT_FALSE}
1050   __shunit_assertsFailed=`expr ${__shunit_assertsFailed} + 1`
1051   __shunit_assertsTotal=`expr ${__shunit_assertsTotal} + 1`
1052   echo "${__SHUNIT_ASSERT_MSG_PREFIX}${_shunit_msg_}"
1053
1054   unset _shunit_msg_
1055 }
1056
1057 _shunit_assertSkip()
1058 {
1059   __shunit_assertsSkipped=`expr ${__shunit_assertsSkipped} + 1`
1060   __shunit_assertsTotal=`expr ${__shunit_assertsTotal} + 1`
1061 }
1062
1063 #------------------------------------------------------------------------------
1064 # main
1065 #
1066
1067 # create a temporary storage location
1068 __shunit_tmpDir=`_shunit_mktempDir`
1069
1070 # provide a public temporary directory for unit test scripts
1071 # TODO(kward): document this
1072 shunit_tmpDir="${__shunit_tmpDir}/tmp"
1073 mkdir "${shunit_tmpDir}"
1074
1075 # setup traps to clean up after ourselves
1076 trap '_shunit_cleanup EXIT' 0
1077 trap '_shunit_cleanup INT' 2
1078 trap '_shunit_cleanup TERM' 15
1079
1080 # create phantom functions to work around issues with Cygwin
1081 _shunit_mktempFunc
1082 PATH="${__shunit_tmpDir}:${PATH}"
1083
1084 # execute the oneTimeSetUp function (if it exists)
1085 oneTimeSetUp
1086
1087 # execute the suite function defined in the parent test script
1088 # deprecated as of 2.1.0
1089 suite
1090
1091 # if no suite function was defined, dynamically build a list of functions
1092 if [ -z "${__shunit_suite}" ]; then
1093   shunit_funcs_=`grep "^[ \t]*test[A-Za-z0-9_]* *()" ${__SHUNIT_PARENT} \
1094       |sed 's/[^A-Za-z0-9_]//g'`
1095   for shunit_func_ in ${shunit_funcs_}; do
1096     suite_addTest ${shunit_func_}
1097   done
1098 fi
1099 unset shunit_func_ shunit_funcs_
1100
1101 # execute the tests
1102 _shunit_execSuite
1103
1104 # execute the oneTimeTearDown function (if it exists)
1105 oneTimeTearDown
1106
1107 # generate the report
1108 _shunit_generateReport
1109
1110 # that's it folks
1111 [ ${__shunit_testsFailed} -eq 0 ]
1112 exit $?
1113
1114 #/**
1115 # </s:shelldoc>
1116 #*/