# # Shell functions used to run the recompilation tests. # # # Set variables `main_module' and `modules' describing the test being run. # Copy in the initial versions of the test files. # test_module () { if [ $# = 0 ] then echo "usage: test_module main_module other_modules" exit 1 fi main_module=$1 modules="$*" echo Testing $main_module for module in $modules do rm -f $module.m cp $module.m.1 $module.m # The module.m. files are the only ones # that should be edited. chmod -w $module.m done rm -f $main_module.res touch $main_module.res # XXX Avoid producing output files with the same timestamp # as the input source file. The up-to-date check for the output # file in recompilation_check.m checks that the output file's # timestamp is strictly greater than the input file's, so it # will recompile if they are the same. # # This won't be a problem in practice, unless for some reason # a user decides to have mmake invoked by their editor # automatically after each edit. If a file takes less # than a second to compile, recompiling it all the time # won't be noticeable. The recompilation will affect # the `--verbose-recompilation' messages, so we need to # avoid it here. sleep 1 } # # Simulate a user editing the file. # update_module () { if [ $# != 2 ] then echo "usage: update_module module_name version" exit 1 fi module=$1 module_version=$2 # GNU make only considers a file out of date if a dependency's # timestamp is strictly greater than the file's timestamp. # We need to make sure that the `.c' file is out of date with # respect to the `.m' file. sleep 1 rm -f $module.m cp $module.m.$module_version $module.m chmod -w $module.m # See comment in test_module(). sleep 1 } mmake_depend () { eval mmake $mmakeopts $main_module.depend || exit 1 } # # Compare the output file with the expected output file, # generating the expected output file if it doesn't exist # and the --generate-missing-exp-files option was given # to runtests. # compare_files () { if [ $# != 2 ] then echo "** usage: compare_files expected_file result_file" exit 1 fi exp_file=$1 res_file=$2 if [ -f $exp_file ] then if diff ${DIFF_OPTS-"-c"} $exp_file \ $res_file >> $main_module.res then : else echo "** Error: $exp_file and $res_file differ." exit 1 fi else if [ $generate_missing_exp_files = true ] then echo "** WARNING: generating $exp_file" cp $res_file $exp_file else echo "** Error: $exp_file not found" exit 1 fi fi } # # Build the test, then run it and compare the output. # mmake_test () { if [ $# != 2 ] then echo "** usage: mmake_test output_file_version should_fail" exit 1 fi output_file_version=$1 mmake_should_fail=$2 # XXX This is a hacky way of testing for Java grades echo "mmakeopts=$mmakeopts" case $mmakeopts in *java*) target=$main_module.classes run_target="java $main_module" ;; *) target=$main_module run_target="./$main_module" ;; esac case $mmake_should_fail in true) # # If the compilation is supposed to fail then the mmake # output should be suppressed to avoid making it harder # to find genuine failures in the nightly test logs. # The `-k' option to mmake avoids differences in the output # when using parallel mmakes. # eval mmake $mmakeopts -k \ $target > $main_module.failing_make_output 2>&1 ;; false) eval mmake $mmakeopts $target ;; esac case $? in 0) case $mmake_should_fail in true) echo \ "** Error: mmake $mmakeopts $target succeeded where it should fail" exit 1 ;; esac $run_target > $main_module.out compare_files $main_module.exp.$output_file_version \ $main_module.out ;; *) case $mmake_should_fail in false) echo "** Error: mmake $mmakeopts $target failed" exit 1 ;; esac ;; esac } check_err_file () { if [ $# != 2 ] then echo "** usage: check_err_file module message_file_version" fi module=$1 error_file_version=$2 # In `.hl*' grades, the compiler sometimes puts an extra line in # the `.err' file ("foo.h has CHANGED"). Filter it out here. # Also filter out any references to the directories created by the # `--use-subdirs' option. sed -e '/has CHANGED/d' \ -e 's/Mercury\/.*\///g' \ $module.err > $module.err2 mv $module.err2 $module.err compare_files $module.err_exp.$error_file_version $module.err } cleanup_test () { case $cleanup in true) eval mmake $mmakeopts $main_module.realclean for module in $modules do rm -f $module.m done ;; esac }