From 9ec26058d1f8bf81205672d96985c5e5529379b5 Mon Sep 17 00:00:00 2001 From: R-Goc Date: Fri, 30 May 2025 10:50:55 +0200 Subject: [PATCH] LibTest/Tests: Build and run test-js on windows This commit allows test-js to build and run, also in CI. Co-authored-by: Andrew Kaster --- .../builtins/Error/Error.prototype.stack.js | 10 +-- Libraries/LibTest/CMakeLists.txt | 5 -- Libraries/LibTest/JavaScriptTestRunner.h | 3 - .../LibTest/JavaScriptTestRunnerMain.cpp | 65 +++++++++++-------- Libraries/LibTest/TestRunnerUtil.h | 15 +++-- Tests/LibJS/CMakeLists.txt | 4 -- 6 files changed, 54 insertions(+), 48 deletions(-) diff --git a/Libraries/LibJS/Tests/builtins/Error/Error.prototype.stack.js b/Libraries/LibJS/Tests/builtins/Error/Error.prototype.stack.js index 36eb4498214..adb4d9e88ae 100644 --- a/Libraries/LibJS/Tests/builtins/Error/Error.prototype.stack.js +++ b/Libraries/LibJS/Tests/builtins/Error/Error.prototype.stack.js @@ -6,11 +6,11 @@ describe("getter - normal behavior", () => { test("basic functionality", () => { const stackFrames = [ /^ at .*Error$/, - /^ at .+\/Error\/Error\.prototype\.stack\.js:\d+:\d+$/, - /^ at test \(.+\/test-common.js:\d+:\d+\)$/, - /^ at .+\/Error\/Error\.prototype\.stack\.js:6:9$/, - /^ at describe \(.+\/test-common\.js:\d+:\d+\)$/, - /^ at .+\/Error\/Error\.prototype\.stack\.js:5:9$/, + /^ at .+[\\/]Error[\\/]Error\.prototype\.stack\.js:\d+:\d+$/, + /^ at test \(.+[\\/]test-common\.js:\d+:\d+\)$/, + /^ at .+[\\/]Error[\\/]Error\.prototype\.stack\.js:6:9$/, + /^ at describe \(.+[\\/]test-common\.js:\d+:\d+\)$/, + /^ at .+[\\/]Error[\\/]Error\.prototype\.stack\.js:5:9$/, ]; const values = [ { diff --git a/Libraries/LibTest/CMakeLists.txt b/Libraries/LibTest/CMakeLists.txt index c58bea2cd7b..f2e09f85add 100644 --- a/Libraries/LibTest/CMakeLists.txt +++ b/Libraries/LibTest/CMakeLists.txt @@ -11,9 +11,4 @@ lagom_generate_export_header(LibTest test) target_link_libraries(LibTest PRIVATE AK LibCore LibFileSystem) set_target_properties(LibTest PROPERTIES OUTPUT_NAME lagom-test) -# FIXME: Increase support for building targets on Windows -if (WIN32 AND ENABLE_WINDOWS_CI) - return() -endif() - add_library(JavaScriptTestRunnerMain OBJECT JavaScriptTestRunnerMain.cpp) diff --git a/Libraries/LibTest/JavaScriptTestRunner.h b/Libraries/LibTest/JavaScriptTestRunner.h index b67e886c019..9650c2f18d6 100644 --- a/Libraries/LibTest/JavaScriptTestRunner.h +++ b/Libraries/LibTest/JavaScriptTestRunner.h @@ -32,9 +32,6 @@ #include #include #include -#include -#include -#include #define STRCAT(x, y) __STRCAT(x, y) #define STRSTRCAT(x, y) __STRSTRCAT(x, y) diff --git a/Libraries/LibTest/JavaScriptTestRunnerMain.cpp b/Libraries/LibTest/JavaScriptTestRunnerMain.cpp index 0b52080efaf..b155548a4b8 100644 --- a/Libraries/LibTest/JavaScriptTestRunnerMain.cpp +++ b/Libraries/LibTest/JavaScriptTestRunnerMain.cpp @@ -6,7 +6,10 @@ * SPDX-License-Identifier: BSD-2-Clause */ +#include #include +#include +#include #include #include #include @@ -36,19 +39,35 @@ using namespace Test::JS; static StringView g_program_name { "test-js"sv }; +static bool set_abort_action(void (*function)(int)) +{ +#if defined(AK_OS_WINDOWS) + auto rc = signal(SIGABRT, function); + if (rc == SIG_ERR) { + perror("sigaction"); + return false; + } + return true; +#else + struct sigaction act; + memset(&act, 0, sizeof(act)); + act.sa_flags = 0; + act.sa_handler = function; + int rc = sigaction(SIGABRT, &act, nullptr); + if (rc < 0) { + perror("sigaction"); + return false; + } + return true; +#endif +} + static void handle_sigabrt(int) { dbgln("{}: SIGABRT received, cleaning up.", g_program_name); Test::cleanup(); - struct sigaction act; - memset(&act, 0, sizeof(act)); - act.sa_flags = 0; - act.sa_handler = SIG_DFL; - int rc = sigaction(SIGABRT, &act, nullptr); - if (rc < 0) { - perror("sigaction"); + if (!set_abort_action(SIG_DFL)) exit(1); - } abort(); } @@ -64,15 +83,8 @@ int main(int argc, char** argv) auto program_name = LexicalPath::basename(argv[0]); g_program_name = program_name; - struct sigaction act; - memset(&act, 0, sizeof(act)); - act.sa_flags = 0; - act.sa_handler = handle_sigabrt; - int rc = sigaction(SIGABRT, &act, nullptr); - if (rc < 0) { - perror("sigaction"); + if (!set_abort_action(handle_sigabrt)) return 1; - } #ifdef SIGINFO signal(SIGINFO, [](int) { @@ -128,7 +140,7 @@ int main(int argc, char** argv) if (test_globs.is_empty()) test_globs.append("*"sv); - if (getenv("DISABLE_DBG_OUTPUT")) { + if (Core::Environment::has("DISABLE_DBG_OUTPUT"sv)) { AK::set_debug_enabled(false); } @@ -137,13 +149,13 @@ int main(int argc, char** argv) if (!specified_test_root.is_empty()) { test_root = ByteString { specified_test_root }; } else { - char* ladybird_source_dir = getenv("LADYBIRD_SOURCE_DIR"); - if (!ladybird_source_dir) { + auto ladybird_source_dir = Core::Environment::get("LADYBIRD_SOURCE_DIR"sv); + if (!ladybird_source_dir.has_value()) { warnln("No test root given, {} requires the LADYBIRD_SOURCE_DIR environment variable to be set", g_program_name); return 1; } - test_root = ByteString::formatted("{}/{}", ladybird_source_dir, g_test_root_fragment); - common_path = ByteString::formatted("{}/Libraries/LibJS/Tests/test-common.js", ladybird_source_dir); + test_root = LexicalPath::join(*ladybird_source_dir, g_test_root_fragment).string(); + common_path = LexicalPath::join(*ladybird_source_dir, "Libraries"sv, "LibJS"sv, "Tests"sv, "test-common.js"sv).string(); } if (!FileSystem::is_directory(test_root)) { warnln("Test root is not a directory: {}", test_root); @@ -151,12 +163,12 @@ int main(int argc, char** argv) } if (common_path.is_empty()) { - char* ladybird_source_dir = getenv("LADYBIRD_SOURCE_DIR"); - if (!ladybird_source_dir) { + auto ladybird_source_dir = Core::Environment::get("LADYBIRD_SOURCE_DIR"sv); + if (!ladybird_source_dir.has_value()) { warnln("No test root given, {} requires the LADYBIRD_SOURCE_DIR environment variable to be set", g_program_name); return 1; } - common_path = ByteString::formatted("{}/Libraries/LibJS/Tests/test-common.js", ladybird_source_dir); + common_path = LexicalPath::join(*ladybird_source_dir, "Libraries"sv, "LibJS"sv, "Tests"sv, "test-common.js"sv).string(); } auto test_root_or_error = FileSystem::real_path(test_root); @@ -173,9 +185,8 @@ int main(int argc, char** argv) } common_path = common_path_or_error.release_value(); - if (chdir(test_root.characters()) < 0) { - auto saved_errno = errno; - warnln("chdir failed: {}", strerror(saved_errno)); + if (auto err = Core::System::chdir(test_root); err.is_error()) { + warnln("chdir failed: {}", err.error()); return 1; } diff --git a/Libraries/LibTest/TestRunnerUtil.h b/Libraries/LibTest/TestRunnerUtil.h index e3832148171..efc3c36624c 100644 --- a/Libraries/LibTest/TestRunnerUtil.h +++ b/Libraries/LibTest/TestRunnerUtil.h @@ -8,9 +8,12 @@ #include #include -#include -#include -#include +#include + +#if !defined(AK_OS_WINDOWS) +# include +# include +#endif namespace Test { @@ -27,11 +30,15 @@ inline void iterate_directory_recursively(ByteString const& directory_path, Call while (directory_iterator.has_next()) { auto name = directory_iterator.next_path(); + auto full_path = LexicalPath::join(directory_path, name).string(); +#if defined(AK_OS_WINDOWS) + bool is_directory = FileSystem::is_directory(full_path); +#else struct stat st = {}; if (fstatat(directory_iterator.fd(), name.characters(), &st, AT_SYMLINK_NOFOLLOW) < 0) continue; bool is_directory = S_ISDIR(st.st_mode); - auto full_path = ByteString::formatted("{}/{}", directory_path, name); +#endif if (is_directory && name != "/Fixtures"sv) { iterate_directory_recursively(full_path, callback); } else if (!is_directory) { diff --git a/Tests/LibJS/CMakeLists.txt b/Tests/LibJS/CMakeLists.txt index 5ae32490f51..32f6a0e80e0 100644 --- a/Tests/LibJS/CMakeLists.txt +++ b/Tests/LibJS/CMakeLists.txt @@ -1,9 +1,5 @@ serenity_test(test-invalid-unicode-js.cpp LibJS LIBS LibJS LibUnicode) serenity_test(test-value-js.cpp LibJS LIBS LibJS LibUnicode) -if (WIN32 AND ENABLE_WINDOWS_CI) - return() -endif() - serenity_testjs_test(test-js.cpp test-js LIBS LibGC) set_tests_properties(test-js PROPERTIES ENVIRONMENT LADYBIRD_SOURCE_DIR=${SERENITY_PROJECT_ROOT})