mirror of
https://github.com/LadybirdBrowser/ladybird.git
synced 2024-11-25 17:10:23 +00:00
Tests+LibJS: Add very simple bytecode LibJS tests
These tests are not meant as a replacement to test-js with the -b option but are meant to test simple cases until that works. Before this it was very easy to accidentally break bytecode since no tests were run in bytecode mode. This hopefully makes it easier to spot such regressions :^).
This commit is contained in:
parent
f06e7dd13f
commit
b40308d0a4
Notes:
sideshowbarker
2024-07-17 20:12:55 +09:00
Author: https://github.com/davidot Commit: https://github.com/SerenityOS/serenity/commit/b40308d0a4f Pull-request: https://github.com/SerenityOS/serenity/pull/12070 Reviewed-by: https://github.com/alimpfard Reviewed-by: https://github.com/nico
3 changed files with 127 additions and 1 deletions
|
@ -604,8 +604,9 @@ if (BUILD_LAGOM)
|
|||
)
|
||||
set_tests_properties(JS PROPERTIES ENVIRONMENT SERENITY_SOURCE_DIR=${SERENITY_PROJECT_ROOT})
|
||||
|
||||
# test-invalid-unicode-js
|
||||
# Extra tests from Tests/LibJS
|
||||
lagom_test(../../Tests/LibJS/test-invalid-unicode-js.cpp LIBS LagomJS)
|
||||
lagom_test(../../Tests/LibJS/test-bytecode-js.cpp LIBS LagomJS)
|
||||
|
||||
# Markdown
|
||||
include(commonmark_spec)
|
||||
|
|
|
@ -5,3 +5,6 @@ link_with_unicode_data(test-js)
|
|||
|
||||
serenity_test(test-invalid-unicode-js.cpp LibJS LIBS LibJS)
|
||||
link_with_unicode_data(test-invalid-unicode-js)
|
||||
|
||||
serenity_test(test-bytecode-js.cpp LibJS LIBS LibJS)
|
||||
link_with_unicode_data(test-bytecode-js)
|
||||
|
|
122
Tests/LibJS/test-bytecode-js.cpp
Normal file
122
Tests/LibJS/test-bytecode-js.cpp
Normal file
|
@ -0,0 +1,122 @@
|
|||
/*
|
||||
* Copyright (c) 2022, David Tuin <davidot@serenityos.org>
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-2-Clause
|
||||
*/
|
||||
|
||||
#include <LibJS/Bytecode/Generator.h>
|
||||
#include <LibJS/Bytecode/Interpreter.h>
|
||||
#include <LibJS/Interpreter.h>
|
||||
#include <LibJS/Runtime/VM.h>
|
||||
#include <LibJS/Script.h>
|
||||
#include <LibTest/TestCase.h>
|
||||
|
||||
#define SETUP_AND_PARSE(source) \
|
||||
auto vm = JS::VM::create(); \
|
||||
auto ast_interpreter = JS::Interpreter::create<JS::GlobalObject>(*vm); \
|
||||
\
|
||||
auto script_or_error = JS::Script::parse(source, ast_interpreter->realm()); \
|
||||
EXPECT(!script_or_error.is_error()); \
|
||||
\
|
||||
auto script = script_or_error.release_value(); \
|
||||
auto const& program = script->parse_node(); \
|
||||
JS::Bytecode::Interpreter bytecode_interpreter(ast_interpreter->global_object(), ast_interpreter->realm());
|
||||
|
||||
#define EXPECT_NO_EXCEPTION(executable) \
|
||||
auto executable = JS::Bytecode::Generator::generate(program); \
|
||||
auto result = bytecode_interpreter.run(executable); \
|
||||
EXPECT(!result.is_error()); \
|
||||
EXPECT(!vm->exception());
|
||||
|
||||
#define EXPECT_NO_EXCEPTION_WITH_OPTIMIZATIONS(executable) \
|
||||
auto& passes = JS::Bytecode::Interpreter::optimization_pipeline(); \
|
||||
passes.perform(executable); \
|
||||
\
|
||||
auto result_with_optimizations = bytecode_interpreter.run(executable); \
|
||||
\
|
||||
EXPECT(!result_with_optimizations.is_error()); \
|
||||
EXPECT(!vm->exception())
|
||||
|
||||
#define EXPECT_NO_EXCEPTION_ALL(source) \
|
||||
SETUP_AND_PARSE(source) \
|
||||
EXPECT_NO_EXCEPTION(executable) \
|
||||
EXPECT_NO_EXCEPTION_WITH_OPTIMIZATIONS(executable)
|
||||
|
||||
TEST_CASE(empty_program)
|
||||
{
|
||||
EXPECT_NO_EXCEPTION_ALL("");
|
||||
}
|
||||
|
||||
TEST_CASE(if_statement_pass)
|
||||
{
|
||||
EXPECT_NO_EXCEPTION_ALL("if (false) throw new Exception('failed');");
|
||||
}
|
||||
|
||||
TEST_CASE(if_statement_fail)
|
||||
{
|
||||
SETUP_AND_PARSE("if (true) throw new Exception('failed');");
|
||||
|
||||
auto executable = JS::Bytecode::Generator::generate(program);
|
||||
auto result = bytecode_interpreter.run(executable);
|
||||
EXPECT(result.is_error());
|
||||
}
|
||||
|
||||
TEST_CASE(trivial_program)
|
||||
{
|
||||
EXPECT_NO_EXCEPTION_ALL("if (1 + 1 !== 2) throw new Exception('failed');");
|
||||
}
|
||||
|
||||
TEST_CASE(variables)
|
||||
{
|
||||
EXPECT_NO_EXCEPTION_ALL("var a = 1; \n"
|
||||
"if (a + 1 !== 2) throw new Exception('failed'); ");
|
||||
}
|
||||
|
||||
TEST_CASE(function_call)
|
||||
{
|
||||
EXPECT_NO_EXCEPTION_ALL("if (!isNaN(NaN)) throw new Exception('failed'); ");
|
||||
}
|
||||
|
||||
TEST_CASE(function_delcaration_and_call)
|
||||
{
|
||||
EXPECT_NO_EXCEPTION_ALL("var passed = false; \n"
|
||||
"function f() { passed = true; return 1; }\n"
|
||||
"if (f() !== 1) throw new Exception('failed');\n"
|
||||
// The passed !== true is needed as otherwise UBSAN
|
||||
// complains about unaligned access, until that
|
||||
// is fixed or ignored care must be taken to prevent such cases in tests.
|
||||
"if (passed !== true) throw new Exception('failed');");
|
||||
}
|
||||
|
||||
TEST_CASE(generator_function_call)
|
||||
{
|
||||
EXPECT_NO_EXCEPTION_ALL("function *g() { yield 2; }\n"
|
||||
"var gen = g();\n"
|
||||
"var result = gen.next();\n"
|
||||
"if (result.value !== 2) throw new Exception('failed');");
|
||||
}
|
||||
|
||||
TEST_CASE(loading_multiple_files)
|
||||
{
|
||||
// This is a testcase which is very much like test-js and test262
|
||||
// which load some common files first and only then the actual test file.
|
||||
|
||||
SETUP_AND_PARSE("function f() { return 'hello'; }");
|
||||
|
||||
{
|
||||
EXPECT_NO_EXCEPTION(common_file_executable);
|
||||
}
|
||||
|
||||
{
|
||||
auto test_file_script_or_error = JS::Script::parse("if (f() !== 'hello') throw new Exception('failed'); ", ast_interpreter->realm());
|
||||
EXPECT(!test_file_script_or_error.is_error());
|
||||
|
||||
auto test_file_script = test_file_script_or_error.release_value();
|
||||
auto const& test_file_program = test_file_script->parse_node();
|
||||
|
||||
auto executable = JS::Bytecode::Generator::generate(test_file_program);
|
||||
auto result = bytecode_interpreter.run(executable);
|
||||
EXPECT(!result.is_error());
|
||||
EXPECT(!vm->exception());
|
||||
}
|
||||
}
|
Loading…
Reference in a new issue