#!/bin/sh
###########################################################################
# @(#)docommand	1.13 18/09/20 Written 2011-2016 by J. Schilling
###########################################################################
# The contents of this file are subject to the terms of the
# Common Development and Distribution License, Version 1.0 only
# (the "License").  You may not use this file except in compliance
# with the License.
#
# See the file CDDL.Schily.txt in this distribution for details.
# A copy of the CDDL is also available via the Internet at
# http://www.opensource.org/licenses/cddl1.txt
#
# When distributing Covered Code, include this CDDL HEADER in each
# file and include the License file CDDL.Schily.txt from this distribution.
###########################################################################
#
# docommand()	the base test function
#
# Call: docommand [options] parameters
#
# Options:
# -silent	do not print command label nor "passed"
# -esilent	be silent for errors to permit hidden tests
# -noremove	do not remove exp.*, got.* and cmd.last
# -wo		call diff -w to compare the stdout
# -we		call diff -w to compare the stderr
# -bo		call diff -b to compare the stdout
# -be		call diff -b to compare the stderr
#
# Parameters:
# $1 a command label to be printed
# $2 a command to be executed
# $3 the expected exit code			or IGNORE or "!=0"
# $4 the expected stdout			or IGNORE or NONEMPTY
# $5 the expected stderr			or IGNORE or NONEMPTY
#
# Example:
# docommand T1 "echo test" 0 "test\n" ""
#
###########################################################################
docommand() {
	fail_init
	do_remove
	silent=false
	esilent=false
	diffout=""
	wo=""
	we=""
	bo=""
	be=""
	noremove=false
	cmd_label="$1"
	while true
	do
		case "$1" in
		-silent | --silent)
			silent=true
			shift
			;;
		-esilent | --esilent)
			esilent=true
			diffout=">/dev/null"
			shift
			;;
		-noremove | --noremove)
			noremove=true
			shift
			;;
		-wo | --wo)
			wo=-w
			shift
			;;
		-we | --we)
			we=-w
			shift
			;;
 		-bo | --bo)
			bo=-b
			shift
			;;
		-be | --be)
			be=-b
			shift
			;;
		*)
			break
			;;
		esac
	done
	cmd_label="$1"

	$silent || echo_nonl "$cmd_label"...

	echo "$2" >  cmd.last			# Remember last command
	echo "$2" >> cmd.log			# Add last command to history
	eval "$2" > got.stdout 2> got.stderr	# run current command
	cmd_exit=$?				# Save exit code

	if test "$3" != "IGNORE"		# Verify exit code?
	then
		if test "$3" = "!=0" -a "$cmd_exit" -ne 0
		then
			:
		# $3 may be text, so always use a string compare
		elif test "$3" != "!=0" -a "$3" = "$cmd_exit"
		then
			:
		else
			if test -s got.stderr
			then
				stderr=`cat got.stderr`
				msg="Error message: $stderr"
			else
				msg="No error message was printed on stderr"
			fi
			fail "$cmd_label: \"$2\" Expected exit code $3, got $cmd_exit
$msg"
		fi
	fi
	if test "$4" = "NONEMPTY"		# Need stdout msg?
	then
		if test ! -s got.stdout
		then
			fail "$cmd_label: \"$2\" No error message was printed on stdout"
		fi
	elif test "$4" != "IGNORE"		# Verify stdout?
	then
		echo_nonl "$4" > exp.stdout	# Save stdout sample to file
		echo		>> exp.stdout	# Make sample end in newline
		echo		>> got.stdout	# Make output end in newline
		eval diff $wo $bo exp.stdout got.stdout $diffout || \
				fail "$cmd_label: stdout format error with $2"
	fi
	if test "$5" = "NONEMPTY"		# Need stderr msg?
	then
		if test ! -s got.stderr
		then
			fail "$cmd_label: \"$2\" No error message was printed on stderr"
		fi
	elif test "$5" != "IGNORE"		# Verify stderr?
	then
		echo_nonl "$5" > exp.stderr	# Save stderr sample to file
		echo		>> exp.stderr	# Make sample end in newline
		echo		>> got.stderr	# Make output end in newline
		eval diff $we $be exp.stderr got.stderr $diffout || \
				fail "$cmd_label: stderr format error with $2"
	fi
	
	$noremove || do_remove
	$silent || echo "passed"
	true
}

