libubox
C utility functions for OpenWrt.
shunit2
Go to the documentation of this file.
1 # $Id: shunit2 189 2008-07-11 11:46:54Z 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.4
10 # 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 
21 SHUNIT_VERSION='2.1.4'
22 
23 _shunit_warn() { echo "shunit2:WARN $@" >&2; }
24 _shunit_error() { echo "shunit2:ERROR $@" >&2; }
25 _shunit_fatal() { echo "shunit2:FATAL $@" >&2; }
26 
27 SHUNIT_TRUE=0
28 SHUNIT_FALSE=1
29 SHUNIT_ERROR=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 # 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
50 shunit_shellFlags_="$-"
51 for shunit_shellFlag_ in `echo "${__SHUNIT_SHELL_FLAGS}" |sed 's/\‍(.\‍)/\1 /g'`
52 do
53  set -${shunit_shellFlag_}
54 done
55 
56 #
57 # constants
58 #
59 
60 __SHUNIT_ASSERT_MSG_PREFIX='ASSERT:'
61 __SHUNIT_PARENT=${SHUNIT_PARENT:-$0}
62 
63 # set the constants readonly
64 shunit_constants_=`set |grep "^__SHUNIT_" |cut -d= -f1`
65 echo "${shunit_constants_}" |grep "^Binary file" >/dev/null
66 if [ $? -eq 0 ]; then
67  # deal with binary junk in 'set' output
68  shunit_constants_=`set |grep -a "^__SHUNIT_" |cut -d= -f1`
69 fi
70 for shunit_const_ in ${shunit_constants_}; do
71  shunit_ro_opts_=''
72  if [ -n "${ZSH_VERSION:-}" ]; then
73  case ${ZSH_VERSION} in
74  [123].*) ;;
75  *) shunit_ro_opts_='-g' ;; # declare readonly constants globally
76  esac
77  fi
78  readonly ${shunit_ro_opts_} ${shunit_const_}
79 done
80 unset shunit_const_ shunit_constants_ shunit_ro_opts_
81 
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 
91 # macros
92 _SHUNIT_LINENO_='eval if [ "${1:-}" = "--lineno" ]; then [ -n "$2" ] && shunit_message_="[$2]"; shift 2; fi'
93 
94 #-----------------------------------------------------------------------------
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 #*/
118 assertEquals()
119 {
120  ${_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
125  _shunit_shouldSkip && return ${SHUNIT_TRUE}
126 
127  [ -z "${shunit_message_:-}" ] && shunit_message_=''
128  if [ $# -eq 3 ]; then
129  shunit_message_="${shunit_message_}$1"
130  shift
131  fi
132  shunit_expected_=$1
133  shunit_actual_=$2
134 
135  shunit_return=${SHUNIT_TRUE}
136  if [ "${shunit_expected_}" = "${shunit_actual_}" ]; then
137  _shunit_testPassed
138  else
139  failNotEquals "${shunit_message_}" "${shunit_expected_}" "${shunit_actual_}"
140  shunit_return=${SHUNIT_FALSE}
141  fi
142 
143  unset shunit_message_ shunit_expected_ shunit_actual_ __shunit_lineno
144  return ${shunit_return}
145 }
146 _ASSERT_EQUALS_='eval assertEquals --lineno "${LINENO:-}"'
147 
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 #*/
166 assertNull()
167 {
168  ${_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
173  _shunit_shouldSkip && return ${SHUNIT_TRUE}
174 
175  [ -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' ]"
182  else
183  assertTrue "[ -z '$1' ]"
184  fi
185 }
186 _ASSERT_NULL_='eval assertNull --lineno "${LINENO:-}"'
187 
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 #*/
207 assertNotNull()
208 {
209  ${_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
214  _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 }
222 _ASSERT_NOT_NULL_='eval assertNotNull --lineno "${LINENO:-}"'
223 
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 #*/
243 assertSame()
244 {
245  ${_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
257 }
258 _ASSERT_SAME_='eval assertSame --lineno "${LINENO:-}"'
259 
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 #*/
280 assertNotSame()
281 {
282  ${_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
287  _shunit_shouldSkip && return ${SHUNIT_TRUE}
288 
289  [ -z "${shunit_message_:-}" ] && shunit_message_=''
290  if [ $# -eq 3 ]; then
291  shunit_message_="${shunit_message_}$1"
292  shift
293  fi
294  shunit_unexpected_=$1
295  shunit_actual_=$2
296 
297  shunit_return=${SHUNIT_TRUE}
298  if [ "${shunit_unexpected_}" != "${shunit_actual_}" ]; then
299  _shunit_testPassed
300  else
301  failSame "${shunit_message_}" "$@"
302  shunit_return=${SHUNIT_FALSE}
303  fi
304 
305  unset shunit_message_ shunit_unexpected_ shunit_actual_
306  return ${shunit_return}
307 }
308 _ASSERT_NOT_SAME_='eval assertNotSame --lineno "${LINENO:-}"'
309 
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 #*/
337 assertTrue()
338 {
339  ${_SHUNIT_LINENO_}
340  if [ $# -gt 2 ]; then
341  _shunit_error 'assertTrue() takes one two arguments'
342  return ${SHUNIT_ERROR}
343  fi
344  _shunit_shouldSkip && return ${SHUNIT_TRUE}
345 
346  [ -z "${shunit_message_:-}" ] && shunit_message_=''
347  if [ $# -eq 2 ]; then
348  shunit_message_="${shunit_message_}$1"
349  shift
350  fi
351  shunit_condition_=$1
352 
353  # see if condition is an integer, i.e. a return value
354  shunit_match_=`expr "${shunit_condition_}" : '\‍([0-9]*\‍)'`
355  shunit_return=${SHUNIT_TRUE}
356  if [ -z "${shunit_condition_}" ]; then
357  # null condition
358  shunit_return=${SHUNIT_FALSE}
359  elif [ "${shunit_condition_}" = "${shunit_match_}" ]; then
360  # possible return value. treating 0 as true, and non-zero as false.
361  [ ${shunit_condition_} -ne 0 ] && shunit_return=${SHUNIT_FALSE}
362  else
363  # (hopefully) a condition
364  ( eval ${shunit_condition_} ) >/dev/null 2>&1
365  [ $? -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
372  _shunit_testFailed "${shunit_message_}"
373  fi
374 
375  unset shunit_message_ shunit_condition_ shunit_match_
376  return ${shunit_return}
377 }
378 _ASSERT_TRUE_='eval assertTrue --lineno "${LINENO:-}"'
379 
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 #*/
407 assertFalse()
408 {
409  ${_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
414  _shunit_shouldSkip && return ${SHUNIT_TRUE}
415 
416  [ -z "${shunit_message_:-}" ] && shunit_message_=''
417  if [ $# -eq 2 ]; then
418  shunit_message_="${shunit_message_}$1"
419  shift
420  fi
421  shunit_condition_=$1
422 
423  # see if condition is an integer, i.e. a return value
424  shunit_match_=`expr "${shunit_condition_}" : '\‍([0-9]*\‍)'`
425  shunit_return=${SHUNIT_TRUE}
426  if [ -z "${shunit_condition_}" ]; then
427  # null condition
428  shunit_return=${SHUNIT_FALSE}
429  elif [ "${shunit_condition_}" = "${shunit_match_}" ]; then
430  # possible return value. treating 0 as true, and non-zero as false.
431  [ ${shunit_condition_} -eq 0 ] && shunit_return=${SHUNIT_FALSE}
432  else
433  # (hopefully) a condition
434  ( eval ${shunit_condition_} ) >/dev/null 2>&1
435  [ $? -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
442  _shunit_testFailed "${shunit_message_}"
443  fi
444 
445  unset shunit_message_ shunit_condition_ shunit_match_
446  return ${shunit_return}
447 }
448 _ASSERT_FALSE_='eval assertFalse --lineno "${LINENO:-}"'
449 
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 #*/
470 fail()
471 {
472  ${_SHUNIT_LINENO_}
473  if [ $# -gt 1 ]; then
474  _shunit_error 'fail() requires one or two arguments'
475  return ${SHUNIT_ERROR}
476  fi
477  _shunit_shouldSkip && return ${SHUNIT_TRUE}
478 
479  [ -z "${shunit_message_:-}" ] && shunit_message_=''
480  if [ $# -eq 1 ]; then
481  shunit_message_="${shunit_message_}$1"
482  shift
483  fi
484 
485  _shunit_testFailed "${shunit_message_}"
486 
487  unset shunit_message_
488  return ${SHUNIT_FALSE}
489 }
490 _FAIL_='eval fail --lineno "${LINENO:-}"'
491 
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 #*/
512 failNotEquals()
513 {
514  ${_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
519  _shunit_shouldSkip && return ${SHUNIT_TRUE}
520 
521  [ -z "${shunit_message_:-}" ] && shunit_message_=''
522  if [ $# -eq 3 ]; then
523  shunit_message_="${shunit_message_}$1"
524  shift
525  fi
526  shunit_unexpected_=$1
527  shunit_actual_=$2
528 
529  _shunit_testFailed "${shunit_message_:+${shunit_message_} }expected:<${shunit_unexpected_}> but was:<${shunit_actual_}>"
530 
531  unset shunit_message_ shunit_unexpected_ shunit_actual_
532  return ${SHUNIT_FALSE}
533 }
534 _FAIL_NOT_EQUALS_='eval failNotEquals --lineno "${LINENO:-}"'
535 
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 #*/
553 failSame()
554 {
555  ${_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
560  _shunit_shouldSkip && return ${SHUNIT_TRUE}
561 
562  [ -z "${shunit_message_:-}" ] && shunit_message_=''
563  if [ $# -eq 3 ]; then
564  shunit_message_="${shunit_message_}$1"
565  shift
566  fi
567 
568  _shunit_testFailed "${shunit_message_:+${shunit_message_} }expected not same"
569 
570  unset shunit_message_
571  return ${SHUNIT_FALSE}
572 }
573 _FAIL_SAME_='eval failSame --lineno "${LINENO:-}"'
574 
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 #*/
595 failNotSame()
596 {
597  ${_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
609 }
610 _FAIL_NOT_SAME_='eval failNotSame --lineno "${LINENO:-}"'
611 
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 #*/
634 startSkipping()
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 #*/
656 endSkipping()
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 #*/
677 isSkipping()
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 #*/
729 suite_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
853  # add 128 to signal and exit
854  exit `expr ${signal} + 128`
855  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 
881 _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 #
905 tests passed: ${_su__passed}
906 tests failed: ${_su__failed}
907 tests skipped: ${_su__skipped}
908 tests total: ${_su__total}
909 EOF
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 
933  _su__tmpDir="${TMPDIR:-/tmp}/shunit.${_su__random}"
934  ( 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
950 exit 0
951 EOF
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
995 trap '_shunit_cleanup EXIT' 0
996 trap '_shunit_cleanup INT' 2
997 trap '_shunit_cleanup TERM' 15
998 
999 # create phantom functions to work around issues with Cygwin
1000 _shunit_mktempFunc
1001 PATH="${__shunit_tmpDir}:${PATH}"
1002 
1003 # execute the oneTimeSetUp function (if it exists)
1004 oneTimeSetUp
1005 
1006 # execute the suite function defined in the parent test script
1007 # deprecated as of 2.1.0
1008 suite
1009 
1010 # if no suite function was defined, dynamically build a list of functions
1011 if [ -z "${__shunit_suite}" ]; then
1012  shunit_funcs_=`grep "^[ \t]*test[A-Za-z0-9_]* *()" ${__SHUNIT_PARENT} \
1013  |sed 's/[^A-Za-z0-9_]//g'`
1014  for shunit_func_ in ${shunit_funcs_}; do
1015  suite_addTest ${shunit_func_}
1016  done
1017 fi
1018 unset shunit_func_ shunit_funcs_
1019 
1020 # execute the tests
1021 _shunit_execSuite
1022 
1023 # execute the oneTimeTearDown function (if it exists)
1024 oneTimeTearDown
1025 
1026 # generate report
1027 _shunit_generateReport
1028 
1029 # restore the previous set of shell flags
1030 for shunit_shellFlag_ in ${__SHUNIT_SHELL_FLAGS}; do
1031  echo ${shunit_shellFlags_} |grep ${shunit_shellFlag_} >/dev/null \
1032  || set +${shunit_shellFlag_}
1033 done
1034 unset shunit_shellFlag_ shunit_shellFlags_
1035 
1036 [ ${__shunit_testsFailed} -eq 0 ] || exit 1
1037 
1038 #/**
1039 # </s:shelldoc>
1040 #*/