From de68d82b888295110887db5048d5d5354c92da49 Mon Sep 17 00:00:00 2001 From: Aster Seker Date: Tue, 16 Sep 2025 01:52:24 +0300 Subject: [PATCH 1/7] test(crash): add crash logger snapshot test Add a crash logger test that stubs _exit, triggers the handler, and verifies the crash log snapshot. --- tests/crash_logger_test.cpp | 132 ++++++++++++++++++++++++++++++++++++ 1 file changed, 132 insertions(+) create mode 100644 tests/crash_logger_test.cpp diff --git a/tests/crash_logger_test.cpp b/tests/crash_logger_test.cpp new file mode 100644 index 0000000..56bed75 --- /dev/null +++ b/tests/crash_logger_test.cpp @@ -0,0 +1,132 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#ifndef _WIN32 +# include +#endif + +namespace logit_test { + static int g_exit_code = -1; + + inline void reset_exit_code() { g_exit_code = -1; } + + inline void fake_exit(int code) { g_exit_code = code; } +} // namespace logit_test + +#define _exit ::logit_test::fake_exit + +#ifdef _WIN32 +# define private public +# include +# undef private +#else +# define private public +# include +# undef private +#endif + +#undef _exit + +#include + +int main() { + namespace fs = std::filesystem; + + logit_test::reset_exit_code(); + + std::error_code ec; + const fs::path temp_dir = fs::temp_directory_path(ec); + if (ec) { + return 1; + } + + const auto unique_suffix = std::chrono::high_resolution_clock::now().time_since_epoch().count(); + const fs::path log_path = temp_dir / ("logit_crash_logger_test_" + std::to_string(unique_suffix) + ".log"); + fs::remove(log_path, ec); + + logit::CrashLogger::Config config; + config.log_path = log_path.string(); + config.buffer_size = 4096; + + LOGIT_ADD_LOGGER(logit::CrashLogger, (config), logit::SimpleLogFormatter, ("%v")); + + const std::vector messages = { + "Crash logger message 1", + "Crash logger message 2", + "Crash logger message 3", + }; + for (const auto& message : messages) { + LOGIT_INFO(message); + } + LOGIT_WAIT(); + + int expected_exit_code = 0; + std::string marker; + +#ifdef _WIN32 + auto& active_logger = logit::CrashLogger::active_logger(); + logit::CrashLogger* crash_logger = active_logger.load(std::memory_order_acquire); + if (crash_logger == nullptr) { + LOGIT_SHUTDOWN(); + return 1; + } + + EXCEPTION_RECORD record{}; + record.ExceptionCode = 0xC0000005; + EXCEPTION_POINTERS pointers{}; + pointers.ExceptionRecord = &record; + + (void)logit::CrashLogger::exception_filter(&pointers); + expected_exit_code = EXIT_FAILURE; + + std::ostringstream marker_builder; + marker_builder << "\n== CRASH EXCEPTION 0x" << std::uppercase << std::hex << record.ExceptionCode << " ==\n"; + marker = marker_builder.str(); +#else + logit::CrashLogger* crash_logger = logit::CrashLogger::s_active_logger.load(std::memory_order_acquire); + if (crash_logger == nullptr) { + LOGIT_SHUTDOWN(); + return 1; + } + + constexpr int kSignalNumber = SIGABRT; + logit::CrashLogger::signal_handler(kSignalNumber, nullptr, nullptr); + expected_exit_code = 128 + kSignalNumber; + marker = "\n== CRASH SIGNAL " + std::to_string(kSignalNumber) + " ==\n"; +#endif + + if (logit_test::g_exit_code != expected_exit_code) { + LOGIT_SHUTDOWN(); + return 1; + } + + LOGIT_SHUTDOWN(); + + std::ifstream input(log_path); + if (!input.is_open()) { + return 1; + } + const std::string contents((std::istreambuf_iterator(input)), std::istreambuf_iterator()); + + for (const auto& message : messages) { + if (contents.find(message) == std::string::npos) { + return 1; + } + } + if (contents.find(marker) == std::string::npos) { + return 1; + } + + fs::remove(log_path, ec); + + return 0; +} From 58fb4dc7f83626e9b3abeafe212c81c8804e31b2 Mon Sep 17 00:00:00 2001 From: Aster Seker Date: Tue, 16 Sep 2025 02:04:23 +0300 Subject: [PATCH 2/7] fix(tests): include exported crash headers --- tests/crash_logger_test.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/crash_logger_test.cpp b/tests/crash_logger_test.cpp index 56bed75..5d5d7d9 100644 --- a/tests/crash_logger_test.cpp +++ b/tests/crash_logger_test.cpp @@ -26,11 +26,11 @@ namespace logit_test { #ifdef _WIN32 # define private public -# include +# include # undef private #else # define private public -# include +# include # undef private #endif From 6cb4bf01b141950415d4049481644991cf443d22 Mon Sep 17 00:00:00 2001 From: Aster Seker Date: Tue, 16 Sep 2025 02:21:27 +0300 Subject: [PATCH 3/7] test(crash_logger): fix portability issues Update the crash logger test to avoid std::filesystem so it builds under the C++11 standard, include the public utility headers before touching crash logger internals, and switch includes to the exported logit_cpp paths while using simple std::remove cleanup. --- tests/crash_logger_test.cpp | 31 +++++++++++++------------------ 1 file changed, 13 insertions(+), 18 deletions(-) diff --git a/tests/crash_logger_test.cpp b/tests/crash_logger_test.cpp index 5d5d7d9..e4d386d 100644 --- a/tests/crash_logger_test.cpp +++ b/tests/crash_logger_test.cpp @@ -1,14 +1,15 @@ #include #include +#include #include -#include #include #include #include #include #include #include -#include + +#include #ifndef _WIN32 # include @@ -26,35 +27,29 @@ namespace logit_test { #ifdef _WIN32 # define private public -# include +# include # undef private #else # define private public -# include +# include # undef private #endif #undef _exit -#include +#include int main() { - namespace fs = std::filesystem; - logit_test::reset_exit_code(); - std::error_code ec; - const fs::path temp_dir = fs::temp_directory_path(ec); - if (ec) { - return 1; - } - const auto unique_suffix = std::chrono::high_resolution_clock::now().time_since_epoch().count(); - const fs::path log_path = temp_dir / ("logit_crash_logger_test_" + std::to_string(unique_suffix) + ".log"); - fs::remove(log_path, ec); + std::ostringstream path_builder; + path_builder << "logit_crash_logger_test_" << unique_suffix << ".log"; + const std::string log_path = path_builder.str(); + std::remove(log_path.c_str()); logit::CrashLogger::Config config; - config.log_path = log_path.string(); + config.log_path = log_path; config.buffer_size = 4096; LOGIT_ADD_LOGGER(logit::CrashLogger, (config), logit::SimpleLogFormatter, ("%v")); @@ -111,7 +106,7 @@ int main() { LOGIT_SHUTDOWN(); - std::ifstream input(log_path); + std::ifstream input(log_path.c_str(), std::ios::binary); if (!input.is_open()) { return 1; } @@ -126,7 +121,7 @@ int main() { return 1; } - fs::remove(log_path, ec); + std::remove(log_path.c_str()); return 0; } From 54be09eb79dcc6ac506a53940dc9f6ca2c50d58c Mon Sep 17 00:00:00 2001 From: Aster Seker Date: Tue, 16 Sep 2025 02:38:12 +0300 Subject: [PATCH 4/7] fix(tests): correct crash logger includes Adjust crash logger test to use exported include paths without duplicating the logit_cpp prefix. --- tests/crash_logger_test.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/tests/crash_logger_test.cpp b/tests/crash_logger_test.cpp index e4d386d..fb0976b 100644 --- a/tests/crash_logger_test.cpp +++ b/tests/crash_logger_test.cpp @@ -9,7 +9,7 @@ #include #include -#include +#include #ifndef _WIN32 # include @@ -27,17 +27,17 @@ namespace logit_test { #ifdef _WIN32 # define private public -# include +# include # undef private #else # define private public -# include +# include # undef private #endif #undef _exit -#include +#include int main() { logit_test::reset_exit_code(); From 0004de56fa759fff1d6402f5bf141841f98a9895 Mon Sep 17 00:00:00 2001 From: Aster Seker Date: Tue, 16 Sep 2025 03:04:38 +0300 Subject: [PATCH 5/7] test: include config in crash logger test Ensure the crash logger test pulls in configuration macros by including logit/config.hpp before other logit headers so compilation succeeds when the test is built on CI. --- tests/crash_logger_test.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/crash_logger_test.cpp b/tests/crash_logger_test.cpp index fb0976b..9cf1cd5 100644 --- a/tests/crash_logger_test.cpp +++ b/tests/crash_logger_test.cpp @@ -9,7 +9,7 @@ #include #include -#include +#include #ifndef _WIN32 # include From a4eeab8d06155747dca44225df4154730b6ae3c7 Mon Sep 17 00:00:00 2001 From: Aster Seker Date: Tue, 16 Sep 2025 03:16:23 +0300 Subject: [PATCH 6/7] test: reorder crash logger includes Move the LogIt entry header before the platform-specific block and rely on it to provide crash logger definitions while keeping the exit stub in place. --- tests/crash_logger_test.cpp | 16 +++------------- 1 file changed, 3 insertions(+), 13 deletions(-) diff --git a/tests/crash_logger_test.cpp b/tests/crash_logger_test.cpp index 9cf1cd5..e51b4ea 100644 --- a/tests/crash_logger_test.cpp +++ b/tests/crash_logger_test.cpp @@ -24,20 +24,10 @@ namespace logit_test { } // namespace logit_test #define _exit ::logit_test::fake_exit - -#ifdef _WIN32 -# define private public -# include -# undef private -#else -# define private public -# include -# undef private -#endif - -#undef _exit - +#define private public #include +#undef private +#undef _exit int main() { logit_test::reset_exit_code(); From 98a20d8099c9aebb575b49d4868503a67dbc928b Mon Sep 17 00:00:00 2001 From: Aster Seker Date: Tue, 16 Sep 2025 03:29:28 +0300 Subject: [PATCH 7/7] test(crash): align exit stub linkage Include the platform exit headers before redefining _exit and give the stub C linkage so macOS and Windows builds use the correct symbol. --- tests/crash_logger_test.cpp | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/tests/crash_logger_test.cpp b/tests/crash_logger_test.cpp index e51b4ea..38f41e2 100644 --- a/tests/crash_logger_test.cpp +++ b/tests/crash_logger_test.cpp @@ -11,18 +11,27 @@ #include -#ifndef _WIN32 +#ifdef _WIN32 +# include +#else # include +# include #endif namespace logit_test { +#if __cplusplus >= 201703L + inline int g_exit_code = -1; +#else static int g_exit_code = -1; +#endif inline void reset_exit_code() { g_exit_code = -1; } - inline void fake_exit(int code) { g_exit_code = code; } + extern "C" void fake_exit(int code); } // namespace logit_test +extern "C" void logit_test::fake_exit(int code) { g_exit_code = code; } + #define _exit ::logit_test::fake_exit #define private public #include