• 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 #include "absl/log/log_streamer.h"
17 
18 #include <ios>
19 #include <iostream>
20 #include <utility>
21 
22 #include "gmock/gmock.h"
23 #include "gtest/gtest.h"
24 #include "absl/base/attributes.h"
25 #include "absl/base/internal/sysinfo.h"
26 #include "absl/base/log_severity.h"
27 #include "absl/log/internal/test_actions.h"
28 #include "absl/log/internal/test_helpers.h"
29 #include "absl/log/internal/test_matchers.h"
30 #include "absl/log/log.h"
31 #include "absl/log/scoped_mock_log.h"
32 #include "absl/strings/string_view.h"
33 
34 namespace {
35 using ::absl::log_internal::DeathTestExpectedLogging;
36 using ::absl::log_internal::DeathTestUnexpectedLogging;
37 using ::absl::log_internal::DeathTestValidateExpectations;
38 #if GTEST_HAS_DEATH_TEST
39 using ::absl::log_internal::DiedOfFatal;
40 #endif
41 using ::absl::log_internal::LogSeverity;
42 using ::absl::log_internal::Prefix;
43 using ::absl::log_internal::SourceFilename;
44 using ::absl::log_internal::SourceLine;
45 using ::absl::log_internal::Stacktrace;
46 using ::absl::log_internal::TextMessage;
47 using ::absl::log_internal::ThreadID;
48 using ::absl::log_internal::TimestampInMatchWindow;
49 using ::testing::AnyNumber;
50 using ::testing::Eq;
51 using ::testing::HasSubstr;
52 using ::testing::IsEmpty;
53 using ::testing::IsTrue;
54 
55 auto* test_env ABSL_ATTRIBUTE_UNUSED = ::testing::AddGlobalTestEnvironment(
56     new absl::log_internal::LogTestEnvironment);
57 
WriteToStream(absl::string_view data,std::ostream * os)58 void WriteToStream(absl::string_view data, std::ostream* os) {
59   *os << "WriteToStream: " << data;
60 }
WriteToStreamRef(absl::string_view data,std::ostream & os)61 void WriteToStreamRef(absl::string_view data, std::ostream& os) {
62   os << "WriteToStreamRef: " << data;
63 }
64 
TEST(LogStreamerTest,LogInfoStreamer)65 TEST(LogStreamerTest, LogInfoStreamer) {
66   absl::ScopedMockLog test_sink(absl::MockLogDefault::kDisallowUnexpected);
67 
68   EXPECT_CALL(
69       test_sink,
70       Send(AllOf(SourceFilename(Eq("path/file.cc")), SourceLine(Eq(1234)),
71                  Prefix(IsTrue()), LogSeverity(Eq(absl::LogSeverity::kInfo)),
72                  TimestampInMatchWindow(),
73                  ThreadID(Eq(absl::base_internal::GetTID())),
74                  TextMessage(Eq("WriteToStream: foo")),
75                  ENCODED_MESSAGE(EqualsProto(R"pb(value {
76                                                     str: "WriteToStream: foo"
77                                                   })pb")),
78                  Stacktrace(IsEmpty()))));
79 
80   test_sink.StartCapturingLogs();
81   WriteToStream("foo", &absl::LogInfoStreamer("path/file.cc", 1234).stream());
82 }
83 
TEST(LogStreamerTest,LogWarningStreamer)84 TEST(LogStreamerTest, LogWarningStreamer) {
85   absl::ScopedMockLog test_sink(absl::MockLogDefault::kDisallowUnexpected);
86 
87   EXPECT_CALL(
88       test_sink,
89       Send(AllOf(SourceFilename(Eq("path/file.cc")), SourceLine(Eq(1234)),
90                  Prefix(IsTrue()), LogSeverity(Eq(absl::LogSeverity::kWarning)),
91                  TimestampInMatchWindow(),
92                  ThreadID(Eq(absl::base_internal::GetTID())),
93                  TextMessage(Eq("WriteToStream: foo")),
94                  ENCODED_MESSAGE(EqualsProto(R"pb(value {
95                                                     str: "WriteToStream: foo"
96                                                   })pb")),
97                  Stacktrace(IsEmpty()))));
98 
99   test_sink.StartCapturingLogs();
100   WriteToStream("foo",
101                 &absl::LogWarningStreamer("path/file.cc", 1234).stream());
102 }
103 
TEST(LogStreamerTest,LogErrorStreamer)104 TEST(LogStreamerTest, LogErrorStreamer) {
105   absl::ScopedMockLog test_sink(absl::MockLogDefault::kDisallowUnexpected);
106 
107   EXPECT_CALL(
108       test_sink,
109       Send(AllOf(SourceFilename(Eq("path/file.cc")), SourceLine(Eq(1234)),
110                  Prefix(IsTrue()), LogSeverity(Eq(absl::LogSeverity::kError)),
111                  TimestampInMatchWindow(),
112                  ThreadID(Eq(absl::base_internal::GetTID())),
113                  TextMessage(Eq("WriteToStream: foo")),
114                  ENCODED_MESSAGE(EqualsProto(R"pb(value {
115                                                     str: "WriteToStream: foo"
116                                                   })pb")),
117                  Stacktrace(IsEmpty()))));
118 
119   test_sink.StartCapturingLogs();
120   WriteToStream("foo", &absl::LogErrorStreamer("path/file.cc", 1234).stream());
121 }
122 
123 #if GTEST_HAS_DEATH_TEST
TEST(LogStreamerDeathTest,LogFatalStreamer)124 TEST(LogStreamerDeathTest, LogFatalStreamer) {
125   EXPECT_EXIT(
126       {
127         absl::ScopedMockLog test_sink;
128 
129         EXPECT_CALL(test_sink, Send)
130             .Times(AnyNumber())
131             .WillRepeatedly(DeathTestUnexpectedLogging());
132 
133         EXPECT_CALL(
134             test_sink,
135             Send(AllOf(
136                 SourceFilename(Eq("path/file.cc")), SourceLine(Eq(1234)),
137                 Prefix(IsTrue()), LogSeverity(Eq(absl::LogSeverity::kFatal)),
138                 TimestampInMatchWindow(),
139                 ThreadID(Eq(absl::base_internal::GetTID())),
140                 TextMessage(Eq("WriteToStream: foo")),
141                 ENCODED_MESSAGE(EqualsProto(R"pb(value {
142                                                    str: "WriteToStream: foo"
143                                                  })pb")))))
144             .WillOnce(DeathTestExpectedLogging());
145 
146         test_sink.StartCapturingLogs();
147         WriteToStream("foo",
148                       &absl::LogFatalStreamer("path/file.cc", 1234).stream());
149       },
150       DiedOfFatal, DeathTestValidateExpectations());
151 }
152 #endif
153 
154 #ifdef NDEBUG
TEST(LogStreamerTest,LogDebugFatalStreamer)155 TEST(LogStreamerTest, LogDebugFatalStreamer) {
156   absl::ScopedMockLog test_sink(absl::MockLogDefault::kDisallowUnexpected);
157 
158   EXPECT_CALL(
159       test_sink,
160       Send(AllOf(SourceFilename(Eq("path/file.cc")), SourceLine(Eq(1234)),
161                  Prefix(IsTrue()), LogSeverity(Eq(absl::LogSeverity::kError)),
162                  TimestampInMatchWindow(),
163                  ThreadID(Eq(absl::base_internal::GetTID())),
164                  TextMessage(Eq("WriteToStream: foo")),
165                  ENCODED_MESSAGE(EqualsProto(R"pb(value {
166                                                     str: "WriteToStream: foo"
167                                                   })pb")),
168                  Stacktrace(IsEmpty()))));
169 
170   test_sink.StartCapturingLogs();
171   WriteToStream("foo",
172                 &absl::LogDebugFatalStreamer("path/file.cc", 1234).stream());
173 }
174 #elif GTEST_HAS_DEATH_TEST
TEST(LogStreamerDeathTest,LogDebugFatalStreamer)175 TEST(LogStreamerDeathTest, LogDebugFatalStreamer) {
176   EXPECT_EXIT(
177       {
178         absl::ScopedMockLog test_sink;
179 
180         EXPECT_CALL(test_sink, Send)
181             .Times(AnyNumber())
182             .WillRepeatedly(DeathTestUnexpectedLogging());
183 
184         EXPECT_CALL(
185             test_sink,
186             Send(AllOf(
187                 SourceFilename(Eq("path/file.cc")), SourceLine(Eq(1234)),
188                 Prefix(IsTrue()), LogSeverity(Eq(absl::LogSeverity::kFatal)),
189                 TimestampInMatchWindow(),
190                 ThreadID(Eq(absl::base_internal::GetTID())),
191                 TextMessage(Eq("WriteToStream: foo")),
192                 ENCODED_MESSAGE(EqualsProto(R"pb(value {
193                                                    str: "WriteToStream: foo"
194                                                  })pb")))))
195             .WillOnce(DeathTestExpectedLogging());
196 
197         test_sink.StartCapturingLogs();
198         WriteToStream(
199             "foo", &absl::LogDebugFatalStreamer("path/file.cc", 1234).stream());
200       },
201       DiedOfFatal, DeathTestValidateExpectations());
202 }
203 #endif
204 
TEST(LogStreamerTest,LogStreamer)205 TEST(LogStreamerTest, LogStreamer) {
206   absl::ScopedMockLog test_sink(absl::MockLogDefault::kDisallowUnexpected);
207 
208   EXPECT_CALL(
209       test_sink,
210       Send(AllOf(SourceFilename(Eq("path/file.cc")), SourceLine(Eq(1234)),
211                  Prefix(IsTrue()), LogSeverity(Eq(absl::LogSeverity::kError)),
212                  TimestampInMatchWindow(),
213                  ThreadID(Eq(absl::base_internal::GetTID())),
214                  TextMessage(Eq("WriteToStream: foo")),
215                  ENCODED_MESSAGE(EqualsProto(R"pb(value {
216                                                     str: "WriteToStream: foo"
217                                                   })pb")),
218                  Stacktrace(IsEmpty()))));
219 
220   test_sink.StartCapturingLogs();
221   WriteToStream(
222       "foo", &absl::LogStreamer(absl::LogSeverity::kError, "path/file.cc", 1234)
223                   .stream());
224 }
225 
226 #if GTEST_HAS_DEATH_TEST
TEST(LogStreamerDeathTest,LogStreamer)227 TEST(LogStreamerDeathTest, LogStreamer) {
228   EXPECT_EXIT(
229       {
230         absl::ScopedMockLog test_sink;
231 
232         EXPECT_CALL(test_sink, Send)
233             .Times(AnyNumber())
234             .WillRepeatedly(DeathTestUnexpectedLogging());
235 
236         EXPECT_CALL(
237             test_sink,
238             Send(AllOf(
239                 SourceFilename(Eq("path/file.cc")), SourceLine(Eq(1234)),
240                 Prefix(IsTrue()), LogSeverity(Eq(absl::LogSeverity::kFatal)),
241                 TimestampInMatchWindow(),
242                 ThreadID(Eq(absl::base_internal::GetTID())),
243                 TextMessage(Eq("WriteToStream: foo")),
244                 ENCODED_MESSAGE(EqualsProto(R"pb(value {
245                                                    str: "WriteToStream: foo"
246                                                  })pb")))))
247             .WillOnce(DeathTestExpectedLogging());
248 
249         test_sink.StartCapturingLogs();
250         WriteToStream("foo", &absl::LogStreamer(absl::LogSeverity::kFatal,
251                                                 "path/file.cc", 1234)
252                                   .stream());
253       },
254       DiedOfFatal, DeathTestValidateExpectations());
255 }
256 #endif
257 
TEST(LogStreamerTest,PassedByReference)258 TEST(LogStreamerTest, PassedByReference) {
259   absl::ScopedMockLog test_sink(absl::MockLogDefault::kDisallowUnexpected);
260 
261   EXPECT_CALL(
262       test_sink,
263       Send(AllOf(SourceFilename(Eq("path/file.cc")), SourceLine(Eq(1234)),
264                  TextMessage(Eq("WriteToStreamRef: foo")),
265                  ENCODED_MESSAGE(EqualsProto(R"pb(value {
266                                                     str: "WriteToStreamRef: foo"
267                                                   })pb")),
268                  Stacktrace(IsEmpty()))));
269 
270   test_sink.StartCapturingLogs();
271   WriteToStreamRef("foo", absl::LogInfoStreamer("path/file.cc", 1234).stream());
272 }
273 
TEST(LogStreamerTest,StoredAsLocal)274 TEST(LogStreamerTest, StoredAsLocal) {
275   absl::ScopedMockLog test_sink(absl::MockLogDefault::kDisallowUnexpected);
276 
277   auto streamer = absl::LogInfoStreamer("path/file.cc", 1234);
278   WriteToStream("foo", &streamer.stream());
279   streamer.stream() << " ";
280   WriteToStreamRef("bar", streamer.stream());
281 
282   // The call should happen when `streamer` goes out of scope; if it
283   // happened before this `EXPECT_CALL` the call would be unexpected and the
284   // test would fail.
285   EXPECT_CALL(
286       test_sink,
287       Send(AllOf(SourceFilename(Eq("path/file.cc")), SourceLine(Eq(1234)),
288                  TextMessage(Eq("WriteToStream: foo WriteToStreamRef: bar")),
289                  ENCODED_MESSAGE(EqualsProto(
290                      R"pb(value {
291                             str: "WriteToStream: foo WriteToStreamRef: bar"
292                           })pb")),
293                  Stacktrace(IsEmpty()))));
294 
295   test_sink.StartCapturingLogs();
296 }
297 
298 #if GTEST_HAS_DEATH_TEST
TEST(LogStreamerDeathTest,StoredAsLocal)299 TEST(LogStreamerDeathTest, StoredAsLocal) {
300   EXPECT_EXIT(
301       {
302         // This is fatal when it goes out of scope, but not until then:
303         auto streamer = absl::LogFatalStreamer("path/file.cc", 1234);
304         std::cerr << "I'm still alive" << std::endl;
305         WriteToStream("foo", &streamer.stream());
306       },
307       DiedOfFatal, HasSubstr("I'm still alive"));
308 }
309 #endif
310 
TEST(LogStreamerTest,LogsEmptyLine)311 TEST(LogStreamerTest, LogsEmptyLine) {
312   absl::ScopedMockLog test_sink(absl::MockLogDefault::kDisallowUnexpected);
313 
314   EXPECT_CALL(test_sink, Send(AllOf(SourceFilename(Eq("path/file.cc")),
315                                     SourceLine(Eq(1234)), TextMessage(Eq("")),
316                                     ENCODED_MESSAGE(EqualsProto(R"pb(value {
317                                                                        str: ""
318                                                                      })pb")),
319                                     Stacktrace(IsEmpty()))));
320 
321   test_sink.StartCapturingLogs();
322   absl::LogInfoStreamer("path/file.cc", 1234);
323 }
324 
325 #if GTEST_HAS_DEATH_TEST
TEST(LogStreamerDeathTest,LogsEmptyLine)326 TEST(LogStreamerDeathTest, LogsEmptyLine) {
327   EXPECT_EXIT(
328       {
329         absl::ScopedMockLog test_sink;
330 
331         EXPECT_CALL(test_sink, Log)
332             .Times(AnyNumber())
333             .WillRepeatedly(DeathTestUnexpectedLogging());
334 
335         EXPECT_CALL(
336             test_sink,
337             Send(AllOf(
338                 SourceFilename(Eq("path/file.cc")), TextMessage(Eq("")),
339                 ENCODED_MESSAGE(EqualsProto(R"pb(value { str: "" })pb")))))
340             .WillOnce(DeathTestExpectedLogging());
341 
342         test_sink.StartCapturingLogs();
343         // This is fatal even though it's never used:
344         auto streamer = absl::LogFatalStreamer("path/file.cc", 1234);
345       },
346       DiedOfFatal, DeathTestValidateExpectations());
347 }
348 #endif
349 
TEST(LogStreamerTest,MoveConstruction)350 TEST(LogStreamerTest, MoveConstruction) {
351   absl::ScopedMockLog test_sink(absl::MockLogDefault::kDisallowUnexpected);
352 
353   EXPECT_CALL(
354       test_sink,
355       Send(AllOf(SourceFilename(Eq("path/file.cc")), SourceLine(Eq(1234)),
356                  LogSeverity(Eq(absl::LogSeverity::kInfo)),
357                  TextMessage(Eq("hello 0x10 world 0x10")),
358                  ENCODED_MESSAGE(EqualsProto(R"pb(value {
359                                                     str: "hello 0x10 world 0x10"
360                                                   })pb")),
361                  Stacktrace(IsEmpty()))));
362 
363   test_sink.StartCapturingLogs();
364   auto streamer1 = absl::LogInfoStreamer("path/file.cc", 1234);
365   streamer1.stream() << "hello " << std::hex << 16;
366   absl::LogStreamer streamer2(std::move(streamer1));
367   streamer2.stream() << " world " << 16;
368 }
369 
TEST(LogStreamerTest,MoveAssignment)370 TEST(LogStreamerTest, MoveAssignment) {
371   absl::ScopedMockLog test_sink(absl::MockLogDefault::kDisallowUnexpected);
372 
373   testing::InSequence seq;
374   EXPECT_CALL(
375       test_sink,
376       Send(AllOf(SourceFilename(Eq("path/file2.cc")), SourceLine(Eq(5678)),
377                  LogSeverity(Eq(absl::LogSeverity::kWarning)),
378                  TextMessage(Eq("something else")),
379                  ENCODED_MESSAGE(EqualsProto(R"pb(value {
380                                                     str: "something else"
381                                                   })pb")),
382                  Stacktrace(IsEmpty()))));
383   EXPECT_CALL(
384       test_sink,
385       Send(AllOf(SourceFilename(Eq("path/file.cc")), SourceLine(Eq(1234)),
386                  LogSeverity(Eq(absl::LogSeverity::kInfo)),
387                  TextMessage(Eq("hello 0x10 world 0x10")),
388                  ENCODED_MESSAGE(EqualsProto(R"pb(value {
389                                                     str: "hello 0x10 world 0x10"
390                                                   })pb")),
391                  Stacktrace(IsEmpty()))));
392 
393   test_sink.StartCapturingLogs();
394   auto streamer1 = absl::LogInfoStreamer("path/file.cc", 1234);
395   streamer1.stream() << "hello " << std::hex << 16;
396   auto streamer2 = absl::LogWarningStreamer("path/file2.cc", 5678);
397   streamer2.stream() << "something else";
398   streamer2 = std::move(streamer1);
399   streamer2.stream() << " world " << 16;
400 }
401 
TEST(LogStreamerTest,CorrectDefaultFlags)402 TEST(LogStreamerTest, CorrectDefaultFlags) {
403   absl::ScopedMockLog test_sink(absl::MockLogDefault::kDisallowUnexpected);
404 
405   // The `boolalpha` and `showbase` flags should be set by default, to match
406   // `LOG`.
407   EXPECT_CALL(test_sink, Send(AllOf(TextMessage(Eq("false0xdeadbeef")))))
408       .Times(2);
409 
410   test_sink.StartCapturingLogs();
411   absl::LogInfoStreamer("path/file.cc", 1234).stream()
412       << false << std::hex << 0xdeadbeef;
413   LOG(INFO) << false << std::hex << 0xdeadbeef;
414 }
415 
416 }  // namespace
417