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