#!/bin/bash # Test suite for Mage. echo "Test suite for Mage" cd "$(dirname "$0")" Z=test-zone rm -rf $Z mkdir $Z cd $Z #exec 3>&2 #exec 1>test.log 2>&1 exec &2' ERR #set -x ln -s ../mage.mk mage.mk function fail { false } function start_section { section="$1" echo echo "SECTION: $1" } function do_mage { echo "Running: make $*" make "$@" 2>&1 | tee mage.log } function assert_contents { if diff -u - "$1"; then echo "File '$1' looks good." else echo "File '$1' has the wrong contents!" fail fi } # Options can be passed to grep: assert_saw -i override function assert_saw { if grep -q "$@" mage.log; then echo "Good, saw '${@:$#}' in build log." else echo "Expected '${@:$#}' in build log but didn't see it! Log:" cat mage.log fail fi } function assert_not_saw { if ! grep -q "$@" mage.log; then echo "Good, saw '${@:$#}' in build log." else echo "Did not expect '${@:$#}' in build log but saw it! Log:" cat mage.log fail fi } function assert_uptodate { assert_saw "make: \`$1' is up to date." } function assert_generated { assert_saw "$1.tmp" } function remember_mtime { while [ $# != 0 ]; do eval "orig_mtime_${1//[^A-Za-z]/}=$(stat --format=%Y $1)" shift done } function assert_touched { mtvar=orig_mtime_${1//[^A-Za-z]/} t1="${!mtvar}" t2="$(stat --format=%Y $1)" echo "Times for '$1': $t1, $t2" if [ "$t1" != "$t2" ]; then echo "Good, '$1' was touched." else echo "Expected '$1' to be touched but it wasn't!" fail fi } function assert_not_touched { mtvar=orig_mtime_${1//[^A-Za-z]/} t1="${!mtvar}" t2="$(stat --format=%Y $1)" echo "Times for '$1': $t1, $t2" if [ "$t1" == "$t2" ]; then echo "Good, '$1' was not touched." else echo "Expected '$1' to be not touched but it was!" fail fi } # Simple makefile for stripping two kinds of comments. # Tests an implicit rule and two competing explicit rules. # Watch those dollar signs! cat >Makefile <<'EOF' include mage.mk .SECONDARY: include hc-rule.mk $(call mg-define-rule,%,%.ssc,sleep 1 && grep 'warn' $$< && sed -e 's_//.*$$$$__' $$< >$$t) $(call mg-define-rule,index,index.in,sort $$< >$$t) EOF cat >hc-rule.mk <<'EOF' $(call mg-define-rule,%,%.hc,sed -e 's_#.*$$$$__' $$< >$$t) EOF # Input files. cat >foo.hc <<'EOF' This is the foo file. # You don't get to see this. But you do get to see this! // Needles: you can lean but you can't hide! EOF cat >bar.ssc <<'EOF' the bar file has a different personality // hey there # I slip through warn: tell me about it! EOF cat >index.in <<'EOF' foo bar EOF # Run and make sure the files were compiled correctly. start_section "Initial full build" do_mage foo bar index assert_contents foo <<'EOF' This is the foo file. But you do get to see this! // Needles: you can lean but you can't hide! EOF assert_contents bar <<'EOF' the bar file has a different personality # I slip through warn: tell me about it! EOF assert_contents index <<'EOF' bar foo EOF assert_generated foo assert_generated bar assert_generated index assert_saw "sed -e 's_#.*\$__' foo.hc >foo.tmp" assert_saw "sleep 1 && grep 'warn' bar.ssc && sed -e 's_//.*\$__' bar.ssc >bar.tmp" assert_saw 'warn: tell me about it!' assert_saw sort index.in >index.tmp # Run it again. Make sure the warning is replayed and bar isn't overridden due # to bar.g accidentally being too old. start_section "Replay bar warning" do_mage foo bar index assert_uptodate foo assert_uptodate bar assert_uptodate index assert_saw -i '#.*warning.*replay' # Indication of warning replay assert_saw 'warn: tell me about it!' # Actual warning assert_not_saw -i overrid # Now override bar and make sure it stays that way and the warning isn't replayed. start_section "Override bar" sleep 1 # No racy cleanliness echo NEWCONTENT >bar do_mage bar assert_saw -i overrid assert_contents bar <<>foo.hc do_mage index foo assert_uptodate index assert_generated foo assert_contents foo <<'EOF' This is the foo file. But you do get to see this! // Needles: you can lean but you can't hide! look: EOF # Change the rule for # comments to strip spaces before a #. # Make sure foo is updated properly. start_section "Command change for % <- %.hc" cat >hc-rule.mk <<'EOF' $(call mg-define-rule,%,%.hc,sed -e 's_ *#.*$$$$__' $$< >$$t) EOF do_mage foo assert_generated foo assert_contents foo <<'EOF' This is the foo file. But you do get to see this! // Needles: you can lean but you can't hide! look: EOF # Remove a space before a # from foo.hc. This is an inconsequential change. # Make sure that foo.g is touched but foo is not. start_section "Inconsequential change to foo.hc" sleep 1 # No racy cleanliness remember_mtime foo foo.g sed -e '$s/look: /look:/' -i foo.hc do_mage foo assert_generated foo assert_touched foo.g assert_not_touched foo cd .. rm -rf test-zone echo echo "TEST SUITE SUCCEEDED"