###########################################################################
#
# do_output()	alternate test function with "stdout" reference in a file
#
# Call: do_output [options] parameters
#
# Options:
# -silent	do not print command label nor "passed"
# -esilent	be silent for errors to permit hidden tests
# -noremove	do not remove exp.*, got.* and cmd.last
# -wo		call diff -w to compare the stdout
# -we		call diff -w to compare the stderr
# -bo		call diff -b to compare the stdout
# -be		call diff -b to compare the stderr
#
# Parameters:
# $1 a command label to be printed
# $2 a command to be executed
# $3 the expected exit code			or IGNORE or "!=0"
# $4 the expected stdout contained in a file	or IGNORE or NONEMPTY
# $5 the expected stderr			or IGNORE or NONEMPTY
#
# Example:
# echo test > out_file
# do_output T1 "echo test" 0 out_file ""
#
###########################################################################
do_output() {
	fail_init
	do_remove
	silent=false
	esilent=false
	diffout=""
	wo=""
	we=""
	bo=""
	be=""
	noremove=false
	cmd_label="$1"
	while true
	do
		case "$1" in
		-silent | --silent)
			silent=true
			shift
			;;
		-esilent | --esilent)
			esilent=true
			diffout=">/dev/null"
			shift
			;;
		-noremove | --noremove)
			noremove=true
			shift
			;;
		-wo | --wo)
			wo=-w
			shift
			;;
		-we | --we)
			we=-w
			shift
			;;
		-bo | --bo)
			bo=-b
			shift
			;;
		-be | --be)
			be=-b
			shift
			;;
		*)
			break
			;;
		esac
	done
	cmd_label="$1"

	$silent || echo_nonl "$cmd_label"...

	echo "$2" >  cmd.last			# Remember last command
	echo "$2" >> cmd.log			# Add last command to history
	eval "$2" > got.stdout 2> got.stderr	# run current command
	cmd_exit=$?				# Save exit code

	if test "$3" != "IGNORE"		# Verify exit code?
	then
		if test "$3" = "!=0" -a "$cmd_exit" -ne 0
		then
			:
		# $3 may be text, so always use a string compare
		elif test "$3" != "!=0" -a "$3" = "$cmd_exit"
		then
			:
		else
			if test -s got.stderr
			then
				stderr=`cat got.stderr`
				msg="Error message: $stderr"
			else
				msg="No error message was printed on stderr"
			fi
			fail "$cmd_label: \"$2\" Expected exit code $3, got $cmd_exit
$msg"
		fi
	fi
	if test "$4" = "NONEMPTY"		# Need stdout msg?
	then
		if test ! -s got.stdout
		then
			fail "$cmd_label: \"$2\" No error message was printed on stdout"
		fi
	elif test "$4" != "IGNORE"		# Verify stdout?
	then
		eval diff $wo $bo "$4" got.stdout $diffout || \
				fail "$cmd_label: stdout format error with $2"
	fi
	if test "$5" = "NONEMPTY"		# Need stderr msg?
	then
		if test ! -s got.stderr
		then
			fail "$cmd_label: \"$2\" No error message was printed on stderr"
		fi
	elif test "$5" != "IGNORE"		# Verify stderr?
	then
		echo_nonl "$5" > exp.stderr	# Save stderr sample to file
		echo		>> exp.stderr	# Make sample end in newline
		echo		>> got.stderr	# Make output end in newline
		eval diff $we $be exp.stderr got.stderr $diffout || \
				fail "$cmd_label: stderr format error with $2"
	fi
	
	$noremove || do_remove
	$silent || echo "passed"
	true
}

###########################################################################
#
# do_error()	alternate test function with "stderr" reference in a file
#
# Call: do_error [options] parameters
#
# Options:
# -silent	do not print command label nor "passed"
# -esilent	be silent for errors to permit hidden tests
# -noremove	do not remove exp.*, got.* and cmd.last
# -wo		call diff -w to compare the stdout
# -we		call diff -w to compare the stderr
# -bo		call diff -b to compare the stdout
# -be		call diff -b to compare the stderr
#
# Parameters:
# $1 a command label to be printed
# $2 a command to be executed
# $3 the expected exit code			or IGNORE or "!=0"
# $4 the expected stdout			or IGNORE or NONEMPTY
# $5 the expected stderr contained in a file	or IGNORE or NONEMPTY
#
# Example:
# :> err_file
# do_error T1 "echo test" 0 "test\n" err_file
#
###########################################################################
do_error() {
	fail_init
	do_remove
	silent=false
	esilent=false
	diffout=""
	wo=""
	we=""
	bo=""
	be=""
	noremove=false
	cmd_label="$1"
	while true
	do
		case "$1" in
		-silent | --silent)
			silent=true
			shift
			;;
		-esilent | --esilent)
			esilent=true
			diffout=">/dev/null"
			shift
			;;
		-noremove | --noremove)
			noremove=true
			shift
			;;
		-wo | --wo)
			wo=-w
			shift
			;;
		-we | --we)
			we=-w
			shift
			;;
		-bo | --bo)
			bo=-b
			shift
			;;
		-be | --be)
			be=-b
			shift
			;;
		*)
			break
			;;
		esac
	done
	cmd_label="$1"

	$silent || echo_nonl "$cmd_label"...

	echo "$2" >  cmd.last			# Remember last command
	echo "$2" >> cmd.log			# Add last command to history
	eval "$2" > got.stdout 2> got.stderr	# run current command
	cmd_exit=$?				# Save exit code

	if test "$3" != "IGNORE"		# Verify exit code?
	then
		if test "$3" = "!=0" -a "$cmd_exit" -ne 0
		then
			:
		# $3 may be text, so always use a string compare
		elif test "$3" != "!=0" -a "$3" = "$cmd_exit"
		then
			:
		else
			if test -s got.stderr
			then
				stderr=`cat got.stderr`
				msg="Error message: $stderr"
			else
				msg="No error message was printed on stderr"
			fi
			fail "$cmd_label: \"$2\" Expected exit code $3, got $cmd_exit
