diff options
Diffstat (limited to 'tests')
-rw-r--r-- | tests/backtrace/buildfile | 12 | ||||
-rw-r--r-- | tests/backtrace/driver.cxx | 97 | ||||
-rw-r--r-- | tests/backtrace/testscript | 20 |
3 files changed, 129 insertions, 0 deletions
diff --git a/tests/backtrace/buildfile b/tests/backtrace/buildfile new file mode 100644 index 0000000..a4120df --- /dev/null +++ b/tests/backtrace/buildfile @@ -0,0 +1,12 @@ +# file : tests/backtrace/buildfile +# copyright : Copyright (c) 2014-2019 Code Synthesis Ltd +# license : MIT; see accompanying LICENSE file + +import libs = libbutl%lib{butl} + +exe{driver}: {hxx cxx}{*} $libs testscript + +# Make sure backtrace() includes function names. +# +if ($cxx.target.class == 'linux') + cxx.loptions += -rdynamic diff --git a/tests/backtrace/driver.cxx b/tests/backtrace/driver.cxx new file mode 100644 index 0000000..5fd9223 --- /dev/null +++ b/tests/backtrace/driver.cxx @@ -0,0 +1,97 @@ +// file : tests/backtrace/driver.cxx -*- C++ -*- +// copyright : Copyright (c) 2014-2019 Code Synthesis Ltd +// license : MIT; see accompanying LICENSE file + +#ifndef _WIN32 +# include <sys/resource.h> // setrlimit() +#endif + +#include <cassert> + +#ifndef __cpp_lib_modules_ts +#include <string> +#include <iostream> +#include <exception> // set_terminate(), terminate_handler +#include <system_error> +#else +import std.io; +#endif + +// Other includes. + +#ifdef __cpp_modules_ts +#ifdef __cpp_lib_modules_ts +import std.core; +#endif +import butl.process; +import butl.backtrace; +#else +#include <libbutl/process.mxx> +#include <libbutl/backtrace.mxx> +#endif + +using namespace std; +using namespace butl; + +namespace test +{ + // Note: is not static to make sure the stack frame is not optimized out. + // + int + func () + { + throw system_error (EINVAL, generic_category ()); + } +} + +static terminate_handler def_term_handler; + +// Usage: argv[0] [-c] +// +// Print the backtrace for an unhandled exception. +// +// -c +// Run as a child process that sets up the backtrace-printing terminate +// handler and throws unhandled exception. +int +main (int argc, const char* argv[]) +{ + // Not to cause the testscript to fail due to the abnormal test driver + // termination, delegate the unhandled exception backtrace printing to the + // child process. + // + bool child (false); + for (int i (1); i != argc; ++i) + { + string o (argv[i]); + + if (o == "-c") + child = true; + else + assert (false); + } + + if (child) + { + // Disable dumping core file on POSIX. + // +#ifndef _WIN32 + struct rlimit rlim {0, 0}; + assert (setrlimit (RLIMIT_CORE, &rlim) == 0); +#endif + + def_term_handler = set_terminate ([]() + { + cerr << backtrace (); + + if (def_term_handler != nullptr) + def_term_handler (); + }); + + return test::func (); + } + + // Report failure with non-zero code if child succeeds. + // + return process_run (0, 1, 2, argv[0], "-c") ? 1 : 0; +} diff --git a/tests/backtrace/testscript b/tests/backtrace/testscript new file mode 100644 index 0000000..bdcd147 --- /dev/null +++ b/tests/backtrace/testscript @@ -0,0 +1,20 @@ +# file : tests/backtrace/testscript +# copyright : Copyright (c) 2014-2019 Code Synthesis Ltd +# license : MIT; see accompanying LICENSE file + +tclass = $cxx.target.class +tsys = $cxx.target.system + +: basic +: +if ($tclass == 'linux' || $tclass == 'macos' || $tsys == 'freebsd') +{ + # The stack frame line format varies among OSes. The only common thing is + # the '0x' function address prefix. + # + $* 2>>~%EOE% + %.* + %.*0x.*% + %.* + EOE +} |