tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

scoped_mock_log_test.cc (9048B)


      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/scoped_mock_log.h"
     17 
     18 #include <memory>
     19 #include <thread>  // NOLINT(build/c++11)
     20 
     21 #include "gmock/gmock.h"
     22 #include "gtest/gtest-spi.h"
     23 #include "gtest/gtest.h"
     24 #include "absl/base/attributes.h"
     25 #include "absl/base/log_severity.h"
     26 #include "absl/log/globals.h"
     27 #include "absl/log/internal/test_helpers.h"
     28 #include "absl/log/internal/test_matchers.h"
     29 #include "absl/log/log.h"
     30 #include "absl/memory/memory.h"
     31 #include "absl/strings/match.h"
     32 #include "absl/strings/string_view.h"
     33 #include "absl/synchronization/barrier.h"
     34 #include "absl/synchronization/notification.h"
     35 
     36 namespace {
     37 
     38 using ::testing::_;
     39 using ::testing::AnyNumber;
     40 using ::testing::Eq;
     41 using ::testing::HasSubstr;
     42 using ::testing::InSequence;
     43 using ::testing::Lt;
     44 using ::testing::Truly;
     45 using absl::log_internal::SourceBasename;
     46 using absl::log_internal::SourceFilename;
     47 using absl::log_internal::SourceLine;
     48 using absl::log_internal::TextMessageWithPrefix;
     49 using absl::log_internal::ThreadID;
     50 
     51 auto* test_env ABSL_ATTRIBUTE_UNUSED = ::testing::AddGlobalTestEnvironment(
     52    new absl::log_internal::LogTestEnvironment);
     53 
     54 #if GTEST_HAS_DEATH_TEST
     55 TEST(ScopedMockLogDeathTest,
     56     StartCapturingLogsCannotBeCalledWhenAlreadyCapturing) {
     57  EXPECT_DEATH(
     58      {
     59        absl::ScopedMockLog log;
     60        log.StartCapturingLogs();
     61        log.StartCapturingLogs();
     62      },
     63      "StartCapturingLogs");
     64 }
     65 
     66 TEST(ScopedMockLogDeathTest, StopCapturingLogsCannotBeCalledWhenNotCapturing) {
     67  EXPECT_DEATH(
     68      {
     69        absl::ScopedMockLog log;
     70        log.StopCapturingLogs();
     71      },
     72      "StopCapturingLogs");
     73 }
     74 
     75 TEST(ScopedMockLogDeathTest, FailsCheckIfStartCapturingLogsIsNeverCalled) {
     76  EXPECT_DEATH({ absl::ScopedMockLog log; },
     77               "Did you forget to call StartCapturingLogs");
     78 }
     79 #endif
     80 
     81 // Tests that ScopedMockLog intercepts LOG()s when it's alive.
     82 TEST(ScopedMockLogTest, LogMockCatchAndMatchStrictExpectations) {
     83  absl::ScopedMockLog log;
     84 
     85  // The following expectations must match in the order they appear.
     86  InSequence s;
     87  EXPECT_CALL(log,
     88              Log(absl::LogSeverity::kWarning, HasSubstr(__FILE__), "Danger."));
     89  EXPECT_CALL(log, Log(absl::LogSeverity::kInfo, _, "Working...")).Times(2);
     90  EXPECT_CALL(log, Log(absl::LogSeverity::kError, _, "Bad!!"));
     91 
     92  log.StartCapturingLogs();
     93  LOG(WARNING) << "Danger.";
     94  LOG(INFO) << "Working...";
     95  LOG(INFO) << "Working...";
     96  LOG(ERROR) << "Bad!!";
     97 }
     98 
     99 TEST(ScopedMockLogTest, LogMockCatchAndMatchSendExpectations) {
    100  absl::ScopedMockLog log;
    101 
    102  EXPECT_CALL(
    103      log,
    104      Send(AllOf(SourceFilename(Eq("/my/very/very/very_long_source_file.cc")),
    105                 SourceBasename(Eq("very_long_source_file.cc")),
    106                 SourceLine(Eq(777)), ThreadID(Eq(absl::LogEntry::tid_t{1234})),
    107                 TextMessageWithPrefix(Truly([](absl::string_view msg) {
    108                   return absl::EndsWith(
    109                       msg, " very_long_source_file.cc:777] Info message");
    110                 })))));
    111 
    112  log.StartCapturingLogs();
    113  LOG(INFO)
    114          .AtLocation("/my/very/very/very_long_source_file.cc", 777)
    115          .WithThreadID(1234)
    116      << "Info message";
    117 }
    118 
    119 TEST(ScopedMockLogTest, ScopedMockLogCanBeNice) {
    120  absl::ScopedMockLog log;
    121 
    122  InSequence s;
    123  EXPECT_CALL(log,
    124              Log(absl::LogSeverity::kWarning, HasSubstr(__FILE__), "Danger."));
    125  EXPECT_CALL(log, Log(absl::LogSeverity::kInfo, _, "Working...")).Times(2);
    126  EXPECT_CALL(log, Log(absl::LogSeverity::kError, _, "Bad!!"));
    127 
    128  log.StartCapturingLogs();
    129 
    130  // Any number of these are OK.
    131  LOG(INFO) << "Info message.";
    132  // Any number of these are OK.
    133  LOG(WARNING).AtLocation("SomeOtherFile.cc", 100) << "Danger ";
    134 
    135  LOG(WARNING) << "Danger.";
    136 
    137  // Any number of these are OK.
    138  LOG(INFO) << "Info message.";
    139  // Any number of these are OK.
    140  LOG(WARNING).AtLocation("SomeOtherFile.cc", 100) << "Danger ";
    141 
    142  LOG(INFO) << "Working...";
    143 
    144  // Any number of these are OK.
    145  LOG(INFO) << "Info message.";
    146  // Any number of these are OK.
    147  LOG(WARNING).AtLocation("SomeOtherFile.cc", 100) << "Danger ";
    148 
    149  LOG(INFO) << "Working...";
    150 
    151  // Any number of these are OK.
    152  LOG(INFO) << "Info message.";
    153  // Any number of these are OK.
    154  LOG(WARNING).AtLocation("SomeOtherFile.cc", 100) << "Danger ";
    155 
    156  LOG(ERROR) << "Bad!!";
    157 
    158  // Any number of these are OK.
    159  LOG(INFO) << "Info message.";
    160  // Any number of these are OK.
    161  LOG(WARNING).AtLocation("SomeOtherFile.cc", 100) << "Danger ";
    162 }
    163 
    164 // Tests that ScopedMockLog generates a test failure if a message is logged
    165 // that is not expected (here, that means ERROR or FATAL).
    166 TEST(ScopedMockLogTest, RejectsUnexpectedLogs) {
    167  EXPECT_NONFATAL_FAILURE(
    168      {
    169        absl::ScopedMockLog log(absl::MockLogDefault::kDisallowUnexpected);
    170        // Any INFO and WARNING messages are permitted.
    171        EXPECT_CALL(log, Log(Lt(absl::LogSeverity::kError), _, _))
    172            .Times(AnyNumber());
    173        log.StartCapturingLogs();
    174        LOG(INFO) << "Ignored";
    175        LOG(WARNING) << "Ignored";
    176        LOG(ERROR) << "Should not be ignored";
    177      },
    178      "Should not be ignored");
    179 }
    180 
    181 TEST(ScopedMockLogTest, CapturesLogsAfterStartCapturingLogs) {
    182  absl::SetStderrThreshold(absl::LogSeverityAtLeast::kInfinity);
    183  absl::ScopedMockLog log;
    184 
    185  // The ScopedMockLog object shouldn't see these LOGs, as it hasn't
    186  // started capturing LOGs yet.
    187  LOG(INFO) << "Ignored info";
    188  LOG(WARNING) << "Ignored warning";
    189  LOG(ERROR) << "Ignored error";
    190 
    191  EXPECT_CALL(log, Log(absl::LogSeverity::kInfo, _, "Expected info"));
    192  log.StartCapturingLogs();
    193 
    194  // Only this LOG will be seen by the ScopedMockLog.
    195  LOG(INFO) << "Expected info";
    196 }
    197 
    198 TEST(ScopedMockLogTest, DoesNotCaptureLogsAfterStopCapturingLogs) {
    199  absl::ScopedMockLog log;
    200  EXPECT_CALL(log, Log(absl::LogSeverity::kInfo, _, "Expected info"));
    201 
    202  log.StartCapturingLogs();
    203 
    204  // This LOG should be seen by the ScopedMockLog.
    205  LOG(INFO) << "Expected info";
    206 
    207  log.StopCapturingLogs();
    208 
    209  // The ScopedMockLog object shouldn't see these LOGs, as it has
    210  // stopped capturing LOGs.
    211  LOG(INFO) << "Ignored info";
    212  LOG(WARNING) << "Ignored warning";
    213  LOG(ERROR) << "Ignored error";
    214 }
    215 
    216 // Tests that all messages are intercepted regardless of issuing thread. The
    217 // purpose of this test is NOT to exercise thread-safety.
    218 TEST(ScopedMockLogTest, LogFromMultipleThreads) {
    219  absl::ScopedMockLog log;
    220 
    221  // We don't establish an order to expectations here, since the threads may
    222  // execute their log statements in different order.
    223  EXPECT_CALL(log, Log(absl::LogSeverity::kInfo, __FILE__, "Thread 1"));
    224  EXPECT_CALL(log, Log(absl::LogSeverity::kInfo, __FILE__, "Thread 2"));
    225 
    226  log.StartCapturingLogs();
    227 
    228  absl::Barrier barrier(2);
    229  std::thread thread1([&barrier]() {
    230    barrier.Block();
    231    LOG(INFO) << "Thread 1";
    232  });
    233  std::thread thread2([&barrier]() {
    234    barrier.Block();
    235    LOG(INFO) << "Thread 2";
    236  });
    237 
    238  thread1.join();
    239  thread2.join();
    240 }
    241 
    242 // Tests that no sequence will be imposed on two LOG message expectations from
    243 // different threads. This test would actually deadlock if replaced to two LOG
    244 // statements from the same thread.
    245 TEST(ScopedMockLogTest, NoSequenceWithMultipleThreads) {
    246  absl::ScopedMockLog log;
    247 
    248  absl::Barrier barrier(2);
    249  EXPECT_CALL(log, Log(absl::LogSeverity::kInfo, _, _))
    250      .Times(2)
    251      .WillRepeatedly([&barrier]() { barrier.Block(); });
    252 
    253  log.StartCapturingLogs();
    254 
    255  std::thread thread1([]() { LOG(INFO) << "Thread 1"; });
    256  std::thread thread2([]() { LOG(INFO) << "Thread 2"; });
    257 
    258  thread1.join();
    259  thread2.join();
    260 }
    261 
    262 TEST(ScopedMockLogTsanTest,
    263     ScopedMockLogCanBeDeletedWhenAnotherThreadIsLogging) {
    264  auto log = absl::make_unique<absl::ScopedMockLog>();
    265  EXPECT_CALL(*log, Log(absl::LogSeverity::kInfo, __FILE__, "Thread log"))
    266      .Times(AnyNumber());
    267 
    268  log->StartCapturingLogs();
    269 
    270  absl::Notification logging_started;
    271 
    272  std::thread thread([&logging_started]() {
    273    for (int i = 0; i < 100; ++i) {
    274      if (i == 50) logging_started.Notify();
    275      LOG(INFO) << "Thread log";
    276    }
    277  });
    278 
    279  logging_started.WaitForNotification();
    280  log.reset();
    281  thread.join();
    282 }
    283 
    284 TEST(ScopedMockLogTest, AsLocalSink) {
    285  absl::ScopedMockLog log(absl::MockLogDefault::kDisallowUnexpected);
    286 
    287  EXPECT_CALL(log, Log(_, _, "two"));
    288  EXPECT_CALL(log, Log(_, _, "three"));
    289 
    290  LOG(INFO) << "one";
    291  LOG(INFO).ToSinkOnly(&log.UseAsLocalSink()) << "two";
    292  LOG(INFO).ToSinkAlso(&log.UseAsLocalSink()) << "three";
    293 }
    294 
    295 }  // namespace