diff options
Diffstat (limited to 'tests/test/script/runner/driver.cxx')
-rw-r--r-- | tests/test/script/runner/driver.cxx | 96 |
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; } |