Index: base/debug/stack_trace_unittest.cc |
diff --git a/base/debug/stack_trace_unittest.cc b/base/debug/stack_trace_unittest.cc |
index 6a35dac7a4bef47c779884e9c6aaaaf7904b44bc..bfbe6ee3d693ffdfb84bcf65f777b75bc6ed785b 100644 |
--- a/base/debug/stack_trace_unittest.cc |
+++ b/base/debug/stack_trace_unittest.cc |
@@ -2,16 +2,30 @@ |
// Use of this source code is governed by a BSD-style license that can be |
// found in the LICENSE file. |
+#include <limits> |
#include <sstream> |
#include <string> |
#include "base/debug/stack_trace.h" |
#include "base/logging.h" |
+#include "base/process_util.h" |
+#include "base/test/test_timeouts.h" |
#include "testing/gtest/include/gtest/gtest.h" |
+#include "testing/multiprocess_func_list.h" |
+ |
+#if defined(OS_POSIX) && !defined(OS_ANDROID) && !defined(OS_IOS) |
+#include "base/test/multiprocess_test.h" |
+#endif |
namespace base { |
namespace debug { |
+#if defined(OS_POSIX) && !defined(OS_ANDROID) && !defined(OS_IOS) |
+typedef MultiProcessTest StackTraceTest; |
+#else |
+typedef testing::Test StackTraceTest; |
+#endif |
+ |
// Note: On Linux, this test currently only fully works on Debug builds. |
// See comments in the #ifdef soup if you intend to change this. |
#if defined(OS_WIN) |
@@ -20,7 +34,7 @@ namespace debug { |
#else |
#define MAYBE_OutputToStream OutputToStream |
#endif |
-TEST(StackTrace, MAYBE_OutputToStream) { |
+TEST_F(StackTraceTest, MAYBE_OutputToStream) { |
StackTrace trace; |
// Dump the trace into a string. |
@@ -69,7 +83,7 @@ TEST(StackTrace, MAYBE_OutputToStream) { |
<< backtrace_message; |
#endif |
-#elif defined(__GLIBCXX__) |
+#elif defined(USE_SYMBOLIZE) |
// This branch is for gcc-compiled code, but not Mac due to the |
// above #if. |
// Expect a demangled symbol. |
@@ -104,7 +118,7 @@ TEST(StackTrace, MAYBE_OutputToStream) { |
} |
// The test is used for manual testing, e.g., to see the raw output. |
-TEST(StackTrace, DebugOutputToStream) { |
+TEST_F(StackTraceTest, DebugOutputToStream) { |
StackTrace trace; |
std::ostringstream os; |
trace.OutputToStream(&os); |
@@ -112,9 +126,86 @@ TEST(StackTrace, DebugOutputToStream) { |
} |
// The test is used for manual testing, e.g., to see the raw output. |
-TEST(StackTrace, DebugPrintBacktrace) { |
+TEST_F(StackTraceTest, DebugPrintBacktrace) { |
StackTrace().PrintBacktrace(); |
} |
+#if defined(OS_POSIX) && !defined(OS_ANDROID) |
+#if !defined(OS_IOS) |
+MULTIPROCESS_TEST_MAIN(MismatchedMallocChildProcess) { |
+ char* pointer = new char[10]; |
+ delete pointer; |
+ return 2; |
+} |
+ |
+// Regression test for StackDumpingSignalHandler async-signal unsafety. |
+// Combined with tcmalloc's debugallocation, that signal handler |
+// and e.g. mismatched new[]/delete would cause a hang because |
+// of re-entering malloc. |
+TEST_F(StackTraceTest, AsyncSignalUnsafeSignalHandlerHang) { |
+ ProcessHandle child = this->SpawnChild("MismatchedMallocChildProcess", false); |
+ ASSERT_NE(kNullProcessHandle, child); |
+ ASSERT_TRUE(WaitForSingleProcess(child, TestTimeouts::action_timeout())); |
+} |
+#endif // !defined(OS_IOS) |
+ |
+namespace { |
+ |
+std::string itoa_r_wrapper(intptr_t i, size_t sz, int base) { |
+ char buffer[1024]; |
+ CHECK_LE(sz, sizeof(buffer)); |
+ |
+ char* result = internal::itoa_r(i, buffer, sz, base); |
+ EXPECT_TRUE(result); |
+ return std::string(buffer); |
+} |
+ |
+} // namespace |
+ |
+TEST_F(StackTraceTest, itoa_r) { |
+ EXPECT_EQ("0", itoa_r_wrapper(0, 128, 10)); |
+ EXPECT_EQ("-1", itoa_r_wrapper(-1, 128, 10)); |
+ |
+ // Test edge cases. |
+ if (sizeof(intptr_t) == 4) { |
+ EXPECT_EQ("ffffffff", itoa_r_wrapper(-1, 128, 16)); |
+ EXPECT_EQ("-2147483648", |
+ itoa_r_wrapper(std::numeric_limits<intptr_t>::min(), 128, 10)); |
+ EXPECT_EQ("2147483647", |
+ itoa_r_wrapper(std::numeric_limits<intptr_t>::max(), 128, 10)); |
+ |
+ EXPECT_EQ("80000000", |
+ itoa_r_wrapper(std::numeric_limits<intptr_t>::min(), 128, 16)); |
+ EXPECT_EQ("7fffffff", |
+ itoa_r_wrapper(std::numeric_limits<intptr_t>::max(), 128, 16)); |
+ } else if (sizeof(intptr_t) == 8) { |
+ EXPECT_EQ("ffffffffffffffff", itoa_r_wrapper(-1, 128, 16)); |
+ EXPECT_EQ("-9223372036854775808", |
+ itoa_r_wrapper(std::numeric_limits<intptr_t>::min(), 128, 10)); |
+ EXPECT_EQ("9223372036854775807", |
+ itoa_r_wrapper(std::numeric_limits<intptr_t>::max(), 128, 10)); |
+ |
+ EXPECT_EQ("8000000000000000", |
+ itoa_r_wrapper(std::numeric_limits<intptr_t>::min(), 128, 16)); |
+ EXPECT_EQ("7fffffffffffffff", |
+ itoa_r_wrapper(std::numeric_limits<intptr_t>::max(), 128, 16)); |
+ } else { |
+ ADD_FAILURE() << "Missing test case for your size of intptr_t (" |
+ << sizeof(intptr_t) << ")"; |
+ } |
+ |
+ // Test hex output. |
+ EXPECT_EQ("688", itoa_r_wrapper(0x688, 128, 16)); |
+ EXPECT_EQ("deadbeef", itoa_r_wrapper(0xdeadbeef, 128, 16)); |
+ |
+ // Check that itoa_r respects passed buffer size limit. |
+ char buffer[1024]; |
+ EXPECT_TRUE(internal::itoa_r(0xdeadbeef, buffer, 10, 16)); |
+ EXPECT_TRUE(internal::itoa_r(0xdeadbeef, buffer, 9, 16)); |
+ EXPECT_FALSE(internal::itoa_r(0xdeadbeef, buffer, 8, 16)); |
+ EXPECT_FALSE(internal::itoa_r(0xdeadbeef, buffer, 7, 16)); |
+} |
+#endif // defined(OS_POSIX) && !defined(OS_ANDROID) |
+ |
} // namespace debug |
} // namespace base |