replace BackTrace::print() with the operator<< where the former is used.
Signed-off-by: Kefu Chai <kchai@redhat.com>
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++) {
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
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",
// 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>` "
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;
// 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>` "
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;
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);
++q) {
lockdep_dout(0) << " * " << lock_names[q->first] << "\n";
if (q->second)
- q->second->print(*_dout);
+ *_dout << *(q->second);
*_dout << dendl;
}
}
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)
--- /dev/null
+// -*- 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));
+}