failure_signal_handler_test.cc
Go to the documentation of this file.
00001 //
00002 // Copyright 2018 The Abseil Authors.
00003 //
00004 // Licensed under the Apache License, Version 2.0 (the "License");
00005 // you may not use this file except in compliance with the License.
00006 // You may obtain a copy of the License at
00007 //
00008 //      https://www.apache.org/licenses/LICENSE-2.0
00009 //
00010 // Unless required by applicable law or agreed to in writing, software
00011 // distributed under the License is distributed on an "AS IS" BASIS,
00012 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
00013 // See the License for the specific language governing permissions and
00014 // limitations under the License.
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 // For the parameterized death tests. GetParam() returns the signal number.
00037 using FailureSignalHandlerDeathTest = ::testing::TestWithParam<int>;
00038 
00039 // This function runs in a fork()ed process on most systems.
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   // Windows doesn't have testing::KilledBySignal().
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   // TEST_TMPDIR is set by Bazel. Try the others when not running under Bazel.
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   // Try something reasonable.
00081   return "/tmp";
00082 }
00083 
00084 // This function runs in a fork()ed process on most systems.
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   // Windows doesn't have testing::KilledBySignal().
00107   EXPECT_DEATH(InstallHandlerWithWriteToFileAndRaise(file.c_str(), signo),
00108                exit_regex);
00109 #endif
00110 
00111   // Open the file in this process and check its contents.
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 }  // namespace
00151 
00152 int main(int argc, char** argv) {
00153   absl::InitializeSymbolizer(argv[0]);
00154   testing::InitGoogleTest(&argc, argv);
00155   return RUN_ALL_TESTS();
00156 }


abseil_cpp
Author(s):
autogenerated on Wed Jun 19 2019 19:42:14