failure_signal_handler_test.cc
Go to the documentation of this file.
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 
18 
19 #include <csignal>
20 #include <cstdio>
21 #include <cstdlib>
22 #include <cstring>
23 #include <fstream>
24 
25 #include "gtest/gtest.h"
29 #include "absl/strings/match.h"
30 #include "absl/strings/str_cat.h"
31 
32 namespace {
33 
34 #if GTEST_HAS_DEATH_TEST
35 
36 // For the parameterized death tests. GetParam() returns the signal number.
37 using FailureSignalHandlerDeathTest = ::testing::TestWithParam<int>;
38 
39 // This function runs in a fork()ed process on most systems.
40 void InstallHandlerAndRaise(int signo) {
42  raise(signo);
43 }
44 
45 TEST_P(FailureSignalHandlerDeathTest, AbslFailureSignal) {
46  const int signo = GetParam();
47  std::string exit_regex = absl::StrCat(
49  " received at time=");
50 #ifndef _WIN32
51  EXPECT_EXIT(InstallHandlerAndRaise(signo), testing::KilledBySignal(signo),
52  exit_regex);
53 #else
54  // Windows doesn't have testing::KilledBySignal().
55  EXPECT_DEATH(InstallHandlerAndRaise(signo), exit_regex);
56 #endif
57 }
58 
59 ABSL_CONST_INIT FILE* error_file = nullptr;
60 
61 void WriteToErrorFile(const char* msg) {
62  if (msg != nullptr) {
63  ABSL_RAW_CHECK(fwrite(msg, strlen(msg), 1, error_file) == 1,
64  "fwrite() failed");
65  }
66  ABSL_RAW_CHECK(fflush(error_file) == 0, "fflush() failed");
67 }
68 
69 std::string GetTmpDir() {
70  // TEST_TMPDIR is set by Bazel. Try the others when not running under Bazel.
71  static const char* const kTmpEnvVars[] = {"TEST_TMPDIR", "TMPDIR", "TEMP",
72  "TEMPDIR", "TMP"};
73  for (const char* const var : kTmpEnvVars) {
74  const char* tmp_dir = std::getenv(var);
75  if (tmp_dir != nullptr) {
76  return tmp_dir;
77  }
78  }
79 
80  // Try something reasonable.
81  return "/tmp";
82 }
83 
84 // This function runs in a fork()ed process on most systems.
85 void InstallHandlerWithWriteToFileAndRaise(const char* file, int signo) {
86  error_file = fopen(file, "w");
87  ABSL_RAW_CHECK(error_file != nullptr, "Failed create error_file");
89  options.writerfn = WriteToErrorFile;
91  raise(signo);
92 }
93 
94 TEST_P(FailureSignalHandlerDeathTest, AbslFatalSignalsWithWriterFn) {
95  const int signo = GetParam();
96  std::string tmp_dir = GetTmpDir();
97  std::string file = absl::StrCat(tmp_dir, "/signo_", signo);
98 
99  std::string exit_regex = absl::StrCat(
101  " received at time=");
102 #ifndef _WIN32
103  EXPECT_EXIT(InstallHandlerWithWriteToFileAndRaise(file.c_str(), signo),
104  testing::KilledBySignal(signo), exit_regex);
105 #else
106  // Windows doesn't have testing::KilledBySignal().
107  EXPECT_DEATH(InstallHandlerWithWriteToFileAndRaise(file.c_str(), signo),
108  exit_regex);
109 #endif
110 
111  // Open the file in this process and check its contents.
112  std::fstream error_output(file);
113  ASSERT_TRUE(error_output.is_open()) << file;
114  std::string error_line;
115  std::getline(error_output, error_line);
116  EXPECT_TRUE(absl::StartsWith(
117  error_line,
118  absl::StrCat("*** ",
120  " received at ")));
121 
123  std::getline(error_output, error_line);
124  EXPECT_TRUE(absl::StartsWith(error_line, "PC: "));
125  }
126 }
127 
128 constexpr int kFailureSignals[] = {
129  SIGSEGV, SIGILL, SIGFPE, SIGABRT, SIGTERM,
130 #ifndef _WIN32
131  SIGBUS, SIGTRAP,
132 #endif
133 };
134 
135 std::string SignalParamToString(const ::testing::TestParamInfo<int>& info) {
136  std::string result =
138  if (result.empty()) {
139  result = absl::StrCat(info.param);
140  }
141  return result;
142 }
143 
144 INSTANTIATE_TEST_SUITE_P(AbslDeathTest, FailureSignalHandlerDeathTest,
145  ::testing::ValuesIn(kFailureSignals),
146  SignalParamToString);
147 
148 #endif // GTEST_HAS_DEATH_TEST
149 
150 } // namespace
151 
152 int main(int argc, char** argv) {
154  testing::InitGoogleTest(&argc, argv);
155  return RUN_ALL_TESTS();
156 }
const char * FailureSignalToString(int signo)
#define ABSL_CONST_INIT
Definition: attributes.h:605
void InitializeSymbolizer(const char *argv0)
std::string StrCat(const AlphaNum &a, const AlphaNum &b)
Definition: str_cat.cc:98
int main(int argc, char **argv)
#define ABSL_RAW_CHECK(condition, message)
Definition: raw_logging.h:57
const char * msg
Definition: mutex.cc:254
bool StartsWith(absl::string_view text, absl::string_view prefix)
Definition: match.h:52
void InstallFailureSignalHandler(const FailureSignalHandlerOptions &options)


abseil_cpp
Author(s):
autogenerated on Mon Feb 28 2022 21:31:18