aboutsummaryrefslogtreecommitdiff
path: root/tests
diff options
context:
space:
mode:
Diffstat (limited to 'tests')
-rw-r--r--tests/backtrace/buildfile12
-rw-r--r--tests/backtrace/driver.cxx97
-rw-r--r--tests/backtrace/testscript20
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
+}