02f04bced95e4e44b4241931221e3a406f30ac3c
[folly.git] / folly / experimental / logging / test / PrintfTest.cpp
1 /*
2  * Copyright 2004-present Facebook, Inc.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *   http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 #include <folly/experimental/logging/printf.h>
17 #include <folly/experimental/logging/test/TestLogHandler.h>
18 #include <folly/portability/GTest.h>
19
20 using namespace folly;
21 using std::make_shared;
22
23 TEST(PrintfTest, printfStyleMacros) {
24   LoggerDB db{LoggerDB::TESTING};
25   Logger logger{&db, "test"};
26   auto* category = logger.getCategory();
27
28   auto handler = make_shared<TestLogHandler>();
29   category->addHandler(handler);
30   category->setLevel(LogLevel::DEBUG, true);
31
32   Logger foo{&db, "test.foo.bar"};
33   Logger foobar{&db, "test.foo.bar"};
34   Logger footest{&db, "test.foo.test"};
35   Logger footest1234{&db, "test.foo.test.1234"};
36   Logger other{&db, "test.other"};
37   db.setLevel("test", LogLevel::ERROR);
38   db.setLevel("test.foo", LogLevel::DBG2);
39   db.setLevel("test.foo.test", LogLevel::DBG7);
40
41   auto& messages = handler->getMessages();
42
43   // test.other's effective level should be ERROR, so a warning
44   // message to it should be discarded
45   FB_LOGC(other, WARN, "this should be discarded: %d", 5);
46   ASSERT_EQ(0, messages.size());
47
48   // Disabled log messages should not evaluate their arguments
49   bool argumentEvaluated = false;
50   auto getValue = [&] {
51     argumentEvaluated = true;
52     return 5;
53   };
54   FB_LOGC(foobar, DBG3, "discarded message: %d", getValue());
55   EXPECT_FALSE(argumentEvaluated);
56
57   FB_LOGC(foobar, DBG1, "this message should pass: %d", getValue());
58   ASSERT_EQ(1, messages.size());
59   EXPECT_EQ("this message should pass: 5", messages[0].first.getMessage());
60   EXPECT_TRUE(argumentEvaluated);
61   messages.clear();
62
63   // The FB_LOGC() macro should work even if the format string does not contain
64   // any format sequences.  Ideally people would just use FB_LOG() if they
65   // aren't actually formatting anything, but making FB_LOGC() work in this
66   // scenario still makes it easier for people to switch legacy printf-style
67   // code to FB_LOGC().
68   FB_LOGC(foobar, DBG1, "no actual format arguments");
69   ASSERT_EQ(1, messages.size());
70   EXPECT_EQ("no actual format arguments", messages[0].first.getMessage());
71   messages.clear();
72
73   // Similar checks with XLOGC()
74   auto* xlogCategory = XLOG_GET_CATEGORY();
75   xlogCategory->addHandler(handler);
76   xlogCategory->setLevel(LogLevel::DBG5, true);
77
78   argumentEvaluated = false;
79   XLOGC(DBG9, "failing log check: %d", getValue());
80   EXPECT_FALSE(argumentEvaluated);
81
82   XLOGC(DBG5, "passing log: %03d", getValue());
83   ASSERT_EQ(1, messages.size());
84   EXPECT_EQ("passing log: 005", messages[0].first.getMessage());
85   EXPECT_TRUE(argumentEvaluated);
86   messages.clear();
87
88   XLOGC(DBG1, "no xlog format arguments");
89   ASSERT_EQ(1, messages.size());
90   EXPECT_EQ("no xlog format arguments", messages[0].first.getMessage());
91   messages.clear();
92
93   // Errors attempting to format the message should not throw
94   FB_LOGC(footest1234, ERROR, "width overflow: %999999999999999999999d", 5);
95   ASSERT_EQ(1, messages.size());
96   EXPECT_EQ(
97       "error formatting printf-style log message: "
98       "width overflow: %999999999999999999999d",
99       messages[0].first.getMessage());
100   messages.clear();
101 }