Skip to content

Commit de68d82

Browse files
committed
test(crash): add crash logger snapshot test
Add a crash logger test that stubs _exit, triggers the handler, and verifies the crash log snapshot.
1 parent c4ea8b1 commit de68d82

File tree

1 file changed

+132
-0
lines changed

1 file changed

+132
-0
lines changed

tests/crash_logger_test.cpp

Lines changed: 132 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,132 @@
1+
#include <atomic>
2+
#include <chrono>
3+
#include <cstdlib>
4+
#include <filesystem>
5+
#include <fstream>
6+
#include <iomanip>
7+
#include <iterator>
8+
#include <sstream>
9+
#include <string>
10+
#include <vector>
11+
#include <system_error>
12+
13+
#ifndef _WIN32
14+
# include <csignal>
15+
#endif
16+
17+
namespace logit_test {
18+
static int g_exit_code = -1;
19+
20+
inline void reset_exit_code() { g_exit_code = -1; }
21+
22+
inline void fake_exit(int code) { g_exit_code = code; }
23+
} // namespace logit_test
24+
25+
#define _exit ::logit_test::fake_exit
26+
27+
#ifdef _WIN32
28+
# define private public
29+
# include <logit_cpp/logit/loggers/CrashWindowsLogger.hpp>
30+
# undef private
31+
#else
32+
# define private public
33+
# include <logit_cpp/logit/loggers/CrashPosixLogger.hpp>
34+
# undef private
35+
#endif
36+
37+
#undef _exit
38+
39+
#include <LogIt.hpp>
40+
41+
int main() {
42+
namespace fs = std::filesystem;
43+
44+
logit_test::reset_exit_code();
45+
46+
std::error_code ec;
47+
const fs::path temp_dir = fs::temp_directory_path(ec);
48+
if (ec) {
49+
return 1;
50+
}
51+
52+
const auto unique_suffix = std::chrono::high_resolution_clock::now().time_since_epoch().count();
53+
const fs::path log_path = temp_dir / ("logit_crash_logger_test_" + std::to_string(unique_suffix) + ".log");
54+
fs::remove(log_path, ec);
55+
56+
logit::CrashLogger::Config config;
57+
config.log_path = log_path.string();
58+
config.buffer_size = 4096;
59+
60+
LOGIT_ADD_LOGGER(logit::CrashLogger, (config), logit::SimpleLogFormatter, ("%v"));
61+
62+
const std::vector<std::string> messages = {
63+
"Crash logger message 1",
64+
"Crash logger message 2",
65+
"Crash logger message 3",
66+
};
67+
for (const auto& message : messages) {
68+
LOGIT_INFO(message);
69+
}
70+
LOGIT_WAIT();
71+
72+
int expected_exit_code = 0;
73+
std::string marker;
74+
75+
#ifdef _WIN32
76+
auto& active_logger = logit::CrashLogger::active_logger();
77+
logit::CrashLogger* crash_logger = active_logger.load(std::memory_order_acquire);
78+
if (crash_logger == nullptr) {
79+
LOGIT_SHUTDOWN();
80+
return 1;
81+
}
82+
83+
EXCEPTION_RECORD record{};
84+
record.ExceptionCode = 0xC0000005;
85+
EXCEPTION_POINTERS pointers{};
86+
pointers.ExceptionRecord = &record;
87+
88+
(void)logit::CrashLogger::exception_filter(&pointers);
89+
expected_exit_code = EXIT_FAILURE;
90+
91+
std::ostringstream marker_builder;
92+
marker_builder << "\n== CRASH EXCEPTION 0x" << std::uppercase << std::hex << record.ExceptionCode << " ==\n";
93+
marker = marker_builder.str();
94+
#else
95+
logit::CrashLogger* crash_logger = logit::CrashLogger::s_active_logger.load(std::memory_order_acquire);
96+
if (crash_logger == nullptr) {
97+
LOGIT_SHUTDOWN();
98+
return 1;
99+
}
100+
101+
constexpr int kSignalNumber = SIGABRT;
102+
logit::CrashLogger::signal_handler(kSignalNumber, nullptr, nullptr);
103+
expected_exit_code = 128 + kSignalNumber;
104+
marker = "\n== CRASH SIGNAL " + std::to_string(kSignalNumber) + " ==\n";
105+
#endif
106+
107+
if (logit_test::g_exit_code != expected_exit_code) {
108+
LOGIT_SHUTDOWN();
109+
return 1;
110+
}
111+
112+
LOGIT_SHUTDOWN();
113+
114+
std::ifstream input(log_path);
115+
if (!input.is_open()) {
116+
return 1;
117+
}
118+
const std::string contents((std::istreambuf_iterator<char>(input)), std::istreambuf_iterator<char>());
119+
120+
for (const auto& message : messages) {
121+
if (contents.find(message) == std::string::npos) {
122+
return 1;
123+
}
124+
}
125+
if (contents.find(marker) == std::string::npos) {
126+
return 1;
127+
}
128+
129+
fs::remove(log_path, ec);
130+
131+
return 0;
132+
}

0 commit comments

Comments
 (0)