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 #include "gmock/gmock.h"
17 #include "gtest/gtest.h"
18 #include "absl/base/attributes.h"
19 #include "absl/base/log_severity.h"
20 #include "absl/log/log.h"
21 #include "absl/log/scoped_mock_log.h"
22
23 namespace {
24 using ::testing::_;
25 using ::testing::Eq;
26
27 namespace not_absl {
28
29 class Dummy {
30 public:
Dummy()31 Dummy() {}
32
33 private:
34 Dummy(const Dummy&) = delete;
35 Dummy& operator=(const Dummy&) = delete;
36 };
37
38 // This line tests that local definitions of INFO, WARNING, ERROR, and
39 // etc don't shadow the global ones used by the logging macros. If
40 // they do, the LOG() calls in the tests won't compile, catching the
41 // bug.
42 const Dummy INFO, WARNING, ERROR, FATAL, NUM_SEVERITIES;
43
44 // These makes sure that the uses of same-named types in the
45 // implementation of the logging macros are fully qualified.
46 class string {};
47 class vector {};
48 class LogMessage {};
49 class LogMessageFatal {};
50 class LogMessageQuietlyFatal {};
51 class LogMessageVoidify {};
52 class LogSink {};
53 class NullStream {};
54 class NullStreamFatal {};
55
56 } // namespace not_absl
57
58 using namespace not_absl; // NOLINT
59
60 // Tests for LOG(LEVEL(()).
61
TEST(LogHygieneTest,WorksForQualifiedSeverity)62 TEST(LogHygieneTest, WorksForQualifiedSeverity) {
63 absl::ScopedMockLog test_sink(absl::MockLogDefault::kDisallowUnexpected);
64
65 ::testing::InSequence seq;
66 EXPECT_CALL(test_sink, Log(absl::LogSeverity::kInfo, _, "To INFO"));
67 EXPECT_CALL(test_sink, Log(absl::LogSeverity::kWarning, _, "To WARNING"));
68 EXPECT_CALL(test_sink, Log(absl::LogSeverity::kError, _, "To ERROR"));
69
70 test_sink.StartCapturingLogs();
71 // Note that LOG(LEVEL()) expects the severity as a run-time
72 // expression (as opposed to a compile-time constant). Hence we
73 // test that :: is allowed before INFO, etc.
74 LOG(LEVEL(absl::LogSeverity::kInfo)) << "To INFO";
75 LOG(LEVEL(absl::LogSeverity::kWarning)) << "To WARNING";
76 LOG(LEVEL(absl::LogSeverity::kError)) << "To ERROR";
77 }
78
TEST(LogHygieneTest,WorksWithAlternativeINFOSymbol)79 TEST(LogHygieneTest, WorksWithAlternativeINFOSymbol) {
80 const double INFO ABSL_ATTRIBUTE_UNUSED = 7.77;
81 absl::ScopedMockLog test_sink(absl::MockLogDefault::kDisallowUnexpected);
82
83 EXPECT_CALL(test_sink, Log(absl::LogSeverity::kInfo, _, "Hello world"));
84
85 test_sink.StartCapturingLogs();
86 LOG(INFO) << "Hello world";
87 }
88
TEST(LogHygieneTest,WorksWithAlternativeWARNINGSymbol)89 TEST(LogHygieneTest, WorksWithAlternativeWARNINGSymbol) {
90 const double WARNING ABSL_ATTRIBUTE_UNUSED = 7.77;
91 absl::ScopedMockLog test_sink(absl::MockLogDefault::kDisallowUnexpected);
92
93 EXPECT_CALL(test_sink, Log(absl::LogSeverity::kWarning, _, "Hello world"));
94
95 test_sink.StartCapturingLogs();
96 LOG(WARNING) << "Hello world";
97 }
98
TEST(LogHygieneTest,WorksWithAlternativeERRORSymbol)99 TEST(LogHygieneTest, WorksWithAlternativeERRORSymbol) {
100 const double ERROR ABSL_ATTRIBUTE_UNUSED = 7.77;
101 absl::ScopedMockLog test_sink(absl::MockLogDefault::kDisallowUnexpected);
102
103 EXPECT_CALL(test_sink, Log(absl::LogSeverity::kError, _, "Hello world"));
104
105 test_sink.StartCapturingLogs();
106 LOG(ERROR) << "Hello world";
107 }
108
TEST(LogHygieneTest,WorksWithAlternativeLEVELSymbol)109 TEST(LogHygieneTest, WorksWithAlternativeLEVELSymbol) {
110 const double LEVEL ABSL_ATTRIBUTE_UNUSED = 7.77;
111 absl::ScopedMockLog test_sink(absl::MockLogDefault::kDisallowUnexpected);
112
113 EXPECT_CALL(test_sink, Log(absl::LogSeverity::kError, _, "Hello world"));
114
115 test_sink.StartCapturingLogs();
116 LOG(LEVEL(absl::LogSeverity::kError)) << "Hello world";
117 }
118
119 #define INFO Bogus
120 #ifdef NDEBUG
121 constexpr bool IsOptimized = false;
122 #else
123 constexpr bool IsOptimized = true;
124 #endif
125
TEST(LogHygieneTest,WorksWithINFODefined)126 TEST(LogHygieneTest, WorksWithINFODefined) {
127 absl::ScopedMockLog test_sink(absl::MockLogDefault::kDisallowUnexpected);
128
129 EXPECT_CALL(test_sink, Log(absl::LogSeverity::kInfo, _, "Hello world"))
130 .Times(2 + (IsOptimized ? 2 : 0));
131
132 test_sink.StartCapturingLogs();
133 LOG(INFO) << "Hello world";
134 LOG_IF(INFO, true) << "Hello world";
135
136 DLOG(INFO) << "Hello world";
137 DLOG_IF(INFO, true) << "Hello world";
138 }
139
140 #undef INFO
141
142 #define _INFO Bogus
TEST(LogHygieneTest,WorksWithUnderscoreINFODefined)143 TEST(LogHygieneTest, WorksWithUnderscoreINFODefined) {
144 absl::ScopedMockLog test_sink(absl::MockLogDefault::kDisallowUnexpected);
145
146 EXPECT_CALL(test_sink, Log(absl::LogSeverity::kInfo, _, "Hello world"))
147 .Times(2 + (IsOptimized ? 2 : 0));
148
149 test_sink.StartCapturingLogs();
150 LOG(INFO) << "Hello world";
151 LOG_IF(INFO, true) << "Hello world";
152
153 DLOG(INFO) << "Hello world";
154 DLOG_IF(INFO, true) << "Hello world";
155 }
156 #undef _INFO
157
TEST(LogHygieneTest,ExpressionEvaluationInLEVELSeverity)158 TEST(LogHygieneTest, ExpressionEvaluationInLEVELSeverity) {
159 auto i = static_cast<int>(absl::LogSeverity::kInfo);
160 LOG(LEVEL(++i)) << "hello world"; // NOLINT
161 EXPECT_THAT(i, Eq(static_cast<int>(absl::LogSeverity::kInfo) + 1));
162 }
163
TEST(LogHygieneTest,ExpressionEvaluationInStreamedMessage)164 TEST(LogHygieneTest, ExpressionEvaluationInStreamedMessage) {
165 int i = 0;
166 LOG(INFO) << ++i;
167 EXPECT_THAT(i, 1);
168 LOG_IF(INFO, false) << ++i;
169 EXPECT_THAT(i, 1);
170 }
171
172 // Tests that macros are usable in unbraced switch statements.
173 // -----------------------------------------------------------
174
175 class UnbracedSwitchCompileTest {
Log()176 static void Log() {
177 switch (0) {
178 case 0:
179 LOG(INFO);
180 break;
181 default:
182 break;
183 }
184 }
185 };
186
187 } // namespace
188