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