From: Kristian H. Kristensen Date: Wed, 29 Jul 2020 04:29:37 +0000 (-0700) Subject: util: Add unit test for stack backtrace caputure X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=d0d14f3f6481e015b4413fa0487164b76fe45296;p=mesa.git util: Add unit test for stack backtrace caputure First test never fails, but exercises the code and is useful for manual inspection. Second test exposes the android implementation bug. Part-of: --- diff --git a/src/util/meson.build b/src/util/meson.build index 909b3e07468..0893f64793b 100644 --- a/src/util/meson.build +++ b/src/util/meson.build @@ -289,6 +289,18 @@ if with_tests suite : ['util'], ) + test( + 'u_debug_stack', + executable( + 'u_debug_stack_test', + files('u_debug_stack_test.cpp'), + include_directories : [inc_include, inc_src, inc_mapi, inc_mesa, inc_gallium, inc_gallium_aux], + dependencies : [idep_mesautil, idep_gtest], + c_args : [c_msvc_compat_args], + ), + suite : ['util'], + ) + process_test_exe = executable( 'process_test', files('process_test.c'), diff --git a/src/util/u_debug_stack_test.cpp b/src/util/u_debug_stack_test.cpp new file mode 100644 index 00000000000..b5f8ea4ba38 --- /dev/null +++ b/src/util/u_debug_stack_test.cpp @@ -0,0 +1,111 @@ +/* + * Copyright © 2020 Google, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#include +#include + +#include "util/u_debug_stack.h" + +static void __attribute__((noinline)) +func_a(void) +{ + struct debug_stack_frame backtrace[16]; + + fprintf(stderr, "--- backtrace from func_a:\n"); + debug_backtrace_capture(backtrace, 0, 16); + debug_backtrace_dump(backtrace, 16); +} + +static void __attribute__((noinline)) +func_b(void) +{ + struct debug_stack_frame backtrace[16]; + + func_a(); + + fprintf(stderr, "--- backtrace from func_b:\n"); + debug_backtrace_capture(backtrace, 0, 16); + debug_backtrace_dump(backtrace, 16); +} + +static void __attribute__((noinline)) +func_c(struct debug_stack_frame *frames) +{ + debug_backtrace_capture(frames, 0, 16); +} + +TEST(u_debug_stack_test, basics) +{ + struct debug_stack_frame backtrace[16]; + struct debug_stack_frame stored_backtrace[16]; + + func_c(stored_backtrace); + + fprintf(stderr, "--- backtrace from main to stderr:\n"); + debug_backtrace_capture(backtrace, 0, 16); + debug_backtrace_print(stderr, backtrace, 16); + + fprintf(stderr, "--- backtrace from main again to debug_printf:\n"); + debug_backtrace_capture(backtrace, 0, 16); + debug_backtrace_dump(backtrace, 16); + + func_a(); + + func_b(); + + fprintf(stderr, "--- stored backtrace from start of main:\n"); + debug_backtrace_dump(stored_backtrace, 16); +} + +#if _POSIX_C_SOURCE >= 200809L + +TEST(u_debug_stack_test, capture_not_overwritten) +{ + struct debug_stack_frame backtrace1[16], backtrace2[16]; + + FILE *fp; + char *bt1, *bt2; + size_t size; + + /* Old android implementation uses one global capture per thread. Test that + * we can store multiple captures and that they decode to different + * backtraces. + */ + + func_c(backtrace1); + debug_backtrace_capture(backtrace2, 0, 16); + + fp = open_memstream(&bt1, &size); + debug_backtrace_print(fp, backtrace1, 16); + fclose(fp); + + fp = open_memstream(&bt2, &size); + debug_backtrace_print(fp, backtrace2, 16); + fclose(fp); + + if (size > 0) { + EXPECT_STRNE(bt1, bt2); + } +} + +#endif