Commit | Line | Data |
---|---|---|
21a50371 MM |
1 | #!/bin/bash |
2 | # Test suite for Mage. | |
3 | ||
4 | echo "Test suite for Mage" | |
5 | ||
6 | cd "$(dirname "$0")" | |
7 | Z=test-zone | |
8 | rm -rf $Z | |
9 | mkdir $Z | |
10 | cd $Z | |
11 | ||
12 | #exec 3>&2 | |
13 | #exec 1>test.log 2>&1 | |
14 | exec </dev/null | |
15 | set -e | |
16 | set -o errtrace | |
17 | section=Initialization | |
18 | trap 'echo; echo "TEST SUITE FAILED in section $section!" >&2' ERR | |
19 | #set -x | |
20 | ||
21 | ln -s ../mage.mk mage.mk | |
22 | ||
23 | function fail { | |
24 | false | |
25 | } | |
26 | ||
27 | function start_section { | |
28 | section="$1" | |
29 | echo | |
30 | echo "SECTION: $1" | |
31 | } | |
32 | ||
33 | function do_mage { | |
34 | echo "Running: make $*" | |
35 | make "$@" 2>&1 | tee mage.log | |
36 | } | |
37 | ||
38 | function assert_contents { | |
39 | if diff -u - "$1"; then | |
40 | echo "File '$1' looks good." | |
41 | else | |
42 | echo "File '$1' has the wrong contents!" | |
43 | fail | |
44 | fi | |
45 | } | |
46 | ||
47 | # Options can be passed to grep: assert_saw -i override | |
48 | function assert_saw { | |
49 | if grep -q "$@" mage.log; then | |
50 | echo "Good, saw '${@:$#}' in build log." | |
51 | else | |
52 | echo "Expected '${@:$#}' in build log but didn't see it! Log:" | |
53 | cat mage.log | |
54 | fail | |
55 | fi | |
56 | } | |
57 | function assert_not_saw { | |
58 | if ! grep -q "$@" mage.log; then | |
59 | echo "Good, saw '${@:$#}' in build log." | |
60 | else | |
61 | echo "Did not expect '${@:$#}' in build log but saw it! Log:" | |
62 | cat mage.log | |
63 | fail | |
64 | fi | |
65 | } | |
66 | function assert_uptodate { | |
67 | assert_saw "make: \`$1' is up to date." | |
68 | } | |
69 | function assert_generated { | |
70 | assert_saw "$1.tmp" | |
71 | } | |
72 | ||
73 | function remember_mtime { | |
74 | while [ $# != 0 ]; do | |
75 | eval "orig_mtime_${1//[^A-Za-z]/}=$(stat --format=%Y $1)" | |
76 | shift | |
77 | done | |
78 | } | |
79 | function assert_touched { | |
80 | mtvar=orig_mtime_${1//[^A-Za-z]/} | |
81 | t1="${!mtvar}" | |
82 | t2="$(stat --format=%Y $1)" | |
83 | echo "Times for '$1': $t1, $t2" | |
84 | if [ "$t1" != "$t2" ]; then | |
85 | echo "Good, '$1' was touched." | |
86 | else | |
87 | echo "Expected '$1' to be touched but it wasn't!" | |
88 | fail | |
89 | fi | |
90 | } | |
91 | function assert_not_touched { | |
92 | mtvar=orig_mtime_${1//[^A-Za-z]/} | |
93 | t1="${!mtvar}" | |
94 | t2="$(stat --format=%Y $1)" | |
95 | echo "Times for '$1': $t1, $t2" | |
96 | if [ "$t1" == "$t2" ]; then | |
97 | echo "Good, '$1' was not touched." | |
98 | else | |
99 | echo "Expected '$1' to be not touched but it was!" | |
100 | fail | |
101 | fi | |
102 | } | |
103 | ||
104 | # Simple makefile for stripping two kinds of comments. | |
105 | # Tests an implicit rule and two competing explicit rules. | |
106 | # Watch those dollar signs! | |
107 | cat >Makefile <<'EOF' | |
108 | include mage.mk | |
109 | .SECONDARY: | |
110 | include hc-rule.mk | |
111 | $(call mg-define-rule,%,%.ssc,sleep 1 && grep 'warn' $$< && sed -e 's_//.*$$$$__' $$< >$$t) | |
112 | $(call mg-define-rule,index,index.in,sort $$< >$$t) | |
113 | EOF | |
114 | cat >hc-rule.mk <<'EOF' | |
115 | $(call mg-define-rule,%,%.hc,sed -e 's_#.*$$$$__' $$< >$$t) | |
116 | EOF | |
117 | ||
118 | # Input files. | |
119 | cat >foo.hc <<'EOF' | |
120 | This is the foo file. | |
121 | # You don't get to see this. | |
122 | But you do get to see this! | |
123 | // Needles: you can lean but you can't hide! | |
124 | EOF | |
125 | cat >bar.ssc <<'EOF' | |
126 | the bar file has a different personality | |
127 | // hey there | |
128 | # I slip through | |
129 | warn: tell me about it! | |
130 | EOF | |
131 | cat >index.in <<'EOF' | |
132 | foo | |
133 | bar | |
134 | EOF | |
135 | ||
136 | # Run and make sure the files were compiled correctly. | |
137 | ||
138 | start_section "Initial full build" | |
139 | do_mage foo bar index | |
140 | ||
141 | assert_contents foo <<'EOF' | |
142 | This is the foo file. | |
143 | ||
144 | But you do get to see this! | |
145 | // Needles: you can lean but you can't hide! | |
146 | EOF | |
147 | assert_contents bar <<'EOF' | |
148 | the bar file has a different personality | |
149 | ||
150 | # I slip through | |
151 | warn: tell me about it! | |
152 | EOF | |
153 | assert_contents index <<'EOF' | |
154 | bar | |
155 | foo | |
156 | EOF | |
157 | assert_generated foo | |
158 | assert_generated bar | |
159 | assert_generated index | |
160 | assert_saw "sed -e 's_#.*\$__' foo.hc >foo.tmp" | |
161 | assert_saw "sleep 1 && grep 'warn' bar.ssc && sed -e 's_//.*\$__' bar.ssc >bar.tmp" | |
162 | assert_saw 'warn: tell me about it!' | |
163 | assert_saw sort index.in >index.tmp | |
164 | ||
165 | # Run it again. Make sure the warning is replayed and bar isn't overridden due | |
166 | # to bar.g accidentally being too old. | |
167 | ||
168 | start_section "Replay bar warning" | |
169 | do_mage foo bar index | |
170 | ||
171 | assert_uptodate foo | |
172 | assert_uptodate bar | |
173 | assert_uptodate index | |
174 | assert_saw -i '#.*warning.*replay' # Indication of warning replay | |
175 | assert_saw 'warn: tell me about it!' # Actual warning | |
176 | assert_not_saw -i overrid | |
177 | ||
178 | # Now override bar and make sure it stays that way and the warning isn't replayed. | |
179 | start_section "Override bar" | |
180 | sleep 1 # No racy cleanliness | |
181 | echo NEWCONTENT >bar | |
182 | do_mage bar | |
183 | ||
184 | assert_saw -i overrid | |
185 | assert_contents bar <<<NEWCONTENT | |
186 | ||
187 | # Change foo.hc and make sure foo is updated properly. | |
188 | ||
189 | start_section "Change foo.hc" | |
190 | sleep 1 # No racy cleanliness | |
191 | echo 'look: # Last-minute addition.' >>foo.hc | |
192 | do_mage index foo | |
193 | ||
194 | assert_uptodate index | |
195 | assert_generated foo | |
196 | assert_contents foo <<'EOF' | |
197 | This is the foo file. | |
198 | ||
199 | But you do get to see this! | |
200 | // Needles: you can lean but you can't hide! | |
201 | look: | |
202 | EOF | |
203 | ||
204 | # Change the rule for # comments to strip spaces before a #. | |
205 | # Make sure foo is updated properly. | |
206 | ||
207 | start_section "Command change for % <- %.hc" | |
208 | cat >hc-rule.mk <<'EOF' | |
209 | $(call mg-define-rule,%,%.hc,sed -e 's_ *#.*$$$$__' $$< >$$t) | |
210 | EOF | |
211 | do_mage foo | |
212 | ||
213 | assert_generated foo | |
214 | assert_contents foo <<'EOF' | |
215 | This is the foo file. | |
216 | ||
217 | But you do get to see this! | |
218 | // Needles: you can lean but you can't hide! | |
219 | look: | |
220 | EOF | |
221 | ||
222 | # Remove a space before a # from foo.hc. This is an inconsequential change. | |
223 | # Make sure that foo.g is touched but foo is not. | |
224 | ||
225 | start_section "Inconsequential change to foo.hc" | |
226 | sleep 1 # No racy cleanliness | |
227 | remember_mtime foo foo.g | |
228 | sed -e '$s/look: /look:/' -i foo.hc | |
229 | do_mage foo | |
230 | ||
231 | assert_generated foo | |
232 | assert_touched foo.g | |
233 | assert_not_touched foo | |
234 | ||
235 | cd .. | |
236 | rm -rf test-zone | |
237 | echo | |
238 | echo "TEST SUITE SUCCEEDED" |