# vim: ts=4 sw=4 expandtab ft=sh # # 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 test "$#" = 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. However, the recompilation will affect # the `--verbose-recompilation' messages, which we compare to the expected # output, so we need to avoid it here. sleep 1 } # Simulate a user editing the file. update_module () { if test "$#" != 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 } # Build the test, then run it and compare the output. mmake_test () { if test "$#" != 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 } # Compare the output file with the expected output file, generating # the expected output file if it doesn't exist and runtests was given # the --generate-missing-exp-files option. compare_files () { if test "$#" != 2 then echo "** usage: compare_files expected_file result_file" exit 1 fi exp_file="$1" res_file="$2" if test -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 test "$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 } check_err_file () { if test "$#" != 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 }