logging: rename the `DEBUG` log level to `DBG`
[folly.git] / folly / experimental / logging / test / LoggerTest.cpp
index 64c52c2edb6e51e048e7a13676edb2788b0279f5..8172abcb5beffc88a6625f182700cf98afee76b5 100644 (file)
@@ -31,7 +31,7 @@ class LoggerTest : public ::testing::Test {
 
     handler_ = make_shared<TestLogHandler>();
     category->addHandler(handler_);
-    category->setLevel(LogLevel::DEBUG, true);
+    category->setLevel(LogLevel::DBG, true);
   }
 
   static StringPiece pathBasename(StringPiece path) {
@@ -67,14 +67,14 @@ TEST_F(LoggerTest, subCategory) {
   // Log from a sub-category.
   Logger subLogger{&db_, "test.foo.bar"};
   auto expectedLine = __LINE__ + 1;
-  FB_LOG(subLogger, ERROR, "sub-category\nlog message");
+  FB_LOG(subLogger, ERR, "sub-category\nlog message");
 
   auto& messages = handler_->getMessages();
   ASSERT_EQ(1, messages.size());
   EXPECT_EQ("sub-category\nlog message", messages[0].first.getMessage());
   EXPECT_EQ("LoggerTest.cpp", pathBasename(messages[0].first.getFileName()));
   EXPECT_EQ(expectedLine, messages[0].first.getLineNumber());
-  EXPECT_EQ(LogLevel::ERROR, messages[0].first.getLevel());
+  EXPECT_EQ(LogLevel::ERR, messages[0].first.getLevel());
   EXPECT_TRUE(messages[0].first.containsNewlines());
   EXPECT_EQ(subLogger.getCategory(), messages[0].first.getCategory());
   EXPECT_EQ(logger_.getCategory(), messages[0].second);
@@ -107,7 +107,8 @@ TEST_F(LoggerTest, follyFormatError) {
   EXPECT_EQ(
       "error formatting log message: "
       "invalid format argument {:6.3f}: invalid specifier 'f'; "
-      "format string: \"param1: {:06d}, param2: {:6.3f}\"",
+      "format string: \"param1: {:06d}, param2: {:6.3f}\", "
+      "arguments: (int: 1234), (char [13]: hello world!)",
       messages[0].first.getMessage());
   EXPECT_EQ("LoggerTest.cpp", pathBasename(messages[0].first.getFileName()));
   EXPECT_EQ(LogLevel::WARN, messages[0].first.getLevel());
@@ -133,6 +134,7 @@ TEST_F(LoggerTest, toString) {
 }
 
 class ToStringFailure {};
+class FormattableButNoToString {};
 
 [[noreturn]] void toAppend(
     const ToStringFailure& /* arg */,
@@ -141,6 +143,30 @@ class ToStringFailure {};
       "error converting ToStringFailure object to a string");
 }
 
+namespace folly {
+template <>
+class FormatValue<ToStringFailure> {
+ public:
+  explicit FormatValue(ToStringFailure) {}
+
+  template <class FormatCallback>
+  void format(FormatArg& arg, FormatCallback& cb) const {
+    FormatValue<std::string>("ToStringFailure").format(arg, cb);
+  }
+};
+
+template <>
+class FormatValue<FormattableButNoToString> {
+ public:
+  explicit FormatValue(FormattableButNoToString) {}
+
+  template <class FormatCallback>
+  void format(FormatArg&, FormatCallback&) const {
+    throw std::runtime_error("test");
+  }
+};
+} // namespace folly
+
 TEST_F(LoggerTest, toStringError) {
   // Use the folly::to<string> log API, with an object that will throw
   // an exception when we try to convert it to a string.
@@ -165,6 +191,47 @@ TEST_F(LoggerTest, toStringError) {
   EXPECT_EQ(logger_.getCategory(), messages[0].second);
 }
 
+TEST_F(LoggerTest, formatFallbackError) {
+  // Check the behavior if logf() fails, and toAppend() also fails.
+  ToStringFailure obj;
+  FB_LOGF(logger_, WARN, "param1: {}, param2: {}, {}", 1234, obj);
+
+  auto& messages = handler_->getMessages();
+  ASSERT_EQ(1, messages.size());
+  EXPECT_EQ(
+      "error formatting log message: "
+      "invalid format argument {}: argument index out of range, max=2; "
+      "format string: \"param1: {}, param2: {}, {}\", "
+      "arguments: (int: 1234), (ToStringFailure: <error_converting_to_string>)",
+      messages[0].first.getMessage());
+  EXPECT_EQ("LoggerTest.cpp", pathBasename(messages[0].first.getFileName()));
+  EXPECT_EQ(LogLevel::WARN, messages[0].first.getLevel());
+  EXPECT_FALSE(messages[0].first.containsNewlines());
+  EXPECT_EQ(logger_.getCategory(), messages[0].first.getCategory());
+  EXPECT_EQ(logger_.getCategory(), messages[0].second);
+}
+
+TEST_F(LoggerTest, formatFallbackUnsupported) {
+  // Check the behavior if logf() fails, and toAppend() also fails.
+  FormattableButNoToString obj;
+  FB_LOGF(logger_, WARN, "param1: {}, param2: {}", 1234, obj);
+
+  auto& messages = handler_->getMessages();
+  ASSERT_EQ(1, messages.size());
+  EXPECT_EQ(
+      "error formatting log message: "
+      "test; "
+      "format string: \"param1: {}, param2: {}\", "
+      "arguments: (int: 1234), "
+      "(FormattableButNoToString: <no_string_conversion>)",
+      messages[0].first.getMessage());
+  EXPECT_EQ("LoggerTest.cpp", pathBasename(messages[0].first.getFileName()));
+  EXPECT_EQ(LogLevel::WARN, messages[0].first.getLevel());
+  EXPECT_FALSE(messages[0].first.containsNewlines());
+  EXPECT_EQ(logger_.getCategory(), messages[0].first.getCategory());
+  EXPECT_EQ(logger_.getCategory(), messages[0].second);
+}
+
 TEST_F(LoggerTest, streamingArgs) {
   auto& messages = handler_->getMessages();
 
@@ -227,13 +294,13 @@ TEST_F(LoggerTest, logMacros) {
   Logger footest{&db_, "test.foo.test"};
   Logger footest1234{&db_, "test.foo.test.1234"};
   Logger other{&db_, "test.other"};
-  db_.setLevel("test", LogLevel::ERROR);
+  db_.setLevel("test", LogLevel::ERR);
   db_.setLevel("test.foo", LogLevel::DBG2);
   db_.setLevel("test.foo.test", LogLevel::DBG7);
 
   auto& messages = handler_->getMessages();
 
-  // test.other's effective level should be ERROR, so a warning
+  // test.other's effective level should be ERR, so a warning
   // message to it should be discarded
   FB_LOG(other, WARN, "this should be discarded");
   ASSERT_EQ(0, messages.size());
@@ -265,12 +332,13 @@ TEST_F(LoggerTest, logMacros) {
   messages.clear();
 
   // Bad format arguments should not throw
-  FB_LOGF(footest1234, ERROR, "whoops: {}, {}", getValue());
+  FB_LOGF(footest1234, ERR, "whoops: {}, {}", getValue());
   ASSERT_EQ(1, messages.size());
   EXPECT_EQ(
       "error formatting log message: "
       "invalid format argument {}: argument index out of range, max=1; "
-      "format string: \"whoops: {}, {}\"",
+      "format string: \"whoops: {}, {}\", "
+      "arguments: (int: 5)",
       messages[0].first.getMessage());
   messages.clear();
 }