aboutsummaryrefslogtreecommitdiff
path: root/tests/recipe/buildscript/testscript
diff options
context:
space:
mode:
Diffstat (limited to 'tests/recipe/buildscript/testscript')
-rw-r--r--tests/recipe/buildscript/testscript1780
1 files changed, 1751 insertions, 29 deletions
diff --git a/tests/recipe/buildscript/testscript b/tests/recipe/buildscript/testscript
index 551f64a..cded5ea 100644
--- a/tests/recipe/buildscript/testscript
+++ b/tests/recipe/buildscript/testscript
@@ -1,6 +1,8 @@
# file : tests/recipe/buildscript/testscript
# license : MIT; see accompanying LICENSE file
+posix = ($cxx.target.class != 'windows')
+
+mkdir build
+cat <<EOI >=build/bootstrap.build
project = test
@@ -17,24 +19,582 @@
: update
:
{
- echo 'bar' >=bar;
+ : success
+ :
+ {
+ echo 'bar' >=bar;
- cat <<EOI >=buildfile;
- foo: bar
- {{
- cp $path($<) $path($>)
- }}
- EOI
+ cat <<EOI >=buildfile;
+ foo: bar
+ {{
+ cp $path($<) $path($>)
+ }}
+ EOI
- $* 2>'cp file{foo}';
+ $* 2>'cp file{bar} -> file{foo}';
- cat <<<foo >'bar';
+ cat <<<foo >'bar';
- # While at it, make sure there is no rebuild.
- #
- $* 2>/'info: dir{./} is up to date';
+ # While at it, make sure there is no rebuild.
+ #
+ $* 2>/'info: dir{./} is up to date';
- $* clean 2>-
+ $* clean 2>-
+ }
+
+ : error
+ :
+ : Test that the target file is removed on error and is created on subsequent
+ : successful update.
+ :
+ {
+ echo 'bar' >=bar;
+
+ cat <<EOI >=buildfile;
+ foo: bar
+ {{
+ diag concat $<
+
+ t = $path($>)
+ p = $path($<)
+
+ cp $p $t
+
+ cat $(p).baz >>$t
+ }}
+ EOI
+
+ $* 2>>~%EOE% != 0;
+ concat file{bar}
+ %cat: unable to print '.+bar.baz': .+%
+ buildfile:10:3: error: builtin cat exited with code 1
+ %.+
+ EOE
+
+ test -f foo != 0;
+
+ echo 'baz' >=bar.baz;
+
+ $* 2>'concat file{bar}';
+
+ cat <<<foo >>EOO;
+ bar
+ baz
+ EOO
+
+ $* clean 2>-
+ }
+
+ : mutual-redirects
+ :
+ {
+ echo 'bar' >=bar;
+
+ cat <<EOI >=buildfile;
+ foo: bar
+ % [diag=cp]
+ {{
+ echo 'copying' 2>&1
+ cp $path($<) $path($>)
+ }}
+ EOI
+
+ $* 2>>~%EOE% != 0;
+ cp file{bar} -> file{foo}
+ buildfile:4:3: error: stdout and stderr redirected to each other
+ %.+
+ EOE
+
+ $* clean 2>-
+ }
+
+ : computed-var
+ :
+ {
+ cat <<EOI >=buildfile;
+ a = a
+ b = b
+ foo:
+ {{
+ x = true
+ echo "$($x ? a : b)" >$path($>)
+ }}
+ EOI
+
+ $* 2>>EOE != 0
+ buildfile:6:10: error: expansion of computed variable is only allowed in depdb preamble
+ info: consider using 'depdb' builtin to track its value changes
+ EOE
+ }
+
+ : untracked-var
+ :
+ {
+ cat <<EOI >=buildfile;
+ a = a
+ b = b
+ foo:
+ {{
+ x = true
+ y = $($x ? a : b)
+ depdb env BOGUS
+ echo $y >$path($>)
+ }}
+ EOI
+
+ $* 2>>~%EOE% != 0;
+ buildfile:6:8: error: use of untracked variable 'a'
+ info: use the 'depdb' builtin to manually track it
+ %.+
+ EOE
+
+ $* clean 2>-
+ }
+
+ : export
+ :
+ if $posix
+ {
+ cat <<EOI >=bar;
+ #!/bin/sh
+ echo "$message"
+ EOI
+
+ cat <<EOI >=buildfile;
+ exe{foo}: bar
+ {{
+ cp $path($<) $path($>)
+ }}
+ % test
+ {{
+ diag test $>
+ export message=text1
+ $> >>>?'text1'
+ env message=text2 -- $> >>>?'text2'
+ }}
+ EOI
+
+ $* test 2>>EOE;
+ cp file{bar} -> exe{foo}
+ test exe{foo}
+ EOE
+
+ $* clean 2>-
+ }
+
+ : diag
+ :
+ {
+ cat <<EOI >=buildfile;
+ foo:
+ {{
+ v1 = foo
+ echo bar | set v2
+ diag echo "$v1 $v2" -> $>
+ echo "$v1 $v2" >$path($>)
+ }}
+ EOI
+
+ $* 2>'echo foo bar -> file{foo}';
+ cat <<<foo >'foo bar';
+
+ $* clean 2>-
+ }
+
+ : depdb
+ :
+ {
+ : track-var-auto
+ :
+ {
+ echo 'bar' >=bar;
+
+ cat <<EOI >=buildfile;
+ s = $process.run(cat bar)
+ foo:
+ {{
+ echo "$s" >$path($>)
+ }}
+ EOI
+
+ $* 2>'echo file{foo}';
+ cat <<<foo >'bar';
+
+ $* 2>/'info: dir{./} is up to date';
+
+ echo 'baz' >=bar;
+
+ $* 2>'echo file{foo}';
+ cat <<<foo >'baz';
+
+ $* clean 2>-
+ }
+
+ : track-var-manual
+ :
+ {
+ echo 'bar' >=bar;
+ echo 'baz' >=baz;
+
+ cat <<EOI >=buildfile;
+ a = $process.run(cat baz)
+ foo: bar
+ {{
+ x = true
+ y = $($x ? a : b)
+ depdb hash "$a"
+
+ diag compose $>
+
+ cp $path($<) $path($>)
+
+ echo $y >>$path($>)
+ }}
+ EOI
+
+ $* 2>'compose file{foo}';
+
+ cat <<<foo >>EOO;
+ bar
+ baz
+ EOO
+
+ $* 2>/'info: dir{./} is up to date';
+
+ # Make sure that on filesystems with a low file timestamps resolution
+ # (for example HFS+) the file is considered as changed.
+ #
+ sleep 1;
+
+ echo 'BAR' >=bar;
+
+ $* 2>'compose file{foo}';
+
+ cat <<<foo >>EOO;
+ BAR
+ baz
+ EOO
+
+ $* 2>/'info: dir{./} is up to date';
+
+ echo 'BAZ' >=baz;
+
+ $* 2>'compose file{foo}';
+
+ cat <<<foo >>EOO;
+ BAR
+ BAZ
+ EOO
+
+ $* 2>/'info: dir{./} is up to date';
+
+ $* clean 2>-
+ }
+
+ : preamble
+ :
+ {
+ : valid
+ :
+ {
+ echo 'bar' >=bar;
+
+ cat <<EOI >=buildfile;
+ s = $process.run(cat bar)
+ foo:
+ {{
+ depdb clear
+
+ s1 = 'abc'
+ s2 = 'xyz'
+
+ if echo "$s" >>>? 'bar'
+ v = "$s1"
+ else
+ echo "$s2" | set v
+ end
+
+ depdb string "$v"
+
+ echo "$v" >$path($>)
+ }}
+ EOI
+
+ $* 2>'echo file{foo}';
+ cat <<<foo >'abc';
+
+ $* 2>/'info: dir{./} is up to date';
+
+ echo 'baz' >=bar;
+ $* 2>'echo file{foo}';
+ cat <<<foo >'xyz';
+
+ $* clean 2>-
+ }
+
+ : invalid
+ :
+ {
+ cat <<EOI >=buildfile;
+ foo:
+ {{
+ v = 'abc'
+ echo "$v" >$path($>)
+ depdb string "$v"
+ }}
+ EOI
+
+ $* 2>>~%EOE% != 0;
+ buildfile:4:3: error: disallowed command in depdb preamble
+ info: only variable assignments are allowed in depdb preamble
+ buildfile:5:3: info: depdb preamble ends here
+ %.+
+ EOE
+
+ $* clean 2>-
+ }
+
+ : temp-dir
+ :
+ {
+ cat <<EOI >=buildfile;
+ foo:
+ {{
+ touch $~/f | set dummy
+
+ if test -f $~/f
+ v = "yes"
+ else
+ v = "no"
+ end
+
+ depdb string "$v"
+ diag echo $>
+
+ test -f $~/f
+ echo "$v" >$path($>)
+ }}
+ EOI
+
+ $* 2>'echo file{foo}';
+
+ $* clean 2>-
+ }
+ }
+
+ : string
+ :
+ {
+ echo 'bar' >=bar;
+
+ cat <<EOI >=buildfile;
+ s = $process.run(cat bar)
+ foo:
+ {{
+ depdb clear
+ depdb string "$s"
+ echo "$s" >$path($>)
+ }}
+ EOI
+
+ $* 2>'echo file{foo}';
+ cat <<<foo >'bar';
+
+ $* 2>/'info: dir{./} is up to date';
+
+ echo 'baz' >=bar;
+
+ $* 2>'echo file{foo}';
+ cat <<<foo >'baz';
+
+ $* clean 2>-
+ }
+
+ : hash
+ :
+ {
+ echo 'bar' >=bar;
+
+ cat <<EOI >=buildfile;
+ s = $process.run(cat bar)
+ foo:
+ {{
+ depdb clear
+ depdb hash "$s"
+ echo "$s" >$path($>)
+ }}
+ EOI
+
+ $* 2>'echo file{foo}';
+ cat <<<foo >'bar';
+
+ $* 2>/'info: dir{./} is up to date';
+
+ echo 'baz' >=bar;
+
+ $* 2>'echo file{foo}';
+ cat <<<foo >'baz';
+
+ $* clean 2>-
+ }
+
+ : env
+ :
+ {
+ : invalid
+ :
+ {
+ cat <<EOI >=buildfile;
+ foo:
+ {{
+ s = $getenv(FOO)
+
+ depdb clear
+ depdb env FOO=bar
+ echo "$s" >$path($>)
+ }}
+ EOI
+
+ $* 2>>/EOE != 0;
+ buildfile:6:3: error: invalid 'depdb env' argument: invalid variable name 'FOO=bar': contains '='
+ info: while updating file{foo}
+ info: while updating dir{./}
+ info: failed to update dir{./}
+ EOE
+
+ $* clean 2>-
+ }
+
+ : valid
+ :
+ {
+ cat <<EOI >=buildfile;
+ foo:
+ {{
+ s = $getenv(FOO)
+
+ depdb clear
+ depdb env FOO
+ echo "$s" >$path($>)
+ }}
+ EOI
+
+ export FOO=foo;
+
+ $* 2>'echo file{foo}';
+ cat <<<foo >'foo';
+
+ $* 2>/'info: dir{./} is up to date';
+
+ export FOO=bar;
+
+ $* 2>'echo file{foo}';
+ cat <<<foo >'bar';
+
+ export -u FOO;
+
+ $* 2>'echo file{foo}';
+ cat <<<foo >'';
+
+ $* clean 2>-
+ }
+ }
+
+ : dyndep
+ :
+ {
+ : normal
+ :
+ {
+ cat <<EOI >=bar.h;
+ bar
+ EOI
+
+ cat <<EOI >=buildfile;
+ define h: file
+ h{*}: extension = h
+
+ ./: h{foo baz}
+
+ h{foo}:
+ {{
+ # Note that strictly speaking we should return $out_base/baz.h
+ # on the second invocation (since it now exists). But our dyndep
+ # machinery skips the entry which it has already seen, so this
+ # works for now.
+ #
+ depdb dyndep "-I$out_base" --what=header --default-type=h -- \
+ echo "$out_base/foo.h: $src_base/bar.h baz.h"
+
+ diag gen $>
+
+ cat $path($<) >$path($>)
+ }}
+
+ h{baz}:
+ {{
+ diag gen $>
+ echo baz >$path($>)
+ }}
+ EOI
+
+ $* 2>>EOE;
+ gen h{baz}
+ gen h{foo}
+ EOE
+
+ cat foo.h >>EOO;
+ bar
+ baz
+ EOO
+
+ $* clean 2>-
+ }
+
+ : byproduct
+ :
+ {
+ cat <<EOI >=bar.h;
+ bar
+ EOI
+
+ cat <<EOI >=buildfile;
+ define h: file
+ h{*}: extension = h
+
+ h{foo}: h{baz}
+ {{
+ o = $path($>)
+ t = $path($>).t
+
+ depdb dyndep --byproduct --what=header --default-type=h --file $t
+
+ diag gen $>
+ cat $src_base/bar.h $out_base/baz.h >$o
+ echo "$out_base/foo.h: $src_base/bar.h $out_base/baz.h" >$t
+ }}
+
+ h{baz}:
+ {{
+ diag gen $>
+ echo baz >$path($>)
+ }}
+ EOI
+
+ $* 2>>EOE;
+ gen h{baz}
+ gen h{foo}
+ EOE
+
+ cat foo.h >>EOO;
+ bar
+ baz
+ EOO
+
+ $* clean 2>-
+ }
+ }
+ }
}
: clean
@@ -65,25 +625,98 @@
: test
:
{
- echo 'bar' >=bar;
+ : success
+ :
+ {
+ echo 'bar' >=bar;
- cat <<EOI >=buildfile;
- foo: bar
- {{
- cp $path($<) $path($>)
- }}
- % [diag=test] test
- {{
- cat <$path($<) >?$path($>)
- }}
- EOI
+ cat <<EOI >=buildfile;
+ foo: bar
+ {{
+ cp $path($<) $path($>)
+ }}
+ % [diag=test] test
+ {{
+ cat <$path($>) >?$path($<)
+ }}
+ EOI
- $* test 2>>EOE;
- cp file{foo}
- test file{foo}
- EOE
+ $* test 2>>EOE;
+ cp file{bar} -> file{foo}
+ test file{foo}
+ EOE
- $* clean 2>-
+ $* clean 2>-
+ }
+
+ : depdb
+ :
+ {
+ echo 'bar' >=bar;
+
+ cat <<EOI >=buildfile;
+ foo: bar
+ {{
+ cp $path($<) $path($>)
+ }}
+ % [diag=test] test
+ {{
+ depdb clear
+ cat <$path($>) >?$path($<)
+ }}
+ EOI
+
+ $* test 2>>EOE != 0
+ buildfile:7:3: error: 'depdb' builtin cannot be used to perform test
+ EOE
+ }
+
+ : runner
+ :
+ if $posix
+ {
+ echo 'bar' >=bar;
+
+ cat <<EOI >=run;
+ #!/bin/sh
+ if test "$1" = "--trace"; then
+ shift
+ echo "$*"
+ fi
+ "$@"
+ EOI
+
+ chmod u+x run;
+
+ cat <<EOI >=buildfile;
+ foo: bar
+ {{
+ cp $path($<) $path($>)
+ }}
+ % [diag=test] test
+ {{
+ if ($test.runner.path != [null])
+ $test.runner.path $test.runner.options cat <$path($>)
+ else
+ cat <$path($>)
+ end
+ }}
+ EOI
+
+ $* test 2>>EOE;
+ cp file{bar} -> file{foo}
+ test file{foo}
+ bar
+ EOE
+
+ $* test config.test.runner="./run --trace" 2>>EOE;
+ test file{foo}
+ cat
+ bar
+ EOE
+
+ $* clean 2>-
+ }
}
: diff-label
@@ -107,3 +740,1092 @@
$* clean 2>-
}
+
+: canned-cmdline
+:
+{
+ cat <<EOI >=buildfile;
+ ./:
+ {{
+ x = echo >|
+ y = [cmdline] echo >|
+ diag update $>
+ $x foo
+ $y bar
+ ([cmdline] $x) baz
+ }}
+ EOI
+
+ $* >> EOO 2>>/EOE
+ bar
+ baz
+ EOO
+ update dir{./}
+ >| foo
+ EOE
+}
+
+: timeout
+:
+if $posix
+{
+ : update
+ :
+ {
+ : expired
+ :
+ {
+ echo 'bar' >=bar;
+
+ cat <<EOI >=buildfile;
+ foo: bar
+ % [diag=update]
+ {{
+ cp $path($<) $path($>)
+ timeout 1
+ ^sleep 5
+ }}
+ EOI
+
+ $* 2>>~%EOE% != 0;
+ update file{bar} -> file{foo}
+ buildfile:6:3: error: process ^sleep terminated: execution timeout expired
+ info: command line: sleep 5
+ info: while updating file{foo}
+ %.+
+ EOE
+
+ $* clean 2>-
+ }
+
+ : successful-timeout
+ :
+ {
+ echo 'bar' >=bar;
+
+ cat <<EOI >=buildfile;
+ foo: bar
+ % [diag=update]
+ {{
+ cp $path($<) $path($>)
+ timeout --success 1
+ ^sleep 5
+ }}
+ EOI
+
+ $* 2>>EOE;
+ update file{bar} -> file{foo}
+ EOE
+
+ $* clean 2>-
+ }
+ }
+
+ : test
+ :
+ {
+ : expired
+ :
+ {
+ echo 'bar' >=bar;
+
+ cat <<EOI >=buildfile;
+ foo: bar
+ {{
+ cp $path($<) $path($>)
+ }}
+ % [diag=test] test
+ {{
+ ^sleep 5
+ }}
+ EOI
+
+ $* test config.test.timeout=1 2>>~%EOE% != 0;
+ cp file{bar} -> file{foo}
+ test file{foo}
+ buildfile:7:3: error: process ^sleep terminated: execution timeout expired
+ info: command line: sleep 5
+ info: while testing file{foo}
+ %.+
+ EOE
+
+ $* test config.test.timeout=/1 2>>~%EOE% != 0;
+ test file{foo}
+ buildfile:7:3: error: process ^sleep terminated: execution timeout expired
+ info: command line: sleep 5
+ info: while testing file{foo}
+ %.+
+ EOE
+
+ $* clean 2>-
+ }
+
+ : not-expired
+ :
+ {
+ echo 'bar' >=bar;
+
+ cat <<EOI >=buildfile;
+ foo: bar
+ % [diag=cp]
+ {{
+ ^sleep 4
+ cp $path($<) $path($>)
+ }}
+ % [diag=test] test
+ {{
+ ^sleep 1
+ }}
+ EOI
+
+ $* test config.test.timeout=3 2>>EOE;
+ cp file{bar} -> file{foo}
+ test file{foo}
+ EOE
+
+ $* clean 2>-
+ }
+ }
+}
+
+# @@ TODO: test $1 when implemented.
+#
+: rule
+:
+{
+ cat <<EOI >=buildfile;
+ alias{far}: alias{bar}
+ alias{bar}:
+
+ alias{~'/f(.+)/'}: alias{~'/b\1/'}
+ {{
+ diag frob $< -> $>
+ }}
+ EOI
+
+ $* 2>>EOE
+ frob alias{bar} -> alias{far}
+ EOE
+}
+
+: loop
+:
+{
+ : while
+ :
+ {
+ : basics
+ :
+ {
+ echo 'bar' >=bar;
+
+ cat <<EOI >=buildfile;
+ foo: bar
+ {{
+ p = $path($>)
+ while test -f $p != 0
+ cp $path($<) $p
+ end
+ }}
+ EOI
+
+ $* 2>'cp file{bar} -> file{foo}';
+
+ cat <<<foo >'bar';
+
+ $* clean 2>-
+ }
+
+ : exit
+ :
+ {
+ echo 'bar' >=bar;
+
+ cat <<EOI >=buildfile;
+ foo: bar
+ {{
+ diag gen ($>)
+
+ p = $path($>)
+ while test -f $p != 0
+ touch $p
+ exit
+ cp $path($<) $p
+ end
+ }}
+ EOI
+
+ $* 2>'gen file{foo}';
+
+ cat <<<foo >:'';
+
+ $* clean 2>-
+ }
+
+ : error
+ :
+ {
+ echo 'bar' >=bar;
+
+ cat <<EOI >=buildfile;
+ foo: bar
+ {{
+ diag gen ($>)
+
+ p = $path($>)
+ while test -f $p != 0
+ touch $p
+ exit 'fed up'
+ cp $path($<) $p
+ end
+ }}
+ EOI
+
+ $* 2>>~%EOE% != 0;
+ gen file{foo}
+ buildfile:8:5: error: fed up
+ %.{3}
+ EOE
+
+ $* clean 2>-
+ }
+
+ : depdb
+ :
+ {
+ : inside
+ :
+ {
+ echo 'bar' >=bar;
+
+ cat <<EOI >=buildfile;
+ foo: bar
+ {{
+ p = $path($>)
+ while test -f $p != 0
+ depdb hash $p
+ cp $path($<) $p
+ end
+ }}
+ EOI
+
+ $* 2>>EOE != 0
+ buildfile:5:5: error: 'depdb' call inside flow control construct
+ EOE
+ }
+
+ : after-commands
+ :
+ {
+ echo 'bar' >=bar;
+
+ cat <<EOI >=buildfile;
+ foo: bar
+ {{
+ p = $path($>)
+ while test -f $p != 0
+ cp $path($<) $p
+ end
+
+ depdb hash $p
+ }}
+ EOI
+
+ $* 2>>~%EOE% != 0;
+ buildfile:5:5: error: disallowed command in depdb preamble
+ info: only variable assignments are allowed in depdb preamble
+ buildfile:8:3: info: depdb preamble ends here
+ %.{3}
+ EOE
+
+ $* clean 2>-
+ }
+
+ : after-vars
+ :
+ {
+ echo 'bar' >=bar;
+
+ cat <<EOI >=buildfile;
+ foo: bar
+ {{
+ p = $path($<)
+
+ h =
+ while test -f $p != 0
+ h += $p
+ end
+
+ depdb hash $p
+
+ cat $p >$path($>)
+ }}
+ EOI
+
+ $* 2>'cat file{bar} -> file{foo}';
+ $* clean 2>-
+ }
+ }
+ }
+
+ : for
+ :
+ {
+ : form-1
+ :
+ : for x: ...
+ :
+ {
+ : basics
+ :
+ {
+ echo 'bar' >=bar;
+ echo 'baz' >=baz;
+
+ cat <<EOI >=buildfile;
+ foo: bar baz
+ {{
+ p = $path($>)
+ rm -f $p
+
+ for f: $<
+ cat $path($f) >>$p
+ end
+ }}
+ EOI
+
+ $* 2>'cat file{bar} -> file{foo}';
+
+ cat <<<foo >>EOO;
+ bar
+ baz
+ EOO
+
+ $* clean 2>-
+ }
+
+ : pair
+ :
+ {
+ mkdir -p src/build;
+ echo 'bar' >=src/bar;
+ echo 'baz' >=src/baz;
+
+ echo 'project =' >=src/build/bootstrap.build;
+
+ cat <<EOI >=src/buildfile;
+ foo: file{bar}@./ file{baz}@./
+ {{
+ p = $path($>)
+ rm -f $p
+
+ for f: $<
+ cat $path($f) >>$p
+ end
+ }}
+ EOI
+
+ $* src/@out/ 2>>/EOE;
+ mkdir fsdir{out/}
+ cat src/file{bar} -> out/file{foo}
+ EOE
+
+ cat <<<out/foo >>EOO;
+ bar
+ baz
+ EOO
+
+ $* 'clean:' src/@out/ 2>-
+ }
+
+ : special-var
+ :
+ {
+ echo 'bar' >=bar;
+ echo 'baz' >=baz;
+
+ cat <<EOI >=buildfile;
+ foo: bar
+ {{
+ p = $path($>)
+ rm -f $p
+
+ for ~: $<
+ cat $path($f) >>$p
+ end
+ }}
+ EOI
+
+ $* 2>>EOE != 0
+ buildfile:6:7: error: attempt to set '~' special variable
+ EOE
+ }
+
+ : exit
+ :
+ {
+ echo 'bar' >=bar;
+ echo 'baz' >=baz;
+
+ cat <<EOI >=buildfile;
+ foo: bar
+ {{
+ p = $path($>)
+ rm -f $p
+
+ for f: $<
+ cat $path($f) >>$p
+ exit
+ end
+ }}
+ EOI
+
+ $* 2>'cat file{bar} -> file{foo}';
+
+ cat <<<foo >>EOO;
+ bar
+ EOO
+
+ $* clean 2>-
+ }
+
+ : error
+ :
+ {
+ echo 'bar' >=bar;
+ echo 'baz' >=baz;
+
+ cat <<EOI >=buildfile;
+ foo: bar
+ {{
+ p = $path($>)
+ rm -f $p
+
+ for f: $<
+ cat $path($f) >>$p
+ exit 'fed up'
+ end
+ }}
+ EOI
+
+ $* 2>>~%EOE% != 0;
+ cat file{bar} -> file{foo}
+ buildfile:8:5: error: fed up
+ %.{3}
+ EOE
+
+ $* clean 2>-
+ }
+
+ : depdb
+ :
+ {
+ : inside
+ :
+ {
+ echo 'bar' >=bar;
+
+ cat <<EOI >=buildfile;
+ foo: bar
+ {{
+ for f: $<
+ depdb hash $f
+ end
+
+ p = $path($>)
+ rm -f $p
+
+ for f: $<
+ cat $path($f) >>$p
+ end
+ }}
+ EOI
+
+ $* 2>>EOE != 0
+ buildfile:4:5: error: 'depdb' call inside flow control construct
+ EOE
+ }
+
+ : after-commands
+ :
+ {
+ echo 'bar' >=bar;
+
+ cat <<EOI >=buildfile;
+ foo: bar
+ {{
+ for f: $<
+ echo $path($f) >-
+ end
+
+ depdb hash a
+ }}
+ EOI
+
+ $* 2>>~%EOE% != 0;
+ buildfile:4:5: error: disallowed command in depdb preamble
+ info: only variable assignments are allowed in depdb preamble
+ buildfile:7:3: info: depdb preamble ends here
+ %.{3}
+ EOE
+
+ $* clean 2>-
+ }
+
+ : after-vars
+ :
+ {
+ echo 'bar' >=bar;
+
+ cat <<EOI >=buildfile;
+ foo: bar
+ {{
+ h =
+ for f: $<
+ h += $path($f)
+ end
+
+ depdb hash $h
+
+ p = $path($>)
+ rm -f $p
+
+ for f: $<
+ cat $path($f) >>$p
+ end
+ }}
+ EOI
+
+ $* 2>'cat file{bar} -> file{foo}';
+ $* clean 2>-
+ }
+ }
+ }
+
+ : form-2
+ :
+ : ... | for x
+ :
+ {
+ : basics
+ :
+ {
+ echo 'bar' >=bar;
+ echo 'baz' >=baz;
+
+ cat <<EOI >=buildfile;
+ foo: bar baz
+ {{
+ diag gen ($>)
+
+ p = $path($>)
+ rm -f $p
+
+ echo $path($<) | for -w f
+ cat $f >>$p
+ end
+ }}
+ EOI
+
+ $* 2>'gen file{foo}';
+
+ cat <<<foo >>EOO;
+ bar
+ baz
+ EOO
+
+ $* clean 2>-
+ }
+
+ : special-var
+ :
+ {
+ echo 'bar' >=bar;
+ echo 'baz' >=baz;
+
+ cat <<EOI >=buildfile;
+ foo: bar
+ {{
+ diag gen ($>)
+
+ p = $path($>)
+ rm -f $p
+
+ echo $path($<) | for ~
+ cat $f >>$p
+ end
+ }}
+ EOI
+
+ $* 2>>~%EOE% != 0;
+ gen file{foo}
+ buildfile:8:3: error: attempt to set '~' special variable
+ %.{3}
+ EOE
+
+ $* clean 2>-
+ }
+
+ : misuse
+ :
+ {
+ : after-var
+ {
+ echo 'bar' >=bar;
+ echo 'baz' >=baz;
+
+ cat <<EOI >=buildfile;
+ foo: bar
+ {{
+ diag gen ($>)
+
+ p = $path($>)
+ rm -f $p
+
+ echo $path($<) | for x:
+ cat $f >>$p
+ end
+ }}
+ EOI
+
+ $* 2>>~%EOE% != 0;
+ gen file{foo}
+ buildfile:8:3: error: for: ':' after variable name
+ %.+
+ EOE
+
+ $* clean 2>-
+ }
+
+ : after-attrs
+ {
+ echo 'bar' >=bar;
+ echo 'baz' >=baz;
+
+ cat <<EOI >=buildfile;
+ foo: bar
+ {{
+ diag gen ($>)
+
+ p = $path($>)
+ rm -f $p
+
+ echo $path($<) | for x [path]:
+ cat $f >>$p
+ end
+ }}
+ EOI
+
+ $* 2>>~%EOE% != 0;
+ gen file{foo}
+ <attributes>:1:7: error: whitespace required after attributes
+ <attributes>:1:1: info: use the '\[' escape sequence if this is a wildcard pattern
+ buildfile:8:3: info: while parsing attributes '[path]:'
+ %.+
+ EOE
+
+ $* clean 2>-
+ }
+ }
+
+ : exit
+ :
+ {
+ echo 'bar' >=bar;
+ echo 'baz' >=baz;
+
+ cat <<EOI >=buildfile;
+ foo: bar
+ {{
+ diag gen ($>)
+
+ p = $path($>)
+ rm -f $p
+
+ echo $path($<) | for -w f
+ cat $f >>$p
+ exit
+ end
+ }}
+ EOI
+
+ $* 2>'gen file{foo}';
+
+ cat <<<foo >>EOO;
+ bar
+ EOO
+
+ $* clean 2>-
+ }
+
+ : error
+ :
+ {
+ echo 'bar' >=bar;
+ echo 'baz' >=baz;
+
+ cat <<EOI >=buildfile;
+ foo: bar
+ {{
+ diag gen ($>)
+
+ p = $path($>)
+ rm -f $p
+
+ echo $path($<) | for -w f
+ cat $f >>$p
+ exit 'fed up'
+ end
+ }}
+ EOI
+
+ $* 2>>~%EOE% != 0;
+ gen file{foo}
+ buildfile:10:5: error: fed up
+ %.{3}
+ EOE
+
+ $* clean 2>-
+ }
+
+ : depdb
+ :
+ {
+ : inside
+ :
+ {
+ echo 'bar' >=bar;
+
+ cat <<EOI >=buildfile;
+ foo: bar
+ {{
+ echo $path($<) | for -w f
+ depdb hash $f
+ end
+
+ p = $path($>)
+ rm -f $p
+
+ echo $path($<) | for -w f
+ cat $f >>$p
+ end
+ }}
+ EOI
+
+ $* 2>>EOE != 0
+ buildfile:4:5: error: 'depdb' call inside flow control construct
+ EOE
+ }
+
+ : after-commands
+ :
+ {
+ echo 'bar' >=bar;
+
+ cat <<EOI >=buildfile;
+ foo: bar
+ {{
+ echo $path($<) | for -w f
+ echo $f >-
+ end
+
+ depdb hash $p
+ }}
+ EOI
+
+ $* 2>>~%EOE% != 0;
+ buildfile:4:5: error: disallowed command in depdb preamble
+ info: only variable assignments are allowed in depdb preamble
+ buildfile:7:3: info: depdb preamble ends here
+ %.{3}
+ EOE
+
+ $* clean 2>-
+ }
+
+ : after-vars
+ :
+ {
+ echo 'bar' >=bar;
+
+ cat <<EOI >=buildfile;
+ foo: bar
+ {{
+ h =
+ echo $path($<) | for -w f
+ h += $f
+ end
+
+ depdb hash $h
+
+ diag gen ($>)
+
+ p = $path($>)
+ rm -f $p
+
+ for f: $<
+ cat $path($f) >>$p
+ end
+ }}
+ EOI
+
+ $* 2>'gen file{foo}';
+ $* clean 2>-
+ }
+ }
+ }
+
+ : form-3
+ :
+ : for x <...
+ :
+ {
+ : basics
+ :
+ {
+ echo 'bar' >=bar;
+ echo 'baz' >=baz;
+
+ cat <<EOI >=buildfile;
+ foo: bar baz
+ {{
+ diag gen ($>)
+
+ p = $path($>)
+ rm -f $p
+
+ for -w f <<"EOF"
+ $path($<)
+ EOF
+ cat $f >>$p
+ end
+
+ for <<"EOF" -w f
+ $path($<)
+ EOF
+ cat $f >>$p
+ end
+ }}
+ EOI
+
+ $* 2>'gen file{foo}';
+
+ cat <<<foo >>EOO;
+ bar
+ baz
+ bar
+ baz
+ EOO
+
+ $* clean 2>-
+ }
+
+ : quoting
+ :
+ {
+ echo 'bar' >=bar;
+ echo 'baz' >=baz;
+
+ cat <<EOI >=buildfile;
+ foo: bar baz
+ {{
+ n = 'gen'
+ diag "($n)" ($>)
+
+ p = $path($>)
+ rm -f $p
+
+ o = -w
+ for "$o" f <<"EOF"
+ $path($<)
+ EOF
+ cat $f >>$p
+ end
+
+ o = -n
+ for "($o)" f <<"EOF"
+ $path($<)
+ EOF
+ echo $f >>$p
+ end
+ }}
+ EOI
+
+ $* 2>'gen file{foo}';
+
+ cat <<<foo >>~%EOO%;
+ bar
+ baz
+ %.+bar .+baz%
+ EOO
+
+ $* clean 2>-
+ }
+
+ : special-var
+ :
+ {
+ echo 'bar' >=bar;
+ echo 'baz' >=baz;
+
+ cat <<EOI >=buildfile;
+ foo: bar
+ {{
+ p = $path($>)
+ rm -f $p
+
+ for ~ <<<$path($<)
+ cat $f >>$p
+ end
+ }}
+ EOI
+
+ $* 2>>EOE != 0
+ buildfile:6:6: error: attempt to set '~' special variable
+ EOE
+ }
+
+ : exit
+ :
+ {
+ echo 'bar' >=bar;
+ echo 'baz' >=baz;
+
+ cat <<EOI >=buildfile;
+ foo: bar
+ {{
+ p = $path($>)
+ rm -f $p
+
+ for f <<<$path($<)
+ cat $f >>$p
+ exit
+ end
+ }}
+ EOI
+
+ $* 2>'cat file{bar} -> file{foo}';
+
+ cat <<<foo >>EOO;
+ bar
+ EOO
+
+ $* clean 2>-
+ }
+
+ : error
+ :
+ {
+ echo 'bar' >=bar;
+ echo 'baz' >=baz;
+
+ cat <<EOI >=buildfile;
+ foo: bar
+ {{
+ p = $path($>)
+ rm -f $p
+
+ for f <<<$path($<)
+ cat $f >>$p
+ exit 'fed up'
+ end
+ }}
+ EOI
+
+ $* 2>>~%EOE% != 0;
+ cat file{bar} -> file{foo}
+ buildfile:8:5: error: fed up
+ %.{3}
+ EOE
+
+ $* clean 2>-
+ }
+
+ : depdb
+ :
+ {
+ : inside
+ :
+ {
+ echo 'bar' >=bar;
+
+ cat <<EOI >=buildfile;
+ foo: bar
+ {{
+ for -w f <<<$path($<)
+ depdb hash $f
+ end
+
+ p = $path($>)
+ rm -f $p
+
+ echo $path($<) | for -w f
+ cat $f >>$p
+ end
+ }}
+ EOI
+
+ $* 2>>EOE != 0
+ buildfile:4:5: error: 'depdb' call inside flow control construct
+ EOE
+ }
+
+ : after-commands
+ :
+ {
+ echo 'bar' >=bar;
+
+ cat <<EOI >=buildfile;
+ foo: bar
+ {{
+ for -w f <<<$path($<)
+ echo $f >-
+ end
+
+ depdb hash a
+ }}
+ EOI
+
+ $* 2>>~%EOE% != 0;
+ buildfile:4:5: error: disallowed command in depdb preamble
+ info: only variable assignments are allowed in depdb preamble
+ buildfile:7:3: info: depdb preamble ends here
+ %.{3}
+ EOE
+
+ $* clean 2>-
+ }
+
+ : after-vars
+ :
+ {
+ echo 'bar' >=bar;
+
+ cat <<EOI >=buildfile;
+ foo: bar
+ {{
+ h =
+ for -w f <<<$path($<)
+ h += $f
+ end
+
+ depdb hash $h
+
+ diag gen ($>)
+
+ p = $path($>)
+ rm -f $p
+
+ for f: $<
+ cat $path($f) >>$p
+ end
+ }}
+ EOI
+
+ $* 2>'gen file{foo}';
+ $* clean 2>-
+ }
+ }
+ }
+ }
+}