00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017 #include "absl/debugging/failure_signal_handler.h"
00018
00019 #include <csignal>
00020 #include <cstdio>
00021 #include <cstdlib>
00022 #include <cstring>
00023 #include <fstream>
00024
00025 #include "gtest/gtest.h"
00026 #include "absl/base/internal/raw_logging.h"
00027 #include "absl/debugging/stacktrace.h"
00028 #include "absl/debugging/symbolize.h"
00029 #include "absl/strings/match.h"
00030 #include "absl/strings/str_cat.h"
00031
00032 namespace {
00033
00034 #if GTEST_HAS_DEATH_TEST
00035
00036
00037 using FailureSignalHandlerDeathTest = ::testing::TestWithParam<int>;
00038
00039
00040 void InstallHandlerAndRaise(int signo) {
00041 absl::InstallFailureSignalHandler(absl::FailureSignalHandlerOptions());
00042 raise(signo);
00043 }
00044
00045 TEST_P(FailureSignalHandlerDeathTest, AbslFailureSignal) {
00046 const int signo = GetParam();
00047 std::string exit_regex = absl::StrCat(
00048 "\\*\\*\\* ", absl::debugging_internal::FailureSignalToString(signo),
00049 " received at time=");
00050 #ifndef _WIN32
00051 EXPECT_EXIT(InstallHandlerAndRaise(signo), testing::KilledBySignal(signo),
00052 exit_regex);
00053 #else
00054
00055 EXPECT_DEATH(InstallHandlerAndRaise(signo), exit_regex);
00056 #endif
00057 }
00058
00059 ABSL_CONST_INIT FILE* error_file = nullptr;
00060
00061 void WriteToErrorFile(const char* msg) {
00062 if (msg != nullptr) {
00063 ABSL_RAW_CHECK(fwrite(msg, strlen(msg), 1, error_file) == 1,
00064 "fwrite() failed");
00065 }
00066 ABSL_RAW_CHECK(fflush(error_file) == 0, "fflush() failed");
00067 }
00068
00069 std::string GetTmpDir() {
00070
00071 static const char* const kTmpEnvVars[] = {"TEST_TMPDIR", "TMPDIR", "TEMP",
00072 "TEMPDIR", "TMP"};
00073 for (const char* const var : kTmpEnvVars) {
00074 const char* tmp_dir = std::getenv(var);
00075 if (tmp_dir != nullptr) {
00076 return tmp_dir;
00077 }
00078 }
00079
00080
00081 return "/tmp";
00082 }
00083
00084
00085 void InstallHandlerWithWriteToFileAndRaise(const char* file, int signo) {
00086 error_file = fopen(file, "w");
00087 ABSL_RAW_CHECK(error_file != nullptr, "Failed create error_file");
00088 absl::FailureSignalHandlerOptions options;
00089 options.writerfn = WriteToErrorFile;
00090 absl::InstallFailureSignalHandler(options);
00091 raise(signo);
00092 }
00093
00094 TEST_P(FailureSignalHandlerDeathTest, AbslFatalSignalsWithWriterFn) {
00095 const int signo = GetParam();
00096 std::string tmp_dir = GetTmpDir();
00097 std::string file = absl::StrCat(tmp_dir, "/signo_", signo);
00098
00099 std::string exit_regex = absl::StrCat(
00100 "\\*\\*\\* ", absl::debugging_internal::FailureSignalToString(signo),
00101 " received at time=");
00102 #ifndef _WIN32
00103 EXPECT_EXIT(InstallHandlerWithWriteToFileAndRaise(file.c_str(), signo),
00104 testing::KilledBySignal(signo), exit_regex);
00105 #else
00106
00107 EXPECT_DEATH(InstallHandlerWithWriteToFileAndRaise(file.c_str(), signo),
00108 exit_regex);
00109 #endif
00110
00111
00112 std::fstream error_output(file);
00113 ASSERT_TRUE(error_output.is_open()) << file;
00114 std::string error_line;
00115 std::getline(error_output, error_line);
00116 EXPECT_TRUE(absl::StartsWith(
00117 error_line,
00118 absl::StrCat("*** ",
00119 absl::debugging_internal::FailureSignalToString(signo),
00120 " received at ")));
00121
00122 if (absl::debugging_internal::StackTraceWorksForTest()) {
00123 std::getline(error_output, error_line);
00124 EXPECT_TRUE(absl::StartsWith(error_line, "PC: "));
00125 }
00126 }
00127
00128 constexpr int kFailureSignals[] = {
00129 SIGSEGV, SIGILL, SIGFPE, SIGABRT, SIGTERM,
00130 #ifndef _WIN32
00131 SIGBUS, SIGTRAP,
00132 #endif
00133 };
00134
00135 std::string SignalParamToString(const ::testing::TestParamInfo<int>& info) {
00136 std::string result =
00137 absl::debugging_internal::FailureSignalToString(info.param);
00138 if (result.empty()) {
00139 result = absl::StrCat(info.param);
00140 }
00141 return result;
00142 }
00143
00144 INSTANTIATE_TEST_SUITE_P(AbslDeathTest, FailureSignalHandlerDeathTest,
00145 ::testing::ValuesIn(kFailureSignals),
00146 SignalParamToString);
00147
00148 #endif // GTEST_HAS_DEATH_TEST
00149
00150 }
00151
00152 int main(int argc, char** argv) {
00153 absl::InitializeSymbolizer(argv[0]);
00154 testing::InitGoogleTest(&argc, argv);
00155 return RUN_ALL_TESTS();
00156 }