#! /bin/sh

######################################################################
#                             CAUTION                                #
# When editing this file be aware that it is the focus of /bin/sh    #
# portability problems.  Be very, very careful!  Problems with this  #
# file could cause test cases to succeed when they should fail!      #
######################################################################

# Common function definitions.
. ../common/command-names

# Try to find an echo command that allows us to suppress the newline
# at the end of the line, and also to use C-style escape codes.  We 
# have our own, as a last resort.

## First, find out how to echo without appending a newline,
## and so on.  We end up with five variables:-
#
# echocmd       The name by which we invoke the "echo" command.
# ac_e          Leading argument for enabling escape codes.
# ac_n          Leading argument for echo to suppress newline.
# ac_c          Arg for suppressing newline (may need -e, we test for that.)
# ac_t          (don't know -- I stole this code from Autoconf...)
#
# FreeBSD echo (or at least some version of it) does not support both the
# -n and the -e option AT THE SAME TIME.  This information from 
# Malcolm Boff <Malcolm_Boff@compuserve.com> on 1997/11/01. 
# He suggested that we use printf(1) but we can't do that because
# many systems just don't support it.
#
# According to Marty Leisner <leisner@sdsp.mc.xerox.com>, SunOS 4.1.4
# has the -n option but not the -e option.
#
# Stardent Vistra SVR4 grep lacks -e, says ghazi@caip.rutgers.edu.
#
for echocmd in echo /bin/echo /usr/bin/echo /usr/5bin/echo ../../testutils/ekko
do
# Unless we're using the builtin, check that the command exists as a file.
if test -f $echocmd || test "$echocmd" = "echo"
then
  # The second echo here ensures that the parenthesised command 
  # succeeds and the output ends with a newline.
  if ($echocmd "testing\c"; echo 1,2,3) | grep c >/dev/null
    then
    # Trailing \c option does not work without -e (it produces a literal c).
    if ($echocmd -e "testing\c"; echo 1,2,3) | grep c >/dev/null
    then
      # \c does not work even with -e.
      if ($echocmd -n testing; echo 1,2,3) | sed s/-n/xn/ | grep xn >/dev/null
      then
          # -n option not known (and \c not known)
          # I don't know what purpose setting ac_c to this value
          # has, but Autoconf does it...
          ac_n= ac_c='
' ac_t='        '
      else
          # -n option works even though -e does not.
          # This is unfortunate since the test scripts assume
          # in places tha ability to expand escape codes.  
          # Send message to STDERR because I want to investigate.
          #
          # According to Marty Leisner <leisner@sdsp.mc.xerox.com>,
          # SunOS 4.1.4 is one such "unusual" system.

          # echo Unusual system\; PLEASE inform '<jay@gnu.org>'. >&2
          ac_n=-n ac_c= ac_t=
      fi
    else
      # \c does work with -e.
      # Hence we do not need to use -n.
      ac_n= ac_c='\c' ec_t= 
      # Break out of the loop, we have a workable solution.
      break
    fi
  else
    ac_n= ac_c='\c' ac_t=
    # Break out of the loop, we have a workable solution.
    break
  fi
fi
done

# If "echo -e" generates an error, don't do that.  Hey, at least
# /dev/null works!
if ($echocmd -e) >/dev/null 2>&1
then
  if ($echocmd -e) | sed s/-e/xe/ | grep xe >/dev/null
  then
    # Fallback position: use our own replacement which supports -e.
    echocmd="../../testutils/ekko"
    ac_e='-e'
  else
    ac_e='-e'
  fi
fi

# echo "ac_n="$ac_n
# echo "ac_e="$ac_e
# echo "ac_t="$ac_t
# echo "ac_c="$ac_c
# echo "echocmd=" $echocmd


# Function for echoing without a newline, with escape chars enabled.
echo_nonl () {
if test -z "$*"
then
    # this works around an apparent bug in Bash where 
    # "$@$x" expands to something starting with char 0177 (DEL).
    true
else
    ${echocmd} ${ac_n} ${ac_e} "$@$ac_c" ;
fi
}


expect_fail=false

# Call fail when a test failed.
fail () { 
name=`basename $0`
if ${expect_fail:-false}
then
        echo XFAIL $name "$@"
        # Return a failure status but don't exit...
	false
else
        echo FAIL $name "$@" ; exit 2; 
fi ;
}


# Call success when a test succeeded.
success () { 
name=`basename $0`

remove got.stdout           got.stderr 
remove expected.stdout expected.stderr 
remove command.log last.command

echo 
echo "All Tests in `/bin/pwd`/$name are now completed on tools in '$dir'"

if ${expect_fail:-false}
then
        echo XPASS $name: $* ; exit 0; 
else
        echo PASS $name:  $* ; exit 0; 
fi ;
}

# Call miscarry wen a test could not be completed.
miscarry () { 
echo `basename $0`: "Test could not be completed: " "$@"
exit 1 ; 
}


remove () { 
    if test -z "$*"
    then
        # no files listed, nothing to do.
        true 
    else
        rm -rf "$@" || miscarry "Could not remove $@"
    fi
}

rename () { mv "$1" "$2" || miscarry "Could not rename $1 to $2" ; }

test_script=

