citrun

watch C/C++ source code execute
Log | Files | Refs | LICENSE

libtap.subr (8031B)


      1 # Shell function library for test cases.
      2 #
      3 # Note that while many of the functions in this library could benefit from
      4 # using "local" to avoid possibly hammering global variables, Solaris /bin/sh
      5 # doesn't support local and this library aspires to be portable to Solaris
      6 # Bourne shell.  Instead, all private variables are prefixed with "tap_".
      7 #
      8 # This file provides a TAP-compatible shell function library useful for
      9 # writing test cases.  It is part of C TAP Harness, which can be found at
     10 # <http://www.eyrie.org/~eagle/software/c-tap-harness/>.
     11 #
     12 # Written by Russ Allbery <eagle@eyrie.org>
     13 # Copyright 2009, 2010, 2011, 2012, 2016 Russ Allbery <eagle@eyrie.org>
     14 # Copyright 2006, 2007, 2008, 2013
     15 #     The Board of Trustees of the Leland Stanford Junior University
     16 #
     17 # Permission is hereby granted, free of charge, to any person obtaining a copy
     18 # of this software and associated documentation files (the "Software"), to
     19 # deal in the Software without restriction, including without limitation the
     20 # rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
     21 # sell copies of the Software, and to permit persons to whom the Software is
     22 # furnished to do so, subject to the following conditions:
     23 #
     24 # The above copyright notice and this permission notice shall be included in
     25 # all copies or substantial portions of the Software.
     26 #
     27 # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
     28 # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
     29 # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
     30 # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
     31 # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
     32 # FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
     33 # IN THE SOFTWARE.
     34 
     35 # Print out the number of test cases we expect to run.
     36 plan () {
     37     count=1
     38     planned="$1"
     39     failed=0
     40     echo "1..$1"
     41     trap finish 0
     42 }
     43 
     44 # Prepare for lazy planning.
     45 plan_lazy () {
     46     count=1
     47     planned=0
     48     failed=0
     49     trap finish 0
     50 }
     51 
     52 # Report the test status on exit.
     53 finish () {
     54     tap_highest=`expr "$count" - 1`
     55     if [ "$planned" = 0 ] ; then
     56         echo "1..$tap_highest"
     57         planned="$tap_highest"
     58     fi
     59     tap_looks='# Looks like you'
     60     if [ "$planned" -gt 0 ] ; then
     61         if [ "$planned" -gt "$tap_highest" ] ; then
     62             if [ "$planned" -gt 1 ] ; then
     63                 echo "$tap_looks planned $planned tests but only ran" \
     64                     "$tap_highest"
     65             else
     66                 echo "$tap_looks planned $planned test but only ran" \
     67                     "$tap_highest"
     68             fi
     69         elif [ "$planned" -lt "$tap_highest" ] ; then
     70             tap_extra=`expr "$tap_highest" - "$planned"`
     71             if [ "$planned" -gt 1 ] ; then
     72                 echo "$tap_looks planned $planned tests but ran" \
     73                     "$tap_extra extra"
     74             else
     75                 echo "$tap_looks planned $planned test but ran" \
     76                     "$tap_extra extra"
     77             fi
     78         elif [ "$failed" -gt 0 ] ; then
     79             if [ "$failed" -gt 1 ] ; then
     80                 echo "$tap_looks failed $failed tests of $planned"
     81             else
     82                 echo "$tap_looks failed $failed test of $planned"
     83             fi
     84         elif [ "$planned" -gt 1 ] ; then
     85             echo "# All $planned tests successful or skipped"
     86         else
     87             echo "# $planned test successful or skipped"
     88         fi
     89     fi
     90 }
     91 
     92 # Skip the entire test suite.  Should be run instead of plan.
     93 skip_all () {
     94     tap_desc="$1"
     95     if [ -n "$tap_desc" ] ; then
     96         echo "1..0 # skip $tap_desc"
     97     else
     98         echo "1..0 # skip"
     99     fi
    100     exit 0
    101 }
    102 
    103 # ok takes a test description and a command to run and prints success if that
    104 # command is successful, false otherwise.  The count starts at 1 and is
    105 # updated each time ok is printed.
    106 ok () {
    107     tap_desc="$1"
    108     if [ -n "$tap_desc" ] ; then
    109         tap_desc=" - $tap_desc"
    110     fi
    111     shift
    112     if "$@" ; then
    113         echo ok "$count$tap_desc"
    114     else
    115         echo not ok "$count$tap_desc"
    116         failed=`expr $failed + 1`
    117     fi
    118     count=`expr $count + 1`
    119 }
    120 
    121 # Skip the next test.  Takes the reason why the test is skipped.
    122 skip () {
    123     echo "ok $count # skip $*"
    124     count=`expr $count + 1`
    125 }
    126 
    127 # Report the same status on a whole set of tests.  Takes the count of tests,
    128 # the description, and then the command to run to determine the status.
    129 ok_block () {
    130     tap_i=$count
    131     tap_end=`expr $count + $1`
    132     shift
    133     while [ "$tap_i" -lt "$tap_end" ] ; do
    134         ok "$@"
    135         tap_i=`expr $tap_i + 1`
    136     done
    137 }
    138 
    139 # Skip a whole set of tests.  Takes the count and then the reason for skipping
    140 # the test.
    141 skip_block () {
    142     tap_i=$count
    143     tap_end=`expr $count + $1`
    144     shift
    145     while [ "$tap_i" -lt "$tap_end" ] ; do
    146         skip "$@"
    147         tap_i=`expr $tap_i + 1`
    148     done
    149 }
    150 
    151 # Portable variant of printf '%s\n' "$*".  In the majority of cases, this
    152 # function is slower than printf, because the latter is often implemented
    153 # as a builtin command.  The value of the variable IFS is ignored.
    154 #
    155 # This macro must not be called via backticks inside double quotes, since this
    156 # will result in bizarre escaping behavior and lots of extra backslashes on
    157 # Solaris.
    158 puts () {
    159     cat << EOH
    160 $@
    161 EOH
    162 }
    163 
    164 # Run a program expected to succeed, and print ok if it does and produces the
    165 # correct output.  Takes the description, expected exit status, the expected
    166 # output, the command to run, and then any arguments for that command.
    167 # Standard output and standard error are combined when analyzing the output of
    168 # the command.
    169 #
    170 # If the command may contain system-specific error messages in its output,
    171 # add strip_colon_error before the command to post-process its output.
    172 ok_program () {
    173     tap_desc="$1"
    174     shift
    175     tap_w_status="$1"
    176     shift
    177     tap_w_output="$1"
    178     shift
    179     tap_output=`"$@" 2>&1`
    180     tap_status=$?
    181     if [ $tap_status = $tap_w_status ] \
    182         && [ x"$tap_output" = x"$tap_w_output" ] ; then
    183         ok "$tap_desc" true
    184     else
    185         echo "#  saw: ($tap_status) $tap_output"
    186         echo "#  not: ($tap_w_status) $tap_w_output"
    187         ok "$tap_desc" false
    188     fi
    189 }
    190 
    191 # Strip a colon and everything after it off the output of a command, as long
    192 # as that colon comes after at least one whitespace character.  (This is done
    193 # to avoid stripping the name of the program from the start of an error
    194 # message.)  This is used to remove system-specific error messages (coming
    195 # from strerror, for example).
    196 strip_colon_error() {
    197     tap_output=`"$@" 2>&1`
    198     tap_status=$?
    199     tap_output=`puts "$tap_output" | sed 's/^\([^ ]* [^:]*\):.*/\1/'`
    200     puts "$tap_output"
    201     return $tap_status
    202 }
    203 
    204 # Bail out with an error message.
    205 bail () {
    206     echo 'Bail out!' "$@"
    207     exit 255
    208 }
    209 
    210 # Output a diagnostic on standard error, preceded by the required # mark.
    211 diag () {
    212     echo '#' "$@"
    213 }
    214 
    215 # Search for the given file first in $C_TAP_BUILD and then in $C_TAP_SOURCE
    216 # and echo the path where the file was found, or the empty string if the file
    217 # wasn't found.
    218 #
    219 # This macro uses puts, so don't run it using backticks inside double quotes
    220 # or bizarre quoting behavior will happen with Solaris sh.
    221 test_file_path () {
    222     if [ -n "$C_TAP_BUILD" ] && [ -f "$C_TAP_BUILD/$1" ] ; then
    223         puts "$C_TAP_BUILD/$1"
    224     elif [ -n "$C_TAP_SOURCE" ] && [ -f "$C_TAP_SOURCE/$1" ] ; then
    225         puts "$C_TAP_SOURCE/$1"
    226     else
    227         echo ''
    228     fi
    229 }
    230 
    231 # Create $C_TAP_BUILD/tmp for use by tests for storing temporary files and
    232 # return the path (via standard output).
    233 #
    234 # This macro uses puts, so don't run it using backticks inside double quotes
    235 # or bizarre quoting behavior will happen with Solaris sh.
    236 test_tmpdir () {
    237     if [ -z "$C_TAP_BUILD" ] ; then
    238         tap_tmpdir="./tmp"
    239     else
    240         tap_tmpdir="$C_TAP_BUILD"/tmp
    241     fi
    242     if [ ! -d "$tap_tmpdir" ] ; then
    243         mkdir "$tap_tmpdir" || bail "Error creating $tap_tmpdir"
    244     fi
    245     puts "$tap_tmpdir"
    246 }