aboutsummaryrefslogtreecommitdiff
path: root/tests/test/script/runner/driver.cxx
diff options
context:
space:
mode:
Diffstat (limited to 'tests/test/script/runner/driver.cxx')
-rw-r--r--tests/test/script/runner/driver.cxx96
1 files changed, 84 insertions, 12 deletions
diff --git a/tests/test/script/runner/driver.cxx b/tests/test/script/runner/driver.cxx
index a82b083..6a3698f 100644
--- a/tests/test/script/runner/driver.cxx
+++ b/tests/test/script/runner/driver.cxx
@@ -4,6 +4,7 @@
#include <limits> // numeric_limits
#include <string>
+#include <cstdlib> // abort()
#include <cassert>
#include <ostream> // endl, *bit
#include <istream> // istream::traits_type::eof()
@@ -11,20 +12,65 @@
#include <exception>
#include <butl/path>
+#include <butl/optional>
#include <butl/fdstream>
#include <butl/filesystem>
using namespace std;
using namespace butl;
+// Call itself recursively causing stack overflow. Parameterized to avoid
+// "stack overflow" warning.
+//
+static void
+stack_overflow (bool overflow)
+{
+ if (overflow)
+ stack_overflow (true);
+}
+
int
main (int argc, char* argv[])
{
- // Usage: driver [-i <int>] [-s <int>] (-o <string>)* (-e <string>)*
- // (-f <file>)* (-d <dir>)*
+ // Usage: driver [-i <int>] (-o <string>)* (-e <string>)* (-f <file>)*
+ // (-d <dir>)* [(-t (a|m|s|z)) | (-s <int>)]
+ //
+ // Execute actions specified by -i, -o, -e, -f, -d 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
+ // descriptor. Read and discard if 0.
+ //
+ // -o <string>
+ // Print the line to STDOUT.
+ //
+ // -e <string>
+ // Print the line to STDERR.
+ //
+ // -f <path>
+ // Create an empty file with the path specified.
+ //
+ // -d <path>
+ // Create a directory with the path specified. Create parent directories
+ // if required.
+ //
+ // -t <method>
+ // Abnormally terminate itself using one of the following methods:
+ //
+ // a - call abort()
+ // m - dereference null-pointer
+ // s - cause stack overflow using infinite function call recursion
+ // z - divide integer by zero
+ //
+ // -s <int>
+ // Exit normally with the status specified. The default status is 0.
//
- int status (256);
int ifd (3);
+ optional<int> status;
+ char aterm ('\0'); // Abnormal termination method.
cout.exceptions (ostream::failbit | ostream::badbit);
cerr.exceptions (ostream::failbit | ostream::badbit);
@@ -64,7 +110,11 @@ main (int argc, char* argv[])
if (ifd == 0)
cin.ignore (numeric_limits<streamsize>::max ());
else if (cin.peek () != istream::traits_type::eof ())
- (ifd == 1 ? cout : cerr) << cin.rdbuf ();
+ {
+ ostream& o (ifd == 1 ? cout : cerr);
+ o << cin.rdbuf ();
+ o.flush ();
+ }
}
else if (o == "-o")
{
@@ -74,13 +124,6 @@ main (int argc, char* argv[])
{
cerr << v << endl;
}
- else if (o == "-s")
- {
- assert (status == 256); // Make sure is not set yet.
-
- status = toi (v);
- assert (status >= 0 && status < 256);
- }
else if (o == "-f")
{
ofdstream os (v);
@@ -90,9 +133,38 @@ main (int argc, char* argv[])
{
try_mkdir_p (dir_path (v));
}
+ 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);
}
- return status == 256 ? 0 : status;
+ switch (aterm)
+ {
+ case 'a': abort (); break;
+ case 'm':
+ {
+ int* p (nullptr);
+ *p = 0;
+ break;
+ }
+ case 's': stack_overflow (true); break;
+ case 'z':
+ {
+ int z (0);
+ z /= z;
+ break;
+ }
+ }
+
+ return status ? *status : 0;
}