proxygen
GlogFormatterTest.cpp
Go to the documentation of this file.
1 /*
2  * Copyright 2017-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 <cstdlib>
17 
18 #include <folly/init/Init.h>
21 #include <folly/logging/Logger.h>
22 #include <folly/logging/LoggerDB.h>
25 
26 using namespace folly;
27 
28 namespace {
39 std::string formatMsg(
40  LogLevel level,
41  StringPiece msg,
42  StringPiece filename,
43  unsigned int lineNumber,
44  StringPiece functionName,
45  // Default timestamp: 2017-04-17 13:45:56.123456 UTC
46  uint64_t timestampNS = 1492436756123456789ULL) {
48  auto* category = db.getCategory("test");
49  GlogStyleFormatter formatter;
50 
51  std::chrono::system_clock::time_point logTimePoint{
52  std::chrono::duration_cast<std::chrono::system_clock::duration>(
53  std::chrono::nanoseconds{timestampNS})};
54  LogMessage logMessage{category,
55  level,
56  logTimePoint,
57  filename,
58  lineNumber,
59  functionName,
60  msg.str()};
61 
62  return formatter.formatMessage(logMessage, category);
63 }
64 } // namespace
65 
66 TEST(GlogFormatter, log) {
67  auto tid = getOSThreadID();
68 
69  // Test a very simple single-line log message
70  auto expected = folly::sformat(
71  "W0417 13:45:56.123456 {:5d} myfile.cpp:1234] hello world\n", tid);
72  EXPECT_EQ(
73  expected,
74  formatMsg(
75  LogLevel::WARN, "hello world", "myfile.cpp", 1234, "testFunction"));
76 }
77 
78 TEST(GlogFormatter, filename) {
79  auto tid = getOSThreadID();
80 
81  // Make sure only the file basename gets logged
82  auto expected = folly::sformat(
83  "W0417 13:45:56.123456 {:5d} myfile.cpp:1234] hello world\n", tid);
84  EXPECT_EQ(
85  expected,
86  formatMsg(
88  "hello world",
89  "src/test/logging/code/myfile.cpp",
90  1234,
91  "testFunction"));
92 
93  // Log a message with a very long file name.
94  expected = folly::sformat(
95  "W0417 13:45:56.123456 {:5d} "
96  "this_is_a_really_long_file_name_that_will_probably_exceed_"
97  "our_buffer_allocation_guess.cpp:123456789] oh noes\n",
98  tid);
99  EXPECT_EQ(
100  expected,
101  formatMsg(
103  "oh noes",
104  "this_is_a_really_long_file_name_that_will_probably_exceed_"
105  "our_buffer_allocation_guess.cpp",
106  123456789,
107  "testFunction"));
108 }
109 
110 TEST(GlogFormatter, multiline) {
111  auto tid = getOSThreadID();
112  std::map<std::string, std::string> formatMap{
113  {"tid", folly::to<std::string>(tid)}};
114 
115  // Log a multi-line message
116  auto expected = folly::svformat(
117  "V0417 13:45:56.123456 {tid:>5s} rodent.cpp:777] Eeek, a mouse!\n"
118  "V0417 13:45:56.123456 {tid:>5s} rodent.cpp:777] . .\n"
119  "V0417 13:45:56.123456 {tid:>5s} rodent.cpp:777] ( ).( )\n"
120  "V0417 13:45:56.123456 {tid:>5s} rodent.cpp:777] (o o) .-._.'\n"
121  "V0417 13:45:56.123456 {tid:>5s} rodent.cpp:777] ( - )\n"
122  "V0417 13:45:56.123456 {tid:>5s} rodent.cpp:777] mm mm\n"
123  "V0417 13:45:56.123456 {tid:>5s} rodent.cpp:777] \n"
124  "V0417 13:45:56.123456 {tid:>5s} rodent.cpp:777] =============\n",
125  formatMap);
126  EXPECT_EQ(
127  expected,
128  formatMsg(
130  "Eeek, a mouse!\n"
131  " . .\n"
132  " ( ).( )\n"
133  " (o o) .-._.'\n"
134  " ( - )\n"
135  " mm mm\n"
136  "\n"
137  "=============",
138  "src/rodent.cpp",
139  777,
140  "testFunction"));
141 }
142 
143 TEST(GlogFormatter, singleNewline) {
144  auto tid = getOSThreadID();
145  std::map<std::string, std::string> formatMap{
146  {"tid", folly::to<std::string>(tid)}};
147 
148  // Logging a single newline is basically two empty strings.
149  auto expected = folly::svformat(
150  "V0417 13:45:56.123456 {tid:>5s} foo.txt:123] \n"
151  "V0417 13:45:56.123456 {tid:>5s} foo.txt:123] \n",
152  formatMap);
153  EXPECT_EQ(
154  expected,
155  formatMsg(LogLevel::DBG9, "\n", "foo.txt", 123, "testFunction"));
156 }
157 
158 TEST(GlogFormatter, unprintableChars) {
159  auto tid = getOSThreadID();
160 
161  // Unprintable characters should be backslash escaped, as should backslashes.
162  auto expected = folly::sformat(
163  "E0417 13:45:56.123456 {:5d} escapes.cpp:97] foo\\x07bar\\x1btest\n",
164  tid);
165  EXPECT_EQ(
166  expected,
167  formatMsg(
169  "foo\abar\x1btest",
170  "escapes.cpp",
171  97,
172  "testFunction"));
173  expected = folly::sformat(
174  "I0417 13:45:56.123456 {:5d} escapes.cpp:98] foo\\\\bar\"test\n", tid);
175  EXPECT_EQ(
176  expected,
177  formatMsg(
178  LogLevel::INFO, "foo\\bar\"test", "escapes.cpp", 98, "testFunction"));
179  expected = folly::sformat(
180  "C0417 13:45:56.123456 {:5d} escapes.cpp:99] nul\\x00byte\n", tid);
181  EXPECT_EQ(
182  expected,
183  formatMsg(
185  std::string("nul\0byte", 8),
186  "escapes.cpp",
187  99,
188  "testFunction"));
189 }
190 
191 int main(int argc, char* argv[]) {
192  testing::InitGoogleTest(&argc, argv);
193  folly::init(&argc, &argv);
194 
195  // Some of our tests check timestamps emitted by the formatter.
196  // Set the timezone to a consistent value so that the tests are not
197  // affected by the local time of the user running the test.
198  //
199  // UTC is the only timezone that we can really rely on to work consistently.
200  // This will work even in the absence of a proper tzdata installation on the
201  // local system.
202  setenv("TZ", "UTC", 1);
203 
204  return RUN_ALL_TESTS();
205 }
std::string str() const
Definition: Range.h:591
int RUN_ALL_TESTS() GTEST_MUST_USE_RESULT_
Definition: gtest.h:2232
std::string sformat(StringPiece fmt, Args &&...args)
Definition: Format.h:280
#define EXPECT_EQ(val1, val2)
Definition: gtest.h:1922
—— Concurrent Priority Queue Implementation ——
Definition: AtomicBitSet.h:29
uint64_t getOSThreadID()
Definition: ThreadId.h:80
void init(int *argc, char ***argv, bool removeFlags)
Definition: Init.cpp:34
char ** argv
int main(int argc, char *argv[])
LogLevel
Definition: LogLevel.h:38
std::string svformat(StringPiece fmt, Container &&container)
Definition: Format.h:307
std::string formatMessage(const LogMessage &message, const LogCategory *handlerCategory) override
const char * string
Definition: Conv.cpp:212
GTEST_API_ void InitGoogleTest(int *argc, char **argv)
Definition: gtest.cc:5370
TEST(SequencedExecutor, CPUThreadPoolExecutor)