From bef7e704c5f7e64e1048c9eabcf8a4f7088b4234 Mon Sep 17 00:00:00 2001 From: Tim Ledbetter Date: Fri, 22 Nov 2024 22:29:21 +0000 Subject: [PATCH] headless-browser: Add support for crash tests These are essentially the same as text tests, but they have no associated expectation file. These tests pass if the test fully loads without crashing. --- UI/Headless/Test.cpp | 35 +++++++++++++++++++++++++++++++++-- UI/Headless/Test.h | 1 + 2 files changed, 34 insertions(+), 2 deletions(-) diff --git a/UI/Headless/Test.cpp b/UI/Headless/Test.cpp index 9aef450735f..aece2eeb33a 100644 --- a/UI/Headless/Test.cpp +++ b/UI/Headless/Test.cpp @@ -57,6 +57,12 @@ static ErrorOr load_test_config(StringView test_root_path) return {}; } +static bool is_valid_test_name(StringView test_name) +{ + auto valid_test_file_suffixes = { ".htm"sv, ".html"sv, ".svg"sv, ".xhtml"sv, ".xht"sv }; + return AK::any_of(valid_test_file_suffixes, [&](auto suffix) { return test_name.ends_with(suffix); }); +} + static ErrorOr collect_dump_tests(Application const& app, Vector& tests, StringView path, StringView trail, TestMode mode) { Core::DirIterator it(ByteString::formatted("{}/input/{}", path, trail), Core::DirIterator::Flags::SkipDots); @@ -70,7 +76,7 @@ static ErrorOr collect_dump_tests(Application const& app, Vector& te continue; } - if (!name.ends_with(".htm"sv) && !name.ends_with(".html"sv) && !name.ends_with(".svg"sv) && !name.ends_with(".xhtml"sv) && !name.ends_with(".xht"sv)) + if (!is_valid_test_name(name)) continue; auto expectation_path = ByteString::formatted("{}/expected/{}/{}.txt", path, trail, LexicalPath::title(name)); @@ -100,6 +106,27 @@ static ErrorOr collect_ref_tests(Application const& app, Vector& tes return {}; } +static ErrorOr collect_crash_tests(Vector& tests, StringView path, StringView trail) +{ + Core::DirIterator it(ByteString::formatted("{}/{}", path, trail), Core::DirIterator::Flags::SkipDots); + while (it.has_next()) { + auto name = it.next_path(); + auto input_path = TRY(FileSystem::real_path(ByteString::formatted("{}/{}/{}", path, trail, name))); + + if (FileSystem::is_directory(input_path)) { + TRY(collect_crash_tests(tests, path, ByteString::formatted("{}/{}", trail, name))); + continue; + } + + if (!is_valid_test_name(name)) + continue; + + tests.append({ TestMode::Crash, input_path, {}, {} }); + } + + return {}; +} + static void clear_test_callbacks(HeadlessWebView& view) { view.on_load_finish = {}; @@ -205,7 +232,7 @@ void run_dump_test(HeadlessWebView& view, Test& test, URL::URL const& url, int t }); }); }; - } else if (test.mode == TestMode::Text) { + } else if (test.mode == TestMode::Text || test.mode == TestMode::Crash) { view.on_load_finish = [&view, &test, on_test_complete, url](auto const& loaded_url) { // We don't want subframe loads to trigger the test finish. if (!url.equals(loaded_url, URL::ExcludeFragment::Yes)) @@ -404,6 +431,9 @@ static void run_test(HeadlessWebView& view, Test& test, Application& app) case TestMode::Ref: run_ref_test(view, test, url, app.per_test_timeout_in_seconds * 1000); return; + case TestMode::Crash: + run_dump_test(view, test, url, app.per_test_timeout_in_seconds * 1000); + return; } VERIFY_NOT_REACHED(); @@ -423,6 +453,7 @@ ErrorOr run_tests(Core::AnonymousBuffer const& theme, Web::DevicePixelSize TRY(collect_dump_tests(app, tests, ByteString::formatted("{}/Layout", app.test_root_path), "."sv, TestMode::Layout)); TRY(collect_dump_tests(app, tests, ByteString::formatted("{}/Text", app.test_root_path), "."sv, TestMode::Text)); TRY(collect_ref_tests(app, tests, ByteString::formatted("{}/Ref", app.test_root_path), "."sv)); + TRY(collect_crash_tests(tests, ByteString::formatted("{}/Crash", app.test_root_path), "."sv)); #if !defined(AK_OS_MACOS) TRY(collect_ref_tests(app, tests, ByteString::formatted("{}/Screenshot", app.test_root_path), "."sv)); #endif diff --git a/UI/Headless/Test.h b/UI/Headless/Test.h index b4c9819239e..277c8eb1af8 100644 --- a/UI/Headless/Test.h +++ b/UI/Headless/Test.h @@ -27,6 +27,7 @@ enum class TestMode { Layout, Text, Ref, + Crash, }; enum class TestResult {