| OLD | NEW |
| (Empty) |
| 1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. | |
| 2 // Use of this source code is governed by a BSD-style license that can be | |
| 3 // found in the LICENSE file. | |
| 4 | |
| 5 #include <limits> | |
| 6 #include <sstream> | |
| 7 #include <string> | |
| 8 | |
| 9 #include "base/debug/stack_trace.h" | |
| 10 #include "base/logging.h" | |
| 11 #include "base/process/kill.h" | |
| 12 #include "base/process/process_handle.h" | |
| 13 #include "base/test/test_timeouts.h" | |
| 14 #include "testing/gtest/include/gtest/gtest.h" | |
| 15 #include "testing/multiprocess_func_list.h" | |
| 16 | |
| 17 #if defined(OS_POSIX) && !defined(OS_ANDROID) && !defined(OS_IOS) | |
| 18 #include "base/test/multiprocess_test.h" | |
| 19 #endif | |
| 20 | |
| 21 namespace base { | |
| 22 namespace debug { | |
| 23 | |
| 24 #if defined(OS_POSIX) && !defined(OS_ANDROID) && !defined(OS_IOS) | |
| 25 typedef MultiProcessTest StackTraceTest; | |
| 26 #else | |
| 27 typedef testing::Test StackTraceTest; | |
| 28 #endif | |
| 29 | |
| 30 #if defined(__UCLIBC__) || defined(FNL_MUSL) | |
| 31 #define MAYBE_OutputToStream DISABLED_OutputToStream | |
| 32 #else | |
| 33 #define MAYBE_OutputToStream OutputToStream | |
| 34 #endif | |
| 35 TEST_F(StackTraceTest, MAYBE_OutputToStream) { | |
| 36 StackTrace trace; | |
| 37 | |
| 38 // Dump the trace into a string. | |
| 39 std::ostringstream os; | |
| 40 trace.OutputToStream(&os); | |
| 41 std::string backtrace_message = os.str(); | |
| 42 | |
| 43 // ToString() should produce the same output. | |
| 44 EXPECT_EQ(backtrace_message, trace.ToString()); | |
| 45 | |
| 46 #if defined(OS_POSIX) && !defined(OS_MACOSX) && NDEBUG | |
| 47 // Stack traces require an extra data table that bloats our binaries, | |
| 48 // so they're turned off for release builds. We stop the test here, | |
| 49 // at least letting us verify that the calls don't crash. | |
| 50 return; | |
| 51 #endif // defined(OS_POSIX) && !defined(OS_MACOSX) && NDEBUG | |
| 52 | |
| 53 size_t frames_found = 0; | |
| 54 trace.Addresses(&frames_found); | |
| 55 ASSERT_GE(frames_found, 5u) << | |
| 56 "No stack frames found. Skipping rest of test."; | |
| 57 | |
| 58 // Check if the output has symbol initialization warning. If it does, fail. | |
| 59 ASSERT_EQ(backtrace_message.find("Dumping unresolved backtrace"), | |
| 60 std::string::npos) << | |
| 61 "Unable to resolve symbols. Skipping rest of test."; | |
| 62 | |
| 63 #if defined(OS_MACOSX) | |
| 64 #if 0 | |
| 65 // Disabled due to -fvisibility=hidden in build config. | |
| 66 | |
| 67 // Symbol resolution via the backtrace_symbol function does not work well | |
| 68 // in OS X. | |
| 69 // See this thread: | |
| 70 // | |
| 71 // http://lists.apple.com/archives/darwin-dev/2009/Mar/msg00111.html | |
| 72 // | |
| 73 // Just check instead that we find our way back to the "start" symbol | |
| 74 // which should be the first symbol in the trace. | |
| 75 // | |
| 76 // TODO(port): Find a more reliable way to resolve symbols. | |
| 77 | |
| 78 // Expect to at least find main. | |
| 79 EXPECT_TRUE(backtrace_message.find("start") != std::string::npos) | |
| 80 << "Expected to find start in backtrace:\n" | |
| 81 << backtrace_message; | |
| 82 | |
| 83 #endif | |
| 84 #elif defined(USE_SYMBOLIZE) | |
| 85 // This branch is for gcc-compiled code, but not Mac due to the | |
| 86 // above #if. | |
| 87 // Expect a demangled symbol. | |
| 88 EXPECT_TRUE(backtrace_message.find("testing::Test::Run()") != | |
| 89 std::string::npos) | |
| 90 << "Expected a demangled symbol in backtrace:\n" | |
| 91 << backtrace_message; | |
| 92 | |
| 93 #elif 0 | |
| 94 // This is the fall-through case; it used to cover Windows. | |
| 95 // But it's disabled because of varying buildbot configs; | |
| 96 // some lack symbols. | |
| 97 | |
| 98 // Expect to at least find main. | |
| 99 EXPECT_TRUE(backtrace_message.find("main") != std::string::npos) | |
| 100 << "Expected to find main in backtrace:\n" | |
| 101 << backtrace_message; | |
| 102 | |
| 103 // Expect to find this function as well. | |
| 104 // Note: This will fail if not linked with -rdynamic (aka -export_dynamic) | |
| 105 EXPECT_TRUE(backtrace_message.find(__func__) != std::string::npos) | |
| 106 << "Expected to find " << __func__ << " in backtrace:\n" | |
| 107 << backtrace_message; | |
| 108 | |
| 109 #endif // define(OS_MACOSX) | |
| 110 } | |
| 111 | |
| 112 // The test is used for manual testing, e.g., to see the raw output. | |
| 113 TEST_F(StackTraceTest, DebugOutputToStream) { | |
| 114 StackTrace trace; | |
| 115 std::ostringstream os; | |
| 116 trace.OutputToStream(&os); | |
| 117 VLOG(1) << os.str(); | |
| 118 } | |
| 119 | |
| 120 // The test is used for manual testing, e.g., to see the raw output. | |
| 121 TEST_F(StackTraceTest, DebugPrintBacktrace) { | |
| 122 StackTrace().Print(); | |
| 123 } | |
| 124 | |
| 125 #if defined(OS_POSIX) && !defined(OS_ANDROID) | |
| 126 #if !defined(OS_IOS) | |
| 127 static char* newArray() { | |
| 128 // Clang warns about the mismatched new[]/delete if they occur in the same | |
| 129 // function. | |
| 130 return new char[10]; | |
| 131 } | |
| 132 | |
| 133 MULTIPROCESS_TEST_MAIN(MismatchedMallocChildProcess) { | |
| 134 char* pointer = newArray(); | |
| 135 delete pointer; | |
| 136 return 2; | |
| 137 } | |
| 138 | |
| 139 // Regression test for StackDumpingSignalHandler async-signal unsafety. | |
| 140 // Combined with tcmalloc's debugallocation, that signal handler | |
| 141 // and e.g. mismatched new[]/delete would cause a hang because | |
| 142 // of re-entering malloc. | |
| 143 TEST_F(StackTraceTest, AsyncSignalUnsafeSignalHandlerHang) { | |
| 144 Process child = SpawnChild("MismatchedMallocChildProcess"); | |
| 145 ASSERT_TRUE(child.IsValid()); | |
| 146 int exit_code; | |
| 147 ASSERT_TRUE(child.WaitForExitWithTimeout(TestTimeouts::action_timeout(), | |
| 148 &exit_code)); | |
| 149 } | |
| 150 #endif // !defined(OS_IOS) | |
| 151 | |
| 152 namespace { | |
| 153 | |
| 154 std::string itoa_r_wrapper(intptr_t i, size_t sz, int base, size_t padding) { | |
| 155 char buffer[1024]; | |
| 156 CHECK_LE(sz, sizeof(buffer)); | |
| 157 | |
| 158 char* result = internal::itoa_r(i, buffer, sz, base, padding); | |
| 159 EXPECT_TRUE(result); | |
| 160 return std::string(buffer); | |
| 161 } | |
| 162 | |
| 163 } // namespace | |
| 164 | |
| 165 TEST_F(StackTraceTest, itoa_r) { | |
| 166 EXPECT_EQ("0", itoa_r_wrapper(0, 128, 10, 0)); | |
| 167 EXPECT_EQ("-1", itoa_r_wrapper(-1, 128, 10, 0)); | |
| 168 | |
| 169 // Test edge cases. | |
| 170 if (sizeof(intptr_t) == 4) { | |
| 171 EXPECT_EQ("ffffffff", itoa_r_wrapper(-1, 128, 16, 0)); | |
| 172 EXPECT_EQ("-2147483648", | |
| 173 itoa_r_wrapper(std::numeric_limits<intptr_t>::min(), 128, 10, 0)); | |
| 174 EXPECT_EQ("2147483647", | |
| 175 itoa_r_wrapper(std::numeric_limits<intptr_t>::max(), 128, 10, 0)); | |
| 176 | |
| 177 EXPECT_EQ("80000000", | |
| 178 itoa_r_wrapper(std::numeric_limits<intptr_t>::min(), 128, 16, 0)); | |
| 179 EXPECT_EQ("7fffffff", | |
| 180 itoa_r_wrapper(std::numeric_limits<intptr_t>::max(), 128, 16, 0)); | |
| 181 } else if (sizeof(intptr_t) == 8) { | |
| 182 EXPECT_EQ("ffffffffffffffff", itoa_r_wrapper(-1, 128, 16, 0)); | |
| 183 EXPECT_EQ("-9223372036854775808", | |
| 184 itoa_r_wrapper(std::numeric_limits<intptr_t>::min(), 128, 10, 0)); | |
| 185 EXPECT_EQ("9223372036854775807", | |
| 186 itoa_r_wrapper(std::numeric_limits<intptr_t>::max(), 128, 10, 0)); | |
| 187 | |
| 188 EXPECT_EQ("8000000000000000", | |
| 189 itoa_r_wrapper(std::numeric_limits<intptr_t>::min(), 128, 16, 0)); | |
| 190 EXPECT_EQ("7fffffffffffffff", | |
| 191 itoa_r_wrapper(std::numeric_limits<intptr_t>::max(), 128, 16, 0)); | |
| 192 } else { | |
| 193 ADD_FAILURE() << "Missing test case for your size of intptr_t (" | |
| 194 << sizeof(intptr_t) << ")"; | |
| 195 } | |
| 196 | |
| 197 // Test hex output. | |
| 198 EXPECT_EQ("688", itoa_r_wrapper(0x688, 128, 16, 0)); | |
| 199 EXPECT_EQ("deadbeef", itoa_r_wrapper(0xdeadbeef, 128, 16, 0)); | |
| 200 | |
| 201 // Check that itoa_r respects passed buffer size limit. | |
| 202 char buffer[1024]; | |
| 203 EXPECT_TRUE(internal::itoa_r(0xdeadbeef, buffer, 10, 16, 0)); | |
| 204 EXPECT_TRUE(internal::itoa_r(0xdeadbeef, buffer, 9, 16, 0)); | |
| 205 EXPECT_FALSE(internal::itoa_r(0xdeadbeef, buffer, 8, 16, 0)); | |
| 206 EXPECT_FALSE(internal::itoa_r(0xdeadbeef, buffer, 7, 16, 0)); | |
| 207 EXPECT_TRUE(internal::itoa_r(0xbeef, buffer, 5, 16, 4)); | |
| 208 EXPECT_FALSE(internal::itoa_r(0xbeef, buffer, 5, 16, 5)); | |
| 209 EXPECT_FALSE(internal::itoa_r(0xbeef, buffer, 5, 16, 6)); | |
| 210 | |
| 211 // Test padding. | |
| 212 EXPECT_EQ("1", itoa_r_wrapper(1, 128, 10, 0)); | |
| 213 EXPECT_EQ("1", itoa_r_wrapper(1, 128, 10, 1)); | |
| 214 EXPECT_EQ("01", itoa_r_wrapper(1, 128, 10, 2)); | |
| 215 EXPECT_EQ("001", itoa_r_wrapper(1, 128, 10, 3)); | |
| 216 EXPECT_EQ("0001", itoa_r_wrapper(1, 128, 10, 4)); | |
| 217 EXPECT_EQ("00001", itoa_r_wrapper(1, 128, 10, 5)); | |
| 218 EXPECT_EQ("688", itoa_r_wrapper(0x688, 128, 16, 0)); | |
| 219 EXPECT_EQ("688", itoa_r_wrapper(0x688, 128, 16, 1)); | |
| 220 EXPECT_EQ("688", itoa_r_wrapper(0x688, 128, 16, 2)); | |
| 221 EXPECT_EQ("688", itoa_r_wrapper(0x688, 128, 16, 3)); | |
| 222 EXPECT_EQ("0688", itoa_r_wrapper(0x688, 128, 16, 4)); | |
| 223 EXPECT_EQ("00688", itoa_r_wrapper(0x688, 128, 16, 5)); | |
| 224 } | |
| 225 #endif // defined(OS_POSIX) && !defined(OS_ANDROID) | |
| 226 | |
| 227 } // namespace debug | |
| 228 } // namespace base | |
| OLD | NEW |