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/JsonValue.h>
|
||||
#include <AK/LexicalPath.h>
|
||||
#include <AK/LogStream.h>
|
||||
#include <AK/QuickSort.h>
|
||||
#include <LibCore/ArgsParser.h>
|
||||
|
@ -126,10 +127,11 @@ public:
|
|||
|
||||
const JSTestRunnerCounts& counts() const { return m_counts; }
|
||||
|
||||
private:
|
||||
protected:
|
||||
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_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;
|
||||
|
||||
iterate_directory_recursively(test_root, [&](const String& file_path) {
|
||||
iterate_directory_recursively(m_test_root, [&](const String& file_path) {
|
||||
if (!file_path.ends_with("test-common.js"))
|
||||
paths.append(file_path);
|
||||
});
|
||||
|
||||
quick_sort(paths);
|
||||
|
||||
return paths;
|
||||
}
|
||||
|
||||
void TestRunner::run()
|
||||
{
|
||||
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) {
|
||||
++progress_counter;
|
||||
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().hint.characters());
|
||||
cleanup_and_exit();
|
||||
;
|
||||
}
|
||||
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)
|
||||
{
|
||||
struct sigaction act;
|
||||
|
@ -601,14 +690,27 @@ int main(int argc, char** argv)
|
|||
#endif
|
||||
|
||||
bool print_times = false;
|
||||
bool test262_parser_tests = false;
|
||||
const char* test_root = nullptr;
|
||||
|
||||
Core::ArgsParser args_parser;
|
||||
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(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.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")) {
|
||||
DebugLogStream::set_enabled(false);
|
||||
}
|
||||
|
@ -632,6 +734,9 @@ int main(int argc, char** argv)
|
|||
|
||||
vm = JS::VM::create();
|
||||
|
||||
if (test262_parser_tests)
|
||||
Test262ParserTestRunner(test_root, print_times).run();
|
||||
else
|
||||
TestRunner(test_root, print_times).run();
|
||||
|
||||
vm = nullptr;
|
||||
|
|
Loading…
Add table
Reference in a new issue