aboutsummaryrefslogtreecommitdiff
path: root/third_party/abseil-cpp/absl/debugging/failure_signal_handler_test.cc
diff options
context:
space:
mode:
Diffstat (limited to 'third_party/abseil-cpp/absl/debugging/failure_signal_handler_test.cc')
-rw-r--r--third_party/abseil-cpp/absl/debugging/failure_signal_handler_test.cc159
1 files changed, 159 insertions, 0 deletions
diff --git a/third_party/abseil-cpp/absl/debugging/failure_signal_handler_test.cc b/third_party/abseil-cpp/absl/debugging/failure_signal_handler_test.cc
new file mode 100644
index 0000000000..863fb5149e
--- /dev/null
+++ b/third_party/abseil-cpp/absl/debugging/failure_signal_handler_test.cc
@@ -0,0 +1,159 @@
+//
+// Copyright 2018 The Abseil Authors.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// https://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#include "absl/debugging/failure_signal_handler.h"
+
+#include <csignal>
+#include <cstdio>
+#include <cstdlib>
+#include <cstring>
+#include <fstream>
+
+#include "gtest/gtest.h"
+#include "gmock/gmock.h"
+#include "absl/base/internal/raw_logging.h"
+#include "absl/debugging/stacktrace.h"
+#include "absl/debugging/symbolize.h"
+#include "absl/strings/match.h"
+#include "absl/strings/str_cat.h"
+
+namespace {
+
+using testing::StartsWith;
+
+#if GTEST_HAS_DEATH_TEST
+
+// For the parameterized death tests. GetParam() returns the signal number.
+using FailureSignalHandlerDeathTest = ::testing::TestWithParam<int>;
+
+// This function runs in a fork()ed process on most systems.
+void InstallHandlerAndRaise(int signo) {
+ absl::InstallFailureSignalHandler(absl::FailureSignalHandlerOptions());
+ raise(signo);
+}
+
+TEST_P(FailureSignalHandlerDeathTest, AbslFailureSignal) {
+ const int signo = GetParam();
+ std::string exit_regex = absl::StrCat(
+ "\\*\\*\\* ", absl::debugging_internal::FailureSignalToString(signo),
+ " received at time=");
+#ifndef _WIN32
+ EXPECT_EXIT(InstallHandlerAndRaise(signo), testing::KilledBySignal(signo),
+ exit_regex);
+#else
+ // Windows doesn't have testing::KilledBySignal().
+ EXPECT_DEATH(InstallHandlerAndRaise(signo), exit_regex);
+#endif
+}
+
+ABSL_CONST_INIT FILE* error_file = nullptr;
+
+void WriteToErrorFile(const char* msg) {
+ if (msg != nullptr) {
+ ABSL_RAW_CHECK(fwrite(msg, strlen(msg), 1, error_file) == 1,
+ "fwrite() failed");
+ }
+ ABSL_RAW_CHECK(fflush(error_file) == 0, "fflush() failed");
+}
+
+std::string GetTmpDir() {
+ // TEST_TMPDIR is set by Bazel. Try the others when not running under Bazel.
+ static const char* const kTmpEnvVars[] = {"TEST_TMPDIR", "TMPDIR", "TEMP",
+ "TEMPDIR", "TMP"};
+ for (const char* const var : kTmpEnvVars) {
+ const char* tmp_dir = std::getenv(var);
+ if (tmp_dir != nullptr) {
+ return tmp_dir;
+ }
+ }
+
+ // Try something reasonable.
+ return "/tmp";
+}
+
+// This function runs in a fork()ed process on most systems.
+void InstallHandlerWithWriteToFileAndRaise(const char* file, int signo) {
+ error_file = fopen(file, "w");
+ ABSL_RAW_CHECK(error_file != nullptr, "Failed create error_file");
+ absl::FailureSignalHandlerOptions options;
+ options.writerfn = WriteToErrorFile;
+ absl::InstallFailureSignalHandler(options);
+ raise(signo);
+}
+
+TEST_P(FailureSignalHandlerDeathTest, AbslFatalSignalsWithWriterFn) {
+ const int signo = GetParam();
+ std::string tmp_dir = GetTmpDir();
+ std::string file = absl::StrCat(tmp_dir, "/signo_", signo);
+
+ std::string exit_regex = absl::StrCat(
+ "\\*\\*\\* ", absl::debugging_internal::FailureSignalToString(signo),
+ " received at time=");
+#ifndef _WIN32
+ EXPECT_EXIT(InstallHandlerWithWriteToFileAndRaise(file.c_str(), signo),
+ testing::KilledBySignal(signo), exit_regex);
+#else
+ // Windows doesn't have testing::KilledBySignal().
+ EXPECT_DEATH(InstallHandlerWithWriteToFileAndRaise(file.c_str(), signo),
+ exit_regex);
+#endif
+
+ // Open the file in this process and check its contents.
+ std::fstream error_output(file);
+ ASSERT_TRUE(error_output.is_open()) << file;
+ std::string error_line;
+ std::getline(error_output, error_line);
+ EXPECT_THAT(
+ error_line,
+ StartsWith(absl::StrCat(
+ "*** ", absl::debugging_internal::FailureSignalToString(signo),
+ " received at ")));
+
+ if (absl::debugging_internal::StackTraceWorksForTest()) {
+ std::getline(error_output, error_line);
+ EXPECT_THAT(error_line, StartsWith("PC: "));
+ }
+}
+
+constexpr int kFailureSignals[] = {
+ SIGSEGV, SIGILL, SIGFPE, SIGABRT, SIGTERM,
+#ifndef _WIN32
+ SIGBUS, SIGTRAP,
+#endif
+};
+
+std::string SignalParamToString(const ::testing::TestParamInfo<int>& info) {
+ std::string result =
+ absl::debugging_internal::FailureSignalToString(info.param);
+ if (result.empty()) {
+ result = absl::StrCat(info.param);
+ }
+ return result;
+}
+
+INSTANTIATE_TEST_SUITE_P(AbslDeathTest, FailureSignalHandlerDeathTest,
+ ::testing::ValuesIn(kFailureSignals),
+ SignalParamToString);
+
+#endif // GTEST_HAS_DEATH_TEST
+
+} // namespace
+
+int main(int argc, char** argv) {
+ absl::InitializeSymbolizer(argv[0]);
+ testing::InitGoogleTest(&argc, argv);
+ return RUN_ALL_TESTS();
+}