From 56e3f056e9a03015aa55392a8028e2cbe097a0fb Mon Sep 17 00:00:00 2001 From: Nick Mathewson Date: Mon, 29 Jul 2013 21:56:31 -0400 Subject: [PATCH] Tests for backtrace.c These need to be a separate executable, since the point of backtrace.c is that it can crash and write stuff. --- .gitignore | 2 + src/test/bt_test.py | 42 +++++++++++++++ src/test/include.am | 8 +++ src/test/test_bt_cl.c | 110 ++++++++++++++++++++++++++++++++++++++++ src/test/test_logging.c | 2 + 5 files changed, 164 insertions(+) create mode 100755 src/test/bt_test.py create mode 100644 src/test/test_bt_cl.c diff --git a/.gitignore b/.gitignore index 201d04da66..a301acc2c4 100644 --- a/.gitignore +++ b/.gitignore @@ -164,9 +164,11 @@ /src/test/bench /src/test/bench.exe /src/test/test +/src/test/test-bt-cl /src/test/test-child /src/test/test-ntor-cl /src/test/test.exe +/src/test/test-bt-cl.exe /src/test/test-child.exe /src/test/test-ntor-cl.exe diff --git a/src/test/bt_test.py b/src/test/bt_test.py new file mode 100755 index 0000000000..2de9924a59 --- /dev/null +++ b/src/test/bt_test.py @@ -0,0 +1,42 @@ +# Copyright 2013, The Tor Project, Inc +# See LICENSE for licensing information + +""" +bt_test.py + +This file tests the output from test-bt-cl to make sure it's as expected. + +Example usage: + +$ ./src/test/test-bt-cl crash | ./src/test/bt_test.py +OK +$ ./src/test/test-bt-cl assert | ./src/test/bt_test.py +OK + +""" + +import sys + + +def matches(lines, funcs): + if len(lines) < len(funcs): + return False + try: + for l, f in zip(lines, funcs): + l.index(f) + except ValueError: + return False + else: + return True + +FUNCNAMES = "crash oh_what a_tangled_web we_weave main".split() + +LINES = sys.stdin.readlines() + +for I in range(len(LINES)): + if matches(LINES[I:], FUNCNAMES): + print "OK" + break +else: + print "BAD" + diff --git a/src/test/include.am b/src/test/include.am index ffbfefba12..e879c2000e 100644 --- a/src/test/include.am +++ b/src/test/include.am @@ -77,3 +77,11 @@ src_test_test_ntor_cl_AM_CPPFLAGS = \ endif +noinst_PROGRAMS += src/test/test-bt-cl +src_test_test_bt_cl_SOURCES = src/test/test_bt_cl.c +src_test_test_bt_cl_LDADD = src/common/libor-testing.a \ + @TOR_LIB_MATH@ \ + @TOR_LIB_WS32@ @TOR_LIB_GDI@ +src_test_test_bt_cl_CFLAGS = $(AM_CFLAGS) $(TEST_CFLAGS) +src_test_test_bt_cl_CPPFLAGS= $(src_test_AM_CPPFLAGS) + diff --git a/src/test/test_bt_cl.c b/src/test/test_bt_cl.c new file mode 100644 index 0000000000..9ac9823dc8 --- /dev/null +++ b/src/test/test_bt_cl.c @@ -0,0 +1,110 @@ +/* Copyright (c) 2012-2013, The Tor Project, Inc. */ +/* See LICENSE for licensing information */ + +#include "orconfig.h" +#include +#include + +#include "or.h" +#include "util.h" +#include "backtrace.h" +#include "torlog.h" + + +/* -1: no crash. + * 0: crash with a segmentation fault. + * 1x: crash with an assertion failure. */ +static int crashtype = 0; + +#ifdef __GNUC__ +#define NOINLINE __attribute__((noinline)) +#define NORETURN __attribute__((noreturn)) +#endif + +int crash(int x) NOINLINE; +int oh_what(int x) NOINLINE; +int a_tangled_web(int x) NOINLINE; +int we_weave(int x) NOINLINE; +static void abort_handler(int s) NORETURN; + +int +crash(int x) +{ + if (crashtype == 0) { + *(volatile int *)0 = 0; + } else if (crashtype == 1) { + tor_assert(1 == 0); + } else if (crashtype == -1) { + ; + } + + crashtype *= x; + return crashtype; +} + +int +oh_what(int x) +{ + /* We call crash() twice here, so that the compiler won't try to do a + * tail-call optimization. Only the first call will actually happen, but + * telling the compiler to maybe do the second call will prevent it from + * replacing the first call with a jump. */ + return crash(x) + crash(x*2); +} + +int +a_tangled_web(int x) +{ + return oh_what(x) * 99 + oh_what(x); +} + +int +we_weave(int x) +{ + return a_tangled_web(x) + a_tangled_web(x+1); +} + +static void +abort_handler(int s) +{ + (void)s; + exit(0); +} + +int +main(int argc, char **argv) +{ + log_severity_list_t severity; + + if (argc < 2) { + puts("I take an argument. It should be \"assert\" or \"crash\" or " + "\"none\""); + return 1; + } + if (!strcmp(argv[1], "assert")) { + crashtype = 1; + } else if (!strcmp(argv[1], "crash")) { + crashtype = 0; + } else if (!strcmp(argv[1], "none")) { + crashtype = -1; + } else { + puts("Argument should be \"assert\" or \"crash\" or \"none\""); + return 1; + } + + init_logging(); + set_log_severity_config(LOG_WARN, LOG_ERR, &severity); + add_stream_log(&severity, "stdout", STDOUT_FILENO); + tor_log_update_sigsafe_err_fds(); + + configure_backtrace_handler(NULL); + + signal(SIGABRT, abort_handler); + + printf("%d\n", we_weave(2)); + + clean_up_backtrace_handler(); + + return 0; +} + diff --git a/src/test/test_logging.c b/src/test/test_logging.c index 4111a46eb9..7e558f83b1 100644 --- a/src/test/test_logging.c +++ b/src/test/test_logging.c @@ -96,6 +96,8 @@ test_sigsafe_err(void *arg) close(STDERR_FILENO); log_err(LD_BUG, "Say, this isn't too cool."); tor_log_err_sigsafe("Minimal.\n", NULL); + + set_log_time_granularity(100*1000); tor_log_err_sigsafe("Testing any ", "attempt to manually log ", "from a signal.\n",