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 <errno.h>
17
18 #include "gmock/gmock.h"
19 #include "gtest/gtest.h"
20 #include "absl/log/internal/test_actions.h"
21 #include "absl/log/internal/test_helpers.h"
22 #include "absl/log/internal/test_matchers.h"
23 #include "absl/log/log.h"
24 #include "absl/log/log_sink.h"
25 #include "absl/log/scoped_mock_log.h"
26 #include "absl/strings/match.h"
27 #include "absl/strings/string_view.h"
28 #include "absl/time/time.h"
29
30 namespace {
31 #if GTEST_HAS_DEATH_TEST
32 using ::absl::log_internal::DeathTestExpectedLogging;
33 using ::absl::log_internal::DeathTestUnexpectedLogging;
34 using ::absl::log_internal::DeathTestValidateExpectations;
35 using ::absl::log_internal::DiedOfQFatal;
36 #endif
37 using ::absl::log_internal::LogSeverity;
38 using ::absl::log_internal::Prefix;
39 using ::absl::log_internal::SourceBasename;
40 using ::absl::log_internal::SourceFilename;
41 using ::absl::log_internal::SourceLine;
42 using ::absl::log_internal::Stacktrace;
43 using ::absl::log_internal::TextMessage;
44 using ::absl::log_internal::TextMessageWithPrefix;
45 using ::absl::log_internal::TextMessageWithPrefixAndNewline;
46 using ::absl::log_internal::TextPrefix;
47 using ::absl::log_internal::ThreadID;
48 using ::absl::log_internal::Timestamp;
49 using ::absl::log_internal::Verbosity;
50
51 using ::testing::AllOf;
52 using ::testing::AnyNumber;
53 using ::testing::AnyOf;
54 using ::testing::Eq;
55 using ::testing::IsEmpty;
56 using ::testing::IsFalse;
57 using ::testing::Truly;
58
TEST(TailCallsModifiesTest,AtLocationFileLine)59 TEST(TailCallsModifiesTest, AtLocationFileLine) {
60 absl::ScopedMockLog test_sink(absl::MockLogDefault::kDisallowUnexpected);
61
62 EXPECT_CALL(
63 test_sink,
64 Send(AllOf(
65 // The metadata should change:
66 SourceFilename(Eq("/my/very/very/very_long_source_file.cc")),
67 SourceBasename(Eq("very_long_source_file.cc")), SourceLine(Eq(777)),
68 // The logged line should change too, even though the prefix must
69 // grow to fit the new metadata.
70 TextMessageWithPrefix(Truly([](absl::string_view msg) {
71 return absl::EndsWith(msg,
72 " very_long_source_file.cc:777] hello world");
73 })))));
74
75 test_sink.StartCapturingLogs();
76 LOG(INFO).AtLocation("/my/very/very/very_long_source_file.cc", 777)
77 << "hello world";
78 }
79
TEST(TailCallsModifiesTest,NoPrefix)80 TEST(TailCallsModifiesTest, NoPrefix) {
81 absl::ScopedMockLog test_sink(absl::MockLogDefault::kDisallowUnexpected);
82
83 EXPECT_CALL(test_sink, Send(AllOf(Prefix(IsFalse()), TextPrefix(IsEmpty()),
84 TextMessageWithPrefix(Eq("hello world")))));
85
86 test_sink.StartCapturingLogs();
87 LOG(INFO).NoPrefix() << "hello world";
88 }
89
TEST(TailCallsModifiesTest,NoPrefixNoMessageNoShirtNoShoesNoService)90 TEST(TailCallsModifiesTest, NoPrefixNoMessageNoShirtNoShoesNoService) {
91 absl::ScopedMockLog test_sink(absl::MockLogDefault::kDisallowUnexpected);
92
93 EXPECT_CALL(test_sink,
94 Send(AllOf(Prefix(IsFalse()), TextPrefix(IsEmpty()),
95 TextMessageWithPrefix(IsEmpty()),
96 TextMessageWithPrefixAndNewline(Eq("\n")))));
97 test_sink.StartCapturingLogs();
98 LOG(INFO).NoPrefix();
99 }
100
TEST(TailCallsModifiesTest,WithVerbosity)101 TEST(TailCallsModifiesTest, WithVerbosity) {
102 absl::ScopedMockLog test_sink(absl::MockLogDefault::kDisallowUnexpected);
103
104 EXPECT_CALL(test_sink, Send(Verbosity(Eq(2))));
105
106 test_sink.StartCapturingLogs();
107 LOG(INFO).WithVerbosity(2) << "hello world";
108 }
109
TEST(TailCallsModifiesTest,WithVerbosityNoVerbosity)110 TEST(TailCallsModifiesTest, WithVerbosityNoVerbosity) {
111 absl::ScopedMockLog test_sink(absl::MockLogDefault::kDisallowUnexpected);
112
113 EXPECT_CALL(test_sink,
114 Send(Verbosity(Eq(absl::LogEntry::kNoVerbosityLevel))));
115
116 test_sink.StartCapturingLogs();
117 LOG(INFO).WithVerbosity(2).WithVerbosity(absl::LogEntry::kNoVerbosityLevel)
118 << "hello world";
119 }
120
TEST(TailCallsModifiesTest,WithTimestamp)121 TEST(TailCallsModifiesTest, WithTimestamp) {
122 absl::ScopedMockLog test_sink(absl::MockLogDefault::kDisallowUnexpected);
123
124 EXPECT_CALL(test_sink, Send(Timestamp(Eq(absl::UnixEpoch()))));
125
126 test_sink.StartCapturingLogs();
127 LOG(INFO).WithTimestamp(absl::UnixEpoch()) << "hello world";
128 }
129
TEST(TailCallsModifiesTest,WithThreadID)130 TEST(TailCallsModifiesTest, WithThreadID) {
131 absl::ScopedMockLog test_sink(absl::MockLogDefault::kDisallowUnexpected);
132
133 EXPECT_CALL(test_sink,
134 Send(AllOf(ThreadID(Eq(absl::LogEntry::tid_t{1234})))));
135
136 test_sink.StartCapturingLogs();
137 LOG(INFO).WithThreadID(1234) << "hello world";
138 }
139
TEST(TailCallsModifiesTest,WithMetadataFrom)140 TEST(TailCallsModifiesTest, WithMetadataFrom) {
141 class ForwardingLogSink : public absl::LogSink {
142 public:
143 void Send(const absl::LogEntry &entry) override {
144 LOG(LEVEL(entry.log_severity())).WithMetadataFrom(entry)
145 << "forwarded: " << entry.text_message();
146 }
147 } forwarding_sink;
148
149 absl::ScopedMockLog test_sink(absl::MockLogDefault::kDisallowUnexpected);
150
151 EXPECT_CALL(
152 test_sink,
153 Send(AllOf(SourceFilename(Eq("fake/file")), SourceBasename(Eq("file")),
154 SourceLine(Eq(123)), Prefix(IsFalse()),
155 LogSeverity(Eq(absl::LogSeverity::kWarning)),
156 Timestamp(Eq(absl::UnixEpoch())),
157 ThreadID(Eq(absl::LogEntry::tid_t{456})),
158 TextMessage(Eq("forwarded: hello world")), Verbosity(Eq(7)),
159 ENCODED_MESSAGE(MatchesEvent(
160 Eq("fake/file"), Eq(123), Eq(absl::UnixEpoch()),
161 Eq(logging::proto::WARNING), Eq(456),
162 ElementsAre(EqualsProto(R"pb(literal: "forwarded: ")pb"),
163 EqualsProto(R"pb(str: "hello world")pb")))))));
164
165 test_sink.StartCapturingLogs();
166 LOG(WARNING)
167 .AtLocation("fake/file", 123)
168 .NoPrefix()
169 .WithTimestamp(absl::UnixEpoch())
170 .WithThreadID(456)
171 .WithVerbosity(7)
172 .ToSinkOnly(&forwarding_sink)
173 << "hello world";
174 }
175
TEST(TailCallsModifiesTest,WithPerror)176 TEST(TailCallsModifiesTest, WithPerror) {
177 absl::ScopedMockLog test_sink(absl::MockLogDefault::kDisallowUnexpected);
178
179 EXPECT_CALL(
180 test_sink,
181 Send(AllOf(TextMessage(AnyOf(Eq("hello world: Bad file number [9]"),
182 Eq("hello world: Bad file descriptor [9]"),
183 Eq("hello world: Bad file descriptor [8]"))),
184 ENCODED_MESSAGE(HasValues(ElementsAre(
185 EqualsProto(R"pb(literal: "hello world")pb"),
186 EqualsProto(R"pb(literal: ": ")pb"),
187 AnyOf(EqualsProto(R"pb(str: "Bad file number")pb"),
188 EqualsProto(R"pb(str: "Bad file descriptor")pb")),
189 EqualsProto(R"pb(literal: " [")pb"),
190 AnyOf(EqualsProto(R"pb(str: "8")pb"),
191 EqualsProto(R"pb(str: "9")pb")),
192 EqualsProto(R"pb(literal: "]")pb")))))));
193
194 test_sink.StartCapturingLogs();
195 errno = EBADF;
196 LOG(INFO).WithPerror() << "hello world";
197 }
198
199 #if GTEST_HAS_DEATH_TEST
TEST(ModifierMethodDeathTest,ToSinkOnlyQFatal)200 TEST(ModifierMethodDeathTest, ToSinkOnlyQFatal) {
201 EXPECT_EXIT(
202 {
203 absl::ScopedMockLog test_sink(
204 absl::MockLogDefault::kDisallowUnexpected);
205
206 auto do_log = [&test_sink] {
207 LOG(QFATAL).ToSinkOnly(&test_sink.UseAsLocalSink()) << "hello world";
208 };
209
210 EXPECT_CALL(test_sink, Send)
211 .Times(AnyNumber())
212 .WillRepeatedly(DeathTestUnexpectedLogging());
213
214 EXPECT_CALL(test_sink, Send(AllOf(TextMessage(Eq("hello world")),
215 Stacktrace(IsEmpty()))))
216 .WillOnce(DeathTestExpectedLogging());
217
218 test_sink.StartCapturingLogs();
219 do_log();
220 },
221 DiedOfQFatal, DeathTestValidateExpectations());
222 }
223 #endif
224
225 } // namespace
226