diff options
author | Nick Mathewson <nickm@torproject.org> | 2013-11-18 11:00:16 -0500 |
---|---|---|
committer | Nick Mathewson <nickm@torproject.org> | 2013-11-18 11:00:16 -0500 |
commit | fbc20294aaf67f9434d5b1e107b8e1c43e42a3a4 (patch) | |
tree | 0d0f0b0aa37423e8f36f11e8410849e48be59ba6 /src/test | |
parent | 7a2b30fe16eacc040b3dd11f8c39c410628c2f43 (diff) | |
parent | c81f64ab44f71a97649a44e10d6fcbf15aa8c835 (diff) | |
download | tor-fbc20294aaf67f9434d5b1e107b8e1c43e42a3a4.tar.gz tor-fbc20294aaf67f9434d5b1e107b8e1c43e42a3a4.zip |
Merge branch 'backtrace_squashed'
Conflicts:
src/common/sandbox.c
src/common/sandbox.h
src/common/util.c
src/or/main.c
src/test/include.am
src/test/test.c
Diffstat (limited to 'src/test')
-rwxr-xr-x | src/test/bt_test.py | 42 | ||||
-rw-r--r-- | src/test/include.am | 12 | ||||
-rw-r--r-- | src/test/test.c | 3 | ||||
-rw-r--r-- | src/test/test_bt_cl.c | 110 | ||||
-rw-r--r-- | src/test/test_logging.c | 135 | ||||
-rw-r--r-- | src/test/test_util.c | 51 |
6 files changed, 353 insertions, 0 deletions
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 5510293cda..c16dd14fe7 100644 --- a/src/test/include.am +++ b/src/test/include.am @@ -30,6 +30,7 @@ src_test_test_SOURCES = \ src/test/test_dir.c \ src/test/test_extorport.c \ src/test/test_introduce.c \ + src/test/test_logging.c \ src/test/test_microdesc.c \ src/test/test_options.c \ src/test/test_pt.c \ @@ -86,6 +87,15 @@ else CMDLINE_TEST_TOR = ./src/or/tor 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) + + check-local: $(NTOR_TEST_DEPS) $(CMDLINE_TEST_TOR) if USEPYTHON $(PYTHON) $(top_srcdir)/src/test/test_cmdline_args.py $(CMDLINE_TEST_TOR) "${top_srcdir}" @@ -93,4 +103,6 @@ if CURVE25519_ENABLED $(PYTHON) $(top_srcdir)/src/test/ntor_ref.py test-tor $(PYTHON) $(top_srcdir)/src/test/ntor_ref.py self-test endif + ./src/test/test-bt-cl assert | $(PYTHON) $(top_srcdir)/src/test/bt_test.py + ./src/test/test-bt-cl crash | $(PYTHON) $(top_srcdir)/src/test/bt_test.py endif diff --git a/src/test/test.c b/src/test/test.c index 562de48016..752f8d7121 100644 --- a/src/test/test.c +++ b/src/test/test.c @@ -1621,6 +1621,8 @@ extern struct testcase_t options_tests[]; extern struct testcase_t socks_tests[]; extern struct testcase_t extorport_tests[]; extern struct testcase_t controller_event_tests[]; +extern struct testcase_t logging_tests[]; +extern struct testcase_t backtrace_tests[]; static struct testgroup_t testgroups[] = { { "", test_array }, @@ -1630,6 +1632,7 @@ static struct testgroup_t testgroups[] = { { "crypto/", crypto_tests }, { "container/", container_tests }, { "util/", util_tests }, + { "util/logging/", logging_tests }, { "cellfmt/", cell_format_tests }, { "cellqueue/", cell_queue_tests }, { "dir/", dir_tests }, 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 <stdio.h> +#include <stdlib.h> + +#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 new file mode 100644 index 0000000000..7e558f83b1 --- /dev/null +++ b/src/test/test_logging.c @@ -0,0 +1,135 @@ +/* Copyright (c) 2013, The Tor Project, Inc. */ +/* See LICENSE for licensing information */ + +#include "orconfig.h" +#include "or.h" +#include "torlog.h" +#include "test.h" + +static void +dummy_cb_fn(int severity, uint32_t domain, const char *msg) +{ + (void)severity; (void)domain; (void)msg; +} + +static void +test_get_sigsafe_err_fds(void *arg) +{ + const int *fds; + int n; + log_severity_list_t include_bug, no_bug, no_bug2; + (void) arg; + init_logging(); + + n = tor_log_get_sigsafe_err_fds(&fds); + tt_int_op(n, ==, 1); + tt_int_op(fds[0], ==, STDERR_FILENO); + + set_log_severity_config(LOG_WARN, LOG_ERR, &include_bug); + set_log_severity_config(LOG_WARN, LOG_ERR, &no_bug); + no_bug.masks[0] &= ~(LD_BUG|LD_GENERAL); + set_log_severity_config(LOG_INFO, LOG_NOTICE, &no_bug2); + + /* Add some logs; make sure the output is as expected. */ + mark_logs_temp(); + add_stream_log(&include_bug, "dummy-1", 3); + add_stream_log(&no_bug, "dummy-2", 4); + add_stream_log(&no_bug2, "dummy-3", 5); + add_callback_log(&include_bug, dummy_cb_fn); + close_temp_logs(); + tor_log_update_sigsafe_err_fds(); + + n = tor_log_get_sigsafe_err_fds(&fds); + tt_int_op(n, ==, 2); + tt_int_op(fds[0], ==, STDERR_FILENO); + tt_int_op(fds[1], ==, 3); + + /* Allow STDOUT to replace STDERR. */ + add_stream_log(&include_bug, "dummy-4", STDOUT_FILENO); + tor_log_update_sigsafe_err_fds(); + n = tor_log_get_sigsafe_err_fds(&fds); + tt_int_op(n, ==, 2); + tt_int_op(fds[0], ==, 3); + tt_int_op(fds[1], ==, STDOUT_FILENO); + + /* But don't allow it to replace explicit STDERR. */ + add_stream_log(&include_bug, "dummy-5", STDERR_FILENO); + tor_log_update_sigsafe_err_fds(); + n = tor_log_get_sigsafe_err_fds(&fds); + tt_int_op(n, ==, 3); + tt_int_op(fds[0], ==, STDERR_FILENO); + tt_int_op(fds[1], ==, STDOUT_FILENO); + tt_int_op(fds[2], ==, 3); + + /* Don't overflow the array. */ + { + int i; + for (i=5; i<20; ++i) { + add_stream_log(&include_bug, "x-dummy", i); + } + } + tor_log_update_sigsafe_err_fds(); + n = tor_log_get_sigsafe_err_fds(&fds); + tt_int_op(n, ==, 8); + + done: + ; +} + +static void +test_sigsafe_err(void *arg) +{ + const char *fn=get_fname("sigsafe_err_log"); + char *content=NULL; + log_severity_list_t include_bug; + smartlist_t *lines = smartlist_new(); + (void)arg; + + set_log_severity_config(LOG_WARN, LOG_ERR, &include_bug); + + init_logging(); + mark_logs_temp(); + add_file_log(&include_bug, fn); + tor_log_update_sigsafe_err_fds(); + close_temp_logs(); + + 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", + NULL); + mark_logs_temp(); + close_temp_logs(); + close(STDERR_FILENO); + content = read_file_to_str(fn, 0, NULL); + + tt_assert(content != NULL); + tor_split_lines(lines, content, (int)strlen(content)); + tt_int_op(smartlist_len(lines), >=, 5); + + if (strstr(smartlist_get(lines, 0), "opening new log file")) + smartlist_del_keeporder(lines, 0); + tt_assert(strstr(smartlist_get(lines, 0), "Say, this isn't too cool")); + /* Next line is blank. */ + tt_assert(!strcmpstart(smartlist_get(lines, 1), "==============")); + tt_assert(!strcmpstart(smartlist_get(lines, 2), "Minimal.")); + /* Next line is blank. */ + tt_assert(!strcmpstart(smartlist_get(lines, 3), "==============")); + tt_str_op(smartlist_get(lines, 4), ==, + "Testing any attempt to manually log from a signal."); + + done: + tor_free(content); + smartlist_free(lines); +} + +struct testcase_t logging_tests[] = { + { "sigsafe_err_fds", test_get_sigsafe_err_fds, TT_FORK, NULL, NULL }, + { "sigsafe_err", test_sigsafe_err, TT_FORK, NULL, NULL }, + END_OF_TESTCASES +}; + diff --git a/src/test/test_util.c b/src/test/test_util.c index ba58b31d4b..ab5928ffd4 100644 --- a/src/test/test_util.c +++ b/src/test/test_util.c @@ -2779,6 +2779,56 @@ test_util_format_hex_number(void *ptr) } /** + * Test for format_hex_number_sigsafe() + */ + +static void +test_util_format_dec_number(void *ptr) +{ + int i, len; + char buf[33]; + const struct { + const char *str; + unsigned int x; + } test_data[] = { + {"0", 0}, + {"1", 1}, + {"1234", 1234}, + {"12345678", 12345678}, + {"99999999", 99999999}, + {"100000000", 100000000}, + {"4294967295", 4294967295u}, +#if UINT_MAX > 0xffffffff + {"18446744073709551615", 18446744073709551615u }, +#endif + {NULL, 0} + }; + + (void)ptr; + + for (i = 0; test_data[i].str != NULL; ++i) { + len = format_dec_number_sigsafe(test_data[i].x, buf, sizeof(buf)); + test_neq(len, 0); + test_eq(len, strlen(buf)); + test_streq(buf, test_data[i].str); + + len = format_dec_number_sigsafe(test_data[i].x, buf, + (int)(strlen(test_data[i].str) + 1)); + test_eq(len, strlen(buf)); + test_streq(buf, test_data[i].str); + } + + test_eq(4, format_dec_number_sigsafe(7331, buf, 5)); + test_streq(buf, "7331"); + test_eq(0, format_dec_number_sigsafe(7331, buf, 4)); + test_eq(1, format_dec_number_sigsafe(0, buf, 2)); + test_eq(0, format_dec_number_sigsafe(0, buf, 1)); + + done: + return; +} + +/** * Test that we can properly format a Windows command line */ static void @@ -3598,6 +3648,7 @@ struct testcase_t util_tests[] = { UTIL_TEST(spawn_background_fail, 0), UTIL_TEST(spawn_background_partial_read, 0), UTIL_TEST(format_hex_number, 0), + UTIL_TEST(format_dec_number, 0), UTIL_TEST(join_win_cmdline, 0), UTIL_TEST(split_lines, 0), UTIL_TEST(n_bits_set, 0), |