]> git.apps.os.sepia.ceph.com Git - ceph-ci.git/commitdiff
common/BackTrace: add operator<<
authorKefu Chai <kchai@redhat.com>
Tue, 10 May 2016 13:56:55 +0000 (21:56 +0800)
committerKefu Chai <kchai@redhat.com>
Sun, 15 Jan 2017 19:03:22 +0000 (03:03 +0800)
replace BackTrace::print() with the operator<< where the former is used.

Signed-off-by: Kefu Chai <kchai@redhat.com>
src/common/BackTrace.cc
src/common/BackTrace.h
src/common/assert.cc
src/common/cmdparse.cc
src/common/lockdep.cc
src/test/common/CMakeLists.txt
src/test/common/test_back_trace.cc [new file with mode: 0644]

index 208c5de8831436ea2d6dbd7a60e15489d2ec019b..33408f33d448ad0a42ed567c2539162622795c5b 100644 (file)
@@ -14,7 +14,7 @@
 
 namespace ceph {
 
-void BackTrace::print(std::ostream& out)
+void BackTrace::print(std::ostream& out) const
 {
   out << " " << pretty_version_to_str() << std::endl;
   for (size_t i = skip; i < size; i++) {
index addfdeeeb28d00d9c4015e5710d624c6172824da..fe0ad0e7efacd21abc705f2797ef0cd0fcaa06c8 100644 (file)
@@ -35,9 +35,14 @@ struct BackTrace {
   BackTrace(const BackTrace& other);
   const BackTrace& operator=(const BackTrace& other);
 
-  void print(std::ostream& out);
+  void print(std::ostream& out) const;
 };
 
+inline std::ostream& operator<<(std::ostream& out, const BackTrace& bt) {
+  bt.print(out);
+  return out;
+}
+
 }
 
 #endif
index 340391742e8eaa131a6920421d10449b2ca44ce0..d4dd048c2fa103672664549c0d8c4df1ebe4b40a 100644 (file)
@@ -50,7 +50,6 @@ namespace ceph {
     tss << ceph_clock_now();
 
     char buf[8096];
-    BackTrace *bt = new BackTrace(1);
     snprintf(buf, sizeof(buf),
             "%s: In function '%s' thread %llx time %s\n"
             "%s: %d: FAILED assert(%s)\n",
@@ -60,7 +59,7 @@ namespace ceph {
 
     // TODO: get rid of this memory allocation.
     ostringstream oss;
-    bt->print(oss);
+    oss << BackTrace(1);
     dout_emergency(oss.str());
 
     dout_emergency(" NOTE: a copy of the executable, or `objdump -rdS <executable>` "
@@ -68,7 +67,7 @@ namespace ceph {
 
     if (g_assert_context) {
       lderr(g_assert_context) << buf << std::endl;
-      bt->print(*_dout);
+      *_dout << oss.str();
       *_dout << " NOTE: a copy of the executable, or `objdump -rdS <executable>` "
             << "is needed to interpret this.\n" << dendl;
 
@@ -130,7 +129,7 @@ namespace ceph {
 
     // TODO: get rid of this memory allocation.
     ostringstream oss;
-    bt->print(oss);
+    oss << *bt;
     dout_emergency(oss.str());
 
     dout_emergency(" NOTE: a copy of the executable, or `objdump -rdS <executable>` "
@@ -138,7 +137,7 @@ namespace ceph {
 
     if (g_assert_context) {
       lderr(g_assert_context) << buf << std::endl;
-      bt->print(*_dout);
+      *_dout << oss.str();
       *_dout << " NOTE: a copy of the executable, or `objdump -rdS <executable>` "
             << "is needed to interpret this.\n" << dendl;
 
index b1e05a7c123cc4786f43ab7b8c6ae8331a0ec913..3fdf94c73676600d72b084a39acd36fb490ede5d 100644 (file)
@@ -329,9 +329,8 @@ handle_bad_get(CephContext *cct, string k, const char *tname)
   errstr << "bad boost::get: key " << k << " is not type " << typestr;
   lderr(cct) << errstr.str() << dendl;
 
-  BackTrace bt(1);
   ostringstream oss;
-  bt.print(oss);
+  oss << BackTrace(1);
   lderr(cct) << oss.rdbuf() << dendl;
   if (status == 0)
     free((char *)typestr);
index 35d18af0ab7026611276c13938d418a9ab92c559..b921eb64a55d5a695252ab5a100d342b737fefbb 100644 (file)
@@ -129,7 +129,7 @@ int lockdep_dump_locks()
         ++q) {
       lockdep_dout(0) << "  * " << lock_names[q->first] << "\n";
       if (q->second)
-       q->second->print(*_dout);
+       *_dout << *(q->second);
       *_dout << dendl;
     }
   }
index f8ebe478089e01ca754aff5cbf0fe767498145c6..a08628562207a9fcd79f649b995d56ac56d46d9c 100644 (file)
@@ -217,3 +217,11 @@ add_executable(unittest_dns_resolve
 target_link_libraries(unittest_dns_resolve global)
 add_ceph_unittest(unittest_dns_resolve
   ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/unittest_dns_resolve)
+
+add_executable(unittest_back_trace
+  test_back_trace.cc)
+set_source_files_properties(test_back_trace.cc PROPERTIES
+  COMPILE_FLAGS -fno-inline)
+target_link_libraries(unittest_back_trace ceph-common)
+add_ceph_unittest(unittest_back_trace
+  ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/unittest_back_trace)
diff --git a/src/test/common/test_back_trace.cc b/src/test/common/test_back_trace.cc
new file mode 100644 (file)
index 0000000..389f4e3
--- /dev/null
@@ -0,0 +1,41 @@
+// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
+// vim: ts=8 sw=2 smarttab
+
+#include <boost/algorithm/string.hpp>
+// std::regex support in libstdc++ 4.8 is incomplete, so let's stick to
+// boost::regex now.
+#include <boost/regex.hpp>
+#include <gtest/gtest.h>
+#include <sstream>
+#include <string>
+
+#include "common/BackTrace.h"
+#include "common/version.h"
+
+// a dummy function, so we can check "foo" in the backtrace.
+// do not mark this function as static or put it into an anonymous namespace,
+// otherwise it's function name will be removed in the backtrace.
+std::string foo()
+{
+  std::ostringstream oss;
+  oss << ceph::BackTrace(1);
+  return oss.str();
+}
+
+// a typical backtrace looks like:
+//
+// ceph version Development (no_version)
+// 1: (foo[abi:cxx11]()+0x4a) [0x5562231cf22a]
+// 2: (BackTrace_Basic_Test::TestBody()+0x28) [0x5562231cf2fc]
+TEST(BackTrace, Basic) {
+  std::string bt = foo();
+  std::vector<std::string> lines;
+  boost::split(lines, bt, boost::is_any_of("\n"));
+  const unsigned lineno = 1;
+  ASSERT_GT(lines.size(), lineno);
+  ASSERT_EQ(lines[0].find(pretty_version_to_str()), 1);
+  boost::regex e{"^ 1: "
+                "\\(foo.*\\)\\s"
+                "\\[0x[[:xdigit:]]+\\]$"};
+  EXPECT_TRUE(boost::regex_match(lines[lineno], e));
+}