run-tests: Dump a backtrace for crashed tests

It only makes sense to see what a crashed test was up to, so generate a
backtrace if we can find the coredump and read it.
This commit is contained in:
Ali Mohammad Pur 2022-01-26 23:16:36 +03:30 committed by Linus Groh
parent 1c121d7488
commit 58ed00f633
Notes: sideshowbarker 2024-07-17 20:05:07 +09:00
2 changed files with 30 additions and 2 deletions

View File

@ -152,7 +152,7 @@ target_link_libraries(pwd LibMain)
target_link_libraries(rev LibMain)
target_link_libraries(rm LibMain)
target_link_libraries(rmdir LibMain)
target_link_libraries(run-tests LibRegex)
target_link_libraries(run-tests LibRegex LibCoredump)
target_link_libraries(shot LibGUI)
target_link_libraries(shuf LibMain)
target_link_libraries(sql LibLine LibSQL LibIPC)

View File

@ -8,6 +8,7 @@
#include <LibCore/ArgsParser.h>
#include <LibCore/ConfigFile.h>
#include <LibCore/File.h>
#include <LibCoredump/Backtrace.h>
#include <LibRegex/Regex.h>
#include <LibTest/TestRunner.h>
#include <signal.h>
@ -27,6 +28,7 @@ struct FileResult {
double time_taken { 0 };
Test::Result result { Test::Result::Pass };
int stdout_err_fd { -1 };
pid_t child_pid { 0 };
};
String g_currently_running_test;
@ -129,6 +131,32 @@ void TestRunner::do_run_single_test(const String& test_path, size_t current_test
print_modifiers({ Test::BG_RED, Test::FG_BLACK, Test::FG_BOLD });
out("{}", test_result.result == Test::Result::Fail ? " FAIL " : "CRASHED");
print_modifiers({ Test::CLEAR });
if (test_result.result == Test::Result::Crashed) {
auto pid_search_string = String::formatted("_{}_", test_result.child_pid);
Core::DirIterator iterator("/tmp/coredump"sv);
if (!iterator.has_error()) {
while (iterator.has_next()) {
auto path = iterator.next_full_path();
if (!path.contains(pid_search_string))
continue;
auto reader = Coredump::Reader::create(path);
if (!reader)
break;
dbgln("Last crash backtrace for {} (was pid {}):", test_path, test_result.child_pid);
reader->for_each_thread_info([&](auto thread_info) {
Coredump::Backtrace thread_backtrace(*reader, thread_info);
auto tid = thread_info.tid; // Note: Yoinking this out of the struct because we can't pass a reference to it (as it's a misaligned field in a packed struct)
dbgln("Thread {}", tid);
for (auto const& entry : thread_backtrace.entries())
dbgln("- {}", entry.to_string(true));
return IterationDecision::Continue;
});
break;
}
}
}
} else {
print_modifiers({ Test::BG_GREEN, Test::FG_BLACK, Test::FG_BOLD });
out(" PASS ");
@ -251,7 +279,7 @@ FileResult TestRunner::run_test_file(const String& test_path)
ret = unlink(child_out_err_path);
VERIFY(ret == 0);
return FileResult { move(path_for_test), get_time_in_ms() - start_time, test_result, child_out_err_file };
return FileResult { move(path_for_test), get_time_in_ms() - start_time, test_result, child_out_err_file, child_pid };
}
int main(int argc, char** argv)