$msg"
		fi
	fi
	if test "$4" = "NONEMPTY"		# Need stdout msg?
	then
		if test ! -s got.stdout
		then
			fail "$cmd_label: \"$2\" No error message was printed on stdout"
		fi
	elif test "$4" != "IGNORE"		# Verify stdout?
	then
		echo_nonl "$4" > exp.stdout	# Save stdout sample to file
		echo		>> exp.stdout	# Make sample end in newline
		echo		>> got.stdout	# Make output end in newline
		eval diff $wo $bo exp.stdout got.stdout $diffout || \
				fail "$cmd_label: stdout format error with $2"
	fi
	if test "$5" = "NONEMPTY"		# Need stderr msg?
	then
		if test ! -s got.stderr
		then
			fail "$cmd_label: \"$2\" No error message was printed on stderr"
		fi
	elif test "$5" != "IGNORE"		# Verify stderr?
	then
		eval diff $we $be "$5" got.stderr $diffout || \
				fail "$cmd_label: stderr format error with $2"
	fi
	
	$noremove || do_remove
	$silent || echo "passed"
	true
}

###########################################################################
#
# do_outerr()	alternate test function with "stdout/err" reference in a file
#
# Call: do_outerr [options] parameters
#
# Options:
# -silent	do not print command label nor "passed"
# -esilent	be silent for errors to permit hidden tests
# -noremove	do not remove exp.*, got.* and cmd.last
# -wo		call diff -w to compare the stdout
# -we		call diff -w to compare the stderr
# -bo		call diff -b to compare the stdout
# -be		call diff -b to compare the stderr
#
# Parameters:
# $1 a command label to be printed
# $2 a command to be executed
# $3 the expected exit code			or IGNORE or "!=0"
# $4 the expected stdout contained in a file	or IGNORE or NONEMPTY
# $5 the expected stderr contained in a file	or IGNORE or NONEMPTY
#
# Example:
# echo test > out_file
# :> err_file
# do_outerr T1 "echo test" 0 out_file err_file
#
###########################################################################
do_outerr() {
	fail_init
	do_remove
	silent=false
	esilent=false
	diffout=""
	wo=""
	we=""
	bo=""
	be=""
	noremove=false
	cmd_label="$1"
	while true
	do
		case "$1" in
		-silent | --silent)
			silent=true
			shift
			;;
		-esilent | --esilent)
			esilent=true
			diffout=">/dev/null"
			shift
			;;
		-noremove | --noremove)
			noremove=true
			shift
			;;
		-wo | --wo)
			wo=-w
			shift
			;;
		-we | --we)
			we=-w
			shift
			;;
		-bo | --bo)
			bo=-b
			shift
			;;
		-be | --be)
			be=-b
			shift
			;;
		*)
			break
			;;
		esac
	done
	cmd_label="$1"

	$silent || echo_nonl "$cmd_label"...

	echo "$2" >  cmd.last			# Remember last command
	echo "$2" >> cmd.log			# Add last command to history
	eval "$2" > got.stdout 2> got.stderr	# run current command
	cmd_exit=$?				# Save exit code

	if test "$3" != "IGNORE"		# Verify exit code?
	then
		if test "$3" = "!=0" -a "$cmd_exit" -ne 0
		then
			:
		# $3 may be text, so always use a string compare
		elif test "$3" != "!=0" -a "$3" = "$cmd_exit"
		then
			:
		else
			if test -s got.stderr
			then
				stderr=`cat got.stderr`
				msg="Error message: $stderr"
			else
				msg="No error message was printed on stderr"
			fi
			fail "$cmd_label: \"$2\" Expected exit code $3, got $cmd_exit
$msg"
		fi
	fi
	if test "$4" = "NONEMPTY"		# Need stdout msg?
	then
		if test ! -s got.stdout
		then
			fail "$cmd_label: \"$2\" No error message was printed on stdout"
		fi
	elif test "$4" != "IGNORE"		# Verify stdout?
	then
		eval diff $wo $bo "$4" got.stdout $diffout || \
				fail "$cmd_label: stdout format error with $2"
	fi
	if test "$5" = "NONEMPTY"		# Need stderr msg?
	then
		if test ! -s got.stderr
		then
			fail "$cmd_label: \"$2\" No error message was printed on stderr"
		fi
	elif test "$5" != "IGNORE"		# Verify stderr?
	then
		eval diff $we $be "$5" got.stderr $diffout || \
				fail "$cmd_label: stderr format error with $2"
	fi
	
	$noremove || do_remove
	$silent || echo "passed"
	true
}

do_remove() {
	remove exp.stdout exp.stderr got.stdout got.stderr cmd.last
}
