headless-browser: Handle WebContent crashes similar to the graphical UIs

Instead of bringing the whole browser down, let's re-initialize the
WebContent client so we can move on. This is particularly needed for
WPT.
This commit is contained in:
Timothy Flynn 2024-11-12 08:50:54 -05:00 committed by Tim Ledbetter
commit 70ce8046c3
Notes: github-actions[bot] 2024-11-12 14:27:00 +00:00
4 changed files with 42 additions and 12 deletions

View file

@ -98,6 +98,13 @@ static ErrorOr<void> collect_ref_tests(Vector<Test>& tests, StringView path, Str
return {};
}
static void clear_test_callbacks(HeadlessWebView& view)
{
view.on_load_finish = {};
view.on_text_test_finish = {};
view.on_web_content_crashed = {};
}
void run_dump_test(HeadlessWebView& view, Test& test, URL::URL const& url, int timeout_in_milliseconds)
{
auto timer = Core::Timer::create_single_shot(timeout_in_milliseconds, [&view, &test]() {
@ -160,17 +167,22 @@ void run_dump_test(HeadlessWebView& view, Test& test, URL::URL const& url, int t
};
auto on_test_complete = [&view, &test, timer, handle_completed_test]() {
clear_test_callbacks(view);
timer->stop();
view.on_load_finish = {};
view.on_text_test_finish = {};
if (auto result = handle_completed_test(); result.is_error())
view.on_test_complete({ test, TestResult::Fail });
else
view.on_test_complete({ test, result.value() });
};
view.on_web_content_crashed = [&view, &test, timer]() {
clear_test_callbacks(view);
timer->stop();
view.on_test_complete({ test, TestResult::Crashed });
};
if (test.mode == TestMode::Layout) {
view.on_load_finish = [&view, &test, url, on_test_complete = move(on_test_complete)](auto const& loaded_url) {
// We don't want subframe loads to trigger the test finish.
@ -257,17 +269,22 @@ static void run_ref_test(HeadlessWebView& view, Test& test, URL::URL const& url,
};
auto on_test_complete = [&view, &test, timer, handle_completed_test]() {
clear_test_callbacks(view);
timer->stop();
view.on_load_finish = {};
view.on_text_test_finish = {};
if (auto result = handle_completed_test(); result.is_error())
view.on_test_complete({ test, TestResult::Fail });
else
view.on_test_complete({ test, result.value() });
};
view.on_web_content_crashed = [&view, &test, timer]() {
clear_test_callbacks(view);
timer->stop();
view.on_test_complete({ test, TestResult::Crashed });
};
view.on_load_finish = [&view, &test, on_test_complete = move(on_test_complete)](auto const&) {
if (test.actual_screenshot) {
view.take_screenshot()->when_resolved([&test, on_test_complete = move(on_test_complete)](RefPtr<Gfx::Bitmap> screenshot) {
@ -418,6 +435,7 @@ ErrorOr<void> run_tests(Core::AnonymousBuffer const& theme, Gfx::IntSize window_
size_t pass_count = 0;
size_t fail_count = 0;
size_t timeout_count = 0;
size_t crashed_count = 0;
size_t skipped_count = 0;
bool is_tty = isatty(STDOUT_FILENO);
@ -473,6 +491,9 @@ ErrorOr<void> run_tests(Core::AnonymousBuffer const& theme, Gfx::IntSize window_
case TestResult::Timeout:
++timeout_count;
break;
case TestResult::Crashed:
++crashed_count;
break;
case TestResult::Skipped:
++skipped_count;
break;
@ -497,9 +518,9 @@ ErrorOr<void> run_tests(Core::AnonymousBuffer const& theme, Gfx::IntSize window_
if (is_tty)
outln("\33[2K\rDone!");
outln("==================================================");
outln("Pass: {}, Fail: {}, Skipped: {}, Timeout: {}", pass_count, fail_count, skipped_count, timeout_count);
outln("==================================================");
outln("==========================================================");
outln("Pass: {}, Fail: {}, Skipped: {}, Timeout: {}, Crashed: {}", pass_count, fail_count, skipped_count, timeout_count, crashed_count);
outln("==========================================================");
for (auto const& non_passing_test : non_passing_tests) {
if (non_passing_test.result == TestResult::Skipped && !app.verbose)