summaryrefslogtreecommitdiffstats
path: root/usr.bin/make/tests/common.sh
diff options
context:
space:
mode:
Diffstat (limited to 'usr.bin/make/tests/common.sh')
-rw-r--r--usr.bin/make/tests/common.sh533
1 files changed, 533 insertions, 0 deletions
diff --git a/usr.bin/make/tests/common.sh b/usr.bin/make/tests/common.sh
new file mode 100644
index 0000000..5c5df1e
--- /dev/null
+++ b/usr.bin/make/tests/common.sh
@@ -0,0 +1,533 @@
+# $FreeBSD$
+#
+# Common code used run regression tests for usr.bin/make.
+
+#
+# Output a message and exit with an error.
+#
+fatal()
+{
+ echo "fatal: $*" >/dev/stderr
+ exit 1
+}
+
+make_is_fmake() {
+ # This test is not very reliable but works for now: the old fmake
+ # does have a -v option while bmake doesn't.
+ ${MAKE_PROG} -f Makefile.non-existent -v 2>&1 | \
+ grep -q "cannot open.*non-existent"
+}
+
+#
+# Check whether the working directory exists - it must.
+#
+ensure_workdir()
+{
+ if [ ! -d ${WORK_DIR} ] ; then
+ fatal "working directory ${WORK_DIR} does not exist."
+ fi
+}
+
+#
+# Make sure all tests have been run
+#
+ensure_run()
+{
+ if [ -z "${TEST_N}" ] ; then
+ TEST_N=1
+ fi
+
+ FAIL=
+ N=1
+ while [ ${N} -le ${TEST_N} ] ; do
+ if ! skip_test ${N} ; then
+ if [ ! -f ${OUTPUT_DIR}/status.${N} -o \
+ ! -f ${OUTPUT_DIR}/stdout.${N} -o \
+ ! -f ${OUTPUT_DIR}/stderr.${N} ] ; then
+ echo "Test ${SUBDIR}/${N} no yet run"
+ FAIL=yes
+ fi
+ fi
+ N=$((N + 1))
+ done
+
+ if [ ! -z "${FAIL}" ] ; then
+ exit 1
+ fi
+}
+
+#
+# Output usage messsage.
+#
+print_usage()
+{
+ echo "Usage: sh -v -m <path> -w <dir> $0 command(s)"
+ echo " setup - setup working directory"
+ echo " run - run the tests"
+ echo " show - show test results"
+ echo " compare - compare actual and expected results"
+ echo " diff - diff actual and expected results"
+ echo " reset - reset the test to its initial state"
+ echo " clean - delete working and output directory"
+ echo " test - setup + run + compare"
+ echo " prove - setup + run + compare + clean"
+ echo " desc - print short description"
+ echo " update - update the expected results with the current results"
+ echo " help - show this information"
+}
+
+#
+# Return 0 if we should skip the test. 1 otherwise
+#
+skip_test()
+{
+ eval skip=\${TEST_${1}_SKIP}
+ if [ -z "${skip}" ] ; then
+ return 1
+ else
+ return 0
+ fi
+}
+
+#
+# Common function for setup and reset.
+#
+common_setup()
+{
+ #
+ # If a Makefile exists in the source directory - copy it over
+ #
+ if [ -e ${SRC_DIR}/Makefile.test -a ! -e ${WORK_DIR}/Makefile ] ; then
+ cp ${SRC_DIR}/Makefile.test ${WORK_DIR}/Makefile
+ fi
+
+ #
+ # If the TEST_MAKE_DIRS variable is set, create those directories
+ #
+ set -- ${TEST_MAKE_DIRS}
+ while [ $# -ne 0 ] ; do
+ if [ ! -d ${WORK_DIR}/${1} ] ; then
+ mkdir -p -m ${2} ${WORK_DIR}/${1}
+ else
+ chmod ${2} ${WORK_DIR}/${1}
+ fi
+ shift ; shift
+ done
+
+ #
+ # If the TEST_COPY_FILES variable is set, copy those files over to
+ # the working directory. The value is assumed to be pairs of
+ # filenames and modes.
+ #
+ set -- ${TEST_COPY_FILES}
+ while [ $# -ne 0 ] ; do
+ local dstname="$(echo ${1} | sed -e 's,Makefile.test,Makefile,')"
+ if [ ! -e ${WORK_DIR}/${dstname} ] ; then
+ cp ${SRC_DIR}/${1} ${WORK_DIR}/${dstname}
+ fi
+ chmod ${2} ${WORK_DIR}/${dstname}
+ shift ; shift
+ done
+
+ #
+ # If the TEST_TOUCH variable is set, it is taken to be a list
+ # of pairs of filenames and arguments to touch(1). The arguments
+ # to touch must be surrounded by single quotes if there are more
+ # than one argument.
+ #
+ eval set -- ${TEST_TOUCH}
+ while [ $# -ne 0 ] ; do
+ eval touch ${2} ${WORK_DIR}/${1}
+ shift ; shift
+ done
+
+ #
+ # Now create links
+ #
+ eval set -- ${TEST_LINKS}
+ while [ $# -ne 0 ] ; do
+ eval ln ${WORK_DIR}/${1} ${WORK_DIR}/${2}
+ shift ; shift
+ done
+}
+
+#
+# Setup the test. This creates the working and output directories and
+# populates it with files. If there is a setup_test() function - call it.
+#
+eval_setup()
+{
+ #
+ # Check whether the working directory exists. If it does exit
+ # fatally so that we don't clobber a test the user is working on.
+ #
+ if [ -d ${WORK_DIR} ] ; then
+ fatal "working directory ${WORK_DIR} already exists."
+ fi
+
+ #
+ # Now create it and the output directory
+ #
+ mkdir -p ${WORK_DIR}
+ rm -rf ${OUTPUT_DIR}
+ mkdir -p ${OUTPUT_DIR}
+
+ #
+ # Common stuff
+ #
+ common_setup
+
+ #
+ # Now after all execute the user's setup function if it exists.
+ #
+ setup_test
+}
+
+#
+# Default setup_test function does nothing. This may be overriden by
+# the test.
+#
+setup_test()
+{
+}
+
+#
+# Reset the test. Here we need to rely on information from the test.
+# We executed the same steps as in the setup, by try not to clobber existing
+# files.
+# All files and directories that are listed on the TEST_CLEAN_FILES
+# variable are removed. Then the TEST_TOUCH list is executed and finally
+# the reset_test() function called if it exists.
+#
+eval_reset()
+{
+ ensure_workdir
+
+ #
+ # Clean the output directory
+ #
+ rm -rf ${OUTPUT_DIR}/*
+
+ #
+ # Common stuff
+ #
+ common_setup
+
+ #
+ # Remove files.
+ #
+ for f in ${TEST_CLEAN_FILES} ; do
+ rm -rf ${WORK_DIR}/${f}
+ done
+
+ #
+ # Execute test's function
+ #
+ reset_test
+}
+
+#
+# Default reset_test function does nothing. This may be overriden by
+# the test.
+#
+reset_test()
+{
+}
+
+#
+# Clean the test. This simply removes the working and output directories.
+#
+eval_clean()
+{
+ #
+ # If you have special cleaning needs, provide a 'cleanup' shell script.
+ #
+ if [ -n "${TEST_CLEANUP}" ] ; then
+ . ${SRC_DIR}/cleanup
+ fi
+ if [ -z "${NO_TEST_CLEANUP}" ] ; then
+ rm -rf ${WORK_DIR}
+ rm -rf ${OUTPUT_DIR}
+ fi
+}
+
+#
+# Run the test.
+#
+eval_run()
+{
+ ensure_workdir
+
+ if [ -z "${TEST_N}" ] ; then
+ TEST_N=1
+ fi
+
+ N=1
+ while [ ${N} -le ${TEST_N} ] ; do
+ if ! skip_test ${N} ; then
+ ( cd ${WORK_DIR} ;
+ exec 1>${OUTPUT_DIR}/stdout.${N} 2>${OUTPUT_DIR}/stderr.${N}
+ run_test ${N}
+ echo $? >${OUTPUT_DIR}/status.${N}
+ )
+ fi
+ N=$((N + 1))
+ done
+}
+
+#
+# Default run_test() function. It can be replaced by the
+# user specified regression test. The argument to this function is
+# the test number.
+#
+run_test()
+{
+ eval args=\${TEST_${1}-test${1}}
+ ${MAKE_PROG} $args
+}
+
+#
+# Show test results.
+#
+eval_show()
+{
+ ensure_workdir
+
+ if [ -z "${TEST_N}" ] ; then
+ TEST_N=1
+ fi
+
+ N=1
+ while [ ${N} -le ${TEST_N} ] ; do
+ if ! skip_test ${N} ; then
+ echo "=== Test ${N} Status =================="
+ cat ${OUTPUT_DIR}/status.${N}
+ echo ".......... Stdout .................."
+ cat ${OUTPUT_DIR}/stdout.${N}
+ echo ".......... Stderr .................."
+ cat ${OUTPUT_DIR}/stderr.${N}
+ fi
+ N=$((N + 1))
+ done
+}
+
+#
+# Compare results with expected results
+#
+eval_compare()
+{
+ ensure_workdir
+ ensure_run
+
+ if [ -z "${TEST_N}" ] ; then
+ TEST_N=1
+ fi
+
+ echo "1..${TEST_N}"
+ N=1
+ while [ ${N} -le ${TEST_N} ] ; do
+ fail=
+ todo=
+ skip=
+ if ! skip_test ${N} ; then
+ do_compare stdout ${N} || fail="${fail}stdout "
+ do_compare stderr ${N} || fail="${fail}stderr "
+ do_compare status ${N} || fail="${fail}status "
+ eval todo=\${TEST_${N}_TODO}
+ else
+ eval skip=\${TEST_${N}_SKIP}
+ fi
+ msg=
+ if [ ! -z "$fail" ]; then
+ msg="${msg}not "
+ fi
+ msg="${msg}ok ${N} ${SUBDIR}/${N}"
+ if [ ! -z "$fail" -o ! -z "$todo" -o ! -z "$skip" ]; then
+ msg="${msg} # "
+ fi
+ if [ ! -z "$skip" ] ; then
+ msg="${msg}skip ${skip}; "
+ fi
+ if [ ! -z "$todo" ] ; then
+ msg="${msg}TODO ${todo}; "
+ fi
+ if [ ! -z "$fail" ] ; then
+ msg="${msg}reason: ${fail}"
+ fi
+ echo ${msg}
+ N=$((N + 1))
+ done
+}
+
+#
+# Check if the test result is the same as the expected result.
+#
+# $1 Input file
+# $2 Test number
+#
+do_compare()
+{
+ local EXPECTED RESULT
+ EXPECTED="${SRC_DIR}/expected.$1.$2"
+ RESULT="${OUTPUT_DIR}/$1.$2"
+
+ if [ -f $EXPECTED ]; then
+ cat $RESULT | sed -e "s,^$(basename $MAKE_PROG):,make:," | \
+ diff -u $EXPECTED -
+ #diff -q $EXPECTED - 1>/dev/null 2>/dev/null
+ return $?
+ else
+ return 1 # FAIL
+ fi
+}
+
+#
+# Diff current and expected results
+#
+eval_diff()
+{
+ ensure_workdir
+ ensure_run
+
+ if [ -z "${TEST_N}" ] ; then
+ TEST_N=1
+ fi
+
+ N=1
+ while [ ${N} -le ${TEST_N} ] ; do
+ if ! skip_test ${N} ; then
+ FAIL=
+ do_diff stdout ${N}
+ do_diff stderr ${N}
+ do_diff status ${N}
+ fi
+ N=$((N + 1))
+ done
+}
+
+#
+# Check if the test result is the same as the expected result.
+#
+# $1 Input file
+# $2 Test number
+#
+do_diff()
+{
+ local EXPECTED RESULT
+ EXPECTED="${SRC_DIR}/expected.$1.$2"
+ RESULT="${OUTPUT_DIR}/$1.$2"
+
+ echo diff -u $EXPECTED $RESULT
+ if [ -f $EXPECTED ]; then
+ diff -u $EXPECTED $RESULT
+ else
+ echo "${EXPECTED} does not exist"
+ fi
+}
+
+#
+# Update expected results
+#
+eval_update()
+{
+ ensure_workdir
+ ensure_run
+
+ if [ -z "${TEST_N}" ] ; then
+ TEST_N=1
+ fi
+
+ FAIL=
+ N=1
+ while [ ${N} -le ${TEST_N} ] ; do
+ if ! skip_test ${N} ; then
+ cp ${OUTPUT_DIR}/stdout.${N} expected.stdout.${N}
+ cp ${OUTPUT_DIR}/stderr.${N} expected.stderr.${N}
+ cp ${OUTPUT_DIR}/status.${N} expected.status.${N}
+ fi
+ N=$((N + 1))
+ done
+}
+
+#
+# Print description
+#
+eval_desc()
+{
+ echo "${SUBDIR}: ${DESC}"
+}
+
+#
+# Run the test
+#
+eval_test()
+{
+ eval_setup
+ eval_run
+ eval_compare
+}
+
+#
+# Run the test for prove(1)
+#
+eval_prove()
+{
+ eval_setup
+ eval_run
+ eval_compare
+ eval_clean
+}
+
+#
+# Main function. Execute the command(s) on the command line.
+#
+eval_cmd()
+{
+ if [ $# -eq 0 ] ; then
+ # if no arguments given default to 'prove'
+ set -- prove
+ fi
+
+ if ! make_is_fmake ; then
+ for i in $(jot ${TEST_N:-1}) ; do
+ eval TEST_${i}_SKIP=\"make is not fmake\"
+ done
+ fi
+
+ for i
+ do
+ case $i in
+
+ setup | run | compare | diff | clean | reset | show | \
+ test | prove | desc | update)
+ eval eval_$i
+ ;;
+ * | help)
+ print_usage
+ ;;
+ esac
+ done
+}
+
+##############################################################################
+#
+# Main code
+#
+
+#
+# Determine our sub-directory. Argh.
+#
+SRC_DIR=$(dirname $0)
+SRC_BASE=`cd ${SRC_DIR} ; while [ ! -f common.sh ] ; do cd .. ; done ; pwd`
+SUBDIR=`echo ${SRC_DIR} | sed "s@${SRC_BASE}/@@"`
+
+#
+# Construct working directory
+#
+WORK_DIR=$(pwd)/work/${SUBDIR}
+OUTPUT_DIR=${WORK_DIR}.OUTPUT
+
+#
+# Make to use
+#
+MAKE_PROG=${MAKE_PROG:-/usr/bin/make}
OpenPOWER on IntegriCloud