aboutsummaryrefslogtreecommitdiff
path: root/tests/test
diff options
context:
space:
mode:
Diffstat (limited to 'tests/test')
-rw-r--r--tests/test/config-test/driver.cxx3
-rw-r--r--tests/test/script/builtin/sleep.testscript18
-rw-r--r--tests/test/script/common.testscript4
-rw-r--r--tests/test/script/runner/cleanup.testscript6
-rw-r--r--tests/test/script/runner/driver.cxx158
-rw-r--r--tests/test/script/runner/env.testscript63
-rw-r--r--tests/test/script/runner/exit.testscript2
-rw-r--r--tests/test/script/runner/export.testscript138
-rw-r--r--tests/test/script/runner/expr.testscript2
-rw-r--r--tests/test/script/runner/for.testscript502
-rw-r--r--tests/test/script/runner/pipe.testscript22
-rw-r--r--tests/test/script/runner/redirect.testscript4
-rw-r--r--tests/test/script/runner/set.testscript353
-rw-r--r--tests/test/script/runner/status.testscript8
-rw-r--r--tests/test/script/runner/test-runner.testscript57
-rw-r--r--tests/test/script/runner/timeout.testscript521
-rw-r--r--tests/test/script/runner/while.testscript16
-rw-r--r--tests/test/simple/generated/buildfile3
-rw-r--r--tests/test/simple/generated/driver.cxx51
-rw-r--r--tests/test/simple/generated/testscript205
20 files changed, 2022 insertions, 114 deletions
diff --git a/tests/test/config-test/driver.cxx b/tests/test/config-test/driver.cxx
index 5902854..7ea10e7 100644
--- a/tests/test/config-test/driver.cxx
+++ b/tests/test/config-test/driver.cxx
@@ -3,6 +3,9 @@
#include <iostream>
+#undef NDEBUG
+#include <cassert>
+
using namespace std;
int
diff --git a/tests/test/script/builtin/sleep.testscript b/tests/test/script/builtin/sleep.testscript
index 21ed07b..c044027 100644
--- a/tests/test/script/builtin/sleep.testscript
+++ b/tests/test/script/builtin/sleep.testscript
@@ -6,3 +6,21 @@
: success
:
$c <'sleep 1' && $b
+
+: timeout
+:
+{
+ : failure
+ :
+ $c <'env -t 1 -- sleep 86400' && $b 2>>~%EOE% != 0
+ %testscript:.*: error: builtin sleep terminated: execution timeout expired%
+ %.
+ EOE
+
+ : success
+ :
+ $c <<EOI && $b
+ timeout --success 1;
+ sleep 86400
+ EOI
+}
diff --git a/tests/test/script/common.testscript b/tests/test/script/common.testscript
index 4469d1c..651e056 100644
--- a/tests/test/script/common.testscript
+++ b/tests/test/script/common.testscript
@@ -31,7 +31,7 @@ end
# Note that the buildfile is clever hack that relies on the first target
# automatically becoming dir{./}'s prerequisite.
#
-c = cat >=testscript
-b = $0 --no-default-options --serial-stop --quiet --buildfile - test \
+c = [cmdline] cat >=testscript
+b = [cmdline] $0 --no-default-options --serial-stop --quiet --buildfile - test \
<"'testscript{testscript}: \$target'" \
&?test/***
diff --git a/tests/test/script/runner/cleanup.testscript b/tests/test/script/runner/cleanup.testscript
index 03153e4..4638982 100644
--- a/tests/test/script/runner/cleanup.testscript
+++ b/tests/test/script/runner/cleanup.testscript
@@ -75,7 +75,7 @@ b += --no-column
: Test cleanup of a directory as a file.
:
$c <'$* -d a &a' && $b 2>>/~%EOE% != 0
- %error: unable to remove file test/1/a: .+%
+ %testscript:1: error: unable to remove file test/1/a: .+%
info: test id: 1
EOE
}
@@ -161,7 +161,7 @@ b += --no-column
: Test cleanup of a file as a directory.
:
$c <'$* -f a &a/' && $b 2>>/~%EOE% != 0
- %error: unable to remove directory test/1/a/: .+%
+ %testscript:1: error: unable to remove directory test/1/a/: .+%
info: test id: 1
EOE
}
@@ -240,7 +240,7 @@ b += --no-column
: Test cleanup of a file as a wildcard.
:
$c <'$* -f a &a/***' && $b 2>>/~%EOE% != 0
- %error: unable to remove directory test/1/a/: .*%
+ %testscript:1: error: unable to remove directory test/1/a/: .*%
info: test id: 1
EOE
}
diff --git a/tests/test/script/runner/driver.cxx b/tests/test/script/runner/driver.cxx
index d5a74a4..b84f167 100644
--- a/tests/test/script/runner/driver.cxx
+++ b/tests/test/script/runner/driver.cxx
@@ -1,19 +1,29 @@
// file : tests/test/script/runner/driver.cxx -*- C++ -*-
// license : MIT; see accompanying LICENSE file
+#ifndef _WIN32
+# include <thread> // this_thread::sleep_for()
+# include <chrono>
+#else
+# include <libbutl/win32-utility.hxx>
+#endif
+
#include <limits> // numeric_limits
#include <string>
#include <cstdlib> // abort()
-#include <cassert>
#include <ostream> // endl, *bit
#include <istream> // istream::traits_type::eof()
#include <iostream>
#include <exception>
-#include <libbutl/path.mxx>
-#include <libbutl/optional.mxx>
-#include <libbutl/fdstream.mxx>
-#include <libbutl/filesystem.mxx>
+#include <libbutl/path.hxx>
+#include <libbutl/path-io.hxx>
+#include <libbutl/optional.hxx>
+#include <libbutl/fdstream.hxx>
+#include <libbutl/filesystem.hxx>
+
+#undef NDEBUG
+#include <cassert>
using namespace std;
using namespace butl;
@@ -36,10 +46,10 @@ main (int argc, char* argv[])
// Usage: driver [-i <int>] (-o <string>)* (-e <string>)* (-f <file>)*
// (-d <dir>)* (-v <name>)* [(-t (a|m|s|z)) | (-s <int>)]
//
- // Execute actions specified by -i, -o, -e, -f, -d, and -v options in the
- // order as they appear on the command line. After that terminate abnormally
- // if -t option is provided, otherwise exit normally with the status
- // specified by -s option (0 by default).
+ // Execute actions specified by -i, -o, -e, -f, -d, -w, -v, and -l options
+ // in the order as they appear on the command line. After that terminate
+ // abnormally if -t option is provided, otherwise exit normally with the
+ // status specified by -s option (0 by default).
//
// -i <fd>
// Forward stdin data to the standard stream denoted by the file
@@ -58,9 +68,15 @@ main (int argc, char* argv[])
// Create a directory with the path specified. Create parent directories
// if required.
//
+ // -w
+ // Print CWD to stdout.
+ //
// -v <name>
- // If the specified variable is set the print its value to stdout and the
- // string '<none>' otherwise.
+ // If the specified variable is set then print its value to stdout and
+ // the string '<none>' otherwise.
+ //
+ // -l <sec>
+ // Sleep the specified number of seconds.
//
// -t <method>
// Abnormally terminate itself using one of the following methods:
@@ -83,10 +99,7 @@ main (int argc, char* argv[])
for (int i (1); i < argc; ++i)
{
- string o (argv[i++]);
- assert (i < argc);
-
- string v (argv[i]);
+ string o (argv[i]);
auto toi = [] (const string& s) -> int
{
@@ -106,57 +119,80 @@ main (int argc, char* argv[])
return r;
};
- if (o == "-i")
+ if (o == "-w")
{
- assert (ifd == 3); // Make sure is not set yet.
-
- ifd = toi (v);
- assert (ifd >= 0 && ifd < 3);
+ cout << dir_path::current_directory () << endl;
+ }
+ else // Handle options other than flags.
+ {
+ ++i;
+ assert (i < argc);
+ string v (argv[i]);
- if (ifd == 0)
- cin.ignore (numeric_limits<streamsize>::max ());
- else if (cin.peek () != istream::traits_type::eof ())
+ if (o == "-i")
{
- ostream& o (ifd == 1 ? cout : cerr);
- o << cin.rdbuf ();
- o.flush ();
+ assert (ifd == 3); // Make sure is not set yet.
+
+ ifd = toi (v);
+ assert (ifd >= 0 && ifd < 3);
+
+ if (ifd == 0)
+ cin.ignore (numeric_limits<streamsize>::max ());
+ else if (cin.peek () != istream::traits_type::eof ())
+ {
+ ostream& o (ifd == 1 ? cout : cerr);
+ o << cin.rdbuf ();
+ o.flush ();
+ }
}
+ else if (o == "-o")
+ {
+ cout << v << endl;
+ }
+ else if (o == "-e")
+ {
+ cerr << v << endl;
+ }
+ else if (o == "-f")
+ {
+ ofdstream os (v);
+ os.close ();
+ }
+ else if (o == "-d")
+ {
+ try_mkdir_p (dir_path (v));
+ }
+ else if (o == "-v")
+ {
+ optional<string> var (getenv (v));
+ cout << (var ? *var : "<none>") << endl;
+ }
+ else if (o == "-l")
+ {
+ size_t t (toi (v));
+
+ // MinGW GCC 4.9 doesn't implement this_thread so use Win32 Sleep().
+ //
+#ifndef _WIN32
+ this_thread::sleep_for (chrono::seconds (t));
+#else
+ Sleep (static_cast<DWORD> (t * 1000));
+#endif
+ }
+ else if (o == "-t")
+ {
+ assert (aterm == '\0' && !status); // Make sure exit method is not set.
+ assert (v.size () == 1 && v.find_first_of ("amsz") != string::npos);
+ aterm = v[0];
+ }
+ else if (o == "-s")
+ {
+ assert (!status && aterm == '\0'); // Make sure exit method is not set.
+ status = toi (v);
+ }
+ else
+ assert (false);
}
- else if (o == "-o")
- {
- cout << v << endl;
- }
- else if (o == "-e")
- {
- cerr << v << endl;
- }
- else if (o == "-f")
- {
- ofdstream os (v);
- os.close ();
- }
- else if (o == "-d")
- {
- try_mkdir_p (dir_path (v));
- }
- else if (o == "-v")
- {
- optional<string> var (getenv (v));
- cout << (var ? *var : "<none>") << endl;
- }
- else if (o == "-t")
- {
- assert (aterm == '\0' && !status); // Make sure exit method is not set.
- assert (v.size () == 1 && v.find_first_of ("amsz") != string::npos);
- aterm = v[0];
- }
- else if (o == "-s")
- {
- assert (!status && aterm == '\0'); // Make sure exit method is not set.
- status = toi (v);
- }
- else
- assert (false);
}
switch (aterm)
diff --git a/tests/test/script/runner/env.testscript b/tests/test/script/runner/env.testscript
index 6fcedfa..512139a 100644
--- a/tests/test/script/runner/env.testscript
+++ b/tests/test/script/runner/env.testscript
@@ -3,5 +3,64 @@
.include ../common.testscript
-$c <'env abc=xyz -- $* -v abc >xyz' && $b : set
-$c <'env --unset=abc -- $* -v abc >"<none>"' && env abc=xyz -- $b : unset
+: cwd
+:
+{
+ : not-exist
+ :
+ $c <'env -c a -- $* -w' && $b 2>>/~%EOE% != 0
+ %testscript:1:1: error: specified working directory .+/a/ does not exist%
+ info: test id: 1
+ EOE
+
+ : process
+ :
+ $c <<EOI && $b
+ mkdir a;
+ env -c a -- $* -w >/~%.+/a%
+ EOI
+
+ : builtin
+ :
+ $c <<EOI && $b
+ mkdir a;
+ env -c a -- touch b;
+ test -f a/b
+ EOI
+
+ : absolute
+ :
+ $c <<EOI && $b
+ mkdir a;
+ env -c $~/a -- touch b;
+ test -f a/b
+ EOI
+}
+
+: variables
+:
+{
+ $c <'env abc=xyz -- $* -v abc >xyz' && $b : set
+ $c <'env --unset=abc -- $* -v abc >"<none>"' && env abc=xyz -- $b : unset
+}
+
+: timeout
+:
+{
+ : expired
+ :
+ $c <'env --timeout 1 -- $* -l 5' && $b 2>>~%EOE% != 0
+ %testscript:1:1: error: .+ terminated: execution timeout expired%
+ info: test id: 1
+ EOE
+
+ : not-expired
+ :
+ $c <'env --timeout 5 -- $* -l 1' && $b
+
+ : invalid
+ :
+ $c <'env --timeout a -- $*' && $b 2>>EOE != 0
+ testscript:1:15: error: env: invalid value 'a' for option '--timeout'
+ EOE
+}
diff --git a/tests/test/script/runner/exit.testscript b/tests/test/script/runner/exit.testscript
index 24e51fa..8d3f052 100644
--- a/tests/test/script/runner/exit.testscript
+++ b/tests/test/script/runner/exit.testscript
@@ -76,7 +76,7 @@ empty_id = ''
: unexpected
:
$c <'exit "foo" "bar"' && $b 2>>EOE != 0
- testscript:1:1: error: unexpected argument 'bar'
+ testscript:1:1: error: exit: unexpected argument 'bar'
info: test id: 1
EOE
}
diff --git a/tests/test/script/runner/export.testscript b/tests/test/script/runner/export.testscript
new file mode 100644
index 0000000..6ed7417
--- /dev/null
+++ b/tests/test/script/runner/export.testscript
@@ -0,0 +1,138 @@
+# file : tests/test/script/runner/export.testscript
+# license : MIT; see accompanying LICENSE file
+
+.include ../common.testscript
+
+# Make sure that the foo variable, which may potentially be set in the build2
+# environment, doesn't affect the tests.
+#
++export --unset foo
+
+: group
+:
+{
+ : add
+ :
+ $c <<EOI && $b
+ {
+ +export foo=bar
+
+ $* -v foo >'bar'
+ }
+ EOI
+
+ : change
+ :
+ $c <<EOI && $b
+ {
+ +export foo=bar
+ +export foo=baz
+
+ $* -v foo >'baz'
+ }
+ EOI
+
+ : remove
+ :
+ $c <<EOI && $b
+ {
+ +export foo=bar
+ +export --unset foo
+
+ $* -v foo >'<none>'
+ }
+ EOI
+
+ : clear
+ :
+ {
+ : added
+ :
+ $c <<EOI && $b
+ {
+ +export foo=bar
+ +export --clear foo
+
+ $* -v foo >'<none>'
+ }
+ EOI
+
+ : removed
+ :
+ $c <<EOI && $b
+ {
+ +export foo=bar
+ +export --unset foo
+ +export --clear foo
+
+ $* -v foo >'<none>'
+ }
+ EOI
+
+ : non-existent
+ :
+ $c <<EOI && $b
+ {
+ +export --clear foo
+
+ $* -v foo >'<none>'
+ }
+ EOI
+ }
+
+ : override
+ :
+ $c <<EOI && $b
+ +export foo=bar
+
+ {
+ +export --unset foo
+
+ export foo=baz;
+ $* -v foo >'baz'
+
+ -$* -v foo >'<none>'
+ }
+
+ -$* -v foo >'bar'
+ EOI
+}
+
+: test
+:
+{
+ : override
+ :
+ $c <<EOI && $b
+ {
+ export foo=bar;
+ env foo=baz -- $* -v foo >'baz';
+ $* -v foo >'bar'
+ }
+ EOI
+}
+
+: invalid
+:
+{
+ : set
+ :
+ $c <'export foo' && $b 2>>~%EOE% != 0
+ testscript:1:1: error: export: expected variable assignment instead of 'foo'
+ %.+
+ EOE
+
+ : unset
+ :
+ $c <'export --unset foo=abc' && $b 2>>~%EOE% != 0
+ testscript:1:1: error: export: invalid value 'foo=abc' for option -u|--unset: contains '='
+ %.+
+ EOE
+
+ : clear
+ :
+ $c <'export --clear foo=abc' && $b 2>>~%EOE% != 0
+ testscript:1:1: error: export: invalid value 'foo=abc' for option -c|--clear: contains '='
+ %.+
+ EOE
+}
diff --git a/tests/test/script/runner/expr.testscript b/tests/test/script/runner/expr.testscript
index 98e495f..95d4bed 100644
--- a/tests/test/script/runner/expr.testscript
+++ b/tests/test/script/runner/expr.testscript
@@ -20,7 +20,7 @@
true = '$* >| -o'
false = '$* -s 1 >| -o'
- bf = $b 2>-
+ bf = [cmdline] $b 2>-
: true
:
diff --git a/tests/test/script/runner/for.testscript b/tests/test/script/runner/for.testscript
new file mode 100644
index 0000000..f43fcc2
--- /dev/null
+++ b/tests/test/script/runner/for.testscript
@@ -0,0 +1,502 @@
+# File : tests/test/script/runner/for.testscript
+# license : MIT; see accompanying LICENSE file
+
+.include ../common.testscript
+
+: form-1
+:
+: for x: ...
+:
+{
+ : basics
+ :
+ $c <<EOI && $b >>EOO
+ for x: a b
+ echo "$x" >|
+ end
+ EOI
+ a
+ b
+ EOO
+
+ : test-options
+ :
+ $c <<EOI && $b >>~%EOO%
+ for test.options: -a -b
+ echo $* >|
+ end
+ EOI
+ %.+ -a%
+ %.+ -b%
+ EOO
+
+ : special-var
+ :
+ $c <<EOI && $b 2>>EOE != 0
+ for ~: -a -b
+ echo $~ >|
+ end
+ EOI
+ testscript:1:5: error: attempt to set '~' variable directly
+ EOE
+
+ : exit
+ :
+ $c <<EOI && $b >>EOO
+ for x: a b
+ echo "$x" >|
+ exit
+ end
+ EOI
+ a
+ EOO
+
+ : error
+ :
+ $c <<EOI && $b >>EOO 2>>EOE != 0
+ for x: a b
+ echo "$x" >|
+ exit 'fed up'
+ end
+ EOI
+ a
+ EOO
+ testscript:3:3: error: fed up
+ info: test id: 1
+ EOE
+}
+
+: form-2
+:
+: ... | for x
+:
+{
+ : whitespace-split
+ :
+ $c <<EOI && $b >>EOO
+ echo " a b " | for -w x
+ echo "'$x'" >|
+ end
+ EOI
+ 'a'
+ 'b'
+ EOO
+
+ : newline-split
+ :
+ $c <<EOI && $b >>EOO
+ cat <<EOF | for -n x
+
+
+ a
+
+
+ b
+
+ EOF
+ echo "'$x'" >|
+ end
+ EOI
+ ''
+ ''
+ 'a'
+ ''
+ ''
+ 'b'
+ ''
+ EOO
+
+ : typed
+ :
+ $c <<EOI && $b >>/EOO
+ echo "a b" | for -w x [dir_path]
+ echo $x >|
+ end
+ EOI
+ a/
+ b/
+ EOO
+
+ : nested
+ :
+ $c <<EOI && $b >>EOO
+ echo "a b" | for -w x
+ echo "x y" | for -w y
+ echo "'$x $y'" >|
+ end
+ end
+ EOI
+ 'a x'
+ 'a y'
+ 'b x'
+ 'b y'
+ EOO
+
+ : nested-diag
+ :
+ $c <<EOI && $b 2>>/~%EOE% != 0
+ echo "a b" | for -w x
+ echo "x y" | for -w y
+ echo "'$x $y'" >"'a x'"
+ end
+ end
+ EOI
+ testscript:3:5: error: echo stdout doesn't match expected
+ info: stdout: test/1/stdout-i1-i2-n3
+ info: expected stdout: test/1/stdout-i1-i2-n3.orig
+ info: stdout diff: test/1/stdout-i1-i2-n3.diff
+ %.+
+ EOE
+
+ : nested-diag-test-id
+ :
+ $c <<EOI && $b 2>>EOE != 0
+ echo "a b" | for -w x
+ echo "x y" | for -w y
+ test -f $x$y
+ end
+ end
+ EOI
+ testscript:3:5: error: builtin test exited with code 1
+ info: test id: 1
+ EOE
+
+ : var-value
+ :
+ $c <<EOI && $b >>EOO
+ x = 'x';
+ echo "a b" | for -w x
+ end;
+ echo $x >|
+ EOI
+ b
+ EOO
+
+ : both-sep-options
+ :
+ $c <<EOI && $b 2>>/~%EOE% != 0
+ echo "a b" | for -n -w x
+ echo $x >|
+ end
+ EOI
+ testscript:1:1: error: for: both -n|--newline and -w|--whitespace specified
+ %.+
+ EOE
+
+ : invalid-option
+ :
+ $c <<EOI && $b 2>>/~%EOE% != 0
+ echo "a b" | for -a x
+ echo $x >|
+ end
+ EOI
+ testscript:1:1: error: for: unknown option '-a'
+ %.+
+ EOE
+
+ : no-variable
+ :
+ $c <<EOI && $b 2>>/~%EOE% != 0
+ echo "a b" | for -w
+ echo $x >|
+ end
+ EOI
+ testscript:1:1: error: for: missing variable name
+ %.+
+ EOE
+
+ : special-var
+ :
+ $c <<EOI && $b 2>>EOE != 0
+ echo "a b" | for -w ~
+ echo $* >|
+ end
+ EOI
+ testscript:1:1: error: attempt to set '~' variable directly
+ info: test id: 1
+ EOE
+
+ : unsep-attrs
+ :
+ $c <<EOI && $b 2>>EOE != 0
+ echo "a b" | for -w x[string]
+ echo $x >|
+ end
+ EOI
+ testscript:1:1: error: for: expected variable name instead of x[string]
+ info: test id: 1
+ EOE
+
+ : misuse
+ :
+ {
+ : after-var
+ :
+ $c <<EOI && $b 2>>EOE != 0
+ echo "a b" | for v:
+ echo $v >|
+ end
+ EOI
+ testscript:1:19: error: expected newline instead of ':'
+ EOE
+
+ : after-attrs
+ :
+ $c <<EOI && $b 2>>EOE != 0
+ echo "a b" | for v [string]:
+ echo $v >|
+ end
+ EOI
+ testscript:1:28: error: expected newline instead of ':'
+ EOE
+ }
+
+ : exit
+ :
+ $c <<EOI && $b >>EOO
+ echo "a b" | for x
+ echo "$x" >|
+ exit
+ end
+ EOI
+ a
+ EOO
+
+ : error
+ :
+ $c <<EOI && $b >>EOO 2>>EOE != 0
+ echo "a b" | for x
+ echo "$x" >|
+ exit 'fed up'
+ end
+ EOI
+ a
+ EOO
+ testscript:3:3: error: fed up
+ info: test id: 1
+ EOE
+}
+
+: form-3
+:
+: for x <...
+:
+{
+ : whitespace-split
+ :
+ $c <<EOI && $b >>EOO
+ for -w x <" a b "
+ echo "'$x'" >|
+ end
+ EOI
+ 'a'
+ 'b'
+ EOO
+
+ : quoted-opt
+ :
+ $c <<EOI && $b >>EOO
+ o = -n
+ for "$o" x <<EOF
+ a
+ b
+ EOF
+ echo "'$x'" >|
+ end;
+ for "($o)" x <<EOF
+ c
+ d
+ EOF
+ echo "'$x'" >|
+ end
+ EOI
+ 'a'
+ 'b'
+ 'c'
+ 'd'
+ EOO
+
+ : newline-split
+ :
+ $c <<EOI && $b >>EOO
+ for -n x <<EOF
+
+
+ a
+
+
+ b
+
+ EOF
+ echo "'$x'" >|
+ end
+ EOI
+ ''
+ ''
+ 'a'
+ ''
+ ''
+ 'b'
+ ''
+ EOO
+
+ : string-before-var
+ :
+ $c <<EOI && $b >>EOO
+ for <"a b" -w x
+ echo "'$x'" >|
+ end
+ EOI
+ 'a'
+ 'b'
+ EOO
+
+ : here-doc-before-var
+ :
+ $c <<EOI && $b >>EOO
+ for <<EOF -n x
+ a
+ b
+ EOF
+ echo "'$x'" >|
+ end
+ EOI
+ 'a'
+ 'b'
+ EOO
+
+ : typed
+ :
+ $c <<EOI && $b >>/EOO
+ for -w x [dir_path] <"a b"
+ echo $x >|
+ end
+ EOI
+ a/
+ b/
+ EOO
+
+ : typed-no-ops
+ :
+ $c <<EOI && $b >>/EOO
+ for x [dir_path] <"a b"
+ echo $x >|
+ end
+ EOI
+ a/
+ b/
+ EOO
+
+ : nested
+ :
+ $c <<EOI && $b >>EOO
+ for -w x <"a b"
+ for -w y <"x y"
+ echo "'$x $y'" >|
+ end
+ end
+ EOI
+ 'a x'
+ 'a y'
+ 'b x'
+ 'b y'
+ EOO
+
+ : nested-diag
+ :
+ $c <<EOI && $b 2>>/~%EOE% != 0
+ for -w x <"a b"
+ for -w y <"x y"
+ echo "'$x $y'" >"'a x'"
+ end
+ end
+ EOI
+ testscript:3:5: error: echo stdout doesn't match expected
+ info: stdout: test/1/stdout-i1-i2-n3
+ info: expected stdout: test/1/stdout-i1-i2-n3.orig
+ info: stdout diff: test/1/stdout-i1-i2-n3.diff
+ %.+
+ EOE
+
+ : nested-diag-test-id
+ :
+ $c <<EOI && $b 2>>EOE != 0
+ for -w x <"a b"
+ for -w y <"x y"
+ test -f $x$y
+ end
+ end
+ EOI
+ testscript:3:5: error: builtin test exited with code 1
+ info: test id: 1
+ EOE
+
+ : var-value
+ :
+ $c <<EOI && $b >>EOO
+ x = 'x';
+ for -w x <"a b"
+ end;
+ echo $x >|
+ EOI
+ b
+ EOO
+
+ : invalid-option
+ :
+ $c <<EOI && $b 2>>/~%EOE% != 0
+ for -a x <"a b"
+ echo $x >|
+ end
+ EOI
+ testscript:1:1: error: for: unknown option '-a'
+ %.
+ EOE
+
+
+ : no-variable
+ :
+ $c <<EOI && $b 2>>/~%EOE% != 0
+ for -w <"a b"
+ echo $x >|
+ end
+ EOI
+ testscript:1:1: error: for: missing variable name
+ %.
+ EOE
+
+ : special-var
+ :
+ $c <<EOI && $b 2>>EOE != 0
+ for ~ <"a b"
+ echo $~ >|
+ end
+ EOI
+ testscript:1:5: error: attempt to set '~' variable directly
+ EOE
+
+ : exit
+ :
+ $c <<EOI && $b >>EOO
+ for x <"a b"
+ echo "$x" >|
+ exit
+ end
+ EOI
+ a
+ EOO
+
+ : error
+ :
+ $c <<EOI && $b >>EOO 2>>EOE != 0
+ for x <"a b"
+ echo "$x" >|
+ exit 'fed up'
+ end
+ EOI
+ a
+ EOO
+ testscript:3:3: error: fed up
+ info: test id: 1
+ EOE
+}
diff --git a/tests/test/script/runner/pipe.testscript b/tests/test/script/runner/pipe.testscript
index 205fd55..cdd30a6 100644
--- a/tests/test/script/runner/pipe.testscript
+++ b/tests/test/script/runner/pipe.testscript
@@ -6,7 +6,6 @@
$c <'cat <foo | $* -i 1 >foo' && $b : builtin-to-process
$c <'$* -o foo | cat >foo' && $b : process-to-builtin
-
: failure
:
: Note that while both commands for the pipe are faulty the diagnostics for
@@ -15,19 +14,28 @@ $c <'$* -o foo | cat >foo' && $b : process-to-builtin
{
: exit-code
:
- $c <'$* -o foo -s 1 | $* -i 1 >foo -s 2' && $b 2>>/~%EOE% != 0
- %testscript:1:1: error: .+ exited with code 2%
- info: stdout: test/1/stdout-2
+ : Also verify that the command line is printed.
+ :
+ $c <'$* -o foo -s 1 | $* -i 1 -s 2 >foo' && $b --verbose 1 2>>/~%EOE% != 0
+ %.
+ %testscript:1:1: error: process .+ exited with code 1%
+ % info: command line: .+driver.* -o foo -s 1%
+ info: test id: 1
+ %.
+ %testscript:1:1: error: process .+ exited with code 2%
+ % info: command line: .+driver.* -i 1 -s 2%
+ info: stdout: test/1/stdout-c2
info: test id: 1
+ %.{2}
EOE
: stderr
:
$c <'$* -o foo -e foo 2>bar | $* -i 2 2>baz' && $b 2>>/~%EOE% != 0
%testscript:1:1: error: .+ stderr doesn't match expected%
- info: stderr: test/1/stderr-2
- info: expected stderr: test/1/stderr-2.orig
- info: stderr diff: test/1/stderr-2.diff
+ info: stderr: test/1/stderr-c2
+ info: expected stderr: test/1/stderr-c2.orig
+ info: stderr diff: test/1/stderr-c2.diff
%.{3}
-baz
+foo
diff --git a/tests/test/script/runner/redirect.testscript b/tests/test/script/runner/redirect.testscript
index 0fe3aa3..209c4ce 100644
--- a/tests/test/script/runner/redirect.testscript
+++ b/tests/test/script/runner/redirect.testscript
@@ -654,9 +654,9 @@ psr = ($cxx.target.class != 'windows' ? '/' : '\\') # Path separator in regex.
$* -o bar >?out
EOI
%testscript:2: error: ../../../../../driver(.exe)? stdout doesn't match expected%
- info: stdout: test/1/stdout-2
+ info: stdout: test/1/stdout-n2
info: expected stdout: test/1/out
- info: stdout diff: test/1/stdout-2.diff
+ info: stdout diff: test/1/stdout-n2.diff
%--- \.*%
%\+\+\+ \.*%
%@@ \.*%
diff --git a/tests/test/script/runner/set.testscript b/tests/test/script/runner/set.testscript
index 9219cbb..1800a7d 100644
--- a/tests/test/script/runner/set.testscript
+++ b/tests/test/script/runner/set.testscript
@@ -52,7 +52,7 @@
: both-newline-whitespace
:
$c <'set -nw' && $b 2>>EOE != 0
- testscript:1:1: error: both -n|--newline and -w|--whitespace specified
+ testscript:1:1: error: set: both -n|--newline and -w|--whitespace specified
info: test id: 1
EOE
}
@@ -63,28 +63,28 @@
: none
:
$c <'set -e' && $b 2>>EOE != 0
- testscript:1:1: error: missing variable name
+ testscript:1:1: error: set: missing variable name
info: test id: 1
EOE
: unexpected
:
$c <'set foo bar baz' && $b 2>>EOE != 0
- testscript:1:1: error: unexpected argument 'baz'
+ testscript:1:1: error: set: unexpected argument 'baz'
info: test id: 1
EOE
: empty-attrs
:
- $c <"set '' baz" && $b 2>>EOE != 0
- testscript:1:1: error: empty variable attributes
+ $c <"set baz ''" && $b 2>>EOE != 0
+ testscript:1:1: error: set: empty variable attributes
info: test id: 1
EOE
: empty-var
:
$c <"set ''" && $b 2>>EOE != 0
- testscript:1:1: error: empty variable name
+ testscript:1:1: error: set: empty variable name
info: test id: 1
EOE
}
@@ -94,10 +94,28 @@
{
: non-exact
:
- $c <<EOI && $b
- set -w baz <' foo bar ';
- echo $baz >'foo bar'
- EOI
+ {
+ : non-empty
+ :
+ $c <<EOI && $b
+ set -w baz <' foo bar ';
+ echo $regex.apply($baz, '^(.*)$', '"\1"') >'"foo" "bar"'
+ EOI
+
+ : empty
+ :
+ $c <<EOI && $b
+ set -w baz <:'';
+ echo $regex.apply($baz, '^(.*)$', '"\1"') >''
+ EOI
+
+ : spaces
+ :
+ $c <<EOI && $b
+ set -w baz <' ';
+ echo $regex.apply($baz, '^(.*)$', '"\1"') >''
+ EOI
+ }
: exact
:
@@ -106,7 +124,7 @@
:
$c <<EOI && $b
set --exact --whitespace baz <' foo bar ';
- echo $baz >'foo bar '
+ echo $regex.apply($baz, '^(.*)$', '"\1"') >'"foo" "bar" ""'
EOI
: no-trailing-ws
@@ -115,8 +133,22 @@
: ':' modifier.
:
$c <<EOI && $b
- set --exact --whitespace baz <:' foo bar';
- echo $baz >'foo bar'
+ set -e -w baz <:' foo bar';
+ echo $regex.apply($baz, '^(.*)$', '"\1"') >'"foo" "bar"'
+ EOI
+
+ : empty
+ :
+ $c <<EOI && $b
+ set -e -w baz <:'';
+ echo $regex.apply($baz, '^(.*)$', '"\1"') >''
+ EOI
+
+ : spaces
+ :
+ $c <<EOI && $b
+ set -e -w baz <' ';
+ echo $regex.apply($baz, '^(.*)$', '"\1"') >'""'
EOI
}
}
@@ -134,7 +166,7 @@
bar
EOF
- echo $baz >' foo bar '
+ echo $regex.apply($baz, '^(.*)$', '"\1"') >'"" "foo" "" "bar" ""'
EOI
: exact
@@ -150,7 +182,7 @@
bar
EOF
- echo $baz >' foo bar '
+ echo $regex.apply($baz, '^(.*)$', '"\1"') >'"" "foo" "" "bar" "" ""'
EOI
: no-trailing-newline
@@ -162,7 +194,7 @@
bar
EOF
- echo $baz >' foo bar'
+ echo $regex.apply($baz, '^(.*)$', '"\1"') >'"" "foo" "" "bar"'
EOI
}
}
@@ -180,7 +212,7 @@
bar
EOF
- echo $baz >>EOO
+ echo ($baz[0]) >>EOO
foo
@@ -209,7 +241,7 @@
bar
EOF
- echo "$baz" >>EOO
+ echo ($baz[0]) >>EOO
foo
@@ -227,7 +259,7 @@
bar
EOF
- echo "$baz" >>EOO
+ echo ($baz[0]) >>EOO
foo
@@ -237,20 +269,291 @@
}
}
+: special-vars
+:
+{
+ $c <<EOI && $b
+ set -w test.options <'-o foo';
+ $* >'foo'
+ EOI
+}
+
+: deadline
+:
+{
+ : not-reached
+ :
+ $c <<EOI && $b
+ env -t 10 -- $* -o 'foo' | set bar;
+ echo "$bar" >'foo'
+ EOI
+
+ : non-pipe
+ :
+ $c <<EOI && $b
+ env -t 10 -- set bar <'foo';
+ echo "$bar" >'foo'
+ EOI
+
+ : set-reached
+ :
+ $c <<EOI && $b 2>>~%EOE% != 0
+ $* -o 'foo' -l 10 | env -t 1 -- set bar
+ EOI
+ %testscript:.*: error: .+driver.* terminated: execution timeout expired%
+ %.
+ EOE
+
+ : driver-reached
+ :
+ $c <<EOI && $b 2>>~%EOE% != 0
+ env -t 1 -- $* -o 'foo' -l 10 | set bar
+ EOI
+ %testscript:.*: error: .+driver.* terminated: execution timeout expired%
+ %.
+ EOE
+
+ : read-some-data
+ :
+ {
+ s="----------------------------------------------------------------------"
+ s="$s$s$s$s$s$s$s$s$s$s$s$s$s$s$s$s$s$s$s$s$s$s$s$s$s$s$s$s$s$s$s$s$s$s$s"
+ s="$s$s$s$s$s$s$s$s$s$s$s$s$s$s$s$s$s$s$s$s$s$s$s$s$s$s$s$s$s$s$s$s$s$s$s"
+
+ : failure
+ :
+ $c <<EOI && $b 2>>~%EOE% != 0
+ echo "$s" >=f;
+ $* -o 'foo' -l 10 | cat f - | env -t 2 -- set bar
+ EOI
+ %testscript:.*: error: process .+driver.* terminated: execution timeout expired%
+ %.
+ %testscript:.*: error: builtin cat terminated: execution timeout expired%
+ %.
+ EOE
+
+ : success
+ :
+ $c <<EOI && $b
+ echo "$s" >=f;
+ timeout --success 2;
+
+ # Suppress cat's 'broken pipe' diagnostics.
+ #
+ $* -o 'foo' -l 10 | cat f - 2>- | set bar
+ EOI
+ }
+
+ : split
+ :
+ : Test various splitting modes as above, but now reading the stream in the
+ : non-blocking mode.
+ :
+ {
+ : whitespace-separated-list
+ :
+ {
+ : non-exact
+ :
+ {
+ : non-empty
+ :
+ $c <<EOI && $b
+ timeout 10;
+ set -w baz <' foo bar ';
+ echo $regex.apply($baz, '^(.*)$', '"\1"') >'"foo" "bar"'
+ EOI
+
+ : empty
+ :
+ $c <<EOI && $b
+ timeout 10;
+ set -w baz <:'';
+ echo $regex.apply($baz, '^(.*)$', '"\1"') >''
+ EOI
+
+ : spaces
+ :
+ $c <<EOI && $b
+ timeout 10;
+ set -w baz <' ';
+ echo $regex.apply($baz, '^(.*)$', '"\1"') >''
+ EOI
+ }
+
+ : exact
+ :
+ {
+ : trailing-ws
+ :
+ $c <<EOI && $b
+ timeout 10;
+ set --exact --whitespace baz <' foo bar ';
+ echo $regex.apply($baz, '^(.*)$', '"\1"') >'"foo" "bar" ""'
+ EOI
+
+ : no-trailing-ws
+ :
+ : Note that we need to strip the default trailing newline as well with the
+ : ':' modifier.
+ :
+ $c <<EOI && $b
+ timeout 10;
+ set -e -w baz <:' foo bar';
+ echo $regex.apply($baz, '^(.*)$', '"\1"') >'"foo" "bar"'
+ EOI
+
+ : empty
+ :
+ $c <<EOI && $b
+ timeout 10;
+ set -e -w baz <:'';
+ echo $regex.apply($baz, '^(.*)$', '"\1"') >''
+ EOI
+
+ : spaces
+ :
+ $c <<EOI && $b
+ timeout 10;
+ set -e -w baz <' ';
+ echo $regex.apply($baz, '^(.*)$', '"\1"') >'""'
+ EOI
+ }
+ }
+
+ : newline-separated-list
+ :
+ {
+ : non-exact
+ :
+ $c <<EOI && $b
+ timeout 10;
+ set -n baz <<EOF;
+
+ foo
+
+ bar
+
+ EOF
+ echo $regex.apply($baz, '^(.*)$', '"\1"') >'"" "foo" "" "bar" ""'
+ EOI
+
+ : exact
+ :
+ {
+ : trailing-newline
+ :
+ $c <<EOI && $b
+ timeout 10;
+ set --exact --newline baz <<EOF;
+
+ foo
+
+ bar
+
+ EOF
+ echo $regex.apply($baz, '^(.*)$', '"\1"') >'"" "foo" "" "bar" "" ""'
+ EOI
+
+ : no-trailing-newline
+ :
+ $c <<EOI && $b
+ timeout 10;
+ set --exact --newline baz <<:EOF;
+
+ foo
+
+ bar
+ EOF
+ echo $regex.apply($baz, '^(.*)$', '"\1"') >'"" "foo" "" "bar"'
+ EOI
+ }
+ }
+
+ : string
+ :
+ {
+ : non-exact
+ :
+ $c <<EOI && $b
+ timeout 10;
+ set baz <<EOF;
+
+ foo
+
+ bar
+
+ EOF
+ echo ($baz[0]) >>EOO
+
+ foo
+
+ bar
+
+ EOO
+ EOI
+
+ : exact
+ :
+ : Note that echo adds the trailing newline, so EOF and EOO here-documents
+ : differ by this newline.
+ :
+ {
+ : trailing-newline
+ :
+ $c <<EOI && $b
+ timeout 10;
+ set -e baz <<EOF;
+
+ foo
+
+ bar
+ EOF
+ echo ($baz[0]) >>EOO
+
+ foo
+
+ bar
+
+ EOO
+ EOI
+
+ : no-trailing-newline
+ :
+ $c <<EOI && $b
+ timeout 10;
+ set -e baz <<:EOF;
+
+ foo
+
+ bar
+ EOF
+ echo ($baz[0]) >>EOO
+
+ foo
+
+ bar
+ EOO
+ EOI
+ }
+ }
+ }
+}
+
: attributes
:
{
: dir_path
:
$c <<EOI && $b
- set [dir_path] bar <'foo';
+ set bar [dir_path] <'foo';
echo $bar >/'foo/'
EOI
: null
:
$c <<EOI && $b
- set [null] foo <-;
+ set foo [null] <-;
echo $foo >''
EOI
@@ -268,7 +571,7 @@
: empty-brackets
:
$c <<EOI && $b 2>>EOE != 0
- set -w '[]' baz <'foo bar';
+ set -w baz '[]' <'foo bar';
echo "$baz"
EOI
testscript:2:8: error: concatenating variable expansion contains multiple values
@@ -277,7 +580,7 @@
: no-left-bracket
:
$c <<EOI && $b 2>>EOE != 0
- set -w x baz
+ set -w baz x
EOI
<attributes>:1:1: error: expected '[' instead of 'x'
testscript:1:1: info: while parsing attributes 'x'
@@ -287,7 +590,7 @@
: unknown
:
$c <<EOI && $b 2>>EOE != 0
- set -w [x] baz
+ set -w baz [x]
EOI
<attributes>:1:1: error: unknown value attribute x
testscript:1:1: info: while parsing attributes '[x]'
@@ -297,7 +600,7 @@
: junk
:
$c <<EOI && $b 2>>EOE != 0
- set -w '[string] x' baz
+ set -w baz '[string] x'
EOI
<attributes>:1:10: error: trailing junk after ']'
testscript:1:1: info: while parsing attributes '[string] x'
diff --git a/tests/test/script/runner/status.testscript b/tests/test/script/runner/status.testscript
index e4586d9..461fd5c 100644
--- a/tests/test/script/runner/status.testscript
+++ b/tests/test/script/runner/status.testscript
@@ -15,7 +15,7 @@ b += --no-column
: false
:
$c <'$* -s 1 == 0' && $b 2>>/~%EOE%d != 0
- %testscript:1: error: ../../../../driver(.exe)? exit code 1 != 0%
+ %testscript:1: error: process ../../../../driver(.exe)? exit code 1 != 0%
info: test id: 1
EOE
}
@@ -30,7 +30,7 @@ b += --no-column
: false
:
$c <'$* -s 1 != 1' && $b 2>>/~%EOE% != 0
- %testscript:1: error: ../../../../driver(.exe)? exit code 1 == 1%
+ %testscript:1: error: process ../../../../driver(.exe)? exit code 1 == 1%
info: test id: 1
EOE
}
@@ -38,7 +38,7 @@ b += --no-column
: error
:
$c <'$* -s 1 -e "Error"' && $b 2>>/~%EOE% != 0
-%testscript:1: error: ../../../driver(.exe)? exited with code 1%
+%testscript:1: error: process ../../../driver(.exe)? exited with code 1%
info: stderr: test/1/stderr
Error
info: test id: 1
@@ -47,7 +47,7 @@ EOE
: error-check
:
$c <'$* -s 1 -e "Error" == 0' && $b 2>>/~%EOE% != 0
-%testscript:1: error: ../../../driver(.exe)? exit code 1 != 0%
+%testscript:1: error: process ../../../driver(.exe)? exit code 1 != 0%
info: stderr: test/1/stderr
Error
info: test id: 1
diff --git a/tests/test/script/runner/test-runner.testscript b/tests/test/script/runner/test-runner.testscript
new file mode 100644
index 0000000..372330b
--- /dev/null
+++ b/tests/test/script/runner/test-runner.testscript
@@ -0,0 +1,57 @@
+# file : tests/test/script/runner/test-runner.testscript
+# license : MIT; see accompanying LICENSE file
+
+.include ../common.testscript
+
++if ($cxx.target.class == 'windows')
+ exit
+end
+
++cat <<EOI >=run
+ #!/bin/sh
+ if test "$1" = "--trace"; then
+ shift
+ echo "$*"
+ fi
+ "$@"
+ EOI
+
++chmod u+x run
+
+run=$~/run
+
+: basic
+:
+$c <<EOI && $b "config.test.runner=$run --trace"
+ +cat <'text' >'text' # Non-test program.
+
+ +$* -o 'text' >>~%EOO% # Test program.
+ %.+/driver -o text%
+ text
+ EOO
+
+ {
+ prog = $0
+ test=cat
+
+ +cat <'text' >>EOO # Test program.
+ cat
+ text
+ EOO
+
+ +$prog -o 'text' >>~%EOO% # Non-test program.
+ text
+ EOO
+
+ test=$prog
+
+ {
+ cat <'text' >'text'; # Non-test program.
+
+ $* -o 'text' >>~%EOO% # Test program.
+ %.+/driver -o text%
+ text
+ EOO
+ }
+ }
+ EOI
diff --git a/tests/test/script/runner/timeout.testscript b/tests/test/script/runner/timeout.testscript
new file mode 100644
index 0000000..f9b6ec7
--- /dev/null
+++ b/tests/test/script/runner/timeout.testscript
@@ -0,0 +1,521 @@
+# file : tests/test/script/runner/timeout.testscript
+# license : MIT; see accompanying LICENSE file
+
+.include ../common.testscript
+
+: test
+:
+{
+ : fragment-timeout
+ :
+ {
+ : set
+ :
+ $c <<EOI && $b 2>>~%EOE% != 0
+ timeout 1;
+ $* -l 3
+ EOI
+ %testscript:.*: error: .+ terminated: execution timeout expired%
+ %.
+ EOE
+
+ : reset
+ :
+ $c <<EOI && $b
+ timeout 1;
+ timeout 0;
+ $* -l 3
+ EOI
+
+ : override
+ :
+ $c <<EOI && $b 2>>~%EOE% != 0
+ +timeout /10
+
+ {
+ +timeout /10
+
+ timeout 1;
+ env -t 10 -- $* -l 3
+ }
+ EOI
+ %testscript:.*: error: .+ terminated: execution timeout expired%
+ %.
+ EOE
+
+ : successful
+ :
+ $c <<EOI && $b
+ timeout --success 1;
+ $* -l 3
+ EOI
+ }
+
+ : missing
+ :
+ $c <'timeout' && $b 2>>~%EOE% != 0
+ testscript:1:1: error: timeout: missing timeout
+ %.
+ EOE
+
+ : invalid
+ :
+ $c <'timeout foo' && $b 2>>~%EOE% != 0
+ testscript:1:1: error: timeout: invalid test fragment timeout 'foo'
+ %.
+ EOE
+}
+
+: group
+:
+{
+ : group-timeout
+ :
+ {
+ : set
+ :
+ $c <<EOI && $b 2>>~%EOE% != 0
+ {
+ +timeout 1
+
+ $* -l 3
+ }
+ EOI
+ %testscript:.*: error: .+ terminated: execution timeout expired%
+ %.
+ EOE
+
+ : reset
+ :
+ $c <<EOI && $b
+ {
+ +timeout 1
+ +timeout 0
+
+ $* -l 3
+ }
+ EOI
+
+ : override
+ :
+ : Also test slash usage inside the timeout value.
+ :
+ $c <<EOI && $b 2>>~%EOE% != 0
+ +timeout 10/10
+
+ {
+ +timeout 1/
+
+ timeout 10;
+ env -t 10 -- $* -l 3
+ }
+ EOI
+ %testscript:.*: error: .+ terminated: execution timeout expired%
+ %.
+ EOE
+
+ : invalid
+ :
+ $c <<EOI && $b 2>>~%EOE% != 0
+ {
+ +timeout foo/
+ }
+ EOI
+ testscript:2:4: error: timeout: invalid test group timeout 'foo'
+ %.
+ EOE
+ }
+
+ : test-timeout
+ :
+ {
+ : set
+ :
+ $c <<EOI && $b 2>>~%EOE% != 0
+ {
+ +timeout /1
+
+ $* -l 3
+ }
+ EOI
+ %testscript:.*: error: .+ terminated: execution timeout expired%
+ %.
+ EOE
+
+ : reset
+ :
+ $c <<EOI && $b
+ {
+ +timeout /1
+ +timeout /0
+
+ $* -l 3
+ }
+ EOI
+
+ : override
+ :
+ $c <<EOI && $b 2>>~%EOE% != 0
+ +timeout 10/10
+
+ {
+ +timeout /1
+
+ timeout 10;
+ env -t 10 -- $* -l 3
+ }
+ EOI
+ %testscript:.*: error: .+ terminated: execution timeout expired%
+ %.
+ EOE
+
+ : invalid
+ :
+ $c <<EOI && $b 2>>~%EOE% != 0
+ {
+ +timeout /foo
+ }
+ EOI
+ testscript:2:4: error: timeout: invalid test timeout 'foo'
+ %.
+ EOE
+ }
+}
+
+: script
+:
+{
+ : group-timeout
+ :
+ {
+ : set
+ :
+ $c <<EOI && $b 2>>~%EOE% != 0
+ +timeout 1
+
+ $* -l 3
+ EOI
+ %testscript:.*: error: .+ terminated: execution timeout expired%
+ %.
+ EOE
+
+ : reset
+ :
+ $c <<EOI && $b
+ +timeout 1
+ +timeout 0
+
+ $* -l 3
+ EOI
+
+ : override
+ :
+ $c <<EOI && $b 2>>~%EOE% != 0
+ +timeout 1
+
+ {
+ +timeout 10
+
+ timeout 10;
+ env -t 10 -- $* -l 3
+ }
+ EOI
+ %testscript:.*: error: .+ terminated: execution timeout expired%
+ %.
+ EOE
+
+ : invalid
+ :
+ $c <<EOI && $b 2>>~%EOE% != 0
+ +timeout foo/
+ EOI
+ testscript:1:2: error: timeout: invalid testscript timeout 'foo'
+ %.
+ EOE
+
+ : successful
+ :
+ $c <<EOI && $b
+ +timeout --success 1
+
+ $* -l 3
+ EOI
+ }
+
+ : test-timeout
+ :
+ {
+ : set
+ :
+ $c <<EOI && $b 2>>~%EOE% != 0
+ +timeout /1
+
+ $* -l 3
+ EOI
+ %testscript:.*: error: .+ terminated: execution timeout expired%
+ %.
+ EOE
+
+ : reset
+ :
+ $c <<EOI && $b
+ +timeout /1
+ +timeout /0
+
+ $* -l 3
+ EOI
+
+ : override
+ :
+ $c <<EOI && $b 2>>~%EOE% != 0
+ +timeout /1
+
+ {
+ +timeout --success /1
+
+ {
+ +timeout 10/10
+
+ timeout 10;
+ env -t 10 -- $* -l 3
+ }
+ }
+ EOI
+ %testscript:.*: error: .+ terminated: execution timeout expired%
+ %.
+ EOE
+
+ : successful
+ :
+ $c <<EOI && $b
+ +timeout --success /1
+
+ $* -l 3
+ EOI
+
+ : invalid
+ :
+ $c <<EOI && $b 2>>~%EOE% != 0
+ {
+ +timeout /foo
+ }
+ EOI
+ testscript:2:4: error: timeout: invalid test timeout 'foo'
+ %.
+ EOE
+ }
+}
+
+: config
+:
+{
+ : operation
+ :
+ {
+ : set
+ :
+ $c <<EOI && $b config.test.timeout=1 2>>~%EOE% != 0
+ timeout 10;
+ $* -l 3
+ EOI
+ %testscript:.*: error: .+ terminated: execution timeout expired%
+ %.
+ EOE
+
+ : reset
+ :
+ $c <<EOI && $b config.test.timeout=1 config.test.timeout=0/10
+ timeout 10;
+ $* -l 3
+ EOI
+
+ : override
+ :
+ $c <<EOI && $b config.test.timeout=1/10 2>>~%EOE% != 0
+ +timeout 10
+
+ {
+ +timeout 10/10
+
+ timeout 10;
+ env -t 10 -- $* -l 3
+ }
+ EOI
+ %testscript:.*: error: .+ terminated: execution timeout expired%
+ %.
+ EOE
+
+ : invalid
+ :
+ $c && $b config.test.timeout=foo 2>>EOE != 0
+ error: invalid config.test.timeout test operation timeout value 'foo'
+ EOE
+ }
+
+ : test
+ :
+ {
+ : set
+ :
+ $c <<EOI && $b config.test.timeout=/1 2>>~%EOE% != 0
+ timeout 10;
+ $* -l 3
+ EOI
+ %testscript:.*: error: .+ terminated: execution timeout expired%
+ %.
+ EOE
+
+ : reset
+ :
+ $c <<EOI && $b config.test.timeout=/1 config.test.timeout=10/0
+ timeout 10;
+ $* -l 3
+ EOI
+
+ : override
+ :
+ $c <<EOI && $b config.test.timeout=10/1 2>>~%EOE% != 0
+ +timeout 10
+
+ {
+ +timeout 10/10
+
+ timeout 10;
+ env -t 10 -- $* -l 3
+ }
+ EOI
+ %testscript:.*: error: .+ terminated: execution timeout expired%
+ %.
+ EOE
+
+ : invalid
+ :
+ $c && $b config.test.timeout=/foo 2>>EOE != 0
+ error: invalid config.test.timeout test timeout value 'foo'
+ EOE
+ }
+}
+
+: failures
+:
+: Here we test that the left-hand side processes are terminated on failure.
+:
+{
+ : set
+ :
+ $c <<EOI && $b 2>>~%EOE% != 0
+ env -t 1 -- $* -l 86400 -o 'foo' | set --foo bar
+ EOI
+ %testscript:.*: error: set: unknown option '--foo'%
+ %.
+ EOE
+
+ : exit
+ :
+ $c <<EOI && $b 2>>~%EOE% != 0
+ env -t 1 -- $* -l 86400 -o 'foo' | exit 0
+ EOI
+ %testscript:.*: error: exit builtin must be the only pipe command%
+ %.
+ EOE
+
+ : redirect
+ :
+ $c <<EOI && $b 2>>~%EOE% != 0
+ env -t 1 -- $* -l 86400 -o 'foo' | touch $~/foo/bar
+ EOI
+ %testscript:.*: error: process .+driver.* terminated: execution timeout expired%
+ %.
+ %testscript:.*: error: builtin touch exited with code 1%
+ %.+
+ EOE
+}
+
+: pipeline
+:
+{
+ : prog-tm-prog
+ :
+ $c <'$* -l 10 | env -t 1 -- $* -i 0' && $b 2>>~%EOE% != 0
+ %testscript:.*: error: process .+driver.* terminated: execution timeout expired%
+ %.
+ %testscript:.*: error: process .+driver.* terminated: execution timeout expired%
+ %.
+ EOE
+
+ : tm-prog-prog
+ :
+ $c <'env -t 1 -- $* -l 10 | $* -i 0' && $b 2>>~%EOE% != 0
+ %testscript:.*: error: process .+driver.* terminated: execution timeout expired%
+ %.
+ %testscript:.*: error: process .+driver.* terminated: execution timeout expired%
+ %.
+ EOE
+
+ : tm-cat-prog
+ :
+ $c <'env -t 3 -- cat <"test" | $* -l 10' && $b 2>>~%EOE% != 0
+ %testscript:.*: error: builtin cat terminated: execution timeout expired%
+ %.
+ %testscript:.*: error: process .+driver.* terminated: execution timeout expired%
+ %.
+ EOE
+
+ : cat-tm-prog
+ :
+ $c <'cat <"test" | env -t 1 -- $* -l 10' && $b 2>>~%EOE% != 0
+ %testscript:.*: error: builtin cat terminated: execution timeout expired%
+ %.
+ %testscript:.*: error: process .+driver.* terminated: execution timeout expired%
+ %.
+ EOE
+
+ : tm-prog-cat
+ :
+ $c <'env -t 1 -- $* -l 10 | cat >-' && $b 2>>~%EOE% != 0
+ %testscript:.*: error: process .+driver.* terminated: execution timeout expired%
+ %.
+ %testscript:.*: error: builtin cat terminated: execution timeout expired%
+ %.
+ EOE
+
+ : tm-echo-prog
+ :
+ $c <'env -t 3 -- echo "test" | $* -l 10' && $b 2>>~%EOE% != 0
+ %testscript:.*: error: builtin echo terminated: execution timeout expired%
+ %.
+ %testscript:.*: error: process .+driver.* terminated: execution timeout expired%
+ %.
+ EOE
+
+ : successful
+ :
+ {
+ : prog-prog
+ :
+ $c <<EOI && $b
+ timeout --success 1;
+ $* -l 10 | $* -i 0
+ EOI
+
+ : prog-cat
+ :
+ $c <<EOI && $b
+ timeout --success 1;
+ $* -l 10 | cat
+ EOI
+
+ : cat-prog
+ :
+ $c <<EOI && $b
+ s="----------------------------------------------------------------------";
+ s="$s$s$s$s$s$s$s$s$s$s$s$s$s$s$s$s$s$s$s$s$s$s$s$s$s$s$s$s$s$s$s$s$s$s$s";
+ s="$s$s$s$s$s$s$s$s$s$s$s$s$s$s$s$s$s$s$s$s$s$s$s$s$s$s$s$s$s$s$s$s$s$s$s";
+ s="$s$s$s$s$s$s$s$s$s$s$s$s$s$s$s$s$s$s$s$s$s$s$s$s$s$s$s$s$s$s$s$s$s$s$s";
+ timeout --success 1;
+ cat <"$s" 2>>~%EOE% | $* -l 10 -i 0
+ %cat: unable to print stdin: .+%
+ EOE
+ EOI
+ }
+}
diff --git a/tests/test/script/runner/while.testscript b/tests/test/script/runner/while.testscript
new file mode 100644
index 0000000..1c58827
--- /dev/null
+++ b/tests/test/script/runner/while.testscript
@@ -0,0 +1,16 @@
+# file : tests/test/script/runner/while.testscript
+# license : MIT; see accompanying LICENSE file
+
+.include ../common.testscript
+
+: basics
+:
+$c <<EOI && $b >>EOO
+ while ($v != "aa")
+ echo "$v" >|
+ v = "$(v)a"
+ end
+ EOI
+
+ a
+ EOO
diff --git a/tests/test/simple/generated/buildfile b/tests/test/simple/generated/buildfile
index 0809bdf..0344891 100644
--- a/tests/test/simple/generated/buildfile
+++ b/tests/test/simple/generated/buildfile
@@ -6,4 +6,5 @@
./: testscript exe{driver} $b file{*.in}
-exe{driver}: cxx{driver}
+import libs = libbutl%lib{butl}
+exe{driver}: cxx{driver} $libs
diff --git a/tests/test/simple/generated/driver.cxx b/tests/test/simple/generated/driver.cxx
index 1d911df..ca6dfcb 100644
--- a/tests/test/simple/generated/driver.cxx
+++ b/tests/test/simple/generated/driver.cxx
@@ -1,30 +1,71 @@
// file : tests/test/simple/generated/driver.cxx -*- C++ -*-
// license : MIT; see accompanying LICENSE file
+#ifndef _WIN32
+# include <chrono>
+# include <thread>
+#else
+# include <libbutl/win32-utility.hxx>
+#endif
+
#include <string>
#include <fstream>
#include <iostream>
+#undef NDEBUG
+#include <cassert>
+
using namespace std;
+// If the -s option is specified, then also sleep for 5 seconds.
+//
int
main (int argc, char* argv[])
{
+ int i (1);
+ for (; i != argc; ++i)
+ {
+ string a (argv[i]);
+
+ if (a == "-s")
+ {
+ // MINGW GCC 4.9 doesn't implement this_thread so use Win32 Sleep().
+ //
+#ifndef _WIN32
+ this_thread::sleep_for (chrono::seconds (5));
+#else
+ Sleep (5000);
+#endif
+ }
+ else
+ break;
+ }
+
int r (0);
- if (argc == 1)
+ if (i == argc)
{
cout << "1.2.3" << endl;
}
else
{
- ifstream ifs (argv[1]);
+ istream* is;
+ ifstream ifs;
+
+ if (argv[i] != string ("-"))
+ {
+ ifs.open (argv[i]);
+
+ if (!ifs.is_open ())
+ cerr << "unable to open " << argv[1] << endl;
- if (!ifs.is_open ())
- cerr << "unable to open " << argv[1] << endl;
+ is = &ifs;
+ }
+ else
+ is = &cin;
string s;
- r = getline (ifs, s) && s == "1.2.3" ? 0 : 1;
+ r = getline (*is, s) && s == "1.2.3" ? 0 : 1;
}
return r;
diff --git a/tests/test/simple/generated/testscript b/tests/test/simple/generated/testscript
index a04dccc..49ddbbd 100644
--- a/tests/test/simple/generated/testscript
+++ b/tests/test/simple/generated/testscript
@@ -42,3 +42,208 @@ driver = $src_root/../exe{driver}
./: file{output}: test.stdout = true
file{output}: in{output} $src_root/manifest #@@ in module
EOI
+
+: output-mismatch
+:
+{
+ # Get rid of --serial-stop --quiet.
+ #
+ test.options = $regex.apply($test.options, '^(--serial-stop|--quiet)$', '')
+
+ : verbose-0
+ :
+ {
+ echo '1.2.3' >=input;
+ echo '3.4.5' >=output;
+ $* -q <<EOI 2>>/~%EOE% != 0
+ driver = $src_root/../exe{driver}
+ ./: test = $driver
+ ./: $driver
+ ./: test.arguments = '-'
+ ./: file{input}: test.stdin = true
+ ./: file{output}: test.stdout = true
+ EOI
+ %.+
+ -3.4.5
+ error: test dir{./} failed
+ error: process diff exited with code 1
+ EOE
+ }
+
+ : verbose-1
+ :
+ {
+ echo '1.2.3' >=input;
+ echo '3.4.5' >=output;
+ $* <<EOI 2>>/~%EOE% != 0
+ driver = $src_root/../exe{driver}
+ ./: test = $driver
+ ./: $driver
+ ./: test.arguments = '-'
+ ./: file{input}: test.stdin = true
+ ./: file{output}: test.stdout = true
+ EOI
+ test dir{./}
+ %.+
+ -3.4.5
+ error: test dir{./} failed
+ error: process diff exited with code 1
+ % info: test command line: cat .+/input \| .+/driver.* - \| diff -u .+%
+ info: while testing dir{./}
+ info: failed to test dir{./}
+ EOE
+ }
+
+ : verbose-2
+ :
+ {
+ echo '1.2.3' >=input;
+ echo '3.4.5' >=output;
+ $* --verbose 2 <<EOI 2>>/~%EOE% != 0
+ driver = $src_root/../exe{driver}
+ ./: test = $driver
+ ./: $driver
+ ./: test.arguments = '-'
+ ./: file{input}: test.stdin = true
+ ./: file{output}: test.stdout = true
+ EOI
+ %cat .+/input \| .+/driver.* - \| diff -u .+%
+ %.+
+ -3.4.5
+ error: test dir{./} failed
+ error: process diff exited with code 1
+ info: while testing dir{./}
+ info: failed to test dir{./}
+ EOE
+ }
+
+ : verbose-3
+ :
+ {
+ echo '1.2.3' >=input;
+ echo '3.4.5' >=output;
+ $* --verbose 3 <<EOI 2>>/~%EOE% != 0
+ driver = $src_root/../exe{driver}
+ ./: test = $driver
+ ./: $driver
+ ./: test.arguments = '-'
+ ./: file{input}: test.stdin = true
+ ./: file{output}: test.stdout = true
+ EOI
+ %cat .+/input \| .+/driver.* - \| diff -u .+%
+ %.+
+ -3.4.5
+ %error: test .+dir\{.+\} failed%
+ error: process diff exited with code 1
+ % info: while testing .+dir\{.+\}%
+ %info: failed to test .+dir\{.+\}%
+ EOE
+ }
+
+ : input-not-found
+ :
+ {
+ echo '1.2.3' >=input;
+ echo '3.4.5' >=output;
+ $* -q <<EOI 2>>/~%EOE% != 0
+ driver = $src_root/../exe{driver}
+ ./: test = $driver
+ ./: $driver
+ ./: test.arguments = 'foo'
+ ./: file{input}: test.stdin = true
+ ./: file{output}: test.stdout = true
+ EOI
+ unable to open foo
+ error: test dir{./} failed
+ % error: process .+/driver.* exited with code 1%
+ EOE
+ }
+}
+
+: timeout
+:
+{
+ : operation
+ :
+ {
+ : no-output
+ :
+ ln -s $src_base/output.in ./;
+ $* config.test.timeout=1 <<EOI 2>>/~%EOE% != 0
+ driver = $src_root/../exe{driver}
+ ./: test = $driver
+ ./: test.options = -s
+ ./: $driver
+ EOI
+ error: test dir{./} failed
+ % error: process .+driver.* terminated: execution timeout expired%
+ EOE
+
+ : stdin-stdout
+ :
+ ln -s $src_base/input.in ./;
+ ln -s $src_base/output.in ./;
+ $* config.test.timeout=1 --verbose 1 &input &input.d &output &output.d <<EOI 2>>/~%EOE% != 0
+ driver = $src_root/../exe{driver}
+ ./: test = $driver
+ ./: test.options = -s
+ ./: $driver
+ ./: file{input}: test.stdin = true
+ ./: file{output}: test.stdout = true
+ file{input}: in{input} $src_root/manifest #@@ in module
+ file{output}: in{output} $src_root/manifest #@@ in module
+ EOI
+ %version in\{.+\} -> .+%{2}
+ test dir{./}
+ error: test dir{./} failed
+ % error: process .+driver.* terminated: execution timeout expired%
+ % info: test command line: cat .+/input \| .+driver.* -s \| diff -u .+%
+ info: while testing dir{./}
+ info: failed to test dir{./}
+ EOE
+ }
+
+ : test
+ :
+ {
+ : no-output
+ :
+ ln -s $src_base/output.in ./;
+ $* config.test.timeout=/1 <<EOI 2>>/~%EOE% != 0
+ driver = $src_root/../exe{driver}
+ ./: test = $driver
+ ./: test.options = -s
+ ./: $driver
+ EOI
+ error: test dir{./} failed
+ % error: process .+driver.* terminated: execution timeout expired%
+ EOE
+ }
+}
+
+: runner
+:
+if ($cxx.target.class != 'windows')
+{
+ cat <<EOI >=run;
+ #!/bin/sh
+ if test "$1" = "--trace"; then
+ shift
+ echo "tracing"
+ fi
+ "$@"
+ EOI
+
+ chmod u+x run;
+
+ echo 'tracing' >=output.in;
+ cat $src_base/output.in >+output.in;
+
+ $* config.test.runner="./run --trace" <<EOI
+ driver = $src_root/../exe{driver}
+ ./: test = $driver
+ ./: $driver
+ ./: file{output}: test.stdout = true
+ file{output}: in{output} $src_root/manifest #@@ in module
+ EOI
+}