mirror of
https://github.com/RGBCube/serenity
synced 2025-07-25 23:07:35 +00:00
LibTest+test-js: Add back the lost test262 parser test option
Fixes #7566.
This commit is contained in:
parent
724b89f90c
commit
f387da4a90
3 changed files with 132 additions and 0 deletions
|
@ -9,6 +9,8 @@
|
||||||
|
|
||||||
TEST_ROOT("Userland/Libraries/LibJS/Tests");
|
TEST_ROOT("Userland/Libraries/LibJS/Tests");
|
||||||
|
|
||||||
|
TESTJS_PROGRAM_FLAG(test262_parser_tests, "Run test262 parser tests", "test262-parser-tests", 0);
|
||||||
|
|
||||||
TESTJS_GLOBAL_FUNCTION(is_strict_mode, isStrictMode, 0)
|
TESTJS_GLOBAL_FUNCTION(is_strict_mode, isStrictMode, 0)
|
||||||
{
|
{
|
||||||
return JS::Value(vm.in_strict_mode());
|
return JS::Value(vm.in_strict_mode());
|
||||||
|
@ -29,3 +31,63 @@ TESTJS_GLOBAL_FUNCTION(run_queued_promise_jobs, runQueuedPromiseJobs)
|
||||||
vm.run_queued_promise_jobs();
|
vm.run_queued_promise_jobs();
|
||||||
return JS::js_undefined();
|
return JS::js_undefined();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TESTJS_RUN_FILE_FUNCTION(const String& test_file, JS::Interpreter&)
|
||||||
|
{
|
||||||
|
if (!test262_parser_tests)
|
||||||
|
return Test::JS::RunFileHookResult::RunAsNormal;
|
||||||
|
|
||||||
|
auto start_time = Test::JS::get_time_in_ms();
|
||||||
|
|
||||||
|
LexicalPath path(test_file);
|
||||||
|
auto& dirname = path.dirname();
|
||||||
|
enum {
|
||||||
|
Early,
|
||||||
|
Fail,
|
||||||
|
Pass,
|
||||||
|
ExplicitPass,
|
||||||
|
} expectation { Pass };
|
||||||
|
|
||||||
|
if (dirname.ends_with("early"))
|
||||||
|
expectation = Early;
|
||||||
|
else if (dirname.ends_with("fail"))
|
||||||
|
expectation = Fail;
|
||||||
|
else if (dirname.ends_with("pass-explicit"))
|
||||||
|
expectation = ExplicitPass;
|
||||||
|
else if (dirname.ends_with("pass"))
|
||||||
|
expectation = Pass;
|
||||||
|
else
|
||||||
|
return Test::JS::RunFileHookResult::SkipFile;
|
||||||
|
|
||||||
|
auto parse_result = Test::JS::parse_file(test_file);
|
||||||
|
bool test_passed = true;
|
||||||
|
String message;
|
||||||
|
String expectation_string;
|
||||||
|
|
||||||
|
switch (expectation) {
|
||||||
|
case Early:
|
||||||
|
case Fail:
|
||||||
|
expectation_string = "File should not parse";
|
||||||
|
test_passed = parse_result.is_error();
|
||||||
|
if (!test_passed)
|
||||||
|
message = "Expected the file to fail parsing, but it did not";
|
||||||
|
break;
|
||||||
|
case Pass:
|
||||||
|
case ExplicitPass:
|
||||||
|
expectation_string = "File should parse";
|
||||||
|
test_passed = !parse_result.is_error();
|
||||||
|
if (!test_passed)
|
||||||
|
message = "Expected the file to parse, but it did not";
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto test_result = test_passed ? Test::Result::Pass : Test::Result::Fail;
|
||||||
|
|
||||||
|
return Test::JS::JSFileResult {
|
||||||
|
LexicalPath::relative_path(test_file, Test::JS::g_test_root),
|
||||||
|
{},
|
||||||
|
Test::JS::get_time_in_ms() - start_time,
|
||||||
|
test_result,
|
||||||
|
{ Test::Suite { "Parse file", test_result, { { expectation_string, test_result, message } } } }
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
|
@ -68,9 +68,28 @@
|
||||||
} __testjs_common_register_##name {}; \
|
} __testjs_common_register_##name {}; \
|
||||||
void __TestJS_main_hook::hook()
|
void __TestJS_main_hook::hook()
|
||||||
|
|
||||||
|
#define TESTJS_PROGRAM_FLAG(flag, help_string, long_name, short_name) \
|
||||||
|
bool flag { false }; \
|
||||||
|
struct __TestJS_flag_hook_##flag { \
|
||||||
|
__TestJS_flag_hook_##flag() \
|
||||||
|
{ \
|
||||||
|
::Test::JS::g_extra_args.set(&(flag), { help_string, long_name, short_name }); \
|
||||||
|
}; \
|
||||||
|
} __testjs_flag_hook_##flag;
|
||||||
|
|
||||||
#define TEST_ROOT(path) \
|
#define TEST_ROOT(path) \
|
||||||
String Test::JS::g_test_root_fragment = path
|
String Test::JS::g_test_root_fragment = path
|
||||||
|
|
||||||
|
#define TESTJS_RUN_FILE_FUNCTION(...) \
|
||||||
|
struct __TestJS_run_file { \
|
||||||
|
__TestJS_run_file() \
|
||||||
|
{ \
|
||||||
|
::Test::JS::g_run_file = hook; \
|
||||||
|
} \
|
||||||
|
static ::Test::JS::IntermediateRunFileResult hook(const String&, JS::Interpreter&); \
|
||||||
|
} __testjs_common_run_file {}; \
|
||||||
|
::Test::JS::IntermediateRunFileResult __TestJS_run_file::hook(__VA_ARGS__)
|
||||||
|
|
||||||
namespace Test::JS {
|
namespace Test::JS {
|
||||||
|
|
||||||
namespace JS = ::JS;
|
namespace JS = ::JS;
|
||||||
|
@ -96,6 +115,7 @@ extern String g_test_root;
|
||||||
extern int g_test_argc;
|
extern int g_test_argc;
|
||||||
extern char** g_test_argv;
|
extern char** g_test_argv;
|
||||||
extern Function<void()> g_main_hook;
|
extern Function<void()> g_main_hook;
|
||||||
|
extern HashMap<bool*, Tuple<String, String, char>> g_extra_args;
|
||||||
|
|
||||||
struct ParserError {
|
struct ParserError {
|
||||||
JS::Parser::Error error;
|
JS::Parser::Error error;
|
||||||
|
@ -113,6 +133,14 @@ struct JSFileResult {
|
||||||
Vector<String> logged_messages {};
|
Vector<String> logged_messages {};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
enum class RunFileHookResult {
|
||||||
|
RunAsNormal,
|
||||||
|
SkipFile,
|
||||||
|
};
|
||||||
|
|
||||||
|
using IntermediateRunFileResult = AK::Result<JSFileResult, RunFileHookResult>;
|
||||||
|
extern IntermediateRunFileResult (*g_run_file)(const String&, JS::Interpreter&);
|
||||||
|
|
||||||
class TestRunner {
|
class TestRunner {
|
||||||
public:
|
public:
|
||||||
static TestRunner* the()
|
static TestRunner* the()
|
||||||
|
@ -302,6 +330,41 @@ inline JSFileResult TestRunner::run_file_test(const String& test_path)
|
||||||
|
|
||||||
interpreter->heap().set_should_collect_on_every_allocation(g_collect_on_every_allocation);
|
interpreter->heap().set_should_collect_on_every_allocation(g_collect_on_every_allocation);
|
||||||
|
|
||||||
|
if (g_run_file) {
|
||||||
|
auto result = g_run_file(test_path, *interpreter);
|
||||||
|
if (result.is_error() && result.error() == RunFileHookResult::SkipFile) {
|
||||||
|
return {
|
||||||
|
test_path,
|
||||||
|
{},
|
||||||
|
0,
|
||||||
|
Test::Result::Skip,
|
||||||
|
{},
|
||||||
|
{}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
if (!result.is_error()) {
|
||||||
|
auto value = result.release_value();
|
||||||
|
for (auto& suite : value.suites) {
|
||||||
|
if (suite.most_severe_test_result == Result::Pass)
|
||||||
|
m_counts.suites_passed++;
|
||||||
|
else if (suite.most_severe_test_result == Result::Fail)
|
||||||
|
m_counts.suites_failed++;
|
||||||
|
for (auto& test : suite.tests) {
|
||||||
|
if (test.result == Result::Pass)
|
||||||
|
m_counts.tests_passed++;
|
||||||
|
else if (test.result == Result::Fail)
|
||||||
|
m_counts.tests_failed++;
|
||||||
|
else if (test.result == Result::Skip)
|
||||||
|
m_counts.tests_skipped++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
++m_counts.files_total;
|
||||||
|
m_total_elapsed_time_in_ms += value.time_taken;
|
||||||
|
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (!m_test_program) {
|
if (!m_test_program) {
|
||||||
auto result = parse_file(m_common_path);
|
auto result = parse_file(m_common_path);
|
||||||
if (result.is_error()) {
|
if (result.is_error()) {
|
||||||
|
|
|
@ -18,6 +18,8 @@ String g_currently_running_test;
|
||||||
String g_test_glob;
|
String g_test_glob;
|
||||||
HashMap<String, FunctionWithLength> s_exposed_global_functions;
|
HashMap<String, FunctionWithLength> s_exposed_global_functions;
|
||||||
Function<void()> g_main_hook;
|
Function<void()> g_main_hook;
|
||||||
|
HashMap<bool*, Tuple<String, String, char>> g_extra_args;
|
||||||
|
IntermediateRunFileResult (*g_run_file)(const String&, JS::Interpreter&) = nullptr;
|
||||||
TestRunner* TestRunner::s_the = nullptr;
|
TestRunner* TestRunner::s_the = nullptr;
|
||||||
String g_test_root;
|
String g_test_root;
|
||||||
int g_test_argc;
|
int g_test_argc;
|
||||||
|
@ -100,6 +102,8 @@ int main(int argc, char** argv)
|
||||||
});
|
});
|
||||||
args_parser.add_option(g_collect_on_every_allocation, "Collect garbage after every allocation", "collect-often", 'g');
|
args_parser.add_option(g_collect_on_every_allocation, "Collect garbage after every allocation", "collect-often", 'g');
|
||||||
args_parser.add_option(g_test_glob, "Only run tests matching the given glob", "filter", 'f', "glob");
|
args_parser.add_option(g_test_glob, "Only run tests matching the given glob", "filter", 'f', "glob");
|
||||||
|
for (auto& entry : g_extra_args)
|
||||||
|
args_parser.add_option(*entry.key, entry.value.get<0>().characters(), entry.value.get<1>().characters(), entry.value.get<2>());
|
||||||
args_parser.add_positional_argument(specified_test_root, "Tests root directory", "path", Core::ArgsParser::Required::No);
|
args_parser.add_positional_argument(specified_test_root, "Tests root directory", "path", Core::ArgsParser::Required::No);
|
||||||
args_parser.add_positional_argument(common_path, "Path to tests-common.js", "common-path", Core::ArgsParser::Required::No);
|
args_parser.add_positional_argument(common_path, "Path to tests-common.js", "common-path", Core::ArgsParser::Required::No);
|
||||||
args_parser.parse(argc, argv);
|
args_parser.parse(argc, argv);
|
||||||
|
@ -145,6 +149,9 @@ int main(int argc, char** argv)
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
test_root = Core::File::real_path_for(test_root);
|
||||||
|
common_path = Core::File::real_path_for(common_path);
|
||||||
|
|
||||||
if (chdir(test_root.characters()) < 0) {
|
if (chdir(test_root.characters()) < 0) {
|
||||||
auto saved_errno = errno;
|
auto saved_errno = errno;
|
||||||
warnln("chdir failed: {}", strerror(saved_errno));
|
warnln("chdir failed: {}", strerror(saved_errno));
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue