#!/bin/bash # Test suite for mgear. echo "Test suite for mgear" 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 ../mgear.mk . function fail { false } function start_section { section="$1" echo echo "SECTION: $1" } function do_mgear { echo "Running: make $*" make --warn-undefined-variables "$@" 2>&1 | tee mgear.log assert_not_saw 'warning: undefined variable' } 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 "$@" mgear.log; then echo "Good, saw '${@:$#}' in build log." else echo "Expected '${@:$#}' in build log but didn't see it!" fail fi } function assert_not_saw { if ! grep -q "$@" mgear.log; then echo "Good, didn't see '${@:$#}' in build log." else echo "Did not expect '${@:$#}' in build log but saw it!" fail fi } function assert_uptodate { assert_saw "make: \`$1' is up to date." } function assert_generated { assert_saw "$1.tmp" } function assert { if eval $*; then echo "Good, $* returned true." else echo "Expected $* to return true but it returned false!" fail fi } 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 mgear.mk .SECONDARY: include hc-rule.mk cmd-ssc=sleep 1 && grep 'warn' $< && sed -e 's_//.*$$__' $< >$@ $(call mg-define-rule,%,%.ssc,cmd-ssc) cmd-index=sort $< >$@ $(call mg-define-rule,index,index.in,cmd-index) clean: $(call mg-clean-cmd,.) .PHONY: clean EOF cat >hc-rule.mk <<'EOF' cmd-hc=sed -e 's_$(hash).*$$__' $< >$@ $(call mg-define-rule,%,%.hc,cmd-hc) 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_mgear 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_mgear 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_mgear bar assert_saw -i overrid assert_contents bar <<>foo.hc do_mgear 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. # Also, make sure commas in commands work properly. start_section "Command change for % <- %.hc" cat >hc-rule.mk <<'EOF' cmd-hc=sed -e 's, *$(hash).*$$,,' $< >$@ $(call mg-define-rule,%,%.hc,cmd-hc) EOF do_mgear 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_mgear foo assert_generated foo assert_touched foo.g assert_not_touched foo # Test cleaning. Remember, bar is still overridden. start_section "Cleaning" do_mgear clean assert_saw 'rm.*foo' # Some sort of indication of foo's deletion assert ! [ -f foo ] # foo deleted assert ! [ -f foo.g ] # foo.g deleted assert [ -f bar ] # bar not actually deleted... assert_contents bar <<bar do_mgear bar assert_saw -i overrid assert_contents bar <<