• 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/internal/test_matchers.h"
17 
18 #include <sstream>
19 #include <string>
20 #include <utility>
21 
22 #include "gmock/gmock.h"
23 #include "gtest/gtest.h"
24 #include "absl/base/config.h"
25 #include "absl/log/internal/config.h"
26 #include "absl/log/internal/test_helpers.h"
27 #include "absl/strings/string_view.h"
28 #include "absl/time/clock.h"
29 #include "absl/time/time.h"
30 
31 namespace absl {
32 ABSL_NAMESPACE_BEGIN
33 namespace log_internal {
34 
SourceFilename(const::testing::Matcher<absl::string_view> & source_filename)35 ::testing::Matcher<const absl::LogEntry&> SourceFilename(
36     const ::testing::Matcher<absl::string_view>& source_filename) {
37   return Property("source_filename", &absl::LogEntry::source_filename,
38                   source_filename);
39 }
40 
SourceBasename(const::testing::Matcher<absl::string_view> & source_basename)41 ::testing::Matcher<const absl::LogEntry&> SourceBasename(
42     const ::testing::Matcher<absl::string_view>& source_basename) {
43   return Property("source_basename", &absl::LogEntry::source_basename,
44                   source_basename);
45 }
46 
SourceLine(const::testing::Matcher<int> & source_line)47 ::testing::Matcher<const absl::LogEntry&> SourceLine(
48     const ::testing::Matcher<int>& source_line) {
49   return Property("source_line", &absl::LogEntry::source_line, source_line);
50 }
51 
Prefix(const::testing::Matcher<bool> & prefix)52 ::testing::Matcher<const absl::LogEntry&> Prefix(
53     const ::testing::Matcher<bool>& prefix) {
54   return Property("prefix", &absl::LogEntry::prefix, prefix);
55 }
56 
LogSeverity(const::testing::Matcher<absl::LogSeverity> & log_severity)57 ::testing::Matcher<const absl::LogEntry&> LogSeverity(
58     const ::testing::Matcher<absl::LogSeverity>& log_severity) {
59   return Property("log_severity", &absl::LogEntry::log_severity, log_severity);
60 }
61 
Timestamp(const::testing::Matcher<absl::Time> & timestamp)62 ::testing::Matcher<const absl::LogEntry&> Timestamp(
63     const ::testing::Matcher<absl::Time>& timestamp) {
64   return Property("timestamp", &absl::LogEntry::timestamp, timestamp);
65 }
66 
TimestampInMatchWindow()67 ::testing::Matcher<const absl::LogEntry&> TimestampInMatchWindow() {
68   return Property("timestamp", &absl::LogEntry::timestamp,
69                   ::testing::AllOf(::testing::Ge(absl::Now()),
70                                    ::testing::Truly([](absl::Time arg) {
71                                      return arg <= absl::Now();
72                                    })));
73 }
74 
ThreadID(const::testing::Matcher<absl::LogEntry::tid_t> & tid)75 ::testing::Matcher<const absl::LogEntry&> ThreadID(
76     const ::testing::Matcher<absl::LogEntry::tid_t>& tid) {
77   return Property("tid", &absl::LogEntry::tid, tid);
78 }
79 
TextMessageWithPrefixAndNewline(const::testing::Matcher<absl::string_view> & text_message_with_prefix_and_newline)80 ::testing::Matcher<const absl::LogEntry&> TextMessageWithPrefixAndNewline(
81     const ::testing::Matcher<absl::string_view>&
82         text_message_with_prefix_and_newline) {
83   return Property("text_message_with_prefix_and_newline",
84                   &absl::LogEntry::text_message_with_prefix_and_newline,
85                   text_message_with_prefix_and_newline);
86 }
87 
TextMessageWithPrefix(const::testing::Matcher<absl::string_view> & text_message_with_prefix)88 ::testing::Matcher<const absl::LogEntry&> TextMessageWithPrefix(
89     const ::testing::Matcher<absl::string_view>& text_message_with_prefix) {
90   return Property("text_message_with_prefix",
91                   &absl::LogEntry::text_message_with_prefix,
92                   text_message_with_prefix);
93 }
94 
TextMessage(const::testing::Matcher<absl::string_view> & text_message)95 ::testing::Matcher<const absl::LogEntry&> TextMessage(
96     const ::testing::Matcher<absl::string_view>& text_message) {
97   return Property("text_message", &absl::LogEntry::text_message, text_message);
98 }
99 
TextPrefix(const::testing::Matcher<absl::string_view> & text_prefix)100 ::testing::Matcher<const absl::LogEntry&> TextPrefix(
101     const ::testing::Matcher<absl::string_view>& text_prefix) {
102   return ResultOf(
103       [](const absl::LogEntry& entry) {
104         absl::string_view msg = entry.text_message_with_prefix();
105         msg.remove_suffix(entry.text_message().size());
106         return msg;
107       },
108       text_prefix);
109 }
110 
Verbosity(const::testing::Matcher<int> & verbosity)111 ::testing::Matcher<const absl::LogEntry&> Verbosity(
112     const ::testing::Matcher<int>& verbosity) {
113   return Property("verbosity", &absl::LogEntry::verbosity, verbosity);
114 }
115 
Stacktrace(const::testing::Matcher<absl::string_view> & stacktrace)116 ::testing::Matcher<const absl::LogEntry&> Stacktrace(
117     const ::testing::Matcher<absl::string_view>& stacktrace) {
118   return Property("stacktrace", &absl::LogEntry::stacktrace, stacktrace);
119 }
120 
121 class MatchesOstreamImpl final
122     : public ::testing::MatcherInterface<absl::string_view> {
123  public:
MatchesOstreamImpl(std::string expected)124   explicit MatchesOstreamImpl(std::string expected)
125       : expected_(std::move(expected)) {}
MatchAndExplain(absl::string_view actual,::testing::MatchResultListener *) const126   bool MatchAndExplain(absl::string_view actual,
127                        ::testing::MatchResultListener*) const override {
128     return actual == expected_;
129   }
DescribeTo(std::ostream * os) const130   void DescribeTo(std::ostream* os) const override {
131     *os << "matches the contents of the ostringstream, which are \""
132         << expected_ << "\"";
133   }
134 
DescribeNegationTo(std::ostream * os) const135   void DescribeNegationTo(std::ostream* os) const override {
136     *os << "does not match the contents of the ostringstream, which are \""
137         << expected_ << "\"";
138   }
139 
140  private:
141   const std::string expected_;
142 };
MatchesOstream(const std::ostringstream & stream)143 ::testing::Matcher<absl::string_view> MatchesOstream(
144     const std::ostringstream& stream) {
145   return ::testing::MakeMatcher(new MatchesOstreamImpl(stream.str()));
146 }
147 
148 // We need to validate what is and isn't logged as the process dies due to
149 // `FATAL`, `QFATAL`, `CHECK`, etc., but assertions inside a death test
150 // subprocess don't directly affect the pass/fail status of the parent process.
151 // Instead, we use the mock actions `DeathTestExpectedLogging` and
152 // `DeathTestUnexpectedLogging` to write specific phrases to `stderr` that we
153 // can validate in the parent process using this matcher.
DeathTestValidateExpectations()154 ::testing::Matcher<const std::string&> DeathTestValidateExpectations() {
155   if (log_internal::LoggingEnabledAt(absl::LogSeverity::kFatal)) {
156     return ::testing::Matcher<const std::string&>(::testing::AllOf(
157         ::testing::HasSubstr("Mock received expected entry"),
158         Not(::testing::HasSubstr("Mock received unexpected entry"))));
159   }
160   // If `FATAL` logging is disabled, neither message should have been written.
161   return ::testing::Matcher<const std::string&>(::testing::AllOf(
162       Not(::testing::HasSubstr("Mock received expected entry")),
163       Not(::testing::HasSubstr("Mock received unexpected entry"))));
164 }
165 
166 }  // namespace log_internal
167 ABSL_NAMESPACE_END
168 }  // namespace absl
169