1 //
2 // Copyright 2022 The Abseil Authors.
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 // https://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 // The testcases in this file are expected to pass or be skipped with any value
17 // of ABSL_MIN_LOG_LEVEL
18
19 #ifndef ABSL_LOG_LOG_BASIC_TEST_IMPL_H_
20 #define ABSL_LOG_LOG_BASIC_TEST_IMPL_H_
21
22 // Verify that both sets of macros behave identically by parameterizing the
23 // entire test file.
24 #ifndef ABSL_TEST_LOG
25 #error ABSL_TEST_LOG must be defined for these tests to work.
26 #endif
27
28 #include <cerrno>
29 #include <sstream>
30 #include <string>
31
32 #include "gmock/gmock.h"
33 #include "gtest/gtest.h"
34 #include "absl/base/internal/sysinfo.h"
35 #include "absl/base/log_severity.h"
36 #include "absl/log/globals.h"
37 #include "absl/log/internal/test_actions.h"
38 #include "absl/log/internal/test_helpers.h"
39 #include "absl/log/internal/test_matchers.h"
40 #include "absl/log/log_entry.h"
41 #include "absl/log/scoped_mock_log.h"
42
43 namespace absl_log_internal {
44 #if GTEST_HAS_DEATH_TEST
45 using ::absl::log_internal::DeathTestExpectedLogging;
46 using ::absl::log_internal::DeathTestUnexpectedLogging;
47 using ::absl::log_internal::DeathTestValidateExpectations;
48 using ::absl::log_internal::DiedOfFatal;
49 using ::absl::log_internal::DiedOfQFatal;
50 #endif
51 using ::absl::log_internal::LoggingEnabledAt;
52 using ::absl::log_internal::LogSeverity;
53 using ::absl::log_internal::Prefix;
54 using ::absl::log_internal::SourceBasename;
55 using ::absl::log_internal::SourceFilename;
56 using ::absl::log_internal::SourceLine;
57 using ::absl::log_internal::Stacktrace;
58 using ::absl::log_internal::TextMessage;
59 using ::absl::log_internal::ThreadID;
60 using ::absl::log_internal::TimestampInMatchWindow;
61 using ::absl::log_internal::Verbosity;
62 using ::testing::AnyNumber;
63 using ::testing::Eq;
64 using ::testing::IsEmpty;
65 using ::testing::IsTrue;
66
67 class BasicLogTest : public testing::TestWithParam<absl::LogSeverityAtLeast> {};
68
ThresholdName(testing::TestParamInfo<absl::LogSeverityAtLeast> severity)69 std::string ThresholdName(
70 testing::TestParamInfo<absl::LogSeverityAtLeast> severity) {
71 std::stringstream ostr;
72 ostr << severity.param;
73 return ostr.str().substr(
74 severity.param == absl::LogSeverityAtLeast::kInfinity ? 0 : 2);
75 }
76
77 INSTANTIATE_TEST_SUITE_P(WithParam, BasicLogTest,
78 testing::Values(absl::LogSeverityAtLeast::kInfo,
79 absl::LogSeverityAtLeast::kWarning,
80 absl::LogSeverityAtLeast::kError,
81 absl::LogSeverityAtLeast::kFatal,
82 absl::LogSeverityAtLeast::kInfinity),
83 ThresholdName);
84
TEST_P(BasicLogTest,Info)85 TEST_P(BasicLogTest, Info) {
86 absl::log_internal::ScopedMinLogLevel scoped_min_log_level(GetParam());
87
88 absl::ScopedMockLog test_sink(absl::MockLogDefault::kDisallowUnexpected);
89
90 const int log_line = __LINE__ + 1;
91 auto do_log = [] { ABSL_TEST_LOG(INFO) << "hello world"; };
92
93 if (LoggingEnabledAt(absl::LogSeverity::kInfo)) {
94 EXPECT_CALL(
95 test_sink,
96 Send(AllOf(SourceFilename(Eq(__FILE__)),
97 SourceBasename(Eq("log_basic_test_impl.h")),
98 SourceLine(Eq(log_line)), Prefix(IsTrue()),
99 LogSeverity(Eq(absl::LogSeverity::kInfo)),
100 TimestampInMatchWindow(),
101 ThreadID(Eq(absl::base_internal::GetTID())),
102 TextMessage(Eq("hello world")),
103 Verbosity(Eq(absl::LogEntry::kNoVerbosityLevel)),
104 ENCODED_MESSAGE(EqualsProto(R"pb(value {
105 literal: "hello world"
106 })pb")),
107 Stacktrace(IsEmpty()))));
108 }
109
110 test_sink.StartCapturingLogs();
111 do_log();
112 }
113
TEST_P(BasicLogTest,Warning)114 TEST_P(BasicLogTest, Warning) {
115 absl::log_internal::ScopedMinLogLevel scoped_min_log_level(GetParam());
116
117 absl::ScopedMockLog test_sink(absl::MockLogDefault::kDisallowUnexpected);
118
119 const int log_line = __LINE__ + 1;
120 auto do_log = [] { ABSL_TEST_LOG(WARNING) << "hello world"; };
121
122 if (LoggingEnabledAt(absl::LogSeverity::kWarning)) {
123 EXPECT_CALL(
124 test_sink,
125 Send(AllOf(SourceFilename(Eq(__FILE__)),
126 SourceBasename(Eq("log_basic_test_impl.h")),
127 SourceLine(Eq(log_line)), Prefix(IsTrue()),
128 LogSeverity(Eq(absl::LogSeverity::kWarning)),
129 TimestampInMatchWindow(),
130 ThreadID(Eq(absl::base_internal::GetTID())),
131 TextMessage(Eq("hello world")),
132 Verbosity(Eq(absl::LogEntry::kNoVerbosityLevel)),
133 ENCODED_MESSAGE(EqualsProto(R"pb(value {
134 literal: "hello world"
135 })pb")),
136 Stacktrace(IsEmpty()))));
137 }
138
139 test_sink.StartCapturingLogs();
140 do_log();
141 }
142
TEST_P(BasicLogTest,Error)143 TEST_P(BasicLogTest, Error) {
144 absl::log_internal::ScopedMinLogLevel scoped_min_log_level(GetParam());
145
146 absl::ScopedMockLog test_sink(absl::MockLogDefault::kDisallowUnexpected);
147
148 const int log_line = __LINE__ + 1;
149 auto do_log = [] { ABSL_TEST_LOG(ERROR) << "hello world"; };
150
151 if (LoggingEnabledAt(absl::LogSeverity::kError)) {
152 EXPECT_CALL(
153 test_sink,
154 Send(AllOf(SourceFilename(Eq(__FILE__)),
155 SourceBasename(Eq("log_basic_test_impl.h")),
156 SourceLine(Eq(log_line)), Prefix(IsTrue()),
157 LogSeverity(Eq(absl::LogSeverity::kError)),
158 TimestampInMatchWindow(),
159 ThreadID(Eq(absl::base_internal::GetTID())),
160 TextMessage(Eq("hello world")),
161 Verbosity(Eq(absl::LogEntry::kNoVerbosityLevel)),
162 ENCODED_MESSAGE(EqualsProto(R"pb(value {
163 literal: "hello world"
164 })pb")),
165 Stacktrace(IsEmpty()))));
166 }
167
168 test_sink.StartCapturingLogs();
169 do_log();
170 }
171
172 #if GTEST_HAS_DEATH_TEST
173 using BasicLogDeathTest = BasicLogTest;
174
175 INSTANTIATE_TEST_SUITE_P(WithParam, BasicLogDeathTest,
176 testing::Values(absl::LogSeverityAtLeast::kInfo,
177 absl::LogSeverityAtLeast::kFatal,
178 absl::LogSeverityAtLeast::kInfinity),
179 ThresholdName);
180
TEST_P(BasicLogDeathTest,Fatal)181 TEST_P(BasicLogDeathTest, Fatal) {
182 absl::log_internal::ScopedMinLogLevel scoped_min_log_level(GetParam());
183
184 const int log_line = __LINE__ + 1;
185 auto do_log = [] { ABSL_TEST_LOG(FATAL) << "hello world"; };
186
187 EXPECT_EXIT(
188 {
189 absl::ScopedMockLog test_sink(
190 absl::MockLogDefault::kDisallowUnexpected);
191
192 EXPECT_CALL(test_sink, Send)
193 .Times(AnyNumber())
194 .WillRepeatedly(DeathTestUnexpectedLogging());
195
196 ::testing::InSequence s;
197
198 // Note the logic in DeathTestValidateExpectations() caters for the case
199 // of logging being disabled at FATAL level.
200
201 if (LoggingEnabledAt(absl::LogSeverity::kFatal)) {
202 // The first call without the stack trace.
203 EXPECT_CALL(
204 test_sink,
205 Send(AllOf(SourceFilename(Eq(__FILE__)),
206 SourceBasename(Eq("log_basic_test_impl.h")),
207 SourceLine(Eq(log_line)), Prefix(IsTrue()),
208 LogSeverity(Eq(absl::LogSeverity::kFatal)),
209 TimestampInMatchWindow(),
210 ThreadID(Eq(absl::base_internal::GetTID())),
211 TextMessage(Eq("hello world")),
212 Verbosity(Eq(absl::LogEntry::kNoVerbosityLevel)),
213 ENCODED_MESSAGE(EqualsProto(
214 R"pb(value { literal: "hello world" })pb")),
215 Stacktrace(IsEmpty()))))
216 .WillOnce(DeathTestExpectedLogging());
217
218 // The second call with the stack trace.
219 EXPECT_CALL(
220 test_sink,
221 Send(AllOf(SourceFilename(Eq(__FILE__)),
222 SourceBasename(Eq("log_basic_test_impl.h")),
223 SourceLine(Eq(log_line)), Prefix(IsTrue()),
224 LogSeverity(Eq(absl::LogSeverity::kFatal)),
225 TimestampInMatchWindow(),
226 ThreadID(Eq(absl::base_internal::GetTID())),
227 TextMessage(Eq("hello world")),
228 Verbosity(Eq(absl::LogEntry::kNoVerbosityLevel)),
229 ENCODED_MESSAGE(EqualsProto(
230 R"pb(value { literal: "hello world" })pb")),
231 Stacktrace(Not(IsEmpty())))))
232 .WillOnce(DeathTestExpectedLogging());
233 }
234
235 test_sink.StartCapturingLogs();
236 do_log();
237 },
238 DiedOfFatal, DeathTestValidateExpectations());
239 }
240
TEST_P(BasicLogDeathTest,QFatal)241 TEST_P(BasicLogDeathTest, QFatal) {
242 absl::log_internal::ScopedMinLogLevel scoped_min_log_level(GetParam());
243
244 const int log_line = __LINE__ + 1;
245 auto do_log = [] { ABSL_TEST_LOG(QFATAL) << "hello world"; };
246
247 EXPECT_EXIT(
248 {
249 absl::ScopedMockLog test_sink(
250 absl::MockLogDefault::kDisallowUnexpected);
251
252 EXPECT_CALL(test_sink, Send)
253 .Times(AnyNumber())
254 .WillRepeatedly(DeathTestUnexpectedLogging());
255
256 if (LoggingEnabledAt(absl::LogSeverity::kFatal)) {
257 EXPECT_CALL(
258 test_sink,
259 Send(AllOf(SourceFilename(Eq(__FILE__)),
260 SourceBasename(Eq("log_basic_test_impl.h")),
261 SourceLine(Eq(log_line)), Prefix(IsTrue()),
262 LogSeverity(Eq(absl::LogSeverity::kFatal)),
263 TimestampInMatchWindow(),
264 ThreadID(Eq(absl::base_internal::GetTID())),
265 TextMessage(Eq("hello world")),
266 Verbosity(Eq(absl::LogEntry::kNoVerbosityLevel)),
267 ENCODED_MESSAGE(EqualsProto(
268 R"pb(value { literal: "hello world" })pb")),
269 Stacktrace(IsEmpty()))))
270 .WillOnce(DeathTestExpectedLogging());
271 }
272
273 test_sink.StartCapturingLogs();
274 do_log();
275 },
276 DiedOfQFatal, DeathTestValidateExpectations());
277 }
278 #endif
279
TEST_P(BasicLogTest,Level)280 TEST_P(BasicLogTest, Level) {
281 absl::log_internal::ScopedMinLogLevel scoped_min_log_level(GetParam());
282
283 for (auto severity : {absl::LogSeverity::kInfo, absl::LogSeverity::kWarning,
284 absl::LogSeverity::kError}) {
285 absl::ScopedMockLog test_sink(absl::MockLogDefault::kDisallowUnexpected);
286
287 const int log_line = __LINE__ + 2;
288 auto do_log = [severity] {
289 ABSL_TEST_LOG(LEVEL(severity)) << "hello world";
290 };
291
292 if (LoggingEnabledAt(severity)) {
293 EXPECT_CALL(
294 test_sink,
295 Send(AllOf(SourceFilename(Eq(__FILE__)),
296 SourceBasename(Eq("log_basic_test_impl.h")),
297 SourceLine(Eq(log_line)), Prefix(IsTrue()),
298 LogSeverity(Eq(severity)), TimestampInMatchWindow(),
299 ThreadID(Eq(absl::base_internal::GetTID())),
300 TextMessage(Eq("hello world")),
301 Verbosity(Eq(absl::LogEntry::kNoVerbosityLevel)),
302 ENCODED_MESSAGE(EqualsProto(R"pb(value {
303 literal: "hello world"
304 })pb")),
305 Stacktrace(IsEmpty()))));
306 }
307 test_sink.StartCapturingLogs();
308 do_log();
309 }
310 }
311
312 #if GTEST_HAS_DEATH_TEST
TEST_P(BasicLogDeathTest,Level)313 TEST_P(BasicLogDeathTest, Level) {
314 // TODO(b/242568884): re-enable once bug is fixed.
315 // absl::log_internal::ScopedMinLogLevel scoped_min_log_level(GetParam());
316
317 // Ensure that `severity` is not a compile-time constant to prove that
318 // `LOG(LEVEL(severity))` works regardless:
319 auto volatile severity = absl::LogSeverity::kFatal;
320
321 const int log_line = __LINE__ + 1;
322 auto do_log = [severity] { ABSL_TEST_LOG(LEVEL(severity)) << "hello world"; };
323
324 EXPECT_EXIT(
325 {
326 absl::ScopedMockLog test_sink(
327 absl::MockLogDefault::kDisallowUnexpected);
328
329 EXPECT_CALL(test_sink, Send)
330 .Times(AnyNumber())
331 .WillRepeatedly(DeathTestUnexpectedLogging());
332
333 ::testing::InSequence s;
334
335 if (LoggingEnabledAt(absl::LogSeverity::kFatal)) {
336 EXPECT_CALL(
337 test_sink,
338 Send(AllOf(SourceFilename(Eq(__FILE__)),
339 SourceBasename(Eq("log_basic_test_impl.h")),
340 SourceLine(Eq(log_line)), Prefix(IsTrue()),
341 LogSeverity(Eq(absl::LogSeverity::kFatal)),
342 TimestampInMatchWindow(),
343 ThreadID(Eq(absl::base_internal::GetTID())),
344 TextMessage(Eq("hello world")),
345 Verbosity(Eq(absl::LogEntry::kNoVerbosityLevel)),
346 ENCODED_MESSAGE(EqualsProto(
347 R"pb(value { literal: "hello world" })pb")),
348 Stacktrace(IsEmpty()))))
349 .WillOnce(DeathTestExpectedLogging());
350
351 EXPECT_CALL(
352 test_sink,
353 Send(AllOf(SourceFilename(Eq(__FILE__)),
354 SourceBasename(Eq("log_basic_test_impl.h")),
355 SourceLine(Eq(log_line)), Prefix(IsTrue()),
356 LogSeverity(Eq(absl::LogSeverity::kFatal)),
357 TimestampInMatchWindow(),
358 ThreadID(Eq(absl::base_internal::GetTID())),
359 TextMessage(Eq("hello world")),
360 Verbosity(Eq(absl::LogEntry::kNoVerbosityLevel)),
361 ENCODED_MESSAGE(EqualsProto(
362 R"pb(value { literal: "hello world" })pb")),
363 Stacktrace(Not(IsEmpty())))))
364 .WillOnce(DeathTestExpectedLogging());
365 }
366
367 test_sink.StartCapturingLogs();
368 do_log();
369 },
370 DiedOfFatal, DeathTestValidateExpectations());
371 }
372 #endif
373
TEST_P(BasicLogTest,LevelClampsNegativeValues)374 TEST_P(BasicLogTest, LevelClampsNegativeValues) {
375 absl::log_internal::ScopedMinLogLevel scoped_min_log_level(GetParam());
376
377 if (!LoggingEnabledAt(absl::LogSeverity::kInfo)) {
378 GTEST_SKIP() << "This test cases required INFO log to be enabled";
379 return;
380 }
381
382 absl::ScopedMockLog test_sink(absl::MockLogDefault::kDisallowUnexpected);
383
384 EXPECT_CALL(test_sink, Send(LogSeverity(Eq(absl::LogSeverity::kInfo))));
385
386 test_sink.StartCapturingLogs();
387 ABSL_TEST_LOG(LEVEL(-1)) << "hello world";
388 }
389
TEST_P(BasicLogTest,LevelClampsLargeValues)390 TEST_P(BasicLogTest, LevelClampsLargeValues) {
391 absl::log_internal::ScopedMinLogLevel scoped_min_log_level(GetParam());
392
393 if (!LoggingEnabledAt(absl::LogSeverity::kError)) {
394 GTEST_SKIP() << "This test cases required ERROR log to be enabled";
395 return;
396 }
397
398 absl::ScopedMockLog test_sink(absl::MockLogDefault::kDisallowUnexpected);
399
400 EXPECT_CALL(test_sink, Send(LogSeverity(Eq(absl::LogSeverity::kError))));
401
402 test_sink.StartCapturingLogs();
403 ABSL_TEST_LOG(LEVEL(static_cast<int>(absl::LogSeverity::kFatal) + 1))
404 << "hello world";
405 }
406
TEST(ErrnoPreservationTest,InSeverityExpression)407 TEST(ErrnoPreservationTest, InSeverityExpression) {
408 errno = 77;
409 int saved_errno;
410 ABSL_TEST_LOG(LEVEL((saved_errno = errno, absl::LogSeverity::kInfo)));
411 EXPECT_THAT(saved_errno, Eq(77));
412 }
413
TEST(ErrnoPreservationTest,InStreamedExpression)414 TEST(ErrnoPreservationTest, InStreamedExpression) {
415 if (!LoggingEnabledAt(absl::LogSeverity::kInfo)) {
416 GTEST_SKIP() << "This test cases required INFO log to be enabled";
417 return;
418 }
419
420 errno = 77;
421 int saved_errno = 0;
422 ABSL_TEST_LOG(INFO) << (saved_errno = errno, "hello world");
423 EXPECT_THAT(saved_errno, Eq(77));
424 }
425
TEST(ErrnoPreservationTest,AfterStatement)426 TEST(ErrnoPreservationTest, AfterStatement) {
427 errno = 77;
428 ABSL_TEST_LOG(INFO);
429 const int saved_errno = errno;
430 EXPECT_THAT(saved_errno, Eq(77));
431 }
432
433 // Tests that using a variable/parameter in a logging statement suppresses
434 // unused-variable/parameter warnings.
435 // -----------------------------------------------------------------------
436 class UnusedVariableWarningCompileTest {
437 // These four don't prove anything unless `ABSL_MIN_LOG_LEVEL` is greater than
438 // `kInfo`.
LoggedVariable()439 static void LoggedVariable() {
440 const int x = 0;
441 ABSL_TEST_LOG(INFO) << x;
442 }
LoggedParameter(const int x)443 static void LoggedParameter(const int x) { ABSL_TEST_LOG(INFO) << x; }
SeverityVariable()444 static void SeverityVariable() {
445 const int x = 0;
446 ABSL_TEST_LOG(LEVEL(x)) << "hello world";
447 }
SeverityParameter(const int x)448 static void SeverityParameter(const int x) {
449 ABSL_TEST_LOG(LEVEL(x)) << "hello world";
450 }
451 };
452
453 } // namespace absl_log_internal
454
455 #endif // ABSL_LOG_LOG_BASIC_TEST_IMPL_H_
456