##############
docommand () {
# $1 is the label.  
# $2 is the command to execute.
# $3 is the return value to expect
# $4 is what to expect on stdout
# $5 is what to expect on stderr.
#
# If --silent is specified before the label, no output is normally made.
#
remove last.command expected.stdout expected.stderr got.stdout got.stderr
silent=false
stdout_regex=false
stderr_regex=false
while case "$1" in
--silent) silent=true ; true ;;
--nosilent) silent=false ; true ;;
--stderr_regex) stderr_regex=true ; true ;;
--nostderr_regex) stderr_regex=false ; true ;;
--stdout_regex) stdout_regex=true ; true ;;
--nostdout_regex) stdout_regex=false ; true ;;
*) false ;;
esac
do
    shift
done
if test -z "${test_script}"; then
    script_dir=`dirname $0`
    case "${script_dir}" in
	.) script_dir=`pwd`;;
    esac
    script_base=`basename ${script_dir}`
    test_script="${script_base}"/`basename $0`
fi
label="${test_script}:$1"
eval "$silent" || echo_nonl "${label}"...

shift

echo_nonl $4 > expected.stderr
echo $1 > last.command

echo  >> command.log
echo "# ${label}"  >> command.log
echo $1 >> command.log
eval "$1" >got.stdout 2>got.stderr
rv=$?
echo '# $? was' "$rv;  $(env LC_ALL=C wc -c < got.stdout) bytes on stdout; $(env LC_ALL=C wc -c < got.stderr) bytes on stderr" >> command.log
sed -e 's/^/# stdout: /' >> command.log < got.stdout
sed -e 's/^/# stderr: /' >> command.log < got.stderr

if test "$2" != "IGNORE"
then
    if test $rv -eq $2
    then
	true
    else
	# If the expected return value (which we didn't get) was zero,
        # stderr may contain an error message.
	errmsg="`cat got.stderr`"
	if test -z "$errmsg"
	then
	    tail="No error message was printed on stderr"
	else
	    tail="error message: $errmsg"
	fi
	fail "$label: $1: Expected return value $2, got return value $rv
$tail"
    fi
fi

if test "$3" != "IGNORE"
then
    if $stdout_regex; then
	# We use egrep regexes to that we can run these tests on old
	# versions of Solaris.  Older versions of Solaris do not
	# support grep -E.
	if egrep -e "$3" < got.stderr >/dev/null
	then
	    echo "# stdout output matches $3"  >> command.log
	else
	    echo "# stdout output does not match $3"  >> command.log
	    fail $label: stdout output did not match "$3"
	fi
    else
	echo_nonl "$3" > expected.stdout
	# diff can fail if the file does not end in newline.
	echo        >>expected.stdout
	echo        >>     got.stdout
	diff expected.stdout got.stdout || fail $label: stdout format error with $1
    fi
fi

if test "$4" != "IGNORE"
then
    if $stderr_regex; then
	# We use egrep regexes to that we can run these tests on old
	# versions of Solaris.  Older versions of Solaris do not
	# support grep -E.
	if egrep -e "$4" < got.stderr >/dev/null
	then
	    echo "# stderr output matches $4"  >> command.log
	else
	    echo "# stderr output does not match $4"  >> command.log
	    fail $label: stderr output did not match "$4"
	fi
    else
	echo_nonl "$4" > expected.stderr
	# diff can fail if the file does not end in newline.
	echo        >>expected.stderr
	echo        >>     got.stderr
	diff expected.stderr got.stderr || fail $label: stderr format error with $1
    fi
fi

remove last.command expected.stdout expected.stderr got.stdout got.stderr
eval "$silent" || echo "passed "
( exit $rv; )
}

#######################
do_output () {
# $1 is the label.
# $2 is the command to execute.
# $3 is the return value to expect
# $4 is a file containing what to expect on stdout.
# $5 is what to expect on stderr.
remove last.command expected.stdout expected.stderr got.stdout got.stderr
label="$1"
echo_nonl "$label..."
shift

echo_nonl $4 > expected.stderr
echo $1 > last.command

echo  >> command.log
echo "# ${label}"  >> command.log
echo $1 >> command.log
$1 >got.stdout 2>got.stderr
rv=$?
echo '# $? was' "$rv;  $(env LC_ALL=C wc -c < got.stdout) bytes on stdout; $(env LC_ALL=C wc -c < got.stderr) bytes on stderr" >> command.log
sed -e 's/^/# stdout: /' >> command.log < got.stdout
sed -e 's/^/# stderr: /' >> command.log < got.stderr

if test "$2" != "IGNORE"
then
    test $rv -eq $2 || fail "$label: $1: Expected return value $2, got return value $rv"
fi

if test "$3" != "IGNORE"
then
    diff $3 got.stdout || fail $label: stdout format error with $1
fi

if test "$4" != "IGNORE"
then
    echo_nonl $4 > expected.stderr
    # diff can fail if the file does not end in newline.
    echo        >>expected.stderr
    echo        >>     got.stderr
    diff expected.stderr got.stderr || fail $label: stderr format error with $1
fi

remove last.command expected.stdout expected.stderr got.stdout got.stderr
echo "passed "
( exit ${rv}; )
}
