mirror of
https://github.com/LadybirdBrowser/ladybird.git
synced 2025-04-25 05:55:13 +00:00
test-js: Support test262 parser tests
test-js now has a --test262-parser-tests option. Modules are skipped for now, current results: Test Suites: 1309 failed, 4314 passed, 5623 total Tests: 1309 failed, 262 skipped, 4052 passed, 5623 total Files: 5361 total Time: ~100ms (Lagom) / 600-800ms (Serenity) For more info, see: https://github.com/tc39/test262-parser-tests
This commit is contained in:
parent
3a72a93b9d
commit
ed116636ce
Notes:
sideshowbarker
2024-07-19 01:51:02 +09:00
Author: https://github.com/linusg Commit: https://github.com/SerenityOS/serenity/commit/ed116636cea Pull-request: https://github.com/SerenityOS/serenity/pull/3794
1 changed files with 115 additions and 10 deletions
|
@ -27,6 +27,7 @@
|
||||||
|
|
||||||
#include <AK/JsonObject.h>
|
#include <AK/JsonObject.h>
|
||||||
#include <AK/JsonValue.h>
|
#include <AK/JsonValue.h>
|
||||||
|
#include <AK/LexicalPath.h>
|
||||||
#include <AK/LogStream.h>
|
#include <AK/LogStream.h>
|
||||||
#include <AK/QuickSort.h>
|
#include <AK/QuickSort.h>
|
||||||
#include <LibCore/ArgsParser.h>
|
#include <LibCore/ArgsParser.h>
|
||||||
|
@ -126,10 +127,11 @@ public:
|
||||||
|
|
||||||
const JSTestRunnerCounts& counts() const { return m_counts; }
|
const JSTestRunnerCounts& counts() const { return m_counts; }
|
||||||
|
|
||||||
private:
|
protected:
|
||||||
static TestRunner* s_the;
|
static TestRunner* s_the;
|
||||||
|
|
||||||
JSFileResult run_file_test(const String& test_path);
|
virtual Vector<String> get_test_paths() const;
|
||||||
|
virtual JSFileResult run_file_test(const String& test_path);
|
||||||
void print_file_result(const JSFileResult& file_result) const;
|
void print_file_result(const JSFileResult& file_result) const;
|
||||||
void print_test_results() const;
|
void print_test_results() const;
|
||||||
|
|
||||||
|
@ -204,24 +206,21 @@ static void iterate_directory_recursively(const String& directory_path, Callback
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static Vector<String> get_test_paths(const String& test_root)
|
Vector<String> TestRunner::get_test_paths() const
|
||||||
{
|
{
|
||||||
Vector<String> paths;
|
Vector<String> paths;
|
||||||
|
iterate_directory_recursively(m_test_root, [&](const String& file_path) {
|
||||||
iterate_directory_recursively(test_root, [&](const String& file_path) {
|
|
||||||
if (!file_path.ends_with("test-common.js"))
|
if (!file_path.ends_with("test-common.js"))
|
||||||
paths.append(file_path);
|
paths.append(file_path);
|
||||||
});
|
});
|
||||||
|
|
||||||
quick_sort(paths);
|
quick_sort(paths);
|
||||||
|
|
||||||
return paths;
|
return paths;
|
||||||
}
|
}
|
||||||
|
|
||||||
void TestRunner::run()
|
void TestRunner::run()
|
||||||
{
|
{
|
||||||
size_t progress_counter = 0;
|
size_t progress_counter = 0;
|
||||||
auto test_paths = get_test_paths(m_test_root);
|
auto test_paths = get_test_paths();
|
||||||
for (auto& path : test_paths) {
|
for (auto& path : test_paths) {
|
||||||
++progress_counter;
|
++progress_counter;
|
||||||
print_file_result(run_file_test(path));
|
print_file_result(run_file_test(path));
|
||||||
|
@ -292,7 +291,6 @@ JSFileResult TestRunner::run_file_test(const String& test_path)
|
||||||
printf("%s\n", result.error().error.to_string().characters());
|
printf("%s\n", result.error().error.to_string().characters());
|
||||||
printf("%s\n", result.error().hint.characters());
|
printf("%s\n", result.error().hint.characters());
|
||||||
cleanup_and_exit();
|
cleanup_and_exit();
|
||||||
;
|
|
||||||
}
|
}
|
||||||
m_test_program = result.value();
|
m_test_program = result.value();
|
||||||
}
|
}
|
||||||
|
@ -579,6 +577,97 @@ void TestRunner::print_test_results() const
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
class Test262ParserTestRunner final : public TestRunner {
|
||||||
|
public:
|
||||||
|
using TestRunner::TestRunner;
|
||||||
|
|
||||||
|
private:
|
||||||
|
virtual Vector<String> get_test_paths() const override;
|
||||||
|
virtual JSFileResult run_file_test(const String& test_path) override;
|
||||||
|
};
|
||||||
|
|
||||||
|
Vector<String> Test262ParserTestRunner::get_test_paths() const
|
||||||
|
{
|
||||||
|
Vector<String> paths;
|
||||||
|
iterate_directory_recursively(m_test_root, [&](const String& file_path) {
|
||||||
|
auto dirname = LexicalPath(file_path).dirname();
|
||||||
|
if (dirname.ends_with("early") || dirname.ends_with("fail") || dirname.ends_with("pass") || dirname.ends_with("pass-explicit"))
|
||||||
|
paths.append(file_path);
|
||||||
|
});
|
||||||
|
quick_sort(paths);
|
||||||
|
return paths;
|
||||||
|
}
|
||||||
|
|
||||||
|
JSFileResult Test262ParserTestRunner::run_file_test(const String& test_path)
|
||||||
|
{
|
||||||
|
currently_running_test = test_path;
|
||||||
|
|
||||||
|
auto dirname = LexicalPath(test_path).dirname();
|
||||||
|
bool expecting_file_to_parse;
|
||||||
|
if (dirname.ends_with("early") || dirname.ends_with("fail")) {
|
||||||
|
expecting_file_to_parse = false;
|
||||||
|
} else if (dirname.ends_with("pass") || dirname.ends_with("pass-explicit")) {
|
||||||
|
expecting_file_to_parse = true;
|
||||||
|
} else {
|
||||||
|
ASSERT_NOT_REACHED();
|
||||||
|
}
|
||||||
|
|
||||||
|
auto start_time = get_time_in_ms();
|
||||||
|
String details = "";
|
||||||
|
TestResult test_result;
|
||||||
|
if (test_path.ends_with(".module.js")) {
|
||||||
|
test_result = TestResult::Skip;
|
||||||
|
m_counts.tests_skipped++;
|
||||||
|
m_counts.suites_passed++;
|
||||||
|
} else {
|
||||||
|
auto parse_result = parse_file(test_path);
|
||||||
|
if (expecting_file_to_parse) {
|
||||||
|
if (!parse_result.is_error()) {
|
||||||
|
test_result = TestResult::Pass;
|
||||||
|
} else {
|
||||||
|
test_result = TestResult::Fail;
|
||||||
|
details = parse_result.error().error.to_string();
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (parse_result.is_error()) {
|
||||||
|
test_result = TestResult::Pass;
|
||||||
|
} else {
|
||||||
|
test_result = TestResult::Fail;
|
||||||
|
details = "File was expected to produce a parser error but didn't";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// test262-parser-tests doesn't have "suites" and "tests" in the usual sense, it just has files
|
||||||
|
// and an expectation whether they should parse or not. We add one suite with one test nonetheless:
|
||||||
|
//
|
||||||
|
// - This makes interpreting skipped test easier as their file is shown as "PASS"
|
||||||
|
// - That way we can show additional information such as "file parsed but shouldn't have" or
|
||||||
|
// parser errors for files that should parse respectively
|
||||||
|
|
||||||
|
JSTest test { expecting_file_to_parse ? "file should parse" : "file should not parse", test_result, details };
|
||||||
|
JSSuite suite { "Parse file", test_result, { test } };
|
||||||
|
JSFileResult file_result {
|
||||||
|
test_path.substring(m_test_root.length() + 1, test_path.length() - m_test_root.length() - 1),
|
||||||
|
{},
|
||||||
|
get_time_in_ms() - start_time,
|
||||||
|
test_result,
|
||||||
|
{ suite }
|
||||||
|
};
|
||||||
|
|
||||||
|
if (test_result == TestResult::Fail) {
|
||||||
|
m_counts.tests_failed++;
|
||||||
|
m_counts.suites_failed++;
|
||||||
|
} else {
|
||||||
|
m_counts.tests_passed++;
|
||||||
|
m_counts.suites_passed++;
|
||||||
|
}
|
||||||
|
m_counts.files_total++;
|
||||||
|
m_total_elapsed_time_in_ms += file_result.time_taken;
|
||||||
|
|
||||||
|
return file_result;
|
||||||
|
}
|
||||||
|
|
||||||
int main(int argc, char** argv)
|
int main(int argc, char** argv)
|
||||||
{
|
{
|
||||||
struct sigaction act;
|
struct sigaction act;
|
||||||
|
@ -601,14 +690,27 @@ int main(int argc, char** argv)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
bool print_times = false;
|
bool print_times = false;
|
||||||
|
bool test262_parser_tests = false;
|
||||||
const char* test_root = nullptr;
|
const char* test_root = nullptr;
|
||||||
|
|
||||||
Core::ArgsParser args_parser;
|
Core::ArgsParser args_parser;
|
||||||
args_parser.add_option(print_times, "Show duration of each test", "show-time", 't');
|
args_parser.add_option(print_times, "Show duration of each test", "show-time", 't');
|
||||||
args_parser.add_option(collect_on_every_allocation, "Collect garbage after every allocation", "collect-often", 'g');
|
args_parser.add_option(collect_on_every_allocation, "Collect garbage after every allocation", "collect-often", 'g');
|
||||||
|
args_parser.add_option(test262_parser_tests, "Run test262 parser tests", "test262-parser-tests", 0);
|
||||||
args_parser.add_positional_argument(test_root, "Tests root directory", "path", Core::ArgsParser::Required::No);
|
args_parser.add_positional_argument(test_root, "Tests root directory", "path", Core::ArgsParser::Required::No);
|
||||||
args_parser.parse(argc, argv);
|
args_parser.parse(argc, argv);
|
||||||
|
|
||||||
|
if (test262_parser_tests) {
|
||||||
|
if (collect_on_every_allocation) {
|
||||||
|
fprintf(stderr, "--collect-often and --test262-parser-tests options must not be used together\n");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
if (!test_root) {
|
||||||
|
fprintf(stderr, "Test root is required with --test262-parser-tests\n");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (getenv("DISABLE_DBG_OUTPUT")) {
|
if (getenv("DISABLE_DBG_OUTPUT")) {
|
||||||
DebugLogStream::set_enabled(false);
|
DebugLogStream::set_enabled(false);
|
||||||
}
|
}
|
||||||
|
@ -632,7 +734,10 @@ int main(int argc, char** argv)
|
||||||
|
|
||||||
vm = JS::VM::create();
|
vm = JS::VM::create();
|
||||||
|
|
||||||
TestRunner(test_root, print_times).run();
|
if (test262_parser_tests)
|
||||||
|
Test262ParserTestRunner(test_root, print_times).run();
|
||||||
|
else
|
||||||
|
TestRunner(test_root, print_times).run();
|
||||||
|
|
||||||
vm = nullptr;
|
vm = nullptr;
|
||||||
|
|
||||||
|
|
Loading…
Add table
Reference in a new issue