• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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
43namespace absl_log_internal {
44#if GTEST_HAS_DEATH_TEST
45using ::absl::log_internal::DeathTestExpectedLogging;
46using ::absl::log_internal::DeathTestUnexpectedLogging;
47using ::absl::log_internal::DeathTestValidateExpectations;
48using ::absl::log_internal::DiedOfFatal;
49using ::absl::log_internal::DiedOfQFatal;
50#endif
51using ::absl::log_internal::LoggingEnabledAt;
52using ::absl::log_internal::LogSeverity;
53using ::absl::log_internal::Prefix;
54using ::absl::log_internal::SourceBasename;
55using ::absl::log_internal::SourceFilename;
56using ::absl::log_internal::SourceLine;
57using ::absl::log_internal::Stacktrace;
58using ::absl::log_internal::TextMessage;
59using ::absl::log_internal::ThreadID;
60using ::absl::log_internal::TimestampInMatchWindow;
61using ::absl::log_internal::Verbosity;
62using ::testing::AnyNumber;
63using ::testing::Eq;
64using ::testing::IsEmpty;
65using ::testing::IsTrue;
66
67class BasicLogTest : public testing::TestWithParam<absl::LogSeverityAtLeast> {};
68
69std::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
77INSTANTIATE_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
85TEST_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.inc")),
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
114TEST_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.inc")),
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
143TEST_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.inc")),
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
173using BasicLogDeathTest = BasicLogTest;
174
175INSTANTIATE_TEST_SUITE_P(WithParam, BasicLogDeathTest,
176                         testing::Values(absl::LogSeverityAtLeast::kInfo,
177                                         absl::LogSeverityAtLeast::kFatal,
178                                         absl::LogSeverityAtLeast::kInfinity),
179                         ThresholdName);
180
181TEST_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.inc")),
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.inc")),
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
241TEST_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.inc")),
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
280TEST_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.inc")),
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
313TEST_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.inc")),
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.inc")),
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
374TEST_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
390TEST_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
407TEST(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
414TEST(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
426TEST(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// -----------------------------------------------------------------------
436class UnusedVariableWarningCompileTest {
437  // These four don't prove anything unless `ABSL_MIN_LOG_LEVEL` is greater than
438  // `kInfo`.
439  static void LoggedVariable() {
440    const int x = 0;
441    ABSL_TEST_LOG(INFO) << x;
442  }
443  static void LoggedParameter(const int x) { ABSL_TEST_LOG(INFO) << x; }
444  static void SeverityVariable() {
445    const int x = 0;
446    ABSL_TEST_LOG(LEVEL(x)) << "hello world";
447  }
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