1057 lines
34 KiB
Bash
1057 lines
34 KiB
Bash
#!/bin/bash
|
|
# This script was automatically generated: Sat Mar 19 22:08:41 AEST 2022
|
|
# by uqpsutto
|
|
|
|
OUTPUT_DIR=$(date +"/tmp/2310test%Y%m%d-%H%M%S")
|
|
|
|
# Environment Variables:
|
|
export LD_LIBRARY_PATH='/local/courses/csse2310/lib'
|
|
|
|
# Common functions
|
|
|
|
# Error handling backtrace code (modified from
|
|
# https://stackoverflow.com/questions/25492953)
|
|
function backtrace () {
|
|
local deptn=${#FUNCNAME[@]}
|
|
|
|
for ((i=2; i<$deptn; i++)); do
|
|
local func="${FUNCNAME[$i]}"
|
|
local line="${BASH_LINENO[$((i-1))]}"
|
|
local src="${BASH_SOURCE[$i]}"
|
|
printf '%*s' $i '' >&2 # indent
|
|
echo "at: $func(), $src, line $line" >&2
|
|
done
|
|
}
|
|
|
|
set -o errtrace
|
|
|
|
# Usage: error_exit <code> <message ...>
|
|
# Prints message to stderr and exits with the given code
|
|
function error_exit() {
|
|
code="$1"
|
|
shift
|
|
echo "${bold}$@${normal}" >&2
|
|
backtrace
|
|
exit ${code}
|
|
}
|
|
|
|
# Usage assert [-code <code>] [-m <message>] <cmd> ...
|
|
# Checks that the execution of the given command results in a "true" result
|
|
# If not, prints the given message (or the command that failed) and
|
|
# exits with the given code (or 1)
|
|
function assert() {
|
|
unset message
|
|
code=1 # Default exit code
|
|
while true; do
|
|
case "$1" in
|
|
"-code") code="$2"; shift 2;;
|
|
"-m") message="$2"; shift 2;;
|
|
*) break;;
|
|
esac
|
|
done
|
|
# Run the command to check
|
|
if ! "$@" &>/dev/null ; then
|
|
if isset message ; then
|
|
error_exit "${code}" "$message"
|
|
else
|
|
error_exit "${code}" "Assertion failed (${code}): ${*@Q}"
|
|
fi
|
|
fi
|
|
}
|
|
|
|
# Usage: isset <variable-name>
|
|
# Returns true if variable name is set, false otherwise
|
|
function isset() {
|
|
#!1 does indirection - name replaced by $1
|
|
#+x will substitute variable value (if set) by x, if unset no change
|
|
test -n "${!1+x}"
|
|
}
|
|
|
|
# Usage: is_integer <string>
|
|
# Returns true if the given string is a non-negative integer, false otherwise
|
|
function is_integer() {
|
|
[[ $1 =~ ^[0-9]+$ ]]
|
|
}
|
|
|
|
# Usage: is_number <string>
|
|
# Returns true if the given string is a non-negative integer or a floating
|
|
# point number expressed with a decimal point and optional digits after the
|
|
# decimal point. Returns false otherwise.
|
|
function is_number() {
|
|
[[ $1 =~ ^[0-9]+(\.[0-9]*)?$ ]]
|
|
}
|
|
|
|
# Usage: is_testid <string>
|
|
# Returns true if the given string is of the form category-num.test-num.
|
|
# (No leading zeroes permitted.)
|
|
# Returns false otherwise.
|
|
function is_testid() {
|
|
[[ $1 =~ ^[1-9][0-9]*\.[1-9][0-9]*$ ]]
|
|
}
|
|
|
|
# Usage: is_command <string>
|
|
# Checks whether the given string is an executable command
|
|
function is_command() {
|
|
type "$1" &>/dev/null
|
|
}
|
|
|
|
# Usage: get_test_num_from_id <testid>
|
|
# testid should be of the form category-number.test-number. (If not, this
|
|
# function exits the program.) Prints the test-number component after the
|
|
# decimal point.
|
|
function get_test_num_from_id() {
|
|
assert is_testid $1
|
|
echo "$1" | cut -d . -f 2
|
|
}
|
|
|
|
# Usage: get_category_num_from_id <testid>
|
|
# testid should be of the form category-number.test-number. (If not, this
|
|
# function exits the program.) Prints the category-number component before
|
|
# the decimal point.
|
|
function get_category_num_from_id() {
|
|
assert is_testid $1
|
|
echo "$1" | cut -d . -f 1
|
|
}
|
|
|
|
# Usage: indent
|
|
# Reads stdin, and echoes to stdout with 4 spaces at the start of each line
|
|
function indent() {
|
|
sed 's/^/ /'
|
|
}
|
|
|
|
# Definitions of terminal colour and styling constants
|
|
#
|
|
#Based on the Stack Overflow answer at
|
|
# https://unix.stackexchange.com/questions/9957/how-to-check-if-bash-can-print-colors
|
|
|
|
if test -t 1 ; then
|
|
# stdout is a tty
|
|
normal="$(tput sgr0)"
|
|
bold="$(tput bold)"
|
|
underline="$(tput smul)"
|
|
# Foreground colours
|
|
black="$(tput setaf 0)"
|
|
red="$(tput setaf 1)"
|
|
green="$(tput setaf 2)"
|
|
yellow="$(tput setaf 3)"
|
|
blue="$(tput setaf 4)"
|
|
magenta="$(tput setaf 5)"
|
|
cyan="$(tput setaf 6)"
|
|
white="$(tput setaf 7)"
|
|
else
|
|
normal=""
|
|
bold=""
|
|
underline=""
|
|
black=""
|
|
red=""
|
|
green=""
|
|
yellow=""
|
|
blue=""
|
|
magenta=""
|
|
cyan=""
|
|
white=""
|
|
fi
|
|
|
|
# Functions and definitions used by testing scripts
|
|
|
|
# By default we send fd 100 to /dev/null. (Sent elsewhere in autograde scripts.)
|
|
jsonfd=100
|
|
eval "exec ${jsonfd}>/dev/null"
|
|
|
|
# Usage: cleanup
|
|
# Function is called on exit
|
|
function cleanup() {
|
|
echo "Cleaning up ..."
|
|
rm -f -r ${OUTPUT_DIR}
|
|
echo "Done"
|
|
}
|
|
|
|
/local/courses/csse2310/bin/csse2310logusage 2>/dev/null
|
|
|
|
trap cleanup EXIT
|
|
|
|
# Usage: check_usage command-line-arguments
|
|
# Prints the action to be taken: run_test or explain_test or mark_test
|
|
# (mark_test is the default if the command name begins with mark or autograde)
|
|
# Overwrites TESTS_TO_RUN if tests are listed on the command line
|
|
function check_usage() {
|
|
if [[ $(basename "$0") =~ ^(mark|repmark|autograde).* ]] ; then
|
|
action=mark_test
|
|
extrausagetext='|mark'
|
|
else
|
|
action=run_test
|
|
fi
|
|
if [ "$1" ] ; then
|
|
# At least one argument supplied - it must be "run", "explain" or "mark"
|
|
case "$1" in
|
|
run) action="run_test";;
|
|
explain) action="explain_test";;
|
|
mark) action="mark_test";;
|
|
*) echo "Usage: $0 [run|explain${extrausagetext} [testid ...]]" >&2
|
|
exit 1
|
|
;;
|
|
esac
|
|
if [ "$2" ] ; then
|
|
# Have one or more arguments - tests to run
|
|
shift
|
|
# expand any single numbers to all subtests
|
|
rm -f /tmp/tests_to_run
|
|
touch /tmp/tests_to_run
|
|
for i in "$@" ; do
|
|
if is_integer "$i" ; then
|
|
echo $TESTS_TO_RUN | tr ' ' '\n' | grep "^${i}\." >> /tmp/tests_to_run
|
|
else
|
|
echo $i >> /tmp/tests_to_run
|
|
fi
|
|
done
|
|
TESTS_TO_RUN=$(cat /tmp/tests_to_run)
|
|
rm -f /tmp/tests_to_run
|
|
fi
|
|
fi
|
|
}
|
|
|
|
# Usage: setup_for_testing
|
|
# Creates a symlink to the testfiles and creates the output directory
|
|
function setup_for_testing() {
|
|
assert isset TESTFILES_DIR
|
|
assert isset OUTPUT_DIR
|
|
|
|
echo "Setting up for tests"
|
|
echo "Time: $(TZ=AEST-10 date)"
|
|
if [ -f .username ] ; then
|
|
echo "User: $(cat .username)"
|
|
fi
|
|
if [ -L testfiles ] ; then
|
|
rm testfiles || error_exit 1 "Unable to remove existing testfiles link"
|
|
fi
|
|
ln -s -T "${TESTFILES_DIR}" testfiles &>/dev/null ||
|
|
error_exit 1 "Unable to create symbolic link 'testfiles'"
|
|
mkdir -p "${OUTPUT_DIR}" ||
|
|
error_exit 1 "Unable to create temporary output directory"
|
|
}
|
|
|
|
# Usage: do_svn_checkout <repo-url> <output-dir>
|
|
function do_svn_checkout() {
|
|
echo "${bold}Checking out code from SVN repo to $2 ...${normal}"
|
|
if [ ! "${SVN_REVISION}" ] ; then
|
|
SVN_REVISION=head
|
|
fi
|
|
if ! svn checkout --depth files "$1" -r ${SVN_REVISION} "$2"; then
|
|
error_exit 2 "Failed to checkout repository"
|
|
fi
|
|
}
|
|
|
|
# Usage: do_make
|
|
function do_make() {
|
|
echo "${bold}Running make...${normal}"
|
|
if ! make ; then
|
|
error_exit 3 "Make failed"
|
|
fi
|
|
}
|
|
|
|
# Usage: run_cmd_and_save_output <timeout-secs> <testid> <output-dir> <cmd> ...
|
|
# Stdout is saved to <output-dir>/<testid>.stdout
|
|
# Stderr is saved to <output-dir>/<testid>.stderr
|
|
# Exit code is returned
|
|
# cmd may include environment variable definitions
|
|
function run_cmd_and_save_output() {
|
|
# Check timeout value is valid
|
|
assert -code 11 is_number "$1"
|
|
timeout="$1"
|
|
# Check testid has valid format (num.num)
|
|
assert -code 12 is_testid "$2"
|
|
testid="$2"
|
|
# Make sure the output directory already exists
|
|
assert -code 13 test -d "$3"
|
|
outputdir="$3"
|
|
shift 3 # Consume the first three arguments
|
|
# Run the command - with a timeout
|
|
# We run in a subshell and send shell error messages to /dev/null
|
|
# We first determine whether any of the arguments are setting envirovnment
|
|
# variables and we set those
|
|
(
|
|
if isset FILESIZELIMIT ; then
|
|
ulimit -f ${FILESIZELIMIT}
|
|
fi
|
|
while [[ "$1" =~ ^[A-Za-z][A-Za-z0-9_]*=.*$ ]] ; do
|
|
export ${1%%=*}=${1#*=}
|
|
shift
|
|
done
|
|
exec 2>/dev/null; timeout ${timeout} "${@}" \
|
|
> "${outputdir}/${testid}.stdout" \
|
|
2> "${outputdir}/${testid}.stderr"
|
|
)
|
|
# Will return with exit code of this last command
|
|
}
|
|
|
|
# Usage: compare_files stdout|stderr|filename \
|
|
# <expected-output-filename> <actual-output-filename>
|
|
# Compares the given files and outputs summary line if differ
|
|
# Returns true (0) if files both match, false otherwise
|
|
function compare_files() {
|
|
assert -code 16 test -f "$2"
|
|
if [ ! -f "$3" ] ; then
|
|
echo "Expected output file $1 not found"
|
|
return 1
|
|
elif ! diff -q "$2" "$3" &>/dev/null; then
|
|
if [ "$1" = "stdout" -o "$1" = "stderr" ] ; then
|
|
echo "Mismatch on $1"
|
|
else
|
|
echo "Mismatch in file $1"
|
|
fi
|
|
return 1
|
|
else
|
|
return 0
|
|
fi
|
|
}
|
|
|
|
# Usage: check_program_output command stdout-file stderr-file
|
|
# Expect the command to return true - print message if not.
|
|
# The given file containing stdout from the test will be supplied as stdin
|
|
# for program. The given file containing stderr from the test will be supplied
|
|
# on file desciptor 3.
|
|
function check_program_output() {
|
|
if ! "$1" <"$2" 3<"$3"&>/dev/null; then
|
|
echo "Program '$1' returned false"
|
|
return 1;
|
|
else
|
|
return 0;
|
|
fi
|
|
}
|
|
|
|
# Usage: explain_exitcode <code>
|
|
# Prints an explanation of an erroneous code with a preceding space - or
|
|
# no explanation if the code is not erroneous
|
|
function explain_exitcode() {
|
|
assert -code 20 is_integer "$1"
|
|
actual="$1"
|
|
if [[ $actual -eq 124 ]] ; then
|
|
explanation=" (Timeout)"
|
|
elif [[ $actual -eq 126 ]] ; then
|
|
explanation=" (Command not executable)"
|
|
elif [[ $actual -eq 127 ]] ; then
|
|
explanation=" (Command not found)"
|
|
elif [[ $actual -eq 135 ]] ; then
|
|
explanation=" (Bus Error)"
|
|
elif [[ $actual -eq 139 ]] ; then
|
|
explanation=" (Segmentation fault)"
|
|
elif [[ $actual -eq 153 ]] ; then
|
|
explanation=" (File size limit (${FILESIZELIMIT}k) exceeded)"
|
|
elif [[ $actual -ge 129 && $actual -le 160 ]] ; then
|
|
explanation=" (SIG"$(kill -l $(($actual - 128)) 2>/dev/null)" signal)"
|
|
else
|
|
explanation=""
|
|
fi
|
|
echo ${explanation}
|
|
}
|
|
|
|
# Usage: compare_exitcodes <expected-exitcode> <actual-exitcode>
|
|
# Compares the two exit codes - outputs a summary if they differ
|
|
# Returns true (0) if they match, false otherwise
|
|
function compare_exitcodes() {
|
|
assert -code 20 is_integer "$1"
|
|
assert -code 21 is_integer "$2"
|
|
expected=$1
|
|
actual=$2
|
|
# Expected exit code should be less than 124
|
|
assert -code 22 test $expected -lt 124
|
|
if [[ $actual -ne $expected ]] ; then
|
|
explanation=$(explain_exitcode $actual)
|
|
echo "Got exitcode ${actual}${explanation} - but expected ${expected}"
|
|
return 1
|
|
else
|
|
return 0
|
|
fi
|
|
}
|
|
|
|
# Usage run_test <testid> <testname> <testdescription>
|
|
# [-exit <expected-exitcode>]
|
|
# [-stdout <expected-stdout-file>]
|
|
# [-stderr <expected-stderr-file>]
|
|
# [-file <file-name> <expected-file-contents>]
|
|
# [-prog command] ...
|
|
# <output-dir> <cmd> ...
|
|
# Note argument format is the same as for explain_test below so that they
|
|
# can be called with the one command.
|
|
function run_test() {
|
|
assert -code 25 is_testid "$1"
|
|
testid="$1"
|
|
testname="$2"
|
|
testdescription="$3" # Not needed in this function
|
|
shift 3
|
|
assert -code 28 is_number "$TIMEOUT"
|
|
|
|
unset check expected progs
|
|
declare -a check
|
|
declare -A expected
|
|
declare -a progs
|
|
while [ "${1:0:1}" = "-" ] ; do
|
|
case "$1" in
|
|
"-exit" )
|
|
expected[exit]="$2"
|
|
assert -code 26 is_integer "$2"
|
|
assert -code 29 [ "$2" -lt 124 ]
|
|
shift 2
|
|
;;
|
|
"-stdout" )
|
|
check+=(stdout)
|
|
expected[stdout]="$2"
|
|
assert -code 27 test -f "$2"
|
|
shift 2
|
|
;;
|
|
"-stderr" )
|
|
check+=(stderr)
|
|
expected[stderr]="$2"
|
|
assert -code 27 test -f "$2"
|
|
shift 2
|
|
;;
|
|
"-file" )
|
|
check+=("$2")
|
|
expected["$2"]="$3"
|
|
assert -code 27 test -f "$3"
|
|
shift 3
|
|
;;
|
|
"-prog" )
|
|
progs+=("$2")
|
|
assert -code 27 is_command "$2"
|
|
shift 2
|
|
;;
|
|
*)
|
|
error_exit 1 "Illegal argument to run_test: $1"
|
|
esac
|
|
done
|
|
outputdir="$1"
|
|
shift
|
|
|
|
printf "%-5s - %-52s" "${testid}" "${testname}"
|
|
|
|
run_cmd_and_save_output ${TIMEOUT} ${testid} "${outputdir}" "$@"
|
|
actual_exitcode=$?
|
|
|
|
rm -f "${outputdir}/.details"
|
|
touch "${outputdir}/.details"
|
|
|
|
declare -i result=0 # Declare result to be an integer
|
|
if [ "${expected[exit]}" ] ; then
|
|
compare_exitcodes ${expected[exit]} ${actual_exitcode} \
|
|
>> "${outputdir}/.details"
|
|
result+=$?
|
|
elif [[ "$actual_exitcode" -ge 124 ]] ; then
|
|
error_explanation=$(explain_exitcode "$actual_exitcode")
|
|
if [ "${error_explanation}" ] ; then
|
|
# We didn't have to check an exit code - but we got a
|
|
# timeout or command not found or signal...
|
|
result+=1
|
|
echo "Got unexpected exitcode ${actual_exitcode}${error_explanation}" \
|
|
>> "${outputdir}/.details"
|
|
fi
|
|
fi
|
|
if [[ "$actual_exitcode" -lt 124 ]] ; then
|
|
# Check files as required
|
|
for file in "${check[@]}" ; do
|
|
if [ "$file" = "stdout" -o "$file" = "stderr" ] ; then
|
|
# Check stdout or stderr
|
|
compare_files $file "${expected[$file]}" \
|
|
"${outputdir}/${testid}.${file}" >> "${outputdir}/.details"
|
|
result+=$?
|
|
else
|
|
# Check file
|
|
compare_files $file "${expected[$file]}" \
|
|
"${file}" >> "${outputdir}/.details"
|
|
result+=$?
|
|
fi
|
|
done
|
|
# Check programs
|
|
for prog in "${progs[@]}" ; do
|
|
check_program_output "${prog}" "${outputdir}/${testid}.stdout" \
|
|
"${outputdir}/${testid}.stderr" >> "${outputdir}/.details"
|
|
result+=$?
|
|
done
|
|
fi
|
|
if [[ "$result" -eq 0 ]] ; then
|
|
echo "${bold}${green}PASS${normal}"
|
|
else
|
|
echo "${bold}${red}FAIL${normal}"
|
|
cat "${outputdir}/.details" | indent
|
|
fi
|
|
rm -f "${outputdir}/.details"
|
|
}
|
|
|
|
# Usage: explain_test <testid> <testname> <testdescription>
|
|
# [-exit <expected-exitcode>]
|
|
# [-stdout <expected-stdout-file>]
|
|
# [-stderr <expected-stderr-file>]
|
|
# [-file <file-name> <expected-file-contents>]
|
|
# [-prog command]
|
|
# <outputdir> <cmd> ...
|
|
function explain_test() {
|
|
assert -code 30 is_testid "$1"
|
|
testid="$1"
|
|
testname="$2"
|
|
test_description="$3"
|
|
shift 3
|
|
echo "${green}${bold}=== ${testid} - ${testname} ===${normal}"
|
|
echo "${bold}Description:${normal} ${test_description}" | fmt
|
|
msg=""
|
|
while [ "${1:0:1}" = "-" ] ; do
|
|
case "$1" in
|
|
"-exit" )
|
|
msg+=" Expect exit code: $2"$'\n';
|
|
assert -code 31 is_integer "$2"
|
|
shift 2;;
|
|
"-stdout" )
|
|
msg+=" Standard output (${testid}.stdout) should match $2"$'\n'
|
|
shift 2;;
|
|
"-stderr" )
|
|
msg+=" Standard error (${testid}.stderr) should match $2"$'\n'
|
|
shift 2;;
|
|
"-file" )
|
|
msg+=" Contents of file '$2' should match $3"$'\n'
|
|
shift 3;;
|
|
"-prog" )
|
|
msg+=" Result of running '$2' should be true (exit status 0)"$'\n'
|
|
shift 2;;
|
|
* )
|
|
error_exit 1 "Illegal argument to explain_test: $1"
|
|
esac
|
|
done
|
|
|
|
outputdir="$1"
|
|
cmd="$2"
|
|
shift 2
|
|
echo "${bold}What the test runs:${normal}"
|
|
echo " ${cmd} ${*@Q} > ${testid}.stdout 2>" \
|
|
"${testid}.stderr"
|
|
echo "${bold}What the test checks:${normal}"
|
|
echo "${msg}"
|
|
echo
|
|
}
|
|
|
|
# Usage: do_tests
|
|
function do_tests() {
|
|
if [[ "${action}" =~ ^(run|mark).* ]] ; then
|
|
# Action is to run or mark tests, not explain tests - make sure we have a
|
|
# program to test
|
|
do_make
|
|
echo "${bold}Running tests ... ${normal}"
|
|
fi
|
|
echo "----------------------------------------------------------------------"
|
|
for i in $TESTS_TO_RUN ; do
|
|
cmd="test${i}"
|
|
if [[ $(type -t ${cmd}) = "function" ]]; then
|
|
"${cmd}" "${action}"
|
|
else
|
|
error_exit 4 "Test ${i} is not known"
|
|
fi
|
|
done
|
|
echo "----------------------------------------------------------------------"
|
|
}
|
|
|
|
# Tests for category 1 - invalid_usage
|
|
# Details for test 1.1. ($1 will be run_test or explain_test)
|
|
function test1.1() {
|
|
"$1" 1.1 "invalid_usage01" "Check that args 'one two' considered invalid" \
|
|
-exit 1 \
|
|
-stdout "testfiles/empty" \
|
|
-stderr "testfiles/1.1.stderr" \
|
|
"${OUTPUT_DIR}" \
|
|
"./wordle-debug" 'one' 'two'
|
|
}
|
|
|
|
# Details for test 1.2. ($1 will be run_test or explain_test)
|
|
function test1.2() {
|
|
"$1" 1.2 "invalid_usage02" "Check that args 'one two three' considered invalid" \
|
|
-exit 1 \
|
|
-stdout "testfiles/empty" \
|
|
-stderr "testfiles/1.1.stderr" \
|
|
"${OUTPUT_DIR}" \
|
|
"./wordle-debug" 'one' 'two' 'three'
|
|
}
|
|
|
|
# Details for test 1.3. ($1 will be run_test or explain_test)
|
|
function test1.3() {
|
|
"$1" 1.3 "invalid_usage03" "Check that args 'one two three four' considered invalid" \
|
|
-exit 1 \
|
|
-stdout "testfiles/empty" \
|
|
-stderr "testfiles/1.1.stderr" \
|
|
"${OUTPUT_DIR}" \
|
|
"./wordle-debug" 'one' 'two' 'three' 'four'
|
|
}
|
|
|
|
# Details for test 1.4. ($1 will be run_test or explain_test)
|
|
function test1.4() {
|
|
"$1" 1.4 "invalid_usage04" "Check that args 'one two three four five' considered invalid" \
|
|
-exit 1 \
|
|
-stdout "testfiles/empty" \
|
|
-stderr "testfiles/1.1.stderr" \
|
|
"${OUTPUT_DIR}" \
|
|
"./wordle-debug" 'one' 'two' 'three' 'four' 'five'
|
|
}
|
|
|
|
# Details for test 1.5. ($1 will be run_test or explain_test)
|
|
function test1.5() {
|
|
"$1" 1.5 "invalid_usage05" "Check that args 'one two three four five six' considered invalid" \
|
|
-exit 1 \
|
|
-stdout "testfiles/empty" \
|
|
-stderr "testfiles/1.1.stderr" \
|
|
"${OUTPUT_DIR}" \
|
|
"./wordle-debug" 'one' 'two' 'three' 'four' 'five' 'six'
|
|
}
|
|
|
|
# Details for test 1.6. ($1 will be run_test or explain_test)
|
|
function test1.6() {
|
|
"$1" 1.6 "invalid_usage06" "Check that args '-max' considered invalid" \
|
|
-exit 1 \
|
|
-stdout "testfiles/empty" \
|
|
-stderr "testfiles/1.1.stderr" \
|
|
"${OUTPUT_DIR}" \
|
|
"./wordle-debug" '-max'
|
|
}
|
|
|
|
# Details for test 1.7. ($1 will be run_test or explain_test)
|
|
function test1.7() {
|
|
"$1" 1.7 "invalid_usage07" "Check that args '-len' considered invalid" \
|
|
-exit 1 \
|
|
-stdout "testfiles/empty" \
|
|
-stderr "testfiles/1.1.stderr" \
|
|
"${OUTPUT_DIR}" \
|
|
"./wordle-debug" '-len'
|
|
}
|
|
|
|
# Details for test 1.8. ($1 will be run_test or explain_test)
|
|
function test1.8() {
|
|
"$1" 1.8 "invalid_usage08" "Check that args '-max nonnumber' considered invalid" \
|
|
-exit 1 \
|
|
-stdout "testfiles/empty" \
|
|
-stderr "testfiles/1.1.stderr" \
|
|
"${OUTPUT_DIR}" \
|
|
"./wordle-debug" '-max' 'nonnumber'
|
|
}
|
|
|
|
# Details for test 1.9. ($1 will be run_test or explain_test)
|
|
function test1.9() {
|
|
"$1" 1.9 "invalid_usage09" "Check that args '-len nonnumber' considered invalid" \
|
|
-exit 1 \
|
|
-stdout "testfiles/empty" \
|
|
-stderr "testfiles/1.1.stderr" \
|
|
"${OUTPUT_DIR}" \
|
|
"./wordle-debug" '-len' 'nonnumber'
|
|
}
|
|
|
|
# Details for test 1.10. ($1 will be run_test or explain_test)
|
|
function test1.10() {
|
|
"$1" 1.10 "invalid_usage10" "Check that args '-max 5 -len' considered invalid" \
|
|
-exit 1 \
|
|
-stdout "testfiles/empty" \
|
|
-stderr "testfiles/1.1.stderr" \
|
|
"${OUTPUT_DIR}" \
|
|
"./wordle-debug" '-max' '5' '-len'
|
|
}
|
|
|
|
# Details for test 1.11. ($1 will be run_test or explain_test)
|
|
function test1.11() {
|
|
"$1" 1.11 "invalid_usage11" "Check that args '-max 2' considered invalid" \
|
|
-exit 1 \
|
|
-stdout "testfiles/empty" \
|
|
-stderr "testfiles/1.1.stderr" \
|
|
"${OUTPUT_DIR}" \
|
|
"./wordle-debug" '-max' '2'
|
|
}
|
|
|
|
# Details for test 1.12. ($1 will be run_test or explain_test)
|
|
function test1.12() {
|
|
"$1" 1.12 "invalid_usage12" "Check that args '-max 10' considered invalid" \
|
|
-exit 1 \
|
|
-stdout "testfiles/empty" \
|
|
-stderr "testfiles/1.1.stderr" \
|
|
"${OUTPUT_DIR}" \
|
|
"./wordle-debug" '-max' '10'
|
|
}
|
|
|
|
# Details for test 1.13. ($1 will be run_test or explain_test)
|
|
function test1.13() {
|
|
"$1" 1.13 "invalid_usage13" "Check that args '-max 3abc' considered invalid" \
|
|
-exit 1 \
|
|
-stdout "testfiles/empty" \
|
|
-stderr "testfiles/1.1.stderr" \
|
|
"${OUTPUT_DIR}" \
|
|
"./wordle-debug" '-max' '3abc'
|
|
}
|
|
|
|
# Details for test 1.14. ($1 will be run_test or explain_test)
|
|
function test1.14() {
|
|
"$1" 1.14 "invalid_usage14" "Check that args '-max 3 dictionary extra-arg' considered invalid" \
|
|
-exit 1 \
|
|
-stdout "testfiles/empty" \
|
|
-stderr "testfiles/1.1.stderr" \
|
|
"${OUTPUT_DIR}" \
|
|
"./wordle-debug" '-max' '3' 'dictionary' 'extra-arg'
|
|
}
|
|
|
|
# Details for test 1.15. ($1 will be run_test or explain_test)
|
|
function test1.15() {
|
|
"$1" 1.15 "invalid_usage15" "Check that args '-max 8 -len nonnumber' considered invalid" \
|
|
-exit 1 \
|
|
-stdout "testfiles/empty" \
|
|
-stderr "testfiles/1.1.stderr" \
|
|
"${OUTPUT_DIR}" \
|
|
"./wordle-debug" '-max' '8' '-len' 'nonnumber'
|
|
}
|
|
|
|
# Details for test 1.16. ($1 will be run_test or explain_test)
|
|
function test1.16() {
|
|
"$1" 1.16 "invalid_usage16" "Check that args '-max 8 -max 8' considered invalid" \
|
|
-exit 1 \
|
|
-stdout "testfiles/empty" \
|
|
-stderr "testfiles/1.1.stderr" \
|
|
"${OUTPUT_DIR}" \
|
|
"./wordle-debug" '-max' '8' '-max' '8'
|
|
}
|
|
|
|
# Details for test 1.17. ($1 will be run_test or explain_test)
|
|
function test1.17() {
|
|
"$1" 1.17 "invalid_usage17" "Check that args '-guess' considered invalid" \
|
|
-exit 1 \
|
|
-stdout "testfiles/empty" \
|
|
-stderr "testfiles/1.1.stderr" \
|
|
"${OUTPUT_DIR}" \
|
|
"./wordle-debug" '-guess'
|
|
}
|
|
|
|
# Details for test 1.18. ($1 will be run_test or explain_test)
|
|
function test1.18() {
|
|
"$1" 1.18 "invalid_usage18" "Check that args '-max 3 -max 5 /usr/share/dict/words' considered invalid" \
|
|
-exit 1 \
|
|
-stdout "testfiles/empty" \
|
|
-stderr "testfiles/1.1.stderr" \
|
|
"${OUTPUT_DIR}" \
|
|
"./wordle-debug" '-max' '3' '-max' '5' '/usr/share/dict/words'
|
|
}
|
|
|
|
# Details for test 1.19. ($1 will be run_test or explain_test)
|
|
function test1.19() {
|
|
"$1" 1.19 "invalid_usage19" "Check that args '-max 5 -len 5 /usr/share/dict/words extra' considered invalid" \
|
|
-exit 1 \
|
|
-stdout "testfiles/empty" \
|
|
-stderr "testfiles/1.1.stderr" \
|
|
"${OUTPUT_DIR}" \
|
|
"./wordle-debug" '-max' '5' '-len' '5' '/usr/share/dict/words' 'extra'
|
|
}
|
|
|
|
# Details for test 1.20. ($1 will be run_test or explain_test)
|
|
function test1.20() {
|
|
"$1" 1.20 "invalid_usage20" "Check that args '-guess 8' considered invalid" \
|
|
-exit 1 \
|
|
-stdout "testfiles/empty" \
|
|
-stderr "testfiles/1.1.stderr" \
|
|
"${OUTPUT_DIR}" \
|
|
"./wordle-debug" '-guess' '8'
|
|
}
|
|
|
|
# Tests for category 2 - invalid_file
|
|
# Details for test 2.1. ($1 will be run_test or explain_test)
|
|
function test2.1() {
|
|
"$1" 2.1 "invalid_file01" "Dictionary 'hello.there.csse2310' unable to be opened with program args ''" \
|
|
-exit 2 \
|
|
-stdout "testfiles/empty" \
|
|
-stderr "testfiles/2.1.stderr" \
|
|
"${OUTPUT_DIR}" \
|
|
"./wordle-debug" 'hello.there.csse2310'
|
|
}
|
|
|
|
# Details for test 2.2. ($1 will be run_test or explain_test)
|
|
function test2.2() {
|
|
"$1" 2.2 "invalid_file02" "Dictionary '/does/not/exist' unable to be opened with program args ''" \
|
|
-exit 2 \
|
|
-stdout "testfiles/empty" \
|
|
-stderr "testfiles/2.2.stderr" \
|
|
"${OUTPUT_DIR}" \
|
|
"./wordle-debug" '/does/not/exist'
|
|
}
|
|
|
|
# Details for test 2.3. ($1 will be run_test or explain_test)
|
|
function test2.3() {
|
|
"$1" 2.3 "invalid_file03" "Dictionary '/var/log/cron' unable to be opened with program args ''" \
|
|
-exit 2 \
|
|
-stdout "testfiles/empty" \
|
|
-stderr "testfiles/2.3.stderr" \
|
|
"${OUTPUT_DIR}" \
|
|
"./wordle-debug" '/var/log/cron'
|
|
}
|
|
|
|
# Details for test 2.4. ($1 will be run_test or explain_test)
|
|
function test2.4() {
|
|
"$1" 2.4 "invalid_file04" "Dictionary '../nope' unable to be opened with program args ''" \
|
|
-exit 2 \
|
|
-stdout "testfiles/empty" \
|
|
-stderr "testfiles/2.4.stderr" \
|
|
"${OUTPUT_DIR}" \
|
|
"./wordle-debug" '../nope'
|
|
}
|
|
|
|
# Details for test 2.5. ($1 will be run_test or explain_test)
|
|
function test2.5() {
|
|
"$1" 2.5 "invalid_file05" "Dictionary 'hello.there.csse2310' unable to be opened with program args '-len 4'" \
|
|
-exit 2 \
|
|
-stdout "testfiles/empty" \
|
|
-stderr "testfiles/2.5.stderr" \
|
|
"${OUTPUT_DIR}" \
|
|
"./wordle-debug" '-len' '4' 'hello.there.csse2310'
|
|
}
|
|
|
|
# Details for test 2.6. ($1 will be run_test or explain_test)
|
|
function test2.6() {
|
|
"$1" 2.6 "invalid_file06" "Dictionary '/does/not/exist' unable to be opened with program args '-len 4'" \
|
|
-exit 2 \
|
|
-stdout "testfiles/empty" \
|
|
-stderr "testfiles/2.6.stderr" \
|
|
"${OUTPUT_DIR}" \
|
|
"./wordle-debug" '-len' '4' '/does/not/exist'
|
|
}
|
|
|
|
# Details for test 2.7. ($1 will be run_test or explain_test)
|
|
function test2.7() {
|
|
"$1" 2.7 "invalid_file07" "Dictionary '/var/log/cron' unable to be opened with program args '-len 4'" \
|
|
-exit 2 \
|
|
-stdout "testfiles/empty" \
|
|
-stderr "testfiles/2.7.stderr" \
|
|
"${OUTPUT_DIR}" \
|
|
"./wordle-debug" '-len' '4' '/var/log/cron'
|
|
}
|
|
|
|
# Details for test 2.8. ($1 will be run_test or explain_test)
|
|
function test2.8() {
|
|
"$1" 2.8 "invalid_file08" "Dictionary '../nope' unable to be opened with program args '-len 4'" \
|
|
-exit 2 \
|
|
-stdout "testfiles/empty" \
|
|
-stderr "testfiles/2.8.stderr" \
|
|
"${OUTPUT_DIR}" \
|
|
"./wordle-debug" '-len' '4' '../nope'
|
|
}
|
|
|
|
# Tests for category 3 - prompt
|
|
# Details for test 3.1. ($1 will be run_test or explain_test)
|
|
function test3.1() {
|
|
"$1" 3.1 "prompt01" "Check for welcome and prompt" \
|
|
-stdout "testfiles/3.1.stdout" \
|
|
"${OUTPUT_DIR}" \
|
|
"testfiles-custom/run_wordle.sh" 'right' '/dev/null' '-lines' '2'
|
|
}
|
|
|
|
# Details for test 3.2. ($1 will be run_test or explain_test)
|
|
function test3.2() {
|
|
"$1" 3.2 "prompt02" "Check for welcome and prompt 2" \
|
|
-stdout "testfiles/3.2.stdout" \
|
|
"${OUTPUT_DIR}" \
|
|
"testfiles-custom/run_wordle.sh" 'right' '/dev/null' '-lines' '2' '-max' '3'
|
|
}
|
|
|
|
# Tests for category 4 - wrong_len
|
|
# Details for test 4.1. ($1 will be run_test or explain_test)
|
|
function test4.1() {
|
|
"$1" 4.1 "wrong_len01" "Check guess of length 4 with default word length" \
|
|
-stdout "testfiles/4.1.stdout" \
|
|
"${OUTPUT_DIR}" \
|
|
"testfiles-custom/run_wordle.sh" 'right' 'testfiles/wronglen.1'
|
|
}
|
|
|
|
# Details for test 4.2. ($1 will be run_test or explain_test)
|
|
function test4.2() {
|
|
"$1" 4.2 "wrong_len02" "Check guess of length 0 with default word length" \
|
|
-stdout "testfiles/4.1.stdout" \
|
|
"${OUTPUT_DIR}" \
|
|
"testfiles-custom/run_wordle.sh" 'right' 'testfiles/wronglen.2'
|
|
}
|
|
|
|
# Details for test 4.3. ($1 will be run_test or explain_test)
|
|
function test4.3() {
|
|
"$1" 4.3 "wrong_len03" "Check guesses that are too long (word length 4)" \
|
|
-stdout "testfiles/4.3.stdout" \
|
|
"${OUTPUT_DIR}" \
|
|
"testfiles-custom/run_wordle.sh" 'word' 'testfiles/wronglen.3' '-len' '4'
|
|
}
|
|
|
|
# Tests for category 5 - non_letters
|
|
# Details for test 5.1. ($1 will be run_test or explain_test)
|
|
function test5.1() {
|
|
"$1" 5.1 "non_letters01" "Check program handles guesses with non letters - with args '-len 6 -max 7'" \
|
|
-stdout "testfiles/5.1.stdout" \
|
|
"${OUTPUT_DIR}" \
|
|
"testfiles-custom/run_wordle.sh" 'right' 'testfiles/nonletters.1'
|
|
}
|
|
|
|
# Details for test 5.2. ($1 will be run_test or explain_test)
|
|
function test5.2() {
|
|
"$1" 5.2 "non_letters02" "Check program handles guesses with non letters - with args '-len 6 -max 7'" \
|
|
-stdout "testfiles/5.2.stdout" \
|
|
"${OUTPUT_DIR}" \
|
|
"testfiles-custom/run_wordle.sh" 'there' 'testfiles/nonletters.2'
|
|
}
|
|
|
|
# Details for test 5.3. ($1 will be run_test or explain_test)
|
|
function test5.3() {
|
|
"$1" 5.3 "non_letters03" "Check program handles guesses with non letters - with args '-len 6 -max 7'" \
|
|
-stdout "testfiles/5.3.stdout" \
|
|
"${OUTPUT_DIR}" \
|
|
"testfiles-custom/run_wordle.sh" 'cat' 'testfiles/nonletters.3' '-len' '3'
|
|
}
|
|
|
|
# Tests for category 6 - incorrect_guesses
|
|
# Details for test 6.1. ($1 will be run_test or explain_test)
|
|
function test6.1() {
|
|
"$1" 6.1 "incorrect_guesses01" "Single invalid guess, default dictionary and other options" \
|
|
-stdout "testfiles/6.1.stdout" \
|
|
"${OUTPUT_DIR}" \
|
|
"testfiles-custom/run_wordle.sh" 'lines' 'testfiles/invalid.1'
|
|
}
|
|
|
|
# Details for test 6.2. ($1 will be run_test or explain_test)
|
|
function test6.2() {
|
|
"$1" 6.2 "incorrect_guesses02" "Multiple invalid guesses, default dictionary and other options" \
|
|
-stdout "testfiles/6.2.stdout" \
|
|
-exit 3 \
|
|
"${OUTPUT_DIR}" \
|
|
"testfiles-custom/run_wordle.sh" 'guess' 'testfiles/invalid.2'
|
|
}
|
|
|
|
# Details for test 6.3. ($1 will be run_test or explain_test)
|
|
function test6.3() {
|
|
"$1" 6.3 "incorrect_guesses03" "Multiple invalid guesses, supplied dictionary and default other options" \
|
|
-stdout "testfiles/6.2.stdout" \
|
|
"${OUTPUT_DIR}" \
|
|
"testfiles-custom/run_wordle.sh" 'marks' 'testfiles/invalid.3' '/local/courses/csse2310/etc/common-words'
|
|
}
|
|
|
|
# Details for test 6.4. ($1 will be run_test or explain_test)
|
|
function test6.4() {
|
|
"$1" 6.4 "incorrect_guesses04" "Multiple invalid guesses, default dictionary, other args given" \
|
|
-stdout "testfiles/6.4.stdout" \
|
|
"${OUTPUT_DIR}" \
|
|
"testfiles-custom/run_wordle.sh" 'answer' 'testfiles/invalid.4' '-len' '6'
|
|
}
|
|
|
|
# Tests for category 7 - various_capitalisation
|
|
# Details for test 7.1. ($1 will be run_test or explain_test)
|
|
function test7.1() {
|
|
"$1" 7.1 "various_capitalisation01" "Single incorrect guess, default dictionary and other options" \
|
|
-stdout "testfiles/7.1.stdout" \
|
|
"${OUTPUT_DIR}" \
|
|
"testfiles-custom/run_wordle.sh" 'hands' 'testfiles/incorrect.1'
|
|
}
|
|
|
|
# Details for test 7.2. ($1 will be run_test or explain_test)
|
|
function test7.2() {
|
|
"$1" 7.2 "various_capitalisation02" "Multiple incorrect guesses, default dictionary and other options" \
|
|
-stdout "testfiles/7.2.stdout" \
|
|
"${OUTPUT_DIR}" \
|
|
"testfiles-custom/run_wordle.sh" 'guess' 'testfiles/incorrect.2'
|
|
}
|
|
|
|
# Details for test 7.3. ($1 will be run_test or explain_test)
|
|
function test7.3() {
|
|
"$1" 7.3 "various_capitalisation03" "Multiple incorrect guesses, supplied dictionary and default other options" \
|
|
-stdout "testfiles/7.3.stdout" \
|
|
"${OUTPUT_DIR}" \
|
|
"testfiles-custom/run_wordle.sh" 'marks' 'testfiles/incorrect.3' '/local/courses/csse2310/etc/common-words'
|
|
}
|
|
|
|
# Details for test 7.4. ($1 will be run_test or explain_test)
|
|
function test7.4() {
|
|
"$1" 7.4 "various_capitalisation04" "Multiple incorrect guesses, default dictionary, other args given" \
|
|
-stdout "testfiles/7.4.stdout" \
|
|
"${OUTPUT_DIR}" \
|
|
"testfiles-custom/run_wordle.sh" 'answer' 'testfiles/incorrect.4' '-len' '6'
|
|
}
|
|
|
|
# Tests for category 8 - running_out_of_attempts
|
|
# Details for test 8.1. ($1 will be run_test or explain_test)
|
|
function test8.1() {
|
|
"$1" 8.1 "running_out_of_attempts01" "Multiple incorrect guesses, default dictionary and other options" \
|
|
-exit 3 \
|
|
-stdout "testfiles/8.1.stdout" \
|
|
-stderr "testfiles/8.1.stderr" \
|
|
"${OUTPUT_DIR}" \
|
|
"testfiles-custom/run_wordle.sh" 'guess' 'testfiles/incorrect.2'
|
|
}
|
|
|
|
# Details for test 8.2. ($1 will be run_test or explain_test)
|
|
function test8.2() {
|
|
"$1" 8.2 "running_out_of_attempts02" "Multiple incorrect guesses, supplied dictionary and max 3 guesses" \
|
|
-exit 3 \
|
|
-stdout "testfiles/8.2.stdout" \
|
|
-stderr "testfiles/8.2.stderr" \
|
|
"${OUTPUT_DIR}" \
|
|
"testfiles-custom/run_wordle.sh" 'marks' 'testfiles/incorrect.3' '-max' '3' '/local/courses/csse2310/etc/common-words'
|
|
}
|
|
|
|
# Details for test 8.3. ($1 will be run_test or explain_test)
|
|
function test8.3() {
|
|
"$1" 8.3 "running_out_of_attempts03" "Multiple incorrect guesses, default dictionary, word length 6" \
|
|
-exit 3 \
|
|
-stdout "testfiles/8.3.stdout" \
|
|
-stderr "testfiles/8.3.stderr" \
|
|
"${OUTPUT_DIR}" \
|
|
"testfiles-custom/run_wordle.sh" 'answer' 'testfiles/incorrect.4' '-len' '6'
|
|
}
|
|
|
|
# Tests for category 9 - handles_eof
|
|
# Details for test 9.1. ($1 will be run_test or explain_test)
|
|
function test9.1() {
|
|
"$1" 9.1 "handles_eof01" "Single blank line input before EOF" \
|
|
-exit 3 \
|
|
-stdout "testfiles/9.1.stdout" \
|
|
-stderr "testfiles/9.1.stderr" \
|
|
"${OUTPUT_DIR}" \
|
|
"testfiles-custom/run_wordle.sh" 'right' 'testfiles/eof.1'
|
|
}
|
|
|
|
# Details for test 9.2. ($1 will be run_test or explain_test)
|
|
function test9.2() {
|
|
"$1" 9.2 "handles_eof02" "EOF after second guess (before newline)" \
|
|
-exit 3 \
|
|
-stdout "testfiles/9.2.stdout" \
|
|
-stderr "testfiles/9.1.stderr" \
|
|
"${OUTPUT_DIR}" \
|
|
"testfiles-custom/run_wordle.sh" 'right' 'testfiles/eof.2'
|
|
}
|
|
|
|
# Tests for category 10 - right_answer
|
|
# Details for test 10.1. ($1 will be run_test or explain_test)
|
|
function test10.1() {
|
|
"$1" 10.1 "right_answer01" "Correct answer on third guess" \
|
|
-exit 0 \
|
|
-stdout "testfiles/10.1.stdout" \
|
|
-stderr "testfiles/empty" \
|
|
"${OUTPUT_DIR}" \
|
|
"testfiles-custom/run_wordle.sh" 'right' 'testfiles/right.1'
|
|
}
|
|
|
|
# Details for test 10.2. ($1 will be run_test or explain_test)
|
|
function test10.2() {
|
|
"$1" 10.2 "right_answer02" "Correct answer on third guess - mixed capitalisation" \
|
|
-exit 0 \
|
|
-stdout "testfiles/10.1.stdout" \
|
|
-stderr "testfiles/empty" \
|
|
"${OUTPUT_DIR}" \
|
|
"testfiles-custom/run_wordle.sh" 'right' 'testfiles/right.2'
|
|
}
|
|
|
|
# Tests for category 11 - repeated_letters
|
|
# Tests for category 12 - memory
|
|
TIMEOUT=10
|
|
TESTS_TO_RUN=' 1.1 1.2 1.3 1.4 1.5 1.6 1.7 1.8 1.9 1.10 1.11 1.12 1.13 1.14 1.15 1.16 1.17 1.18 1.19 1.20 2.1 2.2 2.3 2.4 2.5 2.6 2.7 2.8 3.1 3.2 4.1 4.2 4.3 5.1 5.2 5.3 6.1 6.2 6.3 6.4 7.1 7.2 7.3 7.4 8.1 8.2 8.3 9.1 9.2 10.1 10.2 '
|
|
|
|
check_usage "$@"
|
|
# Now have defined 'action' and 'TESTS_TO_RUN'
|
|
# 'action' will be one of 'run_test', 'explain_test' or 'mark_test'
|
|
|
|
TESTFILES_DIR='/local/courses/csse2310/resources/a1/testfiles.public'
|
|
|
|
# If we're running tests or marking then get setup to do so
|
|
if [ $action = run_test -o $action = mark_test ] ; then
|
|
setup_for_testing
|
|
fi
|
|
|
|
do_tests
|
|
|