tor-browser

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

failure_signal_handler_test.cc (5228B)


      1 //
      2 // Copyright 2018 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 
     17 #include "absl/debugging/failure_signal_handler.h"
     18 
     19 #include <csignal>
     20 #include <cstdio>
     21 #include <cstdlib>
     22 #include <cstring>
     23 #include <fstream>
     24 
     25 #include "gmock/gmock.h"
     26 #include "gtest/gtest.h"
     27 #include "absl/base/internal/raw_logging.h"
     28 #include "absl/debugging/stacktrace.h"
     29 #include "absl/debugging/symbolize.h"
     30 #include "absl/log/check.h"
     31 #include "absl/strings/match.h"
     32 #include "absl/strings/str_cat.h"
     33 
     34 namespace {
     35 
     36 using testing::StartsWith;
     37 
     38 #if GTEST_HAS_DEATH_TEST
     39 
     40 // For the parameterized death tests. GetParam() returns the signal number.
     41 using FailureSignalHandlerDeathTest = ::testing::TestWithParam<int>;
     42 
     43 // This function runs in a fork()ed process on most systems.
     44 void InstallHandlerAndRaise(int signo) {
     45  absl::InstallFailureSignalHandler(absl::FailureSignalHandlerOptions());
     46  raise(signo);
     47 }
     48 
     49 TEST_P(FailureSignalHandlerDeathTest, AbslFailureSignal) {
     50  const int signo = GetParam();
     51  std::string exit_regex = absl::StrCat(
     52      "\\*\\*\\* ", absl::debugging_internal::FailureSignalToString(signo),
     53      " received at time=");
     54 #ifndef _WIN32
     55  EXPECT_EXIT(InstallHandlerAndRaise(signo), testing::KilledBySignal(signo),
     56              exit_regex);
     57 #else
     58  // Windows doesn't have testing::KilledBySignal().
     59  EXPECT_DEATH_IF_SUPPORTED(InstallHandlerAndRaise(signo), exit_regex);
     60 #endif
     61 }
     62 
     63 ABSL_CONST_INIT FILE* error_file = nullptr;
     64 
     65 void WriteToErrorFile(const char* msg) {
     66  if (msg != nullptr) {
     67    ABSL_RAW_CHECK(fwrite(msg, strlen(msg), 1, error_file) == 1,
     68                   "fwrite() failed");
     69  }
     70  ABSL_RAW_CHECK(fflush(error_file) == 0, "fflush() failed");
     71 }
     72 
     73 std::string GetTmpDir() {
     74  // TEST_TMPDIR is set by Bazel. Try the others when not running under Bazel.
     75  static const char* const kTmpEnvVars[] = {"TEST_TMPDIR", "TMPDIR", "TEMP",
     76                                            "TEMPDIR", "TMP"};
     77  for (const char* const var : kTmpEnvVars) {
     78    const char* tmp_dir = std::getenv(var);
     79    if (tmp_dir != nullptr) {
     80      return tmp_dir;
     81    }
     82  }
     83 
     84  // Try something reasonable.
     85  return "/tmp";
     86 }
     87 
     88 // This function runs in a fork()ed process on most systems.
     89 void InstallHandlerWithWriteToFileAndRaise(const char* file, int signo) {
     90  error_file = fopen(file, "w");
     91  CHECK_NE(error_file, nullptr) << "Failed create error_file";
     92  absl::FailureSignalHandlerOptions options;
     93  options.writerfn = WriteToErrorFile;
     94  absl::InstallFailureSignalHandler(options);
     95  raise(signo);
     96 }
     97 
     98 TEST_P(FailureSignalHandlerDeathTest, AbslFatalSignalsWithWriterFn) {
     99  const int signo = GetParam();
    100  std::string tmp_dir = GetTmpDir();
    101  std::string file = absl::StrCat(tmp_dir, "/signo_", signo);
    102 
    103  std::string exit_regex = absl::StrCat(
    104      "\\*\\*\\* ", absl::debugging_internal::FailureSignalToString(signo),
    105      " received at time=");
    106 #ifndef _WIN32
    107  EXPECT_EXIT(InstallHandlerWithWriteToFileAndRaise(file.c_str(), signo),
    108              testing::KilledBySignal(signo), exit_regex);
    109 #else
    110  // Windows doesn't have testing::KilledBySignal().
    111  EXPECT_DEATH_IF_SUPPORTED(
    112      InstallHandlerWithWriteToFileAndRaise(file.c_str(), signo), exit_regex);
    113 #endif
    114 
    115  // Open the file in this process and check its contents.
    116  std::fstream error_output(file);
    117  ASSERT_TRUE(error_output.is_open()) << file;
    118  std::string error_line;
    119  std::getline(error_output, error_line);
    120  EXPECT_THAT(
    121      error_line,
    122      StartsWith(absl::StrCat(
    123          "*** ", absl::debugging_internal::FailureSignalToString(signo),
    124          " received at ")));
    125 
    126  // On platforms where it is possible to get the current CPU, the
    127  // CPU number is also logged. Check that it is present in output.
    128 #if defined(__linux__)
    129  EXPECT_THAT(error_line, testing::HasSubstr(" on cpu "));
    130 #endif
    131 
    132  if (absl::debugging_internal::StackTraceWorksForTest()) {
    133    std::getline(error_output, error_line);
    134    EXPECT_THAT(error_line, StartsWith("PC: "));
    135  }
    136 }
    137 
    138 constexpr int kFailureSignals[] = {
    139    SIGSEGV, SIGILL,  SIGFPE, SIGABRT, SIGTERM,
    140 #ifndef _WIN32
    141    SIGBUS,  SIGTRAP,
    142 #endif
    143 };
    144 
    145 std::string SignalParamToString(const ::testing::TestParamInfo<int>& info) {
    146  std::string result =
    147      absl::debugging_internal::FailureSignalToString(info.param);
    148  if (result.empty()) {
    149    result = absl::StrCat(info.param);
    150  }
    151  return result;
    152 }
    153 
    154 INSTANTIATE_TEST_SUITE_P(AbslDeathTest, FailureSignalHandlerDeathTest,
    155                         ::testing::ValuesIn(kFailureSignals),
    156                         SignalParamToString);
    157 
    158 #endif  // GTEST_HAS_DEATH_TEST
    159 
    160 }  // namespace
    161 
    162 int main(int argc, char** argv) {
    163  absl::InitializeSymbolizer(argv[0]);
    164  testing::InitGoogleTest(&argc, argv);
    165  return RUN_ALL_TESTS();
    166 }