1731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick// Copyright (c) 2010 The Chromium Authors. All rights reserved. 2c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// Use of this source code is governed by a BSD-style license that can be 3c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// found in the LICENSE file. 4c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 5c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include <sstream> 6c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include <string> 7c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 8513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch#include "base/debug/stack_trace.h" 9c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include "base/logging.h" 10c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include "testing/gtest/include/gtest/gtest.h" 11c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 12513209b27ff55e2841eac0e4120199c23acce758Ben Murdochnamespace base { 13513209b27ff55e2841eac0e4120199c23acce758Ben Murdochnamespace debug { 14513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch 15c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// Note: On Linux, this test currently only fully works on Debug builds. 16c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// See comments in the #ifdef soup if you intend to change this. 17513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch#if defined(OS_WIN) 18513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch// Always fails on Windows: crbug.com/32070 19513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch#define MAYBE_OutputToStream FAILS_OutputToStream 20513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch#else 21513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch#define MAYBE_OutputToStream OutputToStream 22513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch#endif 23513209b27ff55e2841eac0e4120199c23acce758Ben MurdochTEST(StackTrace, MAYBE_OutputToStream) { 24c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott StackTrace trace; 25c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 26c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // Dump the trace into a string. 27c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott std::ostringstream os; 28c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott trace.OutputToStream(&os); 29c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott std::string backtrace_message = os.str(); 30c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 31c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#if defined(OS_POSIX) && !defined(OS_MACOSX) && NDEBUG 32c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // Stack traces require an extra data table that bloats our binaries, 33c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // so they're turned off for release builds. We stop the test here, 34c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // at least letting us verify that the calls don't crash. 35c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return; 36c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#endif // defined(OS_POSIX) && !defined(OS_MACOSX) && NDEBUG 37c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 38c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott size_t frames_found = 0; 39c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott trace.Addresses(&frames_found); 40c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott ASSERT_GE(frames_found, 5u) << 41c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott "No stack frames found. Skipping rest of test."; 42c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 43c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // Check if the output has symbol initialization warning. If it does, fail. 44c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott ASSERT_EQ(backtrace_message.find("Dumping unresolved backtrace"), 45c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott std::string::npos) << 46c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott "Unable to resolve symbols. Skipping rest of test."; 47c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 48c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#if defined(OS_MACOSX) 49c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#if 0 50c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // Disabled due to -fvisibility=hidden in build config. 51c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 52c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // Symbol resolution via the backtrace_symbol function does not work well 53c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // in OS X. 54c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // See this thread: 55c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // 56c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // http://lists.apple.com/archives/darwin-dev/2009/Mar/msg00111.html 57c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // 58c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // Just check instead that we find our way back to the "start" symbol 59c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // which should be the first symbol in the trace. 60c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // 61c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // TODO(port): Find a more reliable way to resolve symbols. 62c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 63c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // Expect to at least find main. 64c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott EXPECT_TRUE(backtrace_message.find("start") != std::string::npos) 65c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott << "Expected to find start in backtrace:\n" 66c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott << backtrace_message; 67c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 68c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#endif 69c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#elif defined(__GLIBCXX__) 70c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // This branch is for gcc-compiled code, but not Mac due to the 71c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // above #if. 72c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // Expect a demangled symbol. 73c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott EXPECT_TRUE(backtrace_message.find("testing::Test::Run()") != 74c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott std::string::npos) 75c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott << "Expected a demangled symbol in backtrace:\n" 76c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott << backtrace_message; 77c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 78c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#elif 0 79c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // This is the fall-through case; it used to cover Windows. 80c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // But it's disabled because of varying buildbot configs; 81c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // some lack symbols. 82c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 83c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // Expect to at least find main. 84c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott EXPECT_TRUE(backtrace_message.find("main") != std::string::npos) 85c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott << "Expected to find main in backtrace:\n" 86c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott << backtrace_message; 87c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 88c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#if defined(OS_WIN) 89c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// MSVC doesn't allow the use of C99's __func__ within C++, so we fake it with 90c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// MSVC's __FUNCTION__ macro. 91c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#define __func__ __FUNCTION__ 92c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#endif 93c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 94c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // Expect to find this function as well. 95c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // Note: This will fail if not linked with -rdynamic (aka -export_dynamic) 96c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott EXPECT_TRUE(backtrace_message.find(__func__) != std::string::npos) 97c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott << "Expected to find " << __func__ << " in backtrace:\n" 98c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott << backtrace_message; 99c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 100c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#endif // define(OS_MACOSX) 101c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 102c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 103c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// The test is used for manual testing, e.g., to see the raw output. 104c407dc5cd9bdc5668497f21b26b09d988ab439deBen MurdochTEST(StackTrace, DebugOutputToStream) { 105c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott StackTrace trace; 106c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott std::ostringstream os; 107c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott trace.OutputToStream(&os); 108731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick VLOG(1) << os.str(); 109c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 110c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 111c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// The test is used for manual testing, e.g., to see the raw output. 112c407dc5cd9bdc5668497f21b26b09d988ab439deBen MurdochTEST(StackTrace, DebugPrintBacktrace) { 113c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott StackTrace().PrintBacktrace(); 114c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 115513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch 116513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch} // namespace debug 117513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch} // namespace base 118